Configurations for GNU Emacs

Table of Contents

はじめに

;; init.el --- My init.el -*- lexical-binding: t; -*-

Macro Utilities

when-darwin

(defmacro when-darwin (&rest body)
  (when (string= system-type "darwin")
    `(progn ,@body)))

when-darwin-not-window-system

(defmacro when-darwin-not-window-system (&rest body)
  (when (and (string= system-type "darwin")
             window-system)
    `(progn ,@body)))

when-linux

(defmacro when-linux (&rest body)
  (when (string= system-type "gnu/linux")
    `(progn ,@body)))

when-linux-not-window-system

(defmacro when-linux-not-window-system (&rest body)
  (when (and (string= system-type "gnu/linux")
             (not window-system))
    `(progn ,@body)))

Boot

user

(setq user-full-name "takeokunn")
(setq user-mail-address "bararararatty@gmail.com")

shell-file-name

(setq shell-file-name (or (executable-find "bash") "/bin/sh"))

profile

(defconst my/enable-profile nil
  "If true, enable profile")

(when my/enable-profile
  (require 'profiler)
  (profiler-start 'cpu))

Magic File Name を一時的に無効にする

(defconst my/saved-file-name-handler-alist file-name-handler-alist)

(setq file-name-handler-alist nil)

起動時間計測

  (defconst my/before-load-init-time (current-time))

  ;;;###autoload
  (defun my/load-init-time ()
    "Loading time of user init files including time for `after-init-hook'.
In a daemon the functions in `my/deferred-after-init-functions' run later
and are not counted."
    (let ((time1 (float-time
                  (time-subtract after-init-time my/before-load-init-time)))
          (time2 (float-time
                  (time-subtract (current-time) my/before-load-init-time))))
      (message (concat "Loading init files: %.0f [msec], "
                       "of which %.f [msec] for `after-init-hook'.")
               (* 1000 time1) (* 1000 (- time2 time1)))))
  (add-hook 'after-init-hook #'my/load-init-time t)

  (defvar my/tick-previous-time my/before-load-init-time)

  (defun my/emacs-init-time ()
    "Emacs booting time in msec."
    (interactive)
    (message "Emacs booting time: %.0f [msec] = `emacs-init-time'."
             (* 1000
                (float-time (time-subtract
                             after-init-time
                             before-init-time)))))

  (add-hook 'after-init-hook #'my/emacs-init-time)

autoload-if-found

(defun autoload-if-found (functions file &optional docstring interactive type)
  "Set autoload iff FILE has found."
  (when (locate-library file)
    (dolist (f functions)
      (autoload f file docstring interactive type))
    t))

compat

;; load compat-31 explicitly; it appears after compat-30 in load-path otherwise
(when (version< emacs-version "31")
  (require 'compat-31))

Basic

末尾のスペースを可視化する

(defun my/disable-show-trailing-whitespace ()
  (setq show-trailing-whitespace nil))

(with-eval-after-load 'comint
  (add-hook 'comint-mode-hook #'my/disable-show-trailing-whitespace))

(with-eval-after-load 'esh-mode
  (add-hook 'eshell-mode-hook #'my/disable-show-trailing-whitespace))

(with-eval-after-load 'minibuffer
  (add-hook 'minibuffer-inactive-mode-hook #'my/disable-show-trailing-whitespace))

(with-eval-after-load 'prog-mode
  (add-hook 'prog-mode-hook #'my/disable-show-trailing-whitespace))

(with-eval-after-load 'text-mode
  (add-hook 'text-mode-hook #'my/disable-show-trailing-whitespace))

行番号を表示する

(autoload-if-found '(global-display-line-numbers-mode) "display-line-numbers" nil t)


(with-eval-after-load 'display-line-numbers
  (setopt display-line-numbers-grow-only t))

C-kで行削除

(with-eval-after-load 'simple
  (setopt kill-whole-line t))

カッコの中をハイライトする

(autoload-if-found '(show-paren-local-mode) "display-line-numbers" nil t)

(with-eval-after-load 'prog-mode
  (add-hook 'prog-mode-hook #'show-paren-local-mode))

(with-eval-after-load 'paren
  (setopt show-paren-style 'mixed))

カッコが自動的に作られるようにする

(add-hook 'after-init-hook #'electric-pair-mode)

global-auto-revert-mode

(add-hook 'after-init-hook #'global-auto-revert-mode)

yes/no to y/n

(add-hook 'after-init-hook
          #'(lambda ()
              (fset 'yes-or-no-p 'y-or-n-p)))

minibuffer

(with-eval-after-load 'minibuffer
  (define-key minibuffer-mode-map (kbd "C-j") #'exit-minibuffer)
  (define-key minibuffer-mode-map (kbd "M-RET") #'exit-minibuffer))

(setq enable-recursive-minibuffers t)

savehistを有効にする

(add-hook 'after-init-hook #'savehist-mode)

osx-clipboard

(autoload-if-found '(osx-clipboard-mode) "osx-clipboard" nil t)

(when (fboundp 'osx-clipboard-mode)
  (osx-clipboard-mode +1))

clipetty

(autoload-if-found '(global-clipetty-mode) "clipetty" nil t)

(when (fboundp 'global-clipetty-mode)
  (global-clipetty-mode +1))

terminal escape sequence handling

  ;; daemon evaluates (display-graphic-p) once at start, not per-frame, so hook per-frame instead
  (defun my/setup-terminal-escape-sequences (&optional frame)
    "Set up terminal-specific keybindings for FRAME.
Handles focus reporting (DECSET 1004) and bracketed paste (DECSET 2004)."
    (with-selected-frame (or frame (selected-frame))
      (unless (display-graphic-p frame)
        ;; Focus reporting - prevents 'OI' characters
        (define-key input-decode-map "\e[I" [focus-in])
        (define-key input-decode-map "\e[O" [focus-out])
        (define-key special-event-map [focus-in] #'ignore)
        (define-key special-event-map [focus-out] #'ignore)
        ;; Bracketed paste - prevents '^[[200~' and '^[[201~' characters
        (require 'term/xterm)
        (define-key input-decode-map "\e[200~" #'xterm-translate-bracketed-paste))))

  ;; Apply to new frames (handles emacsclient connections to daemon)
  (add-hook 'after-make-frame-functions #'my/setup-terminal-escape-sequences)

  (unless (daemonp)
    (my/setup-terminal-escape-sequences))

native comp

(with-eval-after-load 'comp-run
  (setopt native-comp-async-jobs-number 8)
  (setopt native-comp-speed 3)
  (setopt native-comp-always-compile t))

(with-eval-after-load 'warnings
  (setopt warning-suppress-types '((comp))))

同一bufferの名前を変える

(with-eval-after-load 'uniquify
  (setopt uniquify-buffer-name-style 'post-forward-angle-brackets))

killできないようにする

(add-hook 'after-init-hook
          #'(lambda ()
              (with-current-buffer "*scratch*"
                (emacs-lock-mode 'kill))
              (with-current-buffer "*Messages*"
                (emacs-lock-mode 'kill))))

日時表示

(with-eval-after-load 'time
  (setopt display-time-24hr-format t))

warning level

(with-eval-after-load 'warnings
  (setopt warning-minimum-level :error))

キーコマンド入力中に入力過程をミニバッファに反映する

(setq echo-keystrokes 0.1)

save-place-mode

(add-hook 'after-init-hook #'save-place-mode)

enable-local-variables

(setq enable-local-variables :all)

password

(with-eval-after-load 'password-cache
  (setq password-cache t)
  (setq password-cache-expiry 3600))

time locale

(setq system-time-locale "C")

kill-ringのサイズを変更

(setopt kill-ring-max 100000)

(custom-set-variables '(savehist-additional-variables '(kill-ring)))

折り返ししない

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

use-dialog-box off

(setq use-dialog-box nil)

ediff

(with-eval-after-load 'ediff-wind
  (setopt ediff-window-setup-function #'ediff-setup-windows-plain))

(with-eval-after-load 'winner
  (add-hook 'after-init-hook #'winner-mode))

debug-on-error

(setq debug-on-error nil)

Global Keybind

basic

(keymap-global-set "M-¥" #'(lambda () (interactive) (insert "\\")))
(keymap-global-set "C-a" #'back-to-indentation)
(keymap-global-set "C-z" nil)
(keymap-global-set "C-;" #'comment-dwim)
(keymap-global-set "C-M-/" #'undo-redo)
(keymap-global-set "C-c i" #'find-function)
(keymap-global-set "C-c C-o" #'org-open-at-point)
(keymap-global-set "C-x C-o" #'other-window)

(keymap-global-unset "C-x C-k")

(keymap-global-set "M-d" #'my/delete-forward-block)

(when window-system
  (keymap-global-unset "C-x C-c"))

Language

ansible

(autoload-if-found '(ansible-mode) "ansible" nil t)

apache-mode

(autoload-if-found '(apache-mode) "apache-mode" nil t)

(add-to-list 'auto-mode-alist '("/\\.htaccess\\'" . apache-mode))
(add-to-list 'auto-mode-alist '("/\\(?:access\\|httpd\\|srm\\)\\.conf\\'" . apache-mode))
(add-to-list 'auto-mode-alist '("/apache2/.+\\.conf\\'" . apache-mode))
(add-to-list 'auto-mode-alist '("/httpd/conf/.+\\.conf\\'" . apache-mode))
(add-to-list 'auto-mode-alist '("/apache2/sites-\\(?:available\\|enabled\\)/" . apache-mode))

(with-eval-after-load 'apache-mode
  (add-hook 'apache-mode-hook #'view-mode))

bazel-mode

(autoload-if-found '(bazel-mode) "bazel" nil t)

bison-mode

(autoload-if-found '(bison-mode flex-mode jison-mode) "bison-mode" nil t)

(add-to-list 'auto-mode-alist '("\\.y\\'" . bison-mode))
(add-to-list 'auto-mode-alist '("\\.l\\'" . flex-mode))
(add-to-list 'auto-mode-alist '("\\.jison\\'" . jison-mode))

cask-mode

(autoload-if-found '(cask-mode) "cask-mode" nil t)

(add-to-list 'auto-mode-alist '("/Cask\\'" . cask-mode))

cfn-mode

(autoload-if-found '(cfn-mode) "cfn-mode" nil t)

(add-to-list 'magic-mode-alist '("\\(---\n\\)?AWSTemplateFormatVersion:" . cfn-mode))

(with-eval-after-load 'cfn-mode
  (add-hook 'cfn-mode-hook #'flycheck-mode)
  (add-hook 'cfn-mode-hook #'view-mode))

clojure-mode

(autoload-if-found '(clojure-mode clojurescript-mode) "clojure-mode" nil t)

(add-to-list 'auto-mode-alist '("\\.clj$" . clojure-mode))
(add-to-list 'auto-mode-alist '("\\.cljs$" . clojurescript-mode))

(with-eval-after-load 'clojure-mode
  (setopt clojure-toplevel-inside-comment-form t))

cmake-mode

(autoload-if-found '(cmake-mode) "cmake-mode" nil t)

(add-to-list 'auto-mode-alist '("\\.cmake$" . cmake-mode))

coffee-mode

(autoload-if-found '(coffee-mode) "coffee-mode" nil t)

(add-to-list 'auto-mode-alist '("\\.coffee$" . coffee-mode))

conf-mode

(add-to-list 'auto-mode-alist '("\\.cnf$" . conf-mode))
(add-to-list 'auto-mode-alist '("yabairc$" . conf-mode))
(add-to-list 'auto-mode-alist '("skhdrc$" . conf-mode))

(with-eval-after-load 'conf-mode
  (add-hook 'conf-mode-hook #'view-mode))

crontab-mode

(autoload-if-found '(crontab-mode) "crontab-mode" nil t)

(add-to-list 'auto-mode-alist '("\\.?cron\\(tab\\)?\\'" . crontab-mode))

(with-eval-after-load 'crontab-mode
  (add-hook 'crontab-mode-hook #'view-mode))

csharp-mode

(autoload-if-found '(csharp-mode) "csharp-mode" nil t)

(add-to-list 'auto-mode-alist '("\\.cs$" . csharp-mode))

csv-mode

(autoload-if-found '(csv-mode) "csv-mode" nil t)

(add-to-list 'auto-mode-alist '("\\.csv$" . csv-mode))

(with-eval-after-load 'csv-mode
  (add-hook 'csv-mode-hook #'view-mode))

cuda-mode

(autoload-if-found '(cuda-mode) "cuda-mode" nil t)

(add-to-list 'auto-mode-alist '("\\.cu$" . cuda-mode))

crystal-mode

(autoload-if-found '(crystal-mode) "crystal-mode" nil t)

(add-to-list 'auto-mode-alist '("Projectfile$" . crystal-mode))
(add-to-list 'auto-mode-alist
             (cons (purecopy (concat "\\(?:\\."
                                     "cr"
                                     "\\)\\'")) 'crystal-mode))

dart-mode

(autoload-if-found '(dart-mode) "dart-mode" nil t)

(add-to-list 'auto-mode-alist '("\\.dart$" . dart-mode))

dhall-mode

(autoload-if-found '(dhall-mode) "dhall-mode" nil t)

(add-to-list 'auto-mode-alist '("\\.dhall$" . dhall-mode))

direnv-mode

(when (autoload-if-found '(direnv-envrc-mode direnv-mode direnv-allow) "direnv" nil t)
  (add-hook 'after-init-hook #'direnv-mode)
  (add-to-list 'auto-mode-alist '("\\.envrc$" . direnv-envrc-mode)))

(with-eval-after-load 'direnv
  (setopt direnv-always-show-summary nil)
  (setopt direnv-show-paths-in-summary nil)
  (setopt direnv-use-faces-in-summary nil)

  (add-hook 'direnv-mode-hook #'view-mode))

docker-compose-mode

(autoload-if-found '(docker-compose-mode) "docker-compose-mode" nil t)

(add-to-list 'auto-mode-alist '("\\docker-compose*" . docker-compose-mode))

(with-eval-after-load 'docker-compose-mode
  (add-hook 'docker-compose-mode-hook #'view-mode))

dockerfile-mode

(autoload-if-found '(dockerfile-mode) "dockerfile-mode" nil t)

(add-to-list 'auto-mode-alist '("\\Dockerfile$" . dockerfile-mode))
(add-to-list 'auto-mode-alist '("\\Dockerfile.dev$" . dockerfile-mode))
(add-to-list 'auto-mode-alist '("\\Dockerfile_Ecs$" . dockerfile-mode))
(add-to-list 'auto-mode-alist '("\\Dockerfile_EcsDeploy" . dockerfile-mode))

(with-eval-after-load 'dockerfile-mode
  (add-hook 'dockerfile-mode-hook #'flycheck-mode))

dotenv-mode

(autoload-if-found '(dotenv-mode) "dotenv-mode" nil t)

(add-to-list 'auto-mode-alist '(".env$" . dotenv-mode))

(with-eval-after-load 'dotenv-mode
  (add-hook 'dotenv-mode-hook #'view-mode))

elixir-mode

(autoload-if-found '(elixir-mode) "elixir-mode" nil t)

(add-to-list 'auto-mode-alist '("\\.elixir$" . elixir-mode))
(add-to-list 'auto-mode-alist '("\\.ex$" . elixir-mode))
(add-to-list 'auto-mode-alist '("\\.exs$" . elixir-mode))
(add-to-list 'auto-mode-alist '("mix\\.lock" . elixir-mode))

elm-mode

(autoload-if-found '(elm-mode) "elm-mode" nil t)

(add-to-list 'auto-mode-alist '("\\.elm$" . elm-mode))

emacs-lisp-mode

(add-to-list 'auto-mode-alist '("Keg" . emacs-lisp-mode))

fish-mode

(autoload-if-found '(fish-mode) "fish-mode" nil t)

(add-to-list 'auto-mode-alist '("\\.fish$" . fish-mode))

(with-eval-after-load 'fish-mode
  (setopt fish-enable-auto-indent t))

forth-mode

(autoload-if-found '(forth-mode) "forth-mode" nil t)

(add-to-list 'auto-mode-alist '("\\.f$" . forth-mode))
(add-to-list 'auto-mode-alist '("\\.fs$" . forth-mode))
(add-to-list 'auto-mode-alist '("\\.fth$" . forth-mode))
(add-to-list 'auto-mode-alist '("\\.forth$" . forth-mode))
(add-to-list 'auto-mode-alist '("\\.4th$" . forth-mode))

fortran

(autoload-if-found '(f90-mode) "f90" nil t)

(add-to-list 'auto-mode-alist '("\\.f\\(y90\\|y?pp\\)\\'" . f90-mode))

fsharp-mode

(autoload-if-found '(fsharp-mode) "fsharp-mode" nil t)

(add-to-list 'auto-mode-alist '("\\.fs[iylx]?$" . fsharp-mode))

git-modes

(autoload-if-found '(gitignore-mode gitconfig-mode gitattributes-mode) "git-modes" nil t)

(add-to-list 'auto-mode-alist '("\\.dockerignore$" . gitignore-mode))
(add-to-list 'auto-mode-alist '("\\.gitignore$" . gitignore-mode))
(add-to-list 'auto-mode-alist '("\\.prettierignore$" . gitignore-mode))
(add-to-list 'auto-mode-alist '("/git/ignore\\'" . gitignore-mode))
(add-to-list 'auto-mode-alist '("/git/ignore\\'" . gitignore-mode))
(add-to-list 'auto-mode-alist '("CODEOWNERS" . gitignore-mode))

(with-eval-after-load 'gitignore-mode
  (add-hook 'gitignore-mode-hook #'view-mode))

(add-to-list 'auto-mode-alist '("\\.git-pr-release$" . gitconfig-mode))
(add-to-list 'auto-mode-alist '("\\.editorconfig$" . gitconfig-mode))
(add-to-list 'auto-mode-alist '("\\.gitconfig$" . gitconfig-mode))
(add-to-list 'auto-mode-alist '("/\\.git/config\\'" . gitconfig-mode))
(add-to-list 'auto-mode-alist '("/modules/.*/config\\'" . gitconfig-mode))
(add-to-list 'auto-mode-alist '("/git/config\\'" . gitconfig-mode))
(add-to-list 'auto-mode-alist '("/\\.gitmodules\\'" . gitconfig-mode))
(add-to-list 'auto-mode-alist '("/etc/gitconfig\\'" . gitconfig-mode))

(with-eval-after-load 'gitconfig-mode
  (add-hook 'gitconfig-mode-hook #'view-mode))

(add-to-list 'auto-mode-alist '("/\\.gitattributes\\'" . gitattributes-mode))
(add-to-list 'auto-mode-alist '("\.gitattributes$" . gitattributes-mode))
(add-to-list 'auto-mode-alist '("/info/attributes\\'" . gitattributes-mode))
(add-to-list 'auto-mode-alist '("/git/attributes\\'" . gitattributes-mode))

(with-eval-after-load 'gitattributes-mode
  (add-hook 'gitattributes-mode-hook #'view-mode))

gleam-ts-mode

(autoload-if-found '(gleam-ts-mode) "gleam-ts-mode" nil t)

(add-to-list 'auto-mode-alist '("\\.gleam\\'" . gleam-ts-mode))

glsl-mode

(autoload-if-found '(glsl-mode) "glsl-mode" nil t)

(add-to-list 'auto-mode-alist '("\\.vsh$" . glsl-mode))
(add-to-list 'auto-mode-alist '("\\.fsh$" . glsl-mode))

go-mode

(autoload-if-found '(go-mode gofmt) "go-mode" nil t)

(add-to-list 'auto-mode-alist '("\\.go$" . go-mode))
(add-to-list 'auto-mode-alist '("^go.mod$" . go-mode))

(with-eval-after-load 'go-mode
  (setopt gofmt-command "goimports"))

gradle-mode

(autoload-if-found '(gradle-mode) "gradle-mode" nil t)

(add-to-list 'auto-mode-alist '("\\.gradle$" . gradle-mode))

graphql-mode

(autoload-if-found '(graphql-mode) "graphql-mode" nil t)

(add-to-list 'auto-mode-alist '("\\.graphql\\'" . graphql-mode))

(with-eval-after-load 'graphql-mode
  (setopt graphql-indent-level 4))

TODO graphviz-dot-mode


groovy-mode

(autoload-if-found '(groovy-mode) "groovy-mode" nil t)

(add-to-list 'auto-mode-alist '("\\.g\\(?:ant\\|roovy\\|radle\\)\\'" . groovy-mode))
(add-to-list 'auto-mode-alist '("/Jenkinsfile\\'" . groovy-mode))
(add-to-list 'interpreter-mode-alist '("groovy" . groovy-mode))

hack-mode

(autoload-if-found '(hack-mode) "hack-mode" nil t)

(add-to-list 'auto-mode-alist '("\\.hack$" . hack-mode))
(add-to-list 'auto-mode-alist '("\\.hck$" . hack-mode))
(add-to-list 'auto-mode-alist '("\\.hhi$" . hack-mode))

haskell-mode

(autoload-if-found '(haskell-mode) "haskell-mode" nil t)

(add-to-list 'auto-mode-alist '("\\.hs$" . haskell-mode))
(add-to-list 'auto-mode-alist '("\\.cable$" . haskell-mode))

hcl-mode

(autoload-if-found '(hcl-mode) "hcl-mode" nil t)

(add-to-list 'auto-mode-alist '("\\.hcl$" . hcl-mode))

hy-mode

(autoload-if-found '(hy-mode) "hy-mode" nil t)

(add-to-list 'auto-mode-alist '("\\.hy$" . hy-mode))

ini-mode

(autoload-if-found '(ini-mode) "ini-mode" nil t)

(add-to-list 'auto-mode-alist '("\\.ini$" . ini-mode))

jade-mode

(autoload-if-found '(jade-mode) "jade-mode" nil t)
(autoload-if-found '(stylus-mode) "stylus-mode" nil t)

(add-to-list 'auto-mode-alist '("\\.jade$" . jade-mode))
(add-to-list 'auto-mode-alist '("\\.styl\\'" . stylus-mode))

java-mode

(autoload-if-found '(java-mode) "java-mode" nil t)

(add-to-list 'auto-mode-alist '("\\.java$" . java-mode))

js2-mode

(autoload-if-found '(js2-mode) "js2-mode" nil t)

(add-to-list 'auto-mode-alist '("\\.js$" . js2-mode))
(add-to-list 'auto-mode-alist '("\\.cjs$" . js2-mode))
(add-to-list 'auto-mode-alist '("\\.mjs$" . js2-mode))

(with-eval-after-load 'js2-mode
  (setopt js2-strict-missing-semi-warning nil)
  (setopt js2-missing-semi-one-line-override nil))

json-mode

(autoload-if-found '(json-mode) "json-mode" nil t)

(add-to-list 'auto-mode-alist '("\\.json$" . json-mode))
(add-to-list 'auto-mode-alist '("\\.textlintrc$" . json-mode))
(add-to-list 'auto-mode-alist '("\\.prettierrc$" . json-mode))
(add-to-list 'auto-mode-alist '("\\.markuplintrc$" . json-mode))

(with-eval-after-load 'json-mode
  (add-hook 'json-mode-hook #'flycheck-mode))

jsonnet-mode

(autoload-if-found '(jsonnet-mode
                     jsonnet-eval-buffer
                     jsonnet-jump
                     jsonnet-reformat-buffer) "jsonnet-mode" nil t)

(add-to-list 'auto-mode-alist (cons "\\.jsonnet\\'" 'jsonnet-mode))
(add-to-list 'auto-mode-alist (cons "\\.libsonnet\\'" 'jsonnet-mode))

(with-eval-after-load 'jsonnet-mode
  (setopt jsonnet-indent-level 4)

  (define-key jsonnet-mode-map (kbd "C-c C-c") #'jsonnet-eval-buffer)
  (define-key jsonnet-mode-map (kbd "C-c C-f") #'jsonnet-jump)
  (define-key jsonnet-mode-map (kbd "C-c C-r") #'jsonnet-reformat-buffer))

just-mode

(autoload-if-found '(just-mode) "just-mode" nil t)

(add-to-list 'auto-mode-alist '("/[Jj]ustfile\\'" . just-mode))
(add-to-list 'auto-mode-alist '("\\.[Jj]ust\\(file\\)?\\'" . just-mode))

kotlin-mode

(autoload-if-found '(kotlin-mode) "kotlin-mode" nil t)

(add-to-list 'auto-mode-alist '("\\.kts?\\'" . kotlin-mode))

lisp-mode

(autoload-if-found '(lisp-mode) "lisp-mode" nil t)

(add-to-list 'auto-mode-alist '("\\.lemrc$" . lisp-mode))
(add-to-list 'auto-mode-alist '("\\.sbclrc$" . lisp-mode))

lua-mode

(autoload-if-found '(lua-mode) "lua-mode" nil t)

(add-to-list 'auto-mode-alist '("\\.lua$" . lua-mode))

markdown-mode

(autoload-if-found '(markdown-mode) "markdown-mode" nil t)

(add-to-list 'auto-mode-alist '("\\.md$" . markdown-mode))
(add-to-list 'auto-mode-alist '("\\.markdown$" . markdown-mode))

(with-eval-after-load 'markdown-mode
  (setopt markdown-code-lang-modes (append '(("diff" . diff-mode)
                                             ("hs" . haskell-mode)
                                             ("html" . web-mode)
                                             ("ini" . conf-mode)
                                             ("js" . web-mode)
                                             ("jsx" . web-mode)
                                             ("md" . markdown-mode)
                                             ("pl6" . raku-mode)
                                             ("py" . python-mode)
                                             ("rb" . ruby-mode)
                                             ("rs" . rustic-mode)
                                             ("sqlite3" . sql-mode)
                                             ("ts" . typescript-mode)
                                             ("typescript" . typescript-mode)
                                             ("tsx" . web-mode)
                                             ("yaml". yaml-mode)
                                             ("zsh" . sh-mode)
                                             ("php" . php-mode))
                                           markdown-code-lang-modes))

  (add-hook 'markdown-mode #'orgtbl-mode)
  (add-hook 'markdown-mode #'view-mode))

mermaid-mode

(autoload-if-found '(mermaid-mode) "mermaid-mode" nil t)

(add-to-list 'auto-mode-alist '("\\.mmd\\'" . mermaid-mode))

makefile-mode

(autoload-if-found '(makefile-mode) "makefile-mode" nil t)

(add-to-list 'auto-mode-alist '("\\.mk$" . makefile-mode))
(add-to-list 'auto-mode-alist '("Makefile" . makefile-mode))

(with-eval-after-load 'makefile-mode
  (setopt makefile-electric-keys t)

  (add-hook 'makefile-mode-hook #'flycheck-mode))

nasm-mode

(autoload-if-found '(nasm-mode) "nasm-mode" nil t)

(add-to-list 'auto-mode-alist '("\\.s$" . nasm-mode))

neon-mode

(autoload-if-found '(neon-mode) "neon-mode" nil t)

(add-to-list 'auto-mode-alist '("\\.neon$" . neon-mode))

(with-eval-after-load 'neon-mode
  (add-hook 'neon-mode-hook #'view-mode))

nim-mode

(autoload-if-found '(nim-mode) "nim-mode" nil t)

(add-to-list 'auto-mode-alist '("\\.nim\\'" . nim-mode))

ninja-mode

(autoload-if-found '(ninja-mode) "ninja-mode" nil t)

(add-to-list 'auto-mode-alist '("\\.ninja$" . ninja-mode))

nix-mode

(autoload-if-found '(nix-mode) "nix-mode" nil t)
(autoload-if-found '(nix-drv-mode) "nix-drv-mode" nil t)
(autoload-if-found '(nix-shell-unpack nix-shell-configure nix-shell-build) "nix-shell" nil t)
(autoload-if-found '(nix-repl) "nix-repl" nil t)
(autoload-if-found '(nix-format-buffer) "nix-format" nil t)

(add-to-list 'auto-mode-alist '("\\.nix$" . nix-mode))
(add-to-list 'auto-mode-alist '("\\.drv$" . nix-drv-mode))

(defun my/nix-fmt ()
  (interactive)
  (let ((default-directory (locate-dominating-file default-directory ".git")))
    (shell-command-to-string "nix fmt")))

nginx-mode

(autoload-if-found '(nginx-mode) "nginx-mode" nil t)

(add-to-list 'auto-mode-alist '("nginx\\.conf\\'" . nginx-mode))
(add-to-list 'auto-mode-alist '("/nginx/.+\\.conf\\'" . nginx-mode))
(add-to-list 'auto-mode-alist '("/nginx/sites-\\(?:available\\|enabled\\)/" . nginx-mode))

(with-eval-after-load 'nginx-mode
  (setopt nginx-indent-tabs-mode t))

nov-mode

(autoload-if-found '(nov-mode) "nov" nil t)

(add-to-list 'auto-mode-alist '("\\.epub\\'" . nov-mode))

(with-eval-after-load 'nov-mode
  (add-hook 'nov-mode-hook #'view-mode))

pcap-mode

(autoload-if-found '(pcap-mode) "pcap" nil t)

(add-to-list 'auto-mode-alist '("\\.pcap$" . pcap-mode))

phel-mode

(define-derived-mode phel-mode clojure-mode "Phel"
  "Major mode for editing Phel language source files."
  (setq-local comment-start "#")
  ;; disable lockfiles: they touch buffer-file-name in a way that confuses the running Phel process during ILT evaluation
  (setq-local create-lockfiles nil)
  )

(add-to-list 'auto-mode-alist '("\\.phel$" . phel-mode))

php-mode

(autoload-if-found '(php-mode php-current-class php-current-namespace) "php-mode" nil t)
(autoload-if-found '(php-format-this-buffer-file) "php-format" nil t)

(add-to-list 'auto-mode-alist '("\\.php$" . php-mode))

(with-eval-after-load 'php-mode
  (define-key php-mode-map (kbd "C-c C--") #'php-current-class)
  (define-key php-mode-map (kbd "C-c C-=") #'php-current-namespace)
  (define-key php-mode-map (kbd "C-.") nil)

  (setopt php-mode-coding-style 'psr2)

  (define-derived-mode phpstan-mode php-mode "phpstan"))

phpt-mode

(autoload-if-found '(phpt-mode) "phpt-mode" nil t)

(add-to-list 'auto-mode-alist '("\\.phpt$" . phpt-mode))

plantuml-mode

(autoload-if-found '(plantuml-mode) "plantuml-mode" nil t)

(add-to-list 'auto-mode-alist '("\\.pu$" . plantuml-mode))

po-mode

(autoload-if-found '(po-mode) "po-mode" nil t)

(add-to-list 'auto-mode-alist '("\\.po$" . po-mode))

prolog

(autoload-if-found '(prolog-mode) "prolog-mode" nil t)

(add-to-list 'auto-mode-alist '("\\.pl$" . prolog-mode))

protobuf-mode

(autoload-if-found '(protobuf-mode) "protobuf-mode" nil t)

(add-to-list 'auto-mode-alist '("\\.proto\\'" . protobuf-mode))

pug-mode

(autoload-if-found '(pug-mode) "pug-mode" nil t)

(add-to-list 'auto-mode-alist '("\\.pug$" . pug-mode))

prisma-mode

(autoload-if-found '(prisma-mode) "prisma-mode" nil t)

(add-to-list 'auto-mode-alist '("\\.prisma" . prisma-mode))

processing-mode

(autoload-if-found '(processing-mode) "processing-mode" nil t)

(add-to-list 'auto-mode-alist '("\\.pde$" . processing-mode))

(with-eval-after-load 'processing-mode
  (setopt processing-output-dir "/tmp"))

python-mode

(autoload-if-found '(python-mode) "python-mode" nil t)

(add-to-list 'auto-mode-alist '("\\.py$" . python-mode))

(with-eval-after-load 'python
  (setopt python-shell-completion-native-enable nil))

qt-pro-mode

(autoload-if-found '(qt-pro-mode) "qt-pro-mode" nil t)

(add-to-list 'auto-mode-alist '("\\.pr[io]$" . qt-pro-mode))

racket-mode

(autoload-if-found '(racket-mode) "racket-mode" nil t)

robots-txt-mode

(autoload-if-found '(robots-txt-mode) "robots-txt-mode" nil t)

(add-to-list 'auto-mode-alist '("/robots\\.txt\\'" . robots-txt-mode))

ruby-mode

(autoload-if-found '(ruby-mode) "ruby-mode" nil t)

(add-to-list 'auto-mode-alist '("\\.rb$" . ruby-mode))
(add-to-list 'auto-mode-alist '("\\.irbrc$" . ruby-mode))
(add-to-list 'auto-mode-alist '("Capfile" . ruby-mode))
(add-to-list 'auto-mode-alist '("Gemfile" . ruby-mode))
(add-to-list 'auto-mode-alist '("Schemafile" . ruby-mode))
(add-to-list 'auto-mode-alist '(".pryrc" . ruby-mode))
(add-to-list 'auto-mode-alist '("Fastfile" . ruby-mode))
(add-to-list 'auto-mode-alist '("Matchfile" . ruby-mode))
(add-to-list 'auto-mode-alist '("Procfile" . ruby-mode))
(add-to-list 'auto-mode-alist '(".git-pr-template" . ruby-mode))
(add-to-list 'auto-mode-alist '(".gemrc" . ruby-mode))
(add-to-list 'auto-mode-alist '("\\.Brewfile" . ruby-mode))

(with-eval-after-load 'ruby-mode
  (setopt ruby-insert-encoding-magic-comment nil))

rust-mode

(autoload-if-found '(rust-mode) "rust-mode" nil t)

(add-to-list 'auto-mode-alist '("\\.rs$" . rust-mode))

(with-eval-after-load 'rust-rustfmt
  (setopt rust-format-on-save t))

scala-mode

(autoload-if-found '(scala-mode) "scala-mode" nil t)

(add-to-list 'auto-mode-alist '("\\.scala$" . scala-mode))

scheme-mode

(add-to-list 'auto-mode-alist '("\\.scheme$" . scheme-mode))
(add-to-list 'auto-mode-alist '(".guix-channel" . scheme-mode))

(with-eval-after-load 'scheme
  (setopt scheme-program-name "gosh -i"))

scad-mode

(autoload-if-found '(scad-mode) "scad-mode" nil t)

(add-to-list 'auto-mode-alist '("\\.scad\\'" . scad-mode))

scss-mode

(autoload-if-found '(scss-mode) "scss-mode" nil t)

(add-to-list 'auto-mode-alist '("\\.scss$" . scss-mode))
(add-to-list 'auto-mode-alist '("\\.sass$" . scss-mode))

(with-eval-after-load 'scss-mode
  (add-hook 'scss-mode-hook #'flycheck-mode))

shell-mode

(autoload-if-found '(shell-mode) "shell-mode" nil t)

(define-derived-mode console-mode shell-mode "console")

slim-mode

(autoload-if-found '(slim-mode) "slim-mode" nil t)

(add-to-list 'auto-mode-alist '("\\.slim$" . slim-mode))

solidity-mode

(autoload-if-found '(solidity-mode) "solidity-mode" nil t)

(add-to-list 'auto-mode-alist '("\\.sol$" . solidity-mode))

ssh-config-mode

(autoload-if-found '(ssh-config-mode ssh-known-hosts-mode ssh-authorized-keys-mode) "ssh-config-mode" nil t)

(add-to-list 'auto-mode-alist '("/\\.ssh/config\\(\\.d/.*\\.conf\\)?\\'" . ssh-config-mode))
(add-to-list 'auto-mode-alist '("/sshd?_config\\(\\.d/.*\\.conf\\)?\\'" . ssh-config-mode))
(add-to-list 'auto-mode-alist '("/known_hosts\\'" . ssh-config-mode))
(add-to-list 'auto-mode-alist '("/authorized_keys2?\\'" . ssh-config-mode))

(with-eval-after-load 'ssh-config-mode
  (add-hook 'ssh-config-mode-hook #'view-mode)
  (add-hook 'ssh-known-hosts-mode-hook #'view-mode))

sql-mode

(with-eval-after-load 'sql
  (load-library "sql-indent")

  (setq sql-user "root")
  (setq sql-password "P@ssw0rd")
  (setq sql-server "127.0.0.1")
  (setq sql-port 13306)
  (setq sql-mysql-login-params '(server port user password database))

  (add-hook 'sql-mode-hook #'flycheck-mode))

swift-mode

(autoload-if-found '(swift-mode) "swift-mode" nil t)

(add-to-list 'auto-mode-alist '("\\.swift$" . swift-mode))

syslog-mode

(autoload-if-found '(syslog-mode) "syslog-mode" nil t)

(add-to-list 'auto-mode-alist '("\\.log$" . syslog-mode))

systemd-mode

(autoload-if-found '(systemd-mode) "systemd" nil t)

(add-to-list 'auto-mode-alist '("\\.nspawn\\'" . systemd-mode))
(add-to-list 'auto-mode-alist `(,(rx (+? (any "a-zA-Z0-9-_.@\\")) "."
                                     (or "automount" "busname" "mount" "service" "slice"
                                         "socket" "swap" "target" "timer" "link" "netdev" "network")
                                     string-end)
                                . systemd-mode))
(add-to-list 'auto-mode-alist `(,(rx ".#"
                                     (or (and (+? (any "a-zA-Z0-9-_.@\\")) "."
                                              (or "automount" "busname" "mount" "service" "slice"
                                                  "socket" "swap" "target" "timer" "link" "netdev" "network"))
                                         "override.conf")
                                     (= 16 (char hex-digit)) string-end)
                                . systemd-mode))
(add-to-list 'auto-mode-alist `(,(rx "/systemd/" (+? anything) ".d/" (+? (not (any ?/))) ".conf" string-end)
                                . systemd-mode))

(with-eval-after-load 'systemd
  (add-hook 'systemd-mode-hook #'view-mode))

terraform-mode

(autoload-if-found '(terraform-mode) "terraform-mode" nil t)

(add-to-list 'auto-mode-alist '("\\.tf$" . terraform-mode))

(with-eval-after-load 'terraform-mode
  (add-hook 'terraform-mode-hook #'flycheck-mode))

text-mode

(autoload-if-found '(conf-space-mode) "conf-mode" nil t)

(add-to-list 'auto-mode-alist '("\\.tigrc$" . conf-space-mode))
(add-to-list 'auto-mode-alist '("\\.editrc$" . conf-space-mode))
(add-to-list 'auto-mode-alist '("\\.inputrc$" . conf-space-mode))
(add-to-list 'auto-mode-alist '("\\.colorrc$" . conf-space-mode))
(add-to-list 'auto-mode-alist '("\\.asdfrc$" . conf-space-mode))
(add-to-list 'auto-mode-alist '("credentials$" . conf-space-mode))

(with-eval-after-load 'conf-mode
  (add-hook 'conf-space-mode-hook #'view-mode))

toml-mode

(autoload-if-found '(toml-mode) "toml-mode" nil t)

(add-to-list 'auto-mode-alist '("\\.toml$" . toml-mode))

(with-eval-after-load 'toml-mode
  (add-hook 'toml-mode-hook #'flycheck-mode)
  (add-hook 'toml-mode-hook #'view-mode))

tmux-mode

(autoload-if-found '(tmux-mode) "tmux-mode" nil t)

(add-to-list 'auto-mode-alist '("\\.tmux\\.conf$" . tmux-mode))

typescript-mode

(autoload-if-found '(typescript-mode) "typescript-mode" nil t)

(add-to-list 'auto-mode-alist '("\\.ts$" . typescript-mode))
(add-to-list 'auto-mode-alist '("\\.mts$" . typescript-mode))

(define-derived-mode typescript-tsx-mode typescript-mode "tsx")
(add-to-list 'auto-mode-alist '("\\.jsx$" . typescript-tsx-mode))
(add-to-list 'auto-mode-alist '("\\.tsx$" . typescript-tsx-mode))

(define-derived-mode deno-mode typescript-mode "deno")

(with-eval-after-load 'typescript-mode
  (add-hook 'typescript-mode-hook #'emmet-mode)
  (add-hook 'typescript-tsx-mode-hook #'emmet-mode))

typst-mode

(autoload-if-found '(typst-mode) "typst-mode" nil t)

(add-to-list 'auto-mode-alist '("\\.typ$" . typst-mode))

(with-eval-after-load 'typst-mode
  (add-hook 'typst-mode-hook #'view-mode))

v-mode

(autoload-if-found '(v-mode v-menu v-format-buffer) "v-mode" nil t)

(add-to-list 'auto-mode-alist '("\\(\\.v?v\\|\\.vsh\\)$" . v-mode))

(with-eval-after-load 'v-mode
  (define-key v-mode-map (kbd "M-z") #'v-menu)
  (define-key v-mode-map (kbd "C-c C-f") #'v-format-buffer))

vue-mode

(autoload-if-found '(vue-mode) "vue-mode" nil t)

(add-to-list 'auto-mode-alist '("\\.vue$" . vue-mode))

(with-eval-after-load 'vue-html-mode
  (setopt vue-html-extra-indent 4))

vimrc-mode

(autoload-if-found '(vimrc-mode) "vimrc-mode" nil t)

(add-to-list 'auto-mode-alist '("vimrc" . vimrc-mode))
(add-to-list 'auto-mode-alist '("\\.vim\\(rc\\)?\\'" . vimrc-mode))

wat-mode

(autoload-if-found '(wat-mode) "wat-mode" nil t)

(add-to-list 'auto-mode-alist '("\\.wat?\\'" . wat-mode))

web-mode

(autoload-if-found '(web-mode) "web-mode" nil t)

(add-to-list 'auto-mode-alist '("\\.html$" . web-mode))
(add-to-list 'auto-mode-alist '("\\.erb$" . web-mode))
(add-to-list 'auto-mode-alist '("\\.gsp$" . web-mode))
(add-to-list 'auto-mode-alist '("\\.svg$" . web-mode))
(add-to-list 'auto-mode-alist '("\\.tpl$" . web-mode))
(add-to-list 'auto-mode-alist '("\\.liquid$" . web-mode))
(add-to-list 'auto-mode-alist '("\\.ejs$" . web-mode))

(with-eval-after-load 'web-mode
  (setopt web-mode-comment-style 2)
  (setopt web-mode-enable-auto-pairing nil)
  (setopt web-mode-enable-auto-indentation nil)

  (add-hook 'web-mode-hook #'emmet-mode))

web-php-blade-mode

(autoload-if-found '(web-php-blade-mode) "web-php-blade-mode" nil t)

(add-to-list 'auto-mode-alist '("\\.blade\\.php$" . web-php-blade-mode))

wolfram-mode

(autoload-if-found '(wolfram-mode run-wolfram) "wolfram-mode" nil t)

(add-to-list 'auto-mode-alist '("\\.m$" . wolfram-mode))
(add-to-list 'auto-mode-alist '("\\.nb$" . wolfram-mode))
(add-to-list 'auto-mode-alist '("\\.cbf$" . wolfram-mode))

(with-eval-after-load 'wolfram-mode
  (setopt wolfram-path "path-to-dir"))

yaml-mode

(autoload-if-found '(yaml-mode) "yaml-mode" nil t)

(add-to-list 'auto-mode-alist '("\\.ya?ml$" . yaml-mode))
(add-to-list 'auto-mode-alist '("\\.aclpolicy$" . yaml-mode))

(with-eval-after-load 'yaml-mode
  (add-hook 'yaml-mode-hook #'flycheck-mode)
  (add-hook 'yaml-mode-hook #'view-mode))

yarn-mode

(autoload-if-found '(yarn-mode) "yarn-mode" nil t)

(add-to-list 'auto-mode-alist '("yarn\\.lock\\'" . yarn-mode))

(with-eval-after-load 'yarn-mode
  (add-hook 'yarn-mode-hook #'view-mode))

zig-mode

(autoload-if-found '(zig-mode) "zig-mode" nil t)

(add-to-list 'auto-mode-alist '("\\.zig$" . zig-mode))

IME

nskk

  (autoload-if-found '(nskk-mode nskk-global-mode) "nskk" nil t)

  (keymap-global-set "C-x C-j" #'nskk-mode)

  (with-eval-after-load 'nskk
    (setopt nskk-state-default-mode 'hiragana)

    (setopt nskk-converter-romaji-style 'azik)
    (setopt nskk-azik-keyboard-type 'jp106)

    (setopt nskk-use-color-cursor t)
    (set-face-attribute 'nskk-cursor-hiragana nil :background "#50fa7b")
    (set-face-attribute 'nskk-cursor-katakana nil :background "#8be9fd")
    (set-face-attribute 'nskk-cursor-latin nil :background "#ff79c6")
    (set-face-attribute 'nskk-cursor-jisx0208-latin nil :background "#ffb86c")
    (set-face-attribute 'nskk-cursor-abbrev nil :background "#bd93f9")

    (defun my/nskk-kakutei-newline-on-hiragana-idle (orig-fn &rest args)
      "`nskk-kakutei' documents `hiragana-idle' as a no-op; turn that no-op
into a newline, so C-j breaks the line whenever nothing is left to confirm.
The state must be read before ORIG-FN runs: committing ▽/▼ leaves nskk in
`hiragana-idle', so an `:after' advice reading it afterwards cannot tell a
commit apart from an idle keypress and appends a newline to every
conversion. A later `:override' advice on `nskk-kakutei' added elsewhere in
this file would silently stop this from firing (nadvice `:override' ignores
anything already wrapped); call this function explicitly from such an
override rather than assuming it still runs."
      (let ((idle (eq (nskk-current-kakutei-state) 'hiragana-idle)))
        (prog1 (apply orig-fn args)
          (when idle
            (condition-case nil
                (newline)
              ((buffer-read-only text-read-only) nil))))))

    (advice-add 'nskk-kakutei :around #'my/nskk-kakutei-newline-on-hiragana-idle)

    (when-darwin
     (setopt nskk-server-enable t)
     (setopt nskk-server-host "localhost")
     (setopt nskk-server-portnum 1178)))

scratchpad

(defun my/scratchpad-init ()
  "Initialize scratchpad: switch to *scratch* and enable nskk-mode."
  (switch-to-buffer "*scratch*")
  (when (and (fboundp 'nskk-mode)
             (not (bound-and-true-p nskk-mode)))
    (nskk-mode 1))
  nil)

(defun my/scratchpad-warm-up ()
  "Enable nskk-mode in *scratch* before the first scratchpad hotkey needs it."
  (when (fboundp 'nskk-mode)
    (with-current-buffer (get-buffer-create "*scratch*")
      (unless (bound-and-true-p nskk-mode)
        (condition-case err
            (nskk-mode 1)
          (error (message "scratchpad warm-up skipped: %s"
                          (error-message-string err))))))))

(run-with-idle-timer 3 nil #'my/scratchpad-warm-up)

Coding

Check

flymake-proc

(require 'flymake-proc)

flycheck

(autoload-if-found '(flycheck-mode) "flycheck" nil t)

flycheck-textlint

(with-eval-after-load 'flycheck
  (flycheck-define-checker textlint
    "A linter for prose."
    :command ("textlint" "--format" "unix" source-inplace)
    :error-patterns
    ((warning line-start (file-name) ":" line ":" column ": "
              (id (one-or-more (not (any " "))))
              (message (one-or-more not-newline)
                       (zero-or-more "\n" (any " ") (one-or-more not-newline)))
              line-end))
    :modes (org-mode))
  (add-to-list 'flycheck-checkers 'textlint))

flycheck-elsa

(autoload-if-found '(flycheck-elsa-setup) "flycheck-elsa" nil t)

(with-eval-after-load 'elisp-mode
  (add-hook 'emacs-lisp-mode-hook #'flycheck-elsa-setup))

flycheck-projectile

(autoload-if-found '(flycheck-projectile-list-errors) "flycheck-projectile" nil t)

flycheck-cfn

(autoload-if-found '(flycheck-cfn-setup) "flycheck-cfn" nil t)

(with-eval-after-load 'cfn-mode
  (add-hook 'cfn-mode-hook #'flycheck-cfn-setup))

Completion

corfu

(autoload-if-found '(global-corfu-mode) "corfu" nil t)

(add-hook 'after-init-hook #'global-corfu-mode)

(with-eval-after-load 'corfu
  (setopt corfu-auto t)
  (setopt corfu-auto-delay 0.2)
  (setopt corfu-auto-prefix 2)
  (setopt corfu-cycle t)
  (setopt corfu-on-exact-match nil)
  (setopt corfu-quit-no-match 'separator)

  (require 'corfu-popupinfo)
  (require 'corfu-history)
  (corfu-popupinfo-mode 1)
  (corfu-history-mode 1)

  (when (< emacs-major-version 31)
    (require 'corfu-terminal)
    (corfu-terminal-mode 1)))

(with-eval-after-load 'savehist
  (add-to-list 'savehist-additional-variables 'corfu-history))

(with-eval-after-load 'indent
  (setopt tab-always-indent 'complete))

cape

(autoload-if-found '(cape-file
                     cape-dabbrev
                     cape-elisp-block
                     cape-history) "cape" nil t)

(with-eval-after-load 'cape
  (setopt cape-dabbrev-min-length 2))

(add-hook 'completion-at-point-functions #'cape-dabbrev)
(add-hook 'completion-at-point-functions #'cape-file)
(add-hook 'completion-at-point-functions #'cape-elisp-block)
(add-hook 'completion-at-point-functions #'cape-history)

prescient

(autoload-if-found '(prescient-persist-mode) "prescient" nil t)

(add-hook 'after-init-hook #'prescient-persist-mode)

(with-eval-after-load 'prescient
  (setopt prescient-aggressive-file-save t))

kind-icon

(autoload-if-found '(kind-icon-margin-formatter) "kind-icon" nil t)

(with-eval-after-load 'corfu
  (add-to-list 'corfu-margin-formatters #'kind-icon-margin-formatter))

Git

magit

  (autoload-if-found '(global-git-commit-mode) "git-commit" nil t)
  (autoload-if-found '(magit-status magit-blame) "magit")
  (autoload-if-found '(magit-branch) "magit-branch")

  (add-hook 'after-init-hook #'global-git-commit-mode)

  (keymap-global-set "C-x g" #'my/magit-status)
  (keymap-global-set "C-x G" #'magit-blame)

  (defun my/vcs-root (dir)
    "Return (KIND . ROOT) for the repository enclosing DIR, or nil.
The nearest ancestor of DIR holding a .jj or .git entry decides, so a git
checkout nested under a jj repository is git and a colocated checkout, which
has both entries, is jj.  KIND is `jj' or `git'; ROOT is a directory name.
statusline.sh applies the same nearest-.jj/.git rule."
    (when-let* ((root (locate-dominating-file
                       dir
                       (lambda (d)
                         (or (file-exists-p (expand-file-name ".jj" d))
                             (file-exists-p (expand-file-name ".git" d)))))))
      (cons (if (file-exists-p (expand-file-name ".jj" root)) 'jj 'git) root)))

  (defun my/jj-call (root &rest args)
    "Run `jj -R ROOT ARGS'; return (EXIT STDOUT STDERR) with both streams trimmed.
Uses `call-process' with an argument list so no value is reinterpreted as
shell syntax."
    (let ((err-file (make-temp-file "jj-stderr-")))
      (unwind-protect
          (with-temp-buffer
            (let ((exit (apply #'call-process "jj" nil (list t err-file) nil "-R" root args)))
              (list exit
                    (string-trim (buffer-string))
                    (progn (erase-buffer)
                           (insert-file-contents err-file)
                           (string-trim (buffer-string))))))
        (delete-file err-file))))

  (defun my/jj-output (root &rest args)
    "Run `jj -R ROOT ARGS'; return trimmed stdout, or nil on nonzero exit."
    (pcase-let ((`(,exit ,out ,_) (apply #'my/jj-call root args)))
      (and (zerop exit) out)))

  (defun my/jj-output-or-error (root &rest args)
    "Like `my/jj-output', but signal an error carrying jj's stderr on failure."
    (pcase-let ((`(,exit ,out ,err) (apply #'my/jj-call root args)))
      (if (zerop exit)
          out
        (error "jj %s failed (exit %s): %s" (string-join args " ") exit err))))

  (defun my/magit-status ()
    "Open majutsu in a jj repository and magit otherwise."
    (interactive)
    (let ((vcs (my/vcs-root default-directory)))
      (if (eq (car vcs) 'jj)
          (majutsu-log (cdr vcs))
        (let ((default-directory (locate-dominating-file default-directory ".git")))
          (magit-status)))))

  (defun my/update-magit-repository-directories (&optional roots)
    "Populate `magit-repository-directories' from the same ghq-aware root set
that backs `projectile-known-projects' (bare repos contribute only their
worktree children; non-bare repos contribute themselves), each paired with
depth 0 per Magit's (DIRECTORY . DEPTH) format (magit-repository-directories
docstring / magit.vc Repository List manual).  ROOTS, when supplied, is used
directly instead of recomputing via `my/ghq-project-roots'."
    (interactive)
    (setopt magit-repository-directories
            (mapcar (lambda (d) (cons (abbreviate-file-name (file-name-as-directory d)) 0))
                    (or roots (my/ghq-project-roots)))))

  (with-eval-after-load 'magit
    (setopt magit-refresh-status-buffer nil))

  (with-eval-after-load 'magit-status


    (define-key magit-status-mode-map (kbd "C-j") #'magit-visit-thing))

  (with-eval-after-load 'magit-log
    (define-key magit-log-mode-map (kbd "C-j") #'magit-visit-thing))

  (with-eval-after-load 'magit-mode
    (setopt magit-display-buffer-function #'magit-display-buffer-fullcolumn-most-v1))

  (with-eval-after-load 'magit-diff
    (setopt magit-diff-visit-prefer-worktree t))

  (defun my/magit-gh-pr-checkout (pr-number detach)
    (let* ((args (append '("pr" "checkout")
                         (when detach '("--detach"))
                         (list (number-to-string pr-number))))
           (cmd (string-join (cons "gh" args) " ")))
      (message "Executing: %s" cmd)
      (apply #'call-process "gh" nil nil nil args)
      (magit-refresh)))

  (defun my/magit-gh-pr-checkout-detach ()
    (interactive)
    (let ((pr (read-number "GitHub PR number (detach): ")))
      (my/magit-gh-pr-checkout pr t)))

  (defun my/magit-gh-pr-checkout-normal ()
    (interactive)
    (let ((pr (read-number "GitHub PR number (branch): ")))
      (my/magit-gh-pr-checkout pr nil)))

  (with-eval-after-load 'magit-branch
    (transient-append-suffix 'magit-branch "c"
      '("p" "Checkout PR (detach)" my/magit-gh-pr-checkout-detach))

    (transient-append-suffix 'magit-branch "c"
      '("P" "Checkout PR (branch)" my/magit-gh-pr-checkout-normal)))

git-gutter

(autoload-if-found '(git-gutter-mode) "git-gutter" nil t)

(with-eval-after-load 'git-gutter
  (setopt git-gutter:update-hooks '(after-save-hook after-revert-hook)))

git-gutter-fringe

(autoload-if-found '(git-gutter-fr:init
                     git-gutter-fr:view-diff-infos
                     git-gutter-fr:clear) "git-gutter-fringe" nil t)

(with-eval-after-load 'git-gutter
  (setopt git-gutter-fr:side 'right-fringe)
  (setopt git-gutter:window-width -1)
  (setopt git-gutter:init-function #'git-gutter-fr:init)
  (setopt git-gutter:view-diff-function #'git-gutter-fr:view-diff-infos)
  (setopt git-gutter:clear-function #'git-gutter-fr:clear))

git-timemachine

(autoload-if-found '(git-timemachine) "git-timemachine" nil t)

gist

(autoload-if-found '(gist-mode) "gist" nil t)

blamer

(autoload-if-found '(blamer-mode) "blamer" nil t)

git-auto-commit-mode

(autoload-if-found '(git-auto-commit-mode) "git-auto-commit-mode" nil t)

(with-eval-after-load 'git-auto-commit-mode
  (setopt gac-automatically-push-p t)
  (setopt gac-silent-message-p t)
  (setopt gac-debounce-interval (* 60 60 3))
  (setopt gac-default-message "Update"))

majutsu

  (autoload-if-found '(majutsu majutsu-log) "majutsu" nil t)

  (defun my/jj-checkout-pr (number)
    "Start a new jj change on top of the head branch of pull request NUMBER.
The head branch is fetched from origin and `jj new' is run on it in the
current jj repository.  A pull request from a fork is refused instead of
adding a remote."
    (interactive (list (read-number "PR number: ")))
    (let* ((root (let ((vcs (my/vcs-root default-directory)))
                   (if (eq (car vcs) 'jj)
                       (cdr vcs)
                     (user-error "Not inside a jj repository"))))
           (default-directory root)
           (url (or (my/jj-origin-url root)
                    (user-error "No origin remote in %s" root)))
           ;; a jj workspace has no .git, so gh cannot infer the repository
           (repo (replace-regexp-in-string "\\`https?://" "" (my/remote-url-to-https url)))
           (info (with-temp-buffer
                   (unless (zerop (call-process "gh" nil (list t nil) nil "pr" "view"
                                                (number-to-string number) "--repo" repo
                                                "--json" "headRefName,isCrossRepository"))
                     (user-error "gh pr view %d failed" number))
                   (goto-char (point-min))
                   (json-parse-string (buffer-string) :object-type 'alist
                                      :false-object nil :null-object nil)))
           (head (alist-get 'headRefName info)))
      (when (alist-get 'isCrossRepository info)
        (user-error "PR %d comes from a fork; add the remote manually" number))
      (unless (and (stringp head)
                   (string-match-p "\\`[A-Za-z0-9._/-]+\\'" head)
                   (not (string-prefix-p "-" head)))
        (user-error "PR %d has an unusable head branch name: %S" number head))
      (pcase-let ((`(,exit ,_ ,err) (my/jj-call root "git" "fetch" "--remote" "origin"
                                                "--branch" (concat "exact:" head))))
        (unless (zerop exit)
          (user-error "jj git fetch of %s failed: %s" head err)))
      (pcase-let ((`(,exit ,_ ,err) (my/jj-call root "new" (concat head "@origin"))))
        (unless (zerop exit)
          (user-error "jj new %s@origin failed: %s" head err)))
      (message "Checked out PR %d (%s@origin)" number head)))

Keyboard

key-chord

(autoload-if-found '(key-chord-mode key-chord-define-global) "key-chord" nil t)

(add-hook 'after-init-hook #'key-chord-mode)
(add-hook 'after-init-hook #'(lambda ()
                               (key-chord-define-global "fj" #'view-mode)
                               (key-chord-define-global "jf" #'view-mode)))

key-combo

(autoload-if-found '(key-combo-mode key-combo-define-local) "key-combo" nil t)

(with-eval-after-load 'php-mode
  )

(with-eval-after-load 'typescript-tsx-mode
  (add-hook 'typescript-tsx-mode
            #'(lambda ()
                (key-combo-mode)
                (key-combo-define-local (kbd "</") #'web-mode-element-close))))

which-key

(autoload-if-found '(which-key-mode) "which-key" nil t)

(add-hook 'after-init-hook #'which-key-mode)

dmacro

(autoload-if-found '(global-dmacro-mode) "dmacro" nil t)

(add-hook 'after-init-hook #'global-dmacro-mode)

god-mode

(autoload-if-found '(god-mode) "god-mode" nil t)

Refactor

emr

(autoload-if-found '(emr-show-refactor-menu) "emr" nil t)

(with-eval-after-load 'prog-mode
  (define-key prog-mode-map (kbd "M-RET") #'emr-show-refactor-menu))

Snippet

yasnippet

(autoload-if-found '(yas-global-mode) "yasnippet" nil t)

(add-hook 'after-init-hook #'yas-global-mode)

consult-yasnippet

(autoload-if-found '(consult-yasnippet) "consult-yasnippet" nil t)

(keymap-global-set "C-c y" #'consult-yasnippet)
(keymap-global-set "C-c C-y" #'consult-yasnippet)

Narrowing

soft-narrow

(autoload-if-found '(soft-narrow-mode) "soft-narrow" nil t)

(add-hook 'after-init-hook #'soft-narrow-mode)

LSP

eglot

(autoload-if-found '(eglot-ensure) "eglot" nil t)

(with-eval-after-load 'eglot
  (setopt eglot-events-buffer-size nil)
  (setopt eglot-autoshutdown t)
  (setopt eglot-extend-to-xref t)

  (add-to-list 'eglot-server-programs
               '(typescript-mode . ("deno" "lsp"
                                    :initializationOptions (:deno (:enable t))))))

eglot-booster

(autoload-if-found '(eglot-booster-mode) "eglot-booster" nil t)

(add-hook 'after-init-hook #'eglot-booster-mode)

lsp-mode

(autoload-if-found '(lsp lsp-deferred lsp-org lsp-register-client make-lsp-client) "lsp-mode" nil t)
(autoload-if-found '(lsp-lens-mode lsp-lens-refresh lsp-lens--enable) "lsp-lens" nil t)
(autoload-if-found '(lsp-modeline-workspace-status-mode lsp-modeline-code-actions-mode) "lsp-modeline" nil t)
(autoload-if-found '(lsp-headerline-breadcrumb-mode) "lsp-headerline" nil t)
(autoload-if-found '(lsp-diagnostics-mode) "lsp-diagnostics" nil t)

(with-eval-after-load 'lsp-mode
  (add-to-list 'lsp-language-id-configuration '("php-ts-mode" . "php"))

  (advice-add 'lsp-rename :around #'my/advice-disable-buffer-readonly)
  (advice-add 'lsp-execute-code-action :around #'my/advice-disable-buffer-readonly)

  (add-to-list 'lsp-file-watch-ignored-directories "[/\\\\]vendor")
  (add-to-list 'lsp-file-watch-ignored-directories "[/\\\\]storage")
  (add-to-list 'lsp-file-watch-ignored-directories "[/\\\\]docs")
  (add-to-list 'lsp-file-watch-ignored-directories "[/\\\\]target")
  (add-to-list 'lsp-file-watch-ignored-directories "[/\\\\].calva")
  (add-to-list 'lsp-file-watch-ignored-directories "[/\\\\].clj-kondo")
  (add-to-list 'lsp-file-watch-ignored-directories "[/\\\\].direnv")

  (add-hook 'lsp-mode-hook #'flycheck-mode)

  (add-hook 'lsp-configure-hook #'lsp-diagnostics-mode)

  (add-hook 'lsp-configure-hook #'corfu-mode)

  (setopt lsp-response-timeout 60)
  (setopt lsp-idle-delay 0.8)
  (setopt lsp-enable-links nil)
  (setopt lsp-log-io nil)
  (setopt lsp-file-watch-threshold 20000)
  (setopt lsp-client-packages (delq 'lsp-volar lsp-client-packages))
  (setopt lsp-modeline-code-actions-enable nil))

(with-eval-after-load 'lsp-diagnostics
  (setopt lsp-diagnostics-flycheck-default-level 'warning))

(with-eval-after-load 'lsp-completion
  (setopt lsp-completion-no-cache t)
  (setopt lsp-completion-provider :none))

(with-eval-after-load 'lsp-php
  (setopt lsp-intelephense-telemetry-enabled t)
  (setopt lsp-intelephense-files-exclude ["**/.git/**" "**/.svn/**" "**/.hg/**" "**/CVS/**" "**/.DS_Store/**"
                                          "**/node_modules/**" "**/bower_components/**" "**/vendor/**/{Test,test,Tests,tests}/**"
                                          "**/.direnv/**"]))

(with-eval-after-load 'lsp-javascript
  (setopt lsp-typescript-references-code-lens-enabled t)
  (setopt lsp-typescript-implementations-code-lens-enabled t)
  (setopt lsp-javascript-display-return-type-hints t)
  (setopt lsp-javascript-display-parameter-type-hints t)
  (setopt lsp-javascript-display-parameter-name-hints-when-argument-matches-name t)
  (setopt lsp-javascript-display-property-declaration-type-hints t)
  (setopt lsp-javascript-display-variable-type-hints t)

  (setopt lsp-clients-deno-enable-unstable t))

(with-eval-after-load 'lsp-ruby
  (setopt lsp-solargraph-autoformat t)
  (setopt lsp-solargraph-multi-root nil))

(with-eval-after-load 'lsp-nix
  (setopt lsp-disabled-clients '(nix-nil))
  (setopt lsp-nix-nixd-server-path "nixd")
  (setopt lsp-nix-nixd-formatting-command ["nixfmt-rfc-style"])
  (let ((flake-path (concat "builtins.getFlake \""
                            (my/ghq-repo-path "github.com/takeokunn/nixos-configuration")
                            "\"")))
    (setopt lsp-nix-nixd-nixpkgs-expr
            (format "import (%s).inputs.nixpkgs { }" flake-path))
    (setopt lsp-nix-nixd-nixos-options-expr
            (format "(%s).darwinConfigurations.M4-Max.options" flake-path))
    (setopt lsp-nix-nixd-home-manager-options-expr
            (format "(%s).darwinConfigurations.M4-Max.options.home-manager.users.type.getSubOptions []" flake-path))))

(with-eval-after-load 'lsp-copilot
  (setopt lsp-copilot-enabled nil))

kakehashi

(with-eval-after-load 'lsp-mode
  (lsp-register-client
   (make-lsp-client
    :new-connection (lsp-stdio-connection '("kakehashi"))
    :activation-fn (lsp-activate-on "markdown")
    :server-id 'kakehashi)))

emacs-lsp-booster

https://github.com/blahgeek/emacs-lsp-booster?tab=readme-ov-file#configure-lsp-mode

(defun lsp-booster--advice-json-parse (old-fn &rest args)
  "Try to parse bytecode instead of json."
  (or
   (when (equal (following-char) ?#)
     (let ((bytecode (read (current-buffer))))
       (when (byte-code-function-p bytecode)
         (funcall bytecode))))
   (apply old-fn args)))

(advice-add (if (progn (require 'json)
                       (fboundp 'json-parse-buffer))
                'json-parse-buffer
              'json-read)
            :around
            #'lsp-booster--advice-json-parse)

(defun lsp-booster--advice-final-command (old-fn cmd &optional test?)
  "Prepend emacs-lsp-booster command to lsp CMD."
  (let ((orig-result (funcall old-fn cmd test?)))
    (if (and (not test?)                             ;; for check lsp-server-present?
             (not (file-remote-p default-directory)) ;; see lsp-resolve-final-command, it would add extra shell wrapper
             lsp-use-plists
             (not (functionp 'json-rpc-connection))  ;; native json-rpc
             (executable-find "emacs-lsp-booster"))
        (progn
          (when-let* ((command-from-exec-path (executable-find (car orig-result))))  ;; resolve command from exec-path (in case not found in $PATH)
            (setcar orig-result command-from-exec-path))
          (message "Using emacs-lsp-booster for %s!" orig-result)
          (cons "emacs-lsp-booster" orig-result))
      orig-result)))

(advice-add 'lsp-resolve-final-command :around #'lsp-booster--advice-final-command)

emacs-ccls

(with-eval-after-load 'lsp-mode
  (add-hook 'lsp-mode-hook #'(lambda () (require 'ccls))))

lsp-php-key

(with-eval-after-load 'lsp-php
  (setopt lsp-intelephense-licence-key "00OXTX8OROOJH9P"))

consult-lsp

(autoload-if-found '(consult-lsp-symbols) "consult-lsp" nil t)

(with-eval-after-load 'lsp-mode
  (define-key lsp-mode-map [remap xref-find-apropos] #'consult-lsp-symbols))

lsp-treemacs

(autoload-if-found '(lsp-treemacs-sync-mode) "lsp-treemacs" nil t)

(with-eval-after-load 'lsp-mode
  (add-hook 'lsp-mode-hook #'lsp-treemacs-sync-mode))

(with-eval-after-load 'lsp-treemacs
  (setopt lsp-treemacs-error-list-severity 1)
  (setopt lsp-treemacs-error-list-current-project-only t))

lsp-dart

(with-eval-after-load 'lsp-mode
  (add-hook 'lsp-mode-hook #'(lambda ()
                             (require 'lsp-dart))))

dap-mode

(autoload-if-found '(dap-debug) "dap-mode" nil t)
(autoload-if-found '(dap-hydra) "dap-hydra" nil t)
(autoload-if-found '(dap-ui-mode dap-ui-controls-mode) "dap-ui" nil t)
(autoload-if-found '(dap-tooltip-mode) "dap-mouse" nil t)
(autoload-if-found '(dap-php-setup) "dap-php" nil t)
(autoload-if-found '(dap-node-setup) "dap-node" nil t)
(autoload-if-found '(dap-go-setup) "dap-go" nil t)
(autoload-if-found '(dap-ruby-setup) "dap-ruby" nil t)

(with-eval-after-load 'dap-mode
  (define-key dap-mode-map (kbd "C-c d") #'dap-breakpoint-toggle)

  (add-hook 'dap-mode-hook #'dap-ui-mode)
  (add-hook 'dap-mode-hook #'dap-ui-controls-mode)
  (add-hook 'dap-mode-hook #'tooltip-mode)
  (add-hook 'dap-mode-hook #'dap-tooltip-mode)
  (add-hook 'dap-stopped-hook #'(lambda (_arg) (call-interactively #'dap-hydra))))

lsp-ui

(autoload-if-found '(lsp-ui-mode) "lsp-ui" nil t)

(with-eval-after-load 'lsp-mode
  (add-hook 'lsp-mode-hook #'lsp-ui-mode))

(with-eval-after-load 'lsp-ui-doc
  (setopt lsp-ui-doc-enable t)
  (setopt lsp-ui-doc-show-with-cursor t)
  (setopt lsp-ui-doc-use-webkit t)
  (setopt lsp-ui-doc-include-signature t)
  (setopt lsp-ui-doc-delay 1)
  (setopt lsp-ui-doc-max-height 30))

(autoload-if-found '(lsp-ui-peek-find-references lsp-ui-peek-find-definitions lsp-ui-peek-find-implementation) "lsp-ui-peek" nil t)
(with-eval-after-load 'lsp-ui-peek
  (setopt lsp-ui-peek-enable nil)
  (setopt lsp-ui-peek-peek-height 30)
  (setopt lsp-ui-peek-list-width 60)
  (setopt lsp-ui-peek-fontify 'on-demand))

(autoload-if-found '(lsp-ui-imenu) "lsp-ui-imenu" nil t)
(with-eval-after-load 'lsp-ui-imenu
  (setopt lsp-ui-imenu-enable nil)
  (setopt lsp-ui-imenu-kind-position 'top))

(autoload-if-found '(lsp-ui-sideline-mode) "lsp-ui-sideline" nil t)
(with-eval-after-load 'lsp-ui-sideline
  (setopt lsp-ui-sideline-enable nil)
  (setopt lsp-ui-sideline-show-hover t))

(with-eval-after-load 'lsp-mode
  (define-key lsp-mode-map (kbd "C-c C-r") #'lsp-ui-peek-find-references)
  (define-key lsp-mode-map (kbd "C-c C-j") #'lsp-ui-peek-find-definitions)
  (define-key lsp-mode-map (kbd "C-c C-i") #'lsp-ui-peek-find-implementation)
  (define-key lsp-mode-map (kbd "C-c C-m") #'lsp-ui-imenu)
  (define-key lsp-mode-map (kbd "C-c C-s") #'lsp-ui-sideline-mode)
  (define-key lsp-mode-map (kbd "C-c C-d") #'lsp-ui-doc-mode))

lsp-scheme

(autoload-if-found '(lsp-scheme) "lsp-scheme" nil t)

(with-eval-after-load 'scheme
  (add-hook 'scheme-mode-hook #'lsp-scheme))

lsp-bridge


Syntax

syntax-subword

(autoload-if-found '(global-syntax-subword-mode) "syntax-subword" nil t)

(add-hook 'after-init-hook #'global-syntax-subword-mode)

Undo

undo-tree

(autoload-if-found '(global-undo-tree-mode) "undo-tree" nil t)

(add-hook 'after-init-hook #'global-undo-tree-mode)

(with-eval-after-load 'undo-tree
  (setopt undo-tree-auto-save-history nil))

View Mode

view-mode

(with-eval-after-load 'prog-mode
  (add-hook 'prog-mode-hook #'view-mode))

(with-eval-after-load 'view
  (define-key view-mode-map (kbd "f") #'forward-char)
  (define-key view-mode-map (kbd "b") #'backward-char)
  (define-key view-mode-map (kbd "n") #'my/org-view-next-heading)
  (define-key view-mode-map (kbd "p") #'my/org-view-previous-heading)
  (define-key view-mode-map (kbd "@") #'set-mark-command)
  (define-key view-mode-map (kbd "C-c '") #'my/org-edit-special)
  (define-key view-mode-map (kbd "C-c C-C") #'my/org-ctrl-c-ctrl-c)
  (define-key view-mode-map (kbd "e") nil)
  (define-key view-mode-map (kbd "C-j") nil)
  (define-key view-mode-map (kbd "C-i") #'my/view-tab)
  (define-key view-mode-map (kbd "S-C-i") #'my/view-shifttab)

  (defun my/org-view-next-heading ()
    (interactive)
    (if (and (derived-mode-p 'org-mode)
             (org-at-heading-p))
        (org-next-visible-heading 1)
      (next-line)))

  (defun my/org-view-previous-heading ()
    (interactive)
    (if (and (derived-mode-p 'org-mode)
             (org-at-heading-p))
        (org-previous-visible-heading 1)
      (previous-line)))

  (defun my/view-tab ()
    (interactive)
    (when (and (derived-mode-p 'org-mode)
               (or (org-at-heading-p)
                   (org-at-property-drawer-p)))
      (let ((view-mode nil))
        (org-cycle))))

  (defun my/view-shifttab ()
    (interactive)
    (when (derived-mode-p 'org-mode)
      (let ((view-mode nil))
        (org-shifttab))))

  (defun my/org-edit-special ()
    (interactive)
    (when (derived-mode-p 'org-mode)
      (view-mode -1)
      (org-edit-special)))

  (defun my/org-ctrl-c-ctrl-c ()
    (interactive)
    (when (derived-mode-p 'org-mode)
      (view-mode -1)
      (org-ctrl-c-ctrl-c)))

  (defun my/disable-buffer-readonly ()
    (setq-local buffer-read-only nil))

  (defun my/advice-disable-buffer-readonly (old-func &rest args)
    (add-hook 'view-mode-hook #'my/disable-buffer-readonly)
    (apply old-func args)
    (remove-hook 'view-mode-hook #'my/disable-buffer-readonly)))

Utility

comint

(with-eval-after-load 'comint
  (setopt comint-buffer-maximum-size 100000)
  (setopt comint-prompt-read-only t)
  (setopt comint-terminfo-terminal "eterm-256color"))

crux

(autoload-if-found '(crux-open-with
                     crux-smart-open-line-above
                     crux-cleanup-buffer-or-region
                     crux-view-url
                     crux-transpose-windows
                     crux-duplicate-current-line-or-region
                     crux-duplicate-and-comment-current-line-or-region
                     crux-rename-file-and-buffer
                     crux-visit-term-buffer
                     crux-kill-other-buffers
                     crux-indent-defun
                     crux-top-join-lines
                     crux-kill-line-backwards) "crux" nil t)

(keymap-global-set "C-c o" #'crux-open-with)
(keymap-global-set "C-S-o" #'crux-smart-open-line-above)
(keymap-global-set "C-c u" #'crux-view-url)
(keymap-global-set "C-x 4 t" #'crux-transpose-windows)
(keymap-global-set "C-c d" #'crux-duplicate-current-line-or-region)
(keymap-global-set "C-c M-d" #'crux-duplicate-and-comment-current-line-or-region)
(keymap-global-set "C-c r" #'crux-rename-file-and-buffer)
(keymap-global-set "C-c M-t" #'crux-visit-term-buffer)
(keymap-global-set "C-c k" #'crux-kill-other-buffers)
(keymap-global-set "C-M-z" #'crux-indent-defun)
(keymap-global-set "C-^" #'crux-top-join-lines)
(keymap-global-set "C-DEL" #'crux-kill-line-backwards)

delsel

(autoload-if-found '(delete-selection-mode) "delsel" nil t)

(add-hook 'after-init-hook #'delete-selection-mode)

dogears

(autoload-if-found '(dogears-go
                     dogears-back
                     dogears-forward
                     dogears-list
                     dogears-sidebar) "dogears" nil t)

(keymap-global-set "M-g d" #'dogears-go)
(keymap-global-set "M-g M-b" #'dogears-back)
(keymap-global-set "M-g M-f" #'dogears-forward)
(keymap-global-set "M-g M-d" #'dogears-list)
(keymap-global-set "M-g M-D" #'dogears-sidebar)

goto-addr

(autoload-if-found '(goto-address-prog-mode goto-address-mode) "goto-address" nil t)

(with-eval-after-load 'prog-mode
  (add-hook 'prog-mode-hook #'goto-address-prog-mode))

(with-eval-after-load 'text-mode
  (add-hook 'text-mode-hook #'goto-address-mode))

minimap

(autoload-if-found '(minimap-mode) "minimap" nil t)

(keymap-global-set "C-c m" #'minimap-mode)

(with-eval-after-load 'minimap
  (setopt minimap-window-location 'right)
  (setopt minimap-update-delay 0.2)
  (setopt minimap-minimum-width 20)
  (setopt minimap-major-modes '(prog-mode org-mode)))

puni

(autoload-if-found '(puni-global-mode puni-disable-puni-mode) "puni" nil t)

(add-hook 'after-init-hook #'puni-global-mode)

(with-eval-after-load 'lisp-mode
  (add-hook 'lisp-mode-hook #'puni-disable-puni-mode))

(with-eval-after-load 'emacs-lisp-mode
  (add-hook 'emacs-lisp-mode-hook #'puni-disable-puni-mode))

(with-eval-after-load 'clojure-mode
  (add-hook 'clojure-mode-hook #'puni-disable-puni-mode))

(with-eval-after-load 'lisp-interaction-mode
  (add-hook 'lisp-interacton-mode-hook #'puni-disable-puni-mode))

(with-eval-after-load 'scheme
  (add-hook 'scheme-mode-hook #'puni-disable-puni-mode))

(with-eval-after-load 'simple
  (add-hook 'eval-expression-minibuffer-setup-hook #'puni-disable-puni-mode))

(with-eval-after-load 'ielm
  (add-hook 'inferior-emacs-lisp-mode-hook #'puni-disable-puni-mode))

(with-eval-after-load 'minibuffer
  (add-hook 'minibuffer-mode-hook #'puni-disable-puni-mode))

quickrun

(autoload-if-found '(quickrun) "quickrun" nil t)

restclient

(autoload-if-found '(restclient-mode) "restclient" nil t)

smart-jump

(autoload-if-found '(smart-jump-setup-default-registers) "smart-jump" nil t)

(add-hook 'after-init-hook #'smart-jump-setup-default-registers)

string-inflection

(autoload-if-found '(string-inflection-all-cycle) "string-inflection" nil t)

uuid

(autoload-if-found '(uuid-string) "uuid" nil t)

(defun my/uuid ()
  (interactive)
  (insert (uuid-string)))

woman

(autoload-if-found '(woman woman-find-file) "woman" nil t)

Remote Access

tramp

(autoload-if-found '(tramp-set-completion-function) "tramp" nil t)

consult-tramp

(autoload-if-found '(consult-tramp) "consult-tramp" nil t)

Monitor

Process

proced

(autoload-if-found '(proced) "proced" nil t)

(with-eval-after-load 'proced
  (add-hook 'proced-mode-hook #'proced-toggle-auto-update)

  (setopt proced-auto-update-interval 10)
  (setopt proced-tree-flag t)
  (setopt proced-format 'long))

proced-narrow

(autoload-if-found '(proced-narrow) "proced-narrow" nil t)

(with-eval-after-load 'proced
  (define-key proced-mode-map (kbd "/") #'proced-narrow))

System

symon

(autoload-if-found '(symon-mode) "symon" nil t)

Minor Modes

command-log-mode

(autoload-if-found '(clm/toggle-command-log-buffer) "command-log-mode" nil t)

(defalias 'command-log #'clm/toggle-command-log-buffer)

Statistics

esup

(autoload-if-found '(esup) "esup" nil t)

explain-pause-mode

(autoload-if-found '(explain-pause-mode) "explain-pause-mode" nil t)

disk-usage

(autoload-if-found '(disk-usage disk-usage-here) "disk-usage" nil t)

keyfreq

(autoload-if-found '(keyfreq-mode keyfreq-autosave-mode) "keyfreq" nil t)

(add-hook 'after-init-hook #'keyfreq-mode)
(add-hook 'after-init-hook #'keyfreq-autosave-mode)

uptimes

(autoload-if-found '(uptimes) "uptimes" nil t)

EWW

xwidges

(require 'xwidget nil t)

basic

(defun my/eww-rename-buffer ()
  "Rename the name of current EWW buffer."
  (let* ((title (plist-get eww-data :title))
         (url (file-name-base (eww-current-url)))
         (buffer-name (or (if (and title (> (length title) 0))
                              title
                            nil)
                          url "")))
    (rename-buffer (format "eww: %s" buffer-name) t)))

(with-eval-after-load 'eww
  (setopt eww-header-line-format nil)
  (setopt eww-search-prefix "http://www.google.co.jp/search?q=")

  (define-key eww-mode-map (kbd "C") #'eww-set-character-encoding)
  (define-key eww-mode-map (kbd "C-j") #'eww-follow-link)
  (define-key eww-mode-map (kbd "T") #'eww-goto-title-heading)
  (define-key eww-mode-map (kbd "T") #'eww-goto-title-heading)

  (add-hook 'eww-after-render #'my/eww-rename-buffer))

eww-lnum

(autoload-if-found '(eww-lnum-follow eww-lnum-universal) "eww-lnum" nil t)

(with-eval-after-load 'eww
  (define-key eww-mode-map "f" #'eww-lnum-follow)
  (define-key eww-mode-map "F" #'eww-lnum-universal))

Dired

basic

(with-eval-after-load 'dired
  (setopt dired-dwim-target nil)
  (setopt dired-hide-details-hide-symlink-targets nil)
  (setopt dired-listing-switches "-alh")
  (setopt dired-recursive-copies 'always)
  (setopt dired-use-ls-dired nil))

wdired

(autoload-if-found '(wdired-change-to-wdired-mode) "wdired" nil t)

(with-eval-after-load 'dired
  (define-key dired-mode-map "r" #'wdired-change-to-wdired-mode)

  (setopt wdired-allow-to-change-permissions 'advanced))

dired-collapse

(autoload-if-found '(dired-collapse-mode) "dired-collapse" nil t)

(with-eval-after-load 'dired
  (add-hook 'dired-mode #'dired-collapse-mode))

dired-filter

(autoload-if-found '(dired-filter-mode) "dired-filter" nil t)

(with-eval-after-load 'dired
  (add-hook 'dired-mode #'dired-filter-mode))

dired-narrow

(autoload-if-found '(dired-narrow-mode) "dired-narrow" nil t)

(with-eval-after-load 'dired
  (add-hook 'dired-mode-hook #'dired-narrow-mode))

dired-open

(autoload-if-found '(dired-open-file) "dired-open" nil t)

(with-eval-after-load 'dired
  (define-key dired-mode-map [remap dired-find-file] #'dired-open-file))

dired-ranger

(autoload-if-found '() "dired-ranger" nil t)

dired-subtree

(autoload-if-found '(dired-subtree-apply-filter) "dired-subtree" nil t)

dired-subtree

(autoload-if-found '(dired-subtree-apply-filter) "dired-subtree" nil t)

diredfl

(autoload-if-found '(diredfl-global-mode) "diredfl" nil t)

(with-eval-after-load 'dired
  (add-hook 'dired-mode-hook #'diredfl-global-mode))

Buffer

auto-save-buffers-enhanced

(autoload-if-found '(auto-save-buffers-enhanced) "auto-save-buffers-enhanced" nil t)


(with-eval-after-load 'auto-save-buffers-enhanced
  (setopt auto-save-buffers-enhanced-interval 10))

editorconfig

(autoload-if-found '(editorconfig-mode) "editorconfig" nil t)

(add-hook 'after-init-hook #'editorconfig-mode)

popwin

(autoload-if-found '(popwin-mode) "popwin" nil t)

(add-hook 'after-init-hook #'popwin-mode)

whitespace

(autoload-if-found '(global-whitespace-mode) "whitespace" nil t)

(when window-system
  (add-hook 'after-init-hook #'global-whitespace-mode))

(with-eval-after-load 'whitespace
  (setopt whitespace-style '(face tabs tab-mark spaces space-mark))
  (setopt whitespace-display-mappings '((space-mark ?\u3000 [?\u25a1])
                                        (tab-mark ?\t [?\xBB ?\t] [?\\ ?\t]))))

File

recentf

(autoload-if-found '(recentf-mode) "recentf" nil t)

(add-hook 'after-init-hook #'recentf-mode)

(with-eval-after-load 'recentf
  (setopt recentf-auto-cleanup 'never)
  (setopt recentf-max-menu-items 10000)
  (setopt recentf-max-saved-items 10000)
  (setopt recentf-save-file  "~/.emacs.d/.recentf")
  (setopt recentf-exclude
          (list (regexp-quote (expand-file-name ".recentf" user-emacs-directory))
                "\\.gpg\\'")))

open-junk-file

(autoload-if-found '(open-junk-file) "open-junk-file" nil t)

(keymap-global-set "C-x j" #'open-junk-file)

(with-eval-after-load 'open-junk-file
  (setopt open-junk-file-format "~/.emacs.d/.junk/%Y-%m-%d-%H%M%S."))

vlf

(autoload-if-found '(vlf-disable-for-function) "vlf-setup" t)

(with-eval-after-load 'dired
  (define-key dired-mode-map (kbd "V") #'dired-vlf))

sudo-edit

(autoload-if-found '(sudo-edit-current-file) "sudo-edit" nil t)

Project

projectile

  (autoload-if-found '(projectile-mode
                       projectile-clear-known-projects
                       projectile-cleanup-known-projects) "projectile" nil t)

  (add-hook 'after-init-hook #'projectile-mode)
  (add-hook 'after-init-hook #'my/update-ghq-project-state)

  (defun my/ghq-bare-repository-p (dir)
    "Return non-nil when DIR is a bare repository.
Tests for the absence of a .git entry rather than a .git suffix on the
directory name, so the answer does not depend on ghq's naming convention."
    (let ((git (expand-file-name ".git" dir)))
      ;; a dangling .git symlink is still a .git entry
      (not (or (file-exists-p git) (file-symlink-p git)))))

  (defun my/ghq-repo-path (relative)
    "Return a directory holding the working files of RELATIVE.
RELATIVE is a ghq-style path such as \"github.com/takeokunn/blog\".  Under the
bare layout the repository is <root>/RELATIVE.git and contains no file to
visit, so resolve instead to one of its worktrees: the fixed `main' one, or
failing that the newest timestamped one, since those names sort chronologically.
A repository still checked out normally resolves to its own path, so this is
safe to use for every repository regardless of which layout it is in."
    (let* ((root (string-trim (shell-command-to-string "ghq root")))
           (plain (expand-file-name relative root))
           (worktrees (expand-file-name ".worktrees" (concat plain ".git")))
           (main (expand-file-name "main" worktrees)))
      (cond
       ((file-directory-p plain) plain)
       ((file-directory-p main) main)
       ((file-directory-p worktrees)
        (let ((dirs (seq-filter #'file-directory-p
                                (directory-files worktrees t directory-files-no-dot-files-regexp))))
          (if dirs (car (last dirs)) plain)))
       (t plain))))

  (defun my/ghq-project-roots ()
    "Return the directories projectile should treat as projects.
`ghq list --full-path' reports one path per repository, but under the bare
layout that path is <repo>.git, which holds no working tree and therefore no
file to visit.  What is navigable there are its worktrees, so a bare entry
contributes its .worktrees/* children and nothing else.  A repository still
checked out normally contributes its own path, plus any worktrees it carries."
    (let (roots)
      (dolist (repo (my/ghq-repo-list))
        (unless (my/ghq-bare-repository-p repo)
          (push repo roots))
        (let ((worktrees (expand-file-name ".worktrees" repo)))
          (when (file-directory-p worktrees)
            (dolist (dir (directory-files worktrees t directory-files-no-dot-files-regexp))
              (when (file-directory-p dir)
                (push dir roots))))))
      (nreverse roots)))

  (defun my/ghq-repo-list ()
    "Return the list of ghq-managed repository paths (bare and non-bare)."
    (split-string (shell-command-to-string "ghq list --full-path") "\n" t))

  (defun my/ghq--git (repo-path &rest args)
    "Run git ARGS in REPO-PATH; return trimmed stdout, or nil on nonzero exit.
Uses `call-process' with an argument list rather than a shell command string,
so a value in ARGS or REPO-PATH can never be reinterpreted as shell syntax."
    (with-temp-buffer
      (let ((exit (apply #'call-process "git" nil (list t nil) nil "-C" repo-path args)))
        (when (zerop exit)
          (string-trim (buffer-string))))))

  (defun my/ghq-repo-worktrees (repo-path)
    "Return REPO-PATH's existing worktree paths, excluding its own bare
git-common-dir entry, followed by its jj workspaces, which `git worktree
list' does not report.  The jj workspace named \"default\" holds jj's store
at REPO-PATH itself and is excluded the same way.  The git half only lists
legacy worktrees: it goes away once `worktree_migrate_jj' has left none."
    ;; LEGACY-GIT: delete once worktree_migrate_jj reports no git worktrees
    (let ((common-dir (my/ghq--git repo-path "rev-parse" "--path-format=absolute" "--git-common-dir"))
          (worktrees nil)
          (workspaces nil))
      (dolist (line (split-string (or (my/ghq--git repo-path "worktree" "list" "--porcelain") "") "\n" t))
        (when (string-prefix-p "worktree " line)
          (let ((wt (substring line (length "worktree "))))
            (unless (string= wt common-dir)
              (push wt worktrees)))))
      (when (file-directory-p (expand-file-name ".jj" repo-path))
        (with-temp-buffer
          (when (zerop (call-process "jj" nil (list t nil) nil "-R" repo-path "--ignore-working-copy"
                                     "workspace" "list" "-T" "if(name != \"default\", root ++ \"\\n\")"))
            (setq workspaces (split-string (buffer-string) "\n" t)))))
      (append (nreverse worktrees) workspaces)))

  (defun my/ghq--jj-run (what &rest args)
    "Run jj with ARGS in `default-directory'; signal an error naming WHAT on failure."
    (with-temp-buffer
      (let ((exit (apply #'call-process "jj" nil t nil args)))
        (unless (zerop exit)
          (error "%s failed (exit %s): %s" what exit (string-trim (buffer-string)))))))

  (defun my/ghq--jj-init-bare (repo-path)
    "Give the bare repository REPO-PATH jj's store at its root.
Mirrors fish's `__fzf_ghq_init_jj'.  The store is initialised in a scratch
directory inside REPO-PATH, with an empty sparse set so no files are checked
out, then moved to REPO-PATH/.jj.  `jj git init --git-repo' records an
absolute git_target, which is rewritten to the relative path the moved store
needs.  Any failure removes the scratch directory and, only when this call's
rename succeeded, the moved .jj, then signals an error.  A .jj that appears
concurrently is never touched.  Does nothing when REPO-PATH already has .jj."
    (unless (my/ghq-bare-repository-p repo-path)
      (error "my/ghq--jj-init-bare: %s is not a bare repository" repo-path))
    (let ((jj-dir (expand-file-name ".jj" repo-path))
          (tmp nil)
          (moved nil)
          (done nil))
      (unless (file-exists-p jj-dir)
        (unwind-protect
            (progn
              (setq tmp (make-temp-file (expand-file-name ".jj-init." repo-path) t))
              (let ((default-directory (file-name-as-directory tmp)))
                (my/ghq--jj-run "jj git init" "git" "init" "--git-repo=.."))
              (my/ghq--jj-run "jj sparse set" "-R" tmp "sparse" "set" "--clear")
              (when (or (file-exists-p jj-dir) (file-symlink-p jj-dir))
                (error "my/ghq--jj-init-bare: concurrent jj init created %s" jj-dir))
              (condition-case nil
                  (rename-file (expand-file-name ".jj" tmp) jj-dir)
                (file-error
                 (error "my/ghq--jj-init-bare: concurrent jj init created %s" jj-dir)))
              (setq moved t)
              (write-region "../../.." nil (expand-file-name "repo/store/git_target" jj-dir)
                            nil 'silent)
              (my/ghq--jj-run "jj workspace list" "-R" repo-path "--ignore-working-copy"
                              "workspace" "list")
              (setq done t))
          (when (and moved (not done))
            (delete-directory jj-dir t))
          (when (and tmp (file-directory-p tmp))
            (delete-directory tmp t))))))

  (defun my/ghq--jj-fetch (repo-path)
    "Fetch every branch of origin into REPO-PATH's jj store, then import.
A bare clone has no remote.origin.fetch refspec, so a plain `jj git fetch'
would fetch nothing; the branch glob is passed explicitly.  A failed fetch
is tolerated with a message, since the local store may already be current."
    (let ((remotes (my/jj-output repo-path "--ignore-working-copy" "git" "remote" "list")))
      (when (and remotes (string-match-p "^origin[ \t]" remotes))
        (pcase-let ((`(,exit ,_ ,err) (my/jj-call repo-path "git" "fetch" "--remote" "origin"
                                                  "--branch" "glob:*")))
          (unless (zerop exit)
            (message "my/ghq--jj-fetch: fetch from origin failed in %s: %s" repo-path err)))))
    (my/jj-output-or-error repo-path "git" "import"))

  (defun my/ghq--jj-resolves-p (repo-path revset)
    "Return non-nil when REVSET names at least one commit in REPO-PATH."
    (let ((out (my/jj-output repo-path "--ignore-working-copy" "log" "--no-graph"
                             "-r" (format "present(%s)" revset) "-T" "commit_id")))
      (and out (not (string-empty-p out)))))

  (defun my/ghq--resolve-base-ref (repo-path)
    "Return a jj revset naming the default branch of REPO-PATH.
Mirrors fish's `__fzf_ghq_new_worktree': fetch origin first, then take the
first of main@origin, master@origin and trunk@origin that resolves, then the
branch REPO-PATH/HEAD points at, and signal an error otherwise."
    (my/ghq--jj-fetch repo-path)
    (or (seq-find (lambda (ref) (my/ghq--jj-resolves-p repo-path ref))
                  '("main@origin" "master@origin" "trunk@origin"))
        (let* ((head-file (expand-file-name "HEAD" repo-path))
               (name (and (file-readable-p head-file)
                          (with-temp-buffer
                            (insert-file-contents head-file)
                            (and (looking-at "ref: refs/heads/\\(.+\\)$")
                                 (match-string 1))))))
          (and name (my/ghq--jj-resolves-p repo-path name) name))
        (error "my/ghq--resolve-base-ref: cannot resolve a base ref in %s" repo-path)))

  (defun my/ghq--link-state (repo-path target-path)
    "Link or copy REPO-PATH's shared .state/ contents into TARGET-PATH,
mirroring __fzf_ghq_new_worktree.fish. .state/.serena/memories and
.state/.claude are symlinked, so a memory written in one worktree stays
visible from every other worktree of the same repository. .state/.envrc and
.state/.env are instead copied: unlike the symlinked pair, per-worktree
environment settings are meant to diverge from that shared file
independently once created, as a one-shot snapshot rather than something
every worktree must keep seeing live. Every target the checkout already
provides as a real path or existing symlink is skipped (with a message),
matching fish's `test -e \"$dst\"; or test -L \"$dst\"' shadow guard exactly
\(file-exists-p alone would miss a broken symlink; file-symlink-p covers it).
A missing .envrc/.env source is skipped silently, since most repositories
have neither. Immediately after a successful .envrc copy specifically (not
.env), runs `direnv allow' on TARGET-PATH when a `direnv' executable is
available; a failed or unavailable direnv is non-fatal, and a failure (as
opposed to unavailability) is reported via `message', mirroring fish's
stderr warning on the same failure."
    (let ((state-dir (expand-file-name ".state" repo-path)))
      (make-directory (expand-file-name ".serena/memories" state-dir) t)
      (make-directory (expand-file-name ".claude" state-dir) t)
      (dolist (pair '(".serena/memories" ".claude"))
        (let ((src (expand-file-name pair state-dir))
              (dst (expand-file-name pair target-path)))
          (if (or (file-exists-p dst) (file-symlink-p dst))
              (message "my/ghq--link-state: %s is provided by the checkout; leaving it unlinked" pair)
            (when (file-directory-p src)
              (make-directory (file-name-directory dst) t)
              (make-symbolic-link src dst)))))
      (dolist (name '(".envrc" ".env"))
        (let ((src (expand-file-name name state-dir))
              (dst (expand-file-name name target-path)))
          (cond
           ((or (file-exists-p dst) (file-symlink-p dst))
            (message "my/ghq--link-state: %s is provided by the checkout; leaving it uncopied" name))
           ((not (file-exists-p src)) nil)
           (t
            (copy-file src dst)
            (when (and (string= name ".envrc") (executable-find "direnv"))
              (condition-case err
                  (let ((direnv-exit (call-process "direnv" nil nil nil "allow" target-path)))
                    (unless (eq direnv-exit 0)
                      (message "my/ghq--link-state: direnv allow failed for %s (exit %s)" target-path direnv-exit)))
                (error
                 (message "my/ghq--link-state: direnv allow failed for %s (%s)" target-path (error-message-string err)))))))))))

  (defun my/ghq-create-worktree (repo-path &optional base-ref naming-mode)
    "Create a new jj workspace under the .worktrees/ of REPO-PATH.
Elisp-native equivalent of __fzf_ghq_new_worktree.fish (fish's Serena
serena_config.yml projects: prune step is deliberately NOT reimplemented here
because it needs YAML parsing this Emacs config has no library for; that
cleanup remains fish's job for worktrees created there).  A bare REPO-PATH
without jj's store is given one first; a non-bare one without it is an error.
BASE-REF is a jj revset that must name exactly one commit; when omitted it is
resolved via `my/ghq--resolve-base-ref'.  NAMING-MODE, when the symbol
`branch', names the created directory <timestamp>-<sanitized-base-ref>
\(trailing \"@origin\" stripped, \"/\" replaced with \"-\") instead of the
default <timestamp>-<short-sha>, mirroring __fzf_ghq_new_worktree.fish's
naming_mode = branch case.  Returns the created workspace's absolute path."
    (unless (file-directory-p (expand-file-name ".jj" repo-path))
      (if (my/ghq-bare-repository-p repo-path)
          (my/ghq--jj-init-bare repo-path)
        (error "my/ghq-create-worktree: %s is not bare and has no jj store" repo-path)))
    (let* ((base-ref (or base-ref (my/ghq--resolve-base-ref repo-path)))
           (_ (my/jj-output-or-error repo-path "git" "import"))
           (shas (split-string
                  (or (my/jj-output repo-path "--ignore-working-copy" "log" "--no-graph"
                                    "-r" base-ref "-T" "commit_id ++ \"\\n\"")
                      "")
                  "\n" t))
           (full-sha (if (= (length shas) 1)
                         (car shas)
                       (error "my/ghq-create-worktree: base ref %s must name exactly one commit in %s, got %d"
                              base-ref repo-path (length shas))))
           (base-sha (substring full-sha 0 8))
           (worktrees-dir (expand-file-name ".worktrees" repo-path))
           (base-name (if (eq naming-mode 'branch)
                          (format "%s-%s"
                                  (format-time-string "%Y%m%dT%H%M%S")
                                  (string-replace "/" "-" (string-remove-suffix "@origin" base-ref)))
                        (format "%s-%s" (format-time-string "%Y%m%dT%H%M%S") base-sha)))
           (target-name base-name)
           (suffix 2))
      (while (file-exists-p (expand-file-name target-name worktrees-dir))
        (setq target-name (format "%s-%d" base-name suffix))
        (setq suffix (1+ suffix)))
      (let ((target-path (expand-file-name target-name worktrees-dir)))
        (make-directory worktrees-dir t)
        (with-temp-buffer
          (unless (zerop (call-process "jj" nil t nil "-R" repo-path "workspace" "add"
                                       "--sparse-patterns" "full" "--name" target-name
                                       "-r" full-sha target-path))
            (error "my/ghq-create-worktree: failed to create workspace at %s: %s" target-path (buffer-string))))
        (my/ghq--link-state repo-path target-path)
        target-path)))

  (defun my/ghq--current-repo-path ()
    "Resolve the repository path containing `default-directory'.
Asks jj for the root of the workspace named \"default\", which holds jj's
store at the bare repository itself, so the answer is the same from a jj
workspace and from a legacy git worktree under REPO-PATH/.worktrees/."
    (with-temp-buffer
      (unless (zerop (call-process "jj" nil (list t nil) nil
                                   "workspace" "root" "--name" "default"))
        (error "my/ghq--current-repo-path: not inside a jj repository"))
      (string-trim (buffer-string))))

  (defun my/ghq-create-worktree-default-branch ()
    "Create a new worktree of the current repository named after its resolved
default branch rather than a commit sha, then switch to it via Projectile.
Elisp equivalent of fish's `worktree_default_branch', which is exactly
`__fzf_ghq_new_worktree \"\" \"\" branch', using the same base-ref resolution as
the default flow, with only the created directory's naming changed. This is
deliberately a standalone command rather than an option inside
`my/ghq-switch-project's \"[new worktree]\" picker, mirroring fish's own
separate-command precedent: `worktree_default_branch' is not reachable from
`fzf_ghq's picker either."
    (interactive)
    (let* ((repo-path (my/ghq--current-repo-path))
           (target (my/ghq-create-worktree repo-path nil 'branch)))
      (projectile-switch-project-by-name target)))

  (defun my/ghq-switch-project ()
    "Two-stage project switch mirroring fish's fzf_ghq: pick a repository,
then (for a bare repository) pick an existing worktree or create a new one,
then hand off to Projectile's own switch machinery so
`projectile-switch-project-action' and existing hooks fire unchanged."
    (interactive)
    ;; :override advice on this symbol discards the :before advice above, so refresh explicitly here
    (my/update-ghq-project-state)
    (let* ((repo (completing-read "Repository: " (my/ghq-repo-list) nil t))
           (target
            (if (my/ghq-bare-repository-p repo)
                (let ((worktrees (my/ghq-repo-worktrees repo)))
                  (if (null worktrees)
                      (my/ghq-create-worktree repo)
                    (let* ((abbrev-alist (mapcar (lambda (w) (cons (abbreviate-file-name w) w)) worktrees))
                           (choice (completing-read "Worktree: "
                                                     (cons "[new worktree]" (mapcar #'car abbrev-alist))
                                                     nil t)))
                      (if (string= choice "[new worktree]")
                          (my/ghq-create-worktree repo)
                        (or (cdr (assoc choice abbrev-alist)) choice)))))
              repo)))
      (projectile-switch-project-by-name target)))

  (defun my/update-projectile-known-projects (&optional roots)
    "Rebuild `projectile-known-projects' from ROOTS, or from
`my/ghq-project-roots' if ROOTS is nil."
    (interactive)
    (projectile-clear-known-projects)
    (projectile-cleanup-known-projects)
    (setopt projectile-known-projects (mapcar
                                       (lambda (x)
                                         (abbreviate-file-name (file-name-as-directory x)))
                                       (or roots (my/ghq-project-roots)))))

  (defun my/update-ghq-project-state ()
    "Compute the ghq-aware project roots once per invocation and refresh both
Projectile's known-projects list and Magit's repository-directories from that
single computation, instead of each recomputing it independently."
    (interactive)
    (let ((roots (my/ghq-project-roots)))
      (my/update-projectile-known-projects roots)
      (my/update-magit-repository-directories roots)))

  (with-eval-after-load 'projectile
    (advice-add 'projectile-replace :around #'my/advice-disable-buffer-readonly)
    (advice-add 'projectile-replace-regexp :around #'my/advice-disable-buffer-readonly)

    (keymap-global-set "C-x p" #'projectile-command-map)
    (keymap-global-set "C-x C-p" #'projectile-command-map)

    (setopt projectile-switch-project-action 'projectile-dired)
    (setopt projectile-use-git-grep t))

  (with-eval-after-load 'fileloop
    (advice-add 'fileloop-continue :before #'my/disable-buffer-readonly))

consult-projectile

(autoload-if-found '(consult-projectile-switch-to-buffer
                     consult-projectile-switch-to-buffer-other-window
                     consult-projectile-switch-to-buffer-other-frame
                     consult-projectile-find-dir
                     consult-projectile-find-file
                     consult-projectile-find-file-other-window
                     consult-projectile-find-file-other-frame
                     consult-projectile-recentf
                     consult-projectile-switch-project) "consult-projectile" nil t)

(with-eval-after-load 'projectile
  (advice-add 'projectile-switch-to-buffer :override #'consult-projectile-switch-to-buffer)
  (advice-add 'projectile-switch-to-buffer-other-window :override #'consult-projectile-switch-to-buffer-other-window)
  (advice-add 'projectile-switch-to-buffer-other-frame :override #'consult-projectile-switch-to-buffer-other-frame)
  (advice-add 'projectile-find-dir :override #'consult-projectile-find-dir)
  (advice-add 'projectile-find-file :override #'consult-projectile-find-file)
  (advice-add 'projectile-find-file-other-window :override #'consult-projectile-find-file-other-window)
  (advice-add 'projectile-find-file-other-frame :override #'consult-projectile-find-file-other-frame)
  (advice-add 'projectile-recentf :override #'consult-projectile-recentf)
  (advice-add 'projectile-switch-project :override #'my/ghq-switch-project)

  (keymap-global-set "C-x C-b" #'consult-projectile-switch-to-buffer))

projectile-git-autofetch

(autoload-if-found '(projectile-git-autofetch-setup) "projectile-git-autofetch" nil t)

(add-hook 'after-init-hook #'projectile-git-autofetch-setup)

(with-eval-after-load 'projectile-git-autofetch
  (setopt projectile-git-autofetch-notify nil)
  (setopt projectile-git-autofetch-interval 60)
  (setopt projectile-git-autofetch-fetch-args '("--no-progress" "--prune" "--prune-tags")))

Window

ace-window

(autoload-if-found '(ace-window) "ace-window" nil t)

(keymap-global-set "C-x o" #'ace-window)

(with-eval-after-load 'ace-window
  (setopt aw-dispatch-always t)
  (setopt aw-scope 'frame)
  (setopt aw-keys '(?a ?s ?d ?f ?g ?h ?j ?k ?l))
  (setopt aw-minibuffer-flag t))

writeroom-mode

(autoload-if-found '(writeroom-mode
                     writeroom-decrease-width
                     writeroom-increase-width
                     writeroom-adjust-width
                     writeroom-width)
                   "writeroom-mode" nil t)

(with-eval-after-load 'writeroom-mode
  (define-key writeroom-mode-map (kbd "C-M-<") #'writeroom-decrease-width)
  (define-key writeroom-mode-map (kbd "C-M->") #'writeroom-increase-width)
  (define-key writeroom-mode-map (kbd "C-M-=") #'writeroom-adjust-width)

  (setopt writeroom-width 150))

zoom-window

(autoload-if-found '(zoom-window-zoom) "zoom-window" nil t)

(keymap-global-set "C-c C-z" #'zoom-window-zoom)

tab-bar

(autoload-if-found '(tab-bar-mode
                     tab-bar-history-mode
                     tab-previous
                     tab-next
                     tab-bar-rename-tab) "tab-bar" nil t)

(add-hook 'after-init-hook #'tab-bar-mode)

(keymap-global-set "C-x C-t" tab-prefix-map)

(defun my/tab-bar-rename-tab (&rest _)
  (interactive)
  (let ((proj-name (if (and (fboundp 'projectile-project-p)
                            (projectile-project-p))
                       (projectile-project-name)
                     "-")))
    (tab-bar-rename-tab proj-name)))

(with-eval-after-load 'window
  (add-hook 'window-selection-change-functions #'my/tab-bar-rename-tab))

(with-eval-after-load 'tab-bar
  (define-key tab-prefix-map (kbd "r") #'my/tab-bar-rename-tab)

  (setopt tab-bar-close-button-show nil)
  (setopt tab-bar-close-last-tab-choice nil)
  (setopt tab-bar-close-tab-select 'left)
  (setopt tab-bar-history-mode nil)
  (setopt tab-bar-new-tab-choice "*scratch*")
  (setopt tab-bar-new-button-show nil)
  (setopt tab-bar-tab-name-truncated-max 12)
  (setopt tab-bar-separator " | ")

  ;; close neotree when tab bar action
  (advice-add 'tab-new :before #'(lambda (&rest _) (neotree-hide)))
  (advice-add 'tab-next :before #'(lambda (&rest _) (neotree-hide)))
  (advice-add 'tab-bar-switch-to-tab :before #'(lambda (&rest _) (neotree-hide))))

Cursor

avy

(autoload-if-found '(avy-goto-char avy-process) "avy" nil t)

(keymap-global-set "C-:" #'avy-goto-char)

(with-eval-after-load 'avy
  (setopt avy-all-windows nil)
  (setopt avy-background t))

avy-zap

(autoload-if-found '(avy-zap-up-to-char-dwim) "avy-zap" nil t)

(keymap-global-set "M-z" #'avy-zap-up-to-char-dwim)

expand-region

(autoload-if-found '(er/expand-region) "expand-region" nil t)

(add-hook 'after-init-hook #'transient-mark-mode)

(keymap-global-set "C-M-@" #'er/expand-region)

multiple-cursors

(autoload-if-found '(mc/mark-next-like-this mc/mark-previous-like-this mc/mark-all-like-this) "multiple-cursors" nil t)

(keymap-global-set "C->" #'mc/mark-next-like-this)
(keymap-global-set "C-<" #'mc/mark-previous-like-this)
(keymap-global-set "C-c C-<" #'mc/mark-all-like-this)

Client

Mail

mu4e

(unless (eq system-type 'darwin)
  (autoload-if-found '(mu4e) "mu4e" nil t)

  (keymap-global-set "C-x C-w" #'mu4e)

  (with-eval-after-load 'mu4e
    (setopt mail-user-agent 'mu4e-user-agent))

  (with-eval-after-load 'mu4e-update
    (setopt mu4e-get-mail-command "offlineimap")
    (setopt mu4e-update-interval (* 1 60))
    (setopt mu4e-index-cleanup nil)
    (setopt mu4e-index-lazy-check t))

  (with-eval-after-load 'mu4e-view
    (setopt mu4e-split-view 'horizontal))

  (with-eval-after-load 'mu4e-folders
    (setopt mu4e-maildir-shortcuts '((:maildir "/Gmail/INBOX" :key ?i)
                                     (:maildir "/Gmail/Emacs" :key ?e)
                                     (:maildir "/Gmail/GitHub" :key ?h)
                                     (:maildir "/Gmail/Guix" :key ?g)
                                     (:maildir "/Gmail/PHP" :key ?p))))

  (with-eval-after-load 'mm-decode
    (add-to-list 'mm-discouraged-alternatives "text/html")
    (add-to-list 'mm-discouraged-alternatives "text/richtext")))

mu4e-views

(unless (eq system-type 'darwin)
  (autoload-if-found '() "mu4e-views" nil t))

mu4e-dashboard

(unless (eq system-type 'darwin)
  (autoload-if-found '(mu4e-dashboard) "mu4e-dashboard" nil t)

  (with-eval-after-load 'mu4e-dashboard
    (setopt mu4e-dashboard-file "~/.emacs.d/misc/mu4e-dashboard.org")))

Googling

google-translate

(autoload-if-found '(google-translate-at-point) "google-translate" nil t)

Client

md4rd

(autoload-if-found '(md4rd
                     md4rd-login
                     md4rd-visit
                     md4rd-widget-expand-all
                     md4rd-widget-collapse-all
                     md4rd-reply
                     md4rd-upvote
                     md4rd-downvote
                     md4rd-widget-toggle-line
                     md4rd-refresh-login
                     md4rd-indent-all-the-lines) "md4rd" nil t)

(with-eval-after-load 'md4rd
  (add-hook 'md4rd-mode-hook #'md4rd-indent-all-the-lines)
  (run-with-timer 0 3540 #'md4rd-refresh-login)

  (setopt md4rd-subs-active '(emacs lisp+Common_Lisp prolog clojure))

  (define-key md4rd-mode-map (kbd "u") 'tree-mode-goto-parent)
  (define-key md4rd-mode-map (kbd "o") 'md4rd-open)
  (define-key md4rd-mode-map (kbd "v") 'md4rd-visit)
  (define-key md4rd-mode-map (kbd "e") 'tree-mode-toggle-expand)
  (define-key md4rd-mode-map (kbd "E") 'md4rd-widget-expand-all)
  (define-key md4rd-mode-map (kbd "C") 'md4rd-widget-collapse-all)
  (define-key md4rd-mode-map (kbd "n") 'widget-forward)
  (define-key md4rd-mode-map (kbd "j") 'widget-forward)
  (define-key md4rd-mode-map (kbd "h") 'backward-button)
  (define-key md4rd-mode-map (kbd "p") 'widget-backward)
  (define-key md4rd-mode-map (kbd "k") 'widget-backward)
  (define-key md4rd-mode-map (kbd "l") 'forward-button)
  (define-key md4rd-mode-map (kbd "q") 'kill-current-buffer)
  (define-key md4rd-mode-map (kbd "r") 'md4rd-reply)
  (define-key md4rd-mode-map (kbd "u") 'md4rd-upvote)
  (define-key md4rd-mode-map (kbd "d") 'md4rd-downvote)
  (define-key md4rd-mode-map (kbd "t") 'md4rd-widget-toggle-line))

Theme

Font

fontset

(defconst my/enable-warning-log nil)

(defun set-fontset-font:around (set-fontset-font name target font-spec &optional frame add)
  "Warn if specified font is not installed."
  (if (stringp font-spec)
      (setopt font-spec (font-spec :family font-spec)))
  (if (and (fontp font-spec)
           (null (find-font font-spec))
           my/enable-warning-log)
      (warn "set-fontset-font: font %s is not found." (font-get font-spec :family))
    (ignore-errors
      (funcall set-fontset-font name target font-spec frame add))))

;; reset all settings in default fontset
(add-hook 'after-init-hook
          #'(lambda ()
              (advice-add 'set-fontset-font :around #'set-fontset-font:around)

              ;; Set default font size to 13pt (height is in 1/10pt units, match kitty)
              (set-face-attribute 'default nil :height 130)

              (when (functionp 'set-fontset-font)
                (if (find-font (font-spec :family "Noto Sans"))
                    (set-fontset-font t '(0 . #x3fffff) "Noto Sans"))

                (set-fontset-font t 'latin "Noto Sans")
                (set-fontset-font t 'greek "Noto Sans")
                (set-fontset-font t 'phonetic "Noto Sans")
                (set-fontset-font t 'coptic "Noto Sans Coptic")
                (set-fontset-font t 'coptic "Noto Sans Symbols2" nil 'append)
                (set-fontset-font t 'cyrillic "Noto Sans")
                (set-fontset-font t 'armenian "Noto Sans Armenian")
                (set-fontset-font t 'hebrew "Noto Sans Hebrew")
                (set-fontset-font t 'arabic "Noto Sans Arabic")
                (set-fontset-font t 'syriac "Noto Sans Syriac")
                (set-fontset-font t 'thaana "Noto Sans Thaana")
                (set-fontset-font t 'nko "Noto Sans N'Ko")
                (set-fontset-font t 'samaritan "Noto Sans Samaritan")
                (set-fontset-font t 'mandaic "Noto Sans Mandaic")
                (set-fontset-font t 'devanagari "Noto Sans Devanagari")
                (set-fontset-font t 'bengali "Noto Sans Bengali")
                (set-fontset-font t 'gurmukhi "Noto Sans Gurmukhi")
                (set-fontset-font t 'gujarati "Noto Sans Gujanrati")
                (set-fontset-font t 'oriya "Noto Sans Oriya")
                (set-fontset-font t 'tamil "Noto Sans Tamil")
                (set-fontset-font t 'tamil "Noto Sans Tamil Supplement" nil 'append)
                (set-fontset-font t 'telugu "Noto Sans Telugu")
                (set-fontset-font t 'kannada "Noto Sans Kannada")
                (set-fontset-font t 'malayalam "Noto Sans Malayalam")
                (set-fontset-font t 'sinhala "Noto Sans Sinhala")
                (set-fontset-font t 'thai "Noto Sans Thai")
                (set-fontset-font t 'lao "Noto Sans Lao")
                (set-fontset-font t 'tibetan "Noto Sans Tibetan")
                (set-fontset-font t 'burmese "Noto Sans Myanmar")
                (set-fontset-font t 'georgian "Noto Sans Georgian")
                (set-fontset-font t 'hangul "Noto Sans CJK KR")
                (set-fontset-font t 'ethiopic "Noto Sans Ethiopic")
                (set-fontset-font t 'cherokee "Noto Sans Cherokee")
                (set-fontset-font t 'canadian-aboriginal "Noto Sans Canadian Aboriginal")
                (set-fontset-font t 'ogham "Noto Sans Ogham")
                (set-fontset-font t 'runic "Noto Sans Runic")
                (set-fontset-font t 'tagalog "Noto Sans Tagalog")
                (set-fontset-font t 'hanunoo "Noto Sans Hanunoo")
                (set-fontset-font t 'buhid "Noto Sans Buhid")
                (set-fontset-font t 'tagbanwa "Noto Sans Tagbanwa")
                (set-fontset-font t 'khmer "Noto Sans Khmer")
                (set-fontset-font t 'mongolian "Noto Sans Mongolian")
                (set-fontset-font t 'limbu "Noto Sans Limbu")
                (set-fontset-font t 'tai-le "Noto Sans Tai Le")
                (set-fontset-font t 'tai-lue "Noto Sans NewTaiLue")
                (set-fontset-font t 'buginese "Noto Sans Buginese")
                (set-fontset-font t 'tai-tham "Noto Sans Tai Tham")
                (set-fontset-font t 'balinese "Noto Sans Balinese")
                (set-fontset-font t 'sundanese "Noto Sans Sundanese")
                (set-fontset-font t 'vedic "Noto Sans Devanagari")
                (set-fontset-font t 'symbol "Noto Color Emoji")
                (set-fontset-font t 'symbol "Noto Sans CJK JP" nil 'append)
                (set-fontset-font t 'symbol "Noto Sans Symbols2" nil 'append)
                (set-fontset-font t 'symbol "Noto Sans" nil 'append)
                (set-fontset-font t 'symbol "Noto Sans Math" nil 'append)
                (set-fontset-font t 'symbol "Noto Sans Symbols" nil 'append)
                (set-fontset-font t 'braille "Noto Sans Symbols2")
                (set-fontset-font t 'batak "Noto Sans Batak")
                (set-fontset-font t 'lepcha "Noto Sans Lepcha")
                (set-fontset-font t 'ol-chiki "Noto Sans Ol Chiki")
                (set-fontset-font t 'glagolitic "Noto Sans Glagolitic")
                (set-fontset-font t 'tifinagh "Noto Sans Tifinagh")
                (set-fontset-font t 'han "Noto Sans CJK JP")
                (set-fontset-font t 'ideographic-description "Noto Sans CJK JP")
                (set-fontset-font t 'cjk-misc "Noto Sans CJK JP")
                (set-fontset-font t 'kana "Noto Sans CJK JP")
                (set-fontset-font t 'bopomofo "Noto Sans CJK TC")
                (set-fontset-font t 'kanbun "Noto Sans CJK JP")
                (set-fontset-font t 'yi "Noto Sans Yi")
                (set-fontset-font t 'lisu "Noto Sans Lisu")
                (set-fontset-font t 'vai "Noto Sans Vai")
                (set-fontset-font t 'bamum "Noto Sans Bamum")
                (set-fontset-font t 'syloti-nagri "Noto Sans Syloti Nagri")
                (set-fontset-font t 'north-indic-number "Noto Sans Devanagari")
                (set-fontset-font t 'phags-pa "Noto Sans Phags Pa")
                (set-fontset-font t 'saurashtra "Noto Sans Saurashtra")
                (set-fontset-font t 'kayah-li "Noto Sans Kayah Li")
                (set-fontset-font t 'rejang "Noto Sans Rejang")
                (set-fontset-font t 'javanese "Noto Sans Javanese")
                (set-fontset-font t 'cham "Noto Sans Cham")
                (set-fontset-font t 'tai-viet "Noto Sans Tai Viet")
                (set-fontset-font t 'meetei-mayek "Noto Sans Meetei Mayek")
                (set-fontset-font t 'vertical-form "Noto Sans CJK JP")
                (set-fontset-font t '(#xfe50 . #xfe6b) "Noto Sans CJK JP")
                (set-fontset-font t '(#xfff9 . #xfffb) "Noto Sans Symbols2")
                (set-fontset-font t 'linear-b "Noto Sans Linear B")
                (set-fontset-font t 'aegean-number "Noto Sans Linear B")
                (set-fontset-font t 'ancient-greek-number "Noto Sans Symbols2")
                (set-fontset-font t 'ancient-symbol "Noto Sans Symbols2")
                (set-fontset-font t 'phaistos-disc "Noto Sans Symbols2")
                (set-fontset-font t 'lycian "Noto Sans Lycian")
                (set-fontset-font t 'carian "Noto Sans Carian")
                (set-fontset-font t 'old-italic "Noto Sans Old Italic")
                (set-fontset-font t 'gothic "Noto Sans Gothic")
                (set-fontset-font t 'old-permic "Noto Sans Old Permic")
                (set-fontset-font t 'ugaritic "Noto Sans Ugaritic")
                (set-fontset-font t 'old-persian "Noto Sans OldPersian")
                (set-fontset-font t 'deseret "Noto Sans Deseret")
                (set-fontset-font t 'shavian "Noto Sans Shavian")
                (set-fontset-font t 'osmanya "Noto Sans Osmanya")
                (set-fontset-font t 'osage "Noto Sans Osage")
                (set-fontset-font t 'elbasan "Noto Sans Elbasan")
                (set-fontset-font t 'caucasian-albanian "Noto Sans CaucAlban")
                (set-fontset-font t 'linear-a "Noto Sans Linear A")
                (set-fontset-font t 'cypriot-syllabary "Noto Sans Cypriot")
                (set-fontset-font t 'aramaic "Noto Sans ImpAramaic")
                (set-fontset-font t 'palmyrene "Noto Sans Palmyrene")
                (set-fontset-font t 'nabataean "Noto Sans Nabataean")
                (set-fontset-font t 'hatran "Noto Sans Hatran")
                (set-fontset-font t 'phoenician "Noto Sans Phoenician")
                (set-fontset-font t 'lydian "Noto Sans Lydian")
                (set-fontset-font t 'meroitic "Noto Sans Meroitic")
                (set-fontset-font t 'kharoshthi "Noto Sans Kharoshthi")
                (set-fontset-font t 'old-south-arabian "Noto Sans OldSouArab")
                (set-fontset-font t 'old-north-arabian "Noto Sans OldNorArab")
                (set-fontset-font t 'manichaean "Noto Sans Manichaean")
                (set-fontset-font t 'avestan "Noto Sans Avestan")
                (set-fontset-font t 'inscriptional-parthian "Noto Sans Inscriptional Parthian")
                (set-fontset-font t 'inscriptional-pahlavi "Noto Sans Inscriptional Pahlavi")
                (set-fontset-font t 'psalter-pahlavi "Noto Sans PsaPahlavi")
                (set-fontset-font t 'old-turkic "Noto Sans Old Turkic")
                (set-fontset-font t 'old-hungarian "Noto Sans OldHung")
                (set-fontset-font t 'hanifi-rohingya "Noto Sans HanifiRohg")
                (set-fontset-font t 'rumi-number "Noto Sans Symbols2")
                (set-fontset-font t 'old-sogdian "Noto Sans OldSogdian")
                (set-fontset-font t 'sogdian "Noto Sans Sogdian")
                (set-fontset-font t 'elymaic "Noto Sans Elymaic")
                (set-fontset-font t 'brahmi "Noto Sans Brahmi")
                (set-fontset-font t 'kaithi "Noto Sans Kaithi")
                (set-fontset-font t 'sora-sompeng "Noto Sans SoraSomp")
                (set-fontset-font t 'chakma "Noto Sans Chakma")
                (set-fontset-font t 'mahajani "Noto Sans Mahajani")
                (set-fontset-font t 'sharada "Noto Sans Sharada")
                (set-fontset-font t 'sinhala-archaic-number "Noto Sans Sinhala")
                (set-fontset-font t 'khojki "Noto Sans Khojki")
                (set-fontset-font t 'multani "Noto Sans Multani")
                (set-fontset-font t 'khudawadi "Noto Sans Khudawadi")
                (set-fontset-font t 'grantha "Noto Sans Grantha")
                (set-fontset-font t 'newa "Noto Sans Newa")
                (set-fontset-font t 'tirhuta "Noto Sans Tirhuta")
                (set-fontset-font t 'siddham "Noto Sans Siddham")
                (set-fontset-font t 'modi "Noto Sans Modi")
                (set-fontset-font t 'takri "Noto Sans Takri")
                (set-fontset-font t 'ahom "Noto Serif Ahom")
                (set-fontset-font t 'dogra "Noto Serif Dogra")
                (set-fontset-font t 'warang-citi "Noto Sans WarangCiti")
                (set-fontset-font t 'zanabazar-square "Noto Sans Zanabazar")
                (set-fontset-font t 'soyombo "Noto Sans Soyombo")
                (set-fontset-font t 'pau-cin-hau "Noto Sans PauCinHau")
                (set-fontset-font t 'bhaiksuki "Noto Sans Bhaiksuki")
                (set-fontset-font t 'marchen "Noto Sans Marchen")
                (set-fontset-font t 'masaram-gondi "Noto Sans Masaram Gondi")
                (set-fontset-font t 'gunjala-gondi "Noto Sans Gunjala Gondi")
                (set-fontset-font t 'cuneiform "Noto Sans Cuneiform")
                (set-fontset-font t 'cuneiform-numbers-and-punctuation "Noto Sans Cuneiform")
                (set-fontset-font t 'egyptian "Noto Sans EgyptHiero")
                (set-fontset-font t 'anatolian "Noto Sans AnatoHiero")
                (set-fontset-font t 'mro "Noto Sans Mro")
                (set-fontset-font t 'bassa-vah "Noto Sans Bassa Vah")
                (set-fontset-font t 'pahawh-hmong "Noto Sans Pahawh Hmong")
                (set-fontset-font t 'miao "Noto Sans Miao")
                (set-fontset-font t 'tangut "Noto Serif Tangut")
                (set-fontset-font t 'tangut-components "Noto Serif Tangut")
                (set-fontset-font t '(#x16fe0 . #x16fe0) "Noto Serif Tangut")
                (set-fontset-font t 'duployan-shorthand "Noto Sans Duployan")
                (set-fontset-font t 'byzantine-musical-symbol "Noto Music")
                (set-fontset-font t 'musical-symbol "Noto Music")
                (set-fontset-font t 'ancient-greek-musical-notation "Noto Music")
                (set-fontset-font t 'mayan-numeral "Noto Sans Mayan Numerals")
                (set-fontset-font t 'tai-xuan-jing-symbol "Noto Sans Symbols2")
                (set-fontset-font t 'counting-rod-numeral "Noto Sans Symbols2")
                (set-fontset-font t 'mathematical "Noto Sans Math")
                (set-fontset-font t 'wancho "Noto Sans Wancho")
                (set-fontset-font t 'mende-kikakui "Noto Sans Mende Kikakui")
                (set-fontset-font t 'adlam "Noto Sans Adlam")
                (set-fontset-font t 'indic-siyaq-number "Noto Sans Indic Siyaq Numbers")
                (set-fontset-font t '(#x1ee00 . #x1eeff) "Noto Sans Math")
                (set-fontset-font t 'mahjong-tile "Noto Sans Symbols2")
                (set-fontset-font t 'domino-tile "Noto Sans Symbols2")
                (set-fontset-font t 'playing-cards "Noto Sans Symbols2")

                (set-fontset-font t 'kana "UniHentaiKana" nil 'append)
                (set-fontset-font t 'latin "HackGenNerd" nil 'append)
                (set-fontset-font t 'symbol "HackGenNerd" nil 'append)

                ;; Nerd Font (defined thru -#xfd46)
                (set-fontset-font t '( #xe000 .  #xf136) "Inconsolata Nerd Font"))))

font-lock-studio

(autoload-if-found '(font-lock-studio) "font-lock-studio" nil t)

Color

ansi-color

(autoload-if-found '(ansi-color-for-comint-mode-on) "ansi-color" nil t)

(with-eval-after-load 'shell-mode
  (add-hook 'shell-mode-hook #'ansi-color-for-comint-mode-on))

(with-eval-after-load 'compile
  (add-hook 'compilation-filter-hook
            #'(lambda ()
                (ansi-color-apply-on-region (point-min) (point-max)))))

highlight-indent-guides

(autoload-if-found '(highlight-indent-guides-mode) "highlight-indent-guides" nil t)


hl-todo

(autoload-if-found '(global-hl-todo-mode) "hl-todo" nil t)

(add-hook 'after-init-hook #'global-hl-todo-mode)

(with-eval-after-load 'hl-todo
  (setopt hl-todo-keyword-faces
          '(("HOLD" . "#d0bf8f")
            ("TODO" . "#cc9393")
            ("NOW" . "#dca3a3")
            ("SOMEDAY" . "#dc8cc3")
            ("WAIT" . "#7cb8bb")
            ("REVIEW" . "e60a39")
            ("QA" . "#88CF88")
            ("DONE" . "#afd8af")
            ("FIXME" . "#cc9393")
            ("MEMO" . "#coffee"))))

xterm-color

(autoload-if-found '(xterm-color-filter) "xterm-color" nil t)

(add-hook 'after-init-hook
          #'(lambda () (setenv "TERM" "xterm-256color")))

(with-eval-after-load 'xterm-color
  (setopt xterm-color-preserve-properties t))

Icon

emojify

(autoload-if-found '(global-emojify-mode) "emojify" nil t)

nerd-icons-dired

(autoload-if-found '(nerd-icons-dired-mode) "nerd-icons-dired" nil t)

(with-eval-after-load 'dired-mode
  (add-hook 'dired-mode-hook #'nerd-icons-dired-mode))

nerd-icons-completion

(autoload-if-found '(nerd-icons-completion-marginalia-setup) "nerd-icons-completion" nil t)

(with-eval-after-load 'marginalia
  (add-hook 'marginalia-mode-hook #'nerd-icons-completion-marginalia-setup))

Dashboard

(autoload-if-found '(dashboard-refresh-buffer) "dashboard" nil t)

(with-eval-after-load 'dashboard
  (setopt dashboard-startup-banner 'logo)
  (setopt dashboard-set-file-icons t)
  (setopt dashboard-startup-banner 4)
  (setopt dashboard-items '((recents . 10))))

Dimmer

(autoload-if-found '(dimmer-mode) "dimmer" nil t)

(add-hook 'after-init-hook #'dimmer-mode)

(with-eval-after-load 'dimmer
  (setopt dimmer-fraction 0.05))

Warm Mode

(autoload-if-found '(warm-mode) "warm-mode" nil t)

Doom

doom-themes

(add-hook 'after-init-hook
          #'(lambda ()
              (when (require 'doom-themes)
                (let ((theme 'doom-dracula))
                  (load-theme theme t)
                  ;; workaround a mutual face-inheritance cycle between gnus-group-news-low(-empty) in doom-themes;
                  ;; must fix here since gnus-group.el loads lazily and would error before any hook could run
                  (custom-theme-set-faces
                   theme '(gnus-group-news-low-empty ((t :inherit nil))))
                  (enable-theme theme)
                  (set-cursor-color "#f8f8f2")))))

(with-eval-after-load 'doom-themes
  (setopt doom-themes-padded-modeline t)
  (setopt doom-themes-enable-bold t)
  (setopt doom-themes-enable-italic t))

doom-modeline

(autoload-if-found '(doom-modeline-mode) "doom-modeline" nil t)

(add-hook 'after-init-hook #'doom-modeline-mode)
(add-hook 'after-init-hook #'(lambda () (line-number-mode 0)))
(add-hook 'after-init-hook #'(lambda () (column-number-mode 0)))

(with-eval-after-load 'doom-modeline
  (setopt doom-modeline-buffer-file-name-style 'truncate-with-project)
  (setopt doom-modeline-icon t)
  (setopt doom-modeline-major-mode-icon t)
  (setopt doom-modeline-minor-modes nil)
  (setopt doom-modeline-check-icon nil)
  ;; doom-modeline-def-segment is a macro; with-eval-after-load doesn't defer compile-time macroexpansion
  (eval-when-compile (require 'doom-modeline))
  (doom-modeline-def-segment my/nskk
    "NSKK input mode indicator."
    (when (and (bound-and-true-p nskk-mode)
               (fboundp 'nskk-modeline-indicator))
      (nskk-modeline-indicator)))
  (let ((main-segments
         (append '(compilation objed-state misc-info project-name persp-name battery grip irc)
                 (when (not (eq system-type 'darwin))
                   '(mu4e))
                 (when (not (eq system-type 'darwin))
                   '(gnus))
                 '(github debug repl lsp my/nskk minor-modes input-method indent-info buffer-encoding major-mode process vcs check time))))
    (doom-modeline-def-modeline 'main
      '(eldoc bar window-state workspace-name window-number modals matches follow buffer-info remote-host buffer-position word-count parrot selection-info)
      main-segments))
  ;; emacsclient -c でGUIフレームが生成されたとき modeline を再描画する
  (add-hook 'after-make-frame-functions
            #'(lambda (frame)
                (when (display-graphic-p frame)
                  (doom-modeline-refresh-bars)))))

hl-line

(autoload-if-found '(global-hl-line-mode) "hl-line-mode" nil t)

(add-hook 'after-init-hook
          #'(lambda ()
              (when (not window-system)
                (global-hl-line-mode))))

(with-eval-after-load 'hl-line
  (set-face-attribute 'hl-line nil :inherit nil)
  (set-face-background 'hl-line "#444642"))

idle-highlight-mode

(autoload-if-found '(idle-highlight-mode) "idle-highlight-mode" nil t)

(with-eval-after-load 'idle-highlight-mode
  (setopt idle-highlight-idle-time 0.1))

(with-eval-after-load 'prog-mode
  (add-hook 'prog-mode-hook #'idle-highlight-mode))

neotree

(autoload-if-found '(neotree-hide neotree-dir neotree-make-executor neo-open-file neo-open-dir) "neotree" nil t)

(defun my/neotree-toggle ()
  (interactive)
  (let ((default-directory (or (locate-dominating-file default-directory ".neotree")
                               (locate-dominating-file default-directory ".git")
                               default-directory)))
    (if (and (fboundp 'neo-global--window-exists-p)
             (neo-global--window-exists-p))
        (neotree-hide)
      (neotree-dir default-directory))))

(keymap-global-set "C-q" #'my/neotree-toggle)

(with-eval-after-load 'neotree
  (setopt neo-theme 'ascii)
  (setopt neo-show-hidden-files t)
  (setopt neo-window-position 'right)
  (setopt neo-window-width 50)

  (define-key neotree-mode-map (kbd "C-j")
              (neotree-make-executor
               :file-fn #'neo-open-file
               :dir-fn  #'neo-open-dir)))

nyan-mode

(autoload-if-found '(nyan-mode) "nyan-mode" nil t)

(add-hook 'after-init-hook #'nyan-mode)

(with-eval-after-load 'nyan-mode
  (setopt nyan-cat-face-number 5)
  (setopt nyan-animate-nyancat t))

volatile-highlights

(autoload-if-found '(volatile-highlights-mode) "volatile-highlights" nil t)

(add-hook 'after-init-hook #'volatile-highlights-mode)

topsy

(autoload-if-found '(topsy-mode) "topsy" nil t)

(with-eval-after-load 'yaml-mode
  (add-hook 'yaml-mode-hook #'topsy-mode))

idle-highlight-mode

(autoload-if-found '(idle-highlight-mode) "idle-highlight-mode" nil t)

(with-eval-after-load 'prog-mode
  (add-hook 'prog-mode-hook #'idle-highlight-mode))

(with-eval-after-load 'idle-highlight-mode
  (setopt idle-highlight-idle-time 0.1))

modus-themes

(autoload-if-found '() "modus-themes" nil t)

Awesome Package

Joke

hacker-typer

(autoload-if-found '(hacker-typer) "hacker-typer" nil t)

power-mode

(autoload-if-found '(power-mode) "power-mode" nil t)

sudden-death

(autoload-if-found '(sudden-death) "sudden-death" nil t)

arto

(autoload-if-found '(arto-open arto-version) "arto" nil t)

(with-eval-after-load 'arto
  (setopt arto-path "/Applications/Arto.app"))

redacted

(autoload-if-found '(redacted-mode) "redacted" nil t)

(defun my/redacted-mode ()
  (interactive)
  (read-only-mode (if redacted-mode -1 1))
  (redacted-mode (if redacted-mode -1 1)))

lorem ipsum

(autoload-if-found '(lorem-ipsum-insert-sentences
                     lorem-ipsum-insert-paragraphs
                     lorem-ipsum-insert-list) "lorem-ipsum" nil t)

(keymap-global-set "C-c C-l s" #'lorem-ipsum-insert-sentences)
(keymap-global-set "C-c C-l p" #'lorem-ipsum-insert-paragraphs)
(keymap-global-set "C-c C-l l" #'lorem-ipsum-insert-list)

zalgo-mode

(autoload-if-found '(zalgo-transform-word
                     zalgo-mode
                     zalgo-transform-region) "zalgo-mode" nil t)

Password

pass

(autoload-if-found '(pass pass-view-mode) "pass" nil t)

(add-to-list 'auto-mode-alist (cons (concat (regexp-quote (my/ghq-repo-path "github.com/takeokunn-private/private-pass")) "/current/.*\\.gpg") 'pass-view-mode))

(with-eval-after-load 'pass
  (setopt pass-suppress-confirmations t))

password-generator

(autoload-if-found '(password-generator-simple
                     password-generator-strong
                     password-generator-paranoid
                     password-generator-numeric
                     password-generator-phonetic
                     password-generator-custom) "password-generator" nil t)

sops

(autoload-if-found '(sops-save-file
                     sops-cancel
                     sops-edit-file
                     global-sops-mode) "sops" nil t)

(add-hook 'after-init-hook #'global-sops-mode)

Dictionary

define-word

(defun my/define-word ()
  (interactive)
  (if (use-region-p)
      (call-interactively #'define-word-at-point)
    (call-interactively #'define-word)))

(with-eval-after-load 'define-word
  (setopt define-word-displayfn-alist
          '((wordnik . takeokunn/define-word--display-in-buffer)
            (openthesaurus . takeokunn/define-word--display-in-buffer)
            (webster . takeokunn/define-word--display-in-buffer)
            (weblio . takeokunn/define-word--display-in-buffer))))

GC

gcmh

(autoload-if-found '(gcmh-mode) "gcmh" nil t)

(add-hook 'after-init-hook #'gcmh-mode)

(with-eval-after-load 'gcmh
  (setopt gcmh-verbose nil)

  (defvar my/gcmh-status nil)
  (advice-add #'garbage-collect
              :before
              (defun my/gcmh-log-start (&rest _)
                (when gcmh-verbose
                  (setopt my/gcmh-status "Running GC..."))))

  (advice-add #'gcmh-message
              :override
              (defun my/gcmh-message (format-string &rest args)
                (setopt my/gcmh-status
                      (apply #'format-message format-string args))
                (run-with-timer 2 nil
                                (lambda ()
                                  (setopt my/gcmh-status nil))))))

GPG

epa-file

(autoload-if-found '(epa-file-enable) "epa-file" nil t)

(add-hook 'after-init-hook #'epa-file-enable)

(fset 'epg-wait-for-status 'ignore)

(with-eval-after-load 'epa-hook
  (setopt epa-file-encrypt-to '("bararararatty@gmail.com")))

(with-eval-after-load 'epa-file
  (setopt epa-file-select-keys 'silent)
  (setopt epa-file-cache-passphrase-for-symmetric-encryption t))

(with-eval-after-load 'epg-config
  (setopt epg-pinentry-mode 'loopback))

pinentry

https://github.com/ch11ng/exwm/wiki#gpg-pinentry

(autoload-if-found '(pinentry-start) "pinentry" nil t)

Help

helpful

(autoload-if-found '(helpful-callable
                     helpful-function
                     helpful-macro
                     helpful-command
                     helpful-key
                     helpful-variable
                     helpful-at-point) "helpful" nil t)

(keymap-global-set "C-h f" #'helpful-callable)
(keymap-global-set "C-h v" #'helpful-variable)
(keymap-global-set "C-h k" #'helpful-key)
(keymap-global-set "C-c C-d" #'helpful-at-point)
(keymap-global-set "C-h F" #'helpful-function)
(keymap-global-set "C-h C" #'helpful-command)

Shell

exec-path-from-shell

(autoload-if-found '(exec-path-from-shell-initialize) "exec-path-from-shell")

;; Configure variables BEFORE initialization
(setopt exec-path-from-shell-arguments '("-l"))
(setopt exec-path-from-shell-variables '("PATH" "TERM" "COPILOT_LANGUAGE_SERVER_PATH"))

(exec-path-from-shell-initialize)

;; Explicitly set SSH_AUTH_SOCK for GPG agent (exec-path-from-shell doesn't handle this correctly on macOS)
(setenv "SSH_AUTH_SOCK" (expand-file-name "~/.gnupg/S.gpg-agent.ssh"))

Utility

htmlize

(with-eval-after-load 'htmlize
  (setopt htmlize-html-charset 'utf-8))

midnight

(autoload-if-found '(midnight-mode) "midnight" nil t)

(add-hook 'after-init-hook #'midnight-mode)

(with-eval-after-load 'midnight
  (setopt clean-buffer-list-delay-general 1))

lte

(autoload-if-found '(lte-truncate-table-mode) "lte" nil t)

(with-eval-after-load 'markdown-mode
  (add-hook 'markdown-mode-hook #'lte-truncate-table-mode))

(with-eval-after-load 'org
  (add-hook 'org-mode-hook #'lte-truncate-table-mode))

Mouse

inhibit-mouse

(autoload-if-found '(inhibit-mouse-mode) "inhibit-mouse" nil t)

(add-hook 'after-init-hook #'inhibit-mouse-mode)

PDF

pdf-tools

(autoload-if-found '(pdf-tools-install) "pdf-tools" nil t)
(autoload-if-found '(pdf-occur-global-minor-mode) "pdf-occur" nil t)

(add-hook 'after-init-hook
          (lambda ()
            (condition-case err
                (pdf-tools-install t)
              (error (message "pdf-tools-install failed: %s" (error-message-string err))))))

Jump

dumb-jump

(autoload-if-found '(dumb-jump-mode
                     dumb-jump-xref-activate
                     dumb-jump-go
                     dumb-jump-back) "dumb-jump" nil t)

(add-hook 'after-init-hook #'dumb-jump-mode)

(with-eval-after-load 'xref
  (add-hook 'xref-backend-functions #'dumb-jump-xref-activate))

(with-eval-after-load 'dumb-jump
  (setopt dumb-jump-force-searcher 'rg)
  (setopt dumb-jump-prefer-searcher 'rg)
  (setopt dumb-jump-default-project "")
  (setopt dumb-jump-disable-obsolete-warnings t))

Language Specific

Basic Lisp

paredit

(autoload-if-found '(enable-paredit-mode
                     paredit-forward-slurp-sexp
                     paredit-splice-sexp
                     paredit-define-keys)
                   "paredit" nil t)

(keymap-global-set "C-c f" #'paredit-forward-slurp-sexp)
(keymap-global-set "M-s" #'paredit-splice-sexp)

(with-eval-after-load 'paredit
  (add-hook 'paredit-mode-hook #'paredit-define-keys))

(with-eval-after-load 'lisp-mode
  (add-hook 'lisp-mode-hook #'enable-paredit-mode)
  (add-hook 'lisp-data-mode-hook #'enable-paredit-mode))

(with-eval-after-load 'emacs-lisp-mode
  (add-hook 'emacs-lisp-mode-hook #'enable-paredit-mode))

(with-eval-after-load 'clojure-mode
  (add-hook 'clojure-mode-hook #'enable-paredit-mode))

(with-eval-after-load 'lisp-interaction-mode
  (add-hook 'lisp-interacton-mode-hook #'enable-paredit-mode))

(with-eval-after-load 'scheme
  (add-hook 'scheme-mode-hook #'enable-paredit-mode))

(with-eval-after-load 'simple
  (add-hook 'eval-expression-minibuffer-setup-hook #'enable-paredit-mode))

(with-eval-after-load 'ielm
  (add-hook 'inferior-emacs-lisp-mode-hook #'enable-paredit-mode))

rainbow-delimiter

(autoload-if-found '(rainbow-delimiters-mode-enable) "rainbow-delimiters" nil t)

(with-eval-after-load 'lisp-mode
  (add-hook 'lisp-mode-hook #'rainbow-delimiters-mode-enable))

(with-eval-after-load 'emacs-lisp-mode
  (add-hook 'emacs-lisp-mode-hook #'rainbow-delimiters-mode-enable))

(with-eval-after-load 'clojure-mode
  (add-hook 'clojure-mode-hook #'rainbow-delimiters-mode-enable))

(with-eval-after-load 'scheme
  (add-hook 'scheme-mode-hook #'rainbow-delimiters-mode-enable))

Common Lisp

sly

(require 'sly-autoloads)

(with-eval-after-load 'sly
  (setopt inferior-lisp-program "sbcl")
  (setopt sly-command-switch-to-existing-lisp 'always))

(with-eval-after-load 'lisp-mode
  (add-hook 'lisp-data-mode-hook #'(lambda () (view-mode -1))))

hyperspec

(autoload-if-found '(hyperspec-lookup) "hyperspec" nil t)

(with-eval-after-load 'lisp-mode
  (define-key lisp-mode-map (kbd "C-c h") #'hyperspec-lookup))

Emacs Lisp

eros

(autoload-if-found '(eros-mode) "eros" nil t)

(with-eval-after-load 'emacs-lisp
  (add-hook 'emacs-lisp-mode-hook #'eros-mode))

eldoc

(autoload-if-found '(turn-on-eldoc-mode) "eldoc" nil t)

(with-eval-after-load 'elisp-mode
  (add-hook 'emacs-lisp-mode-hook #'turn-on-eldoc-mode)
  (add-hook 'lisp-interaction-mode-hook #'turn-on-eldoc-mode))

(with-eval-after-load 'ielm
  (add-hook 'ielm-mode-hook #'turn-on-eldoc-mode))

elsa

(autoload-if-found '(elsa-run) "elsa" nil t)

lispxmp

(autoload-if-found '(lispxmp) "lispxmp" nil t)

macrostep

(autoload-if-found '(macrostep-expand macrostep-mode) "macrostep" nil t)

(with-eval-after-load 'elisp-mode
  (define-key emacs-lisp-mode-map (kbd "C-c e") #'macrostep-expand))

elisp-slime-nav

(autoload-if-found '(elisp-slime-nav-mode) "elisp-slime-nav" nil t)

(with-eval-after-load 'elisp-mode
  (add-hook 'emacs-lisp-mode-hook #'elisp-slime-nav-mode))

(with-eval-after-load 'ielm
  (add-hook 'ielm-mode-hook #'elisp-slime-nav-mode))

nameless

(autoload-if-found '(nameless-mode) "nameless" nil t)

(with-eval-after-load 'elisp-mode
  (add-hook 'emacs-lisp-mode-hook #'nameless-mode))

(with-eval-after-load 'ielm
  (add-hook 'ielm-mode-hook #'nameless-mode))

elisp-refs

(autoload-if-found '(elisp-refs-function
                     elisp-refs-macro
                     elisp-refs-variable
                     elisp-refs-special
                     elisp-refs-symbol) "elisp-refs" nil t)

highlight-quoted

(autoload-if-found '(highlight-quoted-mode) "highlight-quoted" nil t)

(with-eval-after-load 'elisp-mode
  (add-hook 'emacs-lisp-mode-hook #'highlight-quoted-mode))

highlight-defined

(autoload-if-found '(highlight-defined-mode) "highlight-defined" nil t)

(with-eval-after-load 'elisp-mode
  (add-hook 'emacs-lisp-mode-hook #'highlight-defined-mode))

my/ielm-history

(defun my/ielm-history ()
  (interactive)
  (insert
   (completing-read
    "choice history: "
    (progn
      (let ((history nil)
            (comint-input-ring nil))
        (dotimes (index (ring-length comint-input-ring))
          (push (ring-ref comint-input-ring index) history))
        history)))))

Clojure

anakondo

(autoload-if-found '(anakondo-minor-mode) "anakondo" nil t)

cider

(autoload-if-found '(cider cider-format-buffer cider-switch-to-last-clojure-buffer) "cider" nil t)
(autoload-if-found '(cider-doc) "cider-doc" nil t)


(with-eval-after-load 'cider-common
  (setopt cider-special-mode-truncate-lines nil))

(with-eval-after-load 'cider-mode
  (setopt cider-font-lock-reader-conditionals nil)
  (setopt cider-font-lock-dynamically '(macro core function var)))

(with-eval-after-load 'cider-repl
  (setopt cider-repl-buffer-size-limit 1000000)
  (setopt cider-repl-wrap-history t)
  (setopt cider-repl-history-size 10000)
  (setopt cider-repl-tab-command #'indent-for-tab-command)
  (setopt cider-repl-display-in-current-window t))

(with-eval-after-load 'nrepl-client
  (setopt nrepl-use-ssh-fallback-for-remote-hosts t)
  (setopt nrepl-hide-special-buffers t))

(with-eval-after-load 'cider-eval
  (setopt cider-show-error-buffer nil)
  (setopt cider-auto-select-error-buffer nil))

(with-eval-after-load 'clojure-mode
  (define-key clojure-mode-map (kbd "C-c h") #'cider-doc))

kibit-helper

(autoload-if-found '(kibit kibit-current-file kibit-accept-proposed-change) "kibit-helper" nil t)

clj-refactor


inf-clojure

(autoload-if-found '(inf-clojure) "inf-clojure" nil t)

C/C++

clang-format

(autoload-if-found '(clang-format-buffer) "clang-format" nil t)

Csv

rainbow-csv

(autoload-if-found '(rainbow-csv-mode) "rainbow-csv" nil t)

(with-eval-after-load 'csv-mode
  (add-hook 'csv-mode-hook #'rainbow-csv-mode))

JavaScript/TypeScript

nodejs-repl

(autoload-if-found '(nodejs-repl
                     nodejs-repl-send-last-expression
                     nodejs-repl-send-line
                     nodejs-repl-send-region
                     nodejs-repl-send-buffer
                     nodejs-repl-load-file
                     nodejs-repl-switch-to-repl) "nodejs-repl" nil t)

(with-eval-after-load 'js2-mode
  (define-key js2-mode-map (kbd "C-x C-e") #'nodejs-repl-send-last-expression)
  (define-key js2-mode-map (kbd "C-c C-j") #'nodejs-repl-send-line)
  (define-key js2-mode-map (kbd "C-c C-r") #'nodejs-repl-send-region)
  (define-key js2-mode-map (kbd "C-c C-c") #'nodejs-repl-send-buffer)
  (define-key js2-mode-map (kbd "C-c C-l") #'nodejs-repl-load-file)
  (define-key js2-mode-map (kbd "C-c C-z") #'nodejs-repl-switch-to-repl))

js2-refactor

(autoload-if-found '(js2-refactor-mode) "js2-refactor" nil t)

(with-eval-after-load 'js2-refactor
  (setopt js2r-use-strict t))

(with-eval-after-load 'js2-mode
  (add-hook 'js2-mode-hook #'js2-refactor-mode))

(with-eval-after-load 'typescript-mode
  (add-hook 'typescript-mode-hook #'js2-refactor-mode))

jest

(autoload-if-found '(jest
                     jest-file
                     jest-file-dwim
                     jest-function
                     jest-last-failed
                     jest-repeat
                     jest-minor-mode) "jest" nil t)

(with-eval-after-load 'typescript-mode
  (add-hook 'typescript-mode-hook #'jest-minor-mode))

Ruby

robe

(autoload-if-found '(robe-mode inf-ruby-console-auto) "robe" nil t)

rubocop

(autoload-if-found '(rubocop-mode) "rubocop" nil t)

(with-eval-after-load 'ruby-mode
  (setopt rubocop-keymap-prefix "C-c C-x")

  (add-hook 'ruby-mode-hook #'rubocop-mode))

ruby-refactor

(autoload-if-found '(ruby-refactor-mode-launch) "ruby-refactor" nil t)

(with-eval-after-load 'ruby-mode
  (add-hook 'ruby-mode-hook #'ruby-refactor-mode-launch))

inf-ruby

(autoload-if-found '(inf-ruby inf-ruby-minor-mode) "inf-ruby" nil t)

(defun my/irb-history ()
  (interactive)
  (when (and (fboundp '-distinct)
             (fboundp 's-lines)
             (fboundp 'f-read-text))
    (insert
     (completing-read
      "choose history: "
      (mapcar #'list (-distinct (s-lines (f-read-text "~/.irb_history"))))))))

(with-eval-after-load 'ruby-mode
  (add-hook 'ruby-mode-hook #'inf-ruby-minor-mode))

yard-mode

(autoload-if-found '(yard-mode) "yard-mode" nil t)

(with-eval-after-load 'ruby-mode
  (add-hook 'ruby-mode-hook #'yard-mode))

SQL

sql-indent

(autoload-if-found '(sqlind-setup sqlind-minor-mode) "sql-indent" nil t)

(with-eval-after-load 'sql
  (add-hook 'sql-mode-hook #'sqlind-setup)
  (add-hook 'sql-mode-hook #'sqlind-minor-mode))

PHP

composer

(autoload-if-found '(composer-get-config
                     composer-get-bin-dir
                     composer-install
                     composer-dump-autoload
                     composer-require
                     composer-update
                     composer-find-json-file
                     composer-view-lock-file
                     composer-run-vendor-bin-command
                     composer-run-script
                     composer-setup-managed-phar
                     composer) "composer" nil t)

php-runtime

(autoload-if-found '(php-runtime-expr php-runtime-eval) "php-runtime" nil t)

psysh

(autoload-if-found '(psysh psysh-doc) "psysh" nil t)

(with-eval-after-load 'php-mode
  (define-key php-mode-map (kbd "C-c h") #'psysh-doc))

laravel-tinker-repl


emacs-php-doc-block

(autoload-if-found '(php-doc-block) "php-doc-block" nil t)

phpstan

(autoload-if-found '(phpstan-analyze-this-file
                     phpstan-analyze-file
                     phpstan-analyze-project
                     phpstan-generate-baseline
                     phpstan-find-baseline-file
                     phpstan-pro
                     phpstan-insert-ignore
                     phpstan-copy-dumped-type
                     phpstan-insert-dumptype) "phpstan" nil t)

(with-eval-after-load 'phpstan
  (setopt phpstan-memory-limit "4G")
  (setopt phpstan-activate-editor-mode t))

phpunit

(autoload-if-found '(phpunit-current-test
                     phpunit-current-class
                     phpunit-current-project
                     phpunit-group) "phpunit" nil t)

(with-eval-after-load 'php-mode
  (keymap-set php-mode-map "C-c ;" #'phpunit-current-test)
  (keymap-set php-mode-map "C-c C-;" #'phpunit-current-test))

Markdown

poly-markdown

(autoload-if-found '(poly-markdown-mode) "poly-markdown" nil t)

doclive

(autoload-if-found '(doclive-preview-buffer
                     doclive-preview-file
                     doclive-stop-server
                     doclive-reload-page) "doclive" nil t)

(with-eval-after-load 'markdown-mode
  (keymap-set markdown-mode-map "C-c M-v" #'doclive-preview-buffer))

(with-eval-after-load 'org
  (keymap-set org-mode-map "C-c M-v" #'doclive-preview-buffer))

Fish

fish-repl

(autoload-if-found '(fish-repl) "fish-repl" nil t)

Web

emmet-mode

(autoload-if-found '(emmet-mode) "emmet-mode" nil t)

(with-eval-after-load 'html-mode
  (add-hook 'html-mode-hook #'emmet-mode))

(with-eval-after-load 'css-mode
  (add-hook 'css-mode-hook #'emmet-mode))

(with-eval-after-load 'nxml-mode
  (add-hook 'nxml-mode-hook #'emmet-mode))

(with-eval-after-load 'web-php-blade-mode
  (add-hook 'web-php-blade-mode #'emmet-mode))

(with-eval-after-load 'emmet-mode
  (define-key emmet-mode-keymap (kbd "C-j") nil)
  (define-key emmet-mode-keymap (kbd "M-j") #'emmet-expand-line)

  (setopt emmet-self-closing-tag-style "")
  (setopt emmet-indent-after-insert nil))

JSON

jq-mode

(autoload-if-found '(jq-interactively) "jq-mode" nil t)

(with-eval-after-load 'json-mode
  (define-key json-mode-map (kbd "C-c C-j") #'jq-interactively))

json-reformat

(autoload-if-found '(json-reformat-region) "json-reformat" nil t)

dasel

(autoload-if-found '(dasel-interactive) "dasel-interactive" nil t)
(autoload-if-found '(dasel-convert) "dasel-convert" nil t)
(autoload-if-found '(dasel-format-buffer dasel-format-region) "dasel-format" nil t)
(autoload-if-found '(dasel-edit-put) "dasel-edit" nil t)

consult-dasel

(autoload-if-found '(consult-dasel) "consult-dasel" nil t)

Python

py-isort

(autoload-if-found '(py-isort-region
                     py-isort-buffer
                     py-isort-before-save) "py-isort" nil t)

Dart

flutter

(autoload-if-found '(flutter-test-mode
                     flutter-run
                     flutter-run-device
                     flutter-run-or-hot-reload
                     flutter-test-all
                     flutter-test-current-file
                     flutter-test-at-point
                     flutter-mode) "flutter" nil t)

(with-eval-after-load 'flutter
  (add-hook 'flutter-mode-hook
            #'(lambda ()
                (push '("*Flutter*") popwin:special-display-config)
                (flutter--initialize))))

(defun my/flutter-switch-buffer ()
  (interactive)
  (when (get-buffer "*Flutter*")
    (pop-to-buffer "*Flutter*")))

(with-eval-after-load 'dart-mode
  (define-key dart-mode-map (kbd "C-c z") #'my/flutter-switch-buffer))

Go

gotest

(autoload-if-found '(go-test-current-file
                     go-test-current-test
                     go-test-current-project
                     go-test-current-benchmark
                     go-run) "gotest" nil t)

(with-eval-after-load 'go-mode
  (keymap-set go-mode-map "C-x ! f" #'go-test-current-file)
  (keymap-set go-mode-map "C-x ! t" #'go-test-current-test)
  (keymap-set go-mode-map "C-x ! p" #'go-test-current-project)
  (keymap-set go-mode-map "C-x ! b" #'go-test-current-benchmark)
  (keymap-set go-mode-map "C-x ! x" #'go-run))

Terminal

kuro

(autoload-if-found '(kuro-create kuro-list-sessions kuro-attach kuro-kill) "kuro" nil t)

(keymap-global-set "C-c t" #'kuro-create)
(keymap-global-set "C-c T" #'kuro-list-sessions)

Eshell

basic

(with-eval-after-load 'esh-mode
  (define-key eshell-mode-map (kbd "C-h") #'delete-backward-char)
  (define-key eshell-mode-map (kbd "M-p") #'eshell-previous-matching-input-from-input))

(with-eval-after-load 'em-cmpl
  (setopt eshell-cmpl-ignore-case t))

(with-eval-after-load 'em-glob
  (setopt eshell-glob-include-dot-files t)
  (setopt eshell-glob-include-dot-dot nil)
  (setopt eshell-glob-show-progress t))

(with-eval-after-load 'em-hist
  (setopt eshell-history-size 100000)
  (setopt eshell-hist-ignoredups t))

(with-eval-after-load 'em-alias
  (setopt eshell-command-aliases-list '(("ll" "ls -la"))))

(with-eval-after-load 'esh-cmd
  (setopt eshell-prefer-lisp-functions nil))

(with-eval-after-load 'em-term
  (setopt eshell-destroy-buffer-when-process-dies t))

functions

(defun eshell/ff (&rest args)
  "Open a file in Emacs with ARGS, Some habits die hard."
  (if (null args)
      (bury-buffer)
    (mapc #'find-file (mapcar #'expand-file-name (eshell-flatten-list (reverse args))))))

(defun eshell/unpack (file &rest args)
  "Unpack FILE with ARGS."
  (let ((command (some (lambda (x)
                         (if (string-match-p (car x) file)
                             (cadr x)))
                       '((".*\.tar.bz2" "tar xjf")
                         (".*\.tar.gz" "tar xzf")
                         (".*\.bz2" "bunzip2")
                         (".*\.rar" "unrar x")
                         (".*\.gz" "gunzip")
                         (".*\.tar" "tar xf")
                         (".*\.tbz2" "tar xjf")
                         (".*\.tgz" "tar xzf")
                         (".*\.zip" "unzip")
                         (".*\.Z" "uncompress")
                         (".*" "echo 'Could not unpack the file:'")))))
    (let ((unpack-command(concat command " " file " " (mapconcat 'identity args " "))))
      (eshell/printnl "Unpack command: " unpack-command)
      (eshell-command-result unpack-command))))

(defun my/cat-with-syntax-highlight (filename)
  "Like cat(1) but with syntax highlighting."
  (let ((existing-buffer (get-file-buffer filename))
        (buffer (find-file-noselect filename)))
    (eshell-print
     (with-current-buffer buffer
       (if (fboundp 'font-lock-ensure)
           (font-lock-ensure)
         (with-no-warnings
           (font-lock-fontify-buffer)))
       (let ((contents (buffer-string)))
         (remove-text-properties 0 (length contents) '(read-only nil) contents)
         contents)))
    (unless existing-buffer
      (kill-buffer buffer))
    nil))

(advice-add 'eshell/cat :override #'my/cat-with-syntax-highlight)

prompt

(defun my/eshell-prompt ()
  (concat (abbreviate-file-name (eshell/pwd))
          (if (= (user-uid) 0) " # " " $ ")))

(with-eval-after-load 'em-prompt
  (setopt eshell-prompt-function #'my/eshell-prompt))

eshell-fringe-status

(autoload-if-found '(eshell-fringe-status-mode) "eshell-fringe-status" nil t)

(with-eval-after-load 'esh-mode
  (add-hook 'eshell-mode-hook #'eshell-fringe-status-mode))

esh-help

(autoload-if-found '(setup-esh-help-eldoc) "esh-help" nil t)

(with-eval-after-load 'esh-mode
  (add-hook 'eshell-mode-hook #'setup-esh-help-eldoc))

eshell-multiple

(autoload-if-found '(eshell-multiple-new
                     eshell-multiple-next
                     eshell-multiple-prev
                     eshell-multiple-clear-buffer
                     eshell-multiple-switch-buffer
                     eshell-multiple-dedicated-toggle
                     eshell-multiple-dedicated-open
                     eshell-multiple-dedicated-close)
                   "eshell-multiple" nil t)

(defalias 'eshell/new #'eshell-multiple-new)
(defalias 'eshell/next #'eshell-multiple-next)
(defalias 'eshell/prev #'eshell-multiple-prev)
(defalias 'eshell/clear #'eshell-multiple-clear-buffer)

(with-eval-after-load 'esh-mode
  (define-key eshell-mode-map (kbd "C-l") #'eshell-multiple-clear-buffer))

eshell-z

(autoload-if-found '(eshell-z) "eshell-z" nil t)

(with-eval-after-load 'esh-mode
  (define-key eshell-mode-map (kbd "C-c C-q") #'eshell-z))

eshell-did-you-mean

(autoload-if-found '(eshell-did-you-mean-setup) "eshell-did-you-mean" nil t)

(with-eval-after-load 'esh-mode
  (add-hook 'eshell-mode-hook #'eshell-did-you-mean-setup))

eshell-syntax-highlight

(autoload-if-found '(eshell-syntax-highlighting-global-mode) "eshell-syntax-highlighting" nil t)

(with-eval-after-load 'esh-mode
  (add-hook 'eshell-mode-hook #'eshell-syntax-highlighting-global-mode))

emacs-fish-completion

(autoload-if-found '(global-fish-completion-mode) "fish-completion" nil t)

(with-eval-after-load 'esh-mode
  (add-hook 'eshell-mode-hook #'global-fish-completion-mode))

Org Mode

Basic

org

(keymap-global-set "C-c l" #'org-store-link)
(keymap-global-set "C-c a" #'org-agenda)

(with-eval-after-load 'org
  (define-key org-mode-map (kbd "C-c ,") #'org-insert-structure-template)
  (define-key org-mode-map (kbd "C-c C-,") #'org-insert-structure-template)

  (add-hook 'org-mode-hook #'view-mode)

  (setopt org-tags-match-list-sublevels nil)

  (setq org-directory (my/ghq-repo-path "github.com/takeokunn-private/private"))

  (setq org-todo-keywords '((sequence "TODO(t)" "SOMEDAY(s)" "WAIT(w)" "REVIEW(r)" "QA(q)" "|" "DONE(d)")))

  (setq org-startup-folded 'fold)
  (setq org-startup-truncated nil)

  (defvar my/org-agenda-files `(,(concat org-directory "/task")
                                ,(concat org-directory "/archive/2023")
                                ,(concat org-directory "/archive/2024")
                                ,(concat org-directory "/archive/2025")
                                ,(concat org-directory "/archive/2026")))

  (setq org-agenda-files my/org-agenda-files)
  (setq org-archive-location `,(format (expand-file-name "archive/%s/%s.org::* Archived Tasks" org-directory)
                                       (format-time-string "%Y" (current-time))
                                       (format-time-string "%Y-%m-%d" (current-time))))
  (setq org-extend-today-until 4)
  (setq org-use-effective-time t)

  (setq org-log-into-drawer t)
  (setq org-log-done 'time)

  (defun my/update-org-agenda-files ()
    (interactive)
    (setq org-agenda-files my/org-agenda-files)))

org-src

(with-eval-after-load 'org-src
  (setopt org-src-window-setup 'current-window)
  (setopt org-src-fontify-natively nil)
  (setopt org-src-tab-acts-natively nil)

  (add-hook 'org-src-mode-hook
            #'(lambda ()
                (setq-local indent-tabs-mode nil)
                (view-mode -1))))

org-clock

(autoload-if-found '(org-clock-load) "org-clock" nil t)

(with-eval-after-load 'org
  (add-hook 'org-mode-hook #'org-clock-load))

(with-eval-after-load 'org-clock
  (setq org-clock-out-remove-zero-time-clocks t)
  (setq org-clock-clocked-in-display 'mode-line))

org-list

(with-eval-after-load 'org-list
  (setq org-list-allow-alphabetical t))

org-keys

(with-eval-after-load 'org-keys
  (setq org-use-extra-keys t)
  (setq org-use-speed-commands t)

  (add-to-list 'org-speed-commands '("d" org-todo "DONE"))
  (add-to-list 'org-speed-commands '("j" call-interactively #'consult-org-heading))
  (add-to-list 'org-speed-commands '("$" call-interactively #'org-archive-subtree)))

org-capture

(autoload-if-found '(org-capture) "org-capture" nil t)

(keymap-global-set "C-c c" #'org-capture)

(with-eval-after-load 'org-capture
  (advice-add 'org-capture
              :before #'(lambda (&rest _)
                          (remove-hook 'org-mode-hook #'view-mode)
                          (remove-hook 'prog-mode-hook #'view-mode)))
  (advice-add 'org-capture
              :after #'(lambda (&rest _)
                         (add-hook 'org-mode-hook #'view-mode)
                         (add-hook 'prog-mode-hook #'view-mode)))

  (setq org-capture-use-agenda-date t)
  (setq org-capture-bookmark nil)
  (setq org-capture-templates `(("m" "Memo" entry (file ,(expand-file-name "memo.org" org-directory))
                                 "* %T\n%?")
                                ("j" "Journal" entry (file+olp+datetree ,(expand-file-name "journal.org" org-directory))
                                 "* %U\n%?\n%i\n")
                                ("1" "Work" entry (file+headline ,(expand-file-name "task/work.org" org-directory) "Backlog")
                                 "** TODO Capture %U\n%?")
                                ("2" "Other" entry (file+headline ,(expand-file-name "task/other.org" org-directory) "Backlog")
                                 "** TODO Capture %U\n%?"))))

org-duration

(with-eval-after-load 'org-duration
  (setq org-duration-format (quote h:mm)))

org-id

(autoload-if-found '(org-id-store-link) "org-id" nil t)

(with-eval-after-load 'org-id
  (setq org-id-locations-file (expand-file-name ".org-id-locations" org-directory))
  (setq org-id-extra-files (append org-agenda-text-search-extra-files)))

org-crypt

(autoload-if-found '(org-encrypt-entry
                     org-encrypt-entries
                     org-decrypt-entry
                     org-decrypt-entries) "org-crypt" nil t)

(with-eval-after-load 'org
  (setopt org-tags-exclude-from-inheritance '("crypt")))

(with-eval-after-load 'org-crypt
  (setopt org-crypt-key "0B10DAA7BA0236D7382287660F79C0AB03FD7A1C"))

org-table

(autoload-if-found '(orgtbl-mode org-table-begin org-table-end) "org-table" nil t)

(with-eval-after-load 'org-table
  (defun my/org-table-align-markdown ()
    "Replace \"+\" sign with \"|\" in org-table."
    (when (member major-mode '(markdown-mode))
      (save-excursion
        (save-restriction
          (narrow-to-region (org-table-begin) (org-table-end))
          (goto-char (point-min))
          (while (search-forward "-+-" nil t)
            (replace-match "-|-"))))))

  (advice-add 'org-table-align :before #'my/org-table-align-markdown))

org-journal

(with-eval-after-load 'org-journal
  (setq org-journal-dir (expand-file-name "journal" org-directory))
  (setq org-journal-start-on-weekday 7)
  (setq org-journal-prefix-key "C-c j"))

org-generate

(autoload-if-found '(org-generate) "org-generate" nil t)

org-pomodoro

(autoload-if-found '(org-pomodoro) "org-pomodoro" nil t)

org-view-mode

(autoload-if-found '(org-view-mode) "org-view-mode" nil t)

org-random-todo

(autoload-if-found '(org-random-todo org-random-todo-goto-current) "org-random-todo" nil t)

org-dashboard

(autoload-if-found '(org-dashboard-display) "org-dashboard" nil t)

org-volume

(autoload-if-found '(org-volume-update-entry-from-dblock) "org-volume" nil t)

org-sliced-images

(autoload-if-found '(org-sliced-images-mode) "org-sliced-images" nil t)

(with-eval-after-load 'org
  (add-hook 'org-mode-hook #'org-sliced-images-mode))

org-ql

(autoload-if-found '(org-ql-query org-ql-select) "org-ql" nil t)

org-preview-html

(autoload-if-found '(org-preview-html-mode
                     org-preview-html-refresh
                     org-preview-html-pop-window-to-frame) "org-preview-html" nil t)

(with-eval-after-load 'org-preview-html
  (setopt org-preview-html-viewer 'xwidget))

Theme

org-faces

(with-eval-after-load 'org-faces
  (setq org-link '(t (:foreground "#ebe087" :underline t))))

org-superstar

(autoload-if-found '(org-superstar-mode) "org-superstar")

(with-eval-after-load 'org
  (add-hook 'org-mode-hook #'org-superstar-mode))

(with-eval-after-load 'org-superstar
  (setopt org-superstar-headline-bullets-list '("◉" "○" "✸" "✿"))
  (setopt org-superstar-leading-bullet " "))

Content

toc-org

(autoload-if-found '(toc-org-mode) "toc-org" nil t)

(with-eval-after-load 'org
  (add-hook 'org-mode-hook #'toc-org-mode))

Presentation

org-tree-slide

(autoload-if-found '(org-tree-slide-mode org-tree-slide-skip-done-toggle) "org-tree-slide" nil t)

(with-eval-after-load 'org-tree-slide
  (setopt org-tree-slide-skip-outline-level 4))

Org Agenda

Basic

(autoload-if-found '(org-agenda) "org-agenda" nil t)

(with-eval-after-load 'org-agenda
  (setq org-agenda-span 'day)
  (setq org-agenda-start-on-weekday 1)
  (setq org-agenda-todo-ignore-with-date t)
  (setq org-agenda-todo-list-sublevels nil)

  (advice-add 'org-archive-subtree :around #'my/advice-disable-buffer-readonly))

org-super-agenda

(autoload-if-found '(org-super-agenda-mode) "org-super-agenda" nil t)

(add-hook 'after-init-hook #'org-super-agenda-mode)

(with-eval-after-load 'org-agenda
  (setopt org-agenda-custom-commands
          '(("z" "Super Agenda"
             ((agenda "" ((org-agenda-span 'day)
                          (org-super-agenda-groups
                           '((:name "Today"
                                    :time-grid t
                                    :date today
                                    :todo "TODAY"
                                    :scheduled today
                                    :order 1)))))
              (alltodo "" ((org-agenda-overriding-header "")
                           (org-super-agenda-groups
                            '((:name "Next to do"
                                     :todo "NEXT"
                                     :order 1)
                              (:name "Important"
                                     :tag "Important"
                                     :priority "A"
                                     :order 6)
                              (:name "Due Today"
                                     :deadline today
                                     :order 2)
                              (:name "Due Soon"
                                     :deadline future
                                     :order 8)
                              (:name "Overdue"
                                     :deadline past
                                     :order 7)
                              (:name "Assignments"
                                     :tag "Assignment"
                                     :order 10)
                              (:name "Issues"
                                     :tag "Issue"
                                     :order 12)
                              (:name "Projects"
                                     :tag "Project"
                                     :order 14)
                              (:name "Emacs"
                                     :tag "Emacs"
                                     :order 13)
                              (:name "Research"
                                     :tag "Research"
                                     :order 15)
                              (:name "To read"
                                     :tag "Read"
                                     :order 30)
                              (:name "Waiting"
                                     :todo "WAITING"
                                     :order 20)
                              (:name "trivial"
                                     :priority<= "C"
                                     :tag ("Trivial" "Unimportant")
                                     :todo ("SOMEDAY" )
                                     :order 90)
                              (:discard (:tag ("Chore" "Routine" "Daily"))))))))))))

org-hyperscheduler

(autoload-if-found '(org-hyperscheduler-open) "org-hyperscheduler" nil t)

Org External Tools

org-redmine

(autoload-if-found '(org-redmine-get-issue) "org-redmine" nil t)

(with-eval-after-load 'org-redmine
  (setopt org-redmine-template-header "[#%i%] %s%")
  (setopt org-redmine-template-property '(("project_name" . "%p_n%"))))

org-ai

(autoload-if-found '(org-ai-mode) "org-ai" nil t)

(with-eval-after-load 'org
  (add-to-list 'org-structure-template-alist '("A" . "ai"))

  (add-hook 'org-mode-hook #'org-ai-mode))

(with-eval-after-load 'org-ai
  (setopt org-ai-default-chat-model "gpt-3.5-turbo"))

Org Babel

basic

(autoload-if-found '(org-babel-do-load-languages) "org" nil t)

(with-eval-after-load 'org
  (add-hook 'org-mode-hook
            #'(lambda ()
                (org-babel-do-load-languages 'org-babel-load-languages
                                             '((awk . t)
                                               (C . t)
                                               (R . t)
                                               (clojure . t)
                                               (emacs-lisp . t)
                                               (haskell . t)
                                               (java . t)
                                               (js . t)
                                               (lisp . t)
                                               (makefile . t)
                                               (perl . t)
                                               (plantuml . t)
                                               (python . t)
                                               (ruby . t)
                                               (scheme . t)
                                               (shell . t)
                                               (sql . t)
                                               (shell . t))))))

(with-eval-after-load 'ob-core
  (setq org-confirm-babel-evaluate nil)
  (setq org-babel-default-header-args '((:session . "none")
                                        (:results . "drawer replace")
                                        (:exports . "code")
                                        (:cache . "no")
                                        (:noweb . "no")
                                        (:hlines . "no")
                                        (:tangle . "no"))))

(with-eval-after-load 'ob-eval
  (advice-add #'org-babel-eval-error-notify
              :around #'(lambda (old-func &rest args)
                          (when (not (string= (nth 1 args)
                                              "mysql: [Warning] Using a password on the command line interface can be insecure.\n"))
                            (apply old-func args)))))

(with-eval-after-load 'ob-tangle
  (advice-add 'org-babel-tangle :around #'my/advice-disable-buffer-readonly))

ob-async

(autoload-if-found '(ob-async-org-babel-execute-src-block) "ob-async" nil t)

ob-fish

(autoload-if-found '(org-babel-execute:fish) "ob-fish" nil t)

(with-eval-after-load 'org-src
  (add-to-list 'org-src-lang-modes '("fish" . fish)))

ob-rust

(autoload-if-found '(org-babel-execute:rust) "ob-rust" nil t)

(with-eval-after-load 'org-src
  (add-to-list 'org-src-lang-modes '("rust" . rust)))

ob-go

(autoload-if-found '(org-babel-execute:go) "ob-go" nil t)

(with-eval-after-load 'org-src
  (add-to-list 'org-src-lang-modes '("go" . go)))

ob-translate

(autoload-if-found '(ob-translate:google-translate) "ob-translate" nil t)

(with-eval-after-load 'text-mode
  (define-derived-mode translate-mode text-mode "translate"))

(with-eval-after-load 'org-src
  (add-to-list 'org-src-lang-modes '("translate" . translate)))

ob-typescript

(autoload-if-found '(org-babel-execute:typescript) "ob-typescript" nil t)

(with-eval-after-load 'org-src
  (add-to-list 'org-src-lang-modes '("typescript" . typescript)))

ob-php

(autoload-if-found '(org-babel-execute:php) "ob-php" nil t)

(with-eval-after-load 'org-src
  (add-to-list 'org-src-lang-modes '("php" . php)))

ob-phpstan

(autoload-if-found '(org-babel-execute:phpstan) "ob-phpstan" nil t)

(with-eval-after-load 'org-src
  (add-to-list 'org-src-lang-modes '("phpstan" . phpstan)))

ob-http

(autoload-if-found '(org-babel-execute:http) "ob-http" nil t)
(autoload-if-found '(ob-http-mode) "ob-http-mode" nil t)

(with-eval-after-load 'org-src
  (add-to-list 'org-src-lang-modes '("http" . ob-http)))

ob-mermaid

(autoload-if-found '(org-babel-execute:mermaid) "ob-mermaid" nil t)

(with-eval-after-load 'org-src
  (add-to-list 'org-src-lang-modes '("mermaid" . mermaid)))

ob-graphql

(autoload-if-found '(org-babel-execute:graphql) "ob-graphql" nil t)

(with-eval-after-load 'org-src
  (add-to-list 'org-src-lang-modes '("graphql" . graphql)))

ob-rust

(autoload-if-found '(org-babel-execute:rust) "ob-rust" nil t)

(with-eval-after-load 'org-src
  (add-to-list 'org-src-lang-modes '("rust" . rust)))

ob-swift

(autoload-if-found '(org-babel-execute:swift) "ob-swift" nil t)

(with-eval-after-load 'org-src
  (add-to-list 'org-src-lang-modes '("swift" . swift)))

ob-elixir

(autoload-if-found '(org-babel-execute:elixir) "ob-elixir" nil t)

(with-eval-after-load 'org-src
  (add-to-list 'org-src-lang-modes '("elixir" . elixir)))

ob-dart

(autoload-if-found '(org-babel-execute:dart) "ob-dart" nil t)

(with-eval-after-load 'org-src
  (add-to-list 'org-src-lang-modes '("dart" . dart)))

ob-fsharp

(autoload-if-found '(org-babel-execute:fsharp) "ob-fsharp" nil t)

(with-eval-after-load 'org-src
  (add-to-list 'org-src-lang-modes '("fsharp" . fsharp)))

ob-treesitter

(autoload-if-found '(org-babel-execute:treesitter) "ob-treesitter" nil t)

(with-eval-after-load 'prog-mode
  (define-derived-mode treesitter-mode prog-mode "treesitter"))

(with-eval-after-load 'org-src
  (add-to-list 'org-src-lang-modes '("treesitter" . treesitter)))

ob-base64

(autoload-if-found '(org-babel-execute:base64) "ob-base64" nil t)

(with-eval-after-load 'org-src
  (add-to-list 'org-src-lang-modes '("base64" . base64)))

ob-lisp

(with-eval-after-load 'ob-lisp
  (defalias 'org-babel-execute:common-lisp 'org-babel-execute:lisp))

ob-racket

(autoload-if-found '(org-babel-execute:racket) "ob-racket" nil t)

(with-eval-after-load 'org-src
  (add-to-list 'org-src-lang-modes '("racket" . racket)))

ob-prolog

(autoload-if-found '(org-babel-execute:prolog) "ob-prolog" nil t)

(with-eval-after-load 'org-src
  (add-to-list 'org-src-lang-modes '("prolog" . pl)))

ob-deno

(autoload-if-found '(org-babel-execute:deno) "ob-deno" nil t)

(with-eval-after-load 'org-src
  (add-to-list 'org-src-lang-modes '("deno" . deno)))

ob-gleam

(autoload-if-found '(org-babel-execute:gleam) "ob-gleam" nil t)

(with-eval-after-load 'org-src
  (add-to-list 'org-src-lang-modes '("gleam" . gleam)))

org-nix-shell

(autoload-if-found '(org-nix-shell-mode) "org-nix-shell" nil t)

(with-eval-after-load 'org
  (add-hook 'org-mode-hook #'org-nix-shell-mode))

Org Publish

ox

(autoload-if-found '(org-export-define-backend) "ox" nil t)

ox-html

(with-eval-after-load 'ox-html
  (setopt org-html-head-include-default-style nil)
  (setopt org-html-head-include-scripts nil)
  (setopt org-html-doctype "html5")
  (setopt org-html-coding-system 'utf-8-unix))

ox-gfm

(autoload-if-found '(org-gfm-export-as-markdown
                     org-gfm-convert-region-to-md
                     org-gfm-export-to-markdown
                     org-gfm-publish-to-gfm) "ox-gfm" nil t)

ox-zenn

(autoload-if-found '(org-zenn-export-as-markdown
                     org-zenn-export-to-markdown
                     org-zenn-publish-to-markdown
                     org-zenn-convert-region-to-md) "ox-zenn" nil t)

ox-hatena

(autoload-if-found '(org-hatena-export-as-hatena
                     org-hatena-export-to-hatena
                     org-hatena-export-to-hatena-and-open) "ox-hatena" nil t)

ox-qmd

(autoload-if-found '(org-qmd-export-as-markdown
                     org-qmd-convert-region-to-md
                     org-qmd-export-to-markdown) "ox-qmd" nil t)

ox-hugo

(autoload-if-found '(org-hugo-export-as-md
                     org-hugo-export-to-md
                     org-hugo-export-wim-to-md
                     org-hugo-debug-info) "ox-hugo" nil t)

(with-eval-after-load 'ox-hugo
  (setopt org-hugo-auto-set-lastmod t))

ox-typst

(autoload-if-found '(org-typst-export-block
                     org-typst-headline
                     org-typst-item
                     org-typst-keyword
                     org-typst-section
                     org-typst-src-block
                     org-typst-export-as-typst
                     org-typst-export-to-typst
                     org-typst-export-to-pdf
                     org-typst-compile) "ox-typst" nil t)

(org-export-define-backend 'typst-slide
  '((export-block . org-typst-export-block)
    (headline . org-typst-headline)
    (item . org-typst-item)
    (keyword . org-typst-keyword)
    (section . org-typst-section)
    (src-block . org-typst-src-block))
  :menu-entry
  '(?y "Export to Typst"
       ((?F "As Typst buffer" org-typst-export-as-typst)
        (?f "As Typst file" org-typst-export-to-typst)
        (?p "As PDF file" org-typst-export-to-pdf)))
  :options-alist
  '((:typst-format-drawer-function nil nil #'(lambda (_ contents) contents))
    (:typst-format-inlinetask-function nil
                                       nil
                                       #'(lambda (_ contents) contents))))

(defun org-typst-slide-export-as-typst
    (&optional async subtreep visible-only body-only ext-plist)
  (interactive)
  (org-export-to-buffer 'typst-slide "*Org Typst Slide Export*"
    async subtreep visible-only body-only ext-plist))

(defun org-typst-slide-export-to-typst
    (&optional async subtreep visible-only body-only ext-plist)
  (interactive)
  (let ((outfile (org-export-output-file-name ".typ" subtreep)))
    (org-export-to-file 'typst-slide outfile
      async subtreep visible-only body-only ext-plist)))

Org Roam

basic

(autoload-if-found '(org-roam-graph) "org-roam" nil t)

(keymap-global-set "C-c n g" #'org-roam-graph)
(keymap-global-set "C-c n l" #'org-roam-buffer-toggle)
(keymap-global-set "C-c n f" #'org-roam-node-find)
(keymap-global-set "C-c n i" #'org-roam-node-insert)
(keymap-global-set "C-c n c" #'org-roam-capture)
(keymap-global-set "C-c n d" #'org-roam-dailies-map)
(keymap-global-set "C-c n j" #'org-roam-dailies-goto-today)

(with-eval-after-load 'org-roam
  (setopt org-roam-directory `,(my/ghq-repo-path "github.com/takeokunn/blog")))

org-roam-mode

(autoload-if-found '(org-roam-buffer-toggle) "org-roam-mode" nil t)

org-roam-node

(autoload-if-found '(org-roam-node-find org-roam-node-insert) "org-roam-node" nil t)

(with-eval-after-load 'org-roam-node
  (setopt org-roam-completion-everywhere nil))

org-roam-db

  (autoload-if-found '(org-roam-db-autosync-enable) "org-roam-db" nil t)

  (defun my/org-roam-db-autosync-maybe-enable ()
    "Enable Org-roam autosync only when its backing repository is checked out.
`org-roam-directory' resolves through `my/ghq-repo-path', which falls back to
a path that may not exist when the repository has never been cloned; syncing
against a missing directory signals file-missing on every Org buffer visit."
    (when (file-directory-p (my/ghq-repo-path "github.com/takeokunn/blog"))
      (org-roam-db-autosync-enable)))

  (with-eval-after-load 'org
    (add-hook 'org-mode-hook #'my/org-roam-db-autosync-maybe-enable))

  (with-eval-after-load 'org-roam-db
    (setq org-roam-db-gc-threshold (* 4 gc-cons-threshold)))

org-roam-capture

(autoload-if-found '(org-roam-capture) "org-roam-capture" nil t)

(with-eval-after-load 'org-roam-capture
  (setopt org-roam-capture-templates '(("f" "Fleeting(一時メモ)" plain "%?"
                                        :target (file+head "hugo/org/fleeting/%<%Y%m%d%H%M%S>-${slug}.org" "#+TITLE: ${title}\n")
                                        :unnarrowed t)
                                       ("l" "Literature(文献)" plain "%?"
                                        :target (file+head "hugo/org/literature/%<%Y%m%d%H%M%S>-${slug}.org" "#+TITLE: ${title}\n")
                                        :unnarrowed t)
                                       ("p" "Permanent(記事)" plain "%?"
                                        :target (file+head "hugo/org/permanent/%<%Y%m%d%H%M%S>-${slug}.org" "#+TITLE: ${title}\n")
                                        :unnarrowed t)
                                       ("d" "Diary(日記)" plain "%?"
                                        :target (file+head "hugo/org/diary/%<%Y%m%d%H%M%S>-${slug}.org" "#+TITLE: ${title}\n")
                                        :unnarrowed t)
                                       ("z" "Zenn" plain "%?"
                                        :target (file+head "zenn/org/articles/%<%Y%m%d%H%M%S>.org" "#+TITLE: ${title}\n")
                                        :unnarrowed t)
                                       ("t" "dev.to" plain "%?"
                                        :target (file+head "devto/articles/%<%Y%m%d%H%M%S>.org" "#+TITLE: ${title}\n")
                                        :unnarrowed t)
                                       ("m" "Private" plain "%?"
                                        :target (file+head "hugo/org/private/%<%Y%m%d%H%M%S>.org.gpg" "#+TITLE: ${title}\n")
                                        :unnarrowed t)
                                       ("o" "Poem" plain "%?"
                                        :target (file+head "hugo/org/poem/%<%Y%m%d%H%M%S>-${slug}.org" "#+TITLE: ${title}\n")
                                        :unnarrowed t))))

org-roam-dailies

(autoload-if-found '(org-roam-dailies-map
                     org-roam-dailies-goto-today
                     org-roam-dailies-goto-yesterday
                     org-roam-dailies-goto-tomorrow
                     org-roam-dailies-capture-today
                     org-roam-dailies-goto-next-note
                     org-roam-dailies-goto-previous-note
                     org-roam-dailies-goto-date
                     org-roam-dailies-capture-date
                     org-roam-dailies-find-directory) "org-roam-dailies" nil t)

(with-eval-after-load 'org-roam-dailies
  (setopt org-roam-dailies-directory "org/daily/")

  (define-key org-roam-dailies-map (kbd "d") #'org-roam-dailies-goto-today)
  (define-key org-roam-dailies-map (kbd "y") #'org-roam-dailies-goto-yesterday)
  (define-key org-roam-dailies-map (kbd "t") #'org-roam-dailies-goto-tomorrow)
  (define-key org-roam-dailies-map (kbd "n") #'org-roam-dailies-capture-today)
  (define-key org-roam-dailies-map (kbd "f") #'org-roam-dailies-goto-next-note)
  (define-key org-roam-dailies-map (kbd "b") #'org-roam-dailies-goto-previous-note)
  (define-key org-roam-dailies-map (kbd "c") #'org-roam-dailies-goto-date)
  (define-key org-roam-dailies-map (kbd "v") #'org-roam-dailies-capture-date)
  (define-key org-roam-dailies-map (kbd ".") #'org-roam-dailies-find-directory))

org-roam-export

(autoload-if-found '(org-roam-export--org-html--reference) "org-roam-export" nil t)

(with-eval-after-load 'ox-html
  (advice-add 'org-html--reference :override #'org-roam-export--org-html--reference))

org-roam-graph

(autoload-if-found '(org-roam-graph org-roam-graph--open) "org-roam-graph" nil t)

org-roam-overlay

(autoload-if-found '(org-roam-overlay-mode) "org-roam-overlay" nil t)

(with-eval-after-load 'org-roam-mode
  (add-hook 'org-roam-mode-hook #'org-roam-overlay-mode))

org-roam-protocol

(autoload-if-found '(org-roam-protocol-open-ref org-roam-protocol-open-node) "org-roam-protocol" nil t)

(with-eval-after-load 'org-roam-protocol
  (add-to-list 'org-protocol-protocol-alist '("org-roam-ref" :protocol "roam-ref" :function org-roam-protocol-open-ref))
  (add-to-list 'org-protocol-protocol-alist '("org-roam-node" :protocol "roam-node" :function org-roam-protocol-open-node))

  (setopt org-roam-protocol-store-links t))

consult-org-roam

(autoload-if-found '(consult-org-roam-mode
                     consult-org-roam-file-find
                     consult-org-roam-backlinks
                     consult-org-roam-backlinks-recursive
                     consult-org-roam-forward-links
                     consult-org-roam-search) "consult-org-roam" nil t)

(keymap-global-set "C-c n f" #'consult-org-roam-file-find)
(keymap-global-set "C-c n b" #'consult-org-roam-backlinks)
(keymap-global-set "C-c n B" #'consult-org-roam-backlinks-recursive)
(keymap-global-set "C-c n l" #'consult-org-roam-forward-links)
(keymap-global-set "C-c n r" #'consult-org-roam-search)

(with-eval-after-load 'org
  (add-hook 'org-mode-hook #'consult-org-roam-mode))

(with-eval-after-load 'consult-org-roam
  (setq consult-org-roam-grep-func #'consult-ripgrep)
  (setq consult-org-roam-buffer-narrow-key ?r)
  (setq consult-org-roam-buffer-after-buffers nil))

;; consult-org-roam-buffer.el reads/sets org-roam-buffer-open-buffer-list
;; without ever declaring it, so exiting the minibuffer before its :items
;; function has run signals (void-variable org-roam-buffer-open-buffer-list).
(with-eval-after-load 'consult-org-roam-buffer
  (defvar org-roam-buffer-open-buffer-list nil))

org-roam-ui

(autoload-if-found '(org-roam-ui-mode) "org-roam-ui" nil t)

(with-eval-after-load 'org-roam-mode
  (add-hook 'org-roam-mode-hook #'org-roam-ui-mode))

(with-eval-after-load 'org-roam-ui
  (setopt org-roam-ui-sync-theme t)
  (setopt org-roam-ui-follow t)
  (setopt org-roam-ui-update-on-save t)
  (setopt org-roam-ui-open-on-start t))

org-roam-timestamps

(autoload-if-found '(org-roam-timestamps-mode) "org-roam-timestamps" nil t)

(with-eval-after-load 'org-roam-mode
  (add-hook 'org-roam-mode #'org-roam-timestamps-mode))

(with-eval-after-load 'org-roam-timestamps
  (setopt org-roam-timestamps-remember-timestamps nil))

org-roam-ql

(autoload-if-found '(org-roam-ql-nodes
                     org-roam-ql-search
                     org-roam-ql-defpred
                     org-roam-ql-agenda-buffer-from-roam-buffer
                     org-roam-ql-refresh-buffer
                     org-dblock-write:org-roam-ql) "org-roam-ql" nil t)

org-roam-ql-ql

(autoload-if-found '(org-roam-ql-ql-init) "org-roam-ql-ql" nil t)

(add-hook 'after-init-hook #'org-roam-ql-ql-init)

Citar

citar

(autoload-if-found '(citar-open
                     citar-open-entry
                     citar-open-files
                     citar-open-notes
                     citar-insert-citation
                     citar-insert-reference
                     citar-insert-bibtex) "citar" nil t)

(autoload-if-found '(citar-org-local-bib-files) "citar-org" nil t)

(keymap-global-set "C-c b o" #'citar-open)
(keymap-global-set "C-c b e" #'citar-open-entry)
(keymap-global-set "C-c b f" #'citar-open-files)
(keymap-global-set "C-c b n" #'citar-open-notes)
(keymap-global-set "C-c b i" #'citar-insert-citation)

(with-eval-after-load 'citar
  (setopt citar-bibliography
          `,(list (expand-file-name "hugo/references.bib" (my/ghq-repo-path "github.com/takeokunn/blog"))))

  (setopt org-cite-insert-processor 'citar)
  (setopt org-cite-follow-processor 'citar)
  (setopt org-cite-activate-processor 'citar))

citar-embark

(autoload-if-found '(citar-embark-mode) "citar-embark" nil t)

(with-eval-after-load 'citar
  (citar-embark-mode 1))

citar-org-roam

(autoload-if-found '(citar-org-roam-mode
                     citar-org-roam-cited
                     citar-org-roam-ref-add
                     citar-org-roam-open-current-refs) "citar-org-roam" nil t)

(with-eval-after-load 'citar
  (citar-org-roam-mode 1))

(with-eval-after-load 'citar-org-roam
  (setopt citar-org-roam-subdir "hugo/org/literature")
  (setopt citar-org-roam-note-title-template "${author} - ${title}"))

EXWM

exwm


exwm-edit


exwm-modeline


AI

copilot.el

(autoload-if-found '(copilot-login copilot-mode) "copilot" nil t)

(keymap-global-set "C-x C-:" #'copilot-mode)

(with-eval-after-load 'copilot
  (setopt copilot-log-max 100000)
  (when-let* ((path (getenv "COPILOT_LANGUAGE_SERVER_PATH")))
    (setopt copilot-server-executable path))

  (define-key copilot-mode-map (kbd "C-S-i") #'copilot-complete)
  (define-key copilot-mode-map (kbd "C-S-a") #'copilot-accept-completion)
  (define-key copilot-mode-map (kbd "C-c # a") #'copilot-accept-completion))

copilot-chat.el

(autoload-if-found '(copilot-chat-transient-code copilot-chat-insert-commit-message) "copilot-chat" nil t)

(with-eval-after-load 'git-commit
  (add-hook 'git-commit-setup-hook #'copilot-chat-insert-commit-message))

(with-eval-after-load 'copilot-chat
  (setopt copilot-chat-frontend 'shell-maker))

(with-eval-after-load 'copilot-chat-prompts
  (let ((my/copilot-chat-prompt "日本語で回答してください。\nコードと概念を正確に説明し、ユーザーの要件に従ってください。\n名前を尋ねられた場合は「GitHub Copilot」と答えてください。\n専門知識はソフトウェア開発に限定してください。\nMicrosoft のコンテンツポリシーに従い、著作権を侵害する内容は避けてください。\nソフトウェア開発以外の質問には、AIプログラミングアシスタントであることを簡潔に伝えてください。\n回答は簡潔で非個人的な Markdown 形式にしてください。\nコードブロックの先頭に言語名を記述し、回答全体を三重バッククオートで囲まないでください。\n提供されたコード、質問、エラー、プロジェクト情報を確認してから回答してください。\n不明確な点がある場合は確認し、必要に応じて可読性やパフォーマンスの改善案を示してください。\n"))
    (setopt copilot-chat-markdown-prompt my/copilot-chat-prompt)
    (setopt copilot-chat-org-prompt my/copilot-chat-prompt)))

(with-eval-after-load 'copilot-chat-copilot
  (setopt copilot-chat-prompt-review "次のコードをレビューしてください。\n"))

MyFunc

my/beginning-of-intendation

(defun my/beginning-of-intendation ()
  "move to beginning of line, or indentation"
  (interactive)
  (back-to-indentation))

my/copy-buffer

(defun my/copy-buffer ()
  (interactive)
  (save-excursion
    (mark-whole-buffer)
    (copy-region-as-kill (region-beginning) (region-end))))

my/gh-browse

(defun my/gh-browse ()
  (interactive)
  (message
   (shell-command-to-string
    (mapconcat #'shell-quote-argument
               (list "gh" "browse")
               " "))))

my/indent-all

(defun my/indent-buffer ()
  (interactive)
  (save-excursion
    (mark-whole-buffer)
    (untabify (region-beginning) (region-end))
    (indent-region (region-beginning) (region-end))))

my/move-line

(defun my/move-line (arg)
  (interactive)
  (let ((col (current-column)))
    (unless (eq col 0)
      (move-to-column 0))
    (save-excursion
      (forward-line)
      (transpose-lines arg))
    (forward-line arg)))

(defun my/move-line-down ()
  (interactive)
  (my/move-line 1))

(defun my/move-line-up ()
  (interactive)
  (my/move-line -1))

(keymap-global-set "M-N" #'my/move-line-down)
(keymap-global-set "M-P" #'my/move-line-up)

my/reload-major-mode

(defun my/reload-major-mode ()
  "Reload current major mode."
  (interactive)
  (let ((current-mode major-mode))
    (fundamental-mode)
    (funcall current-mode)
    current-mode))

my/toggle-kill-emacs

(defvar my/kill-emacs-keybind-p t)

(defun my/toggle-kill-emacs ()
  (interactive)
  (if my/kill-emacs-keybind-p
      (progn
        (message "C-x C-c save-buffers-kill-emacs OFF")
        (setq my/kill-emacs-keybind-p nil)
        (keymap-global-set "C-x C-c" nil))
    (progn
      (message "C-x C-c save-buffers-kill-emacs ON")
      (setq my/kill-emacs-keybind-p t)
      (keymap-global-set "C-x C-c" 'save-buffers-kill-emacs))))

my/insert-clipboard

(defun my/insert-clipboard (arg)
  (interactive "sstring: ")
  (kill-new arg))

my/build-info

(defun my/build-info ()
  "Display build information in a buffer."
  (interactive)
  (switch-to-buffer (get-buffer-create "*Build info*"))
  (setq tab-width 4)
  (let ((buffer-read-only nil))
    (erase-buffer)
    (insert (format "GNU Emacs %s\nCommit:\t\t%s\nBranch:\t\t%s\n"
                    emacs-version
                    emacs-repository-version
                    emacs-repository-branch))
    (insert (format "System:\t\t%s\nDate:\t\t%s\n"
                    system-configuration
                    (format-time-string "%Y-%m-%d %T (%Z)" emacs-build-time)))
    (insert (format "Patch:\t\t%s ns-inline.patch\n"
                    (if (boundp 'mac-ime--cursor-type) "with" "without")))
    (insert (format "Features:\t%s\n" system-configuration-features))
    (view-mode)))

my/today

(defun my/today (&optional iso-format)
  (interactive "P")
  (insert
   (format-time-string
    (if iso-format "%Y-%m-%dT%T%z" "%Y-%m-%d %a")
    (current-time))))

my/delete-forward-block

(defun my/delete-forward-block ()
  (interactive)
  (if (eobp)
      (message "End of buffer")
    (let* ((syntax-move-point
            (save-excursion
              (skip-syntax-forward (string (char-syntax (char-after))))
              (point)))
           (subword-move-point
            (save-excursion
              (subword-forward)
              (point))))
      (kill-region (point) (min syntax-move-point subword-move-point)))))

my/insert-date-at-point

(defun my/insert-date-at-point ()
  "Minibufferで日付を選択し、カーソル位置に `YYYY/MM/DD DOW` フォーマットで挿入する。"
  (interactive)
  (let ((date (org-read-date nil nil nil "日付を選択してください:")))
    (insert (format-time-string "%Y/%m/%d %a" (org-time-string-to-time date)))))

my/copy-projectile-github-url

(defun my/remote-url-to-https (remote-url)
  "Return REMOTE-URL as an https URL without a trailing .git."
  (let ((https-remote
         (cond
          ;; ssh://git@github.com/ORG/REPO
          ((string-match "^ssh://git@\\(.*?\\)/\\(.*\\)$" remote-url)
           (format "https://%s/%s" (match-string 1 remote-url) (match-string 2 remote-url)))
          ;; git@github.com:ORG/REPO.git
          ((string-match "^git@\\(.*?\\):\\(.*\\)$" remote-url)
           (format "https://%s/%s" (match-string 1 remote-url) (match-string 2 remote-url)))
          (t remote-url))))
    (replace-regexp-in-string
     "\\`\\(https?://\\)[^/@]*@" "\\1"
     (replace-regexp-in-string "\\.git$" "" https-remote))))

(defun my/jj-origin-url (root)
  "Return the URL of the origin remote of the jj repository at ROOT, or nil."
  (let ((remotes (my/jj-output root "--ignore-working-copy" "git" "remote" "list")))
    (when (and remotes (string-match "^origin[ \t]+\\(.+\\)$" remotes))
      (match-string 1 remotes))))

(defun my/copy-projectile-github-url ()
  "Copy the GitHub URL of the current line in the current Projectile project."
  (interactive)
  (unless (projectile-project-p)
    (error "Not in a Projectile project"))
  (let* ((project-root (projectile-project-root))
         (file-path (file-relative-name (buffer-file-name) project-root))
         (line-number (line-number-at-pos))
         (vcs (my/vcs-root project-root))
         (jj-root (and (eq (car vcs) 'jj) (cdr vcs)))
         (remote-url (if jj-root
                         (or (my/jj-origin-url jj-root)
                             (error "No origin remote in %s" jj-root))
                       (string-trim (shell-command-to-string "git config --get remote.origin.url"))))
         (branch (if jj-root
                     ;; a commit known to exist on the remote; `git rev-parse HEAD'
                     ;; in a jj workspace would report the bare root's HEAD
                     (let ((out (my/jj-output jj-root "--ignore-working-copy" "log" "--no-graph"
                                              "-r" "heads(::@- & ::remote_bookmarks())"
                                              "-T" "commit_id ++ \"\\n\"")))
                       (or (and out (car (split-string out "\n" t)))
                           (error "No commit reachable from a remote bookmark in %s" jj-root)))
                   ;; a detached worktree reports literal "HEAD" here; name the commit instead
                   (let ((ref (string-trim (shell-command-to-string "git rev-parse --abbrev-ref HEAD"))))
                     (if (string= ref "HEAD")
                         (string-trim (shell-command-to-string "git rev-parse HEAD"))
                       ref))))
         (https-remote (my/remote-url-to-https remote-url))
         (url (format "%s/blob/%s/%s#L%d"
                      https-remote branch file-path line-number)))
    (kill-new url)
    (message "Copied to clipboard: %s" url)))

my/copy-projectile-relative-path

  (defun my/copy-projectile-relative-path (arg)
    "Copy the project-relative path to kill-ring.
With prefix argument ARG, include line number as #L<line>."
    (interactive "P")
    (let* ((relative-path (string-remove-prefix (projectile-project-root) buffer-file-name))
           (result (if arg
                       (format "%s#L%d" relative-path (line-number-at-pos))
                     relative-path)))
      (kill-new result)
      (message "Copied to clipboard: %s" result)))

my/open-projectile-github-url

(defun my/open-projectile-github-url ()
  "Open the GitHub URL of the current line in the browser."
  (interactive)
  (my/copy-projectile-github-url)
  (browse-url (current-kill 0)))

Author: takeokunn

Created: 2026-10-07 Wed 09:21

Validate