From b89a78e88bd650e7fa08eed2da8a29d2fad201d1 Mon Sep 17 00:00:00 2001 From: rearman Date: Tue, 14 May 2024 10:46:50 -0400 Subject: [PATCH] Move defuns up, generalize send-on-close-paren --- init.org | 1755 ++++++++++++++++++++++++++++-------------------------- 1 file changed, 899 insertions(+), 856 deletions(-) diff --git a/init.org b/init.org index 16a2f8e..e4347dd 100644 --- a/init.org +++ b/init.org @@ -604,1173 +604,1216 @@ Use =recycle bin=, DON'T use =AltGr=, and tell emacs where =diff= is. w32-recognize-altgr 'nil)) #+END_SRC -** org configuration +** Defuns and Bindings :PROPERTIES: -:ID: 3ace6f84-14f7-4d64-a78c-b46b4a1ca66c +:ID: c9362b6e-5e89-4d4c-b358-58236816f698 :END: -My (now-sprawling) org configuration -*** Startup options +I have quite a few math and work-related defuns, and fewer editing ones. Inversely, I have more editing related bindings than work-related ones. This makes sense, considering my usage patterns. + +*** Editing :PROPERTIES: -:ID: 86db2539-2da8-49a5-852d-19f99dd81393 +:ID: e235c02e-dfdd-41c3-93ec-42f44594488f :END: -Start folded, and show stars as indentation. -#+BEGIN_SRC emacs-lisp -(setq org-startup-folded t - org-startup-indented t) -#+END_SRC +Most of these are to re-create something from vim/readline/sam/acme. Some are just helper functions or wrappers. -*** Basics +**** Visiting Files :PROPERTIES: -:ID: d7161d70-f42c-43da-b454-974604d2b005 +:ID: 9f4775e4-6c76-46d6-b4e0-7dbce717907a :END: -Don't split my line, just make a new one, follow links with return, export tables as csvs, and use an absolute path for other links (while shortening home to ~). +Bind ~find-file-at-point~ and ~bookmark-jump-other-window~. #+BEGIN_SRC emacs-lisp -(setq org-M-RET-may-split-line nil - org-return-follows-link t - org-table-export-default-format "orgtbl-to-csv" - org-link-file-path-type 'absolute) +(keymap-global-set "C-x M-f" 'find-file-at-point) +(keymap-global-set "C-x r B" 'bookmark-jump-other-window) #+END_SRC -*** TO-DO options +**** Undo/redo :PROPERTIES: -:ID: 28154d92-b384-4d0e-bf9d-35bd9de59f58 +:ID: da7cd3d7-1b85-48d3-8f68-e6b496e184ea :END: -Select with single key, enforce sub-tasks, only change the color of the keyword. +I like putting redo on ~C-\~. Easier for me to remember than the ~C-M-_~ default. #+BEGIN_SRC emacs-lisp -(setq org-use-fast-todo-selection 'expert - org-fast-tag-selection-single-key 'expert - org-enforce-todo-dependencies t - org-enforce-todo-checkbox-dependencies t - org-fontify-done-headline nil - org-fontify-todo-headline nil) +(keymap-global-set "C-\\" 'undo-redo) #+END_SRC -*** Navigation +**** Renaming Files :PROPERTIES: -:ID: 7c85b584-936b-4763-90c0-3de8fabc36ae +:ID: 11b46ac1-befc-4920-8672-24a01333ca1f :END: -Make the =C-c C-j= binding more useful +I took this from [[https://whattheemacsd.com][whattheemacsd.com]]. It is occasionally handy. #+BEGIN_SRC emacs-lisp -(setq org-goto-interface 'outline-path-completion - org-goto-max-level 9) -#+END_SRC +(defun rename-current-buffer-file () + "Renames the current buffer and the file it is visiting." + (interactive) + (let ((name (buffer-name)) + (filename (buffer-file-name))) + (if (not (and filename (file-exists-p filename))) + (error "Buffer '%s' is not visiting a file!" name) + (let ((new-name (read-file-name "New name: " filename))) + (if (get-buffer new-name) + (error "A buffer named '%s' already exists!" new-name) + (rename-file filename new-name 1) + (rename-buffer new-name) + (set-visited-file-name new-name) + (set-buffer-modified-p nil) + (message "File '%s' successfully renamed to '%s'" + name (file-name-nondirectory new-name))))))) -*** Special keys & subtree yanking +(keymap-global-set "C-x C-r" 'rename-current-buffer-file) +#+END_SRC +**** Buffer Menu :PROPERTIES: -:ID: 396b69c0-7078-420a-9be3-5bf478a87584 +:ID: 485c4ac3-839f-4289-a4c9-43da1a3ae048 :END: -Org special keys - do logical things with =C-a/e/k=, and adjust subtree level when yanking. +Usually I want the buffer menu in the same window I am already on. Occasionally I want it in a different window. Bind accordingly. #+BEGIN_SRC emacs-lisp -(setq org-special-ctrl-a/e t - org-special-ctrl-k t - org-yank-adjusted-subtrees t) +(keymap-global-set "C-x C-b" 'buffer-menu) +(keymap-global-set "C-x M-b" 'buffer-menu-other-window) #+END_SRC -*** File Opening +**** Switch to Scratch :PROPERTIES: -:ID: e7426184-8474-45d8-b0c4-a4a2ed99101d +:ID: 2d37f85a-de5a-408c-a6ce-4b8078a95775 :END: -Don't open links in another window, just use the current one. This variable is otherwise as default. +I often want to bring up the scratch buffer in my current window, and sometimes I want only one window that is the scratch buffer. Emacs 29 added the ~scratch-buffer~ function, so one less defun needed here. #+BEGIN_SRC emacs-lisp -(setq org-link-frame-setup '((vm . vm-visit-folder-other-frame) - (vm-imap . vm-visit-imap-folder-other-frame) - (gnus . org-gnus-no-new-news) - (file . find-file) - (wl . wl-other-frame))) +(defun scratch-only () + "Bring up the scratch buffer as the only visible buffer." + (interactive) + (scratch-buffer) + (delete-other-windows)) + +(keymap-global-set "" 'scratch-buffer) +(keymap-global-set "S-" 'scratch-only) #+END_SRC -*** Directories + +**** Line joining :PROPERTIES: -:ID: 5fbbe7e3-8da5-453e-b7a3-45eee036d662 +:ID: 76950919-72fc-4d2c-becf-9ef702b906f1 :END: -Tell org where everything is +The ~M-^~ binding is handy, but usually I want the ed/sam/vi join function, which pulls the next line up into the current line. I bind this to ~M-j~. #+BEGIN_SRC emacs-lisp -(setq org-directory "~/org" - org-agenda-files '("~/org") - org-default-notes-file "~/org/refile.org" - org-journal-file "~/org/journal.org") +(defun backward-join-line () + "A wrapper for join-line to make it go in the right direction." + (interactive) + (join-line 0)) + +(keymap-global-set "M-j" 'backward-join-line) #+END_SRC -*** Refile + +**** Line opening :PROPERTIES: -:ID: 4cca59d2-f47a-4e9d-8c22-162a81aac629 +:ID: fb7d3259-0e5c-4330-9da9-14c5c1f051e8 :END: -Let me refile anywhere, use outline paths, confirm when creating parent nodes. +The default behavior of =open-line= is ridiculous. It acheives the same function as hitting =RET=. I don't want to split the current line, I want to OPEN a new one, and usually go to it. These wrappers remedy that. + #+BEGIN_SRC emacs-lisp -(setq org-refile-targets '((nil :maxlevel . 9) - (org-agenda-files :maxlevel . 9)) - org-refile-use-outline-path 'file - org-refile-allow-creating-parent-nodes 'confirm) +(defun open-line-below (n) + "Creates a new empty line below the current line and moves to it." + (interactive "*p") + (end-of-line) + (open-line n) + (call-interactively (next-line)) + (indent-for-tab-command)) + +(defun open-line-above (n) + "Creates a new empty line above the current line." + (interactive "*p") + (beginning-of-line) + (open-line n) + (indent-for-tab-command)) #+END_SRC -*** Keywords -:PROPERTIES: -:ID: 8505da9e-71ae-42da-a5ff-8e80ca96dd30 -:END: -Set up some more todo keywords +I Bind the previous functions to =C-o= and =M-o=. + #+BEGIN_SRC emacs-lisp -(setq org-todo-keywords '((sequence "TODO(t)" - "WAITING(w@/!)" - "IN-PROGRESS(i!)" - "APPT(a!)" - "|" - "DELEGATED(l@)" - "DONE(d!/@)" - "CANCELLED(c@)"))) +(keymap-global-set "C-o" 'open-line-below) +(keymap-global-set "M-o" 'open-line-above) #+END_SRC -*** Tag Filtering +**** Commenting :PROPERTIES: -:ID: 1aa94af1-7a65-4ad1-8ac5-dd919252b4ab +:ID: eb1fa08e-66f0-4620-9e93-eed42fe770b7 :END: -Add some much-used tags with shortcuts. +I stole this directly from [[https://depp.brause.cc/dotemacs][depp.brause.cc/dotemacs]]. Very good, simple solution. #+BEGIN_SRC emacs-lisp -(setq org-tag-alist '((:startgroup . nil) - ("need" . ?n) - ("standard" . ?s) - ("wisdom" . ?w) - (:endgroup . nil))) +(defun my-comment-dwim () + "Comment region if active, otherwise comment line. +Stolen from https://depp.brause.cc/dotemacs" + (interactive) + (if (use-region-p) + (comment-or-uncomment-region (region-beginning) (region-end)) + (comment-or-uncomment-region (line-beginning-position) + (line-end-position)))) + +(keymap-global-set "M-;" 'my-comment-dwim) #+END_SRC -*** Agenda +**** Killing :PROPERTIES: -:ID: f9839acc-459b-42be-983d-3b3609d470cf +:ID: 4b90fe0e-ffe5-4aca-b46b-9fd9980bda69 :END: -**** General options +***** Kill Whole Line :PROPERTIES: -:ID: a0e6d683-63ac-4cfe-b2fc-4eb0d096f704 +:ID: ed167953-3a6c-4dce-9045-372c6c73cd00 :END: -Go back to previous view on quit, always start on current day, warn me for 30 days of a deadline, use the current window for the agenda, and don't show tags, but show full heirarchy. +Bind =kill-whole-line= to =C-S-K= for something somewhat pnemonic. + #+BEGIN_SRC emacs-lisp -(setq org-agenda-restore-windows-after-quit t - org-agenda-start-on-weekday nil - org-deadline-warning-days 30 - org-agenda-window-setup 'current-window - org-agenda-remove-tags t - org-agenda-prefix-format '((agenda . " %:c %b %?-12t% s") - (todo . " %:c % b") - (tags . " %:c % b") - (search . " %:c % b"))) +(keymap-global-set "C-S-K" 'kill-whole-line) #+END_SRC - -**** Custom View +***** Zap up to char :PROPERTIES: -:ID: 12d59694-3e27-4e53-8ba3-7c341a0d1c2d +:ID: 44c6ede5-89a0-496c-9a1f-d0d1e69ad727 :END: -Set up the agenda view. Access it with ~C-c a SPC~, [[id:3281906e-1f44-4abb-9f9d-0a0a39221752][or ~F2~]]. +Bind =C-z= to zap-up-to-char, sice zap-to-char is on =M-z=. + #+BEGIN_SRC emacs-lisp -(setq org-agenda-custom-commands '((" " "Agenda" - ((agenda "" nil) - (tags "need" - ((org-agenda-overriding-header "Needed Items"))) - (tags-todo "-REFILE+TODO=\"IN-PROGRESS\"" - ((org-agenda-overriding-header "In Progress"))) - (tags "REFILE" - ((org-agenda-overriding-header "Tasks to Refile"))) - (tags-todo "-TODO=\"WAITING\"-TODO=\"IN-PROGRESS\"-standard-REFILE" - ((org-agenda-overriding-header "Filed Tasks"))) - (tags-todo "TODO=\"WAITING\"-REFILE" - ((org-agenda-overriding-header "Holding"))) - (tags-todo "standard" - ((org-agenda-overriding-header "Changes to Standard"))))))) +(keymap-global-set "C-z" 'zap-up-to-char) #+END_SRC - -**** Custom Agenda on Single key +***** UNIX C-w and C-u :PROPERTIES: -:ID: c921d7e6-63ef-4a89-851a-0f3a122e9fa0 +:ID: 80589df3-9a23-4b2c-b103-9263db7efaab :END: -Stolen from [[https://emacs.stackexchange.com/questions/864/how-to-bind-a-key-to-a-specific-agenda-command-list-in-org-mode][Stack Exchange]] +=C-w= is very much engrained for killing back one word, as is =C-u= for killing back to the beginning of the line. [[http://unix-kb.cat-v.org/][These have been standard bindings since TENEX...]] +****** =C-w= +:PROPERTIES: +:ID: dd0452c4-59c0-4c05-9ace-8988f28d736d +:END: +I didn't want to re-bind =C-w= away from =kill-region=, so I made it do both. + #+BEGIN_SRC emacs-lisp -(defun org-agenda-show-custom (&optional arg) - "Show my custom agenda." - (interactive "P") - (org-agenda arg " ")) +(defun kill-bword-or-region () + "Kill region if active, otherwise kill back one word." + (interactive) + (if (use-region-p) + (call-interactively 'kill-region) + (call-interactively 'backward-kill-word))) + +(keymap-global-set "C-w" 'kill-bword-or-region) #+END_SRC -**** Column View +****** =C-u= :PROPERTIES: -:ID: b30e7269-c0ba-4014-9fb9-e03e6734a4db +:ID: 6bd8af3f-f277-4328-9037-020c9529a1ee :END: -Set up the format for column view. +There is no pre-made function to kill backward to the beginning of line from point, so I made one that passes the correct argument to =kill-line=, and bound it to =C-u=. + #+BEGIN_SRC emacs-lisp -(setq org-columns-default-format "%50ITEM(Task) %10CLOCKSUM %16TIMESTAMP_IA" - org-agenda-start-with-log-mode t) -#+END_SRC - -**** Clock settings -:PROPERTIES: -:ID: 31a4e74d-dab5-43dc-9953-b3beb6db9150 -:END: -Resume clocking when emacs restarts, save&load running clock and history on exit/startup, resume last task on clock-in if clock is open, resume active clock without prompt, include current clocking task in reports, and make the clocktable look nice. -#+BEGIN_SRC emacs-lisp -(org-clock-persistence-insinuate) +(defun backward-kill-line () + "Kill back to beginning of line from point." + (interactive) + (kill-line 0)) -(setq org-clock-persist t - org-clock-in-resume t - org-clock-persist-query-resume nil - org-clock-report-include-clocking-task t - org-pretty-entities t) +(keymap-global-set "C-u" 'backward-kill-line) #+END_SRC -*** Capture Templates -:PROPERTIES: -:ID: ab7c773c-5a03-4c7b-be8a-318f2b3fd0db -:END: -Capture Templates per my proclivities. +Since =C-u= is =universal-argument=, I put that functionality on =M-'=. + #+BEGIN_SRC emacs-lisp -(setq org-capture-templates '(("n" "Note" entry (file org-default-notes-file) - "* %? %u" - :clock-in t - :clock-resume t) - ("t" "TODO" entry (file org-default-notes-file) - "* TODO %?\n%U\n" - :clock-in t - :clock-resume t) - ("m" "Meeting" entry (file+olp+datetree org-journal-file) - "* %? :meeting:%^g \n%t\n** Notes\n** Action Items\n*** TODO " - :clock-in t - :clock-resume t) - ("a" "Appointment" entry (file+olp+datetree org-journal-file) - "* APPT %?\nSCHEDULED: %t" - :time-prompt t) - ("j" "Journal" entry (file+olp+datetree org-journal-file) - "* %?\n%U\n"))) +(keymap-global-set "M-'" 'universal-argument) #+END_SRC -*** Abbreviations & Snippets +**** Moving :PROPERTIES: -:ID: d4d9cdef-583a-4fad-9cb2-17a80e093374 +:ID: e8c8fd42-e96a-4804-8ce0-6e3ab4d9233d :END: -**** Abbrev-Mode settings +***** Home/End :PROPERTIES: -:ID: ce23e846-972f-46c7-b7a6-b313b4149e79 +:ID: 9f81584b-4ce1-48ff-b69f-b0bab2c1d0c5 :END: -Start up =abbrev-mode= for org +I want =Home= and =End= to take me to the top and bottom of the file. #+BEGIN_SRC emacs-lisp -(add-hook 'org-mode-hook #'abbrev-mode) -(setq abbrev-file-name (expand-file-name "abbrev_defs" user-emacs-directory) - save-abbrevs 'silently) +(keymap-global-set "" 'beginning-of-buffer) +(keymap-global-set "" 'end-of-buffer) #+END_SRC -**** Skeletons -:PROPERTIES: -:ID: fffe9361-bae6-4ceb-8a71-5d06e711528d -:END: -***** General source Block +***** Beginning of line :PROPERTIES: -:ID: f469a595-d370-46b5-8d8e-afab9a816c97 +:ID: e8ddfa3d-4be7-4da7-bf6a-5dee3fcac91f :END: -#+BEGIN_SRC emacs-lisp -(define-skeleton skel-org-block - "Insert an org source code block" - "" - "#+BEGIN_SRC " - _ - \n\n - "#+END_SRC\n") -#+END_SRC - -***** Emacs Lisp source Block +****** ~smart-beginning-of-line~ :PROPERTIES: -:ID: eb47039c-d264-4a61-8da8-7659cbc02b62 +:ID: 7b9d4bde-5ed4-4618-899e-4a0a82359f7f :END: +I have the infamous =smart-beginning-of-line= command here. #+BEGIN_SRC emacs-lisp -(define-skeleton skel-org-block-elisp - "Insert an org emacs lisp block" - "" - "#+BEGIN_SRC emacs-lisp\n" - _ - \n - "#+END_SRC\n") +(defun smart-beginning-of-line () + "Move point to first non-whitespace character or beginning-of-line. +If point was already at that position, move point to beginning of +line. Stolen from BrettWitty's dotemacs github repo." + (interactive "^") + (let ((oldpos (point))) + (back-to-indentation) + (and (= oldpos (point)) + (beginning-of-line)))) #+END_SRC -***** Facility properties block +****** Play nice with ~visual-line-mode~ :PROPERTIES: -:ID: 30630b60-66ca-40ed-a30b-9a95a2be7c70 +:ID: c8ad20f0-755c-4075-ae97-a43d4869cca9 :END: +I had issues with ~smart-beginning-of-line~ in ~visual-line-mode~, so ~smart-beginning-of-visual-line~ was created. It implements part of ~back-to-indentation~, but with changes to use ~beginning-of-visual-line~ instead of ~beginning-of-line~. #+BEGIN_SRC emacs-lisp -(define-skeleton skel-facility-properties - "Insert the org title and filetags for a new facility." - "" - "#+TITLE: " - _ - \n - "#+FILETAGS: customer city state pm sm ee ce aka c#\n\n" - "* System Notes\n" - "* PLC [/]\n" - "* Wonderware [/]\n" - "* Commissioning [/]\n") +(defun smart-beginning-of-visual-line () + "Move point to first non-whitespace character or beginning-of-line. +If point was already at that position, move point to beginning of +line. Stolen from BrettWitty's dotemacs github repo. Modified to +work in visual-line-mode. Re-implementing `back-to-indentation' +as a visual-line respecter." + (interactive "^") + (let ((oldpos (point))) + (beginning-of-visual-line 1) + (skip-syntax-forward " " (line-end-position)) + (backward-prefix-chars) + (and (= oldpos (point)) + (beginning-of-visual-line)))) #+END_SRC - -***** Person properties block +****** Re-mappings :PROPERTIES: -:ID: 0e57ecbf-b0f5-4f7c-ad1d-d3ef69cb7581 +:ID: 4a8e9670-2783-4f4a-ada7-f1837a8632be :END: +Remap =move-beginning-of-line=, then remap =beginning-of-visual-line= when going into =visual-line-mode=. A simple remap would not work for =visual-line-mode=, so I explicitly set =C-a=. #+BEGIN_SRC emacs-lisp -(define-skeleton skel-person-properties - "Insert the org title and filetags for a person." - "" - "#+TITLE: @" - _ - \n - "#+FILETAGS: company position\n" - "#+EMAIL:\n" - "#+OFFICE:\n" - "#+CELL:\n") +(global-set-key [remap move-beginning-of-line] 'smart-beginning-of-line) +(add-hook 'visual-line-mode-hook + (lambda () + (keymap-global-set "C-a" 'smart-beginning-of-visual-line))) #+END_SRC - -***** Workorder properties block +***** Line Numbers on move only :PROPERTIES: -:ID: a0062c3f-caf0-4de4-9d95-0dffc04eba31 +:ID: 2a73fd23-0869-4d5b-b727-8fa2486dc99b :END: +I don't want line numbers in the margin unless I am actively trying to go to a line. I override =goto-line= with this function, which shows line numbers, asks me where I want to go, and then hides line numbers. #+BEGIN_SRC emacs-lisp -(define-skeleton skel-workorder-properties - "Insert the org title and filetags for a workorder" - "" - "#+TITLE: Workorder " - _ - \n - "#+FILETAGS: wo# workorder customer city state topics\n") -#+END_SRC +(defun my-goto-line () + "Show line numbers before going to line, then hide them again." + (interactive) + (display-line-numbers-mode 1) + (call-interactively 'goto-line) + (display-line-numbers-mode -1)) -**** Bind the snippets (in the =abbrev-file-name= file) -:PROPERTIES: -:ID: 1e9362ab-d7da-4d87-bef4-9a6c39530832 -:END: -#+BEGIN_SRC emacs-lisp :tangle ./abbrev_defs -;;-*-coding: utf-8;-*- -(define-abbrev-table 'org-mode-abbrev-table - '(("ssrc" "" skel-org-block) - ("selisp" "" skel-org-block-elisp) - ("sfac" "" skel-facility-properties) - ("sper" "" skel-person-properties) - ("swo" "" skel-workorder-properties))) +(global-set-key [remap goto-line] 'my-goto-line) #+END_SRC - -*** Auto-archive +***** Other window or split window :PROPERTIES: -:ID: f1e0b6cf-023f-44e3-a489-15fa04208cd3 +:ID: 7e9a99eb-18fd-4254-a20c-a1cb2fe0584d :END: -A function to automatically archive *DONE* items in an org file. I sometimes use this as an after-save-hook header declaration as such: -#+BEGIN_SRC emacs-lisp :tangle no --*- after-save-hook: (org-auto-archive) -*- -#+END_SRC - +I ripped this defun and binding from [[https://github.com/lem-project/lem][lem]]. Can't live without it now. Does similar things as [[id:1c8d7229-796f-446a-8ae8-247cd6164a12][Windmove]], but without having to specify a direction. #+BEGIN_SRC emacs-lisp -(defun org-auto-archive () - "Automatically archive completed tasks in an org file. -Intended for use as an after-save-hook." +(defun other-window-or-split-window (&optional window) (interactive) - (org-map-entries - (lambda () - (org-archive-subtree) - (setq org-map-continue-from (org-element-property :begin (org-element-at-point)))) - "TODO=\"DONE\"|TODO=\"CANCELLED\"|TODO=\"DELEGATED\"" - 'file) - (save-buffer)) -#+END_SRC + (if (= (count-windows) 1) + (funcall split-window-preferred-function window) + (other-window 1))) -Also add that defun to =safe-local-variables= so that emacs will run it. -#+BEGIN_SRC emacs-lisp -(setq safe-local-variable-values '((after-save-hook org-auto-archive))) +(keymap-global-set "C-M-o" 'other-window-or-split-window) #+END_SRC - -*** Auto-Generate IDs +**** Search and Replace :PROPERTIES: -:ID: f2660fb6-f995-4b5b-a01c-6bf8b5d9c894 +:ID: 32daa74b-39b2-4275-bd88-55e9f9d0ffb5 :END: -**** On Capture +I made these bindings to put my more-used commands on better keys, and swap them with the less-used ones. Also add bindings for ~isearch-*-regexp~. +#+BEGIN_SRC emacs-lisp +(keymap-global-set "M-s ." 'isearch-forward-thing-at-point) +(keymap-global-set "M-s M-." 'isearch-forward-symbol-at-point) +(keymap-global-set "M-%" 'replace-regexp) +(keymap-global-set "C-%" 'replace-string) +(keymap-global-set "C-S-S" 'isearch-forward-regexp) +(keymap-global-set "C-S-R" 'isearch-backward-regexp) +#+END_SRC +*** Elisp/Eval bindings :PROPERTIES: -:ID: b40f11e3-8569-4fcd-b083-f1b682f23dc1 +:ID: 05c8bf80-e35f-49bc-97b0-b6caccb63ab6 :END: -Generate an ID when I capture someting, and when I try to link to it. Stolen from [[https://stackoverflow.com/questions/13340616/assign-ids-to-every-entry-in-org-mode][Stack Overflow]] +Some old Emacs-like editor (Edwin?) used this binding, so I put it in here. Less used than the =C-M-x= =eval-defun= binding, but occasionally nice to have. #+BEGIN_SRC emacs-lisp -(setq org-id-link-to-org-use-id t) +(keymap-global-set "C-M-z" 'eval-region) #+END_SRC -**** Existing File +**** Send on Close-Paren :PROPERTIES: -:ID: 4120cfb4-59d5-441d-abaa-b49f847f5b90 +:ID: 325c01c5-b877-4281-adff-ea956bdb5f2c :END: -Automatically generate unique IDs if not already created. Stolen from [[https://stackoverflow.com/questions/13340616/assign-ids-to-every-entry-in-org-mode][Stack Overflow]] +I wanted something like what the Genera environment has, where putting in a final close-paren will send the command, without having to hit enter. This is a general command, used by [[id:325c01c5-b877-4281-adff-ea956bdb5f2c][Eshell]], [[id:664ba0e7-0826-4868-9480-e1338a6e9f63][Ielm]], and #+BEGIN_SRC emacs-lisp -(defun org-auto-generate-ids-in-file () - "Add ID properties to all headlines in the current - file which do not already have one." +(defun send-on-close-paren (executor) + "Generalizes sending an execute on close paren. +When a sexp is complete - that is when parens balance as you type - execute it." (interactive) - (org-map-entries 'org-id-get-create)) -#+END_SRC - -Run this on save of any org-mode file -#+BEGIN_SRC emacs-lisp -(add-hook 'org-mode-hook - (lambda () - (add-hook 'before-save-hook 'org-auto-generate-ids-in-file nil 'local))) + (insert-char ?\)) + (when (= 0 (car (syntax-ppss))) + (call-interactively executor))) #+END_SRC -*** Tangling -:PROPERTIES: -:ID: f0c4710a-0172-41bc-9744-4fd48872d4a2 -:END: -**** Settings +*** *NIX :PROPERTIES: -:ID: 3d8f6700-07a2-4e1e-b3c7-7d77afdcf85c +:ID: ecfe90a8-05d6-468b-b82a-5558c4a226c1 :END: -Don't make a new window for source-code edits, and keep indentation consistent. +These defuns are here so that I can use doas/sudo over tramp to edit /local/ files requiring root permissions. Doas for BSD, Sudo for Linux, nothing for Windows. #+BEGIN_SRC emacs-lisp -(setq org-src-window-setup 'current-window - org-src-preserve-indentation t - org-src-fontify-natively t) +(unless (or (equal system-type 'windows-nt) + (equal system-type 'android)) + (if(equal system-type 'berkeley-unix) + (defun doas () + "Use TRAMP to reopen the current buffer as root using doas." + (interactive) + (when buffer-file-name + (find-alternate-file + (concat "/doas:root@localhost:" + buffer-file-name)))) + (defun sudo () + "Use TRAMP to reopen the current buffer as root using sudo." + (interactive) + (when buffer-file-name + (find-alternate-file + (concat "/doas:root@localhost:" + buffer-file-name)))))) #+END_SRC -**** Auto-tangle init.org +*** Windows :PROPERTIES: -:ID: cd914118-d6e7-485d-b27e-3172f3b77af9 +:ID: 857da290-c22e-4e38-a427-714527cf392f :END: -Make a function to tangle this file, and run it on save. +If you've ever had the /pleasure/ of using Aveva (*Formerly WonderWare*) version 2020, you'll understand. #+BEGIN_SRC emacs-lisp -(defun tangle-init () - "Tangle and compile init.org. -Stolen from https://github.com/larstvei/dot-emacs." - (when (equal (buffer-file-name) - (expand-file-name (concat user-emacs-directory "init.org"))) - (let ((prog-mode-hook nil)) - (org-babel-tangle)))) - -(add-hook 'after-save-hook 'tangle-init) +(when (equal system-type 'windows-nt) + (defun unfuck-aveva-license () + "Remove the offending xml files. +Use this when aveva can't find ass with both hands." + (interactive) + (let ((xml1 "c:/ProgramData/AVEVA/Licensing/License API2/Data/LocalAcquireInfo.xml") + (xml2 "c:/ProgramData/AVEVA/Licensing/License API2/Data/LocalBackEndAcquireInfo.xml")) + (when (file-exists-p xml1) (delete-file xml1)) + (when (file-exists-p xml2) (delete-file xml2))))) #+END_SRC -*** Bindings -:PROPERTIES: -:ID: adf21035-f2f1-443b-a599-4ce4f282a2ff -:END: -**** Global +*** Math :PROPERTIES: -:ID: 3281906e-1f44-4abb-9f9d-0a0a39221752 +:ID: 69a05305-6b16-4abf-bf9a-b858d9a7e642 :END: -The usual bindings. -#+BEGIN_SRC emacs-lisp -(keymap-global-set "C-c l" 'org-store-link) -(keymap-global-set "C-c a" 'org-agenda) -(keymap-global-set "C-c c" 'org-capture) -(keymap-global-set "C-c b" 'org-switchb) -(keymap-global-set "" 'org-agenda-show-custom) -#+END_SRC - -**** Mode-Specific +General Math defuns, often used in later defuns. +**** Exponentiation :PROPERTIES: -:ID: 99906320-74b0-4414-8d87-1ce1ddddad97 +:ID: 14d9a8c0-2984-4d53-b933-01366b286208 :END: -Give me logical in/out-denting on the easier binding, since I use that more often. +I'm tired of writing out ='expt=, and I want to use the same notation every other programming language does. #+BEGIN_SRC emacs-lisp -(add-hook 'org-mode-hook - (lambda () - (keymap-set org-mode-map "M-" 'org-shiftmetaright) - (keymap-set org-mode-map "M-" 'org-shiftmetaleft) - (keymap-set org-mode-map "M-S-" 'org-metaright) - (keymap-set org-mode-map "M-S-" 'org-metaleft))) +(defalias '^ 'expt) #+END_SRC - -** Dired configuration +**** Square, Cube, and Inv :PROPERTIES: -:ID: 245c157b-036f-4489-b221-193691a7f94b +:ID: 871f50e4-447e-4da0-b86f-ec253c7d48cf :END: -Make dired use the same switches I prefer for =ls=, give me a simpler listing, and default to using its current buffer for visiting a file, rather than creating a new one. +Define square, cube, and inv for brevity of common usages. #+BEGIN_SRC emacs-lisp -(setq dired-listing-switches "-alv --group-directories-first") +(defun square (x) + "Calculate the square of a value." + (^ x 2)) -(add-hook 'dired-mode-hook - (lambda () - (dired-hide-details-mode t) - (keymap-set dired-mode-map - "RET" 'dired-find-alternate-file))) -#+END_SRC +(defun cube (x) + "Calculate the cube of a value." + (^ x 3)) -** Eshell configuration -:PROPERTIES: -:ID: 700392e5-d07b-474f-baa9-f563b4a6197f -:END: -Here are the various customizations I have for eshell. -*** Binding to start eshell -:PROPERTIES: -:ID: 9178eac2-5f69-4574-ae47-b491374f643f -:END: -#+BEGIN_SRC emacs-lisp -(keymap-global-set "C-c s" 'eshell) +(defun inv (x) + "Calculate the inverse of a value." + (/ 1 (float x))) #+END_SRC -*** Make it play nice with corfu +*** Unit Conversions :PROPERTIES: -:ID: dc7f2345-2ee3-4883-90ff-b0a8c25c9422 +:ID: d756d65e-aca5-4718-af09-aaecbbd62f99 :END: +The rest of the world decided to self-castrate because some French guys told them things Definitely Made More Sense if everything was divisible by 10. I'm convinced the average Frenchman simply couldn't grasp fractions, and that's why he came up with this crap. What's 1/3 of a meter? What's 1/3 of a yard? And 1/3 of a foot? How likely are you to need to divide a measurement by 3 when you're building something? Maybe the [[https://dozenal.org/][Dozenal]] people were right all along. Anyway, I'm now forced to convert into proper units daily because of this grave error. #+BEGIN_SRC emacs-lisp -(add-hook 'eshell-mode-hook (lambda () - ;; (setq-local corfu-auto nil) - (corfu-mode))) -#+END_SRC +(defun mm->in (mm) + "Convert milimeters to inches." + (/ mm 25.4)) -*** Send on Close-Paren -:PROPERTIES: -:ID: 325c01c5-b877-4281-adff-ea956bdb5f2c -:END: -I wanted something like what the Genera environment has, where putting in a final close-paren will send the command, without having to hit enter. +(defun in->mm (in) + "Convert inches to milimeters." + (* in 25.4)) -#+BEGIN_SRC emacs-lisp -(defun eshell-send-on-close-paren () - "Makes eshell act somewhat like genera. -Makes a closing paren execute the sexp." - (interactive) - (insert-char ?\)) - (when (= 0 (car (syntax-ppss))) - (eshell-send-input))) -#+END_SRC +(defun k->c (tempk) + "Convert degrees Kelvin to degrees Celsius." + (- tempk 273.15)) -*** Quit or delete-char -:PROPERTIES: -:ID: ed19265d-4b5c-426b-8c74-cf36939a8b8f -:END: -I want =C-d= to end the shell if it is on an empty line, otherwise act normally. +(defun c->k (tempc) + "Convert degrees Celsius to degrees Kelvin." + (+ tempc 273.15)) -#+BEGIN_SRC emacs-lisp -(defun eshell-quit-or-delete-char (arg) - "Delete char if at one, quit eshell if on empty prompt. -Stolen from https://depp.brause.cc/dotemacs" - (interactive "p") - (if (and (eolp) (looking-back eshell-prompt-regexp 0 t)) - (eshell-life-is-too-much) ; https://emacshorrors.com/post/life-is-too-much - (delete-char arg))) -#+END_SRC +(defun c->f (tempc) + "Convert degrees Celsius to degrees Fahrenheit." + (+ (* tempc 1.8) 32.0)) -*** Bind the defuns -:PROPERTIES: -:ID: eac8b87a-0ca9-4d0f-8cd4-1d1538ec16d0 -:END: -I have only been able to get these to work when they are within an add-hook lambda. +(defun f->c (tempf) + "Convert degrees Fahrenheit to degrees Celsius." + (/ (- tempf 32.0) 1.8)) -#+BEGIN_SRC emacs-lisp -(add-hook 'eshell-mode-hook - (lambda () - (keymap-set eshell-mode-map ")" 'eshell-send-on-close-paren) - (keymap-set eshell-mode-map "C-d" 'eshell-quit-or-delete-char))) -#+END_SRC -** ielm configuration -:PROPERTIES: -:ID: e7a7b861-8f63-4036-9f68-59fb954a7561 -:END: -I wanted something more like a standard lisp REPL in emacs. Found =ielm=. -*** Send on Close-Paren -:PROPERTIES: -:ID: 664ba0e7-0826-4868-9480-e1338a6e9f63 -:END: -I wanted something like what the Genera environment has, where putting in a final close-paren will send the command, without having to hit enter. +(defun k->f (tempk) + "Convert degrees Kelvin to degrees Fahrenheit. +Applies `c->f' to `k->c'." + (c->f (k->c tempk))) -#+BEGIN_SRC emacs-lisp -(defun ielm-send-on-close-paren () - "Makes ielm act somewhat like genera. -Makes a closing paren execute the sexp." - (interactive) - (insert-char ?\)) - (when (= 0 (car (syntax-ppss))) - (ielm-send-input))) +(defun f->k (tempf) + "Convert degrees Fahrenheit to degrees Kelvin. +Applies `c->k' to `f->c'." + (c->k (f->c tempf))) #+END_SRC -*** Persistent command history -:PROPERTIES: -:ID: 19726597-2a2e-4059-9447-d7e90696fe08 -:END: -**** Read History -:PROPERTIES: -:ID: 6db9d990-00e7-44ec-a83c-b2999fa8db73 -:END: -#+BEGIN_SRC emacs-lisp -(defun g-ielm-init-history () - "Stolen from https://n16f.net/blog/making-ielm-more-comfortable." - (let ((path (expand-file-name "ielm/history" user-emacs-directory))) - (make-directory (file-name-directory path) t) - (setq-local comint-input-ring-file-name path)) - (setq-local comint-input-ring-size 10000 - comint-input-ignoredups t) - (comint-read-input-ring)) -(add-hook 'ielm-mode-hook 'g-ielm-init-history) -#+END_SRC -**** Write History +*** Electrical :PROPERTIES: -:ID: f7f1df1f-9531-4ef6-b66f-dc0d46295864 +:ID: 8c0d72bc-b8ba-4f9f-be49-876bd624c2ae :END: +These defuns are all about electronics. Effective impedance, amps to volts, and back again. #+BEGIN_SRC emacs-lisp -(defun g-ielm-write-history (&rest _args) - "Stolen from https://n16f.net/blog/making-ielm-more-comfortable." - (with-file-modes #o600 - (comint-write-input-ring))) +(defun eff-imp (r1 &optional r2) + "Calculate the effective input impedance, given two resistances. +For use in `amps->volts' and related. The handling of only one +resistance given is done here, instead of doing it in every +function that uses this." + (if (eq nil r2) + r1 + (inv (+ (inv r1) (inv r2))))) -(advice-add 'ielm-send-input :after 'g-ielm-write-history) +(defun amps->volts (amps r1 &optional r2) + "Calculate the voltage, given amperage and impedance. +Multiplies the amperage by the effective impedance calculated +with `eff-imp'." + (* amps (eff-imp r1 r2))) + +(defun volts->amps (volts r1 &optional r2) + "Calculate the amperage, given voltage and impedance. +Divides the voltage by the effective impedance calculated with +`eff-imp'." + (/ volts (eff-imp r1 r2))) #+END_SRC -*** Bindings + +*** PLC :PROPERTIES: -:ID: 68c34ab5-7149-49f5-91e8-fcea22d98fcd +:ID: 850536ef-64b6-44d6-9b64-61d2a4ed050a :END: -~C-l~ to clear buffer, send on close paren. +The nitty-gritty. These defuns build on the previous ones to help me do various calculations related to analog signals and how they interact with [[https://en.wikipedia.org/wiki/Programmable_logic_controller][PLCs]], also called PACs. Counts, volts, amps, bit-resolutions, and relating them to each other. #+BEGIN_SRC emacs-lisp -(keymap-global-set "C-c i" 'ielm) -(add-hook 'ielm-mode-hook - (lambda () - (keymap-set inferior-emacs-lisp-mode-map "C-l" 'comint-clear-buffer) - (keymap-set inferior-emacs-lisp-mode-map ")" 'ielm-send-on-close-paren))) +(defun max-counts (resolution) + "Calculate the max count for a PLC analog, given card's bit-resolution." + (- (^ 2 resolution) 1)) + +(defun volts->counts (vmax vin resolution) + "Convert a voltage signal to a PLC count. +Calculates a ratio of vin/vmax, then scales by `max-counts'." + (* (/ (float vin) vmax) (max-counts resolution))) + +(defun counts->volts (vmax cin resolution) + "Convert a PLC count to a voltage. +Calculates a ratio of cin/`max-counts', then multiplies by vmax." + (* (/ (float cin) (max-counts resolution)) vmax)) + +(defun amps->counts (vmax amps resolution r1 &optional r2) + "Convert a current signal to PLC Counts. +Converts the amperage to a voltage using `amps->volts' (with r1 +and optional r2), then applies `volts->counts' to the resulting +voltage, vmax, and resolution." + (volts->counts vmax (amps->volts amps r1 r2) resolution)) + +(defun count-range (upper lower vmax resolution &optional r1 r2) + "Given an upper and lower signal, return the list of upper and lower PLC counts. +With a current signal, use r1 and maybe r2 to +calculate `amps->counts'. Otherwise ignore r1/r2 and calculate +`volts->counts'." + (if (eq nil r1) + (list (volts->counts vmax upper resolution) + (volts->counts vmax lower resolution)) + (list (amps->counts vmax upper resolution r1 r2) + (amps->counts vmax lower resolution r1 r2)))) + +(defun divisor (raw-max raw-min scaled-max scaled-min) + "Calculate 1/slope given PLC Max/Min and Eng. Max/Min." + (/ (float (- raw-max raw-min)) (- scaled-max scaled-min))) + +(defun offset (raw-max raw-min scaled-max scaled-min) + "Calculate offset given PLC Max/Min and Eng. Max/Min." + (- scaled-min (/ raw-min (divisor raw-max raw-min scaled-max scaled-min)))) + +(defun final (analog-input divisor offset) + "Calculate the scaled value of an input." + (+ (/ analog-input divisor) offset)) + +(defun scale (raw-max raw-min scaled-max scaled-min &optional analog-input) + "Calculate the divisor, offset, and maybe final value, given the parameters." + (let* ((div (divisor raw-max raw-min scaled-max scaled-min)) + (os (offset raw-max raw-min scaled-max scaled-min))) + (if (eq nil analog-input) + (list div os) + (list div os (final analog-input div os))))) #+END_SRC -** Defuns and Bindings + +*** Refrigeration :PROPERTIES: -:ID: c9362b6e-5e89-4d4c-b358-58236816f698 +:ID: 18225f24-139e-4707-8935-03a6cf48290a :END: -I have quite a few math and work-related defuns, and fewer editing ones. Inversely, I have more editing related bindings than work-related ones. This makes sense, considering my usage patterns. +More nitty-gritty. These are for calculating specific refrigeration-related things. Somewhat specialized. +#+BEGIN_SRC emacs-lisp +(defun cfm-circ (fpm radius) + "Calculate the CFM of a circular duct. +Inputs are feet/minute and radius (in)." + (list (* float-pi fpm (square (/ radius 12.0))))) -*** Editing +(defun cfm-rect (fpm width height) + "Calculate the CFM of a rectangular duct. +Inputs are feet/minute, width (in) and height (in)." + (list (* fpm (/ width 12.0) (/ height 12.0)))) + +(defun gn-water-per-lb (temp humidity) + "Calculate the grains of water per lb of air. +Inputs are temp (F) and humidity (%). Returns a list of +Saturated Water Pressure, Humidity Ratio, and Grains of water per +lb of air." + (let* ((sat-water-press (+ .0182795 + (* temp .001029904) + (* (square temp) 0.00002579408) + (* (cube temp) (* 2.400493 (^ 10 -7))) + (* (^ temp 4) (* 8.100939 (^ 10 -10))) + (* (^ temp 5) (* 3.256805 (^ 10 -11))) + (* (^ temp 6) (* -1.001922 (^ 10 -13))) + (* (^ temp 7) (* 2.44161 (^ 10 -16))))) + (hum-press (* (/ humidity 100.0) sat-water-press)) + (hum-ratio (/ (* hum-press 0.62198) (- 14.7 hum-press))) + (gns-water-lb-air (* hum-ratio 7000))) + (list sat-water-press hum-ratio gns-water-lb-air))) +#+END_SRC + +** org configuration :PROPERTIES: -:ID: e235c02e-dfdd-41c3-93ec-42f44594488f +:ID: 3ace6f84-14f7-4d64-a78c-b46b4a1ca66c :END: -Most of these are to re-create something from vim/readline/sam/acme. Some are just helper functions or wrappers. - -**** Visiting Files +My (now-sprawling) org configuration +*** Startup options :PROPERTIES: -:ID: 9f4775e4-6c76-46d6-b4e0-7dbce717907a +:ID: 86db2539-2da8-49a5-852d-19f99dd81393 :END: -Bind ~find-file-at-point~ and ~bookmark-jump-other-window~. +Start folded, and show stars as indentation. #+BEGIN_SRC emacs-lisp -(keymap-global-set "C-x M-f" 'find-file-at-point) -(keymap-global-set "C-x r B" 'bookmark-jump-other-window) +(setq org-startup-folded t + org-startup-indented t) #+END_SRC -**** Undo/redo +*** Basics :PROPERTIES: -:ID: da7cd3d7-1b85-48d3-8f68-e6b496e184ea +:ID: d7161d70-f42c-43da-b454-974604d2b005 :END: -I like putting redo on ~C-\~. Easier for me to remember than the ~C-M-_~ default. +Don't split my line, just make a new one, follow links with return, export tables as csvs, and use an absolute path for other links (while shortening home to ~). #+BEGIN_SRC emacs-lisp -(keymap-global-set "C-\\" 'undo-redo) +(setq org-M-RET-may-split-line nil + org-return-follows-link t + org-table-export-default-format "orgtbl-to-csv" + org-link-file-path-type 'absolute) #+END_SRC -**** Renaming Files +*** TO-DO options :PROPERTIES: -:ID: 11b46ac1-befc-4920-8672-24a01333ca1f +:ID: 28154d92-b384-4d0e-bf9d-35bd9de59f58 :END: -I took this from [[https://whattheemacsd.com][whattheemacsd.com]]. It is occasionally handy. +Select with single key, enforce sub-tasks, only change the color of the keyword. #+BEGIN_SRC emacs-lisp -(defun rename-current-buffer-file () - "Renames the current buffer and the file it is visiting." - (interactive) - (let ((name (buffer-name)) - (filename (buffer-file-name))) - (if (not (and filename (file-exists-p filename))) - (error "Buffer '%s' is not visiting a file!" name) - (let ((new-name (read-file-name "New name: " filename))) - (if (get-buffer new-name) - (error "A buffer named '%s' already exists!" new-name) - (rename-file filename new-name 1) - (rename-buffer new-name) - (set-visited-file-name new-name) - (set-buffer-modified-p nil) - (message "File '%s' successfully renamed to '%s'" - name (file-name-nondirectory new-name))))))) - -(keymap-global-set "C-x C-r" 'rename-current-buffer-file) +(setq org-use-fast-todo-selection 'expert + org-fast-tag-selection-single-key 'expert + org-enforce-todo-dependencies t + org-enforce-todo-checkbox-dependencies t + org-fontify-done-headline nil + org-fontify-todo-headline nil) #+END_SRC -**** Buffer Menu + +*** Navigation :PROPERTIES: -:ID: 485c4ac3-839f-4289-a4c9-43da1a3ae048 +:ID: 7c85b584-936b-4763-90c0-3de8fabc36ae :END: -Usually I want the buffer menu in the same window I am already on. Occasionally I want it in a different window. Bind accordingly. +Make the =C-c C-j= binding more useful #+BEGIN_SRC emacs-lisp -(keymap-global-set "C-x C-b" 'buffer-menu) -(keymap-global-set "C-x M-b" 'buffer-menu-other-window) +(setq org-goto-interface 'outline-path-completion + org-goto-max-level 9) #+END_SRC -**** Switch to Scratch +*** Special keys & subtree yanking :PROPERTIES: -:ID: 2d37f85a-de5a-408c-a6ce-4b8078a95775 +:ID: 396b69c0-7078-420a-9be3-5bf478a87584 :END: -I often want to bring up the scratch buffer in my current window, and sometimes I want only one window that is the scratch buffer. Emacs 29 added the ~scratch-buffer~ function, so one less defun needed here. +Org special keys - do logical things with =C-a/e/k=, and adjust subtree level when yanking. #+BEGIN_SRC emacs-lisp -(defun scratch-only () - "Bring up the scratch buffer as the only visible buffer." - (interactive) - (scratch-buffer) - (delete-other-windows)) - -(keymap-global-set "" 'scratch-buffer) -(keymap-global-set "S-" 'scratch-only) +(setq org-special-ctrl-a/e t + org-special-ctrl-k t + org-yank-adjusted-subtrees t) #+END_SRC -**** Line joining +*** File Opening :PROPERTIES: -:ID: 76950919-72fc-4d2c-becf-9ef702b906f1 +:ID: e7426184-8474-45d8-b0c4-a4a2ed99101d :END: -The ~M-^~ binding is handy, but usually I want the ed/sam/vi join function, which pulls the next line up into the current line. I bind this to ~M-j~. +Don't open links in another window, just use the current one. This variable is otherwise as default. #+BEGIN_SRC emacs-lisp -(defun backward-join-line () - "A wrapper for join-line to make it go in the right direction." - (interactive) - (join-line 0)) - -(keymap-global-set "M-j" 'backward-join-line) +(setq org-link-frame-setup '((vm . vm-visit-folder-other-frame) + (vm-imap . vm-visit-imap-folder-other-frame) + (gnus . org-gnus-no-new-news) + (file . find-file) + (wl . wl-other-frame))) #+END_SRC - -**** Line opening +*** Directories :PROPERTIES: -:ID: fb7d3259-0e5c-4330-9da9-14c5c1f051e8 +:ID: 5fbbe7e3-8da5-453e-b7a3-45eee036d662 :END: -The default behavior of =open-line= is ridiculous. It acheives the same function as hitting =RET=. I don't want to split the current line, I want to OPEN a new one, and usually go to it. These wrappers remedy that. - -#+BEGIN_SRC emacs-lisp -(defun open-line-below (n) - "Creates a new empty line below the current line and moves to it." - (interactive "*p") - (end-of-line) - (open-line n) - (call-interactively (next-line)) - (indent-for-tab-command)) - -(defun open-line-above (n) - "Creates a new empty line above the current line." - (interactive "*p") - (beginning-of-line) - (open-line n) - (indent-for-tab-command)) -#+END_SRC - -I Bind the previous functions to =C-o= and =M-o=. - +Tell org where everything is #+BEGIN_SRC emacs-lisp -(keymap-global-set "C-o" 'open-line-below) -(keymap-global-set "M-o" 'open-line-above) +(setq org-directory "~/org" + org-agenda-files '("~/org") + org-default-notes-file "~/org/refile.org" + org-journal-file "~/org/journal.org") #+END_SRC - -**** Commenting +*** Refile :PROPERTIES: -:ID: eb1fa08e-66f0-4620-9e93-eed42fe770b7 +:ID: 4cca59d2-f47a-4e9d-8c22-162a81aac629 :END: -I stole this directly from [[https://depp.brause.cc/dotemacs][depp.brause.cc/dotemacs]]. Very good, simple solution. +Let me refile anywhere, use outline paths, confirm when creating parent nodes. #+BEGIN_SRC emacs-lisp -(defun my-comment-dwim () - "Comment region if active, otherwise comment line. -Stolen from https://depp.brause.cc/dotemacs" - (interactive) - (if (use-region-p) - (comment-or-uncomment-region (region-beginning) (region-end)) - (comment-or-uncomment-region (line-beginning-position) - (line-end-position)))) - -(keymap-global-set "M-;" 'my-comment-dwim) +(setq org-refile-targets '((nil :maxlevel . 9) + (org-agenda-files :maxlevel . 9)) + org-refile-use-outline-path 'file + org-refile-allow-creating-parent-nodes 'confirm) #+END_SRC -**** Killing -:PROPERTIES: -:ID: 4b90fe0e-ffe5-4aca-b46b-9fd9980bda69 -:END: -***** Kill Whole Line +*** Keywords :PROPERTIES: -:ID: ed167953-3a6c-4dce-9045-372c6c73cd00 +:ID: 8505da9e-71ae-42da-a5ff-8e80ca96dd30 :END: -Bind =kill-whole-line= to =C-S-K= for something somewhat pnemonic. - +Set up some more todo keywords #+BEGIN_SRC emacs-lisp -(keymap-global-set "C-S-K" 'kill-whole-line) +(setq org-todo-keywords '((sequence "TODO(t)" + "WAITING(w@/!)" + "IN-PROGRESS(i!)" + "APPT(a!)" + "|" + "DELEGATED(l@)" + "DONE(d!/@)" + "CANCELLED(c@)"))) #+END_SRC -***** Zap up to char + +*** Tag Filtering :PROPERTIES: -:ID: 44c6ede5-89a0-496c-9a1f-d0d1e69ad727 +:ID: 1aa94af1-7a65-4ad1-8ac5-dd919252b4ab :END: -Bind =C-z= to zap-up-to-char, sice zap-to-char is on =M-z=. - +Add some much-used tags with shortcuts. #+BEGIN_SRC emacs-lisp -(keymap-global-set "C-z" 'zap-up-to-char) +(setq org-tag-alist '((:startgroup . nil) + ("need" . ?n) + ("standard" . ?s) + ("wisdom" . ?w) + (:endgroup . nil))) #+END_SRC -***** UNIX C-w and C-u + +*** Agenda :PROPERTIES: -:ID: 80589df3-9a23-4b2c-b103-9263db7efaab +:ID: f9839acc-459b-42be-983d-3b3609d470cf :END: -=C-w= is very much engrained for killing back one word, as is =C-u= for killing back to the beginning of the line. [[http://unix-kb.cat-v.org/][These have been standard bindings since TENEX...]] -****** =C-w= +**** General options :PROPERTIES: -:ID: dd0452c4-59c0-4c05-9ace-8988f28d736d +:ID: a0e6d683-63ac-4cfe-b2fc-4eb0d096f704 :END: -I didn't want to re-bind =C-w= away from =kill-region=, so I made it do both. - +Go back to previous view on quit, always start on current day, warn me for 30 days of a deadline, use the current window for the agenda, and don't show tags, but show full heirarchy. #+BEGIN_SRC emacs-lisp -(defun kill-bword-or-region () - "Kill region if active, otherwise kill back one word." - (interactive) - (if (use-region-p) - (call-interactively 'kill-region) - (call-interactively 'backward-kill-word))) - -(keymap-global-set "C-w" 'kill-bword-or-region) +(setq org-agenda-restore-windows-after-quit t + org-agenda-start-on-weekday nil + org-deadline-warning-days 30 + org-agenda-window-setup 'current-window + org-agenda-remove-tags t + org-agenda-prefix-format '((agenda . " %:c %b %?-12t% s") + (todo . " %:c % b") + (tags . " %:c % b") + (search . " %:c % b"))) #+END_SRC -****** =C-u= +**** Custom View :PROPERTIES: -:ID: 6bd8af3f-f277-4328-9037-020c9529a1ee +:ID: 12d59694-3e27-4e53-8ba3-7c341a0d1c2d :END: -There is no pre-made function to kill backward to the beginning of line from point, so I made one that passes the correct argument to =kill-line=, and bound it to =C-u=. - +Set up the agenda view. Access it with ~C-c a SPC~, [[id:3281906e-1f44-4abb-9f9d-0a0a39221752][or ~F2~]]. #+BEGIN_SRC emacs-lisp -(defun backward-kill-line () - "Kill back to beginning of line from point." - (interactive) - (kill-line 0)) - -(keymap-global-set "C-u" 'backward-kill-line) +(setq org-agenda-custom-commands '((" " "Agenda" + ((agenda "" nil) + (tags "need" + ((org-agenda-overriding-header "Needed Items"))) + (tags-todo "-REFILE+TODO=\"IN-PROGRESS\"" + ((org-agenda-overriding-header "In Progress"))) + (tags "REFILE" + ((org-agenda-overriding-header "Tasks to Refile"))) + (tags-todo "-TODO=\"WAITING\"-TODO=\"IN-PROGRESS\"-standard-REFILE" + ((org-agenda-overriding-header "Filed Tasks"))) + (tags-todo "TODO=\"WAITING\"-REFILE" + ((org-agenda-overriding-header "Holding"))) + (tags-todo "standard" + ((org-agenda-overriding-header "Changes to Standard"))))))) #+END_SRC -Since =C-u= is =universal-argument=, I put that functionality on =M-'=. - +**** Custom Agenda on Single key +:PROPERTIES: +:ID: c921d7e6-63ef-4a89-851a-0f3a122e9fa0 +:END: +Stolen from [[https://emacs.stackexchange.com/questions/864/how-to-bind-a-key-to-a-specific-agenda-command-list-in-org-mode][Stack Exchange]] #+BEGIN_SRC emacs-lisp -(keymap-global-set "M-'" 'universal-argument) +(defun org-agenda-show-custom (&optional arg) + "Show my custom agenda." + (interactive "P") + (org-agenda arg " ")) #+END_SRC -**** Moving -:PROPERTIES: -:ID: e8c8fd42-e96a-4804-8ce0-6e3ab4d9233d -:END: -***** Home/End +**** Column View :PROPERTIES: -:ID: 9f81584b-4ce1-48ff-b69f-b0bab2c1d0c5 +:ID: b30e7269-c0ba-4014-9fb9-e03e6734a4db :END: -I want =Home= and =End= to take me to the top and bottom of the file. +Set up the format for column view. #+BEGIN_SRC emacs-lisp -(keymap-global-set "" 'beginning-of-buffer) -(keymap-global-set "" 'end-of-buffer) +(setq org-columns-default-format "%50ITEM(Task) %10CLOCKSUM %16TIMESTAMP_IA" + org-agenda-start-with-log-mode t) #+END_SRC -***** Beginning of line -:PROPERTIES: -:ID: e8ddfa3d-4be7-4da7-bf6a-5dee3fcac91f -:END: -****** ~smart-beginning-of-line~ +**** Clock settings :PROPERTIES: -:ID: 7b9d4bde-5ed4-4618-899e-4a0a82359f7f +:ID: 31a4e74d-dab5-43dc-9953-b3beb6db9150 :END: -I have the infamous =smart-beginning-of-line= command here. +Resume clocking when emacs restarts, save&load running clock and history on exit/startup, resume last task on clock-in if clock is open, resume active clock without prompt, include current clocking task in reports, and make the clocktable look nice. #+BEGIN_SRC emacs-lisp -(defun smart-beginning-of-line () - "Move point to first non-whitespace character or beginning-of-line. -If point was already at that position, move point to beginning of -line. Stolen from BrettWitty's dotemacs github repo." - (interactive "^") - (let ((oldpos (point))) - (back-to-indentation) - (and (= oldpos (point)) - (beginning-of-line)))) +(org-clock-persistence-insinuate) + +(setq org-clock-persist t + org-clock-in-resume t + org-clock-persist-query-resume nil + org-clock-report-include-clocking-task t + org-pretty-entities t) #+END_SRC -****** Play nice with ~visual-line-mode~ + +*** Capture Templates :PROPERTIES: -:ID: c8ad20f0-755c-4075-ae97-a43d4869cca9 +:ID: ab7c773c-5a03-4c7b-be8a-318f2b3fd0db :END: -I had issues with ~smart-beginning-of-line~ in ~visual-line-mode~, so ~smart-beginning-of-visual-line~ was created. It implements part of ~back-to-indentation~, but with changes to use ~beginning-of-visual-line~ instead of ~beginning-of-line~. +Capture Templates per my proclivities. #+BEGIN_SRC emacs-lisp -(defun smart-beginning-of-visual-line () - "Move point to first non-whitespace character or beginning-of-line. -If point was already at that position, move point to beginning of -line. Stolen from BrettWitty's dotemacs github repo. Modified to -work in visual-line-mode. Re-implementing `back-to-indentation' -as a visual-line respecter." - (interactive "^") - (let ((oldpos (point))) - (beginning-of-visual-line 1) - (skip-syntax-forward " " (line-end-position)) - (backward-prefix-chars) - (and (= oldpos (point)) - (beginning-of-visual-line)))) +(setq org-capture-templates '(("n" "Note" entry (file org-default-notes-file) + "* %? %u" + :clock-in t + :clock-resume t) + ("t" "TODO" entry (file org-default-notes-file) + "* TODO %?\n%U\n" + :clock-in t + :clock-resume t) + ("m" "Meeting" entry (file+olp+datetree org-journal-file) + "* %? :meeting:%^g \n%t\n** Notes\n** Action Items\n*** TODO " + :clock-in t + :clock-resume t) + ("a" "Appointment" entry (file+olp+datetree org-journal-file) + "* APPT %?\nSCHEDULED: %t" + :time-prompt t) + ("j" "Journal" entry (file+olp+datetree org-journal-file) + "* %?\n%U\n"))) #+END_SRC -****** Re-mappings + +*** Abbreviations & Snippets :PROPERTIES: -:ID: 4a8e9670-2783-4f4a-ada7-f1837a8632be +:ID: d4d9cdef-583a-4fad-9cb2-17a80e093374 :END: -Remap =move-beginning-of-line=, then remap =beginning-of-visual-line= when going into =visual-line-mode=. A simple remap would not work for =visual-line-mode=, so I explicitly set =C-a=. -#+BEGIN_SRC emacs-lisp -(global-set-key [remap move-beginning-of-line] 'smart-beginning-of-line) -(add-hook 'visual-line-mode-hook - (lambda () - (keymap-global-set "C-a" 'smart-beginning-of-visual-line))) -#+END_SRC -***** Line Numbers on move only +**** Abbrev-Mode settings :PROPERTIES: -:ID: 2a73fd23-0869-4d5b-b727-8fa2486dc99b +:ID: ce23e846-972f-46c7-b7a6-b313b4149e79 :END: -I don't want line numbers in the margin unless I am actively trying to go to a line. I override =goto-line= with this function, which shows line numbers, asks me where I want to go, and then hides line numbers. +Start up =abbrev-mode= for org #+BEGIN_SRC emacs-lisp -(defun my-goto-line () - "Show line numbers before going to line, then hide them again." - (interactive) - (display-line-numbers-mode 1) - (call-interactively 'goto-line) - (display-line-numbers-mode -1)) - -(global-set-key [remap goto-line] 'my-goto-line) +(add-hook 'org-mode-hook #'abbrev-mode) +(setq abbrev-file-name (expand-file-name "abbrev_defs" user-emacs-directory) + save-abbrevs 'silently) #+END_SRC -***** Other window or split window + +**** Skeletons :PROPERTIES: -:ID: 7e9a99eb-18fd-4254-a20c-a1cb2fe0584d +:ID: fffe9361-bae6-4ceb-8a71-5d06e711528d :END: -I ripped this defun and binding from [[https://github.com/lem-project/lem][lem]]. Can't live without it now. Does similar things as [[id:1c8d7229-796f-446a-8ae8-247cd6164a12][Windmove]], but without having to specify a direction. -#+BEGIN_SRC emacs-lisp -(defun other-window-or-split-window (&optional window) - (interactive) - (if (= (count-windows) 1) - (funcall split-window-preferred-function window) - (other-window 1))) - -(keymap-global-set "C-M-o" 'other-window-or-split-window) -#+END_SRC -**** Search and Replace +***** General source Block :PROPERTIES: -:ID: 32daa74b-39b2-4275-bd88-55e9f9d0ffb5 +:ID: f469a595-d370-46b5-8d8e-afab9a816c97 :END: -I made these bindings to put my more-used commands on better keys, and swap them with the less-used ones. Also add bindings for ~isearch-*-regexp~. #+BEGIN_SRC emacs-lisp -(keymap-global-set "M-s ." 'isearch-forward-thing-at-point) -(keymap-global-set "M-s M-." 'isearch-forward-symbol-at-point) -(keymap-global-set "M-%" 'replace-regexp) -(keymap-global-set "C-%" 'replace-string) -(keymap-global-set "C-S-S" 'isearch-forward-regexp) -(keymap-global-set "C-S-R" 'isearch-backward-regexp) +(define-skeleton skel-org-block + "Insert an org source code block" + "" + "#+BEGIN_SRC " + _ - \n\n + "#+END_SRC\n") #+END_SRC -*** Elisp/Eval bindings + +***** Emacs Lisp source Block :PROPERTIES: -:ID: 05c8bf80-e35f-49bc-97b0-b6caccb63ab6 +:ID: eb47039c-d264-4a61-8da8-7659cbc02b62 :END: -Some old Emacs-like editor (Edwin?) used this binding, so I put it in here. Less used than the =C-M-x= =eval-defun= binding, but occasionally nice to have. #+BEGIN_SRC emacs-lisp -(keymap-global-set "C-M-z" 'eval-region) +(define-skeleton skel-org-block-elisp + "Insert an org emacs lisp block" + "" + "#+BEGIN_SRC emacs-lisp\n" + _ - \n + "#+END_SRC\n") #+END_SRC - -*** *NIX +***** Facility properties block :PROPERTIES: -:ID: ecfe90a8-05d6-468b-b82a-5558c4a226c1 +:ID: 30630b60-66ca-40ed-a30b-9a95a2be7c70 :END: -These defuns are here so that I can use doas/sudo over tramp to edit /local/ files requiring root permissions. Doas for BSD, Sudo for Linux, nothing for Windows. #+BEGIN_SRC emacs-lisp -(unless (or (equal system-type 'windows-nt) - (equal system-type 'android)) - (if(equal system-type 'berkeley-unix) - (defun doas () - "Use TRAMP to reopen the current buffer as root using doas." - (interactive) - (when buffer-file-name - (find-alternate-file - (concat "/doas:root@localhost:" - buffer-file-name)))) - (defun sudo () - "Use TRAMP to reopen the current buffer as root using sudo." - (interactive) - (when buffer-file-name - (find-alternate-file - (concat "/doas:root@localhost:" - buffer-file-name)))))) +(define-skeleton skel-facility-properties + "Insert the org title and filetags for a new facility." + "" + "#+TITLE: " + _ - \n + "#+FILETAGS: customer city state pm sm ee ce aka c#\n\n" + "* System Notes\n" + "* PLC [/]\n" + "* Wonderware [/]\n" + "* Commissioning [/]\n") #+END_SRC -*** Windows +***** Person properties block :PROPERTIES: -:ID: 857da290-c22e-4e38-a427-714527cf392f +:ID: 0e57ecbf-b0f5-4f7c-ad1d-d3ef69cb7581 :END: -If you've ever had the /pleasure/ of using Aveva (*Formerly WonderWare*) version 2020, you'll understand. #+BEGIN_SRC emacs-lisp -(when (equal system-type 'windows-nt) - (defun unfuck-aveva-license () - "Remove the offending xml files. -Use this when aveva can't find ass with both hands." - (interactive) - (let ((xml1 "c:/ProgramData/AVEVA/Licensing/License API2/Data/LocalAcquireInfo.xml") - (xml2 "c:/ProgramData/AVEVA/Licensing/License API2/Data/LocalBackEndAcquireInfo.xml")) - (when (file-exists-p xml1) (delete-file xml1)) - (when (file-exists-p xml2) (delete-file xml2))))) +(define-skeleton skel-person-properties + "Insert the org title and filetags for a person." + "" + "#+TITLE: @" + _ - \n + "#+FILETAGS: company position\n" + "#+EMAIL:\n" + "#+OFFICE:\n" + "#+CELL:\n") #+END_SRC -*** Math +***** Workorder properties block :PROPERTIES: -:ID: 69a05305-6b16-4abf-bf9a-b858d9a7e642 +:ID: a0062c3f-caf0-4de4-9d95-0dffc04eba31 :END: -General Math defuns, often used in later defuns. -**** Exponentiation +#+BEGIN_SRC emacs-lisp +(define-skeleton skel-workorder-properties + "Insert the org title and filetags for a workorder" + "" + "#+TITLE: Workorder " + _ - \n + "#+FILETAGS: wo# workorder customer city state topics\n") +#+END_SRC + +**** Bind the snippets (in the =abbrev-file-name= file) :PROPERTIES: -:ID: 14d9a8c0-2984-4d53-b933-01366b286208 +:ID: 1e9362ab-d7da-4d87-bef4-9a6c39530832 :END: -I'm tired of writing out ='expt=, and I want to use the same notation every other programming language does. -#+BEGIN_SRC emacs-lisp -(defalias '^ 'expt) +#+BEGIN_SRC emacs-lisp :tangle ./abbrev_defs +;;-*-coding: utf-8;-*- +(define-abbrev-table 'org-mode-abbrev-table + '(("ssrc" "" skel-org-block) + ("selisp" "" skel-org-block-elisp) + ("sfac" "" skel-facility-properties) + ("sper" "" skel-person-properties) + ("swo" "" skel-workorder-properties))) #+END_SRC -**** Square, Cube, and Inv + +*** Auto-archive :PROPERTIES: -:ID: 871f50e4-447e-4da0-b86f-ec253c7d48cf +:ID: f1e0b6cf-023f-44e3-a489-15fa04208cd3 :END: -Define square, cube, and inv for brevity of common usages. -#+BEGIN_SRC emacs-lisp -(defun square (x) - "Calculate the square of a value." - (^ x 2)) +A function to automatically archive *DONE* items in an org file. I sometimes use this as an after-save-hook header declaration as such: +#+BEGIN_SRC emacs-lisp :tangle no +-*- after-save-hook: (org-auto-archive) -*- +#+END_SRC -(defun cube (x) - "Calculate the cube of a value." - (^ x 3)) +#+BEGIN_SRC emacs-lisp +(defun org-auto-archive () + "Automatically archive completed tasks in an org file. +Intended for use as an after-save-hook." + (interactive) + (org-map-entries + (lambda () + (org-archive-subtree) + (setq org-map-continue-from (org-element-property :begin (org-element-at-point)))) + "TODO=\"DONE\"|TODO=\"CANCELLED\"|TODO=\"DELEGATED\"" + 'file) + (save-buffer)) +#+END_SRC -(defun inv (x) - "Calculate the inverse of a value." - (/ 1 (float x))) +Also add that defun to =safe-local-variables= so that emacs will run it. +#+BEGIN_SRC emacs-lisp +(setq safe-local-variable-values '((after-save-hook org-auto-archive))) #+END_SRC -*** Unit Conversions +*** Auto-Generate IDs :PROPERTIES: -:ID: d756d65e-aca5-4718-af09-aaecbbd62f99 +:ID: f2660fb6-f995-4b5b-a01c-6bf8b5d9c894 :END: -The rest of the world decided to self-castrate because some French guys told them things Definitely Made More Sense if everything was divisible by 10. I'm convinced the average Frenchman simply couldn't grasp fractions, and that's why he came up with this crap. What's 1/3 of a meter? What's 1/3 of a yard? And 1/3 of a foot? How likely are you to need to divide a measurement by 3 when you're building something? Maybe the [[https://dozenal.org/][Dozenal]] people were right all along. Anyway, I'm now forced to convert into proper units daily because of this grave error. - +**** On Capture +:PROPERTIES: +:ID: b40f11e3-8569-4fcd-b083-f1b682f23dc1 +:END: +Generate an ID when I capture someting, and when I try to link to it. Stolen from [[https://stackoverflow.com/questions/13340616/assign-ids-to-every-entry-in-org-mode][Stack Overflow]] #+BEGIN_SRC emacs-lisp -(defun mm->in (mm) - "Convert milimeters to inches." - (/ mm 25.4)) +(setq org-id-link-to-org-use-id t) +#+END_SRC -(defun in->mm (in) - "Convert inches to milimeters." - (* in 25.4)) +**** Existing File +:PROPERTIES: +:ID: 4120cfb4-59d5-441d-abaa-b49f847f5b90 +:END: +Automatically generate unique IDs if not already created. Stolen from [[https://stackoverflow.com/questions/13340616/assign-ids-to-every-entry-in-org-mode][Stack Overflow]] +#+BEGIN_SRC emacs-lisp +(defun org-auto-generate-ids-in-file () + "Add ID properties to all headlines in the current + file which do not already have one." + (interactive) + (org-map-entries 'org-id-get-create)) +#+END_SRC -(defun k->c (tempk) - "Convert degrees Kelvin to degrees Celsius." - (- tempk 273.15)) +Run this on save of any org-mode file +#+BEGIN_SRC emacs-lisp +(add-hook 'org-mode-hook + (lambda () + (add-hook 'before-save-hook 'org-auto-generate-ids-in-file nil 'local))) +#+END_SRC -(defun c->k (tempc) - "Convert degrees Celsius to degrees Kelvin." - (+ tempc 273.15)) +*** Tangling +:PROPERTIES: +:ID: f0c4710a-0172-41bc-9744-4fd48872d4a2 +:END: +**** Settings +:PROPERTIES: +:ID: 3d8f6700-07a2-4e1e-b3c7-7d77afdcf85c +:END: +Don't make a new window for source-code edits, and keep indentation consistent. +#+BEGIN_SRC emacs-lisp +(setq org-src-window-setup 'current-window + org-src-preserve-indentation t + org-src-fontify-natively t) +#+END_SRC -(defun c->f (tempc) - "Convert degrees Celsius to degrees Fahrenheit." - (+ (* tempc 1.8) 32.0)) +**** Auto-tangle init.org +:PROPERTIES: +:ID: cd914118-d6e7-485d-b27e-3172f3b77af9 +:END: +Make a function to tangle this file, and run it on save. +#+BEGIN_SRC emacs-lisp +(defun tangle-init () + "Tangle and compile init.org. +Stolen from https://github.com/larstvei/dot-emacs." + (when (equal (buffer-file-name) + (expand-file-name (concat user-emacs-directory "init.org"))) + (let ((prog-mode-hook nil)) + (org-babel-tangle)))) -(defun f->c (tempf) - "Convert degrees Fahrenheit to degrees Celsius." - (/ (- tempf 32.0) 1.8)) +(add-hook 'after-save-hook 'tangle-init) +#+END_SRC -(defun k->f (tempk) - "Convert degrees Kelvin to degrees Fahrenheit. -Applies `c->f' to `k->c'." - (c->f (k->c tempk))) +*** Bindings +:PROPERTIES: +:ID: adf21035-f2f1-443b-a599-4ce4f282a2ff +:END: +**** Global +:PROPERTIES: +:ID: 3281906e-1f44-4abb-9f9d-0a0a39221752 +:END: +The usual bindings. +#+BEGIN_SRC emacs-lisp +(keymap-global-set "C-c l" 'org-store-link) +(keymap-global-set "C-c a" 'org-agenda) +(keymap-global-set "C-c c" 'org-capture) +(keymap-global-set "C-c b" 'org-switchb) +(keymap-global-set "" 'org-agenda-show-custom) +#+END_SRC -(defun f->k (tempf) - "Convert degrees Fahrenheit to degrees Kelvin. -Applies `c->k' to `f->c'." - (c->k (f->c tempf))) +**** Mode-Specific +:PROPERTIES: +:ID: 99906320-74b0-4414-8d87-1ce1ddddad97 +:END: +Give me logical in/out-denting on the easier binding, since I use that more often. +#+BEGIN_SRC emacs-lisp +(add-hook 'org-mode-hook + (lambda () + (keymap-set org-mode-map "M-" 'org-shiftmetaright) + (keymap-set org-mode-map "M-" 'org-shiftmetaleft) + (keymap-set org-mode-map "M-S-" 'org-metaright) + (keymap-set org-mode-map "M-S-" 'org-metaleft))) #+END_SRC -*** Electrical +** Dired configuration :PROPERTIES: -:ID: 8c0d72bc-b8ba-4f9f-be49-876bd624c2ae +:ID: 245c157b-036f-4489-b221-193691a7f94b :END: -These defuns are all about electronics. Effective impedance, amps to volts, and back again. +Make dired use the same switches I prefer for =ls=, give me a simpler listing, and default to using its current buffer for visiting a file, rather than creating a new one. #+BEGIN_SRC emacs-lisp -(defun eff-imp (r1 &optional r2) - "Calculate the effective input impedance, given two resistances. -For use in `amps->volts' and related. The handling of only one -resistance given is done here, instead of doing it in every -function that uses this." - (if (eq nil r2) - r1 - (inv (+ (inv r1) (inv r2))))) +(setq dired-listing-switches "-alv --group-directories-first") -(defun amps->volts (amps r1 &optional r2) - "Calculate the voltage, given amperage and impedance. -Multiplies the amperage by the effective impedance calculated -with `eff-imp'." - (* amps (eff-imp r1 r2))) +(add-hook 'dired-mode-hook + (lambda () + (dired-hide-details-mode t) + (keymap-set dired-mode-map + "RET" 'dired-find-alternate-file))) +#+END_SRC -(defun volts->amps (volts r1 &optional r2) - "Calculate the amperage, given voltage and impedance. -Divides the voltage by the effective impedance calculated with -`eff-imp'." - (/ volts (eff-imp r1 r2))) +** Eshell configuration +:PROPERTIES: +:ID: 700392e5-d07b-474f-baa9-f563b4a6197f +:END: +Here are the various customizations I have for eshell. +*** Binding to start eshell +:PROPERTIES: +:ID: 9178eac2-5f69-4574-ae47-b491374f643f +:END: +#+BEGIN_SRC emacs-lisp +(keymap-global-set "C-c s" 'eshell) #+END_SRC -*** PLC +*** Make it play nice with corfu :PROPERTIES: -:ID: 850536ef-64b6-44d6-9b64-61d2a4ed050a +:ID: dc7f2345-2ee3-4883-90ff-b0a8c25c9422 :END: -The nitty-gritty. These defuns build on the previous ones to help me do various calculations related to analog signals and how they interact with [[https://en.wikipedia.org/wiki/Programmable_logic_controller][PLCs]], also called PACs. Counts, volts, amps, bit-resolutions, and relating them to each other. + #+BEGIN_SRC emacs-lisp -(defun max-counts (resolution) - "Calculate the max count for a PLC analog, given card's bit-resolution." - (- (^ 2 resolution) 1)) +(add-hook 'eshell-mode-hook (lambda () + ;; (setq-local corfu-auto nil) + (corfu-mode))) +#+END_SRC -(defun volts->counts (vmax vin resolution) - "Convert a voltage signal to a PLC count. -Calculates a ratio of vin/vmax, then scales by `max-counts'." - (* (/ (float vin) vmax) (max-counts resolution))) +*** Send on Close-Paren +:PROPERTIES: +:ID: 325c01c5-b877-4281-adff-ea956bdb5f2c +:END: +I wanted something like what the Genera environment has, where putting in a final close-paren will send the command, without having to hit enter. See [[id:325c01c5-b877-4281-adff-ea956bdb5f2c][Send on Close-Paren]]. -(defun counts->volts (vmax cin resolution) - "Convert a PLC count to a voltage. -Calculates a ratio of cin/`max-counts', then multiplies by vmax." - (* (/ (float cin) (max-counts resolution)) vmax)) +#+BEGIN_SRC emacs-lisp +(defun eshell-send-on-close-paren () + "Makes eshell act somewhat like genera. +Makes a closing paren execute the sexp." + (interactive) + (send-on-close-paren 'eshell-send-input)) +#+END_SRC -(defun amps->counts (vmax amps resolution r1 &optional r2) - "Convert a current signal to PLC Counts. -Converts the amperage to a voltage using `amps->volts' (with r1 -and optional r2), then applies `volts->counts' to the resulting -voltage, vmax, and resolution." - (volts->counts vmax (amps->volts amps r1 r2) resolution)) +*** Quit or delete-char +:PROPERTIES: +:ID: ed19265d-4b5c-426b-8c74-cf36939a8b8f +:END: +I want =C-d= to end the shell if it is on an empty line, otherwise act normally. -(defun count-range (upper lower vmax resolution &optional r1 r2) - "Given an upper and lower signal, return the list of upper and lower PLC counts. -With a current signal, use r1 and maybe r2 to -calculate `amps->counts'. Otherwise ignore r1/r2 and calculate -`volts->counts'." - (if (eq nil r1) - (list (volts->counts vmax upper resolution) - (volts->counts vmax lower resolution)) - (list (amps->counts vmax upper resolution r1 r2) - (amps->counts vmax lower resolution r1 r2)))) +#+BEGIN_SRC emacs-lisp +(defun eshell-quit-or-delete-char (arg) + "Delete char if at one, quit eshell if on empty prompt. +Stolen from https://depp.brause.cc/dotemacs" + (interactive "p") + (if (and (eolp) (looking-back eshell-prompt-regexp 0 t)) + (eshell-life-is-too-much) ; https://emacshorrors.com/post/life-is-too-much + (delete-char arg))) +#+END_SRC -(defun divisor (raw-max raw-min scaled-max scaled-min) - "Calculate 1/slope given PLC Max/Min and Eng. Max/Min." - (/ (float (- raw-max raw-min)) (- scaled-max scaled-min))) +*** Bind the defuns +:PROPERTIES: +:ID: eac8b87a-0ca9-4d0f-8cd4-1d1538ec16d0 +:END: +I have only been able to get these to work when they are within an add-hook lambda. -(defun offset (raw-max raw-min scaled-max scaled-min) - "Calculate offset given PLC Max/Min and Eng. Max/Min." - (- scaled-min (/ raw-min (divisor raw-max raw-min scaled-max scaled-min)))) +#+BEGIN_SRC emacs-lisp +(add-hook 'eshell-mode-hook + (lambda () + (keymap-set eshell-mode-map ")" 'eshell-send-on-close-paren) + (keymap-set eshell-mode-map "C-d" 'eshell-quit-or-delete-char))) +#+END_SRC +** ielm configuration +:PROPERTIES: +:ID: e7a7b861-8f63-4036-9f68-59fb954a7561 +:END: +I wanted something more like a standard lisp REPL in emacs. Found =ielm=. +*** Send on Close-Paren +:PROPERTIES: +:ID: 664ba0e7-0826-4868-9480-e1338a6e9f63 +:END: +I wanted something like what the Genera environment has, where putting in a final close-paren will send the command, without having to hit enter. See [[id:325c01c5-b877-4281-adff-ea956bdb5f2c][Send on Close-Paren]]. -(defun final (analog-input divisor offset) - "Calculate the scaled value of an input." - (+ (/ analog-input divisor) offset)) +#+BEGIN_SRC emacs-lisp +(defun ielm-send-on-close-paren () + "Makes ielm act somewhat like genera. +Makes a closing paren execute the sexp." + (send-on-close-paren 'ielm-send-input)) +#+END_SRC +*** Persistent command history +:PROPERTIES: +:ID: 19726597-2a2e-4059-9447-d7e90696fe08 +:END: +**** Read History +:PROPERTIES: +:ID: 6db9d990-00e7-44ec-a83c-b2999fa8db73 +:END: +#+BEGIN_SRC emacs-lisp +(defun g-ielm-init-history () + "Stolen from https://n16f.net/blog/making-ielm-more-comfortable." + (let ((path (expand-file-name "ielm/history" user-emacs-directory))) + (make-directory (file-name-directory path) t) + (setq-local comint-input-ring-file-name path)) + (setq-local comint-input-ring-size 10000 + comint-input-ignoredups t) + (comint-read-input-ring)) -(defun scale (raw-max raw-min scaled-max scaled-min &optional analog-input) - "Calculate the divisor, offset, and maybe final value, given the parameters." - (let* ((div (divisor raw-max raw-min scaled-max scaled-min)) - (os (offset raw-max raw-min scaled-max scaled-min))) - (if (eq nil analog-input) - (list div os) - (list div os (final analog-input div os))))) +(add-hook 'ielm-mode-hook 'g-ielm-init-history) #+END_SRC +**** Write History +:PROPERTIES: +:ID: f7f1df1f-9531-4ef6-b66f-dc0d46295864 +:END: +#+BEGIN_SRC emacs-lisp +(defun g-ielm-write-history (&rest _args) + "Stolen from https://n16f.net/blog/making-ielm-more-comfortable." + (with-file-modes #o600 + (comint-write-input-ring))) -*** Refrigeration +(advice-add 'ielm-send-input :after 'g-ielm-write-history) +#+END_SRC +*** Bindings :PROPERTIES: -:ID: 18225f24-139e-4707-8935-03a6cf48290a +:ID: 68c34ab5-7149-49f5-91e8-fcea22d98fcd :END: -More nitty-gritty. These are for calculating specific refrigeration-related things. Somewhat specialized. +~C-l~ to clear buffer, send on close paren. #+BEGIN_SRC emacs-lisp -(defun cfm-circ (fpm radius) - "Calculate the CFM of a circular duct. -Inputs are feet/minute and radius (in)." - (list (* float-pi fpm (square (/ radius 12.0))))) +(keymap-global-set "C-c i" 'ielm) +(add-hook 'ielm-mode-hook + (lambda () + (keymap-set inferior-emacs-lisp-mode-map "C-l" 'comint-clear-buffer) + (keymap-set inferior-emacs-lisp-mode-map ")" 'ielm-send-on-close-paren))) +#+END_SRC +** Lisp interaction mode configuration +:PROPERTIES: +:ID: 5b958a6f-130d-449c-b6ab-f870947820b8 +:END: +I want the scratch buffer to act more like a repl -(defun cfm-rect (fpm width height) - "Calculate the CFM of a rectangular duct. -Inputs are feet/minute, width (in) and height (in)." - (list (* fpm (/ width 12.0) (/ height 12.0)))) +** Send on Close-Paren +:PROPERTIES: +:ID: 664ba0e7-0826-4868-9480-e1338a6e9f63 +:END: +I wanted something like what the Genera environment has, where putting in a final close-paren will send the command, without having to hit enter. See [[id:325c01c5-b877-4281-adff-ea956bdb5f2c][Send on Close-Paren]]. +*** Send on Close Paren +:PROPERTIES: +:ID: 72ead9d2-fc5c-42f0-a1b4-db28a532d920 +:END: +#+BEGIN_SRC emacs-lisp +(defun lisp-interaction-send-on-close-paren () + "Makes lisp interaction mode act somewhat like genera. +Makes a closing paren execute the sexp." + (interactive) + (send-on-close-paren 'lisp-interaction-send-on-close-paren)) +#+END_SRC -(defun gn-water-per-lb (temp humidity) - "Calculate the grains of water per lb of air. -Inputs are temp (F) and humidity (%). Returns a list of -Saturated Water Pressure, Humidity Ratio, and Grains of water per -lb of air." - (let* ((sat-water-press (+ .0182795 - (* temp .001029904) - (* (square temp) 0.00002579408) - (* (cube temp) (* 2.400493 (^ 10 -7))) - (* (^ temp 4) (* 8.100939 (^ 10 -10))) - (* (^ temp 5) (* 3.256805 (^ 10 -11))) - (* (^ temp 6) (* -1.001922 (^ 10 -13))) - (* (^ temp 7) (* 2.44161 (^ 10 -16))))) - (hum-press (* (/ humidity 100.0) sat-water-press)) - (hum-ratio (/ (* hum-press 0.62198) (- 14.7 hum-press))) - (gns-water-lb-air (* hum-ratio 7000))) - (list sat-water-press hum-ratio gns-water-lb-air))) +*** Binding +:PROPERTIES: +:ID: 9930f99d-aa36-4f00-8bc7-8c619979712a +:END: +#+BEGIN_SRC emacs-lisp +(add-hook 'lisp-interaction-mode-map + (lambda () + (keymap-set lisp-interaction-mode-map ")" 'lisp-interaction-send-on-close-paren))) #+END_SRC ** Customize system -- 2.39.5