#+title: Emacs Configuration
#+author: JaeYoo-Im
#+email: (cpu3792@gmail.com)

* Basic Configuration
Emacs Configuration for emacs 29.50
** Early Init
#+begin_src emacs-lisp :tangle ~/.config/emacs/early-init.el
  ;;; early-init.el -*- lexical-binding: t; -*-
  ;; garbage collection
  (setq gc-cons-threshold (* 50 1024 1024)) ;; 50MB
  ;; prefers newest version of a file
  (customize-set-variable 'load-prefer-newer t)

  ;;; Native compilation settings
  (when (featurep 'native-compile)
    ;; Silence compiler warnings as they can be pretty disruptive
    (setq native-comp-async-report-warnings-errors nil)

    ;; Make native compilation happens asynchronously
    (setq native-comp-deferred-compilation t))

  (setq inhibit-startup-message nil)
  (setq frame-resize-pixelwise t)
  (scroll-bar-mode -1)
  (tool-bar-mode -1)
  (tooltip-mode -1)
  (set-fringe-mode 10)
  (menu-bar-mode -1)
  ;;(blink-cursor-mode 0)

  ;; initial load with blue theme
  (load-theme 'deeper-blue)

  (customize-set-variable 'initial-major-mode 'fundamental-mode)

#+end_src
** Init
*** Startup hook
#+begin_src emacs-lisp :tangle ~/.config/emacs/init.el
  ;;; init.el -*- lexical-binding: t; -*-
  (add-hook 'emacs-startup-hook
            (lambda ()
              (message "Emacs loaded in %s"
                       (emacs-init-time))))
#+end_src
*** Package Function
**** Use-package
#+begin_src emacs-lisp :tangle ~/.config/emacs/init.el
  (require 'package)
  (when (version< emacs-version "28")
    (add-to-list 'package-archives '("nongnu" . "https://elpa.nongnu.org/nongnu/")))
  (add-to-list 'package-archives '("stable" . "https://stable.melpa.org/packages/"))
  (add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/"))

  (customize-set-variable 'package-archive-priorities
            '(("gnu"    . 99)   ; prefer GNU packages
              ("nongnu" . 80)   ; use non-gnu packages if
                        ; not found in GNU elpa
              ("stable" . 70)   ; prefer "released" versions
                        ; from melpa
              ("melpa"  . 0)))  ; if all else fails, get it
                        ; from melpa
  (customize-set-variable 'package-user-dir
            (expand-file-name "elpa/" user-emacs-directory))

  (unless (package-installed-p 'use-package)
    (package-install 'use-package))

  (require 'use-package)
  (setq use-package-always-ensure t)
#+end_src
*** Add other modules
#+begin_src emacs-lisp :tangle ~/.config/emacs/init.el
  (add-to-list 'load-path (expand-file-name "modules/" user-emacs-directory))
  (setq custom-theme-directory (expand-file-name "custom-themes/" user-emacs-directory))
#+end_src
*** Edit options
**** Whitespace clean
#+begin_src emacs-lisp :tangle ~/.config/emacs/init.el
  (add-hook 'before-save-hook #'whitespace-cleanup)
#+end_src
**** Tabs
#+begin_src emacs-lisp :tangle ~/.config/emacs/init.el
  (setq-default indent-tabs-mode nil)
  (setq-default tab-width 4)
#+end_src

협업에 있어서 코드에 tabs 크기를 명시하는 것도 방법일듯.
***** Modeline Indentation example
- Emacs
  #+begin_src rust
  /* -*- Mode: rust; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
  #+end_src
- Vim
  #+begin_src shell
  # Embeded VIM Configurations
  # vim: filetype=sh noet sw=4 ts=4 fdm=marker
  #+end_src
- Visual Studio Code
  install extension =modeline=.
  #+begin_src javascript
  // vim: set ft=js ts=4 sw=4 et:
  // vim :ts=4 :sw=4 :et :ft=js
  // -*- mode: js; indent-tabs-mode: nil; tab-width: 4 -*-
  // code: language=rust insertSpaces=false tabSize=4
  #+end_src

*** Backup options
#+begin_src emacs-lisp :tangle ~/.config/emacs/init.el
  (use-package no-littering
    :config
    (setq no-littering-etc-directory
          (expand-file-name "config/" user-emacs-directory))
    (setq no-littering-var-directory
          (expand-file-name "data/" user-emacs-directory)))
  (require 'recentf)
  (add-to-list 'recentf-exclude no-littering-var-directory)
  (add-to-list 'recentf-exclude no-littering-etc-directory)

  ;; interlocking file name
  (setq lock-file-name-transforms
        `((".*" ,(no-littering-expand-var-file-name "lock/") t)))

  ;; Auto save
  (setq auto-save-file-name-transforms
        `((".*" ,(no-littering-expand-var-file-name "auto-save/") t)))
  ;;(when (fboundp 'startup-redirect-eln-cache)
  ;;  (startup-redirect-eln-cache
  ;;   (convert-standard-filename
  ;;    (expand-file-name "var/eln-cache/" user-emacs-directory))))

  ;;(setq backup-directory-alist `(("." . ,(no-litter "auto-save/"))))
  (setq custom-file (no-littering-expand-etc-file-name "custom.el"))
  (when (file-exists-p custom-file)
    (load custom-file))
  (setq delete-by-moving-to-trash t
        trash-directory "~/.local/share/Trash/files/")
  (setq undo-limit 100000000
        auto-save-default t)
#+end_src


*** Other options
#+begin_src emacs-lisp :tangle ~/.config/emacs/init.el
  (set-default-coding-systems 'utf-8)
  (set-language-environment "utf-8")
  (prefer-coding-system 'utf-8)
  (customize-set-variable 'large-file-warning-threshold 100000000) ;; 100MB

  (defconst ON-LINUX (eq system-type 'gnu/linux))
  (defconst ON-MAC (eq system-type 'darwin))
  (defconst ON-WINDOWS (memq system-type '(cygwin windows-nt ms-dos)))

  (setq gc-cons-threshold (* 2 1024 1024)) ; decreasing the threshold to 2MB

  (defvar my-config-file (expand-file-name "config.el" user-emacs-directory))
  (load my-config-file nil 'nomessage)

  (setq use-short-answer t)

  (setq global-auto-revert-non-file-buffers t)
  (global-auto-revert-mode t)

  (set-frame-parameter (selected-frame) 'fullscreen 'maximized)
  (add-to-list 'default-frame-alist '(fullscreen . maximized))
  (unless (display-graphic-p)
    (xterm-mouse-mode))
#+end_src
* Define some unused variable.
#+begin_src emacs-lisp :tangle ~/.config/emacs/config.el
  (setq global-linum-mode nil)
#+end_src
* Modules Selection module
#+begin_src emacs-lisp :tangle ~/.config/emacs/config.el
  ;;; config.el -*- lexical-binding: t; -*-
  (setq user-full-name "JaeYoo-Im"
        user-mail-address "cpu3792@gmail.com")

  (setq default-input-method "korean-hangul")

  ;; when programming _
  (modify-syntax-entry ?_ "w")
  (setq visible-bell t)

  ;; split threshold
  (setq split-width-threshold 160
        split-height-threshold nil)
  (add-hook 'emacs-startup-hook
            (lambda ()
              (custom-set-faces
               `(default ((t (:font "Fira Code Nerd Font 13"))))
               `(fixed-pitch ((t (:inherit (default)))))
               `(fixed-pitch-serif ((t (:inherit (default)))))
               `(variable-pitch ((t (:font "Ubuntu 13")))))))

  (require 'custom-ui)
  (require 'custom-keybindings)
  (require 'custom-default)
  (require 'custom-completion)
  ;;(require 'custom-edit)
  ;;(require 'custom-projects)
  ;;(require 'custom-latex)
  ;;(require 'custom-org)
  ;;(require 'custom-languages)
  ;;(require 'custom-extra)

  ;;(require 'custom-workspaces)

  ;;; config.el ends here
#+end_src

** Module Lists
*** Default
emacs built-in package config
**** Ediff
#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/emacs/modules/custom-default.el
;; Don't let ediff break EXWM, keep it in one frame
(setq ediff-diff-options "-w"
      ediff-split-window-function 'split-window-horizontally
      ediff-window-setup-function 'ediff-setup-windows-plain)
#+end_src
**** Eshell
#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/emacs/modules/custom-default.el
  (when (eq system-type 'windows-nt)
    (setq explicit-shell-file-name "powershell.exe")
    (setq explicit-powershell.exe-args '()))
  (defun ju/get-prompt-path ()
    (let* ((current-path (eshell/pwd))
           (git-output (shell-command-to-string "git rev-parse --show-toplevel"))
           (has-path (not (string-match "^fatal" git-output))))
      (if (not has-path)
          (abbreviate-file-name current-path)
       (string-remove-prefix (file-name-directory git-output) current-path))))

  (defun ju/eshell-prompt ()
    (let ((current-branch (magit-get-current-branch)))
      (concat
       "\n"
       (propertize (system-name) 'face `(:foreground "#62aeed"))
       (propertize " ॐ " 'face `(:foreground "white"))
       (propertize (ju/get-prompt-path) 'face `(:foreground "#82cfd3"))
       (when current-branch
         (concat
          (propertize " • " 'face `(:foreground "white"))
          (propertize (concat " " current-branch) 'face `(:foreground "#c475f0"))))
       (propertize " • " 'face `(:foreground "white"))
       (propertize (format-time-string "%I:%M:%S %p") 'face `(:foreground "#5a5b7f"))
       (if (= (user-uid) 0)
           (propertize "\n#" 'face `(:foreground "red2"))
         (propertize "\nλ" 'face `(:foreground "#aece4a")))
       (propertize " " 'face `(:foreground "white")))))

  (defun ju/configure-eshell ()
    ;; Save command history when commands are entered
    (add-hook 'eshell-pre-command-hook 'eshell-save-some-history)

    ;; Truncate buffer for performance
    (add-to-list 'eshell-output-filter-functions 'eshell-truncate-buffer)

    ;; Bind some useful keys for evil-mode
    (evil-define-key '(normal insert visual) eshell-mode-map (kbd "C-r") 'counsel-esh-history)
    (evil-define-key '(normal insert visual) eshell-mode-map (kbd "<home>") 'eshell-bol)
    (evil-normalize-keymaps)

    (setq eshell-prompt-function      'ju/eshell-prompt
          eshell-prompt-regexp        "^λ "
          eshell-history-size         10000
          eshell-buffer-maximum-lines 10000
          eshell-hist-ignoredups t
          eshell-scroll-to-bottom-on-input t))
  (add-hook 'eshell-first-time-mode-hook #'ju/configure-eshell)
  (setq eshell-prompt-function
        (lambda ()
          (concat (abbreviate-file-name (eshell/pwd))
                  (if (= (user-uid) 0) " # " " λ ")))
        eshell-prompt-regexp "^[^#λ\n]* [#λ] ")
#+end_src
**** Dired
#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/emacs/modules/custom-default.el
  (use-package dired
    :ensure nil
    :straight (:type built-in)
    :commands (dired dired-jump)
    :bind (("C-x C-j" . dired-jump))
    :custom ((dired-listing-switches "-agho --group-directories-first"))
    :config
    (evil-collection-define-key 'normal 'dired-mode-map
      "h" 'dired-single-up-directory
      "l" 'dired-single-buffer
      "e" 'my/dired-openwith-external-program))
  (defun my/dired-openwith-external-program ()
    (interactive)
    (let (current-file current-ex)
      (setq current-file
            (dired-get-filename nil t))
      (setq current-ex
            (file-name-extension current-file))
      (cond ((string-equal current-ex "pdf")
             (async-shell-command
              (format "zathura \"%s\"" current-file)))
            ((string-equal current-ex "html")
             (async-shell-command
              (format "qutebrowser \"%s\"" current-file)))
            (t (message "file exception.")))))
  (use-package dired-single
    :defer t
    :commands (dired dired-jump))
  (use-package diredfl  ;; colorful dired
    :defer t
    :hook dired-mode)
  (use-package dired-git-info
    :defer t
    :config
    (evil-collection-define-key 'normal 'dired-mode-map
      ")" 'dired-git-info-mode))
  (use-package diff-hl
    :defer t
    :hook ((dired-mode . diff-hl-dired-mode-unless-remote)
           (magit-post-refresh . diff-hl-magit-post-refresh))
    :config
    (diff-hl-margin-mode))
  (use-package dired-rsync
    :defer t
    :bind (:map dired-mode-map
                ("C-c C-r" . dired-rsync)))
  (use-package all-the-icons-dired
    :defer t
    :hook dired-mode)
  (use-package dired-hide-dotfiles
    :defer t
    :hook (dired-mode)
    :config
    (evil-collection-define-key 'normal 'dired-mode-map
      "H" 'dired-hide-dotfiles-mode))

  ;; HACK:Fixes #1929: icons break file renaming in Emacs 27+, because the icon
  ;;      is considered part of the filename, so we disable icons while we're in
  ;;      wdired-mode.
  ;;(when EMACS27+
  (defvar +wdired-icons-enabled -1)

  ;; TODO: check emacs29 updates
  ;;(csetq dired-mouse-drag-files                   t
  ;;       mouse-drag-and-drop-region-cross-program t)

  (use-package peep-dired
    :defer t
    :hook (peep-dired . evil-normalize-keymaps)
    :config
    (evil-define-key 'normal peep-dired-mode-map
      (kbd "j") 'peep-dired-next-file
      (kbd "k") 'peep-dired-prev-file))
#+end_src
**** Provide Modules
#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/emacs/modules/custom-default.el
  (provide 'custom-default)
  ;;; custom-default.el ends here
#+end_src
*** UI
**** Line number
#+begin_src emacs-lisp :tangle ~/.config/emacs/init.el
  (column-number-mode)
  (global-display-line-numbers-mode t)
  ;; Disable line numbers for some modes
  (dolist (mode '(org-mode-hook
                  nov-mode-hook
                  dashboard-mode-hook
                  dired-mode-hook
                  eshell-mode-hook))
    (add-hook mode (lambda () (display-line-numbers-mode 0))))
#+end_src

**** Doom themes
#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/emacs/modules/custom-ui.el
  (use-package doom-themes
    :defer t
    :init
    (disable-theme 'deeper-blue)
    (if (display-graphic-p)
        ;;(load-theme 'doom-palenight t)
        (load-theme 'doom-one t)
      (load-theme 'doom-gruvbox t)))
#+end_src
**** Rainbow Delimiters
#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/emacs/modules/custom-ui.el
  (use-package rainbow-delimiters
    :defer t
    :hook (prog-mode . rainbow-delimiters-mode))
#+end_src
**** Setting Transparency
***** emacs 28
#+begin_src emacs-lisp :mkdirp yes
;;:tangle ~/.config/emacs/modules/custom-ui.el
   (set-frame-parameter (selected-frame) 'alpha '(85 . 50))
   (add-to-list 'default-frame-alist '(alpha . '(85 . 50)))
   (defun toggle-transparency ()
     (interactive)
     (let ((alpha (frame-parameter nil 'alpha)))
       (set-frame-parameter
        nil 'alpha
        (if (eql (cond ((numberp alpha) alpha)
                       ((numberp (cdr alpha)) (cdr alpha))
                       ;; Also handle undocumented (<active> <inactive>) form.
                       ((numberp (cadr alpha)) (cadr alpha)))
                 100)
            '(85 . 50) '(100 . 100)))))
   (defun my/transparency-round (val)
     "Round VAL to the nearest tenth of an integer."
     (/ (round (* 10 val)) 10.0))

   (defun my/increase-frame-alpha-background ()
     "Increase current frame’s alpha background."
     (interactive)
     (set-frame-parameter nil
                          'alpha-background
                          (my/transparency-round
                           (min 1.0
                                (+ (frame-parameter nil 'alpha-background) 0.1))))
     (message "%s" (frame-parameter nil 'alpha-background)))

   (defun my/decrease-frame-alpha-background ()
     "Decrease current frame’s alpha background."
     (interactive)
     (set-frame-parameter nil
                          'alpha-background
                          (my/transparency-round
                           (max 0.0
                                (- (frame-parameter nil 'alpha-background) 0.1))))
     (message "%s" (frame-parameter nil 'alpha-background)))
   (global-set-key (kbd "C-c t") 'toggle-transparency)
#+end_src
***** emacs 29
#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/emacs/modules/custom-ui.el
  (set-frame-parameter nil 'alpha-background 0.9)
  (add-to-list 'default-frame-alist '(alpha-background . 0.9))
  (defun toggle-transparency ()
    "toggle transparency."
    (interactive)
    (let ((alpha-transparency 1.0))
      (if (eq (frame-parameter nil 'alpha-background) alpha-transparency)
          (set-frame-parameter nil 'alpha-background 0.9)
        (set-frame-parameter nil 'alpha-background alpha-transparency))))
  (defun my/transparency-round (val)
    "Round VAL to the nearest tenth of an integer."
    (/ (round (* 10 val)) 10.0))

  (defun my/increase-frame-alpha-background ()
    "Increase current frame’s alpha background."
    (interactive)
    (set-frame-parameter nil
                         'alpha-background
                         (my/transparency-round
                          (min 1.0
                               (+ (frame-parameter nil 'alpha-background) 0.1))))
    (message "%s" (frame-parameter nil 'alpha-background)))

  (defun my/decrease-frame-alpha-background ()
    "Decrease current frame’s alpha background."
    (interactive)
    (set-frame-parameter nil
                         'alpha-background
                         (my/transparency-round
                          (max 0.0
                               (- (frame-parameter nil 'alpha-background) 0.1))))
    (message "%s" (frame-parameter nil 'alpha-background)))
  (global-set-key (kbd "C-c t") 'toggle-transparency)
#+end_src
**** Modeline
#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/emacs/modules/custom-ui.el
  (use-package doom-modeline
    :defer t
    :init (doom-modeline-mode 1)
    :config
    (setq doom-modeline-height 15
          doom-modeline-env-version t
          doom-modeline-persp-name t
          doom-modeline-persp-icon t
          doom-modeline-display-default-persp-name t
          doom-modeline-indent-info t))
#+end_src
**** Writeroom mode
#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/emacs/modules/custom-ui.el
  (use-package writeroom-mode
    :defer t
    :init (global-writeroom-mode 1)
    :config
    (setq writeroom-width 100
          writeroom-fullscreen-effect nil
          writeroom-maximize-window nil
          writeroom-mode-line t
          writeroom-major-modes '(org-mode markdown-mode nov-mode)))
#+end_src
**** All The Icons
#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/emacs/modules/custom-ui.el
  (use-package all-the-icons)
#+end_src
**** Dashboard
#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/emacs/modules/custom-ui.el
  (use-package dashboard
    :after all-the-icons
    :config
    (setq dashboard-set-heading-icons t)
    (setq dashboard-set-file-icons t)
    ;;(setq dashboard-banner-logo-title "Emacs is more than a text editor!")
    ;; logo from github.com/egstatsml/emacs_fancy_logos
    ;;(setq dashboard-startup-banner "~/.config/emacs/logos/xemacs_color.png")
    ;;(setq dashboard-startup-banner 'logo)
    (setq dashboard-center-content t)
    (setq dashboard-week-agenda t)
    (setq dashboard-set-footer t)
    (setq dashboard-page-separator "\n\n")
    ;;(setq dashboard-page-separator "\n\f\n")
    (setq dashboard-agenda-time-string-format "%d/%m/%Y %A %H:%M")
    (setq dashboard-projects-backend 'project-el)
    (setq dashboard-items '((recents . 10)
                            (agenda . 5)
                            (bookmarks . 5)
                            ;;(if (version< emacs-version "29")
                            ;;(projects . 5)
                            (registers . 5)))
    (setq dashboard-set-navigator t)

    (setq dashboard-navigator-buttons
          `(;; line1
            ((,(all-the-icons-octicon "mark-github" :height 1.1 :v-adjust 0.0)
              "Github"
              "Browse my Github"
              (lambda (&rest _) (browse-url "https://github.com/JaeUs3792/")))
             (,(all-the-icons-octicon "home" :height 1.1 :v-adjust 0.0)
              "Homepage"
              "Browse my Homepage"
              (lambda (&rest _) (browse-url "https://jaeus.net")))
             (,(all-the-icons-octicon "zap" :height 1.1 :v-adjust 0.0)
              "Refresh"
              "Refresh Packages"
              (lambda (&rest _) (package-refresh-contents)) warning))))

    (dashboard-setup-startup-hook)
    (dashboard-modify-heading-icons '((recents . "file-text")
                                      (bookmarks . "book")))
    (setq initial-buffer-choice (lambda () (get-buffer-create "*dashboard*"))))
#+end_src
**** Beacon
#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/emacs/modules/custom-ui.el
  (use-package beacon
    :defer t
    :config (beacon-mode 1))
#+end_src
**** Others
#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/emacs/modules/custom-ui.el
  (defun my/self-screenshot (&optional type)
    "Save a screenshot of type TYPE of the current Emacs frame.
        As shown by the function `', type can weild the value `svg',
        `png', `pdf'.

        This function will output in /tmp a file beginning with \"Emacs\"
        and ending with the extension of the requested TYPE."
    (interactive)
    (let* ((type (if type type
                   (intern (completing-read "Screenshot Type: "
                                            '(png svg pdf postscript)))))
           (extension (pcase type
                        ('png        ".png")
                        ('svg        ".svg")
                        ('pdf        ".pdf")
                        ('postscript ".ps")
                        (otherwise (error "Cannot export screenshot of type %s" otherwise))))
           (filename (make-temp-file "Emacs-" nil extension))
           (data     (x-export-frames nil type)))
      (with-temp-file filename
        (insert data))
      (kill-new filename)
      (rename-file filename (expand-file-name (file-name-nondirectory filename) "~"))
      (message filename)))
#+end_src

**** Provide Modules
#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/emacs/modules/custom-ui.el
(provide 'custom-ui)
;;; custom-ui.el ends here
#+end_src

*** Key Bindings
**** Global Key
#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/emacs/modules/custom-keybindings.el
  ;; Make ESC quit prompts
  (global-set-key (kbd "<escape>") 'keyboard-escape-quit)
  ;; this annoying binding.
  (global-unset-key (kbd "C-j"))
  (global-unset-key (kbd "C-k"))
  (global-unset-key (kbd "S-SPC"))    ;; use only S-\
#+end_src
**** Which keys
When you begin a keybind, whichkey will show you all keybinds you can follow the first one with in order to form a full keywords.
#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/emacs/modules/custom-keybindings.el
  (use-package which-key
    :defer t
    :init (which-key-mode)
    :diminish which-key-mode
    :config
    (setq which-key-idle-delay 0.5))
#+end_src
**** General
for managing keybindings.
#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/emacs/modules/custom-keybindings.el
  (use-package general
    :init
    (general-auto-unbind-keys)
    :config
    (general-evil-setup t)
    (general-create-definer ju/leader-key-def
      :keymaps '(normal insert visual emacs)
      :prefix "SPC"
      :global-prefix "C-SPC"))

  (ju/leader-key-def
    "." 'find-file
    ;; Buffer
    "b" '(:ignore t :which-key "buffer handling")
    "b i" '(ibuffer :which-key "IBuffer")
    "b r" '(revert-buffer :which-key "Revert Buffer")
    "b k" '(kill-current-buffer :which-key "Kill current buffer")
    "b n" '(next-buffer :which-key "Next buffer")
    "b p" '(previous-buffer :which-key "Previous buffer")
    "b B" '(ibuffer-list-buffers :which-key "IBuffer List Buffers")
    "b K" '(kill-buffer :which-key "IBuffer Kill Buffers")
    ;; Eshell
    "e" '(:ignore t :which-key "eshell")
    "e h" '(counsel-esh-history :which-key "Kill history")
    "e s" '(eshell :which-key "run eshell")
    "e e" '(elfeed :which-key "elfeed")
    ;; Counsel
    "f" '(:ignore t :which-key "file op.")
    "f r" '(consult-recent-file :which-key "Recent files")
    ;; Shortcut
    "f o" '(:ignore t :which-key "dOt files")
    "f o d" '((lambda () (interactive) (find-file "~/.config/emacs/desktop.org")) :which-key "open exwm config")
    "f o c" '((lambda () (interactive) (find-file "~/.config/emacs/emacs.org")) :which-key "open emacs config")
    ;; Insert something
    "i" '(:ignore t :which-key "insert something.")
    ;; Project-el
    "p" '(:ignore t :which-key "project")
    "p ." '(project-switch-project :which-key "switch project")
    "p p" '(project-switch-project :which-key "switch project")
    "p c" '(project-compile :which-key "compile")
    "p f" '(project-find-file :which-key "find-file")
    "p k" '(project-kill-buffers :which-key "kill buffers")
    "p s" '(project-shell :which-key "shell")
    "p e" '(project-eshell :which-key "eshell")
    "p d" '(project-dired :which-key "dired")
    ;;"p g" '(project-find-regexp :which-key "find-regexp")
    "p g" '(consult-ripgrep :which-key "ripgrep")
    ;; register
    "r" '(:ignore t :which-key "register")
    "r y" '(consult-register-save :which-key "yank to register")
    "r p" '(consult-register-load :which-key "paste to buffer")
    ;; Extra
    "t" '(:ignore t :which-key "extra")
    "t a" '(toggle-transparency :which-key "Toggle Transparency")
    "t t" '(toggle-truncate-lines :which-key "Toggle truncate lines"))
#+end_src
**** Evil Mode
#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/emacs/modules/custom-keybindings.el
  (use-package evil
    :after general
    :init
    (setq evil-want-integration t
          evil-want-keybinding nil
          evil-want-C-u-scroll t
          evil-want-C-i-jump nil)
    ;;(setq evil-respect-visual-line-mode nil) ; t : on the screen, nil : by cr characters
    (require 'evil-vars)
    (evil-set-undo-system 'undo-tree)
    ;;(evil-set-undo-system 'undo-redo)

    ;; Make evil search more like vim (makes emacs slow)
    ;;(evil-select-search-module 'evil-search-module 'evil-search)

    :config
    (evil-mode 1)
    (setq evil-want-fine-undo t) ; more granular undo with evil
    (evil-set-initial-state 'messages-buffer-mode 'normal)
    (evil-set-initial-state 'dashboard-mode 'normal)
    ;; eshell no evil
    (dolist (mode '(eshell-mode))
      (add-to-list 'evil-emacs-state-modes mode)))

  (use-package evil-collection
    :after evil
    :config
    (evil-collection-init))

  (use-package evil-nerd-commenter
    :after evil
    :config
    ;; evil nerd commenter
    (define-key evil-normal-state-map (kbd "g c") 'evilnc-comment-or-uncomment-lines)
    (define-key evil-visual-state-map (kbd "g c") 'evilnc-comment-or-uncomment-lines))

  (use-package evil-numbers
    :after evil
    :config
    ;; evil numbers
    ;; unfortunately C-x is emacs common key binding.
    (define-key evil-normal-state-map (kbd "g =") 'evil-numbers/inc-at-pt)
    (define-key evil-normal-state-map (kbd "g -") 'evil-numbers/dec-at-pt)
    (define-key evil-visual-state-map (kbd "g =") 'evil-numbers/inc-at-pt)
    (define-key evil-visual-state-map (kbd "g -") 'evil-numbers/dec-at-pt))


#+end_src
**** Undo Tree
#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/emacs/modules/custom-keybindings.el
  (use-package undo-tree
    :defer t
    :custom
    (undo-tree-history-directory-alist
     `(("." . ,(expand-file-name (file-name-as-directory "undo-tree-hist")
                                 user-emacs-directory))))
    :init
    (global-undo-tree-mode)
    :config
    (setq undo-tree-visualizer-diff       t
          undo-tree-visualizer-timestamps t
          undo-tree-auto-save-history     t
          undo-tree-enable-undo-in-region t
          undo-limit        (* 800 1024)
          undo-strong-limit (* 12 1024 1024)
          undo-outer-limit  (* 128 1024 1024)))
#+end_src
**** Hydra
#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/emacs/modules/custom-keybindings.el
  (use-package hydra
    :defer t)
  (defhydra hydra-text-scale (:timeout 4)
    "scale text"
    ("t" text-scale-increase "in")
    ("s" text-scale-decrease "out")
    ("q" nil "finished" :exit t))
  (defhydra hydra-writeroom-scale (:timeout 4)
    "scale whiteroom"
    ("t" writeroom-increase-width "enlarge")
    ("S" writeroom-decrease-width "shrink")
    ("r" writeroom-adjust-width "adjust")
    ("q" nil "finished" :exit t))
  (defhydra hydra-modify-alpha ()
    ("s" my/decrease-frame-alpha-background "decrease alpha")
    ("t" my/increase-frame-alpha-background "increase alpha")
    ("q" nil "finished" :exit t))
  (ju/leader-key-def
    ;; Hydra
    "h" '(:ignore t :which-key "hydra")
    "h t" '(hydra-text-scale/body :which-key "scale text")
    "h w" '(hydra-writeroom-scale/body :which-key "scale whiteroom")
    "h a" '(hydra-modify-alpha/body :which-key "modify alpha background"))
#+end_src

**** Provide Modules
#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/emacs/modules/custom-keybindings.el
(provide 'custom-keybindings)
;;; custom-keybindings.el ends here
#+end_src

*** Completion
config from crafted-emacs
https://github.com/SystemCrafters/crafted-emacs
**** Vertico
#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/emacs/modules/custom-completion.el
  (use-package vertico
    :bind (:map vertico-map
                ("C-j" . vertico-next)
                ("C-k" . vertico-previous))
    :custom
    (vertico-cycle t)
    :init
    (vertico-mode))
#+end_src
**** Prescient
simple but effective sorting and filtering for emacs.
#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/emacs/modules/custom-completion.el
  (use-package vertico-prescient
    :defer t
    :config
    (vertico-prescient-mode))
#+end_src
**** Marginalia
annotations placed at the margin of the minibuffer
#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/emacs/modules/custom-completion.el
  (use-package marginalia
    :after vertico
    :defer t
    :custom
    (marginalia-annotators '(marginalia-annotators-heavy marginalia-annotators-light nil))
    :init (marginalia-mode))
#+end_src
**** Consult
#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/emacs/modules/custom-completion.el
  (use-package consult
    :demand t
    :bind (:map minibuffer-local-map
                ("C-r" . consult-history))
    :custom
    (completion-in-region-function #'consult-completion-in-region)
    :config
    (global-set-key (kbd "C-s") 'consult-line)
    (global-set-key (kbd "C-M-j") 'consult-buffer))
#+end_src
**** Orderless
orderless completion
#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/emacs/modules/custom-completion.el
  (use-package orderless
    :defer t
    :custom
    (completion-styles '(orderless basic))
    (completion-category-overrides '((file (style basic partial-completion)))))
#+end_src
**** Embark / Embark Consult
Quick Action in minibuffer
#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/emacs/modules/custom-completion.el
  (use-package embark
    :defer t
    :bind (("C-." . embark-act))
    :config
    (with-eval-after-load 'embark-consult
      (add-hook 'embark-collect-mode-hook #'consult-preview-at-point-mode))
    (global-set-key [remap describe-bindings] #'embark-bindings)
    ;; Use Embark to show bindings in a key prefix with `C-h`
    (setq prefix-help-command #'embark-prefix-help-command))

  (use-package embark-consult
    :defer t
    :after embark)
#+end_src

**** Corfu / Cape
#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/emacs/modules/custom-completion.el
   ;;; Corfu
  (use-package corfu
    :custom
    (corfu-cycle t)                ;; Enable cycling for `corfu-next/previous'
    (corfu-auto t)                 ;; Enable auto completion
    (corfu-auto-prefix 2)
    (corfu-auto-delay 0.0)
    (corfu-echo-documentation 0.25)
    ;; (corfu-separator ?\s)          ;; Orderless field separator
    ;; (corfu-quit-at-boundary nil)   ;; Never quit at completion boundary
    ;; (corfu-quit-no-match nil)      ;; Never quit, even if there is no match
    ;; (corfu-preview-current nil)    ;; Disable current candidate preview
    ;; (corfu-preselect 'prompt)      ;; Preselect the prompt
    ;; (corfu-on-exact-match nil)     ;; Configure handling of exact matches
    ;; (corfu-scroll-margin 5)        ;; Use scroll margin
    :init
    (global-corfu-mode))
  ;; load extension
  (add-to-list 'load-path
               (expand-file-name "straight/build/corfu/extensions"
                                 straight-base-dir))
  (require 'corfu-popupinfo)
  (corfu-popupinfo-mode 1)
  (eldoc-add-command #'corfu-insert)
  (define-key corfu-map (kbd "M-p") #'corfu-popupinfo-scroll-down)
  (define-key corfu-map (kbd "M-n") #'corfu-popupinfo-scroll-up)
  (define-key corfu-map (kbd "M-d") #'corfu-popupinfo-toggle)

   ;;; Cape
  ;; Setup Cape for better completion-at-point support and more
  (use-package cape
    :config
    ;; Add useful defaults completion sources from cape
    (add-to-list 'completion-at-point-functions #'cape-file)
    (add-to-list 'completion-at-point-functions #'cape-dabbrev)
    ;;(add-to-list 'completion-at-point-functions #'cape-ispell)
    ;; Silence the pcomplete capf, no errors or messages!
    ;; Important for corfu
    (advice-add 'pcomplete-completions-at-point :around #'cape-wrap-silent)
    ;; Ensure that pcomplete does not write to the buffer
    ;; and behaves as a pure `completion-at-point-function'.
    (advice-add 'pcomplete-completions-at-point :around #'cape-wrap-purify)
    (add-hook 'eshell-mode-hook
              (lambda () (setq-local corfu-quit-at-boundary t
                                     corfu-quit-no-match t
                                     corfu-auto nil)
                (corfu-mode))))
  (unless (package-installed-p 'corfu-terminal)
    (package-install 'corfu-terminal))
  (unless (display-graphic-p)
    (require 'corfu-terminal)
    (corfu-terminal-mode +1))
#+end_src
**** Provide Modules
#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/emacs/modules/custom-completion.el
(provide 'custom-completion)
;;; custom-completion.el ends here
#+end_src
*** Edit
**** Helpful
#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/emacs/modules/custom-edit.el
  (use-package helpful
    :defer t
    :custom
    (counsel-describe-function-function #'helpful-callable)
    (counsel-describe-variable-function #'helpful-variable))
  ;;:commands (helpful-callable helpful-variable helpful-command helpful-key)
  (global-set-key [remap describe-function] #'describe-function)
  (global-set-key [remap describe-command] #'helpful-command)
  (global-set-key [remap describe-variable] #'describe-variable)
  (global-set-key [remap describe-key] #'helpful-key)
#+end_src
**** Avy
#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/emacs/modules/custom-edit.el
  (use-package avy
    :defer t
    :config
    (setq avy-all-windows t))
  (ju/leader-key-def
    "v" '(:ignore t :which-key "Avy")
    "vc" '(avy-goto-char :which-key "Avy Goto Char")
    "vw" '(avy-goto-word-0 :which-key "Avy Goto Word")
    "vl" '(avy-goto-line :which-key "Avy Goto Line"))
#+end_src
**** Snippet
#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/emacs/modules/custom-edit.el
  (use-package yasnippet
    :defer t
    :hook (prog-mode . yas-minor-mode)
    :config
  (defvar yas-snippet-dirs nil)
  (add-to-list 'yas-snippet-dirs "~/.config/emacs/snippets")
  (yas-global-mode 1))
  (ju/leader-key-def
    "i s" '(yas-insert-snippet :which-key "snippet"))
#+end_src
***** Doom-Snippet
#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/emacs/modules/custom-edit.el
  (use-package doom-snippets
    :straight (doom-snippets :type git :host github :repo "doomemacs/snippets" :files ("*.el" "*"))
    :after yasnippet)
#+end_src

**** Emojify
#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/emacs/modules/custom-edit.el
  (use-package emojify
    :defer t
    :init (global-emojify-mode 1))
  (ju/leader-key-def
    "i e" '(emojify-insert-emoji :which-key "emoji"))
#+end_src
**** Provide Modules
#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/emacs/modules/custom-edit.el
(provide 'custom-edit)
;;; custom-completion.el ends here
#+end_src

*** Org Mode
**** Normal Function
***** configure org
#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/emacs/modules/custom-org.el
  (setq org-directory "~/org") ; use for relative file location
  (with-no-warnings
    (custom-declare-face '+org-todo-active  '((t (:inherit (bold font-lock-constant-face org-todo)))) "")
    (custom-declare-face '+org-todo-project '((t (:inherit (bold font-lock-doc-face org-todo)))) "")
    (custom-declare-face '+org-todo-onhold  '((t (:inherit (bold warning org-todo)))) "")
    (custom-declare-face '+org-todo-cancel  '((t (:inherit (bold error org-todo)))) ""))
  (use-package org
    :defer t
    :config
    (add-hook 'org-mode-hook #'org-indent-mode)
    (add-hook 'org-mode-hook #'org-fold-hide-drawer-all)
    (add-hook 'org-mode-hook #'visual-line-mode)
    (setq org-todo-keywords
          '((sequence
             "TODO(t)"  ; A task that needs doing & is ready to do
             "PROJ(p)"  ; A project, which usually contains other tasks
             "STRT(s)"  ; A task that is in progress
             "WAIT(w)"  ; Something external is holding up this task
             "HOLD(h)"  ; This task is paused/on hold because of me
             "IDEA(i)"  ; An unconfirmed and unapproved task or notion
             "|"
             "DONE(d)"  ; Task successfully completed
             "KILL(k)") ; Task was cancelled, aborted or is no longer applicable
            (sequence
             "[ ](T)"   ; A task that needs doing
             "[-](S)"   ; Task is in progress
             "[?](W)"   ; Task is being held up or paused
             "|"
             "[X](D)")  ; Task was completed
            ))
    (setq org-todo-keyword-faces
        '(("[-]"  . +org-todo-active)
          ("STRT" . +org-todo-active)
          ("[?]"  . +org-todo-onhold)
          ("WAIT" . +org-todo-onhold)
          ("HOLD" . +org-todo-onhold)
          ("PROJ" . +org-todo-project)
          ("KILL" . +org-todo-cancel)))
    (setq org-ellipsis                       " ⤵"
          org-hide-emphasis-markers          t
          org-redisplay-inline-images        t
          org-display-inline-images          t
          org-startup-with-inline-images     "inlineimages"
          org-src-fontify-natively           t
          org-fontify-quote-and-verse-blocks t
          org-agenda-start-with-log-mode     t
          org-startup-indented               t
          org-startup-align-all-tables       t
          org-log-done                       'time
          org-log-into-drawer                "LOGBOOK"
          org-clock-into-drawer              "CLOCKING"
          org-lowest-priority                68)
    ;;(setq org-format-latex-options (plist-put org-format-latex-options :scale 1.8))

    (setq org-use-sub-superscripts '{})
    ;; Do not ask when run code block
    (setq org-confirm-babel-evaluate nil)

    (setq org-image-actual-width nil)

    (custom-set-faces
     '(org-level-1 ((t (:height 1.7  :weight ultra-bold :foreground "#81a2be"))))         ;; :foreground "#81a2be"
     '(org-level-2 ((t (:height 1.6  :weight extra-bold :foreground "#b294bb"))))         ;; :foreground "#b294bb"
     '(org-level-3 ((t (:height 1.5  :weight bold :foreground "#b5bd68"))))               ;; :foreground "#b5bd68"
     '(org-level-4 ((t (:height 1.4  :weight semi-bold :foreground "#e6c547"))))          ;; :foreground "#e6c547"
     '(org-level-5 ((t (:height 1.3  :weight normal :foreground "#cc6666"))))             ;; :foreground "#cc6666"
     '(org-level-6 ((t (:height 1.2  :weight normal :foreground "#70c0ba"))))             ;; :foreground "#70c0ba"
     '(org-level-7 ((t (:height 1.1  :weight normal :foreground "#b77ee0"))))             ;; :foreground "#b77ee0"
     '(org-level-8 ((t (:height 1.0  :weight normal :foreground "#9ec400"))))
     '(org-document-title ((t (:height 2.0  :weight ultra-bold :foreground "#9ec400")))))
    ;; org latex preview scaled.
    (setq org-format-latex-options (plist-put org-format-latex-options :scale 2.5))
    ;; odt -> docx
    (setq org-odt-preferred-output-format "docx" ;; opt -> docx
          org-export-with-sub-superscripts '{}   ;; ODT export to docx
          org-latex-compiler "xelatex"))
  (use-package org-contrib
    :after org
    :defer t)
    #+end_src
***** Org fancy Priorities
#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/emacs/modules/custom-org.el
  (use-package org-fancy-priorities
    :defer t
    :after (org all-the-icons)
    :hook (org-mode org-agenda-mode)
    :config
  (setq org-fancy-priorities-list `(,(all-the-icons-faicon "flag"     :height 1.1 :v-adjust 0.0)
                                    ,(all-the-icons-faicon "arrow-up" :height 1.1 :v-adjust 0.0)
                                    ,(all-the-icons-faicon "square"   :height 1.1 :v-adjust 0.0)
                                    ,(all-the-icons-faicon "ban"      :height 1.1 :v-adjust 0.0))))
#+end_src
***** Org superstar
#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/emacs/modules/custom-org.el
  (use-package org-superstar
    :hook (org-mode)
    :config
    (setq org-superstar-item-bullet-alist
          '((?+ . ?➢)
            (?* . ?✰)
            (?- . ?➸))))
#+end_src
***** Valign
| 12345678 |   |
|----------+---|
|   일이삼사 |   |
#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/emacs/modules/custom-org.el
  (use-package valign
    :defer t
    :custom
    (valign-fancy-bar t))
#+end_src
***** Emphasize text
bold : *bold*
italic : /italic/
unerline : _unerline_
verbatim : =verbatim=
code : ~code~
strike-through : +strike-through+
***** Org Appear
#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/emacs/modules/custom-org.el
  (use-package org-appear
    :defer t
    :hook (org-mode)
    :config
    (setq org-appear-autoemphasis   t
          org-appear-autolinks      t
          org-appear-autoentities   t
          org-appear-autosubmarkers t))
#+end_src
***** Org fragtog
#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/emacs/modules/custom-org.el
  (use-package org-fragtog
    :defer t
    :hook (org-mode))
#+end_src
**** Attachment
***** Org attach screenshot (linux)
to use org-screenshot-take
#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/emacs/modules/custom-org.el
  (use-package org-attach-screenshot
    :defer t)
#+end_src
***** Org download
download image link
#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/emacs/modules/custom-org.el
  (use-package org-download
    :defer t)
#+end_src

***** ob-latex-as-png
#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/emacs/modules/custom-org.el
  (use-package ob-latex-as-png
    :defer t)
#+end_src

****** Example 1
#+begin_src latex-as-png :results replace :file neural-networks :exports both
\usepackage{neuralnetwork}
% in
\begin{neuralnetwork}[height=4]
  \newcommand{\x}[2]{$x_#2$}
  \newcommand{\y}[2]{$y_#2$}
  \newcommand{\hfirst}[2]{\small $h^{(1)}_#2$}
  \newcommand{\hsecond}[2]{\small $h^{(2)}_#2$}
  \newcommand{\mylinktext}[4] {
    % from layer=#1, from node=#2
    % to layer=#3, to node=#4
  \ifnum1=#1\relax
     \ifnum3=#4\relax $w^{#1}_{#4,#2}$ \fi
  \else \fi
  }
  % Then assign it:
  \setdefaultlinklabel{\mylinktext}
  \inputlayer[count=3, bias=false, title=Input\\layer, text=\x]
  \hiddenlayer[count=4, bias=false, title=Hidden\\layer 1, text=\hfirst] \linklayers
  \hiddenlayer[count=3, bias=false, title=Hidden\\layer 2, text=\hsecond] \linklayers
  \outputlayer[count=2, title=Output\\layer, text=\y] \linklayers
\end{neuralnetwork}
#+end_src

#+RESULTS:
[[file:neural-networks.png]]

****** Example 2
#+PROPERTY: header-args:latex-as-png :results raw value replace
#+begin_src latex-as-png :file example.pdf :resolution 120
   \smartdiagram[bubble diagram]{Emacs,Org-mode, \LaTeX, Pretty Images, HTML}
#+end_src

****** Example 3
#+begin_src latex-as-png :file using-picture-environment :exports both
\input GoudyIn.fd \input Acorn.fd
\def\light#1{\huge \usefont{U}{Acorn}{xl}{n} #1}
\def\thick#1{\fontsize{50}{60}\selectfont \usefont{U}{GoudyIn}{xl}{n} #1}
% \fontsize{X}{Y} ⇒ Write with point size X, using Y point size between lines

\pagecolor{brown}

\begin{picture}(124,60)
\put(0,0){\thick{ORG}}
\put(18,42){\light{JaeUs}}
\put(0,55){\rotatebox{-45}{\scriptsize \LaTeX}}
\put(109,43){\rotatebox{45}{\scriptsize \texttt{HTML}}}
\end{picture}
#+end_src

#+RESULTS:
[[file:using-picture-environment.png]]
***** def-functions
#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/emacs/modules/custom-org.el
  (defun my/org-remove-link-and-trash-linked-file ()
    "Remove `org-mode' link at point and trash linked file."
    (interactive)
    (let* ((link (org-element-context))
           (path (org-element-property :path link)))
      (move-file-to-trash path)
      (delete-region (org-element-property :begin link)
                     (org-element-property :end link))))
  (defun my/powershell (script)
    "executes the given script within a powershell and returns its return value"
    (call-process "powershell.exe" nil nil nil
                  "-Command" (concat "& {" script "}")))
  (defun my/as-windows-path (unix-path)
    "Takes a unix path and returns a matching WSL path"
    ;; substring removes the trailing \n
    (substring
     (shell-command-to-string
      (concat "wslpath -w " unix-path)) 0 -1))
  (defun my/org-paste-image-win2wsl ()
    "Paste an image into a time stamped unique-named file in the
          same directory as the org-buffer and insert a link to this file."
    (interactive)
    (let* ((target-file
            (concat
             (make-temp-name
              (concat org-directory
                      "/images/"
                      (f-filename buffer-file-name)
                      "_"
                      (format-time-string "%Y%m%d_%H%M%S_"))) ".png"))
           (wsl-path
            (concat (my/as-windows-path(file-name-directory target-file))
                    "/"
                    (file-name-nondirectory target-file)))
           (ps-script
            (concat "(Get-Clipboard -Format image).Save('" wsl-path "')")))

      (my/powershell ps-script)

      (if (file-exists-p target-file)
          (progn (insert (concat "[[" target-file "]]"))
                 (org-display-inline-images))
        (user-error
         "Error pasting the image, make sure you have an image in the clipboard!"))
      ))
  (defun org-time-stamp-with-time()
        "Insert org mode timestamp at point with current date and time"
        (interactive)
        (org-insert-time-stamp (current-time) t))
#+end_src
**** Exporter
***** Hugo
my-blog jaeus.net
#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/emacs/modules/custom-org.el
  (use-package ox-hugo
    :defer t
    :after ox)
#+end_src
***** TODO Engrave-faces
latex export code block
#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/emacs/modules/custom-org.el
  ;;(usr-package-install 'engrave-faces)
  ;;(require 'engrave-faces)
  ;;(require 'engrave-faces-latex)
  ;;(setq org-latex-src-block-backend 'engraved)
#+end_src
***** Code Block Minted
#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/emacs/modules/custom-org.el
  (setq org-latex-minted-options '(("breaklines" "true")
                                   ("tabsize" "4")
                                   ("autogobble")
                                   ("breakanywhere" "true")
                                   ("bgcolor" "gray!40")
                                   ("frame" "single")
                                   ("numbers" "left")))
  (setq org-latex-listings 'minted
        org-latex-packages-alist '(("" "minted"))
        org-latex-pdf-process
        '("pdflatex -shell-escape -interaction nonstopmode -output-directory %o %f"
          "pdflatex -interaction nonstopmode -output-directory %o %f"))
#+end_src
***** Org latex classes
=article= is default.
#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/emacs/modules/custom-org.el
  (with-eval-after-load 'ox-latex
    (add-to-list 'org-latex-classes
                 '("article"
                   "\\documentclass[11pt,a4paper]{article}
    \\usepackage[left=2.5cm,right=2.5cm,top=3cm,bottom=3cm,a4paper]{geometry}
    [DEFAULT-PACKAGES]
    \\usepackage{kotex}
    [PACKAGES]
    [EXTRA]
    \\linespread{1.1}
    \\hypersetup{pdfborder=0 0 0}"
                   ("\\section{%s}" . "\\section*{%s}")
                   ("\\subsection{%s}" . "\\subsection*{%s}")
                   ("\\subsubsection{%s}" . "\\subsubsection*{%s}")
                   ("\\paragraph{%s}" . "\\paragraph*{%s}")))
    (add-to-list 'org-latex-classes
                 '("org-plain-latex"
                   "\\documentclass[a4paper,11pt,titlepage]{memoir}
  \\usepackage[left=2.5cm,right=2.5cm,top=3cm,bottom=3cm,a4paper]{geometry}
  [DEFAULT-PACKAGES]
  \\usepackage{kotex}
  [PACKAGES]
  [EXTRA]
  \\linespread{1.1}
  \\hypersetup{pdfborder=0 0 0}"
                   ("\\chapter{%s}" . "\\chapter*{%s}")
                   ("\\section{%s}" . "\\section*{%s}")
                   ("\\subsection{%s}" . "\\subsection*{%s}")
                   ("\\subsubsection{%s}" . "\\subsubsection*{%s}")
                   ("\\paragraph{%s}" . "\\paragraph*{%s}")
                   ("\\subparagraph{%s}" . "\\subparagraph*{%s}"))))

#+end_src

**** Additional Functions
***** Org Journal
#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/emacs/modules/custom-org.el
  (use-package org-journal
    :defer t
    :config
    (setq org-journal-dir (expand-file-name "journal/" org-directory))
    (setq org-journal-file-type 'weekly))
#+end_src

***** Org Agenda
#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/emacs/modules/custom-org.el
  (defvar my/org-agenda-default-file "~/org/agenda/agenda.org")
  (setq org-agenda-files (list my/org-agenda-default-file))
#+end_src
***** Org Roam
#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/emacs/modules/custom-org.el
  (use-package org-roam
    :ensure t
    ;;:demand t ;; ensure org-roam is loaded by default
    :custom
    (org-roam-directory "~/org/roam")
    (org-roam-node-display-template (concat "${title:*} " (propertize "${tags:*}" 'face 'org-tag)))
    ;;(org-roam-completion-everywhere t)
    :config
    (setq org-roam-capture-templates '(("d" "default" plain "%?"
                                        :target (file+head
                                                 "%<%Y%m%d%H%M%S>-${slug}.org"
                                                 "#+title: ${title}\n")
                                        :unnarrowed t)
                                       ("p" "project" plain "* TODO %?"
                                        :target (file+head+olp
                                                 "%<%Y%m%d%H%M%S>-${slug}.org"
                                                 "#+title: ${title}\n#+category: ${title}\n#+filetags: Project"
                                                 ("Tasks"))
                                        :unnarrowed t)))
    (org-roam-db-autosync-mode))
  ;; Org roam ui
  (use-package org-roam-ui
    :defer t
    :config
    (setq org-roam-ui-sync-theme t
          org-roam-ui-follow t
          org-roam-ui-update-on-save t
          org-roam-ui-open-on-start nil))
#+end_src

- Org roam related function
#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/emacs/modules/custom-org.el
  (defun my/org-roam-rg-search ()
    "Search org-roam directory using consult-ripgrep. With live-preview."
    (interactive)
    (let ((consult-ripgrep-command "rg --null --ignore-case --type org --line-buffered --color=always --max-columns=500 --no-heading --line-number . -e ARG OPTS"))
      (consult-ripgrep org-roam-directory)))
  (defun my/org-roam-filter-by-tag (tag-name)
    (lambda (node)
      (member tag-name (org-roam-node-tags node))))
  (defun my/org-roam-list-notes-by-tag (tag-name)
    (mapcar #'org-roam-node-file
            (seq-filter
             (my/org-roam-filter-by-tag tag-name)
             (org-roam-node-list))))
  (defun my/org-roam-refresh-agenda-list ()
    (interactive)
    (setq org-agenda-files (my/org-roam-list-notes-by-tag "Project"))
    (add-to-list 'org-agenda-files my/org-agenda-default-file))
  (defun my/org-roam-project-finalize-hook ()
    "Adds the captured project file to `org-agenda-files' if the
      capture was not aborted."
    ;; Remove the hook since it was added temporarily
    (remove-hook 'org-capture-after-finalize-hook #'my/org-roam-project-finalize-hook)

    ;; Add project file to the agenda list if the capture was confirmed
    (unless org-note-abort
      (with-current-buffer (org-capture-get :buffer)
        (add-to-list 'org-agenda-files (buffer-file-name)))))
  (my/org-roam-refresh-agenda-list)
#+end_src

**** Tools
***** ob-async
asynchronous execution of org-babel src blocks
#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/emacs/modules/custom-org.el
  (use-package ob-async
    :defer t)
#+end_src

some language should add
#+begin_src emacs-lisp
(setq ob-async-no-async-languages-alist '("ipython"))
#+end_src
***** Org PDF tools
get link from pdf,
#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/emacs/modules/custom-org.el
  (use-package org-pdftools
    :defer t
    :hook (org-mode . org-pdftools-setup-link))
#+end_src
**** Keybindings
#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/emacs/modules/custom-org.el
  (ju/leader-key-def
    ;; Org mode
    "o" '(:ignore t :which-key "Org mode")
    "o a" '(:ignore t :which-key "Org Agenda")
    "o a a" '(org-agenda :which-key "open org agenda")
    "o a r" '(my/org-roam-refresh-agenda-list :which-key "Org agenda refresh list")
    "o a c" '((lambda () (interactive) (find-file (expand-file-name "agenda/agenda.org" org-directory))) :which-key "org agenda file")
    "o c" '(cfw:open-org-calendar :which-key "org calendar"))
  (ju/leader-key-def
    "n j" '(:ignore t :which-key "Org Journal")
    "n j j" '(org-journal-new-entry :which-key "new Entry")
    "n j J" '(org-journal-new-scheduled-entry :which-key "New Scheduled entry")
    "n j s" '(org-journal-search :which-key "Journal Search"))
  (ju/leader-key-def
    "n r" '(:ignore t :which-key "Org Roam")
    "n r c" '(org-roam-capture :which-key "capture")
    "n r u" '(org-roam-ui-open :which-key "UI")
    "n r l" '(org-roam-buffer-toggle :which-key "buffer toggle")
    "n r f" '(org-roam-node-find :which-key "node find")
    "n r i" '(org-roam-node-insert :which-key "node insert")
    "n r I" '(org-id-get-create :which-key "create id")
    "n r g" '(my/org-roam-rg-search :which-key "roam ripgrep")
    "n r t" '(:ignore t :which-key "Org Roam Tags")
    "n r t t" '(org-roam-tag-add :which-key "new tag")
    "n r t d" '(org-roam-tag-remove :which-key "delete tag"))
#+end_src

**** Provide Modules
#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/emacs/modules/custom-org.el
  (provide 'custom-org)
  ;;; custom-org.el ends here
#+end_src
*** Projects
**** MAGIT
#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/emacs/modules/custom-projects.el
  (use-package magit
    :defer t
    :commands (magit-status magit-get-current-branch)
    :custom
    (magit-display-buffer-function #'magit-display-buffer-same-window-except-diff-v1)
    :config
    (setq magit-clone-default-directory "~/Project/"))
  (ju/leader-key-def
    ;; Magit
    "g" '(:ignore t :which-key "magit")
    "g g" '(magit :which-key "magit"))
#+end_src
**** Gitgutter
#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/emacs/modules/custom-projects.el
  (use-package git-gutter
    :defer t
    :init (global-git-gutter-mode)
    :custom
    (git-gutter:update-interval 2)
    (git-gutter:linum-enabled nil))
#+end_src
**** Highlight TODOs
***** TODO: test
#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/emacs/modules/custom-projects.el
  (use-package hl-todo
    :defer t
    :init (global-hl-todo-mode 1)
    :config
    (setq hl-todo-keyword-faces
          `(;; For things that need to be done, just not today.
            ("TODO" warning bold)
            ;; For problems that will become bigger problems later if not
            ;; fixed ASAP.
            ("FIXME" error bold)
            ;; For tidbits that are unconventional and not intended uses of the
            ;; constituent parts, and may break in a future update.
            ("HACK" font-lock-constant-face bold)
            ;; For things that were done hastily and/or hasn't been thoroughly
            ;; tested. It may not even be necessary!
            ("REVIEW" font-lock-keyword-face bold)
            ;; For especially important gotchas with a given implementation,
            ;; directed at another user other than the author.
            ("NOTE" success bold)
            ;; For things that just gotta go and will soon be gone.
            ("DEPRECATED" font-lock-doc-face bold)
            ;; For a known bug that needs a workaround
            ("BUG" error bold)
            ;; For warning about a problematic or misguiding code
            ("XXX" font-lock-constant-face bold))))
#+end_src
**** Magit TODOs
#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/emacs/modules/custom-projects.el
  (use-package magit-todos
    :defer t
    :after (magit hl-todo)
    :hook (magit-mode))
#+end_src
**** Provide Modules
#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/emacs/modules/custom-projects.el
  (provide 'custom-projects)
  ;;; custom-projects.el ends here
#+end_src
*** Workspaces
**** Tabspace
#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/emacs/modules/custom-workspaces.el
  ;;(use-package tabspaces
  ;;  :disabled
  ;;  ;; use this next line only if you also use straight, otherwise ignore it.
  ;;  :hook (after-init . tabspaces-mode) ;; use this only if you want the minor-mode loaded at startup.
  ;;  :commands (tabspaces-switch-or-create-workspace
  ;;             tabspaces-open-or-create-project-and-workspace)
  ;;  :custom
  ;;  (tabspaces-use-filtered-buffers-as-default t)
  ;;  (tabspaces-default-tab "Default")
  ;;  (tabspaces-remove-to-default t)
  ;;  (tabspaces-include-buffers '("*scratch*"))
  ;;  ;; sessions
  ;;  (tabspaces-session t)
  ;;  (tabspaces-session-auto-restore t)
  ;;  :config
  ;;  (ju/leader-key-def
  ;;    "TAB" '(tabspaces-command-map :which-key "tabspaces-command-map")))
#+end_src

**** Perspective
#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/emacs/modules/custom-workspaces.el
  ;;(use-package perspective
  ;;  :disabled
  ;;  :demand t
  ;;  :bind (("C-M-j" . consult-buffer)
  ;;         ("C-M-k" . persp-switch)
  ;;         ("C-M-n" . persp-next)
  ;;         ("C-x k" . persp-kill-buffer*))
  ;;  :custom
  ;;  (persp-initial-frame-name "Main")
  ;;  (persp-mode-prefix-key (kbd "C-c p"))
  ;;  :config
  ;;  (ju/leader-key-def
  ;;    "TAB" '(perspective-map :which-key "perspective"))
  ;;  ;; Running `persp-mode' multiple times resets the perspective list...
  ;;  (unless (equal persp-mode t)
  ;;    (persp-mode)))
  ;;(provide 'custom-workspaces)
    ;;; custom-workspaces.el ends here
#+end_src
*** Latex
**** AUCTEX
writing and formatting tex file in Emacs.
#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/emacs/modules/custom-latex.el
  (use-package auctex
    :defer t
    :custom
    (TeX-auto-save t)
    (TeX-parse-self t)
    ;; to use pdfview with auctex
    (TeX-view-program-selection '((output-pdf "PDF Tools")))
    (TeX-view-program-list '(("PDF Tools" TeX-pdf-tools-sync-view)))
    (TeX-source-correlate-start-server t)
    ;; electric pairs in auctex
    (TeX-electric-sub-and-superscript t)
    (LaTeX-electric-left-right-brace t)
    (TeX-electric-math (cons "$" "$"))
    :config
    (setq-default TeX-master nil)
    ;; compile to pdf
    (tex-pdf-mode)
    ;; correlate the source and the output
    (TeX-source-correlate-mode)
    ;; set a correct indentation in a few additional environments
    (add-to-list 'LaTeX-indent-environment-list '("lstlisting" current-indentation))
    (add-to-list 'LaTeX-indent-environment-list '("tikzcd" LaTeX-indent-tabular))
    (add-to-list 'LaTeX-indent-environment-list '("tikzpicture" current-indentation))
    ;; add a few macros and environment as verbatim
    (add-to-list 'LaTeX-verbatim-environments "lstlisting")
    (add-to-list 'LaTeX-verbatim-environments "Verbatim")
    (add-to-list 'LaTeX-verbatim-macros-with-braces "lstinline")
    (add-to-list 'LaTeX-verbatim-macros-with-delims "lstinline")

    ;; open all buffers with the math mode and auto-fill mode
    (add-hook 'LaTeX-mode-hook #'auto-fill-mode)
    (add-hook 'LaTeX-mode-hook #'LaTeX-math-mode)

    ;; add support for references
    (add-hook 'LaTeX-mode-hook 'turn-on-reftex)
    (customize-set-variable 'reftex-plug-into-AUCTeX t)

    ;; to have the buffer refresh after compilation
    (add-hook 'TeX-after-compilation-finished-functions #'TeX-revert-document-buffer))
#+end_src
**** Cdlatex
speed-up insertion of environments and math templates.
#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/emacs/modules/custom-latex.el
  ;;(use-package cdlatex
  ;;  :hook
  ;;  ;(org-mode . org-cdlatex-mode)
  ;;  (LaTex-mode . cdlatex-mode)
  ;;  :config
  ;;  (setq cdlatex-use-dollar-to-ensure-math nil))
#+end_src
**** Provide Modules
#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/emacs/modules/custom-latex.el
  (provide 'custom-latex)
  ;;; custom-latex.el ends here
#+end_src
*** Extra
**** PDF Tool
enhanced PDF viewer on emacs
#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/emacs/modules/custom-extra.el
  (use-package pdf-tools
    :defer t
    :hook ((pdf-tools-enabled . pdf-view-themed-minor-mode)
           (pdf-tools-enabled . pdf-view-fit-page-to-window))
    :config

    (pdf-tools-install :no-query)
    (setq-default pdf-view-display-size 'fit-width))
  (defun my/pdf-view-open-in-zathura ()
    (interactive)
    (save-window-excursion
      (let ((current-file (buffer-file-name))
            (current-page (number-to-string (pdf-view-current-page))))
        (async-shell-command
         (format "zathura -P %s \"%s\"" current-page current-file))))
    (message "Sent to zathura"))
#+end_src
**** PDF view restore
#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/emacs/modules/custom-extra.el
  (use-package pdf-view-restore
    :defer t
    :hook (pdf-view-mode . pdf-view-restore-mode)
    :config
    (setq pdf-view-restore-filename (no-littering-expand-var-file-name "pdf-view-restore")))
#+end_src
**** Nov
#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/emacs/modules/custom-extra.el
  (use-package nov
    :defer t
    :config
    (add-to-list 'auto-mode-alist '("\\.epub\\'" . nov-mode)))
#+end_src
**** Openwith
#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/emacs/modules/custom-extra.el
  (defun my/html-file-open-in-qutebrowser ()
    (interactive)
    (save-window-excursion
      (let ((current-file (buffer-file-name)))
        (async-shell-command
         (format "qutebrowser \"%s\"" current-file))))
    (message "Sent to qutebrowser"))

#+end_src
**** Calfw
calendar
#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/emacs/modules/custom-extra.el
  (use-package calfw)
  (use-package calfw-org
    :after calfw)
#+end_src
**** ELFEED
#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/emacs/modules/custom-extra.el
  (use-package elfeed
    :defer t)
  (use-package elfeed-goodies
    :defer t)
  (use-package elfeed-org
    :defer t
    :config
    (elfeed-org)
    (setq rmh-elfeed-org-files (list (expand-file-name "elfeed.org" user-emacs-directory))))
#+end_src
**** Chat-GPT
https://github.com/xenodium/chatgpt-shell
#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/emacs/modules/custom-extra.el
  (use-package chatgpt-shell
    :config
    (setq chatgpt-shell-openai-key "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"))
#+end_src
**** Provide Modules
#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/emacs/modules/custom-extra.el
  (provide 'custom-extra)
  ;;; custom-extra.el ends here
#+end_src

*** Languages
**** Treesitter
#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/emacs/modules/custom-languages.el
  ;;(if (version< emacs-version "29")
  ;;(use-package tree-sitter
  ;;  :defer t
  ;;  :init (global-tree-sitter-mode))
  ;;(use-package tree-sitter-langs
  ;;  :defer t
  ;;  :after tree-sitter))
#+end_src
**** eglot
#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/emacs/modules/custom-languages.el
  (if (version< emacs-version "29")
      (use-package eglot
        :defer t))
#+end_src
**** Rust
#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/emacs/modules/custom-languages.el
  (use-package rust-mode
    :defer t)
#+end_src
**** Python
#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/emacs/modules/custom-languages.el
  (use-package jupyter
    :ensure t)
#+end_src
**** CMAKE
#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/emacs/modules/custom-languages.el
  ;;(use-package cmake-mode
  ;;  :defer t)
#+end_src

**** Markdown
#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/emacs/modules/custom-languages.el
  (use-package markdown-mode
    :defer t
    :config
    (add-to-list 'auto-mode-alist '("README\\.md\\'" . gfm-mode))
    (add-to-list 'auto-mode-alist '("\\.md\\'" . markdown-mode))
    (add-to-list 'auto-mode-alist '("\\.markdown\\'" . markdown-mode))
    (setq markdown-command "multimarkdown"))
#+end_src
**** PKGBUILD
#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/emacs/modules/custom-languages.el
  (use-package pkgbuild-mode
    :defer t)
#+end_src
**** Systemd
#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/emacs/modules/custom-languages.el
  (use-package systemd
    :defer t)
#+end_src
**** Toml
#+begin_src emacs-lisp
  (use-package toml-mode
    :defer t
    :config
    (add-to-list 'auto-mode-alist '("/\\(Cargo.lock\\|\\.cargo/config\\)\\'" . toml-mode)))
#+end_src
**** Nu
#+begin_src emacs-lisp
  (use-package nushell-mode
    :straight (nushell-mode :type git :host github :repo "azzamsa/emacs-nushell"))
#+end_src

#+RESULTS:

**** Gnuplot
#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/emacs/modules/custom-languages.el
  (use-package gnuplot
    :defer t)
#+end_src
**** Graphviz dot Mode
org mode graph drawing with graphviz
#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/emacs/modules/custom-languages.el
  (use-package graphviz-dot-mode
    :defer t)
#+end_src
**** Verilog Indent
LSP -> veriloter
#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/emacs/modules/custom-languages.el
  (custom-set-variables
   '(verilog-indent-level 4)
   '(verilog-indent-level-module 0)
   '(verilog-indent-level-declaration 0)
   '(verilog-indent-level-behavioral 0)
   '(verilog-indent-level-directive 0)
   '(verilog-cexp-indent 0)
   '(verilog-case-indent 4)

   '(verilog-auto-newline nil))
#+end_src
**** Default
#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/emacs/modules/custom-languages.el
  (with-eval-after-load 'org
    (org-babel-do-load-languages
     'org-babel-load-languages
     '((emacs-lisp . t)
       (python . t)
       ;;(jupyter . t)
       (dot . t)
       (latex . t)))
    ;;(org-babel-jupyter-override-src-block "python")
    (push '("conf-unix" . conf-unix) org-src-lang-modes)
    ;; This is needed as of Org 9.2
    (require 'org-tempo)

    (add-to-list 'org-structure-template-alist '("sh" . "src shell"))
    (add-to-list 'org-structure-template-alist '("el" . "src emacs-lisp"))
    (add-to-list 'org-structure-template-alist '("hs" . "src haskell"))
    (add-to-list 'org-structure-template-alist '("cc" . "src c"))
    (add-to-list 'org-structure-template-alist '("cp" . "src c++"))
    (add-to-list 'org-structure-template-alist '("rs" . "src rust"))
    (add-to-list 'org-structure-template-alist '("py" . "src python"))
    (add-to-list 'org-structure-template-alist '("oc" . "src octave"))
    (add-to-list 'org-structure-template-alist '("vl" . "src verilog"))
    (add-to-list 'org-structure-template-alist '("vh" . "src vhdl"))
    (org-reload))
#+end_src
**** Provide modules
#+begin_src emacs-lisp :mkdirp yes :tangle ~/.config/emacs/modules/custom-languages.el
  (provide 'custom-languages)
  ;;; custom-languages.el ends here
#+end_src
