├── .gitignore ├── Makefile ├── README.org ├── cc-agenda-timeline.el ├── cc-bookmarks-bmenu-mode.el ├── cc-calc-mode.el ├── cc-calendar-mode.el ├── cc-context-menu-macros.el ├── cc-context-menu.el ├── cc-csv-mode.el ├── cc-diff-hl-mode.el ├── cc-digital-logic.el ├── cc-dired-mode.el ├── cc-doc-mode-ux.el ├── cc-ediff-mode.el ├── cc-edit-text-menu.el ├── cc-elfeed-mode.el ├── cc-emacs-lisp-mode.el ├── cc-eshell-mode.el ├── cc-find-menu.el ├── cc-gh.el ├── cc-global-keybindings.el ├── cc-google-translate.el ├── cc-grep-mode.el ├── cc-ibuffer-mode.el ├── cc-image-mode.el ├── cc-info-mode.el ├── cc-insert-org-plot.el ├── cc-js-mode.el ├── cc-magit-mode.el ├── cc-main-tmenu.el ├── cc-make-mode.el ├── cc-markdown-mode.el ├── cc-menu-reconfig.el ├── cc-nxml-mode.el ├── cc-objc-mode.el ├── cc-occur-mode.el ├── cc-org-agenda.el ├── cc-org-mode.el ├── cc-org-smart-quotes.el ├── cc-package-menu-mode.el ├── cc-prog-mode.el ├── cc-python-mode.el ├── cc-re-builder.el ├── cc-region-operations-menu.el ├── cc-repeat-mode.el ├── cc-save-hooks.el ├── cc-sgml-mode.el ├── cc-shell-mode.el ├── cc-style-text-menu.el ├── cc-swift-mode.el ├── cc-symbol-overlay.el ├── cc-tetris-mode.el ├── cc-text-mode.el ├── cc-transform-text-menu.el ├── cc-truth-table.el ├── cc-view-mode.el ├── cc-wgrep-mode.el ├── ccinit.el ├── cclisp.el ├── custom.el ├── kill-with-intelligence.el ├── recent-rgrep.el ├── scrim-utils.el └── tests ├── Makefile ├── test-cc-agenda-timeline.el └── test-cc-digital-logic.el /.gitignore: -------------------------------------------------------------------------------- 1 | *.elc 2 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | ## 2 | # Copyright 2025 Charles Y. Choi 3 | # 4 | 5 | TIMESTAMP := $(shell /bin/date "+%Y%m%d_%H%M%S") 6 | INSTALL_DIR=$(HOME)/bin 7 | EXEC_NAME=foo 8 | 9 | .PHONY: checkout-development 10 | checkout-development: 11 | git checkout development 12 | git branch --set-upstream-to=origin/development development 13 | git fetch origin --prune 14 | git pull 15 | 16 | .PHONY: checkout-main 17 | checkout-main: 18 | git checkout main 19 | git branch --set-upstream-to=origin/main main 20 | git fetch origin --prune 21 | git pull 22 | 23 | .PHONY: sync-development-with-main 24 | sync-development-with-main: checkout-main checkout-development 25 | git merge main 26 | 27 | .PHONY: create-merge-development-branch 28 | create-merge-development-branch: checkout-development 29 | git checkout -b merge-development-to-main-$(TIMESTAMP) 30 | git push --set-upstream origin merge-development-to-main-$(TIMESTAMP) 31 | 32 | ## Create GitHub pull request for development 33 | .PHONY: create-pr 34 | create-pr: 35 | gh pr create --base development --fill 36 | 37 | .PHONY: create-patch-pr 38 | create-patch-pr: 39 | gh pr create --base main --fill 40 | 41 | .PHONY: create-release-pr 42 | create-release-pr: create-merge-development-branch 43 | gh pr create --base main \ 44 | --title "Merge development to main $(TIMESTAMP)" \ 45 | --fill-verbose 46 | -------------------------------------------------------------------------------- /README.org: -------------------------------------------------------------------------------- 1 | * Charles Choi Emacs Configuration Files 2 | 3 | This directory contains Elisp files used by Charles Choi to customize his usage of Emacs. 4 | 5 | Initially ~ccinit.el~ is loaded from ~init.el~. Personal variable configuration (~custom-set-variables~, ~custom-set-faces~) is stored in ~custom.el~. Note that ~init.el~ is *not* included in this repo, however its relevant contents are shown below: 6 | 7 | #+begin_src elisp 8 | ;; CC's Emacs Init File. 9 | 10 | (require 'package) ;; You might already have this line 11 | (add-to-list 'package-archives 12 | '("melpa" . "http://melpa.org/packages/") t) 13 | 14 | (setq cc/cclisp-path (concat (getenv "HOME") "/" "emacs/cclisp")) 15 | (setq load-path (cons cc/cclisp-path load-path)) 16 | 17 | ;; (setenv "EMACS_APP_EXEC" 18 | ;; "/Applications/MacPorts/Emacs.app/Contents/MacOS/Emacs") 19 | 20 | ;; Run this on fresh install or reset of installed packages. 21 | ;; (package-refresh-contents) 22 | 23 | (package-initialize) ;; You nmight already have this line 24 | (unless package-archive-contents 25 | (package-refresh-contents)) 26 | 27 | (unless (package-installed-p 'use-package) 28 | (package-install 'use-package)) 29 | 30 | (setq custom-file (concat cc/cclisp-path "/" "custom.el")) 31 | (load custom-file 'noerror) 32 | 33 | (package-install-selected-packages) 34 | 35 | (load "ccinit") 36 | ;;(load custom-file 'noerror) 37 | 38 | (put 'dired-find-alternate-file 'disabled nil) 39 | (put 'upcase-region 'disabled nil) 40 | (put 'downcase-region 'disabled nil) 41 | #+end_src 42 | 43 | From ~ccinit.el~, all other Elisp files in this directory are loaded. 44 | 45 | 46 | 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /cc-agenda-timeline.el: -------------------------------------------------------------------------------- 1 | ;;; cc-agenda-timeline.el --- Org Agenda Timeline -*- lexical-binding: t; -*- 2 | 3 | ;; Copyright (C) 2023 Charles Choi 4 | 5 | ;; Author: Charles Choi 6 | ;; Keywords: tools 7 | 8 | ;; This program is free software; you can redistribute it and/or modify 9 | ;; it under the terms of the GNU General Public License as published by 10 | ;; the Free Software Foundation, either version 3 of the License, or 11 | ;; (at your option) any later version. 12 | 13 | ;; This program is distributed in the hope that it will be useful, 14 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | ;; GNU General Public License for more details. 17 | 18 | ;; You should have received a copy of the GNU General Public License 19 | ;; along with this program. If not, see . 20 | 21 | ;;; Commentary: 22 | 23 | ;; Visualize Org Agenda as a horizontal timeline plot. Implementation is done 24 | ;; via PlantUML Gantt chart. Default output is SVG. 25 | 26 | ;;; Code: 27 | 28 | (require 'org) 29 | (require 'calendar) 30 | (require 'holidays) 31 | (require 'diary-lib) 32 | 33 | (defun cc/at/closed-agenda-element-p (e) 34 | (let ((closed (assoc-default "CLOSED" e)) 35 | (timestamp (assoc-default "TIMESTAMP" e)) 36 | (scheduled (assoc-default "SCHEDULED" e)) 37 | (deadline (assoc-default "DEADLINE" e)) 38 | ) 39 | 40 | (if (or closed (not (or timestamp scheduled deadline))) 41 | t 42 | nil))) 43 | 44 | (defun cc/test-timestamp (e &optional days-out) 45 | (let ((days-out (or days-out 40)) 46 | (timestamp-buf (assoc-default "TIMESTAMP" e)) 47 | (scheduled-buf (assoc-default "SCHEDULED" e)) 48 | (deadline-buf (assoc-default "DEADLINE" e)) 49 | (timestamp nil) 50 | (scheduled nil) 51 | (deadline nil)) 52 | ;; TODO: handle possible case where timestamp and/or scheduled are repeating 53 | ;; TODO: handle date and time intervals "<2024-02-05 Mon>--<2024-02-12 Mon>" 54 | ;; (string-match "--" "<2024-02-05 Mon>--<2024-02-12 Mon>") 55 | 56 | (cond (timestamp-buf 57 | (if (stringp (org-get-repeat timestamp-buf)) 58 | (setq timestamp (cc/at/next-time-from-repeating-org-timestamp timestamp-buf)) 59 | (setq timestamp (time-convert (org-read-date nil t timestamp-buf) 'list))) 60 | ;; now timestamp is a Lisp timesstamp 61 | (cc/timestamp-filter timestamp 2 days-out)) 62 | 63 | (scheduled-buf 64 | (if (stringp (org-get-repeat scheduled-buf)) 65 | (setq scheduled (cc/at/next-time-from-repeating-org-timestamp scheduled-buf)) 66 | (setq scheduled (time-convert (org-read-date nil t scheduled-buf) 'list))) 67 | ;; now timestamp is a Lisp timesstamp 68 | (cc/timestamp-filter scheduled 2 days-out)) 69 | 70 | (deadline-buf 71 | (if (stringp (org-get-repeat deadline-buf)) 72 | (setq deadline (cc/at/next-time-from-repeating-org-timestamp deadline-buf)) 73 | (setq deadline (time-convert (org-read-date nil t deadline-buf) 'list))) 74 | ;; now timestamp is a Lisp timesstamp 75 | (cc/timestamp-filter deadline 2 days-out)) 76 | 77 | (t 78 | nil)))) 79 | 80 | ;; this is good 81 | (defun cc/at/next-time-from-repeating-org-timestamp (timestamp) 82 | "Next Lisp timestamp if Org string TIMESTAMP is repeating. 83 | 84 | If TIMESTAMP is repeating then return the next Lisp timestamp (ticks . hz), 85 | otherwise nil." 86 | (let* ((repeat-value (org-get-repeat timestamp)) 87 | (from-string (concat " " repeat-value)) 88 | (amended-timestamp (concat repeat-value 89 | " " 90 | (string-replace from-string "" timestamp)))) 91 | (if (not repeat-value) 92 | (error "timestamp `%s' does not have a repeat value." timestamp)) 93 | (time-convert (org-read-date nil t amended-timestamp) 'list))) 94 | 95 | 96 | 97 | (defun cc/timestamp-filter (timestamp start end) 98 | (let ((start-timestamp (time-subtract (current-time) (* 60 60 24 start))) 99 | (end-timestamp (time-add (current-time) (* 60 60 24 end)))) 100 | (if (and (time-less-p start-timestamp timestamp) (time-less-p timestamp end-timestamp)) 101 | timestamp 102 | nil))) 103 | 104 | 105 | (defun cc/agenda-timeline-items (match scope &optional days-out include-diary include-holidays) 106 | (interactive) 107 | (let* ((days-out (or days-out 40)) 108 | 109 | (agenda-items (org-map-entries 'org-entry-properties match scope)) 110 | (active-agenda-items (seq-remove #'cc/at/closed-agenda-element-p agenda-items)) 111 | (timestamped-items (seq-filter (lambda (x) (cc/test-timestamp x days-out)) active-agenda-items)) 112 | 113 | (items (mapcar (lambda (x) (list 114 | (assoc-default "ITEM" x) 115 | (cc/test-timestamp x days-out))) 116 | timestamped-items)) 117 | 118 | ;;(items-with-diary (append items (cc/extract-diary-items days-out) (cc/extract-holiday-items days-out))) 119 | ;;(sorted-items (sort items-with-diary (lambda (x y) (time-less-p (nth 1 x) (nth 1 y))))) 120 | (results (list))) 121 | 122 | (if include-diary 123 | (setq items (append items (cc/extract-diary-items days-out)))) 124 | 125 | (if include-holidays 126 | (setq items (append items (cc/extract-holiday-items days-out)))) 127 | 128 | (let ((sorted-items (sort items (lambda (x y) (time-less-p (nth 1 x) (nth 1 y)))))) 129 | (mapc (lambda (x) 130 | (push 131 | (format "[%s] happens %s" 132 | (cc/scrub-item-string (nth 0 x)) 133 | (format-time-string "%Y-%m-%d" (nth 1 x))) 134 | results)) 135 | sorted-items)) 136 | 137 | 138 | 139 | (reverse results))) 140 | 141 | (defun cc/extract-holiday-items (days) 142 | (let* ((holidays 143 | (holiday-in-range 144 | (calendar-absolute-from-gregorian (calendar-current-date)) 145 | (calendar-absolute-from-gregorian (calendar-current-date days))))) 146 | (mapcar 'cc/diary-info holidays))) 147 | 148 | (defun cc/agenda-timeline (match scope &optional days-out include-diary include-holidays) 149 | (interactive) 150 | (let* ((headers (list)) 151 | (footers (list)) 152 | (today (format-time-string "%Y-%m-%d" (time-subtract (current-time) (* 60 60 24 2))))) 153 | 154 | (push "@startgantt" headers) 155 | (push "printscale daily" headers) 156 | (push "hide footbox" headers) 157 | (push "saturday is colored wheat" headers) 158 | (push "sunday is colored wheat" headers) 159 | (push "today is colored in Orange" headers) 160 | (push "skinparam backgroundColor #EEEEEE" headers) 161 | (push (format "Project starts %s" today) headers) 162 | 163 | (push "@endgantt" footers) 164 | 165 | (mapconcat 'identity 166 | (append (reverse headers) 167 | (cc/agenda-timeline-items match scope days-out include-diary include-holidays) 168 | (reverse footers)) 169 | "\n"))) 170 | 171 | (defun cc/extract-diary-items (days) 172 | (let ((diary-entries (diary-list-entries (calendar-current-date) days t)) 173 | ) 174 | (mapcar 'cc/diary-info diary-entries))) 175 | 176 | (defun cc/diary-info (e) 177 | (let* ((date-list (nth 0 e)) 178 | (item (nth 1 e)) 179 | (month (nth 0 date-list)) 180 | (day (nth 1 date-list)) 181 | (year (nth 2 date-list)) 182 | (datestamp (format "%4d-%02d-%02d" year month day)) 183 | (results (list))) 184 | 185 | (push (time-convert (date-to-time datestamp) 'list) results) 186 | (push item results) 187 | results 188 | )) 189 | 190 | (defun cc/scrub-item-string (item) 191 | (string-trim 192 | (replace-regexp-in-string "\\[\\([[:digit:]]*\\)/\\([[:digit:]]*\\)\\]" "(\\1/\\2)" 193 | (replace-regexp-in-string "<[[:digit:]]\\{4\\}-[[:digit:]]\\{2\\}-[[:digit:]]\\{2\\}.*>" "" item)))) 194 | 195 | ;; (cc/scrub-item-string "한글 <2023-10-23 Mon 10:00-11:00 +1d> [2/4]") 196 | 197 | ;;(kill-new (cc/agenda-timeline t 'agenda)) 198 | 199 | 200 | ;;(org-map-entries 'org-entry-properties "+dj" 'agenda) 201 | 202 | ;; (kill-new (pp (org-map-entries 'org-entry-properties t 'agenda))) 203 | 204 | ;; (org-get-repeat "<2023-08-31 Thu 22:00 +1w>") 205 | 206 | ;; (org-time-string-to-absolute "<2023-08-31 Thu 22:00 +1w>") 207 | 208 | ;; (defun cc/org-timestamp-process (timestamp) 209 | ;; ) 210 | 211 | ;; TODO: This right here 212 | ;; (org-read-date nil nil "<2023-08-31 Thu 22:00 +1w>") 213 | 214 | ;; (kill-new (pp (diary-list-entries (calendar-current-date) 40 t))) 215 | 216 | ;; (kill-new (pp (seq-filter 'cc/test-timestamp (seq-remove 'cc/at/closed-agenda-element-p (org-map-entries 'org-entry-properties "+dj" 'agenda))))) 217 | 218 | (provide 'cc-agenda-timeline) 219 | ;;; cc-agenda-timeline.el ends here 220 | -------------------------------------------------------------------------------- /cc-bookmarks-bmenu-mode.el: -------------------------------------------------------------------------------- 1 | ;;; cc-bookmarks-bmenu-mode.el --- Bookmarks Bmenu Mode Config -*- lexical-binding: t; -*- 2 | 3 | ;; Copyright (C) 2024 Charles Choi 4 | 5 | ;; Author: Charles Choi 6 | ;; Keywords: tools 7 | 8 | ;; This program is free software; you can redistribute it and/or modify 9 | ;; it under the terms of the GNU General Public License as published by 10 | ;; the Free Software Foundation, either version 3 of the License, or 11 | ;; (at your option) any later version. 12 | 13 | ;; This program is distributed in the hope that it will be useful, 14 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | ;; GNU General Public License for more details. 17 | 18 | ;; You should have received a copy of the GNU General Public License 19 | ;; along with this program. If not, see . 20 | 21 | ;;; Commentary: 22 | 23 | ;; 24 | 25 | ;;; Code: 26 | (require 'casual-bookmarks) 27 | 28 | (easy-menu-add-item global-map '(menu-bar) 29 | casual-bookmarks-main-menu 30 | "Tools") 31 | 32 | (use-package bookmark 33 | :ensure nil 34 | :defer t) 35 | 36 | (use-package cc-main-tmenu 37 | :ensure nil 38 | :defer t) 39 | 40 | (use-package casual-bookmarks 41 | :ensure nil 42 | :bind (:map bookmark-bmenu-mode-map 43 | ("C-o" . casual-bookmarks-tmenu) 44 | ("S" . casual-bookmarks-sortby-tmenu) 45 | ("J" . bookmark-jump) 46 | ("C-M-o" . cc/main-menu)) 47 | :after (bookmark cc-main-tmenu)) 48 | 49 | (provide 'cc-bookmarks-bmenu-mode) 50 | ;;; cc-bookmarks-bmenu-mode.el ends here 51 | -------------------------------------------------------------------------------- /cc-calc-mode.el: -------------------------------------------------------------------------------- 1 | ;;; cc-calc-mode.el --- Calc customization -*- lexical-binding: t; -*- 2 | 3 | ;; Copyright (C) 2024-2025 Charles Choi 4 | 5 | ;; Author: Charles Choi 6 | ;; Keywords: tools 7 | 8 | ;; This program is free software; you can redistribute it and/or modify 9 | ;; it under the terms of the GNU General Public License as published by 10 | ;; the Free Software Foundation, either version 3 of the License, or 11 | ;; (at your option) any later version. 12 | 13 | ;; This program is distributed in the hope that it will be useful, 14 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | ;; GNU General Public License for more details. 17 | 18 | ;; You should have received a copy of the GNU General Public License 19 | ;; along with this program. If not, see . 20 | 21 | ;;; Commentary: 22 | 23 | ;; 24 | 25 | ;;; Code: 26 | 27 | (require 'calc) 28 | (require 'calc-ext) 29 | (require 'casual-calc) 30 | 31 | (add-hook 'calc-mode-hook (lambda () (setq calc-gnuplot-default-device "aqua"))) 32 | 33 | (keymap-set calc-mode-map "C-o" #'casual-calc-tmenu) 34 | (keymap-set calc-alg-map "C-o" #'casual-calc-tmenu) 35 | 36 | (keymap-set calc-mode-map "" #'calc-pop) 37 | 38 | (defun cc/ptop () 39 | "Print top of Calc stack." 40 | (interactive) 41 | (kill-new (pp (calc-top)))) 42 | 43 | ;; (defun cc/confirm-before-calc-quit () 44 | ;; "Raise confirm prompt before invoking `calc-quit'." 45 | ;; (interactive) 46 | ;; (if (y-or-n-p "Really Quit? ") 47 | ;; (calc-quit) 48 | ;; (message "all good"))) 49 | 50 | ;; (keymap-set calc-mode-map "q" 'cc/confirm-before-calc-quit) 51 | ;; (add-hook 'calc-mode-hook #'calc-total-algebraic-mode) 52 | 53 | (provide 'cc-calc-mode) 54 | ;;; cc-calc-mode.el ends here 55 | -------------------------------------------------------------------------------- /cc-calendar-mode.el: -------------------------------------------------------------------------------- 1 | ;;; cc-calendar-mode.el --- Calendar Configuration -*- lexical-binding: t; -*- 2 | 3 | ;; Copyright (C) 2024 Charles Choi 4 | 5 | ;; Author: Charles Choi 6 | ;; Keywords: calendar 7 | 8 | ;; This program is free software; you can redistribute it and/or modify 9 | ;; it under the terms of the GNU General Public License as published by 10 | ;; the Free Software Foundation, either version 3 of the License, or 11 | ;; (at your option) any later version. 12 | 13 | ;; This program is distributed in the hope that it will be useful, 14 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | ;; GNU General Public License for more details. 17 | 18 | ;; You should have received a copy of the GNU General Public License 19 | ;; along with this program. If not, see . 20 | 21 | ;;; Commentary: 22 | 23 | ;; 24 | 25 | ;;; Code: 26 | (require 'casual-calendar) 27 | 28 | (keymap-set calendar-mode-map "C-o" #'casual-calendar) 29 | 30 | (provide 'cc-calendar-mode) 31 | ;;; cc-calendar-mode.el ends here 32 | -------------------------------------------------------------------------------- /cc-context-menu-macros.el: -------------------------------------------------------------------------------- 1 | ;;; cc-context-menu-macros.el --- Context Menu Macros -*- lexical-binding: t; -*- 2 | 3 | ;; Copyright (C) 2023-2024 Charles Choi 4 | 5 | ;; Author: Charles Choi 6 | 7 | ;; Keywords: tools 8 | 9 | ;; This program is free software; you can redistribute it and/or modify 10 | ;; it under the terms of the GNU General Public License as published by 11 | ;; the Free Software Foundation, either version 3 of the License, or 12 | ;; (at your option) any later version. 13 | 14 | ;; This program is distributed in the hope that it will be useful, 15 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | ;; GNU General Public License for more details. 18 | 19 | ;; You should have received a copy of the GNU General Public License 20 | ;; along with this program. If not, see . 21 | 22 | ;;; Commentary: 23 | ;; 24 | 25 | ;;; Code: 26 | (require 'ol) 27 | 28 | (defmacro cc/context-menu-item-separator (menu key) 29 | "Add single line separator to MENU with KEY." 30 | `(define-key-after ,menu [,key] 31 | '(menu-item "--single-line"))) 32 | 33 | (defmacro cc/add-context-menu-item (menu command label help) 34 | "Add COMMAND to MENU annotated with LABEL and property HELP." 35 | `(define-key-after ,menu [,command] 36 | '(menu-item ,label ,command 37 | :help ,help))) 38 | 39 | (defmacro cc/add-context-menu-item-visible (menu command label help visible) 40 | "Add COMMAND to MENU annotated with LABEL and properties HELP, VISIBLE." 41 | `(define-key-after ,menu [,command] 42 | '(menu-item ,label ,command 43 | :help ,help 44 | :visible ,visible))) 45 | 46 | (defmacro cc/add-context-menu-item-enable (menu command label help enable) 47 | "Add COMMAND to MENU annotated with LABEL and properties HELP, ENABLE." 48 | `(define-key-after ,menu [,command] 49 | '(menu-item ,label ,command 50 | :help ,help 51 | :enable ,enable))) 52 | 53 | (defmacro cc/add-first-context-menu-item (menu command label help) 54 | "Add first COMMAND to MENU annotated with LABEL and HELP." 55 | `(define-key ,menu [,command] 56 | '(menu-item ,label ,command 57 | :help ,help))) 58 | 59 | (defmacro cc/add-context-menu-submenu (menu submenu label) 60 | "Add SUBMENU to MENU annotated with LABEL. 61 | SUBMENU is a keymap." 62 | `(define-key-after ,menu [,submenu] 63 | (list 'menu-item ,label ,submenu))) 64 | 65 | (defun cc/context-menu-label (prefix) 66 | "Generate context menu label with region string prepended by PREFIX." 67 | (let* ((start (region-beginning)) 68 | (end (region-end)) 69 | (buf "") 70 | (max 25) 71 | (size (abs (- start end)))) 72 | (if (> size max) 73 | (setq buf (concat prefix " “"(buffer-substring start (+ max start)) "…”")) 74 | (setq buf (concat prefix " “" (buffer-substring start end) "”"))) 75 | buf)) 76 | 77 | (defun cc/context-menu-last-word-in-region (prefix) 78 | "Generate context menu label with last word in region prepended by PREFIX." 79 | (let* ((start (region-beginning)) 80 | (end (region-end)) 81 | (buf (buffer-substring start end)) 82 | (last-word (car (last (split-string buf " "))))) 83 | (concat prefix " “" last-word "”"))) 84 | 85 | (defun cc/org-stored-links-p () 86 | "Predicate if `org-stored-links' is populated. 87 | Return t if populated, nil otherwise." 88 | (if (> (length org-stored-links) 0) 89 | t 90 | nil)) 91 | 92 | (provide 'cc-context-menu-macros) 93 | ;;; cc-context-menu-macros.el ends here 94 | -------------------------------------------------------------------------------- /cc-context-menu.el: -------------------------------------------------------------------------------- 1 | ;;; cc-context-menu.el --- Context Menu Customization -*- lexical-binding: t -*- 2 | 3 | ;; Copyright (C) 2023-2024 Charles Choi 4 | 5 | ;; Author: Charles Choi 6 | 7 | ;; Keywords: tools 8 | 9 | ;; This program is free software; you can redistribute it and/or modify 10 | ;; it under the terms of the GNU General Public License as published by 11 | ;; the Free Software Foundation, either version 3 of the License, or 12 | ;; (at your option) any later version. 13 | 14 | ;; This program is distributed in the hope that it will be useful, 15 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | ;; GNU General Public License for more details. 18 | 19 | ;; You should have received a copy of the GNU General Public License 20 | ;; along with this program. If not, see . 21 | 22 | ;;; Commentary: 23 | ;; 24 | 25 | ;;; Code: 26 | (require 'easymenu) 27 | (require 'mouse) 28 | (require 'org) 29 | (require 'cclisp) 30 | (require 'cc-context-menu-macros) 31 | (require 'cc-transform-text-menu) 32 | (require 'cc-style-text-menu) 33 | (require 'cc-region-operations-menu) 34 | (require 'cc-insert-org-plot) 35 | (require 'cc-find-menu) 36 | (require 'cc-edit-text-menu) 37 | (require 'cc-wgrep-mode) 38 | (require 'cc-dired-mode) 39 | (require 'casual-dired) 40 | 41 | (defun cc/context-menu-addon-items (menu click) 42 | "Charles Choi context menu hook function using MENU and CLICK event. 43 | 44 | MENU - menu to be configured. 45 | CLICK - event" 46 | (save-excursion 47 | (mouse-set-point click) 48 | (cc/context-menu-journal-items menu) 49 | (cc/context-menu-org-table-items menu (not (org-at-table-p))) 50 | (cc/context-menu-buffers-items menu) 51 | (cc/context-menu-narrow-items menu) 52 | (cc/context-menu-workflow-items menu) 53 | (cc/context-menu-open-in-items menu) 54 | (cc/context-menu-dired-items menu (not (derived-mode-p 'dired-mode))) 55 | (cc/context-menu-dictionary-items menu (not (use-region-p))) 56 | (cc/context-menu-occur-items menu) 57 | (cc/context-menu-vc-items menu (not (vc-responsible-backend default-directory t))) 58 | (cc/context-menu-region-actions-items menu (not (use-region-p))) 59 | (cc/context-menu-reveal-markup-items menu) 60 | (cc/context-menu-timekeeping-items menu) 61 | (cc/context-menu-word-count-items menu (not (derived-mode-p 'text-mode))) 62 | (easy-menu-add-item menu nil cc/wgrep-menu) 63 | menu)) 64 | 65 | (defun cc/context-menu-word-count-items (menu &optional inapt) 66 | "Menu items to populate MENU for word count section if INAPT nil." 67 | (when (not inapt) 68 | (cc/context-menu-item-separator menu count-words-separator) 69 | (if (use-region-p) 70 | (easy-menu-add-item menu nil ["Count Words in Region" 71 | count-words 72 | :help "Count words in region"]) 73 | 74 | (easy-menu-add-item menu nil ["Count Words in Buffer" 75 | count-words 76 | :help "Count words in buffer"])))) 77 | 78 | (defun cc/context-menu-reveal-markup-items (menu &optional inapt) 79 | "Menu items to populate MENU for reveal markup section if INAPT nil." 80 | (when (not inapt) 81 | (cond 82 | ((derived-mode-p 'org-mode) 83 | (cc/context-menu-item-separator menu org-mode-operations-separator) 84 | (easy-menu-add-item menu nil 85 | ["Toggle Reveal Markup" 86 | visible-mode 87 | :help "Toggle making all invisible text \ 88 | temporarily visible (Visible mode)"]) 89 | 90 | (easy-menu-add-item menu nil 91 | ["Paste Last Org Link" 92 | org-insert-last-stored-link 93 | :enable (cc/org-stored-links-p) 94 | :help "Insert the last link stored in org-stored-links"])) 95 | 96 | ((derived-mode-p 'markdown-mode) 97 | (cc/context-menu-item-separator menu markdown-mode-operations-separator) 98 | (easy-menu-add-item menu nil 99 | ["Toggle Reveal Markup" 100 | markdown-toggle-markup-hiding 101 | :help "Toggle the display or hiding of markup"]))))) 102 | 103 | (defun cc/context-menu-vc-items (menu &optional inapt) 104 | "Menu items to populate MENU for version control section if INAPT nil." 105 | (when (not inapt) 106 | (keymap-set-after menu 107 | "" 108 | '(menu-item "--" 109 | :visible (vc-responsible-backend default-directory t)) 110 | 'Find\ and/or\ Replace) 111 | 112 | (easy-menu-add-item 113 | menu nil 114 | ["Magit Status" 115 | magit-status 116 | :help "Show the status of the current Git repository in a buffer"]) 117 | 118 | (easy-menu-add-item 119 | menu nil 120 | ["Ediff revision…" 121 | cc/ediff-revision-from-menu 122 | :visible (and (bound-and-true-p buffer-file-name) 123 | (vc-registered (buffer-file-name))) 124 | :help "Ediff this file with revision"]))) 125 | 126 | (defun cc/context-menu-region-actions-items (menu &optional inapt) 127 | "Menu items to populate MENU for region actions section if INAPT nil." 128 | (when (not inapt) 129 | (cc/context-menu-item-separator menu transform-text-separator) 130 | (easy-menu-add-item menu nil cc/transform-text-menu) 131 | (easy-menu-add-item menu nil cc/region-operations-menu) 132 | (cond 133 | ((derived-mode-p 'prog-mode) 134 | (easy-menu-add-item menu nil 135 | ["Toggle Comment" 136 | comment-dwim 137 | :help "Toggle comment on selected region"])) 138 | 139 | ((derived-mode-p 'org-mode) 140 | (easy-menu-add-item menu nil cc/emphasize-menu) 141 | (easy-menu-add-item menu nil ["Copy as Slack" 142 | org-slack-export-to-clipboard-as-slack 143 | :help "Copy as Slack to clipboard"]) 144 | (easy-menu-add-item menu nil ["Copy as Slack" 145 | org-slack-export-to-clipboard-as-slack 146 | :help "Copy as Slack to clipboard"]) 147 | (easy-menu-add-item menu nil ["Copy as RTF" 148 | dm/copy-as-rtf 149 | :help "Copy as RTF to clipboard"])) 150 | 151 | ((derived-mode-p 'markdown-mode) 152 | (easy-menu-add-item menu nil cc/emphasize-menu))))) 153 | 154 | (defun cc/context-menu-timekeeping-items (menu &optional inapt) 155 | "Menu items to populate MENU for timekeeping section if INAPT nil." 156 | (when (not inapt) 157 | (cc/context-menu-item-separator menu world-clock-separator) 158 | (easy-menu-add-item menu nil 159 | ["Calendar" 160 | calendar 161 | :help "Display a three-month Gregorian calendar"]) 162 | (easy-menu-add-item menu nil 163 | ["World Clock" 164 | world-clock 165 | :help "Display times from around the world"]))) 166 | 167 | (defun cc/context-menu-journal-items (menu &optional inapt) 168 | "Menu items to populate MENU for journal section if INAPT nil." 169 | (when (not inapt) 170 | (easy-menu-add-item menu nil ["Journal" 171 | status-report 172 | :help "Go to current day journal"]) 173 | 174 | (easy-menu-add-item menu nil ["Agenda - All TODOs" 175 | (lambda () (interactive)(org-agenda nil "n")) 176 | :help "Show Org agenda with all TODO tasks."]))) 177 | 178 | (defun cc/context-menu-dictionary-items (menu &optional inapt) 179 | "Menu items to populate MENU for section if INAPT nil." 180 | (when (not inapt) 181 | (cc/context-menu-item-separator menu dictionary-operations-separator) 182 | (easy-menu-add-item menu nil ["Look Up" 183 | osx-dictionary-search-word-at-point 184 | :label (cc/context-menu-last-word-in-region "Look Up") 185 | :help "Look up selected region in macOS dictionary"]))) 186 | 187 | (defun cc/context-menu-occur-items (menu &optional inapt) 188 | "Menu items to populate MENU for occur section if INAPT nil." 189 | (when (not inapt) 190 | (cc/context-menu-item-separator menu occur-separator) 191 | ;;(easy-menu-add-item menu nil cc/find-menu) 192 | (if (use-region-p) 193 | (easy-menu-add-item menu nil 194 | ["Find word in buffer (occur)" 195 | ;;occur-word-at-mouse 196 | occur-symbol-at-mouse 197 | :visible (not buffer-read-only) 198 | :label (cc/context-menu-last-word-in-region 199 | "Occur") 200 | :help "Show all lines in the current buffer containing \ 201 | a match for selected word"]) 202 | (easy-menu-add-item menu nil 203 | ["Occur…" 204 | occur 205 | :visible (not buffer-read-only) 206 | :help "Show all lines in the current buffer \ 207 | containing a match for regex"])))) 208 | 209 | (defun cc/context-menu-dired-items (menu &optional inapt) 210 | "Menu items to populate MENU for Dired section if INAPT nil." 211 | (when (not inapt) 212 | (easy-menu-add-item menu nil casual-dired-sort-menu) 213 | (easy-menu-add-item menu nil 214 | ["Duplicate" 215 | cc/dired-duplicate-file 216 | :label (concat "Duplicate" 217 | " “" 218 | (file-name-base (dired-get-filename)) 219 | "." 220 | (file-name-extension (dired-get-filename)) 221 | "”") 222 | :help "Duplicate selected item"]))) 223 | 224 | 225 | (defun cc/context-menu-workflow-items (menu &optional inapt) 226 | "Menu items to populate MENU for workflow section if INAPT nil." 227 | (when (not inapt) 228 | (cc/context-menu-item-separator menu capture-flow-separator) 229 | (easy-menu-add-item menu nil 230 | ["New Workflow…" 231 | org-capture 232 | :help "Create new task or workflow via org-capture"]))) 233 | 234 | (defun cc/context-menu-buffers-items (menu &optional inapt) 235 | "Menu items to populate MENU for buffers section if INAPT nil." 236 | (when (not inapt) 237 | (cc/context-menu-item-separator menu buffer-navigation-separator) 238 | 239 | (easy-menu-add-item menu nil ["List All Buffers" 240 | ibuffer 241 | :help "List all buffers"]) 242 | 243 | (easy-menu-add-item menu nil ["Previous Buffer" 244 | previous-buffer 245 | :help "Go to previous buffer"]) 246 | 247 | (easy-menu-add-item menu nil ["Next Buffer" 248 | next-buffer 249 | :help "Go to next buffer"]))) 250 | 251 | 252 | (defun cc/context-menu-open-in-items (menu &optional inapt) 253 | "Menu items to populate MENU for open in section if INAPT nil." 254 | (when (not inapt) 255 | (cc/context-menu-item-separator menu open-in-separator) 256 | 257 | (easy-menu-add-item menu nil 258 | ["Open in Finder" 259 | reveal-in-folder-this-buffer 260 | :visible (or (buffer-file-name) (derived-mode-p 'dired-mode)) 261 | :help "Open file (buffer) in Finder"]) 262 | 263 | (easy-menu-add-item menu nil 264 | ["Open in Dired" 265 | dired-jump-other-window 266 | :visible (and (buffer-file-name) (not (derived-mode-p 'dired-mode))) 267 | :help "Open file in Dired"]))) 268 | 269 | 270 | (defun cc/context-menu-narrow-items (menu &optional inapt) 271 | "Menu items to populate MENU for narrow section if INAPT nil." 272 | (when (not inapt) 273 | (when buffer-file-name 274 | (cond ((use-region-p) 275 | (cc/context-menu-item-separator menu narrow-separator) 276 | (easy-menu-add-item menu nil 277 | ["Narrow Region" narrow-to-region 278 | :label (cc/context-menu-label "Narrow Region") 279 | :help "Restrict editing in this buffer \ 280 | to the current region"])) 281 | 282 | ((and (not (buffer-narrowed-p)) (derived-mode-p 'prog-mode)) 283 | (cc/context-menu-item-separator menu narrow-separator) 284 | (easy-menu-add-item menu nil 285 | ["Narrow to defun" narrow-to-defun 286 | :help "Restrict editing in this buffer \ 287 | to the current defun"])) 288 | 289 | ((and (not (buffer-narrowed-p)) (derived-mode-p 'org-mode)) 290 | (cc/context-menu-item-separator menu narrow-separator) 291 | (easy-menu-add-item menu nil 292 | ["Narrow to subtree" org-narrow-to-subtree 293 | :help "Restrict editing in this buffer \ 294 | to the current subtree"])) 295 | 296 | 297 | ((and (not (buffer-narrowed-p)) (derived-mode-p 'markdown-mode)) 298 | (cc/context-menu-item-separator menu narrow-separator) 299 | (easy-menu-add-item menu nil 300 | ["Narrow to subtree" markdown-narrow-to-subtree 301 | :help "Restrict editing in this buffer \ 302 | to the current subtree"]))) 303 | 304 | (when (buffer-narrowed-p) 305 | (cc/context-menu-item-separator menu widen-separator) 306 | (easy-menu-add-item menu nil 307 | ["Widen buffer" widen 308 | :help "Remove narrowing restrictions \ 309 | from current buffer"]))))) 310 | 311 | (defun cc/context-menu-org-table-items (menu &optional inapt) 312 | "Menu items to populate MENU for Org table section if INAPT nil." 313 | (when (not inapt) 314 | (cc/context-menu-item-separator menu org-table-sqeparator) 315 | (easy-menu-add-item menu nil 316 | ["Table Cell Info" 317 | cc/mouse-copy-org-table-reference-dwim 318 | :label (cc/org-table-reference-dwim) 319 | :help "Copy Org table reference (field or range) into kill ring via mouse"]) 320 | (easy-menu-add-item menu nil 321 | ["Show Coordinates" 322 | org-table-toggle-coordinate-overlays 323 | :style toggle 324 | :selected org-table-coordinate-overlays 325 | :help "Toggle the display of row/column numbers in tables"]) 326 | (easy-menu-add-item menu nil 327 | ["Edit Table Formulas" 328 | org-table-edit-formulas 329 | :help " Edit the formulas of the current table in a separate buffer."]) 330 | 331 | (easy-menu-add-item menu nil cc/insert-org-plot-menu) 332 | (easy-menu-add-item menu nil ["Run gnuplot" 333 | org-plot/gnuplot 334 | :help "Plot table using gnuplot"]))) 335 | 336 | (add-hook 'context-menu-functions #'cc/context-menu-addon-items) 337 | 338 | ;; (defvar cchoi-mouse-file nil "some thing") 339 | 340 | ;; (defun cc/track-mouse (event) 341 | ;; (interactive "e") 342 | ;; (if (mouse-posn-property (event-start event) 'dired-filename) 343 | ;; (let (window pos file) 344 | ;; (save-excursion 345 | ;; (setq window (posn-window (event-end event)) 346 | ;; pos (posn-point (event-end event))) 347 | ;; (if (not (windowp window)) 348 | ;; (error "No file chosen")) 349 | ;; (set-buffer (window-buffer window)) 350 | ;; (goto-char pos) 351 | ;; (setq file (dired-get-filename))) 352 | ;; (setq cchoi-mouse-file file))) 353 | ;; (setq cchoi-mouse-file nil)) 354 | 355 | 356 | ;; (defun cc/kill-image-info (e) 357 | ;; "Show file type. 358 | ;; E - event" 359 | ;; (interactive "e") 360 | ;; (ignore e) 361 | ;; (dired-show-file-type)) 362 | 363 | (provide 'cc-context-menu) 364 | ;;; cc-context-menu.el ends here 365 | -------------------------------------------------------------------------------- /cc-csv-mode.el: -------------------------------------------------------------------------------- 1 | ;;; cc-csv-mode.el --- CSV Mode Customization -*- lexical-binding: t; -*- 2 | 3 | ;; Copyright (C) 2025 Charles Choi 4 | 5 | ;; Author: Charles Choi 6 | ;; Keywords: tools 7 | 8 | ;; This program is free software; you can redistribute it and/or modify 9 | ;; it under the terms of the GNU General Public License as published by 10 | ;; the Free Software Foundation, either version 3 of the License, or 11 | ;; (at your option) any later version. 12 | 13 | ;; This program is distributed in the hope that it will be useful, 14 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | ;; GNU General Public License for more details. 17 | 18 | ;; You should have received a copy of the GNU General Public License 19 | ;; along with this program. If not, see . 20 | 21 | ;;; Commentary: 22 | 23 | ;; 24 | 25 | ;;; Code: 26 | (require 'csv-mode) 27 | (require 'casual-lib) 28 | 29 | (add-hook 'csv-mode-hook 30 | (lambda () 31 | (visual-line-mode -1))) 32 | 33 | 34 | (transient-define-prefix casual-csv-tmenu () 35 | ["Casual CSV" 36 | 37 | ["Display" 38 | ("a" "Align" csv-align-fields) 39 | ("u" "Unalign" csv-unalign-fields)] 40 | ] 41 | ) 42 | 43 | (keymap-set csv-mode-map "M-m" #'casual-csv-tmenu) 44 | 45 | 46 | (provide 'cc-csv-mode) 47 | ;;; cc-csv-mode.el ends here 48 | -------------------------------------------------------------------------------- /cc-diff-hl-mode.el: -------------------------------------------------------------------------------- 1 | ;;; cc-diff-hl-mode.el --- diff-hl-mode configuration -*- lexical-binding: t; -*- 2 | 3 | ;; Copyright (C) 2023-2024 Charles Choi 4 | 5 | ;; Author: Charles Choi 6 | 7 | ;; Keywords: tools 8 | 9 | ;; This program is free software; you can redistribute it and/or modify 10 | ;; it under the terms of the GNU General Public License as published by 11 | ;; the Free Software Foundation, either version 3 of the License, or 12 | ;; (at your option) any later version. 13 | 14 | ;; This program is distributed in the hope that it will be useful, 15 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | ;; GNU General Public License for more details. 18 | 19 | ;; You should have received a copy of the GNU General Public License 20 | ;; along with this program. If not, see . 21 | 22 | ;;; Commentary: 23 | ;; 24 | (require 'diff-hl) 25 | 26 | (global-diff-hl-mode) 27 | 28 | (add-hook 'magit-pre-refresh-hook 'diff-hl-magit-pre-refresh) 29 | (add-hook 'magit-post-refresh-hook 'diff-hl-magit-post-refresh) 30 | 31 | (provide 'cc-diff-hl-mode) 32 | 33 | ;;; cc-diff-hl-mode.el ends here 34 | -------------------------------------------------------------------------------- /cc-digital-logic.el: -------------------------------------------------------------------------------- 1 | ;;; cc-digital-logic.el --- Digital Boolean Operations -*- lexical-binding: t; -*- 2 | 3 | ;; Copyright (C) 2024 Charles Choi 4 | 5 | ;; Author: Charles Choi 6 | ;; Keywords: tools 7 | 8 | ;; This program is free software; you can redistribute it and/or modify 9 | ;; it under the terms of the GNU General Public License as published by 10 | ;; the Free Software Foundation, either version 3 of the License, or 11 | ;; (at your option) any later version. 12 | 13 | ;; This program is distributed in the hope that it will be useful, 14 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | ;; GNU General Public License for more details. 17 | 18 | ;; You should have received a copy of the GNU General Public License 19 | ;; along with this program. If not, see . 20 | 21 | ;;; Commentary: 22 | 23 | ;; This is a library of functions for performing digital boolean logic where 24 | ;; the only legal input values are 0 and 1. 25 | 26 | ;; The following boolean logic operations are supported: 27 | ;; - multi-input and (`digital-and') 28 | ;; - multi-input or (`digital-or') 29 | ;; - multi-input nand (`digital-nand') 30 | ;; - multi-input nor (`digital-nor') 31 | ;; - 2-input xor (`digital-xor') 32 | 33 | ;;; Code: 34 | (require 'shortdoc) 35 | 36 | (defun digital-value-to-bool (a) 37 | "Convert digital value A to Elisp boolean type." 38 | (cond 39 | ((eq a 0) nil) 40 | ((eq a 1) t) 41 | (t (error "Invalid input: %S" a)))) 42 | 43 | (defun digital-bool-to-value (a) 44 | "Convert Elisp boolean A to digital value." 45 | (cond 46 | ((eq a t) 1) 47 | ((eq a nil) 0) 48 | ((eq a 1) 1) 49 | ((eq a 0) 0) 50 | (t (error "Invalid input: %S" a)))) 51 | 52 | (defun digital-and (a b &rest c) 53 | "Digital and operation on operands A, B and if available sequence C." 54 | (let* ((args (list a b)) 55 | (args (append c args)) 56 | (bool-args (mapcar 'digital-value-to-bool args))) 57 | (digital-bool-to-value (seq-reduce '(lambda (x y) (and x y)) bool-args t)))) 58 | 59 | (defun digital-nand (a b &rest c) 60 | "Digital nand operation on operands A, B and if available sequence C." 61 | (let* ((args (list a b)) 62 | (args (append c args)) 63 | (bool-args (mapcar 'digital-value-to-bool args))) 64 | (digital-bool-to-value 65 | (not (seq-reduce '(lambda (x y) (and x y)) bool-args t))))) 66 | 67 | (defun digital-or (a b &rest c) 68 | "Digital or operation on operands A, B and if available sequence C." 69 | (let* ((args (list a b)) 70 | (args (append c args)) 71 | (bool-args (mapcar 'digital-value-to-bool args))) 72 | (digital-bool-to-value (seq-reduce '(lambda (x y) (or x y)) bool-args nil)))) 73 | 74 | (defun digital-nor (a b &rest c) 75 | "Digital nor operation on operands A, B and if available sequence C." 76 | (let* ((args (list a b)) 77 | (args (append c args)) 78 | (bool-args (mapcar 'digital-value-to-bool args))) 79 | (digital-bool-to-value 80 | (not (seq-reduce '(lambda (x y) (or x y)) bool-args nil))))) 81 | 82 | (defun digital-xor (a b) 83 | "Digital xor operation on operands A and B." 84 | (let ((i (digital-value-to-bool a)) 85 | (j (digital-value-to-bool b))) 86 | (digital-bool-to-value (xor i j)))) 87 | 88 | (define-short-documentation-group digital-logic 89 | "Digital Logic Operations" 90 | (digital-and 91 | :eval (digital-and 0 0 0 0 ) 92 | :eval (digital-and 1 1 1 1) 93 | :no-manual) 94 | (digital-or 95 | :eval (digital-or 0 0 0 0 ) 96 | :eval (digital-or 1 1 1 1) 97 | :no-manual) 98 | (digital-nand 99 | :eval (digital-nand 0 0 0 0 ) 100 | :eval (digital-nand 1 1 1 1) 101 | :no-manual) 102 | (digital-nor 103 | :eval (digital-nor 0 0 0 0) 104 | :eval (digital-nor 1 1 1 1) 105 | :no-manual) 106 | (digital-xor 107 | :eval (digital-xor 0 0) 108 | :eval (digital-xor 0 1) 109 | :eval (digital-xor 1 0) 110 | :eval (digital-xor 1 1) 111 | :no-manual)) 112 | 113 | (provide 'cc-digital-logic) 114 | ;;; cc-digital-logic.el ends here 115 | -------------------------------------------------------------------------------- /cc-dired-mode.el: -------------------------------------------------------------------------------- 1 | ;;; cc-dired-mode.el --- Dired Customization -*- lexical-binding: t -*- 2 | 3 | ;; Copyright (C) 2023-2025 Charles Choi 4 | 5 | ;; Author: Charles Choi 6 | 7 | ;; Keywords: tools 8 | 9 | ;; This program is free software; you can redistribute it and/or modify 10 | ;; it under the terms of the GNU General Public License as published by 11 | ;; the Free Software Foundation, either version 3 of the License, or 12 | ;; (at your option) any later version. 13 | 14 | ;; This program is distributed in the hope that it will be useful, 15 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | ;; GNU General Public License for more details. 18 | 19 | ;; You should have received a copy of the GNU General Public License 20 | ;; along with this program. If not, see . 21 | 22 | ;;; Commentary: 23 | ;; 24 | 25 | ;;; Code: 26 | (require 'dired) 27 | (require 'dired-x) 28 | (require 'cclisp) 29 | (require 'wdired) 30 | (require 'image-dired) 31 | (require 'image-dired-dired) 32 | (require 'casual-dired) 33 | (require 'casual-editkit) 34 | (require 'cc-main-tmenu) 35 | 36 | ;; (use-package image-dired 37 | ;; :defer t 38 | ;; :bind (:map 39 | ;; image-dired-thumbnail-mode-map 40 | ;; ("n" . #'image-dired-display-next) 41 | ;; ("p" . #'image-dired-display-previous)) 42 | ;; :after (dired)) 43 | 44 | ;; (use-package image-dired-dired 45 | ;; :defer t 46 | ;; :bind (:map 47 | ;; dired-mode-map 48 | ;; (";" . #'image-dired-dired-toggle-marked-thumbs)) 49 | ;; :after (image-dired)) 50 | 51 | ;; (use-package wdired 52 | ;; :defer t 53 | ;; :bind (:map 54 | ;; dired-mode-map 55 | ;; ("E" . #'wdired-change-to-wdired-mode)) 56 | ;; :after (dired)) 57 | 58 | ;; (use-package dired-x 59 | ;; :defer t 60 | ;; :after (dired)) 61 | 62 | 63 | ;; (use-package browse-url 64 | ;; :defer t) 65 | 66 | ;; (use-package cclisp :defer t) 67 | ;; (use-package cc-main-tmenu :defer t) 68 | 69 | ;; (use-package dired 70 | ;; :bind (:map 71 | ;; dired-mode-map 72 | ;; ("M-o" . #'dired-omit-mode) 73 | ;; ("M-p" . #'dired-prev-dirline) 74 | ;; ("M-n" . #'dired-next-dirline) 75 | ;; ("[" . #'dired-prev-subdir) 76 | ;; ("]" . #'dired-next-subdir) 77 | ;; ("M-j" . #'dired-goto-subdir) 78 | ;; ("TAB" . #'dired-next-subdir) 79 | ;; ("" . #'dired-prev-subdir) 80 | ;; ("A-M-" . #'browse-url-of-dired-file) 81 | ;; ("C-M-o" . #'casual-editkit-main-tmenu)) 82 | ;; :after (browse-url cclisp cc-main-tmenu)) 83 | 84 | ;; (use-package casual-dired 85 | ;; :bind (:map dired-mode-map 86 | ;; ("C-o" . #'casual-dired-tmenu) 87 | ;; ("s" . #'casual-dired-sort-by-tmenu) 88 | ;; ("/" . #'casual-dired-search-replace-tmenu)) 89 | ;; ) 90 | ;; ;; :after (dired image-dired image-dired-dired wdired)) 91 | 92 | ;; (use-package mouse 93 | ;; :hook ((dired-mode . context-menu-mode))) 94 | 95 | ;; (use-package dired-async 96 | ;; :hook ((dired-mode . dired-async-mode))) 97 | 98 | ;; (use-package hl-line 99 | ;; :hook ((dired-mode . hl-line-mode))) 100 | 101 | 102 | (add-hook 'dired-mode-hook 'hl-line-mode) 103 | (add-hook 'dired-mode-hook 'context-menu-mode) 104 | (add-hook 'dired-mode-hook 'dired-async-mode) 105 | (add-hook 106 | 'dired-mode-hook 107 | (lambda () 108 | (setq-local mouse-1-click-follows-link 'double))) 109 | 110 | (keymap-set dired-mode-map "" #'dired-mouse-find-file) 111 | (keymap-set dired-mode-map "M-o" #'dired-omit-mode) 112 | (keymap-set dired-mode-map "C-M-o" #'casual-editkit-main-tmenu) 113 | (keymap-set dired-mode-map "E" #'wdired-change-to-wdired-mode) 114 | (keymap-set dired-mode-map "C-o" #'casual-dired-tmenu) 115 | (keymap-set dired-mode-map "s" #'casual-dired-sort-by-tmenu) 116 | (keymap-set dired-mode-map "/" #'casual-dired-search-replace-tmenu) 117 | (keymap-set dired-mode-map "M-n" #'dired-next-dirline) 118 | (keymap-set dired-mode-map "M-p" #'dired-prev-dirline) 119 | (keymap-set dired-mode-map "]" #'dired-next-subdir) 120 | (keymap-set dired-mode-map "[" #'dired-prev-subdir) 121 | (keymap-set dired-mode-map "M-j" #'dired-goto-subdir) 122 | (keymap-set dired-mode-map ";" #'image-dired-dired-toggle-marked-thumbs) 123 | 124 | ;; Added to be consistent with IBuffer 125 | (keymap-set dired-mode-map "" #'dired-prev-subdir) 126 | (keymap-set dired-mode-map "TAB" #'dired-next-subdir) 127 | 128 | (keymap-set dired-mode-map "A-M-" #'browse-url-of-dired-file) 129 | 130 | (keymap-set image-dired-thumbnail-mode-map "n" #'image-dired-display-next) 131 | (keymap-set image-dired-thumbnail-mode-map "p" #'image-dired-display-previous) 132 | 133 | (add-hook 'wdired-mode-hook 'superword-mode) 134 | 135 | (defun eli/dired--move-to-next-line (arg jumpfun) 136 | (let ((wrapped nil) 137 | (old-arg arg) 138 | (old-position (progn 139 | ;; It's always true that we should move 140 | ;; to the filename when possible. 141 | (dired-move-to-filename) 142 | (point))) 143 | ;; Up/Down indicates the direction. 144 | (moving-down (if (cl-plusp arg) 145 | 1 ; means Down. 146 | -1))) ; means Up. 147 | ;; Line by line in case we forget to skip empty lines. 148 | (while (not (zerop arg)) 149 | (funcall jumpfun moving-down) 150 | (when (= old-position (point)) 151 | ;; Now point is at beginning/end of movable area, 152 | ;; but it still wants to move farther. 153 | (cond 154 | ;; `cycle': go to the other end. 155 | ((eq dired-movement-style 'cycle) 156 | ;; Argument not changing on the second wrap 157 | ;; means infinite loop with no files found. 158 | (if (and wrapped (eq old-arg arg)) 159 | (setq arg 0) 160 | (goto-char (if (cl-plusp moving-down) 161 | (point-min) 162 | (point-max)))) 163 | (setq wrapped t)) 164 | ;; `bounded': go back to the last non-empty line. 165 | (dired-movement-style ; Either 'bounded or anything else non-nil. 166 | (while (and (dired-between-files) 167 | (not (dired-get-subdir)) 168 | (not (zerop arg))) 169 | (funcall jumpfun (- moving-down)) 170 | ;; Point not moving means infinite loop. 171 | (if (= old-position (point)) 172 | (setq arg 0) 173 | (setq old-position (point)))) 174 | ;; Encountered a boundary, so let's stop movement. 175 | (setq arg (if (and (dired-between-files) 176 | (not (dired-get-subdir))) 177 | 0 moving-down))))) 178 | (unless (and (dired-between-files) (not (dired-get-subdir))) 179 | ;; Has moved to a non-empty line. This movement does 180 | ;; make sense. 181 | (cl-decf arg moving-down)) 182 | (setq old-position (point))))) 183 | 184 | 185 | (advice-add #'dired--move-to-next-line :override #'eli/dired--move-to-next-line) 186 | 187 | (provide 'cc-dired-mode) 188 | ;;; cc-dired-mode.el ends here 189 | -------------------------------------------------------------------------------- /cc-doc-mode-ux.el: -------------------------------------------------------------------------------- 1 | ;;; cc-doc-mode-ux.el --- Doc Mode UX Mods -*- lexical-binding: t; -*- 2 | 3 | ;; Copyright (C) 2023-2024 Charles Choi 4 | 5 | ;; Author: Charles Choi 6 | 7 | ;; Keywords: tools 8 | 9 | ;; This program is free software; you can redistribute it and/or modify 10 | ;; it under the terms of the GNU General Public License as published by 11 | ;; the Free Software Foundation, either version 3 of the License, or 12 | ;; (at your option) any later version. 13 | 14 | ;; This program is distributed in the hope that it will be useful, 15 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | ;; GNU General Public License for more details. 18 | 19 | ;; You should have received a copy of the GNU General Public License 20 | ;; along with this program. If not, see . 21 | 22 | ;;; Commentary: 23 | ;; UX modifications for different Emacs documentation modes. 24 | ;; Covers Info, Help, Man, and Shortdoc. 25 | 26 | ;;; Code: 27 | (require 'info) 28 | (require 'help) 29 | (require 'shortdoc) 30 | (require 'man) 31 | (require 'hl-line) 32 | (require 'simple) 33 | (require 'cclisp) 34 | (require 'casual-info) 35 | 36 | (defun cc/confirm-before-quit-window () 37 | "Raise confirm prompt before invoking `quit-window'." 38 | (interactive) 39 | (if (y-or-n-p "Really Quit? ") 40 | (quit-window) 41 | (message "all good"))) 42 | 43 | ;; # Info 44 | ;; Prompt before quitting 45 | ;;(keymap-set Info-mode-map "q" 'cc/confirm-before-quit-window) 46 | ;; Use web-browser history navigation bindings 47 | (keymap-set Info-mode-map "M-[" #'Info-history-back) 48 | (keymap-set Info-mode-map "M-]" #'Info-history-forward) 49 | ;; Bind p and n to paragraph navigation 50 | (keymap-set Info-mode-map "p" #'casual-info-browse-backward-paragraph) 51 | (keymap-set Info-mode-map "n" #'casual-info-browse-forward-paragraph) 52 | ;; Bind to help 53 | (keymap-set Info-mode-map "" #'Info-help) 54 | ;; Bind h and l to navigate to previous and next nodes 55 | ;; Bind j and k to navigate to next and previous references 56 | (keymap-set Info-mode-map "h" #'Info-prev) 57 | (keymap-set Info-mode-map "j" #'Info-next-reference) 58 | (keymap-set Info-mode-map "k" #'Info-prev-reference) 59 | (keymap-set Info-mode-map "l" #'Info-next) 60 | ;; Bind / to search 61 | (keymap-set Info-mode-map "/" #'Info-search) 62 | ;; Set Bookmark 63 | (keymap-set Info-mode-map "B" #'bookmark-set) 64 | ;; Bind side mouse buttons on Logitech mouse 65 | (keymap-set Info-mode-map "" #'Info-history-forward) 66 | (keymap-set Info-mode-map "" #'Info-history-back) 67 | 68 | (add-hook 'Info-mode-hook #'hl-line-mode) 69 | (add-hook 'Info-mode-hook #'scroll-lock-mode) 70 | 71 | ;; # Help 72 | ;; Use web-browser history navigation bindings 73 | (keymap-set help-mode-map "M-[" #'help-go-back) 74 | (keymap-set help-mode-map "M-]" #'help-go-forward) 75 | ;; Bind p and n to paragraph navigation 76 | (keymap-set help-mode-map "p" #'casual-info-browse-backward-paragraph) 77 | (keymap-set help-mode-map "n" #'casual-info-browse-forward-paragraph) 78 | ;; Bind to help 79 | (keymap-set help-mode-map "" #'describe-mode) 80 | ;; Bind M-j, M-k to scrolling up/down line 81 | (keymap-set help-mode-map "M-j" #'scroll-up-line) 82 | (keymap-set help-mode-map "M-k" #'scroll-down-line) 83 | ;; Bind j and k to navigate to forward and backward buttons 84 | (keymap-set help-mode-map "j" #'forward-button) 85 | (keymap-set help-mode-map "k" #'backward-button) 86 | ;; Bind side mouse buttons on Logitech mouse 87 | (keymap-set help-mode-map "" #'help-go-forward) 88 | (keymap-set help-mode-map "" #'help-go-back) 89 | 90 | (add-hook 'help-mode-hook #'hl-line-mode) 91 | (add-hook 'help-mode-hook #'scroll-lock-mode) 92 | 93 | ;; # Shortdoc 94 | ;; Bind to help 95 | (keymap-set shortdoc-mode-map "" #'describe-mode) 96 | ;; Bind M-j, M-k to scrolling up/down line 97 | (keymap-set shortdoc-mode-map "M-j" #'scroll-up-line) 98 | (keymap-set shortdoc-mode-map "M-k" #'scroll-down-line) 99 | ;; Bind h and l to navigate to previous and next sections 100 | ;; Bind j and k to navigate to next and previous 101 | (keymap-set shortdoc-mode-map "h" #'shortdoc-previous-section) 102 | (keymap-set shortdoc-mode-map "j" #'shortdoc-next) 103 | (keymap-set shortdoc-mode-map "k" #'shortdoc-previous) 104 | (keymap-set shortdoc-mode-map "l" #'shortdoc-next-section) 105 | 106 | (add-hook 'shortdoc-mode-hook #'hl-line-mode) 107 | (add-hook 'shortdoc-mode-hook #'scroll-lock-mode) 108 | 109 | ;; # Man 110 | ;; Bind to help 111 | (keymap-set Man-mode-map "" #'describe-mode) 112 | ;; Bind M-j, M-k to scrolling up/down line 113 | (keymap-set Man-mode-map "M-j" #'scroll-up-line) 114 | (keymap-set Man-mode-map "M-k" #'scroll-down-line) 115 | ;; Bind j and k to navigate forward and backward paragraphs 116 | (keymap-set Man-mode-map "j" #'casual-info-browse-forward-paragraph) 117 | (keymap-set Man-mode-map "k" #'casual-info-browse-backward-paragraph) 118 | ;; Bind K to kill buffer to replace override of default k above 119 | (keymap-set Man-mode-map "K" #'Man-kill) 120 | 121 | (add-hook 'Man-mode-hook #'hl-line-mode) 122 | (add-hook 'Man-mode-hook #'scroll-lock-mode) 123 | 124 | (provide 'cc-doc-mode-ux) 125 | 126 | ;;; cc-doc-mode-ux.el ends here 127 | -------------------------------------------------------------------------------- /cc-ediff-mode.el: -------------------------------------------------------------------------------- 1 | ;;; cc-ediff-mode.el --- Ediff configuration -*- lexical-binding: t; -*- 2 | 3 | ;; Copyright (C) 2023-2025 Charles Choi 4 | 5 | ;; Author: Charles Choi 6 | 7 | ;; Keywords: tools 8 | 9 | ;; This program is free software; you can redistribute it and/or modify 10 | ;; it under the terms of the GNU General Public License as published by 11 | ;; the Free Software Foundation, either version 3 of the License, or 12 | ;; (at your option) any later version. 13 | 14 | ;; This program is distributed in the hope that it will be useful, 15 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | ;; GNU General Public License for more details. 18 | 19 | ;; You should have received a copy of the GNU General Public License 20 | ;; along with this program. If not, see . 21 | 22 | ;;; Commentary: 23 | ;; 24 | 25 | (require 'ediff) 26 | (require 'casual-lib) 27 | ;;; Code: 28 | 29 | ;; these defvars are here to let cc-ediff-mode.el compile clean 30 | (defvar ediff-buffer-A) 31 | (defvar ediff-buffer-B) 32 | (defvar ediff-buffer-C) 33 | (defvar ediff-merge-job) 34 | (defvar ediff-ancestor-buffer) 35 | 36 | ;; CC: I set my Ediff variables in `custom-set-variables' 37 | ;; Use your own preference. 38 | ;; '(ediff-keep-variants nil) 39 | ;; '(ediff-split-window-function 'split-window-horizontally) 40 | ;; '(ediff-window-setup-function 'ediff-setup-windows-plain) 41 | 42 | (defvar cc/ediff-revision-session-p nil 43 | "If t then `cc/ediff-revision-actual' has been called. 44 | This state variable is used to insert added behavior to the overridden 45 | function `ediff-janitor'.") 46 | 47 | (defun cc/ediff-revision-from-menu (e) 48 | "Invoke `ediff-revision' on E with variable `buffer-file-name'." 49 | (interactive "e") 50 | (ignore e) 51 | (cc/ediff-revision)) 52 | 53 | (defun cc/ediff-revision () 54 | "Run Ediff on the current `buffer-file-name' provided that it is `vc-registered'. 55 | This function handles the interactive concerns found in `ediff-revision'. 56 | This function will also test if a diff should apply to the current buffer." 57 | (interactive) 58 | (when (and (bound-and-true-p buffer-file-name) 59 | (vc-registered (buffer-file-name))) 60 | (if (and (buffer-modified-p) 61 | (y-or-n-p (format "Buffer %s is modified. Save buffer? " 62 | (buffer-name)))) 63 | (save-buffer (current-buffer))) 64 | (message buffer-file-name) 65 | (cc/ediff-revision-actual)) 66 | 67 | (cond ((not (bound-and-true-p buffer-file-name)) 68 | (message (concat (buffer-name) " is not a file that can be diffed."))) 69 | ((not (vc-registered buffer-file-name)) 70 | (message (concat buffer-file-name " is not under version control."))))) 71 | 72 | (defun cc/ediff-revision-actual () 73 | "Invoke Ediff logic to diff the modified repo file to its counterpart in the 74 | current branch. 75 | This function handles the actual diff behavior called by `ediff-revision'." 76 | (let ((rev1 "") 77 | (rev2 "")) 78 | (setq cc/ediff-revision-session-p t) 79 | (ediff-load-version-control) 80 | (funcall 81 | (intern (format "ediff-%S-internal" ediff-version-control-package)) 82 | rev1 rev2 nil))) 83 | 84 | (defun cc/ediff-janitor (ask keep-variants) 85 | "Kill buffers A, B, and, possibly, C, if these buffers aren't modified. 86 | In merge jobs, buffer C is not deleted here, but rather according to 87 | `ediff-quit-merge-hook'. 88 | ASK non-nil means ask the user whether to keep each unmodified buffer, unless 89 | KEEP-VARIANTS is non-nil, in which case buffers are never killed. 90 | A side effect of cleaning up may be that you should be careful when comparing 91 | the same buffer in two separate Ediff sessions: quitting one of them might 92 | delete this buffer in another session as well. 93 | 94 | CC MODIFICATION: This method overrides the original Ediff function." 95 | (let ((ask (if (and (boundp 'cc/ediff-revision-session-p) 96 | cc/ediff-revision-session-p) 97 | nil 98 | ask))) 99 | (ediff-dispose-of-variant-according-to-user 100 | ediff-buffer-A 'A ask keep-variants) 101 | ;; !!!: CC Note: Test global state variable `cc/ediff-revision-session-p' to 102 | ;; determine if the modified repo file should be kept. 103 | ;; Guarding in place to hopefully avoid side-effects when `ediff-janitor' is 104 | ;; called from other Ediff functions. Informal testing has not revealed any 105 | ;; side-effects but YOLO. 106 | (if (and (boundp 'cc/ediff-revision-session-p) 107 | cc/ediff-revision-session-p) 108 | (ediff-dispose-of-variant-according-to-user 109 | ;; CC Note: keep-variants argument is hard-coded to t to keep 110 | ;; buffer holding modified repo file around. 111 | ediff-buffer-B 'B t t) 112 | (ediff-dispose-of-variant-according-to-user 113 | ediff-buffer-B 'B ask keep-variants)) 114 | (if ediff-merge-job ; don't del buf C if merging--del ancestor buf instead 115 | (ediff-dispose-of-variant-according-to-user 116 | ediff-ancestor-buffer 'Ancestor ask keep-variants) 117 | (ediff-dispose-of-variant-according-to-user 118 | ediff-buffer-C 'C ask keep-variants)) 119 | ;; CC Note: Reset global state variable `cc/ediff-revision-session-p'. 120 | (if (and (boundp 'cc/ediff-revision-session-p) 121 | cc/ediff-revision-session-p) 122 | (setq cc/ediff-revision-session-p nil)))) 123 | 124 | (advice-add 'ediff-janitor :override #'cc/ediff-janitor) 125 | ;; (advice-remove 'ediff-janitor #'cc/ediff-janitor) 126 | 127 | (defun cc/stash-window-configuration-for-ediff () 128 | "Store window configuration to register 🧊. 129 | Use of emoji is to avoid potential use of keyboard character to reference 130 | the register." 131 | (window-configuration-to-register ?🧊)) 132 | 133 | (defun cc/restore-window-configuration-for-ediff () 134 | "Restore window configuration from register 🧊. 135 | Use of emoji is to avoid potential use of keyboard character to reference 136 | the register." 137 | (jump-to-register ?🧊)) 138 | 139 | (add-hook 'ediff-before-setup-hook #'cc/stash-window-configuration-for-ediff) 140 | ;; !!!: CC Note: Why this is not `ediff-quit-hook' I do not know. But this works 141 | ;; for cleaning up ancillary buffers on quitting an Ediff session. 142 | (add-hook 'ediff-after-quit-hook-internal #'cc/restore-window-configuration-for-ediff) 143 | 144 | 145 | (transient-define-prefix casual-ediff-tmenu () 146 | :refresh-suffixes t 147 | ["Casual Ediff" 148 | ["A" 149 | :if (lambda () (and ediff-buffer-A) (not ediff-buffer-C)) 150 | :description (lambda () (format "A: %s" (buffer-name ediff-buffer-A))) 151 | ("a" "A→B" ediff-copy-A-to-B 152 | :transient t 153 | :if-not (lambda () (casual-ediff-buffer-read-only-p ediff-buffer-B))) 154 | ("ra" "Restore A" 155 | (lambda () 156 | (interactive) 157 | (casual-ediff-restore-diff ?a) 158 | (casual-ediff-save-buffer ?a)) 159 | :transient t 160 | :if-not (lambda () (casual-ediff-buffer-read-only-p ediff-buffer-A)) 161 | :inapt-if-not (lambda () (buffer-modified-p ediff-buffer-A)))] 162 | 163 | ["A" 164 | :if (lambda () (and ediff-buffer-A ediff-buffer-C)) 165 | :description (lambda () (format "A: %s" (buffer-name ediff-buffer-A))) 166 | ("ac" "A→C" ediff-copy-A-to-C 167 | :transient t 168 | :if-not (lambda () (casual-ediff-buffer-read-only-p ediff-buffer-C))) 169 | ("ra" "Restore A" 170 | (lambda () 171 | (interactive) 172 | (casual-ediff-restore-diff ?a) 173 | (casual-ediff-save-buffer ?a)) 174 | :transient t 175 | :if-not (lambda () (casual-ediff-buffer-read-only-p ediff-buffer-A)) 176 | :inapt-if-not (lambda () (buffer-modified-p ediff-buffer-A)))] 177 | 178 | 179 | ["Diff" 180 | :if (lambda () (not ediff-buffer-C)) 181 | ("p" "↑" ediff-previous-difference :transient t) 182 | ("n" "↓" ediff-next-difference :transient t) 183 | ("!" "⟲" ediff-update-diffs :transient t) 184 | ("|" "H/V" ediff-toggle-split 185 | :transient t 186 | :description (lambda () 187 | (if (eq ediff-split-window-function 'split-window-vertically) 188 | "Split ――" 189 | "Split |"))) 190 | ("#" "Skip 𝑤𝑠" ediff-toggle-skip-similar :transient t 191 | :description (lambda () 192 | (if ediff-ignore-similar-regions 193 | "Include 𝑤𝑠" 194 | "Skip 𝑤𝑠")))] 195 | 196 | ["B" 197 | :if (lambda () (and ediff-buffer-B (not ediff-buffer-C))) 198 | :description (lambda () (format "B: %s" (buffer-name ediff-buffer-B))) 199 | ("b" "A←B" ediff-copy-B-to-A :transient t 200 | :if-not (lambda () (casual-ediff-buffer-read-only-p ediff-buffer-A))) 201 | 202 | ;; ("bc" "B→C" ediff-copy-B-to-C :transient t 203 | ;; :if-not (lambda () (casual-ediff-buffer-read-only-p ediff-buffer-C))) 204 | 205 | ("wb" "Save B" 206 | (lambda () 207 | (interactive) 208 | (casual-ediff-save-buffer ?b)) 209 | :transient t 210 | :if-not (lambda () (casual-ediff-buffer-read-only-p ediff-buffer-B)) 211 | :inapt-if-not (lambda () (buffer-modified-p ediff-buffer-B))) 212 | 213 | ("rb" "Restore B" 214 | (lambda () 215 | (interactive) 216 | (casual-ediff-restore-diff ?b) 217 | (casual-ediff-save-buffer ?b)) 218 | :transient t 219 | :if-not (lambda () (casual-ediff-buffer-read-only-p ediff-buffer-B)) 220 | :inapt-if-not (lambda () (buffer-modified-p ediff-buffer-B)))] 221 | 222 | 223 | ["B" 224 | :if (lambda () (if (and ediff-buffer-B ediff-buffer-C) t nil)) 225 | :description (lambda () (format "B: %s" (buffer-name ediff-buffer-B))) 226 | ("ba" "A←B" ediff-copy-B-to-A :transient t 227 | :if-not (lambda () (casual-ediff-buffer-read-only-p ediff-buffer-A))) 228 | 229 | ("bc" "B→C" ediff-copy-B-to-C :transient t 230 | :if-not (lambda () (casual-ediff-buffer-read-only-p ediff-buffer-C))) 231 | 232 | ("wb" "Save B" 233 | (lambda () 234 | (interactive) 235 | (casual-ediff-save-buffer ?b)) 236 | :transient t 237 | :if (lambda () 238 | (if (string= (file-name-extension (buffer-name ediff-buffer-B)) "~{index}") 239 | nil 240 | (if (not (casual-ediff-buffer-read-only-p ediff-buffer-B)) 241 | t 242 | nil))) 243 | :inapt-if-not (lambda () (buffer-modified-p ediff-buffer-B))) 244 | 245 | ("rb" "Restore B" 246 | (lambda () 247 | (interactive) 248 | (casual-ediff-restore-diff ?b) 249 | (casual-ediff-save-buffer ?b)) 250 | :transient t 251 | :if (lambda () 252 | (if (string= (file-name-extension (buffer-name ediff-buffer-B)) "~{index}") 253 | nil 254 | (if (not (casual-ediff-buffer-read-only-p ediff-buffer-B)) 255 | t 256 | nil))) 257 | :inapt-if-not (lambda () (buffer-modified-p ediff-buffer-B)))] 258 | 259 | ["Diff" 260 | :if (lambda () (and ediff-buffer-C t)) 261 | ("p" "↑" ediff-previous-difference :transient t) 262 | ("n" "↓" ediff-next-difference :transient t) 263 | ("!" "⟲" ediff-update-diffs :transient t) 264 | ("|" "H/V" ediff-toggle-split 265 | :description (lambda () 266 | (if (eq ediff-split-window-function 'split-window-vertically) 267 | "Split ――" 268 | "Split |")) 269 | :transient t)] 270 | 271 | ["C" 272 | :if (lambda () (if ediff-buffer-C t nil)) 273 | :description (lambda () 274 | (if ediff-buffer-C 275 | (format "C: %s" (buffer-name ediff-buffer-C)) 276 | )) 277 | 278 | ("cb" "B←C" ediff-copy-C-to-B :transient t 279 | :if (lambda () 280 | (if (not (casual-ediff-buffer-read-only-p ediff-buffer-B)) 281 | (if (string= (file-name-extension (buffer-name ediff-buffer-B)) "~{index}") 282 | nil 283 | t) 284 | nil))) 285 | 286 | ("ca" "A←C" ediff-copy-C-to-A :transient t 287 | :if-not (lambda () (casual-ediff-buffer-read-only-p ediff-buffer-A))) 288 | 289 | ("rc" "Restore C" 290 | (lambda () 291 | (interactive) 292 | (casual-ediff-restore-diff ?c) 293 | (casual-ediff-save-buffer ?c)) 294 | :transient t 295 | :if (lambda () 296 | (if (not (casual-ediff-buffer-read-only-p ediff-buffer-C)) 297 | (if (not (string= (buffer-name ediff-buffer-C) "*ediff-merge*")) 298 | t 299 | nil) 300 | nil)) 301 | :inapt-if-not (lambda () (buffer-modified-p ediff-buffer-C))) 302 | 303 | ;; Note: Ediff doesn't support combining merge conflicts from both. The 304 | ;; workaround is to directly edit the C buffer. 305 | 306 | ;; TODO: The buffer *ediff-merge* is already modified. How can you tell if it needs to be restored? 307 | 308 | ("r" "Restore Merge" 309 | (lambda () 310 | (interactive) 311 | (ediff-restore-diff-in-merge-buffer nil)) 312 | :transient t 313 | :if (lambda () 314 | (if (not (casual-ediff-buffer-read-only-p ediff-buffer-C)) 315 | (if (string= (buffer-name ediff-buffer-C) "*ediff-merge*") 316 | t 317 | nil) 318 | nil)))]] 319 | 320 | [:class transient-row 321 | (casual-lib-quit-one) 322 | ("q" "Quit Ediff" ediff-quit)]) 323 | 324 | (defun casual-ediff-restore-diff (key) 325 | (interactive) 326 | (ediff-restore-diff nil key)) 327 | 328 | (defun casual-ediff-save-buffer (key) 329 | (interactive) 330 | (setq last-command-event key) 331 | (ediff-save-buffer nil)) 332 | 333 | (defun casual-ediff-buffer-read-only-p (buf) 334 | (with-current-buffer buf 335 | (if buffer-read-only t nil))) 336 | 337 | (add-hook 'ediff-keymap-setup-hook 338 | (lambda () 339 | (keymap-set ediff-mode-map "C-o" #'casual-ediff-tmenu))) 340 | 341 | (provide 'cc-ediff-mode) 342 | 343 | ;;; cc-ediff-mode.el ends here 344 | -------------------------------------------------------------------------------- /cc-edit-text-menu.el: -------------------------------------------------------------------------------- 1 | ;;; cc-edit-text-menu.el --- Edit Text Menus -*- lexical-binding: t; -*- 2 | 3 | ;; Copyright (C) 2023-2024 Charles Choi 4 | 5 | ;; Author: Charles Choi 6 | 7 | ;; Keywords: tools 8 | 9 | ;; This program is free software; you can redistribute it and/or modify 10 | ;; it under the terms of the GNU General Public License as published by 11 | ;; the Free Software Foundation, either version 3 of the License, or 12 | ;; (at your option) any later version. 13 | 14 | ;; This program is distributed in the hope that it will be useful, 15 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | ;; GNU General Public License for more details. 18 | 19 | ;; You should have received a copy of the GNU General Public License 20 | ;; along with this program. If not, see . 21 | 22 | ;;; Commentary: 23 | ;; 24 | 25 | (require 'casual-editkit) 26 | 27 | (easy-menu-define cc/transpose-menu nil 28 | "Keymap for Transpose submenu" 29 | '("Transpose" 30 | :visible (not buffer-read-only) 31 | ["Characters" transpose-chars 32 | :help "Interchange characters around point, moving forward one character."] 33 | 34 | ["Words" transpose-words 35 | :help "Interchange words around point, leaving point at end of them."] 36 | 37 | ["Lines" transpose-lines 38 | :help "Exchange current line and previous line, leaving point after both."] 39 | 40 | ["Sentences" transpose-sentences 41 | :help "Interchange the current sentence with the next one."] 42 | 43 | ["Paragraphs" transpose-paragraphs 44 | :help "Interchange the current paragraph with the next one."] 45 | 46 | ["Regions" transpose-regions 47 | :help "region STARTR1 to ENDR1 with STARTR2 to ENDR2."] 48 | 49 | ["Balanced Expressions (sexps)" transpose-sexps 50 | :help "Like C-t (‘transpose-chars’), but applies to balanced \ 51 | expressions (sexps)."])) 52 | 53 | (easy-menu-define cc/move-text-menu nil 54 | "Keymap for Move Text submenu" 55 | '("Move Text" 56 | :visible (not buffer-read-only) 57 | ["Word Forward" casual-editkit-move-word-forward 58 | :help "Move word to the right of point forward one word."] 59 | 60 | ["Word Backward" casual-editkit-move-word-backward 61 | :help "Move word to the right of point backward one word."] 62 | 63 | ["Sentence Forward" casual-editkit-move-sentence-forward 64 | :help "Move sentence to the right of point forward one sentence."] 65 | 66 | ["Sentence Backward" casual-editkit-move-sentence-backward 67 | :help "Move sentence to the right of point backward one sentence."] 68 | 69 | ["Balanced Expression (sexp) Forward" casual-editkit-move-sexp-forward 70 | :help "Move balanced expression (sexp) to the right of point forward \ 71 | one sexp."] 72 | 73 | ["Balanced Expression (sexp) Backward" casual-editkit-move-sexp-backward 74 | :help "Move balanced expression (sexp) to the right of point backward \ 75 | one sexp."])) 76 | 77 | (easy-menu-define cc/delete-space-menu nil 78 | "Keymap for Deleting Space submenu" 79 | '("Delete Space" 80 | :visible (not buffer-read-only) 81 | ["Join Line" join-line 82 | :help "Join this line to previous and fix up \ 83 | whitespace at join"] 84 | 85 | ["Just One Space" just-one-space 86 | :help "Delete all spaces and tabs around point, leaving \ 87 | one space."] 88 | 89 | ["Delete Horizontal Space" delete-horizontal-space 90 | :help "Delete all spaces and tabs around point."] 91 | 92 | ["Delete Blank Lines" delete-blank-lines 93 | :help "On blank line, delete all surrounding blank lines, \ 94 | leaving just one."] 95 | 96 | ["Whitespace Cleanup" whitespace-cleanup 97 | :help "Cleanup some blank problems in all buffer or at region."] 98 | 99 | ["Delete Trailing Whitespace" delete-trailing-whitespace 100 | :help "Delete trailing whitespace between START and END."])) 101 | 102 | 103 | (provide 'cc-edit-text-menu) 104 | 105 | ;;; cc-edit-text-menu.el ends here 106 | -------------------------------------------------------------------------------- /cc-elfeed-mode.el: -------------------------------------------------------------------------------- 1 | ;;; cc-elfeed-mode.el --- elfeed customization -*- lexical-binding: t; -*- 2 | 3 | ;; Copyright (C) 2023-2024 Charles Choi 4 | 5 | ;; Author: Charles Choi 6 | 7 | ;; Keywords: tools 8 | 9 | ;; This program is free software; you can redistribute it and/or modify 10 | ;; it under the terms of the GNU General Public License as published by 11 | ;; the Free Software Foundation, either version 3 of the License, or 12 | ;; (at your option) any later version. 13 | 14 | ;; This program is distributed in the hope that it will be useful, 15 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | ;; GNU General Public License for more details. 18 | 19 | ;; You should have received a copy of the GNU General Public License 20 | ;; along with this program. If not, see . 21 | 22 | ;;; Commentary: 23 | ;; 24 | 25 | ;;; Code: 26 | (require 'elfeed-search) 27 | 28 | (keymap-set elfeed-search-mode-map "/" #'elfeed-search-live-filter) 29 | 30 | (provide 'cc-elfeed-mode) 31 | ;;; cc-elfeed-mode.el ends here 32 | -------------------------------------------------------------------------------- /cc-eshell-mode.el: -------------------------------------------------------------------------------- 1 | ;;; cc-eshell-mode.el --- eshell customization -*- lexical-binding: t; -*- 2 | 3 | ;; Copyright (C) 2023-2025 Charles Choi 4 | 5 | ;; Author: Charles Choi 6 | 7 | ;; Keywords: tools 8 | 9 | ;; This program is free software; you can redistribute it and/or modify 10 | ;; it under the terms of the GNU General Public License as published by 11 | ;; the Free Software Foundation, either version 3 of the License, or 12 | ;; (at your option) any later version. 13 | 14 | ;; This program is distributed in the hope that it will be useful, 15 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | ;; GNU General Public License for more details. 18 | 19 | ;; You should have received a copy of the GNU General Public License 20 | ;; along with this program. If not, see . 21 | 22 | ;;; Commentary: 23 | ;; 24 | 25 | ;;; Code: 26 | (require 'eshell) 27 | (require 'esh-mode) 28 | (require 'em-hist) 29 | (require 'company) 30 | (require 'hl-line) 31 | (require 'helm-eshell) 32 | (require 'eshell-git-prompt) 33 | (require 'cclisp) 34 | (require 'casual-lib) 35 | 36 | (defvar eshell-mode-map) 37 | (defvar eshell-visual-options) 38 | (defvar eshell-visual-commands) 39 | (defvar eshell-visual-subcommands) 40 | (declare-function eshell/pwd "pwd" ()) 41 | 42 | (defun cc/prompt-function () 43 | (concat "\n┏━ " 44 | (user-login-name) "@" (system-name) ":" 45 | (propertize (if (string= (eshell/pwd) (getenv "HOME")) 46 | "~" 47 | (replace-regexp-in-string 48 | (concat "^" (getenv "HOME")) "~" (eshell/pwd))) 49 | 'face `(:foreground "orange red")) 50 | (if (and (not (file-remote-p default-directory)) 51 | (eshell-git-prompt--branch-name)) 52 | (format " (%s)" (eshell-git-prompt--branch-name)) 53 | "") 54 | "\n┗━━ " 55 | (if (= (user-uid) 0) "# " "$ "))) 56 | 57 | (setopt eshell-prompt-function #'cc/prompt-function) 58 | ;;(setopt eshell-banner-message (format "Eshell ⌨️\n%s" (sunrise-sunset))) 59 | 60 | (add-hook 'eshell-mode-hook 'company-mode) 61 | (add-hook 'eshell-mode-hook 'hl-line-mode) 62 | (add-hook 'eshell-mode-hook (lambda () 63 | (keymap-set eshell-mode-map "" #'eshell-list-history) 64 | ;;(keymap-set eshell-mode-map "" 'company-complete) 65 | (keymap-set eshell-mode-map "C-r" 'helm-eshell-history) 66 | (keymap-set eshell-mode-map "M-b" #'backward-sexp) 67 | (keymap-set eshell-mode-map "" #'eshell-kill-input) 68 | (keymap-set eshell-mode-map "M-f" #'cc/next-sexp) 69 | (keymap-set eshell-mode-map "C-" #'backward-sexp) 70 | (keymap-set eshell-mode-map "C-" #'cc/next-sexp) 71 | ;; (keymap-set eshell-mode-map "C-" #'backward-up-list) 72 | ;; (keymap-set eshell-mode-map "C-" #'down-list) 73 | (setenv "NO_COLOR" "1") 74 | (setenv "CLICOLOR" "0"))) 75 | 76 | 77 | (transient-define-prefix casual-eshell-tmenu () 78 | "Transient menu for Eshell." 79 | ["Casual Eshell" 80 | ["Prompt" 81 | ("p" "Previous" eshell-previous-prompt :transient t) 82 | ("n" "Next" eshell-next-prompt :transient t)] 83 | 84 | ["Argument" 85 | ("b" "Backward" eshell-backward-argument :transient t) 86 | ("f" "Forward" eshell-forward-argument :transient t) 87 | ("y" "Repeat" eshell-repeat-argument :transient t)] 88 | 89 | ["Output" 90 | ("s" "Show" eshell-show-output) 91 | ("S" "Show Max" eshell-show-maximum-output) 92 | ("m" "Mark" eshell-mark-output) 93 | ("D" "Delete" eshell-delete-output)] 94 | 95 | ["Input" 96 | ("B" "Insert Buffer…" eshell-insert-buffer-name) 97 | ("k" "Kill Input" eshell-kill-input) 98 | ("h" "History" eshell-list-history)] 99 | 100 | ["Misc" 101 | ("d" "Dired" dired-jump-other-window) 102 | ("J" "Bookmark Jump…" bookmark-jump) 103 | ("g" "Magit" magit-status :if casual-editkit-version-controlled-p)]] 104 | 105 | [:class transient-row 106 | (casual-lib-quit-one) 107 | ("RET" "Dismiss" transient-quit-all) 108 | (casual-lib-quit-all)]) 109 | 110 | 111 | (keymap-set eshell-mode-map "C-o" #'casual-eshell-tmenu) 112 | 113 | 114 | (provide 'cc-eshell-mode) 115 | ;;; cc-eshell-mode.el ends here 116 | -------------------------------------------------------------------------------- /cc-find-menu.el: -------------------------------------------------------------------------------- 1 | ;;; cc-find-menu.el --- find menu -*- lexical-binding: t; -*- 2 | 3 | ;; Copyright (C) 2023-2024 Charles Choi 4 | 5 | ;; Author: Charles Choi 6 | 7 | ;; Keywords: tools 8 | 9 | ;; This program is free software; you can redistribute it and/or modify 10 | ;; it under the terms of the GNU General Public License as published by 11 | ;; the Free Software Foundation, either version 3 of the License, or 12 | ;; (at your option) any later version. 13 | 14 | ;; This program is distributed in the hope that it will be useful, 15 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | ;; GNU General Public License for more details. 18 | 19 | ;; You should have received a copy of the GNU General Public License 20 | ;; along with this program. If not, see . 21 | 22 | ;;; Commentary: 23 | ;; 24 | 25 | (require 'cc-context-menu-macros) 26 | 27 | ;;; Code: 28 | 29 | (easy-menu-define cc/find-menu nil 30 | "Keymap for Find submenu." 31 | '("Find and/or Replace" 32 | ["Find in files (rgrep)…" rgrep 33 | :help "Recursively find for Emacs regex in files rooted at \ 34 | current buffer"] 35 | 36 | ["Query Replace…" query-replace 37 | :help "Replace some occurrences of from-string with \ 38 | to-string"] 39 | 40 | ["Query Replace Regex…" query-replace-regexp 41 | :help "Replace some occurrences of Emacs regex with \ 42 | to-string"] 43 | 44 | ["Regex Builder…" re-builder 45 | :help "Construct an Emacs regex interactively"])) 46 | 47 | (provide 'cc-find-menu) 48 | 49 | ;;; cc-find-menu.el ends here 50 | -------------------------------------------------------------------------------- /cc-gh.el: -------------------------------------------------------------------------------- 1 | ;;; cc-gh.el --- gh commands -*- lexical-binding: t; -*- 2 | 3 | ;; Copyright (C) 2024-2025 Charles Choi 4 | 5 | ;; Author: Charles Choi 6 | ;; Keywords: tools 7 | 8 | ;; This program is free software; you can redistribute it and/or modify 9 | ;; it under the terms of the GNU General Public License as published by 10 | ;; the Free Software Foundation, either version 3 of the License, or 11 | ;; (at your option) any later version. 12 | 13 | ;; This program is distributed in the hope that it will be useful, 14 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | ;; GNU General Public License for more details. 17 | 18 | ;; You should have received a copy of the GNU General Public License 19 | ;; along with this program. If not, see . 20 | 21 | ;;; Commentary: 22 | 23 | ;; 24 | 25 | ;;; Code: 26 | (require 'seq) 27 | (require 'map) 28 | (require 'vtable) 29 | 30 | ;; TODO: Rebind < and > to move point while staying in the same column. 31 | ;; 32 | ;; (length (vtable-objects (vtable-current-table))) 33 | ;; (line-number-at-pos) 34 | 35 | ;; TODO: Design bindings for table navigation. (n, p, P, N) 36 | ;; TODO: Explore :objects-function for regenerating table 37 | ;; TODO: Format column widths 38 | ;; TODO: Make Transient menu for Org and Markdown export 39 | 40 | (defvar cc/gh--last-repo-history nil 41 | "Private variable to store last used GitHub repository name.") 42 | 43 | (defvar cc/gh--last-issue-numbers nil 44 | "Private variable to store last used GitHub issue numbers.") 45 | 46 | (defun cc/gh-read-repo (prompt) 47 | "Prompt the user with PROMPT, using the last history entry as the default input." 48 | (let* ((history 'cc/gh--last-repo-history) ; Define the history variable 49 | (last-history-entry (car (symbol-value history)))) ; Get the last entry 50 | (string-trim (read-string prompt last-history-entry history)))) 51 | 52 | (defun cc/gh-list-issues () 53 | "Insert Org table containing current issues for a GitHub repository. 54 | 55 | The command prompts the user for a GitHub repository, which if it 56 | exists will then retrieve the current list of issues for it via gh." 57 | (interactive) 58 | 59 | (let* ((repo (cc/gh-read-repo "repo: ")) 60 | (cmd-list (list)) 61 | (output-list (list)) 62 | (repo-buffer-name (format "*issues: %s*" repo))) 63 | (push "gh" cmd-list) 64 | (push "--repo" cmd-list) 65 | (push (format "'%s'" repo) cmd-list) 66 | (push "issue" cmd-list) 67 | (push "list" cmd-list) 68 | (push "--json" cmd-list) 69 | (push "number,title,url,state,labels,createdAt,updatedAt,milestone" cmd-list) 70 | 71 | (let* ((issues (json-parse-string 72 | (shell-command-to-string 73 | (string-join (seq-reverse cmd-list) " ")))) 74 | (header (list '((:label . "#") (:span . 0)) 75 | '((:label . "Title") (:span . 40)) 76 | ;; '((:label . "State") (:span . 0)) 77 | '((:label . "Labels") (:span . 5)) 78 | ;; '((:label . "Milestone") (:span . 5)) 79 | '((:label . "Created") (:span . 11)) 80 | '((:label . "Updated") (:span . 11)))) 81 | (header-labels (mapcar (lambda (x) (alist-get :label x)) header)) 82 | (header-spans (mapcar (lambda (x) (alist-get :span x)) header)) 83 | (numbers (list))) 84 | 85 | (mapc (lambda (issue) 86 | (let* ((number (gethash "number" issue)) 87 | (title (gethash "title" issue)) 88 | ;;(state (gethash "state" issue)) 89 | (labels (gethash "labels" issue)) 90 | (created (cc/gh-iso8601-to-local-org-time (gethash "createdAt" issue))) 91 | (updated (cc/gh-iso8601-to-local-org-time (gethash "updatedAt" issue))) 92 | (url (gethash "url" issue)) 93 | ;;(milestone (gethash "milestone" issue)) 94 | (temp-list (list))) 95 | 96 | (push (number-to-string number) numbers) 97 | (push (format "[[%s][%d]]" url number) temp-list) 98 | (push (format "[[%s][%s]]" url title) temp-list) 99 | ;; (push state temp-list) 100 | ;; (push milestone temp-list) 101 | (push (cc/gh-format-labels labels) temp-list) 102 | (push created temp-list) 103 | (push updated temp-list) 104 | 105 | (push 106 | (format "| %s |\n" (string-join (seq-reverse temp-list) " | ")) 107 | output-list))) 108 | issues) 109 | 110 | (setq cc/gh--last-issue-numbers (reverse numbers)) 111 | 112 | (get-buffer-create repo-buffer-name) 113 | (switch-to-buffer (set-buffer repo-buffer-name)) 114 | (erase-buffer) 115 | (org-mode) 116 | (visual-line-mode 0) 117 | 118 | (insert "|") 119 | (mapc (lambda (x) 120 | (if (> x 0) 121 | (insert (format "<%d>|" x)) 122 | (insert " |"))) 123 | header-spans) 124 | (insert "\n") 125 | 126 | (insert (format "| %s |\n" (string-join header-labels " | "))) 127 | (insert "|") 128 | (dotimes (_ (length header)) (insert "---|")) 129 | (insert "\n") 130 | 131 | (insert (string-join (seq-reverse output-list) "")) 132 | (goto-char (point-min)) 133 | 134 | (org-table-next-field) 135 | (goto-char (point-min)) 136 | 137 | (insert (format "* %s\n" repo))))) 138 | 139 | (defun cc/gh-issue () 140 | "Insert Org table issue for a GitHub repository. 141 | 142 | The command prompts the user for a GitHub repository, which if it 143 | exists will then retrieve the current list of issues for it via gh." 144 | (interactive) 145 | 146 | (let* ((repo (cc/gh-read-repo "repo: ")) 147 | (id (if cc/gh--last-issue-numbers 148 | (completing-read "Number: " cc/gh--last-issue-numbers) 149 | (read-string "Number: "))) 150 | (cmd-list (list))) 151 | (push "gh" cmd-list) 152 | (push "--repo" cmd-list) 153 | (push (format "'%s'" repo) cmd-list) 154 | (push "issue" cmd-list) 155 | (push "view" cmd-list) 156 | (push id cmd-list) 157 | (push "--json" cmd-list) 158 | (push "'number,title,url,body,createdAt'" cmd-list) 159 | 160 | (let* ((issue (json-parse-string 161 | (shell-command-to-string 162 | (string-join (seq-reverse cmd-list) " ")))) 163 | (number (gethash "number" issue)) 164 | (body (gethash "body" issue)) 165 | (title (gethash "title" issue)) 166 | (url (gethash "url" issue)) 167 | (created (cc/gh-iso8601-to-local-org-time (gethash "createdAt" issue))) 168 | (temp-list (list))) 169 | (push (format "** TODO %s #%d: %s" repo number title) temp-list) 170 | (push ":PROPERTIES:" temp-list) 171 | (push (format ":CREATED: %s" created) temp-list) 172 | (push ":END:" temp-list) 173 | (push "" temp-list) 174 | (push (format "[[%s][%s #%d: %s]]" url repo number title) temp-list) 175 | (push "" temp-list) 176 | (push (cc/gh-md2org body) temp-list) 177 | (push "" temp-list) 178 | (insert (string-join (seq-reverse temp-list) "\n"))))) 179 | 180 | (defun cc/gh-md2org (buf) 181 | "Convert BUF text format from Markdown to Org." 182 | (save-excursion 183 | (with-temp-buffer 184 | (insert buf) 185 | (shell-command-on-region (point-min) (point-max) "pandoc --to=org --wrap=preserve" (current-buffer) t) 186 | (buffer-string)))) 187 | 188 | (defun cc/gh-format-labels (labels) 189 | "Convert LABELS to a comma-separated string. 190 | 191 | LABELS is a vector of hash-tables, each hash-table corresponding 192 | to the JSON dictionary containing label information returned by 193 | gh." 194 | (if labels 195 | (let* ((temp-list (list))) 196 | (mapc (lambda (label) 197 | (let* ((name (map-elt label "name"))) 198 | (push name temp-list))) 199 | labels) 200 | 201 | (string-join temp-list ", ")) 202 | "")) 203 | 204 | (defun cc/gh-iso8601-to-local-org-time (timestamp) 205 | "Convert an ISO 8601 UTC TIMESTAMP to local Org timestamp." 206 | (let* ((time-components (parse-time-string timestamp)) 207 | (utc-time (encode-time time-components)) 208 | (local-time (current-time-zone utc-time))) 209 | (format-time-string "%Y-%m-%d %H:%M:%S" (apply 'encode-time time-components) local-time))) 210 | 211 | ;; ;; Example usage 212 | ;; (let ((utc-timestamp "2024-12-23T02:42:41Z")) 213 | ;; (message "Local time: %s" (cc/gh-iso8601-to-local-org-time utc-timestamp))) 214 | 215 | 216 | 217 | ;; (defvar-keymap vtable-map 218 | ;; "S" #'vtable-sort-by-current-column 219 | ;; "{" #'vtable-narrow-current-column 220 | ;; "}" #'vtable-widen-current-column 221 | ;; "g" #'vtable-revert-command 222 | ;; "M-" #'vtable-previous-column 223 | ;; "M-" #'vtable-next-column) 224 | 225 | (keymap-set vtable-map "TAB" #'vtable-next-column) 226 | (keymap-set vtable-map "" #'vtable-previous-column) 227 | 228 | (defun cc/gh-browse-url (obj) 229 | (let* ((url (map-elt obj "url"))) 230 | (browse-url url))) 231 | 232 | 233 | (defun cc/gh-list-issues-vtable () 234 | "Put current issues for a GitHub repository in a vtable. 235 | 236 | The command prompts the user for a GitHub repository, which if it 237 | exists will then retrieve the current list of issues for it via gh." 238 | (interactive) 239 | 240 | (let* ((repo (cc/gh-read-repo "repo: ")) 241 | (cmd-list (list)) 242 | (repo-buffer-name (format "*issues: %s*" repo))) 243 | (push "gh" cmd-list) 244 | (push "--repo" cmd-list) 245 | (push (format "'%s'" repo) cmd-list) 246 | (push "issue" cmd-list) 247 | (push "list" cmd-list) 248 | (push "--json" cmd-list) 249 | (push "number,title,url,state,labels,createdAt,updatedAt,milestone" cmd-list) 250 | 251 | (let* ((issues (json-parse-string 252 | (shell-command-to-string 253 | (string-join (seq-reverse cmd-list) " ")))) 254 | ;; (header (list '((:label . "#") (:span . 0)) 255 | ;; '((:label . "Title") (:span . 40)) 256 | ;; ;; '((:label . "State") (:span . 0)) 257 | ;; '((:label . "Labels") (:span . 5)) 258 | ;; ;; '((:label . "Milestone") (:span . 5)) 259 | ;; '((:label . "Created") (:span . 11)) 260 | ;; '((:label . "Updated") (:span . 11)))) 261 | 262 | ;;(header-labels (mapcar (lambda (x) (alist-get :label x)) header)) 263 | ;;(header-spans (mapcar (lambda (x) (alist-get :span x)) header)) 264 | ;; (numbers (list)) 265 | ) 266 | 267 | (unless (> (length issues) 0) 268 | (error (format "Repository %s has no issues." repo))) 269 | 270 | 271 | (get-buffer-create repo-buffer-name) 272 | (switch-to-buffer (set-buffer repo-buffer-name)) 273 | 274 | (read-only-mode) 275 | (let ((inhibit-read-only t)) 276 | (erase-buffer) 277 | (make-vtable 278 | :columns '((:name "#") 279 | (:name "Title" :width 40) 280 | (:name "Labels") 281 | (:name "Updated" :primary descend) 282 | (:name "Created")) 283 | 284 | :actions '("RET" cc/gh-browse-url 285 | "" cc/gh-browse-url) 286 | :objects (seq-into issues 'list) 287 | 288 | :getter (lambda (issue column table) 289 | (pcase (vtable-column table column) 290 | ("#" (map-elt issue "number")) 291 | ("Title" (map-elt issue "title")) 292 | ("Labels" (cc/gh-format-labels (map-elt issue "labels"))) 293 | ("Created" (cc/gh-iso8601-to-local-org-time (map-elt issue "createdAt"))) 294 | ("Updated" (cc/gh-iso8601-to-local-org-time (map-elt issue "updatedAt"))) 295 | )) 296 | :keymap (define-keymap 297 | "q" #'quit-window)))))) 298 | 299 | 300 | (provide 'cc-gh) 301 | ;;; cc-gh.el ends here 302 | -------------------------------------------------------------------------------- /cc-global-keybindings.el: -------------------------------------------------------------------------------- 1 | ;;; cc-global-keybindings.el --- Global Keybindings -*- lexical-binding: t; -*- 2 | 3 | ;; Copyright (C) 2023-2025 Charles Choi 4 | 5 | ;; Author: Charles Choi 6 | 7 | ;; Keywords: tools 8 | 9 | ;; This program is free software; you can redistribute it and/or modify 10 | ;; it under the terms of the GNU General Public License as published by 11 | ;; the Free Software Foundation, either version 3 of the License, or 12 | ;; (at your option) any later version. 13 | 14 | ;; This program is distributed in the hope that it will be useful, 15 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | ;; GNU General Public License for more details. 18 | 19 | ;; You should have received a copy of the GNU General Public License 20 | ;; along with this program. If not, see . 21 | 22 | ;;; Commentary: 23 | ;; 24 | ;; Global Keyboard Mappings for Charles Choi 25 | 26 | ;;; Code: 27 | 28 | (require 'cc-ediff-mode) 29 | (require 'minibuffer) 30 | (require 'helm-buffers) 31 | (require 'neotree) 32 | (require 'bookmark) 33 | (require 'avy) 34 | (require 'expand-region) 35 | (require 'cclisp) 36 | (require 'osx-dictionary) 37 | (require 'google-this) 38 | (require 'treemacs) 39 | (require 'neotree) 40 | (require 'python) 41 | (require 'ibuffer) 42 | (require 'magit-status) 43 | (require 'casual-avy) 44 | (require 'cc-main-tmenu) 45 | (require 'casual-editkit) 46 | (require 'minibuffer) 47 | (require 'recent-rgrep) 48 | 49 | (keymap-global-set "C-=" #'er/expand-region) 50 | ;(keymap-global-set (kbd "M-g") 'goto-line) 51 | (keymap-global-set "C-x v" #'view-file) 52 | (keymap-global-set "M-q" #'query-replace) 53 | (keymap-global-set "M-j" #'cc/journal-entry) 54 | (keymap-global-set "C-x 2" #'cc/split-window-below) 55 | (keymap-global-set "C-x 3" #'cc/split-window-right) 56 | 57 | ;;(keymap-global-set "\C-h" 'delete-backward-char) 58 | ;;(keymap-global-set "\C-xh" 'help-for-help) 59 | ;;(keymap-global-set "\r" 'newline-and-indent) 60 | 61 | (keymap-global-set "" #'kill-region) 62 | (keymap-global-set "" #'save-buffer) 63 | (keymap-global-set "" #'ibuffer) 64 | (keymap-global-set "s-" #'other-window) 65 | (keymap-global-set "" #'save-buffers-kill-emacs) 66 | (keymap-global-set "M-" #'casual-editkit-windows-tmenu) 67 | (keymap-global-set "" #'bookmark-jump) 68 | (keymap-global-set "S-" #'cc/select-journal-file) 69 | (keymap-global-set "" #'journal) 70 | (keymap-global-set "s-" #'cc/org-search) 71 | (keymap-global-set "" #'osx-dictionary-search-input) 72 | (keymap-global-set "" #'repeat) 73 | (keymap-global-set "M-" #'repeat-complex-command) 74 | (keymap-global-set "C-o" #'casual-editkit-main-tmenu) 75 | (if (string-equal (window-system) "mac") 76 | (keymap-global-set "" #'casual-editkit-main-tmenu)) 77 | 78 | (keymap-global-set "" #'org-capture) 79 | (keymap-global-set "" #'compile) 80 | (keymap-global-set "" #'bookmark-set-no-overwrite) 81 | 82 | (keymap-global-set "M-" #'cc/open-url) 83 | ;;(keymap-global-set "M-" #'google-this) 84 | ;;(keymap-global-set "C-c C-;" #'shell-command) 85 | (keymap-global-set "M-" #'google-this) 86 | 87 | (keymap-global-set "" #'google-this) 88 | (keymap-global-set "M-" #'neotree-toggle) 89 | (keymap-global-set "C-" #'treemacs) 90 | (keymap-global-set "" #'eshell) ;regular 91 | ;;(keymap-global-set (kbd "") 'save-buffer) ;logitech 92 | (keymap-global-set "" #'cc/ediff-revision) 93 | 94 | (keymap-global-set "" #'calc) 95 | (keymap-global-set "" #'run-python) 96 | (keymap-global-set "M-" #'cc/switch-to-scratch) ;; this need to be in main 97 | (keymap-global-set "C-x C-b" #'ibuffer) 98 | 99 | ;; Avy 100 | (keymap-global-set "M-g" #'casual-avy-tmenu) 101 | 102 | ;; Terminal 103 | (keymap-global-set "M-SPC" #'set-mark-command) 104 | (keymap-global-set "M-c" #'kill-ring-save) 105 | 106 | ;;(keymap-global-set (kbd "") 'next-error) 107 | ;;(keymap-global-set (kbd "M-") 'previous-error) 108 | ;;(keymap-global-set (kbd "") 'compile) 109 | 110 | (keymap-global-set "C-" #'delete-other-windows) 111 | (keymap-global-set "C-" #'kill-buffer) 112 | (keymap-global-set "C-" #'view-file) 113 | (keymap-global-set "C-z" #'pop-global-mark) 114 | 115 | (keymap-global-set "" #'beginning-of-buffer) 116 | (keymap-global-set "" #'end-of-buffer) 117 | (keymap-global-set "C-" #'beginning-of-line) 118 | (keymap-global-set "C-" #'end-of-line) 119 | (keymap-global-set "S-" #'back-to-indentation) 120 | (keymap-global-set "S-" #'end-of-line) 121 | (keymap-global-set "" #'scroll-down-command) 122 | (keymap-global-set "" #'scroll-up-command) 123 | (keymap-global-set "M-z" #'undo) 124 | (keymap-global-set "" #'delete-forward-char) 125 | 126 | ;; (if (eq window-system 'ns) 127 | ;; (keymap-global-set "s-" #'ns-do-show-character-palette)) 128 | 129 | ;; (when (string-equal (window-system) "mac") 130 | ;; (keymap-global-set "C-" #'mac-next-tab) 131 | ;; ;; this binding breaks terminal behavior 132 | ;; ;(keymap-global-set (kbd "M-]") 'mac-next-tab) 133 | ;; ;(keymap-global-set (kbd "M-[") 'mac-previous-tab) 134 | ;; (define-key-after global-map 135 | ;; [menu-bar file mac-toggle] 136 | ;; '("Toggle Tab Bar" . mac-toggle-tab-bar) 'close-tab)) 137 | 138 | ;; Left Side Keys 139 | ;; (keymap-global-set (kbd "") 'shell) 140 | ;; (keymap-global-set (kbd "C-") 'shell-new) 141 | 142 | ;; Keypad Keys 143 | (keymap-global-set "M-" #'forward-word) 144 | (keymap-global-set "M-" #'backward-word) 145 | (keymap-global-set "s-" #'forward-word) 146 | (keymap-global-set "s-" #'backward-word) 147 | (keymap-global-set "s-" #'scroll-one-line-down) 148 | (keymap-global-set "s-" #'scroll-one-line-up) 149 | (keymap-global-set "C-" #'enlarge-window) 150 | (keymap-global-set "C-" #'shrink-window) 151 | (keymap-global-set "M-" #'enlarge-window-horizontally) 152 | (keymap-global-set "M-" #'shrink-window-horizontally) 153 | (keymap-global-set "C-" #'other-window) 154 | (keymap-global-set "M-" #'switch-to-buffer) 155 | (keymap-global-set "C-" #'other-window) 156 | (keymap-global-set "C-`" #'other-window) ; Xcode 157 | 158 | ;; Mouse Button Bindings 159 | (keymap-global-set "" #'next-buffer) 160 | (keymap-global-set "" #'previous-buffer) 161 | 162 | (keymap-global-set " " #'transpose-frame) 163 | 164 | ;; Magit 165 | (keymap-global-set "C-x g" #'magit-status) 166 | 167 | (keymap-global-unset "C-x f") 168 | ;;(global-unset-key (kbd "C-x f")) 169 | 170 | ;; Find in files (rgrep) 171 | (keymap-global-set "M-F" #'recent-rgrep) 172 | ;;(keymap-global-set "M-F" #'rgrep) 173 | 174 | (global-set-key [vertical-scroll-bar down-mouse-1] #'scroll-bar-drag) 175 | 176 | ;; Window Navigation 177 | (keymap-global-set "C-" #'windmove-up) 178 | (keymap-global-set "C-" #'windmove-down) 179 | (keymap-global-set "C-" #'windmove-down) 180 | (keymap-global-set "C-" #'windmove-left) 181 | (keymap-global-set "C-" #'windmove-right) 182 | (keymap-global-set "C-" #'ace-select-window) 183 | (keymap-global-set "C-" #'transpose-frame) 184 | 185 | (keymap-set minibuffer-local-shell-command-map "M-b" #'backward-sexp) 186 | (keymap-set minibuffer-local-shell-command-map "M-f" #'cc/next-sexp) 187 | (keymap-set minibuffer-local-shell-command-map "C-M-b" #'backward-word) 188 | (keymap-set minibuffer-local-shell-command-map "C-M-f" #'forward-word) 189 | (keymap-set minibuffer-local-shell-command-map "C-" #'backward-sexp) 190 | (keymap-set minibuffer-local-shell-command-map "C-" #'cc/next-sexp) 191 | 192 | (keymap-set minibuffer-mode-map "M-b" #'backward-sexp) 193 | (keymap-set minibuffer-mode-map "M-f" #'cc/next-sexp) 194 | (keymap-set minibuffer-mode-map "C-M-b" #'backward-word) 195 | (keymap-set minibuffer-mode-map "C-M-f" #'forward-word) 196 | 197 | (keymap-set minibuffer-mode-map "C-" #'backward-sexp) 198 | (keymap-set minibuffer-mode-map "C-" #'cc/next-sexp) 199 | (keymap-set minibuffer-mode-map "C-" #'backward-up-list) 200 | (keymap-set minibuffer-mode-map "C-" #'down-list) 201 | (keymap-set minibuffer-mode-map "" #'delete-minibuffer-contents) 202 | 203 | (keymap-global-set "M-\\" #'cycle-spacing) 204 | (keymap-global-set "s-SPC" #'cycle-spacing) 205 | 206 | (provide 'cc-global-keybindings) 207 | ;;; cc-global-keybindings.el ends here 208 | -------------------------------------------------------------------------------- /cc-google-translate.el: -------------------------------------------------------------------------------- 1 | ;;; cc-google-translate.el --- Google Translate Customization -*- lexical-binding: t; -*- 2 | 3 | ;; Copyright (C) 2023-2024 Charles Choi 4 | 5 | ;; Author: Charles Choi 6 | 7 | ;; Keywords: tools 8 | 9 | ;; This program is free software; you can redistribute it and/or modify 10 | ;; it under the terms of the GNU General Public License as published by 11 | ;; the Free Software Foundation, either version 3 of the License, or 12 | ;; (at your option) any later version. 13 | 14 | ;; This program is distributed in the hope that it will be useful, 15 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | ;; GNU General Public License for more details. 18 | 19 | ;; You should have received a copy of the GNU General Public License 20 | ;; along with this program. If not, see . 21 | 22 | ;;; Commentary: 23 | ;; 24 | 25 | (require 'google-translate) 26 | (require 'google-translate-smooth-ui) 27 | ;;(global-set-key "\C-ct" 'google-translate-smooth-translate) 28 | 29 | ;;; Code: 30 | 31 | (setq google-translate-translation-directions-alist 32 | '(("ko" . "en") ("en" . "ko"))) 33 | 34 | (provide 'cc-google-translate) 35 | ;;; cc-google-translate.el ends here 36 | -------------------------------------------------------------------------------- /cc-grep-mode.el: -------------------------------------------------------------------------------- 1 | ;;; cc-grep-mode.el --- grep mode customization -*- lexical-binding: t; -*- 2 | 3 | ;; Copyright (C) 2024 Charles Choi 4 | 5 | ;; Author: Charles Choi 6 | ;; Keywords: tools 7 | 8 | ;; This program is free software; you can redistribute it and/or modify 9 | ;; it under the terms of the GNU General Public License as published by 10 | ;; the Free Software Foundation, either version 3 of the License, or 11 | ;; (at your option) any later version. 12 | 13 | ;; This program is distributed in the hope that it will be useful, 14 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | ;; GNU General Public License for more details. 17 | 18 | ;; You should have received a copy of the GNU General Public License 19 | ;; along with this program. If not, see . 20 | 21 | ;;; Commentary: 22 | 23 | ;; 24 | 25 | ;;; Code: 26 | 27 | (require 'grep) 28 | (require 'hl-line) 29 | (require 'cc-main-tmenu) 30 | 31 | (add-hook 'grep-mode-hook 'hl-line-mode) 32 | 33 | (keymap-set grep-mode-map "C-o" #'casual-editkit-main-tmenu) 34 | 35 | (provide 'cc-grep-mode) 36 | ;;; cc-grep-mode.el ends here 37 | -------------------------------------------------------------------------------- /cc-ibuffer-mode.el: -------------------------------------------------------------------------------- 1 | ;;; cc-ibuffer-mode.el --- ibuffer configuration -*- lexical-binding: t; -*- 2 | 3 | ;; Copyright (C) 2024 Charles Choi 4 | 5 | ;; Author: Charles Choi 6 | ;; Keywords: tools 7 | 8 | ;; This program is free software; you can redistribute it and/or modify 9 | ;; it under the terms of the GNU General Public License as published by 10 | ;; the Free Software Foundation, either version 3 of the License, or 11 | ;; (at your option) any later version. 12 | 13 | ;; This program is distributed in the hope that it will be useful, 14 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | ;; GNU General Public License for more details. 17 | 18 | ;; You should have received a copy of the GNU General Public License 19 | ;; along with this program. If not, see . 20 | 21 | ;;; Commentary: 22 | 23 | ;; 24 | 25 | ;;; Code: 26 | (use-package ibuffer 27 | :hook (ibuffer-mode . ibuffer-auto-mode) 28 | :defer t) 29 | 30 | (use-package casual-ibuffer 31 | :ensure nil 32 | :bind (:map 33 | ibuffer-mode-map 34 | ("C-o" . casual-ibuffer-tmenu) 35 | ("F" . casual-ibuffer-filter-tmenu) 36 | ("s" . casual-ibuffer-sortby-tmenu) 37 | ("" . ibuffer-visit-buffer) 38 | ("M-" . ibuffer-visit-buffer-other-window) 39 | ("{" . ibuffer-backwards-next-marked) 40 | ("}" . ibuffer-forward-next-marked) 41 | ("[" . ibuffer-backward-filter-group) 42 | ("]" . ibuffer-forward-filter-group) 43 | ("$" . ibuffer-toggle-filter-group)) 44 | :after (ibuffer)) 45 | 46 | ;; (require 'ibuffer) 47 | ;; (require 'hl-line) 48 | ;; (require 'mouse) 49 | ;; (require 'casual-ibuffer) 50 | 51 | ;; (add-hook 'ibuffer-mode-hook #'hl-line-mode) 52 | ;; (add-hook 'ibuffer-mode-hook #'ibuffer-auto-mode) 53 | 54 | ;;(keymap-set ibuffer-mode-map "" #'mouse-set-point) 55 | ;; (keymap-set ibuffer-mode-map "" #'ibuffer-visit-buffer) 56 | ;; (keymap-set ibuffer-mode-map "M-" #'ibuffer-visit-buffer-other-window) 57 | 58 | ;; (keymap-set ibuffer-mode-map "C-o" #'casual-ibuffer-tmenu) 59 | ;; (keymap-set ibuffer-mode-map "F" #'casual-ibuffer-filter-tmenu) 60 | ;; (keymap-set ibuffer-mode-map "s" #'casual-ibuffer-sortby-tmenu) 61 | 62 | ;; (keymap-set ibuffer-mode-map "{" #'ibuffer-backwards-next-marked) 63 | ;; (keymap-set ibuffer-mode-map "}" #'ibuffer-forward-next-marked) 64 | ;; (keymap-set ibuffer-mode-map "[" #'ibuffer-backward-filter-group) 65 | ;; (keymap-set ibuffer-mode-map "]" #'ibuffer-forward-filter-group) 66 | ;; (keymap-set ibuffer-mode-map "$" #'ibuffer-toggle-filter-group) 67 | 68 | (provide 'cc-ibuffer-mode) 69 | ;;; cc-ibuffer-mode.el ends here 70 | -------------------------------------------------------------------------------- /cc-image-mode.el: -------------------------------------------------------------------------------- 1 | ;;; cc-image-mode.el --- image mode customization -*- lexical-binding: t; -*- 2 | 3 | ;; Copyright (C) 2024-2025 Charles Choi 4 | 5 | ;; Author: Charles Choi 6 | ;; Keywords: tools 7 | 8 | ;; This program is free software; you can redistribute it and/or modify 9 | ;; it under the terms of the GNU General Public License as published by 10 | ;; the Free Software Foundation, either version 3 of the License, or 11 | ;; (at your option) any later version. 12 | 13 | ;; This program is distributed in the hope that it will be useful, 14 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | ;; GNU General Public License for more details. 17 | 18 | ;; You should have received a copy of the GNU General Public License 19 | ;; along with this program. If not, see . 20 | 21 | ;;; Commentary: 22 | 23 | ;; 24 | 25 | ;;; Code: 26 | (require 'casual-image) 27 | 28 | (keymap-set image-mode-map "C-o" #'casual-image-tmenu) 29 | 30 | (provide 'cc-image-mode) 31 | ;;; cc-image-mode.el ends here 32 | -------------------------------------------------------------------------------- /cc-info-mode.el: -------------------------------------------------------------------------------- 1 | ;;; cc-info-mode.el --- Info mode customization -*- lexical-binding: t; -*- 2 | 3 | ;; Copyright (C) 2024-2025 Charles Choi 4 | 5 | ;; Author: Charles Choi 6 | ;; Keywords: tools 7 | 8 | ;; This program is free software; you can redistribute it and/or modify 9 | ;; it under the terms of the GNU General Public License as published by 10 | ;; the Free Software Foundation, either version 3 of the License, or 11 | ;; (at your option) any later version. 12 | 13 | ;; This program is distributed in the hope that it will be useful, 14 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | ;; GNU General Public License for more details. 17 | 18 | ;; You should have received a copy of the GNU General Public License 19 | ;; along with this program. If not, see . 20 | 21 | ;;; Commentary: 22 | 23 | ;; 24 | 25 | ;;; Code: 26 | (require 'info) 27 | (require 'cc-main-tmenu) 28 | (require 'casual-info) 29 | 30 | (defun cc/clone-in-new-tab () 31 | (interactive) 32 | (unless (fboundp #'tab-bar-mode) (error "Error: tab-bar-mode not available.")) 33 | (unless (derived-mode-p 'Info-mode) (error "Error: must only be run in Info.")) 34 | (tab-new-to -1) 35 | (clone-buffer nil t) 36 | (delete-other-windows)) 37 | 38 | (defun cc/rename-to-info-manual () 39 | "Rename buffer to *info *." 40 | (interactive) 41 | (unless (derived-mode-p 'Info-mode) (error "Error: can only run in Info buffer.")) 42 | (let ((manual-name (file-name-nondirectory Info-current-file))) 43 | (rename-buffer (format "*info %s*" manual-name)))) 44 | 45 | (keymap-set Info-mode-map "C-o" #'casual-info-tmenu) 46 | (keymap-set Info-mode-map "C-M-o" #'casual-editkit-main-tmenu) 47 | 48 | (keymap-set Info-mode-map "" #'Info-history-forward) 49 | (keymap-set Info-mode-map "" #'Info-history-back) 50 | (keymap-set Info-mode-map "s-" #'cc/clone-in-new-tab) 51 | (keymap-set Info-mode-map "M-t" #'cc/clone-in-new-tab) 52 | 53 | (provide 'cc-info-mode) 54 | ;;; cc-info-mode.el ends here 55 | -------------------------------------------------------------------------------- /cc-insert-org-plot.el: -------------------------------------------------------------------------------- 1 | ;;; cc-insert-org-plot.el --- Functions supporting Org Plot configuration -*- lexical-binding: t; -*- 2 | 3 | ;; Copyright (C) 2023-2024 Charles Choi 4 | 5 | ;; Author: Charles Choi 6 | 7 | ;; Keywords: tools 8 | 9 | ;; This program is free software; you can redistribute it and/or modify 10 | ;; it under the terms of the GNU General Public License as published by 11 | ;; the Free Software Foundation, either version 3 of the License, or 12 | ;; (at your option) any later version. 13 | 14 | ;; This program is distributed in the hope that it will be useful, 15 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | ;; GNU General Public License for more details. 18 | 19 | ;; You should have received a copy of the GNU General Public License 20 | ;; along with this program. If not, see . 21 | 22 | ;;; Commentary: 23 | ;; 24 | 25 | ;;; Code: 26 | (require 'yasnippet) 27 | (require 'org) 28 | 29 | (require 'cc-context-menu-macros) 30 | 31 | (defmacro cc/insert-org-plot-snippet (snippet-name) 32 | `(lambda () 33 | (if (org-at-table-p) 34 | (progn 35 | (org-backward-paragraph) 36 | (yas-expand-snippet (yas-lookup-snippet ,snippet-name))) 37 | (message "Error: not in org-table")))) 38 | 39 | (defun cc/org-plot-insert-snippet (name) 40 | "Insert NAME snippet at top of the table. 41 | 42 | If the point is not within an Org table then an error message 43 | will be displayed." 44 | (if (org-at-table-p) 45 | (progn 46 | (org-backward-paragraph) 47 | (yas-expand-snippet (yas-lookup-snippet name))) 48 | (message "Error: not in org-table"))) 49 | 50 | (defun cc/org-plot-insert-lines-plot () 51 | "Invoke snippet named \"org-plot lines\"." 52 | (interactive) 53 | (cc/org-plot-insert-snippet "org-plot lines")) 54 | 55 | (defun cc/org-plot-insert-lines-timestamp-plot () 56 | "Invoke snippet named \"org-plot lines timestamp\"." 57 | (interactive) 58 | (cc/org-plot-insert-snippet "org-plot lines timestamp")) 59 | 60 | (defun cc/org-plot-insert-histogram-plot () 61 | "Invoke snippet named \"org-plot histogram\"." 62 | (interactive) 63 | (cc/org-plot-insert-snippet "org-plot histogram")) 64 | 65 | (defun cc/org-plot-insert-lines-plot-image () 66 | "Invoke snippet named \"org-plot lines image\"." 67 | (interactive) 68 | (cc/org-plot-insert-snippet "org-plot lines image")) 69 | 70 | (defun cc/org-plot-insert-lines-timestamp-plot-image () 71 | "Invoke snippet named \"org-plot lines timestamp image\"." 72 | (interactive) 73 | (cc/org-plot-insert-snippet "org-plot lines timestamp image")) 74 | 75 | (defun cc/org-plot-insert-histogram-plot-image () 76 | "Invoke snippet named \"org-plot histogram image\"." 77 | (interactive) 78 | (cc/org-plot-insert-snippet "org-plot histogram image")) 79 | 80 | (easy-menu-define cc/insert-org-plot-menu nil 81 | "Kaymap for Org Plot submenu" 82 | '("Org Plot" 83 | ["Lines - GUI" 84 | cc/org-plot-insert-lines-plot 85 | :help "Insert lines, linespoints, or impulses \ 86 | style chart for GUI interaction"] 87 | 88 | ["Lines Timestamp - GUI" 89 | cc/org-plot-insert-lines-timestamp-plot 90 | :help "Insert lines, linespoints, or impulses style \ 91 | chart with timestamps for GUI interaction"] 92 | 93 | ["Histogram - GUI" 94 | cc/org-plot-insert-histogram-plot 95 | :help "Insert histogram (column) style chart for GUI interaction"] 96 | 97 | "---" 98 | 99 | ["Lines - Image" 100 | cc/org-plot-insert-lines-plot-image 101 | :help "Insert lines, linespoints, or impulses style chart for \ 102 | image creation"] 103 | 104 | ["Lines Timestamp - Image" 105 | cc/org-plot-insert-lines-timestamp-plot-image 106 | :help "Insert lines, linespoints, or impulses style chart \ 107 | with timestamps for image creation"] 108 | 109 | 110 | ["Histogram - Image" 111 | cc/org-plot-insert-histogram-plot-image 112 | :help "Insert histogram (column) style chart for image creation"])) 113 | 114 | (provide 'cc-insert-org-plot) 115 | ;;; cc-insert-org-plot.el ends here 116 | -------------------------------------------------------------------------------- /cc-js-mode.el: -------------------------------------------------------------------------------- 1 | ;;; cc-js-mode.el --- JS mode customization -*- lexical-binding: t; -*- 2 | 3 | ;; Copyright (C) 2023-2024 Charles Choi 4 | 5 | ;; Author: Charles Choi 6 | 7 | ;; Keywords: tools 8 | 9 | ;; This program is free software; you can redistribute it and/or modify 10 | ;; it under the terms of the GNU General Public License as published by 11 | ;; the Free Software Foundation, either version 3 of the License, or 12 | ;; (at your option) any later version. 13 | 14 | ;; This program is distributed in the hope that it will be useful, 15 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | ;; GNU General Public License for more details. 18 | 19 | ;; You should have received a copy of the GNU General Public License 20 | ;; along with this program. If not, see . 21 | 22 | ;;; Commentary: 23 | ;; 24 | 25 | ;;; Code: 26 | 27 | (add-hook 'js-mode-hook 'hs-minor-mode) 28 | 29 | (provide 'cc-js-mode) 30 | ;;; cc-js-mode.el ends here 31 | -------------------------------------------------------------------------------- /cc-magit-mode.el: -------------------------------------------------------------------------------- 1 | ;;; cc-magit-mode.el --- Magit configuration -*- lexical-binding: t; -*- 2 | 3 | ;; Copyright (C) 2023-2025 Charles Choi 4 | 5 | ;; Author: Charles Choi 6 | ;; Keywords: tools 7 | 8 | ;; This program is free software; you can redistribute it and/or modify 9 | ;; it under the terms of the GNU General Public License as published by 10 | ;; the Free Software Foundation, either version 3 of the License, or 11 | ;; (at your option) any later version. 12 | 13 | ;; This program is distributed in the hope that it will be useful, 14 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | ;; GNU General Public License for more details. 17 | 18 | ;; You should have received a copy of the GNU General Public License 19 | ;; along with this program. If not, see . 20 | 21 | ;;; Commentary: 22 | ;; 23 | 24 | ;;; Code: 25 | 26 | (require 'magit) 27 | (require 'git-link-transient) 28 | (require 'casual-lib) 29 | (require 'cc-gh) 30 | 31 | (add-hook 'magit-status-mode-hook (lambda () (toggle-truncate-lines -1))) 32 | 33 | (keymap-set magit-status-mode-map "" #'git-link-homepage) 34 | (keymap-set magit-status-mode-map "C-c m" #'git-link-dispatch) 35 | 36 | (transient-define-prefix cc/magit-tmenu () 37 | 38 | ["Magit" 39 | ["Life-cycle" 40 | ("b" "Branch›" magit-branch) 41 | ("l" "Log›" magit-log) 42 | ("r" "Rebase›" magit-rebase)] 43 | 44 | ["Fetch/Pull" 45 | ("f" "Fetch›" magit-fetch) 46 | ("F" "Pull›" magit-pull)] 47 | ["Push" 48 | ("p" "Push›" magit-push)] 49 | 50 | ["Misc" 51 | ("c" "Compile…" compile) 52 | ("d" "Dired" dired-jump-other-window) 53 | ("J" "Jump…" bookmark-jump)] 54 | 55 | ["gh" 56 | ("i" "List Issues" cc/gh-list-issues-vtable)]] 57 | 58 | [:class transient-row 59 | (casual-lib-quit-one) 60 | (casual-lib-quit-all) 61 | ("q" "Quit" magit-mode-bury-buffer)]) 62 | 63 | (keymap-set magit-status-mode-map "C-o" #'cc/magit-tmenu) 64 | 65 | (provide 'cc-magit-mode) 66 | ;;; cc-magit-mode.el ends here 67 | -------------------------------------------------------------------------------- /cc-main-tmenu.el: -------------------------------------------------------------------------------- 1 | ;;; cc-main-tmenu.el --- Main Menu -*- lexical-binding: t; -*- 2 | 3 | ;; Copyright (C) 2024-2025 Charles Choi 4 | 5 | ;; Author: Charles Choi 6 | ;; Keywords: tools 7 | 8 | ;; This program is free software; you can redistribute it and/or modify 9 | ;; it under the terms of the GNU General Public License as published by 10 | ;; the Free Software Foundation, either version 3 of the License, or 11 | ;; (at your option) any later version. 12 | 13 | ;; This program is distributed in the hope that it will be useful, 14 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | ;; GNU General Public License for more details. 17 | 18 | ;; You should have received a copy of the GNU General Public License 19 | ;; along with this program. If not, see . 20 | 21 | ;;; Commentary: 22 | 23 | ;; 24 | 25 | ;;; Code: 26 | (require 'casual-editkit) 27 | (require 'cclisp) 28 | (require 'password-store-menu) 29 | (require 'google-translate-smooth-ui) 30 | (require 'webpaste) 31 | (require 'markdown-mode) 32 | (require 'git-link) 33 | 34 | (defvar cc-main-tmenu-customize-enable t 35 | "If t then enable Casual menu customizations.") 36 | 37 | (when (and cc-main-tmenu-customize-enable (not (featurep 'cc-main-tmenu))) 38 | ;; modify `casual-editkit-main-tmenu' 39 | (transient-append-suffix 'casual-editkit-main-tmenu "R" 40 | '("j" "Goto Journal…" cc/select-journal-file)) 41 | 42 | (transient-append-suffix 'casual-editkit-main-tmenu "C-o" 43 | '("I" "Korean Input" 44 | (lambda () (interactive)(set-input-method 'korean-hangul)) 45 | :transient nil)) 46 | 47 | (transient-append-suffix 'casual-editkit-main-tmenu "I" 48 | '("1" "Translate" 49 | google-translate-smooth-translate 50 | :inapt-if-not use-region-p 51 | :transient nil)) 52 | 53 | ;; (transient-append-suffix 'casual-editkit-main-tmenu "C" 54 | ;; '("!" "Shell Command…" shell-command)) 55 | 56 | ;; modify `casual-editkit-tools-tmenu' 57 | (transient-append-suffix 'casual-editkit-tools-tmenu "w" 58 | '("P" "Password›" password-store-menu)) 59 | 60 | (transient-append-suffix 'casual-editkit-tools-tmenu "P" 61 | '("l" "Git Link›" git-link-dispatch 62 | :if casual-editkit-version-controlled-p)) 63 | 64 | (transient-append-suffix 'casual-editkit-tools-tmenu "l" 65 | '("H" "Git Homepage›" git-link-homepage 66 | :if casual-editkit-version-controlled-p)) 67 | 68 | (transient-append-suffix 'casual-editkit-tools-tmenu "M-e" 69 | '("C-p" "Call" cc/call-nanp-phone-number 70 | :inapt-if-not use-region-p)) 71 | 72 | (transient-append-suffix 'casual-editkit-tools-tmenu "C-p" 73 | '("m" "Maps" cc/open-region-in-apple-maps 74 | :inapt-if-not use-region-p)) 75 | 76 | (transient-append-suffix 'casual-editkit-tools-tmenu "m" 77 | '("M-s" "Say" cc/say-region 78 | :inapt-if-not use-region-p)) 79 | 80 | (transient-append-suffix 'casual-editkit-tools-tmenu "M-s" 81 | '("M-t" "Translate" google-translate-smooth-translate 82 | :inapt-if-not use-region-p)) 83 | 84 | (transient-append-suffix 'casual-editkit-tools-tmenu "M-t" 85 | '("M-p" "Webpaste" webpaste-paste-region 86 | :inapt-if-not use-region-p)) 87 | 88 | (transient-append-suffix 'casual-editkit-tools-tmenu "z" 89 | '("F" "Fireplace" fireplace)) 90 | 91 | (transient-append-suffix 'casual-editkit-tools-tmenu "F" 92 | '("Z" "Snow" snow)) 93 | 94 | (transient-append-suffix 'casual-editkit-narrow-tmenu '(0 0) 95 | ["Markdown" 96 | :if (lambda () (derived-mode-p 'markdown-mode)) 97 | ("s" "Subtree" markdown-narrow-to-subtree) 98 | ("b" "Block" markdown-narrow-to-block) 99 | ("p" "Page" markdown-narrow-to-page)])) 100 | 101 | (provide 'cc-main-tmenu) 102 | ;;; cc-main-tmenu.el ends here 103 | -------------------------------------------------------------------------------- /cc-make-mode.el: -------------------------------------------------------------------------------- 1 | ;;; cc-make-mode.el --- makefile-mode configuration -*- lexical-binding: t; -*- 2 | 3 | ;; Copyright (C) 2024-2025 Charles Choi 4 | 5 | ;; Author: Charles Choi 6 | ;; Keywords: tools 7 | 8 | ;; This program is free software; you can redistribute it and/or modify 9 | ;; it under the terms of the GNU General Public License as published by 10 | ;; the Free Software Foundation, either version 3 of the License, or 11 | ;; (at your option) any later version. 12 | 13 | ;; This program is distributed in the hope that it will be useful, 14 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | ;; GNU General Public License for more details. 17 | 18 | ;; You should have received a copy of the GNU General Public License 19 | ;; along with this program. If not, see . 20 | 21 | ;;; Commentary: 22 | 23 | ;; 24 | 25 | ;;; Code: 26 | (require 'make-mode) 27 | (require 'compile) 28 | (require 'casual-make) 29 | 30 | (keymap-set makefile-mode-map "" #'compile) 31 | (keymap-set makefile-mode-map "C-6" #'imenu) 32 | 33 | ;;(add-hook 'makefile-mode-hook #'makefile-gmake-mode) 34 | 35 | (add-hook 'makefile-mode-hook #'imenu-add-menubar-index) 36 | (add-hook 'makefile-mode-hook 37 | (lambda () 38 | (setq-local imenu-auto-rescan t) 39 | (setq-local imenu-sort-function #'imenu--sort-by-name))) 40 | 41 | (keymap-set makefile-mode-map "M-m" #'casual-make-tmenu) 42 | (keymap-set makefile-mode-map "C-c m" #'casual-make-tmenu) 43 | 44 | (provide 'cc-make-mode) 45 | ;;; cc-make-mode.el ends here 46 | -------------------------------------------------------------------------------- /cc-markdown-mode.el: -------------------------------------------------------------------------------- 1 | ;;; cc-markdown-mode.el --- Markdown customizations -*- lexical-binding: t; -*- 2 | 3 | ;; Copyright (C) 2023-2024 Charles Choi 4 | 5 | ;; Author: Charles Choi 6 | 7 | ;; Keywords: tools 8 | 9 | ;; This program is free software; you can redistribute it and/or modify 10 | ;; it under the terms of the GNU General Public License as published by 11 | ;; the Free Software Foundation, either version 3 of the License, or 12 | ;; (at your option) any later version. 13 | 14 | ;; This program is distributed in the hope that it will be useful, 15 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | ;; GNU General Public License for more details. 18 | 19 | ;; You should have received a copy of the GNU General Public License 20 | ;; along with this program. If not, see . 21 | 22 | ;;; Commentary: 23 | ;; 24 | 25 | ;;; Code: 26 | (require 'markdown-mode) 27 | (require 'face-remap) 28 | (require 'cc-save-hooks) 29 | (require 'cc-style-text-menu) 30 | (require 'org-table) 31 | (require 'imenu) 32 | (defvar markdown-mode-map) 33 | 34 | (autoload 'markdown-mode "markdown-mode" 35 | "Major mode for editing Markdown files" t) 36 | 37 | (add-hook 'markdown-mode-hook #'variable-pitch-mode) 38 | ;;(add-hook 'markdown-mode-hook 'markdown-toggle-markup-hiding) 39 | 40 | (add-hook 'markdown-mode-hook #'turn-on-orgtbl) 41 | 42 | (keymap-set markdown-mode-map "C-" #'markdown-backward-same-level) 43 | (keymap-set markdown-mode-map "C-" #'markdown-forward-same-level) 44 | (keymap-set markdown-mode-map "M-v" #'markdown-outline-previous) 45 | (keymap-set markdown-mode-map "C-v" #'markdown-outline-next) 46 | (keymap-set markdown-mode-map "M-" #'markdown-toggle-inline-images) 47 | (keymap-set markdown-mode-map "C-/" #'cc/emphasize-dwim) 48 | ;; (define-key markdown-mode-map [f13] 'markdown-preview) 49 | 50 | (add-hook 'markdown-mode-hook #'cc/save-hook-delete-trailing-whitespace) 51 | (add-hook 'markdown-mode-hook #'imenu-add-menubar-index) 52 | (add-hook 'markdown-mode-hook (lambda () (setq-local imenu-auto-rescan t))) 53 | 54 | (provide 'cc-markdown-mode) 55 | ;;; cc-markdown-mode.el ends here 56 | -------------------------------------------------------------------------------- /cc-menu-reconfig.el: -------------------------------------------------------------------------------- 1 | ;;; cc-menu-reconfig.el --- Menu reconfiguration -*- lexical-binding: t; -*- 2 | 3 | ;; Copyright (C) 2023-2025 Charles Choi 4 | 5 | ;; Author: Charles Choi 6 | 7 | ;; Keywords: tools 8 | 9 | ;; This program is free software; you can redistribute it and/or modify 10 | ;; it under the terms of the GNU General Public License as published by 11 | ;; the Free Software Foundation, either version 3 of the License, or 12 | ;; (at your option) any later version. 13 | 14 | ;; This program is distributed in the hope that it will be useful, 15 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | ;; GNU General Public License for more details. 18 | 19 | ;; You should have received a copy of the GNU General Public License 20 | ;; along with this program. If not, see . 21 | 22 | ;;; Commentary: 23 | ;; 24 | 25 | ;; Menu Settings 26 | (require 'cc-transform-text-menu) 27 | (require 'cc-style-text-menu) 28 | (require 'text-mode) 29 | (require 'vc) 30 | (require 'helm) 31 | (require 'dired) 32 | (require 'transpose-frame) 33 | (require 'cc-region-operations-menu) 34 | (require 'cc-edit-text-menu) 35 | (require 'cc-truth-table) 36 | 37 | (defun cc/dired-side-right (path) 38 | "Side-by-side layout with Dired buffer on the right set to PATH." 39 | (interactive "DDirectory: ") 40 | (delete-other-windows) 41 | (dired-other-window path) 42 | (transpose-frame) 43 | (other-window 1)) 44 | 45 | (easy-menu-add-item (lookup-key global-map [menu-bar file]) nil 46 | ["Swap Windows" 47 | window-swap-states 48 | :visible (> (count-windows) 1) 49 | :help "Swap the states of live windows WINDOW-1 and \ 50 | WINDOW-2."] 51 | "New Window Below") 52 | 53 | (easy-menu-add-item (lookup-key global-map [menu-bar file]) nil 54 | ["Transpose Windows" 55 | transpose-frame 56 | :visible (> (count-windows) 1) 57 | :help "Transpose windows arrangement at FRAME."] 58 | "New Window Below") 59 | 60 | ;;; Reconfigure Text Mode Menu 61 | 62 | (easy-menu-remove-item text-mode-menu nil "Center Line") 63 | (easy-menu-remove-item text-mode-menu nil "Center Region") 64 | (easy-menu-remove-item text-mode-menu nil "Center Paragraph") 65 | (easy-menu-remove-item text-mode-menu nil "Paragraph Indent") 66 | (easy-menu-remove-item text-mode-menu nil "---") 67 | 68 | (easy-menu-add-item text-mode-menu nil cc/transform-text-menu "Auto Fill") 69 | (easy-menu-add-item text-mode-menu nil cc/emphasize-menu "Auto Fill") 70 | (easy-menu-add-item text-mode-menu nil cc/region-operations-menu "Auto Fill") 71 | 72 | ;;; Reconfigure Edit Menu 73 | 74 | (easy-menu-add-item (lookup-key global-map [menu-bar edit]) nil 75 | cc/transpose-menu "Fill") 76 | 77 | (easy-menu-add-item (lookup-key global-map [menu-bar edit]) nil 78 | cc/move-text-menu "Fill") 79 | 80 | (easy-menu-add-item (lookup-key global-map [menu-bar edit]) nil 81 | cc/delete-space-menu "Fill") 82 | 83 | (easy-menu-add-item global-map '(menu-bar edit) 84 | ["Flush Lines…" 85 | flush-lines 86 | :help "Delete lines containing matches for REGEXP." 87 | :visible (not buffer-read-only)] 88 | "Fill") 89 | 90 | (easy-menu-add-item global-map '(menu-bar edit) 91 | ["Keep Lines…" 92 | keep-lines 93 | :help "Delete all lines except those containing matches \ 94 | for REGEXP." 95 | :visible (not buffer-read-only)] 96 | "Fill") 97 | 98 | (easy-menu-add-item global-map '(menu-bar edit) 99 | ["Emoji & Symbols" 100 | ns-do-show-character-palette 101 | :help "Show macOS Character Palette." 102 | :visible (eq window-system 'ns)]) 103 | 104 | ;;; Reconfigure Tools Menu 105 | 106 | (easy-menu-add-item global-map '(menu-bar tools) 107 | ["Agenda - All TODOs" 108 | (lambda () (interactive)(org-agenda nil "n")) 109 | :help "Show Org agenda with all TODO tasks."] 110 | "Shell Commands") 111 | 112 | (easy-menu-add-item global-map '(menu-bar tools) 113 | ["Set Input Method - Korean" 114 | (lambda () (interactive)(set-input-method 'korean-hangul)) 115 | :enable (not current-input-method) 116 | :help "Set input method to Korean"] 117 | "Shell Commands") 118 | 119 | (easy-menu-add-item global-map '(menu-bar tools) 120 | ["Open in Finder" 121 | reveal-in-folder-this-buffer 122 | :visible (or (buffer-file-name) (derived-mode-p 'dired-mode)) 123 | :help "Reveal the current buffer in folder."] 124 | "Shell Commands") 125 | 126 | (keymap-set-after (lookup-key global-map [menu-bar tools]) 127 | "" 128 | '(menu-item "--") 129 | 'Agenda\ -\ All\ TODOs) 130 | 131 | (easy-menu-add-item global-map '(menu-bar tools) 132 | ["Find File…" 133 | helm-find-files 134 | :help "Fuzzy find file."] 135 | "Shell Commands") 136 | 137 | (easy-menu-add-item global-map '(menu-bar tools) 138 | ["Find in Files (rgrep)…" 139 | rgrep 140 | :help "Recursively grep for REGEXP in FILES in directory \ 141 | tree rooted at DIR."] 142 | "Shell Commands") 143 | 144 | (easy-menu-add-item global-map '(menu-bar tools) 145 | ["Search Org Notes…" 146 | cc/org-search 147 | :help "Search Org Notes in ~/org."] 148 | "Shell Commands") 149 | 150 | (easy-menu-add-item global-map '(menu-bar tools) 151 | ["IELM" 152 | ielm 153 | :help "Interactively evaluate Emacs Lisp expressions."] 154 | "Language Server Support (Eglot)") 155 | 156 | (keymap-set-after (lookup-key global-map [menu-bar tools]) 157 | "" 158 | '(menu-item "--") 159 | 'Search\ Org\ Notes…) 160 | 161 | (define-key global-map [menu-bar tools grep] nil t) 162 | (define-key global-map [menu-bar tools rgrep] nil t) 163 | (define-key global-map [menu-bar tools ede] nil t) 164 | (define-key global-map [menu-bar tools semantic] nil t) 165 | (define-key global-map [menu-bar tools compile] nil t) 166 | (define-key global-map [menu-bar tools gdb] nil t) 167 | (define-key global-map [menu-bar tools gnus] nil t) 168 | (define-key global-map [menu-bar tools rmail] nil t) 169 | (define-key global-map [menu-bar tools compose-mail] nil t) 170 | (define-key global-map [menu-bar tools directory-search] nil t) 171 | (define-key global-map [menu-bar tools browse-web] nil t) 172 | (define-key global-map [menu-bar tools separator-net] nil t) 173 | (define-key global-map [menu-bar tools encryption-decryption] nil t) 174 | (define-key global-map [menu-bar tools separator-encryption-decryption] nil t) 175 | (define-key global-map [menu-bar tools Table] nil t) 176 | 177 | (define-key global-map [menu-bar buffer list-all-buffers] nil t) 178 | (easy-menu-add-item global-map '(menu-bar buffer) 179 | ["List All Buffers" 180 | ibuffer 181 | :help "Begin using Ibuffer to edit a list of buffers."] 182 | "Select Buffer in Project...") 183 | 184 | (easy-menu-add-item global-map '(menu-bar tools) 185 | ["Magit Status" 186 | magit-status 187 | :visible (vc-responsible-backend default-directory t) 188 | :help "Show the status of the current Git repository \ 189 | in a buffer"] 190 | "Version Control") 191 | 192 | (easy-menu-add-item global-map '(menu-bar tools) 193 | ["Count Words" 194 | count-words 195 | :help "Count words in buffer or region if active."] 196 | "Calendar") 197 | 198 | (easy-menu-add-item global-map '(menu-bar tools) 199 | ["Eshell" 200 | eshell 201 | :help "Create an interactive Eshell buffer."] 202 | "Calendar") 203 | 204 | (easy-menu-add-item global-map '(menu-bar tools) 205 | ["Python Shell" 206 | run-python 207 | :help "Run an inferior Python process."] 208 | "Calendar") 209 | 210 | (easy-menu-add-item global-map '(menu-bar tools) 211 | ["Dired on Right Side" 212 | cc/dired-side-right 213 | :help "Side-by-side layout with Dired buffer on the right set to PATH."] 214 | "Calendar") 215 | 216 | (easy-menu-add-item global-map '(menu-bar tools) 217 | ["Insert Truth Table…" 218 | cc/insert-truth-table-input 219 | :visible (not buffer-read-only) 220 | :help "Insert truth table input with 2^BITS rows into current buffer."] 221 | "Calendar") 222 | 223 | (easy-menu-add-item global-map '(menu-bar tools) 224 | ["RE-Builder" 225 | re-builder 226 | :help "Construct a regexp interactively."] 227 | "Calendar") 228 | 229 | (keymap-set-after (lookup-key global-map [menu-bar tools]) 230 | "" 231 | '(menu-item "--") 232 | 'RE-Builder) 233 | 234 | (easy-menu-add-item global-map '(menu-bar tools) 235 | ["World Clock" 236 | world-clock 237 | :help "Display a world clock buffer with times in \ 238 | various time zones."] 239 | "Programmable Calculator") 240 | 241 | (easy-menu-add-item global-map '(menu-bar tools) 242 | ["Babel Ingest - Org Table To SQL" 243 | (org-babel-lob-ingest "~/org/babel/cc-org-table-to-sql.org") 244 | :help "Ingest code block to convert Org Table to SQLite."] 245 | "Games") 246 | 247 | (keymap-set-after (lookup-key global-map [menu-bar tools]) 248 | "" 249 | '(menu-item "--") 250 | 'Babel\ Ingest\ -\ Org\ Table\ To\ SQL) 251 | 252 | 253 | (define-key global-map [menu-bar edit bookmark] nil t) 254 | 255 | (provide 'cc-menu-reconfig) 256 | 257 | ;;; cc-menu-reconfig.el ends here 258 | -------------------------------------------------------------------------------- /cc-nxml-mode.el: -------------------------------------------------------------------------------- 1 | ;;; cc-nxml-mode.el --- nXML Mode Customization -*- lexical-binding: t; -*- 2 | 3 | ;; Copyright (C) 2024 Charles Choi 4 | 5 | ;; Author: Charles Choi 6 | ;; Keywords: tools 7 | 8 | ;; This program is free software; you can redistribute it and/or modify 9 | ;; it under the terms of the GNU General Public License as published by 10 | ;; the Free Software Foundation, either version 3 of the License, or 11 | ;; (at your option) any later version. 12 | 13 | ;; This program is distributed in the hope that it will be useful, 14 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | ;; GNU General Public License for more details. 17 | 18 | ;; You should have received a copy of the GNU General Public License 19 | ;; along with this program. If not, see . 20 | 21 | ;;; Commentary: 22 | 23 | ;; 24 | 25 | ;;; Code: 26 | (require 'nxml-mode) 27 | (require 'hl-line) 28 | 29 | (keymap-set nxml-mode-map "M-[" #'backward-sexp) 30 | (keymap-set nxml-mode-map "M-]" #'forward-sexp) 31 | (keymap-set nxml-mode-map "M-" #'nxml-down-element) 32 | (keymap-set nxml-mode-map "M-" #'nxml-backward-up-element) 33 | (keymap-set nxml-mode-map "M-" #'backward-sexp) 34 | (keymap-set nxml-mode-map "M-" #'forward-sexp) 35 | 36 | 37 | (add-hook 'nxml-mode-hook #'hl-line-mode) 38 | 39 | (provide 'cc-nxml-mode) 40 | ;;; cc-nxml-mode.el ends here 41 | -------------------------------------------------------------------------------- /cc-objc-mode.el: -------------------------------------------------------------------------------- 1 | ;;; cc-objc-mode.el --- ObjC Mode Customization -*- lexical-binding: t; -*- 2 | 3 | ;; Copyright (C) 2023-2024 Charles Choi 4 | 5 | ;; Author: Charles Choi 6 | 7 | ;; Keywords: tools 8 | 9 | ;; This program is free software; you can redistribute it and/or modify 10 | ;; it under the terms of the GNU General Public License as published by 11 | ;; the Free Software Foundation, either version 3 of the License, or 12 | ;; (at your option) any later version. 13 | 14 | ;; This program is distributed in the hope that it will be useful, 15 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | ;; GNU General Public License for more details. 18 | 19 | ;; You should have received a copy of the GNU General Public License 20 | ;; along with this program. If not, see . 21 | 22 | ;;; Commentary: 23 | ;; 24 | 25 | ;;; Code: 26 | 27 | (defvar c-basic-offset) 28 | 29 | (setq auto-mode-alist 30 | (cons '("\\.m$" . objc-mode) auto-mode-alist)) 31 | (setq auto-mode-alist 32 | (cons '("\\.mm$" . objc-mode) auto-mode-alist)) 33 | 34 | (add-hook 'objc-mode-hook (lambda() 35 | (setq c-basic-offset 4) 36 | (setq-default indent-tabs-mode nil))) 37 | 38 | (provide 'cc-objc-mode) 39 | ;;; cc-objc-mode.el ends here 40 | -------------------------------------------------------------------------------- /cc-occur-mode.el: -------------------------------------------------------------------------------- 1 | ;;; cc-occur-mode.el --- Occur Mode Configuration -*- lexical-binding: t; -*- 2 | 3 | ;; Copyright (C) 2024 Charles Choi 4 | 5 | ;; Author: Charles Choi 6 | ;; Keywords: tools 7 | 8 | ;; This program is free software; you can redistribute it and/or modify 9 | ;; it under the terms of the GNU General Public License as published by 10 | ;; the Free Software Foundation, either version 3 of the License, or 11 | ;; (at your option) any later version. 12 | 13 | ;; This program is distributed in the hope that it will be useful, 14 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | ;; GNU General Public License for more details. 17 | 18 | ;; You should have received a copy of the GNU General Public License 19 | ;; along with this program. If not, see . 20 | 21 | ;;; Commentary: 22 | 23 | ;; 24 | 25 | ;;; Code: 26 | (require 'replace) 27 | (require 'hl-line) 28 | 29 | (add-hook 'occur-mode-hook #'hl-line-mode) 30 | 31 | (provide 'cc-occur-mode) 32 | ;;; cc-occur-mode.el ends here 33 | -------------------------------------------------------------------------------- /cc-org-agenda.el: -------------------------------------------------------------------------------- 1 | ;;; cc-org-agenda.el --- Org Agenda Configuration -*- lexical-binding: t; -*- 2 | 3 | ;; Copyright (C) 2024 Charles Choi 4 | 5 | ;; Author: Charles Choi 6 | ;; Keywords: tools 7 | 8 | ;; This program is free software; you can redistribute it and/or modify 9 | ;; it under the terms of the GNU General Public License as published by 10 | ;; the Free Software Foundation, either version 3 of the License, or 11 | ;; (at your option) any later version. 12 | 13 | ;; This program is distributed in the hope that it will be useful, 14 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | ;; GNU General Public License for more details. 17 | 18 | ;; You should have received a copy of the GNU General Public License 19 | ;; along with this program. If not, see . 20 | 21 | ;;; Commentary: 22 | 23 | ;; 24 | 25 | ;;; Code: 26 | (require 'casual-agenda) 27 | (require 'bookmark) 28 | 29 | (keymap-set org-agenda-mode-map "C-o" #'casual-agenda-tmenu) 30 | (keymap-set org-agenda-mode-map "M-j" #'org-agenda-clock-goto) 31 | (keymap-set org-agenda-mode-map "J" #'bookmark-jump) 32 | 33 | ;; (use-package casual-agenda 34 | ;; :ensure nil 35 | ;; :bind (:map 36 | ;; org-agenda-mode-map 37 | ;; ("C-o" . casual-agenda-tmenu) 38 | ;; ("M-j" . org-agenda-clock-goto) ; optional 39 | ;; ("J" . bookmark-jump))) ; optional 40 | 41 | (provide 'cc-org-agenda) 42 | ;;; cc-org-agenda.el ends here 43 | -------------------------------------------------------------------------------- /cc-org-smart-quotes.el: -------------------------------------------------------------------------------- 1 | ;;; cc-org-smart-quotes.el --- CC Org Smart Quotes Config -*- lexical-binding: t; -*- 2 | 3 | ;; Copyright (C) 2024 Charles Choi 4 | 5 | ;; Author: Charles Choi 6 | ;; Keywords: tools 7 | 8 | ;; This program is free software; you can redistribute it and/or modify 9 | ;; it under the terms of the GNU General Public License as published by 10 | ;; the Free Software Foundation, either version 3 of the License, or 11 | ;; (at your option) any later version. 12 | 13 | ;; This program is distributed in the hope that it will be useful, 14 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | ;; GNU General Public License for more details. 17 | 18 | ;; You should have received a copy of the GNU General Public License 19 | ;; along with this program. If not, see . 20 | 21 | ;;; Commentary: 22 | 23 | ;; 24 | 25 | ;;; Code: 26 | (require 'org) 27 | (require 'ox) 28 | 29 | (defun cc/reconfig-org-smart-quotes-lang (lang) 30 | "Reconfigure Org smart quotes to use utf-8 per LANG." 31 | (let* ((db-entry (assoc-string lang org-export-smart-quotes-alist)) 32 | (utf8-primary-opening (plist-get (assoc-default 'primary-opening db-entry) :utf-8)) 33 | (utf8-primary-closing (plist-get (assoc-default 'primary-closing db-entry) :utf-8)) 34 | (utf8-secondary-opening (plist-get (assoc-default 'secondary-opening db-entry) :utf-8)) 35 | (utf8-secondary-closing (plist-get (assoc-default 'secondary-closing db-entry) :utf-8)) 36 | (utf8-apostrophe (plist-get (assoc-default 'apostrophe db-entry) :utf-8)) 37 | ) 38 | 39 | (setf (plist-get 40 | (assoc-default 'primary-opening 41 | (assoc-string lang org-export-smart-quotes-alist)) 42 | :html) 43 | utf8-primary-opening) 44 | 45 | (setf (plist-get 46 | (assoc-default 'primary-closing 47 | (assoc-string lang org-export-smart-quotes-alist)) 48 | :html) 49 | utf8-primary-closing) 50 | 51 | (setf (plist-get 52 | (assoc-default 'secondary-opening 53 | (assoc-string lang org-export-smart-quotes-alist)) 54 | :html) 55 | utf8-secondary-opening) 56 | 57 | (setf (plist-get 58 | (assoc-default 'secondary-closing 59 | (assoc-string lang org-export-smart-quotes-alist)) 60 | :html) 61 | utf8-secondary-closing) 62 | 63 | (setf (plist-get 64 | (assoc-default 'apostrophe 65 | (assoc-string lang org-export-smart-quotes-alist)) 66 | :html) 67 | utf8-apostrophe))) 68 | 69 | 70 | (provide 'cc-org-smart-quotes) 71 | ;;; cc-org-smart-quotes.el ends here 72 | -------------------------------------------------------------------------------- /cc-package-menu-mode.el: -------------------------------------------------------------------------------- 1 | ;;; cc-package-menu-mode.el --- Package menu customization -*- lexical-binding: t; -*- 2 | 3 | ;; Copyright (C) 2024 Charles Choi 4 | 5 | ;; Author: Charles Choi 6 | ;; Keywords: tools 7 | 8 | ;; This program is free software; you can redistribute it and/or modify 9 | ;; it under the terms of the GNU General Public License as published by 10 | ;; the Free Software Foundation, either version 3 of the License, or 11 | ;; (at your option) any later version. 12 | 13 | ;; This program is distributed in the hope that it will be useful, 14 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | ;; GNU General Public License for more details. 17 | 18 | ;; You should have received a copy of the GNU General Public License 19 | ;; along with this program. If not, see . 20 | 21 | ;;; Commentary: 22 | 23 | ;; 24 | 25 | ;;; Code: 26 | (require 'package) 27 | (require 'hl-line) 28 | 29 | (add-hook 'package-menu-mode-hook 'hl-line-mode) 30 | 31 | (provide 'cc-package-menu-mode) 32 | ;;; cc-package-menu-mode.el ends here 33 | -------------------------------------------------------------------------------- /cc-prog-mode.el: -------------------------------------------------------------------------------- 1 | ;;; cc-prog-mode.el --- Programming Customizations -*- lexical-binding: t; -*- 2 | 3 | ;; Copyright (C) 2023-2025 Charles Choi 4 | 5 | ;; Author: Charles Choi 6 | 7 | ;; Keywords: tools 8 | 9 | ;; This program is free software; you can redistribute it and/or modify 10 | ;; it under the terms of the GNU General Public License as published by 11 | ;; the Free Software Foundation, either version 3 of the License, or 12 | ;; (at your option) any later version. 13 | 14 | ;; This program is distributed in the hope that it will be useful, 15 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | ;; GNU General Public License for more details. 18 | 19 | ;; You should have received a copy of the GNU General Public License 20 | ;; along with this program. If not, see . 21 | 22 | ;;; Commentary: 23 | ;; 24 | (require 'prog-mode) 25 | (require 'make-mode) 26 | (require 'mouse) 27 | (require 'elec-pair) 28 | (require 'company) 29 | (require 'cc-save-hooks) 30 | (require 'rainbow-mode) 31 | (require 'display-line-numbers) 32 | (require 'display-fill-column-indicator) 33 | (require 'hl-line) 34 | (require 'gud) 35 | (require 'flyspell) 36 | (require 'compile) 37 | (require 'imenu) 38 | (require 'cc-main-tmenu) 39 | 40 | ;;; Code: 41 | (add-hook 'prog-mode-hook 'display-line-numbers-mode) 42 | (add-hook 'prog-mode-hook 'electric-pair-mode) 43 | (add-hook 'prog-mode-hook 'company-mode) 44 | (add-hook 'prog-mode-hook 'context-menu-mode) 45 | (add-hook 'prog-mode-hook 'rainbow-mode) 46 | (add-hook 'prog-mode-hook 'display-fill-column-indicator-mode) 47 | (add-hook 'prog-mode-hook 'hl-line-mode) 48 | (add-hook 'prog-mode-hook 'flyspell-prog-mode) 49 | (add-hook 'prog-mode-hook #'cc/save-hook-delete-trailing-whitespace) 50 | (add-hook 'prog-mode-hook #'imenu-add-menubar-index) 51 | (add-hook 'prog-mode-hook 52 | (lambda () 53 | (setq-local imenu-auto-rescan t) 54 | (setq-local imenu-sort-function #'imenu--sort-by-name))) 55 | 56 | (define-key prog-mode-map [remap indent-for-tab-command] 57 | #'company-indent-or-complete-common) 58 | (keymap-set prog-mode-map "C-a" #'back-to-indentation) 59 | (keymap-set prog-mode-map "C-6" #'imenu) 60 | (keymap-set prog-mode-map "M-p" #'beginning-of-defun) 61 | (keymap-set prog-mode-map "M-n" #'end-of-defun) 62 | 63 | (keymap-set compilation-mode-map "C-o" #'casual-editkit-main-tmenu) 64 | 65 | ;; GUD - mode preferences 66 | ;; (setq gud-mode-hook 67 | ;; '((lambda () 68 | ;; (local-set-key [f7] 'gud-step) 69 | ;; (local-set-key [f8] 'gud-next) 70 | ;; (local-set-key [f9] 'gud-cont)))) 71 | 72 | (provide 'cc-prog-mode) 73 | ;;; cc-prog-mode.el ends here 74 | -------------------------------------------------------------------------------- /cc-python-mode.el: -------------------------------------------------------------------------------- 1 | ;;; cc-python-mode.el --- Python mode configuration -*- lexical-binding: t; -*- 2 | 3 | ;; Copyright (C) 2024 Charles Choi 4 | 5 | ;; Author: Charles Choi 6 | ;; Keywords: tools 7 | 8 | ;; This program is free software; you can redistribute it and/or modify 9 | ;; it under the terms of the GNU General Public License as published by 10 | ;; the Free Software Foundation, either version 3 of the License, or 11 | ;; (at your option) any later version. 12 | 13 | ;; This program is distributed in the hope that it will be useful, 14 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | ;; GNU General Public License for more details. 17 | 18 | ;; You should have received a copy of the GNU General Public License 19 | ;; along with this program. If not, see . 20 | 21 | ;;; Commentary: 22 | 23 | ;; 24 | 25 | ;;; Code: 26 | (require 'python) 27 | 28 | (keymap-set python-mode-map "M-[" #'backward-sexp) 29 | (keymap-set python-mode-map "M-]" #'forward-sexp) 30 | 31 | (provide 'cc-python-mode) 32 | ;;; cc-python-mode.el ends here 33 | -------------------------------------------------------------------------------- /cc-re-builder.el: -------------------------------------------------------------------------------- 1 | ;;; cc-re-builder.el --- Re-Builder Customization -*- lexical-binding: t; -*- 2 | 3 | ;; Copyright (C) 2024 Charles Choi 4 | 5 | ;; Author: Charles Choi 6 | ;; Keywords: tools 7 | 8 | ;; This program is free software; you can redistribute it and/or modify 9 | ;; it under the terms of the GNU General Public License as published by 10 | ;; the Free Software Foundation, either version 3 of the License, or 11 | ;; (at your option) any later version. 12 | 13 | ;; This program is distributed in the hope that it will be useful, 14 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | ;; GNU General Public License for more details. 17 | 18 | ;; You should have received a copy of the GNU General Public License 19 | ;; along with this program. If not, see . 20 | 21 | ;;; Commentary: 22 | 23 | ;; 24 | 25 | ;;; Code: 26 | 27 | (use-package re-builder 28 | :defer t) 29 | 30 | (use-package casual-re-builder 31 | :ensure nil 32 | :bind (:map 33 | reb-mode-map ("C-o" . casual-re-builder-tmenu) 34 | :map 35 | reb-lisp-mode-map ("C-o" . casual-re-builder-tmenu)) 36 | :after (re-builder)) 37 | 38 | (provide 'cc-re-builder) 39 | ;;; cc-re-builder.el ends here 40 | -------------------------------------------------------------------------------- /cc-region-operations-menu.el: -------------------------------------------------------------------------------- 1 | ;;; cc-region-operations-menu.el --- Region Operations Menu -*- lexical-binding: t; -*- 2 | 3 | ;; Copyright (C) 2023-2024 Charles Choi 4 | 5 | ;; Author: Charles Choi 6 | 7 | ;; Keywords: tools 8 | 9 | ;; This program is free software; you can redistribute it and/or modify 10 | ;; it under the terms of the GNU General Public License as published by 11 | ;; the Free Software Foundation, either version 3 of the License, or 12 | ;; (at your option) any later version. 13 | 14 | ;; This program is distributed in the hope that it will be useful, 15 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | ;; GNU General Public License for more details. 18 | 19 | ;; You should have received a copy of the GNU General Public License 20 | ;; along with this program. If not, see . 21 | 22 | ;;; Commentary: 23 | ;; 24 | 25 | (require 'cc-context-menu-macros) 26 | 27 | ;;; Code: 28 | 29 | (easy-menu-define cc/region-operations-menu nil 30 | "Keymap for Region Operations submenu." 31 | '("Operate on Region" 32 | :visible (region-active-p) 33 | ["Write to file…" write-region 34 | :enable (region-active-p) 35 | :help "Write current region into specified file."] 36 | 37 | ["Search with Google" google-this-noconfirm 38 | :enable (region-active-p) 39 | :label (cc/context-menu-label "Search with Google") 40 | :help "Search Google with selected region"] 41 | 42 | ["Translate" google-translate-smooth-translate 43 | :enable (region-active-p) 44 | :label (concat (cc/context-menu-label "Translate") "…") 45 | :help "Translate selected region with Google Translate"] 46 | 47 | ["Upload to Webpaste" webpaste-paste-region 48 | :enable (region-active-p) 49 | :label (cc/context-menu-label "Upload to Webpaste") 50 | :help "Upload selected region to paste service leaving \ 51 | link in the clipboard"] 52 | 53 | ["Start Speaking" cc/say-region 54 | :enable (region-active-p) 55 | :help "Start speaking selected region"] 56 | 57 | ["Call" cc/call-nanp-phone-number 58 | :enable (region-active-p) 59 | :label (cc/context-menu-label "Call") 60 | :visible (cc/nanp-phone-number-p) 61 | :help "Call phone number"] 62 | 63 | ["Open in Apple Maps" cc/open-region-in-apple-maps 64 | :enable (region-active-p) 65 | :label (cc/context-menu-label "Open in Apple Maps") 66 | :visible (not (cc/nanp-phone-number-p)) 67 | :help "Open in Apple Maps"])) 68 | 69 | (provide 'cc-region-operations-menu) 70 | ;;; cc-region-operations-menu.el ends here 71 | -------------------------------------------------------------------------------- /cc-repeat-mode.el: -------------------------------------------------------------------------------- 1 | ;;; cc-repeat-mode.el --- Repeat Mode Customization -*- lexical-binding: t; -*- 2 | 3 | ;; Copyright (C) 2023-2024 Charles Choi 4 | 5 | ;; Author: Charles Choi 6 | 7 | ;; Keywords: tools 8 | 9 | ;; This program is free software; you can redistribute it and/or modify 10 | ;; it under the terms of the GNU General Public License as published by 11 | ;; the Free Software Foundation, either version 3 of the License, or 12 | ;; (at your option) any later version. 13 | 14 | ;; This program is distributed in the hope that it will be useful, 15 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | ;; GNU General Public License for more details. 18 | 19 | ;; You should have received a copy of the GNU General Public License 20 | ;; along with this program. If not, see . 21 | 22 | ;;; Commentary: 23 | ;; 24 | 25 | ;;; Code: 26 | (require 'org) 27 | 28 | (defvar vifon/buffer-nextprev-repeat-map 29 | (let ((map (make-sparse-keymap))) 30 | (keymap-set map "" #'next-buffer) 31 | (keymap-set map "" #'next-buffer) 32 | (keymap-set map "" #'previous-buffer) 33 | (keymap-set map "" #'previous-buffer) 34 | map)) 35 | ;;(put 'next-buffer 'repeat-map 'vifon/buffer-nextprev-repeat-map) 36 | ;;(put 'previous-buffer 'repeat-map 'vifon/buffer-nextprev-repeat-map) 37 | 38 | (defun repeatize (keymap) 39 | "Add `repeat-mode' support to a KEYMAP." 40 | (map-keymap 41 | (lambda (_key cmd) 42 | (when (symbolp cmd) 43 | (put cmd 'repeat-map keymap))) 44 | (symbol-value keymap))) 45 | 46 | (defvar cc/org-header-navigation-repeat-map 47 | (let ((map (make-sparse-keymap))) 48 | (keymap-set map "p" #'org-previous-visible-heading) 49 | (keymap-set map "n" #'org-next-visible-heading) 50 | map)) 51 | 52 | (repeatize 'vifon/buffer-nextprev-repeat-map) 53 | (repeatize 'cc/org-header-navigation-repeat-map) 54 | 55 | (repeat-mode) 56 | 57 | (provide 'cc-repeat-mode) 58 | ;;; cc-repeat-mode.el ends here 59 | -------------------------------------------------------------------------------- /cc-save-hooks.el: -------------------------------------------------------------------------------- 1 | ;;; cc-save-hooks.el --- CC Save Hooks -*- lexical-binding: t; -*- 2 | 3 | ;; Copyright (C) 2023-2024 Charles Choi 4 | 5 | ;; Author: Charles Choi 6 | ;; Keywords: tools 7 | 8 | ;; This program is free software; you can redistribute it and/or modify 9 | ;; it under the terms of the GNU General Public License as published by 10 | ;; the Free Software Foundation, either version 3 of the License, or 11 | ;; (at your option) any later version. 12 | 13 | ;; This program is distributed in the hope that it will be useful, 14 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | ;; GNU General Public License for more details. 17 | 18 | ;; You should have received a copy of the GNU General Public License 19 | ;; along with this program. If not, see . 20 | 21 | ;;; Commentary: 22 | 23 | ;; 24 | 25 | ;;; Code: 26 | 27 | (defun cc/save-hook-delete-trailing-whitespace () 28 | (add-hook 'before-save-hook #'delete-trailing-whitespace nil t)) 29 | 30 | (provide 'cc-save-hooks) 31 | ;;; cc-save-hooks.el ends here 32 | -------------------------------------------------------------------------------- /cc-sgml-mode.el: -------------------------------------------------------------------------------- 1 | ;;; cc-sgml-mode.el --- SGML Mode Customization -*- lexical-binding: t; -*- 2 | 3 | ;; Copyright (C) 2024 Charles Choi 4 | 5 | ;; Author: Charles Choi 6 | ;; Keywords: tools 7 | 8 | ;; This program is free software; you can redistribute it and/or modify 9 | ;; it under the terms of the GNU General Public License as published by 10 | ;; the Free Software Foundation, either version 3 of the License, or 11 | ;; (at your option) any later version. 12 | 13 | ;; This program is distributed in the hope that it will be useful, 14 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | ;; GNU General Public License for more details. 17 | 18 | ;; You should have received a copy of the GNU General Public License 19 | ;; along with this program. If not, see . 20 | 21 | ;;; Commentary: 22 | 23 | ;; 24 | 25 | ;;; Code: 26 | 27 | (require 'sgml-mode) ;; inherits from text-mode 28 | (require 'display-line-numbers) 29 | (require 'elec-pair) 30 | (require 'hl-line) 31 | (require 'cc-save-hooks) 32 | 33 | (add-hook 'sgml-mode-hook #'display-line-numbers-mode) 34 | (add-hook 'sgml-mode-hook #'rainbow-mode) 35 | (add-hook 'sgml-mode-hook #'electric-pair-mode) 36 | (add-hook 'sgml-mode-hook #'sgml-electric-tag-pair-mode) 37 | (add-hook 'sgml-mode-hook #'cc/save-hook-delete-trailing-whitespace) 38 | (add-hook 'sgml-mode-hook #'hl-line-mode) 39 | 40 | (keymap-set sgml-mode-map "M-[" #'sgml-skip-tag-backward) 41 | (keymap-set sgml-mode-map "M-]" #'sgml-skip-tag-forward) 42 | 43 | (provide 'cc-sgml-mode) 44 | ;;; cc-sgml-mode.el ends here 45 | -------------------------------------------------------------------------------- /cc-shell-mode.el: -------------------------------------------------------------------------------- 1 | ;;; cc-shell-mode.el --- Shell Mode Customization -*- lexical-binding: t; -*- 2 | 3 | ;; Copyright (C) 2023-2024 Charles Choi 4 | 5 | ;; Author: Charles Choi 6 | 7 | ;; Keywords: tools 8 | 9 | ;; This program is free software; you can redistribute it and/or modify 10 | ;; it under the terms of the GNU General Public License as published by 11 | ;; the Free Software Foundation, either version 3 of the License, or 12 | ;; (at your option) any later version. 13 | 14 | ;; This program is distributed in the hope that it will be useful, 15 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | ;; GNU General Public License for more details. 18 | 19 | ;; You should have received a copy of the GNU General Public License 20 | ;; along with this program. If not, see . 21 | 22 | ;;; Commentary: 23 | ;; 24 | 25 | ;;; Code: 26 | 27 | (add-hook 'shell-mode-hook 'context-menu-mode) 28 | (keymap-set shell-mode-map "C-p" #'comint-previous-input) 29 | (keymap-set shell-mode-map "C-n" #'comint-next-input) 30 | 31 | (keymap-set shell-mode-map "M-b" #'backward-sexp) 32 | (keymap-set shell-mode-map "M-f" #'cc/next-sexp) 33 | (keymap-set shell-mode-map "C-" #'backward-sexp) 34 | (keymap-set shell-mode-map "C-" #'cc/next-sexp) 35 | ;; (keymap-set shell-mode-map "C-" #'backward-up-list) 36 | ;; (keymap-set shell-mode-map "C-" #'down-list) 37 | 38 | (provide 'cc-shell-mode) 39 | ;;; cc-shell-mode.el ends here 40 | -------------------------------------------------------------------------------- /cc-style-text-menu.el: -------------------------------------------------------------------------------- 1 | ;;; cc-style-text-menu.el --- Style Text Menus -*- lexical-binding: t; -*- 2 | 3 | ;; Copyright (C) 2023-2024 Charles Choi 4 | 5 | ;; Author: Charles Choi 6 | 7 | ;; Keywords: tools 8 | 9 | ;; This program is free software; you can redistribute it and/or modify 10 | ;; it under the terms of the GNU General Public License as published by 11 | ;; the Free Software Foundation, either version 3 of the License, or 12 | ;; (at your option) any later version. 13 | 14 | ;; This program is distributed in the hope that it will be useful, 15 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | ;; GNU General Public License for more details. 18 | 19 | ;; You should have received a copy of the GNU General Public License 20 | ;; along with this program. If not, see . 21 | 22 | ;;; Commentary: 23 | ;; 24 | 25 | (require 'cc-context-menu-macros) 26 | (require 'markdown-mode) 27 | (require 'org) 28 | 29 | ;; (defun cc/org-emphasize-reset () 30 | ;; ;; this won't work when org-hide-emphasis-markers is turned on. 31 | ;; (interactive) 32 | ;; (org-emphasize ?\s)) 33 | 34 | ;;; Code: 35 | 36 | (defun cc/emphasize-bold () 37 | "Mark region bold for Org or Markdown modes." 38 | (interactive) 39 | (when (not (use-region-p)) 40 | (beginning-of-thing 'sexp) 41 | (mark-sexp)) 42 | (cond ((derived-mode-p 'org-mode) 43 | (org-emphasize ?*)) 44 | ((derived-mode-p 'markdown-mode) 45 | (markdown-insert-bold)) 46 | (t nil))) 47 | 48 | (defun cc/emphasize-italic () 49 | "Mark region italic for Org or Markdown modes." 50 | (interactive) 51 | (when (not (use-region-p)) 52 | (beginning-of-thing 'sexp) 53 | (mark-sexp)) 54 | (cond ((derived-mode-p 'org-mode) 55 | (org-emphasize ?/)) 56 | ((derived-mode-p 'markdown-mode) 57 | (markdown-insert-italic)) 58 | (t nil))) 59 | 60 | (defun cc/emphasize-code () 61 | "Mark region code for Org or Markdown modes." 62 | (interactive) 63 | (when (not (use-region-p)) 64 | (beginning-of-thing 'sexp) 65 | (mark-sexp)) 66 | (cond ((derived-mode-p 'org-mode) 67 | (org-emphasize ?~)) 68 | ((derived-mode-p 'markdown-mode) 69 | (markdown-insert-code)) 70 | (t nil))) 71 | 72 | (defun cc/emphasize-underline () 73 | "Mark region underline for Org mode." 74 | (interactive) 75 | (when (not (use-region-p)) 76 | (beginning-of-thing 'sexp) 77 | (mark-sexp)) 78 | (cond ((derived-mode-p 'org-mode) 79 | (org-emphasize ?_)) 80 | (t nil))) 81 | 82 | (defun cc/emphasize-verbatim () 83 | "Mark region verbatim for Org mode." 84 | (interactive) 85 | (when (not (use-region-p)) 86 | (beginning-of-thing 'sexp) 87 | (mark-sexp)) 88 | (cond ((derived-mode-p 'org-mode) 89 | (org-emphasize ?=)) 90 | (t nil))) 91 | 92 | (defun cc/emphasize-strike-through () 93 | "Mark region strike-through for Org or Markdown modes." 94 | (interactive) 95 | (when (not (use-region-p)) 96 | (beginning-of-thing 'sexp) 97 | (mark-sexp)) 98 | (cond ((derived-mode-p 'org-mode) 99 | (org-emphasize ?+)) 100 | ((derived-mode-p 'markdown-mode) 101 | (markdown-insert-strike-through)) 102 | (t nil))) 103 | 104 | (defun cc/emphasize-remove () 105 | "Remove marked region." 106 | (interactive) 107 | (when (not (use-region-p)) 108 | (beginning-of-thing 'sexp) 109 | (mark-sexp)) 110 | (cond ((derived-mode-p 'org-mode) 111 | (org-emphasize ? )) 112 | ((derived-mode-p 'markdown-mode) 113 | (message "unsupported.")) 114 | (t nil))) 115 | 116 | (defun cc/emphasize-dwim () 117 | "DWIM emphasize text for Org or Markdown. 118 | 119 | This command will appropriately style either a region or the text 120 | the point is in depending on whether the current major mode is 121 | Org or Markdown. Selection of the emphasis style is done by 122 | mini-buffer command completion. 123 | 124 | If no region is defined, then the text amount is considered to be 125 | a balanced expression (sexp). A balanced expression is used as it 126 | can cover most cases of applying the style to text that is 127 | contiguous without spaces." 128 | (interactive) 129 | (let* ((styles (list "bold" "italic" "code" 130 | "underline" "verbatim" "strike" "remove")) 131 | (choice (car (completing-read-multiple "Style: " styles)))) 132 | (when (not (use-region-p)) 133 | (beginning-of-thing 'sexp) 134 | (mark-sexp)) 135 | (cond 136 | ((string= choice "bold") (cc/emphasize-bold)) 137 | ((string= choice "italic") (cc/emphasize-italic)) 138 | ((string= choice "code") (cc/emphasize-code)) 139 | ((string= choice "verbatim") (cc/emphasize-verbatim)) 140 | ((string= choice "underline") (cc/emphasize-underline)) 141 | ((string= choice "strike") (cc/emphasize-strike-through)) 142 | ((string= choice "remove") 143 | (if (derived-mode-p 'org-mode) 144 | (org-emphasize ? ) 145 | (message "remove not supported for Markdown."))) 146 | (t (message "ERROR: undefined choice: %s" choice))))) 147 | 148 | (easy-menu-define cc/emphasize-menu nil 149 | "Keymap for Emphasize Menu." 150 | '("Style" 151 | :visible (region-active-p) 152 | ["Bold" cc/emphasize-bold 153 | :enable (region-active-p) 154 | :visible (or (derived-mode-p 'org-mode) (derived-mode-p 'markdown-mode)) 155 | :help "Bold selected region"] 156 | ["Italic" cc/emphasize-italic 157 | :enable (region-active-p) 158 | :visible (or (derived-mode-p 'org-mode) (derived-mode-p 'markdown-mode)) 159 | :help "Italic selected region"] 160 | ["Code" cc/emphasize-code 161 | :enable (region-active-p) 162 | :visible (or (derived-mode-p 'org-mode) (derived-mode-p 'markdown-mode)) 163 | :help "Code selected region"] 164 | ["Underline" cc/emphasize-underline 165 | :enable (region-active-p) 166 | :visible (derived-mode-p 'org-mode) 167 | :help "Underline selected region"] 168 | ["Verbatim" cc/emphasize-verbatim 169 | :enable (region-active-p) 170 | :visible (derived-mode-p 'org-mode) 171 | :help "Verbatim selected region"] 172 | ["Strike Through" cc/emphasize-strike-through 173 | :enable (region-active-p) 174 | :visible (or (derived-mode-p 'org-mode) (derived-mode-p 'markdown-mode)) 175 | :help "Strike-through selected region"])) 176 | 177 | (provide 'cc-style-text-menu) 178 | 179 | ;;; cc-style-text-menu.el ends here 180 | -------------------------------------------------------------------------------- /cc-swift-mode.el: -------------------------------------------------------------------------------- 1 | ;;; cc-swift-mode.el --- Swift mode configuration -*- lexical-binding: t; -*- 2 | 3 | ;; Copyright (C) 2024 Charles Choi 4 | 5 | ;; Author: Charles Choi 6 | ;; Keywords: tools 7 | 8 | ;; This program is free software; you can redistribute it and/or modify 9 | ;; it under the terms of the GNU General Public License as published by 10 | ;; the Free Software Foundation, either version 3 of the License, or 11 | ;; (at your option) any later version. 12 | 13 | ;; This program is distributed in the hope that it will be useful, 14 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | ;; GNU General Public License for more details. 17 | 18 | ;; You should have received a copy of the GNU General Public License 19 | ;; along with this program. If not, see . 20 | 21 | ;;; Commentary: 22 | 23 | ;; 24 | 25 | ;;; Code: 26 | 27 | (require 'swift-mode) 28 | 29 | (keymap-set swift-mode-map "M-[" #'backward-sexp) 30 | (keymap-set swift-mode-map "M-]" #'forward-sexp) 31 | 32 | (add-hook 'swift-mode-hook (lambda () 33 | (setq fill-column 120))) 34 | 35 | (provide 'cc-swift-mode) 36 | ;;; cc-swift-mode.el ends here 37 | -------------------------------------------------------------------------------- /cc-symbol-overlay.el: -------------------------------------------------------------------------------- 1 | ;;; cc-symbol-overlay.el --- Configuration for Symbol Overlay -*- lexical-binding: t; -*- 2 | 3 | ;; Copyright (C) 2024 Charles Choi 4 | 5 | ;; Author: Charles Choi 6 | ;; Keywords: tools 7 | 8 | ;; This program is free software; you can redistribute it and/or modify 9 | ;; it under the terms of the GNU General Public License as published by 10 | ;; the Free Software Foundation, either version 3 of the License, or 11 | ;; (at your option) any later version. 12 | 13 | ;; This program is distributed in the hope that it will be useful, 14 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | ;; GNU General Public License for more details. 17 | 18 | ;; You should have received a copy of the GNU General Public License 19 | ;; along with this program. If not, see . 20 | 21 | ;;; Commentary: 22 | 23 | ;; 24 | 25 | ;;; Code: 26 | ;;(require 'symbol-overlay) 27 | ;;(require 'casual-lib) 28 | 29 | (require 'casual-symbol-overlay) 30 | (keymap-set symbol-overlay-map "C-o" #'casual-symbol-overlay-tmenu) 31 | 32 | ;; (use-package casual-symbol-overlay 33 | ;; :ensure nil 34 | ;; :bind (:map 35 | ;; symbol-overlay-map 36 | ;; ("C-o" . casual-symbol-overlay-tmenu))) 37 | 38 | (provide 'cc-symbol-overlay) 39 | ;;; cc-symbol-overlay.el ends here 40 | -------------------------------------------------------------------------------- /cc-tetris-mode.el: -------------------------------------------------------------------------------- 1 | ;;; cc-tetris-mode.el --- Tetris Customization -*- lexical-binding: t; -*- 2 | 3 | ;; Copyright (C) 2023-2024 Charles Choi 4 | 5 | ;; Author: Charles Choi 6 | 7 | ;; Keywords: tools 8 | 9 | ;; This program is free software; you can redistribute it and/or modify 10 | ;; it under the terms of the GNU General Public License as published by 11 | ;; the Free Software Foundation, either version 3 of the License, or 12 | ;; (at your option) any later version. 13 | 14 | ;; This program is distributed in the hope that it will be useful, 15 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | ;; GNU General Public License for more details. 18 | 19 | ;; You should have received a copy of the GNU General Public License 20 | ;; along with this program. If not, see . 21 | 22 | ;;; Commentary: 23 | ;; 24 | 25 | (require 'tetris) 26 | 27 | ;;; Code: 28 | 29 | (keymap-set tetris-mode-map "j" 'tetris-move-left) 30 | (keymap-set tetris-mode-map "i" 'tetris-rotate-prev) 31 | (keymap-set tetris-mode-map "k" 'tetris-rotate-next) 32 | (keymap-set tetris-mode-map "l" 'tetris-move-right) 33 | (keymap-set tetris-mode-map "m" 'tetris-move-down) 34 | 35 | (provide 'cc-tetris-mode) 36 | ;;; cc-tetris-mode.el ends here 37 | -------------------------------------------------------------------------------- /cc-text-mode.el: -------------------------------------------------------------------------------- 1 | ;;; cc-text-mode.el --- Text Mode Customization -*- lexical-binding: t; -*- 2 | 3 | ;; Copyright (C) 2023-2024 Charles Choi 4 | 5 | ;; Author: Charles Choi 6 | 7 | ;; Keywords: tools 8 | 9 | ;; This program is free software; you can redistribute it and/or modify 10 | ;; it under the terms of the GNU General Public License as published by 11 | ;; the Free Software Foundation, either version 3 of the License, or 12 | ;; (at your option) any later version. 13 | 14 | ;; This program is distributed in the hope that it will be useful, 15 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | ;; GNU General Public License for more details. 18 | 19 | ;; You should have received a copy of the GNU General Public License 20 | ;; along with this program. If not, see . 21 | 22 | ;;; Commentary: 23 | ;; 24 | 25 | ;;; Code: 26 | 27 | (add-hook 'text-mode-hook 'visual-line-mode) 28 | (add-hook 'text-mode-hook 'context-menu-mode) 29 | (add-hook 'text-mode-hook 'flyspell-mode) 30 | (add-hook 'text-mode-hook 'company-mode) 31 | 32 | (add-hook 'text-mode-hook (lambda () 33 | (setq-local line-spacing 0.1))) 34 | 35 | (keymap-set text-mode-map "A-" #'backward-sentence) 36 | (keymap-set text-mode-map "A-" #'forward-sentence) 37 | (keymap-set text-mode-map "A-M-" #'backward-paragraph) 38 | (keymap-set text-mode-map "A-M-" #'forward-paragraph) 39 | (keymap-set text-mode-map "M-/" #'hippie-expand) 40 | 41 | ;;(setq auto-mode-alist (cons (cons "\\.txt$" 'text-mode) auto-mode-alist)) 42 | ;;(setq auto-mode-alist (cons (cons "\\.text$" 'text-mode) auto-mode-alist)) 43 | ;;(setq auto-mode-alist (cons (cons "\\.mml$" 'text-mode) auto-mode-alist)) 44 | 45 | (provide 'cc-text-mode) 46 | ;;; cc-text-mode.el ends here 47 | -------------------------------------------------------------------------------- /cc-transform-text-menu.el: -------------------------------------------------------------------------------- 1 | ;;; cc-transform-text-menu.el --- Transform Text Menu -*- lexical-binding: t; -*- 2 | 3 | ;; Copyright (C) 2023-2024 Charles Choi 4 | 5 | ;; Author: Charles Choi 6 | 7 | ;; Keywords: tools 8 | 9 | ;; This program is free software; you can redistribute it and/or modify 10 | ;; it under the terms of the GNU General Public License as published by 11 | ;; the Free Software Foundation, either version 3 of the License, or 12 | ;; (at your option) any later version. 13 | 14 | ;; This program is distributed in the hope that it will be useful, 15 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | ;; GNU General Public License for more details. 18 | 19 | ;; You should have received a copy of the GNU General Public License 20 | ;; along with this program. If not, see . 21 | 22 | ;;; Commentary: 23 | ;; 24 | 25 | (require 'cc-context-menu-macros) 26 | 27 | ;; (defvar cc/transform-text-menu (make-sparse-keymap "Transform Text") 28 | ;; "Keymap for Transform Text submenu.") 29 | 30 | ;;; Code: 31 | 32 | (easy-menu-define cc/transform-text-menu nil 33 | "Keymap for Transform Text submenu." 34 | '("Transform Text" 35 | :visible (region-active-p) 36 | ["Make Upper Case" upcase-region 37 | :enable (region-active-p) 38 | :help "Convert selected region to upper case"] 39 | ["Make Lower Case" downcase-region 40 | :enable (region-active-p) 41 | :help "Convert selected region to lower case"] 42 | ["Capitalize" capitalize-region 43 | :enable (region-active-p) 44 | :help "Convert the selected region to capitalized form"])) 45 | 46 | (provide 'cc-transform-text-menu) 47 | ;;; cc-transform-text-menu.el ends here 48 | -------------------------------------------------------------------------------- /cc-truth-table.el: -------------------------------------------------------------------------------- 1 | ;;; cc-truth-table.el --- Truth Table -*- lexical-binding: t; -*- 2 | 3 | ;; Copyright (C) 2024 Charles Choi 4 | 5 | ;; Author: Charles Choi 6 | ;; Keywords: tools 7 | 8 | ;; This program is free software; you can redistribute it and/or modify 9 | ;; it under the terms of the GNU General Public License as published by 10 | ;; the Free Software Foundation, either version 3 of the License, or 11 | ;; (at your option) any later version. 12 | 13 | ;; This program is distributed in the hope that it will be useful, 14 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | ;; GNU General Public License for more details. 17 | 18 | ;; You should have received a copy of the GNU General Public License 19 | ;; along with this program. If not, see . 20 | 21 | ;;; Commentary: 22 | 23 | ;; This package includes functions to support the insertion of a truth table 24 | ;; input into a buffer. Primarily intended for use in Org mode so that the 25 | ;; the input values can be operated on with boolean functions defined in 26 | ;; `cc-digital-logic'. 27 | ;; 28 | 29 | ;;; Code: 30 | 31 | (defun tj/int-to-binary-string (i) 32 | "Convert integer I into its binary representation in string format. 33 | This code written by Trey Jackson as SO example. 34 | https://stackoverflow.com/questions/20568684/converting-number-to-base-2-binary-string-representation" 35 | (let ((res "")) 36 | (while (not (= i 0)) 37 | (setq res (concat (if (= 1 (logand i 1)) "1" "0") res)) 38 | (setq i (ash i -1))) 39 | (if (string= res "") 40 | (setq res "0")) 41 | res)) 42 | 43 | (defun cc-int-to-binary-list (i) 44 | "Generate list holding binary string representation of I." 45 | (mapcar (lambda (x) (string x)) (tj/int-to-binary-string i))) 46 | 47 | (defun py-range (start &optional end step) 48 | "Python range emulation. 49 | This function emulates the Python range function in Elisp. 50 | START - start value of range. 51 | END - end value of range. 52 | STEP - step value for generated range. 53 | 54 | Written by michaelJohn 55 | https://stackoverflow.com/questions/15014996/range-data-type-or-generator-in-emacs-lisp-elisp" 56 | (unless end 57 | (setq end start 58 | start 0)) 59 | (number-sequence start (1- end) step)) 60 | 61 | (defun cc/truth-table-input (bits) 62 | "Generate list of strings holding a truth table input with 2^BITS rows." 63 | (let* ((max (expt 2 bits)) 64 | (truth-table-range (py-range max)) 65 | (header-list-exponents 66 | (mapcar 'number-to-string (reverse (py-range bits)))) 67 | (header-list (push "i" header-list-exponents)) 68 | (header (format "|%s|" (string-join header-list "|"))) 69 | (header-separator 70 | (format "|%s|" 71 | (string-join (make-list (1+ bits) "-") 72 | "+"))) 73 | (result (list header-separator header))) 74 | 75 | (dolist (e truth-table-range) 76 | (setq-local binary-list (cc-int-to-binary-list e)) 77 | (setq-local binary-list-offset (- bits (length binary-list))) 78 | 79 | (if (> binary-list-offset 0) 80 | (dolist (_ (py-range 0 binary-list-offset)) 81 | (push "0" binary-list))) 82 | 83 | (push (format "|%s|%s|" e (string-join binary-list "|")) result)) 84 | (reverse result))) 85 | 86 | (defun cc/insert-truth-table-input (bits) 87 | "Insert truth table input with 2^BITS rows into current buffer. 88 | If BITS is greater than 4, then a prompt is asked to avoid creation of 89 | large tables." 90 | (interactive "nNumber of inputs (bits): ") 91 | 92 | (if (> bits 4) 93 | (if (y-or-n-p 94 | (format 95 | "This will generate a table with %s rows. Continue? " 96 | (expt 2 bits))) 97 | (let ((truth-table (cc/truth-table-input bits))) 98 | (insert (string-join truth-table "\n")))) 99 | (let ((truth-table (cc/truth-table-input bits))) 100 | (insert (string-join truth-table "\n"))))) 101 | 102 | 103 | (provide 'cc-truth-table) 104 | ;;; cc-truth-table.el ends here 105 | -------------------------------------------------------------------------------- /cc-view-mode.el: -------------------------------------------------------------------------------- 1 | ;;; cc-view-mode.el -*- lexical-binding: t; -*- 2 | 3 | ;; Copyright (C) 2023-2024 Charles Choi 4 | 5 | ;; Author: Charles Choi 6 | 7 | ;; Keywords: tools 8 | 9 | ;; This program is free software; you can redistribute it and/or modify 10 | ;; it under the terms of the GNU General Public License as published by 11 | ;; the Free Software Foundation, either version 3 of the License, or 12 | ;; (at your option) any later version. 13 | 14 | ;; This program is distributed in the hope that it will be useful, 15 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | ;; GNU General Public License for more details. 18 | 19 | ;; You should have received a copy of the GNU General Public License 20 | ;; along with this program. If not, see . 21 | ;;; Commentary: 22 | 23 | ;;; Code: 24 | 25 | (require 'view) 26 | (require 'cclisp) 27 | (require 'org) 28 | (require 'markdown-mode) 29 | (require 'sgml-mode) 30 | (require 'python) 31 | (require 'elisp-mode) 32 | (require 'make-mode) 33 | (require 'cc-cmds) 34 | 35 | (add-hook 'view-mode-hook 'hl-line-mode) 36 | 37 | (defun cc/view-exit () 38 | "Advice function to disable highlighting upon exiting view-mode." 39 | (if (not (derived-mode-p 'prog-mode)) 40 | (hl-line-mode -1))) 41 | 42 | (advice-add 'View-exit :after #'cc/view-exit) 43 | 44 | (add-hook 45 | 'view-mode-hook 46 | (lambda () 47 | (cond ((derived-mode-p 'org-mode) 48 | (keymap-set view-mode-map "j" #'cc/browse-forward-paragraph) 49 | (keymap-set view-mode-map "k" #'cc/browse-backward-paragraph) 50 | (keymap-set view-mode-map "p" #'org-previous-visible-heading) 51 | (keymap-set view-mode-map "n" #'org-next-visible-heading)) 52 | ((derived-mode-p 'markdown-mode) 53 | (keymap-set view-mode-map "j" #'cc/browse-forward-paragraph) 54 | (keymap-set view-mode-map "k" #'cc/browse-backward-paragraph) 55 | (keymap-set view-mode-map "p" #'markdown-outline-previous) 56 | (keymap-set view-mode-map "n" #'markdown-outline-next)) 57 | ((derived-mode-p 'html-mode) 58 | (keymap-set view-mode-map "p" #'sgml-skip-tag-backward) 59 | (keymap-set view-mode-map "n" #'sgml-skip-tag-forward)) 60 | ((derived-mode-p 'python-mode) 61 | (keymap-set view-mode-map "p" #'python-nav-backward-block) 62 | (keymap-set view-mode-map "n" #'python-nav-forward-block)) 63 | ((derived-mode-p 'emacs-lisp-mode) 64 | (keymap-set view-mode-map "p" #'backward-sexp) 65 | (keymap-set view-mode-map "n" #'forward-sexp)) 66 | ((derived-mode-p 'makefile-mode) 67 | (keymap-set view-mode-map "p" #'makefile-previous-dependency) 68 | (keymap-set view-mode-map "n" #'makefile-next-dependency)) 69 | ((derived-mode-p 'c-mode) 70 | (keymap-set view-mode-map "p" #'c-beginning-of-defun) 71 | (keymap-set view-mode-map "n" #'c-end-of-defun)) 72 | (t 73 | (keymap-set view-mode-map "p" #'scroll-down-command) 74 | (keymap-set view-mode-map "n" #'scroll-up-command))))) 75 | 76 | (provide 'cc-view-mode) 77 | ;;; cc-view-mode.el ends here 78 | -------------------------------------------------------------------------------- /cc-wgrep-mode.el: -------------------------------------------------------------------------------- 1 | ;;; cc-wgrep-mode.el --- wgrep configuration -*- lexical-binding: t; -*- 2 | 3 | ;; Copyright (C) 2023-2024 Charles Choi 4 | 5 | ;; Author: Charles Choi 6 | 7 | ;; Keywords: tools 8 | 9 | ;; This program is free software; you can redistribute it and/or modify 10 | ;; it under the terms of the GNU General Public License as published by 11 | ;; the Free Software Foundation, either version 3 of the License, or 12 | ;; (at your option) any later version. 13 | 14 | ;; This program is distributed in the hope that it will be useful, 15 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | ;; GNU General Public License for more details. 18 | 19 | ;; You should have received a copy of the GNU General Public License 20 | ;; along with this program. If not, see . 21 | 22 | ;;; Commentary: 23 | ;; 24 | 25 | (require 'wgrep) 26 | 27 | (easy-menu-define cc/wgrep-menu nil 28 | "Keymap for wgrep menu" 29 | '("Writeable Grep" 30 | :visible (derived-mode-p 'grep-mode) 31 | ["Change to wgrep mode" wgrep-change-to-wgrep-mode 32 | :enable (equal buffer-read-only t) 33 | :help "Change to wgrep mode."] 34 | 35 | ["Finish Edit" wgrep-finish-edit 36 | :enable (not buffer-read-only) 37 | :help "Apply the changes to file buffers and exit."] 38 | 39 | ["Mark Current Line for Deletion" wgrep-mark-deletion 40 | :enable (not buffer-read-only) 41 | :help "Mark as delete to current line (including newline)."] 42 | 43 | ["Toggle Readonly" wgrep-toggle-readonly-area 44 | :enable (not buffer-read-only) 45 | :help "Toggle read-only area to remove a whole line."] 46 | 47 | ["Remove Change" wgrep-remove-change 48 | :enable (not buffer-read-only) 49 | :help "Remove changes in the region between BEG and END."] 50 | 51 | ["Remove All Changes" wgrep-remove-all-change 52 | :enable (not buffer-read-only) 53 | :help "Remove changes in the whole buffer."] 54 | 55 | ["Abort Changes and Exit" wgrep-abort-changes 56 | :enable (not buffer-read-only) 57 | :help "Discard all changes and return to original mode."] 58 | 59 | ["Exit" wgrep-exit 60 | :enable (not buffer-read-only) 61 | :help "Return to original mode."])) 62 | 63 | (easy-menu-add-item grep-menu-map nil 64 | cc/wgrep-menu 65 | nil) 66 | 67 | (provide 'cc-wgrep-mode) 68 | ;;; cc-wgrep-mode.el ends here 69 | -------------------------------------------------------------------------------- /ccinit.el: -------------------------------------------------------------------------------- 1 | ;;; ccinit.el --- CC Emacs Init File -*- lexical-binding: t; -*- 2 | 3 | ;; Copyright (C) 2023-2025 Charles Choi 4 | 5 | ;; Author: Charles Choi 6 | 7 | ;; Keywords: tools 8 | 9 | ;; This program is free software; you can redistribute it and/or modify 10 | ;; it under the terms of the GNU General Public License as published by 11 | ;; the Free Software Foundation, either version 3 of the License, or 12 | ;; (at your option) any later version. 13 | 14 | ;; This program is distributed in the hope that it will be useful, 15 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | ;; GNU General Public License for more details. 18 | 19 | ;; You should have received a copy of the GNU General Public License 20 | ;; along with this program. If not, see . 21 | 22 | ;;; Commentary: 23 | ;; Charles Choi Emacs Initialization File 24 | 25 | ;;; Code: 26 | (setenv "CDPATH" ".:..:~") 27 | 28 | (when (or (eq window-system 'mac) (eq window-system 'ns)) 29 | (setenv "PATH" (concat "/Applications/Inkscape.app/Contents/MacOS:" (getenv "PATH"))) 30 | (setenv "PATH" (concat "/opt/local/bin:" (getenv "PATH"))) 31 | (setenv "PATH" (concat "/opt/local/libexec/gnubin:" (getenv "PATH"))) 32 | (setenv "PATH" (concat "/opt/local/lib/ImageMagick7/bin:" (getenv "PATH"))) 33 | (setenv "PATH" (concat (getenv "HOME") "/bin:" (getenv "PATH"))) 34 | (add-to-list 'exec-path "/Applications/Inkscape.app/Contents/MacOS") 35 | (add-to-list 'exec-path "/opt/local/bin") 36 | (add-to-list 'exec-path "/opt/local/libexec/gnubin") 37 | (add-to-list 'exec-path "/opt/local/lib/ImageMagick7/bin") 38 | (add-to-list 'exec-path (concat (getenv "HOME") "/bin"))) 39 | 40 | (require 'use-package) 41 | (require 'expand-region) 42 | (require 'wgrep) 43 | (require 'yasnippet) 44 | ;;(require 'pbcopy) 45 | (add-hook 'calendar-today-visible-hook 'calendar-mark-today) 46 | 47 | (yas-global-mode 1) 48 | (set-language-environment "UTF-8") 49 | (set-default-coding-systems 'utf-8-unix) 50 | (recentf-mode 1) 51 | 52 | ;; (when (eq window-system 'x) 53 | ;; (setq x-meta-keysym 'super 54 | ;; x-super-keysym 'meta) 55 | ;; (turn-on-pbcopy)) 56 | 57 | ;;(setq mouse-wheel-scroll-amount '(1 ((shift) . 1))) 58 | ;;(setq mouse-wheel-progressive-speed nil) 59 | ;;(setq mouse-wheel-follow-mouse 't) 60 | ;;(setq scroll-step 1) 61 | 62 | ;; (when (eq window-system 'mac) 63 | ;; (setq mac-mouse-wheel-mode t) 64 | ;; (setq mac-mouse-wheel-smooth-scroll t)) 65 | 66 | ;;(setq pixel-scroll-precision-large-scroll-height 10.0) 67 | 68 | (when (eq window-system 'ns) 69 | (setq mac-command-modifier 'meta)) 70 | 71 | (require 'cclisp) 72 | (require 'cc-ibuffer-mode) 73 | (require 'cc-prog-mode) 74 | (require 'cc-emacs-lisp-mode) 75 | (require 'cc-text-mode) 76 | (require 'cc-org-mode) 77 | (require 'cc-org-agenda) 78 | (require 'cc-markdown-mode) 79 | (require 'cc-objc-mode) 80 | (require 'cc-nxml-mode) 81 | (require 'cc-sgml-mode) 82 | (require 'cc-bookmarks-bmenu-mode) 83 | (require 'cc-dired-mode) 84 | (require 'cc-js-mode) 85 | (require 'cc-tetris-mode) 86 | (require 'cc-eshell-mode) 87 | (require 'cc-shell-mode) 88 | (require 'cc-elfeed-mode) 89 | (require 'cc-google-translate) 90 | (require 'cc-repeat-mode) 91 | (require 'cc-doc-mode-ux) 92 | (require 'cc-info-mode) 93 | (require 'cc-ediff-mode) 94 | (require 'cc-occur-mode) 95 | (require 'cc-context-menu) 96 | (require 'cc-diff-hl-mode) 97 | (require 'cc-python-mode) 98 | (require 'cc-swift-mode) 99 | (require 'flyspell) 100 | (require 'cc-view-mode) 101 | (require 'cc-global-keybindings) 102 | (require 'cc-magit-mode) 103 | (require 'cc-menu-reconfig) 104 | (require 'cc-grep-mode) 105 | (require 'kill-with-intelligence) 106 | (require 'cc-agenda-timeline) 107 | (require 'cc-truth-table) 108 | (require 'cc-digital-logic) 109 | (require 'cc-package-menu-mode) 110 | (require 'cc-calc-mode) 111 | (require 'cc-re-builder) 112 | (require 'cc-symbol-overlay) 113 | (require 'cc-calendar-mode) 114 | (require 'password-store-menu) 115 | (require 'cc-image-mode) 116 | (require 'cc-make-mode) 117 | (require 'cc-csv-mode) 118 | (require 'cc-gh) 119 | (require 'ffap) 120 | (require 'calle24) 121 | (require 'scrim-utils) 122 | 123 | ;;; Configure MELPA Packages 124 | (require 'casual-isearch) 125 | (keymap-set isearch-mode-map "C-o" #'casual-isearch-tmenu) 126 | 127 | ;; calle24 config 128 | (when (featurep 'calle24) 129 | (calle24-refresh-appearance) 130 | (add-hook 'compilation-mode-hook #'calle24-refresh-appearance)) 131 | 132 | (use-package hl-line 133 | :ensure nil 134 | :defer t 135 | :hook ((bookmark-bmenu-mode . hl-line-mode) 136 | (ibuffer-mode . hl-line-mode))) 137 | 138 | ;;; Local Customizations 139 | 140 | (when (and (string= (system-name) "bingsu.local") (display-graphic-p)) 141 | (server-start) 142 | (require 'org-protocol)) 143 | 144 | (eval-after-load "flyspell" 145 | '(progn 146 | (define-key flyspell-mouse-map [down-mouse-3] #'flyspell-correct-word) 147 | (define-key flyspell-mouse-map [mouse-3] #'undefined))) 148 | 149 | ;; Miscellaneous Stuff 150 | (fset 'yes-or-no-p 'y-or-n-p) ; set yes-or-no to y-or-n 151 | 152 | ;; (setq tab-bar-mode-hook 153 | ;; '((lambda () 154 | ;; (if (display-graphic-p) 155 | ;; (progn 156 | ;; (local-set-key (kbd "M-]") 'tab-bar-switch-to-next-tab) 157 | ;; (local-set-key (kbd "M-[") 'tab-bar-switch-to-prev-tab))) 158 | ;; ))) 159 | 160 | (add-to-list 'auto-mode-alist '("\\.msc\\'" . graphviz-dot-mode)) 161 | (add-to-list 'auto-mode-alist '("\\.xcconfig\\'" . conf-mode)) 162 | 163 | ;; (when (eq window-system 'mac) 164 | ;; (mac-toggle-tab-bar)) 165 | 166 | (defun cc/tty-mouse () 167 | (interactive) 168 | (unless (display-graphic-p) 169 | (xterm-mouse-mode 1) 170 | (global-set-key (kbd "") 'scroll-down-line) 171 | (global-set-key (kbd "") 'scroll-up-line))) 172 | 173 | (password-store-menu-enable) 174 | 175 | (ffap-bindings) 176 | -------------------------------------------------------------------------------- /kill-with-intelligence.el: -------------------------------------------------------------------------------- 1 | ;; kill-with-intelligence.el --- Making buffer killing suck less. -*- lexical-binding: t -*- 2 | ;; 3 | ;;; Commentary: 4 | ;; Original function at the time of this writing is at: 5 | ;; https://github.com/emacs-mirror/emacs/blob/3907c884f03cf5f2a09696bda015b1060c7111ba/lisp/simple.el#L10980 6 | ;; 7 | ;;; Code: 8 | 9 | (defun ct/kill-buffer--possibly-save--advice (original-function buffer &rest args) 10 | "Ask user in the minibuffer whether to save before killing. 11 | 12 | Replaces `kill-buffer--possibly-save' as advice, so 13 | ORIGINAL-FUNCTION is unused and never delegated to. Its first 14 | parameter is the buffer, which is the `car' or ARGS." 15 | (let ((response 16 | (car 17 | (read-multiple-choice 18 | (format "Buffer %s modified." 19 | (buffer-name)) 20 | '((?s "save" "save then kill buffer") 21 | (?d "discard" "kill buffer without saving") 22 | (?c "cancel" "exit without doing anything")) 23 | nil nil (and (not use-short-answers) 24 | (not (use-dialog-box-p))))))) 25 | (cond ((= response ?s) 26 | (with-current-buffer buffer (save-buffer)) 27 | t) 28 | ((= response ?d) 29 | t) 30 | ((= response ?c) 31 | nil) 32 | ))) 33 | 34 | (advice-add 'kill-buffer--possibly-save :around #'ct/kill-buffer--possibly-save--advice) 35 | 36 | ;;; 37 | 38 | (provide 'kill-with-intelligence) 39 | ;; kill-with-intelligence.el ends here 40 | -------------------------------------------------------------------------------- /recent-rgrep.el: -------------------------------------------------------------------------------- 1 | ;;; recent-rgrep.el --- Sort rgrep by modification time -*- lexical-binding: t; -*- 2 | 3 | ;; Copyright (C) 2025 Charles Choi 4 | 5 | ;; Author: Charles Choi 6 | ;; URL: https://github.com/kickingvegas/recent-rgrep 7 | ;; Keywords: tools 8 | ;; Version: 0.1.0 9 | ;; Package-Requires: ((emacs "29.1")) 10 | 11 | ;; This program is free software; you can redistribute it and/or modify 12 | ;; it under the terms of the GNU General Public License as published by 13 | ;; the Free Software Foundation, either version 3 of the License, or 14 | ;; (at your option) any later version. 15 | 16 | ;; This program is distributed in the hope that it will be useful, 17 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | ;; GNU General Public License for more details. 20 | 21 | ;; You should have received a copy of the GNU General Public License 22 | ;; along with this program. If not, see . 23 | 24 | ;;; Commentary: 25 | 26 | ;; 27 | 28 | ;;; Code: 29 | 30 | (defcustom recent-rgrep-glob-extensions 31 | '("*" 32 | "*.asm" 33 | "*.c" 34 | "*.c++" 35 | "*.cpp" 36 | "*.css" 37 | "*.csv" 38 | "*.dot" 39 | "*.el" 40 | "*.gnuplot" 41 | "*.go" 42 | "*.gv" 43 | "*.h" 44 | "*.htm" 45 | "*.html" 46 | "*.js" 47 | "*.json" 48 | "*.log" 49 | "*.m" 50 | "*.markdown" 51 | "*.md" 52 | "*.org" 53 | "*.pl" 54 | "*.plantuml" 55 | "*.py" 56 | "*.rb" 57 | "*.rs" 58 | "*.sh" 59 | "*.sql" 60 | "*.swift" 61 | "*.txt" 62 | "*.xml") 63 | "List of glob-conforming text extensions." 64 | :group 'grep 65 | :type '(repeat string)) 66 | 67 | 68 | (defun recent-rgrep (query) 69 | "Search QUERY in files recursively and sort by recent modification time. 70 | 71 | From the current directory, this command shall recursively search 72 | files for lines that match the pattern QUERY that is entered with 73 | the first prompt. The results are sorted in recently modified 74 | file order with the most recent files presented at the top of the 75 | buffer. By default, matching QUERY is case-insensitive. 76 | 77 | A second prompt to filter the extent of files to search is 78 | presented. By default, the extent of files searched will be all 79 | non-binary files. Pressing enter with no value on the second 80 | prompt will accomplish this. If filtering is desired, then the 81 | user can specify a file name glob expression via completion. 82 | 83 | The list of different file name glob expressions can be 84 | controlled via the customizable variable 85 | `recent-rgrep-glob-extensions'. 86 | 87 | The format of the QUERY and the glob expression must be GNU grep 88 | compatible. 89 | 90 | If this command is invoked with a prefix (C-u) then the search 91 | will be case-sensitive. 92 | 93 | * Implementation Details 94 | 95 | This command invokes the Bash script recent-rgrep which in turn 96 | invokes grep to do a recursive search of QUERY. 97 | 98 | This script is configured to only look at non-binary files. It 99 | will also not look into SCM directories such as .git. 100 | 101 | * References 102 | 103 | - Info node `(grep) Top' 104 | - Info node `(grep) File and Directory Selection'" 105 | 106 | (interactive "sSearch regexp: ") 107 | 108 | (let* ((file-pattern (completing-read 109 | "In files with extension (default: all): " 110 | recent-rgrep-glob-extensions)) 111 | (dir default-directory) 112 | (commands (list))) 113 | 114 | (push "recent-rgrep" commands) 115 | (if current-prefix-arg 116 | (push "-c" commands)) 117 | 118 | (if (not (string= file-pattern "")) 119 | (push (format "-f '%s'" file-pattern) commands)) 120 | 121 | (push (format "'%s'" query) commands) 122 | 123 | (compilation-start (string-join (reverse commands) " ") #'grep-mode) 124 | (if (eq next-error-last-buffer (current-buffer)) 125 | (setq default-directory dir)))) 126 | 127 | (provide 'recent-rgrep) 128 | ;;; recent-rgrep.el ends here 129 | -------------------------------------------------------------------------------- /scrim-utils.el: -------------------------------------------------------------------------------- 1 | ;;; scrim-utils.el --- Scrim Utilities -*- lexical-binding: t; -*- 2 | 3 | ;; Copyright (C) 2025 Charles Choi 4 | 5 | ;; Author: Charles Choi 6 | ;; Keywords: tools 7 | 8 | ;; This program is free software; you can redistribute it and/or modify 9 | ;; it under the terms of the GNU General Public License as published by 10 | ;; the Free Software Foundation, either version 3 of the License, or 11 | ;; (at your option) any later version. 12 | 13 | ;; This program is distributed in the hope that it will be useful, 14 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | ;; GNU General Public License for more details. 17 | 18 | ;; You should have received a copy of the GNU General Public License 19 | ;; along with this program. If not, see . 20 | 21 | ;;; Commentary: 22 | 23 | ;; 24 | 25 | ;;; Code: 26 | 27 | (require 'info) 28 | (require 'url-util) 29 | 30 | (defun scrim-copy-file-link (arg) 31 | "Copy Scrim file URL into the kill ring with prefix ARG. 32 | 33 | Generate a Scrim file URL “scrim://open” for the current buffer 34 | associated with a file. 35 | 36 | By default the path uses the ‘~’ to substitute for HOME environment 37 | variable. If a prefix ARG is used (‘C-u’) then an absolute path to the 38 | file is used." 39 | (interactive "P") 40 | (if buffer-file-name 41 | (progn 42 | (let* ((filename buffer-file-name) 43 | (filename (if (not arg) 44 | (string-replace (getenv "HOME") "~" filename) 45 | filename)) 46 | (filename (url-encode-url filename)) 47 | (scrim-url (format "scrim://open?file=%s" filename))) 48 | 49 | (message "%s" scrim-url) 50 | (kill-new scrim-url))) 51 | (message "Error: No file name associated with buffer: %s" (buffer-name)))) 52 | 53 | (defun scrim-copy-directory-link (arg) 54 | "Copy Scrim directory URL into the kill ring with prefix ARG. 55 | 56 | Generate a Scrim directory URL “scrim://open” for the current buffer. 57 | 58 | By default the path uses the ‘~’ to substitute for HOME environment 59 | variable. If a prefix ARG is used (‘C-u’) then an absolute path to the 60 | file is used." 61 | (interactive "P") 62 | (if default-directory 63 | (progn 64 | (let* ((dirname default-directory) 65 | (dirname (if (not arg) 66 | (string-replace (getenv "HOME") "~" dirname) 67 | dirname)) 68 | (dirname (url-encode-url dirname)) 69 | (scrim-url (format "scrim://open?file=%s" dirname))) 70 | (message "%s" scrim-url) 71 | (kill-new scrim-url))) 72 | (message "Error: Not a Dired buffer."))) 73 | 74 | (defun scrim-copy-info-link () 75 | "Copy Scrim info URL for current Info node into the kill ring. 76 | 77 | Generate a Scrim info node URL “scrim://info” for the current buffer." 78 | (interactive) 79 | (if (derived-mode-p 'Info-mode) 80 | (progn 81 | (Info-copy-current-node-name) 82 | (let* ((node-name (car kill-ring)) 83 | (node-name (url-encode-url node-name)) 84 | (scrim-url (format "scrim://info?node=%s" node-name))) 85 | 86 | (message "%s" scrim-url) 87 | (kill-new scrim-url))) 88 | (message "Error: Must be in Info buffer."))) 89 | 90 | (provide 'scrim-utils) 91 | ;;; scrim-utils.el ends here 92 | -------------------------------------------------------------------------------- /tests/Makefile: -------------------------------------------------------------------------------- 1 | ## 2 | # Copyright 2024 Charles Y. Choi 3 | # 4 | 5 | TIMESTAMP := $(shell /bin/date "+%Y%m%d_%H%M%S") 6 | INSTALL_DIR=$(HOME)/bin 7 | EXEC_NAME=/Applications/MacPorts/EmacsMac.app/Contents/MacOS/Emacs.sh 8 | ERT_ARGS=-batch -l ert 9 | EMACS=$(EXEC_NAME) $(ERT_ARGS) 10 | ERT_RUN=-f ert-run-tests-batch-and-exit 11 | #ERT_RUN=-f ert-run-tests-batch 12 | 13 | .PHONY: tests 14 | 15 | tests: 16 | $(EMACS) -l ../cc-digital-logic.el \ 17 | -l test-cc-digital-logic.el $(ERT_RUN) 18 | -------------------------------------------------------------------------------- /tests/test-cc-agenda-timeline.el: -------------------------------------------------------------------------------- 1 | (require 'ert) 2 | (require 'cc-agenda-timeline) 3 | 4 | (ert-deftest test-cc/at/closed-agenda-element-p () 5 | (let () 6 | (should (cc/at/closed-agenda-element-p '(("CLOSED" . "<2023-12-03 Sun 16:20>")))) 7 | (should-not (cc/at/closed-agenda-element-p '(("TIMESTAMP" . "<2023-12-03 Sun 16:20>")))) 8 | (should-not (cc/at/closed-agenda-element-p '(("SCHEDULED" . "<2023-12-03 Sun 16:20>")))) 9 | (should-not (cc/at/closed-agenda-element-p '(("DEADLINE" . "<2023-12-03 Sun 16:20>")))) 10 | (should-not (cc/at/closed-agenda-element-p '(("DEADLINE" . "<2023-12-03 Sun 16:20>") 11 | ("SCHEDULED" . "<2023-12-03 Sun 16:20>") 12 | ("TIMESTAMP" . "<2023-12-03 Sun 16:20>")))) 13 | 14 | (should (cc/at/closed-agenda-element-p '(("CLOSED" . "<2023-12-03 Sun 16:20>") 15 | ("DEADLINE" . "<2023-12-03 Sun 16:20>") 16 | ("SCHEDULED" . "<2023-12-03 Sun 16:20>") 17 | ("TIMESTAMP" . "<2023-12-03 Sun 16:20>")))))) 18 | 19 | ;; (ert-deftest test-cc/test-timestamp () 20 | ;; (let () 21 | 22 | ;; )) 23 | 24 | 25 | (ert-deftest test-cc/timestamp-filter () 26 | (let* ( 27 | (now (current-time)) 28 | (now-string (format-time-string "<%Y-%m-%d %a %H:%M>" now)) 29 | (filter-start 2) 30 | (filter-end 5) 31 | (prior-timestamp (time-subtract now (* 60 60 24 (+ filter-start 1)))) 32 | (post-timestamp (time-add now (* 60 60 24 (+ filter-end 1)))) 33 | ) 34 | (should (cc/timestamp-filter now filter-start filter-end)) 35 | (should-not (cc/timestamp-filter prior-timestamp filter-start filter-end)) 36 | (should-not (cc/timestamp-filter post-timestamp filter-start filter-end)))) 37 | 38 | 39 | -------------------------------------------------------------------------------- /tests/test-cc-digital-logic.el: -------------------------------------------------------------------------------- 1 | ;;; test-cc-digital-logic.el --- Tests for cc-digital-logic -*- lexical-binding: t; -*- 2 | 3 | ;; Copyright (C) 2024 Charles Choi 4 | 5 | ;; Author: Charles Choi 6 | ;; Keywords: tools 7 | 8 | ;; This program is free software; you can redistribute it and/or modify 9 | ;; it under the terms of the GNU General Public License as published by 10 | ;; the Free Software Foundation, either version 3 of the License, or 11 | ;; (at your option) any later version. 12 | 13 | ;; This program is distributed in the hope that it will be useful, 14 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | ;; GNU General Public License for more details. 17 | 18 | ;; You should have received a copy of the GNU General Public License 19 | ;; along with this program. If not, see . 20 | 21 | ;;; Commentary: 22 | 23 | ;; 24 | 25 | ;;; Code: 26 | 27 | (require 'ert) 28 | (require 'cc-digital-logic) 29 | 30 | (ert-deftest test-digital-and () 31 | (let () 32 | (should (= 0 (digital-and 0 0 0))) 33 | (should (= 0 (digital-and 0 0 1))) 34 | (should (= 0 (digital-and 0 1 0))) 35 | (should (= 0 (digital-and 0 1 1))) 36 | (should (= 0 (digital-and 1 0 0))) 37 | (should (= 0 (digital-and 1 0 0))) 38 | (should (= 0 (digital-and 1 0 1))) 39 | (should (= 0 (digital-and 1 1 0))) 40 | (should (= 1 (digital-and 1 1 1))))) 41 | 42 | (ert-deftest test-digital-nand () 43 | (let () 44 | (should (= 1 (digital-nand 0 0 0))) 45 | (should (= 1 (digital-nand 0 0 1))) 46 | (should (= 1 (digital-nand 0 1 0))) 47 | (should (= 1 (digital-nand 0 1 1))) 48 | (should (= 1 (digital-nand 1 0 0))) 49 | (should (= 1 (digital-nand 1 0 0))) 50 | (should (= 1 (digital-nand 1 0 1))) 51 | (should (= 1 (digital-nand 1 1 0))) 52 | (should (= 0 (digital-nand 1 1 1))))) 53 | 54 | (ert-deftest test-digital-or () 55 | (let () 56 | (should (= 0 (digital-or 0 0 0))) 57 | (should (= 1 (digital-or 0 0 1))) 58 | (should (= 1 (digital-or 0 1 0))) 59 | (should (= 1 (digital-or 0 1 1))) 60 | (should (= 1 (digital-or 1 0 0))) 61 | (should (= 1 (digital-or 1 0 0))) 62 | (should (= 1 (digital-or 1 0 1))) 63 | (should (= 1 (digital-or 1 1 0))) 64 | (should (= 1 (digital-or 1 1 1))))) 65 | 66 | (ert-deftest test-digital-nor () 67 | (let () 68 | (should (= 1 (digital-nor 0 0 0))) 69 | (should (= 0 (digital-nor 0 0 1))) 70 | (should (= 0 (digital-nor 0 1 0))) 71 | (should (= 0 (digital-nor 0 1 1))) 72 | (should (= 0 (digital-nor 1 0 0))) 73 | (should (= 0 (digital-nor 1 0 0))) 74 | (should (= 0 (digital-nor 1 0 1))) 75 | (should (= 0 (digital-nor 1 1 0))) 76 | (should (= 0 (digital-nor 1 1 1))))) 77 | 78 | (ert-deftest test-digital-xor () 79 | (let () 80 | (should (= 0 (digital-xor 0 0))) 81 | (should (= 1 (digital-xor 0 1))) 82 | (should (= 1 (digital-xor 1 0))) 83 | (should (= 0 (digital-xor 1 1))))) 84 | 85 | (ert-deftest test-digital-value-to-bool () 86 | (let () 87 | (should-not (digital-value-to-bool 0)) 88 | (should (digital-value-to-bool 1)) 89 | (should-error (digital-value-to-bool 2)) 90 | (should-error (digital-value-to-bool "hey")))) 91 | 92 | (ert-deftest test-digital-bool-to-value () 93 | (let () 94 | (should (= 1 (digital-bool-to-value t))) 95 | (should (= 0 (digital-bool-to-value nil))) 96 | (should (= 1 (digital-bool-to-value 1))) 97 | (should (= 0 (digital-bool-to-value 0))) 98 | (should-error (digital-bool-to-value 2)))) 99 | 100 | (provide 'test-cc-digital-logic) 101 | ;;; test-cc-digital-logic.el ends here 102 | --------------------------------------------------------------------------------