Architectural Upgrade 2026-03-30: Modular Emacs, org-gtd v4.0, and PSF Phase 1
This commit is contained in:
254
system/emacs-writing.org
Normal file
254
system/emacs-writing.org
Normal file
@@ -0,0 +1,254 @@
|
||||
#+TITLE: Reading and Writing Configuration
|
||||
#+PROPERTY: header-args :tangle yes
|
||||
|
||||
* Text and Case
|
||||
|
||||
** Convert DOuble capitals to single capitals
|
||||
|
||||
#+begin_src elisp :tangle yes
|
||||
(defun my/dcaps-to-scaps ()
|
||||
"Convert word in DOuble CApitals to Single Capitals."
|
||||
(interactive)
|
||||
(and (= ?w (char-syntax (char-before)))
|
||||
(save-excursion
|
||||
(and (if (called-interactively-p)
|
||||
(skip-syntax-backward "w")
|
||||
(= -3 (skip-syntax-backward "w"))
|
||||
)
|
||||
(let (case-fold-search)
|
||||
(looking-at "\\b[[:upper:]]\\{2\\}[[:lower:]]")
|
||||
)
|
||||
(capitalize-word 1)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
#+end_src
|
||||
|
||||
Then, let’s define a minor mode for it to be activated.
|
||||
#+begin_src elisp :tangle yes
|
||||
(define-minor-mode my-dubcaps-mode
|
||||
"Toggle 'my-dubcaps-mode' and convert words in DOuble CApitals to Single Capitals as you type."
|
||||
:init-value nil
|
||||
:lighter (" DC")
|
||||
(if my-dubcaps-mode
|
||||
(add-hook 'post-self-insert-hook #'my/dcaps-to-scaps nil 'local)
|
||||
(remove-hook 'post-self-insert-hook #'my/dcaps-to-scaps 'local)))
|
||||
#+end_src
|
||||
|
||||
Finally, let’s add a hook so that it is on for all the text files Emacs opens.
|
||||
#+begin_src elisp :tangle yes
|
||||
(add-hook 'text-mode-hook #'my-dubcaps-mode)
|
||||
#+end_src
|
||||
|
||||
Also, since we add a minor mode string (it might be useful sometimes), currently I prefer to diminish it.
|
||||
#+begin_src elisp :tangle yes
|
||||
(defun my/diminish-dubcaps ()
|
||||
(interactive)
|
||||
(diminish 'my-dubcaps-mode ""))
|
||||
(add-hook 'my-dubcaps-mode-hook 'my/diminish-dubcaps)
|
||||
#+end_src
|
||||
|
||||
* Reading and Writing
|
||||
|
||||
** Move correctly over camelCased words
|
||||
|
||||
#+begin_src elisp
|
||||
(subword-mode)
|
||||
#+end_src
|
||||
|
||||
** Understand the more common sentence with double space
|
||||
|
||||
#+begin_src elisp
|
||||
(setq sentence-end-double-space nil)
|
||||
#+end_src
|
||||
|
||||
** Join lines into paragraph
|
||||
|
||||
#+begin_src elisp
|
||||
(defun my/fill-or-unfill-paragraph (&optional unfill region)
|
||||
"Fill paragraph (or REGION). With the prefix argument UNFILL, fill it instead."
|
||||
(interactive (progn
|
||||
(barf-if-buffer-read-only)
|
||||
(list (if current-prefix-arg 'fill) t)))
|
||||
(let ((fill-column (if unfill fill-column (point-max))))
|
||||
(fill-paragraph nil region)))
|
||||
|
||||
(bind-key "M-q" 'my/fill-or-unfill-paragraph)
|
||||
#+end_src
|
||||
|
||||
#+begin_src elisp
|
||||
(defun my/fill-or-unfill-all-paragraphs (&optional unfill)
|
||||
"Fill or unfill all paragraphs in the current buffer.
|
||||
With the prefix argument UNFILL, fill them instead."
|
||||
(interactive (list (if current-prefix-arg 'fill)))
|
||||
(let ((fill-column (if unfill fill-column (point-max))))
|
||||
(save-excursion
|
||||
(goto-char (point-min))
|
||||
(while (not (eobp))
|
||||
(fill-paragraph nil t)
|
||||
(forward-paragraph)))))
|
||||
|
||||
(bind-key "M-Q" 'my/fill-or-unfill-all-paragraphs)
|
||||
#+end_src
|
||||
|
||||
#+begin_src elisp
|
||||
(remove-hook 'text-mode-hook #'turn-on-auto-fill)
|
||||
(add-hook 'text-mode-hook 'turn-on-visual-line-mode)
|
||||
#+end_src
|
||||
|
||||
** Expand some words with auto-correct
|
||||
|
||||
#+begin_src elisp :tangle yes
|
||||
(setq save-abbrevs 'silently)
|
||||
(setq-default abbrev-mode t)
|
||||
#+end_src
|
||||
|
||||
** ediff
|
||||
|
||||
#+begin_src elisp :tangle yes
|
||||
(setq ediff-window-setup-function 'ediff-setup-windows-plain)
|
||||
(setq ediff-split-window-function 'split-window-horizontally)
|
||||
#+end_src
|
||||
|
||||
** tramp
|
||||
|
||||
#+begin_src elisp :tangle yes
|
||||
(setq tramp-default-method "ssh"
|
||||
tramp-backup-directory-alist backup-directory-alist
|
||||
tramp-ssh-controlmaster-options "ssh")
|
||||
#+end_src
|
||||
|
||||
** Clean up space
|
||||
#+begin_src elisp :tangle yes
|
||||
(bind-key "M-SPC" 'cycle-spacing)
|
||||
#+end_src
|
||||
|
||||
** Transform <a href> links into org links
|
||||
|
||||
#+begin_src elisp :tangle yes
|
||||
(defun my/transform-html-links-to-org ()
|
||||
"Transform all HTML <a> links in the current buffer into 'org-mode' links."
|
||||
(interactive)
|
||||
(goto-char (point-min))
|
||||
(while (re-search-forward "<a href=\"\\(.*?\\)\">\\(.*?\\)</a>" nil t)
|
||||
(replace-match (org-make-link-string (match-string 1) (match-string 2)))))
|
||||
#+end_src
|
||||
|
||||
** Count words per minute
|
||||
#+begin_src elisp :tangle yes
|
||||
(require 'org-clock)
|
||||
(defun my/org-entry-wpm ()
|
||||
(interactive)
|
||||
(save-restriction
|
||||
(save-excursion
|
||||
(org-narrow-to-subtree)
|
||||
(goto-char (point-min))
|
||||
(let* ((words (count-words-region (point-min) (point-max)))
|
||||
|
||||
(minutes (org-clock-sum-current-item))
|
||||
(wpm (/ words minutes)))
|
||||
(message "WPM: %d (words: %d, minutes: %d)" wpm words minutes)
|
||||
(kill-new (number-to-string wpm))
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
#+end_src
|
||||
|
||||
** Enable dict mode
|
||||
#+begin_src elisp :tangle yes
|
||||
(setq dictionary-server "automatic")
|
||||
#+end_src
|
||||
|
||||
** Pick out passive voice and weasel words
|
||||
#+begin_src elisp :tangle yes
|
||||
(use-package writegood-mode
|
||||
:diminish writegood-mode
|
||||
:config
|
||||
(progn (add-hook 'text-mode-hook 'writegood-mode))
|
||||
)
|
||||
#+end_src
|
||||
|
||||
** Org-babel docker
|
||||
#+begin_src elisp :tangle yes
|
||||
(use-package ob-docker-build
|
||||
:straight (ob-docker-build :type git :host github :repo "ifitzpat/ob-docker-build")
|
||||
:defer t
|
||||
:config
|
||||
(add-to-list 'org-babel-load-languages '(docker-build . t))
|
||||
(org-babel-do-load-languages 'org-babel-load-languages org-babel-load-languages)
|
||||
)
|
||||
#+end_src
|
||||
|
||||
* Spelling and syntax
|
||||
|
||||
** Spell checking
|
||||
|
||||
This requires installation of hunspell
|
||||
#+begin_src bash :tangle yes
|
||||
sudo apt install hunspell
|
||||
#+end_src
|
||||
|
||||
#+begin_src elisp
|
||||
(use-package flyspell
|
||||
:config (setq ispell-program-name "hunspell"
|
||||
ispell-default-dictionary "en_US"
|
||||
)
|
||||
:diminish (flyspell-mode . "φ")
|
||||
:hook (text-mode . flyspell-mode)
|
||||
:bind (
|
||||
("M-<f7>" . flyspell-buffer)
|
||||
("<f7>" . flyspell-word)
|
||||
("C-;" . flyspell-auto-correct-previous-word)
|
||||
)
|
||||
)
|
||||
#+end_src
|
||||
|
||||
** Flyspell correct
|
||||
#+begin_src elisp :tangle yes
|
||||
(use-package flyspell-correct
|
||||
:after flyspell
|
||||
:bind (:map flyspell-mode-map ("C-;" . flyspell-correct-wrapper))
|
||||
)
|
||||
#+end_src
|
||||
|
||||
** Flycheck
|
||||
|
||||
Needs external checkers installed
|
||||
|
||||
#+begin_src elisp
|
||||
(use-package flycheck
|
||||
:defer t
|
||||
:diminish (flycheck-mode . "")
|
||||
:config
|
||||
(setq flycheck-emacs-lisp-load-path 'inherit)
|
||||
(setq flycheck-emacs-lisp-load-path (concat user-emacs-directory "straight/build")))
|
||||
|
||||
#+end_src
|
||||
|
||||
** Flycheck bash
|
||||
#+begin_src bash :tangle yes
|
||||
sudo apt install devscripts
|
||||
#+end_src
|
||||
|
||||
#+begin_src elisp :tangle yes
|
||||
(use-package flycheck-checkbashisms
|
||||
:config
|
||||
(flycheck-checkbashisms-setup)
|
||||
)
|
||||
#+end_src
|
||||
|
||||
** Yaml
|
||||
#+begin_src elisp :tangle yes
|
||||
(use-package yaml-mode
|
||||
:config
|
||||
(add-to-list 'auto-mode-alist '("\\.yml\\'" . yaml-mode))
|
||||
(add-to-list 'auto-mode-alist '("\\.yaml\\'" . yaml-mode))
|
||||
)
|
||||
#+end_src
|
||||
|
||||
** Docker
|
||||
#+begin_src elisp :tangle yes
|
||||
(use-package docker-compose-mode)
|
||||
#+end_src
|
||||
Reference in New Issue
Block a user