Skip to content

Latest commit

 

History

History
1970 lines (1737 loc) · 67.9 KB

config.org

File metadata and controls

1970 lines (1737 loc) · 67.9 KB

Config

Contents

Doom default config

;;; $DOOMDIR/config.el -*- lexical-binding: t; -*-

;; Place your private configuration here! Remember, you do not need to run 'doom
;; refresh' after modifying this file!

;; Key Configuration for Doom as Vanilla Emacs
;;(setq evil-default-state 'emacs)

;; Some functionality uses this to identify you, e.g. GPG configuration, email
;; clients, file templates and snippets.
(setq user-full-name "Tru"
      user-mail-address "tru.zhou@gmail.com")

;; Doom exposes five (optional) variables for controlling fonts in Doom. Here
;; are the three important ones:
;;
;; + `doom-font'
;; + `doom-variable-pitch-font'
;; + `doom-big-font' -- used for `doom-big-font-mode'
;;
;; They all accept either a font-spec, font string ("Input Mono-12"), or xlfd
;; font string. You generally only need these two:

;; (setq doom-font (font-spec :family "Operator Mono SSm" :size 20))
;;(set-face-attribute 'default nil :family "Operator Mono SSm Lig" :weight 'normal)
;(setq doom-font (font-spec :family "Operator Mono SSm Lig" :weight 'normal :size 20))
(setq doom-font (font-spec :family "MesloLGS NF" :weight 'normal :size 20)
      doom-variable-pitch-font (font-spec :family "MesloLGS NF" :size 20))
(setq doom-unicode-font doom-font)

;; There are two ways to load a theme. Both assume the theme is installed and
;; available. You can either set `doom-theme' or manually load a theme with the
;; `load-theme' function. These are the defaults.
;; (setq doom-theme 'doom-one)
;; (load-theme 'doom-one)

;; If you intend to use org, it is recommended you change this!
(setq org-directory "~/Dropbox/Org")

;; If you want to change the style of line numbers, change this to `relative' or
;; `nil' to disable it:
(setq display-line-numbers-type t)

Font

(when (display-graphic-p)
  (add-hook 'window-setup-hook #'+ui/toggle-transparency)
  )

UI

Doom dashboard ascii banner

"           _____"
"         ===///    , ,-. ,-   .-, , , ,-  ,_  ,  ,_ ,-"
"         --///    /_ |_/ _)  /''|/|/ |_] /=_ /_ /=_ _)"
"       ___///    __    __  __  ______  ____    ___"
"         ///  --/||  --// .'   //  '/ _//  )) (|  '/"
"     ---///   /' ||  _//.;  __//_.    //_=''  _\\"
"     --///- -/---||  //'||   //  ', _//  ;|     \\     ;"
" _____/// __/_  _||_/<  `||_//__'/ _// --|\ /-._//    /"
"    _///      ,                        ---\\\       .'"
" ___///_____'/                              `;=__.-'"





"                    _..n-'''/''--.._ "
"                 .n' _.-\-''('''--._`-. "
"               ,' .\'   \   `.      ``';. "
"           ___/_-'  |    \    `.         `. "
"         ===///    , ,-. .-   .-; , , ,-  ,L  ,  ,_ ,- "
"         --///    /_ |_/ _)  /''|/|/ |_] /=_ /_ /=_ _) "
"       ___///    __    __  __  ______  ____ |  ___ "
"         ///  --/||  --// .'   //  '/ _//  ))|(|  '/ "
"     ---///   /' ||  _//.;  __//_.    //_=''  _\\ "
"     --///- -/---||  //'||   //  ', _//  ;|     \\     ; "
"______///|__/_  _||_/<  ||_ //__'/ _// --|\ /-._//    / "
"    _///  |   ,   |          \         ---\\\       .' "
" ___///_____'/     \         \             /`;=__.-' "
"            \       \         \           / "
"             `.      \        \         ,' "
"               `.     \        \      ,' "
"                 `-._  \        \ _.-' "
"                     `--\......--' "



(defun doom-dashboard-draw-ascii-emacs-banner-fn ()
  (let* ((banner
          '(
"           _____"
"         ===///    , ,-. ,-   .-, , , ,-  ,_  ,  ,_ ,-"
"         --///    /_ |_/ _)  /''|/|/ |_] /=_ /_ /=_ _)"
"       ___///    __    __  __  ______  ____    ___"
"         ///  --/||  --// .'   //  '/ _//  )) (|  '/"
"     ---///   /' ||  _//.;  __//_.    //_=''  _\\"
"     --///- -/---||  //'||   //  ', _//  ;|     \\     ;"
" _____/// __/_  _||_/<  `||_//__'/ _// --|\ /-._//    /"
"    _///      ,                        ---\\\       .'"
" ___///_____'/                              `;=__.-'"
" "
" "

))
         (longest-line (apply #'max (mapcar #'length banner))))
    (put-text-property
     (point)
     (dolist (line banner (point))
       (insert (+doom-dashboard--center
                +doom-dashboard--width
                (concat
                 line (make-string (max 0 (- longest-line (length line)))
                                   32)))
               "\n"))
     'face 'doom-dashboard-banner)))

(unless (display-graphic-p) ; for some reason this messes up the graphical splash screen atm
  (setq +doom-dashboard-ascii-banner-fn #'doom-dashboard-draw-ascii-emacs-banner-fn))
(setq +doom-dashboard-ascii-banner-fn #'doom-dashboard-draw-ascii-emacs-banner-fn)
(defun my-weebery-is-always-greater ()
  (mapc (lambda (line)
          (insert (propertize (+doom-dashboard--center +doom-dashboard--width line)
                              'face 'doom-dashboard-banner) " ")
          (insert "\n"))
        '(
"█████╗   █████╗ ██╗     ██╗         ██████╗  ██████╗ ███╗   ██╗████████╗    ██╗     ██╗███████╗"
"██╔══██╗██╔══██╗██║     ██║         ██╔══██╗██╔═══██╗████╗  ██║╚══██╔══╝    ██║     ██║██╔════╝"
"██████╔╝███████║██║     ██║         ██║  ██║██║   ██║██╔██╗ ██║   ██║       ██║     ██║█████╗"
"██╔══██╗██╔══██║██║     ██║         ██║  ██║██║   ██║██║╚██╗██║   ██║       ██║     ██║██╔══╝"
"██████╔╝██║  ██║███████╗███████╗    ██████╔╝╚██████╔╝██║ ╚████║   ██║       ███████╗██║███████╗"
"Emacs TRU Edition")))

(setq +doom-dashboard-ascii-banner-fn #'my-weebery-is-always-greater)


(defun my-weebery-is-always-greater ()
  (mapc (lambda (line)
          (insert (propertize (+doom-dashboard--center +doom-dashboard--width line)
                              'face 'doom-dashboard-banner) " ")
          (insert "\n"))
        '(
"           _____"
"         ===///    , ,-. ,-   .-, , , ,-  ,_  ,  ,_ ,-"
"         --///    /_ |_/ _)  /''|/|/ |_] /=_ /_ /=_ _)"
"       ___///    __    __  __  ______  ____    ___"
"         ///  --/||  --// .'   //  '/ _//  )) (|  '/"
"     ---///   /' ||  _//.;  __//_.    //_=''  _\\"
"     --///- -/---||  //'||   //  ', _//  ;|     \\     ;"
" _____/// __/_  _||_/<  ||_ //__'/ _// --|\ /-._//    /"
"    _///      ,                        ---\\\       .'"
" ___///_____'/                              `;=__.-'"

          )))

(setq +doom-dashboard-ascii-banner-fn #'my-weebery-is-always-greater)

Doom dashboard menu

Doom-modeline

;; (after! doom-modeline
;;   (doom-modeline-def-modeline 'my/modeline
;;     '(bar matches buffer-info remote-host buffer-position parrot selection-info)
;;     '(misc-info minor-modes checker input-method buffer-encoding major-mode process vcs))
;;   (defun setup-custom-doom-modeline ()
;;     (doom-modeline-set-modeline 'my/modeline 'default))
;;   (add-hook 'doom-modeline-mode-hook 'setup-custom-doom-modeline))

;; (custom-set-faces!
;;   '(mode-line :height 180)
;;   '(mode-line-inactive :height 180))
;; (after! doom-modeline
;;   (setq
;;         doom-modeline-height 1
;;         doom-modeline-icon t
;;         doom-modeline-major-mode-icon t
;;         doom-modeline-major-mode-color-icon t
;;         doom-modeline-buffer-state-icon t
;;         doom-modeline-buffer-modification-icon t
;;         doom-modeline-enable-word-count nil
;;         doom-modeline-indent-info t
;;         doom-modeline-workspace-name t)
;;   (set-face-attribute 'mode-line nil :height 180)
;;   (set-face-attribute 'mode-line-inactive nil :height 180)
;; )
;; (defun enable-doom-modeline-icons (_frame)
;;   (setq doom-modeline-icon t))
;; (add-hook 'after-make-frame-functions
;;           #'enable-doom-modeline-icons)

Whitespace

;; (ws-butler-global-mode -1)
;; (setq-default show-trailing-whitespace t)

;; ;;; Whitespace
;; (defun sanityinc/show-trailing-whitespace ()
;;   "Enable display of trailing whitespace in this buffer."
;;   (setq-local show-trailing-whitespace t))
;; (dolist (hook '(prog-mode-hook text-mode-hook conf-mode-hook))
;;   (add-hook hook 'sanityinc/show-trailing-whitespace))
;; (use-package! whitespace-cleanup-mode
;;   :diminish whitespace-cleanup-mode)
;; (add-hook 'after-init-hook 'global-whitespace-cleanup-mode)
;; (global-set-key [remap just-one-space] 'cycle-spacing)

toggle-transparency

(defun +ui/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)
          '(90 . 80) '(100 . 100)))))

(map!
 "s-u"                         #'+ui/toggle-transparency
 :leader
 :prefix ("t" . "toggle")
 :desc "Transparency"
 :n "t" #'+ui/toggle-transparency)

nyan-mode

(use-package! nyan-mode
  :after doom-modeline
  :init
  (setq
        ;; nyan-animate-nyancat t
        ;; nyan-wavy-trail t
        nyan-minimum-window-width 81
        nyan-bar-length 24)
  (nyan-mode t))

Tabs

(after! centaur-tabs
  (centaur-tabs-group-by-projectile-project)
  (define-key global-map "\C-q" nil)
  (global-set-key (kbd "C-S-<tab>") 'centaur-tabs-backward)
  (global-set-key (kbd "C-<tab>") 'centaur-tabs-forward)
)
;; (define-key global-map (kbd "C-q") (make-sparse-keymap))
;; (global-tab-line-mode 1)
;; ;global-map <C-tab>
;; (define-key global-map (kbd "C-<tab>") nil)
;; (global-set-key (kbd "C-<tab>") 'tab-line-switch-to-next-tab)
;; (global-set-key (kbd "C-S-<tab>") 'tab-line-switch-to-prev-tab)
;; (tab-bar-mode 1)
;; (global-set-key (kbd "ESC C-<tab>") 'tab-bar-switch-to-prev-tab)
;; (global-set-key (kbd "ESC C-S-<tab>") 'tab-bar-switch-to-next-tab)
;; (global-set-key (kbd "C-q C-q RET") 'tab-bar-select-tab-by-name)

ivy-postframe

(after! ivy-posframe
  (setq ivy-posframe-display-functions-alist
        '((swiper          . ivy-posframe-display-at-point)
          (complete-symbol . ivy-posframe-display-at-point)
          (t               . ivy-posframe-display-at-frame-top-center))
        ivy-posframe-parameters '((internal-border-width . 10)))
  (setq ivy-posframe-height-alist '((swiper . 20)
                                    (t      . 35)))
  (ivy-posframe-mode 1))

Tag everywhere

https://gist.github.com/rougier/f0f291f681cb5b95aef5ad51a83166fd https://www.reddit.com/r/emacs/comments/jc4uou/tags_everywhere/

window

(global-set-key (kbd "M-s-<left>") 'shrink-window-horizontally)
(global-set-key (kbd "M-s-<right>") 'enlarge-window-horizontally)
(global-set-key (kbd "M-s-<down>") 'shrink-window)
(global-set-key (kbd "M-s-<up>") 'enlarge-window)
;(setq window-safe-min-height 18)

helm window size

(setq helm-autoresize-max-height 50)
(setq helm-autoresize-min-height 45)
;(helm-autoresize-mode 1)

Display Line Number

(setq display-line-numbers-type 'relative)

Frame size

Tip: Setting initial frame size and position : emacs

;; Set initial frame size and position
;; (defun my/set-initial-frame ()
;;   (let* ((base-factor 0.81)
;; 	(a-width (* (display-pixel-width) base-factor))
;;         (a-height (* (display-pixel-height) base-factor))
;;         (a-left (truncate (/ (- (display-pixel-width) a-width) 2)))
;; 	(a-top (truncate (/ (- (display-pixel-height) a-height) 2))))
;;     (set-frame-position (selected-frame) a-left a-top)
;;     (set-frame-size (selected-frame) (truncate a-width)  (truncate a-height) t)))
;; (setq frame-resize-pixelwise t)
;; (my/set-initial-frame)
(add-to-list 'default-frame-alist '(top . 10))
(add-to-list 'default-frame-alist '(left . 81))

(add-to-list 'default-frame-alist '(height . 50))
(add-to-list 'default-frame-alist '(width . 153))
;(add-to-list 'default-frame-alist '(top . 10))
;(add-to-list 'default-frame-alist '(top . 81))

Fill-column

;(setq-default fill-column 2000)

Quickly visit Emacs configuration

(defun tru/visit-emacs-config ()
  (interactive)
  (find-file "/Users/tru/Dropbox/Apps/emacs/tru/doom-emacs/config.org"))
(global-set-key (kbd "ESC ESC e") 'tru/visit-emacs-config)
(global-set-key (kbd "ESC ESC ESC") 'doom/switch-to-scratch-buffer)

macOS

Define const is-a-mac

(defconst *is-a-mac* (eq system-type 'darwin))

keybinding

(when *is-a-mac*
  (setq mac-command-modifier 'meta)
  (setq mac-option-modifier 'super)
  ;; Make mouse wheel / trackpad scrolling less jerky
  (setq mouse-wheel-scroll-amount '(1
                                    ((shift) . 5)
                                    ((control))))
  (dolist (multiple '("" "double-" "triple-"))
    (dolist (direction '("right" "left"))
      (global-set-key (read-kbd-macro (concat "<" multiple "wheel-" direction ">")) 'ignore)))
  (global-set-key (kbd "M-`") 'ns-next-frame)
  (global-set-key (kbd "M-h") 'ns-do-hide-emacs)
  (global-set-key (kbd "M-˙") 'ns-do-hide-others)
  )
(global-set-key (kbd "M-v") 'yank)
(global-set-key (kbd "M-V") 'scroll-down)

macOS Daemon

(when *is-a-mac*
  (setq mac-pseudo-daemon-mode 't)
  (mac-pseudo-daemon-mode 1))

Others

;;(global-set-key (kbd "C-x C-b") 'ibuffer)

Dictionary

;; Support Chinese word
;; (setq osx-dictionary-use-chinese-text-segmentation t)

;; Key bindings
(global-set-key (kbd "C-c d") 'osx-dictionary-search-word-at-point)
;; (global-set-key (kbd "C-c i") 'osx-dictionary-search-input)

;; Work with popwin-el (https://github.com/m2ym/popwin-el)
;; (push "*osx-dictionary*" popwin:special-display-config)

Quickly visit macOS configuration

zshrc

(defun tru/visit-custom-dotzshrc ()
  (interactive)
  (find-file "/Users/tru/Dropbox/Dev/configs/zshrc.d/README.org"))
(global-set-key (kbd "ESC ESC z") 'tru/visit-custom-dotzshrc)

zsh custom functions

(defun tru/visit-custom-functions ()
  (interactive)
  (find-file "/Users/tru/Dropbox/git/src/github.com/Ubiquiti-UID/uid.literate-devops/README.org"))
(global-set-key (kbd "ESC ESC f") 'tru/visit-custom-functions)

org-mac-iCal.el – import Mac OS X iCal.app events into Emacs diary

https://orgmode.org/worg/org-contrib/org-mac-iCal.html https://github.com/ndw/org-mac-iCal

;; #(use-package! org-mac-iCal)
(load-file "/Users/tru/Dropbox/git/src/github.com/tru2dagame/org-mac-iCal/org-mac-iCal.el")
;; (load-file (locate-library "org-mac-iCal.el"))
(add-to-list 'org-modules 'org-mac-iCal)
(setq org-agenda-include-diary t)

Editing

sudo edit

(use-package! sudo-edit)

Auto Save

(setq auto-save-visited-file-name t)
(setq auto-save-visited-interval 600)
(auto-save-visited-mode +1)
(setq buffer-save-without-query 't)

Super Save

(use-package! super-save
  :config
  (super-save-mode +1)
  (setq super-save-auto-save-when-idle t))

Always indent with spaces

Never use tabs. Tabs are the devil’s whitespace.

(setq-default indent-tabs-mode nil)

undo-tree

;; (after! undo-tree
;;   (define-key undo-tree-map (kbd "C-/") nil)
;;   (define-key undo-tree-map (kbd "C-_") nil)
;;   (define-key undo-tree-map [remap undo] nil)
;;   (define-key global-map (kbd "C-/") nil)
;;   (global-set-key (kbd "C-/") 'undo))

undo

;; (after! undo-fu
;;   (define-key undo-fu-mode-map [remap undo] nil)
;;   (define-key global-map (kbd "C-/") nil)
;;   (global-set-key (kbd "C-/") 'undo)
;;   (global-set-key (kbd "M-z") 'undo-fu-only-undo)
;;   (global-set-key (kbd "M-Z") 'undo-fu-only-redo)
;; )

tramp

(setq tramp-shell-prompt-pattern "^[^$>\n]*[#$%>] *\\(\[[0-9;]*[a-zA-Z] *\\)*")

rg

(setq counsel-rg-base-command '("rg" "-C" "2" "--max-columns" "240" "--with-filename" "--no-heading" "--line-number" "--color" "never" "%s"))

avy-goto-char-2

;; (global-set-key (kbd "M-s M-s") 'avy-goto-char-timer)
(global-set-key (kbd "M-s M-s") 'avy-goto-char-2)
(setq avy-timeout-seconds 0.35)
(setq avy-all-windows 't)

better-jump

(global-set-key (kbd "C-c j p") 'better-jumper-jump-backward)
(global-set-key (kbd "s-<") 'better-jumper-jump-backward)
(global-set-key (kbd "C-c j n") 'better-jumper-jump-forward)
(global-set-key (kbd "s->") 'better-jumper-jump-forward)
(global-set-key (kbd "C-c j m") 'better-jumper-set-jump)
(global-set-key (kbd "C-c j c") 'better-jumper-clear-jumps)
(global-set-key (kbd "C-c j l") 'better-jumper-jump-newest)

mark ring

https://stackoverflow.com/questions/39000917/making-emacs-push-the-location-to-the-mark-ring-on-every-big-movement

;(defun my-set-mark ()
;  (interactive)
;  (push-mark (point) t nil))

;(defadvice find-file (before set-mark activate) (my-set-mark))
;(defadvice goto-char (before set-mark activate) (my-set-mark))
;(defadvice goto-line (before set-mark activate) (my-set-mark))
;(defadvice isearch-update (before set-mark activate) (my-set-mark))
;(defadvice beginning-of-buffer (before set-mark activate) (my-set-mark))
;(defadvice end-of-buffer (before set-mark activate) (my-set-mark))

https://stackoverflow.com/questions/25374287/how-to-move-to-the-last-point-position-before-popping-mark-ring?rq=1

;; (defun save-mark-before-pop ()
;;   (push-mark (point) t)
;;   (pop-mark))

;; (advice-add 'pop-to-mark-command :before 'save-mark-before-pop)
;; (setq set-mark-command-repeat-pop t)

;; (defadvice set-mark-command (before record-current-position (arg) activate)
;;   (when arg (push-mark)))

isearch enhancements

(setq search-whitespace-regexp ".*?")

RG

(use-package wgrep
  :config
  (setq wgrep-auto-save-buffer t)
  (setq wgrep-change-readonly-file t))

(use-package! rg
  :after wgrep
  :config
  (setq rg-group-result t)
  (setq rg-hide-command t)
  (setq rg-show-columns nil)
  (setq rg-show-header t)
  (setq rg-custom-type-aliases nil)
  (setq rg-default-alias-fallback "all")

  (rg-define-search rg/grep-vc-or-dir
    :query ask
    :format regexp
    :files "everything"
    :dir (let ((vc (vc-root-dir)))
           (if vc
               vc                         ; search root project dir
             default-directory))          ; or from the current dir
    :confirm prefix
    :flags ("--hidden -g !.git"))

  (defun rg/rg-save-search-as-name ()
    "Save `rg' buffer, naming it after the current search query.

This function is meant to be mapped to a key in `rg-mode-map'."
    (interactive)
    (let ((pattern (car rg-pattern-history)))
      (rg-save-search-as-name (concat "«" pattern "»"))))

  :bind (
         :map rg-mode-map
         ("s" . rg/rg-save-search-as-name)
         ("C-n" . next-line)
         ("C-p" . previous-line)
         ("M-n" . rg-next-file)
         ("M-p" . rg-prev-file)))

Google it

(use-package! google-this
  :diminish google-this-mode
  :bind-keymap ("ESC ESC 1" . google-this-mode-submap))

Org

Org settings from purcell

(after! org
;; Various preferences
(setq org-log-done t
      org-log-into-drawer t
      org-edit-timestamp-down-means-later t
      org-hide-emphasis-markers t
      org-catch-invisible-edits 'show
      org-export-coding-system 'utf-8
      org-fast-tag-selection-single-key 'expert
      org-html-validation-link nil
      org-export-kill-product-buffer-when-displayed t
      org-tags-column 80)

(setq org-support-shift-select t)
(setq org-refile-use-cache nil)
)

;; Re-align tags when window shape changes
(after! 'org-agenda
  (add-hook 'org-agenda-mode-hook
            (lambda () (add-hook 'window-configuration-change-hook 'org-agenda-align-tags nil t))))

(after! org
;;; To-do settings
;; (setq org-todo-keywords
;;       (quote ((sequence "TODO(t)" "NEXT(n)" "|" "DONE(d!/!)")
;;               (sequence "PROJECT(p)" "|" "DONE(d!/!)" "CANCELLED(c@/!)")
;;               (sequence "WAITING(w@/!)" "DELEGATED(e!)" "HOLD(h)" "|" "CANCELLED(c@/!)")))
;;       org-todo-repeat-to-state "NEXT")

;; (setq org-todo-keyword-faces
;;       (quote (("NEXT" :inherit warning)
;;               ("PROJECT" :inherit font-lock-string-face))))

(setq-default org-agenda-clockreport-parameter-plist '(:link t :maxlevel 4))


;; (let ((active-project-match "-INBOX/PROJECT"))

;;   (setq org-stuck-projects
;;         `(,active-project-match ("NEXT")))

;;   (setq org-agenda-compact-blocks t
;;         org-agenda-sticky t
;;         org-agenda-start-on-weekday nil
;;         org-agenda-span 'day
;;         org-agenda-include-diary nil
;;         org-agenda-sorting-strategy
;;         '((agenda habit-down time-up user-defined-up effort-up category-keep)
;;           (todo category-up effort-up)
;;           (tags category-up effort-up)
;;           (search category-up))
;;         org-agenda-window-setup 'current-window
;;         org-agenda-custom-commands
;;         `(("N" "Notes" tags "NOTE"
;;            ((org-agenda-overriding-header "Notes")
;;             (org-tags-match-list-sublevels t)))
;;           ("g" "GTD"
;;            ((agenda "" nil)
;;             (tags "INBOX"
;;                   ((org-agenda-overriding-header "Inbox")
;;                    (org-tags-match-list-sublevels nil)))
;;             (stuck ""
;;                    ((org-agenda-overriding-header "Stuck Projects")
;;                     (org-agenda-tags-todo-honor-ignore-options t)
;;                     (org-tags-match-list-sublevels t)
;;                     (org-agenda-todo-ignore-scheduled 'future)))
;;             (tags-todo "-INBOX"
;;                        ((org-agenda-overriding-header "Next Actions")
;;                         (org-agenda-tags-todo-honor-ignore-options t)
;;                         (org-agenda-todo-ignore-scheduled 'future)
;;                         (org-agenda-skip-function
;;                          '(lambda ()
;;                             (or (org-agenda-skip-subtree-if 'todo '("HOLD" "WAITING"))
;;                                 (org-agenda-skip-entry-if 'nottodo '("NEXT")))))
;;                         (org-tags-match-list-sublevels t)
;;                         (org-agenda-sorting-strategy
;;                          '(todo-state-down effort-up category-keep))))
;;             (tags-todo ,active-project-match
;;                        ((org-agenda-overriding-header "Projects")
;;                         (org-tags-match-list-sublevels t)
;;                         (org-agenda-sorting-strategy
;;                          '(category-keep))))
;;             (tags-todo "-INBOX/-NEXT"
;;                        ((org-agenda-overriding-header "Orphaned Tasks")
;;                         (org-agenda-tags-todo-honor-ignore-options t)
;;                         (org-agenda-todo-ignore-scheduled 'future)
;;                         (org-agenda-skip-function
;;                          '(lambda ()
;;                             (or (org-agenda-skip-subtree-if 'todo '("PROJECT" "HOLD" "WAITING" "DELEGATED"))
;;                                 (org-agenda-skip-subtree-if 'nottododo '("TODO")))))
;;                         (org-tags-match-list-sublevels t)
;;                         (org-agenda-sorting-strategy
;;                          '(category-keep))))
;;             (tags-todo "/WAITING"
;;                        ((org-agenda-overriding-header "Waiting")
;;                         (org-agenda-tags-todo-honor-ignore-options t)
;;                         (org-agenda-todo-ignore-scheduled 'future)
;;                         (org-agenda-sorting-strategy
;;                          '(category-keep))))
;;             (tags-todo "/DELEGATED"
;;                        ((org-agenda-overriding-header "Delegated")
;;                         (org-agenda-tags-todo-honor-ignore-options t)
;;                         (org-agenda-todo-ignore-scheduled 'future)
;;                         (org-agenda-sorting-strategy
;;                          '(category-keep))))
;;             (tags-todo "-INBOX"
;;                        ((org-agenda-overriding-header "On Hold")
;;                         (org-agenda-skip-function
;;                          '(lambda ()
;;                             (or (org-agenda-skip-subtree-if 'todo '("WAITING"))
;;                                 (org-agenda-skip-entry-if 'nottodo '("HOLD")))))
;;                         (org-tags-match-list-sublevels nil)
;;                         (org-agenda-sorting-strategy
;;                          '(category-keep))))
;;             ;; (tags-todo "-NEXT"
;;             ;;            ((org-agenda-overriding-header "All other TODOs")
;;             ;;             (org-match-list-sublevels t)))
;;             )))))
)

(add-hook 'org-agenda-mode-hook 'hl-line-mode)

;;; Archiving
(after! org
(setq org-archive-mark-done nil)
(setq org-archive-location "%s_archive::* Archive")
)

Org capture template

https://www.reddit.com/r/emacs/comments/7zqc7b/share_your_org_capture_templates/

(after! org
  (setq org-capture-templates
        (append '(("1" "Tru's Entry")
                  ("1t" "todo" entry (file "~/Dropbox/Org/inbox.org")
                   "* TODO %?\n%U\n" :clock-resume t)
                  ("1n" "note" entry (file "~/Dropbox/Org/notes.org")
                   "* %? :NOTE:\n%U\n%a\n" :clock-resume t)
        )
        org-capture-templates))
)

org-mode automatically wrap lines

(after! org
(visual-line-mode 1))

Org note file

(after! org
  (setq org-default-notes-file "~/Dropbox/Org/inbox.org"))

Org Agenda File

(after! org
  (setq org-agenda-files "~/Dropbox/Apps/org-agenda/agenda_files"))

org refile targets

(after! org
  ;;(setq org-refile-targets '((nil :maxlevel . 3) (org-agenda-files :maxlevel . 3)))
  (add-to-list 'org-refile-targets '("~/Dropbox/Org/org-roam/study/20220605052908-capture.org"  :maxlevel . 3))
)

Org Capture for alfred

https://github.com/ifitzpat/org-capture-popclip-extension/blob/master/el/alfred-org-capture.el

(defvar org-mac-context nil)

;;; Use org-mac to get link context and insert it to the captured item
(add-hook 'org-capture-prepare-finalize-hook
          (lambda ()
            (when (equal
                   (cdr (assoc 'name (frame-parameters (selected-frame))))
                   "remember")
              (progn
                (goto-char (point-max))
                (if org-mac-context
                    (progn
                      (insert (concat org-mac-context "\n"))
                      (setq org-mac-context nil))
                  nil)
                ;;(call-interactively 'org-mac-link-link)
                ))))

;;; Delete frame when capture is done
(add-hook 'org-capture-after-finalize-hook
          (lambda ()
            (when (equal
                   (cdr (assoc 'name (frame-parameters (selected-frame))))
                   "remember")
              (delete-frame))))

;;; Code:
(defun make-orgcapture-frame (&optional mytext)
  "Create a new frame and run org-capture."
  (interactive)
  (setq org-mac-context mytext)
  (make-frame '((name . "remember") (width . 100) (height . 30)
                (top . 400) (left . 300)
                ))
  (select-frame-by-name "remember")
  (org-capture))


;;     (add-to-list 'default-frame-alist '(height . 39))
;;     (add-to-list 'default-frame-alist '(width . 124))

;; ;;; Code:
;; ;;; https://github.com/jjasghar/alfred-org-capture
;; (defun make-orgcapture-frame ()
;;   "Create a new frame and run org-capture."
;;   (interactive)
;;   (make-frame '((name . "remember") (width . 124) (height . 39)
;;                 (top . 400) (left . 300)
;;                 (font . "Operator Mono SSm")
;;                 ))
;;   (select-frame-by-name "remember")
;;   (org-capture))

Visit daily org file

(defun tru/visit-my-org-daily ()
  (interactive)
  (find-file "~/Dropbox/Org/daily.org"))
(global-set-key (kbd "ESC ESC d") 'tru/visit-my-org-daily)
(defun tru/visit-my-org-inbox ()
  (interactive)
  (find-file "~/Dropbox/Org/inbox.org"))
(global-set-key (kbd "ESC ESC i") 'tru/visit-my-org-inbox)
(defun tru/visit-my-org-journal ()
  (interactive)
  (find-file "~/Dropbox/Org/journal.org"))
(global-set-key (kbd "ESC ESC j") 'tru/visit-my-org-journal)

Org ansi

;(require 'loadhist)
;(file-dependents (feature-file 'cl))
(require 'cl-lib)
(defun tru/org-redisplay-ansi-export-blocks ()
  "Refresh the display of ANSI text source blocks."
  (interactive)
  (org-element-map (org-element-parse-buffer) 'export-block
    (lambda (export)
      (when (equalp "ansi" (org-element-property :type export))
        (let ((begin (org-element-property :begin export))
              (end (org-element-property :end export)))
          (ansi-color-apply-on-region begin end))))))

(defun tru/org-redisplay-ansi-example-blocks ()
  "Refresh the display of ANSI text source blocks."
  (interactive)
  (org-element-map (org-element-parse-buffer) 'example-block
    (lambda (example)
      (when (equalp "ansi" (org-element-property :switches example))
        (let ((begin (org-element-property :begin example))
              (end (org-element-property :end example)))
          (ansi-color-apply-on-region begin end))))))

(use-package! org
  :defer t
  :config
  (add-to-list 'org-babel-after-execute-hook #'tru/org-redisplay-ansi-export-blocks)
  (add-to-list 'org-babel-after-execute-hook #'tru/org-redisplay-ansi-example-blocks)
  (org-babel-do-load-languages 'org-babel-load-languages '((shell . t)))
)

example:

;#+begin_src shell :results output verbatim drawer :wrap export ansi
echo "\e[33mTest text\e[0m"
echo Styles: '\e[3mitalic\e[0m' '\e[1mbold\e[0m' '\e[4munderline\e[0m' '\e[1m\e[3mbolditalics\e[0m'
;#+end_src

;#+RESULTS:
;#+begin_export ansi
Test text
Styles: italic bold underline bolditalics
;#+end_export

Display preferences

Make TAB act as if it were issued in a buffer of the language’s major mode.

(after! org
(setq org-src-tab-acts-natively t))

When editing a code snippet, use the current window rather than popping open a new one (which shows the same information).

(after! org
(setq org-src-window-setup 'current-window))

Quickly insert a block of elisp:

(after! org
(add-to-list 'org-structure-template-alist '("el" . "src emacs-lisp")))

Ob-async

(use-package! ob-async)

Ob-tmux

(use-package! ob-tmux)

Org-rifle

(use-package! helm-org-rifle)

Org clock zone color

https://emacs-china.org/t/org-agenda/8679

(defun my:org-agenda-time-grid-spacing ()
  "Set different line spacing w.r.t. time duration."
  (save-excursion
    (let* ((background (alist-get 'background-mode (frame-parameters)))
           (background-dark-p (string= background "dark"))
           (colors (if background-dark-p
                       (list "#aa557f" "DarkGreen" "DarkSlateGray" "DarkSlateBlue")
                     (list "#F6B1C3" "#FFFF9D" "#BEEB9F" "#ADD5F7")))
           pos
           duration)
      (nconc colors colors)
      (goto-char (point-min))
      (while (setq pos (next-single-property-change (point) 'duration))
        (goto-char pos)
        (when (and (not (equal pos (point-at-eol)))
                   (setq duration (org-get-at-bol 'duration)))
          (let ((line-height (if (< duration 30) 1.0 (+ 0.5 (/ duration 60))))
                (ov (make-overlay (point-at-bol) (1+ (point-at-eol)))))
            (overlay-put ov 'face `(:background ,(car colors)
                                                :foreground
                                                ,(if background-dark-p "black" "white")))
            (setq colors (cdr colors))
            (overlay-put ov 'line-height line-height)
            (overlay-put ov 'line-spacing (1- line-height))))))))

(add-hook 'org-agenda-finalize-hook #'my:org-agenda-time-grid-spacing)

Org babel

Unset org-babel-execute-buffer keybinding because I thought its dangerous.

(define-key helm-org-rifle-occur-map "\C-c\C-v\C-b" nil)
(define-key helm-org-rifle-occur-map "\C-c\C-vb" nil)
(define-key org-babel-map "\C-b" nil)
(define-key org-babel-map "b" nil)
(define-key org-mode-map "\C-c\C-v\C-b" nil)
(define-key org-mode-map "\C-c\C-vb" nil)

Org debug

;; debug
(defun tru/tt-parse-buff ()
  "2019-01-14"
  (interactive)
  (let ((tt (org-element-parse-buffer )))
    (with-output-to-temp-buffer "*xah temp out*"
      (print tt))))

(defun tru/tt-headline ()
  "2019-01-14"
  (interactive)
  (let ((tt (org-element-parse-buffer 'headline )))
    (with-output-to-temp-buffer "*xah temp out*"
      (print tt))))

Org table valign

https://emacs-china.org/t/org-mode/13248

(use-package! valign)

Org-roam

(setq org-roam-directory "/Users/tru/Dropbox/Org/org-roam/")
(defun tru/org-roam-node-find-by-tag ()
  (interactive)
    (let ((chosen-tag
    (completing-read "filter by tag: "
       (seq-uniq
        (org-roam-db-query
         [:select [tag]
           :from tags ])))))
      (org-roam-node-find
       nil
       nil
       (lambda (node) (member chosen-tag (org-roam-node-tags node))))))
(setq org-roam-capture-templates
      '(
        ("w" "workstuff" plain (file "/Users/tru/Dropbox/Org/org-roam/templates/workstuff.org")
         :target (file+head "work/%<%Y%m%d%H%M%S>-${slug}.org"
                            "#+title: ${title}\n") :unnarrowed t)
        ("r" "research" plain (file "/Users/tru/Dropbox/Org/org-roam/templates/research.org")
         :target (file+head "study/%<%Y%m%d%H%M%S>-${slug}.org"
                            "#+title: ${title}\n") :unnarrowed t)
        )
)

org-roam-ui

(use-package! websocket
    :after org-roam)

(use-package! org-roam-ui
    :after org-roam ;; or :after org
;;         normally we'd recommend hooking orui after org-roam, but since org-roam does not have
;;         a hookable mode anymore, you're advised to pick something yourself
;;         if you don't care about startup time, use
;;  :hook (after-init . org-roam-ui-mode)
    :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 t))

Org-mouse

(after! org
  (setq org-modules
        (append '(
                  org-mouse
                  )org-modules)))

Org display a single inline image

Display a single inline image : orgmode

;;(defun org-display-inline-images (&optional include-linked refresh beg end))

Org presentation

https://github.com/daviwil/dotfiles/blob/master/Emacs.org#presentations

(defun dw/org-start-presentation ()
  (interactive)
  (org-tree-slide-mode 1)
  (setq text-scale-mode-amount 1)
  (text-scale-mode 1)
  (global-tab-line-mode 0)
  (tab-bar-mode 0))

(defun dw/org-end-presentation ()
  (interactive)
  (text-scale-mode 0)
  (org-tree-slide-mode 0)
  (global-tab-line-mode 1)
  (tab-bar-mode 1))

(use-package! org-tree-slide
  :after org
  :functions (org-display-inline-images
              org-remove-inline-images)
  :bind (:map org-mode-map
         ("<f8>" . dw/org-start-presentation)
         :map org-tree-slide-mode-map
         ("C-q" . dw/org-end-presentation)
         ("<right>" . org-tree-slide-move-next-tree)
         ("<left>" . org-tree-slide-move-previous-tree))
  :config
  (setq org-tree-slide-slide-in-effect nil
        org-tree-slide-activate-message "Presentation started."
        org-tree-slide-deactivate-message "Presentation ended."
        org-tree-slide-header t
        org-tree-slide-fold-subtrees-skipped nil
        org-tree-slide-cursor-init nil))
(defun dw/org-present-prepare-slide ()
  (org-overview)
  ;; (org-show-entry)
  ;; (org-show-children)
  )

(defun dw/org-present-hook ()
  (setq header-line-format " ")
  (org-display-inline-images)
  (dw/org-present-prepare-slide))

(defun dw/org-present-quit-hook ()
  (setq header-line-format nil)
  (org-present-small)
  (org-remove-inline-images))

(defun dw/org-present-prev ()
  (interactive)
  (org-present-prev)
  (dw/org-present-prepare-slide))

(defun dw/org-present-next ()
  (interactive)
  (org-present-next)
  (dw/org-present-prepare-slide))

(use-package! org-present
  :bind (:map org-present-mode-keymap
         ("C-c C-j" . dw/org-present-next)
         ("C-c C-k" . dw/org-present-prev))
  :hook ((org-present-mode . dw/org-present-hook)
         (org-present-mode-quit . dw/org-present-quit-hook)))

Auto babel tangle

(after! org
  (add-hook 'after-save-hook (lambda ()(org-babel-tangle)) nil t))

Org-toggle-emphasis

https://stackoverflow.com/questions/10969617/hiding-markup-elements-in-org-mode

(defun tru/org-toggle-emphasis ()
  "Toggle hiding/showing of org emphasize markers."
  (interactive)
  (if org-hide-emphasis-markers
      (set-variable 'org-hide-emphasis-markers nil)
    (set-variable 'org-hide-emphasis-markers t))
  (org-mode-restart))

org-bars

(use-package! org-bars)
;; (after! org
;;   (add-hook 'org-mode-hook #'org-bars-mode))

org-mac-link

(when IS-MAC
  (use-package! org-mac-link
    :after org
    :config
    (setq org-mac-grab-Acrobat-app-p nil) ; Disable grabbing from Adobe Acrobat
    (setq org-mac-grab-devonthink-app-p nil) ; Disable grabbinb from DevonThink
    (map! :map org-mode-map          "C-c g"  #'org-mac-link-link)))

Denote

protesilaos/denote: Simple notes for Emacs with an efficient file-naming scheme (we are close to the first stable release)

;; (use-package! denote
;;   :config
;;   (add-hook 'find-file-hook #'denote-link-buttonize-buffer)

;;   ;; Remember to check the doc strings of those variables.
;;   (setq denote-directory (expand-file-name "~/Dropbox/Org/denote/note"))
;;   (setq denote-known-keywords
;;         '("emacs" "research" "work" "todo"))
;;   (setq denote-infer-keywords t)
;;   (setq denote-sort-keywords t)
;;   (setq denote-file-type nil) ; Org is the default, set others here

;;   ;; We allow multi-word keywords by default.  The author's personal
;;   ;; preference is for single-word keywords for a more rigid workflow.
;;   (setq denote-allow-multi-word-keywords t)
;;   (setq denote-front-matter-date-format nil) ; change this to `org-timestamp' or custom string

;;   (defun my-denote-markdown-toml ()
;;     "Create Markdown+TOML note in ~/Documents/blog/."
;;     (interactive)
;;     (let ((denote-file-type 'markdown-toml)
;;           (denote-directory "~/Dropbox/Org/denote/note"))
;;       (call-interactively #'denote)))

;;   (defun my-denote-work ()
;;     (interactive)
;;     (let ((denote-directory "~/Dropbox/Org/denote/work/"))
;;       (call-interactively #'denote)))

;;   (defun my-denote-research ()
;;     (interactive)
;;     (let ((denote-directory "~/Dropbox/Org/denote/research/"))
;;       (call-interactively #'denote)))

;;   (defun my-denote-journal ()
;;     "Create an entry tagged 'journal', while prompting for a title."
;;     (interactive)
;;     (let ((denote-file-type 'org) ; it supports other file types as well: read its doc string
;;           (denote-directory "~/Dropbox/Org/denote/journal/"))
;;       (denote
;;        (denote--title-prompt)
;;        "journal"))
;;     )
;; )
;; Denote does not define any key bindings.  This is for the user to
;; decide.  For example:
;; (let ((map global-map))
;;   (define-key map (kbd "C-c n e j") #'my-denote-journal) ; our custom command
;;   (define-key map (kbd "C-c n e n") #'denote)
;;   (define-key map (kbd "C-c n e N") #'denote-type)
;;   (define-key map (kbd "C-c n e d") #'denote-date)
;;   ;; If you intend to use Denote with a variety of file types, it is
;;   ;; easier to bind the link-related commands to the `global-map', as
;;   ;; shown here.  Otherwise follow the same pattern for `org-mode-map',
;;   ;; `markdown-mode-map', and/or `text-mode-map'.
;;   (define-key map (kbd "C-c n e i") #'denote-link) ; "insert" mnemonic
;;   (define-key map (kbd "C-c n e I") #'denote-link-add-links)
;;   (define-key map (kbd "C-c n e l") #'denote-link-find-file) ; "list" links
;;   (define-key map (kbd "C-c n e b") #'denote-link-backlinks)
;;   ;; Note that `denote-dired-rename-file' can work from any context, not
;;   ;; just Dired bufffers.  That is why we bind it here to the
;;   ;; `global-map'.
;;   (define-key map (kbd "C-c n e r") #'denote-dired-rename-file))

;; (with-eval-after-load 'org-capture
;;   (require 'denote-org-capture)
;;   (setq denote-org-capture-specifiers "%l\n%i\n%?")
;;   (add-to-list 'org-capture-templates
;;                '("n" "New note (with denote.el)" plain
;;                  (file denote-last-path)
;;                  #'denote-org-capture
;;                  :no-save t
;;                  :immediate-finish nil
;;                  :kill-buffer t
;;                  :jump-to-captured t)))
;; (defvar prot-search--grep-hist '()
;;   "Input history of grep searches.")

;; ;;;###autoload
;; (defun prot-search-grep (regexp &optional recursive)
;;   "Run grep for REGEXP.

;; Search in the current directory using `lgrep'.  With optional
;; prefix argument (\\[universal-argument]) for RECURSIVE, run a
;; search starting from the current directory with `rgrep'."
;;   (interactive
;;    (list
;;     (read-from-minibuffer (concat (if current-prefix-arg
;;                                       (propertize "Recursive" 'face 'warning)
;;                                     "Local")
;;                                   " grep for PATTERN: ")
;;                           nil nil nil 'prot-search--grep-hist)
;;     current-prefix-arg))
;;   (unless grep-command
;;     (grep-compute-defaults))
;;   (if recursive
;;       (rgrep regexp "*" default-directory)
;;     (lgrep regexp "*" default-directory)))

Email

mu4e

;; (require 'mu4e-contrib)
;; (setq mu4e-html2text-command 'mu4e-shr2text)
;; (setq mu4e-html2text-command "iconv -c -t utf-8 | pandoc -f html -t plain")
;; (add-to-list 'mu4e-view-actions '("ViewInBrowser" . mu4e-action-view-in-browser) t)

notmuch

(defun get-string-from-file (filePath)
  "Return filePath's file content."
  (with-temp-buffer
    (insert-file-contents filePath)
    (buffer-string)))

(fset '+notmuch-view-in-mailapp
   (kmacro-lambda-form [?\M-x ?n ?o ?t ?m ?u ?c ?h ?- ?s ?h ?o ?w ?- ?s ?t ?a ?s ?h ?- ?m ?e ?s ?s ?a ?g ?e ?- ?i ?d ?- ?s ?t ?r ?\C-m ?\C-\[ ?! ?o ?p ?e ?n ?  ?m ?e ?s ?s ?a ?g ?e ?: ?/ ?/ ?% ?3 ?C ?\C-y ?% ?3 ?E ?\C-  ?\C-a ?\M-w ?\C-m] 0 "%d"))

(fset '+notmuch-view-in-gmail
   (kmacro-lambda-form [?c ?F ?\M-x ?u ?r ?l ?m ?a ?c ?o ?s ?x return ?j ?j ?\C-  ?\C-a ?\C-d ?\C-y ?j ?j ?j ?\C-\M-b ?\C-\M-b ?\C-\M-b ?\C-\M-f ?\M-b ?\C-  ?\C-a ?\C-d ?\M-f ?\C-k ?\C-a ?h ?t ?t ?p ?s ?: ?/ ?/ ?m ?a ?i ?l ?. ?g ?o ?o ?g ?l ?e ?. ?c ?o ?m ?/ ?m ?a ?i ?l ?? ?# ?a ?l ?l ?/ ?\C-e return] 0 "%d"))
;(mm-display-parts (mm-dissect-buffer))
;; workaround multi database
(when (string-match "work" (get-string-from-file "/Users/tru/Dropbox/Apps/org-agenda/.git/HEAD"))
  (setenv "NOTMUCH_CONFIG" "/Users/tru/Dropbox/Apps/emacs/tru/notmuchmail/ubiquiti/notmuch.conf")
  (setq +notmuch-mail-folder "~/Dropbox/Apps/emacs/tru/notmuchmail/ubiquiti"))
(when (string-match "life" (get-string-from-file "/Users/tru/Dropbox/Apps/org-agenda/.git/HEAD"))
  (setenv "NOTMUCH_CONFIG" "/Users/tru/Dropbox/Apps/emacs/tru/notmuchmail/tru.zhou/notmuch.conf")
  (setq +notmuch-mail-folder "~/Dropbox/Apps/emacs/tru/notmuchmail/tru.zhou"))

(after! notmuch
  (setq mm-text-html-renderer 'w3m)
  (setq w3m-fill-column 72)
  (setq w3m-default-display-inline-images t)
  (setq notmuch-message-headers-visible t)
  (setq notmuch-saved-searches
        '((:name "inbox"      :query "tag:inbox"                    :count-query "tag:inbox and tag:unread"                    :key "i")
          (:name "personal"   :query "tag:inbox and tag:personal"   :count-query "tag:inbox and tag:unread and tag:personal"   :key "p")
          (:name "social"     :query "tag:inbox and tag:social"     :count-query "tag:inbox and tag:unread and tag:social"     :key "o")
          (:name "promotions" :query "tag:inbox and tag:promotions" :count-query "tag:inbox and tag:unread and tag:promotions" :key "r")
          (:name "updates"    :query "tag:inbox and tag:updates"    :count-query "tag:inbox and tag:unread and tag:updates"    :key "u")
          (:name "forums"     :query "tag:inbox and tag:forums"     :count-query "tag:inbox and tag:unread and tag:forums"     :key "f")

          (:name "flagged" :query "tag:flagged" :key "s")
          (:name "sent"    :query "tag:sent"    :key "e")
          (:name "drafts"  :query "tag:draft"   :key "d")))
  (defun =notmuch ()
    "Activate (or switch to) `notmuch' in its workspace."
    (interactive)

    ;; workaround multi database
    (when (string-match "work" (get-string-from-file "/Users/tru/Dropbox/Apps/org-agenda/.git/HEAD"))
      (setenv "NOTMUCH_CONFIG" "/Users/tru/Dropbox/Apps/emacs/tru/notmuchmail/ubiquiti/notmuch.conf")
      (setq +notmuch-mail-folder "~/Dropbox/Apps/emacs/tru/notmuchmail/ubiquiti"))
    (when (string-match "life" (get-string-from-file "/Users/tru/Dropbox/Apps/org-agenda/.git/HEAD"))
      (setenv "NOTMUCH_CONFIG" "/Users/tru/Dropbox/Apps/emacs/tru/notmuchmail/tru.zhou/notmuch.conf")
      (setq +notmuch-mail-folder "~/Dropbox/Apps/emacs/tru/notmuchmail/tru.zhou"))
    (unless (featurep! :ui workspaces)
      (user-error ":ui workspaces is required, but disabled"))
    (condition-case-unless-debug e
        (progn
          (+workspace-switch "*MAIL*" t)
          (if-let* ((buf (cl-find-if (lambda (it) (string-match-p "^\\*notmuch" (buffer-name (window-buffer it))))
                                     (doom-visible-windows))))
              (select-window (get-buffer-window buf))
            (notmuch-search "tag:inbox and tag:unread"))
          (+workspace/display))
      ('error
       (+notmuch/quit)
       (signal (car e) (cdr e)))))

  (define-key notmuch-show-mode-map (kbd ". m") #'+notmuch-view-in-mailapp)
  (define-key notmuch-show-mode-map (kbd ". g") #'+notmuch-view-in-gmail)

  (defun tru/notmuch/update ()
    (interactive)
    ;; create output buffer and jump to beginning
    (let ((buf (get-buffer-create "*notmuch update*")))
      (with-current-buffer buf
        (erase-buffer))
      (pop-to-buffer buf nil t)
      (set-process-sentinel
       (start-process-shell-command
        "notmuch update" buf
        (pcase +notmuch-sync-backend
          (`gmi
           ;&& export DYLD_FALLBACK_LIBRARY_PATH=/opt/homebrew/lib/
           (setenv "DYLD_FALLBACK_LIBRARY_PATH" "")
           (concat "cd " +notmuch-mail-folder " && export DYLD_FALLBACK_LIBRARY_PATH=/opt/homebrew/lib:/usr/local/lib/ && gmi sync && gmi sync"))
          (`custom +notmuch-sync-command)))
       ;; refresh notmuch buffers if sync was successful
       (lambda (_process event)
         (if (string= event "finished\n")
             (notmuch-refresh-all-buffers))))))

  (map! :localleader
        :map (notmuch-search-mode-map notmuch-tree-mode-map notmuch-show-mode-map)
        ;; :desc "Compose email"   "c" #'+notmuch/compose
        :desc "Sync email" "u" #'tru/notmuch/update
        ;; :desc "Quit notmuch"    "q" #'+notmuch/quit
        ;; :map notmuch-search-mode-map
        ;; :desc "Mark as deleted" "d" #'+notmuch/search-delete
        ;; :desc "Mark as spam"    "s" #'+notmuch/search-spam
        ;; :map notmuch-tree-mode-map
        ;; :desc "Mark as deleted" "d" #'+notmuch/tree-delete
        ;; :desc "Mark as spam"    "s" #'+notmuch/tree-spam
        )
  )
;; (use-package! notmuch-labeler
;;   :commands notmuch-labeler-rename
;;   :after notmuch
;;   :defer nil
;;   :config
;;   (notmuch-labeler-rename "unread" "new" ':foreground "blue"))

;; Inline images?
(setq mm-attachment-override-types '("image/.*"))
;; Or, like this:
(add-to-list 'mm-attachment-override-types "image/.*")
(setq w3m-default-display-inline-images t)

(defun notmuch-view-html ()
  "Open the HTML parts of a mail in a web browser."
  (interactive)
  (with-current-notmuch-show-message
   (let ((mm-handle (mm-dissect-buffer)))
     (notmuch-foreach-mime-part
      (lambda (p)
        (if (string-equal (mm-handle-media-type p) "text/html")
            (mm-display-external p (lambda ()
                                     (message "Opening web browser...")
                                     (browse-url-of-buffer)
                                     (bury-buffer)))))
      mm-handle))))
(defun tru/notmuch-show-toggle-message ()
  (interactive)
  (let ((url (thing-at-point 'url 'no-properties)))
    (if url
      (goto-address-at-point)
      (notmuch-show-toggle-message))))

Deft

(setq deft-directory "~/Dropbox/Org"
      deft-extensions '("txt" "org")
      deft-recursive t)

Display ansi color

(defun tru/display-ansi-colors ()
  (interactive)
  (let ((inhibit-read-only t))
    (ansi-color-apply-on-region (point-min) (point-max))))

CANCELLED recentf

  • State “CANCELLED” from [2020-02-26 Wed 03:48]
;; (add-hook 'after-init-hook 'recentf-mode)
;; (setq-default
;;  recentf-max-saved-items 1000
;;  recentf-exclude '("/tmp/" "/ssh:"))

defhydra

multiple-cursors

(defhydra hydra-multiple-cursors (:hint nil)
  "
 Up^^             Down^^           Miscellaneous           % 2(mc/num-cursors) cursor%s(if (> (mc/num-cursors) 1) \"s\" \"\")
------------------------------------------------------------------
 [_p_]   Next     [_n_]   Next     [_l_] Edit lines  [_0_] Insert numbers
 [_P_]   Skip     [_N_]   Skip     [_a_] Mark all    [_A_] Insert letters
 [_M-p_] Unmark   [_M-n_] Unmark   [_s_] Search
 [Click] Cursor at point       [_q_] Quit"
  ("l" mc/edit-lines :exit t)
  ("a" mc/mark-all-like-this :exit t)
  ("n" mc/mark-next-like-this)
  ("N" mc/skip-to-next-like-this)
  ("M-n" mc/unmark-next-like-this)
  ("p" mc/mark-previous-like-this)
  ("P" mc/skip-to-previous-like-this)
  ("M-p" mc/unmark-previous-like-this)
  ("s" mc/mark-all-in-region-regexp :exit t)
  ("0" mc/insert-numbers :exit t)
  ("A" mc/insert-letters :exit t)
  ("<mouse-1>" mc/add-cursor-on-click)
  ;; Help with click recognition in this hydra
  ("<down-mouse-1>" ignore)
  ("<drag-mouse-1>" ignore)
  ("q" nil))

vterm

(after! vterm
   (define-key vterm-mode-map (kbd "M-v")                #'vterm-yank)
   ;;(define-key vterm-mode-map [remap whole-line-or-region-yank]                #'vterm-yank)
   (define-key vterm-mode-map (kbd "C-h") nil)
   (define-key vterm-mode-map (kbd "C-h") #'vterm-send-C-h)
   (setq vterm-max-scrollback 20000)
)

Auto-Correct Words

void-function ispell-get-word

http://endlessparentheses.com/ispell-and-abbrev-the-perfect-auto-correct.html https://www.youtube.com/watch?v=fhI_riv_6HM

brew install ispell

(setq ispell-program-name "/opt/homebrew/bin/ispell")

(define-key ctl-x-map "\C-i"
  #'endless/ispell-word-then-abbrev)

(defun endless/simple-get-word ()
  (car-safe (save-excursion (ispell-get-word nil))))

(defun endless/ispell-word-then-abbrev (p)
  "Call `ispell-word', then create an abbrev for it.
With prefix P, create local abbrev. Otherwise it will
be global.
If there's nothing wrong with the word at point, keep
looking for a typo until the beginning of buffer. You can
skip typos you don't want to fix with `SPC', and you can
abort completely with `C-g'."
  (interactive "P")
  (let (bef aft)
    (save-excursion
      (while (if (setq bef (endless/simple-get-word))
                 ;; Word was corrected or used quit.
                 (if (ispell-word nil 'quiet)
                     nil ; End the loop.
                   ;; Also end if we reach `bob'.
                   (not (bobp)))
               ;; If there's no word at point, keep looking
               ;; until `bob'.
               (not (bobp)))
        (backward-word)
        (backward-char))
      (setq aft (endless/simple-get-word)))
    (if (and aft bef (not (equal aft bef)))
        (let ((aft (downcase aft))
              (bef (downcase bef)))
          (define-abbrev
            (if p local-abbrev-table global-abbrev-table)
            bef aft)
          (message "\"%s\" now expands to \"%s\" %sally"
                   bef aft (if p "loc" "glob")))
      (user-error "No typo at or before point"))))

(setq save-abbrevs 'silently)
(setq-default abbrev-mode t)

Easy-hugo

(use-package! easy-hugo
  :init
  ;; Main blog
  (setq easy-hugo-basedir "~/Dropbox/git/github/hugo-blog/")
  (setq easy-hugo-url "https://tru2dagame.github.io")
  (setq easy-hugo-previewtime "300")
  ;; (define-key global-map (kbd "C-c C-e") 'easy-hugo)

  (setq easy-hugo-bloglist
        ;; blog2 setting
        '(((easy-hugo-basedir . "/Users/tru/Dropbox/git/src/git.ubnt.com.cn/ubnt-hugo-blog/blog-ui/")
           (easy-hugo-url . "http://blog.stg.ui.com.cn")
           )
          ;; blog5 for github pages
          ((easy-hugo-basedir . "~/Dropbox/git/src/github.com/Ubiquiti-UID/uid.manual/")
           (easy-hugo-url . "https://developer.uid.ui.com")
           (easy-hugo-postdir . "~/Dropbox/git/src/github.com/Ubiquiti-UID/uid.manual/content/UID"))
          ;; ;; blog6 for firebase hosting
          ;; ((easy-hugo-basedir . "~/src/github.com/masasam/firebase/")
          ;;  (easy-hugo-url . "https://yourproject.firebaseapp.com"))

          ))
  ;:bind ("C-c C-e" . easy-hugo)
  )
(define-key global-map "\C-c \C-e" nil)
(define-key mode-specific-map "\C-e" nil)

Git auto commit

(use-package! git-auto-commit-mode
  :config
  ;;(setq shell-command-prompt-show-cwd t)
  (setq-default gac-automatically-push-p t)
  (setq-default gac-debounce-interval 120)
)

Server mode

(use-package! server
  :hook (after-init . server-mode))

Edit server

https://chrome.google.com/webstore/detail/edit-with-emacs/ljobjlafonikaiipfkggjbhkghgicgoh

(use-package! edit-server
  :config
  (edit-server-start)
  (setq edit-server-default-major-mode 'markdown-mode)
  (setq edit-server-new-frame nil)
)

Chinese

(use-package! pinyinlib
  :config

  (defun re-builder-extended-pattern (str)
    (let* ((len (length str)))
      (cond
       ;; do nothing
       ((<= (length str) 0))

       ;; If the first charater of input in ivy is ":",
       ;; remaining input is converted into Chinese pinyin regex.
       ((string= (substring str 0 1) ":")
        (setq str (pinyinlib-build-regexp-string (substring str 1 len) t)))

       ;; If the first charater of input in ivy is "/",
       ;; remaining input is converted to pattrn to search camel case word
       ((string= (substring str 0 1) "/")
        (let* ((rlt "")
               (i 0)
               (subs (substring str 1 len))
               c)
          (when (> len 2)
            (setq subs (upcase subs))
            (while (< i (length subs))
              (setq c (elt subs i))
              (setq rlt (concat rlt (cond
                                     ((and (< c ?a) (> c ?z) (< c ?A) (> c ?Z))
                                      (format "%c" c))
                                     (t
                                      (concat (if (= i 0) (format "[%c%c]" (+ c 32) c)
                                                (format "%c" c))
                                              "[a-z]+")))))
              (setq i (1+ i))))
          (setq str rlt))))
      (ivy--regex-plus str))))
(use-package! pinyin-search)
(use-package! youdao-dictionary
  :config
  (setq url-automatic-caching t)
  ;; Example Key binding
  (global-set-key (kbd "C-c y") 'youdao-dictionary-search-at-point)
)

macOS open iTerm in current directory

(defun my/iterm-goto-filedir-or-home ()
  "Go to present working dir and focus iterm"
  (interactive)
  (do-applescript
   " do shell script \"open -a iTerm\"\n"
   )
  (do-applescript
   (concat
    " tell application \"iTerm\"\n"
    "   tell the current session of current window\n"
    (format "     write text \"cd %s\" \n"
            ;; string escaping madness for applescript
            (replace-regexp-in-string "\\\\" "\\\\\\\\"
                                      (shell-quote-argument (or default-directory "~"))))
    "   end tell\n"
    " end tell\n"
    " do shell script \"open -a iTerm\"\n"
    ))
  )

Macros

src-example add html details

(fset 'tru/details-src-example
   [?\C-s ?# ?+ ?b ?e ?g ?i ?n ?_ ?e ?x ?a ?m ?p ?l ?e ?\C-a ?\C-o ?\C-c ?\C-, ?h ?\C-o ?< ?> ?\C-b ?d ?e ?t ?a ?i ?l ?s ?\C-e ?R ?e ?s ?u ?l ?t ?s ?: ?\C-s ?# ?+ ?e ?n ?d ?_ ?e ?x ?a ?m ?p ?l ?e ?\C-a ?\C-e ?\C-m ?\C-c ?\C-, ?h ?\C-o ?< ?> ?\C-b ?/ ?d ?e ?t ?a ?i ?l ?s ?\C-a ?\C-o ?< ?> ?\C-b ?h ?r ?  ?\C-? ?\C-n ?\C-e ?< ?> ?\C-b ?b ?r ?\C-n])
(fset 'tru/details-src-code
   [?\C-s ?# ?+ ?b ?e ?g ?i ?n ?_ ?s ?r ?c ?\C-a ?\M-f ?\M-f ?\C-a ?\C-o ?\C-c ?\C-, ?h ?\C-o ?< ?> ?\C-b ?d ?e ?t ?a ?i ?l ?s ?\C-e ?R ?e ?s ?u ?l ?t ?s ?: ?\C-s ?# ?+ ?e ?n ?d ?_ ?s ?r ?c ?\C-a ?\C-e ?\C-m ?\C-c ?\C-, ?h ?\C-o ?< ?> ?\C-b ?/ ?d ?e ?t ?a ?i ?l ?s ?\C-a ?\C-o ?< ?> ?\C-b ?h ?r ?  ?\C-? ?\C-n ?\C-e ?< ?> ?\C-b ?b ?r ?\C-n])

Magit

magit-status-here

(global-set-key (kbd "C-x g") 'magit-status-here)

magit-gitflow

(setq magit-gitflow-popup-key "C-c m f")

magit forge

(after! forge
  (add-to-list 'forge-alist '("git.ubnt.com.cn" "git.ubnt.com.cn/api/v4" "git.ubnt.com.cn" forge-gitlab-repository))
  (add-to-list 'forge-alist '("git.uidev.tools" "git.uidev.tools/api/v3" "git.uidev.tools" forge-github-repository))
                                        ;(setq auth-sources '((:source "~/.authinfo")))
  (setq ghub-use-workaround-for-emacs-bug nil)
                                        ;(setq ghub-use-workaround-for-emacs-bug 'force)
  (setq gitlab.user "tru")
  (setq gitlab.host "git.ubnt.com.cn")
  )

;; (use-package! ghub)
;; (use-package! forge
;;   :after magit
;;   :config
;;   (add-to-list 'forge-alist '("git.ubnt.com.cn" "git.ubnt.com.cn/api/v4" "git.ubnt.com.cn" forge-gitlab-repository))
;;   (add-to-list 'forge-alist '("git.uidev.tools" "git.uidev.tools/api/v3" "git.uidev.tools" forge-github-repository))
;;   (setq auth-sources '((:source "~/.authinfo")))
;  (setq gitlab.user "tru")
;  (setq gitlab.host "gitlab.git.ubnt.com.cn")

  (setq ghub-use-workaround-for-emacs-bug nil) ;; fixies an issue where are workaround breaks gitlab
  ;; https://github.com/magit/forge/issues/140
  ;; (setq forge-topic-list-columns ;; get more details in the list of topics
  ;;       '(("#" 5
  ;;          (lambda (a b)
  ;;            (> (car a) (car b)))
  ;;          (:right-align t) number nil)
  ;;         ("Title" 35 t nil title  nil)
  ;;         ("Milestone" 4 t nil milestone nil)
  ;;         ("State" 4 t nil state nil)
  ;;         ("Updated" 10 t nill updated nil)
  ;;         ))
  (defun forge-create-secret-auth ()
    "Prompts for and creates the git forge secret. Mostly for gitlab."
    (interactive)
    (let*
        (
         (repo (forge-get-repository 'full))
         (host (oref repo apihost))
         (username (ghub--username host  'gitlab))
         (user (concat username "^forge"))
         token
         )
      (setq token (read-passwd (format "Enter your token for %s @ %s: " username host)))
      (ghub-clear-caches)
      (auth-source-forget-all-cached)
      (secrets-create-item
       "Login" (format "%s @ %s" user host)
       token
       :host host
       :user user
       )
      )
    )
;  )

git blamer

https://github.com/Artawower/blamer.el

(use-package blamer
  :defer 20
  :custom
  (blamer-idle-time 1.5)
  (blamer-min-offset 50)
  (blamer-type 'both)
  (blamer-max-lines 10)
  (blamer-author-formatter " ✎ %s ")
  (blamer-datetime-formatter "[%s]")
  (blamer-commit-formatter "● %s")
  :custom-face
  (blamer-face ((t :foreground "#7a88cf"
                   :background nil
                   ;; :height 140
                   :italic t
                    )))
  :config
  (global-blamer-mode 0))

silicon-el

https://github.com/iensu/silicon-el

(use-package! silicon)

HOLD screenshot

tecosaur/screenshot#13 ERROR: insert: Symbol’s function definition is void: x-export-frames

(use-package! screenshot)
(load-file (locate-library "screenshot.el"))

HOLD Graphql

(use-package! graphql-mode)
(use-package! ob-graphql)
(use-package! company-graphql
 :config
 (add-to-list 'company-backends 'company-graphql))

WAIT EAF emacs-application-framework

(use-package! eaf
  :load-path "/Users/tru/Dropbox/git/src/github.com/manateelazycat/emacs-application-framework"
  :init
  (use-package! epc :defer t)
  (use-package! ctable :defer t)
  (use-package! deferred :defer t)
  (use-package! s :defer t)
  :custom
  (eaf-browser-continue-where-left-off t)
  :config
  (eaf-setq eaf-browser-enable-adblocker "true")
  (eaf-bind-key scroll_up "C-n" eaf-pdf-viewer-keybinding)
  (eaf-bind-key scroll_down "C-p" eaf-pdf-viewer-keybinding)
  (eaf-bind-key take_photo "p" eaf-camera-keybinding)
  (eaf-bind-key nil "M-q" eaf-browser-keybinding)) ;; unbind, see more in the Wiki