dotemacs/init.org

3238 lines
105 KiB
Org Mode
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#+TODO: TODO WIP WISH CLEANUP FIXME REVIEW |
#+PROPERTY: header-args :tangle yes
=org-babel-tangle= takes nearly 27 seconds to tangle this file, at the time of writing. So for a brief while I used this sed script instead -
# eval: (progn (make-local-variable 'after-save-hook) (add-hook 'after-save-hook (lambda () (start-process-shell-command "sed-tangle" "sed-tangle" "sed -n -e '/#+BEGIN_SRC emacs-lisp$/,/#+END_SRC$/{//!p;}' init.org > init.el"))))
But after ironing out [[https://github.com/jingtaozf/literate-elisp/issues/7][some issues]], I switched back to =literate-elisp=. It /does/ interoperate with the rest of Emacs, just be sure to not get any errors in your init!
* init.org
** TODO dvorak [60%]
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.
1. [X] M-n, M-p, -> M-r, M-c
2. [X] M-q -> M-'
3. [X] M--
4. [ ] multiple-cursors
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.
6. [ ] M-n M-n not getting bound to font-lock-fontify-block ?
7. [ ] binding C-d to keyboard-quit in the minibuffer
#+BEGIN_SRC emacs-lisp
(general-auto-unbind-keys)
;; Most if not all of these are translations of their earlier QWERTY bindings.
(general-def
"M-h" 'default-indent-new-line ;; see also org-mode
"M-'" 'fill-paragraph
"C-j" 'ctl-x-map
"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
;; ;; Emacs-like
"M-e" 'kill-word
"C-e" 'delete-char
"M-x" 'backward-word ;; !!!
"M-u" 'forward-word
"M-q" 'execute-extended-command
;; "C-x" 'forward-char
;; ;; Boon-like
;; "M-h" 'forward-word
;; "M-s" 'forward-word
"C-n" 'forward-char
"C-t" 'backward-char)
(bind-keys
("C-h" . backward-delete-char) ;; see also ivy, company
:map text-mode-map
;; Boon already binds xref-find-definitions to f
;; see also latex-mode
("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
(general-def 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)
(general-def 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)
(general-def ivy-minibuffer-map
"C-c" 'previous-line
"C-r" 'next-line
"M-c" 'ivy-previous-history-element
"M-r" 'ivy-next-history-element)
(general-def swiper-map
"C-c" 'previous-line)
(general-auto-unbind-keys t)
#+END_SRC
** user interface
#+BEGIN_SRC emacs-lisp
(use-package cp-ui
:demand
:load-path "~/.emacs.d/contrapunctus/")
#+END_SRC
** ediff
#+BEGIN_SRC emacs-lisp
(use-package ediff
:config
(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
** atomic-chrome
#+BEGIN_SRC emacs-lisp
(require 'atomic-chrome)
(atomic-chrome-start-server)
(setq atomic-chrome-url-major-mode-alist
'(("wikisource" . mediawiki-mode)))
#+END_SRC
** emacs settings
#+BEGIN_SRC emacs-lisp
(use-package emacs
:config
(setq gc-cons-threshold 100000000
delete-by-moving-to-trash t
trash-directory "~/.trash/"
history-length 1000
use-file-dialog nil)
(setq-default undo-limit (* 80 1000)))
#+END_SRC
** esup, the Emacs StartUp Profiler
#+BEGIN_SRC emacs-lisp
(use-package esup
:config (setq esup-depth 0))
#+END_SRC
** doc-view
#+BEGIN_SRC emacs-lisp
(use-package doc-view
:config
(setq doc-view-resolution 300))
#+END_SRC
** 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
** ag, the Silver Searcher
#+BEGIN_SRC emacs-lisp
(use-package ag
:bind
("<f2> p" . ag)
("<f2> P" . ag-project-regexp)
:config
(setq ag-highlight-search t))
#+END_SRC
** ido-mini
This needs to be before =boon=, or you get a "failed to define function ido-mini" error when you press the keybinding.
#+BEGIN_SRC emacs-lisp
(add-to-list 'load-path "~/.emacs.d/user/")
(add-to-list 'load-path "~/.emacs.d/contrapunctus/")
;; (add-to-list 'load-path "~/.emacs.d/contrapunctus/fin/")
(use-package ido-mini
:load-path "~/.emacs.d/contrapunctus/ido-mini/"
:bind (("C-x C-l" . ido-mini)
:map boon-command-map
("H" . ido-mini))
:config
(ivy-mode))
#+END_SRC
**
#+BEGIN_SRC emacs-lisp
(load "cp")
;; (if (not (server-running-p)) (server-start))
(server-start)
#+END_SRC
** modal editing
*** active boon config
#+BEGIN_SRC emacs-lisp
(use-package boon
:ensure t
:commands (boon-mode)
:load-path "~/.emacs.d/elisp-git/boon"
:bind
(:map boon-command-map
("C-l" . recenter-top-bottom)
("p" . swiper)
("I" . join-line)
;; ("TAB" . 'company-indent-or-complete-common) ;; this works,
;; but also breaks unfolding in org mode :\ ("<tab>" .
;; 'company-indent-or-complete-common)
("J" . 'boon-toggle-comment)
("y" . nil)
("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'
("(" . boon-navigate-backward)
(")" . boon-navigate-forward)
(". p" . swiper-thing-at-point)
("M" . ido-mini)
("H" . ido-mini)
;; 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))
(dolist (var '((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)))
(add-to-list 'boon-special-conditions var))
(setq hi-lock-auto-select-face t)
;; (define-key boon-command-map (kbd "x d f") nil)
(general-def boon-command-map
"M" 'ido-mini
"H" 'ido-mini
;; "x d" 'dired-jump
)
;; :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
*** experimental boon+modalka config :disabled:
#+BEGIN_SRC emacs-lisp :load no
(use-package boon
:ensure t
: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
*** experimental Emacs-flavored-Boon config :disabled:
#+BEGIN_SRC emacs-lisp :load no
(use-package boon
:ensure t
: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
*** 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)))
(require 'cp-god)
#+END_SRC
** Applications
*** time tracking - chronometrist
choice.el is required by =chronometrist-key-values=
**** goal
#+BEGIN_SRC emacs-lisp
(use-package chronometrist-goal
:load-path "~/.emacs.d/contrapunctus/chronometrist-goal/"
:hook (chronometrist-mode . chronometrist-goal-minor-mode)
:config
(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")
(20 "Subtitles")
(15 "Acting")
(30 "Keyboard")
(15 "Wikisource"))
alert-default-style 'libnotify))
#+END_SRC
**** spark
#+BEGIN_SRC emacs-lisp
(use-package chronometrist-spark
:hook (chronometrist-mode . chronometrist-spark-minor-mode)
:config (setq chronometrist-spark-length (* 7 4)))
#+END_SRC
**** chronometrist
#+BEGIN_SRC emacs-lisp
(use-package chronometrist
;; :disabled t
:load-path "~/.emacs.d/contrapunctus/chronometrist/elisp/"
: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)
("d" . chronometrist-details))
(:map chronometrist-report-mode-map
("h" . chronometrist-report-previous-week)
("s" . chronometrist-report-next-week)))
:config
(setq 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 'contrapunctus-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)]))
#+END_SRC
***** activity-indicator
#+BEGIN_SRC emacs-lisp
(defun contrapunctus-chronometrist-activity-indicator ()
(thread-last (plist-put (chronometrist-last)
:stop (chronometrist-format-time-iso8601))
list
chronometrist-events-to-durations
(-reduce #'+)
truncate
chronometrist-format-duration))
#+END_SRC
***** find-two-files
#+BEGIN_SRC emacs-lisp
(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))
#+END_SRC
***** outline-open-heading
#+BEGIN_SRC emacs-lisp
(defun cp-outline-open-heading (n)
(goto-char (point-min))
(outline-next-visible-heading n)
(outline-show-subtree))
#+END_SRC
***** start-project
#+BEGIN_SRC emacs-lisp
(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"))
("Arrangement/new edition"
(delete-other-windows)
;; (find-file "/media/data/anon/1-music-scores/4-my-arrangements/2020/2020-11-27 Winterreise/01 Gute Nacht/music/")
;; (launch-file "/media/data/anon/1-music-scores/4-my-arrangements/2020/2020-11-27 Winterreise/01 Gute Nacht/output/01 Gute Nacht-pacON.pdf")
;; (launch-file "/media/data/anon/Sync/Scores/voice/Schubert, Franz/IMSLP570459-PMLP2203-D_911,_Winterreise.pdf")
(find-file "/media/data/anon/1-music-scores/4-my-arrangements/2020/2020-10-14 An die ferne Geliebte/music/")
(launch-file
"/media/data/anon/1-music-scores/4-my-arrangements/2020/2020-10-14 An die ferne Geliebte/output/2020-10-14 An die ferne Geliebte-pacON.pdf")
(launch-file
"/media/data/anon/Sync/Scores/voice/Beethoven, Ludwig van/IMSLP47561-PMLP11572-Beethoven_Lieder_Peters_9535_Op_98_An_die_ferne_Geliebte.pdf"))
("Aural exercises"
(find-file-other-window
"/media/data/anon/Documents/Text Files/music_stuff/harmonic-analysis.org"))
("Composing"
(find-file-other-window
;; "/media/data/anon/1-music-scores/2-my-compositions/2017/2017-02 The Rainbow Flower/1 Chhutti Ka Din/music/"
"/media/data/anon/1-music-scores/2-my-compositions/2019/2019-03 Kahe Natak Karte Ho Ji?/2 Adi Kal Se/")
(launch-file "/media/data/anon/1-music-scores/2-my-compositions/2019/2019-03 Kahe Natak Karte Ho Ji?/2 Adi Kal Se/output/2 Adi Kal Se-pacON.pdf")
(start-process "qtractor" nil "qtractor" "/media/data/anon/8-music-production/1-my-creations/2019/natyashastra/2-adi-kal-se/adi-kal-se.qtr"))
("Data organization"
(find-dired "/media/data/anon/" "-name \\'dl\\' -size +0c"))
("Digitization"
(find-file
"/media/data/anon/Documents/Text Files/latex/Don't, Mr. Disraeli!/dont-mr-disraeli.tex")
(launch-file
"/media/data/anon/Documents/Text Files/latex/Don't, Mr. Disraeli!/dont-mr-disraeli.pdf"))
("Exercise" (chronometrist-key-values-unified-prompt "Exercise")
(chronometrist-open-log))
("Guitar"
(let* ((path-1 "/media/data/anon/Sync/Scores/guitar-solo/repertoire.org")
(path-2 "/media/data/anon/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)
(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"
;; (async-shell-command "java -jar ~/josm-tested.jar" " *JOSM*" " *JOSM errors*")
;; (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/Texinfo/mcclim.html")
(find-file-other-window
"/media/data/phone/anon/Nokia 6.1/Documents/Markor/Computers/todo.md"))
("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 "/media/data/anon/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")
(launch-file "/media/data/anon/1-music-scores/4-my-arrangements/2021/2021-03-11 Hallelujah/output/2021-03-11 Hallelujah-pacON.pdf")
(find-file "/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
***** commit-prompt
#+BEGIN_SRC emacs-lisp
(autoload 'magit-anything-modified-p "magit")
(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.
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
***** before-project-stop
#+BEGIN_SRC emacs-lisp
(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
***** after-project-stop
#+BEGIN_SRC emacs-lisp
(require 'request)
(require 'esxml-query)
(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.
(request
"https://api.openstreetmap.org/api/0.6/changesets"
:params '(("display_name" . "contrapunctus"))
:parser (lambda () (libxml-parse-xml-region (point) (point-max)))
:success
(cl-function
(lambda (&key data &allow-other-keys)
(let* ((latest-changeset (-> data
(esxml-node-children)
(car)))
(comment (->> latest-changeset
(esxml-query "[k=comment]")
(esxml-node-attributes)
(cdr)
(car)
(cdr)))
(id (-> latest-changeset
(esxml-node-attributes)
(car)
(cdr))))
(chronometrist-append-to-last-expr nil
`(:osm-url ,(concat "https://www.openstreetmap.org/changeset/" id)
:osm-comment ,comment)))))))
(_ (delete-other-windows))))
#+END_SRC
***** display-key-values
#+BEGIN_SRC emacs-lisp
;; (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))
(defun contrapunctus-display-key-values-function (plist)
"Function used to print key-values in `chronometrist-details' buffers."
(let ((key-values (chronometrist-plist-key-values plist)))
(pcase (plist-get plist :name)
("Programming"
(-let [(&plist :project project
:feature feature
:component component) plist]
(contrapunctus-objects-to-string " - " project component feature)))
("Guitar"
(-let* (((&plist :piece
(&plist :name name
:bwv bwv :opus opus
:movement movement))
plist)
(catalog-name (cond (opus "Op.") (bwv "BWV ") (t "")))
(catalog (format "(%s%s)" catalog-name (or opus bwv)))
(movement (cond ((not movement) "")
((chronometrist-plist-pp-alist-p movement)
(contrapunctus-objects-to-string ", " " - " (mapcar #'cdr movement)))
(t (format "- %s" (cdr movement))))))
(contrapunctus-objects-to-string " " name catalog movement)))
("Cooking"
(-let (((&plist :recipe (&plist :name name)) plist)
((&plist :recipe recipe) plist))
recipe))
("Video editing"
(-let [(&plist :episode ep) plist]
(contrapunctus-objects-to-string " " "episode" ep)))
("Exercise"
(-let* (((&plist :warm-up warm-up
:syllabus syllabus
:abdomen abdomen) plist)
(key (cond (warm-up :warm-up)
(syllabus :syllabus)
(abdomen :abdomen)))
(content (or warm-up syllabus abdomen))
(key-string (format "%s - " (s-chop-prefix ":" (symbol-name key))))
(content-string (if (chronometrist-plist-pp-alist-p content)
(cl-loop for elt in content
if (and (consp elt)
(atom (car elt))
(atom (cdr elt)))
collect (format "%s %s" (car elt) (cdr elt))
else collect (format "%s" elt)))))
(concat key-string (contrapunctus-objects-to-string ", " content-string))))
(_ "Task not implemented"))))
#+END_SRC
**** key-values
#+BEGIN_SRC emacs-lisp
(use-package chronometrist-key-values
:after chronometrist
:load-path "~/.emacs.d/contrapunctus/chronometrist/elisp/")
#+END_SRC
**** count-expressions
#+BEGIN_SRC emacs-lisp
(defun contrapunctus-count-expressions ()
(interactive)
(chronometrist-sexp-in-file chronometrist-file
(goto-char (point-min))
(cl-loop with count = 0
while (ignore-errors (read (current-buffer)))
do (cl-incf count)
finally do (message "%s" count))))
#+END_SRC
**** tangling
Wrote these two as potential alternatives to `org-babel-tangle', which was far slower than I'd like (took around 20s for chronometrist.org when I checked during the migration process, and 43s after the migration was complete.) These, on the other hand, are almost instant, but I don't use them anywhere because I run a sed script as a file local variable.
#+BEGIN_SRC emacs-lisp
(defun chronometrist-tangle ()
(goto-char (point-min))
(cl-loop with source
while (not (eobp))
when (looking-at-p (rx (and line-start (zero-or-more blank) line-end)))
concat (progn
(forward-line 1)
(buffer-substring-no-properties
(point)
(cl-loop while (not (eobp))
if (looking-at-p (rx (and line-start
(zero-or-more blank)
line-end)))
do (cl-return (point))
else do (forward-line 1)))) into source
do (forward-line 1)
finally do
(with-current-buffer (find-file-noselect "chronometrist.el")
(delete-region (point-min) (point-max))
(insert source)
(save-buffer))))
(defun chronometrist-tangle-sed ()
(let* ((file-path (buffer-file-name
(current-buffer)))
(base (file-name-base file-path)))
(when (equal "chronometrist.org" (file-name-nondirectory file-path))
(start-process-shell-command
"sed-tangle"
(generate-new-buffer-name "sed-tangle")
(format "sed -n '/#+BEGIN_SRC emacs-lisp$/,/#+END_SRC$/{//!p;}' ~s.org > ~s.el" base base)))))
#+END_SRC
**** querying data
An example of querying the Chronometrist file data - finding out how much time I've spent on tasks matching a certain criteria.
#+BEGIN_SRC emacs-lisp :tangle no :load no
(chronometrist-loop-file for plist in chronometrist-file
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 over %s days."
(ts-human-format-duration seconds)
count)))
#+END_SRC
Intervals and durations for task Exercise.
#+BEGIN_SRC emacs-lisp :tangle no :load no
(chronometrist-loop-file for plist in chronometrist-file
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)))
#+END_SRC
Unique key-values for task "Exercise"
#+BEGIN_SRC emacs-lisp :tangle no :load no
(chronometrist-loop-file for plist in chronometrist-file
when
(equal (plist-get plist :name) "Exercise")
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))))
#+END_SRC
*** 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
#+BEGIN_SRC emacs-lisp
(use-package emms
:after hydra
:bind
("<f2> e" . #'contrapunctus-emms-hydra/body)
("<f2> E" . #'emms)
(:map dired-mode-map
("E" . #'contrapunctus-emms-hydra/body))
:commands
(emms-minimalistic emms emms-play-dired emms-add-dired)
:config
(emms-minimalistic)
(emms-default-players)
(setq emms-player-mpv-parameters
(lambda ()
(append
'("--fs"
"--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))))))
;; ;; 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)))
(use-package emms-playlist-mode
:bind
(: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)
("M-c" . #'emms-playlist-mode-center-current)
("SPC" . #'emms-pause)
("K" . #'emms-playlist-clear))
:config
(setq emms-playlist-buffer-name "EMMS Playlist"))
(use-package emms-info-tinytag
:init
(setq emms-info-functions '(emms-info-tinytag))
:config
(setq emms-info-tinytag-python-name "python3"))
#+END_SRC
*** Internet
**** eww
#+BEGIN_SRC emacs-lisp
(use-package eww
:config
(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))
;; end boon-specific config
(:map eww-mode-map
("b" . #'eww-back-url)
("f" . #'eww-forward-url)
("v" . nil)))
#+END_SRC
**** url-cookie
Ask for confirmation before saving cookies. I'd rather just disallow them all though 🤔
#+BEGIN_SRC emacs-lisp
(use-package url-cookie
:config
(setq url-cookie-confirmation t))
#+END_SRC
**** elpher
#+BEGIN_SRC emacs-lisp
(use-package elpher
: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)))
#+END_SRC
**** elfeed
#+BEGIN_SRC emacs-lisp
(use-package elfeed
:bind (:map elfeed-show-mode-map
("v" . nil))
:config
(add-to-list 'boon-special-mode-list 'elfeed-show-mode)
(add-to-list 'boon-special-mode-list 'elfeed-search-mode))
#+END_SRC
**** jabber
#+BEGIN_SRC emacs-lisp
(use-package jabber
:load-path "/home/anon/.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
*** sxiv
#+BEGIN_SRC emacs-lisp
(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
**
#+BEGIN_SRC emacs-lisp
;; (load "cp-adb")
#+END_SRC
**
#+BEGIN_SRC emacs-lisp
(require 'cp-editing)
;; (load "cp-evil")
(require 'cp-lily)
(require 'cp-sfz)
(require 'cp-lisp)
(require 'cp-nav)
;; (ispell-change-dictionary "en")
(setq ispell-dictionary "en")
#+END_SRC
*** TODO emacsshot
PR ideas
1. [ ] create directories in save path if they don't exist
2. [ ] grammar - "written /path/to/file"
#+BEGIN_SRC emacs-lisp
(use-package emacsshot
:config
(setq emacsshot-with-timestamp t
emacsshot-snap-window-filename "/media/data/anon/Pictures/screenshots/emacsshot/emacsshot.png"))
#+END_SRC
*** File management
#+BEGIN_SRC emacs-lisp
(use-package dired
:init (add-hook 'dired-mode-hook 'turn-on-launch-mode)
:config
(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"
;; by date, no --group-directories-first
;; "-cgGhlt --time-style=long-iso"
)
: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)
("H" . dired-omit-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))))
(use-package dired-async
:init (dired-async-mode 1))
(use-package dired-x
:commands dired-jump
:bind
("C-x C-d" . dired-jump))
#+END_SRC
#+BEGIN_SRC emacs-lisp
;; 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))
#+END_SRC
#+BEGIN_SRC emacs-lisp
(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))))
#+END_SRC
#+BEGIN_SRC emacs-lisp
;; (with-eval-after-load 'project-explorer
;; (global-set-key (kbd "<f5> e") 'project-explorer-toggle))
(use-package dired-hide-dotfiles
:hook (dired-mode . (lambda () (dired-hide-dotfiles-mode))))
;; (require 'sudo-edit)
(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))))))
(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)))))
(defun cp/launch-file-archive ()
(interactive)
(launch-file
(concat
default-directory
(aref (archive-get-descr) 0))))
;; (define-key archive-mode-map (kbd "j") 'cp/launch-file-archive)
;; 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"))))))
;; 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))))
(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))))
(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))))
#+END_SRC
#+BEGIN_SRC emacs-lisp
(use-package contrasync
:load-path "~/.emacs.d/contrapunctus/contrasync/"
:config
(setq contrasync-disk-path "/media/anon/kash-sg-2tb/"
contrasync-source-paths
`("~/.emacs.d/"
"/media/data/anon/1-music-notation/"
"/media/data/anon/Documents/"
"~/.config/"
"~/.local/"
("/media/data/anon/phone/Nokia 6.1/" ,contrasync-disk-path "phone/Nokia 6.1/"))))
(use-package peep-dired
:disabled
;; ;; didn't work too well 🤔
;; :config
;; (setq peep-dired-cleanup-eagerly t)
:hook
(dired-mode . peep-dired))
#+END_SRC
*** mail
#+BEGIN_SRC emacs-lisp
(use-package wl
:disabled
:config
(setq wl-icon-directory "~/.emacs.d/wl/icons"
wl-smtp-posting-server "disroot.org"))
(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))
(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"))
(use-package message
:hook
(message-mode . (lambda () (auto-fill-mode -1)))
(message-mode . visual-fill-column-mode))
#+END_SRC
** comint
#+BEGIN_SRC emacs-lisp
(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
** company-emoji
#+BEGIN_SRC emacs-lisp
(use-package company-emoji
:hook (text-mode . company-emoji-init)
:config (add-to-list 'company-backends 'company-emoji))
#+END_SRC
** counsel
#+BEGIN_SRC emacs-lisp
(use-package counsel
:bind ("M-x" . counsel-M-x)
:config
(setq counsel-find-file-ignore-regexp "\\`\\."))
;; (use-package elsa
;; :commands flycheck-elsa-setup)
#+END_SRC
** 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
** easy-kill :disabled:editing:
#+BEGIN_SRC emacs-lisp
(use-package easy-kill
:disabled
:bind (("M-w" . easy-kill)
("M-d" . easy-kill-delete-region)))
#+END_SRC
** TODO hydra [66%]
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. [ ] remove duplication
#+BEGIN_SRC emacs-lisp
(use-package hydra :commands defhydra)
#+END_SRC
*** Line display
#+BEGIN_SRC emacs-lisp
(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"))
#+END_SRC
*** Window
#+BEGIN_SRC emacs-lisp
(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"))
#+END_SRC
*** multiple cursors
#+BEGIN_SRC emacs-lisp
(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)
("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
*** 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")
("l" (info "(lilypond-notation)") "Lilypond notation")
("L" (info "(lilypond-learning)") "Lilypond learning")
("o" (info "(org)") "Org")
("g" (info "(guile)") "Guile"))
#+END_SRC
*** General
#+BEGIN_SRC emacs-lisp
(defhydra contrapunctus-general-hydra (:color blue)
"What command?"
("G" elpher "elpher")
("O" cp-org/body "org")
("p" contrapunctus-programming-hydra-dispatch-language "programming")
("P" list-packages "packages")
("e" contrapunctus-emms-hydra/body "emms")
("j" cp-jabber/body "Jabber")
("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)
("c" chronometrist "chronometrist")
("C" contrapunctus-mc-hydra/body "multiple cursors")
("d" dired-jump "dired-jump")
("D" (cp-insert-timestamp t) "date")
("E" toggle-debug-on-error "tdoe")
("h" helpful-at-point "Help")
("i" (find-file "~/.emacs.d/init.org") "open init")
("I" contrapunctus-info-hydra/body "Info")
("k" (kill-buffer (current-buffer)) "kill")
("m" magit-status "magit")
("N" contrapunctus-line-display-hydra/body "line display")
("o" save-buffer "save")
("Q" toggle-debug-on-quit "tdoq")
("T" cp-insert-timestamp "timestamp")
("u" find-file "new")
("U" launch-file "launch-file")
("v" find-alternate-file "revert")
("w" contrapunctus-window-hydra/body "window"))
#+END_SRC
*** org
#+BEGIN_SRC emacs-lisp
(defhydra cp-org (:color blue)
"Org"
("p" org-set-property "property")
("b" cp-org-block/body "source block")
("t" cp-org-set-tags "tags")
("n" cp-org-nav/body "navigation")
("B" contrapunctus-async-tangle "babel-tangle")
("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)
("c" chronometrist "chronometrist")
("C" contrapunctus-mc-hydra/body "multiple cursors")
("d" dired-jump "dired-jump")
("D" (cp-insert-timestamp t) "date")
("E" toggle-debug-on-error "tdoe")
("G" contrapunctus-general-hydra/body "up")
("h" helpful-at-point "Help")
("i" (find-file "~/.emacs.d/init.org") "open init")
("I" contrapunctus-info-hydra/body "Info")
("k" (kill-buffer (current-buffer)) "kill")
("m" magit-status "magit")
("N" contrapunctus-line-display-hydra/body "line display")
("o" save-buffer "save")
("Q" toggle-debug-on-quit "tdoq")
("T" cp-insert-timestamp "timestamp")
("u" find-file "new")
("U" launch-file "launch-file")
("v" find-alternate-file "revert")
("w" contrapunctus-window-hydra/body "window"))
#+END_SRC
**** org block
#+BEGIN_SRC emacs-lisp
(defhydra cp-org-block (:color blue)
"Org source block"
("e" (cp-org-insert-block "SRC" "emacs-lisp") "Emacs Lisp")
("t" (cp-org-insert-block "SRC" "emacs-lisp :tangle test :load test") "Emacs Lisp test")
("E" (cp-org-insert-block "SRC" "emacs-lisp :tangle no :load no") "Emacs Lisp example")
("s" (cp-org-insert-block "SRC" "shell :tangle no") "Shell")
("o" (cp-org-insert-block "QUOTE") "quote")
("v" (cp-org-insert-block "VERSE") "verse"))
#+END_SRC
**** org navigation
#+BEGIN_SRC emacs-lisp
(defhydra cp-org-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")
("s" outline-down-heading "down 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")
;; modification
("C" org-drag-element-backward "drag backward")
("R" org-drag-element-forward "drag forward")
("H" org-promote-subtree "promote")
("S" org-demote-subtree "demote"))
#+END_SRC
*** jabber
#+BEGIN_SRC emacs-lisp
(defhydra cp-jabber (:color blue)
"Jabber"
("c" jabber-connect "connect")
("r" jabber-display-roster "roster")
("n" jabber-activity-switch-to "next" :color red)
("i" (find-file "~/.emacs.d/init.org") "open init")
("I" contrapunctus-info-hydra/body "Info")
("E" toggle-debug-on-error "tdoe")
("w" contrapunctus-window-hydra/body "window")
("k" (kill-buffer (current-buffer)) "kill")
("N" contrapunctus-line-display-hydra/body "line display")
("G" contrapunctus-general-hydra/body "up"))
#+END_SRC
*** Emacs Lisp
#+BEGIN_SRC emacs-lisp
(defhydra cp-el (:color blue)
"Emacs Lisp"
("r" ielm "REPL")
("E" cp-el-debug/body "Debug")
("e" cp-el-eval/body "Eval")
("h" helpful-at-point "Help")
("j" xref-find-definitions "Jump to definition")
("J" org-babel-tangle-jump-to-org "Jump to definition (Org)")
("t" (contrapunctus-el-test/body) "Test")
("B" contrapunctus-async-tangle "babel-tangle")
("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)
("C" contrapunctus-mc-hydra/body "multiple cursors")
("i" (find-file "~/.emacs.d/init.org") "open init")
("I" contrapunctus-info-hydra/body "Info")
("d" dired-jump "dired-jump")
("u" find-file "new")
("o" save-buffer "save")
("k" (kill-buffer (current-buffer)) "kill")
("N" contrapunctus-line-display-hydra/body "line display")
("w" contrapunctus-window-hydra/body "window")
("c" chronometrist "chronometrist")
("m" magit-status "Magit")
("G" contrapunctus-programming-hydra/body "up")
("T" cp-insert-timestamp "timestamp")
("D" (cp-insert-timestamp t) "date"))
#+END_SRC
**** eval
#+BEGIN_SRC emacs-lisp
(defhydra cp-el-eval (:color blue)
("b" eval-buffer "buffer")
("e" eval-defun "defun")
("l" eval-last-sexp "last sexp"))
#+END_SRC
**** unit testing
#+BEGIN_SRC emacs-lisp
(defhydra contrapunctus-el-test (:color blue)
("e" (cp/compile-project "Cask" "cask exec buttercup -L . --traceback pretty") "buttercup")
("r" ert "ert"))
#+END_SRC
**** debug
#+BEGIN_SRC emacs-lisp
(defhydra cp-el-debug (:color blue)
"Debug"
("e" (funcall-interactively #'eval-defun t) "edebug")
("o" toggle-debug-on-error "tdoe")
("u" toggle-debug-on-quit "tdoq"))
#+END_SRC
*** Common Lisp
#+BEGIN_SRC emacs-lisp
(defhydra cp-cl (:color blue)
"Common Lisp"
("C" slime-connect "connect")
("d" cp-cl-doc/body "Documentation")
("e" cp-cl-eval/body "Eval")
("r" slime "REPL")
("i" (find-file "~/.emacs.d/init.org") "open init")
("D" dired-jump "dired-jump")
("u" find-file "new")
("o" save-buffer "save")
("k" (kill-buffer (current-buffer)) "kill")
("N" contrapunctus-line-display-hydra/body "line display")
("w" contrapunctus-window-hydra/body "window")
("c" chronometrist "chronometrist")
("m" magit-status "Magit")
("G" contrapunctus-programming-hydra/body "up"))
#+END_SRC
**** eval
#+BEGIN_SRC emacs-lisp
(defhydra cp-cl-eval (:color blue)
("b" slime-eval-buffer "buffer")
("e" slime-eval-defun "defun"))
#+END_SRC
**** documentation
#+BEGIN_SRC emacs-lisp
(defhydra cp-cl-doc (:color blue)
("d" slime-documentation "slime")
("e" slime-documentation-lookup "CLHS"))
#+END_SRC
*** 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"))
#+END_SRC
**** CHICKEN Scheme
#+BEGIN_SRC emacs-lisp
(defhydra cp-cs (:color blue)
"CHICKEN Scheme"
("e" cp-scm-eval/body "Eval")
("r" run-chicken "REPL")
("i" (find-file "~/.emacs.d/init.org") "open init")
("d" dired-jump "dired-jump")
("u" find-file "new")
("o" save-buffer "save")
("k" (kill-buffer (current-buffer)) "kill")
("N" contrapunctus-line-display-hydra/body "line display")
("w" contrapunctus-window-hydra/body "window")
("c" chronometrist "chronometrist")
("m" magit-status "Magit")
("G" contrapunctus-programming-hydra/body "up"))
#+END_SRC
**** Guile
#+BEGIN_SRC emacs-lisp
(defhydra cp-guile (:color blue)
"Guile"
("e" cp-scm-eval/body "Eval")
("r" run-guile "REPL")
("i" (find-file "~/.emacs.d/init.org") "open init")
("d" dired-jump "dired-jump")
("u" find-file "new")
("o" save-buffer "save")
("k" (kill-buffer (current-buffer)) "kill")
("N" contrapunctus-line-display-hydra/body "line display")
("w" contrapunctus-window-hydra/body "window")
("c" chronometrist "chronometrist")
("m" magit-status "Magit")
("G" contrapunctus-programming-hydra/body "up"))
#+END_SRC
*** Lilypond
#+BEGIN_SRC emacs-lisp
(defhydra cp-ly (:color blue)
"Lilypond"
("b" (cp/compile-project "main.ly" "./mkly dev") "Compile")
("i" (find-file "~/.emacs.d/init.org") "open init")
("I" contrapunctus-info-hydra/body "Info")
("d" dired-jump "dired-jump")
("u" find-file "new")
("o" save-buffer "save")
("k" (kill-buffer (current-buffer)) "kill")
("N" contrapunctus-line-display-hydra/body "line display")
("w" contrapunctus-window-hydra/body "window")
("c" chronometrist "chronometrist")
("m" magit-status "Magit")
("E" toggle-debug-on-error "tdoe")
("Q" toggle-debug-on-quit "tdoq")
("G" contrapunctus-programming-hydra/body "up"))
#+END_SRC
*** Prolog
#+BEGIN_SRC emacs-lisp
(defhydra cp-prolog (:color blue)
"Prolog"
("r" ediprolog-dwim "REPL")
("i" (find-file "~/.emacs.d/init.org") "open init")
("d" dired-jump "dired-jump")
("u" find-file "new")
("o" save-buffer "save")
("k" (kill-buffer (current-buffer)) "kill")
("N" contrapunctus-line-display-hydra/body "line display")
("w" contrapunctus-window-hydra/body "window")
("c" chronometrist "chronometrist")
("m" magit-status "Magit")
("G" contrapunctus-programming-hydra/body "up"))
#+END_SRC
*** Programming
#+BEGIN_SRC emacs-lisp
(defhydra contrapunctus-programming-hydra (:color blue)
"Which language?"
("e" cp-el/body "Emacs Lisp")
("c" cp-cs/body "CHICKEN Scheme")
("g" cp-guile/body "Guile")
("L" cp-ly/body "Lilypond")
("l" cp-cl/body "Common Lisp")
("O" cp-org/body "Org")
("p" cp-prolog/body "Prolog")
("i" (find-file "~/.emacs.d/init.org") "open init")
("d" dired-jump "dired-jump")
("u" find-file "new")
("o" save-buffer "save")
("k" (kill-buffer (current-buffer)) "kill")
("N" contrapunctus-line-display-hydra/body "line display")
("w" contrapunctus-window-hydra/body "window")
("c" chronometrist "chronometrist")
("m" magit-status "Magit")
("E" toggle-debug-on-error "tdoe")
("Q" toggle-debug-on-quit "tdoq")
("G" contrapunctus-general-hydra/body "up")
("D" (cp-insert-timestamp t) "date"))
#+END_SRC
Don't try to check if there are files with a certain extension...it will lead to false positives.
#+BEGIN_SRC emacs-lisp
(defun contrapunctus-programming-hydra-dispatch-language ()
(interactive)
(cond ((derived-mode-p 'emacs-lisp-mode
'inferior-emacs-lisp-mode
'debugger-mode)
(cp-el/body))
(;; (or (locate-dominating-file default-directory "build.scm")
;; (locate-dominating-file default-directory "main.ly"))
(derived-mode-p 'LilyPond-mode)
(cp-ly/body))
((and (featurep 'geiser)
(bound-and-true-p geiser-mode))
(cond ((equal 'chicken geiser-impl--implementation)
(cp-cs/body))
((equal 'guile geiser-impl--implementation)
(cp-guile/body))
(t (error "Couldn't detect Scheme implementation."))))
((derived-mode-p 'lisp-mode 'slime-repl-mode)
(cp-cl/body))
((derived-mode-p 'org-mode)
(cp-org/body))
((derived-mode-p 'prog-mode)
(contrapunctus-programming-hydra/body))
(t (contrapunctus-general-hydra/body))))
(define-key boon-command-map (kbd "m") #'contrapunctus-programming-hydra-dispatch-language)
(global-set-key (kbd "C-s") #'contrapunctus-programming-hydra-dispatch-language)
(define-key boon-command-map (kbd "C-s") #'contrapunctus-programming-hydra-dispatch-language)
#+END_SRC
** eshell
#+BEGIN_SRC emacs-lisp
(use-package eshell
:config (setq eshell-history-size 999))
#+END_SRC
** image-mode
#+BEGIN_SRC emacs-lisp
(use-package image-mode
:bind
(:map image-map
("o" . nil)
("r" . nil))
(:map image-mode-map
("o" . nil)
("r" . nil)))
#+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
;; :ensure t
;; :init (global-flycheck-mode))
;; (use-package flycheck-elsa
;; :hook (emacs-lisp-mode . flycheck-elsa-setup))
#+END_SRC
** environment variables
#+BEGIN_SRC emacs-lisp
(setenv "PATH" (concat "/home/anon/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
#+BEGIN_SRC emacs-lisp
;; (add-to-list 'load-path "~/.emacs.d/elisp-git/yafolding.el/")
#+END_SRC
** general (keybindings)
#+BEGIN_SRC emacs-lisp
(use-package general
:commands general-define-key)
;; 2017-06-09T00:24:36+0530
;; my laptop's X, W, and G keys gave up the ghost
;; temporary bindings, till my laptop keyboard is fixed
;; 2020-01-07T12:43:41+0530
;; update to use general, add M-f8 binding
#+END_SRC
** misc keybindings
#+BEGIN_SRC emacs-lisp
(general-define-key
"<f8>" 'keyboard-quit
"M-<f8>" 'eval-defun
"M-<f9>" 'dired-jump
"<f10>" 'save-buffer
"M-<f10>" 'find-file
"<f11>" 'ido-mini
"M-<f11>" 'ibuffer
"<f12>" 'execute-extended-command
"M-<f12>" 'text-scale-adjust
"C-c C-j" 'join-line
"C-c C-r" (lambda () (interactive) (revert-buffer t t))
;; for swapped parenthesis and square brackets layout
"C-)" 'abort-recursive-edit)
;;;; UTF-8 magic
#+END_SRC
** UTF-8 incantations
#+BEGIN_SRC emacs-lisp
(setq locale-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)
#+END_SRC
** Linewrapping
#+BEGIN_SRC emacs-lisp
(add-hook 'erc-mode-hook 'visual-line-mode)
(add-hook 'text-mode-hook 'visual-line-mode)
(use-package visual-fill-column
:hook
(markdown-mode . visual-fill-column-mode)
(markdown-mode . visual-line-mode)
(org-mode . visual-line-mode)
(org-mode . visual-fill-column-mode)
(message-mode . visual-fill-column-mode)
(eww-mode . visual-line-mode)
(eww-mode . visual-fill-column-mode))
#+END_SRC
** TODO LaTeX
1. [ ] merge personal commands with those in Lilypond mode
#+BEGIN_SRC emacs-lisp
(use-package auctex
: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
TeX-view-program-selection '(((output-dvi has-no-display-manager)
"dvi2tty")
((output-dvi style-pstricks)
"dvips and gv")
(output-dvi "xdvi")
(output-pdf "Zathura")
(output-html "xdg-open")))
;; 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
** Org
#+BEGIN_SRC emacs-lisp
(use-package org
:commands (org-drag-line-backward org-drag-line-forward)
: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))
:config
(general-def "<f5> o" 'org-mode)
(general-def org-mode-map
"C-," 'nil
"M-r" 'org-metadown
"M-c" 'org-metaup
"C-c C--" 'org-ctrl-c-minus
"C-c C-," 'org-metaleft
"C-c C-." 'org-metaright
;; "C-j" 'org-return
;; "C-m" 'org-return-indent
"C-c C-9" 'org-mark-ring-goto
"C-c C-/" 'org-sparse-tree
"M-w" 'cp-copy-line-or-link
"C-c C-]" 'cp-org-set-tags
"C-M-x" 'cp/eval-sexp
"C-c C-o" 'cp/org-open
;; boon
"C-c C--" 'org-ctrl-c-minus
"C-c ]" 'cp-org-set-tags
"C-c ," 'org-metaleft
"C-c ." 'org-metaright
"M-h" 'default-indent-new-line)
(mapc (lambda (pair)
(add-to-list 'org-file-apps pair))
'(("txt" . emacs)
("org" . emacs)
;; ("pdf" . zathura)
("\\(?:gif\\|jpe?g\\|png\\)" . "sxiv -f %s")
;; (t . "xdg-open %s")
("pdf" . system)
;; ("pdf" . "zathura %s")
;; (auto-mode . emacs)
;; (system . "xdg-open %s")
(system . "zathura %s")
;; (t . system)
))
(setq org-todo-keywords '((sequence "TODO" "RESEARCH" "STARTED" "DONE"))
org-image-actual-width 400
org-cycle-include-plain-lists 'integrate
org-link-search-must-match-exact-headline nil
org-html-head "<link rel=\"stylesheet\" type=\"text/css\" href=\"contrapunctus/org-html.css\" />"
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"
"xpm" "pbm" "pgm" "ppm" "webp") t)))))
;; https://lists.gnu.org/archive/html/emacs-orgmode/2018-02/msg00082.html
(defun org-link-gemini-export-link (link desc format)
"Create export version of LINK and DESC to FORMAT."
(let ((link (concat "gemini://" link)))
(cond
((eq format 'html)
(format "<a href=\"%s\">%s</a>" link desc))
((eq format 'latex)
(format "\\href{%s}{%s}" link desc))
(t ;; `ascii', `md', `hugo', etc.
(format "[%s](%s)" desc link)))))
(org-link-set-parameters "gemini" :export #'org-link-gemini-export-link)
(add-hook 'org-insert-heading-hook #'contrapunctus-org-insert-timestamp))
(defun cp-org-insert-block (type &optional lang)
"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\"."
(let* ((column (- (point) (point-at-bol)))
(indent (make-string column ?\ ))
(region-start (region-beginning))
(region-end (region-end))
(start-string (format "#+BEGIN_%s %s\n" type
(if (stringp lang) lang "")))
(end-string (format "%s#+END_%s" indent type)))
;; create a block around a region - preserve position of point
(cond ((region-active-p)
(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))))))
;; (use-package org-src-mode
;; :hook (org-src-mode . (lambda () (when (derived-mode-p 'emacs-lisp-mode)))))
;; (defun cp-org-expand-all ()
;; (interactive)
;; ;; todo - define inner recursive function
;; (beginning-of-buffer)
;; ;; todo - check if we are on a heading
;; (org-forward-heading-same-level)
;; ())
;; 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.
(defun cp/org-open (&optional arg reference-buffer)
(interactive "P")
(beginning-of-visual-line)
(unless (looking-at-p (rx-to-string '(or "http" "[")))
(org-next-link))
(org-open-at-point))
(defun cp-copy-line-or-link (prefix-arg)
"Copy address of org-mode link after point, ignoring whitespace,
link description (if any) and org-mode header and list syntax. If
not before a link, or with a prefix arg, call
`whole-line-or-region-kill-ring-save' instead.
BUG - improper behaviour with checkboxes.
2018-03-17T21:15:17+0530 - hopefully fixed now."
(interactive "P")
(let ((point-a (point)))
(cl-flet ((copy-to-closing-bracket
()
(let ((point-b (point)))
(re-search-forward "\\]")
(copy-region-as-kill point-b
(- (point) 1)))))
(if (save-excursion
(or (use-region-p)
prefix-arg
(cp/re-search-line "\\[[-X ]\\]")))
(whole-line-or-region-kill-ring-save prefix-arg)
(cond ( ;; (cp/org-link-ahead-p)
(cp/re-search-line "\\[")
;; (if (looking-at "\\[")
;; (forward-char))
(forward-char)
(copy-to-closing-bracket)
(goto-char point-a))
( ;; (cp/org-link-ahead-p 'implicit)
(cp/re-search-line "http")
(backward-word)
(let ((point-b (point)))
(re-search-forward (rx (or eol (and printing " "))))
(copy-region-as-kill point-b
(point)))
(goto-char point-a))
;; TODO - org-previous-link will land you at the start
;; of the DESCRIPTION of the previous link, if it has
;; one, but to the user it will look like they are at
;; the start of the link. Add a case to handle this.
;; Does not work if there is an org TODO marker in a
;; header.
(t (whole-line-or-region-kill-ring-save prefix-arg)))))))
(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: "))))
(defun cp-org-set-tags ()
(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)))))
(defun contrapunctus-org-insert-timestamp ()
(save-excursion
(insert "\n" "<" (format-time-string "%FT%T%z") ">")))
(use-package org-indent
:hook (org-mode . org-indent-mode))
(use-package ox-texinfo)
#+END_SRC
** markdown-mode :editing:
#+BEGIN_SRC emacs-lisp
(use-package markdown-mode
: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)))
(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))))))
#+END_SRC
**
#+BEGIN_SRC emacs-lisp
(setq truncate-partial-width-windows nil
truncate-lines t)
#+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
** scrolling
#+BEGIN_SRC emacs-lisp
(setq scroll-conservatively 10000
scroll-preserve-screen-position t
auto-window-vscroll nil)
#+END_SRC
** 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)
#+END_SRC
**
#+BEGIN_SRC emacs-lisp
(global-set-key (kbd "C-s") 'isearch-forward-regexp)
#+END_SRC
**
#+BEGIN_SRC emacs-lisp
(global-set-key (kbd "C-r") 'isearch-backward-regexp)
;;;; While we're at it, let's add that to next-error as well
;;;; (this affects jumping to match from M-x grep , too)
#+END_SRC
**
#+BEGIN_SRC emacs-lisp
(add-hook 'next-error-hook 'recenter)
#+END_SRC
** date and time
#+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)))))
(use-package time
:config
(setq display-time-next-load-average t)
(add-to-list 'zoneinfo-style-world-list '("Europe/Berlin" "Berlin")))
#+END_SRC
**
#+BEGIN_SRC emacs-lisp
(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
** helpful
#+BEGIN_SRC emacs-lisp
(use-package helpful
:bind (("<f1> <f1>" . #'helpful-at-point)
("<f1> f" . #'helpful-callable)
("<f1> c" . #'helpful-command)
("<f1> k" . #'helpful-key)
("<f1> v" . #'helpful-variable)))
#+END_SRC
** ibuffer
#+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
** info
#+BEGIN_SRC emacs-lisp
(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
**
#+BEGIN_SRC emacs-lisp
(general-define-key
;; "s-k" 'cp-kill-buffer
"s-k" 'bury-buffer
"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
;; [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
** help-mode
#+BEGIN_SRC emacs-lisp
(use-package help-mode
:bind
(:map help-mode-map
("b" . help-go-back)
("f" . help-go-forward)))
#+END_SRC
** Unicode keys
#+BEGIN_SRC emacs-lisp
(general-auto-unbind-keys)
(general-def
:prefix "M--"
"r -" [?₹] "- r" [?₹]
"- -" [?—]
"- L" [] "L -" []
;; German
"\" a" [] "a \"" [] "\" A" [] "A \"" []
"\" e" [] "e \"" [] "\" E" [] "E \"" []
"\" o" [] "o \"" [] "\" O" [] "O \"" []
"\" u" [] "u \"" [] "\" U" [] "U \"" []
"s s" []
;; French
", c" [] "c ," [] ", C" [] "C ," []
"' e" [] "e '" []
"e `" [] "` e" []
"e ^" [] "^ e" []
"' a" [] "a '" []
"a `" [] "` a" []
"a ^" [] "^ a" []
"o e" []
"o o" [] "x x" [?×]
"1 2" [] "1 3" [?⅓] "1 4" []
"2 3" [?⅔] "2 5" [?⅖]
"3 4" [] "3 5" [?⅗]
"4 5" [?⅘]
"b" [?♭]
"e" [?€]
"< -" [?←]
"- >" [?→]
"^ |" [?↑] "| ^" [?↑]
"v |" [?↓] "| v" [?↓]
", \\" [] "l" []
"C-' F" (kbd "ƒ"))
(general-auto-unbind-keys t)
(setq default-input-method "devanagari-itrans")
#+END_SRC
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
** backup configuration
#+BEGIN_SRC emacs-lisp
(setq backup-by-copying t
backup-directory-alist '(("." . "~/.emacs.d/saves/"))
delete-old-versions t
kept-new-versions 2
kept-old-versions 2
version-control t)
#+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
** Ivy
#+BEGIN_SRC emacs-lisp
(use-package ivy
:commands ivy-mode
:init (ivy-mode)
:bind (:map ivy-minibuffer-map
("C-h" . ivy-backward-delete-char))
:config
(setq ivy-re-builders-alist
'((t . ivy--regex-ignore-order))))
#+END_SRC
** TODO magit [0%]
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" :\
#+BEGIN_SRC emacs-lisp
(use-package magit
: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-post-stage . (lambda () (recenter)))
:config
(defadvice magit-section-toggle
(after magit-section-toggle-recenter activate) (recenter 3))
(ad-activate 'magit-section-toggle)
(defadvice magit-unstage-item
(after magit-unstage-item-move) (next-line))
(ad-activate 'magit-unstage-item)
(defadvice magit-goto-next-section
(after magit-next-section-recenter activate) (recenter 3))
(ad-activate 'magit-goto-next-section)
(defadvice magit-goto-previous-section
(after magit-previous-section-recenter activate) (recenter 3))
(ad-activate 'magit-goto-previous-section))
#+END_SRC
#+BEGIN_SRC emacs-lisp
(use-package git-commit
:bind
(:map git-commit-mode-map
("M-c" . git-commit-prev-message)
("M-r" . git-commit-next-message)))
#+END_SRC
** markup
*** mediawiki-mode
#+BEGIN_SRC emacs-lisp
(use-package mediawiki
:commands mediawiki-mode)
#+END_SRC
*** asciidoc-mode
Used by Eldev documentation.
#+BEGIN_SRC emacs-lisp
(use-package adoc-mode
:mode "\\.adoc$")
#+END_SRC
** midnight-mode
#+BEGIN_SRC emacs-lisp
(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))
:hook
(midnight . clean-buffer-list))
#+END_SRC
** Programming
*** 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=
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.
#+BEGIN_SRC emacs-lisp
(use-package keyswap
:disabled t
: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)
(emacs-lisp-mode . keyswap-colon-semicolon)
(ielm-mode . contrapunctus-swap-brackets-parens)
(ielm-mode . keyswap-colon-semicolon)
(lisp-mode . keyswap-colon-semicolon)
(slime-repl-mode . contrapunctus-swap-brackets-parens)
(slime-repl-mode . keyswap-colon-semicolon)
(scheme-mode . keyswap-colon-semicolon)
(geiser-repl-mode . contrapunctus-swap-brackets-parens)
(geiser-repl-mode . keyswap-colon-semicolon))
:config
(defun contrapunctus-keyswap-common ()
(setq-local keyswap-pairs nil) ;; dont swap numbers and symbols
(keyswap-mode))
(defun contrapunctus-swap-brackets-parens ()
;; (message "keyswap-pairs is %s" keyswap-pairs)
(contrapunctus-keyswap-common)
(keyswap-add-pairs ?\[ ?\()
(keyswap-add-pairs ?\] ?\))
(keyswap-update-keys)))
#+END_SRC
**** other things
#+BEGIN_SRC emacs-lisp
(use-package projectile
:hook (prog-mode . projectile-mode)
:bind (:map boon-command-map
("\\" . projectile-command-map)))
#+END_SRC
#+BEGIN_SRC emacs-lisp
(use-package rainbow-delimiters
:hook (prog-mode . rainbow-delimiters-mode))
#+END_SRC
#+BEGIN_SRC emacs-lisp
(use-package company
:diminish company-mode
:commands global-company-mode
:init (global-company-mode)
:bind ;; ("TAB" . company-indent-or-complete-common)
(:map emacs-lisp-mode-map
("TAB" . company-indent-or-complete-common)
("C-i" . company-indent-or-complete-common))
(:map company-active-map
("M-c" . company-select-previous)
("M-r" . company-select-next)
("C-h" . backward-delete-char))
;; 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))
#+END_SRC
#+BEGIN_SRC emacs-lisp
(use-package feature-mode
:mode "\\.feature$")
#+END_SRC
#+BEGIN_SRC emacs-lisp
(defun cp/compile-project (file cmd)
"Locate directory with FILE and run compile command CMD."
(cd (locate-dominating-file default-directory file))
(compile cmd))
#+END_SRC
**** smartparens
#+BEGIN_SRC emacs-lisp
(use-package smartparens
:load-path "~/.emacs.d/elisp-git/smartparens/"
:init
(smartparens-global-mode)
: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)
("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
**** 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)
#+BEGIN_SRC emacs-lisp
(use-package lispy
:hook (emacs-lisp-mode . lispy-mode)
;; Boon-style keys on Dvorak
:bind
(:map lispy-mode-map
;; change HJKL to Boon-like (QWERTY) KIOL
("t" . special-lispy-left) ;; QWERTY K
("n" . special-lispy-right) ;; QWERTY L
("c" . special-lispy-up) ;; QWERTY I
("r" . special-lispy-down) ;; QWERTY O
;; bind the replaced commands to Dvorak HJKL
("h" . special-lispy-teleport)
("j" . special-lispy-occur)
("k" . special-lispy-clone)
("l" . special-lispy-new-copy)
;; Lispy shadows this, but it's essential for Org literate programs
("M-o" . nil)
("M-o M-o" . font-lock-fontify-block)))
**** treemacs
#+BEGIN_SRC emacs-lisp
(use-package treemacs
:bind (:map treemacs-mode-map
([mouse-1] . #'treemacs-single-click-expand-action))
:config
(treemacs-tag-follow-mode)
(treemacs-toggle-fixed-width)
(setq treemacs-tag-follow-delay 0))
#+END_SRC
**** imenu
#+BEGIN_SRC emacs-lisp
(use-package imenu
:config (setq imenu-auto-rescan t))
#+END_SRC
**** side-hustle
#+BEGIN_SRC emacs-lisp
(use-package side-hustle
:bind
(:map side-hustle-mode-map
(("r" . next-line)
("c" . previous-line))))
#+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
**** 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
**** nameless-mode
#+BEGIN_SRC emacs-lisp
(use-package nameless
:commands nameless-mode
:hook
(ert-results-mode . nameless-mode)
(emacs-lisp-mode . nameless-mode)
(org-mode . nameless-mode)
:bind (:map emacs-lisp-mode-map
("C-c C-n" . nameless-mode)))
#+END_SRC
**** explain-pause-mode
#+BEGIN_SRC emacs-lisp
(use-package explain-pause-mode
:load-path "/home/anon/.emacs.d/elisp-git/explain-pause-mode/"
:disabled t
:diminish
:commands explain-pause-mode
:init (explain-pause-mode))
#+END_SRC
**** async-tangle
#+BEGIN_SRC emacs-lisp
(defun contrapunctus-async-tangle (&optional prefix)
(interactive "P")
(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))
(new-win (split-window-below)))
(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))
;; to avoid messing up my usual two-windows-same-buffer setup
(select-window new-win)
(switch-to-buffer proc-buffer)
;; so I can access my Hydra to switch back
(boon-mode)
(select-window old-win)))
#+END_SRC
*** Common Lisp
#+BEGIN_SRC emacs-lisp
(use-package redshank
:hook (slime-mode . redshank-mode))
(use-package slime
:commands (slime-eval-buffer slime-eval-defun)
:bind
(:map slime-mode-map
("M-n" . next-line)
("M-p" . previous-line)
("SPC" . self-insert-command)
("<f1> <f1>" . slime-documentation))
(:map slime-repl-mode-map
("M-p" . slime-repl-previous-matching-input) ;; QWERTY "r"
("M-c" . slime-repl-previous-input)
("M-r" . slime-repl-next-input))
:config
(slime-setup t)
(setq inferior-lisp-program
;; "/usr/bin/ecl"
"/home/anon/bin/sbcl"
;; "/usr/bin/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"
:username "contrapunctus")))
(defun set-cl-repl-keys ()
(if (or (cp-buffer-name-match-p "^\*inferior-lisp\*\\(<[0-9]*>\\)?")
(eq major-mode 'lisp-mode))
(progn
(local-set-key (kbd "TAB") 'completion-at-point)
(local-set-key (kbd "M-'") 'sp-indent-defun))))
(add-hook 'slime-connected-hook 'set-cl-repl-keys)
(add-hook 'comint-mode-hook 'set-cl-repl-keys)
(add-hook 'lisp-mode-hook 'set-cl-repl-keys)
#+END_SRC
*** Scheme
**** CHICKEN Scheme
**** Guile
*** Lilypond
*** Prolog
#+BEGIN_SRC emacs-lisp
(use-package ediprolog
:commands ediprolog-dwim)
#+END_SRC
*** c
#+BEGIN_SRC emacs-lisp
(use-package c-mode
:bind (:map c-mode-map
("TAB" . company-indent-or-complete-common)
("C-i" . company-indent-or-complete-common)))
(use-package cc-mode)
(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
** nov.el
#+BEGIN_SRC emacs-lisp
(use-package nov
:mode ("\\.epub\\'" . nov-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)
("M-c" . nov-history-back)
("M-r" . nov-history-forward)))
#+END_SRC
** package
#+BEGIN_SRC emacs-lisp
(use-package package
:bind
(:map package-menu-mode-map
("c" . package-autoremove))
:config
(when (featurep 'boon)
(general-def package-menu-mode-map
"X" 'package-menu-execute)))
#+END_SRC
** feather
#+BEGIN_SRC emacs-lisp
(use-package feather
:diminish
:hook (package-menu-mode . feather-mode)
:bind ("<f5> p " . list-packages))
#+END_SRC
**
#+BEGIN_SRC emacs-lisp
#+END_SRC
**
#+BEGIN_SRC emacs-lisp
(use-package swiper
:bind
(("C-s" . swiper)
("C-r" . swiper-backward))
:config
(setq swiper-action-recenter t))
#+END_SRC
** mode line
*** powerline :disabled:
#+BEGIN_SRC emacs-lisp
(use-package powerline)
#+END_SRC
** undo-tree
#+BEGIN_SRC emacs-lisp
(use-package undo-tree
:commands global-undo-tree-mode
:if (not (featurep 'evil))
:diminish undo-tree-mode
:init (global-undo-tree-mode))
#+END_SRC
**
#+BEGIN_SRC emacs-lisp
(with-eval-after-load 'text-mode
(define-key text-mode-map (kbd "M-p") 'org-drag-line-backward)
(define-key text-mode-map (kbd "M-n") 'org-drag-line-forward))
#+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
(let ((project-dir (locate-dominating-file file-path ;; "build.scm""
;; "mkly-rules.scm"
"mkly")))
(when project-dir
(cd project-dir)
(compile "./mkly dev"
;; "./build.scm main pac=on"
))))
('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
**
#+BEGIN_SRC emacs-lisp
(use-package compile
:config
;; (add-hook 'compilation-start-hook
;; (lambda (proc)
;; (delete-other-windows)))
(setq compilation-always-kill t))
#+END_SRC
**
#+BEGIN_SRC emacs-lisp
(require 'cp-hindi)
;; (require 'cp-parens)
#+END_SRC
**
#+BEGIN_SRC emacs-lisp
(use-package keyfreq
:disabled
:init
(keyfreq-mode 1)
(keyfreq-autosave-mode 1))
;; ;; 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
** recentf
#+BEGIN_SRC emacs-lisp
(use-package recentf
:init (recentf-mode 1)
:bind ("C-x C-r C-o" . recentf-open-files)
:config
(setq recentf-auto-cleanup 'never
recentf-max-menu-items 500
recentf-max-saved-items 1000
recentf-save-file "/home/anon/.emacs.d/recentf"
recentf-exclude '("\\.html\\(\\.orig\\)?$"
"\\.jpe?g$"
"\\.png$"
"\\.mp4$"
"\\.etc"
"\\.umstuff"))
:hook
(kill-emacs . recentf-cleanup))
#+END_SRC
**
#+BEGIN_SRC emacs-lisp
;;;; text size change
;; nicked from wasamasa's init - https://github.com/wasamasa/dotemacs/blob/934d0b37692d62fe9af56b52accac5bcd4445ae3/init.org
#+END_SRC
**
#+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
**
#+BEGIN_SRC emacs-lisp
(use-package wgrep
:commands (wgrep-change-to-wgrep-mode))
#+END_SRC
** outline-minor-mode
#+BEGIN_SRC emacs-lisp
(use-package outline
:hook (adoc-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
** custom.el
#+BEGIN_SRC emacs-lisp
(setq custom-file "~/.emacs.d/custom.el")
(load custom-file)
#+END_SRC
** Theme
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
(load-theme 'doom-acario-dark)
#+END_SRC
Similar to doom-acario-dark, with paler colors. But Org headlines are all much too similar for my liking.
#+BEGIN_SRC emacs-lisp :load no
(load-theme 'doom-material)
#+END_SRC
#+BEGIN_SRC emacs-lisp
(load-theme 'doom-molokai)
#+END_SRC
** enabling disabled commands
#+BEGIN_SRC emacs-lisp
(mapc (lambda (command)
(put command 'disabled nil))
'(downcase-region
upcase-region
set-goal-column
scroll-left
erc-remove-text-properties-region))
#+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 ""
desktop-buffers-not-to-save "")
(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
**
#+BEGIN_SRC emacs-lisp
(put 'list-timers 'disabled nil)
#+END_SRC
** GC reset
#+BEGIN_SRC emacs-lisp
(setq gc-cons-threshold 400000)
;; (toggle-debug-on-quit)
;; (profiler-stop)
;; (emacs-init-time)
;; (profiler-report)
#+END_SRC
** The End
#+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)
# End: