My Emacs Configuration

Emacs Configuration

leafで管理するようにしました。 必要以上にカスタマイズしないようにしています。

init.el


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

(eval-and-compile
  (customize-set-variable
   'package-archives '(("gnu"   . "https://elpa.gnu.org/packages/")
                       ("melpa" . "https://melpa.org/packages/")
                       ("org"   . "https://orgmode.org/elpa/")))
  (package-initialize)
  (unless (package-installed-p 'leaf)
    (package-refresh-contents)
    (package-install 'leaf))

  (leaf leaf-keywords
    :ensure t
    :init
    (leaf hydra :ensure t)
    (leaf blackout :ensure t)
    (leaf bind-key :ensure t :require t)
    (leaf eshell)

    :config
    ;; initialize leaf-keywords.el
    (leaf-keywords-init)))

(leaf leaf
  :config
  (leaf leaf-convert
        :ensure t
        :config (leaf use-package :ensure t))
  (leaf leaf-tree
    :ensure t
    :custom ((imenu-list-size . 30)
             (imenu-list-position . 'left))))

(leaf macrostep
  :ensure t
  :bind (("C-c e" . macrostep-expand)))

(leaf cus-edit
  :doc "tools for customizing Emacs and Lisp packages"
  :tag "builtin" "faces" "help"
  :custom `((custom-file . ,(locate-user-emacs-file "custom.el"))))

(leaf server
  :require t
  :defun (server-running-p)
  :custom ((server-port . 50545)
           (server-use-tcp . t))
  :config
  (unless (server-running-p)
    (server-start))
  (when (display-graphic-p)
    (add-to-list 'default-frame-alist
                 '(font . "jetbrains mono-12:foundry=JB:slant=normal:weight=normal:height=128:width=normal"))
    (set-face-attribute 'default nil :font "jetbrains mono-12:foundry=JB:slant=normal:weight=normal:height=128:width=normal")))

(leaf startup
  :custom
  ((inhibit-startup-screen . t)
   (inhibit-startup-message . t)
   (inhibit-splash-screen . t)
   (inhibit-startup-echo-area-message . t)
   (initial-scratch-message . nil))
  :config
  (menu-bar-mode -1)
  (tool-bar-mode 0))

(leaf basic
  :setq-default
  ((explicit-shell-file-name . "/usr/bin/bash"))
  :setq
  `((read-process-output-max . ,(* 1024 1024 2))
    (gc-cons-threshold . 100000000))

  :custom
  `((gc-cons-threshold . ,(* 8 1024 1024))
    (garbage-collection-messages . nil)
    (cua-enable-cua-keys . nil)
    (fill-column . 100)
    (c-basic-offset . 2)
    (tab-width . 2)
    (indent-tabs-mode . nil)
    (vc-follow-symlinks . t)
    (make-backup-files . nil)
    (auto-save-default . nil)
    (auto-save-list-file-prefix . nil)
    (create-lockfiles . nil)
    (recentf-save-file . "~/.emacs.d/.recentf")
    (recentf-max-saved-items . 10000)
    (history-length . 10000)
    (messagep-log-max . 10000)
    (redisplay-dont-pause . t)
    (frame-title-format . "%b")
    (truncate-lines . t)
    (truncate-partial-width-windows . nil)
    (kill-whole-line . t))

  :config
  (global-display-line-numbers-mode t)
  (global-unset-key (kbd "C-\\"))
  (prefer-coding-system 'utf-8)
  (set-default-coding-systems 'utf-8)
  (set-terminal-coding-system 'utf-8)
  (column-number-mode t)
  (cua-mode t)
  (savehist-mode t)
  (transient-mark-mode t)
  (delete-selection-mode t)
  (global-whitespace-mode t)

  (leaf paren
    :custom
    ((show-paren-style  . 'mixed))
    :hook
    (after-init-hook . show-paren-mode))

  (leaf s
    :require t
    :ensure t)

  (leaf autorevert
    :custom
    ((auto-revert-check-vc-info . t)
     (auto-revert-interval . 5))
    :global-minor-mode global-auto-revert-mode)

  (leaf xclip
    :require t
    :ensure t
    :config
    (xclip-mode 1))

  (leaf eldoc
    :ensure t
    :blackout t)

  (leaf whitespace
    :require t
    :ensure t
    :custom ((whitespace-style . '(space-mark tab-mark face spaces trailing))
             (whitespace-display-mappings . '((space-mark 160 [164] [95])
                                              (space-mark 2208 [2212] [95])
                                              (space-mark 2336 [2340] [95])
                                              (space-mark 3616 [3620] [95])
                                              (space-mark 3872 [3876] [95])
                                              (space-mark 12288 [9633] [95 95])
                                              (tab-mark 9 [187 9] [92 9])))
             (whitespace-space-regexp . "\\( +\\)"))
    :blackout t
    :config
    (set-face-foreground 'whitespace-space "cyan")
    (set-face-background 'whitespace-space 'nil)
    (set-face-underline 'whitespace-trailing t)
    (set-face-foreground 'whitespace-trailing "cyan")
    (set-face-background 'whitespace-trailing 'nil))

  (leaf mozc
    :ensure t
    :blackout t
    :custom ((set-language-environment . "Japanese")
             (default-input-method . "japanese-mozc"))
    :config
    (global-set-key [zenkaku-hankaku] 'toggle-input-method)
    (global-set-key [henkan] (lambda ()
                               (interactive)
                               (when (null current-input-method)
                                 (toggle-input-method))))
    (global-set-key [muhenkan] (lambda ()
                                 (interactive)
                                 (deactivate-input-method)))

    (defadvice mozc-handle-event (around intercept-keys (event))
      "Intercept keys muhenkan and zenkaku-hankaku, before passing keys\nto mozc-server (which the function mozc-handle-event does), to\nproperly disable mozc-mode."
      (if (member event (list 'zenkaku-hankaku 'muhenkan))
          (progn
            (mozc-clean-up-session)
            (toggle-input-method))
        (progn
          ad-do-it)))
    (ad-activate 'mozc-handle-event))

  (leaf auto-sudoedit
    :ensure t
    :blackout t
    :hook (after-init-hook)))

(leaf projectile
  :ensure t
  :custom ((projectile-completion-system . 'ivy))
  :blackout t
  :config
  (projectile-mode 1)
  (leaf counsel-projectile
    :ensure t
    :config
    (counsel-projectile-mode 1)))

(leaf gui
  :config
  (leaf all-the-icons :ensure t)
  (leaf all-the-icons-dired :ensure t)
  (leaf focus
    :ensure t)

  (leaf doom-themes
    :ensure t
    :custom ((doom-themes-enable-italic . t)
             (doom-themes-enable-bold . t)
             (doom-challenger-deep-brighter-comments . t)
             (doom-molokai-brighter-comments . t)
             (doom-dracula-brighter-comments . t))
    :custom-face ((line-number . '((t (:foreground "#757878"))))
                  (ivy-virtual . '((t (:foreground "#FF6188")))))
    :config
    (doom-themes-neotree-config)
    (doom-themes-org-config))

  (leaf color-identifiers-mode
    :ensure t
    :blackout t
    :commands global-color-identifiers-mode
    :hook ((after-init-hook . global-color-identifiers-mode)))

  (leaf highlight-indent-guides
    :ensure t
    :blackout t
    :hook (yaml-mode-hook)
    :custom ((highlight-indent-guides-auto-enabled . t)
             (highlight-indent-guides-responsive . t)
             (highlight-indent-guides-method . 'character)))

  (leaf git-gutter
    :ensure t
    :custom ((git-gutter:modified-sign . "~")
             (git-gutter:added-sign . "+")
             (git-gutter:deleted-sign . "-"))
    :custom-face ((git-gutter:modified . '((t (:background "#f1fa8c"))))
                  (git-gutter:added . '((t (:background "#50fa7b"))))
                  (git-gutter:deleted . '((t (:background "#ff79c6")))))
    :config
    (global-git-gutter-mode 1))

  (leaf doom-modeline
    :ensure t
    :hook (after-init-hook)
    :custom ((doom-modeline-buffer-file-name-style quote truncate-with-project)
             (doom-modeline-icon . t)
             (doom-modeline-major-mode-icon . t)
             (doom-modeline-major-mode-color-icon . t)
             (line-number-mode . 1)
             (column-number-mode . 1)))

  (leaf volatile-highlights
    :ensure t
    :hook (after-init-hook)
    :blackout t
    :custom-face
    ((vhl/default-face . '((nil (:foreground "#FF3333" :background "#FFCDCD"))))))

  (leaf beacon
    :ensure t
    :blackout t
    :hook (prog-mode-hook)
    :custom ((beacon-color . "#77fffa")
             (beacon-blink-duration . 0.7)
             (beacon-size . 100)))

  (leaf fill-column-indicator
    :commands fci-mode)

  (leaf rainbow-delimiters
    :ensure t
    :blackout t
    :hook (prog-mode-hook))

  (leaf presentation
    :ensure t
    :commands presentation-mode)

  (leaf rainbow-mode
    :ensure t)

  (leaf centaur-tabs
    :ensure t
    :custom ((centaur-tabs-height . 28)
             (centaur-tabs-style . "bar")
             (centaur-tabs-set-icons . t)
             (centaur-tabs-set-bar . 'over)
             (centaur-tabs-set-close-button . nil)
             (centaur-tabs-set-modified-marker . t)
             (centaur-tabs-modified-marker . "●"))
    :config
    (centaur-tabs-mode t))

  (if (daemonp)
      (add-hook
       'after-make-frame-functions
       (lambda (frame)
         (select-frame frame)
         (setenv "SSH_AUTH_SOCK" "/run/user/1000/gnupg/S.gpg-agent.ssh")
         (when (display-graphic-p)
           (add-to-list 'default-frame-alist '(font . "jetbrains mono-12:foundry=JB:slant=normal:weight=normal:height=128:width=normal"))
           (set-face-attribute 'default nil :font "jetbrains mono-12:foundry=JB:slant=normal:weight=normal:height=128:width=normal")
           (set-fontset-font (frame-parameter nil 'font)
                             'japanese-jisx0208
                             (font-spec :family "Ricty" :size 16))
           (set-fontset-font (frame-parameter nil 'font)
                             'katakana-jisx0201
                             (font-spec :family "Ricty" :size 16))
           (set-frame-parameter (window-frame) 'cursor-type 'bar))
         (load-theme 'doom-monokai-pro t)))
    (load-theme 'doom-monokai-pro t)))

(leaf dired
  :require t
  :custom ((dired-recursive-deletes . 'always)
           (dired-recursive-copies . 'always))
  :config
  (leaf diredfl
    :require t
    :ensure t
    :config
    (diredfl-global-mode 1))

  (leaf all-the-icons-dired
    :require t
    :ensure t
    :hook (dired-mode-hook)
    :custom-face ((all-the-icons-dired-dir-face '((t (:foreground nil))))))

  (leaf dired-aux
    :require t))

(leaf yasnippet
  :ensure t
  :blackout t
  :commands yas-global-mode
  :hook ((after-init-hook . yas-global-mode))
  :custom ((yas-snippet-dirs . '("~/.emacs.d/snippets"))))

(leaf ivy
  :blackout t
  :ensure t
  :bind (("C-c C-r" . ivy-resume)
         (ivy-minibuffer-map
          ("<backspace>" . backward-delete-char-untabify)
          ("<right>" . ivy-alt-done)
          ("<left>" . ivy-alt-done)
          ("<enter>" . ivy-immediate-done)
          ("C-z" . ivy-dispatching-done)))
  :global-minor-mode t
  :leaf-defer nil
  :custom ((ivy-initial-inputs-alist . nil)
           (enable-recursive-minibuffers . t)
           (ivy-use-virtual-buffers . t)
           (ivy-count-format . "(%d/%d) ")
           (ivy-use-selectable-prompt . t)
           (ivy-format-function . 'ivy-format-function-line))

  :config

  (leaf wgrep
    :ensure t
    :after ivy
    :custom ((wgrep-enable-key . "e")
             (wgrep-auto-save-buffer . t)
             (wgrep-change-readonly-file . t)))

  (leaf swiper
    :ensure t
    :blackout t
    :commands swiper
    :bind (("C-S-s" . swiper-all))
    :custom ((swiper-action-recenter . t)))

  (leaf counsel
    :ensure t
    :blackout t
    :global-minor-mode t
    :bind (("M-x" . counsel-M-x)
           ("C-x C-f" . counsel-find-file)
           ("C-x C-b" . ivy-switch-buffer)
           ("C-c g" . counsel-git)
           ("C-c i" . counsel-imenu)
           ("C-M-." . counsel-imenu)
           ("C-c a" . counsel-ag)
           ("C-c r" . counsel-rg)
           (minibuffer-local-map
            ("C-r" . counsel-minibuffer-history)))
    :custom ((counsel-find-file-at-point . t)))

  (leaf ivy-rich
    :ensure t
    :after ivy
    :global-minor-mode t)

  (leaf prescient
    :ensure t
    :commands (prescient-persist-mode)
    :custom `((prescient-aggressive-file-save . t)
              (prescient-save-file . ,(locate-user-emacs-file "prescient")))
    :global-minor-mode prescient-persist-mode)

  (leaf ivy-prescient
    :ensure t
    :after prescient ivy
    :custom ((ivy-prescient-retain-classic-highlighting . t))
    :global-minor-mode t)

  (leaf ivy-xref
    :ensure t))

(leaf edit
  :config
  (leaf expand-region
    :ensure t
    :bind (("C-@" . er/expand-region)
           ("C-M-@" . er/contract-region)))
  (leaf undo-tree
    :ensure t
    :config
    (global-undo-tree-mode))

  (leaf browse-kill-ring
    :ensure t
    :bind (("M-y" . browse-kill-ring))
    :custom ((browse-kill-ring-display-style . 'one-line)
             (browse-kill-ring-replace-yank . t)))
  (leaf smart-hungry-delete
    :ensure t
    :require t
    :bind (("<backspace>" . smart-hungry-delete-backward-char)
           ("<DEL>" . smart-hungry-delete-backward-char)
           ("C-d" . smart-hungry-delete-forward-char))
    :config
    (smart-hungry-delete-add-default-hooks))

  )

(leaf search
  :config
  (leaf posframe :ensure t)

  (leaf ace-jump-mode
    :ensure t
    :blackout t)

  (leaf avy
    :ensure t
    :blackout t)

  (leaf ace-isearch
    :ensure t
    :blackout t
    :commands global-ace-isearch-mode
    :hook ((after-init-hook . global-ace-isearch-mode))
    :custom ((ace-isearch-input-length . 6)
             (ace-isearch-jump-delay . 1.2)
             (ace-isearch-function quote avy-goto-char)
             (ace-isearch-use-jump quote printing-char)
             (ace-isearch-function-from-isearch quote ace-isearch-swiper-from-isearch)))

  (leaf anzu
    :ensure t
    :commands global-anzu-mode anzu-mode
    :bind (("M-%" . anzu-query-replace)
           ("C-M-%" . anzu-query-replace-regexp))
    :hook ((after-init-hook . global-anzu-mode))
    :custom ((anzu-mode-lighter . "")
             (anzu-search-threshold . 1000)
             (anzu-replace-to-string-separator . " => ")))

  (leaf symbol-overlay
    :ensure t
    :blackout t
    :commands symbol-overlay-get-symbol symbol-overlay-assoc symbol-overlay-get-list symbol-overlay-jump-call
    :bind (("M-i" . symbol-overlay-put)
           ("C-M-n" . symbol-overlay-jump-next)
           ("C-M-m" . symbol-overlay-jump-prev)
           ("M-n" . symbol-overlay-switch-forward)
           ("M-p" . symbol-overlay-switch-backward)
           ("M-c" . symbol-overlay-remove-all))
    :hook (prog-mode-hook))

  (leaf dumb-jump
    :ensure t
    :commands dumb-jump-mode
    :custom ((dumb-jump-selector . 'ivy)))

  (leaf jumplist
    :require t
    :ensure t
    :defvar (initial-mark)
    :defun (jumplist--set set-initial-mark)
    :preface
    (defvar initial-mark nil)
    (defun set-initial-mark ()
      (unless initial-mark
        (setq initial-mark t)
        (jumplist--set)))
    :bind (("C-c p" . jumplist-previous)
           ("C-c n" . jumplist-next)
           ("M-<left>" . jumplist-previous)
           ("M-<right>" . jumplist-next))
    :custom ((jumplist-ex-mode . t)
             (jumplist-hook-commands . '(find-file
                                         dired-jump
                                         counsel-find-file
                                         counsel-git
                                         counsel-git-grep
                                         counsel-ag
                                         counsel-rg
                                         counsel-fzf
                                         smart-jump-go
                                         dumb-jump-go
                                         buffer-expose
                                         swiper
                                         ivy-switch-buffer
                                         isearch-forward
                                         end-of-buffer
                                         beginning-of-buffer
                                         godef-jump
                                         xref-location
                                         meghanada-jump-declaration)))
    :hook ((prog-mode markdown-mode)
            .
            (lambda ()
              (set-initial-mark))))

  (leaf smart-jump
    :ensure t
    :config
    (smart-jump-setup-default-registers)))

(leaf company
  :ensure t
  :blackout t
  :defvar (company-dabbrev-ignore-case
           company-dabbrev-downcase
           company-backends)
  :global-minor-mode global-company-mode
  :leaf-defer nil
  :bind (("M-/" . company-complete)
         (company-active-map
          ("C-p" . company-select-previous)
          ("C-n" . company-select-next)
          ("<tab>" . company-complete-common-or-cycle))
         (company-search-map
          ("C-p" . company-select-previous)
          ("C-n" . company-select-next)))
  :hook ((after-init-hook . global-company-mode)
         ((go-mode
           c++-mode
           c-mode
           dart-mode
           vue-mode
           js2-mode
           rust-mode
           objc-mode
           typescript-mode
           json-mode)
          .
          (lambda ()
            (set (make-local-variable 'company-backends)
                 '((company-capf
                    :with
                    company-tabnine
                    company-yasnippet
                    company-files
                    company-dabbrev-code))))))

  :custom ((company-transformers . '(company-sort-by-backend-importance))
           (company-tooltip-align-annotations . t)
           (company-idle-delay . 0)
           (company-echo-delay . 0)
           (company-minimum-prefix-length . 2)
           (company-quickhelp-mode . t)
           (company-require-match . nil)
           (company-dabbrev-ignore-case . nil)
           (company-dabbrev-downcase . nil))
  :config
  (leaf eacl
    :ensure t
    :bind (("C-c C-c" . eacl-complete-line)))
  (leaf company-quickhelp
    :ensure t)
  (leaf company-terraform
    :ensure t)
  (leaf company-tabnine
    :ensure t))

(leaf flycheck
  :ensure t
  :blackout t
  :commands flycheck-mode
  :global-minor-mode global-flycheck-mode
  :bind (("M-p" . flycheck-previous-error)
         ("M-n" . flycheck-next-error)))

(leaf flymake
  :blackout t
  :config
  (leaf flymake-diagnostic-at-point
    :ensure t
    :after flymake
    :hook (flymake-mode-hook)
    :custom ((flymake-diagnostic-at-point-timer-delay . 0.1)
             (flymake-diagnostic-at-point-error-prefix . "☠ ")
             (flymake-diagnostic-at-point-display-diagnostic-function quote flymake-diagnostic-at-point-display-popup))))

(leaf shell
  :config

  (leaf direnv
    :ensure t
    :config
    (direnv-mode))

  (leaf popwin
    :ensure t
    :blackout t
    :commands popwin-mode
    :custom
    (popwin:special-display-config . '(("*Completions*" :noselect t :height 0.4)
                                       ("*tag" :noselect t :regexp t :height 0.4)
                                       ("*Flutter*" :noselect t :regexp t :height 0.4)
                                       ("helm" :regexp t :height 0.4)
                                       ("typeinfo" :regexp t :height 0.4)
                                       ("reference" :regexp t :height 0.4)
                                       ("*cider-repl" :regexp t :height 0.4)
                                       ("*cider-error" :regexp t :height 0.4)
                                       ("*cider-doc" :regexp t :height 0.4)
                                       ("*cider-apropos" :regexp t :height 0.4))))

  (leaf shell-pop
    :ensure t
    :blackout t
    :bind (("C-t" . shell-pop))
    :custom ((shell-pop-shell-type . '("eshell" "*eshell*" (lambda () (eshell shell-pop-term-shell))))
             (shell-pop-universal-key . "C-t")
             (shell-pop-window-size . 70)
             (shell-pop-full-span . t)
             (shell-pop-window-position . "bottom")))

  (leaf eshell
    :blackout t
    :defun (eshell-copy-environment eshell-flatten-and-stringify eshell-stringify-list eshell-view-file)
    :preface
    (defun eshell/nop ()
      (interactive))

    (defun eshell/clear ()
      "Clear the eshell buffer."
      (interactive)
      (let ((inhibit-read-only t))
        (erase-buffer)
        (eshell-send-input)))

    (defun eshell/emacs (&rest args)
      "Open a file (ARGS) in Emacs.  Some habits die hard."
      (if (null args)
          (bury-buffer)
        (mapc #'find-file
              (mapcar #'expand-file-name
                      (eshell-flatten-list
                       (reverse args))))))

    (defalias 'eshell/e 'eshell/emacs)

    (defun eshell/ec (&rest args)
      "Compile a file (ARGS) in Emacs.  Use `compile' to do background make."
      (if (eshell-interactive-output-p)
          (let ((compilation-process-setup-function (list 'lambda nil
                                                          (list 'setq 'process-environment
                                                                (list 'quote
                                                                      (eshell-copy-environment))))))
            (compile
             (eshell-flatten-and-stringify args))
            (pop-to-buffer compilation-last-buffer))
        (throw 'eshell-replace-command
               (let ((l (eshell-stringify-list
                         (eshell-flatten-list args))))
                 (eshell-parse-command
                  (car l)
                  (cdr l))))))
    (put 'eshell/ec 'eshell-no-numeric-conversions t)
    (defun eshell-view-file (file)
      "View FILE.  A version of `view-file' which properly rets the eshell prompt."
      (interactive "fView file: ")
      (unless (file-exists-p file)
        (error "%s does not exist" file))
      (let ((buffer (find-file-noselect file)))
        (if (eq
             (get
              (buffer-local-value 'major-mode buffer)
              'mode-class)
             'special)
            (progn
              (switch-to-buffer buffer)
              (message "Not using View mode because the major mode is special"))

          (let ((undo-window (list
                              (window-buffer)
                              (window-start)
                              (+
                               (window-point)
                               (length
                                (funcall eshell-prompt-function))))))
            (switch-to-buffer buffer)
            (view-mode-enter
             (cons
              (selected-window)
              (cons nil undo-window))
             'kill-buffer)))))

    (defun eshell/less (&rest args)
      "Invoke `view-file' on a file (ARGS).  \"less +42 foo\" will go to line 42 in the buffer for foo."
      (while args
        (if (string-match "\\`\\+\\([0-9]+\\)\\'"
                          (car args))
            (let* ((line (string-to-number
                          (match-string 1
                                        (pop args))))
                   (file (pop args)))
              (eshell-view-file file)
              (forward-line line))
          (eshell-view-file
           (pop args)))))

    (defalias 'eshell/more 'eshell/less)

    :defvar compilation-last-buffer eshell-prompt-function eshell-mode  eshell-mode-map
    :commands eshell/alias eshell-send-input eshell-flatten-list eshell-interactive-output-p eshell-parse-command
    :config
    (setq-local eshell-mode-map (make-sparse-keymap))

    (leaf eshell-bookmark
      :ensure t
      :after eshell
      :hook ((eshell-mode-hook . eshell-bookmark-setup)))

    (leaf esh-autosuggest
      :defvar ivy-display-functions-alist
      :preface
      (defun setup-eshell-ivy-completion nil
        (setq-local ivy-display-functions-alist (remq
                                                 (assoc 'ivy-completion-in-region ivy-display-functions-alist)
                                                 ivy-display-functions-alist)))
      :commands setup-eshell-ivy-completion
      :bind ((eshell-mode-map
              ([remap eshell-pcomplete] . completion-at-point)))
      :hook (eshell-mode-hook
             (eshell-mode-hook . setup-eshell-ivy-completion)))


    (add-hook 'eshell-mode-hook
              #'(lambda nil
                  (bind-key "C-l" 'eshell/clear eshell-mode-map)
                  (bind-key "C-x C-b" 'eshell/nop eshell-mode-map)
                  (bind-key "C-x b" 'eshell/nop eshell-mode-map)
                  (bind-key "C-x C-f" 'eshell/nop eshell-mode-map)
                  (bind-key "C-x f" 'eshell/nop eshell-mode-map)
                  (eshell/alias "f" "find-file $1")
                  (eshell/alias "fo" "find-file-other-window $1")
                  (eshell/alias "d" "dired $1")
                  (eshell/alias "ll" "ls -l")
                  (eshell/alias "la" "ls -al")))))

(leaf *docker
  :config
  (leaf dockerfile-mode
    :ensure t
    :mode ("Dockerfile\\'")
    :hook (dockerfile-mode-hook
           .
           (lambda ()
             (lsp))))
  (leaf docker
    :ensure t
    :bind (("C-c d" . docker))))

(leaf magit
  :blackout t
  :ensure t
  :commands magit-status magit-dispatch-popup magit-list-repositories
  :custom ((magit-repository-directories . '(("~/repos/" . 3))))
  :config
  (leaf forge
    :ensure t
    :after magit))

(leaf misc
  :config

  (leaf quickrun
    :ensure t)

  (leaf reformatter
    :ensure t)

  (leaf smartparens
    :ensure t
    :blackout t
    :commands smartparens-global-mode
    :hook (prog-mode-hook markdown-mode-hook))

  (leaf paradox
    :commands paradox-list-packages paradox-enable
    :custom ((paradox-github-token . t)))

  (leaf flyspell
    :ensure t
    :blackout t
    :defvar (flyspell-mode-map)
    :when (executable-find "aspell")
    :commands flyspell-prog-mode
    :hook (text-mode-hook outline-mode-hook
                          (prog-mode-hook . flyspell-prog-mode))
    :custom ((flyspell-issue-message-flag . t)
             (ispell-program-name . "aspell")
             (ispell-extra-args . '("--sug-mode=ultra" "--lang=en_US" "--run-together")))
    :hook (flyspell-mode-hook
           .
           (lambda ()
             (dolist (key '("C-;" "C-," "C-."))
               (unbind-key key flyspell-mode-map)))))

  (leaf imenu-list
    :ensure t
    :custom ((imenu-list-focus-after-activation . t)
             (imenu-list-auto-resize))
    :custom-face ((imenu-list-entry-face-1 . '((t (:foreground "white"))))))

  (leaf which-key
    :ensure t
    :blackout t
    :hook (after-init-hook))

  (leaf restclient
    :ensure t)

  (leaf easy-hugo
    :ensure t
    :bind (("C-c C-e" . easy-hugo))
    :custom
    (easy-hugo-basedir . "~/repos/github.com/mopemope/blog/")
    (easy-hugo-url . "https://yourblogdomain")
    (easy-hugo-sshdomain . "blogdomain")
    (easy-hugo-postdir . "content/post")
    (easy-hugo-root . "~/repos/github.com/mopemope/blog/")
    (easy-hugo-previewtime . "300"))

  (leaf browse-kill-ring
    :ensure t
    :bind (("M-y" . browse-kill-ring))
    :custom ((browse-kill-ring-display-style . 'one-line)
             (browse-kill-ring-replace-yank . t)))

  (leaf dashboard
    :ensure t
    :blackout t
    :defun (my-banner-path dashboard-get-banner-path)
    :preface
    (defun my-banner-path (&rest _)
      "Return the full path to banner."
      (expand-file-name "banner.txt" user-emacs-directory))

    :commands dashboard-setup-startup-hook
    :hook ((after-init-hook . dashboard-setup-startup-hook))
    :custom ((dashboard-center-content . t)
             (dashboard-startup-banner . 4)
             (dashboard-items . '((recents . 15)
                                  (projects . 5)
                                  (bookmarks . 5)))
             (dashboard-set-heading-icons . t)
             (dashboard-set-file-icons . t))
    :custom-face ((dashboard-text-banner . '((t (:foreground "#feff8f" :weight bold)))))
    :config
    (advice-add #'dashboard-get-banner-path :override #'my-banner-path))

  (leaf google-this
    :ensure t
    :config
    (google-this-mode 1))

  (leaf browse-at-remote
    :ensure t
    :bind (("M-g r" . browse-at-remote))
    :custom ((browse-at-remote-prefer-symbolic))))

(leaf lsp
  :config
  (leaf lsp-docker
    :ensure t
    :require t
    :defun lsp-docker-init-clients
    :config
    (defvar lsp-docker-client-packages
      '(lsp-css lsp-clients lsp-bash lsp-go lsp-pyls lsp-html lsp-typescript
                lsp-terraform lsp-cpp))

    (defvar lsp-docker-client-configs
      (list
       (list :server-id 'bash-ls :docker-server-id 'bashls-docker :server-command "bash-language-server start")
       (list :server-id 'clangd :docker-server-id 'clangd-docker :server-command "ccls")
       (list :server-id 'css-ls :docker-server-id 'cssls-docker :server-command "css-languageserver --stdio")
       (list :server-id 'dockerfile-ls :docker-server-id 'dockerfilels-docker :server-command "docker-langserver --stdio")
       (list :server-id 'gopls :docker-server-id 'gopls-docker :server-command "gopls")
       (list :server-id 'html-ls :docker-server-id 'htmls-docker :server-command "html-languageserver --stdio")
       (list :server-id 'pyls :docker-server-id 'pyls-docker :server-command "pyls")
       (list :server-id 'ts-ls :docker-server-id 'tsls-docker :server-command "typescript-language-server --stdio")))
    (lsp-docker-init-clients
     :path-mappings '(("/home/ma2/repos" . "/projects"))
     :client-packages lsp-docker-client-packages
     :client-configs lsp-docker-client-configs))

  (leaf lsp-mode
    :ensure t
    :commands lsp-deferred lsp-enable-which-key-integration lsp
    :hook ((go-mode-hook . lsp-deferred)
           (lsp-mode-hook . lsp-enable-which-key-integration))
    :custom ((lsp-inhibit-message . t)
             (lsp-completion-provider . :none)
             (lsp-idle-delay . 0.5))
    :config

    (leaf lsp-ui
      :ensure t
      :after lsp
      :custom ((lsp-ui-doc-position quote bottom)
               (lsp-ui-doc-use-childframe)
               (lsp-ui-doc-delay . 1.5)))
    (leaf lsp-ivy
      :ensure t
      :commands lsp-ivy-workspace-symbol)

    (leaf dap-mode
      :ensure t
      :after lsp)))

(leaf c-mode

  :config
  (leaf google-c-style
    :ensure t
    :commands google-set-c-style)

  (leaf clang-format
    :ensure t
    :commands clang-format clang-format-buffer)

  (leaf ccls
    :ensure t
    :custom ((indent-tabs-mode . t)
             (tab-width . 2)
             (c-basic-offset . 2))
    :hook ((c-mode-hook c++-mode-hook)
           .
           (lambda ()
             (lsp)))))

(leaf java
  :defun (string-ends-with)
  :preface
  (defun my-java-ascii-to-native ()
    (interactive)
    (let ((p (point)))
      (when (and buffer-file-name
                 (string-ends-with buffer-file-name ".properties" ))
        (erase-buffer)
        (insert (shell-command-to-string (format "native2ascii -encoding UTF-8 -reverse '%s'" buffer-file-name)))
        (goto-char p))))

  (defun my-java-native-to-ascii ()
    (interactive)
    (let ((p (point)))
      (when (and buffer-file-name
                 (string-ends-with buffer-file-name ".properties" ))
        (erase-buffer)
        (insert (shell-command-to-string (format "native2ascii -encoding UTF-8 '%s'" buffer-file-name)))
        (goto-char p))))
  (defalias 'n2a 'my-java-native-to-ascii)
  (defalias 'a2n 'my-java-ascii-to-native)

  :config
  (leaf autodisass-java-bytecode
    :ensure t)

  (leaf google-c-style
    :ensure t
    :commands google-set-c-style)

  (leaf lsp-java
    :ensure t
    :hook (java-mode-hook . (lambda () (lsp))))

  (leaf groovy-mode
    :ensure t
    :mode ("\\.gradle\\'")
    :custom ((groovy-indent-offset . 2))))

;;   (leaf meghanada
;;     :load-path "~/repos/github.com/mopemope/meghanada-emacs"
;;     :commands meghanada-mode
;;     :hook (java-mode-hook
;;            .
;;            (lambda ()
;;              (google-set-c-style)
;;              (google-make-newline-indent)
;;              (flycheck-mode t)
;;              (meghanada-mode t)
;;              (add-hook 'before-save-hook
;;                        (lambda ()
;;                          (meghanada-code-beautify-before-save)))))
;;     :custom ((indent-tabs-mode . nil)
;;              (tab-width . 2)
;;              (c-basic-offset . 2)
;;              (meghanada-server-remote-debug . t)
;;              (meghanada-telemetry-enable . t)
;;              (meghanada-javac-xlint . "-Xlint:all,-processing")
;;              (meghanada-server-jvm-option . "-Xms256m -Xmx2048m -Dmeghanada.zpage.port=8080")
;;              (meghanada-import-static-enable . "java.util.Objects,org.junit.Assert")
;;              (meghanada-cache-in-project . nil))
;;     :config
;;     (defun _exit ()
;;       (interactive)
;;       (if (display-graphic-p)
;;           (delete-frame)
;;         (exit)))

;;     (defhydra hydra-meghanada (:hint nil :exit t)
;;       "
;; ^Java menu^
;; ^^^^^^--------------------------------------------------------------------
;; _C_: compile-file         _m_: restart-server         _a_: counsel-rg
;; _c_: compile-project      _t_: run-task               _f_: counsel-fzf
;; _o_: optimize-import      _j_: run-junit-test-case
;; _S_: switch-test-case     _J_: run-junit-class
;; _v_: local-variable       _R_: run-junit-recent
;; _i_: import-at-point      _r_: reference
;; _I_: import-all           _T_: typeinfo
;; _p_: show-project         _e_: exec-main

;; _q_: exit
;; "
;;       ("C" meghanada-compile-file)
;;       ("c" meghanada-compile-project)
;;       ("m" meghanada-restart)
;;       ("o" meghanada-optimize-import)
;;       ("S" meghanada-switch-test-case)
;;       ("v" meghanada-local-variable)
;;       ("i" meghanada-import-at-point)
;;       ("I" meghanada-import-all)
;;       ("p" meghanada-show-project)

;;       ("g" magit-status)
;;       ("a" counsel-rg)
;;       ("f" counsel-fzf)
;;       ("l" counsel-git)
;;       ("." counsel-imenu)
;;       ("+" text-scale-increase)
;;       ("-" text-scale-decrease)
;;       ("t" meghanada-run-task)
;;       ("T" meghanada-typeinfo)
;;       ("j" meghanada-run-junit-test-case)
;;       ("J" meghanada-run-junit-class)
;;       ("r" meghanada-reference)
;;       ("R" meghanada-run-junit-recent)
;;       ("e" meghanada-exec-main)
;;       ("s" split-window-horizontally)
;;       ("q" _exit)
;;       ("z" nil "leave"))
;;     )

(leaf go-mode
  :defun (go-format-region)
  :preface
  ;;;###autoload (autoload 'go-format-buffer "go-format" nil t)
  ;;;###autoload (autoload 'go-format-on-save-mode "go-format" nil t)
  (reformatter-define go-format
    :program "go"
    :args (list "fmt")
    :group 'go
    :lighter 'GoFmt)

  :mode ("\\.go$")
  :custom (gofmt-command . "goimports")
  :hook (go-mode-hook
         .
         (lambda ()
           (add-hook 'before-save-hook 'gofmt-before-save)))
  :config
  (leaf go-add-tags
    :ensure t
    :custom ((go-add-tags-style . 'lower-camel-case)))
  (leaf go-fill-struct
        :ensure t)
  (leaf go-gen-test
        :ensure t)
  (leaf go-impl
        :ensure t)
  (leaf go-playground
        :ensure t)
  (leaf go-rename
        :ensure t)
  (leaf go-scratch
        :ensure t)
  (leaf go-stacktracer
        :ensure t)
  (leaf go-snippets
        :ensure t))

(leaf rust
  :config
  (leaf rustic
    :ensure t
    :defvar (flycheck-checkers)
    :defun (rust-format-region)
    :preface
    ;;;###autoload (autoload 'rust-format-buffer "rust-format" nil t)
    ;;;###autoload (autoload 'rust-format-on-save-mode "rust-format" nil t)
    (reformatter-define rust-format
      :program "cargo"
      :args (list "fmt" "-q")
      :group 'rust
      :lighter 'RustFmt)

    :custom ((rustic-format-on-save . t))
    :config
    (push 'rustic-clippy flycheck-checkers)))

(leaf javascript
  :defun (vue-format-region typescript-format-region)
  :preface
  ;;;###autoload (autoload 'vue-format-buffer "vue-format" nil t)
  ;;;###autoload (autoload 'vue-format-on-save-mode "vue-format" nil t)
  (reformatter-define vue-format
    :program "prettier"
    :args (list "--parser" "vue")
    :group 'vue
    :lighter 'VueFmt)

  ;;;###autoload (autoload 'typescript-format-buffer "typescript-format" nil t)
  ;;;###autoload (autoload 'typescript-format-on-save-mode "typescript-format" nil t)
  (reformatter-define typescript-format
    :program "prettier"
    :args (list "--parser" "typescript")
    :group 'typescript
    :lighter 'TSFmt)

  :config
  (leaf add-node-modules-path
    :ensure t
    :commands add-node-modules-path)

  (leaf js2-mode
    :mode ("\\.js$")
    :custom ((js2-basic-offset . 2))
    :hook (js2-mode-hook
           .
           (lambda ()
             (add-node-modules-path)
             (lsp)
             (yas-minor-mode)
             (add-hook 'before-save-hook 'delete-trailing-whitespace))))

  (leaf json-mode
    :ensure t
    :mode ("\\.json$")
    :hook (json-mode-hook . (lambda ()))
    :custom ((js-indent-level . 2)
             (json-reformat:indent-width . 2)
             (tab-width . 2)))

  (leaf tide
    :ensure t
    :commands tide-setup)

  (leaf typescript-mode
    :ensure t
    :mode ("\\.ts$" "\\.tsx$")
    :hook (typescript-mode-hook
           .
           (lambda ()
             (add-node-modules-path)
             (lsp)
             (flycheck-mode t)
             (eldoc-mode t)
             (add-hook 'before-save-hook 'delete-trailing-whitespace)
             (yas-minor-mode)))

    :custom ((js-indent-level . 2)
             (typescript-indent-level . 2)
             (indent-tabs-mode)
             (c-basic-offset . 2)))

  (leaf vue-mode
    :ensure t
    :mode ("\\.vue$")
    :hook (vue-mode-hook
           .
           (lambda ()
             (add-node-modules-path)
             (lsp)
             (yas-minor-mode)))
    :custom ((js-indent-level . 2)
             (indent-tabs-mode)
             (typescript-indent-level . 2)
             (c-basic-offset . 2))))

(leaf python-mode
  :ensure t
  :hook (python-mode-hook
         .
         (lambda ()
           (lsp)))
  :config
  (leaf conda
    :ensure t
    :custom ((conda-anaconda-home . "~/miniconda3"))))

(leaf dart-flutter
  :config
  (leaf lsp-dart
    :defun (flutter-format-region)
    :ensure t
    :preface
  ;;;###autoload (autoload 'flutter-format-buffer "flutter-format" nil t)
  ;;;###autoload (autoload 'flutter-format-on-save-mode "flutter-format" nil t)
    (reformatter-define flutter-format
      :program "flutter"
      :args (list "format", "lib/*")
      :group 'flutter
      :lighter 'FlutterFmt)

    :hook ((dart-mode-hook . lsp))
    :config
    (leaf hover
      :ensure t)))

(leaf *shell
  :config
  (leaf sh-mode
    :hook (sh-mode-hook . (lambda () (lsp))))
  (leaf fish-mode
    :ensure t))

(leaf emacs-lisp-mode
  :commands emacs-lisp-mode
  :hook (emacs-lisp-mode-hook
         .
         (lambda ()
           (add-hook 'before-save-hook 'delete-trailing-whitespace)))
  :bind (([remap backward-delete-char-untabify] . smart-hungry-delete-backward-char))
  :config
  (leaf flycheck-package
    :ensure t
    :defun (flycheck-package-setup)
    :config
    (flycheck-package-setup))
  (leaf flycheck-elsa
    :ensure t
    :defun (flycheck-elsa-setup)
    :config
    (flycheck-elsa-setup)))

(leaf yaml-mode
  :ensure t
  :defun (yaml-format-region)
  :preface
  ;;;###autoload (autoload 'yaml-format-buffer "yaml-format" nil t)
  ;;;###autoload (autoload 'yaml-format-on-save-mode "yaml-format" nil t)
  (reformatter-define yaml-format
    :program "prettier"
    :group 'yaml
    :lighter 'YAMLFmt)
  :hook (yaml-mode-hook
         .
         (lambda ()
           (lsp)))
  :config
  (leaf flycheck-yamllint
    :ensure t))

(leaf sql
  :ensure t
  :mode ("\\.sql$")
  :custom ((sql-indent-offset . 2)
           (indent-tabs-mode)
           (tab-width . 2)
           (c-basic-offset . 2)
           (sql-mysql-options . '("--prompt=mysql> ")))
  :hook (sql-mode-hook
         .
         (lambda ()
           (add-hook 'before-save-hook 'delete-trailing-whitespace)))
  :config
  (leaf sql-indent
    :ensure t))

(leaf markdown-mode
  :ensure t
  :mode ("\\.md$")
  :defun (markdown-format-region)
  :preface
  ;;;###autoload (autoload 'markdown-format-buffer "markdown-format" nil t)
  ;;;###autoload (autoload 'markdown-format-on-save-mode "markdown-format" nil t)
  (reformatter-define markdown-format
    :program "prettier"
    :args (list "--parser" "markdown")
    :group 'markdown
    :lighter 'MarkdownFmt)

  :config
  (leaf vmd-mode
    :ensure t
    :after markdown-mode)
  (leaf gh-md
    :ensure t
    :after markdown-mode)
  (leaf markdown-toc
    :ensure t
    :after markdown-mode))

(leaf terraform-mode
  :mode ("\\.tf$")
  :hook (terraform-mode-hook
         .
         (lambda ()
           (add-hook 'before-save-hook 'delete-trailing-whitespace)))
  :config
  (company-terraform-init))

(leaf leetcode
  :load-path "~/repos/github.com/ginqi7/leetcode-emacs"
  :commands leetcode-show
  :custom ((leetcode-path . "~/repos/github.com/mopemope/leetcode")
           (leetcode-language . "rust")))

(leaf hydra
  :require t
  :ensure t
  :defun (generate-tmp-buffer
          _exit eshell-new
          origami-recursively-toggle-node
          origami-toggle-all-nodes)
  :preface
  (defun generate-tmp-buffer ()
    (interactive)
    (switch-to-buffer (make-temp-name "temp-")))

  (defun _exit ()
    (interactive)
    (require 'server)
    (if (display-graphic-p)
        (delete-frame)
      (save-buffers-kill-terminal)))

  (defun eshell-new ()
    "Open a new instance of eshell."
    (interactive)
    (require 'eshell)
    (eshell 'N))

  :bind (("C-z" . hydra-main-menu/body)
         ("C-q" . hydra-main-menu/body))
  :config
  (defhydra hydra-main-menu (:hint nil :exit t)
    "
^Menu^
^^^^^^------------------------------------------------------------------------------------------------
_e_: eval-buffer              _a_: counsel-projectile-rg        _r_: anzu-query-replace
_d_: describe-key             _S_: counsel-projectile-switch    _R_: quickrun
_g_: magit-status             _v_: counsel-describe-variable    _G_: google-this
_p_: paradox-list-packages    _._: counsel-imenu                _I_: imenu-list-smart-toggle
_t_: generate-tmp-buffer
_x_: eval-expression
_b_: set bookmark
_B_: jump bookmark

_q_: exit
"
    ("e" eval-buffer)
    ("x" eval-expression)
    ("E" eshell-new)
    ("d" describe-key)
    ("g" magit-status)
    ("p" paradox-list-packages)
    ("I" imenu-list-smart-toggle)
    ("t" generate-tmp-buffer)
    ("D" posframe-delete-all)
    ("m" make-frame-command)
    ("s" split-window-horizontally)
    ("0" delete-window)
    ("b" bookmark-set)
    ("B" bookmark-jump)

    ("a" counsel-projectile-rg)
    ("f" counsel-projectile-find-file)
    ("S" counsel-projectile-switch-project)
    ("v" counsel-describe-variable)
    ("." counsel-imenu)
    ("F" counsel-flycheck)

    ("r" anzu-query-replace)
    ("R" quickrun)
    ("G" google-this)
    ("o" origami-recursively-toggle-node)
    ("c" origami-toggle-all-nodes)

    ("<up>" centaur-tabs-backward-group)
    ("<down>" centaur-tabs-forward-group)
    ("<right>" centaur-tabs-forward)
    ("<left>" centaur-tabs-backward)

    ("q" _exit)
    ("z" nil "leave")))

(leaf smerge-mode
  :defun (smerge-prev
          smerge-keep-base
          smerge-keep-current
          smerge-keep-all
          smerge-keep-lower
          smerge-keep-uppersmerge-keep-mine
          smerge-keep-other
          smerge-resolve
          smerge-refine
          smerge-next
          smerge-keep-upper
          smerge-keep-mine)
  :commands smerge-mode
  :bind ((smerge-mode-map
          ("C-z" . hydra-smerge/body)))
  :config
  (defhydra hydra-smerge (:hint nil)
    "
^Move^             ^Edit^
^^^^^^~~-----------------------------------
_n_: next          _b_: keep-base
_p_: prev          _c_: keep-current
                 ^^_a_: keep-all
                 ^^_l_: keep-lower
                 ^^_u_: keep-upper
                 ^^_m_: keep-mine
                 ^^_o_: keep-other
                 ^^_r_: resolve
                 ^^_R_: refine
                 ^^_g_: magit-status
                 ^^_S_: smerge-mode

"
    ("n" smerge-next)
    ("p" smerge-prev)

    ("b" smerge-keep-base)
    ("c" smerge-keep-current)
    ("a" smerge-keep-all)
    ("l" smerge-keep-lower)
    ("u" smerge-keep-upper)
    ("m" smerge-keep-mine)
    ("o" smerge-keep-other)
    ("r" smerge-resolve)
    ("R" smerge-refine)
    ("g" magit-status)
    ("S" smerge-mode)

    ("z" nil "leave")))

(provide 'init)