Last active
October 29, 2024 15:37
-
-
Save Ladicle/6825bf1e16987e0d5e4347b2de91339d to your computer and use it in GitHub Desktop.
Emacs Configuration 2024
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;;; early-init.el --- load before init.el | |
;;; Commentary: | |
;;; Code: | |
(custom-set-variables | |
;; custom-set-variables was added by Custom. | |
;; If you edit it by hand, you could mess it up, so be careful. | |
;; Your init file should contain only one such instance. | |
;; If there is more than one, they won't work right. | |
'(inhibit-startup-screen t) | |
'(inhibit-startup-message t) | |
'(inhibit-startup-echo-area-message t) | |
'(initial-scratch-message nil) | |
'(initial-frame-alist | |
'((left-fringe . 0) | |
(right-fringe . 0) | |
(internal-border-width . 8) | |
(tool-bar-lines . 0))) | |
'(menu-bar-mode nil) | |
'(scroll-bar-mode nil) | |
'(tool-bar-mode nil) | |
'(initial-buffer-choice t) | |
'(initial-major-mode 'fundamental-mode) | |
'(frame-inhibit-implied-resize t) | |
'(frame-title-format nil) | |
'(cursor-in-non-selected-windows nil) | |
'(font-lock-maximum-decoration nil) | |
'(font-lock-maximum-size nil) | |
'(x-underline-at-descent-line t) | |
'(window-divider-default-right-width 16) | |
'(window-divider-default-places 'right-only) | |
'(gc-cons-threshold most-positive-fixnum)) | |
;; For Emacs v29 | |
(add-to-list 'default-frame-alist '(undecorated . t)) | |
(provide 'early-init) | |
;;; early-init.el ends here |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;;; init.el --- ladicle's init.el -*- lexical-binding: t; -*- | |
;;; Commentary: | |
;;; Code: | |
;; (require 'profiler) | |
;; (profiler-start 'cpu) | |
;; Temporally disabled magic files for Performance | |
(defconst my:saved-file-name-handler-alist file-name-handler-alist) | |
(setq file-name-handler-alist nil) | |
(add-hook 'emacs-startup-hook | |
(lambda () | |
(setq file-name-handler-alist my:saved-file-name-handler-alist))) | |
;; Temporally Maximize GC | |
(setq gc-cons-threshold most-positive-fixnum) | |
(eval-and-compile | |
(when (or load-file-name byte-compile-current-file) | |
(setq user-emacs-directory | |
(expand-file-name | |
(file-name-directory (or load-file-name byte-compile-current-file)))))) | |
;; Initialize package manager for compile time | |
(eval-and-compile | |
(customize-set-variable | |
'package-archives '(("org" . "https://orgmode.org/elpa/") | |
("melpa" . "https://melpa.org/packages/") | |
("gnu" . "https://elpa.gnu.org/packages/"))) | |
(package-initialize) | |
(unless (package-installed-p 'leaf) | |
(package-refresh-contents) | |
(package-install 'leaf)) | |
;; Leaf keywords | |
(leaf leaf-keywords | |
:doc "Use leaf as a package manager" | |
:url "https://github.com/conao3/leaf.el" | |
:ensure t | |
:init | |
(leaf el-get | |
:ensure t | |
:custom | |
(el-get-notify-type . 'message) | |
(el-get-git-shallow-clone . t)) | |
(leaf hydra :ensure t) | |
:config | |
(leaf-keywords-init))) | |
;; Compile | |
(eval-and-compile | |
(leaf *byte-compile | |
:custom | |
(byte-compile-warnings . '(not free-vars docstrings lexical unresolved constants)) | |
(warning-suppress-types . '(comp)) | |
(debug-on-error . nil))) | |
;; Package Manager | |
(leaf package-utils | |
:doc "Interactive package manager" | |
:url "https://github.com/Silex/package-utils" | |
:ensure t) | |
;; ----------------------------------------------------------------------------------------- | |
;; | |
;; Generic Configurations | |
;; | |
;; ----------------------------------------------------------------------------------------- | |
;; Silencer | |
(leaf cus-edit | |
:doc "tools for customizing Emacs and Lisp packages" | |
:custom `((custom-file . ,(locate-user-emacs-file "custom.el")))) | |
(leaf no-littering | |
:doc "Keep .emacs.d clean" | |
:url "https://github.com/emacscollective/no-littering" | |
:ensure t) | |
(leaf *to-be-quiet | |
:doc "Quite annoying messages" | |
:preface | |
(defun display-startup-echo-area-message () | |
"no startup message" | |
(message "")) | |
:custom | |
(ring-bell-function . 'ignore) | |
:config | |
(defalias 'yes-or-no-p #'y-or-n-p)) | |
(leaf *server | |
:doc "Use Emacs as a Server" | |
:global-minor-mode server-mode | |
:custom | |
(confirm-kill-emacs . #'yes-or-no-p)) | |
(leaf *encoding | |
:doc "It's time to use UTF-8" | |
:config | |
(set-locale-environment "en_US.UTF-8") | |
(prefer-coding-system 'utf-8-unix) | |
(set-default-coding-systems 'utf-8-unix) | |
(set-selection-coding-system 'utf-8-unix) | |
(set-buffer-file-coding-system 'utf-8-unix)) | |
(leaf *formatting | |
:custom | |
(truncate-lines . t) | |
(require-final-newline . t) | |
(tab-width . 2) | |
(indent-tabs-mode . nil)) | |
(leaf *autorevert | |
:doc "Revert changes if local file is updated" | |
:global-minor-mode global-auto-revert-mode | |
:custom (auto-revert-interval . 0.1)) | |
(leaf *recovery | |
:doc "Save place of cursor" | |
:global-minor-mode save-place-mode) | |
(leaf *tramp | |
:doc "Edit remote file via SSH or SCP" | |
:custom | |
(tramp-auto-save-directory . "~/.emacs.d/.cache/tramp/") | |
(tramp-default-remote-shell . "/bin/bash")) | |
(leaf *history | |
:doc "save history of minibuffer" | |
:hook (after-init-hook . savehist-mode) | |
:custom | |
(savehist-additional-variables . '(kill-ring consult-shell-command-history))) | |
(leaf backup | |
:custom | |
(make-backup-files . nil) | |
(auto-save-default . nil)) | |
(leaf *recentf | |
:doc "Record open files history" | |
:global-minor-mode recentf-mode | |
:custom | |
(recentf-max-saved-items . 20000) | |
(recentf-max-menu-items . 20000) | |
(recentf-auto-cleanup . 'never) | |
(recentf-exclude | |
. '((expand-file-name package-user-dir) | |
".cache" | |
"cache" | |
"bookmarks" | |
"recentf" | |
"*.png" | |
"*.jpeg" | |
".org_archive" | |
"COMMIT_EDITMSG\\'"))) | |
(leaf *large-file | |
:doc "Adjust large file threshold" | |
:custom | |
(large-file-warning-threshold . 1000000)) | |
;; Basic Editing Operation | |
(leaf *delsel | |
:doc "Replace the region just by typing text, or delete just by hitting the DEL key" | |
:global-minor-mode delete-selection-mode) | |
(leaf undo-fu | |
:doc "Redo and Undo operations" | |
:url "https://github.com/emacsmirror/undo-fu" | |
:ensure t | |
:bind | |
("C-/" . undo-fu-only-undo) | |
("M-/" . undo-fu-only-redo)) | |
(leaf string-inflection :ensure t) | |
;; ----------------------------------------------------------------------------------------- | |
;; | |
;; Window System | |
;; | |
;; ----------------------------------------------------------------------------------------- | |
(leaf *adjust-frame-position | |
:doc "Place frame on the right side of the screen" | |
:if (window-system) | |
:config | |
;; for not-titlebar frame | |
(setq frame-resize-pixelwise t)) | |
;; Font Size checker | |
;; | |
;; |∞≤≥∏∑∫ ×±⊆⊇| | |
;; |αβγδεζ ηθικλu| | |
;; |abcdef ghijkl| | |
;; |ABCDEF GHIJKL| | |
;; |'";:-+ =/\~`?| | |
;; |日本語 の美観| | |
;; |あいう えおか| | |
;; |アイウ エオカ| | |
;; |アイウエオカ キクケコサシ| | |
;; | |
;; | hoge | hogeghoe | age | | |
;; |----------------------+----------+-------------------| | |
;; | 今日もいい天気ですね | お、 | 等幅になった :+1: | | |
(leaf font | |
:doc "Use Nerd & Adjust font size" | |
:if (window-system) | |
:preface | |
(defun set-fonts (name family) | |
(set-fontset-font name 'japanese-jisx0208 (font-spec :family family)) | |
(set-fontset-font name 'japanese-jisx0212 (font-spec :family family)) | |
(set-fontset-font name 'jisx0201 (font-spec :family family)) | |
(set-fontset-font name 'han (font-spec :family family)) | |
(set-fontset-font name 'kana (font-spec :family family)) | |
(set-fontset-font name 'ascii (font-spec :family family)) | |
(set-fontset-font name 'latin (font-spec :family family)) | |
(set-fontset-font name 'greek (font-spec :family family)) | |
(set-fontset-font name 'arabic (font-spec :family family)) | |
(set-fontset-font name 'symbol (font-spec :family family))) | |
(defun ladicle-setup-fonts () | |
(set-fonts nil japanese-font-family) | |
;; NOTE: Adjust font size depends on macOS display resolution (currently use default scale) | |
(set-face-attribute 'default nil :family japanese-font-family :height 140) | |
(set-face-attribute 'default t :family japanese-font-family :height 140) | |
(set-fontset-font nil 'emoji (font-spec :family emoji-font-family :slant 'normal)) | |
;; NOTE: [workaround]: without this setting, some unicode characters to be italic. | |
(set-fontset-font t 'unicode (font-spec :slant 'normal))) | |
(defun ladicle-post-setup-fonts () | |
(set-fonts t japanese-font-family) | |
(set-face-attribute 'default t :family japanese-font-family :height 140) | |
(set-fontset-font t 'emoji (font-spec :family emoji-font-family :slant 'normal))) | |
:custom | |
(japanese-font-family . "SF Mono Square") | |
(emoji-font-family . "Twitter Color Emoji") | |
:hook | |
(after-init-hook . ladicle-post-setup-fonts) | |
(dashboard-mode-hook . ladicle-setup-fonts)) | |
;; ----------------------------------------------------------------------------------------- | |
;; | |
;; Japanese Input | |
;; | |
;; ----------------------------------------------------------------------------------------- | |
(leaf ddskk | |
:doc "Simple Kana to Kanji conversion program" | |
:url "https://ddskk.read thedocs.io/ja/latest/index.html" | |
:ensure t | |
:require ccc ; Package for change cursor color | |
:bind | |
("M-l" . skk-mode) | |
:bind* | |
("C-x C-j" . skk-mode) | |
:hook | |
(skk-mode-hook . (lambda () (define-key skk-j-mode-map "l" 'skk-mode))) | |
:custom | |
(mac-pass-control-to-system . nil) | |
(default-input-method . "japanese-skk") | |
(skk-user-directory . "~/.emacs.d/var/ddskk") | |
(skk-server-host . "localhost") ; Use yaskkserv2 | |
(skk-show-candidates-nth-henkan-char . 1) | |
(skk-server-portnum . 1178) ; Use AquaSKK as a dictionary Server. | |
(skk-egg-like-newline . nil) ; Insert new line by <enter> during converting. | |
(skk-auto-insert-paren . t) ; Auto-insert corresponding parentheses. | |
(skk-use-auto-enclose-pair-of-region . t) ; 選択範囲を括弧で囲む | |
(skk-henkan-strict-okuri-precedence . t) ; 送り仮名 makes conversion content smarter. | |
(skk-delete-implies-kakutei . nil) ; Type <delete> during converting, select previous candidate. | |
(skk-isearch-start-mode . 'latin) ; Disabled SKK in isearch. | |
(skk-dcomp-multiple-activate . t) ; 動的補完で候補を複数表示する | |
(skk-dcomp-multiple-rows . 5) ; 動的補完の候補数 | |
(skk-use-search-web . t) | |
(skk-cursor-hiragana-color . "#ff79c6") | |
(skk-cursor-katakana-color . "#50fa7b") | |
(skk-cursor-latin-color . "cyan") | |
:custom-face | |
(skk-prefix-hiragana-face . '((t (:foreground "#ff79c6")))) | |
(skk-prefix-katakana-face . '((t (:foreground "#50fa7b")))) | |
(skk-henkan-rest-indicator-face . '((t (:foreground "#8995ba")))) | |
(skk-dcomp-multiple-face . '((t (:background "#282a36" :foreground "#8995ba")))) | |
(skk-dcomp-multiple-trailing-face . '((t (:foreground "#6272a4" :weight normal)))) | |
(skk-dcomp-multiple-selected-face . '((t (:background "#3B4252")))) | |
:preface | |
(defun skk-set-display-table () | |
(walk-windows (lambda (w) | |
(let ((disptab (make-display-table))) | |
(aset disptab ?\▼ (vector (make-glyph-code ?\ue007 'escape-glyph))) ; or \uf0eb | |
(aset disptab ?\▽ (vector (make-glyph-code ?\uf107 'escape-glyph))) | |
(set-window-display-table w disptab))))) | |
:hook | |
(window-configuration-change-hook . skk-set-display-table)) | |
(leaf ddskk-posframe | |
:doc "SKK interface using posframe" | |
:url "https://github.com/conao3/ddskk-posframe.el" | |
:ensure t | |
:custom | |
(ddskk-posframe-mode . t) | |
(ddskk-posframe-font . japanese-font-family) | |
:custom-face | |
(ddskk-posframe . '((t (:background "#282a36" :foreground "#8995ba")))) | |
(ddskk-posframe-border . '((t (:background "#323445"))))) | |
;; NOTE: Required to enable Accessibility in Security Settings panel at first time. | |
;; If it does not work, try removing and adding Emacs to Accessibility again. | |
;; After reinstall or upgrade Emacs, remove and add app again in the accessibility panel. | |
;; https://stackoverflow.com/questions/54973241/applescript-application-is-not-allowed-to-send-keystrokes | |
(leaf always-eisuu-on-emacs | |
:config | |
(when (eq system-type 'darwin) | |
(add-function | |
:after after-focus-change-function | |
(lambda () | |
(if (frame-focus-state) | |
(progn | |
(do-applescript "tell application \"System Events\" to key code 102"))))))) ; send eisuu | |
;; ----------------------------------------------------------------------------------------- | |
;; | |
;; MacOS | |
;; | |
;; ----------------------------------------------------------------------------------------- | |
(leaf *pbcopy-and-pbpaste | |
:if (equal system-type 'darwin) | |
:preface | |
:custom | |
(mac-option-modifier . 'super) | |
(mac-command-modifier . 'meta)) | |
(leaf exec-path-from-shell | |
:doc "Share PATH from shell environment variables" | |
:url "https://github.com/purcell/exec-path-from-shell" | |
:ensure t | |
:if (and (equal system-type 'darwin) (window-system)) | |
:custom | |
(exec-path-from-shell-check-startup-files . nil) | |
(exec-path-from-shell-variables . '("PATH" "GOPATH" "LANG")) | |
:init | |
(setq exec-path (parse-colon-path (string-trim-right (shell-command-to-string "echo $PATH")))) | |
(setenv "PATH" (string-trim-right (shell-command-to-string "echo $PATH"))) | |
(setenv "GOPATH" (string-trim-right (shell-command-to-string "echo $GOPATH")))) | |
;; ----------------------------------------------------------------------------------------- | |
;; | |
;; Terminal | |
;; | |
;; ----------------------------------------------------------------------------------------- | |
(leaf vterm | |
:doc "Emacs libvterm integration" | |
:url "https://github.com/akermu/emacs-libvterm" | |
:ensure t | |
:custom | |
(cursor-type . 'bar) | |
(vterm-ignore-blink-cursor . t) | |
:bind | |
(:vterm-mode-map | |
("C-c C-l" . vterm-clear) | |
("C-o" . previous-window-any-frame)) | |
:custom-face | |
(vterm-color-red . '((t (:foreground "#ff79c6" :background "#ff9ad4")))) | |
(vterm-color-magenta . '((t (:foreground "#bd93f9" :background "#a9a1e1"))))) | |
(leaf vterm-toggle | |
:doc "Toggles between the vterm buffer and whatever buffer you are editing." | |
:url "https://github.com/jixiuf/vterm-toggle" | |
:ensure t | |
:bind | |
("<f12>" . vterm-toggle-cd-show) | |
("C-<f12>" . vterm-toggle-show) | |
(:vterm-mode-map | |
("<f12>" . vterm-toggle-hide) | |
("C-<enter>" . vterm-toggle-insert-cd) | |
("S-<right>" . vterm-toggle-forward) | |
("S-<left>" . vterm-toggle-backward)) | |
:custom | |
(vterm-toggle-cd-auto-create-buffer . t) | |
(vterm-toggle-fullscreen-p . nil) | |
(vterm-toggle-scope . 'project) | |
:config | |
(add-to-list 'display-buffer-alist | |
'((lambda (buffer-or-name _) | |
(let ((buffer (get-buffer buffer-or-name))) | |
(with-current-buffer buffer | |
(or (equal major-mode 'vterm-mode) | |
(string-prefix-p vterm-buffer-name (buffer-name buffer)))))) | |
(display-buffer-reuse-window display-buffer-in-direction) | |
(direction . bottom) | |
(dedicated . t) | |
(reusable-frames . visible) | |
(window-height . 0.3)))) | |
;; ----------------------------------------------------------------------------------------- | |
;; | |
;; Brackets Guide | |
;; | |
;; ----------------------------------------------------------------------------------------- | |
(leaf smartparens | |
:ensure t | |
:require smartparens-config | |
:global-minor-mode smartparens-global-mode | |
:bind | |
(:smartparens-mode-map | |
("M-<DEL>" . sp-backward-unwrap-sexp) | |
("M-]" . sp-up-sexp) | |
("M-[" . sp-down-sexp) | |
("C-(" . sp-beginning-of-sexp) | |
("C-)" . sp-end-of-sexp) | |
("C-M-f" . sp-forward-sexp) | |
("C-M-b" . sp-backward-sexp) | |
("C-M-n" . sp-next-sexp) | |
("C-M-p" . sp-previous-sexp)) | |
:config | |
(sp-local-pair 'org-mode "*" "*") | |
(sp-local-pair 'org-mode "=" "=") | |
(sp-local-pair 'org-mode "~" "~") | |
(sp-local-pair 'org-mode "+" "+")) | |
;; ----------------------------------------------------------------------------------------- | |
;; | |
;; Custom Functions | |
;; | |
;; ----------------------------------------------------------------------------------------- | |
(leaf *convert-letter-case | |
:bind | |
(("M-u" . upcase-backward-word) | |
("M-_" . downcase-backward-word) | |
("M-c" . capitalize-backward-word)) | |
:preface | |
(defun upcase-backward-word (arg) | |
(interactive "p") | |
(upcase-word (- arg))) | |
(defun downcase-backward-word (arg) | |
(interactive "p") | |
(downcase-word (- arg))) | |
(defun capitalize-backward-word (arg) | |
(interactive "p") | |
(capitalize-word (- arg)))) | |
(leaf *smart-kill | |
:bind | |
(("M-d" . kill-word-at-point) | |
("C-w" . backward-kill-word-or-region)) | |
:init | |
(defun kill-word-at-point () | |
(interactive) | |
(let ((char (char-to-string (char-after (point))))) | |
(cond | |
((string= " " char) (delete-horizontal-space)) | |
((string-match "[\t\n -@\[-`{-~],.、。" char) (kill-word 1)) | |
(t (forward-char) (backward-word) (kill-word 1))))) | |
(defun backward-kill-word-or-region (&optional arg) | |
(interactive "p") | |
(if (region-active-p) | |
(call-interactively #'kill-region) | |
(backward-kill-word arg)))) | |
(leaf *copy-info-to-clipboard | |
:preface | |
(defun browse-url-or-copy () | |
"Browse URL if window-sytem otherwise copy it" | |
(interactive) | |
(if (window-system) | |
(browse-url-at-point) | |
(kill-new (thing-at-point-url-at-point))))) | |
(leaf *chmod-executable-file | |
:doc "Change file mode to executable if it has shebang" | |
:hook (after-save-hook . executable-make-buffer-file-executable-if-script-p)) | |
;; ----------------------------------------------------------------------------------------- | |
;; | |
;; Cursor | |
;; | |
;; ----------------------------------------------------------------------------------------- | |
(leaf *general-cursor-options | |
:custom | |
(kill-whole-line . t) | |
(track-eol . t) | |
(line-move-visual . nil)) | |
(leaf mwim | |
:doc "Move cursor to beginning/end of code or line" | |
:url "https://github.com/alezost/mwim.el" | |
:ensure t | |
:bind | |
(("C-a" . mwim-beginning-of-code-or-line) | |
("C-e" . mwim-end-of-code-or-line))) | |
;; Avy | |
(leaf avy | |
:doc "Jump to things in tree-style" | |
:url "https://github.com/abo-abo/avy" | |
:ensure t) | |
(leaf avy-zap | |
:doc "Zap to char using avy" | |
:url "https://github.com/cute-jumper/avy-zap" | |
:ensure t) | |
(leaf dmacro | |
:doc "dynamic macro" | |
:load-path "~/.emacs.d/el-get/dmacro" | |
:config | |
(defconst *dmacro-key* "\C-t") | |
(global-set-key *dmacro-key* 'dmacro-exec) | |
(autoload 'dmacro-exec "dmacro" nil t)) | |
;; ----------------------------------------------------------------------------------------- | |
;; | |
;; Window Layout | |
;; | |
;; ----------------------------------------------------------------------------------------- | |
(leaf split-threshold | |
:custom | |
(split-height-threshold . nil) | |
(split-width-threshold . 160)) | |
(leaf ace-window | |
:doc "Select window like tmux" | |
:url "https://github.com/abo-abo/ace-window" | |
:ensure t | |
:bind | |
("C-o" . ace-window) | |
:custom | |
(aw-keys . '(?j ?k ?l ?i ?o ?h ?y ?u ?p)) | |
:custom-face | |
(aw-leading-char-face . '((t (:height 4.0 :foreground "#f1fa8c"))))) | |
(leaf rotate | |
:doc "Rotate the layout like tmux panel" | |
:url "https://github.com/daichirata/emacs-rotate" | |
:el-get "daichirata/emacs-rotate" | |
:require t) | |
(leaf presentation | |
:doc "Scale all for presentation" | |
:url "https://github.com/zonuexe/emacs-presentation-mode" | |
:if (window-system) | |
:ensure t) | |
(leaf *window-maximizer | |
:doc "Maximize current window" | |
:if (window-system) | |
:custom | |
(is-window-maximized . nil) | |
:preface | |
(defun toggle-window-maximize () | |
(interactive) | |
(progn | |
(if is-window-maximized | |
(balance-windows) | |
(maximize-window)) | |
(setq is-window-maximized | |
(not is-window-maximized))))) | |
(leaf *window-transparency | |
:doc "Set window transparency level" | |
:if (window-system) | |
:hook (after-init-hook . toggle-window-transparency) | |
:custom | |
(window-transparency . 82) | |
:preface | |
(defun toggle-window-transparency () | |
"Cycle the frame transparency from default to transparent." | |
(interactive) | |
(let ((transparency window-transparency) | |
(opacity 100)) | |
(if (and (not (eq (frame-parameter nil 'alpha) nil)) | |
(< (frame-parameter nil 'alpha) opacity)) | |
(set-frame-parameter nil 'alpha opacity) | |
(set-frame-parameter nil 'alpha transparency))))) | |
;; ----------------------------------------------------------------------------------------- | |
;; | |
;; Error Checker | |
;; | |
;; ----------------------------------------------------------------------------------------- | |
(leaf flyspell | |
:doc "Spell checker" | |
:url "https://www.emacswiki.org/emacs/FlySpell" | |
:if (executable-find "aspell") | |
:ensure t | |
:hook | |
(prog-mode-hook . flyspell-prog-mode) | |
((markdown-mode-hook git-commit-mode-hook) . flyspell-mode) | |
:custom | |
(ispell-program-name . "aspell") | |
(ispell-extra-args . '("--sug-mode=ultra" "--lang=en_US" "--run-together")) | |
:custom-face | |
(flyspell-incorrect . '((t (:underline (:color "#f1fa8c" :style wave))))) | |
(flyspell-duplicate . '((t (:underline (:color "#50fa7b" :style wave)))))) | |
(leaf flyspell-correct | |
:doc "Correcting misspelled words with flyspell using favourite interface" | |
:url "https://github.com/d12frosted/flyspell-correct" | |
:ensure t | |
:bind* | |
("C-M-i" . flyspell-correct-at-point) | |
:custom | |
(flyspell-correct-interface . #'flyspell-correct-completing-read)) | |
;; ----------------------------------------------------------------------------------------- | |
;; | |
;; Tools | |
;; | |
;; ----------------------------------------------------------------------------------------- | |
;; Git ------------------------------------------------------------------------------------ | |
(leaf *git-commit-mode | |
:doc "Mode for git commit message editing" | |
:mode "\\COMMIT_EDITMSG\\'") | |
(leaf git-modes | |
:doc "Modes for git configuration files" | |
:url "https://github.com/magit/git-modes" | |
:ensure t) | |
(leaf magit | |
:doc "Complete text-based user interface to Git" | |
:url "https://magit.vc/" | |
:ensure t | |
:init | |
(setq magit-auto-revert-mode nil)) | |
(leaf git-gutter | |
:doc "Show git status in fringe & operate hunks" | |
:url "https://github.com/emacsorphanage/git-gutter" | |
:ensure t | |
:global-minor-mode global-git-gutter-mode | |
:custom | |
(git-gutter:modified-sign . "┃") | |
(git-gutter:added-sign . "┃") | |
(git-gutter:deleted-sign . "┃") | |
:custom-face | |
(git-gutter:modified . '((t (:foreground "#f1fa8c")))) | |
(git-gutter:added . '((t (:foreground "#50fa7b")))) | |
(git-gutter:deleted . '((t (:foreground "#ff79c6"))))) | |
(leaf browse-at-remote | |
:doc "Browse target page on github/bitbucket" | |
:url "https://github.com/rmuslimov/browse-at-remote" | |
:ensure t | |
:preface | |
(defun browse-at-remote-or-copy () | |
(interactive) | |
(if (window-system) | |
(browse-at-remote) | |
(browse-at-remote-kill))) | |
:custom | |
(browse-at-remote-prefer-symbolic . nil)) | |
(leaf smerge-mode | |
:doc "Manage git confliction" | |
:ensure t | |
:preface | |
(defun start-smerge-mode-with-hydra () | |
(interactive) | |
(progn | |
(smerge-mode 1) | |
(smerge-mode/body))) | |
:pretty-hydra | |
((:color blue :quit-key "q" :foreign-keys warn) | |
("Move" | |
(("n" smerge-next "next") | |
("p" smerge-prev "preview")) | |
"Keep" | |
(("b" smerge-keep-base "base") | |
("u" smerge-keep-upper "upper") | |
("l" smerge-keep-lower "lower") | |
("a" smerge-keep-all "both") | |
("\C-m" smerge-keep-current "current")) | |
"Others" | |
(("C" smerge-combine-with-next "combine with next") | |
("r" smerge-resolve "resolve") | |
("k" smerge-kill-current "kill current")) | |
"End" | |
(("ZZ" (lambda () | |
(interactive) | |
(save-buffer) | |
(bury-buffer)) | |
"Save and bury buffer" :color blue) | |
("q" nil "cancel" :color blue))))) | |
;; ----------------------------------------------------------------------------------------- | |
;; | |
;; Programming Mode | |
;; | |
;; ----------------------------------------------------------------------------------------- | |
(leaf quickrun | |
:doc "Run program quickly" | |
:url "https://github.com/emacsorphanage/quickrun" | |
:ensure t | |
:require t) | |
(leaf yasnippet | |
:doc "Template system" | |
:url "https://github.com/joaotavora/yasnippet" | |
:ensure t | |
:hook ((after-init-hook . yas-reload-all) | |
(prog-mode-hook . yas-minor-mode)) | |
:custom (yas-snippet-dirs . '("~/.emacs.d/snippets"))) | |
(leaf lsp-bridge | |
:doc "fast LSP client" | |
:url "https://github.com/manateelazycat/lsp-bridge" | |
:el-get "manateelazycat/lsp-bridge" | |
:require t | |
:hook | |
((go-mode-hook | |
python-mode-hook | |
emacs-lisp-mode-hook | |
fish-mode-hook | |
protobuf-mode-hook | |
dockerfile-mode-hook | |
terraform-mode-hook | |
yaml-mode-hook | |
markdown-mode-hook) | |
. (lambda () | |
(yas-minor-mode) | |
(lsp-bridge-mode))) | |
:custom-face | |
(acm-frame-select-face . '((t (:background "#44475a" :foreground "cyan")))) | |
(acm-frame-default-face . '((t (:background "#323445")))) | |
:bind | |
(:lsp-bridge-mode-map | |
("C-c C-j" . lsp-bridge-find-def) | |
("C-c C-s-j" . lsp-bridge-find-def-other-window) | |
("C-c r" . lsp-bridge-rename) | |
("C-c C-c" . lsp-bridge-code-action) | |
("C-c C-r" . lsp-bridge-find-references) | |
("C-c i" . lsp-bridge-find-impl) | |
("C-c I" . lsp-bridge-find-impl-other-window) | |
("C-c d" . lsp-bridge-popup-documentation)) | |
:custom | |
(acm-enable-tabnine . nil) | |
(acm-enable-copilot . t) | |
(acm-enable-quick-access . t) | |
(lsp-bridge-enable-hover-diagnostic . t) | |
(acm-backend-yas-candidates-number . 5) | |
;; Icon Collections: | |
;; - bootstrap: https://icons.getbootstrap.com/ | |
;; - material: https://pictogrammers.com/library/mdi/ | |
;; - octicons: https://primer.style/design/foundations/icons | |
;; - boxicons: https://boxicons.com/ | |
;; customize icons, then run `acm-icon-fetch-all' | |
(acm-icon-alist | |
. `(("unknown" . ("material" "file-find-outline" "#74d2e7")) | |
("text" . ("material" "format-text" "#98c807")) | |
("method" . ("material" "function-variant" "#a76efa")) | |
("function" . ("material" "function" "#bd93f9")) | |
("fun" . ("material" "function-variant" "#0abf53")) | |
("constructor" . ("material" "all-inclusive" "#7ac143")) | |
("search" . ("material" "alphabetical-variant" "#6272a4")) | |
("ctor" . ("material" "cube" "#b84592")) | |
("field" . ("material" "rhombus-medium" "#61bfff")) | |
("variable" . ("material" "rhombus-medium-outline" "#8be9fd")) | |
("var" . ("material" "square-medium-outline" "#e04646")) | |
("class" . ("material" "keyboard-caps" "#8be9fd")) | |
("interface" . ("material" "layers-outline" "#ff79c6")) | |
("i/f" . ("material" "share" "#ee3322")) | |
("module" . ("material" "cube-outline" "#61bfff")) | |
("mod" . ("material" "cube-outline" "#ff6908")) | |
("property" . ("material" "wrench" "#bf033b")) | |
("prop" . ("material" "tools" "#0eb24e")) | |
("unit" . ("material" "alpha-u-box-outline" "#98c807")) | |
("value" . ("material" "format-align-right" "#ff0092")) | |
("enum" . ("material" "database" "#dc5034")) | |
("keyword" . ("material" "keyboard-caps" "#f1fa8c")) | |
("k/w" . ("material" "filter-outline" "#ed6856")) | |
("snippet" . ("material" "xml" "#50fa7b")) | |
("yas-snippet" . ("material" "xml" "#50fa7b")) | |
("sn" . ("material" "format-align-center" "#f69653")) | |
("color" . ("material" "palette" "#099d84")) | |
("file" . ("material" "file-outline" "#e30061")) | |
("reference" . ("material" "bookmark-box-multiple" "#954a97")) | |
("ref" . ("material" "bookmark-box-multiple-outline" "#006e96")) | |
("folder" . ("material" "folder" "#f56040")) | |
("dir" . ("material" "folder" "#d25238")) | |
("enum-member" . ("material" "google-circles-extended" "#ff9900")) | |
("enummember" . ("material" "google-circles-extended" "#8a8acb")) | |
("member" . ("material" "guitar-pick" "#e55e5e")) | |
("constant" . ("material" "square-medium-outline" "#f1fa8c")) | |
("const" . ("material" "square-medium-outline" "#f65314")) | |
("struct" . ("material" "layers" "#76e0f3")) | |
("event" . ("material" "bell" "#e990ab")) | |
("operator" . ("material" "plus-circle-outline" "#f47b7b")) | |
("op" . ("material" "plus-circle-multiple-outline" "#eb0973")) | |
("type-parameter" . ("material" "arrow-split-vertical" "#39a6dd")) | |
("param" . ("material" "arrow-split-horizontal" "#ff0e83")) | |
("template" . ("material" "file-document-multiple" "#207c88")) | |
("macro" . ("material" "lambda" "#ff9900")) | |
("face" . ("material" "invert-colors" "#6272a4")) | |
("translate" . ("material" "translate" "#98c807")) | |
("emmet abbreviation" . ("material" "expand-all-outline" "#98c807")) | |
("custom" . ("material" "apple-keyboard-option" "#ed6856")) | |
("special form" . ("material" "function-variant" "#0abf53")) | |
("feature" . ("material" "pyramid" "#00c4cc")) | |
("at" . ("material" "at" "#0085c3")) | |
("tabnine" . ("material" "alpha-t-box-outline" "#954a97")) | |
("port" . ("material" "blinds-open" "#39a6dd")) | |
("net" . ("material" "chart-timeline-variant" "#ed6856")) | |
("register" . ("material" "cellphone-key" "#ff6908")) | |
("block" . ("material" "contain" "#96cbb3")) | |
("prototype" . ("material" "currency-sign" "#0085c3")) | |
("instance" . ("material" "city-variant-outline" "#da1884")) | |
("task" . ("material" "text-recognition" "#e22272")) | |
("typedef" . ("material" "label-outline" "#bf11b6")) | |
("tailwind" . ("material" "creation" "#39a6dd")) | |
("namespace" . ("material" "pan" "#dc5034")) | |
("package" . ("material" "package" "#dc5034")) | |
("string" . ("material" "code-string" "#98c807")) | |
("number" . ("material" "numeric-1" "#98c807")) | |
("boolean" . ("material" "star-check" "#98c807")) | |
("array" . ("material" "code-array" "#0085c3")) | |
("object" . ("material" "steering" "#0085c3")) | |
("key" . ("material" "account-key" "#0085c3")) | |
("null" . ("material" "null" "##98c807")) | |
("typeparameter" . ("material" "format-list-bulleted-type" "#dc5034")) | |
("codeium" . ("material" "code-braces" "#09b6a2")) | |
("copilot" . ("material" "github" "#6272a4")) | |
(t . ("octicons" "question" "#90cef1"))))) | |
;; Go | |
(leaf go-mode | |
:doc "Go development environment" | |
:url "https://github.com/dominikh/go-mode.el" | |
:if (executable-find "go") | |
:ensure t | |
:mode "\\.go\\'" | |
:custom | |
(gofmt-command . "goimports") | |
:hook | |
(go-mode-hook | |
. (lambda () | |
(add-hook 'before-save-hook #'gofmt-before-save t t))) | |
:bind | |
(:go-mode-map | |
("C-c C-n" . go-run) | |
("C-c C-m" . consult-make-in-project-root))) | |
(leaf gotest | |
:doc "Run Go unit-tests" | |
:url "https://github.com/nlamirault/gotest.el" | |
:if (executable-find "go") ; $ brew install go | |
:after go-mode | |
:ensure t | |
:require t | |
:bind | |
(:go-mode-map | |
("C-c t" . go-test-clean-and-current-test) | |
("C-c f" . go-test-clean-and-current-file) | |
("C-c T" . go-test-current-test) | |
("C-c F" . go-test-current-file) | |
("C-c a" . go-test-current-project)) | |
:preface | |
(defun go-test-clean-and-current-test() | |
(interactive) | |
(progn | |
(call-process-shell-command "go clean -testcache" nil 0) | |
(go-test-current-test))) | |
(defun go-test-clean-and-current-file() | |
(interactive) | |
(progn | |
(call-process-shell-command "go clean -testcache" nil 0) | |
(go-test-current-file)))) | |
(leaf go-tag | |
:doc "Generate & Edit field tags for golang struct fields" | |
:url "https://github.com/brantou/emacs-go-tag" | |
:if (executable-find "gomodifytags") ; $ go get github.com/fatih/gomodifytags | |
:ensure t) | |
(leaf go-playground | |
:doc "setup local Go playground for code snippets" | |
:url "https://github.com/grafov/go-playground" | |
:ensure t) | |
;; Python | |
(leaf python | |
:doc "Python development environment" | |
:url "https://wiki.python.org/moin/EmacsPythonMode" | |
:mode ("\\.py\\'" . python-mode) | |
:hook | |
(python-mode-hook | |
. (lambda () | |
(lsp-deferred) | |
(add-hook 'before-save-hook #'lsp-organize-imports t t)))) | |
(leaf yapfify | |
:doc "Python formatter" | |
:url "https://github.com/JorisE/yapfify" | |
:if (executable-find "yapf") ; $ pip install yapf | |
:ensure t | |
:hook (python-mode-hook . yapf-mode)) | |
;; Rust | |
;; (leaf rustic | |
;; :doc "Rust development environment" | |
;; :url "https://github.com/brotzeit/rustic" | |
;; :if (executable-find "rs") | |
;; :ensure t | |
;; :bind | |
;; (:rust-mode-map | |
;; ("C-c C-n" . rustic-cargo-run)) | |
;; :custom | |
;; (rustic-format-trigger . 'on-save) | |
;; (rustic-babel-auto-wrap-main . t)) | |
;; C/C++/Objective-C | |
;; (leaf cc-mode | |
;; :doc "Mode for C, C++, Objective-C, Java, CORBA IDL, Pike and AWK code" | |
;; :url "https://www.gnu.org/software/emacs/manual/html_mono/ccmode.html" | |
;; :ensure t | |
;; :custom (c-base-offset . 4) | |
;; :bind (:c-mode-base-map ("C-c C-n" . compile))) | |
;; (leaf ccls | |
;; :doc "ccls client" | |
;; :url "https://github.com/emacs-lsp/emacs-ccls" | |
;; :if (executable-find "ccls") ; $ brew install ccls | |
;; :ensure t | |
;; :require ccls | |
;; :custom `((ccls-executable . ,(executable-find "ccls")))) | |
;; (leaf modern-cpp-font-lock | |
;; :doc "Syntax highlighting support for `Modern C++' until C++20 and Technical Specification" | |
;; :url "https://github.com/ludwigpacifici/modern-cpp-font-lock" | |
;; :ensure t | |
;; :config (modern-c++-font-lock-global-mode t)) | |
;; Javascript | |
;; (leaf js2-mode | |
;; :doc "Improved JavaScript editing mode" | |
;; :url "https://github.com/mooz/js2-mode" | |
;; :ensure t | |
;; :mode "\\.js\\'") | |
;; (leaf typescript-mode | |
;; :doc "Major-mode for editing Typescript-files" | |
;; :url "https://github.com/emacs-typescript/typescript.el" | |
;; :if (executable-find "tsc") ; $ npm install -g typescript | |
;; :ensure t | |
;; :mode "\\.ts\\'") | |
;; Shell Script | |
(leaf fish-mode | |
:doc "Major-mode for fish shell scripts" | |
:url "https://github.com/wwwjfy/emacs-fish" | |
:if (executable-find "fish") ; $ brew install fish | |
:ensure t | |
:mode "\\.fish\\'") | |
;; ----------------------------------------------------------------------------------------- | |
;; | |
;; Configuration Language | |
;; | |
;; ----------------------------------------------------------------------------------------- | |
(leaf yaml-mode | |
:doc "Major mode for editing files in the YAML data serialization format" | |
:url "https://github.com/yoshiki/yaml-mode" | |
:ensure t | |
:mode ("\\.yaml\\'" "\\.yml\\'" "\\.rule\\'") ; .rule is a file for Prometheus alert manager | |
:defvar yaml-file-threshold | |
:custom | |
(lsp-yaml-schemas . '(:file:///Users/aigarash/zap-standalone/all.json "/*.yaml")) | |
(yaml-file-threshold . 100000) | |
:hook | |
(yaml-mode-hook | |
. (lambda () | |
(if (< (buffer-size (current-buffer)) yaml-file-threshold) | |
(progn | |
(if (window-system) | |
(highlight-indent-guides-mode)) | |
(yas-minor-mode) | |
(lsp-deferred))))) | |
:custom-face | |
(font-lock-variable-name-face . '((t (:foreground "violet"))))) | |
(leaf systemd | |
:doc "Major mode for editing systemd units" | |
:url "https://github.com/holomorph/systemd-mode" | |
:ensure t | |
:mode | |
("\\.service\\'" "\\.timer\\'" "\\.target\\'" "\\.mount\\'" | |
"\\.automount\\'" "\\.slice\\'" "\\.socket\\'" "\\.path\\'" | |
"\\.netdev\\'" "\\.network\\'" "\\.link\\'")) | |
(leaf protobuf-mode | |
:doc "Major mode for protobuf file editing" | |
:url "https://github.com/protocolbuffers/protobuf/blob/master/editors/protobuf-mode.el" | |
:if (executable-find "protoc") ; $ brew install protobuf | |
:ensure t | |
:mode "\\.proto\\'" | |
:hook | |
(protobuf-mode-hook . (lambda () (setq-local c-basic-offset 2)))) | |
(leaf dockerfile-mode | |
:doc "Mode for handling Dockerfiles" | |
:url "https://github.com/spotify/dockerfile-mode" | |
:ensure t | |
:mode "\\Dockerfile\\'") | |
(leaf terraform-mode | |
:doc "Major mode of Terraform configuration file" | |
:url "https://github.com/emacsorphanage/terraform-mode" | |
:ensure t | |
:mode "\\.tf\\'") | |
;; ----------------------------------------------------------------------------------------- | |
;; | |
;; Drawing | |
;; | |
;; ----------------------------------------------------------------------------------------- | |
(leaf gnuplot | |
:doc "Major mode for Emacs for interacting with Gnuplot" | |
:url "https://github.com/emacs-gnuplot/gnuplot" | |
:if (executable-find "gnuplot") ; $ brew install gnuplot | |
:ensure t | |
:mode ("\\.gp\\'")) | |
; Used by markdown-mode | |
(leaf mermaid-mode | |
:doc "Major mode for working with mermaid graphs" | |
:url "https://github.com/abrochard/mermaid-mode" | |
:ensure t) | |
;; ----------------------------------------------------------------------------------------- | |
;; | |
;; Markdown | |
;; | |
;; ----------------------------------------------------------------------------------------- | |
(leaf edit-indirect ; for markdown-mode | |
:doc "Edit source code block in other buffer" | |
:url "https://github.com/Fanael/edit-indirect" | |
:ensure t) | |
(leaf markdown-mode | |
:doc "Major mode for editing Markdown-formatted text" | |
:url "https://github.com/jrblevin/markdown-mode" | |
:ensure t | |
:mode | |
(("README\\.md\\'" . gfm-mode) | |
("\\.md\\'" . markdown-mode)) | |
:preface | |
(defun markdown-live-preview-window-xwidget (file) | |
"Preview file with xwidget browser" | |
(xwidget-webkit-browse-url (concat "file://" file)) | |
(let ((buf (xwidget-buffer (xwidget-webkit-current-session)))) | |
(when (buffer-live-p buf) | |
(and (eq buf (current-buffer)) (quit-window)) | |
(pop-to-buffer buf)))) | |
:custom | |
(markdown-hide-urls . nil) | |
(markdown-hide-markup . nil) | |
(markdown-max-image-size . '(700 . nil)) | |
(markdown-list-item-bullets . '("–")) | |
(markdown-gfm-additional-languages . '("Mermaid")) | |
(markdown-fontify-code-blocks-natively . t) | |
(markdown-live-preview-window-function . 'markdown-live-preview-window-xwidget) | |
(markdown-content-type . "application/xhtml+xml") | |
(markdown-css-paths . '("https://cdnjs.cloudflare.com/ajax/libs/github-markdown-css/5.1.0/github-markdown.min.css" | |
"https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.5.0/styles/github.min.css")) | |
(markdown-xhtml-header-content | |
. " | |
<meta name='viewport' content='width=device-width, initial-scale=1, shrink-to-fit=no'> | |
<style> | |
body { max-width: 740px; padding: 1em 2em; } | |
.markdown-body { margin: 0 auto; } | |
</style> | |
<script src='https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.5.0/highlight.min.js'></script> | |
<script> | |
document.addEventListener('DOMContentLoaded', () => { | |
document.body.classList.add('markdown-body'); | |
document.querySelectorAll('pre code').forEach((code) => { | |
if (code.className != 'mermaid') { | |
hljs.highlightBlock(code); | |
} | |
}); | |
}); | |
</script> | |
<script src='https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.min.js'></script> | |
<script>mermaid.initialize({ startOnLoad: true });</script>") | |
:custom-face | |
(markdown-header-face-1 . '((t (:inherit outline-1 :weight bold :height 1.2)))) | |
(markdown-header-face-2 . '((t (:inherit outline-1 :weight normal)))) | |
(markdown-header-face-3 . '((t (:inherit outline-1 :weight normal)))) | |
(markdown-header-face-4 . '((t (:inherit outline-1 :weight normal)))) | |
(markdown-bold-face . '((t (:foreground "#f8f8f2" :weight bold)))) | |
(markdown-italic-face . '((t (:foreground "#f8f8f2" :slant italic)))) | |
(markdown-header-delimiter-face . '((t (:foreground "#6272a4" :weight normal)))) | |
(markdown-link-face . '((t (:foreground "#f1fa8c")))) | |
(markdown-url-face . '((t (:foreground "#6272a4")))) | |
(markdown-list-face . '((t (:foreground "#6272a4")))) | |
(markdown-gfm-checkbox-face . '((t (:foreground "#6272a4")))) | |
(markdown-metadata-value-face . '((t (:foreground "#8995ba")))) | |
(markdown-metadata-key-face . '((t (:foreground "#6272a4")))) | |
(markdown-pre-face . '((t (:foreground "#8be9fd")))) | |
:config | |
;; NOTE: `multimarkdown' is required for `highlight.js' and `mermaid.js' | |
;; inspired by https://github.com/seagle0128/.emacs.d/blob/master/lisp/init-markdown.el | |
;; download from https://github.com/fletcher/MultiMarkdown-6/releases | |
(when (executable-find "multimarkdown") | |
(setq markdown-command "multimarkdown")) | |
(add-to-list 'markdown-code-lang-modes '("mermaid" . mermaid-mode))) | |
(leaf markdown-toc | |
:doc "Generate a TOC in markdown file" | |
:url "https://github.com/ardumont/markdown-toc" | |
:ensure t) | |
;; ----------------------------------------------------------------------------------------- | |
;; | |
;; Org Mode - Your life in plain text | |
;; | |
;; ----------------------------------------------------------------------------------------- | |
;; Fix: L219: org-preview-html--open-browser | |
;; (setq-local org-preview-html--html-file | |
;; (concat "file://" (make-temp-file (file-name-base buffer-file-name)) ".html")) | |
(leaf org-preview-html | |
:doc "Automatically preview org-exported HTML files within Emacs." | |
:url https://github.com/jakebox/org-preview-html | |
:ensure t | |
:custom | |
(org-preview-html-viewer . 'xwidget)) | |
;; Use protocol for chrome-extension & original programs | |
;; https://github.com/sprig/org-capture-extension | |
(leaf org-protocol | |
:doc "Integrate with other applications" | |
:url "https://orgmode.org/worg/org-contrib/org-protocol.html" | |
:if (and (eq system-type 'darwin) | |
(file-exists-p "/Applications/EmacsClient.app") ; https://github.com/sprig/org-capture-extension#under-osx | |
(window-system)) | |
:require org-protocol) | |
;; If org-capture via Chrome does not work, please check the path of the appscript in Emacsclient. | |
;; The path to the Emacs is specified absolutely. | |
(leaf org-roam | |
:doc "A plain-text personal knowledge management system." | |
:url "https://www.orgroam.com/" | |
:ensure t | |
;; :require org-roam-protocol | |
:custom | |
(org-roam-directory . "~/doc/content/") | |
(org-roam-db-location . "~/doc/org-roam.db") | |
:preface | |
(defun org-roam-open-page-on-hugo() | |
(interactive) | |
(let ((filename | |
(concat | |
"http://localhost:1313/" | |
(nth 5 (split-string (file-name-directory (buffer-file-name)) "/")) | |
"/" | |
(file-name-base (buffer-file-name))))) | |
(shell-command (concat "open " filename)))) | |
:bind (("C-c n l" . org-roam-buffer-toggle) | |
("C-c n f" . org-roam-node-find) | |
("C-c n g" . org-roam-graph) | |
("C-c n i" . org-roam-node-insert) | |
("C-c n c" . org-capture) | |
("C-c n I" . org-id-get-create) | |
("C-c n r" . org-roam-ref-add) | |
("C-c n t" . org-roam-tag-add) | |
("C-C n o" . org-roam-open-page-on-hugo) | |
("C-c n s" . org-store-link) | |
("C-c n j" . org-roam-dailies-capture-today)) | |
:config | |
(org-roam-db-autosync-mode) | |
(setq org-roam-capture-templates | |
'(("c" "card" plain "#+title: ${title}\n%[~/doc/content/trigger/roam/card.org]" | |
:target (file "card/${name}.org") | |
:immediate-finish t :jump-to-captured t) | |
("p" "post" plain "#+title: ${title}\n%[~/doc/content/trigger/roam/post.org]" | |
:target (file "post/${name}.org") | |
:immediate-finish t :jump-to-captured t) | |
("b" "book" plain "#+title: ${title}\n%[~/doc/content/trigger/roam/book.org]" | |
:target (file "book/${name}.org") | |
:immediate-finish t :jump-to-captured t) | |
("w" "work" plain "#+title: ${title}\n%[~/doc/content/trigger/roam/card.org]" | |
:target (file "work/card/${name}.org") | |
:immediate-finish t :jump-to-captured t) | |
("F" "Focus" plain "#+title: ${title}\n%[~/doc/content/trigger/roam/plan-week.org]" | |
:target (file "agenda/weekly/weekly-goal-%<%Y-W%U>.org") | |
:immediate-finish t :jump-to-captured t) | |
("W" "weekly" plain "#+title: ${title}\n%[~/doc/content/trigger/roam/review-weekly.org]" | |
:target (file "work/review/weekly-review-%<%Y-W%U>.org") | |
:immediate-finish t :jump-to-captured t) | |
("M" "monthly" plain "#+title: ${title}\n%[~/doc/content/trigger/roam/review-monthly.org]" | |
:target (file "work/review/monthly-review-%<%Y-%m>.org") | |
:immediate-finish t :jump-to-captured t) | |
("Q" "quarter" plain "#+title: ${title}\n%[~/doc/content/trigger/roam/review-quarter.org]" | |
:target (file "work/review/quarter-review-%<%Y>-Q${quarter}.org") | |
:immediate-finish :jump-to-captured t))) | |
(setq org-roam-dailies-capture-templates | |
'(("d" "default" entry "* %?" | |
:target (file+head "%<%Y-%m-%d>.org" | |
"#+title: %<%Y-%m-%d (%a)>\n")))) | |
(cl-defmethod org-roam-node-type ((node org-roam-node)) | |
"Return the TYPE of NODE." | |
(condition-case nil | |
(file-name-nondirectory | |
(directory-file-name | |
(file-name-directory | |
(file-relative-name (org-roam-node-file node) org-roam-directory)))) | |
(error ""))) | |
(setq org-roam-node-display-template | |
(concat "${type:15} ${title:*} " (propertize "${tags:20}" 'face 'org-tag)))) | |
(leaf org | |
:doc "Major mode for keeping notes, authoring documents, computational notebooks, | |
literate programming, maintaining to-do lists, planning projects, and more" | |
:url "https://orgmode.org/" | |
:mode "\\.org\\'" | |
:ensure t | |
:init | |
(setq org-directory "~/doc/content/" | |
org-agenda-dir "~/doc/content/agenda/task/" | |
org-journal-dir "~/memo/daily/" | |
org-cards-dir (concat org-directory "card/") | |
org-posts-dir (concat org-directory "post/") | |
org-work-dir (concat org-directory "work/") | |
org-books-dir (concat org-directory "book/") | |
org-task-file (concat org-agenda-dir "task.org") | |
org-work-file (concat org-agenda-dir "work.org")) | |
:bind | |
((:org-mode-map | |
("C-m" . electric-newline-and-maybe-indent) | |
("C-j" . newline-and-indent) | |
("C-M-m" . org-meta-return) | |
("C-c i" . org-clock-in) | |
("C-c o" . org-clock-out) | |
("C-c e" . org-set-effort) | |
("C-c f" . org-footnote-new) | |
("C-c p" . org-preview-html-mode) | |
("C-c 0" . org-list-bullet-num) | |
("C-c -" . org-list-bullet-slash) | |
("C-c 1" . org-show-lv1) | |
("C-c 2" . org-show-lv2) | |
("C-c 3" . org-show-lv3) | |
("C-c a" . org-narrow-to-subtree) | |
("C-c w" . widen) | |
("C-s-s" . org-save-all-org-buffers) | |
("C-c C-." . org-time-stamp-inactive))) | |
:custom | |
(org-src-preserve-indentation . nil) | |
(org-edit-src-content-indentation . 0) | |
(org-src-fontify-natively . t) ; enable syntax highlight for source block | |
(org-image-actual-width . 500) ; default size is too big | |
(org-startup-folded . 'content) | |
(org-hierarchical-todo-statistics . nil) | |
;; Disabled unused modules to speedup startup. | |
(org-modules | |
. (delete '(org-gnus org-w3m org-bbdb org-bibtex org-docview | |
org-info org-irc org-mhe org-rmail org-eww) org-modules)) | |
;; Use slash(-) as bullets in lists when change the layer. | |
(org-list-demote-modify-bullet | |
. '(("+" . "-") ("*" . "-") | |
("1." . "-") ("1)" . "-") | |
("A)" . "-") ("B)" . "-") ("A." . "-") ("B." . "-") | |
("a)" . "-") ("b)" . "-") ("a." . "-") ("b." . "-"))) | |
:preface | |
(defun org-show-lv1 () (interactive) (org-content 1)) | |
(defun org-show-lv2 () (interactive) (org-content 2)) | |
(defun org-list-bullet-num () (interactive) (org-cycle-list-bullet 2)) | |
(defun org-list-bullet-num-lv2 () (interactive) (org-cycle-list-bullet 3)) | |
(defun org-list-bullet-num-lv3 () (interactive) (org-cycle-list-bullet 4)) | |
(defun org-list-bullet-slash () (interactive) (org-cycle-list-bullet 0))) | |
;; Theme ---------------------------------------------------------------------------------- | |
(leaf org-theme | |
:doc "Theme for org-mode" | |
:custom | |
(org-todo-keyword-faces | |
. '(("WAIT" . (:foreground "#6272a4" :weight bold :width condensed)) | |
("NEXT" . (:foreground "#f1fa8c" :weight bold :width condensed)))) | |
:custom-face | |
;; general | |
(org-level-1 . '((t (:inherit outline-1 :weight normal :height 1.2)))) | |
(org-level-2 . '((t (:inherit outline-2 :weight normal)))) | |
(org-level-3 . '((t (:inherit outline-3 :weight normal)))) | |
(org-level-4 . '((t (:inherit outline-4 :weight normal)))) | |
(org-level-5 . '((t (:inherit outline-5 :weight normal)))) | |
(org-level-6 . '((t (:inherit outline-6 :weight normal)))) | |
(org-link . '((t (:foreground "#bd93f9" :underline t :weight normal)))) | |
(org-list-dt . '((t (:foreground "#bd93f9")))) | |
(org-checkbox-statistics-todo . '((t (:foreground "#6272a4" :weight normal :height 0.9)))) | |
(org-checkbox-statistics-done . '((t (:foreground "#44475a" :weight normal :height 0.9)))) | |
(org-document-title . '((t (:foreground "#61bfff" :weight normal :height 1.0)))) | |
(org-document-info-keyword . '((t (:foreground "#6272a4" :height 1.0)))) | |
(org-document-info . '((t (:foreground "#6272a4" :height 1.0)))) | |
(org-meta-line . '((t (:foreground "#44475a" :height 1.0)))) | |
(org-footnote . '((t (:foreground "#76e0f3")))) | |
(org-agenda-calendar-event . '((t (:foreground "#8995ba")))) | |
(org-special-keyword . '((t (:foreground "#6272a4")))) | |
(org-drawer . '((t (:foreground "#44475a")))) | |
(org-checkbox . '((t (:foreground "#bd93f9")))) | |
(org-tag . '((t (:foreground "#6272a4")))) | |
(org-date . '((t (:foreground "#8995ba" :height 0.9 :weight light :width condensed)))) | |
(org-priority . '((t (:foreground "#f1fa8c")))) ; #ebe087 | |
(org-todo . '((t (:foreground "#ad92dd" :weight bold :width condensed)))) | |
(org-done . '((t (:background "#282a36" :foreground "#3b216a" :strike-through nil :weight bold :width condensed))))) | |
(leaf org-modern | |
:doc "To Be Modern Looks" | |
:url "https://github.com/minad/org-modern" | |
:ensure t | |
:hook (org-mode-hook . org-modern-mode) | |
:custom | |
(org-modern-star . 'replace) | |
(org-modern-hide-stars . " ") | |
(org-modern-progress . nil) | |
(org-modern-tag . nil) | |
(org-modern-todo . t) | |
(org-modern-priority . t) | |
(org-modern-statistics . nil) | |
(org-modern-timestamp . nil) | |
(org-modern-block-name . nil) | |
(org-modern-block-fringe . nil) | |
(org-modern-table-vertical . 1) | |
(org-modern-variable-pitch . t) | |
;; todo faces | |
(org-modern-todo-faces | |
. (quote (("TODO" :background "#673AB7" :foreground "#f8f8f2") | |
("WAIT" :background "#6272a4" :foreground "#f8f8f2") | |
("NEXT" :background "#f1fa8c" :foreground "#1E2029") ; #bd93f9 | |
("DONE" :background "#373844" :foreground "#b0b8d1")))) | |
;; use nerd font icons | |
(org-modern-list . '((?+ . "◦") (?- . "–") (?* . "•"))) | |
(org-modern-checkbox . '((?X . "") (?- . "") (?\s . ""))) | |
(org-modern-priority . '((?A . "") (?B . "") (?C . ""))) | |
(org-modern-replace-stars . "") | |
:custom-face | |
(org-modern-date-active . '((t (:background "#373844" :foreground "#f8f8f2" :height 0.75 :weight light :width condensed)))) | |
(org-modern-time-active . '((t (:background "#44475a" :foreground "#f8f8f2" :height 0.75 :weight light :width condensed)))) | |
(org-modern-date-inactive . '((t (:background "#373844" :foreground "#b0b8d1" :height 0.75 :weight light :width condensed)))) | |
(org-modern-time-inactive . '((t (:background "#44475a" :foreground "#b0b8d1" :height 0.75 :weight light :width condensed)))) | |
(org-modern-tag . '((t (:background "#44475a" :foreground "#b0b8d1" :height 0.75 :weight light :width condensed)))) | |
(org-modern-statistics . '((t (:foreground "violet" :weight light))))) | |
;; Agenda ---------------------------------------------------------------------------------- | |
(leaf *org-agenda | |
:doc "TODO & Schedule management system" | |
:url "https://orgmode.org/manual/Agenda-Views.html" | |
:after org | |
:bind | |
(:org-agenda-mode-map | |
("r" . org-agenda-refile)) | |
:preface | |
(defun org-clock-out-and-save () | |
"Save buffers and stop clocking." | |
(ignore-errors (org-clock-out) t) | |
(save-some-buffers t)) | |
(defun color-org-agenda-header (tag col) | |
"Set s color to org-agenda header with the specified tag." | |
(interactive) | |
(goto-char (point-min)) | |
(while (re-search-forward tag nil t) | |
(add-text-properties (match-beginning 0) (pos-eol) | |
`(face (:foreground ,col))))) | |
:hook | |
(kill-emacs-hook . org-clock-out-and-save) | |
:custom | |
(org-deadline-warning-days . 7) | |
(org-clock-out-remove-zero-time-clocks . t) | |
(org-clock-clocked-in-display . 'both) | |
(org-agenda-span . 'day) | |
(org-agenda-current-time-string . "← now") | |
(org-agenda-include-diary . t) | |
(org-agenda-include-deadlines . t) | |
(org-agenda-start-with-log-mode . t) | |
(org-agenda-compact-blocks . t) | |
(org-agenda-skip-scheduled-if-done . t) | |
(org-agenda-skip-deadline-if-done . t) | |
(org-agenda-block-separator . nil) | |
(org-agenda-log-mode-items . (quote (closed clock))) | |
(org-agenda-time-grid | |
. '((daily today require-timed) | |
(0800 1000 1200 1500 1700 1900 2100 2300) | |
"-" "────────────────")) | |
:custom-face | |
(org-scheduled-today . '((t (:foreground "#f8f8f2"))))) | |
(leaf xbar-org-clock | |
:doc "show clock-in item on menu bar" | |
:url "https://github.com/Ladicle/xbar-plugin-org-clock" | |
:defvar | |
(xbar-org-clock-status-file | |
xbar-org-clock-agenda-file | |
xbar-org-clock-agenda-key | |
xbar-org-clock-agenda-sync-interval) | |
:custom | |
(xbar-org-clock-status-file . "~/.clockin_task") | |
(xbar-org-clock-agenda-file . "~/.agenda") | |
(xbar-org-clock-agenda-key . "n") | |
(xbar-org-clock-agenda-sync-interval . 1800) ;; 30m | |
:preface | |
(defun xbar-org-clock--write-agenda () | |
(progn | |
(org-agenda nil xbar-org-clock-agenda-key) | |
(org-agenda-write xbar-org-clock-agenda-file))) | |
(defun xbar-org-clock--write-clockin-status () | |
(with-temp-buffer | |
(insert (concat | |
(format-time-string "%s" org-clock-start-time) "\t" org-clock-heading)) | |
(write-region (point-min) (point-max) xbar-org-clock-status-file))) | |
(defun xbar-org-clock--delete-clockin-status () | |
(delete-file xbar-org-clock-status-file)) | |
:hook | |
(org-clock-in-hook . xbar-org-clock--write-clockin-status) | |
(org-clock-out-hook . xbar-org-clock--delete-clockin-status) | |
(org-clock-cancel-hook . xbar-org-clock--delete-clockin-status) | |
:init | |
(defun date-range-to-files (start-date end-date) | |
"Return a list of file paths from START-DATE to END-DATE." | |
(let ((files '()) | |
(current-date start-date)) | |
(while (not (time-less-p end-date current-date)) | |
(let* ((year (format-time-string "%Y" current-date)) | |
(month (format-time-string "%m" current-date)) | |
(day (format-time-string "%d" current-date)) | |
(file (expand-file-name (format "~/memo/daily/%s/%s/%s.org" year month day)))) | |
(when (file-exists-p file) | |
(add-to-list 'files file))) | |
(setq current-date (time-add current-date (days-to-time 1)))) | |
files)) | |
(let* ((today (current-time)) | |
(five-days-ago (time-subtract today (days-to-time 5))) | |
(files (date-range-to-files five-days-ago today))) | |
(setq org-agenda-files | |
(append '("~/doc/content/agenda/task/task.org" | |
"~/doc/content/agenda/task/work.org") | |
files))) | |
:config | |
(run-with-timer 0 xbar-org-clock-agenda-sync-interval 'xbar-org-clock--write-agenda)) | |
(leaf org-super-agenda | |
:doc "Supercharge your Org daily/weekly agenda by grouping items Topics" | |
:url "https://github.com/alphapapa/org-super-agenda" | |
:ensure t | |
:global-minor-mode org-super-agenda-mode | |
:config | |
;; inspired by https://github.com/alphapapa/org-super-agenda/blob/master/examples.org#zaen323 | |
(setq org-agenda-custom-commands | |
'(("r" "Review view" | |
((todo "DONE"))) | |
("u" "Super view" | |
((agenda "" ((org-agenda-overriding-header "") | |
(org-agenda-todo-keyword-format "") | |
(org-super-agenda-unmatched-name "Scheduled") | |
(org-super-agenda-groups | |
'((:name "Today" :time-grid t) | |
(:discard (:category "Work" :category "Diary")))))) | |
(todo "" ((org-agenda-overriding-header "") | |
(org-agenda-todo-keyword-format "") | |
(org-agenda-prefix-format '((todo . " %-9:c %e %-10T"))) | |
(org-super-agenda-date-format "%e %B %Y") | |
(org-super-agenda-unmatched-name "Others") | |
(org-super-agenda-keep-order t) | |
(org-super-agenda-groups | |
'((:discard (:category "Work")) | |
(:name "Inbox" :tag "#inbox" :face (:foreground "#ccd0dc")) | |
(:name "Next Action" :todo "NEXT" :face (:foreground "#ccd0dc")) | |
(:name "Waiting" :todo "WAIT" :face (:foreground "#6272a4")) | |
(:discard (:anything t)))))))) | |
("n" "Next view" | |
((todo "" ((org-agenda-overriding-header "") | |
(org-agenda-todo-keyword-format "") | |
(org-agenda-prefix-format '((todo . " %-9:c %e"))) | |
(org-super-agenda-date-format "%e %B %Y") | |
(org-super-agenda-unmatched-name "Others") | |
(org-super-agenda-keep-order t) | |
(org-super-agenda-groups | |
'((:discard (:category "Work")) | |
(:name "Inbox" :tag "#inbox" :face (:foreground "#ccd0dc")) | |
(:name "Today" :deadline today :face (:foreground "#ccd0dc")) | |
(:name "Next Action" :todo "NEXT" :face (:foreground "#ccd0dc")) | |
(:discard (:anything t)))))))) | |
("w" "Work view" | |
((agenda "" ((org-agenda-overriding-header "") | |
(org-agenda-todo-keyword-format "") | |
(org-deadline-warning-days 4) | |
(org-super-agenda-groups | |
'((:name "Timeline" :time-grid t) | |
(:discard (:not (:category "Work" :category "Diary"))))))) | |
(todo "" ((org-agenda-overriding-header "") | |
(org-agenda-prefix-format '((todo . " "))) | |
(org-super-agenda-keep-order t) | |
(org-super-agenda-groups | |
'((:discard (:not (:category "Work" :category "Diary"))) | |
(:name "Inbox" :tag "#inbox" :face (:foreground "#ccd0dc")) | |
(:name "Goals" :children todo :face (:foreground "#ccd0dc")) | |
(:name "Tasks" :todo "NEXT" :todo "TODO") | |
(:name "Waiting" :todo "WAIT" :face (:foreground "#6272a4")) | |
(:name "Others" :not (:tag "#someday" :tag "#routine" :tag "#event") :face (:foreground "#6272a4")) | |
(:discard (:anything t)))))))) | |
("f" "Full view" | |
((todo "" ((org-agenda-overriding-header "") | |
(org-agenda-todo-keyword-format "") | |
(org-agenda-prefix-format '((todo . " %-9:c %e %-10T"))) | |
(org-super-agenda-date-format "%e %B %Y") | |
(org-super-agenda-unmatched-name "Someday") | |
(org-super-agenda-keep-order t) | |
(org-super-agenda-groups | |
'((:name "Inbox" :tag "#inbox" :face (:foreground "#ccd0dc")) | |
(:name "Next Action" :todo "NEXT" :face (:foreground "#ccd0dc")) | |
(:name "Waiting" :todo "WAIT" :face (:foreground "#ccd0dc")) | |
(:name "Projects" :children todo :face (:foreground "#ccd0dc")) | |
(:name "Others" :not (:tag "#someday") :face (:foreground "#ccd0dc"))))))))))) | |
;; Exporter ------------------------------------------------------------------------------- | |
(leaf ox-hugo | |
:doc "Org to Markdown for Hugo" | |
:url "https://ox-hugo.scripter.co/" | |
:if (executable-find "hugo") ; $ brew install hugo | |
:after ox | |
:ensure t | |
:require t) | |
(leaf ox-qmd | |
:doc "Org exporter for Qiita Markdown" | |
:url "https://github.com/0x60df/ox-qmd" | |
:after ox | |
:ensure t | |
:require t) | |
;; Babel ---------------------------------------------------------------------------------- | |
(leaf org-babel | |
:doc "Literate programming tools :: letting many different languages work together" | |
:url "https://orgmode.org/worg/org-contrib/babel/intro.html" | |
:custom | |
(org-export-babel-evaluate . nil) | |
(org-confirm-babel-evaluate . nil) | |
(org-babel-default-header-args:emacs-lisp . nil) | |
(org-babel-default-header-args:latex . nil) | |
(org-babel-default-header-args:python . '((:results . "output"))) | |
(org-babel-default-header-args:go . '((:imports . '("\"fmt\"")))) | |
;; Drawing | |
(org-ditaa-jar-path . "/usr/share/ditaa/ditaa.jar") | |
(org-plantuml-jar-path . "~/.emacs.d/plantuml.jar") | |
;; Language extensions :: completion candidates for company-org | |
(org-babel-tangle-lang-exts | |
. '(("java" . "java") ("lisp" . "lisp") ("python" . "python") ("rust" . "rust") | |
("C++" . "cpp") ("go" . "go") ("emacs-lisp" . "emacs-lisp") | |
("fish" . "fish") ("bash" . "bash") ("diff" . "diff") | |
("terraform" . "terraform") ("dockerfile" . "dockerfile") ("conf" . "conf") | |
("yaml" . "yaml") ("json" . "json") | |
("sql" . "sql") | |
("html" . "html") ("css" . "css") | |
("markdown" . "markdown") ("text" . "text") ("latex" . "latex"))) | |
:preface | |
(defun toggle-org-export-babel-evaluate () | |
(interactive) | |
(if toggle-org-export-babel-evaluate | |
(progn | |
(setq toggle-org-export-babel-evaluate nil) | |
(message "toggle-org-export-babel-evaluate disabled :-P")) | |
(progn | |
(setq toggle-org-export-babel-evaluate t) | |
(message "toggle-org-export-babel-evaluate enabled :-)")))) | |
:config | |
;; rust is enabled by rustic | |
(org-babel-do-load-languages | |
'org-babel-load-languages | |
'((plantuml . t) | |
(dot . t) | |
(gnuplot . t) | |
(latex . t) | |
(go . t) | |
(C . t) | |
(python . t) | |
(shell . t)))) | |
(leaf ob-async | |
:doc "Asynchronous src_block execution for org-babel" | |
:url "https://github.com/astahlman/ob-async" | |
:ensure t | |
:custom | |
(ob-async-no-async-languages-alist . '("python" "go"))) | |
(leaf ob-go | |
:doc "Org-Babel support for evaluating go code" | |
:url "https://github.com/pope/ob-go" | |
:if (executable-find "go") | |
:ensure t) | |
;; Journal -------------------------------------------------------------------------------- | |
(leaf org-journal | |
:doc "A simple org-mode based journaling mode" | |
:url "https://github.com/bastibe/org-journal" | |
:ensure t | |
:preface | |
(defun org-journal-direct-open-entry (_arg &optional event) | |
"Open journal entry for selected date for viewing" | |
(interactive | |
(list current-prefix-arg last-nonmenu-event)) | |
(let* ((time (org-journal--calendar-date->time | |
(calendar-cursor-to-date t event)))) | |
(find-file-other-window (org-journal--get-entry-path time)))) | |
(defun org-journal-file-header-func (&optional time) | |
"Custom function to create journal header." | |
(concat | |
(pcase org-journal-file-type | |
(`daily (format-time-string | |
(concat | |
"#+title: %Y/%m/%d (%a)\n" | |
"#+date: [%Y-%m-%d %a %H:%M]\n" | |
"#+category: Diary\n" | |
"#+setupfile: ~/doc/setup.org") | |
time)) | |
(`weekly "#+title: Weekly Journal\n %s") | |
(`monthly "#+title: Monthly Journal\n") | |
(`yearly "#+title: Yearly Journal\n")))) | |
:bind | |
((:calendar-mode-map | |
("j" . org-journal-direct-open-entry) | |
("n" . org-journal-new-date-entry))) | |
:custom | |
(org-journal-enable-agenda-integration . t) | |
(org-journal-file-header . 'org-journal-file-header-func) | |
(org-journal-file-format . "%Y/%m/%d.org") | |
(org-journal-date-format . "") | |
(org-journal-time-prefix . "") | |
:custom-face | |
(org-journal-calendar-entry-face . '((t (:foreground "#ff79c6"))))) | |
;; Capture -------------------------------------------------------------------------------- | |
(leaf *org-capture | |
:doc "Capture lets you quickly store notes with little interruption of your work flow" | |
:url "https://orgmode.org/manual/Capture-templates.html#Capture-templates" | |
:after org | |
:preface | |
(defun today-journal-file () (concat org-journal-dir (format-time-string org-journal-file-format (current-time)))) | |
(defun new-card-file () (concat org-cards-dir (read-string "file name: ") ".org")) | |
(defun new-post-file () (concat org-posts-dir (read-string "file name: ") ".org")) | |
(defun new-book-file () (concat org-books-dir (read-string "file name: ") ".org")) | |
(defun new-work-file () (concat org-work-dir "card/" (read-string "file name: ") ".org")) | |
(defun new-qreview-file () (concat org-work-dir | |
"review/" | |
(format-time-string "quarter-review-%Y-Q" (current-time)) | |
(- (string-to-number (format-time-string "%q" (current-time))) 1) | |
".org")) | |
(defun new-mreview-file () (concat org-work-dir "review/" (format-time-string "monthly-review-%Y-%m.org" (current-time)))) | |
(defun new-wreview-file () (concat org-work-dir "review/" (format-time-string "weekly-review-%Y-W%U.org" (current-time)))) | |
(defun playground-file (lang ext) (format "%s/%s/%s/main.%s" playground-dir lang (format-time-string "%Y%m%d%H%M" (current-time)) ext)) | |
(defun go-playground-file () (playground-file "go" "go")) | |
(defun cpp-playground-file () (playground-file "cpp" "cpp")) | |
(defun rust-playground-file () (playground-file "rust" "rs")) | |
(defun python-playground-file () (playground-file "python" "py")) | |
(defun org-code-capture-here () | |
"Register current subtree as a capture point." | |
(interactive) | |
(setq org-code-capture-store-file (buffer-file-name)) | |
(setq org-code-capture-store-header (nth 4 (org-heading-components)))) | |
(defun org-code-info-store-point () | |
"Find registered capture point and move the cursor to it." | |
(let ((filename (if (string= "" org-code-capture-store-file) | |
(format-time-string org-journal-file-format) | |
org-code-capture-store-file))) | |
(set-buffer (org-capture-target-buffer filename))) | |
(goto-char (point-min)) | |
(unless (derived-mode-p 'org-mode) | |
(error | |
"Target buffer \"%s\" for org-code-info-store-point should be in Org mode" | |
(current-buffer)) | |
(current-buffer)) | |
(if (re-search-forward org-code-capture-store-header nil t) | |
(goto-char (pos-bol)) | |
(goto-char (point-max)) | |
(or (bolp) (insert "\n")) | |
(insert "* Capture\n") | |
(beginning-of-line 0)) | |
(org-end-of-subtree)) | |
:config | |
(setq playground-dir (concat (getenv "GOPATH") "/src/github.com/Ladicle/playground")) | |
(require 'browse-at-remote) | |
(setq org-capture-templates | |
'(;; Task Management | |
("t" "task @tech" entry (file+headline org-task-file "Inbox") "* TODO %?\n") | |
("w" "task @work" entry (file+headline org-work-file "Inbox") "* TODO %?\n") | |
;; Code Reading Notes | |
("c" "Store the code-reading notes with links." plain (function org-code-info-store-point) "%?\n%(with-current-buffer (org-capture-get :original-buffer) (browse-at-remote-get-url))\n# %a\n") | |
("j" "Immediately store code-reading links." plain (function org-code-info-store-point) "%(with-current-buffer (org-capture-get :original-buffer) (browse-at-remote-get-url))\n# %a\n" :immediate-finish t) | |
;; Coding Playground | |
("P" "Write a python snippet code." plain (file python-playground-file) "" :immediate-finish t :jump-to-captured t) | |
("C" "Write a c++ snippet code." plain (file cpp-playground-file) "" :immediate-finish t :jump-to-captured t) | |
("R" "Write a rust snippet code." plain (file rust-playground-file) "" :immediate-finish t :jump-to-captured t)))) | |
;; Manage Image & Screenshot -------------------------------------------------------------- | |
(leaf org-download | |
:doc "Download drag and drop image" | |
:url "https://github.com/abo-abo/org-download" | |
:if (window-system) | |
:ensure t | |
:require org-download) | |
;; NOTE: When the directory name contains Japanese character, this function fails to convert the image format from tig to png. | |
(leaf *org-screenshot | |
:doc "org-download supports screenshot but it doesn't allow store path customization." | |
:if (and (executable-find "pngpaste") ; $ brew install pngpaste | |
(eq system-type 'darwin)) | |
:bind | |
((:org-mode-map | |
:package org | |
("C-M-w" . org-yank-image-to-clipboard) | |
("C-M-y" . org-insert-clipboard-image) | |
("C-M-o" . org-image-open-in-finder))) | |
:preface | |
(defun org-insert-clipboard-image () | |
"Generate png file from a clipboard image and insert a link to current buffer." | |
(interactive) | |
(let* ((filename | |
(concat (file-name-base (buffer-file-name)) | |
"/" | |
(format-time-string "%Y%m%d_%H%M%S") | |
".png"))) | |
(unless (file-exists-p (file-name-directory filename)) | |
(make-directory (file-name-directory filename))) | |
(let* ((output-buffer (generate-new-buffer "*Async Image Generator*")) | |
(proc (progn | |
(async-shell-command (concat "pngpastet " filename) output-buffer) | |
(get-buffer-process output-buffer)))) | |
(if (process-live-p proc) | |
(set-process-sentinel proc #'org-display-inline-images))) | |
(insert (concat | |
"#+DOWNLOADED: clipboard @ " | |
(format-time-string "%Y-%m-%d %H:%M:%S\n#+CAPTION: \n") | |
"[[file:" filename "]]")) | |
(forward-line -1) | |
(end-of-line))) | |
(defun org-image-open-in-finder() | |
(interactive) | |
(let* ((linkp (bounds-of-thing-at-point 'sentence)) | |
(link (buffer-substring-no-properties (car linkp) (cdr linkp))) | |
(filename | |
(replace-regexp-in-string | |
"\\[\\[\\([^:]*:\\)?\\([^]]+\\)\\].*" "\\2" link))) | |
(shell-command (concat "open " (file-name-directory filename))))) | |
:config | |
(add-to-list 'display-buffer-alist '("^*Async Image Generator*" . (display-buffer-no-window)))) | |
;; Input assistance ----------------------------------------------------------------------- | |
;; INFO: convert this into capf in cope. | |
(leaf company-org-block | |
:doc "Insert Emacs org blocks via company" | |
:url "https://github.com/xenodium/company-org-block" | |
:ensure t | |
:after org | |
:require t | |
:hook | |
(org-mode-hook . (lambda () | |
(setq-local company-backends '(company-org-block)) | |
(company-mode +1))) | |
:custom | |
(company-org-block-edit-style . 'auto) ;; 'auto, 'prompt, or 'inline | |
(org-structure-template-alist | |
. '(("s" . "src") ("e" . "example") | |
("I" . "info") ("N" . "note") ("q" . "quote") | |
("g" . "goal") ("S" . "summary") ("D" . "details")))) | |
(leaf *org-hydra | |
:doc "Hydra template for org metadata" | |
:bind | |
((:org-mode-map | |
:package org | |
("#" . insert-or-open-org-hydra)) | |
(:mozc-mode-map | |
:package mozc | |
("#" . *org-hydra/body))) | |
:preface | |
(defun insert-or-open-org-hydra () | |
(interactive) | |
(if (or (region-active-p) (looking-back "^\s*" 1)) | |
(*org-hydra/body) | |
(self-insert-command 1))) | |
:pretty-hydra | |
((:title " Org Mode" :color blue :quit-key "q" :foreign-keys warn :separator "-") | |
("Header" | |
(("t" (insert "#+title: ") "title") | |
("l" (insert "#+lang: ") "language") | |
("u" (insert "#+setupfile: ~/doc/setup.org") "setupfile") | |
("i" (insert "#+include: ") "include") | |
("o" (insert "#+options: ") "options") | |
("a" (insert (format-time-string "#+lastmod: [%Y-%m-%d %a %H:%M]" (current-time))) "lastmod")) | |
"Hugo" | |
(("d" (insert "#+draft: true") "draft") | |
("S" (insert "#+stale: true") "stale") | |
("m" (insert "#+menu: pin") "pinned") | |
("g" (insert "#+tags[]: ") "tags") | |
("x" (insert "#+hugo_base_dir: ~/Developments/src/github.com/Ladicle/blog") "base-dir") | |
("s" (insert "#+hugo_section: post") "section")) | |
"Book" | |
(("p" (insert "#+progress: true") "progress") | |
("f" (insert "#+format: PDF") "format")) | |
"Inline" | |
(("h" (insert "#+html: ") "HTML") | |
("r" (insert "#+attr_html: ") "attributes") | |
("c" (insert "#+caption: ") "caption") | |
("n" (insert "#+name: ") "name") | |
("w" (insert (concat "{{< tweet user=\"Ladicle\" id=\"" (read-string "TweetID ⇢ ") "\" >}}")) "tweet shortcode")) | |
"Others" | |
(("#" self-insert-command "#") | |
("." (insert (concat "#+" (read-string "metadata: ") ": ")) "#+<metadata>:"))))) | |
;; ----------------------------------------------------------------------------------------- | |
;; | |
;; Theme | |
;; | |
;; ----------------------------------------------------------------------------------------- | |
(leaf doom-themes | |
:doc "Megapack of themes" | |
:url "https://github.com/doomemacs/themes" | |
:ensure t | |
:defer-config | |
(let ((display-table (or standard-display-table (make-display-table)))) | |
(set-display-table-slot display-table 'vertical-border (make-glyph-code ?│)) | |
(setq standard-display-table display-table)) | |
:config | |
(load-theme 'doom-dracula t) | |
(doom-themes-neotree-config) | |
(doom-themes-org-config) | |
:custom-face | |
(hl-line . '((t (:background "#3B4252" :extend t )))) | |
(vertical-border . '((t (:background "#282a36" :foreground "#1E2029"))))) | |
(leaf nyan-mode | |
:url "https://github.com/TeMPOraL/nyan-mode" | |
:ensure t | |
:init | |
(nyan-mode 1)) | |
(leaf doom-modeline | |
:url "https://github.com/seagle0128/doom-modeline" | |
:ensure t | |
:custom | |
(doom-modeline-icon . nil) | |
(doom-modeline-buffer-encoding . nil) | |
:init | |
(doom-modeline-mode 1)) | |
(leaf hide-mode-line | |
:url "https://github.com/hlissner/emacs-hide-mode-line" | |
:ensure t | |
:hook | |
(neotree-mode-hook . hide-mode-line-mode) | |
(imenu-list-major-mode-hook . hide-mode-line-mode)) | |
(leaf *cursor-style | |
:doc "Set cursor style and color" | |
:if (window-system) | |
:config | |
(blink-cursor-mode 0) | |
(set-cursor-color "cyan") | |
(add-to-list 'default-frame-alist '(cursor-type . bar))) | |
;; ----------------------------------------------------------------------------------------- | |
;; | |
;; Widgets | |
;; | |
;; ----------------------------------------------------------------------------------------- | |
;; NOTE: Run `all-the-icons-install-fonts' command at first time! | |
(leaf all-the-icons | |
:if (display-graphic-p) | |
:doc "All the icons is used by NeoTree" | |
:url "https://github.com/domtronn/all-the-icons.el" | |
:ensure t) | |
(leaf neotree | |
:doc "Sidebar for dired" | |
:url "https://github.com/jaypei/emacs-neotree" | |
:ensure t | |
:bind | |
("<f9>" . neotree-projectile-toggle) | |
:custom | |
(neo-theme . 'nerd) | |
(neo-cwd-line-style . 'button) | |
(neo-autorefresh . t) | |
(neo-show-hidden-files . t) | |
(neo-mode-line-type . nil) | |
(neo-window-fixed-size . nil) | |
:config | |
(make-face 'nano-modeline-face) | |
(set-face-background 'nano-modeline-face "#282a36") | |
:preface | |
(defun neotree-projectile-toggle () | |
"Toggle function for projectile." | |
(interactive) | |
(let ((project-dir | |
(ignore-errors | |
(projectile-project-root))) | |
(file-name (buffer-file-name))) | |
(if (and (fboundp 'neo-global--window-exists-p) | |
(neo-global--window-exists-p)) | |
(neotree-hide) | |
(progn | |
(neotree-show) | |
(if project-dir | |
(neotree-dir project-dir)) | |
(if file-name | |
(neotree-find file-name))))))) | |
(leaf imenu-list | |
:doc "Show the current buffer's imenu entries in a seperate buffer" | |
:url "https://github.com/Ladicle/imenu-list" | |
:el-get "Ladicle/imenu-list" | |
:bind ("<f10>" . imenu-list-smart-toggle) | |
:custom | |
(imenu-list-auto-resize . t) | |
(imenu-list-focus-after-activation . t) | |
(imenu-list-entry-prefix . "•") | |
(imenu-list-subtree-prefix . "•") | |
:custom-face | |
(imenu-list-entry-face-1 . '((t (:foreground "white")))) | |
(imenu-list-entry-subalist-face-0 . '((nil (:weight normal)))) | |
(imenu-list-entry-subalist-face-1 . '((nil (:weight normal)))) | |
(imenu-list-entry-subalist-face-2 . '((nil (:weight normal)))) | |
(imenu-list-entry-subalist-face-3 . '((nil (:weight normal))))) | |
(leaf dashboard | |
:doc "An extensible emacs dashboard" | |
:url "https://github.com/emacs-dashboard/emacs-dashboard" | |
:ensure t | |
:custom | |
(dashboard-startup-banner . "~/.emacs.d/banner.png") | |
(dashboard-banner-logo-title . "") | |
(dashboard-center-content . t) | |
(dashboard-set-heading-icons . t) | |
(dashboard-set-footer . t) | |
(dashboard-set-init-info . t) | |
(dashboard-week-agenda . nil) | |
(dashboard-image-banner-max-width . 520) | |
(dashboard-agenda-prefix-format . "%i%-5:c %s") | |
(dashboard-agenda-tags-format . 'ignore) | |
(dashboard-filter-agenda-entry . 'ladicle-agenda-filter) | |
(dashboard-footer-messages . '("Happy Hacking!")) | |
(dashboard-items | |
. '((agenda . 5) | |
(projects . 5) | |
(recents . 5))) | |
:config | |
(dashboard-setup-startup-hook) | |
(require 'all-the-icons) | |
(require 'projectile) | |
(setq dashboard-footer-icon | |
(all-the-icons-octicon "octoface" | |
:height 1.1 | |
:v-adjust -0.05 | |
:face 'shadow)) | |
(add-hook 'dashboard-mode-hook #'hide-nano-header t t) | |
:preface | |
(defun ladicle-agenda-filter () | |
"No filter agenda entries." | |
(unless (and (string= (org-get-category) "Work") | |
(org-entry-is-todo-p) | |
(not (org-entry-is-done-p)) | |
(not (org-in-archived-heading-p))) | |
(point))) | |
(defun hide-nano-header() | |
(setq-local header-line-format "")) | |
:custom-face | |
(dashboard-items-face . '((t (:weight normal :foreground "#a9a1e1"))))) | |
;; ----------------------------------------------------------------------------------------- | |
;; | |
;; Accessibility | |
;; | |
;; ----------------------------------------------------------------------------------------- | |
;; Input Assistance | |
(leaf *hydra-theme | |
:doc "Make emacs bindings that stick around" | |
:url "https://github.com/abo-abo/hydra" | |
:custom-face | |
(hydra-face-red . '((t (:foreground "#bd93f9")))) | |
(hydra-face-blue . '((t (:foreground "#8be9fd")))) | |
(hydra-face-pink . '((t (:foreground "#ff79c6")))) | |
(hydra-face-teal . '((t (:foreground "#61bfff")))) | |
(hydra-face-amaranth . '((t (:foreground "#f1fa8c"))))) | |
(leaf major-mode-hydra | |
:doc "Use pretty-hydra to define template easily" | |
:url "https://github.com/jerrypnz/major-mode-hydra.el" | |
:ensure t | |
:require pretty-hydra) | |
(leaf hydra-posframe | |
:doc "Show hidra hints on posframe" | |
:url "https://github.com/Ladicle/hydra-posframe" | |
:if (window-system) | |
:el-get "Ladicle/hydra-posframe" | |
:global-minor-mode hydra-posframe-mode | |
:custom | |
(hydra-posframe-border-width . 5) | |
(hydra-posframe-parameters . '((left-fringe . 8) (right-fringe . 8))) | |
:custom-face | |
(hydra-posframe-border-face . '((t (:background "#323445"))))) | |
(leaf which-key | |
:doc "Displays available keybindings in popup" | |
:url "https://github.com/justbur/emacs-which-key" | |
:ensure t | |
:global-minor-mode which-key-mode) | |
;; fill-column | |
(leaf visual-fill-column | |
:doc "Centering & Wrap text visually" | |
:url "https://codeberg.org/joostkremers/visual-fill-column" | |
:ensure t | |
:hook (markdown-mode-hook . visual-fill-column-mode) | |
:custom | |
(visual-fill-column-width . 100) | |
(visual-fill-column-center-text . t) | |
:preface | |
(defun toggle-visual-fill-column-center () | |
(interactive) | |
(if visual-fill-column-center-text | |
(setq visual-fill-column-center-text nil) | |
(setq visual-fill-column-center-text t)))) | |
(leaf display-fill-column-indicator-mode | |
:doc "Indicate maximum colum" | |
:url "https://www.emacswiki.org/emacs/FillColumnIndicator" | |
:hook ((markdown-mode-hook git-commit-mode-hook) . display-fill-column-indicator-mode)) | |
(leaf display-line-numbers | |
:doc "Display line number" | |
:url "https://www.emacswiki.org/emacs/LineNumbers" | |
:hook (terraform-mode-hook . display-line-numbers-mode)) | |
(leaf rainbow-mode | |
:doc "Color letter that indicate the color" | |
:url "https://elpa.gnu.org/packages/rainbow-mode.html" | |
:ensure t | |
:hook (emacs-lisp-mode-hook . rainbow-mode)) | |
(leaf rainbow-delimiters | |
:doc "Display brackets in rainbow" | |
:url "https://www.emacswiki.org/emacs/RainbowDelimiters" | |
:ensure t | |
:hook (prog-mode-hook . rainbow-delimiters-mode)) | |
;; ----------------------------------------------------------------------------------------- | |
;; | |
;; Highlighting | |
;; | |
;; ----------------------------------------------------------------------------------------- | |
(leaf *paren | |
:doc "Hilight paired brackets" | |
:url "https://www.emacswiki.org/emacs/ShowParenMode" | |
:global-minor-mode show-paren-mode | |
:custom | |
(show-paren-style . 'mixed) | |
(show-paren-when-point-inside-paren . t) | |
(show-paren-when-point-in-periphery . t) | |
:custom-face | |
(show-paren-match . '((nil (:background "#44475a" :foreground "#f1fa8c"))))) | |
(leaf highlight-symbol | |
:doc "Automatic & Manual symbol highlighting" | |
:url "https://github.com/nschum/highlight-symbol.el" | |
:ensure t | |
:bind | |
(("M-p" . highlight-symbol-prev) | |
("M-n" . highlight-symbol-next))) | |
(leaf volatile-highlights | |
:doc "Hilight the pasted region" | |
:url "https://github.com/k-talo/volatile-highlights.el" | |
:el-get "k-talo/volatile-highlights.el" | |
:require volatile-highlights | |
:global-minor-mode volatile-highlights-mode | |
:custom-face | |
(vhl/default-face . '((nil (:inherit diff-refine-added))))) | |
(leaf *highlight-whitespace | |
:doc "Highligh trailing whitespace" | |
:hook | |
((prog-mode-hook markdown-mode-hook) | |
. (lambda () | |
(interactive) | |
(setq show-trailing-whitespace t)))) | |
(leaf highlight-indent-guides | |
:doc "Display structure for easy viewing" | |
:url "https://github.com/DarthFennec/highlight-indent-guides" | |
:ensure t | |
:hook (prog-mode-hook . highlight-indent-guides-mode) | |
:custom | |
(highlight-indent-guides-auto-enabled . t) | |
;; For Emacs 29 | |
(highlight-indent-guides-auto-enabled . nil) | |
(highlight-indent-guides-responsive . t) | |
(highlight-indent-guides-method . 'bitmap) | |
;; For Emacs v29 | |
:custom-face | |
(highlight-indent-guides-character-face . '((t (:foreground "#333544")))) | |
(highlight-indent-guides-top-character-face . '((t (:foreground "#44475a"))))) | |
(leaf hl-todo | |
:doc "Highlight TODO and similar keywords in comments and strings" | |
:url "https://github.com/tarsius/hl-todo" | |
:ensure t | |
:hook (prog-mode-hook . hl-todo-mode) | |
:custom (hl-todo-keyword-faces | |
. '(("TODO" . "#50fa7b") | |
("FIXME" . "#ff79c6") | |
("INFO" . "#f1fa8c") | |
("NOTE" . "#f1fa8c")))) | |
(leaf beacon | |
:doc "A light that follows your cursor around so you don't lose it!" | |
:url "https://github.com/Malabarba/beacon" | |
:ensure t | |
:custom (beacon-color . "#f1fa8c")) | |
;; ----------------------------------------------------------------------------------------- | |
;; | |
;; Search Interface | |
;; | |
;; ----------------------------------------------------------------------------------------- | |
(leaf migemo | |
:doc "Japanese increment search with 'Romanization of Japanese'" | |
:url "https://github.com/emacs-jp/migemo" | |
:if (executable-find "cmigemo") | |
:ensure t | |
:require migemo | |
:custom | |
(migemo-options . '("-q" "--nonewline" "--emacs")) | |
(migemo-command . "/opt/homebrew/bin/cmigemo") | |
(migemo-dictionary . "/opt/homebrew/Cellar/cmigemo/20110227/share/migemo/utf-8/migemo-dict") | |
(migemo-user-dictionary . nil) | |
(migemo-regex-dictionary . nil) | |
(migemo-coding-system . 'utf-8-unix) | |
:hook (after-init-hook . migemo-init)) | |
(leaf anzu | |
:doc "Displays current match and total matches information" | |
:url "https://github.com/emacsorphanage/anzu" | |
:ensure t | |
:bind ("M-r" . anzu-query-replace-regexp)) | |
(leaf projectile | |
:doc "Project navigation and management library" | |
:url "https://github.com/bbatsov/projectile" | |
:ensure t | |
:global-minor-mode projectile-mode) | |
;; Vertico -------------------------------------------------------------------------------- | |
(leaf vertico | |
:doc "Completion interface" | |
:url "https://github.com/minad/vertico/" | |
:global-minor-mode vertico-mode | |
:ensure t | |
:custom | |
(vertico-cycle . t) | |
(vertico-count . 18)) | |
(leaf vertico-posframe | |
:doc "Show Vertico in posframe" | |
:url "https://github.com/tumashu/vertico-posframe" | |
:global-minor-mode vertico-posframe-mode | |
:ensure t | |
:custom | |
(vertico-posframe-border-width . 5) | |
(vertico-posframe-parameters | |
. '((left-fringe . 8) | |
(right-fringe . 8))) | |
:custom-face | |
(vertico-posframe-border . '((t (:background "#323445"))))) | |
(leaf consult | |
:doc "Generate completion candidates and provide commands for completion" | |
:url "https://github.com/minad/consult" | |
:ensure t | |
:bind | |
("M-y" . consult-yank-pop) | |
("C-M-s" . consult-line) | |
:custom (consult-async-min-input . 1)) | |
(leaf consult-flycheck | |
:doc "Consult integration for Flycheck" | |
:url "https://github.com/minad/consult-flycheck" | |
:ensure t) | |
(leaf affe | |
:doc "Asynchronous Fuzzy Finder" | |
:url "https://github.com/minad/affe" | |
:ensure t) | |
(leaf consult-ghq | |
:doc "Consult integration for ghq (with affe)" | |
:url "https://github.com/tomoya/consult-ghq" | |
:ensure t | |
:require t | |
:config | |
(setq consult-ghq-find-function #'projectile-find-file)) | |
(leaf consult-make | |
:doc "Run make command in project root" | |
:after (consult projectile) | |
:require (consult projectile) | |
:custom | |
(consult-make-buffer-name . "*Consult Make*") | |
:preface | |
(defun consult-make--target-candidates () | |
"Generate candidates for GNU make" | |
(split-string | |
(let ((default-directory (projectile-project-root))) | |
;; Inspired by https://github.com/fish-shell/fish-shell/blob/master/share/completions/make.fish#L14-L18 | |
(shell-command-to-string | |
(concat "make -pRrq 2>/dev/null |\ | |
awk -F: '/^# Files/,/^# Finished Make data base/ { | |
if ($1 == \"# Not a target\") skip = 1; | |
if ($1 !~ \"^[#.\t]\") { if (!skip) print $1; skip=0 } | |
}'"))))) | |
(defun consult-make-in-project-root () | |
"Run make command in project root" | |
(interactive) | |
(let* ((default-directory (projectile-project-root)) | |
(makefile (concat default-directory "Makefile"))) | |
(if (file-readable-p makefile) | |
(let ((target (consult--read (consult-make--target-candidates) :prompt "Make Target: "))) | |
(async-shell-command (concat "make " target " && echo \"\ndone!\" || echo \"\nfailed...\"") consult-make-buffer-name)) | |
(message (concat "Not found Makefile in " default-directory)))))) | |
(leaf consult-shell-command | |
:doc "Select history using consult & run shell command" | |
:after (consult projectile) | |
:require (consult projectile) | |
:init | |
;; Change shell from zsh to fish | |
(setq-default shell-file-name (executable-find "fish")) | |
:custom | |
(consult-shell-command-prompt . "Command: ") | |
:preface | |
(defun consult-shell-command--history-candidates () | |
"Return shell command history candidate." | |
(split-string (shell-command-to-string "history") "\n" t)) | |
(defun consult-shell-command--execute (fn) | |
"Select shell command history or type new one using consult, | |
and then run it." | |
(interactive) | |
(let ((cmd (consult--read | |
(consult-shell-command--history-candidates) | |
:prompt consult-shell-command-prompt))) | |
(funcall fn cmd))) | |
(defun consult-shell-command () | |
"Select shell command history or type new one using consult, | |
and then run it." | |
(interactive) | |
(consult-shell-command--execute #'shell-command)) | |
(defun consult-async-shell-command () | |
"Select shell command history or type new one using consult, | |
and then run it asynchronous." | |
(interactive) | |
(consult-shell-command--execute #'async-shell-command)) | |
(defun consult-projectile-run-shell-command-in-root () | |
"Select shell command history or type new one using consult, | |
and then run it in the project root." | |
(interactive) | |
(consult-shell-command--execute #'projectile-run-shell-command-in-root)) | |
(defun consult-projectile-run-async-shell-command-in-root () | |
"Select shell command history or type new one using consult, | |
and then run it asynchronous in the project root." | |
(interactive) | |
(consult-shell-command--execute #'projectile-run-async-shell-command-in-root))) | |
(leaf consult-xwidget | |
:doc "Custom consult functions for xwidget" | |
:after consult | |
:require consult | |
:custom | |
(consult-xwidget-bookmarks | |
. '("https://chatgpt.com/?temporary-chat=true" | |
"https://localhost:1313/")) | |
:preface | |
(defun consult-browse () | |
(interactive) | |
(let ((url (consult--read consult-xwidget-bookmarks :prompt "URL: "))) | |
(progn | |
(funcall #'xwidget-webkit-browse-url url))))) | |
(leaf marginalia | |
:doc "Explain details of the consult candidates" | |
:url "https://github.com/minad/marginalia" | |
:global-minor-mode marginalia-mode | |
:ensure t | |
:custom-face | |
(marginalia-documentation . '((t (:foreground "#6272a4"))))) | |
(leaf orderless | |
:doc "Completion style that matches multiple regexps" | |
:url "https://github.com/oantolin/orderless" | |
:ensure t | |
:custom | |
;; NOTE: commented-out because to use fussy instead of orderless | |
(completion-styles . '(orderless)) | |
(completion-category-defaults . nil)) | |
(leaf fussy | |
:doc "About Emacs completion-style leveraging flx" | |
:url "https://github.com/jojojames/fussy" | |
:ensure t | |
:config | |
(push 'fussy completion-styles)) | |
(leaf fzf-native | |
:doc "Emacs package for fuzzy match scoring" | |
:url "https://github.com/dangduc/fzf-native" | |
:after fussy | |
:load-path "~/.emacs.d/el-get/fzf-native" | |
:require t | |
;; NOTE: el-get fail to build command, therefore I run the following command manually. | |
;; :el-get | |
;; (fzf-native | |
;; :type github | |
;; :pkgname "dangduc/fzf-native" | |
;; :build ("mkdir build" "cmake -B build -DCMAKE_C_FLAGS='-O3 -march=native'" "cmake --build build")) | |
:config | |
(setq fussy-score-fn #'fussy-fzf-native-score) | |
(fzf-native-load-dyn)) | |
;; I don't know why but this block does not work well only when the first boot. | |
;; Thus, I need to disabled this block for that time. | |
(leaf orderless-migemo | |
:doc "orderless migemo style for org-roam" | |
:require orderless | |
:preface | |
(defun orderless-migemo (component) | |
"Match COMPONENT as a migemo." | |
(let ((pattern (migemo-get-pattern component))) | |
(condition-case nil | |
(progn (string-match-p pattern "") pattern) | |
(invalid-regexp nil)))) | |
:config | |
(orderless-define-completion-style orderless-migemo-style | |
(orderless-matching-styles '(;; orderless-literal | |
;; orderless-regexp | |
orderless-migemo))) | |
;; Inspired by https://nyoho.jp/diary/?date=20210615 | |
(setq completion-category-overrides | |
'((file (styles . (partial-completion))) | |
;; e.g. consult-line | |
(consult-location (styles orderless-migemo-style)) | |
(org-roam-node (styles orderless-migemo-style))))) | |
;; wgrep is used for `consult-grep -> embark-export -> wgrep' combo | |
(leaf wgrep :ensure t) | |
(leaf embark | |
:doc "Mini-Buffer Actions Rooted in Keymaps Resources" | |
:url "https://github.com/oantolin/embark" | |
:ensure t | |
:bind | |
("M-a" . embark-act) | |
:custom | |
(prefix-help-command . #'embark-prefix-help-command) | |
:config | |
(setq embark-action-indicator | |
(lambda (map _target) | |
(which-key--show-keymap "Embark" map nil nil 'no-paging) | |
#'which-key--hide-popup-ignore-command) | |
embark-become-indicator embark-action-indicator)) | |
(leaf embark-consult | |
:ensure t | |
:hook | |
(embark-collect-mode . consult-preview-at-point-mode)) | |
;; ----------------------------------------------------------------------------------------- | |
;; | |
;; Global Bindings | |
;; | |
;; ----------------------------------------------------------------------------------------- | |
(leaf *custom-binding-maps | |
:init | |
(define-prefix-command 'ladicle-window-map) | |
(define-prefix-command 'ladicle-toggle-map) | |
(define-key global-map (kbd "M-o") 'ladicle-window-map) | |
(define-key global-map (kbd "M-t") 'ladicle-toggle-map)) | |
(leaf *global-bindings | |
:init | |
(define-key key-translation-map (kbd "C-h") (kbd "<DEL>")) | |
:bind | |
(("C-h" . delete-backward-char) | |
("C-m" . electric-newline-and-maybe-indent) | |
("C-j" . newline-and-indent) | |
("M-:" . comment-dwim) | |
;; Move ring | |
("C-," . pop-to-mark-command) | |
("C-." . consult-mark) | |
;; Move Buffer | |
("M-," . previous-buffer) | |
("M-." . next-buffer) | |
;; Shell Command | |
("M-!" . consult-async-shell-command) | |
("M-@" . consult-shell-command) | |
;; Browse | |
("C-c C-o" . browse-url-or-copy))) | |
;; Hydra Templates ------------------------------------------------------------------------- | |
(leaf *hydra-goto2 | |
:doc "Search and move cursor" | |
:bind ("M-j" . *hydra-goto2/body) | |
:pretty-hydra | |
((:title "↗ Goto" :color blue :quit-key "q" :foreign-keys warn :separator "╌") | |
("Got" | |
(("i" avy-goto-char "char") | |
("t" avy-goto-char-timer "timer") | |
("l" avy-goto-line "line") | |
("j" avy-resume "resume")) | |
"Line" | |
(("h" avy-goto-line "head") | |
("e" avy-goto-end-of-line "end") | |
("n" consult-goto-line "number")) | |
"Topic" | |
(("o" consult-outline "outline") | |
("m" consult-imenu "imenu") | |
("gm" consult-global-imenu "global imenu")) | |
"Error" | |
(("," lsp-bridge-diagnostic-jump-prev "previous") | |
("." lsp-bridge-diagnostic-jump-next "next") | |
("L" lsp-bridge-diagnostic-list "list")) | |
"Spell" | |
((">" flyspell-goto-next-error "next" :exit nil) | |
("cc" flyspell-correct-at-point "correct" :exit nil))))) | |
(leaf *hydra-toggle2 | |
:doc "Toggle functions" | |
:bind ("M-t" . *hydra-toggle2/body) | |
:pretty-hydra | |
((:title " Toggle" :color blue :quit-key "q" :foreign-keys warn :separator "-") | |
("Basic" | |
(("v" view-mode "view mode" :toggle t) | |
("w" whitespace-mode "whitespace" :toggle t) | |
("W" whitespace-cleanup "whitespace cleanup") | |
("r" rainbow-mode "rainbow" :toggle t) | |
("b" beacon-mode "beacon" :toggle t)) | |
"Line & Column" | |
(("l" toggle-truncate-lines "truncate line" :toggle t) | |
("n" display-line-numbers-mode "line number" :toggle t) | |
("F" display-fill-column-indicator-mode "column indicator" :toggle t) | |
("f" visual-fill-column-mode "visual column" :toggle t) | |
("c" toggle-visual-fill-column-center "fill center")) | |
"Highlight" | |
(("h" highlight-symbol "highligh symbol" :toggle t) | |
("L" hl-line-mode "line" :toggle t) | |
("t" hl-todo-mode "todo" :toggle t) | |
("g" git-gutter-mode "git gutter" :toggle t) | |
("i" highlight-indent-guides-mode "indent guide" :toggle t)) | |
"Window" | |
(("t" toggle-window-transparency "transparency" :toggle t) | |
("m" toggle-window-maximize "maximize" :toggle t) | |
("p" presentation-mode "presentation" :toggle t))))) | |
(leaf *hydra-toggle-markdown1 | |
:doc "Toggle functions for Markdown" | |
:bind | |
(:markdown-mode-map | |
:package markdown-mode | |
("M-t" . *hydra-toggle-markdown1/body)) | |
:pretty-hydra | |
((:title " Toggle" :color blue :quit-key "q" :foreign-keys warn :separator "╌") | |
("Basic" | |
(("w" whitespace-mode "whitespace" :toggle t) | |
("W" whitespace-cleanup "whitespace cleanup") | |
("l" hl-line-mode "line" :toggle t) | |
("g" git-gutter-mode "git gutter" :toggle t)) | |
"Markdown" | |
(("v" markdown-view-mode "view mode") | |
("u" markdown-toggle-markup-hiding "markup hiding" :toggle t) | |
("l" markdown-toggle-url-hiding "url hiding" :toggle t)) | |
"Line & Column" | |
(("l" toggle-truncate-lines "truncate line" :toggle t) | |
("i" display-fill-column-indicator-mode "column indicator" :toggle t) | |
("c" visual-fill-column-mode "visual column" :toggle t)) | |
"Window" | |
(("t" toggle-window-transparency "transparency" :toggle t) | |
("m" toggle-window-maximize "maximize" :toggle t) | |
("p" presentation-mode "presentation" :toggle t))))) | |
(leaf *hydra-search | |
:doc "Search functions" | |
:bind | |
("M-s" . *hydra-search/body) | |
:pretty-hydra | |
((:title "🔍 Search" :color blue :quit-key "q" :foreign-keys warn :separator "╌") | |
("Buffer" | |
(("l" consult-line "line") | |
("o" consult-outline "outline") | |
("m" consult-imenu "imenu")) | |
"Project" | |
(("f" affe-find "find") | |
("r" consult-ripgrep "grep") | |
("R" affe-grep "affe")) | |
"Document" | |
(("df" consult-find-doc "find") | |
("dd" consult-grep-doc "grep"))))) | |
(leaf *hydra-git | |
:bind | |
("M-g" . *hydra-git/body) | |
:pretty-hydra | |
((:title " Git" :color blue :quit-key "q" :foreign-keys warn :separator "╌") | |
("Basic" | |
(("w" magit-checkout "checkout") | |
("s" magit-status "status") | |
("b" magit-branch "branch") | |
("F" magit-pull "pull") | |
("f" magit-fetch "fetch") | |
("A" magit-apply "apply") | |
("c" magit-commit "commit") | |
("P" magit-push "push")) | |
"" | |
(("d" magit-diff "diff") | |
("l" magit-log "log") | |
("r" magit-rebase "rebase") | |
("z" magit-stash "stash") | |
("!" magit-run "run shell command") | |
("y" magit-show-refs "references")) | |
"Hunk" | |
(("," git-gutter:previous-hunk "previous" :exit nil) | |
("." git-gutter:next-hunk "next" :exit nil) | |
("g" git-gutter:stage-hunk "stage") | |
("v" git-gutter:revert-hunk "revert") | |
("p" git-gutter:popup-hunk "popup")) | |
" GitHub" | |
(("C" checkout-gh-pr "checkout PR") | |
("o" browse-at-remote-or-copy"browse at point") | |
("k" browse-at-remote-kill "copy url") | |
("O" (shell-command "hub browse") "browse repository"))))) | |
(leaf *hydra-shortcuts | |
:doc "General Shortcuts" | |
:bind ("M-o" . *hydra-shortcuts/body) | |
:pretty-hydra | |
((:title " Shortcuts" :color blue :quit-key "q" :foreign-keys warn :separator "╌") | |
("Transform" | |
(("<left>" (shrink-window-horizontally 3) "←" :exit nil) | |
("<up>" (shrink-window 3) "↑" :exit nil) | |
("<down>" (enlarge-window 3) "↓" :exit nil) | |
("<right>"(enlarge-window-horizontally 3) "→" :exit nil) | |
("<SPC>" rotate-layout "rotate" :exit nil) | |
("-" split-window-vertically "vertical") | |
("/" split-window-horizontally "horizontal")) | |
"Window" | |
(("d" kill-current-buffer "close") | |
("D" kill-buffer-and-window "kill") | |
("O" delete-other-windows "close others") | |
("s" ace-swap-window "swap") | |
("m" toggle-window-maximize "maximize")) | |
"Utility" | |
(("T" gts-do-translate "translate") | |
("v" vterm-toggle-cd-show "vterm") | |
("g" hack-go-current-abc-quiz "go ABC") | |
("P" consult-tramp "tramp") | |
("z" presentation-mode "presentation")) | |
"Buffer" | |
(("x" consult-browse "web") | |
("b" consult-buffer "open") | |
("B" consult-buffer-other-window "open other") | |
("R" (switch-to-buffer (get-buffer-create "*scratch*")) "scratch") | |
("," previous-buffer "previous" :exit nil) | |
("." next-buffer "next" :exit nil)) | |
"File" | |
(("r" consult-buffer "recent") | |
;; ("f" affe-find "find") | |
("f" projectile-find-file "find") | |
("p" consult-ghq-find "ghq") | |
("@" consult-projectile-run-shell-command-in-root "$run") | |
("!" consult-projectile-run-async-shell-command-in-root "$async")) | |
"Org" | |
(("c" org-capture "capture") | |
("l" calendar "calendar") | |
("a" org-agenda "agenda") | |
("o" org-clock-goto "clock") | |
("j" (if (file-exists-p (today-journal-file)) | |
(org-open-file (today-journal-file)) | |
(org-journal-new-entry "")) | |
"journal") | |
("t" (org-open-file org-task-file) "task") | |
("w" (org-open-file org-work-file) "work"))))) | |
;; (profiler-report) | |
;; (profiler-stop) | |
(setq gc-cons-threshold 16777216) ; 16mb | |
(provide 'init) | |
;;; init.el ends here |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment