はじめに
基本情報
- repo: takeokunn/.emacs.d
- twitter: たけてぃ@takeokunn
- blog: https://takeokunn.org
;; init.el --- My init.el -*- lexical-binding: t; -*-
(defmacro when-darwin (&rest body) (when (string= system-type "darwin") `(progn ,@body)))
(defmacro when-darwin-not-window-system (&rest body) (when (and (string= system-type "darwin") window-system) `(progn ,@body)))
(defmacro when-linux (&rest body) (when (string= system-type "gnu/linux") `(progn ,@body)))
(defmacro when-linux-not-window-system (&rest body) (when (and (string= system-type "gnu/linux") (not window-system)) `(progn ,@body)))
(setq user-full-name "takeokunn") (setq user-mail-address "bararararatty@gmail.com")
(setq shell-file-name (or (executable-find "bash") "/bin/sh"))
(defconst my/enable-profile nil "If true, enable profile") (when my/enable-profile (require 'profiler) (profiler-start 'cpu))
(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)
(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))
;; load compat-31 explicitly; it appears after compat-30 in load-path otherwise (when (version< emacs-version "31") (require 'compat-31))
(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))
(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)
(add-hook 'after-init-hook #'global-auto-revert-mode)
(add-hook 'after-init-hook
#'(lambda ()
(fset 'yes-or-no-p 'y-or-n-p)))
(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)
(add-hook 'after-init-hook #'savehist-mode)
(autoload-if-found '(osx-clipboard-mode) "osx-clipboard" nil t) (when (fboundp 'osx-clipboard-mode) (osx-clipboard-mode +1))
(autoload-if-found '(global-clipetty-mode) "clipetty" nil t) (when (fboundp 'global-clipetty-mode) (global-clipetty-mode +1))
;; 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))
(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))))
(with-eval-after-load 'uniquify (setopt uniquify-buffer-name-style 'post-forward-angle-brackets))
(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))
(with-eval-after-load 'warnings (setopt warning-minimum-level :error))
(setq echo-keystrokes 0.1)
(add-hook 'after-init-hook #'save-place-mode)
(setq enable-local-variables :all)
(with-eval-after-load 'password-cache (setq password-cache t) (setq password-cache-expiry 3600))
(with-eval-after-load 'minibuffer (setopt read-file-name-completion-ignore-case t)) (setq completion-ignore-case t) (setq read-buffer-completion-ignore-case t)
(setq system-time-locale "C")
(setopt kill-ring-max 100000)
(custom-set-variables '(savehist-additional-variables '(kill-ring)))
(setq truncate-lines t) (setq truncate-partial-width-windows t)
(setq use-dialog-box nil)
(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))
(setq debug-on-error nil)
(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"))
(autoload-if-found '(ansible-mode) "ansible" nil t)
(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))
(autoload-if-found '(bazel-mode) "bazel" nil t)
(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))
(autoload-if-found '(cask-mode) "cask-mode" nil t) (add-to-list 'auto-mode-alist '("/Cask\\'" . cask-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))
(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))
(autoload-if-found '(cmake-mode) "cmake-mode" nil t) (add-to-list 'auto-mode-alist '("\\.cmake$" . cmake-mode))
(autoload-if-found '(coffee-mode) "coffee-mode" nil t) (add-to-list 'auto-mode-alist '("\\.coffee$" . coffee-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))
(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))
(autoload-if-found '(csharp-mode) "csharp-mode" nil t) (add-to-list 'auto-mode-alist '("\\.cs$" . csharp-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))
(autoload-if-found '(cuda-mode) "cuda-mode" nil t) (add-to-list 'auto-mode-alist '("\\.cu$" . cuda-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))
(autoload-if-found '(dart-mode) "dart-mode" nil t) (add-to-list 'auto-mode-alist '("\\.dart$" . dart-mode))
(autoload-if-found '(dhall-mode) "dhall-mode" nil t) (add-to-list 'auto-mode-alist '("\\.dhall$" . dhall-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))
(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))
(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))
(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))
(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))
(autoload-if-found '(elm-mode) "elm-mode" nil t) (add-to-list 'auto-mode-alist '("\\.elm$" . elm-mode))
(add-to-list 'auto-mode-alist '("Keg" . emacs-lisp-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))
(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))
(autoload-if-found '(f90-mode) "f90" nil t) (add-to-list 'auto-mode-alist '("\\.f\\(y90\\|y?pp\\)\\'" . f90-mode))
(autoload-if-found '(fsharp-mode) "fsharp-mode" nil t) (add-to-list 'auto-mode-alist '("\\.fs[iylx]?$" . fsharp-mode))
(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))
(autoload-if-found '(gleam-ts-mode) "gleam-ts-mode" nil t) (add-to-list 'auto-mode-alist '("\\.gleam\\'" . gleam-ts-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))
(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"))
(autoload-if-found '(gradle-mode) "gradle-mode" nil t) (add-to-list 'auto-mode-alist '("\\.gradle$" . gradle-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))
(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))
(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))
(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))
(autoload-if-found '(hcl-mode) "hcl-mode" nil t) (add-to-list 'auto-mode-alist '("\\.hcl$" . hcl-mode))
(autoload-if-found '(hy-mode) "hy-mode" nil t) (add-to-list 'auto-mode-alist '("\\.hy$" . hy-mode))
(autoload-if-found '(ini-mode) "ini-mode" nil t) (add-to-list 'auto-mode-alist '("\\.ini$" . ini-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))
(autoload-if-found '(java-mode) "java-mode" nil t) (add-to-list 'auto-mode-alist '("\\.java$" . java-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))
(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))
(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))
(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))
(autoload-if-found '(kotlin-mode) "kotlin-mode" nil t) (add-to-list 'auto-mode-alist '("\\.kts?\\'" . kotlin-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))
(autoload-if-found '(lua-mode) "lua-mode" nil t) (add-to-list 'auto-mode-alist '("\\.lua$" . lua-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))
(autoload-if-found '(mermaid-mode) "mermaid-mode" nil t) (add-to-list 'auto-mode-alist '("\\.mmd\\'" . mermaid-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))
(autoload-if-found '(nasm-mode) "nasm-mode" nil t) (add-to-list 'auto-mode-alist '("\\.s$" . nasm-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))
(autoload-if-found '(nim-mode) "nim-mode" nil t) (add-to-list 'auto-mode-alist '("\\.nim\\'" . nim-mode))
(autoload-if-found '(ninja-mode) "ninja-mode" nil t) (add-to-list 'auto-mode-alist '("\\.ninja$" . ninja-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")))
(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))
(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))
(autoload-if-found '(pcap-mode) "pcap" nil t) (add-to-list 'auto-mode-alist '("\\.pcap$" . pcap-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))
(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"))
(autoload-if-found '(phpt-mode) "phpt-mode" nil t) (add-to-list 'auto-mode-alist '("\\.phpt$" . phpt-mode))
(autoload-if-found '(plantuml-mode) "plantuml-mode" nil t) (add-to-list 'auto-mode-alist '("\\.pu$" . plantuml-mode))
(autoload-if-found '(po-mode) "po-mode" nil t) (add-to-list 'auto-mode-alist '("\\.po$" . po-mode))
(autoload-if-found '(prolog-mode) "prolog-mode" nil t) (add-to-list 'auto-mode-alist '("\\.pl$" . prolog-mode))
(autoload-if-found '(protobuf-mode) "protobuf-mode" nil t) (add-to-list 'auto-mode-alist '("\\.proto\\'" . protobuf-mode))
(autoload-if-found '(pug-mode) "pug-mode" nil t) (add-to-list 'auto-mode-alist '("\\.pug$" . pug-mode))
(autoload-if-found '(prisma-mode) "prisma-mode" nil t) (add-to-list 'auto-mode-alist '("\\.prisma" . prisma-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"))
(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))
(autoload-if-found '(qt-pro-mode) "qt-pro-mode" nil t) (add-to-list 'auto-mode-alist '("\\.pr[io]$" . qt-pro-mode))
(autoload-if-found '(racket-mode) "racket-mode" nil t)
(autoload-if-found '(robots-txt-mode) "robots-txt-mode" nil t) (add-to-list 'auto-mode-alist '("/robots\\.txt\\'" . robots-txt-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))
(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))
(autoload-if-found '(scala-mode) "scala-mode" nil t) (add-to-list 'auto-mode-alist '("\\.scala$" . scala-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"))
(autoload-if-found '(scad-mode) "scad-mode" nil t) (add-to-list 'auto-mode-alist '("\\.scad\\'" . scad-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))
(autoload-if-found '(shell-mode) "shell-mode" nil t) (define-derived-mode console-mode shell-mode "console")
(autoload-if-found '(slim-mode) "slim-mode" nil t) (add-to-list 'auto-mode-alist '("\\.slim$" . slim-mode))
(autoload-if-found '(solidity-mode) "solidity-mode" nil t) (add-to-list 'auto-mode-alist '("\\.sol$" . solidity-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))
(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))
(autoload-if-found '(swift-mode) "swift-mode" nil t) (add-to-list 'auto-mode-alist '("\\.swift$" . swift-mode))
(autoload-if-found '(syslog-mode) "syslog-mode" nil t) (add-to-list 'auto-mode-alist '("\\.log$" . syslog-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))
(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))
(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))
(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))
(autoload-if-found '(tmux-mode) "tmux-mode" nil t) (add-to-list 'auto-mode-alist '("\\.tmux\\.conf$" . tmux-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))
(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))
(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))
(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))
(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))
(autoload-if-found '(wat-mode) "wat-mode" nil t) (add-to-list 'auto-mode-alist '("\\.wat?\\'" . wat-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))
(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))
(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"))
(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))
(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))
(autoload-if-found '(zig-mode) "zig-mode" nil t) (add-to-list 'auto-mode-alist '("\\.zig$" . zig-mode))
(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)))
(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)
(require 'flymake-proc)
(autoload-if-found '(flycheck-mode) "flycheck" nil t)
(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))
(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))
(autoload-if-found '(flycheck-projectile-list-errors) "flycheck-projectile" nil t)
(autoload-if-found '(flycheck-cfn-setup) "flycheck-cfn" nil t) (with-eval-after-load 'cfn-mode (add-hook 'cfn-mode-hook #'flycheck-cfn-setup))
(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))
(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)
(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))
(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))
(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)))
(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)))
(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))
(autoload-if-found '(git-timemachine) "git-timemachine" nil t)
(autoload-if-found '(gist-mode) "gist" nil t)
(autoload-if-found '(blamer-mode) "blamer" nil t)
(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"))
(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)))
(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)))
(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))))
(autoload-if-found '(which-key-mode) "which-key" nil t)
(add-hook 'after-init-hook #'which-key-mode)
(autoload-if-found '(global-dmacro-mode) "dmacro" nil t)
(add-hook 'after-init-hook #'global-dmacro-mode)
(autoload-if-found '(god-mode) "god-mode" nil t)
(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))
(autoload-if-found '(yas-global-mode) "yasnippet" nil t)
(add-hook 'after-init-hook #'yas-global-mode)
(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)
(autoload-if-found '(soft-narrow-mode) "soft-narrow" nil t)
(add-hook 'after-init-hook #'soft-narrow-mode)
(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))))))
(autoload-if-found '(eglot-booster-mode) "eglot-booster" nil t)
(add-hook 'after-init-hook #'eglot-booster-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))
(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)))
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)
(with-eval-after-load 'lsp-mode (add-hook 'lsp-mode-hook #'(lambda () (require 'ccls))))
(with-eval-after-load 'lsp-php (setopt lsp-intelephense-licence-key "00OXTX8OROOJH9P"))
(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))
(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))
(with-eval-after-load 'lsp-mode (add-hook 'lsp-mode-hook #'(lambda () (require 'lsp-dart))))
(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))))
(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))
(autoload-if-found '(lsp-scheme) "lsp-scheme" nil t) (with-eval-after-load 'scheme (add-hook 'scheme-mode-hook #'lsp-scheme))
(autoload-if-found '(global-syntax-subword-mode) "syntax-subword" nil t)
(add-hook 'after-init-hook #'global-syntax-subword-mode)
(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))
(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)))
(with-eval-after-load 'comint (setopt comint-buffer-maximum-size 100000) (setopt comint-prompt-read-only t) (setopt comint-terminfo-terminal "eterm-256color"))
(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)
(autoload-if-found '(delete-selection-mode) "delsel" nil t)
(add-hook 'after-init-hook #'delete-selection-mode)
(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)
(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))
(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)))
(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))
(autoload-if-found '(quickrun) "quickrun" nil t)
(autoload-if-found '(restclient-mode) "restclient" nil t)
(autoload-if-found '(smart-jump-setup-default-registers) "smart-jump" nil t)
(add-hook 'after-init-hook #'smart-jump-setup-default-registers)
(autoload-if-found '(string-inflection-all-cycle) "string-inflection" nil t)
(autoload-if-found '(uuid-string) "uuid" nil t) (defun my/uuid () (interactive) (insert (uuid-string)))
(autoload-if-found '(woman woman-find-file) "woman" nil t)
(autoload-if-found '(tramp-set-completion-function) "tramp" nil t)
(autoload-if-found '(consult-tramp) "consult-tramp" nil t)
(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))
(autoload-if-found '(proced-narrow) "proced-narrow" nil t) (with-eval-after-load 'proced (define-key proced-mode-map (kbd "/") #'proced-narrow))
(autoload-if-found '(symon-mode) "symon" nil t)
(autoload-if-found '(clm/toggle-command-log-buffer) "command-log-mode" nil t) (defalias 'command-log #'clm/toggle-command-log-buffer)
(autoload-if-found '(esup) "esup" nil t)
(autoload-if-found '(explain-pause-mode) "explain-pause-mode" nil t)
(autoload-if-found '(disk-usage disk-usage-here) "disk-usage" nil t)
(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)
(autoload-if-found '(uptimes) "uptimes" nil t)
(require 'xwidget nil t)
(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))
(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))
(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))
(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))
(autoload-if-found '(dired-collapse-mode) "dired-collapse" nil t) (with-eval-after-load 'dired (add-hook 'dired-mode #'dired-collapse-mode))
(autoload-if-found '(dired-filter-mode) "dired-filter" nil t) (with-eval-after-load 'dired (add-hook 'dired-mode #'dired-filter-mode))
(autoload-if-found '(dired-narrow-mode) "dired-narrow" nil t) (with-eval-after-load 'dired (add-hook 'dired-mode-hook #'dired-narrow-mode))
(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))
(autoload-if-found '() "dired-ranger" nil t)
(autoload-if-found '(dired-subtree-apply-filter) "dired-subtree" nil t)
(autoload-if-found '(dired-subtree-apply-filter) "dired-subtree" nil t)
(autoload-if-found '(diredfl-global-mode) "diredfl" nil t) (with-eval-after-load 'dired (add-hook 'dired-mode-hook #'diredfl-global-mode))
(autoload-if-found '(wgrep-setup) "wgrep" nil t) (with-eval-after-load 'grep (add-hook 'grep-setup-hook 'wgrep-setup))
(autoload-if-found '(consult-bookmark
consult-buffer
consult-buffer-other-frame
consult-buffer-other-tab
consult-buffer-other-window
consult-complex-command
consult-find
consult-flycheck
consult-focus-lines
consult-git-grep
consult-global-mark
consult-goto-line
consult-grep
consult-history
consult-isearch-history
consult-keep-lines
consult-line
consult-line-multi
consult-locate
consult-man
consult-mark
consult-outline
consult-project-buffer
consult-register
consult-register-load
consult-register-store
consult-ripgrep
consult-yank-pop
consult-mode-command
consult-completion-in-region
consult-preview-at-point-mode
consult-register-window) "consult" nil t)
(autoload-if-found '(consult-compile-error) "consult-compile" nil t)
(autoload-if-found '(consult-org-heading consult-org-agenda) "consult-org" nil t)
(autoload-if-found '(consult-imenu consult-imenu-multi) "consult-imenu" nil t)
(autoload-if-found '(consult-kmacro) "consult-kmacro" nil t)
(autoload-if-found '(consult-xref) "consult-xref" nil t)
(keymap-global-set "C-c M-x" #'consult-mode-command)
(keymap-global-set "C-c h" #'consult-history)
(keymap-global-set "C-x M-:" #'consult-complex-command)
(keymap-global-set "C-x b" #'consult-buffer)
(keymap-global-set "C-x 4 b" #'consult-buffer-other-window)
(keymap-global-set "C-x 5 b" #'consult-buffer-other-frame)
(keymap-global-set "M-y" #'consult-yank-pop)
(keymap-global-set "M-g e" #'consult-compile-error)
(keymap-global-set "M-g f" #'consult-flycheck)
(keymap-global-set "M-g g" #'consult-goto-line)
(keymap-global-set "M-g M-g" #'consult-goto-line)
(keymap-global-set "M-g o" #'consult-outline)
(keymap-global-set "M-g m" #'consult-mark)
(keymap-global-set "M-g k" #'consult-global-mark)
(keymap-global-set "M-g i" #'consult-imenu)
(keymap-global-set "M-g I" #'consult-imenu-multi)
(keymap-global-set "C-o" #'(lambda ()
(interactive)
(let ((word (thing-at-point 'symbol 'no-properties)))
(consult-line word))))
(with-eval-after-load 'isearch
(define-key isearch-mode-map (kbd "M-e") #'consult-isearch-history))
(with-eval-after-load 'minibuffer
(setopt completion-in-region-function #'consult-completion-in-region)
(define-key minibuffer-local-map (kbd "M-s") #'consult-history)
(define-key minibuffer-local-map (kbd "M-r") #'consult-history))
(with-eval-after-load 'simple
(add-hook 'completion-list-mode #'consult-preview-at-point-mode))
(with-eval-after-load 'register
(advice-add #'register-preview :override #'consult-register-window))
(with-eval-after-load 'xref
(setopt xref-show-xrefs-function #'consult-xref)
(setopt xref-show-definitions-function #'consult-xref))
(autoload-if-found '(affe-grep) "affe" nil t) (with-eval-after-load 'affe (setopt affe-count 100000) (setopt affe-highlight-function 'orderless-highlight-matches) (setopt affe-find-command "fd --color=never --full-path") (setopt affe-regexp-function 'orderless-pattern-compiler))
(autoload-if-found '(embark-act embark-dwim embark-prefix-help-command) "embark" nil t) (keymap-global-set "C-." #'embark-act) (keymap-global-set "C-h B" #'embark-prefix-help-command) (with-eval-after-load 'embark (defmacro my/embark-ace-action (fn) `(defun ,(intern (concat "my/embark-ace-" (symbol-name fn))) () (interactive) (with-demoted-errors "%s" (aw-switch-to-window (aw-select nil)) (call-interactively (symbol-function ',fn))))) (defmacro my/embark-split-action (fn split-type) `(defun ,(intern (concat "my/embark-" (symbol-name fn) "-" (car (last (split-string (symbol-name split-type) "-"))))) () (interactive) (funcall #',split-type) (call-interactively #',fn))) (defun my/sudo-find-file (file) "Open FILE as root." (interactive "FOpen file as root: ") (when (file-writable-p file) (user-error "File is user writeable, aborting sudo")) (find-file (if (file-remote-p file) (concat "/" (file-remote-p file 'method) ":" (file-remote-p file 'user) "@" (file-remote-p file 'host) "|sudo:root@" (file-remote-p file 'host) ":" (file-remote-p file 'localname)) (concat "/sudo:root@localhost:" file)))) (setopt embark-mixed-indicator-delay 0.1) (setopt prefix-help-command #'embark-prefix-help-command) (define-key embark-file-map (kbd "o") (my/embark-ace-action find-file)) (define-key embark-buffer-map (kbd "o") (my/embark-ace-action switch-to-buffer)) (define-key embark-bookmark-map (kbd "o") (my/embark-ace-action bookmark-jump)) (define-key embark-file-map (kbd "2") (my/embark-split-action find-file split-window-below)) (define-key embark-buffer-map (kbd "2") (my/embark-split-action switch-to-buffer split-window-below)) (define-key embark-bookmark-map (kbd "2") (my/embark-split-action bookmark-jump split-window-below)) (define-key embark-file-map (kbd "3") (my/embark-split-action find-file split-window-right)) (define-key embark-buffer-map (kbd "3") (my/embark-split-action switch-to-buffer split-window-right)) (define-key embark-bookmark-map (kbd "3") (my/embark-split-action bookmark-jump split-window-right)) (define-key embark-file-map (kbd "S") #'my/sudo-find-file) (define-key embark-general-map (kbd "C") #'copilot-chat-transient-code) (add-hook 'embark-collect-mode-hook #'consult-preview-at-point-mode))
(autoload-if-found '(compile-multi) "compile-multi" nil t) (keymap-global-set "C-x m" #'compile-multi)
(autoload-if-found '(vertico-mode) "vertico-autoloads" nil t) (add-hook 'after-init-hook #'vertico-mode) (with-eval-after-load 'vertico (setopt vertico-count 8) (setopt vertico-cycle t))
(autoload-if-found '(marginalia-mode marginalia-cycle) "marginalia" nil t) (add-hook 'after-init-hook #'marginalia-mode) (with-eval-after-load 'minibuffer (setopt marginalia-align-offset 25) (define-key minibuffer-local-map (kbd "M-A") #'marginalia-cycle))
(autoload-if-found '(orderless-all-completions orderless-try-completion) "orderless" nil t) (with-eval-after-load 'minibuffer (require 'orderless) (setopt completion-styles '(orderless initials flex basic)) (setopt completion-category-overrides '((file (styles flex basic partial-completion)))))
(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))
(autoload-if-found '(editorconfig-mode) "editorconfig" nil t)
(add-hook 'after-init-hook #'editorconfig-mode)
(autoload-if-found '(popwin-mode) "popwin" nil t)
(add-hook 'after-init-hook #'popwin-mode)
(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]))))
(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\\'")))
(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."))
(autoload-if-found '(vlf-disable-for-function) "vlf-setup" t) (with-eval-after-load 'dired (define-key dired-mode-map (kbd "V") #'dired-vlf))
(autoload-if-found '(sudo-edit-current-file) "sudo-edit" nil t)
(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))
(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))
(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")))
(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))
(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))
(autoload-if-found '(zoom-window-zoom) "zoom-window" nil t) (keymap-global-set "C-c C-z" #'zoom-window-zoom)
(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))))
(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))
(autoload-if-found '(avy-zap-up-to-char-dwim) "avy-zap" nil t) (keymap-global-set "M-z" #'avy-zap-up-to-char-dwim)
(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)
(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)
(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")))
(unless (eq system-type 'darwin) (autoload-if-found '() "mu4e-views" nil t))
(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")))
(autoload-if-found '(google-translate-at-point) "google-translate" nil t)
(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))
(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"))))
(autoload-if-found '(font-lock-studio) "font-lock-studio" nil t)
(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)))))
(autoload-if-found '(highlight-indent-guides-mode) "highlight-indent-guides" nil t)
(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"))))
(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))
(autoload-if-found '(global-emojify-mode) "emojify" nil t)
(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))
(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))
(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))))
(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))
(autoload-if-found '(warm-mode) "warm-mode" nil t)
(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))
(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)))))
(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"))
(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))
(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)))
(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))
(autoload-if-found '(volatile-highlights-mode) "volatile-highlights" nil t)
(add-hook 'after-init-hook #'volatile-highlights-mode)
(autoload-if-found '(topsy-mode) "topsy" nil t) (with-eval-after-load 'yaml-mode (add-hook 'yaml-mode-hook #'topsy-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))
(autoload-if-found '() "modus-themes" nil t)
(autoload-if-found '(hacker-typer) "hacker-typer" nil t)
(autoload-if-found '(power-mode) "power-mode" nil t)
(autoload-if-found '(sudden-death) "sudden-death" nil t)
(autoload-if-found '(arto-open arto-version) "arto" nil t) (with-eval-after-load 'arto (setopt arto-path "/Applications/Arto.app"))
(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)))
(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)
(autoload-if-found '(zalgo-transform-word
zalgo-mode
zalgo-transform-region) "zalgo-mode" nil t)
(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))
(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)
(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)
(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))))
(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))))))
(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))
https://github.com/ch11ng/exwm/wiki#gpg-pinentry
(autoload-if-found '(pinentry-start) "pinentry" nil t)
(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)
(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"))
(with-eval-after-load 'htmlize (setopt htmlize-html-charset 'utf-8))
(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))
(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))
(autoload-if-found '(inhibit-mouse-mode) "inhibit-mouse" nil t)
(add-hook 'after-init-hook #'inhibit-mouse-mode)
(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))))))
(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))
(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))
(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))
(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))))
(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))
(autoload-if-found '(eros-mode) "eros" nil t) (with-eval-after-load 'emacs-lisp (add-hook 'emacs-lisp-mode-hook #'eros-mode))
(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))
(autoload-if-found '(elsa-run) "elsa" nil t)
(autoload-if-found '(lispxmp) "lispxmp" nil t)
(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))
(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))
(autoload-if-found '(elisp-refs-function
elisp-refs-macro
elisp-refs-variable
elisp-refs-special
elisp-refs-symbol) "elisp-refs" nil t)
(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))
(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))
(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)))))
(autoload-if-found '(anakondo-minor-mode) "anakondo" nil t)
(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))
(autoload-if-found '(kibit kibit-current-file kibit-accept-proposed-change) "kibit-helper" nil t)
(autoload-if-found '(inf-clojure) "inf-clojure" nil t)
(autoload-if-found '(clang-format-buffer) "clang-format" nil t)
(autoload-if-found '(rainbow-csv-mode) "rainbow-csv" nil t) (with-eval-after-load 'csv-mode (add-hook 'csv-mode-hook #'rainbow-csv-mode))
(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))
(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))
(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))
(autoload-if-found '(robe-mode inf-ruby-console-auto) "robe" nil t)
(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))
(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))
(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))
(autoload-if-found '(yard-mode) "yard-mode" nil t) (with-eval-after-load 'ruby-mode (add-hook 'ruby-mode-hook #'yard-mode))
(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))
(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)
(autoload-if-found '(php-runtime-expr php-runtime-eval) "php-runtime" nil t)
(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))
(autoload-if-found '(php-doc-block) "php-doc-block" nil t)
(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))
(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))
(autoload-if-found '(poly-markdown-mode) "poly-markdown" nil t)
(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))
(autoload-if-found '(fish-repl) "fish-repl" nil t)
(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))
(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))
(autoload-if-found '(json-reformat-region) "json-reformat" nil t)
(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)
(autoload-if-found '(consult-dasel) "consult-dasel" nil t)
(autoload-if-found '(py-isort-region
py-isort-buffer
py-isort-before-save) "py-isort" nil t)
(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))
(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))
(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)
(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))
(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)
(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))
(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))
(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))
(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))
(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))
(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))
(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))
(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))
(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)))
(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))))
(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))
(with-eval-after-load 'org-list (setq org-list-allow-alphabetical t))
(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)))
(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%?"))))
(with-eval-after-load 'org-duration (setq org-duration-format (quote h:mm)))
(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)))
(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"))
(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))
(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"))
(autoload-if-found '(org-generate) "org-generate" nil t)
(autoload-if-found '(org-pomodoro) "org-pomodoro" nil t)
(autoload-if-found '(org-view-mode) "org-view-mode" nil t)
(autoload-if-found '(org-random-todo org-random-todo-goto-current) "org-random-todo" nil t)
(autoload-if-found '(org-dashboard-display) "org-dashboard" nil t)
(autoload-if-found '(org-volume-update-entry-from-dblock) "org-volume" nil t)
(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))
(autoload-if-found '(org-ql-query org-ql-select) "org-ql" nil t)
(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))
(with-eval-after-load 'org-faces (setq org-link '(t (:foreground "#ebe087" :underline t))))
(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 " "))
(autoload-if-found '(toc-org-mode) "toc-org" nil t) (with-eval-after-load 'org (add-hook 'org-mode-hook #'toc-org-mode))
(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))
(autoload-if-found '(org-store-link) "ol" nil t) (with-eval-after-load 'ol (setq org-link-file-path-type 'relative))
(autoload-if-found '(orgit-store-link
orgit-status-store
orgit-status-open
orgit-status-export
orgit-status-complete-link
orgit-log-store
orgit-log-open
orgit-log-export
orgit-log-complete-link
orgit-rev-store
orgit-rev-open
orgit-rev-export
orgit-rev-complete-link) "orgit" nil t)
(with-eval-after-load 'org
(org-link-set-parameters "orgit"
:store #'orgit-status-store
:follow #'orgit-status-open
:export #'orgit-status-export
:complete #'orgit-status-complete-link)
(org-link-set-parameters "orgit-log"
:store #'orgit-log-store
:follow #'orgit-log-open
:export #'orgit-log-export
:complete #'orgit-log-complete-link)
(org-link-set-parameters "orgit-rev"
:store #'orgit-rev-store
:follow #'orgit-rev-open
:export #'orgit-rev-export
:complete #'orgit-rev-complete-link))
(with-eval-after-load 'magit
(keymap-set magit-mode-map "<remap> <org-store-link>" #'orgit-store-link))
(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))
(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"))))))))))))
(autoload-if-found '(org-hyperscheduler-open) "org-hyperscheduler" nil t)
(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%"))))
(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"))
(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))
(autoload-if-found '(ob-async-org-babel-execute-src-block) "ob-async" nil t)
(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)))
(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)))
(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)))
(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)))
(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)))
(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)))
(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)))
(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)))
(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)))
(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)))
(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)))
(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)))
(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)))
(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)))
(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)))
(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)))
(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)))
(with-eval-after-load 'ob-lisp (defalias 'org-babel-execute:common-lisp 'org-babel-execute:lisp))
(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)))
(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)))
(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)))
(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)))
(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))
(autoload-if-found '(org-export-define-backend) "ox" nil t)
(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))
(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)
(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)
(autoload-if-found '(org-hatena-export-as-hatena
org-hatena-export-to-hatena
org-hatena-export-to-hatena-and-open) "ox-hatena" nil t)
(autoload-if-found '(org-qmd-export-as-markdown
org-qmd-convert-region-to-md
org-qmd-export-to-markdown) "ox-qmd" nil t)
(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))
(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)))
(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")))
(autoload-if-found '(org-roam-buffer-toggle) "org-roam-mode" nil t)
(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))
(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)))
(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))))
(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))
(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))
(autoload-if-found '(org-roam-graph org-roam-graph--open) "org-roam-graph" nil t)
(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))
(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))
(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))
(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))
(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))
(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)
(autoload-if-found '(org-roam-ql-ql-init) "org-roam-ql-ql" nil t)
(add-hook 'after-init-hook #'org-roam-ql-ql-init)
(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))
(autoload-if-found '(citar-embark-mode) "citar-embark" nil t) (with-eval-after-load 'citar (citar-embark-mode 1))
(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}"))
(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))
(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"))
(defun my/beginning-of-intendation () "move to beginning of line, or indentation" (interactive) (back-to-indentation))
(defun my/copy-buffer () (interactive) (save-excursion (mark-whole-buffer) (copy-region-as-kill (region-beginning) (region-end))))
(defun my/gh-browse () (interactive) (message (shell-command-to-string (mapconcat #'shell-quote-argument (list "gh" "browse") " "))))
(defun my/indent-buffer () (interactive) (save-excursion (mark-whole-buffer) (untabify (region-beginning) (region-end)) (indent-region (region-beginning) (region-end))))
(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)
(defun my/reload-major-mode () "Reload current major mode." (interactive) (let ((current-mode major-mode)) (fundamental-mode) (funcall current-mode) current-mode))
(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))))
(defun my/insert-clipboard (arg) (interactive "sstring: ") (kill-new arg))
(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)))
(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))))
(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)))))
(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)))))
(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)))
(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)))
(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)))
(setq file-name-handler-alist my/saved-file-name-handler-alist)
daemonは after-init-hook を実行し終えるまでserver socketを公開しない.
起動時間を測る2関数以外をtimerで1関数ずつ実行し, その間もemacsclientに応答できるようにする.
最初のframeが作られた時点で残りをまとめて実行するので, frameからは従来と同じmodeが有効に見える.
(defvar my/deferred-after-init-functions nil "`after-init-hook' functions the daemon runs after starting its server.") (defun my/run-deferred-after-init-function (fn) "Call FN, logging an error instead of aborting the caller." (with-demoted-errors "Deferred after-init function failed: %S" (funcall fn))) (defun my/flush-deferred-after-init-functions (&rest _) "Run every remaining deferred `after-init-hook' function now." (remove-hook 'after-make-frame-functions #'my/flush-deferred-after-init-functions) (while my/deferred-after-init-functions (my/run-deferred-after-init-function (pop my/deferred-after-init-functions)))) (defun my/schedule-deferred-after-init-function () "Run the next deferred `after-init-hook' function from a timer." ;; With a zero delay the whole chain ran before emacsclient got a reply; ;; a short delay lets Emacs accept connections between functions. (run-with-timer 0.01 nil #'my/run-next-deferred-after-init-function)) (defun my/run-next-deferred-after-init-function () "Run one deferred `after-init-hook' function and schedule the next." (if (null my/deferred-after-init-functions) (remove-hook 'after-make-frame-functions #'my/flush-deferred-after-init-functions) (my/schedule-deferred-after-init-function) (my/run-deferred-after-init-function (pop my/deferred-after-init-functions)))) (when (daemonp) (let ((kept '(my/load-init-time my/emacs-init-time))) (setq my/deferred-after-init-functions (seq-remove (lambda (fn) (memq fn kept)) after-init-hook)) (setq after-init-hook (seq-filter (lambda (fn) (memq fn kept)) after-init-hook))) (add-hook 'after-init-hook #'my/schedule-deferred-after-init-function) (add-hook 'after-make-frame-functions #'my/flush-deferred-after-init-functions -100))
(when my/enable-profile
(profiler-report)
(profiler-stop))
Created: 2026-10-07 Wed 09:21