Skip to content
This repository has been archived by the owner on Sep 1, 2023. It is now read-only.

Latest commit

 

History

History
1488 lines (1369 loc) · 45.4 KB

main.org

File metadata and controls

1488 lines (1369 loc) · 45.4 KB

My Emacs Configuration

This is not a true literate configuration. Packages that demand complex configuration are configured in separate files. I am rewriting this configuration for a better understanding of my previous work and organizing it in a more sensible way.

Table of contents

Dependencies for other packages

These packages may be required by other packages loaded later on.

Built-in

(autoload 'setq-mode-local "mode-local")

dash.el

Quite a few packages depend on dash.el and/or dash-functional.el, so they should be loaded in the very beginning of package declarations.

(use-package dash)
(use-package dash-functional)

f

(use-package f)

Ivy

(akirak/require 'setup-ivy t)

Helm

(akirak/require 'setup-helm t)

posframe

(akirak/require 'setup-posframe)

Hydra

(akirak/require 'setup-hydra)
(defconst akirak/major-mode-hydra-key "M-SPC")

ov (overlays)

(use-package ov
  :straight (ov :host github :repo "ShingoFukuyama/ov.el"))

ts (date-time library by alphapapa)

(use-package ts
  :straight (ts :host github :repo "alphapapa/ts.el"))

org-ql

(use-package org-ql
  :custom
  (org-ql-views nil))

all-the-icons

(use-package all-the-icons
  ;; I prefer install fonts using Nix
  ;; :preface
  ;; (defconst akirak/all-the-icons-status-file
  ;;   (no-littering-expand-var-file-name "all-the-icons"))
  ;; (defvar akirak/all-the-icons-fonts-installed
  ;;   (file-exists-p akirak/all-the-icons-status-file))
  ;; :config
  ;; (defun akirak/all-the-icons-install-fonts-if-missing ()
  ;;   (unless akirak/all-the-icons-fonts-installed
  ;;     (all-the-icons-install-fonts t)))
  ;; (defun akirak/all-the-icons-mark-as-fonts-installed ()
  ;;   (with-temp-buffer
  ;;     (write-file akirak/all-the-icons-status-file))
  ;;   (setq akirak/all-the-icons-fonts-installed t))
  ;; (advice-add #'all-the-icons-install-fonts
  ;;             :after #'akirak/all-the-icons-mark-as-fonts-installed)
  ;; (when (and (window-system)
  ;;            (not akirak/all-the-icons-fonts-installed))
  ;;   (all-the-icons-install-fonts))
  :general
  ("C-x 8 i" #'all-the-icons-ivy))

emacsql-sqlite

emacsql-sqlite depends on a pre-built binary executable. This is built and installed by Nix package manager.

(use-package emacsql-sqlite
  :straight (emacsql-sqlite :type built-in)
  :if (akirak/library-exists-p "emacsql-sqlite"))

memoize

(use-package memoize)

desktop integration

(defun akirak/locate-xdg-desktop-file (desktop)
  (-some (lambda (root)
           (when (file-directory-p root)
             (car (directory-files-recursively root
                                               (concat "^" (regexp-quote desktop) "$")
                                               t))))
         counsel-linux-apps-directories))

(defun akirak/get-xdg-desktop-window-class (desktop-file)
  (with-temp-buffer
    (insert-file-contents desktop-file)
    (goto-char (point-min))
    (when (re-search-forward (rx bol "StartupWmClass=") nil t)
      (buffer-substring-no-properties (point) (line-end-position)))))

language-detection

language-detection is used by eww.

(akirak/require 'setup-language-detection)

elexandria

(use-package elexandria
  :straight (:host github :repo "alphapapa/elexandria"))

Appearances

Theme

  • You can set the default theme using the customization interface.
  • You can override the default theme at startup with --theme command line option, e.g. emacs --theme poet.
(defcustom akirak/default-theme-module 'setup-dracula-theme
  "Symbol of a module to load the default theme."
  :type '(choice (const :tag "Dracula (dark bg)" setup-dracula-theme)
                 (const :tag "Poet (light bg, especially nice for Org mode)" setup-poet-theme)
                 (const :tag "Kaolin Light (light bg)" setup-kaolin-light-theme)
                 (const :tag "Doom Solarized Light" setup-doom-solarized-light-theme)
                 (const :tag "McCarthy (light bg)" setup-mccarthy-theme))
  :group 'akirak)

(defun akirak/set-theme-from-command-line (_arg)
  (if-let ((theme-name (pop command-line-args-left)))
      (or (akirak/require (intern (concat "setup-" theme-name "-theme")))
          (progn
            (message "%s failed to load. Fallback to the default theme.")
            (akirak/require akirak/default-theme-module)))
    (error "--theme must be followed by a theme name")))

(add-to-list 'command-switch-alist
             '("--theme" . akirak/set-theme-from-command-line))

;; If the option is not given, load the default theme.
(unless (member "--theme" (cdr command-line-args))
  (akirak/require akirak/default-theme-module))

Frame elements

Due to consistency with other applications on computer, my eyes tend to stay in the upper area of a window. I prefer relying on the header line extensively rather than the modeline.

(akirak/require 'setup-header-line t)
                                        ; Hide the mode line and use the header line
(akirak/require 'setup-feebleline t)  ; Display extra information in the echo area

;; (akirak/require 'setup-centaur-tabs)

Typeface

This modules configures extra face attributes for typography. This feature is enabled if and only if a window system is available.

(cond
 ((window-system)
  (akirak/require 'setup-typeface2))
 ((daemonp)
  (defun akirak/init-typeface ()
    (let ((frame (make-frame `((window-system . ,(cl-case system-type
                                                   (darwin 'ns)
                                                   (windows-nt 'w32)
                                                   (t 'x)))
                               (visibility . nil)))))
      (unwind-protect
          (progn
            (defun akirak/ad-around-font-family-list (orig &optional _frame)
              (funcall orig frame))
            (advice-add 'font-family-list :around #'akirak/ad-around-font-family-list)
            (akirak/require 'setup-typeface2)
            (advice-remove 'font-family-list #'akirak/ad-around-font-family-list))
        (delete-frame frame))))
  (add-hook 'after-init-hook #'akirak/init-typeface)))

If your operating system supports Docker, you can use fonts-container to install fonts used in the module.

Visual enhancements

page-break-lines

(use-package page-break-lines
  :hook ((doc-mode
          compilation-mode
          outline-mode
          prog-mode
          haskell-mode
          help-mode
          magit-mode) . page-break-lines-mode))

Color support in terminal and compilation buffers

(akirak/require 'setup-terminal-colors)

Colorize color names

(use-package rainbow-mode
  ;; :diminish 'rainbow-mode
  :commands (rainbow-mode)
  :hook
  (prog-mode . (lambda () (rainbow-mode 1))))

fontify-face

(use-package fontify-face
  :hook
  (emacs-lisp . (lambda () (fontify-face-mode 1))))

Centralizing window contents

(akirak/require 'setup-perfect-margin)

I’m not using olivetti-mode

(use-package olivetti
  :disabled t
  :commands (turn-on-olivetti-mode)
  :custom (olivetti-body-width 92))

A bunch of useful features

;; desktop needs to be configured in prior to other convenience packages
(akirak/require 'setup-desktop)
(akirak/require 'setup-meta)
(akirak/require 'setup-misc)

Customizing Emacs

(akirak/require 'setup-custom)

Pretty hydras

;; C-c h
(akirak/bind-user "h" #'akirak/minor-mode-hydra/body)
(general-def [remap text-scale-adjust] 'akirak/appearance-hydra/body)
(akirak/bind-user "k" #'akirak/window-layout-hydra/body)

Minor-mode-hydra: hydra for toggling minor modes

(pretty-hydra-define akirak/minor-mode-hydra
  (:title "Minor modes"
          :foreign-keys nil
          :quit-key "q")
  ("Focus"
   (("v" view-mode :toggle t))
   "Info/check/linting"
   (("ed" eldoc-mode :toggle t)
    ("fc" flycheck-mode :toggle t)
    ("fv" flycheck-verify-setup)
    ("fs" flyspell-mode :toggle t)
    ("fp" flyspell-prog-mode :toggle t)
    ("ld" lsp-ui-doc-mode :toggle t)
    ("lp" lsp-ui-peek-mode :toggle t)
    ("ls" lsp-ui-sideline-mode :toggle t))
   "Edit/assistance"
   (("s" smartparens-mode :toggle t)
    ("S" smartparens-strict-mode :toggle t)
    ("y" lispy-mode :toggle t)
    ("el" electric-layout-mode :toggle t)
    ("ei" electric-indent-local-mode :toggle t)
    ("eq" electric-quote-local-mode :toggle t)
    ("ea" aggressive-indent-mode :toggle t)
    ("o" origami-mode :toggle t)
    ("W" whitespace-cleanup-mode))
   "Visual"
   (("w" whitespace-mode :toggle t)
    ("r" rainbow-delimiters-mode :toggle t)
    ("p" page-break-lines-mode :toggle t)
    ("n" line-number-mode :toggle t)
    ("hi" highlight-indent-guides-mode :toggle t)
    ("hc" fci-mode :toggle t))
   "LSP"
   (("lh" lsp-describe-session)
    ("lR" lsp-restart-workspace)
    ("lS" lsp-shutdown-workspace))))

Hydra for changing the appearance

(pretty-hydra-define akirak/appearance-hydra
  (:title (format "Font height: %d" akirak/font-height)
          :quit-key "q")
  ("Default font height"
   (("=" akirak/font-height-increase "increase")
    ("-" akirak/font-height-decrease "decrease")
    ("s" akirak/set-font-height "set temporarily")
    ("C-s" (customize-save-variable 'akirak/font-height akirak/font-height)
     "save"))
   "Buffer font height"
   (("+" text-scale-increase "increase")
    ("_" text-scale-decrease "decrease")
    ("!" text-scale-set "default"))
   ;; TODO: Add commands to change the theme and font families
   ;; "Faces"
   ;; (("t" akirak/load-theme-package "Change theme")
   ;;  ("f" akirak/configure-font-families "Font families"))
   "Inspect"
   (("c" describe-char))))

Hydra for managing window layouts

(pretty-hydra-define akirak/window-layout-hydra
  (:title (format "Layout\n Window size %sx%s"
                  (window-width)
                  (window-height))
          :quit-key "q")
  ("Window size"
   (("w" enlarge-window-horizontally "width+")
    ("W" shrink-window-horizontally "width-")
    ("h" enlarge-window "height+")
    ("H" shrink-window "height-")
    ("ah" (set-window-text-height (selected-window) current-prefix-arg) "abs h"))
   "Layout"
   (("b" balance-windows "Balance frm")
    ("B" (balance-windows (selected-window)) "Balance win")
    ("s" split-window-below "Split below")
    ("v" split-window-right "Split right")
    ("d" delete-window "Delete win"))
   "Switch win/buf"
   (("j" other-window "Next win")
    ("k" (other-window -1) "Prev win")
    ("l" counsel-ibuffer "Switch buf"))
   "Extra windows"
   (("tt" treemacs)
    ("te" akirak/toggle-flycheck-error-list "flycheck")
    ("ti" imenu-list-smart-toggle "imenu")
    ("tb" ibuffer-sidebar "buffers"))
   "Views"
   (("pv" ivy-pop-view "pop")
    ("pV" ivy-push-view "push")
    ("ps" ivy-switch-view "switch"))))

(defun akirak/toggle-flycheck-error-list ()
  (interactive)
  (if-let ((window (get-buffer-window "*Flycheck errors*")))
      (quit-window nil window)
    (flycheck-list-errors)))

Terminal and shells

Using vterm

I will use vterm.

(akirak/require 'setup-vterm)

To open a terminal, use vterm-toggle. vterm-toggle-cd command supports tramp.

(akirak/bind-user "t" #'akirak/vterm-toggle-cd)

Dired

(general-def "C-x C-j" #'dired-jump)

File operations

(akirak/require 'setup-files)

Full-text search (and replace)

(akirak/bind-search
  "M-f" #'org-recoll-search)

Recoll

(akirak/require 'setup-recoll)

Buffer management

;; buffer management
(general-def
  "<f5>" 'revert-buffer
  "C-x k" #'kill-this-buffer  
  "C-x C-b" #'ibuffer)

Git

Git modes

(use-package git-modes)

Git attr linguist

(use-package git-attr-linguist
  :straight git-attr
  :commands (git-attr-linguist)
  :hook (find-file . git-attr-linguist))

Magit-Todos

(use-package magit-todos
  :after magit
  :config
  (unless (akirak/windows-subsystem-for-linux-p)
    (magit-todos-mode 1))
  :custom
  (magit-todos-depth 0)
  (magit-todos-exclude-globs '("**/*.map")))

GitHub/GitLab workflow

Create a prefix key for browse-at-remote-variant commands:

(general-create-definer akirak/bind-browse-at-remote :prefix "C-x w"
  :wk "browse-at-remote")

Use forge for working with GitHub and GitLab repositories:

(akirak/require 'setup-github)

To create/fork a repository on GitHub, use hub CLI.

github-review.el looks useful for reviewing pull requests on GitHub, but I seldom receive pull requests, so I have never used it.

Browse-at-remote

browse-at-remote is another package that lets you browse a corresponding web page of the file.

(use-package browse-at-remote
  :commands (browse-at-remote))

(akirak/bind-browse-at-remote
  "l" #'browse-at-remote
  "k" #'browse-at-remote-kill)

Differences between browse-at-remote and equivalent commands from forge package:

  • browse-at-remote provides browse-at-remote-kill command.
  • browse-at-remote opens a link with a line number.

Cloning Git repositories

akirak/git-clone function lets you clone a Git repository to a designated location from a Git repository, a GitHub repository page, or a path on GitHub (account/name). It is integrated with ivy-clipurl, so you can clone a Git repository from its web page URL in the clipboard.

Vc-Msg

(akirak/require 'setup-vc-msg)

(akirak/bind-user "v" #'vc-msg-show)

Magit-List-Repositories

magit-list-repositories is a convenient command which lets you browse your repositories on the file system.

To use it, you first have to customize magit-repository-directories.

Project management

EditorConfig

(use-package editorconfig
  :config
  (editorconfig-mode 1))

DirEnv

(akirak/require 'setup-direnv)

Experimenting with remote APIs

(akirak/require 'setup-verb)

Web browser integration

(akirak/require 'setup-browse-url)
(use-package atomic-chrome
  :disabled t
  :init
  (atomic-chrome-start-server))

Emacs also provides eww:

(akirak/require 'setup-eww)

Templates

(akirak/require 'setup-expansion)

File templates

(akirak/require 'setup-autoinsert)

Frequent counsel commands

(general-def
  "C-x /" #'counsel-rg
  "C-x F" #'counsel-recentf
  "C-x L" #'counsel-locate)

Avy

(akirak/require 'setup-avy)

link-hint is not part of avy package, but it is covenient for following a link:

(akirak/bind-jump "f" 'akirak/link-hint-open-link)

Source code navigation

dumb-jump

(use-package dumb-jump
  ;; Don't enable dumb-jump-mode. Bind only necessary commands.
  :custom
  (dumb-jump-selector 'ivy))

(akirak/bind-jump
  ". " #'dumb-jump-go
  "," #'dumb-jump-back)

IMenu

(akirak/bind-search "i" 'counsel-imenu)

(akirak/bind-search :package 'org :keymaps 'org-mode-map
  "u"
  (defun akirak/helm-org-ancestors ()
    (interactive)
    (unless (derived-mode-p 'org-mode)
      (user-error "Not in org-mode"))
    (let (result
          preselect)
      (save-excursion
        (org-back-to-heading)
        (cl-flet
            ((add-candidate
              ()
              (let ((start (point-at-bol))
                    (end (point-at-eol)))
                (font-lock-ensure start end)
                (let ((cand (buffer-substring start end)))
                  (push (cons cand (point-marker))
                        result)
                  ;; Pre-select the first candidate, i.e. the current heading.
                  (unless preselect
                    (setq preselect cand))))))
          (add-candidate)
          (while (> (org-outline-level) 1)
            (org-up-heading-all 1)
            (add-candidate))))
      (helm :sources (helm-build-sync-source "Ancestor headings"
                       :candidates result
                       :action 'helm-org-headings-actions)
            :keymaps 'helm-org-headings-map
            :preselect preselect)))

  ;; Simply browse headings in the buffer.
  "i" #'helm-org-in-buffer-headings)

(akirak/bind-search :package 'restclient-helm :keymaps 'restclient-mode-map
  "i" #'helm-restclient)

imenu-list is a useful package which displays an overview of the current buffer. I’ve added it to akirak/window-layout-hydra.

(akirak/require 'setup-imenu-list)

Outline navigation

(akirak/bind-search "o" 'counsel-outline)
(akirak/bind-search :package 'org :keymaps 'org-mode-map
  "o" #'helm-org-ql)

Outline editing

(general-def :keymaps 'outline-minor-mode-map :package 'outshine
  "M-RET" 'outshine-insert-heading)
(general-unbind :keymaps 'lispy-mode-map :package 'lispy "M-RET")
(akirak/require 'setup-origami)

Referencing and reading

(akirak/require 'setup-referencing)

PDF

Use pdf-tools.

pdf-tools is installed using Nix.

EPUB

(akirak/require 'setup-epub)

Pocket

Read pocket-reader to read web pages on Emacs.

(akirak/require 'setup-pocket)

Annotating documents

You can use org-noter to annotate PDF documents as well as other formats supported by doc-view.

I will bind A to org-noter both in pdf-tools and doc-view:

(general-def :keymaps 'doc-view-mode-map :package 'doc-view
  "A" #'org-noter)

(general-def :keymaps 'pdf-view-mode-map :package 'pdf-view
  "A" #'org-noter)

General tools for editing source code

(akirak/require 'setup-edit)

Expand Region

(akirak/require 'setup-expand-region)

Formatting

I am using reformatter.
(akirak/require 'setup-reformatter)

Search and replace

I prefer swiper= and counsel-rg. I added additional keybindings to the keymaps of those commands, so I can now dispatch an occur/noccur session from those commands.

(akirak/require 'setup-occur)

Another useful command is projectile-replace (and its regexp variant projectile-replace-regexp).

Resources:

Commenting

(use-package comment-dwim-2
  :general
  ("M-;" 'comment-dwim-2))

Case conversion

(use-package fix-word
  :commands (fix-word-upcase fix-word-downcase fix-word-capitalize)
  :hook
  (prog-mode . (lambda () (setq fix-word-thing 'symbol)))
  :general
  ([remap upcase-word] 'fix-word-upcase
   [remap downcase-word] 'fix-word-downcase
   [remap capitalize-word] 'fix-word-capitalize))
(akirak/require 'setup-string-inflection)

Highlighting todos via hl-todo

Use hl-todo by tarsius

(use-package hl-todo
  :config
  (akirak/bind-search :keymaps 'hl-todo-mode-map
    "t" #'hl-todo-occur)
  (akirak/bind-jump :keymaps 'hl-todo-mode-map
    "t" #'hl-todo-next
    "r" #'hl-todo-previous)
  (general-add-hook 'hl-todo-keyword-faces
                    '(("REVIEW" . "DarkOrange3")
                      ("OPTIMIZE" . "LightSeaGreen")))
  :hook
  (prog-mode . hl-todo-mode))

There is another package named comment-tags for the same purpose, but I won’t use it since there is hl-todo

(use-package comment-tags
  :disabled t
  :hook (prog-mode . comment-tags-mode)
  :custom
  (comment-tags-case-sensitive t)
  (comment-tags-comment-start-only t))

Editing specific types of formats

Deprecated. Use web-mode.
;; (akirak/require 'setup-tagedit)

Miscellaneous commands

Switching to an Org window

(defvar org-select-window-last-window nil)

(defun org-select-window (arg)
  (interactive "P")
  (if arg
      (progn
        (when org-select-window-last-window
          (select-window org-select-window-last-window)
          (setq org-select-window-last-window nil)))
    (let* ((wlist (window-list))
           (i0 (-elem-index (selected-window) wlist))
           (queue (append (-slice wlist (1+ i0))
                          (-take i0 wlist)))
           (w (-find (lambda (w)
                       (with-current-buffer (window-buffer w)
                         (derived-mode-p 'org-mode)))
                     queue)))
      (if w
          (progn
            (unless (derived-mode-p 'org-mode)
              (setq org-select-window-last-window (selected-window)))
            (select-window w))
        (message "No other org window in this frame")))))

modi/org-split-block

(use-package modi-org-split-block
  :straight nil
  :load-path "contrib/modi")
(general-def :package 'org :keymaps 'org-mode-map
  [remap org-meta-return] 'modi/org-meta-return)

Window management

(akirak/bind-user
  "u" #'winner-undo-repeat)
(defun akirak/switch-to-last-buffer-other-window ()
  (interactive)
  (switch-to-buffer-other-window (other-buffer)))

(general-def ctl-x-map
  "B" #'akirak/switch-to-last-buffer-other-window)

I created a hydra for managing frames and windows.

(general-def "M-o" #'ace-window)
;; You can also display the help from the start
;; (akirak/bind-key "M-o" #'aw-show-dispatch-help)
(general-unbind :keymaps 'lispy-mode-map :package 'lispy "M-o")

Other packages for window management

(use-package fwb-cmds
  :straight (fwb-cmds :host github :repo "tarsius/fwb-cmds"))
(use-package buffer-move
  :commands (buf-move-up buf-move-down buf-move-left buf-move-right))
(use-package window-go
  :straight (window-go :host github :repo "akirak/emacs-window-go"))

Visual cues and extra information display

Additional visual cues can increase productivity, but they can be noisy at the same time. Therefore I need to justify each package added to my config.

Beacon

I often lose sight of the cursor when I switch to another window, so this is necessary.

(use-package beacon           ; Highlight the cursor on certain events
  :disabled t
  :unless (akirak/windows-subsystem-for-linux-p)
  :config
  (general-add-hook 'beacon-dont-blink-commands
                    '(akirak/scroll-half-page-forward
                      akirak/scroll-half-page-backward))
  (beacon-mode 1))

Rainbow-delimiters

This is especially useful in editing Lisp code.

(use-package rainbow-delimiters         ; Colourize parentheses in source code
  :hook
  ((lisp-mode
    emacs-lisp-mode
    elixir-mode
    haskell-mode
    purescript-mode
    ) . rainbow-delimiters-mode))

Dimmer

This package makes the focused window stands out by dimming the other windows. However, the dimness should be kept small to make referenced text readable.

(akirak/require 'setup-dimmer)

Git-gutter

This lets you know which parts of the buffers are modified since the last commit.

(use-package git-gutter
  :diminish git-gutter-mode
  :init
  (global-git-gutter-mode))

(akirak/bind-jump
  "j" #'git-gutter:next-hunk
  "k" #'git-gutter:previous-hunk)

(general-advice-add '(git-gutter:next-hunk
                      git-gutter:previous-hunk)
                    :around
                    (defun akirak/git-gutter-follow-up-navigation (orig &rest args)
                      (when (buffer-narrowed-p)
                        (widen))
                      (let ((pos (point)))
                        (prog1 (apply orig args)
                          (unless (eq pos (point))
                            (when (derived-mode-p 'org-mode)
                              (org-show-context)))))))

(akirak/bind-user
  "g" 'git-gutter:mark-hunk)

Highlight-indent-guides

This is helpful in programming languages that depend on indentation levels.

(use-package highlight-indent-guides
  :config
  (defun akirak/turn-on-highlight-indent-guides-mode ()
    (interactive)
    (highlight-indent-guides-mode 1))
  :hook
  ((python-mode nim-mode yaml-mode)
   . akirak/turn-on-highlight-indent-guides-mode))

Prism

(akirak/require 'setup-prism)

Column-enforce-mode

(use-package column-enforce-mode
  :disabled t
  :hook
  ((prog-mode markdown-mode)
   . 80-column-rule))

Fill-column-indicator

Visualise (usually) 80 columns.

(use-package fill-column-indicator
  :unless (akirak/windows-subsystem-for-linux-p)
  :disabled t
  :init
  (add-hook 'prog-mode-hook 'fci-mode))

Whitespace

Visualise unnecessary, extra whitespace characters in source code.

(akirak/require 'setup-whitespace)

Manual highlighting

Symbol overlays
(use-package symbol-overlay
  :commands (symbol-overlay-put symbol-overlay-mode)
  :config

  (akirak/bind-search
    "s"
    (defun akirak/symbol-overlay-jump ()
      (interactive)
      (let* ((name (completing-read "Highlighted symbol: "
                                    (-map #'car symbol-overlay-keywords-alist)))
             (x (assoc name symbol-overlay-keywords-alist))
             (face (cddr x))
             (initial (point))
             pos)
        (goto-char (point-min))
        (unless (catch 'finish
                  (while (setq pos (next-single-char-property-change (point) 'face))
                    (goto-char pos)
                    (when (eq face (get-char-property pos 'face))
                      (throw 'finish t))))
          (goto-char initial))))))

Visual bookmarks
(akirak/require 'setup-bm)

Startup buffer

By default, *Messages* buffer is shown at startup.

(akirak/require 'setup-initial-buffer)

Auto saving

Files are automatically saved on certain events by super-save-mode:

(akirak/require 'setup-super-save)

org-web-tools and clipurl

org-web-tools is handy, but commands in the package often fail to retrieve a proper URL I want to operate on. Therefore I created clipurl package to pick a URL from the kill ring.

 (akirak/require 'setup-org-web-tools)

 (defun akirak/insert-previous-url-link ()
   (interactive)
   (if current-prefix-arg
	(call-interactively 'ivy-clipurl)
     ;; Use ivy-clipurl in place of org-web-tools-insert-link.
     (let ((ivy-clipurl-default-action 'clipurl-insert-url-dwim)
	    (ivy-clipurl-prompt "Choose a URL to insert: "))
	(call-interactively 'ivy-clipurl))
     ;; (call-interactively 'org-web-tools-insert-link-for-url)
     ))

 (akirak/bind-user "w" 'akirak/insert-previous-url-link)

To visit a URL, use browse-url-at-point:

(akirak/bind-user "o" #'browse-url-at-point)

Highlighting part(s) of source code and focusing

  • bm (visual bookmarks)
  • symbol-overlay
(akirak/bind-user
  "b" 'helm-bm
  "m" 'bm-toggle
  "s" 'symbol-overlay-put)
(general-def
  "C-x n" #'akirak/narrow-or-widen-dwim)

(general-def :keymaps 'org-mode-map
  "C-x n" #'akirak/narrow-or-widen-dwim)

Development workflow

(general-def
  "<f9>" 'recompile)

Scratch buffers

;; Development
(akirak/bind-user
  "i" 'scratch)

Debugging Emacs

(akirak/require 'setup-debug-emacs)

External tools

Storage management

(akirak/require 'setup-storage)

Background services

(akirak/require 'setup-services)

Personal finance (beancount)

(akirak/require 'setup-beancount)

Optimization

(akirak/require 'optimize-minibuf)

Startup

Use benchmark-init for profiling of the startup time.

(akirak/require 'setup-init-time-log)

Writing

Multi-lingual support

A modules for supporting a natural language should follow the naming convention of setup-LANGUAGE-SYSTEM. For example, setup-chinese-pyim is a Chinese support through pyim.el.

You can customize a list of modules for supported languages through the following variable. This setting can be done per machine, so different machines can support different languages:

(defcustom akirak/enabled-language-supports
  nil
  "List of enabled modules for supporting natural languages other than English.

These modules are loaded at startup.

I also suggest you set `default-input-method' to your preferred
input method in the environment."
  :group 'akirak
  :type '(set (const :tag "Japanese/日本語 (mozc)" setup-japanese-mozc)
              (const :tag "Chinese/简体中文 (pyim)" setup-chinese-pyim)
              (const :tag "Japanese/日本語 (SKK)" setup-japanese-skk))
  :set (lambda (sym value)
         (set sym value)
         (dolist (module value)
           (akirak/require module))
         (when (= 1 (length value))
           (setq default-input-method
                 (string-remove-prefix "setup-" (symbol-name (car value)))))))

I don’t set the default input method here. Set default-input-method in your custom-file.

(akirak/require 'setup-language-tools)

Utilities

(akirak/require 'setup-writing)

Spell checking with flyspell

I will use flyspell-correct to run flyspell.

  • flyspell-correct-wrapper is the main entry point to the package. I bind C-c f to the command.
    • When flyspell-mode is not on, the key sequence turns the mode on.
(akirak/bind-user
  "f" #'flyspell-mode)

(akirak/bind-user :keymaps 'flyspell-mode-map
  "f" #'flyspell-correct-wrapper)

Quotation marks

Typo

Typo.el is a successor to typopunct.el.

Note it doesn’t support CJK languages. It can be useful for European languages.

Counting words

Use wc-mode or org-wc for counting words.

WriteGood mode

Using Org mode

Set basic options for org-mode:

(akirak/require 'setup-org t)
;; Use org-edna for dependency management
(akirak/require 'setup-org-edna)

;; org-starter should be loaded after org is loaded
(akirak/require 'setup-org-starter)

Org hydra

Use major-mode-hydra to define a hydra for Org mode:

(akirak/require 'setup-org-hydra)

Org-babel

(akirak/require 'setup-org-babel t)

Exporting

  • Exporting to Hugo
(akirak/require 'setup-ox)
(akirak/require 'setup-org-hugo)

Markdown

Markdown is supported as well:

(akirak/require 'setup-markdown)

Programming languages

Ideally, this section should be a portfolio of my skills.

Elixir

(akirak/require 'setup-elixir)

Gleam

(akirak/require 'setup-gleam)

Go

(akirak/require 'setup-go)

Haskell

(akirak/require 'setup-haskell)

Java

Use lsp-mode.

JavaScript

(akirak/require 'setup-javascript)
(akirak/require 'setup-json)

Lisp (Emacs Lisp and Common Lisp)

(akirak/require 'setup-emacs-lisp)

PureScript

(akirak/require 'setup-purescript)

Python

Rust

(use-package rust-mode)

Shell scripts (bash)

(akirak/require 'setup-shell-scripts)

Vue

(akirak/require 'setup-vue)

Web-mode

(akirak/require 'setup-web-mode)

Restclient is useful for development in teams where it is used.

(akirak/require 'setup-restclient)

CSS

(akirak/require 'setup-css)

DSLs

Bats

(use-package bats-mode)

Dhall

(akirak/require 'setup-dhall)

Dockerfile

(akirak/require 'setup-dockerfile)

GraphQL

(akirak/require 'setup-graphql)

GraphViz

(akirak/require 'setup-graphviz-dot)

Mermaid

(akirak/require 'setup-mermaid)

Nix

(akirak/require 'setup-nix)

Pug

(akirak/require 'setup-pug)

Systemd

(akirak/require 'setup-systemd)

Svelte

(akirak/require 'setup-svelte)

Terraform

(akirak/require 'setup-terraform)

YAML

(akirak/require 'setup-yaml)

Ansible

(akirak/require 'setup-ansible)

Org mode

Global bindings related to Org mode

(akirak/bind-jump "M-j" #'counsel-org-clock-goto)
(akirak/bind-search "M-c" #'counsel-org-clock-context)
(akirak/bind-user
  "l" 'org-store-link)

Recurring tasks

(akirak/require 'setup-org-recur)

Org Journal

;; (akirak/require 'setup-org-journal)

Org-agenda keybindings

(general-def org-agenda-mode-map :package 'org-agenda
  "M-n" #'org-agenda-drag-line-forward
  "M-p" #'org-agenda-drag-line-backward)

EXWM

(when (member "--exwm" command-line-args)
  (akirak/require 'setup-exwm)
  (exwm-enable))

(add-to-list 'command-switch-alist '("--exwm" . (lambda (_) nil)))

When you connect/disconnect to an external monitor, run akirak/exwm-configure-screens command, unless it is automatically called by the screen change hook.

Meta

Synchronizing my configuration repositories

I am now using myrepos to synchronize my configuration repositories.

(defun akirak/mr-update ()
  "Run 'mr update' in the home directory."
  (interactive)
  (save-some-buffers)
  (let ((default-directory "~"))
    (akirak/run-interactive-shell-command "mr update")))

(defalias 'akirak/update-configuration 'akirak/mr-update)
(defun akirak/mr-push ()
  (interactive)
  (let ((default-directory "~"))
    (akirak/run-interactive-shell-command "mr push")))

Rebuild packages

(akirak/require 'setup-straight)

Sort entries in this file

(defun akirak/org-sort-entries-as-desired ()
  (interactive)
  (org-with-wide-buffer
   (goto-char (point-min))
   (while (re-search-forward (org-re-property "sort") nil t)
     (let ((line (thing-at-point 'line t)))
       (if (string-match org-property-re line)
           (pcase (match-string 3 line)
             ("a" (org-sort-entries nil ?a)))
         (error "Property didn't match")))
     (org-end-of-subtree)))
  (when (org-find-property "TOC")
    (org-make-toc)))