dotemacs/init.org

5388 lines
173 KiB
Org Mode
Raw Normal View History

#+TODO: TODO WIP WISH CLEANUP FIXME REVIEW |
2021-11-15 16:56:21 +00:00
#+OPTIONS: use-property-inheritance:t
2022-01-15 07:26:04 +00:00
#+PROPERTY: header-args :load yes :tangle init.el :comments link
2022-01-15 20:41:22 +00:00
Some background is important to understand my keybinding choices -
1. I use modifier-less bindings wherever possible. Hydra and modal editing make up most of my interaction with Emacs.
2. I use Kmonad to have Space act as Control when held. This makes Control the modifier which disrupts the typing position the least. It is also held with the thumbs - the strongest digits - reducing fatigue. So if I must use a modifier, I use Control.
2022-01-15 07:21:09 +00:00
3. I use the Dvorak layout.
2022-01-16 08:28:10 +00:00
4. I've used Vim and Evil for the longest time, but I like Boon's movement layout best -
* QWERTY IO move up and down
* QWERTY KL move left and right in small units (characters), and
* QWERTY J; move left and right in larger units (words or s-expressions)
This has several benefits over HJKL -
1. To move left, the wrist need not to be angled awkwardly to sit on QWERTY HJKL (which also means the keyboard tactile nub on J does not sit under the index finger),
2. ...nor need the finger make an awkward jump to QWERTY H on each left-moving operation.
3. The relaxed position of the fingers placed on a flat surface is a curl, not a line, which is reflected in Boon's default JIO; position.
2021-08-04 08:34:12 +00:00
2022-01-15 07:26:04 +00:00
* package.el :package:
<2021-12-20T20:41:17+0530>
#+BEGIN_SRC emacs-lisp
(require 'package)
;; ;; when GNU ELPA is down
;; (setq package-archives (assoc-delete-all "gnu" package-archives))
(add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/") t)
;; Comment/uncomment this line to enable MELPA Stable if desired. See
;; `package-archive-priorities` and `package-pinned-packages`. Most
;; users will not need or want to do this.
;; (add-to-list 'package-archives '("melpa-stable" . "https://stable.melpa.org/packages/") t)
(package-initialize)
#+END_SRC
2021-08-04 08:34:12 +00:00
2022-01-16 07:39:58 +00:00
* use-package :package:
2021-11-18 09:28:23 +00:00
#+BEGIN_SRC emacs-lisp
2022-01-16 10:36:34 +00:00
(add-to-list 'load-path "~/.emacs.d/elisp-git/use-package/")
(require 'use-package)
(setq use-package-compute-statistics t)
2021-11-18 09:28:23 +00:00
#+END_SRC
* TODO dvorak [60%]
2021-02-19 07:26:09 +00:00
At first I decided to remap all Emacs, Boon, and Hydra bindings, but it turned out to not be my idea of fun. I wrote boon-dvorak, and let [most of] the others be.
(QWERTY) C-w, C-u, and C-h are probably best left as they are, since they are also present in other applications.
2021-02-19 07:26:09 +00:00
1. [X] M-n, M-p, -> M-r, M-c
2. [X] M-q -> M-'
2021-02-19 15:58:27 +00:00
3. [X] M--
2021-02-19 07:26:09 +00:00
4. [ ] multiple-cursors
2021-02-19 15:58:27 +00:00
5. [ ] boon-c-god is bound to "j", which emulates QWERTY "c", but the bindings after it do not. Thus, to input "C-c C-c", one must press "j c" in Dvorak. Yuck.
2021-02-20 06:19:14 +00:00
6. [ ] M-n M-n not getting bound to font-lock-fontify-block ?
7. [ ] binding C-d to keyboard-quit in the minibuffer
2021-02-19 07:26:09 +00:00
2021-02-18 22:34:51 +00:00
#+BEGIN_SRC emacs-lisp
2021-12-19 06:05:43 +00:00
(use-package general
2022-01-16 06:00:55 +00:00
:commands (general-auto-unbind-keys general-def general-define-key))
2021-02-18 22:34:51 +00:00
#+END_SRC
2022-01-15 07:27:22 +00:00
2021-11-15 16:56:21 +00:00
* exwm :disabled:
:PROPERTIES:
:literate-load: no
2021-11-15 16:56:21 +00:00
:header-args: :load no :tangle no
:CUSTOM_ID: exwm
2021-11-15 16:56:21 +00:00
:END:
#+BEGIN_SRC emacs-lisp :load no
(setq exwm-input-global-keys
'(([?\C-1] . select-window-1)
([?\C-2] . select-window-2)
([?\C-3] . select-window-3)
([?\C-4] . select-window-4)
2021-08-08 17:42:33 +00:00
([?\C-7] . select-window-1)
([?\C-8] . select-window-2)
([?\C-9] . select-window-3)
([?\C-0] . select-window-4)
2021-08-04 08:37:36 +00:00
([?\C-\\] . toggle-input-method)
2021-08-08 17:42:33 +00:00
([?\C-`] . shell)
2021-07-30 18:50:39 +00:00
([?\s-q] . exwm-input-toggle-keyboard)
([?\s-j] . split-window-below)
([?\s-k] . split-window-right)
([?\s-x] . delete-other-windows)
([?\s-b] . delete-other-windows)
([?\s-m] . my-general-hydra/body)
2022-01-15 21:02:18 +00:00
([?\s-w] . consult-buffer)
([?\s-v] . exwm-input-toggle-keyboard)))
#+END_SRC
2022-01-16 08:00:17 +00:00
Use window title for buffer names.
#+BEGIN_SRC emacs-lisp :load no
(require 'exwm)
2022-01-16 08:00:17 +00:00
(add-hook 'exwm-update-title-hook (lambda () (exwm-workspace-rename-buffer exwm-title)))
(exwm-enable)
2021-07-30 23:37:29 +00:00
#+END_SRC
2022-01-15 07:27:22 +00:00
** Helpers
2022-01-16 08:00:17 +00:00
:PROPERTIES:
:literate-load: yes
:header-args: :load yes :tangle yes
:END:
2021-07-30 23:37:29 +00:00
A less repetitive way to start processes. Also enables Boon in the process buffer, so I can easy navigate it, copy text in it, or switch away from it.
#+BEGIN_SRC emacs-lisp :load no
2021-07-30 09:13:20 +00:00
(defun my-start-process (program &optional name &rest args)
2021-07-30 23:37:29 +00:00
"Run PROGRAM with ARGS in buffer NAME."
2021-07-30 09:13:20 +00:00
(interactive "P")
(let* ((name (if name name program))
(proc-buffer (generate-new-buffer-name name)))
(apply #'start-process name proc-buffer program args)
(with-current-buffer proc-buffer (boon-mode))))
2021-07-30 23:37:29 +00:00
#+END_SRC
2021-07-30 09:13:20 +00:00
2021-09-01 12:24:07 +00:00
This is useful even without EXWM - switching does not work (...yet?), but I can launch apps via Hydra, and the output goes into the familiar environment of an Emacs buffer.
2022-01-16 08:00:17 +00:00
#+BEGIN_SRC emacs-lisp
(defun my-start-app-or-switch (program &optional class-re title-re name &rest args)
"Switch to EXWM buffer matching CLASS-RE or TITLE-RE, or run PROGRAM with ARGS.
NAME is the name of the process and its buffer."
2021-07-30 23:37:29 +00:00
(let* ((name (if name name program))
(regex (or class-re title-re program))
(buffer (when (featurep 'exwm)
(seq-find
(lambda (buffer)
(with-current-buffer buffer
(if title-re
(and exwm-title
(string-match-p title-re exwm-title))
(and exwm-class-name
(string-match-p regex exwm-class-name)))))
(buffer-list)))))
2021-07-30 23:37:29 +00:00
(if buffer (switch-to-buffer buffer)
(apply #'my-start-process program name args))))
#+END_SRC
2022-01-16 08:00:17 +00:00
** Startup programs :disabled:
#+BEGIN_SRC emacs-lisp :load no :tangle no
2021-11-15 16:56:21 +00:00
(my-start-process (expand-file-name "~/bin/kmonad") "kmonad" (expand-file-name "~/kmonad-tvs.kbd"))
(my-start-process (expand-file-name "~/bin/kmonad") "kmonad" (expand-file-name "~/kmonad-legion.kbd"))
2021-07-30 09:13:20 +00:00
(my-start-process "transmission-gtk")
(my-start-process "gajim")
(my-start-process "/usr/lib/notification-daemon/notification-daemon")
2021-07-30 02:32:15 +00:00
#+END_SRC
2021-07-31 14:58:56 +00:00
** volume
2021-07-31 14:58:56 +00:00
#+BEGIN_SRC emacs-lisp
(use-package volume
:ensure t
2021-07-31 14:58:56 +00:00
:bind
(:map volume-mode-map
("c" . volume-raise)
("r" . volume-lower)
("C-c" . volume-raise-10)
("C-r" . volume-lower-10)))
#+END_SRC
2022-01-16 07:20:06 +00:00
* Emacs-wide settings and Emacs-specific packages
2022-01-14 07:36:20 +00:00
:PROPERTIES:
:CUSTOM_ID: emacs-settings
:END:
#+BEGIN_SRC emacs-lisp
(use-package emacs
:config
(setq gc-cons-threshold 100000000
delete-by-moving-to-trash t
trash-directory "~/.trash/"
history-length 10000
use-file-dialog nil
load-prefer-newer t
;; disable the disabled commands behavior
disabled-command-function nil
custom-file "~/.emacs.d/custom.el"
edebug-print-length nil
2022-01-14 11:11:12 +00:00
ispell-dictionary "en"
scroll-conservatively 10000
scroll-preserve-screen-position t
2022-01-16 07:20:06 +00:00
auto-window-vscroll nil
locale-coding-system 'utf-8
file-name-coding-system 'utf-8
buffer-file-coding-system 'utf-8)
(set-terminal-coding-system 'utf-8)
(set-keyboard-coding-system 'utf-8)
(set-selection-coding-system 'utf-8)
(prefer-coding-system 'utf-8)
2022-01-14 07:36:20 +00:00
(setq-default undo-limit (* 80 1000))
(load custom-file)
:bind
("M-h" . default-indent-new-line) ;; QWERTY M-j ;; see also org-mode
("M-'" . fill-paragraph) ;; QWERTY M-q
("C-j" . ctl-x-map) ;; QWERTY C-c
("M-n M-n" . font-lock-fontify-block)
;; basic Modifier-based editing commands
;; "C-d" 'backward-delete-char ;; unnecessary - QWERTY C-h is merely next to your index finger, but Dvorak C-h is directly under it
("C-," . backward-kill-word) ;; QWERTY C-w
;; ;; Emacs-like
2022-01-16 08:32:15 +00:00
("M-e" . kill-word) ;; QWERTY M-d
("C-e" . delete-char) ;; QWERTY C-d
("M-u" . forward-word) ;; QWERTY M-f
("C-." . end-of-line) ;; QWERTY C-e
;; new
("C-h" . backward-delete-char) ;; Dvorak C-h = QWERTY C-j (an improvement)
("C-c RET" . #'consult-mark) ;; c m/c RET with boon-c-god
("C-c S-RET" . #'consult-global-mark) ;; c M/c S-RET with boon-c-god
2022-01-16 08:32:15 +00:00
;; for swapped parenthesis and square brackets layout
("C-)" . abort-recursive-edit)
(:map text-mode-map ("M-." . forward-sentence))
;; ;; The old C-n/C-p/M-n/M-p were not the most comfortable to begin with, so I take this opportunity to bind them to something consistent with Boon
(:map minibuffer-local-map
("C-c" . previous-line)
("C-r" . next-line)
("M-c" . previous-history-element)
("M-r" . next-history-element)
("M-p" . previous-matching-history-element))
(:map read-expression-map ;; not sure if this works
("C-c" . previous-line)
("C-r" . next-line)
("M-c" . previous-history-element)
("M-r" . next-history-element)))
2022-01-14 07:36:20 +00:00
#+END_SRC
2022-01-16 07:20:06 +00:00
** package.el :package:
2022-01-14 11:11:12 +00:00
#+BEGIN_SRC emacs-lisp
(use-package package
:bind
(:map package-menu-mode-map
("k" . package-autoremove)
("c" . previous-line)
("r" . next-line)
("X" . package-menu-execute)))
2022-01-14 11:11:12 +00:00
#+END_SRC
2022-01-16 07:39:58 +00:00
** feather :package:
2022-01-14 11:11:12 +00:00
#+BEGIN_SRC emacs-lisp
(use-package feather
:ensure t
2022-01-14 11:11:12 +00:00
:diminish
:hook (package-menu-mode . feather-mode)
:bind ("<f5> p " . list-packages))
#+END_SRC
** esup, the Emacs StartUp Profiler
#+BEGIN_SRC emacs-lisp
(use-package esup
:ensure t
2022-01-14 11:11:12 +00:00
:config (setq esup-depth 0))
#+END_SRC
2022-01-14 07:36:20 +00:00
** gnutls
#+BEGIN_SRC emacs-lisp
(use-package gnutls
:config
;; https://debbugs.gnu.org/cgi/bugreport.cgi?bug=36749
(setq gnutls-algorithm-priority "NORMAL:-VERS-TLS1.3"))
#+END_SRC
2022-01-16 07:39:58 +00:00
** help-mode :viewer:
2022-01-14 11:11:12 +00:00
#+BEGIN_SRC emacs-lisp
(use-package help-mode
:bind
(:map help-mode-map
("b" . help-go-back)
("f" . help-go-forward)))
#+END_SRC
2022-01-15 07:27:22 +00:00
2022-01-16 07:39:58 +00:00
** helpful :viewer:
2022-01-14 11:11:12 +00:00
#+BEGIN_SRC emacs-lisp
(use-package helpful
:ensure t
2022-01-14 11:11:12 +00:00
:bind (("<f1> <f1>" . #'helpful-at-point)
("<f1> f" . #'helpful-callable)
("<f1> c" . #'helpful-command)
("<f1> k" . #'helpful-key)
("<f1> v" . #'helpful-variable)))
#+END_SRC
2022-01-15 07:27:22 +00:00
2022-01-16 07:20:06 +00:00
** keyfreq :disabled:
#+BEGIN_SRC emacs-lisp
(use-package keyfreq
:init
(keyfreq-mode 1)
(keyfreq-autosave-mode 1))
2022-01-18 19:47:59 +00:00
#+END_SRC
#+BEGIN_SRC emacs-lisp
2022-01-16 07:20:06 +00:00
;; ;; disabled on 2017-08-18T19:39:21+0530, no longer interested
;; (open-dribble-file (concat "~/.emacs.d/keylogs/"
;; (format-time-string "%Y%m%d-%H%M%S")
;; ".txt"))
;; 2017-10-14T15:22:56+0530 - I suspect devanagari-itrans tires the
;; left hand faster than the right - let's find out!
;; ;; 2020-08-05T16:28:07+0530 commented out, no longer interested
;; (add-hook
;; 'input-method-activate-hook
;; (lambda ()
;; (open-dribble-file
;; (concat
;; "~/.emacs.d/keylogs/"
;; (format-time-string "%Y%m%d-%H%M%S")
;; "-"
;; current-input-method
;; ".txt"))))
;; (add-hook
;; 'input-method-deactivate-hook
;; (lambda () (open-dribble-file nil)))
#+END_SRC
2022-01-15 12:04:00 +00:00
* User interface
:PROPERTIES:
:CUSTOM_ID: ui
:END:
#+BEGIN_SRC emacs-lisp
2022-01-06 05:49:40 +00:00
;; Simplify the GUI, thanks
;; http://www.masteringemacs.org/articles/2010/10/04/beginners-guide-to-emacs/
;; (menu-bar-mode -1)
(tool-bar-mode -1)
(scroll-bar-mode -1)
(horizontal-scroll-bar-mode -1)
(display-time-mode t)
(setq focus-follows-mouse t
mouse-autoselect-window t
display-time-format "%a, %d %h %Y %T"
display-time-interval 1
use-dialog-box nil)
;; Highlight current line
(global-hl-line-mode 1)
(defalias 'yes-or-no-p 'y-or-n-p)
2022-01-06 05:55:50 +00:00
#+END_SRC
2022-01-06 05:49:40 +00:00
2022-01-16 07:20:06 +00:00
** time
:PROPERTIES:
:CREATED: 2022-01-16T12:47:09+0530
:END:
#+BEGIN_SRC emacs-lisp
(use-package time
:config
(setq display-time-next-load-average t)
(add-to-list 'zoneinfo-style-world-list '("Europe/Berlin" "Berlin")))
#+END_SRC
2022-01-06 05:55:50 +00:00
** shackle
:PROPERTIES:
:CUSTOM_ID: ui-shackle
:END:
2022-01-06 05:55:50 +00:00
#+BEGIN_SRC emacs-lisp
2022-01-06 05:49:40 +00:00
(use-package shackle
:ensure t
2022-01-06 05:49:40 +00:00
:init (shackle-mode)
:config (setq shackle-rules '((Info-mode :same t))))
2022-01-06 05:55:50 +00:00
#+END_SRC
2022-01-06 05:49:40 +00:00
2022-01-06 05:55:50 +00:00
** moody
:PROPERTIES:
:CUSTOM_ID: ui-moody
:END:
2022-01-06 05:55:50 +00:00
#+BEGIN_SRC emacs-lisp
2022-01-06 05:49:40 +00:00
;; nicked from https://github.com/tarsius/moody
;; (use-package solarized-theme
;; :config
;; (load-theme 'solarized-light t)
;; (let ((line (face-attribute 'mode-line :underline)))
;; (set-face-attribute 'mode-line nil :overline line)
;; (set-face-attribute 'mode-line-inactive nil :overline line)
;; (set-face-attribute 'mode-line-inactive nil :underline line)
;; (set-face-attribute 'mode-line nil :box nil)
;; (set-face-attribute 'mode-line-inactive nil :box nil)
;; (set-face-attribute 'mode-line-inactive nil :background "#f9f2d9")))
(use-package moody
:ensure t
2022-01-06 05:49:40 +00:00
:config
(setq x-underline-at-descent-line t)
(moody-replace-mode-line-buffer-identification)
(moody-replace-vc-mode))
2022-01-06 05:55:50 +00:00
#+END_SRC
2022-01-06 05:49:40 +00:00
2022-01-14 07:36:20 +00:00
** Theme
:PROPERTIES:
:CUSTOM_ID: ui-theme
:END:
2022-01-14 07:36:20 +00:00
Must put this after loading the custom file, or I get prompted about the theme each time.
#+BEGIN_SRC emacs-lisp
(require 'doom-themes)
#+END_SRC
#+BEGIN_SRC emacs-lisp :load no :tangle no
(load-theme 'doom-acario-dark)
;; Similar to doom-acario-dark, with paler colors. But Org headlines are all much too similar for my liking.
(load-theme 'doom-material)
#+END_SRC
#+BEGIN_SRC emacs-lisp
(load-theme 'doom-molokai)
#+END_SRC
2022-01-06 05:55:50 +00:00
#+BEGIN_SRC emacs-lisp
2022-01-06 05:49:40 +00:00
;(load-theme 'distinguished t)
;(require 'github-theme)
;(require 'heroku-theme)
;;;; Good theme but uses different font sizes in org-mode, and (I think) some weird non-monospace font
;; (require 'monokai-theme)
;; ;; disabled on 2021-02-11T19:58:37+0530 - was coloring Org source blocks as comments? :\
;; (require 'molokai-theme)
;; (enable-theme 'molokai)
;; (require 'fullscreen-mode)
;; (fullscreen-mode 1)
;; (require 'relative-line-numbers)
;; ;; old
;; ;; (setq relative-line-numbers-motion-function 'vertical-motion)
;; ;; new
;; (setq relative-line-numbers-motion-function 'forward-visible-line)
;; (global-relative-line-numbers-mode 1)
2022-01-06 05:49:40 +00:00
;; (add-hook 'shell-mode-hook 'previous-buffer)
;; ;; is this what deletes windows when you run a shell command?
;; (add-hook 'shell-mode-hook 'delete-other-windows)
2022-01-06 05:49:40 +00:00
;; 2018-08-26T22:39:09+0530
(defun cp/change-split ()
"Switch between two windows in horizontal layout and vice-versa."
(interactive)
(let (()))
;; if height of window > width, we're in a vertical split
;; otherwise we're in a horizontal split
)
#+END_SRC
2022-01-06 07:32:53 +00:00
2022-01-14 13:57:10 +00:00
** powerline
#+BEGIN_SRC emacs-lisp
(use-package powerline
:ensure t)
2022-01-14 11:11:12 +00:00
#+END_SRC
**
#+BEGIN_SRC emacs-lisp
(autoload 'byte-recompile-file "bytecomp" "byte-recompile-file" t)
;; (2017-12-29T13:21:57+0530
;; TODO - watch Org and MD files and recompile it if they are newer
;; than their associated HTML files (e.g. I edited the source on a
;; phone and synced it back to the laptop)
;; see (info "(elisp) File Notifications")
;; and (describe-function 'file-newer-than-file-p)
;; )
#+END_SRC
**
#+BEGIN_SRC emacs-lisp
(defun cp/after-save ()
(let* ((file-path (buffer-file-name))
(file-path-shell (shell-quote-argument file-path)))
(cl-case major-mode
;; ;; This would be more useful if it was only displayed when
;; ;; tests failed. But even a constantly failing test result
;; ;; being shown each time you save can be annoying.
;; ('emacs-lisp-mode (let ((project-dir (locate-dominating-file file-path "Cask")))
;; (when project-dir
;; (cd project-dir)
;; (compile "cask exec buttercup -L . --traceback pretty"))))
;; ;; Handy as long as my only means of viewing Org data on mobile was the HTML export; not so much since I have Orgzly
;; ('org-mode
;; (pcase (file-name-nondirectory
;; (buffer-file-name
;; (current-buffer)))
;; ((or "chronometrist.org" "chronometrist-key-values.org" "init.org") t)
;; (_ (org-html-export-to-html))))
('LilyPond-mode
(my-compile-project "mkly" nil "./mkly dev"))
('latex-mode
(if (file-exists-p "Makefile")
(compile (car compile-history))
(compile (concat "xelatex " file-path-shell))))
;; ('markdown-mode (markdown-export))
('c-mode
(compile (concat "gcc -static -o "
(shell-quote-argument
(file-name-base))
" "
file-path-shell))))))
(add-hook 'after-save-hook 'cp/after-save)
#+END_SRC
** compile
#+BEGIN_SRC emacs-lisp
(use-package compile
:config
;; (add-hook 'compilation-start-hook
2022-01-16 07:20:06 +00:00
;; (lambda (proc) (delete-other-windows)))
2022-01-14 11:11:12 +00:00
(setq compilation-always-kill t))
#+END_SRC
2022-01-16 07:20:06 +00:00
*** my-compile-project
:PROPERTIES:
:CREATED: 2022-01-16T12:44:33+0530
:END:
#+BEGIN_SRC emacs-lisp
(defun my-compile-project (file &optional prefix cmd)
"Enter ancestor directory containing FILE and run compile command CMD.
If CMD is not supplied, use `compile-command'.
With PREFIX argument and omitted CMD, prompt for command."
(interactive "fDominating File: \nP")
(when-let ((dir (locate-dominating-file default-directory file)))
(cd dir))
(compile
(cond (prefix
(compilation-read-command
(or cmd "")))
(cmd cmd)
(t compile-command)))
;; (select-window (split-window-below))
;; (switch-to-buffer (compilation-find-buffer))
(boon-mode))
#+END_SRC
2022-01-14 11:11:12 +00:00
*** jump to Org LP from compilation output
:PROPERTIES:
:CUSTOM_ID: compile-org-lp-jump
:END:
#+BEGIN_SRC emacs-lisp
(defun my-org-lp-goto-error (oldfn &optional prefix &rest args)
"Make `compile-goto-error' lead to an Org literate program, if present.
This is meant to be used as `:around' advice for `compile-goto-error'.
OLDFN is `compile-goto-error'.
With PREFIX arg, just run `compile-goto-error' as though unadvised.
ARGS are ignored."
(interactive "P")
(if prefix
(funcall oldfn)
(let (buffer position column tangled-file-exists-p)
(save-window-excursion
(funcall oldfn)
(setq column (- (point) (point-at-bol)))
;; `compile-goto-error' might be called from the output of
;; `literate-elisp-byte-compile-file', which means
;; `org-babel-tangle-jump-to-org' would error
(when (ignore-errors (org-babel-tangle-jump-to-org))
(setq buffer (current-buffer)
position (point)
tangled-file-exists-p t)))
;; back to where we started - the `compilation-mode' buffer
(if tangled-file-exists-p
(let ((org-window (get-buffer-window buffer)))
;; if the Org buffer is visible, switch to its window
(if (window-live-p org-window)
(select-window org-window)
(switch-to-buffer buffer))
(goto-char (+ position column)))
(funcall oldfn)))))
(advice-add 'compile-goto-error :around #'my-org-lp-goto-error)
;; (advice-remove 'compile-goto-error #'my-org-lp-goto-error)
#+END_SRC
**
#+BEGIN_SRC emacs-lisp
2022-01-23 18:57:56 +00:00
(add-to-list 'load-path "~/.emacs.d/contrapunctus/")
2022-01-14 11:11:12 +00:00
(require 'cp-hindi)
#+END_SRC
2022-01-16 07:20:06 +00:00
** TODO Hydra [0%]
2022-01-15 12:04:00 +00:00
I started off using Hydra for programming modes, when I noticed that Elisp, Common Lisp, and Scheme all had some semantically-analogous operations with different names, which could be abstracted away behind a generic interface. Then, around the time I got into using Org for literate programs, I added an Org hydra, and then a general hydra for frequently-used operations.
Add these common operations to the hydra -
1. [X] =enlarge-window=, =enlarge-window-horizontally=
2. [X] =save-buffer=, =kill-buffer=
3. [ ] switch to last buffer, such that pressing it twice brings you back to the original buffer. Bind to "m" (same key as the one to launch the Hydra), moving magit to "M".
* Trickier to implement than I thought.
4. [X] =toggle-debug-on-error=
5. [X] "insert" hydra, for timestamps, dates; in Elisp, insert as strings; in Org, in angular brackets; etc
6. [X] remove duplication
#+BEGIN_SRC emacs-lisp
2022-01-15 12:04:00 +00:00
(use-package hydra
:ensure t
2022-01-15 12:04:00 +00:00
:commands defhydra)
#+END_SRC
2021-02-18 09:31:40 +00:00
2022-01-15 12:04:00 +00:00
*** common hydra heads
2021-07-25 15:10:18 +00:00
#+BEGIN_SRC emacs-lisp
2022-01-15 12:04:00 +00:00
(defvar my-hydra-common-heads
'(("0" delete-window "delete this" :color red)
("1" delete-other-windows "delete others" :color red)
("2" split-window-below "split below" :color red)
("3" split-window-right "split right" :color red)
("]" text-scale-increase "zoom in" :color red)
("[" text-scale-decrease "zoom out" :color red)
("\\" (text-scale-increase 0) "zoom reset" :color red)
2022-01-15 12:04:00 +00:00
("a" my-app-hydra/body "applications")
("z" my-app-hydra/body "applications")
("C" contrapunctus-mc-hydra/body "multiple cursors")
("d" dired-jump "dired-jump")
("D" (cp-insert-timestamp t) "date")
("f" my-search-hydra/body "find")
("i" (find-file "~/.emacs.d/init.org") "open init")
("I" contrapunctus-info-hydra/body "Info")
("k" (kill-buffer (current-buffer)) "kill" :color red)
("m" my-buffer-switch "Switch buffers")
("N" contrapunctus-line-display-hydra/body "line display")
2022-01-21 16:17:32 +00:00
("o" save-buffer "save") ;; QWERTY s
("s" save-buffer "save")
("n" imenus "imenus")
2022-01-15 12:04:00 +00:00
("S" imenu-list "sidebar")
("T" cp-insert-timestamp "timestamp")
("u" find-file "new")
("U" launch-file "launch-file")
2022-01-18 19:58:26 +00:00
("V" volume "volume")
2022-01-15 12:04:00 +00:00
("C-v" find-alternate-file "revert")
("w" contrapunctus-window-hydra/body "window")))
(defmacro my-defhydra (name body docstring &rest unique-forms)
(declare (indent defun))
`(defhydra ,name ,body
,docstring
,@unique-forms
,@my-hydra-common-heads))
2021-07-25 15:10:18 +00:00
#+END_SRC
2022-01-15 12:04:00 +00:00
*** Line display
2022-01-14 10:57:23 +00:00
#+BEGIN_SRC emacs-lisp
2022-01-15 12:04:00 +00:00
(defhydra contrapunctus-line-display-hydra (:color red)
"Line display"
("a" adaptive-wrap-prefix-mode "adaptive-prefix-wrap")
("c" visual-fill-column-mode "visual-fill-column")
("k" visual-line-mode "visual-line")
("o" org-indent-mode "org-indent-mode")
("t" toggle-truncate-lines "truncate"))
2022-01-14 10:57:23 +00:00
#+END_SRC
2022-01-15 12:04:00 +00:00
*** Window
2022-01-14 11:11:12 +00:00
#+BEGIN_SRC emacs-lisp
2022-01-15 12:04:00 +00:00
(defhydra contrapunctus-window-hydra (:color red)
"Window"
("e" delete-window "delete this") ;; QWERTY d
("o" delete-other-windows "delete others")
("z" delete-window "delete this")
("v" delete-other-windows "delete others")
("t" split-window-below "split below")
("n" split-window-right "split right")
("c" enlarge-window "increase height")
("r" shrink-window "decrease height")
("h" enlarge-window-horizontally "increase width")
("s" shrink-window-horizontally "decrease width")
("b" balance-windows "balance"))
2022-01-14 11:11:12 +00:00
#+END_SRC
2022-01-15 12:04:00 +00:00
*** multiple cursors
#+BEGIN_SRC emacs-lisp
2022-01-15 12:04:00 +00:00
(defhydra contrapunctus-mc-hydra (:color red :hint none)
"
_a_: previous word ^^^^ _h_: previous whole symbol
_,_: all words ^_i_: insert letters^ _c_: all symbols
_._: words in defun ^_d_: insert numbers^ _r_: symbols in defun
_u_: next word ^_l_: edit lines^ _s_: next whole symbol
"
("l" mc/edit-lines)
2022-01-15 12:04:00 +00:00
("a" mc/mark-previous-word-like-this)
("," mc/mark-all-words-like-this)
("." mc/mark-all-words-like-this-in-defun)
("u" mc/mark-next-word-like-this)
;; ("a" mc/mark-previous-like-this-word "previous word")
;; ("u" mc/mark-next-like-this-word "next word")
("h" mc/mark-previous-symbol-like-this)
("c" mc/mark-all-symbols-like-this)
("r" mc/mark-all-symbols-like-this-in-defun)
("s" mc/mark-next-symbol-like-this)
;; ("s" mc/mark-previous-like-this-symbol "previous symbol")
;; ("h" mc/mark-next-like-this-symbol "next symbol")
("d" mc/insert-numbers)
("i" mc/insert-letters))
#+END_SRC
2022-01-18 19:58:13 +00:00
2022-01-15 12:04:00 +00:00
*** info
#+BEGIN_SRC emacs-lisp
(defhydra contrapunctus-info-hydra (:color blue)
"Info"
("i" info "info")
("a" info-apropos "apropos")
("E" (info "(emacs)") "Emacs")
("e" (info "(elisp)") "Elisp")
("c" (info "(cl)") "CL-Lib")
("l" (info "(lilypond-notation)") "Lilypond notation")
("L" (info "(lilypond-learning)") "Lilypond learning")
("o" (info "(org)") "Org")
("g" (info "(guile)") "Guile")
("t" (info "(texinfo)") "Texinfo"))
#+END_SRC
2022-01-18 19:58:13 +00:00
2022-01-15 12:04:00 +00:00
*** Help
#+BEGIN_SRC emacs-lisp
(defhydra my-help-hydra (:color blue)
"Help"
("l" find-library "library")
("v" helpful-variable "variable")
("f" helpful-callable "function")
("k" helpful-key "key")
("h" helpful-at-point "here")
("m" man "man page")
("c" describe-char "character"))
#+END_SRC
2022-01-18 19:58:13 +00:00
2022-01-15 12:04:00 +00:00
*** Search
#+BEGIN_SRC emacs-lisp
(defhydra my-search-hydra (:color blue)
"Search command:"
("f" find-dired "find-dired")
("g" grep "grep")
("r" rgrep "rgrep")
("a" ag "ag")
("h" find-grep "find-grep"))
#+END_SRC
2022-01-15 12:04:00 +00:00
*** General
#+BEGIN_SRC emacs-lisp
(my-defhydra my-general-hydra (:color blue)
2022-01-15 12:04:00 +00:00
"What command?"
("b" (my-compile-project "Makefile") "compile")
("B" (my-compile-project "Makefile" t) "compile (prompt)")
("h" my-help-hydra/body "Help")
("E" toggle-debug-on-error "tdoe")
("Q" toggle-debug-on-quit "tdoq"))
#+END_SRC
2022-01-15 12:04:00 +00:00
*** applications
#+BEGIN_SRC emacs-lisp
(defhydra my-app-hydra (:color blue)
"What application?"
;; built-in
("c" chronometrist "chronometrist")
2022-02-09 16:32:11 +00:00
("e" contrapunctus-emms-hydra/body "emms")
2022-01-15 12:04:00 +00:00
("i" sxiv "sxiv")
("l" proced "list processes")
2022-02-08 07:53:03 +00:00
("m" mu4e "mu4e")
("v" magit-status "magit")
2022-01-15 12:04:00 +00:00
("p" list-packages "packages")
("j" (my-start-app-or-switch
"java" nil nil "josm"
"-jar" (expand-file-name "~/josm-tested.jar"))
"JOSM")
;; less-used
("J" my-jabber-hydra/body "Jabber")
2022-02-09 16:32:11 +00:00
("E" elpher "elpher")
2022-01-15 12:04:00 +00:00
;; external
("g" (my-start-app-or-switch "gajim" nil "^Gajim$") "Gajim")
("b" (my-start-app-or-switch
"/media/data/anon/ext/tor-browser_en-US/Browser/start-tor-browser"
"^Tor Browser$")
"Tor Browser")
("B" (my-start-app-or-switch
"/media/data/anon/ext/firefox/firefox" "firefox")
"Firefox")
("k" (my-start-app-or-switch "keepassxc") "KeePassXC")
("t" (my-start-app-or-switch "xfce4-terminal") "terminal")
("T" (my-start-app-or-switch "transmission-gtk") "bittorrent")
("s" (my-start-app-or-switch "xfce4-screenshooter") "screenshot")
("q" (my-start-app-or-switch "qtractor") "Qtractor")
("w" my-eww "eww"))
#+END_SRC
2022-01-18 19:58:13 +00:00
2022-01-15 12:04:00 +00:00
*** org
#+BEGIN_SRC emacs-lisp
(defun my-compile-org-lp (&optional prefix)
(interactive)
2022-01-15 12:04:00 +00:00
(my-compile-project "Makefile" prefix))
2022-01-15 12:04:00 +00:00
(defhydra my-literate-elisp-hydra (:color blue)
"Literate Elisp"
("l" (literate-elisp-load (buffer-file-name)) "load")
("b" (literate-elisp-byte-compile-file (buffer-file-name)) "byte-compile"))
2022-01-15 12:04:00 +00:00
(my-defhydra my-org-hydra (:color blue)
"Org"
("L" my-literate-elisp-hydra/body "literate-elisp")
("p" org-set-property "property")
("l" my-org-hydra-block/body "source block")
("t" my-org-set-tags "tags")
2022-01-15 12:04:00 +00:00
("C-t" org-todo "todo" :color red)
2022-01-18 19:58:26 +00:00
("v" my-org-hydra-nav/body "navigation")
2022-01-15 12:04:00 +00:00
("b" (my-compile-org-lp) "compile")
("B" (my-compile-org-lp t) "compile (prompt)")
("C-b" contrapunctus-async-tangle "babel-tangle")
("e" my-org-eval-hydra/body "eval")
2022-01-15 12:04:00 +00:00
("h" my-help-hydra/body "Help")
("E" toggle-debug-on-error "tdoe")
("Q" toggle-debug-on-quit "tdoq"))
#+END_SRC
2022-01-15 12:04:00 +00:00
**** eval
#+BEGIN_SRC emacs-lisp
(defhydra my-org-eval-hydra (:color blue)
"Eval"
("e" org-babel-execute-src-block "eval block"))
#+END_SRC
2022-01-15 12:04:00 +00:00
**** org block
#+BEGIN_SRC emacs-lisp
(defhydra my-org-hydra-block (:color blue)
"Org block"
("l" (my-org-insert-block "SRC" nil) "Source (current language)")
("L" (my-org-insert-block "SRC" nil nil t) "Source (prompt)")
("t" (my-org-insert-block "SRC" nil ":tangle test :load test") "Source test")
("e" (my-org-insert-block "SRC" nil ":tangle no :load no") "Source example")
("o" (my-org-insert-block "QUOTE") "quote")
("v" (my-org-insert-block "VERSE") "verse"))
2022-01-15 12:04:00 +00:00
#+END_SRC
2022-01-15 12:04:00 +00:00
**** org navigation
#+BEGIN_SRC emacs-lisp
(defhydra my-org-hydra-nav (:color red)
"Navigation"
;; movement
("c" org-previous-visible-heading "previous heading")
("r" org-next-visible-heading "next heading")
("h" outline-up-heading "up heading")
("t" org-backward-heading-same-level "backward heading")
("n" org-forward-heading-same-level "forward heading")
;; folding
("k" outline-show-branches "branches")
("<tab>" org-cycle "cycle")
2022-01-27 17:56:03 +00:00
("<C-tab>" org-global-cycle "global cycle")
2022-01-15 12:04:00 +00:00
;; modification
("C" org-metaup "drag backward")
("R" org-metadown "drag forward")
("H" org-metaleft "promote")
("S" org-metaright "demote"))
#+END_SRC
2022-01-15 12:04:00 +00:00
*** jabber
#+BEGIN_SRC emacs-lisp
(my-defhydra my-jabber-hydra (:color blue)
"Jabber"
("c" jabber-connect "connect")
("r" jabber-display-roster "roster")
("n" jabber-activity-switch-to "next" :color red)
2022-01-15 12:04:00 +00:00
("E" toggle-debug-on-error "tdoe")
("Q" toggle-debug-on-quit "tdoq"))
#+END_SRC
2022-01-15 12:04:00 +00:00
*** Emacs Lisp
#+BEGIN_SRC emacs-lisp
(my-defhydra my-elisp-hydra (:color blue)
"Emacs Lisp"
("c" my-elisp-bytecomp-hydra/body "byte compile")
("b" my-compile-org-lp "compile")
("B" (my-compile-org-lp t) "compile (prompt)")
("C-b" contrapunctus-async-tangle "babel-tangle")
("e" my-elisp-hydra-eval/body "Eval")
("E" my-elisp-hydra-debug/body "Debug")
("h" my-help-hydra/body "Help")
("j" xref-find-definitions "Jump to definition")
("J" org-babel-tangle-jump-to-org "Jump to definition (Org)")
("r" ielm "REPL")
("t" contrapunctus-el-test/body "Test")
("L" my-literate-elisp-hydra/body "literate-elisp"))
#+END_SRC
2022-01-15 12:04:00 +00:00
**** eval
#+BEGIN_SRC emacs-lisp
(defhydra my-elisp-hydra-eval (:color blue)
("b" eval-buffer "buffer")
("e" eval-defun "defun")
("l" eval-last-sexp "last sexp"))
#+END_SRC
2022-01-15 12:04:00 +00:00
**** unit testing
2022-01-14 11:11:12 +00:00
#+BEGIN_SRC emacs-lisp
2022-01-15 12:04:00 +00:00
(defhydra contrapunctus-el-test (:color blue)
("e" (my-compile-project "Cask" "cask exec buttercup -L . --traceback pretty") "buttercup")
("r" ert "ert"))
2022-01-14 11:11:12 +00:00
#+END_SRC
2022-01-15 12:04:00 +00:00
**** debug
2022-01-14 07:36:20 +00:00
#+BEGIN_SRC emacs-lisp
2022-01-15 12:04:00 +00:00
(defhydra my-elisp-hydra-debug (:color blue)
"Debug"
("e" (funcall-interactively #'eval-defun t) "edebug")
("o" toggle-debug-on-error "tdoe")
("u" toggle-debug-on-quit "tdoq"))
2022-01-14 07:36:20 +00:00
#+END_SRC
2022-01-15 12:04:00 +00:00
**** byte-compile
#+BEGIN_SRC emacs-lisp
2022-01-15 12:04:00 +00:00
(defhydra my-elisp-bytecomp-hydra (:color blue)
"Byte compile"
("d" byte-recompile-directory "directory")
("c" (byte-compile-file (buffer-file-name)) "file")
("r" (byte-recompile-file (buffer-file-name)) "recompile")
("R" byte-force-recompile "force recompile"))
#+END_SRC
2022-01-15 12:04:00 +00:00
**** insert
:PROPERTIES:
2022-01-15 12:04:00 +00:00
:CREATED: 2022-01-05T19:45:33+0530
:END:
#+BEGIN_SRC emacs-lisp
2022-01-15 12:04:00 +00:00
(defhydra my-elisp-insert-hydra (:color blue)
"Insert"
("g" (yas-expand-snippet (yas-lookup-snippet "cl-defgeneric")) "defgeneric")
("m" (yas-expand-snippet (yas-lookup-snippet "cl-defmethod")) "defmethod"))
#+END_SRC
2022-01-15 12:04:00 +00:00
*** Common Lisp
#+BEGIN_SRC emacs-lisp
2022-01-15 12:04:00 +00:00
(my-defhydra my-cl-hydra (:color blue)
"Common Lisp"
("R" slime-connect "connect")
("h" my-cl-help-hydra/body "Documentation")
("e" my-cl-hydra-eval/body "Eval")
("E" toggle-debug-on-error "tdoe")
("Q" toggle-debug-on-quit "tdoq")
("r" slime "REPL")
("j" slime-edit-definition "Jump to definition")
("p" slime-repl-set-package "Set package"))
#+END_SRC
2022-01-18 19:58:13 +00:00
2022-01-15 12:04:00 +00:00
**** eval
#+BEGIN_SRC emacs-lisp
2022-01-15 12:04:00 +00:00
(defhydra my-cl-hydra-eval (:color blue)
"Eval (CL)"
("b" slime-eval-buffer "buffer")
("e" slime-eval-defun "defun")
("r" slime-eval-region "region")
("l" slime-eval-last-expression "last expression"))
#+END_SRC
2022-01-18 19:58:13 +00:00
2022-01-15 12:04:00 +00:00
**** help
2022-01-14 06:55:59 +00:00
#+BEGIN_SRC emacs-lisp
2022-01-15 12:04:00 +00:00
(defhydra my-cl-help-hydra (:color blue)
("s" slime-documentation "slime")
("h" slime-documentation-lookup "CLHS")
("l" find-library "library")
("v" helpful-variable "variable")
("f" helpful-function "function")
("k" helpful-key "key")
("m" man "man page"))
#+END_SRC
2022-01-18 19:58:13 +00:00
2022-01-15 12:04:00 +00:00
*** Scheme
**** eval
#+BEGIN_SRC emacs-lisp
(defhydra cp-scm-eval (:color blue)
("b" geiser-eval-buffer "buffer")
("e" geiser-eval-definition "defun")
("l" geiser-eval-last-sexp "last sexp")
("E" toggle-debug-on-error "tdoe")
("Q" toggle-debug-on-quit "tdoq"))
2022-01-14 06:55:59 +00:00
#+END_SRC
2022-01-18 19:58:13 +00:00
2022-01-15 12:04:00 +00:00
**** CHICKEN Scheme
#+BEGIN_SRC emacs-lisp
(my-defhydra my-chicken-hydra (:color blue)
"CHICKEN Scheme"
("e" cp-scm-eval/body "Eval")
("r" run-chicken "REPL")
2022-01-14 06:55:59 +00:00
2022-01-15 12:04:00 +00:00
("h" my-help-hydra/body "Help")
("E" toggle-debug-on-error "tdoe")
("Q" toggle-debug-on-quit "tdoq"))
#+END_SRC
**** Guile
#+BEGIN_SRC emacs-lisp
2022-01-15 12:04:00 +00:00
(my-defhydra cp-guile (:color blue)
"Guile"
("e" cp-scm-eval/body "Eval")
("r" run-guile "REPL")
("h" my-help-hydra/body "Help")
("E" toggle-debug-on-error "tdoe")
("Q" toggle-debug-on-quit "tdoq"))
#+END_SRC
2022-01-15 12:04:00 +00:00
*** Lilypond
2022-01-14 11:11:12 +00:00
#+BEGIN_SRC emacs-lisp
2022-01-15 12:04:00 +00:00
(defun my-compile-ly (&optional prefix)
(interactive)
(my-compile-project "main.ly" prefix "./mkly dev"))
2022-01-14 11:11:12 +00:00
2022-01-15 12:04:00 +00:00
(my-defhydra my-lilypond-hydra (:color blue)
"Lilypond"
("b" my-compile-ly "Compile")
("B" (my-compile-ly t) "Compile")
2022-01-14 11:11:12 +00:00
2022-01-15 12:04:00 +00:00
("h" my-help-hydra/body "Help")
("E" toggle-debug-on-error "tdoe")
("Q" toggle-debug-on-quit "tdoq"))
#+END_SRC
2022-01-14 11:11:12 +00:00
2022-01-15 12:04:00 +00:00
*** Prolog
#+BEGIN_SRC emacs-lisp
(my-defhydra my-prolog-hydra (:color blue)
"Prolog"
("r" ediprolog-dwim "REPL")
("E" toggle-debug-on-error "tdoe")
("Q" toggle-debug-on-quit "tdoq"))
#+END_SRC
2022-01-14 11:11:12 +00:00
2022-01-15 12:04:00 +00:00
*** Programming
Don't try to check if there are files with a certain extension...it will lead to false positives.
#+BEGIN_SRC emacs-lisp
(defun my-dispatch-hydra ()
(interactive)
(cond ((derived-mode-p 'emacs-lisp-mode
'inferior-emacs-lisp-mode
2022-01-15 19:03:31 +00:00
'debugger-mode) (my-elisp-hydra/body))
2022-01-15 12:04:00 +00:00
(;; (or (locate-dominating-file default-directory "build.scm")
;; (locate-dominating-file default-directory "main.ly"))
(derived-mode-p 'LilyPond-mode)
(my-lilypond-hydra/body))
2022-01-15 19:03:31 +00:00
((and (featurep 'geiser) (bound-and-true-p geiser-mode))
2022-01-15 12:04:00 +00:00
(if (eq 'guile geiser-scheme-implementation)
(cp-guile/body)
(my-chicken-hydra/body)))
2022-01-15 19:03:31 +00:00
((derived-mode-p 'lisp-mode
'slime-repl-mode) (my-cl-hydra/body))
((derived-mode-p 'prolog-mode) (my-prolog-hydra/body))
((derived-mode-p 'org-mode) (my-org-hydra/body))
((derived-mode-p 'sh-mode) (my-shell-hydra/body))
((derived-mode-p 'sql-mode) (my-sql-hydra/body))
2022-01-24 15:28:51 +00:00
((derived-mode-p 'comint-mode) (my-comint-hydra/body))
(t (my-general-hydra/body))))
2022-01-14 11:11:12 +00:00
2022-01-15 19:32:29 +00:00
(use-package boon
:bind (:map boon-command-map
("m" . my-dispatch-hydra)
("C-s" . my-dispatch-hydra)))
2022-01-15 12:04:00 +00:00
(global-set-key (kbd "C-s") #'my-dispatch-hydra)
#+END_SRC
2022-01-14 11:11:12 +00:00
2022-01-24 15:28:51 +00:00
*** shell script
2022-01-15 12:04:00 +00:00
#+BEGIN_SRC emacs-lisp
(my-defhydra my-shell-hydra (:color blue)
"Shell"
("e" my-shell-eval-hydra/body "eval")
("h" my-help-hydra/body "Help"))
2022-01-14 11:11:12 +00:00
2022-01-15 12:04:00 +00:00
(defhydra my-shell-eval-hydra (:color blue)
"Evaluate"
("b" org-babel-execute-src-block "source block"))
#+END_SRC
2022-01-14 11:11:12 +00:00
2022-01-16 07:20:06 +00:00
*** SQL
2022-01-15 12:04:00 +00:00
#+BEGIN_SRC emacs-lisp
(my-defhydra my-sql-hydra (:color blue)
"SQL"
("r" sql-sqlite "REPL")
("e" my-sql-eval-hydra/body "eval")
("h" my-help-hydra/body "Help"))
2022-02-06 12:09:30 +00:00
(defhydra my-sql-eval-hydra (:color blue)
"Eval"
("e" sql-send-paragraph "paragraph")
("b" sql-send-buffer "buffer"))
2022-01-14 11:11:12 +00:00
#+END_SRC
2022-01-24 15:28:51 +00:00
*** comint
#+BEGIN_SRC emacs-lisp
(my-defhydra my-comint-hydra (:color blue)
"comint"
2022-02-06 12:09:30 +00:00
("v" my-comint-nav-hydra/body "Navigation")
("h" my-help-hydra/body "Help"))
2022-01-24 15:28:51 +00:00
(defhydra my-comint-nav-hydra (:color red)
"Navigation"
("c" comint-previous-prompt "previous")
("r" comint-next-prompt "next"))
#+END_SRC
** marginalia
:PROPERTIES:
:CREATED: 2022-01-16T00:28:51+0530
2022-01-15 20:39:07 +00:00
:CUSTOM_ID: marginalia
:END:
#+BEGIN_SRC emacs-lisp
(use-package marginalia
:ensure t
:init (marginalia-mode))
#+END_SRC
2022-01-15 12:04:00 +00:00
* Searching
:PROPERTIES:
:CUSTOM_ID: search
:END:
2022-01-20 17:11:55 +00:00
** isearch
#+BEGIN_SRC emacs-lisp
(use-package isearch
:bind (:map isearch-mode-map
("C-c" . #'isearch-repeat-backward)
("C-r" . #'isearch-repeat-forward)))
#+END_SRC
2022-01-15 12:04:00 +00:00
** ag, the Silver Searcher
:PROPERTIES:
:CUSTOM_ID: ag
:END:
#+BEGIN_SRC emacs-lisp
(use-package ag
:ensure t
:bind
("<f2> p" . ag)
("<f2> P" . ag-project-regexp)
:config
(setq ag-highlight-search t))
2022-01-14 11:11:12 +00:00
#+END_SRC
2022-01-15 12:04:00 +00:00
** Swiper
:PROPERTIES:
:CUSTOM_ID: search-swiper
:END:
#+BEGIN_SRC emacs-lisp
2022-01-15 12:04:00 +00:00
(use-package swiper
:disabled t
:ensure t
:bind (("C-s" . swiper)
("C-r" . swiper-backward))
(:map swiper-map
("C-c" . previous-line)
("C-r" . next-line))
:config
2022-01-15 12:04:00 +00:00
(setq swiper-action-recenter t))
#+END_SRC
2022-01-15 12:04:00 +00:00
** wgrep
:PROPERTIES:
:CREATED: 2022-01-14T16:23:41+0530
:CUSTOM_ID: wgrep
:END:
#+BEGIN_SRC emacs-lisp
(use-package wgrep
:commands (wgrep-change-to-wgrep-mode))
#+END_SRC
2022-01-15 12:04:00 +00:00
** Recenter screen on isearch matches
#+BEGIN_SRC emacs-lisp
(add-hook 'isearch-mode-hook 'recenter)
(add-hook 'isearch-update-post-hook 'recenter)
(defadvice isearch-repeat-forward
(after isearch-repeat-forward-recenter activate) (recenter))
(defadvice isearch-repeat-backward
(after isearch-repeat-backward-recenter activate) (recenter))
(ad-activate 'isearch-repeat-forward)
(ad-activate 'isearch-repeat-backward)
(global-set-key (kbd "C-s") 'isearch-forward-regexp)
(global-set-key (kbd "C-r") 'isearch-backward-regexp)
#+END_SRC
2022-01-15 12:04:00 +00:00
**
#+BEGIN_SRC emacs-lisp
;; (if (not (server-running-p)) (server-start))
(server-start)
2022-01-11 07:47:18 +00:00
#+END_SRC
2022-01-15 12:04:00 +00:00
* Editing
2022-01-11 07:47:18 +00:00
:PROPERTIES:
2022-01-15 12:04:00 +00:00
:CREATED: 2022-01-13T20:48:58+0530
:CUSTOM_ID: editing
2022-01-11 07:47:18 +00:00
:END:
2022-01-14 13:57:10 +00:00
#+BEGIN_SRC emacs-lisp
2022-01-15 12:04:00 +00:00
(setq sentence-end-double-space nil)
2022-01-11 07:47:18 +00:00
2022-01-15 12:04:00 +00:00
(general-define-key
"C-h" 'backward-delete-char
"C-w" 'backward-kill-word
"C-u" 'cp-kill-line-0
"C-<" 'beginning-of-buffer
"C->" 'end-of-buffer)
2022-01-11 07:47:18 +00:00
2022-01-15 12:04:00 +00:00
(define-key isearch-mode-map (kbd "C-h") 'isearch-delete-char)
(defun cp-kill-line-0 ()
(interactive)
(kill-line 0))
2021-02-18 09:31:40 +00:00
2022-01-15 12:04:00 +00:00
(global-unset-key (kbd "C-x C-r"))
(general-define-key
:prefix "C-x C-r"
"C-i" 'string-insert-rectangle
"C-r" 'replace-rectangle
"C-k" 'kill-rectangle)
2022-01-15 12:04:00 +00:00
(defun cp/downcase-dwim (arg)
"Like `downcase-word', but if region is active, run
`downcase-region' instead. Unlike `downcase-region', rectangular
regions are handled correctly as well.")
2022-01-15 12:04:00 +00:00
;; open-line should always move to the beginning of the current line
;; first, so one can run it anywhere. I also want it to indent it to
;; the next or the previous line...
2022-01-10 04:34:08 +00:00
2022-01-15 12:04:00 +00:00
;; These affect org-meta-return and org-insert-heading-respect-content
;;
2022-01-10 04:34:08 +00:00
2022-01-15 12:04:00 +00:00
;; (defadvice open-line
;; (before open-line-bol activate)
;; (beginning-of-visual-line))
;; (defadvice open-line
;; (after open-line-indent activate)
;; (if (not (looking-at "\\** "))
;; (indent-for-tab-command)))
;; (global-set-key (kbd "C-o") 'open-line)
(defun cp/open-line ()
"The opposite of `cp/open-line-before'. Start a new line below
the current line, regardless of where point is in the current
line. Will not affect the content of the current line. Applies
the correct indentation according to the mode."
(interactive)
(progn
(end-of-line)
(electric-indent-just-newline t)
(indent-according-to-mode)))
(defun cp/open-line-before (arg)
"Like `open-line' but a bit more sane.
In org-mode, run org-open-line.
In other modes, insert a newline above the current line,
regardless of where point is in current line. Will not affect
content of current line. Applies the correct indentation
according to the mode."
(interactive "p")
(if (and (equal major-mode 'org-mode)
(org-at-table-p))
(org-open-line arg)
(progn
(beginning-of-line)
(electric-indent-just-newline t)
(forward-char -1)
(indent-according-to-mode))))
(global-set-key (kbd "C-o") 'cp/open-line-before)
;; I wish you could press e.g. S-o in god-mode to get C-S-o.
;; 10/10 would make life better.
(global-set-key (kbd "C-S-o") 'cp/open-line)
(setq dired-bind-jump nil)
(global-set-key (kbd "C-x C-j") 'join-line)
;; C-z (suspend-frame) is utterly useless and disruptive - good place to put universal-argument
(global-unset-key (kbd "C-z"))
(global-set-key (kbd "C-z") 'universal-argument)
(global-set-key (kbd "C-x C-z") 'repeat)
(global-set-key (kbd "C-x C-;") 'repeat-complex-command)
;; (defun cp-kill-line (&optional arg)
;; (interactive)
;; (if arg
;; (if mark-active
;; (kill-region arg)
;; (kill-line arg))
;; (if mark-active
;; (kill-region)
;; (kill-line))))
;; (global-set-key (kbd "C-k") 'cp-kill-line)
;; Chris Done (god-mode) recommends this, but Emacs' repeat command is almost useless...
;; (global-set-key (kbd "C-.") 'repeat)
(defun cp/delete-trailing-whitespace ()
(unless (derived-mode-p 'markdown-mode)
(delete-trailing-whitespace)))
(add-hook 'before-save-hook 'cp/delete-trailing-whitespace)
;; BUG - (dired-get-marked-files) returns file name at point if none are marked
;; BUG - (dired-get-marked-files) always returns an alphabetically-sorted list, even when the Dired buffer is sorted by date
(defun cp/marked-files->markup-links ()
"From a Dired buffer, insert the file at point or marked files
as links into an Org or Markdown document."
(interactive)
(if (derived-mode-p 'dired-mode)
(let* ((filenames (dired-get-marked-files 'no-dir))
(other-buffer (->> (window-list)
(cadr)
(window-buffer)))
(other-buffer-mode (with-current-buffer other-buffer major-mode))
(two-window-op (and (= (length (window-list)) 2)
(member other-buffer-mode
'(org-mode markdown-mode))))
(output-buffer (if two-window-op
other-buffer
(read-buffer "Insert links in buffer: ")))
(output-mode (with-current-buffer output-buffer major-mode))
(output-text (cl-case output-mode
('org-mode
(cp/marked-files->markup-links-org filenames))
('markdown-mode
(cp/marked-files->markup-links-md filenames))
(t (error "Only Markdown and Org are currently supported.")))))
(if two-window-op
(other-window 1)
(switch-to-buffer output-buffer))
(mapc #'insert output-text))
(user-error "Run this command from a Dired buffer with some marked files."))
(when markdown-inline-image-overlays
(markdown-display-inline-images)))
#+END_SRC
2022-01-16 07:20:06 +00:00
#+BEGIN_SRC emacs-lisp
(defun cp-insert-timestamp (&optional date-only-p)
"Insert current date and time in ISO-8601 format in the current buffer."
(interactive)
(let ((timestamp (format-time-string
(if date-only-p "%F" "%FT%T%z"))))
(cond ((derived-mode-p 'emacs-lisp-mode)
(insert "\"" timestamp "\""))
(t (insert timestamp)))))
#+END_SRC
2022-01-16 08:35:47 +00:00
** text-mode
:PROPERTIES:
:CREATED: 2022-01-16T14:02:56+0530
:END:
#+BEGIN_SRC emacs-lisp
(use-package text-mode
:bind
(:map text-mode-map
("M-c" . 'org-drag-line-backward)
("M-r" . 'org-drag-line-forward)))
#+END_SRC
2022-01-15 12:04:00 +00:00
** undo-tree
:PROPERTIES:
:CUSTOM_ID: editing-undo-tree
:END:
#+BEGIN_SRC emacs-lisp
(use-package undo-tree
:ensure t
:commands global-undo-tree-mode
:if (not (featurep 'evil))
:diminish undo-tree-mode
2022-01-19 10:01:39 +00:00
:init (global-undo-tree-mode)
:hook (wdired-mode . undo-tree-mode))
2022-01-15 12:04:00 +00:00
#+END_SRC
** ediff
:PROPERTIES:
:CUSTOM_ID: editing-ediff
:END:
#+BEGIN_SRC emacs-lisp
(use-package ediff
:config
2022-01-15 12:04:00 +00:00
(setq ediff-window-setup-function 'ediff-setup-windows-plain)
;; boon-like bindings
(add-hook 'ediff-keymap-setup-hook
(lambda ()
(define-key ediff-mode-map (kbd "c") 'ediff-previous-difference)
(define-key ediff-mode-map (kbd "r") 'ediff-next-difference))))
#+END_SRC
2022-01-15 12:04:00 +00:00
** iedit
:PROPERTIES:
:CREATED: 2022-01-13T20:51:14+0530
:CUSTOM_ID: editing-iedit
:END:
#+BEGIN_SRC emacs-lisp
2022-01-15 12:04:00 +00:00
(use-package iedit
:ensure t
:bind (("C-;" . iedit-mode)
("C-:" . iedit-mode-toggle-on-function)
(:map iedit-mode-keymap
("C-h" . backward-delete-char))))
#+END_SRC
2022-01-15 12:04:00 +00:00
** multiple cursors
:PROPERTIES:
:CREATED: 2022-01-13T20:52:14+0530
:CUSTOM_ID: editing-multiple-cursors
:END:
#+BEGIN_SRC emacs-lisp
2022-01-15 12:04:00 +00:00
(use-package multiple-cursors
:ensure t
:bind (("C-M-l" . #'mc/mark-previous-like-this-symbol)
("C-M-;" . #'mc/mark-next-like-this-symbol)
("C-M-'" . #'mc/mark-all-symbols-like-this)
("C-M-," . #'mc/mark-previous-word-like-this)
("C-M-." . #'mc/mark-next-word-like-this)
("C-M-/" . #'mc/mark-all-words-like-this)
("C-M-<" . #'mc/unmark-previous-like-this)
("C-M->" . #'mc/unmark-next-like-this)
("C-M-]" . #'mc-hide-unmatched-lines-mode)))
#+END_SRC
2022-01-15 12:04:00 +00:00
** transpose commands
:PROPERTIES:
:CREATED: 2022-01-13T20:50:03+0530
:CUSTOM_ID: editing-transpose
:END:
#+BEGIN_SRC emacs-lisp
2022-01-15 12:04:00 +00:00
(global-unset-key (kbd "C-t"))
(general-define-key
:prefix "C-t"
"C-t C-c" 'transpose-chars
"C-t C-w" 'transpose-words
"C-t C-l" 'transpose-lines
"C-t C-s" 'transpose-sentences
"C-t C-e" 'transpose-sexps
"C-t C-p" 'transpose-paragraphs)
#+END_SRC
2022-01-15 12:04:00 +00:00
** easy-kill :disabled:
:PROPERTIES:
:CUSTOM_ID: editing-easy-kill
:END:
#+BEGIN_SRC emacs-lisp
2022-01-15 12:04:00 +00:00
(use-package easy-kill
:disabled
:bind (("M-w" . easy-kill)
("M-d" . easy-kill-delete-region)))
#+END_SRC
2022-01-15 12:04:00 +00:00
** atomic-chrome
:PROPERTIES:
:CUSTOM_ID: editing-atomic-chrome
:END:
Doesn't work in my current main browser (Tor Browser), and thus barely used of late...
#+BEGIN_SRC emacs-lisp
2022-01-15 12:04:00 +00:00
(use-package atomic-chrome
:ensure t
:init (atomic-chrome-start-server)
:config
(setq atomic-chrome-url-major-mode-alist
'(("wikisource" . mediawiki-mode))))
#+END_SRC
2022-01-15 12:04:00 +00:00
** Unicode keys
#+BEGIN_SRC emacs-lisp
2022-01-15 12:04:00 +00:00
(general-auto-unbind-keys)
(general-def
:prefix "C-t"
;; currency
"r" [?₹] "- L" [?£] "L -" [?£] "e" [?€]
"." [?…]
2022-01-15 12:04:00 +00:00
"- m" [?—] "- n" [?] "m -" [?—] "n -" [?]
"t" [?™]
2022-01-15 12:04:00 +00:00
;; German
"\" a" [?ä] "a \"" [?ä] "\" A" [?Ä] "A \"" [?Ä]
"\" e" [?ë] "e \"" [?ë] "\" E" [?Ë] "E \"" [?Ë]
"\" o" [?ö] "o \"" [?ö] "\" O" [?Ö] "O \"" [?Ö]
"\" u" [?ü] "u \"" [?ü] "\" U" [?Ü] "U \"" [?Ü]
2022-01-15 12:04:00 +00:00
;; ;; " a/e/o/u are slow to type...
;; "a" [?ä] "A" [?Ä]
;; "e" [?ë] "E" [?Ë]
;; "o" [?ö] "O" [?Ö]
;; "u" [?ü] "U" [?Ü]
2022-01-15 12:04:00 +00:00
;; but "o" conflicts with "o o" for °, so...
"u a" [?ä] "u A" [?Ä]
"u e" [?ë] "u E" [?Ë]
"u o" [?ö] "u O" [?Ö]
"u u" [?ü] "u U" [?Ü]
"s s" [?ß]
2022-01-15 12:04:00 +00:00
;; French
", c" [?ç] "c ," [?ç] ", C" [?ç] "C ," [?Ç]
"' e" [?é] "e '" [?é] "' E" [?É] "E '" [?É]
"e `" [?è] "` e" [?è] "E `" [?È] "` E" [?È]
"e ^" [?ê] "^ e" [?ê] "E `" [?È] "` E" [?È]
"' a" [?á] "a '" [?á] "' A" [?Á] "A '" [?Á]
"a `" [?à] "` a" [?à] "A `" [?À] "` A" [?À]
"a ^" [?â] "^ a" [?â] "A ^" [?Â] "^ A" [?Â]
"~ n" [?ñ] "n ~" [?ñ] "~ N" [?Ñ] "N ~" [?Ñ]
2022-01-15 12:04:00 +00:00
"e e" [?ə]
2022-01-15 12:04:00 +00:00
"o e" [?œ] "O E" [?Œ]
"o o" [?°] "x" [?×]
"1 2" [?½] "1 3" [?⅓] "1 4" [?¼]
"2 3" [?⅔] "2 5" [?⅖]
"3 4" [?¾] "3 5" [?⅗]
"4 5" [?⅘]
2022-01-15 12:04:00 +00:00
"b" [?♭] "#" [?♯]
2022-01-15 12:04:00 +00:00
"< -" [?←] "- >" [?→]
"^ |" [?↑] "| ^" [?↑]
"v |" [?↓] "| v" [?↓]
", \\" [?λ] "l" [?λ]
"f" [?ƒ]
"q o" [?“] "q c" [?”])
(general-auto-unbind-keys t)
(setq default-input-method "devanagari-itrans")
#+END_SRC
2022-01-15 12:04:00 +00:00
Suggestion by lampilelo for extending =iso-transl-ctl-x-8-map= (https://dpaste.com/BAQUXSDVL.txt)
#+BEGIN_SRC emacs-lisp :tangle no
(eval-after-load 'iso-transl
'(let ((map (make-sparse-keymap)))
(define-key map (kbd "c") [?č])
(define-key map (kbd "C") [?Č])
(define-key iso-transl-ctl-x-8-map (kbd "v") map)))
#+END_SRC
2022-01-15 12:04:00 +00:00
** modal editing
*** active boon config
#+BEGIN_SRC emacs-lisp
2022-01-15 12:04:00 +00:00
(use-package boon
:ensure t
2022-01-15 12:04:00 +00:00
:commands (boon-mode)
:load-path "~/.emacs.d/elisp-git/boon"
:bind
(:map boon-command-map
("C-l" . recenter-top-bottom)
("p" . consult-line)
(". p" . my-consult-line)
(". c" . #'isearch-backward-regexp)
(". r" . #'isearch-forward-regexp)
(", r" . #'iy-go-up-to-char)
(", c" . #'iy-go-up-to-char-backward)
2022-01-16 08:26:56 +00:00
("I" . join-line) ;; QWERTY G
("U" . #'consult-yank-pop)
;; ("TAB" . 'company-indent-or-complete-common) ;; this works,
2022-01-15 12:04:00 +00:00
;; but also breaks unfolding in org mode :\ ("<tab>" .
2022-01-16 08:26:56 +00:00
;; 'company-indent-or-complete-common)
2022-01-15 12:04:00 +00:00
("J" . 'boon-toggle-comment)
2022-01-16 08:26:56 +00:00
("y" . nil) ;; QWERTY t
2022-01-15 12:04:00 +00:00
("y w" . 'transpose-words)
("y e" . 'transpose-sexps)
("y l" . 'transpose-lines)
("y p" . 'transpose-paragraphs)
("y c" . 'transpose-chars)
;; ("\\" . projectile-command-map) ;; error - define this in projectile's `use-package'
;; are these being buggy?
;; ("(" . boon-navigate-backward)
;; (")" . boon-navigate-forward)
2022-01-15 21:02:18 +00:00
("M" . consult-buffer)
("H" . consult-buffer)
2022-01-15 12:04:00 +00:00
;; these I prefer in their Dvorak positions rather than their QWERTY positions
("/" . undo-tree-undo)
("?" . undo-tree-redo)
("z" . boon-repeat-command))
(:map boon-x-map
("," . 'write-file)
("o" . 'save-buffer)
("e" . 'dired-jump)
("." . 'eval-last-sexp)
("u" . 'find-file)
("j" . 'kill-emacs)
("x" . 'ibuffer)
(")" . text-scale-adjust)
("(" . text-scale-adjust))
:config
(require 'boon-dvorak)
;; (add-to-list 'boon-enclosures `(40 "(" ")")) ;; 40 = (
;; (use-package boon-powerline)
;; (boon-powerline-theme)
(mapc (lambda (mode)
(add-to-list 'boon-special-mode-list mode))
'(emms-playlist-mode
emms-browser-mode
edebug-mode
sldb-mode
macrostep-mode
view-mode
slime-popup-buffer-mode
finder-mode
inferior-emacs-lisp-mode
shell-mode))
(add-to-list 'boon-special-conditions
'(or (bound-and-true-p edebug-mode)
(bound-and-true-p view-mode)
(bound-and-true-p macrostep-mode)
(bound-and-true-p slime-popup-buffer-mode)
(derived-mode-p 'comint-mode)))
(setq hi-lock-auto-select-face t)
;; (define-key boon-command-map (kbd "x d f") nil)
;; :hook
;; ((text-mode . turn-on-boon-mode)
;; (prog-mode . turn-on-boon-mode)
;; (shell-mode . turn-on-boon-mode)
;; (helpful-mode . turn-on-boon-mode)
;; (fundamental-mode . turn-on-boon-mode))
:init
(boon-mode))
#+END_SRC
2022-01-15 12:04:00 +00:00
*** experimental boon+modalka config :disabled:
#+BEGIN_SRC emacs-lisp :load no
(use-package boon
:disabled
:bind
("C-d" . 'boon-take-region)
("C-a" . 'boon-beginning-of-line)
("C-e" . 'boon-end-of-line)
("M-f" . 'boon-smarter-forward)
("M-b" . 'boon-smarter-backward))
#+END_SRC
2021-04-16 04:09:48 +00:00
2022-01-15 12:04:00 +00:00
*** experimental Emacs-flavored-Boon config :disabled:
#+BEGIN_SRC emacs-lisp :load no
(use-package boon
:disabled
:bind
(:map boon-command-map
("n" . next-line)
("p" . previous-line)
("f" . 'forward-char)
("b" . 'backward-char)
("a" . 'boon-beginning-of-line)
("e" . 'boon-end-of-line)
("y" . 'boon-splice)
("r" . swiper)
("x l" . ido-mini)
("/" . undo-tree-undo)
("?" . undo-tree-redo))
(:map boon-x-map
("s" . #'save-buffer)
("d" . #'dired-jump))
:config
(use-package boon-qwerty)
(boon-mode))
#+END_SRC
2021-12-29 15:07:36 +00:00
2022-01-15 12:04:00 +00:00
*** modalka :disabled:
<2019-11-03>
I'm pretty much using this to emulate `god-mode', which was great, but is no longer actively developed and had no support for non-Latin input methods.
#+BEGIN_SRC emacs-lisp :load no
(use-package modalka
:disabled
:bind
(("<escape>" . #'modalka-mode)
:map modalka-mode-map
("J" . #'join-line)
("P" . #'backward-paragraph)
("N" . #'forward-paragraph)
("M" . mark-sexp))
:config
(let ((keybind-re (rx-to-string '(group-n 1 (or (and bow (1+ (char graph)) eow)
(and (1+ (char graph))))))))
(mapc
(lambda (actual)
(let ((target (replace-regexp-in-string keybind-re "C-\\1" actual)))
(modalka-define-kbd actual target)))
;; no "t", "x", or "c", because they are prefix keys used later
'("`" "1" "2" "3" "4" "5" "6" "7" "8" "9" "0" "-" "="
"q" "w" "e" "r" "y" "u" "i" "o" "p" "[" "]" "\\"
"a" "s" "d" "f" "h" "j" "k" "l" ";" "'"
"z" "v" "b" "n" "m" "," "." "/"
"<" ">" "?"
"SPC"
;; (2019-11-03) It's a little unfortunate that these cannot be
;; elided by entering ("x" "C-x") ("t" "C-t") ("c" "C-c") just
;; once :\ (I did try)
"x =" "x -" "x e" "x s" "x d"
"x f" "x l" "x x" "x c" "x v" "x b"
"t w" "t e" "t l"
"c n" "c ," "c ." "c p"
"c c n" "c h u" "c h m")))
(modalka-define-kbd "O" "C-S-o")
(setq-default cursor-type '(bar . 1))
(setq modalka-cursor-type 'box)
:hook
((text-mode . modalka-mode)
(prog-mode . modalka-mode)))
2021-12-29 15:07:36 +00:00
#+END_SRC
2022-01-15 12:04:00 +00:00
*** god mode :disabled:
:PROPERTIES:
:CREATED: 2022-01-11T12:54:58+0530
:END:
TODO - make mode-line indicator prominent by placing it first, like in Evil
#+BEGIN_SRC emacs-lisp
2022-01-15 12:04:00 +00:00
(use-package god-mode
:disabled t
:bind ("<escape>" . god-mode-all)
:init (god-mode-all)
:config
2022-01-15 12:04:00 +00:00
;; from https://github.com/chrisdone/god-mode#change-modeline-color
(defun c/god-mode-update-cursor ()
(cond (god-local-mode
(progn
(setq cursor-type 'box)
(set-face-background 'mode-line "black")
(set-face-background 'mode-line-inactive "black")))
(t
(progn
(setq cursor-type 'bar)
(set-face-background 'mode-line "dark red")
(set-face-background 'mode-line-inactive "dark red")))))
(add-hook 'god-mode-enabled-hook #'c/god-mode-update-cursor)
(add-hook 'god-mode-disabled-hook #'c/god-mode-update-cursor)
:custom
(god-exempt-major-modes nil)
(god-exempt-predicates nil))
2022-01-15 12:04:00 +00:00
;; for helm
;; (define-key helm-map (kbd "<escape>") 'god-local-mode)
2022-01-14 19:14:11 +00:00
2022-01-15 12:04:00 +00:00
(use-package god-mode-isearch
:disabled t
2022-01-14 19:14:11 +00:00
:bind
2022-01-15 12:04:00 +00:00
((:map isearch-mode-map
("<escape>" . god-mode-isearch-activate))
(:map god-mode-isearch-map
("<escape>" . god-mode-isearch-disable))))
#+END_SRC
2022-01-15 12:04:00 +00:00
* Applications
Things not directly pertaining to text editing.
2022-01-15 12:04:00 +00:00
#+BEGIN_SRC emacs-lisp
(defun my-find-file* (&rest paths)
(mapc #'find-file paths))
#+END_SRC
2022-01-16 07:39:58 +00:00
** time tracking - chronometrist :creator:
2022-01-15 12:04:00 +00:00
choice.el is required by =chronometrist-key-values=
*** goal
#+BEGIN_SRC emacs-lisp
2022-01-15 12:04:00 +00:00
(use-package chronometrist-goal
:load-path "~/.emacs.d/contrapunctus/chronometrist-goal/"
:hook (chronometrist-mode . chronometrist-goal-minor-mode)
:config
2022-01-15 12:04:00 +00:00
(setq chronometrist-goal-list
'((30 "Arrangement/new edition")
(15 "Aural exercises")
(15 "Transcription" "Theory")
;; was 30 before, but that was too little for composing
(60 "Composing" "Writing" "Recording")
(15 "Data organization" "Physical organization" "Khilona archiving")
(60 "Exercise")
(120 "Guitar")
(90 "Reading")
(60 "Singing")
(30 "Subtitles")
(15 "Acting")
(30 "Keyboard")
(15 "Wikisource"))
alert-default-style 'libnotify))
#+END_SRC
2022-01-15 12:04:00 +00:00
*** spark
#+BEGIN_SRC emacs-lisp
2022-01-15 12:04:00 +00:00
(use-package chronometrist-spark
2022-01-19 18:56:21 +00:00
:load-path "/media/data/anon/Documents/Text Files/programming/elisp/chronometrist/elisp/"
2022-01-15 12:04:00 +00:00
:hook (chronometrist-mode . chronometrist-spark-minor-mode)
:config (setq chronometrist-spark-length (* 7 4)))
#+END_SRC
2022-01-13 16:09:17 +00:00
2022-01-15 12:04:00 +00:00
*** chronometrist
#+BEGIN_SRC emacs-lisp
2022-01-15 12:04:00 +00:00
(use-package chronometrist
;; :disabled t
2022-01-19 18:56:21 +00:00
:load-path "/media/data/anon/Documents/Text Files/programming/elisp/chronometrist/elisp/"
2022-01-15 12:04:00 +00:00
:init
(chronometrist-goal-minor-mode)
(chronometrist-spark-minor-mode)
:hook
(chronometrist-kv-read-mode . visual-line-mode)
(chronometrist-sexp-mode . auto-revert-mode)
(chronometrist-sexp-mode . visual-line-mode)
(kill-emacs-query-functions . chronometrist-query-stop)
:bind (("<f9>" . chronometrist)
("<kp-insert>" . chronometrist)
(:map chronometrist-mode-map
("c" . previous-line)
("r" . next-line)
("R" . chronometrist-report))
(:map chronometrist-report-mode-map
("h" . chronometrist-report-previous-week)
("s" . chronometrist-report-next-week)))
:config
2022-01-15 12:04:00 +00:00
(setq chronometrist-debug-enable t
chronometrist-active-backend :plist-group
chronometrist-before-in-functions '()
chronometrist-after-in-functions '(;; chronometrist-tags-add
;; chronometrist-kv-add
contrapunctus-start-project)
chronometrist-before-out-functions '(;; contrapunctus-before-project-stop
;; chronometrist-tags-add
;; chronometrist-tag-choice
chronometrist-key-values-unified-prompt
;; chronometrist-kv-add
;; chronometrist-skip-query-reset
)
chronometrist-after-out-functions '(contrapunctus-after-project-stop)
chronometrist-activity-indicator 'my-chronometrist-activity-indicator
chronometrist-details-display-key-values #'contrapunctus-display-key-values-function
chronometrist-details-schema `[("#" 3 t)
("Task" 20 t)
("Tags" 20 t)
("Details" 55 t)
("Duration" 20 t :right-align t :pad-right 3)
("Time" 10 t)]
chronometrist-task-list '("Acting" "Arrangement/new edition" "Aural exercises"
"Composing" "Cooking"
"Data organization" "Digitization"
"Exercise" "Guitar" "Housekeeping" "Keyboard" "Khilona archiving"
"OSM" "Performance" "Physical organization" "Programming"
"Reading" "Recording" "Sequencing" "Singing" "Subtitles"
"Teaching" "Theatre" "Theory" "Transcription"
"Video editing" "Voice" "Wikisource" "Wiktionary" "Writing")))
#+END_SRC
2022-01-13 16:08:48 +00:00
2022-01-15 12:04:00 +00:00
**** activity-indicator
#+BEGIN_SRC emacs-lisp
2022-01-15 12:04:00 +00:00
(defun my-chronometrist-activity-indicator ()
(--> (chronometrist-latest-record (chronometrist-active-backend))
(plist-put it :stop (chronometrist-format-time-iso8601))
(list it)
(chronometrist-events-to-durations it)
(-reduce #'+ it)
(truncate it)
(chronometrist-format-duration it)))
#+END_SRC
2022-01-15 12:04:00 +00:00
**** find-two-files
2021-02-18 09:31:40 +00:00
#+BEGIN_SRC emacs-lisp
2022-01-15 12:04:00 +00:00
(defun contrapunctus-find-two-files (file-1 file-2)
"Open FILE-1 and FILE-2 in new windows.
FILE-1 will appear above FILE-2."
(find-file-other-window file-2)
(split-window-below)
(find-file file-1))
2021-02-20 13:44:12 +00:00
#+END_SRC
2022-01-15 12:04:00 +00:00
**** outline-open-heading
2021-02-20 13:44:12 +00:00
#+BEGIN_SRC emacs-lisp
2022-01-15 12:04:00 +00:00
(defun cp-outline-open-heading (n)
(goto-char (point-min))
(outline-next-visible-heading n)
(outline-show-subtree))
2021-02-18 09:31:40 +00:00
#+END_SRC
2022-01-15 12:04:00 +00:00
**** start-project
#+BEGIN_SRC emacs-lisp
2022-01-15 12:04:00 +00:00
(defvar my-arrangement-frameset
[frameset
1 (24907 10263 320473 920000) nil nil nil nil
((((minibuffer . t)
(undecorated)
(override-redirect)
(font . "-PfEd-DejaVu Sans Mono-normal-normal-normal-*-14-*-*-*-m-0-iso10646-1")
(font-parameter . "DejaVu Sans Mono-10.5")
(border-width . 0)
(internal-border-width . 0)
(right-divider-width . 0)
(bottom-divider-width . 0)
(vertical-scroll-bars)
(horizontal-scroll-bars)
(foreground-color . "#d6d6d4")
(background-color . "#1c1e1f")
(mouse-color . "black")
(border-color . "black")
(screen-gamma)
(line-spacing)
(left-fringe . 4)
(right-fringe . 4)
(no-special-glyphs)
(scroll-bar-foreground)
(scroll-bar-background)
(menu-bar-lines . 1)
(tab-bar-lines . 0)
(height . 40)
(tool-bar-lines . 0)
(title)
(wait-for-wm . t)
(tool-bar-position . top)
(inhibit-double-buffering)
(icon-type . t)
(auto-raise)
(auto-lower)
(cursor-type . box)
(scroll-bar-width . 16)
(scroll-bar-height . 16)
(alpha)
(no-focus-on-map)
(no-accept-focus)
(fullscreen . maximized)
(visibility . t)
(skip-taskbar)
(z-group)
(display-type . color)
(background-mode . dark)
(cursor-color . "#fb2874")
(sticky)
(environment)
(last-focus-update . t)
(powerline-cache)
(frameset--id . "6557-E2CE-3D63-0FD0")
(frameset--mini t . t)
(width . 169)
(modeline . t)
(unsplittable)
(left . 0)
(top . 0)
(icon-name)
(display . ":0.0")
(explicit-name))
((min-height . 8)
(min-width . 20)
(min-height-ignore . 4)
(min-width-ignore . 6)
(min-height-safe . 2)
(min-width-safe . 4)
(min-pixel-height . 136)
(min-pixel-width . 160)
(min-pixel-height-ignore . 68)
(min-pixel-width-ignore . 48)
(min-pixel-height-safe . 34)
(min-pixel-width-safe . 32))
vc (pixel-width . 1366)
(pixel-height . 669)
(total-width . 171)
(total-height . 39)
(normal-height . 1.0)
(normal-width . 1.0)
(combination-limit)
(hc
(pixel-width . 1366)
(pixel-height . 507)
(total-width . 171)
(total-height . 29)
(normal-height . 0.7661169415292354)
(normal-width . 1.0)
(combination-limit)
(leaf (pixel-width . 686)
(pixel-height . 507)
(total-width . 86)
(total-height . 29)
(normal-height . 1.0)
(normal-width . 0.5)
(buffer "2021-09-12 Songs of Travel-pacON.pdf"
(selected)
(hscroll . 0)
(fringes 4 4 nil nil)
(margins nil)
(scroll-bars nil 0 t nil 0 t nil)
(vscroll . 0)
(dedicated)
(point . 1)
(start . 1)))
(leaf (last . t)
(pixel-width . 680)
(pixel-height . 507)
(total-width . 85)
(total-height . 29)
(normal-height . 1.0)
(normal-width . 0.5)
(buffer "IMSLP89688-PMLP183796-SongsOfTravel.pdf"
(selected)
(hscroll . 0)
(fringes 4 4 nil nil)
(margins nil)
(scroll-bars nil 0 t nil 0 t nil)
(vscroll . 0)
(dedicated)
(point . 1)
(start . 1))))
(leaf (last . t)
(pixel-width . 1366)
(pixel-height . 162)
(total-width . 171)
(total-height . 9)
(normal-height . 0.23388305847076465)
(normal-width . 1.0)
(buffer "guitar.ly"
(selected . t)
(hscroll . 0)
(fringes 4 4 nil nil)
(margins nil)
(scroll-bars nil 0 t nil 0 t nil)
(vscroll . 0)
(dedicated)
(point . 1)
(start . 1)))))])
#+END_SRC
#+BEGIN_SRC emacs-lisp
2022-01-15 12:04:00 +00:00
(defvar my-composition-frameset
[frameset 1
2022-02-06 12:08:07 +00:00
(25081 27011 924166 854000)
nil nil nil nil
((((minibuffer . t)
(undecorated)
(override-redirect)
(font . "-PfEd-DejaVu Sans Mono-normal-normal-normal-*-14-*-*-*-m-0-iso10646-1")
(font-parameter . "DejaVu Sans Mono-10.5")
(border-width . 0)
(internal-border-width . 0)
(right-divider-width . 0)
(bottom-divider-width . 0)
(vertical-scroll-bars)
(horizontal-scroll-bars)
(foreground-color . "#d6d6d4")
(background-color . "#1c1e1f")
(mouse-color . "black")
(border-color . "black")
(screen-gamma)
(line-spacing)
(left-fringe . 4)
(right-fringe . 4)
(no-special-glyphs)
(scroll-bar-foreground)
(scroll-bar-background)
(menu-bar-lines . 1)
(tab-bar-lines . 0)
(height . 58)
(tool-bar-lines . 0)
(title)
(wait-for-wm . t)
(tool-bar-position . top)
(inhibit-double-buffering)
(icon-type . t)
(auto-raise)
(auto-lower)
(cursor-type . box)
(scroll-bar-width . 16)
(scroll-bar-height . 16)
(alpha)
(no-focus-on-map)
(no-accept-focus)
(fullscreen . maximized)
(visibility . t)
(skip-taskbar)
(z-group)
(display-type . color)
(background-mode . dark)
(cursor-color . "#fb2874")
(sticky)
(environment)
(powerline-cache)
(last-focus-update . t)
(frameset--id . "3226-BFF7-1499-D0C7")
(frameset--mini t . t)
(modeline . t)
(unsplittable)
(icon-name)
(display . ":0.0")
(explicit-name)
(width . 235)
(left . 31)
(top . 0))
((min-height . 8)
(min-width . 20)
(min-height-ignore . 4)
(min-width-ignore . 6)
(min-height-safe . 2)
(min-width-safe . 4)
(min-pixel-height . 136)
(min-pixel-width . 160)
(min-pixel-height-ignore . 68)
(min-pixel-width-ignore . 48)
(min-pixel-height-safe . 34)
(min-pixel-width-safe . 32))
hc
(pixel-width . 1889)
2022-01-15 12:04:00 +00:00
(pixel-height . 981)
2022-02-06 12:08:07 +00:00
(total-width . 236)
2022-01-15 12:04:00 +00:00
(total-height . 58)
(normal-height . 1.0)
2022-02-06 12:08:07 +00:00
(normal-width . 1.0)
(combination-limit)
(vc
(pixel-width . 945)
(pixel-height . 981)
2022-01-15 12:04:00 +00:00
(total-width . 118)
2022-02-06 12:08:07 +00:00
(total-height . 58)
(normal-height . 1.0)
(normal-width . 0.5)
(combination-limit)
(leaf
(pixel-width . 945)
(pixel-height . 862)
(total-width . 118)
(total-height . 51)
(normal-height . 0.884102564102564)
(normal-width . 1.0)
(buffer "music"
(selected . t)
(hscroll . 0)
(fringes 4 4 nil nil)
(margins nil)
(scroll-bars nil 0 t nil 0 t nil)
(vscroll . 0)
(dedicated)
(point . 444)
(start . 1))
(prev-buffers
("init.org[emacs-lisp]" 35109 35711)
("music" 1 444)
("2 Mera Mera Kyon-pacON.pdf" 1 1)
("composition-portfolio.org" 1 3240)
("*Chronometrist*" 1 302)
("Birthdays.md" 1 28)
("Markor" 1 900)
("People" 1 162)
("*compilation*" 1 1)
("*async-backup*" 1 624)
("pdf-tools.el" 18146 19210)))
(leaf
(last . t)
(pixel-width . 945)
(pixel-height . 119)
(total-width . 118)
(total-height . 7)
(normal-height . 0.11589743589743609)
(normal-width . 1.0)
(buffer "*compilation*"
(selected)
(hscroll . 0)
(fringes 4 4 nil nil)
(margins nil)
(scroll-bars nil 0 t nil 0 t nil)
(vscroll . 0)
(dedicated)
(point . 1)
(start . 1))
(prev-buffers
("music" 232 444)
("*compilation*" 1 1)
("composition-portfolio.org" 3080 3240)
("2 Mera Mera Kyon-pacON.pdf" 1 1)
("init.org[emacs-lisp]" 35577 35711))))
(leaf
(last . t)
(pixel-width . 944)
(pixel-height . 981)
(total-width . 118)
(total-height . 58)
(normal-height . 1.0)
(normal-width . 0.5)
(buffer "2 Mera Mera Kyon-pacON.pdf"
(selected)
(hscroll . 0)
(fringes 4 4 nil nil)
(margins nil)
(scroll-bars nil 0 t nil 0 t nil)
(vscroll . 0)
(dedicated)
(point . 1)
(start . 1))
(prev-buffers
("music" 1 444)
("2 Mera Mera Kyon-pacON.pdf" 1 1)
("pdf-tools.el" 18146 19210)
("init.org[emacs-lisp]" 35577 35711)))))])
#+END_SRC
#+BEGIN_SRC emacs-lisp
2022-01-15 12:04:00 +00:00
(defun contrapunctus-start-project (project)
(delete-other-windows)
(pcase project
("Acting"
;; (find-file
;; "/media/data/anon/Documents/sync/Wilde, Oscar/The Importance of Being Earnest/gutenberg-script.txt")
(find-file "/media/data/anon/Documents/sync/hindi/Harishankar Parsai - Nithalle Ki Diary.pdf")
)
("Arrangement/new edition"
(my-find-file*
"/media/data/anon/1-music-scores/4-my-arrangements/2021/2021-09-12 Songs of Travel/1 The Vagabond/music/guitar.ly"
"/media/data/anon/1-music-scores/4-my-arrangements/2021/2021-09-12 Songs of Travel/output/2021-09-12 Songs of Travel-pacON.pdf"
"~/Sync/Scores/voice/Vaughan Williams/IMSLP89688-PMLP183796-SongsOfTravel.pdf")
(frameset-restore my-arrangement-frameset :reuse-frames t))
("Aural exercises"
(find-file-other-window "/media/data/anon/Documents/Text Files/music_stuff/harmonic-analysis.org"))
((or "Sequencing" "Composing")
(my-find-file*
"~/1-music-scores/2-my-compositions/composition-portfolio.org"
"~/1-music-scores/2-my-compositions/2016/2016-07 Sab Ka Sooraj/2 Mera Mera Kyon/output/2 Mera Mera Kyon-pacON.pdf"
"~/1-music-scores/2-my-compositions/2016/2016-07 Sab Ka Sooraj/2 Mera Mera Kyon/music/")
(frameset-restore my-composition-frameset :reuse-frames t))
("Data organization"
(find-dired "/media/data/anon/" "-name \\'dl\\' -size +0c"))
("Digitization"
(my-find-file*
"/media/data/anon/Documents/Text Files/latex/Don't, Mr. Disraeli!/dont-mr-disraeli.tex"
"/media/data/anon/Documents/Text Files/latex/Don't, Mr. Disraeli!/dont-mr-disraeli.pdf"))
("Exercise" (chronometrist-key-values-unified-prompt "Exercise")
(chronometrist-edit-backend (chronometrist-active-backend)))
("Guitar"
(let* ((path-1 "~/Sync/Scores/guitar-solo/repertoire.org")
(path-2 "~/Sync/Scores/guitar-duo/repertoire.org")
(weekday (elt (decode-time) 6))
(week (string-to-number (format-time-string "%U"))))
;; (contrapunctus-find-two-files path-1 path-2)
(find-file-other-window path-1)
(select-window (get-buffer-window (get-file-buffer path-1)))
(org-match-sparse-tree nil "perform")))
("Keyboard"
(find-file-other-window "/media/data/anon/Documents/Text Files/music_stuff/piano.org")
(outline-show-subtree))
("Khilona archiving"
(find-file-other-window "/media/data/anon/Documents/sync/Khilona/")
(split-window-below)
(other-window 1)
(find-file "~/Khilona/Videos/Me?/")
(other-window 1)
(find-file "/media/data/anon/Documents/Text Files/khilona/2011 Me?/script/script.tex"))
("OSM"
;; (delete-window (get-buffer-window " *JOSM*"))
(contrapunctus-find-two-files "/media/data/phone/anon/Nokia 6.1/Android/data/net.osmand.plus/files/"
;; "/media/data/phone/anon/Nokia 6.1/external/DCIM/OpenCamera/osm/"
"/media/data/phone/anon/Nokia 6.1/Documents/Markor/OSM/TODO.md"))
("Programming"
;; (eww-open-file "/media/data/anon/git/cl/McCLIM/Documentation/Manual/mcclim.html")
(find-file-other-window "~/Documents/Text Files/programming/projects.org"))
("Reading"
(find-file-other-window "/media/data/anon/Documents/sync/"))
("Recording"
(find-file-other-window
"/media/data/anon/8-music-production/1-my-creations/BWV 1006a/1 Prelude/"))
("Singing"
(find-file-other-window
"~/Sync/Scores/voice/repertoire.org"))
("Subtitles"
;; (find-file-other-window "/media/data/anon/Music/0-classical/vocal/musical/Company/")
(start-process "subtitleeditor" nil "subtitleeditor" "/media/data/khilona/Videos/Peer Gynt/peer-gynt.srt"))
("Teaching"
(find-file-other-window "/media/data/anon/Documents/Text Files/students/")
;; (launch-file "/media/data/anon/Sync/Scores/voice/jingle-bell-rock.pdf")
)
("Theatre rehearsal"
(contrapunctus-find-two-files
"/media/data/anon/Documents/Text Files/khilona/voices.org"
"/media/data/anon/1-music-scores/2-my-compositions/2019/2019-03 Kahe Natak Karte Ho Ji/Kahe Natak Karte Ho Ji.org"))
("Transcription"
;; (find-file-other-window
;; "/media/data/phone/anon/Nokia 6.1/Documents/Markor/Music/transcriptions.md")
;; (emms-play-file "/media/data/anon/Music/Hallelujah Rufus Wainwright-xR0DKOGco_o.opus")
(my-find-file*
"/media/data/anon/1-music-scores/4-my-arrangements/2021/2021-03-11 Hallelujah/output/2021-03-11 Hallelujah-pacON.pdf"
"/media/data/anon/1-music-scores/4-my-arrangements/2021/"))
("Video editing"
(start-process "kdenlive" (generate-new-buffer-name "kdenlive")
;; "flatpak" "run" "org.kde.kdenlive"
"kdenlive"
;; "/home/khilona/Videos/ghar ghar theatre 3/ggt3.kdenlive"
"/media/data/khilona/Videos/podcast/episode 3/episode 3.kdenlive")
(find-file-other-window ;; "/home/khilona/Videos/ghar ghar theatre 3/"
"/media/data/khilona/Videos/podcast/"))
("Wiktionary"
(find-file-other-window
"/media/data/phone/anon/Nokia 6.1/Documents/Markor/Languages/hindi.md"))
("Writing"
(find-file-other-window
"/media/data/phone/anon/Nokia 6.1/Documents/Markor/Songs or Poems/"))))
#+END_SRC
2022-01-15 12:04:00 +00:00
**** commit-prompt
#+BEGIN_SRC emacs-lisp
2022-01-15 12:04:00 +00:00
(autoload 'magit-anything-modified-p "magit")
2022-01-15 12:04:00 +00:00
(defun contrapunctus-commit-prompt ()
"Prompt user if `default-directory' is a dirty Git repository.
Return t if the user answers yes, if the repository is clean, or
if there is no Git repository.
2022-01-15 12:04:00 +00:00
Return nil (and run `magit-status') if the user answers no."
(cond ((not (magit-anything-modified-p)) t)
((yes-or-no-p
(format "You have uncommitted changes in %S. Really clock out? "
default-directory)) t)
(t (magit-status) nil)))
#+END_SRC
2022-01-15 12:04:00 +00:00
**** before-project-stop
#+BEGIN_SRC emacs-lisp
2022-01-15 12:04:00 +00:00
(defun contrapunctus-before-project-stop (project)
(if (member project '("Composing" "Khilona archiving" "Programming"))
(contrapunctus-commit-prompt)
;; all functions in `chronometrist-before-project-stop-functions'
;; must return t for successful clock-out
t))
#+END_SRC
2022-01-14 11:11:12 +00:00
2022-01-15 12:04:00 +00:00
**** after-project-stop
FIXME -
1. instead of changing the last plist, change the last plist with name "OSM" and without tags or key-values (because a new plist may have been inserted in the meantime)
2022-01-14 11:11:12 +00:00
#+BEGIN_SRC emacs-lisp
2022-01-15 12:04:00 +00:00
(use-package request
:ensure t)
(use-package esxml
:ensure t)
2022-02-06 12:07:10 +00:00
(use-package esxml-query)
2022-01-14 11:11:12 +00:00
2022-01-15 12:04:00 +00:00
(defun my-get-changeset-comment (changeset)
(->> (esxml-query "[k=comment]" changeset)
(esxml-node-attributes)
(alist-get 'v)))
2022-01-14 13:57:10 +00:00
2022-01-15 12:04:00 +00:00
(defun my-make-osm-url (id)
(concat "https://www.openstreetmap.org/changeset/" id))
2022-01-14 11:11:12 +00:00
2022-01-15 12:04:00 +00:00
(defun my-get-saved-changeset-id (backend)
(-let* (((&plist :changesets saved-changesets)
(cl-loop for plist in
;; the very latest OSM plist is the one we just created -
;; we want the one before that
(rest (chronometrist-to-list backend))
when (and (equal "OSM" (plist-get plist :name))
;; ignore plists without a :changesets keyword
(plist-get plist :changesets))
return plist))
(((&plist :osm-url last-url)) (last saved-changesets)))
(when last-url
(first (last (split-string last-url "/"))))))
2022-01-14 11:11:12 +00:00
2022-01-15 12:04:00 +00:00
(cl-defun my-save-osm-details (&key data &allow-other-keys)
(-let* ((backend (chronometrist-active-backend))
(last-id (my-get-saved-changeset-id backend))
(response-changesets (esxml-node-children data))
(new-changesets
(if last-id
(cl-loop with id
for changeset in response-changesets do
(setq id (alist-get 'id
(esxml-node-attributes changeset)))
if (equal id last-id)
return (reverse changesets)
else collect
(list
:osm-url
(my-make-osm-url id)
:osm-comment
(my-get-changeset-comment changeset)) into changesets)
;; no changeset information in file - just use
;; the latest changeset from the response
(let* ((changeset (first response-changesets))
(id (alist-get 'id (esxml-node-attributes changeset)))
(comment (my-get-changeset-comment changeset)))
`((:osm-url ,(my-make-osm-url id)
:osm-comment ,comment)))))
(new-plist (chronometrist-plist-update
(chronometrist-latest-record (chronometrist-active-backend))
`(:changesets ,new-changesets))))
;; (message "Last changeset ID - %s" last-id)
(chronometrist-replace-last (chronometrist-active-backend) new-plist)))
(defun my-save-osm-changeset-details ()
"Save OSM changeset details in the Chronometrist file."
(request
"https://api.openstreetmap.org/api/0.6/changesets"
:params '(("display_name" . "contrapunctus"))
:parser (lambda () (libxml-parse-xml-region (point) (point-max)))
:success #'my-save-osm-details))
2022-01-14 13:57:10 +00:00
2022-01-15 12:04:00 +00:00
(defun contrapunctus-after-project-stop (project)
(pcase project
("OSM"
(delete-other-windows)
;; What should we do when there's no network connectivity?
;; Ideally - note the clock-out time, and retry every five
;; minutes. When connected, request the changesets, look for the
;; first changeset with a "created_at" which is less than the
;; clock-out time.
(my-save-osm-changeset-details))
(_ (delete-other-windows))))
2022-01-14 13:57:10 +00:00
#+END_SRC
2022-01-15 12:04:00 +00:00
**** display-key-values
Schema I use for plists - values can be -
1. integer
2. ="string"= | =("list" "of" "strings")=
3. =(INTEGER . "string")=
4. mixed alist - elements can be either #1 or #2
5. a plist, or a list of plists
2022-01-15 12:04:00 +00:00
Programming - =:project=, [ =:component=,] =:feature=
2022-01-15 12:04:00 +00:00
What if...
1. =(a b c)= -> ="a, b, c"=
2. =(a . b)= -> ="a b"= (e.g. =(a (b . c) d)= -> ="a, b c, d"=)
3. sublist - recurse
2022-01-14 13:57:10 +00:00
#+BEGIN_SRC emacs-lisp
2022-01-15 12:04:00 +00:00
;; (contrapunctus-objects-to-string " - " nil) => ""
;; (contrapunctus-objects-to-string " - " 1) => "1"
(defun contrapunctus-objects-to-string (separator &rest args)
"Return ARGS as a string, removing nil values."
(mapconcat (lambda (elt)
(format "%s" elt))
(flatten-list
(seq-filter #'identity args))
separator))
2022-01-15 12:04:00 +00:00
(defun contrapunctus-display-key-values-helper (list)
(cl-loop for elt in list
collect
(cond ((stringp elt) elt)
((chronometrist-pp-pair-p elt)
(format "%s %s" (car elt) (cdr elt)))
((listp elt)
(contrapunctus-display-key-values-function elt))
(t "")) into strings
finally return
(mapconcat #'identity (seq-filter #'identity strings) ", ")))
(defun contrapunctus-display-key-values-function (plist)
"Function used to print key-values in `chronometrist-details' buffers."
(let ((values (seq-remove #'keywordp (chronometrist-plist-key-values plist))))
(contrapunctus-display-key-values-helper values)))
2022-01-06 07:32:53 +00:00
2021-08-21 13:52:29 +00:00
#+END_SRC
2022-01-14 19:16:44 +00:00
2022-01-15 12:04:00 +00:00
*** key-values
2022-01-13 20:05:59 +00:00
#+BEGIN_SRC emacs-lisp
2022-01-15 12:04:00 +00:00
(use-package chronometrist-key-values
:ensure t
2022-01-15 12:04:00 +00:00
:after chronometrist
2022-01-19 18:56:21 +00:00
:load-path "/media/data/anon/Documents/Text Files/programming/elisp/chronometrist/elisp/")
2022-01-13 20:05:59 +00:00
#+END_SRC
2022-01-27 17:56:41 +00:00
#+BEGIN_SRC emacs-lisp
(defun my-copy-gpx-timestamps ()
"Copy ISO-8601 timestamps from GPX data as ISO-8601 timestamps in local time."
(interactive)
(let* ((dom (libxml-parse-xml-region (point-min) (point-max)))
(trkseg (esxml-query "trkseg" dom))
(first-trkpt (third trkseg))
(first-iso (second (alist-get 'time first-trkpt)))
(first-unix (parse-iso8601-time-string first-iso))
(last-trkpt (first (last trkseg)))
(last-iso (second (alist-get 'time last-trkpt)))
(last-unix (parse-iso8601-time-string last-iso))
(plist (list :start (chronometrist-format-time-iso8601 first-unix)
:stop (chronometrist-format-time-iso8601 last-unix)))
(string (apply #'format "%S %S\n%S %S" plist)))
(kill-new string)
(apply #'message "Copied %S %S %S %S to kill ring" plist)))
#+END_SRC
2022-01-15 12:04:00 +00:00
*** count-expressions
*** querying data
An example of querying the Chronometrist file data - finding out how much time I've spent on tasks matching a certain criteria.
2022-01-15 12:04:00 +00:00
#+BEGIN_SRC emacs-lisp :tangle no :load no
;; XXX - day count is incorrect
2022-01-15 12:04:00 +00:00
(cl-loop for plist in (chronometrist-to-list (chronometrist-active-backend))
with count = 0
when (and (equal (plist-get plist :name) "Composing")
(equal (plist-get plist :song) "आदि काल से आज तलक"))
sum (chronometrist-interval plist) into seconds
and do (cl-incf count)
finally return
(unless (zerop seconds)
(format "%s, in %s days."
(format-seconds "%Y, %D, %H, %M, and %S%z" seconds)
count)))
#+END_SRC
2022-01-15 12:04:00 +00:00
**** Intervals and durations for task Exercise.
#+BEGIN_SRC emacs-lisp :tangle no :load no
(cl-loop for plist in (chronometrist-to-list (chronometrist-active-backend))
with count = 0
when (equal (plist-get plist :name) "Exercise")
collect
(let* ((plist (copy-list plist))
(interval-seconds (chronometrist-interval plist))
(start (plist-get plist :start)))
(plist-put plist :duration (ts-human-format-duration interval-seconds))
(plist-put plist :date (seq-take start 10))
(chronometrist-plist-remove plist :start :stop)))
2022-01-13 16:02:38 +00:00
#+END_SRC
2022-01-15 12:04:00 +00:00
**** Unique key-values for task "Exercise"
#+BEGIN_SRC emacs-lisp :tangle no :load no
(cl-loop with task = "Exercise"
for plist in (chronometrist-to-list (chronometrist-active-backend))
when (equal (plist-get plist :name) task)
2022-01-15 12:04:00 +00:00
collect (chronometrist-plist-key-values plist) into key-values
finally do
(let ((buffer (get-buffer-create (generate-new-buffer-name "chronometrist-query"))))
(with-current-buffer buffer
(->> (cl-remove-duplicates key-values)
(seq-filter #'identity)
(format "%S")
(insert))
(emacs-lisp-mode)
(switch-to-buffer buffer))))
2021-02-18 09:31:40 +00:00
#+END_SRC
2022-01-15 12:04:00 +00:00
**** Time spent running since the 13th of December.
#+BEGIN_SRC emacs-lisp :tangle no :load no
(cl-loop with start = (parse-iso8601-time-string "2021-12-13")
with buffer = (get-buffer-create "*chronometrist-query*")
with output
for plists being the hash-values of (chronometrist-to-hash-table (chronometrist-active-backend))
using (hash-keys date-iso)
when
;; create a list of strings for each date on which I ran
(cl-loop with first-line = t
with date = (parse-iso8601-time-string date-iso)
for plist in plists
when (and (plist-get plist :running)
(or (time-less-p start date)
(time-equal-p start date)))
collect
(let* ((plist (copy-list plist))
(duration-seconds (chronometrist-interval plist))
(start (plist-get plist :start))
(distance (plist-get plist :running))
(distance-int (car distance))
(distance-km (/ (float distance-int) 1000))
(duration-hours (/ (float duration-seconds) 60 60))
(distance-string (format "% 4s %s" distance-int (cdr distance)))
(speed-string (format "%.2f" (/ distance-km duration-hours))))
(format "%s%s in %s (% 5s kmph)\n"
2022-01-15 12:04:00 +00:00
(if (not first-line)
(make-string (+ 3 (length date-iso)) ?\s)
(setq first-line nil)
(concat date-iso " - "))
distance-string
(format-seconds "%m:%02s" duration-seconds)
speed-string)))
2022-01-15 12:04:00 +00:00
collect it into lists
;; Add indices for each date, and indentation when there are >1
;; instances of running in a date
finally do
(setq output
(cl-loop for list in (reverse lists)
count list into index
concat
(let* ((index-string (format "%2s. " index))
(indent (if (> (length list) 1)
(make-string (length index-string) ?\s)
"")))
(concat index-string (first list) indent
(mapconcat #'identity (rest list) indent)))))
(with-current-buffer buffer
(erase-buffer)
(insert output)
(text-mode)
(switch-to-buffer-other-window buffer)))
2022-01-14 11:11:12 +00:00
#+END_SRC
2022-01-15 12:04:00 +00:00
** WISH emms
1. [ ] make toggle command for emms-start/emms-stop
2. [ ] change mode line display - don't show the whole file path, just the name
2022-01-14 11:11:12 +00:00
#+BEGIN_SRC emacs-lisp
2022-01-15 12:04:00 +00:00
(use-package emms
:ensure t
2022-01-15 12:04:00 +00:00
:after hydra
:init (setq emms-info-functions '(emms-info-tinytag))
:bind
("<f2> e" . #'contrapunctus-emms-hydra/body)
("<f2> E" . #'emms)
(:map dired-mode-map
("E" . #'contrapunctus-emms-hydra/body))
:commands
(emms-all emms emms-play-dired emms-add-dired)
2022-01-14 11:11:12 +00:00
:config
2022-01-15 12:04:00 +00:00
(emms-all)
(emms-default-players)
(setq emms-player-mpv-parameters #'my-emms-mpv-parameters
emms-info-tinytag-python-name "python3")
;; ;; This won't work for `emms-random', because it runs in a `save-excursion'
;; (add-to-list 'emms-playlist-selection-changed-hook 'emms-playlist-mode-center-current)
;; (--map (add-to-list 'emms-player-mpv-parameters it)
;; '("--fs"))
(defun contrapunctus-emms-toggle-player ()
(interactive)
(if emms-player-stopped-p
(emms-start)
(emms-stop)))
:init (defhydra contrapunctus-emms-hydra ()
("e" #'emms "EMMS")
("n" #'emms-next "Next")
("p" #'emms-previous "Previous")
("SPC" #'emms-pause "Pause")
("s" #'contrapunctus-emms-toggle-player "Start/Stop")
("0" #'emms-volume-raise)
("9" #'emms-volume-lower)
("<up>" #'emms-volume-raise)
("<down>" #'emms-volume-lower)
("<left>" #'emms-seek-backward)
("<right>" #'emms-seek-forward)
("l" #'emms-play-dired "Play file (dired)")
("a" #'emms-add-dired "Add file (dired)")
("A" #'emms-add-directory-tree "Add directory")
("u" #'emms-play-url)))
2022-01-14 11:11:12 +00:00
2022-01-15 12:04:00 +00:00
(defun my-emms-mpv-parameters ()
(append
'("--quiet"
"--really-quiet"
;; "--vid=no"
"--force-window=yes"
;; "-ao=jack,alsa"
;; "--loop-file=inf"
)
(let* ((dir (->> (emms-playlist-current-selected-track)
(alist-get 'name)
(file-name-directory)))
(subs-in-dir (f-glob "*.srt" dir))
(subs-in-subdir (f-glob "*/*.srt" dir)))
(->> (append subs-in-dir subs-in-subdir)
(-interpose ":")
(append '("--sub-files="))
(apply #'concat)
(list)))))
(use-package emms-playlist-mode
2022-01-14 11:11:12 +00:00
:bind
2022-01-15 12:04:00 +00:00
(:map emms-playlist-mode-map
("0" . #'emms-volume-raise)
("9" . #'emms-volume-lower)
("<up>" . #'emms-volume-raise)
("<down>" . #'emms-volume-lower)
("<left>" . #'emms-seek-backward)
("<right>" . #'emms-seek-forward)
("r" . #'next-line)
("c" . #'previous-line)
("R" . #'emms-next)
("C" . #'emms-previous)
("C-r" . #'emms-toggle-random-playlist)
("M-r" . #'emms-random)
("C-c" . #'emms-playlist-mode-center-current)
("SPC" . #'emms-pause)
("K" . #'emms-playlist-clear))
:config (setq emms-playlist-buffer-name "EMMS Playlist"))
2022-01-14 11:11:12 +00:00
#+END_SRC
2022-01-15 12:04:00 +00:00
** Internet
2022-01-16 07:39:58 +00:00
*** eww :viewer:
2022-01-13 20:04:37 +00:00
#+BEGIN_SRC emacs-lisp
2022-01-15 12:04:00 +00:00
(use-package eww
2022-01-13 20:04:37 +00:00
:config
2022-01-15 12:04:00 +00:00
(setq shr-image-animate nil)
:bind
;; start boon-specific config
(:map shr-map
("v" . nil))
(:map shr-image-map
("i" . nil)
("v" . nil))
(:map eww-link-keymap
("i" . nil)
("v" . nil))
(:map eww-mode-map
("h" . #'eww-back-url)
("s" . #'eww-forward-url)
("c" . #'shr-previous-link)
("r" . #'shr-next-link)
("v" . nil))
;; end boon-specific config
)
(defun my-eww ()
(interactive)
(cond ((derived-mode-p 'dired-mode)
(eww-open-file
(dired-file-name-at-point)))
((derived-mode-p 'html-mode)
(eww-open-file (buffer-file-name)))
(t (call-interactively #'eww))))
2022-01-13 20:04:37 +00:00
#+END_SRC
2022-01-15 12:04:00 +00:00
*** url-cookie
Ask for confirmation before saving cookies. I'd rather just disallow them all though 🤔
2021-02-18 09:31:40 +00:00
#+BEGIN_SRC emacs-lisp
2022-01-15 12:04:00 +00:00
(use-package url-cookie
2021-02-18 09:31:40 +00:00
:config
2022-01-15 12:04:00 +00:00
(setq url-cookie-confirmation t))
2021-02-18 09:31:40 +00:00
#+END_SRC
2022-01-16 07:39:58 +00:00
*** elpher :viewer:
#+BEGIN_SRC emacs-lisp
2022-01-15 12:04:00 +00:00
(use-package elpher
:ensure t
2022-01-15 12:04:00 +00:00
:bind (:map elpher-mode-map
("r" . elpher-next-link)
("c" . elpher-prev-link)
("h" . elpher-back)
("s" . push-button)
("w" . elpher-copy-current-url)
("W" . elpher-copy-link-url)
("g" . elpher-reload)))
#+END_SRC
2022-01-15 12:04:00 +00:00
*** elfeed
#+BEGIN_SRC emacs-lisp
2022-01-15 12:04:00 +00:00
(use-package elfeed
:ensure t
2022-01-15 12:04:00 +00:00
:bind (:map elfeed-show-mode-map
("v" . nil))
:config
2022-01-15 12:04:00 +00:00
(add-to-list 'boon-special-mode-list 'elfeed-show-mode)
(add-to-list 'boon-special-mode-list 'elfeed-search-mode))
#+END_SRC
2022-01-16 07:39:58 +00:00
*** jabber :disabled:communication:
#+BEGIN_SRC emacs-lisp
2022-01-15 12:04:00 +00:00
(use-package jabber
:disabled t
:load-path "~/.emacs.d/elisp-git/emacs-jabber-wgreenhouse/"
:commands jabber-connect
:config (global-unset-key (kbd "C-x C-j"))
(global-set-key (kbd "C-x C-j") 'join-line)
(setq jabber-history-enabled t
jabber-history-muc-enabled t
jabber-alert-presence-message-function nil
jabber-account-list '(("contrapunctus@jabjab.de")))
(add-to-list 'jabber-post-connect-hooks 'jabber-enable-carbons))
#+END_SRC
2022-01-16 07:39:58 +00:00
** sxiv :viewer:
#+BEGIN_SRC emacs-lisp
2022-01-15 12:04:00 +00:00
(use-package sxiv
:load-path "~/.emacs.d/contrapunctus/sxiv/"
:config (setq sxiv-exclude-strings '("meh" "\\.NEF$"))
:bind ("<f2> s" . sxiv)
(:map dired-mode-map
("I" . sxiv)))
#+END_SRC
#+END_SRC
2022-01-16 07:39:58 +00:00
** TODO emacsshot :creator:
2022-01-15 12:04:00 +00:00
PR ideas
1. [ ] create directories in save path if they don't exist
2. [ ] grammar - "written /path/to/file"
#+BEGIN_SRC emacs-lisp
2022-01-15 12:04:00 +00:00
(use-package emacsshot
:ensure t
:bind
2022-01-15 12:04:00 +00:00
("<print> <f10>" . emacsshot-snap-window-filename)
("<print> <f11>" . emacsshot-snap-frame-filename)
("<print> <f12>" . emacsshot-snap-mouse-filename)
:config
(setq emacsshot-with-timestamp t
emacsshot-snap-window-filename "/media/data/anon/Pictures/screenshots/emacsshot/emacsshot.png"))
#+END_SRC
2022-02-09 11:09:47 +00:00
** dired :file:
2022-01-13 20:04:37 +00:00
#+BEGIN_SRC emacs-lisp
2022-01-15 12:04:00 +00:00
(use-package dired
:init (add-hook 'dired-mode-hook 'turn-on-launch-mode)
2022-01-13 20:04:37 +00:00
:config
2022-01-15 12:04:00 +00:00
(setq dired-listing-switches
;; by date
;; "-cgGhlt --group-directories-first --time-style=long-iso"
;; by name
"-Achl --group-directories-first --time-style=long-iso"
;; no -h
;; "-cgGl --group-directories-first --time-style=long-iso"
2022-01-13 20:04:37 +00:00
2022-01-15 12:04:00 +00:00
;; by date, no --group-directories-first
;; "-cgGhlt --time-style=long-iso"
2022-02-09 11:09:47 +00:00
dired-bind-info nil)
2022-01-15 12:04:00 +00:00
:bind
(:map dired-mode-map
("W" . wdired-change-to-wdired-mode)
("e" . #'cp/dired-do-ediff)
;; after learning that this copies whole paths with null
;; argument, this became a whole lot more useful
("C-w" . dired-copy-filename-as-kill)
("C-c C-f" . cp/corresponding-text-file)
("h" . dired-hide-dotfiles-mode)
([mouse-2] . cp/dired-launch-or-open)
("C-j" . launch-files-dired)
("j" . launch-files-dired)
("M-s r" . dired-do-query-replace-regexp)
("M-s s" . dired-do-isearch-regexp)
("P" . emms-play-dired)
("X" . dired-do-flagged-delete)
("M-n" . dired-next-marked-file)
("M-p" . dired-prev-marked-file)
("I" . sxiv)
("c" . dired-previous-line)
("r" . dired-next-line))
:hook
(dired-mode . (lambda () (dired-hide-details-mode t)))
(dired-mode . auto-revert-mode))
(use-package dired-async
:init (dired-async-mode 1))
(use-package dired-x
:commands (dired-jump dired-omit-mode)
:bind
("C-x C-d" . dired-jump)
(:map dired-mode-map
("H" . dired-omit-mode)
("I" . sxiv)))
#+END_SRC
2022-01-13 17:32:35 +00:00
#+BEGIN_SRC emacs-lisp
2022-01-15 12:04:00 +00:00
;; TODO - make launch-file suggest the path at point by default
(use-package launch
:commands turn-on-launch-mode launch-files-dired
:bind ("s-l" . launch-file))
2022-01-13 17:32:35 +00:00
#+END_SRC
2022-01-15 11:50:48 +00:00
#+BEGIN_SRC emacs-lisp
2022-01-15 12:04:00 +00:00
(defun cp/open-random-file (&optional find-args dir cmd)
"Open a random file in DIR, prompting the user for it if not supplied."
(interactive)
(let* ((find-args (if find-args find-args " -type f "))
(dir (if dir dir
(read-directory-name "Directory: "
(if file-name-history
(car file-name-history)
default-directory)
nil t)))
(file-name (--> (expand-file-name dir)
(concat "find " "\"" it "\" "
find-args " | shuf | sed 1q")
(shell-command-to-string it)
(replace-regexp-in-string "\n" "" it))))
(if cmd
(async-shell-command (concat cmd " \"" file-name "\""))
(find-file file-name))))
2022-01-15 11:50:48 +00:00
#+END_SRC
2021-02-18 09:31:40 +00:00
#+BEGIN_SRC emacs-lisp
2022-01-15 12:04:00 +00:00
;; (with-eval-after-load 'project-explorer
;; (global-set-key (kbd "<f5> e") 'project-explorer-toggle))
2021-02-18 09:31:40 +00:00
2022-01-15 12:04:00 +00:00
(use-package dired-hide-dotfiles
:hook (dired-mode . (lambda () (dired-hide-dotfiles-mode))))
2021-08-01 07:57:08 +00:00
2022-01-15 12:04:00 +00:00
;; (require 'sudo-edit)
2022-01-15 12:04:00 +00:00
(defun cp/dired-do-ediff (&optional format)
"Ediff (first two or three) marked files."
(interactive)
(let* ((files (dired-get-marked-files t))
(file-1 (car files))
(files-dir default-directory))
;; 2018-04-08T11:31:20+0530 TODO - if there is only one marked
;; file, check the other window for a marked file and ediff with
;; that.
(cl-case (length files)
(1 (progn
(other-window 1)
(let ((files2 (dired-get-marked-files t))
(files2-dir default-directory))
(if files2
(ediff (expand-file-name
(concat files-dir (car files)))
(expand-file-name
(concat files2-dir (car files2))))))))
(2 (ediff file-1 (cadr files)))
(t (ediff3 file-1 (cadr files) (elt files 2))))))
2021-08-01 07:57:08 +00:00
2022-01-15 12:04:00 +00:00
(defun cp/change-all-units ()
"for fdupes output"
(interactive)
(while (re-search-forward "^[0-9]+" nil t)
(shell-command-on-region (point-at-bol) (point) "numfmt --to=iec-i --suffix=B" nil t)
(forward-word)
(delete-region (point) (progn (forward-word) (point)))))
2021-08-01 07:57:08 +00:00
2022-01-15 12:04:00 +00:00
(defun cp/launch-file-archive ()
(interactive)
(launch-file
(concat
default-directory
(aref (archive-get-descr) 0))))
2022-01-06 05:39:23 +00:00
2022-01-15 12:04:00 +00:00
;; (define-key archive-mode-map (kbd "j") 'cp/launch-file-archive)
2022-01-06 05:39:23 +00:00
2022-01-15 12:04:00 +00:00
;; 2018-02-28T21:00:57+0530
(defun cp/corresponding-text-file ()
(interactive)
(save-excursion
(end-of-line)
(if (derived-mode-p 'dired-mode)
;; 2018-08-05T02:01:26+0530 - support directories too
(let* ((file-or-dir (dired-file-name-at-point))
(file (if (file-directory-p file-or-dir)
(replace-regexp-in-string "/$" "" file-or-dir)
file-or-dir)))
(find-file (concat file ".txt"))))))
2022-01-06 05:39:23 +00:00
2022-01-15 12:04:00 +00:00
;; 2018-07-09T23:22:17+0530
;; a little buggy wrt clicks
(defun cp/dired-launch-or-open (event)
(interactive "e")
;; if point is on a folder, open it with dired
;; otherwise, call launch-files-dired
(if (directory-name-p (dired-file-name-at-point))
(dired-find-file)
(launch-files-dired nil (dired-get-marked-files))))
2021-02-19 23:25:55 +00:00
2022-01-15 12:04:00 +00:00
(defun contrapunctus-delete-file-at-point (&optional prefix)
(interactive "P")
(let ((file (buffer-substring (point-at-bol) (point-at-eol))))
(if (file-exists-p file)
(progn
(delete-file file)
(if prefix
;; delete current line
(delete-region (point-at-bol)
(1+ (point-at-eol)))
;; delete current paragraph
(mark-paragraph)
(delete-active-region)
(forward-line 2))
(message "Deleted %s" file))
(error "File %s does not exist!" file))))
2021-02-19 23:25:55 +00:00
2022-01-15 12:04:00 +00:00
(defun contrapunctus-file-at-point-exists-p ()
(interactive)
(let ((file (buffer-substring (point-at-bol)
(point-at-eol))))
(if (and (not (string-empty-p file))
(file-exists-p file))
(message "%s" t)
(error "File %S does not exist!" file))))
2021-02-19 23:25:55 +00:00
#+END_SRC
2022-01-15 12:04:00 +00:00
2022-01-16 07:39:58 +00:00
** peep-dired :disabled:file:ui:
2022-01-15 12:04:00 +00:00
:PROPERTIES:
:CREATED: 2022-01-14T18:57:56+0530
:END:
2021-07-31 15:04:44 +00:00
#+BEGIN_SRC emacs-lisp
2022-01-15 12:04:00 +00:00
(use-package peep-dired
:disabled
;; ;; didn't work too well 🤔
;; :config
;; (setq peep-dired-cleanup-eagerly t)
:hook
(dired-mode . peep-dired))
2021-07-31 15:04:44 +00:00
#+END_SRC
2022-01-15 12:04:00 +00:00
2021-08-17 09:28:15 +00:00
#+BEGIN_SRC emacs-lisp
2022-01-15 12:04:00 +00:00
(defun contrapunctus-rename-this-file ()
(interactive)
(rename-file ;; message "will rename %s to %s"
(buffer-file-name (current-buffer))
(read-file-name "New name: " nil nil nil
(file-name-nondirectory
(buffer-file-name (current-buffer)))))
;; (rename-file (buffer-file-name (current-buffer)) new-name)
)
2021-08-17 09:28:15 +00:00
#+END_SRC
2022-01-15 04:58:59 +00:00
2022-01-15 12:04:00 +00:00
** backup configuration
#+BEGIN_SRC emacs-lisp
2022-01-15 12:04:00 +00:00
(setq backup-by-copying t
backup-directory-alist '(("." . "~/.emacs.d/saves/"))
kept-new-versions 50
kept-old-versions 50
version-control t
delete-old-versions t)
#+END_SRC
2022-01-17 06:01:00 +00:00
** async-backup (backup on save) :file:vc:
2022-01-15 12:04:00 +00:00
:PROPERTIES:
:CREATED: 2022-01-14T16:38:38+0530
:CUSTOM_ID: async-backup
:END:
#+BEGIN_SRC emacs-lisp
2022-01-15 12:04:00 +00:00
(use-package async-backup
:ensure t
:config (setq async-backup-location
"/media/data/anon/backups/emacs-async-backup/"))
#+END_SRC
2022-01-15 07:21:54 +00:00
2022-01-16 07:39:58 +00:00
** mail :communication:
2022-01-15 12:04:00 +00:00
*** wanderlust :disabled:
:PROPERTIES:
:CREATED: 2022-01-14T18:58:32+0530
:END:
#+BEGIN_SRC emacs-lisp
2022-01-15 12:04:00 +00:00
(use-package wl
:disabled
:config
(setq wl-icon-directory "~/.emacs.d/wl/icons"
wl-smtp-posting-server "disroot.org"))
#+END_SRC
2022-01-15 12:04:00 +00:00
*** mew :disabled:
:PROPERTIES:
:CREATED: 2022-01-14T18:58:53+0530
:END:
#+BEGIN_SRC emacs-lisp
(use-package mew
:disabled
:config
(setq mew-user "contrapunctus"
mew-name mew-user
mew-mail-domain "disroot.org"
mew-proto "%"
mew-smtp-server mew-mail-domain
mew-imap-server mew-mail-domain))
#+END_SRC
2022-01-15 12:04:00 +00:00
*** gnus
:PROPERTIES:
:CREATED: 2022-01-14T18:58:56+0530
:END:
#+BEGIN_SRC emacs-lisp
(use-package gnus
:init ;; I composed an email without loading Gnus, and it wasn't
;; saved in my sent folder; here's hoping that changing :config to
;; :init will do it.
(setq gnus-select-method '(nnnil "")
gnus-secondary-select-methods '((nnml "")
(nnimap "disroot.org")
;; (nnimap "imap.gmail.com"
;; (nnimap-stream starttls))
)
user-mail-address "contrapunctus@disroot.org"
user-full-name "contrapunctus"
gnus-mime-display-multipart-related-as-mixed t
smiley-style 'medium
message-send-mail-function 'smtpmail-send-it
;; gnus-message-archive-method '(nnimap "disroot.org")
gnus-message-archive-group "nnimap+disroot.org:Sent"))
2021-02-19 08:13:53 +00:00
2022-01-15 12:04:00 +00:00
(use-package message
:hook
(message-mode . (lambda () (auto-fill-mode -1)))
(message-mode . visual-fill-column-mode))
2021-09-22 03:53:03 +00:00
#+END_SRC
2021-08-01 07:57:08 +00:00
2022-02-06 18:34:14 +00:00
*** mu4e
#+BEGIN_SRC emacs-lisp
(use-package mu4e
:bind
(:map mu4e-headers-mode-map
("c" . #'mu4e-headers-prev)
("r" . #'mu4e-headers-next))
2022-02-08 07:53:55 +00:00
(:map mu4e-view-mode-map
("c" . #'mu4e-view-headers-prev)
("r" . #'mu4e-view-headers-next))
(:map gnus-mime-button-map
("c" . nil)
("r" . nil))
2022-02-06 18:34:14 +00:00
:config
2022-02-08 07:53:41 +00:00
(setq mu4e-get-mail-command "mbsync -aV"
2022-02-06 18:34:14 +00:00
mu4e-drafts-folder "/Drafts/"
mu4e-sent-folder "/Sent/"
2022-02-08 07:53:23 +00:00
mu4e-trash-folder "/Trash/"
;; Use vertico, not ido.
mu4e-completing-read-function #'completing-read))
2022-02-06 18:34:14 +00:00
#+END_SRC
2022-02-11 05:53:51 +00:00
**** mu4e-alert
#+BEGIN_SRC emacs-lisp
(use-package mu4e-alert
:ensure t
:init (mu4e-alert-enable-notifications))
#+END_SRC
**** mu4e-conversation
#+BEGIN_SRC emacs-lisp
(use-package mu4e-conversation
:disabled t
2022-02-11 05:53:51 +00:00
:ensure t
:after mu4e
:init (global-mu4e-conversation-mode))
#+END_SRC
2022-01-16 07:39:58 +00:00
** doc-view :viewer:
2021-09-22 03:53:03 +00:00
#+BEGIN_SRC emacs-lisp
2022-01-15 12:04:00 +00:00
(use-package doc-view
:config (setq doc-view-resolution 300))
#+END_SRC
2021-09-22 03:53:03 +00:00
2022-01-16 07:39:58 +00:00
** pdf-tools :viewer:
2021-02-19 20:40:34 +00:00
#+BEGIN_SRC emacs-lisp
2022-01-15 12:04:00 +00:00
(use-package pdf-tools
:ensure t
:init (pdf-tools-install)
:hook
(pdf-view-mode . auto-revert-mode)
(pdf-view-mode . pdf-view-midnight-minor-mode)
:bind
(:map pdf-view-mode-map
("h" . pdf-history-backward)
("s" . pdf-history-forward)
("c" . pdf-view-scroll-down-or-previous-page)
("r" . pdf-view-scroll-up-or-next-page)
("C-s" . isearch-forward)
("g" . pdf-view-first-page)
("l" . pdf-view-last-page))
:config
(setq-default pdf-view-display-size 'fit-width))
(use-package pdf-history
:bind
(:map pdf-history-minor-mode-map
("r" . nil)))
2021-02-19 20:40:34 +00:00
#+END_SRC
2022-01-16 07:39:58 +00:00
** nov.el :viewer:
2021-02-19 20:40:34 +00:00
#+BEGIN_SRC emacs-lisp
2022-01-15 12:04:00 +00:00
(use-package nov
:ensure t
:mode ("\\.epub\\'" . nov-mode)
:hook (nov-mode . visual-line-mode)
:bind
(:map nov-mode-map
;; make (Boon) c and r work even when point is in a link
("c" . nil)
("r" . nil)
("y" . nov-copy-url)
("c" . nov-previous-document)
("r" . nov-next-document)
("h" . nov-history-back)
("s" . nov-history-forward)
("T" . nov-goto-toc)
("m" . my-dispatch-hydra)))
2021-02-19 20:40:34 +00:00
#+END_SRC
2022-01-10 04:34:08 +00:00
2022-01-15 12:04:00 +00:00
** proced
2021-04-09 08:39:37 +00:00
#+BEGIN_SRC emacs-lisp
2022-01-15 12:04:00 +00:00
(use-package proced
:config
(setq-default proced-auto-update-flag t))
#+END_SRC
2021-04-09 08:39:37 +00:00
2022-01-15 12:04:00 +00:00
** webpaste
#+BEGIN_SRC emacs-lisp
(use-package webpaste
:ensure t
:config (setq webpaste-provider-priority
(delete "ix.io" (mapcar #'car webpaste-providers-alist))))
2021-04-09 08:39:37 +00:00
#+END_SRC
2022-01-10 04:34:08 +00:00
2022-01-16 07:39:58 +00:00
** eshell :shell:
#+BEGIN_SRC emacs-lisp
2022-01-15 12:04:00 +00:00
(use-package eshell
:config (setq eshell-history-size 999))
#+END_SRC
2022-01-10 04:34:08 +00:00
2022-01-16 07:39:58 +00:00
** comint :shell:
#+BEGIN_SRC emacs-lisp
2022-01-15 12:04:00 +00:00
(use-package comint
:bind (:map comint-mode-map
("M-p" . comint-history-isearch-backward-regexp) ;; QWERTY "r"
("M-c" . comint-previous-matching-input-from-input)
("M-r" . comint-next-matching-input-from-input)
("C-c C-s" . comint-next-prompt)
("C-c C-h" . comint-previous-prompt)))
#+END_SRC
2022-01-10 04:34:08 +00:00
2022-01-16 07:39:58 +00:00
** info :viewer:
#+BEGIN_SRC emacs-lisp
2022-01-15 12:04:00 +00:00
(use-package info
:config
(info-initialize)
(cl-loop for dir in
'("~/.emacs.d/info/"
"~/.emacs.d/elisp-git/geiser/doc/"
"~/lilypond/usr/share/info/")
do (add-to-list #'Info-directory-list dir))
:bind
(:map Info-mode-map
("b" . Info-history-back)
("f" . Info-history-forward)))
#+END_SRC
2022-01-10 04:34:08 +00:00
2022-01-16 07:39:58 +00:00
** image-mode :viewer:
2021-02-21 22:59:30 +00:00
#+BEGIN_SRC emacs-lisp
2022-01-15 12:04:00 +00:00
(use-package image-mode
:bind
(:map image-map
("c" . nil)
("r" . nil)
("o" . nil))
(:map image-mode-map
("c" . image-previous-file)
("r" . image-next-file)
("W" . image-transform-fit-to-width)
("H" . image-transform-fit-to-height)
("o" . nil)
("R" . contrapunctus-rename-this-file)))
2021-02-21 22:59:30 +00:00
#+END_SRC
2022-01-10 04:34:08 +00:00
2022-01-17 06:01:00 +00:00
** TODO magit [0%] :vc:
2022-01-15 12:04:00 +00:00
1. [ ] It'd be really cool to =(recenter 3)= when you /open/ a section, and =(recenter)= when you close a section
2. [ ] binding "c" to magit-section-backward and "j" to magit-commit means I can't nonchalantly hit "c c" to commit like before...it becomes "j c" :\
2021-08-03 01:00:22 +00:00
#+BEGIN_SRC emacs-lisp
2022-01-15 12:04:00 +00:00
(use-package magit
:ensure t
:bind (;; boon-like keys
:map magit-mode-map
("r" . magit-section-forward)
("c" . magit-section-backward)
("C" . magit-commit)
("R" . magit-rebase)
:map magit-diff-section-base-map
("C" . magit-commit)
("R" . magit-rebase)
:map magit-status-mode-map
;; ([mouse-3] . 'magit-section-toggle)
([down-mouse-3] . 'mouse-set-point)
([up-mouse-3] . 'magit-section-toggle)
("C" . magit-commit))
:commands magit-status
:hook
(magit-mode . visual-line-mode)
(magit-post-stage . (lambda () (recenter)))
:config
(cl-loop for symbol in '(magit-section-toggle
magit-section-forward
magit-section-backward)
do (advice-add symbol :after (lambda (&rest r) (recenter 3))))
;; (advice-add 'magit-unstage-item :after (lambda (&rest r) (next-line)))
)
2021-08-03 01:00:22 +00:00
#+END_SRC
2022-01-10 04:34:08 +00:00
2022-01-17 06:01:00 +00:00
** git-commit :vc:
:PROPERTIES:
2022-01-15 12:04:00 +00:00
:CREATED: 2022-01-14T16:36:44+0530
:END:
#+BEGIN_SRC emacs-lisp
2022-01-15 12:04:00 +00:00
(use-package git-commit
2022-01-17 06:01:00 +00:00
:ensure t
2022-01-15 12:04:00 +00:00
:bind
(:map git-commit-mode-map
("M-c" . git-commit-prev-message)
("M-r" . git-commit-next-message)))
#+END_SRC
2021-08-03 01:00:22 +00:00
2022-01-15 12:04:00 +00:00
* Completion
:PROPERTIES:
:CREATED: 2022-01-13T20:39:41+0530
2022-01-15 20:39:07 +00:00
:CUSTOM_ID: completion
2022-01-15 12:04:00 +00:00
:END:
2022-01-15 20:41:22 +00:00
The =initials= completion style is excellent! Instead of typing =(w-o-t-t|<TAB>)= to get =(with-output-to-temp-buffer|)=, you can just type =(wott|<TAB>)=.
2022-01-15 12:04:00 +00:00
But with =initials=, the desired completion is often buried in the results. That is where =prescient= shines - it remembers your input text and ranks previously-selected suggestions higher.
#+BEGIN_SRC emacs-lisp
2022-01-15 12:04:00 +00:00
(use-package emacs
:config
(setq tags-add-tables nil ;; don't prompt me for tag tables
completion-styles '(initials orderless substring partial-completion emacs22)
completion-cycle-threshold t))
#+END_SRC
=intials= is great for code (or at least Lisp code), but I prefer =orderless= for command names. It is basically the same as Ivy/Counsel completion, as far as I can make out.
** orderless
:PROPERTIES:
:CREATED: 2022-01-13T17:31:53+0530
2022-01-15 20:39:07 +00:00
:CUSTOM_ID: orderless
:END:
#+BEGIN_SRC emacs-lisp
(use-package orderless)
#+END_SRC
2022-01-15 12:04:00 +00:00
** company
:PROPERTIES:
:CREATED: 2022-01-05T20:16:03+0530
2022-01-15 20:39:07 +00:00
:CUSTOM_ID: company
2022-01-15 12:04:00 +00:00
:END:
#+BEGIN_SRC emacs-lisp
2022-01-15 12:04:00 +00:00
(use-package company
:ensure t
:diminish company-mode
2022-02-09 16:32:39 +00:00
:hook
(prog-mode . company-mode)
(tex-mode . company-mode)
(special-mode . company-mode)
(comint-mode . company-mode)
2022-01-15 12:04:00 +00:00
(slime-repl-mode . company-mode)
2022-01-21 18:16:48 +00:00
:bind
("TAB" . #'company-indent-or-complete-common)
("C-i" . #'company-indent-or-complete-common)
2022-01-15 12:04:00 +00:00
(:map company-active-map
("C-c" . company-select-previous)
("C-r" . company-select-next)
("C-h" . backward-delete-char)
("C-w" . backward-kill-word)
;; the following is necessary to shadow the window-switching
;; keybindings on the same keys
("C-1" . company-complete-quick-access)
("C-2" . company-complete-quick-access)
("C-3" . company-complete-quick-access)
("C-4" . company-complete-quick-access)
("C-5" . company-complete-quick-access)
("C-6" . company-complete-quick-access)
("C-7" . company-complete-quick-access)
("C-8" . company-complete-quick-access)
("C-9" . company-complete-quick-access)
2022-01-19 18:51:30 +00:00
("C-0" . company-complete-quick-access)
("<tab>" . #'company-complete-common-or-cycle)
("TAB" . #'company-complete-common-or-cycle)
("C-i" . #'company-complete-common-or-cycle))
2022-01-15 12:04:00 +00:00
;; Error (use-package): company/:catch: Symbols value as variable is void: c-mode-map
;; (:map c-mode-map
;; ("TAB" . company-indent-or-complete-common)
;; ("C-i" . company-indent-or-complete-common))
:config
(add-to-list 'company-backends 'company-irony)
2022-01-22 14:40:40 +00:00
(setq company-show-quick-access t
company-idle-delay nil) ;; do not pop up suggestions automatically
2022-01-15 12:04:00 +00:00
(customize-set-variable company-quick-access-modifier 'control))
2021-02-18 09:31:40 +00:00
#+END_SRC
2022-01-15 12:04:00 +00:00
** company-emoji
2022-01-15 20:39:07 +00:00
:PROPERTIES:
:CUSTOM_ID: company-emoji
:END:
#+BEGIN_SRC emacs-lisp
2022-01-15 12:04:00 +00:00
(use-package company-emoji
:ensure t
:hook (text-mode . company-emoji-init)
:config (add-to-list 'company-backends 'company-emoji))
#+END_SRC
2022-01-06 05:37:46 +00:00
2022-01-15 12:04:00 +00:00
** company-prescient
:PROPERTIES:
:CREATED: 2022-01-13T22:42:28+0530
2022-01-15 20:39:07 +00:00
:CUSTOM_ID: company-prescient
2022-01-15 12:04:00 +00:00
:END:
2022-01-06 05:37:46 +00:00
#+BEGIN_SRC emacs-lisp
2022-01-15 12:04:00 +00:00
(use-package company-prescient
:ensure t
:init (company-prescient-mode)
(prescient-persist-mode))
#+END_SRC
2022-01-06 05:37:46 +00:00
2022-01-15 12:04:00 +00:00
** yasnippet
:PROPERTIES:
:CREATED: 2022-01-05T20:16:31+0530
2022-01-15 20:39:07 +00:00
:CUSTOM_ID: yasnippet
2022-01-15 12:04:00 +00:00
:END:
#+BEGIN_SRC emacs-lisp
(use-package yasnippet
:ensure t
:commands (yas-expand-snippet)
:hook (prog-mode . yas-minor-mode-on)
2022-01-27 17:57:31 +00:00
(comint-mode . yas-minor-mode-on)
(slime-repl-mode . yas-minor-mode-on)
:bind (:map yas-minor-mode-map
2022-01-22 14:41:11 +00:00
("<tab>" . nil) ("TAB" . nil) ;; use TAB only for completion
("C-n" . #'yas-expand))
(:map yas-keymap
("C-n" . #'yas-next-field-or-maybe-expand)))
2022-01-06 05:37:46 +00:00
#+END_SRC
** vertico
:PROPERTIES:
:CREATED: 2022-01-15T18:44:49+0530
2022-01-15 20:39:07 +00:00
:CUSTOM_ID: vertico
:END:
#+BEGIN_SRC emacs-lisp
(use-package vertico
:ensure t
:init (vertico-mode)
(vertico-indexed-mode)
(vertico-multiform-mode)
2022-01-27 17:58:14 +00:00
(vertico-mouse-mode)
;; Different scroll margin
;; (setq vertico-scroll-margin 0)
;; Show more candidates
;; (setq vertico-count 20)
;; Grow and shrink the Vertico minibuffer
;; (setq vertico-resize t)
:bind (:map vertico-map
("C-h" . #'vertico-directory-delete-char)
("<backspace>" . #'vertico-directory-delete-char)
("C-w" . #'vertico-directory-delete-word)
("<C-backspace>" . #'vertico-directory-delete-word)
("<prior>" . #'vertico-scroll-down)
("<next>" . #'vertico-scroll-up))
:config
(setq completion-category-defaults nil
completion-category-overrides nil
vertico-multiform-commands
'((chronometrist-toggle-task (vertico-sort-function . nil))
(chronometrist-toggle-task-no-hooks (vertico-sort-function . nil))
(chronometrist-toggle-task-button (vertico-sort-function . nil))
2022-02-08 07:57:14 +00:00
(chronometrist-key-values-unified-prompt (vertico-sort-function . nil))
(consult-line (vertico-sort-function . nil))
(my-consult-line (vertico-sort-function . nil)))))
#+END_SRC
#+BEGIN_SRC emacs-lisp
;; Persist history over Emacs restarts. Vertico sorts by history position.
(use-package savehist
:init (savehist-mode))
#+END_SRC
#+BEGIN_SRC emacs-lisp
;; A few more useful configurations...
(use-package emacs
:init
;; Add prompt indicator to `completing-read-multiple'.
;; Alternatively try `consult-completing-read-multiple'.
(defun crm-indicator (args)
(cons (concat "[CRM] " (car args)) (cdr args)))
(advice-add #'completing-read-multiple :filter-args #'crm-indicator)
;; Do not allow the cursor in the minibuffer prompt
(setq minibuffer-prompt-properties
'(read-only t cursor-intangible t face minibuffer-prompt))
(add-hook 'minibuffer-setup-hook #'cursor-intangible-mode)
;; Emacs 28: Hide commands in M-x which do not work in the current mode.
;; Vertico commands are hidden in normal buffers.
;; (setq read-extended-command-predicate
;; #'command-completion-default-include-p)
;; Enable recursive minibuffers
(setq enable-recursive-minibuffers t))
#+END_SRC
** consult
:PROPERTIES:
:CREATED: 2022-01-15T21:32:45+0530
2022-01-15 20:39:07 +00:00
:CUSTOM_ID: consult
:END:
#+BEGIN_SRC emacs-lisp
(use-package consult
:ensure t)
(defun my-consult-line ()
"Like `consult-line', but use symbol at point or active region."
(interactive)
(let ((string (cond ((region-active-p)
(buffer-substring-no-properties (region-beginning) (region-end)))
((or (thing-at-point 'symbol)
(thing-at-point 'url)
(thing-at-point 'word)))
(t nil))))
(consult-line string)))
#+END_SRC
** counsel :disabled:
2022-01-15 13:12:43 +00:00
#+BEGIN_SRC emacs-lisp
(use-package counsel
:disabled t
2022-01-15 13:12:43 +00:00
:ensure t
:bind ("M-x" . counsel-M-x)
:config
(setq counsel-find-file-ignore-regexp "\\`\\."))
#+END_SRC
** ivy :disabled:
2022-01-15 13:12:43 +00:00
#+BEGIN_SRC emacs-lisp
(use-package ivy
:disabled t
2022-01-15 13:12:43 +00:00
:ensure t
:commands ivy-mode
:init (ivy-rich-mode) ;; display command docstrings in `counsel-M-x'
:bind (:map ivy-minibuffer-map
("C-h" . ivy-backward-delete-char)
("C-c" . previous-line)
("C-r" . next-line)
("M-c" . ivy-previous-history-element)
("M-r" . ivy-next-history-element))
:config
(setq ivy-re-builders-alist
'((t . ivy--regex-ignore-order))))
#+END_SRC
** ivy-xref :disabled:
2022-01-15 13:12:43 +00:00
#+BEGIN_SRC emacs-lisp
(use-package ivy-xref
:disabled t
2022-01-15 13:12:43 +00:00
:ensure t
:config
(setq xref-show-definitions-function #'ivy-xref-show-defs))
#+END_SRC
** flx-ido :disabled:
#+BEGIN_SRC emacs-lisp
(use-package flx-ido
:disabled
:init (flx-ido-mode 1)
(setq ido-enable-flex-matching t
ido-use-faces nil))
#+END_SRC
** flx-isearch :disabled:
#+BEGIN_SRC emacs-lisp
(use-package flx-isearch
:disabled
:bind
("C-s" . #'flx-isearch-forward)
("C-r" . #'flx-isearch-backward))
;; (use-package flycheck
;; :init (global-flycheck-mode))
;; (use-package flycheck-elsa
;; :hook (emacs-lisp-mode . flycheck-elsa-setup))
#+END_SRC
** flex-isearch :disabled:
:PROPERTIES:
:CREATED: 2022-01-13T20:50:41+0530
:END:
#+BEGIN_SRC emacs-lisp
(use-package flex-isearch
:disabled t
:init (flex-isearch-mode 1)
:bind
("C-M-s" . flex-isearch-forward)
("C-M-r" . flex-isearch-backward))
#+END_SRC
** bookmarks
#+BEGIN_SRC emacs-lisp
(use-package bookmark
:config (setq bookmark-save-flag 1))
#+END_SRC
** recentf
#+BEGIN_SRC emacs-lisp
(use-package recentf
:init
;; default is to cleanup when `recentf-mode' is enabled, which we don't want
(setq recentf-auto-cleanup 'never)
(recentf-mode 1)
:bind ("C-x C-r C-o" . recentf-open-files)
:config
(setq recentf-max-menu-items 500
recentf-max-saved-items 1000
recentf-save-file (locate-user-emacs-file "recentf")
recentf-exclude '("\\.html\\(\\.orig\\)?$"
"\\.jpe?g$"
"\\.png$"
"\\.mp4$"
"\\.etc"
"\\.umstuff"))
(advice-add 'recentf-save-list :before (lambda (&rest args) (async-backup recentf-save-file)))
;; I'd rather run cleanup manually, if ever required; running
;; cleanup automatically is a recipe for periodically losing your
;; recentf entries when your disk happens to be unmounted.
;; :hook (kill-emacs . recentf-cleanup)
)
#+END_SRC
2022-01-15 12:04:00 +00:00
* misc keybindings
#+BEGIN_SRC emacs-lisp
(global-set-key (kbd "M-w") 'kill-ring-save)
(define-key emacs-lisp-mode-map (kbd "M-w") nil)
;; ;; M-d is useful in the minibuffer
;; (define-key emacs-lisp-mode-map (kbd "M-d") nil)
;; (global-set-key (kbd "M-d") 'easy-kill-delete-region)
#+END_SRC
* environment variables
#+BEGIN_SRC emacs-lisp
2021-11-18 09:29:49 +00:00
(setenv "PATH" (concat "~/bin:" (getenv "PATH")))
(setenv "EDITOR" "emacsclient")
;; what on earth is this message after every init -
;; ad-handle-definition: `tramp-read-passwd' got redefined
;; ;; (profiler-start 'cpu)
;; (toggle-debug-on-error)
;; ;; (toggle-debug-on-quit)
#+END_SRC
* Linewrapping
#+BEGIN_SRC emacs-lisp
(add-hook 'erc-mode-hook 'visual-line-mode)
(add-hook 'text-mode-hook 'visual-line-mode)
2021-06-06 02:11:21 +00:00
(use-package visual-fill-column
:ensure t
2021-06-06 02:11:21 +00:00
:hook
(markdown-mode . visual-fill-column-mode)
(markdown-mode . visual-line-mode)
2021-07-06 01:12:44 +00:00
(org-mode . visual-line-mode)
;; (org-mode . visual-fill-column-mode)
(message-mode . visual-fill-column-mode))
2021-06-06 02:11:21 +00:00
(use-package adaptive-wrap
:ensure t
:hook (markdown-mode . adaptive-wrap-prefix-mode))
#+END_SRC
* Navigation
2021-08-03 01:12:05 +00:00
#+BEGIN_SRC emacs-lisp
;; (require 'view)
;; (cp-set-keys
;; :bindings
;; `((,(kbd "C-v") View-scroll-half-page-forward)
;; (,(kbd "M-v") View-scroll-half-page-backward)))
;; ;; (cp-set-keys
;; ;; :bindings
;; ;; `((,(kbd "C-v") scroll-up)
;; ;; (,(kbd "M-v") scroll-down)))
;;;; Need to make maps for
;;;; mark-* commands (-sexp, -page, -word, etc)
;;;; mark ring
;;;; Other custom keys
(bind-keys
("C-x C-1" . delete-other-windows)
("C-x C-2" . split-window-below)
("C-x C-3" . split-window-right)
("C-x C-0" . delete-window)
("C-x C-4 C-f" . find-file-other-window)
;; ("C-`" . point-to-register)
;; ("C-'" . jump-to-register)
("C-x C-d" . dired-jump)
;; I usually keep Super for the window manager and global hotkeys...
("s-i" . imenu)
;; keypad
;; set this to run whatever command is bound to C-c C-c, or maybe just C-c
;; see (info "(elisp)Translation Keymaps")
)
(with-eval-after-load 'dired
(define-key dired-mode-map (kbd "b") 'dired-up-directory)
;; (add-hook 'dired-mode-hook 'visual-line-mode)
;(global-set-key (kbd "C-,") 'string-rectangle 'TAB)
)
(global-unset-key (kbd "C-x d"))
;; (require 'dired-toggle-sudo)
;; (define-key dired-mode-map (kbd "C-c C-s") 'dired-toggle-sudo)
;; (eval-after-load 'tramp
;; '(progn
;; ;; Allow to use: /sudo:user@host:/path/to/file
;; (add-to-list 'tramp-default-proxies-alist
;; '(".*" "\\`.+\\'" "/ssh:%h:"))))
(global-set-key (kbd "C-x df") 'delete-frame)
;;;; make-frame key is after Helm's config
;(setq compilation-read-command nil)
(defun cp-open-init ()
"Open the init.el file."
(interactive)
(find-file "~/.emacs.d/init.el"))
;; todo - store current file name → kill the buffer →
;; find-file-literally with the stored filename. also, find out if you
;; can open it without modes but with the proper encoding.
(defun cp-fcf-literally ()
"Find the current file literally. Like find-file-literally but
does not prompt for a file name."
(interactive)
(find-file-literally (buffer-file-name)))
(defun cp-kill-buffer ()
"Kill the current buffer without prompting."
(interactive)
(kill-buffer nil))
(use-package ibuffer
:bind (("C-x C-b" . ibuffer)
:map ibuffer-mode-map
("m" . nil)
("U" . nil)
("m f" . ibuffer-mark-by-file-name-regexp)
("m m" . ibuffer-mark-by-mode-regexp)
("m n" . ibuffer-mark-by-name-regexp)
("M" . ibuffer-mark-forward)
("r" . ibuffer-do-replace-regexp)
("U" . ibuffer-unmark-all))
:hook (ibuffer-mode . ibuffer-set-filter-groups-by-mode))
;; (require 'win-switch)
;; (global-set-key "\C-xo" 'win-switch-dispatch)
;; (win-switch-setup-keys-ijkl)
;; (setq win-switch-idle-time 0.5)
;; (setq win-switch-other-window-first nil)
;; ;(setq win-switch-other-window-first nil)
(use-package window-numbering
:ensure t
:commands (window-numbering-mode)
:init (window-numbering-mode 1)
:bind (:map window-numbering-keymap
("M-1" . nil) ("M-2" . nil) ("M-3" . nil)
("M-4" . nil) ("M-5" . nil) ("M-6" . nil)
("M-7" . nil) ("M-8" . nil) ("M-9" . nil)
("C-1" . select-window-1)
("C-2" . select-window-2)
("C-3" . select-window-3)
("C-4" . select-window-4)
("C-5" . select-window-5)
("C-6" . select-window-6)
;; for one-handed operation with the right hand
("C-7" . select-window-1)
("C-8" . select-window-2)
("C-9" . select-window-3)))
(defun cp-maximize-window ()
"Run maximize-window if more than one window is present."
(interactive)
(if (> (length (window-list)) 1)
(maximize-window)))
(defun cp-minimize-window ()
"Run minimize-window if more than one window is present."
(interactive)
(if (> (length (window-list)) 1)
(minimize-window)))
(with-eval-after-load 'doc-view
(define-key doc-view-mode-map (kbd "=") 'doc-view-fit-height-to-window))
(use-package view-mode
:bind
(:map view-mode-map
("x" . nil)
("<backspace>" . scroll-down-command)
("SPC" . scroll-up-command)))
(use-package avy
:ensure t
:config
(setq avy-case-fold-search nil))
#+END_SRC
2022-01-16 09:57:22 +00:00
** ido-mini :disabled:buffer:file:
:PROPERTIES:
:CUSTOM_ID: ido-mini
:END:
This needs to be before =boon=/=exwm=, or you get a "failed to define function ido-mini" error when you press the keybinding.
#+BEGIN_SRC emacs-lisp
(use-package ido-mini
:disabled t
:demand
:load-path "~/.emacs.d/contrapunctus/ido-mini/"
:bind ("C-x C-l" . ido-mini))
#+END_SRC
** outline-minor-mode
#+BEGIN_SRC emacs-lisp
(use-package outline
:hook (adoc-mode . outline-minor-mode)
(gemini-mode . outline-minor-mode)
;; Does this cause this error?
;; Polymode error (pm--mode-setup org-mode): recentering a window that does not display current-buffer.
;; (outline-view-change . (lambda () (recenter 3)))
:bind (:map outline-minor-mode-map
("TAB" . contrapunctus-outline-indent-or-toggle-children)
;; this (rather than `outline-show-children') seems to
;; be the equivalent of `org-show-subtree'
("C-c C-k" . outline-show-branches)
;; wow, in adoc-mode these also replace the first letter of the heading with an "e"... 😒
;; ("C-c ," . outline-promote)
;; ("C-c ." . outline-demote)
)
("C-c ," . adoc-demote)
("C-c ." . adoc-promote)
("C-c C-c" . outline-previous-heading)
("C-c C-r" . outline-next-heading)
("C-c C-h" . nil)
("C-c C-h" . outline-up-heading))
#+END_SRC
#+BEGIN_SRC emacs-lisp
(defun contrapunctus-outline-indent-or-toggle-children ()
(interactive)
(if (save-excursion
(goto-char (point-at-bol))
(looking-at-p outline-regexp))
(outline-toggle-children)
(indent-for-tab-command)))
#+END_SRC
2022-01-14 19:16:44 +00:00
** outshine
#+BEGIN_SRC emacs-lisp
(use-package outshine
2022-01-14 11:11:12 +00:00
:commands (outshine-mode outshine-cycle)
:hook (texinfo-mode . outshine-mode))
#+END_SRC
2022-01-14 19:16:44 +00:00
* scrolling
2022-01-14 11:11:12 +00:00
While we're at it, let's add that to next-error as well (this affects
jumping to match from M-x grep , too)
#+BEGIN_SRC emacs-lisp
(add-hook 'next-error-hook 'recenter)
#+END_SRC
* Buffer management
2021-08-01 08:53:03 +00:00
#+BEGIN_SRC emacs-lisp
(defun my-buffer-switch ()
(interactive)
(let ((buffers (remove-if (lambda (buffer)
(or (string-match-p "^ " (buffer-name buffer))
(get-buffer-window-list buffer)))
(buffer-list))))
(switch-to-buffer (first buffers))))
#+END_SRC
2022-01-16 07:39:58 +00:00
** ibuffer :buffer:
#+BEGIN_SRC emacs-lisp
(use-package ibuffer
:bind
(:map ibuffer-mode-map
("X" . 'ibuffer-do-kill-on-deletion-marks))) ;; Boon hijacks the x key.
#+END_SRC
#+BEGIN_SRC emacs-lisp
(general-define-key
"C-x k" 'cp-kill-buffer
"C-`" 'shell
"M-`" 'eshell
"M-<f2>" 'compile
"M-<f3>" 'run-chicken
"M-<f4>" 'run-lisp
"M-<f5>" 'ielm)
#+END_SRC
#+BEGIN_SRC emacs-lisp
(general-define-key
:prefix "<f1>"
"M" 'describe-mode
"m" 'man
"l" 'find-library)
#+END_SRC
#+BEGIN_SRC emacs-lisp
(general-define-key
:prefix "<f2>"
;; "<f2>" 'imenu
"<f2>" 'xref-find-definitions
"r" 'xref-find-references
"m" 'imenu
;; "p" 'grep
"o" 'find-grep
"i" 'find-dired
"h" 'proced)
#+END_SRC
#+BEGIN_SRC emacs-lisp
(general-define-key
:prefix "<f5>"
"<f5>" 'eval-buffer
"i" 'cp-open-init
"v" 'visual-line-mode
"f" 'cp-fcf-literally
"f" 'fundamental-mode
"t" 'text-mode
"T" 'cp-insert-timestamp
"d" 'cp-insert-date
"c" 'calendar
"p" 'list-packages)
#+END_SRC
#+BEGIN_SRC emacs-lisp
(general-define-key
;; [down-mouse-1] 'mouse-set-point
2022-01-14 11:11:12 +00:00
;; [up-mouse-1] 'er/expand-region
[s-mouse-3] 'bury-buffer
[mouse-8] 'delete-window
;; (kbd "<mouse-9>") 'keyboard-quit
;; [mouse-9] 'buffer-menu
[mouse-9] 'ibuffer
[C-mouse-9] 'recentf-open-files
[M-mouse-4] 'next-buffer
[M-mouse-5] 'previous-buffer
[M-mouse-8] 'split-window-right
[M-mouse-9] 'split-window-below
;; quitting from helm-mini - whether with keyboard-quit or
;; keyboard-escape-quit - "banishes" the mouse pointer to the
;; top-right corner!? wtf, helm.
;; (kbd "s-<mouse-9>") 'helm-mini
)
#+END_SRC
2022-01-14 11:11:12 +00:00
** midnight-mode (automatic buffer cleanup)
#+BEGIN_SRC emacs-lisp
2022-01-14 11:11:12 +00:00
(use-package midnight
:init
(midnight-mode)
:config
(setq clean-buffer-list-kill-regexps '("")
clean-buffer-list-delay-general 1
clean-buffer-list-delay-special (* 60 60 12))
(add-to-list 'clean-buffer-list-kill-never-buffer-names "Gajim")
:hook
(midnight . clean-buffer-list))
#+END_SRC
* browse-url
SLIME opens CLHS links in Firefox, but I'd rather open them in Tor Browser; Tor Browser, however, does not permit other applications to open tabs in a running instance. So I wrote this to copy the links automatically instead.
#+BEGIN_SRC emacs-lisp
(use-package browse-url
:config
(defun cp-copy-url (url &rest args)
(with-temp-buffer
(insert url)
(kill-ring-save (point-min) (point-max)))
(message "Copied %s to kill ring" url))
(setq browse-url-browser-function #'cp-copy-url))
#+END_SRC
2021-12-04 06:06:56 +00:00
2022-01-14 11:11:12 +00:00
* Markup
** Org
2021-02-18 05:26:52 +00:00
#+BEGIN_SRC emacs-lisp
(use-package org
:load-path "~/.emacs.d/elisp-git/org-mode"
:hook (org-mode . contrapunctus-disable-nameless-key)
(org-mode . auto-revert-mode)
2021-02-18 05:26:52 +00:00
:commands (org-drag-line-backward org-drag-line-forward)
2021-04-03 09:01:32 +00:00
:bind (("C-c C-h" . nil)
:map org-mode-map
("C-c C-c" . org-previous-visible-heading)
("C-c C-r" . org-next-visible-heading)
("C-c C-s" . org-forward-heading-same-level)
;; does not work...
("C-c C-h" . org-backward-heading-same-level)
2022-01-22 16:18:55 +00:00
("C-c C-j" . org-ctrl-c-ctrl-c) ;; "c c" in boon/dvorak
([mouse-1] . org-cycle)
("<C-tab>" . org-global-cycle))
2021-02-18 05:26:52 +00:00
:config
(general-def "<f5> o" 'org-mode)
(general-def org-mode-map
"C-," 'nil
"M-r" 'org-metadown
"M-c" 'org-metaup
2021-02-18 05:26:52 +00:00
"C-c C--" 'org-ctrl-c-minus
"C-c C-," 'org-metaleft
"C-c C-." 'org-metaright
;; "C-j" 'org-return
2021-04-03 09:01:32 +00:00
;; "C-m" 'org-return-indent
2021-02-18 05:26:52 +00:00
"C-c C-9" 'org-mark-ring-goto
"C-c C-/" 'org-sparse-tree
"C-M-x" 'cp/eval-sexp
2021-11-18 09:44:48 +00:00
"C-c C-o" 'my-org-open
2021-02-18 05:26:52 +00:00
;; boon
"C-c C--" 'org-ctrl-c-minus
"C-c ," 'org-metaleft
"C-c ." 'org-metaright
"M-h" 'default-indent-new-line)
2021-02-18 05:26:52 +00:00
(mapc (lambda (pair)
(add-to-list 'org-file-apps pair))
'(("txt" . emacs)
("org" . emacs)
2021-08-21 13:46:47 +00:00
("pdf" . emacs)
2021-02-18 05:26:52 +00:00
;; (t . "xdg-open %s")
))
(setq org-todo-keywords '((sequence "TODO" "RESEARCH" "STARTED" "DONE"))
org-image-actual-width 400
2021-02-18 05:26:52 +00:00
org-cycle-include-plain-lists 'integrate
org-link-search-must-match-exact-headline nil
org-html-head "<link rel=\"stylesheet\" type=\"text/css\" href=\"style.css\" />"
org-html-self-link-headlines t
2021-02-18 05:26:52 +00:00
org-export-default-inline-image-rule
`(("https" .
,(format "\\.%s\\'"
(regexp-opt
'("png" "jpeg" "jpg" "gif" "tiff" "tif" "xbm"
"xpm" "pbm" "pgm" "ppm" "webp") t)))
("file" .
,(format "\\.%s\\'"
(regexp-opt
'("png" "jpeg" "jpg" "gif" "tiff" "tif" "xbm"
2021-09-15 14:08:47 +00:00
"xpm" "pbm" "pgm" "ppm" "webp") t))))
org-link-file-path-type 'relative
;; https://emacs.stackexchange.com/questions/18877/how-to-indent-without-the-two-extra-spaces-at-the-beginning-of-code-blocks-in-or
org-edit-src-content-indentation 0
org-src-fontify-natively t
org-src-window-setup 'current-window
org-src-strip-leading-and-trailing-blank-lines t
org-src-preserve-indentation t
org-src-tab-acts-natively t)
(org-link-set-parameters "gemini" :export #'my-export-gemini-link)
(org-link-set-parameters "xmpp" :export #'my-export-xmpp-link))
(defun contrapunctus-disable-nameless-key ()
(define-key nameless-mode-map (kbd "C-c C--") nil))
#+END_SRC
2021-07-31 09:27:57 +00:00
*** gemini: and xmpp: links
https://lists.gnu.org/archive/html/emacs-orgmode/2018-02/msg00082.html
#+BEGIN_SRC emacs-lisp
(defun my-export-link-helper (link desc format)
(cond
((eq format 'html)
(format "<a href=\"%s\">%s</a>" link desc))
((eq format 'latex)
;; (format "\\href{%s}{%s}" link desc)
(format "\\url{%s}" link))
(t ;; `ascii', `md', `hugo', etc.
(format "[%s](%s)" desc link))))
#+END_SRC
#+BEGIN_SRC emacs-lisp
2021-07-29 18:01:24 +00:00
(defun my-export-gemini-link (link desc format)
"Create export version of LINK and DESC to FORMAT."
(let ((link (concat "gemini:" link)))
2021-07-31 09:27:57 +00:00
(my-export-link-helper link desc format)))
#+END_SRC
2021-07-31 09:27:57 +00:00
#+BEGIN_SRC emacs-lisp
2021-07-31 09:27:57 +00:00
(defun my-export-xmpp-link (link desc format)
"Create export version of LINK and DESC to FORMAT."
(let ((link (concat "xmpp:" link)))
(my-export-link-helper link desc format)))
#+END_SRC
2021-07-31 09:27:57 +00:00
*** my-org-insert-block
#+BEGIN_SRC emacs-lisp
(defun my-org-insert-block (type &optional lang header-args ask)
"Insert block of TYPE at point, or at beginning and end of region.
TYPE should be an Org block type, e.g. SRC, QUOTE, etc.
If TYPE is SRC, LANG should be the name of the language as a string, e.g. \"emacs-lisp\".
If LANG is not supplied, use the value of
`my-org-src-default-lang'. If `my-org-src-default-lang' is nil,
or with ASK, prompt the user for a language."
(let* ((src-block-p (equal type "SRC"))
(lang (cond ((stringp lang) lang)
((and (bound-and-true-p my-org-src-default-lang)
(stringp my-org-src-default-lang)
(not ask))
my-org-src-default-lang)
((and src-block-p (or (not lang) ask))
(completing-read "Source block language: "
(mapcar #'cl-first org-src-lang-modes)))
(t nil)))
(column (- (point) (point-at-bol)))
2021-11-28 05:18:56 +00:00
(indent (make-string column ?\s))
(start-string (format "#+BEGIN_%s %s%s\n" type
(if src-block-p lang "")
(if (and src-block-p header-args)
(format " %s" header-args)
"")))
2021-11-28 05:18:56 +00:00
(end-string (format "%s#+END_%s\n" indent type)))
;; create a block around a region - preserve position of point
(cond ((region-active-p)
2022-01-20 06:21:21 +00:00
(let ((region-start (region-beginning))
(region-end (region-end)))
(save-excursion
;; inserting at region-start would make region-end
;; invalid, so we insert at the end first
(goto-char region-end)
(insert end-string "\n")
(goto-char region-start)
(insert start-string))))
;; new empty block - insert the block syntax and place point
;; inside the block
(t (insert start-string)
(let ((point-inside-block (point)))
(insert "\n" end-string)
(goto-char point-inside-block)
(insert indent))))))
#+END_SRC
2021-02-18 05:26:52 +00:00
#+BEGIN_SRC emacs-lisp
2021-02-18 05:26:52 +00:00
;; (use-package org-src-mode
;; :hook (org-src-mode . (lambda () (when (derived-mode-p 'emacs-lisp-mode)))))
2021-08-01 07:57:08 +00:00
;; (defun my-org-hydra-expand-all ()
2021-02-18 05:26:52 +00:00
;; (interactive)
;; ;; todo - define inner recursive function
;; (beginning-of-buffer)
;; ;; todo - check if we are on a heading
;; (org-forward-heading-same-level)
;; ())
#+END_SRC
2021-02-18 05:26:52 +00:00
*** my-org-open
#+BEGIN_SRC emacs-lisp
2021-02-18 05:26:52 +00:00
;; I dislike having to navigate within a line to reach a link - with
;; this command I just need to be on the same line as the link.
2021-11-18 09:44:48 +00:00
(defun my-org-open (&optional arg reference-buffer)
2021-02-18 05:26:52 +00:00
(interactive "P")
(beginning-of-visual-line)
(unless (looking-at-p (rx-to-string '(or "http" "[")))
(org-next-link))
(org-open-at-point))
#+END_SRC
2021-02-18 05:26:52 +00:00
*** org-table-convert-tsv
#+BEGIN_SRC emacs-lisp
2021-02-18 05:26:52 +00:00
(defun cp/org-table-convert-tsv ()
(interactive)
(with-output-to-temp-buffer "cp/org-table-convert-tsv"
(->> (buffer-substring-no-properties (region-beginning) (region-end))
(replace-regexp-in-string "^| *" "")
(replace-regexp-in-string " *| *" " ")
(replace-regexp-in-string "^-.*$" "")))
(with-current-buffer "cp/org-table-convert-tsv"
(remove-hook 'before-save-hook 'delete-trailing-whitespace)
(write-file (read-from-minibuffer "Output filename: "))))
#+END_SRC
2021-02-18 05:26:52 +00:00
*** my-org-set-tags - using completing-read-multiple for setting tags
#+BEGIN_SRC emacs-lisp
(defun my-org-set-tags ()
2021-02-18 05:26:52 +00:00
(interactive)
(let ((all-tags (org-get-buffer-tags))
(current-tags (org-get-tags)))
(save-excursion
(org-back-to-heading)
(org-set-tags
(completing-read-multiple
"Tag: " all-tags nil 'confirm
(mapconcat #'identity current-tags ",")
'org-tags-history)))))
#+END_SRC
***
#+BEGIN_SRC emacs-lisp
(defun cp/marked-files->markup-links-org (filenames)
(mapcar (lambda (filename)
(let ((link-pre "[[file:")
(link-post "][]]\n"))
(concat link-pre filename link-post)))
filenames))
#+END_SRC
*** my-org-insert-timestamp
#+BEGIN_SRC emacs-lisp
(defun my-org-insert-timestamp ()
(save-excursion
(org-set-property "CREATED" (format-time-string "%FT%T%z"))))
(use-package org-indent
:hook (org-mode . org-indent-mode))
(with-eval-after-load 'ox
(require 'ox-texinfo)) ;; ideally, I'd load this in :before advice for org-export...
#+END_SRC
2021-09-22 03:53:03 +00:00
*** load org-babel languages on demand
2021-09-22 03:53:03 +00:00
From https://emacs.stackexchange.com/questions/20577/org-babel-load-all-languages-on-demand
2021-09-22 03:53:03 +00:00
#+BEGIN_SRC emacs-lisp
(defadvice org-babel-execute-src-block (around load-language nil activate)
"Load language if needed"
(let ((language (org-element-property :language (org-element-at-point))))
2021-09-22 03:55:01 +00:00
(unless (cdr (assoc (intern language)
org-babel-load-languages))
(add-to-list 'org-babel-load-languages
(cons (intern language) t))
(org-babel-do-load-languages 'org-babel-load-languages
org-babel-load-languages))
2021-09-22 03:53:03 +00:00
ad-do-it))
#+END_SRC
*** my-org-fix-newlines
#+BEGIN_SRC emacs-lisp
(defun my-org-fix-newlines ()
"Insert newlines around Org headings.
Newlines are inserted before headings (unless immediately
preceded by another heading) and after headings."
(interactive)
(org-map-tree
(lambda ()
(save-excursion
(forward-line -1)
(goto-char (point-at-bol))
(unless (or (looking-at-p "^$")
(org-at-heading-p))
(goto-char (point-at-eol))
(insert "\n")))
(save-excursion
(forward-line)
(goto-char (point-at-bol))
(when (looking-at-p "^$")
(join-line))))))
#+END_SRC
*** org-html-themify
#+BEGIN_SRC emacs-lisp
(use-package org-html-themify
:disabled t
:load-path "~/.emacs.d/elisp-git/org-html-themify/"
:load-path "~/.emacs.d/elisp-git/hexrgb/"
:hook (org-mode . org-html-themify-mode)
:config
(setq org-html-themify-themes
'((dark . doom-molokai))))
#+END_SRC
*** ox-publish
#+BEGIN_SRC emacs-lisp
(use-package ox-publish
:config
(require 'ox-gemini)
(setq org-publish-project-alist
'(("tilde.team-html"
:base-directory
"/media/data/anon/Documents/Text Files/homepage/contrapunctus/org/"
:publishing-directory
"/ssh:contrapunctus@tilde.team:/home/contrapunctus/public_html/"
:recursive t
:publishing-function org-html-publish-to-html)
("tilde.team-gmi"
:base-directory
"/media/data/anon/Documents/Text Files/homepage/contrapunctus/org/"
:publishing-directory
"/ssh:contrapunctus@tilde.team:/home/contrapunctus/public_gemini/"
:recursive t
:publishing-function org-gemini-publish-to-gemini))))
(defun my-org-publish-html (plist filename pub-dir)
)
#+END_SRC
** markdown-mode :editing:
#+BEGIN_SRC emacs-lisp
(use-package markdown-mode
:ensure t
:mode "\\.md\\'"
:hook
(markdown-mode . (lambda ()
(make-local-variable 'before-save-hook)
(add-hook 'before-save-hook 'markdown-cleanup-list-numbers)))
(markdown-mode . markdown-display-inline-images)
:config (setq markdown-command "cmark"
markdown-css-paths '("style.css")
markdown-display-remote-images t
markdown-max-image-size '(500 . 500)
;; reflows text to suit different screens
markdown-xhtml-header-content
(concat "<meta name=\"viewport\" "
"content=\"width=device-width, "
"initial-scale=1.0, "
"user-scalable=yes\" />"))
(when (featurep 'boon)
(general-def markdown-mode-map
"C-c ," 'markdown-promote
"C-c ." 'markdown-demote
"C-c C-e" 'markdown-export))
(setq-default ;; markdown-hide-markup t ;; has a bug with heading cycling
markdown-hide-urls t)
:bind
(:map markdown-mode-map
;; ("M-n" . org-drag-element-forward)
;; ("M-p" . org-drag-element-backward)
;; ("C-c C-o" . markdown-follow-link-at-point)
("M-r" . markdown-move-down)
("M-c" . markdown-move-up)
("C-c C--" . org-cycle-list-bullet)
([mouse-1] . markdown-cycle)
("C-c C-x C-n" . markdown-next-link)
("C-c C-x C-p" . markdown-previous-link)
("C-c C-h C-u" . #'markdown-toggle-url-hiding)
("C-c C-h C-m" . #'markdown-toggle-markup-hiding)
("C-c C-h C-i" . #'markdown-toggle-inline-images)
("C-c C-r" . #'reverse-region)
("M-w" . cp/copy-md-link)
("TAB" . markdown-cycle)
("C-c C-." . markdown-demote)
("C-c C-," . markdown-promote)
("C-c C-l" . markdown-insert-link)))
(defun cp/copy-line-or-md-link (prefix-arg)
(interactive "P")
(save-excursion
(beginning-of-line)
(if (looking-at-p ".*http")
(progn
(cp/re-search-line "http")
(forward-char -4)
(kill-new (thing-at-point 'url))))))
(with-eval-after-load 'markdown-mode
(defun cp/copy-md-link (prefix-arg)
"Copy address of Markdown link after point in the current line.
If there is no link in the current line, or if the region is
active, or with a prefix arg - call
whole-line-or-region-kill-ring-save instead."
(interactive "P")
(save-excursion
(if (or (use-region-p)
prefix-arg
(not (cp/re-search-line
;; 2018-03-21T22:47:55+0530 - fix bug where a line with parenthesized text would not be copied
;; "\("
;; 2018-07-22T10:20:03+0530
;; "\\[.*?\\](.*?)"
"\\[.*?\\]("
)))
(whole-line-or-region-kill-ring-save prefix-arg)
(let ((point-a (point)))
(forward-char -1)
(forward-sexp)
(copy-region-as-kill point-a (- (point) 1)))))))
(defun cp/copy-bus-entry ()
"For personal use, when working between Markdown and the OSM wiki."
(interactive)
(let ((point-a (region-beginning))
(point-b (region-end))
(point-b-line (line-number-at-pos)))
(query-replace "[ ]" "☐" nil point-a point-b)
(query-replace "[x]" "☑" nil point-a point-b)
(query-replace-regexp "^[\\*-] " "::" nil point-a point-b)
(query-replace-regexp "^### " ":" nil point-a point-b)
(goto-char (point-min))
(forward-line (- point-b-line 1))
(copy-region-as-kill point-a (point-at-bol))))
;; 2018-08-21T03:41:47+0530
(defun cp/copy-md-link (prefix-arg)
"Copy address of Markdown link after point in the current line.
If there is no link in the current line, or if the region is
active, or with a prefix arg - call
whole-line-or-region-kill-ring-save instead."
(interactive "P")
(save-excursion
(cond
((or (use-region-p) prefix-arg)
(whole-line-or-region-kill-ring-save prefix-arg))
((cp/re-search-line "\\[.*?\\](")
(let ((point-a (point)))
(forward-char -1)
(forward-sexp)
(copy-region-as-kill point-a (- (point) 1))))
((cp/re-search-line "http")
(kill-new (thing-at-point 'url)))
(t (whole-line-or-region-kill-ring-save prefix-arg)))))
(defun cp/marked-files->markup-links-md (filenames)
(mapcar (lambda (filename)
(if (member (downcase
(file-name-extension filename))
image-file-name-extensions)
(let ((link-pre "![](")
(link-post ")\n"))
(concat link-pre filename link-post))
(let ((link-pre "[](")
(link-post ")\n"))
(concat link-pre filename link-post))))
filenames))
#+END_SRC
**
#+BEGIN_SRC emacs-lisp
(add-hook 'erc-mode-hook 'visual-line-mode)
#+END_SRC
**
#+BEGIN_SRC emacs-lisp
(add-hook 'comint-mode-hook 'visual-line-mode)
;; commented out on 2018-03-19T14:18:34+0530
;; (add-hook 'markdown-mode-hook 'auto-fill-mode)
;; (add-hook 'text-mode-hook 'auto-fill-mode)
;; (add-hook 'paredit-mode-hook 'auto-fill-mode)
;;;; Tab settings
;; (setq default-tab-width 4)
#+END_SRC
**
#+BEGIN_SRC emacs-lisp
(setq tab-width 4)
;(define-key text-mode-map (kbd "TAB") 'self-insert-command)
#+END_SRC
**
#+BEGIN_SRC emacs-lisp
(setq-default indent-tabs-mode nil)
#+END_SRC
** mediawiki-mode
#+BEGIN_SRC emacs-lisp
(use-package mediawiki
:commands mediawiki-mode)
#+END_SRC
** asciidoc-mode
2021-06-06 02:12:19 +00:00
Used by Eldev documentation.
#+BEGIN_SRC emacs-lisp
(use-package adoc-mode
:mode "\\.adoc$")
#+END_SRC
** gemini-mode
2021-07-23 14:01:45 +00:00
<2021-07-12T16:06:08+0530>
#+BEGIN_SRC emacs-lisp
(use-package gemini-mode
:ensure t
2021-07-23 14:01:45 +00:00
:hook (gemini-mode . (lambda ()
(make-local-variable 'outline-regexp)
(setq outline-regexp "[#]+")))
:bind (:map gemini-mode-map
("TAB" . contrapunctus-outline-indent-or-toggle-children)))
2021-07-23 14:01:45 +00:00
#+END_SRC
** TODO LaTeX
2021-08-03 01:12:05 +00:00
1. [ ] merge personal commands with those in Lilypond mode
#+BEGIN_SRC emacs-lisp
(use-package auctex
:ensure t
2021-08-03 01:12:05 +00:00
:hook ((tex-mode . TeX-source-correlate-mode))
:bind (:map LaTeX-mode-map
("M-c" . cp-backward-def)
("M-r" . cp-forward-def)
("M-." . forward-sentence))
:config
(setq ;; TeX-auto-save t
;; TeX-parse-self t
TeX-engine 'xetex
;; 2017-10-14T18:55:05+0530
)
2022-01-16 14:18:10 +00:00
(add-to-list 'TeX-view-program-selection '(output-pdf "PDF Tools" TeX-pdf-tools-sync-view))
2021-08-03 01:12:05 +00:00
;; 2017-10-19T09:19:34+0530 - these should be merged with
;; cp-forward-def/cp-backward-def in cp-lily...
(defun cp-backward-def ()
(interactive)
(push-mark)
(re-search-backward "\\\\scene" nil t)
(beginning-of-line)
(recenter))
(defun cp-forward-def ()
(interactive)
(push-mark)
(if (not (re-search-forward "\\\\scene" nil t 2))
(re-search-forward "\\end{document}" nil t))
(beginning-of-line)
(recenter)))
#+END_SRC
* Programming
2022-01-14 07:57:34 +00:00
:PROPERTIES:
:CUSTOM_ID: programming
:END:
** FIXME common [%]
*** swap keys :disabled:
1. [X] =keyswap-mode= swaps numeric keys with symbols by default. We want to swap just () with [] (to begin with), but the code below doesn't work, for some reason.
2. [ ] Does not always work in the minibuffer, namely =eval-expression=
2021-02-18 20:39:40 +00:00
Swap [] with () in programming and text modes.
pjb suggested a different approach [[http://paste.lisp.org/display/10157][here]], which is basically -
#+BEGIN_SRC emacs-lisp :tangle no :load no
(defun contrapunctus-swap-brackets-parens ()
(interactive)
(keyboard-translate ?\( ?\[)
(keyboard-translate ?\) ?\])
(keyboard-translate ?\[ ?\()
(keyboard-translate ?\] ?\)))
(add-hook 'prog-mode-hook 'contrapunctus-swap-brackets-parens)
(add-hook 'text-mode-hook 'contrapunctus-swap-brackets-parens)
(defun normal-brackets-parens ()
(interactive)
(keyboard-translate ?\( ?\()
(keyboard-translate ?\) ?\))
(keyboard-translate ?\[ ?\[)
(keyboard-translate ?\] ?\]))
#+END_SRC
...which I tried, but experienced some subtle bugs, and luckily I got keyswap mode to work the way I wanted - no number-symbol switching, just parens and brackets.
2021-02-18 12:03:42 +00:00
#+BEGIN_SRC emacs-lisp
2021-02-18 20:39:40 +00:00
(use-package keyswap
:disabled t
2021-02-21 22:44:09 +00:00
:hook ((minibuffer-setup-hook . contrapunctus-swap-brackets-parens) ;; probably unnecessary
(eval-expression-minibuffer-setup-hook . contrapunctus-swap-brackets-parens)
(prog-mode . contrapunctus-swap-brackets-parens)
(text-mode . contrapunctus-swap-brackets-parens)
2021-04-06 09:30:27 +00:00
2021-02-18 20:39:40 +00:00
(emacs-lisp-mode . keyswap-colon-semicolon)
2021-04-06 09:30:27 +00:00
(ielm-mode . contrapunctus-swap-brackets-parens)
2021-04-03 08:56:59 +00:00
(ielm-mode . keyswap-colon-semicolon)
2021-04-06 09:30:27 +00:00
2021-02-18 20:39:40 +00:00
(lisp-mode . keyswap-colon-semicolon)
2021-04-03 08:56:59 +00:00
(slime-repl-mode . contrapunctus-swap-brackets-parens)
2021-06-13 11:53:44 +00:00
(slime-repl-mode . keyswap-colon-semicolon)
2021-04-06 09:30:27 +00:00
2021-04-03 08:56:59 +00:00
(scheme-mode . keyswap-colon-semicolon)
(geiser-repl-mode . contrapunctus-swap-brackets-parens)
(geiser-repl-mode . keyswap-colon-semicolon))
2021-02-18 12:03:42 +00:00
:config
2021-02-21 22:44:09 +00:00
(defun contrapunctus-keyswap-common ()
(setq-local keyswap-pairs nil) ;; dont swap numbers and symbols
(keyswap-mode))
2021-02-18 12:03:42 +00:00
(defun contrapunctus-swap-brackets-parens ()
2021-02-18 20:39:40 +00:00
;; (message "keyswap-pairs is %s" keyswap-pairs)
2021-02-21 22:44:09 +00:00
(contrapunctus-keyswap-common)
2021-02-18 12:03:42 +00:00
(keyswap-add-pairs ?\[ ?\()
(keyswap-add-pairs ?\] ?\))
(keyswap-update-keys)))
#+END_SRC
*** other things
#+BEGIN_SRC emacs-lisp
(use-package projectile
:ensure t
:hook (prog-mode . projectile-mode)
:bind (:map boon-command-map
("\\" . projectile-command-map)))
#+END_SRC
#+BEGIN_SRC emacs-lisp
(use-package rainbow-delimiters
:ensure t
:hook (prog-mode . rainbow-delimiters-mode))
#+END_SRC
2022-01-13 20:04:37 +00:00
*** feature-mode
:PROPERTIES:
2022-01-13 20:04:37 +00:00
:CREATED: 2022-01-14T01:31:08+0530
:END:
#+BEGIN_SRC emacs-lisp
(use-package feature-mode
:mode "\\.feature$")
#+END_SRC
*** paredit :disabled:
:PROPERTIES:
:CREATED: 2022-01-13T23:04:41+0530
:END:
#+BEGIN_SRC emacs-lisp :load no :tangle no
(require 'paredit)
(add-hook 'emacs-lisp-mode-hook 'paredit-mode)
(add-hook 'lisp-mode-hook 'paredit-mode)
(add-hook 'scheme-mode-hook 'paredit-mode)
(add-hook 'inferior-scheme-mode-hook 'paredit-mode)
(add-hook 'inferior-lisp-mode-hook 'paredit-mode)
(add-hook 'ielm-mode-hook 'paredit-mode)
(global-set-key (kbd "C-x C-p") 'paredit-mode)
(cp-set-keys
:keymap paredit-mode-map
:bindings
`((,(kbd "C-p") paredit-backward-down)
(,(kbd "C-n") paredit-forward-up)
(,(kbd "C-b") paredit-backward)
(,(kbd "C-f") paredit-forward)
(,(kbd "C-u") paredit-backward-up)
(,(kbd "C-d") paredit-forward-down)
(,(kbd "M-b") backward-char)
(,(kbd "M-f") forward-char)
(,(kbd "M-p") previous-line)
(,(kbd "M-n") next-line)
(,(kbd "M-u") paredit-kill-0)
(,(kbd "M-d") paredit-forward-delete)
(,(kbd "C-M-b") backward-word)
(,(kbd "C-M-f") forward-word)
(,(kbd "C-M-u") upcase-word)
(,(kbd "C-M-d") paredit-forward-kill-word)
(,(kbd "C-M-p") nil)
(,(kbd "C-M-n") nil)
(,(kbd "M-w") paredit-copy-as-kill)
(,(kbd "C-h") paredit-backward-delete)
(,(kbd "C-w") paredit-backward-kill-word)))
(cp-set-keys
:keymap comint-mode-map
:bindings
`((,(kbd "C-d") paredit-forward-down)
(,(kbd "C-M-p") comint-previous-input)
(,(kbd "C-M-n") comint-next-input)))
#+END_SRC
*** smartparens
#+BEGIN_SRC emacs-lisp
(use-package smartparens
:ensure t
:init
(smartparens-global-mode)
:config
2022-01-10 04:30:50 +00:00
(require 'smartparens-config)
(add-to-list 'sp-no-reindent-after-kill-modes 'markdown-mode)
;; (sp-pair "(" ")" :trigger-wrap (kbd "M-(") :actions '(insert wrap
;; autoskip navigate escape))
(sp-pair "(" ")" :wrap "M-(")
(sp-pair "[" "]" :wrap "M-[")
(sp-pair "\"" "\"" :wrap "M-\"")
;; (global-unset-key (kbd "M-\'")) (sp-pair "\'" "\'" :wrap "M-\'")
;; ;; buggy
(sp-pair "<" ">" :wrap "M-<")
(sp-pair "{" "}" :wrap "M-{")
;; (sp-pair "\\\\*" "\\\\*" :actions '(wrap)) (sp-pair "\\\\*" :wrap)
;; (sp-pair "\\\\/" :wrap)
;; Disable inserting pair if preceded by : (e.g. in IRC smileys)
(defun cp-point-after-colon-p ()
(equal (string (char-before)) ":"))
;; (sp-pair "(" nil :unless '(cp-point-after-colon-p))
;; sp-backward-kill-word and subword-backward-kill conflict
;; (define-key emacs-lisp-mode-map (kbd "C-p") 'sp-previous-sexp)
;; (define-key emacs-lisp-mode-map (kbd "C-n") 'sp-next-sexp)
:bind
(("M-<up>" . sp-splice-sexp-killing-backward)
:map prog-mode-map
("M-'" . sp-indent-defun)
:map smartparens-mode-map
("C-)" . sp-forward-slurp-sexp)
("C-(" . sp-backward-slurp-sexp)
("C-}" . sp-forward-barf-sexp)
("C-{" . sp-backward-barf-sexp)
("C-j" . sp-newline)
("C-|" . sp-join-sexp)
("C-k" . sp-kill-hybrid-sexp)
("C-h" . sp-backward-delete-char)
("<backspace>" . sp-backward-delete-char)
("C-w" . sp-backward-kill-word)
("<C-backspace>" . sp-backward-kill-word)
("M-DEL" . sp-backward-kill-word)
2021-02-20 06:19:14 +00:00
("M-e" . sp-kill-word)
("C-M-p" . sp-backward-down-sexp)
("C-M-n" . sp-backward-up-sexp)
("C-M-b" . sp-backward-sexp)
("C-M-f" . sp-forward-sexp)
("C-M-u" . sp-up-sexp)
("C-M-d" . sp-down-sexp)
("C-M-a" . sp-beginning-of-sexp)
("C-M-e" . sp-end-of-sexp)
("C-M-k" . sp-kill-sexp)
("C-M-w" . sp-copy-sexp)
:map emacs-lisp-mode-map
(";" . sp-comment))
:hook
(eval-expression-minibuffer-setup . smartparens-mode)
(paredit-mode . turn-off-smartparens-mode)
(erc-mode . smartparens-mode))
#+END_SRC
2022-01-14 10:56:35 +00:00
*** lispy
Create advice for =lispy-pair= - if =lispy--in-string-or-comment-p= is true, self-insert (which =smartparens= will add the closing pair for)
2021-07-06 01:43:26 +00:00
#+BEGIN_SRC emacs-lisp
(use-package lispy
:ensure t
2021-07-30 03:47:07 +00:00
:hook
(emacs-lisp-mode . lispy-mode)
(inferior-emacs-lisp-mode . lispy-mode)
2021-07-29 18:01:53 +00:00
(lisp-mode . lispy-mode)
(scheme-mode . lispy-mode)
2021-11-19 19:56:10 +00:00
(slime-repl-mode . lispy-mode)
;; Boon-style keys on Dvorak
:bind
(:map lispy-mode-map
2022-01-14 13:56:09 +00:00
;; essential movement
("h" . special-lispy-left) ;; QWERTY J
("s" . special-lispy-right) ;; QWERTY ;
("c" . special-lispy-up) ;; QWERTY I
("r" . special-lispy-down) ;; QWERTY O
;; ;; defined in :config
2022-01-14 13:56:09 +00:00
;; ("t" . special-lispy-backward)
;; ("n" . special-lispy-forward)
("i" . special-lispy-flow) ;; "inwards"
("l" . special-lispy-teleport)
("j" . special-lispy-occur)
2022-01-14 13:56:09 +00:00
;; essential manipulation
("k" . special-lispy-clone) ;; QWERTY c
("K" . #'special-lispy-convolute) ;; QWERTY C
2022-01-14 13:56:09 +00:00
("C" . special-lispy-move-up)
("R" . special-lispy-move-down)
("o" . special-lispy-splice) ;; QWERTY S
("p" . special-lispy-raise)
;; ;; defined in :config
;; ("T" . special-lispy-splice-sexp-killing-forward)
;; ("N" . special-lispy-splice-sexp-killing-backward)
2022-01-14 13:56:09 +00:00
;; ("l" . special-lispy-new-copy)
;; ;; Lispy shadows this, but it's essential for Org literate programs
("M-o" . nil)
2021-07-30 03:47:07 +00:00
("M-o M-o" . font-lock-fontify-block)
;; It does not insert a pair in strings or comments. I want
;; that. I'll let smartparens take care of it.
("(" . self-insert-command))
;; :config (setq lispy-mode-map-c-digits nil)
:config
2021-07-31 00:08:54 +00:00
;; (dolist (key '("C-1" "C-2" "C-3" "C-4"))
;; (define-key lispy-mode-map-c-digits (kbd key) nil))
2022-01-14 13:56:09 +00:00
(lispy-set-key-theme '(lispy special))
;; These keys do not have special-* variants defined by default, so
;; here we define them ourselves.
(cl-loop for (key . cmd) in
'(("t" . lispy-backward)
("n" . lispy-forward)
("T" . lispy-splice-sexp-killing-forward)
("N" . lispy-splice-sexp-killing-backward))
do (lispy-define-key lispy-mode-map (kbd key) cmd)))
2021-07-30 03:47:07 +00:00
#+END_SRC
2022-01-14 10:56:35 +00:00
2022-01-14 13:57:10 +00:00
*** treemacs :disabled:
#+BEGIN_SRC emacs-lisp
(use-package treemacs
:disabled t
:bind (:map treemacs-mode-map
2022-02-09 16:33:05 +00:00
([mouse-1] . #'treemacs-TAB-action)
("c" . #'treemacs-previous-line)
("r" . #'treemacs-next-line))
:config
(treemacs-tag-follow-mode)
(treemacs-toggle-fixed-width)
(setq treemacs-tag-follow-delay 0))
2021-07-06 01:43:26 +00:00
#+END_SRC
2022-01-14 10:56:35 +00:00
*** imenu
#+BEGIN_SRC emacs-lisp
(use-package imenu
2022-01-20 18:46:14 +00:00
:hook (imenu-after-jump . (lambda () (recenter 0))) ;; also applies to `imenus'
:config (setq imenu-auto-rescan t
org-imenu-depth 5))
2021-12-04 06:14:35 +00:00
#+END_SRC
2021-07-06 01:43:26 +00:00
2021-12-04 06:14:35 +00:00
**** imenus
#+BEGIN_SRC emacs-lisp
(use-package imenus
:ensure t
2021-12-04 06:14:35 +00:00
:commands imenus)
#+END_SRC
2021-12-04 06:14:35 +00:00
2022-01-14 11:11:12 +00:00
*** side-hustle :disabled:
#+BEGIN_SRC emacs-lisp
(use-package side-hustle
:disabled t
:bind
(:map side-hustle-mode-map
(("r" . next-line)
("c" . previous-line))))
#+END_SRC
** lisp
:PROPERTIES:
:CREATED: 2022-01-13T21:03:15+0530
:END:
#+BEGIN_SRC emacs-lisp
(defun contrapunctus-lisp-copy (arg)
"Run `whole-line-or-region-copy-region-as-kill' if region is
active, else `sp-copy-sexp'."
(interactive "P")
(if (region-active-p)
(whole-line-or-region-copy-region-as-kill arg)
(sp-copy-sexp arg)))
(defun colorize-compilation-buffer ()
(ansi-color-apply-on-region compilation-filter-start
(point)))
(add-hook 'compilation-filter-hook 'colorize-compilation-buffer)
;; Stopped calling `exec-path-from-shell-initialize' on init, but
;; won't this keep running it excessively?
;; `exec-path-from-shell-copy-envs' (which it calls internally)
;; doesn't seem idempotent, either.
(use-package exec-path-from-shell
:ensure t
:hook
(compilation-mode . exec-path-from-shell-initialize)
(shell-mode-hook . exec-path-from-shell-initialize)
(minibuffer-setup-hook . exec-path-from-shell-initialize))
#+END_SRC
** Emacs Lisp
#+BEGIN_SRC emacs-lisp
(use-package elisp-mode
:diminish
:bind
(:map emacs-lisp-mode-map
;; ("<tab>" . 'company-indent-or-complete-common)
;; ("<C-tab>" . 'outline-toggle-children)
("M-n" . 'outline-next-heading)
("M-p" . 'outline-previous-heading)
("M-m" . macrostep-expand))
:config
(put 'cl-loop 'lisp-indent-function 'defun)
(setq print-length nil
eval-expression-print-length nil))
#+END_SRC
#+BEGIN_SRC emacs-lisp
(use-package ielm
:bind (:map ielm-map
("M-'" . sp-indent-defun)))
#+END_SRC
#+BEGIN_SRC emacs-lisp
2022-01-16 07:20:06 +00:00
(defun cp/eval-sexp (arg)
"In emacs-lisp-mode, just run eval-defun.
In other modes - jump to first Lisp expression in current line
and eval it."
(interactive "P")
(save-excursion
(cond ((or (equal major-mode 'emacs-lisp-mode)
(equal major-mode 'lisp-interaction-mode))
(eval-defun arg))
((cp/re-search-line "(")
(progn
(forward-char -1)
(forward-sexp)
(eval-last-sexp arg)))
(t nil))))
#+END_SRC
*** ELSA - Emacs Lisp Static Analyzer :disabled:
#+BEGIN_SRC emacs-lisp
(use-package elsa
:disabled t
:commands flycheck-elsa-setup)
#+END_SRC
*** literate-elisp
#+BEGIN_SRC emacs-lisp
(use-package literate-elisp
:ensure t
:commands (literate-elisp-load))
#+END_SRC
*** eldoc
#+BEGIN_SRC emacs-lisp
(use-package eldoc
:diminish
:if (featurep 'elisp-mode)
:init (add-hook 'emacs-lisp-mode-hook 'eldoc-mode)
:config (setq eldoc-idle-delay 0))
#+END_SRC
*** emr - emacs refactor
#+BEGIN_SRC emacs-lisp
(use-package emr
:bind (:map prog-mode-map
("M-S-<return>" . emr-show-refactor-menu)))
#+END_SRC
2022-01-15 04:36:34 +00:00
*** nameless-mode
#+BEGIN_SRC emacs-lisp
(use-package nameless
:ensure t
:commands nameless-mode
:hook
(ert-results-mode . nameless-mode)
(emacs-lisp-mode . nameless-mode)
(org-mode . nameless-mode)
:bind (:map emacs-lisp-mode-map
2021-12-02 04:55:10 +00:00
("C-c C-n" . nameless-mode)
("C-c C--" . nameless-insert-name)))
#+END_SRC
2022-01-24 09:03:52 +00:00
*** explain-pause-mode :disabled:
#+BEGIN_SRC emacs-lisp
(use-package explain-pause-mode
2022-01-24 09:03:52 +00:00
:disabled t
2021-11-18 09:29:49 +00:00
:load-path "~/.emacs.d/elisp-git/explain-pause-mode/"
:diminish
2022-01-15 04:41:47 +00:00
:commands (explain-pause-mode)
:init (explain-pause-mode))
#+END_SRC
2022-01-10 04:30:24 +00:00
2021-12-04 06:15:51 +00:00
*** WIP async-tangle
Adapted from https://stackoverflow.com/questions/16815598/run-commands-in-emacs-asynchronously-but-display-output-incrementally/16816575#16816575 and the Elisp manual
#+BEGIN_SRC emacs-lisp
(defun my-start-process* (buffer &rest command-specs)
"Execute COMMAND-SPECS sequentially.
All COMMAND-SPECS should be a list in the form
\(NAME COMMAND COMMAND-ARGS*\)"
(with-current-buffer buffer
(set (make-local-variable 'commands-list) command-specs)
(boon-mode)
(my-start-next-process)))
(defun my-start-next-process ()
"Run the first command in the list."
(if (null commands-list)
(insert "\nDone.")
(-let* [(command-spec (car commands-list))
((name command . command-args) command-spec)]
(setq commands-list (cdr commands-list))
(insert (format ">>> %s\n" command))
(let ((process (funcall #'start-process name (current-buffer) command command-args)))
(set-process-sentinel process 'my-sentinel)))))
(defun my-sentinel (process event)
"After a process exited, call `my-start-next-process' again"
(let ((buffer (process-buffer process)))
(when (buffer-live-p buffer)
(with-current-buffer buffer
(let ((moving (= (point) (process-mark process))))
(save-excursion
;; Insert the text, advancing the process marker.
(goto-char (process-mark process))
;; (insert (format "Command `%s' %s" process event))
(set-marker (process-mark process) (point))
(my-start-next-process))
(when moving (goto-char (process-mark process))))))))
#+END_SRC
2021-07-07 04:15:24 +00:00
#+BEGIN_SRC emacs-lisp
(defun contrapunctus-async-tangle (&optional prefix)
2021-12-04 06:15:51 +00:00
"Use `org-babel-tangle' on the file visited by the current buffer."
2021-07-07 04:15:24 +00:00
(interactive "P")
2021-12-04 06:15:51 +00:00
(let* ((proc-buffer (get-buffer-create "*async-tangle-process*"))
(file-name (buffer-file-name))
(file-name-no-ext (file-name-sans-extension (buffer-file-name)))
(old-win (selected-window)) ; ?
(process (start-process
"async-tangle" proc-buffer "emacs" "-q" "-Q" "--batch"
"--eval=(require 'ob-tangle)"
(format "--eval=(org-babel-tangle-file \"%s\")"
file-name file-name-no-ext))))
;; don't create window if buffer already visible
(unless (get-buffer-window-list proc-buffer)
;; to avoid messing up my usual two-windows-same-buffer setup
(select-window (split-window-below))
(switch-to-buffer proc-buffer)
;; so I can access my Hydra to switch back
(boon-mode))
;; (select-window old-win)
))
2021-07-07 04:15:24 +00:00
#+END_SRC
2022-01-15 07:27:22 +00:00
** Common Lisp
2022-01-14 07:57:34 +00:00
:PROPERTIES:
:CUSTOM_ID: programming-common-lisp
:END:
2022-01-23 19:13:07 +00:00
#+BEGIN_SRC emacs-lisp
(use-package lisp-mode
:interpreter ("cl" . lisp-mode)) ;; cl-launch scripts
#+END_SRC
2022-01-14 08:01:07 +00:00
*** redshank
#+BEGIN_SRC emacs-lisp
(use-package redshank
:ensure t
:hook (slime-mode . redshank-mode))
2022-01-14 08:01:07 +00:00
#+END_SRC
2022-01-14 08:01:07 +00:00
*** slime
:PROPERTIES:
:CUSTOM_ID: slime
:END:
#+BEGIN_SRC emacs-lisp
(use-package slime
:ensure t
:commands (slime-eval-buffer slime-eval-defun)
2022-01-17 13:01:04 +00:00
:mode ("\\.asd$" . asdf-mode)
:bind
(:map slime-mode-map
("M-n" . next-line)
("M-p" . previous-line)
("SPC" . self-insert-command)
2022-01-14 19:15:52 +00:00
("<f1> <f1>" . slime-documentation)
("TAB" . company-indent-or-complete-common)
("C-i" . company-indent-or-complete-common))
2021-04-03 09:01:32 +00:00
(:map slime-repl-mode-map
("M-p" . slime-repl-previous-matching-input) ;; QWERTY "r"
("M-c" . slime-repl-previous-input)
2022-01-14 06:56:57 +00:00
("M-r" . slime-repl-next-input)
("TAB" . company-indent-or-complete-common)
("C-i" . company-indent-or-complete-common))
:config (slime-setup '(slime-fancy slime-company slime-tramp))
2021-11-19 19:55:09 +00:00
(setq inferior-lisp-program
;; "/usr/bin/ecl"
2021-11-19 19:55:09 +00:00
"sbcl"
slime-net-coding-system 'utf-8-unix)
(defun cp-slime-completion-in-region (_fn completions start end)
(funcall completion-in-region-function start end completions))
(advice-add 'slime-display-or-scroll-completions
:around #'cp-slime-completion-in-region)
(add-to-list 'slime-filename-translations
(slime-create-filename-translator
:machine-instance "tilde"
:remote-host "tilde.team"
2022-01-14 06:56:57 +00:00
:username "contrapunctus"))
(add-to-list 'company-backends 'company-slime))
2022-01-14 08:01:07 +00:00
#+END_SRC
2022-01-14 08:01:07 +00:00
*** slime-company
:PROPERTIES:
:CUSTOM_ID: slime-company
:END:
#+BEGIN_SRC emacs-lisp
(use-package slime-company
:ensure t
:after (slime company)
:config (setq slime-company-completion 'fuzzy
slime-company-after-completion 'slime-company-just-one-space))
#+END_SRC
2022-01-14 06:58:22 +00:00
2022-01-17 13:02:01 +00:00
*** common-lisp-snippets
:PROPERTIES:
:CREATED: 2022-01-17T12:07:32+0530
:END:
#+BEGIN_SRC emacs-lisp
(use-package common-lisp-snippets
:ensure t
:init (common-lisp-snippets-initialize))
#+END_SRC
** Scheme
#+BEGIN_SRC emacs-lisp
(setq scheme-program-name "csi -:c")
(setq comint-prompt-read-only t)
(use-package geiser
:mode ("\\.scm\\'" . geiser-mode)
:commands (run-chicken run-guile geiser-mode)
:custom (geiser-active-implementations '(chicken))
:config (setq geiser-scheme-implementation 'chicken))
;; (with-eval-after-load 'geiser-mode
;; (setq geiser-mode-smart-tab-p t)
;; (define-key geiser-mode-map (kbd "C-.") nil)
;; ;; (cp-set-keys
;; ;; :unset t
;; ;; :keymap geiser-mode-map
;; ;; :bindings
;; ;; `((,(kbd "C-."))))
;; )
(use-package scheme-mode
:mode ("\\.scm\\'" . scheme-mode)
:interpreter "csi")
#+END_SRC
*** CHICKEN Scheme
*** Guile
** Lilypond
#+BEGIN_SRC emacs-lisp
(use-package lilypond-mode
:load-path "elisp-git/lilypond/elisp"
:bind
(("M-]" . set-selective-display)
:map LilyPond-mode-map
("M-c" . cp-backward-def)
("M-r" . cp-forward-def)
("M-C" . cp-upper-level)
("M-R" . cp-lower-level)
("C-c C-w" . cp-ly-wrap-para))
:commands LilyPond-mode
:mode (("\\.ly$" . LilyPond-mode)
("\\.ily$" . LilyPond-mode))
:config
(--map (add-hook 'LilyPond-mode-hook it)
'(subword-mode
(lambda () (turn-on-font-lock))))
(defalias 'string-to-int #'string-to-number)
(defvar cp/ly-definition-rx
'(and bol
(1+ (any "a-z" "A-Z" "\\\\"))
(1+ (any "a-z" "A-Z" "\\\\" " "))
(any "{" "=" "#")))
(defun cp-backward-def ()
(interactive)
(unless (region-active-p)
(push-mark))
(re-search-backward (rx-to-string cp/ly-definition-rx)
nil t)
(beginning-of-line)
(recenter))
(defun cp-forward-def ()
(interactive)
(let* ((regex (rx-to-string cp/ly-definition-rx))
(count (if (looking-at-p regex) 2 1)))
(unless (region-active-p)
(push-mark))
;; (forward-char)
(if (not (re-search-forward regex nil t count))
(re-search-forward "^}" nil t))
;; (re-search-forward "^[\\a-zA-Z]" nil t)
(beginning-of-line)
(recenter)))
;; (defun cp-backward-def ()
;; (interactive)
;; (re-search-backward "\(^\\\\?[a-zA-Z]\|^ *\\[a-zA-Z]\)")
;; (beginning-of-line))
;; (defun cp-forward-def ()
;; (interactive)
;; (forward-char)
;; (re-search-forward "\(^\\\\?[a-zA-Z]\|^ *\\[a-zA-Z]\)")
;; (beginning-of-line))
(defun cp-upper-level ()
(interactive)
(re-search-backward "{"))
(defun cp-lower-level ()
(interactive)
(if (equal (string (char-after)) "{")
(forward-char))
(if (not (re-search-forward "{"))
(message "At deepest level."))
(backward-char))
;; (defun cp-lilypond-enclose-<< ()
;; (interactive)
;; (if (equal (string (char-after)) "\\")
;; (progn (insert "<< ")
;; (search-forward "{")
;; (backward-char)
;; (forward-sexp))))
;; if at a \new ... block - enclose expression
;; otherwise, enclose current position and after the first bar check
;; found
;; if region is active, enclose beginning and end
;; (defun cp-lilypond-enclose-<< ()
;; (interactive)
;; (if (equal (thing-at-point 'sexp)
;; "\\new")
;; (progn ;; (insert "<< ")
;; (newline-and-indent)
;; (search-forward "{")
;; (backward-char)
;; (forward-list)
;; ;; (forward-sexp))
;; )
;; ;; (let ((point1 (point)))
;; ;; (next-line)
;; ;; (goto-char point1))
;; ))
;; (define-key LilyPond-mode-map (kbd "<<")
;; 'cp-lilypond-enclose-<<)
;; If I change files, it's still main.ly that gets compiled; this is
;; good most of the time, but many times I want to compile a part-*
;; file instead. If we compile both main.ly and the respective part-*
;; file every time, it's wasteful. Having to select means giving up
;; the 'effortless-compilation' behaviour.
;; 2017-03-14T00:52:07+0530 - commented out, see cp/after-save
;; (defadvice LilyPond-save-buffer
;; (after lysb activate)
;; ;; (compile "make")
;; (cd (locate-dominating-file (buffer-file-name)
;; "main.ly"))
;; (compile (car compile-history)))
;;
;; (defadvice compile
;; (before compile activate)
;; (if (equal major-mode 'LilyPond-mode)
;; (cd (locate-dominating-file (buffer-file-name)
;; "main.ly"))))
;; TODO - refactor into one COND, with one case per operation.
;; TODO - operate on region as well.
(defun cp-ly-wrap-para (arg)
"Wrap current paragraph with -
\\relative c { ... } with no args,
\\repeat { ... } with universal argument,
and only braces - { ... } - with null argument.
Numeric arg wraps that many paragraphs.
TODO - wrap region if region active"
(interactive "P")
(let ((point-a (point)))
(beginning-of-line)
(unless (looking-at "[[:blank:]]*$")
;; go to start of paragraph or block, or previous blank line
(re-search-backward (rx (or (and bol (0+ blank) eol)
(and "{" eol))))
(end-of-line))
(newline-and-indent)
(insert (pcase arg
(`(,x) "\\repeat {")
(0 "{")
;; nil
(_ "\\relative c {")))
(let ((indent-start (point)))
(forward-paragraph (pcase arg
(`(,x) 1)
(_ (if (and arg (<= arg 0))
1 arg))))
(indent-region indent-start (point))
(insert "}")
(indent-for-tab-command)
(newline)
;; FIXME
(goto-char (pcase arg
(0 point-a)
(_ (- indent-start 2))))))))
;; TODO - cp-ly-new-var, bind to M-RET.
;; Exits current variable body, if in any, and inserts "| = \relative
;; c {\n\n \n}", where | is the cursor
#+END_SRC
** Prolog
#+BEGIN_SRC emacs-lisp
(use-package ediprolog
:commands ediprolog-dwim)
#+END_SRC
2022-01-18 19:58:13 +00:00
** C
#+BEGIN_SRC emacs-lisp
2021-11-19 19:54:52 +00:00
(use-package cc-mode
:bind (:map c-mode-map
("TAB" . company-indent-or-complete-common)
("C-i" . company-indent-or-complete-common)))
(use-package irony-eldoc
:hook
(c-mode . irony-eldoc))
(use-package irony
:config
(add-hook 'irony-mode-hook #'irony-eldoc))
(use-package company-irony)
(use-package rtags
:hook
(c-mode . rtags-call-rc)
:config
(setq rtags-rc-binary-name "rtags-rc"
rtags-rdm-binary-name "rtags-rdm")
:bind
(:map c-mode-map
("<f2> <f2>" . rtags-find-symbol-at-point)))
#+END_SRC
** nodejs-repl :disabled:
#+BEGIN_SRC emacs-lisp
(use-package nodejs-repl
:disabled
:config (setq nodejs-repl-command "nodejs"))
#+END_SRC
2022-01-14 10:56:35 +00:00
** web development
https://emacs.cafe/emacs/javascript/setup/2017/04/23/emacs-setup-javascript.html
Potentially useful - https://www.draketo.de/software/emacs-javascript.html
2022-01-14 10:58:40 +00:00
*** js2-mode
:PROPERTIES:
:CREATED: 2022-01-14T16:22:00+0530
:END:
#+BEGIN_SRC emacs-lisp
(use-package js2-mode
:mode ("\\.js\\'" . js2-mode)
;; Better imenu
:hook (js2-mode-hook . js2-imenu-extras-mode))
2022-01-14 10:58:40 +00:00
#+END_SRC
2022-01-14 10:58:40 +00:00
*** js2-refactor
:PROPERTIES:
:CREATED: 2022-01-14T16:22:05+0530
:END:
#+BEGIN_SRC emacs-lisp
(use-package js2-refactor
:hook (js2-mode-hook . js2-refactor-mode))
2022-01-14 10:58:40 +00:00
#+END_SRC
2022-01-14 10:58:40 +00:00
*** tern
:PROPERTIES:
:CREATED: 2022-01-14T16:22:10+0530
:END:
#+BEGIN_SRC emacs-lisp
2021-11-19 19:53:49 +00:00
(use-package tern)
2022-01-14 10:58:40 +00:00
#+END_SRC
2021-11-19 19:53:49 +00:00
2022-01-14 10:58:40 +00:00
*** company-tern
:PROPERTIES:
:CREATED: 2022-01-14T16:22:13+0530
:END:
#+BEGIN_SRC emacs-lisp
(use-package company-tern
2021-11-19 19:53:49 +00:00
:load-path "~/.emacs.d/elisp-git/company-tern/"
:init (add-to-list 'company-backends 'company-tern))
2022-01-14 10:58:40 +00:00
#+END_SRC
2022-01-14 10:58:40 +00:00
*** skewer-mode
:PROPERTIES:
:CREATED: 2022-01-14T16:22:17+0530
:END:
#+BEGIN_SRC emacs-lisp
(use-package skewer-mode
:hook (js2-mode-hook . skewer-mode))
#+END_SRC
2022-01-14 10:58:09 +00:00
text size change
nicked from wasamasa's init - https://github.com/wasamasa/dotemacs/blob/934d0b37692d62fe9af56b52accac5bcd4445ae3/init.org
#+BEGIN_SRC emacs-lisp
(setq default-frame-alist '((font . "DejaVu Sans Mono-10.5")))
#+END_SRC
#+BEGIN_SRC emacs-lisp
(defun my-fix-emojis (&optional frame)
(set-fontset-font "fontset-default" nil "Symbola" frame 'append))
(my-fix-emojis)
(add-hook 'after-make-frame-functions 'my-fix-emojis)
;; (set-face-attribute 'default nil :font "-outline-Bitstream Vera Sans Mono-normal-normal-normal-mono-12-*-*-*-c-*-iso8859-1")
#+END_SRC
* desktop - session management
#+BEGIN_SRC emacs-lisp
(use-package desktop
:init
(desktop-save-mode t)
(desktop-auto-save-enable)
:config
(setq desktop-dirname "~/.emacs.d/desktop-save/"
desktop-save 'ask-if-new
;; don't save buffers, just the history
desktop-files-not-to-save ""
2021-09-01 20:13:38 +00:00
desktop-buffers-not-to-save ""
desktop-restore-frames nil)
(cl-loop for var in
'(grep-history
grep-find-history
find-args-history
extended-command-history
read-expression-history
default-input-method
input-method-history
query-replace-history
compile-history
string-rectangle-history
regexp-history
dired-shell-command-history
dired-regexp-history
shell-command-history
org-tags-history
minibuffer-history
erc-server-history-list
cp/activity-history
LaTeX-environment-history
swiper-history
counsel-M-x-history)
do (add-to-list 'desktop-globals-to-save var)))
;; (add-to-list 'desktop-locals-to-save 'comint-input-ring)
(defun cp/backup-desktop-file ()
(let ((new-filename (->> (shell-command-to-string "date -Is")
(replace-regexp-in-string "\n" "")
(concat "~/.emacs.d/.emacs.desktop."))))
(copy-file "~/.emacs.d/.emacs.desktop" new-filename)))
(defun cp/cleanup-desktop-backups ()
(let ((desktop-file-backups (-> (concat "find ~/.emacs.d/ -maxdepth 1 -type f |"
" grep -E \"\.emacs\.desktop\.[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}[-+]?[0-9]{2}:?[0-9]{2}\"")
(shell-command-to-string )) )))
(if (> 10 )))
;; ;; this one created loads and loads of backups
;; (add-hook 'desktop-save-hook 'cp/backup-desktop-file)
;; ;; not enough space for this - wasteful
;; (add-hook 'kill-emacs-hook 'cp/backup-desktop-file)
#+END_SRC
2022-01-15 12:04:00 +00:00
* The end
Reset the GC settings, so Emacs doesn't use up tons of RAM.
#+BEGIN_SRC emacs-lisp
(setq gc-cons-threshold 400000)
;; (toggle-debug-on-quit)
;; (profiler-stop)
;; (emacs-init-time)
;; (profiler-report)
#+END_SRC
2022-01-14 10:56:35 +00:00
#+BEGIN_SRC emacs-lisp
(provide 'init)
;;; init.el ends here
#+END_SRC
# Local Variables:
# nameless-current-name: "contrapunctus"
# eval: (visual-fill-column-mode -1)
# eval: (nameless-mode)
# compile-command: "make -Bk tangle"
2022-01-17 12:57:50 +00:00
# my-org-src-default-lang: "emacs-lisp"
# eval: (when (package-installed-p 'literate-elisp) (require 'literate-elisp) (literate-elisp-load (buffer-file-name)))
# End: