dotemacs/init.org

46 KiB

I initially tried using the literate-elisp package, but -

  1. It doesn't interoperate with describe-*, helpful, or xref (see https://github.com/jingtaozf/literate-elisp/issues/7 )
  2. It seems to evaluate one source block at a time, resulting in an error if I split up a form across multiple source blocks.

And org-babel-tangle takes nearly 27 seconds to tangle this file, at the time of writing. So I went back to using sed - see file local variables below.

init.org

user interface

(use-package cp-ui
  :demand
  :load-path "~/.emacs.d/contrapunctus/")

ediff

(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 "i") 'ediff-previous-difference)
              (define-key ediff-mode-map (kbd "o") 'ediff-next-difference))))

atomic-chrome

(require 'atomic-chrome)
(atomic-chrome-start-server)
(setq atomic-chrome-url-major-mode-alist
      '(("wikisource" . mediawiki-mode)))

emacs settings

(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)))

esup, the Emacs StartUp Profiler

(use-package esup
  :config (setq esup-depth 0))

doc-view

(use-package doc-view
  :config
  (setq doc-view-resolution 300))

gnutls

(use-package gnutls
  :config
  ;; https://debbugs.gnu.org/cgi/bugreport.cgi?bug=36749
  (setq gnutls-algorithm-priority "NORMAL:-VERS-TLS1.3"))

ag, the Silver Searcher

(use-package ag
  :bind
  ("<f2> p" . ag)
  ("<f2> P" . ag-project-regexp)
  :config
  (setq ag-highlight-search t))

modal editing

active boon config

(use-package boon
  :ensure t
  :commands (boon-mode)
  :bind
  (:map boon-command-map
        ("C-l" . recenter-top-bottom)
        ("r"   . swiper)
        ("/"   . undo-tree-undo)
        ("?"   . undo-tree-redo)
        ("G"   . join-line) ;; mnemonic - Glue (I'd like to bind J and
        ;; : to sentence movement once I extend
        ;; Boon to select by sentence movement)
      ;; ("TAB" . 'company-indent-or-complete-common)
        ;; ;; this works, but also breaks unfolding in org mode :\
      ;; ("<tab>" . 'company-indent-or-complete-common)
        ("C"   . 'boon-toggle-comment)
        ("t"   . nil)
        ("t w" . 'transpose-words)
        ("t e" . 'transpose-sexps)
        ("t l" . 'transpose-lines)
        ("t p" . 'transpose-paragraphs)
        ("t c" . 'transpose-chars)
        ("\\" . projectile-command-map)
        ("("  . boon-navigate-backward)
        (")"  . boon-navigate-forward)
        ("e r" . swiper-thing-at-point))
  (:map boon-x-map
        ("w" . 'write-file)
        ("s" . 'save-buffer)
        ("d" . 'dired-jump)
        ("e" . 'eval-last-sexp)
        ("f" . 'find-file)
        ("c" . 'kill-emacs)
        ("v" . 'find-alternate-file)
        ("b" . 'ibuffer)
        ("=" . text-scale-adjust)
        ("-" . text-scale-adjust))
  :config
  (use-package boon-qwerty)
  ;; (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)
  ;; :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))

experimental boon+modalka config   disabled

(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))

experimental Emacs-flavored-Boon config   disabled

(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))

modalka   disabled

<2019-11-03 Sun> 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.

(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)

time tracking - chronometrist   application

choice.el is required by chronometrist-key-values

(use-package choice
  :load-path "~/.emacs.d/contrapunctus/choice/")

(use-package chronometrist
  ;; :disabled t
  :load-path "~/.emacs.d/contrapunctus/chronometrist/elisp/"
  :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))
  :config
  (require 'chronometrist-key-values)
  (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-choice
                                  ;; chronometrist-kv-add
                                  ;; chronometrist-skip-query-reset
                                  )
        chronometrist-after-out-functions  '(contrapunctus-after-project-stop)
        chronometrist-activity-indicator   'contrapunctus-chronometrist-activity-indicator))

(use-package chronometrist-goal
  :load-path "~/.emacs.d/contrapunctus/chronometrist-goal/"
  :hook (chronometrist-mode . chronometrist-goal-minor-mode)
  :config
  (setq chronometrist-goal-list
        '((15  "Arrangement/new edition")
          (15  "Aural exercises")
          (15  "Transcription" "Theory")
          (30  "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))

(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-time))

(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))

(defun cp-outline-open-heading (n)
  (goto-char (point-min))
  (outline-next-visible-heading n)
  (outline-show-subtree))

(defun contrapunctus-start-project (project)
  (delete-other-windows)
  (pcase project
    ("Arrangement/new edition"
     (delete-other-windows)
     (find-file
      "~/1-music-notation/4-my-arrangements/2020/2020-11-27 Winterreise/01 Gute Nacht/music/")
     (launch-file
      "~/1-music-notation/4-my-arrangements/2020/2020-11-27 Winterreise/01 Gute Nacht/output/01 Gute Nacht-pacON.pdf")
     (launch-file
      "~/Sync/Scores/voice/Schubert, Franz/IMSLP570459-PMLP2203-D_911,_Winterreise.pdf"))
    ("Aural exercises"
     (find-file-other-window "~/phone/Nokia 6.1/Documents/Markor/Music/Analyse.md"))
    ("Composing"
     (find-file-other-window
      "~/1-music-notation/2-my-compositions/2017/2017-02 The Rainbow Flower/1 Chhutti Ka Din/music/"))
    ("Data organization"
     (find-dired "~/" "-name \\'dl\\' -size +0c"))
    ("Digitization"
     (find-file "~/Documents/Text Files/latex/Don't, Mr. Disraeli!/dont-mr-disraeli.tex")
     (split-window-below)
     (find-file "~/Pictures/1280px-KB_Programmer_Dvorak.svg.png"))
    ("Exercise"
     (let* ((path-1 "~/Documents/Text Files/ma/practice.org")
            (path-2 "~/Documents/Text Files/ma/0shoto-syllabus.org")
            (file-1 (file-name-nondirectory path-1))
            (file-2 (file-name-nondirectory path-2)))
       (contrapunctus-find-two-files path-1 path-2)
       (select-window (get-buffer-window file-1))))
    ("Guitar"
     (let* ((path-1 "~/Sync/Scores/guitar-solo/repertoire.org")
            (path-2 "~/Sync/Scores/guitar-duo/repertoire.org")
            (weekday (elt (decode-time) 6))
            (week    (string-to-number (format-time-string "%U"))))
       (contrapunctus-find-two-files path-1 path-2)
       (select-window (get-buffer-window (get-file-buffer path-1)))
       (org-match-sparse-tree nil "perform")))
    ("Keyboard"
     (find-file-other-window "~/Documents/Text Files/music_stuff/piano.org")
     (outline-show-subtree))
    ("Khilona archiving"
     (find-file-other-window "~/Documents/sync/Khilona/")
     (split-window-below)
     (other-window 1)
     (find-file "~/Khilona/Videos/Me?/")
     (other-window 1)
     (find-file "~/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 "~/phone/Nokia 6.1/Android/data/net.osmand.plus/files/"
                                     ;; "~/phone/Nokia 6.1/external/DCIM/OpenCamera/osm/"
                                     "~/phone/Nokia 6.1/Documents/Markor/OSM/TODO.md"))
    ("Programming"
     (launch-file "~/git/cl/McCLIM/Documentation/Manual/Texinfo/mcclim.pdf")
     (find-file-other-window "~/phone/Nokia 6.1/Documents/Markor/Computers/todo.md"))
    ("Singing"
     (find-file-other-window "~/Sync/Scores/voice/repertoire.org"))
    ("Subtitles"
     ;; (find-file-other-window "~/Music/0-classical/vocal/musical/Company/")
     (start-process "subtitleeditor" nil "subtitleeditor" "/home/khilona/Videos/Peer Gynt/peer-gynt.srt"))
    ("Teaching"
     (find-file-other-window "~/Documents/Text Files/students/")
     ;; (launch-file "~/Sync/Scores/voice/jingle-bell-rock.pdf")
     )
    ("Theatre rehearsal"
     (contrapunctus-find-two-files
      "~/Documents/Text Files/khilona/voices.org"
      "~/1-music-notation/2-my-compositions/2019/2019-03 Kahe Natak Karte Ho Ji/Kahe Natak Karte Ho Ji.org"))
    ("Transcription"
     ;; (find-file-other-window
     ;;  "~/phone/Nokia 6.1/Documents/Markor/Music/transcriptions.md")
     (emms-play-file "~/Music/christmas/Glee - Jingle Bell Rock (Lyrics)-VfLf7A_-1Vw.webm")
     (find-file "~/1-music-notation/3-my-transcriptions/Glee - Jingle Bell Rock/music/")
     (launch-file "~/1-music-notation/3-my-transcriptions/Glee - Jingle Bell Rock/output/Glee - Jingle Bell Rock-pacON.pdf"))
    ("Video editing"
     (start-process "flatpak" (generate-new-buffer-name "kdenlive")
                    "flatpak" "run" "org.kde.kdenlive"
                    "/home/khilona/Videos/ghar ghar theatre 3/ggt3.kdenlive")
     (find-alternate-file-other-window "/home/khilona/Videos/ghar ghar theatre 3/"
                                       ;; "/home/khilona/Videos/podcast/"
                                       ))
    ("Wiktionary"
     (find-file-other-window
      "~/phone/Nokia 6.1/Documents/Markor/Languages/hindi.md"))
    ("Writing"
     (find-file-other-window
      "~/phone/Nokia 6.1/Documents/Markor/Songs or Poems/"))))

(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)))

(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))

(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))))

(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))))

;; 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.
(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)))))

comint

(use-package comint
  :bind (:map comint-mode-map
              ("M-p" . #'comint-previous-matching-input-from-input)
              ("M-n" . #'comint-next-matching-input-from-input)))

company-emoji

(use-package company-emoji
  :hook (text-mode . company-emoji-init)
  :config (add-to-list 'company-backends 'company-emoji))

counsel

(use-package counsel
  :bind ("M-x" . counsel-M-x)
  :config
  (setq counsel-find-file-ignore-regexp "\\`\\."))

;; (use-package elsa
;;   :commands flycheck-elsa-setup)

misc keybindings

(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)

easy-kill   disabled

(use-package easy-kill
  :disabled
  :bind (("M-w" . easy-kill)
         ("M-d" . easy-kill-delete-region)))

elpher   application

(use-package elpher
  :bind (:map elpher-mode-map
              ("n" . elpher-next-link)
              ("p" . elpher-prev-link)
              ("b" . elpher-back)
              ("w" . elpher-copy-current-url)
              ("W" . elpher-copy-link-url)))

elfeed   application

(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))

hydra

(use-package hydra
  :commands defhydra)

WISH emms   application

  1. make toggle command for emms-start/emms-stop
  2. change mode line display - don't show the whole file path, just the name
(use-package emms
  :after hydra
  :bind
  ("<f2> e"   . #'hydra-emms/body)
  ("<f2> E"   . #'emms)
  (:map dired-mode-map
        ("E" . #'hydra-emms/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 hydra-emms ()
          ("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)
        ("n"        . #'next-line)
        ("p"        . #'previous-line)
        ("N"        . #'emms-next)
        ("P"        . #'emms-previous)
        ("R"        . #'emms-toggle-random-playlist)
        ("M-n"      . #'emms-cue-next)
        ("M-p"      . #'emms-cue-previous)
        ("SPC"      . #'emms-pause))
  :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"))

eshell

(use-package eshell
  :config (setq eshell-history-size 999))

eww   application

(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)))

url-cookie

Ask for confirmation before saving cookies. I'd rather just disallow them all though 🤔

(use-package url-cookie
  :config
  (setq url-cookie-confirmation t))

image-mode

(use-package image-mode
  :bind
  (:map image-map
        ("o" . nil))
  (:map image-mode-map
        ("o" . nil)))

flx-ido   disabled

(use-package flx-ido
  :disabled
  :init (flx-ido-mode 1)
  (setq ido-enable-flex-matching t
        ido-use-faces nil))

flx-isearch   disabled

(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))

environment variables

(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)
;; (add-to-list 'load-path "~/.emacs.d/elisp-git/yafolding.el/")

ido-mini

(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
         ("J" . ido-mini)
         ("M" . ido-mini)
         :map boon-x-map
         ("l" . ido-mini))
  :config
  (ivy-mode))

**

(load "cp")

;; (if (not (server-running-p)) (server-start))

**

(server-start)

**

(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

misc keybindings

(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

UTF-8 incantations

(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)

Linewrapping

(add-hook 'org-mode-hook 'visual-line-mode)
(add-hook 'erc-mode-hook 'visual-line-mode)
;(global-set-key (kbd "C-x t") 'toggle-truncate-lines)
(add-hook 'text-mode-hook 'visual-line-mode)
(cl-loop for hook in
  '(dired-mode-hook prog-mode-hook diff-mode-hook message-mode-hook)
  do (add-hook hook (lambda () (toggle-truncate-lines 1))))
(global-visual-line-mode -1)

markdown-mode   editing

(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-n" . markdown-move-down)
        ("M-p" . 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))))))

**

(setq truncate-partial-width-windows nil
      truncate-lines t)

**

(add-hook 'erc-mode-hook 'visual-line-mode)

**

(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)

**

(setq tab-width 4)
;(define-key text-mode-map (kbd "TAB") 'self-insert-command)

**

(setq-default indent-tabs-mode nil)

scrolling

(setq scroll-conservatively 10000
      scroll-preserve-screen-position t
      auto-window-vscroll nil)

Recenter screen on isearch matches

(add-hook 'isearch-mode-hook 'recenter)
(add-hook 'isearch-update-post-hook 'recenter)
(defadvice isearch-repeat-forward
    (after isearch-repeat-forward-recenter activate) (recenter))
(defadvice isearch-repeat-backward
    (after isearch-repeat-backward-recenter activate) (recenter))
(ad-activate 'isearch-repeat-forward)
(ad-activate 'isearch-repeat-backward)

**

(global-set-key (kbd "C-s") 'isearch-forward-regexp)

**

(global-set-key (kbd "C-r") 'isearch-backward-regexp)

;;;; While we're at it, let's add that to next-error as well
;;;; (this affects jumping to match from M-x grep , too)

**

(add-hook 'next-error-hook 'recenter)

date and time

(defun cp-insert-timestamp ()
  (interactive)
  (insert (format-time-string "%FT%T%z")))

(defun cp-insert-date ()
  (interactive)
  (insert (format-time-string "%F")))

(use-package time
  :config
  (setq display-time-next-load-average t)
  (add-to-list 'zoneinfo-style-world-list '("Europe/Berlin" "Berlin")))

**

(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))))

helpful

(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)))

ibuffer

(use-package ibuffer
  :bind
  (:map ibuffer-mode-map

This is basically here because Boon hijacks the x key.

        ("X" . 'ibuffer-do-kill-on-deletion-marks)))

info

(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
  (("<f1> i" . nil)
   ("<f1> i i" . info)
   ("<f1> i a" . info-apropos)
   ("<f1> i q" . (lambda () (interactive) (info "(emacs)")))
   ("<f1> i w" . (lambda () (interactive) (info "(elisp)")))
   ("<f1> i l" . (lambda () (interactive) (info "(lilypond-notation)")))
   ("<f1> i r" . (lambda () (interactive) (info "(lilypond-learning)")))
   ("<f1> i s" . (lambda () (interactive) (info "(stumpwm)")))
   ("<f1> i o" . (lambda () (interactive) (info "(org)")))
   ("<f1> i g" . (lambda () (interactive) (info "(guile)"))))
  :bind
  (:map Info-mode-map
        ("b" . Info-history-back)
        ("f" . Info-history-forward)))

**

(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)

**

(general-define-key
 :prefix "<f1>"
 "M"    'describe-mode
 "m"    'man
 "l"    'find-library)

**

(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)

**

(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)

**

(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
 )

help-mode

(use-package help-mode
  :bind
  (:map help-mode-map
        ("b" . help-go-back)
        ("f" . help-go-forward)))

Unicode keys

(global-unset-key (kbd "M-["))
(general-def
  "C-' r"   (kbd "₹")
  "C-' C-r" (kbd "₹")
  "C-' e"   (kbd "€")
  "C-' b"   (kbd "←")
  "C-' f"   (kbd "→")
  "C-' p"   (kbd "↑")
  "C-' n"   (kbd "↓")
  "C-' l"   (kbd "λ")
  "C-' F"   (kbd "ƒ"))
(setq default-input-method "devanagari-itrans")

backup configuration

(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)

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.

(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))

Ivy

(use-package ivy
  :commands ivy-mode
  :init (ivy-mode)
  :config
  (setq ivy-re-builders-alist
        '((t . ivy--regex-ignore-order))))

jabber   disabled

(use-package jabber
  :disabled
  :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))

WISH magit

It'd be really cool to (recenter 3) when you open a section, and (recenter) when you close a section

(use-package magit
  :bind (("<f5> m" . #'magit-status)
         :map magit-revision-mode-map
         ;; boon
         ("o" . magit-section-forward)
         ("i" . magit-section-backward)
         :map magit-status-mode-map
         ;; boon
         ("o" . magit-section-forward)
         ("i" . magit-section-backward)
         ;; ([mouse-3] . 'magit-section-toggle)
         ([down-mouse-3] . 'mouse-set-point)
         ([up-mouse-3] . 'magit-section-toggle))
  :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))

mediawiki-mode

(use-package mediawiki
  :commands mediawiki-mode)

midnight-mode

(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))

nodejs-repl   disabled

(use-package nodejs-repl
  :disabled
  :config (setq nodejs-repl-command "nodejs"))

nov.el

(use-package nov
  :mode ("\\.epub\\'" . nov-mode))

package

(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)))

feather

(use-package feather
  :diminish
  :hook (package-menu-mode . feather-mode)
  :bind ("<f5> p " . list-packages))

**

(use-package powerline)

**

(use-package rainbow-delimiters
  :hook (prog-mode . rainbow-delimiters-mode))

**

(use-package swiper
  :bind
  (("C-s" . swiper)
   ("C-r" . swiper-backward))
  :config
  (setq swiper-action-recenter t))

sxiv   application

(use-package sxiv
  :config (setq sxiv-exclude-strings '("meh" "\\.NEF$")))

**

;; (load "cp-adb")

**

(require 'cp-editing)
;; (load "cp-evil")
(require 'cp-fm)
(require 'cp-lily)
(require 'cp-sfz)
(require 'cp-prog)
(require 'cp-lisp)
(require 'cp-nav)

;; (ispell-change-dictionary "en")

**

(setq ispell-dictionary "en")

undo-tree

(use-package undo-tree
  :commands global-undo-tree-mode
  :if (not (featurep 'evil))
  :diminish undo-tree-mode
  :init (global-undo-tree-mode))

**

(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))

**

(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)
;;  )

**

(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"))))
      ('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")))
         (when project-dir
           (cd project-dir)
           (compile "~/bin/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)

**

(use-package compile
  :config
  ;; (add-hook 'compilation-start-hook
  ;;           (lambda (proc)
  ;;             (delete-other-windows)))
  (setq compilation-always-kill t))

**

(require 'cp-hindi)
(require 'cp-parens)

**

(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)))

recentf

(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))

**

;;;; text size change
;; nicked from wasamasa's init - https://github.com/wasamasa/dotemacs/blob/934d0b37692d62fe9af56b52accac5bcd4445ae3/init.org

**

(setq default-frame-alist '((font . "DejaVu Sans Mono-10.5")))

**

(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")

**

(use-package wgrep
  :commands (wgrep-change-to-wgrep-mode))

custom.el

(setq custom-file "~/.emacs.d/custom.el")
(load custom-file)

doom-acario-dark

Must put this after loading the custom file, or I get prompted about the theme each time.

(require 'doom-themes)
(load-theme 'doom-acario-dark)

**

(mapc (lambda (command)
        (put command 'disabled nil))
      '(downcase-region
        upcase-region
        set-goal-column
        scroll-left
        erc-remove-text-properties-region))

**

(require 'cp-org)
(require 'cp-desktop)
(require 'cp-mail)

**

(put 'list-timers 'disabled nil)

GC reset

(setq gc-cons-threshold 400000)

;; (toggle-debug-on-quit)
;; (profiler-stop)
;; (emacs-init-time)
;; (profiler-report)

The End

(provide 'init)
;;; init.el ends here