README

Sorry, your browser does not support SVG.

1 Introduction

This Emacs configuration file is written in literate programming method.1 The elisp file is extracted from this file, and then compiled to binary elc file for fast loading in the future.

2 Installation

First of all, you should get and install emacs.

2.1 Windows/Cygwin

Cygwin project2 is required for this configuration in Windows, which is a large collection of GNU and Open Source tools provide functionality similar to a Linux distribution on Windows.

In order to make life easier, we will use apt-cyg 3 to install emacs and other tools. Let's download apt-cyg and install emacs and git:

curl https://raw.githubusercontent.com/transcode-open/apt-cyg/master/apt-cyg > /usr/local/bin/apt-cyg
chmod +x /usr/local/bin/apt-cyg
apt-cyg install emacs-w32 git

Then start emacs from terminal, and right click the emacs to pin it to taskbar, and click the property of this icon to add C:\cygwin64\bin\run.exe emacs in the target field. This way will hide the black terminal.

2.2 macOS

For Apple macOS, most UNIX tools are installed already. Homebrew 4 is used to install additional application if it is missing.

/bin/bash -c \
"$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"

2.3 Linux

Most of the external tools I used in this Emacs configuration should be easily installed or already available in main Linux distributions.

3 Preparation

3.1 Install fonts

Because Incosolata font is really great for programming, and Microsoft Yahei is nice font to view Chinese characters, you'd better download and install these two fonts from:

3.2 Get emacs config

To use of this configuration, you can follow below shell commands to prepare the emacs configuration files and folders:

  • back up .emacs file and .emacs.d folder, if you have your own emacs configuration files
  • clone kimim-emacs to home folder ~
  • copy .emacs from kimim-emacs to ~
  cd ~ && mv .emacs .emacs-backup && mv .emacs.d .emacs.d-backup && \
  git clone https://github.com/kimim/kimim-emacs && \
  cp kimim-emacs/.emacs ~

This emacs setting uses several path to keep different informations, you should specify in ~/.emacs:

  • kimim/path-sync is the root of sync folder
  • kimim/path-sync-emacs to sync emacs settings
  • kimim/path-org to sync todo list and journals
  • kimim/path-notes to sync notes
  • kimim/path-ref to keep reference documents
  • kimim/path-kimim-emacs where kimim-emacs you clone to

If these pathes are not set, emacs will report errors:

(mapc (lambda (path)
        (if (not (boundp path))
            (error (concat "please set " (symbol-name path) " in ~/.emacs"))))
      '(kimim/path-sync
        kimim/path-sync-emacs
        kimim/path-org
        kimim/path-notes
        kimim/path-ref
        kimim/path-kimim-emacs))

Then execute emacs to bootstrap itself.

4 Emacs Frame

Set look & feel before all other settings.

4.1 Menu Bar and Tool Bar

Show menu bar only in macOS desktop environment, because the system preserves menu bar for every applications.

(defun kimim/menu-and-bar ()
  (cond
   ((eq window-system 'w32)
    ;; Enable copy and paste in Win32
    (setq select-enable-clipboard t)
    (menu-bar-mode 0)
    (tool-bar-mode -1)
    (scroll-bar-mode -1))
   ((eq window-system 'ns)
    (menu-bar-mode 1)
    (tool-bar-mode -1)
    (scroll-bar-mode -1))
   ((eq window-system 'x)
    (menu-bar-mode 0)
    (tool-bar-mode -1)
    (scroll-bar-mode -1))
   ((eq window-system nil)
    (menu-bar-mode 0))))

(kimim/menu-and-bar)

4.2 Font and Frame Size

Set default font and frame size for both Windows and macOS. You should set-default-font first, otherwise, the frame height and width will be calculated with original default font height and width: frame-char-height and frame-char-width.

  ;; set default font and default frame dimension
  (defun kimim/frame-and-font ()
    (cond
     ((eq window-system 'w32)
      (cond
       ((< (display-pixel-width) 1400)
        (set-fontset-font
         "fontset-default"
         'unicode-bmp (font-spec :family "YaheiInconsolata"))
        (set-frame-font "Inconsolata-14"))
       ((> (display-pixel-width) 1400)
        (set-fontset-font
         "fontset-default"
         'unicode-bmp (font-spec :family "YaheiInconsolata"))
        (set-frame-font "Inconsolata-14"))))
     ((eq window-system 'ns)
      (set-fontset-font
       "fontset-default"
       'unicode-bmp (font-spec :family "YaheiInconsolata"))
      (set-frame-font "Inconsolata-18"))
     ((eq window-system 'x)
      (set-fontset-font
       "fontset-default"
       'unicode-bmp (font-spec :family "YaheiInconsolata"))
      (set-frame-font "Inconsolata-12")))
    (when window-system
      ;; top, left ... must be integer
      (add-to-list 'default-frame-alist
                   (cons 'top  (/ (x-display-pixel-height) 10)))
      (add-to-list 'default-frame-alist
                   (cons 'left (/ (x-display-pixel-width) 10)))
      (add-to-list 'default-frame-alist
                   (cons 'height (/ (* 4 (x-display-pixel-height))
                                    (* 5 (frame-char-height)))))
      (add-to-list 'default-frame-alist
                   (cons 'width (/ (* 4 (x-display-pixel-width))
                                   (* 5 (frame-char-width)))))))

  (kimim/frame-and-font)

5 Environment

5.1 PATH, exec-path and Info

Environment variable PATH is the the searching path of executables by the shell running in Emacs while exec-path is the search path of Emacs itself. So we should set both of them to almost the same paths.

As I have a Windows box in the office, and a Apple macOS at home, so I need to specify these variables in different way.

(cond
 ((eq system-type 'cygwin)
  (setq kimim/path-root "/"))
 ((eq system-type 'darwin)
  (setq kimim/path-root "/")
  (add-to-list 'exec-path "/Library/TeX/texbin")
  (add-to-list 'exec-path (concat (getenv "HOME") "/Library/Python/2.7/bin")))
 ((eq system-type 'gnu/linux)
  (setq kimim/path-root "/")
  (add-to-list 'exec-path "/usr/local/texlive/2020/bin/x86_64-linux/")))

(add-to-list 'exec-path (concat kimim/path-root "bin"))
(add-to-list 'exec-path (concat kimim/path-root "usr/bin"))
(add-to-list 'exec-path (concat kimim/path-root "usr/local/bin"))

Then append exec-path to PATH:

(setenv "PATH"
        (concat
         (mapconcat #'identity exec-path path-separator)
         (getenv "PATH")))

5.2 Language

(setenv "LANG" "en_US.UTF-8")
(setenv "LC_ALL" "en_US.UTF-8")
;; remove svn log LC_TYPE not defined warning.
(setenv "LC_CTYPE" "en_US")
(set-locale-environment "en_US.UTF-8")
(set-language-environment 'English)
(prefer-coding-system 'utf-8)
(set-buffer-file-coding-system 'utf-8)
(set-keyboard-coding-system 'utf-8)
(set-selection-coding-system 'utf-8)
(set-file-name-coding-system 'utf-8)
(set-terminal-coding-system 'utf-8)
(cond
 ((member system-type '(windows-nt cygwin))
  (set-clipboard-coding-system 'utf-16le))
 ((eq system-type 'gnu/linux)
  (set-clipboard-coding-system 'utf-8)))

5.3 global key map

Define new command prefix for keys such as "C-x m f", "C-x m v".

(define-prefix-command 'ctl-x-m-map)
(global-set-key "\C-xm" 'ctl-x-m-map)

6 Package

package 5 is the modern elisp package management system, which let you easily download and install packages that implement additional features. Each package is a separate Emacs Lisp program, sometimes including other components such as an Info manual.

All the extensions used in this file are installed and managed by package.

Here I use use-package to defer the package loading and even installation, When you use the :commands keyword, it creates autoloads for those commands and defers loading of the module until they are used.

(setq package-user-dir "~/.emacs.d/elpa")
(setq package-archives
      '(("gnu" . "http://mirrors.tuna.tsinghua.edu.cn/elpa/gnu/")
        ("melpa" . "http://mirrors.tuna.tsinghua.edu.cn/elpa/melpa/")
        ("org" . "http://mirrors.tuna.tsinghua.edu.cn/elpa/org/")))
(mapc
 (lambda (package)
   (unless (package-installed-p package)
     (progn (message "installing %s" package)
            (package-refresh-contents)
            (package-install package))))
 '(use-package diminish bind-key))

(require 'use-package)
(require 'diminish)
(require 'bind-key)
;; install package if missing
(setq use-package-always-ensure t)
(setq use-package-always-defer t)
(setq use-package-verbose t)

7 Title and Header

(setq frame-title-format
      '("" invocation-name ": "
        (:eval (if (buffer-file-name)
                   (abbreviate-file-name (buffer-file-name))
                 "%b"))))

(use-package path-headerline-mode
  :commands (path-headerline-mode)
  :config
  ;; only display headerline for real files
  (defun kimim/ph--display-header (orig-fun &rest args)
    (if (buffer-file-name)
        (apply orig-fun args)
      (setq header-line-format nil)))
  (advice-add 'ph--display-header :around #'kimim/ph--display-header))

8 Mode Line

Display time and (line, column) numbers in mode line.

(use-package time
  :defer 1
  :init
  (setq display-time-24hr-format t)
  (setq display-time-day-and-date t)
  (setq display-time-interval 10)
  :config
  (display-time-mode t))

(use-package simple
  :ensure nil
  :defer 3
  :config
  (line-number-mode 1)
  (column-number-mode 1))

9 Color Theme

(setq font-lock-maximum-decoration t)
(setq font-lock-global-modes '(not shell-mode text-mode))
(setq font-lock-verbose t)
(global-font-lock-mode 1)
(use-package kimim-light-theme
  :ensure nil
  :defer 0
  :load-path "~/kimim-emacs/site-lisp/"
  :config
  (load-theme 'kimim-night t))

10 Highlight

;; highlight current line
(use-package hl-line
  :defer 5
  :config
  (if window-system
      (global-hl-line-mode 1)))

;; highlight current symbol
(use-package auto-highlight-symbol
  :diminish auto-highlight-symbol-mode
  :bind ("C-x m e" . ahs-edit-mode)
  :config
  (global-auto-highlight-symbol-mode t))

11 Dealing with Unicode fonts

(use-package unicode-fonts
  :defer 3
  :config
  (defun unicode-fonts-setup-advice ()
    (if window-system
        (set-fontset-font
         "fontset-default"
         'cjk-misc (font-spec :family "YaheiInconsolata"))))
  (advice-add 'unicode-fonts-setup :after 'unicode-fonts-setup-advice)
  (defun kimim/add-font (group font)
    (let ((font-list (assoc group unicode-fonts-block-font-mapping)))
      (setf (cadr font-list) (cons font (cadr font-list)))))
  (seq-map (lambda (group) (kimim/add-font group "YaheiInconsolata"))
           '("Bopomofo" "Bopomofo Extended" "CJK Compatibility" "CJK Compatibility Forms"
             "CJK Compatibility Ideographs" "CJK Compatibility Ideographs Supplement"
             "CJK Radicals Supplement" "CJK Strokes" "CJK Symbols and Punctuation"
             "CJK Unified Ideographs" "CJK Unified Ideographs Extension A"
             "CJK Unified Ideographs Extension B" "CJK Unified Ideographs Extension C"
             "CJK Unified Ideographs Extension D" "CJK Unified Ideographs Extension E"
             "Enclosed Ideographic Supplement" "Halfwidth and Fullwidth Forms"
             "Hangul Compatibility Jamo" "Hangul Jamo" "Hangul Jamo Extended-A"
             "Hangul Jamo Extended-B" "Hangul Syllables" "Ideographic Description Characters"
             "IPA Extensions" "Mathematical Alphanumeric Symbols"))
  (seq-map (lambda (group) (kimim/add-font group "Consolas"))
           '("Combining Diacritical Marks" "Combining Half Marks" "Cyrillic"
             "Cyrillic Supplement" "Greek Extended" "Greek and Coptic" "Phonetic Extensions"
             "Phonetic Extensions Supplement" "Superscripts and Subscripts"))
  (add-to-list 'unicode-fonts-block-font-mapping
               '("Spacing Modifier Letters"
                 ("Consolas" "Monaco" "YaheiInconsolata")))
  (unicode-fonts-setup))

12 Other Visual Element

(setq inhibit-startup-message t)
(setq initial-scratch-message nil)
(setq visible-bell t)
(setq ring-bell-function #'ignore)
(fset 'yes-or-no-p 'y-or-n-p)
(show-paren-mode 1)
(setq blink-cursor-blinks 3)
(blink-cursor-mode 1)
(tooltip-mode nil)

13 Help

13.1 Info

(use-package info
  :commands (info)
  :config
  (add-to-list 'Info-additional-directory-list
               (concat kimim/path-root "usr/share/info"))
  (add-to-list 'Info-additional-directory-list
               (concat kimim/path-root "usr/local/share/info"))
  ;; additional info, collected from internet
  (add-to-list 'Info-additional-directory-list
               "~/info"))

13.2 tldr

TL;DR stands for "Too Long; Didn't Read"6. tldr.el 7 is the Emacs client.

(use-package tldr)

14 Controlling

14.1 Window and Frame

(use-package winner
  ;; restore windows configuration, built-in package
  :commands winner-mode
  :config
  (winner-mode t))

(use-package window-numbering
  :commands window-numbering-mode
  :config
  (window-numbering-mode 1))

(use-package frame
  :ensure nil
  :defer 1
  :bind ("C-x m w" . make-frame)
  :config
  (add-hook 'after-make-frame-functions
            (lambda (frame)
              (select-frame frame)
              (kimim/menu-and-bar)
              (kimim/frame-and-font))))

scroll slowly with touchpad.

  (setq mouse-wheel-scroll-amount '(0.01))

14.2 Command

;; https://github.com/justbur/emacs-which-key
(use-package which-key
  :defer 3
  :diminish which-key-mode
  :config
  ;; use minibuffer as the popup type, otherwise conflict in ecb mode
  (setq which-key-popup-type 'minibuffer)
  (which-key-mode 1))

;; smex will list the recent function on top of the cmd list
(use-package smex
  :commands (smex)
  :config
  (smex-initialize))

(use-package counsel
  :defer 1
  :bind
  (("M-x" . counsel-M-x)
   ("C-x C-f" . counsel-find-file)
   ("C-x m f" . counsel-describe-function)
   ("C-x m v" . counsel-describe-variable)
   ("C-x m l" . counsel-load-library)
   ("C-x m i" . counsel-info-lookup-symbol)
   ("C-x m j" . counsel-bookmark)
   ("C-x m r" . counsel-recentf)
   ("C-x m u" . counsel-unicode-char)
   ("C-c j" . counsel-git-grep)
   ("C-c g" . counsel-grep)
   ("C-x b" . counsel-ibuffer)
   ("C-c k" . counsel-ag)
   ("C-c p" . counsel-pt)
   ("C-x l" . counsel-locate)
   :map read-expression-map
   ("C-r" . counsel-minibuffer-history))
  :config
  (use-package ivy)
  (use-package smex)
  (add-hook 'counsel-grep-post-action-hook 'recenter)
  (ivy-mode 1))

14.3 Key Frequency

(use-package keyfreq
  :config
  (keyfreq-mode)
  (keyfreq-autosave-mode)
  (setq keyfreq-file "~/.emacs.d/emacs.keyfreq"))

15 Editing

15.1 General

(setq inhibit-eol-conversion nil)
;; fill-column is a buffer-local variable
;; use setq-default to change it globally
(setq-default fill-column 80)
(if window-system
    (setq-default fill-column
                  (min 80
                       (ceiling
                        (/ (x-display-pixel-width)
                           (frame-char-width)
                           2.3))))
  (setq-default fill-column 80))
(toggle-word-wrap -1)
(use-package drag-stuff
  :diminish drag-stuff-mode
  :config
  (drag-stuff-global-mode 1))
(delete-selection-mode 1)
(setq kill-ring-max 200)
(setq kill-whole-line t)
(setq require-final-newline t)
(setq-default tab-width 4)
(setq tab-stop-list
      (number-sequence 4 120 4))
(setq track-eol t)
(setq backup-directory-alist '(("." . "~/temp")))
(setq version-control t)
(setq kept-old-versions 10)
(setq kept-new-versions 20)
(setq delete-old-versions t)
(setq backup-by-copying t)

(setq auto-save-interval 50)
(setq auto-save-timeout 60)
(setq auto-save-default nil)
(setq auto-save-list-file-prefix "~/temp/auto-saves-")
(setq auto-save-file-name-transforms `((".*"  , "~/temp/")))
(setq create-lockfiles nil)
(use-package time-stamp
  :config
  (setq time-stamp-active t)
  (setq time-stamp-warn-inactive t)
  (setq time-stamp-format "%:y-%02m-%02d %3a %02H:%02M:%02S Kimi MA")
  (add-hook 'write-file-functions 'time-stamp))

(defun kimim/save-buffer-advice (orig-fun &rest arg)
  (delete-trailing-whitespace)
  (apply orig-fun arg))

(advice-add 'save-buffer :around #'kimim/save-buffer-advice)

(setq ispell-program-name "aspell")
(diminish 'visual-line-mode)
(add-hook 'text-mode-hook
          (lambda ()
            (when (derived-mode-p 'org-mode 'markdown-mode 'text-mode)
              (visual-line-mode))))
(setq-default indent-tabs-mode nil)

(setq uniquify-buffer-name-style 'forward)
(setq suggest-key-bindings 5)
(setq auto-mode-alist
      (append '(("\\.css\\'" . css-mode)
                ("\\.S\\'" . asm-mode)
                ("\\.md\\'" . markdown-mode)
                ("\\.markdown\\'" . markdown-mode)
                ("\\.svg\\'" . html-mode)
                ("\\.pas\\'" . delphi-mode)
                ("\\.txt\\'" . poly-org-mode)
                ("\\.org\\'" . poly-org-mode)
                )
              auto-mode-alist))

(require 'saveplace)
(setq-default save-place t)
(setq save-place-file (expand-file-name "saveplace" "~"))

15.2 visual-fill-mode

(use-package visual-fill-column)
(setq visual-fill-column-width fill-column)
(setq visual-fill-column-center-text t)

15.3 undo-tree

  (use-package undo-tree
    :diminish undo-tree-mode
    :config
    (global-undo-tree-mode)
    (setq undo-tree-visualizer-timestamps t))

16 File Management

16.1 dired

(use-package dired
  :ensure nil
  :bind
  (("C-x C-j" . dired-jump)
   :map dired-mode-map
   ("<left>" . dired-up-directory)
   ("<right>" . dired-find-file)
   ("o" . kimim/open-in-external-app)
   ("M-n" . dired-narrow))
  :config
  (require 'dired-x)
  (use-package dired-narrow)
  (use-package dired-collapse)
  (add-hook 'dired-mode-hook
            (lambda ()
              (turn-on-gnus-dired-mode)
              ;; Set dired-x buffer-local variables here.  For example:
              (dired-omit-mode 1)
              (dired-collapse-mode 1)
              (setq dired-omit-localp t)
              (setq dired-omit-files
                    (concat "|NTUSER\\|ntuser\\"
                            "|Cookies\\|AppData\\"
                            "|Contacts\\|Links\\"
                            "|Intel\\|NetHood\\"
                            "|PrintHood\\|Recent\\"
                            "|Start\\|SendTo\\"
                            "|^\\.DS_Store\\"
                            "|qms-bmh"))))
  (setq dired-listing-switches "-Avhlgo --group-directories-first")
  (if (eq system-type 'darwin)
      (setq dired-listing-switches "-Avhlgo"))

  (setq dired-recursive-copies t)
  (setq dired-recursive-deletes t)

  (defadvice dired-next-line (after dired-next-line-advice (arg) activate)
    "Move down lines then position at filename, advice"
    (interactive "p")
    (if (eobp)
        (progn
          (goto-char (point-min))
          (forward-line 2)
          (dired-move-to-filename))))

  (defadvice dired-previous-line (before dired-previous-line-advice (arg) activate)
    "Move up lines then position at filename, advice"
    (interactive "p")
    (if (= 3 (line-number-at-pos))
        (goto-char (point-max)))))

16.2 dired-collapse

(use-package dired-collapse)

16.3 dired-narrow

(use-package dired-narrow)

16.4 ibuffer

(use-package ibuffer
  :bind (("C-x C-b" . ibuffer-other-window)
         :map ibuffer-mode-map
         ("<right>" . ibuffer-visit-buffer))
  :config
  (defun ibuffer-visit-buffer-other-window (&optional noselect)
    "Visit the buffer on this line in another window."
    (interactive)
    (let ((buf (ibuffer-current-buffer t)))
      (bury-buffer (current-buffer))
      (if noselect
          (let ((curwin (selected-window)))
            (pop-to-buffer buf)
            (select-window curwin))
        (switch-to-buffer-other-window buf)
        (kill-buffer-and-its-windows "*Ibuffer*")
        )))

  ;; Use human readable Size column instead of original one
  (define-ibuffer-column size-h
    (:name "Size" :inline t)
    (cond
     ((> (buffer-size) 1000000) (format "%7.1fM" (/ (buffer-size) 1000000.0)))
     ((> (buffer-size) 100000) (format "%7.0fk" (/ (buffer-size) 1000.0)))
     ((> (buffer-size) 1000) (format "%7.1fk" (/ (buffer-size) 1000.0)))
     (t (format "%8d" (buffer-size)))))

  ;; Modify the default ibuffer-formats
  (setq ibuffer-formats
        '((mark modified read-only " "
                (name 32 32 :left :elide)
                " "
                (size-h 9 -1 :right)
                " "
                (mode 14 14 :left :elide)
                " "
                filename-and-process))))

17 Navigation

  ;; bookmark setting
  (setq bookmark-default-file "~/.emacs.d/emacs.bmk")
  (setq bookmark-save-flag 1)

  (use-package bm
    :bind (("C-x m t" . bm-toggle)
           ("C-x m s" . bm-show-all)))

  (use-package ace-jump-mode
    :bind
    ("C-x j" . ace-jump-mode)
    ("M-g j" . ace-jump-mode)
    ("C-`" . ace-jump-mode)
    ("<apps>" . ace-jump-mode))

  (use-package ace-window
    :bind
    ("C-\"" . ace-window)
    :config
    (setq aw-keys '(?a ?s ?d ?f ?g ?h ?j ?k ?l)))

18 Search and Finding

18.1 swiper replaces isearch

  (use-package swiper
    :init (setq swiper-action-recenter t)
    :bind
    ("C-s" . swiper))

18.2 ag: the silver searcher

ag 8 is really a very fast grep tool, and ag.el 9 provide the Emacs interface to ag:

  (use-package ag
    :bind
    ("C-x g" . ag-project)
    :config
    (setq ag-highlight-search t))

18.3 pt: the platium searcher

Because counsel-ag is not working in my Win64 machine, so I switch to pt now.

Download pt from https://github.com/monochromegane/the_platinum_searcher/releases, and it works out of the box.

18.4 imenu & imenu-anywhere

imenu is used to navigate the function definitions in current buffer.

  (use-package imenu
    :bind ("C-c C-i" . imenu)
    :config
    (advice-add 'imenu-default-goto-function
                :around
                #'kimim/imenu-default-goto-function-advice))

  (use-package imenu-anywhere
    :bind ("C-c i" . imenu-anywhere))

19 auto-complete

19.1 abbrev

(diminish 'abbrev-mode)

19.2 ivy-mode

  (use-package ivy
    :diminish ivy-mode
    :bind ("<f6>" . ivy-resume)
    :config
    (setq ivy-use-virtual-buffers t)
    (setq ivy-count-format "(%d/%d) ")
    (setq ivy-wrap nil)
    (ivy-mode 1))

19.3 auto parenthesis

  ;; add pair parenthis and quote automatically
  (use-package autopair
    :diminish autopair-mode
    :config
    (autopair-global-mode 1))

19.4 yasnippet

  (use-package yasnippet
    :defer 10
    :config
    (require 'yasnippet)
    (add-to-list
     'yas-snippet-dirs (concat kimim/path-sync-emacs "snippets"))
    (yas-global-mode 1)
    (use-package company)
    (eval-after-load 'company
      '(add-to-list  'company-backends 'company-yasnippet))
    (use-package warnings)
    (setq warning-suppress-types '((yasnippet backquote-change))))

In order to remove following warning:

Warning (yasnippet): ‘xxx’ modified buffer in a backquote expression. To hide this warning, add (yasnippet backquote-change) to ‘warning-suppress-types’.

19.5 company dict

  (use-package company-dict
    :config
    ;; Where to look for dictionary files
    (setq company-dict-dir (concat kimim/path-sync-emacs "dict"))
    ;; Optional: if you want it available everywhere
    (eval-after-load 'company
      '(add-to-list 'company-backends 'company-dict)))

19.6 company mode

English word list fetch from https://github.com/dwyl/english-words

  (use-package company-try-hard
    :bind ("C-\\" . company-try-hard))

  (use-package company
    :bind (:map company-active-map
                ("C-n" . (lambda () (interactive) (company-complete-common-or-cycle 1)))
                ("C-p" . (lambda () (interactive) (company-complete-common-or-cycle -1))))
    :diminish company-mode
    :commands (global-company-mode)
    :config
    (use-package company-dict)
    (setq company-idle-delay 0)
    (setq company-minimum-prefix-length 1)
    ;; macOS will use system dict file directly
    (cond ((eq system-type 'windows-nt)
           (setq ispell-alternate-dictionary "~/.emacs.d/dict/words3.txt")))
    (eval-after-load 'company
      '(add-to-list 'company-backends 'company-ispell)))

19.7 company statistics

Sort candidates using completion history.

  (use-package company-statistics
    :config
    (company-statistics-mode 1))

20 Programming General

20.1 Compiling

  (setq next-error-recenter 20)
  (bind-key "C-<f11>" 'compile)

20.2 Tagging

  (use-package ggtags
    :bind (("C-c f" . ggtags-find-file)
           ("M-." . ggtags-find-tag-dwim))
    :config
    (setq ggtags-global-ignore-case t)
    (setq ggtags-sort-by-nearness t))

20.3 Version Control

  (use-package magit
    :bind ("C-x m g" . magit-status))

Following error will reported when using magit to commit changes:

server-ensure-safe-dir: The directory ‘~/.emacs.d/server’ is unsafe

The solution is to change the owner of ~/.emacs.d/server 10

Click R-mouse on ~/.emacs.d/server and select “Properties” (last item in menu). From Properties select the Tab “Security” and then select the button “Advanced”. Then select the Tab “Owner” and change the owner from “Administrators (\Administrators)” into “ (\”. Now the server code will accept this directory as secure because you are the owner.

20.4 Code folding

(use-package yafolding
  :bind (("C-c h" . yafolding-hide-element)
         ("C-c s" . yafolding-show-element)))

20.5 static code analysis

(use-package flycheck
  :commands (global-flycheck-mode))

21 Programming Language

21.1 C

  (use-package cc-mode
    :ensure nil
    :config
    (add-to-list 'auto-mode-alist '("\\.c\\'" . c-mode))
    (use-package ggtags)
    (add-hook 'c-mode-hook 'ggtags-mode)
    (add-hook 'c++-mode-hook 'ggtags-mode)

    (add-hook 'c-mode-common-hook
              (lambda ()
                ;;(c-set-style "gnu")
                (c-toggle-auto-newline 0)
                (c-toggle-auto-hungry-state 0)
                (c-toggle-syntactic-indentation 1)
                ;;(highlight-indentation-mode 1)
                (which-function-mode 1)
                (local-set-key "\C-co" 'ff-find-other-file)
                (setq c-basic-offset 4))))

21.2 C#

  (use-package csharp-mode
    :mode ("\\.cs\\'" . csharp-mode))

21.3 Clojure

Clojure11 is a lisp over JVM. Emm, I like it.

(use-package paredit
  :bind (("C-M-w" . paredit-copy-as-kill)
         ("M-<right>" . paredit-forward)
         ("M-<left>" . paredit-backward))
  :commands (enable-paredit-mode))

(use-package clojure-mode
  :mode ("\\.clj\\'" . clojure-mode)
  :config
  (use-package cider)
  (use-package company)
  (use-package flycheck)
  (use-package flycheck-clj-kondo)
  (use-package clojure-snippets)
  (eval-after-load 'company
    '(progn
       (delete 'company-capf company-backends)
       (add-to-list 'company-backends 'company-capf)))
  (add-hook 'cider-repl-mode-hook #'company-mode)
  (add-hook 'cider-mode-hook #'company-mode)
  (add-hook 'clojure-mode-hook #'cider-mode)
  (use-package clojure-mode-extra-font-locking)
  (add-to-list 'auto-mode-alist '("\\.\\(clj\\|dtm\\|edn\\)\\'" . clojure-mode))
  (add-to-list 'auto-mode-alist '("\\.cljc\\'" . clojurec-mode))
  (add-to-list 'auto-mode-alist '("\\.cljs\\'" . clojurescript-mode))
  (add-to-list 'auto-mode-alist '("\\(?:build\\|profile\\)\\.boot\\'" . clojure-mode))
  (add-hook 'clojure-mode-hook
            (lambda ()
              (enable-paredit-mode))))

(use-package clojurescript-mode
  :mode ("\\.cljs\\'" . clojurescript-mode)
  :ensure clojure-mode
  :config
  (use-package cider)
  (use-package company)
  (use-package flycheck)
  (use-package flycheck-clj-kondo)
  (use-package clojure-snippets)
  (eval-after-load 'company
    '(progn
       (delete 'company-capf company-backends)
       (add-to-list 'company-backends 'company-capf)))
  (add-hook 'cider-repl-mode-hook #'company-mode)
  (add-hook 'cider-mode-hook #'company-mode)
  (add-hook 'clojurescript-mode-hook #'cider-mode)
  (use-package clojure-mode-extra-font-locking)
  (add-to-list 'auto-mode-alist '("\\.cljc\\'" . clojurec-mode))
  (add-to-list 'auto-mode-alist '("\\.cljs\\'" . clojurescript-mode))
  (add-hook 'clojure-mode-hook
            (lambda ()
              (enable-paredit-mode))))

21.3.1 clj-kondo

Install with npm:

npm install -g clj-kondo
(use-package flycheck-clj-kondo)

21.3.2 Cider

Cider12 extends Emacs with support for interactive programming in Clojure.

(use-package cider
  :config
  (setq nrepl-use-ssh-fallback-for-remote-hosts t)
  (setq nrepl-sync-request-timeout 100)
  (defun nrepl--ssh-tunnel-command (ssh dir port)
    "Command string to open SSH tunnel to the host associated with DIR's PORT."
    (with-parsed-tramp-file-name dir v
      ;; this abuses the -v option for ssh to get output when the port
      ;; forwarding is set up, which is used to synchronise on, so that
      ;; the port forwarding is up when we try to connect.
      (format-spec
       "%s -v -N -L %p:localhost:%p %u'%h' %x"
       `((?s . ,ssh)
         (?p . ,port)
         (?h . ,v-host)
         (?u . ,(if v-user (format "-l '%s' " v-user) ""))
         (?x . "-o \"ProxyCommand=nc -X connect -x 127.0.0.1:1080 %h %p\"")))))
  )
(use-package ob-clojure
  :ensure org
  :config
  (use-package clojure-mode)
  (require 'ob-clojure)
  (use-package cider)
  (setq org-babel-clojure-backend 'cider)
  (defun org-babel-expand-body:clojure (body params)
    "Expand BODY according to PARAMS, return the expanded body."
    (let* ((vars (org-babel--get-vars params))
           (ns (or (cdr (assq :ns params))
                   (org-babel-clojure-cider-current-ns)))
           (result-params (cdr (assq :result-params params)))
           (print-level nil)
           (print-length nil)
           (body (org-trim
                  (concat
                   ;; Source block specified namespace :ns.
                   (and (cdr (assq :ns params)) (format "(ns %s)\n" ns))
                   ;; Variables binding.
                   (if (null vars) (org-trim body)
                     (format "(let [%s]\n%s)"
                             (mapconcat
                              (lambda (var)
                                (format "%S (quote %S)" (car var) (cdr var)))
                              vars
                              "\n      ")
                             body))))))
      (if (or (member "code" result-params)
              (member "pp" result-params))
          (format "(print (str (do %s)))" body)
        body))))

21.4 Python

Python development configuration is quite easy. elpy 13 is used here:

  (use-package elpy
    :config
    (elpy-enable))

  (use-package python
    :ensure nil
    :mode ("\\.py\\'" . python-mode)
    :interpreter ("python" . python-mode)
    :config
    (add-hook 'python-mode-hook
              (lambda ()
                (setq yas-indent-line nil)))
    (add-to-list 'python-shell-completion-native-disabled-interpreters "python"))

  (use-package company-jedi
    :config
    (setq elpy-rpc-backend "jedi")
    (eval-after-load 'company
      '(add-to-list 'company-backends 'company-jedi)))

Following python package is required according to elpy mannual:

pip install rope
pip install jedi
# flake8 for code checks
pip install flake8
# importmagic for automatic imports
pip install importmagic
# and autopep8 for automatic PEP8 formatting
pip install autopep8
# and yapf for code formatting
pip install yapf
# install virtualenv for jedi
pip install virtualenv

21.5 Swift

  (use-package swift-mode
    :mode ("\\.swift\\'" . swift-mode))

21.6 Go lang

Open .go file with go-mode.

  (use-package go-mode
    :mode ("\\.go\\'" . go-mode))

21.7 Docker file

Some dockerfile is not end with .dockerfile, so lets guess:

  (use-package dockerfile-mode
    :mode ("\\dockerfile\\'" . dockerfile-mode))

21.8 Emacs lisp

(use-package elisp-mode
  :ensure nil
  :mode ("\\.el\\'" . emacs-lisp-mode)
  :config
  (define-derived-mode lisp-interaction-mode emacs-lisp-mode "λ")
  (global-company-mode t)
  (global-flycheck-mode t)
  (eval-after-load 'company
    '(add-to-list 'company-backends 'company-elisp))
  (add-hook 'emacs-lisp-mode-hook
            (lambda ()
              (enable-paredit-mode))))

21.9 AutoHotKey

ahk-mode developed by Rich Alesi14

  (use-package ahk-mode
    :mode ("\\.ahk\\'" . ahk-mode))

22 Calendar

  (if (not (boundp 'kimim/file-diary))
      (defvar kimim/file-diary (concat kimim/path-sync-emacs "diary")))
  (if (not (file-exists-p kimim/file-diary))
      (write-region "" nil kimim/file-diary))
  (setq diary-file kimim/file-diary)
  (setq calendar-latitude +30.16)
  (setq calendar-longitude +120.12)
  (setq calendar-location-name "Hangzhou")
  (setq calendar-remove-frame-by-deleting t)
  (setq calendar-week-start-day 1)
  (setq holiday-christian-holidays nil)
  (setq holiday-hebrew-holidays nil)
  (setq holiday-islamic-holidays nil)
  (setq holiday-solar-holidays nil)
  (setq holiday-bahai-holidays nil)
  (setq holiday-general-holidays
        '((holiday-fixed 1 1 "元旦")
          (holiday-float 5 0 2 "父親節")
          (holiday-float 6 0 3 "母親節")))
  (setq calendar-mark-diary-entries-flag t)
  (setq calendar-mark-holidays-flag nil)
  (setq calendar-view-holidays-initially-flag nil)
  (setq chinese-calendar-celestial-stem
        ["甲" "乙" "丙" "丁" "戊" "己" "庚" "辛" "壬" "癸"])
  (setq chinese-calendar-terrestrial-branch
        ["子" "丑" "寅" "卯" "辰" "巳" "午" "未" "申" "酉" "戌" "亥"])

23 Orgmode

23.1 orgalist

  (use-package orgalist
    :commands (orgalist-mode))

23.2 org general setting

  ;; path and system environment setting for orgmode
  (use-package org
    :bind
    ("C-c a" . org-agenda)
    ("C-c b" . org-iswitchb)
    ("C-c c" . org-capture)
    ("C-c l" . org-store-link)
    ("C-c  !" . org-time-stamp-inactive)
    ("C-c  。" . org-time-stamp)
    :config
    ;; (org-roam-mode t)
    (org-download-enable)
    (setq org-support-shift-select t)
    ;; no empty line after collapsed
    (setq org-cycle-separator-lines 0)
    (setq org-src-fontify-natively t)
    (setq org-src-preserve-indentation t)
    (if window-system
        (setq org-startup-indented t)
      (setq org-startup-indented nil))
    (setq org-image-actual-width 600))

23.3 org for writing

(use-package org-download
  :commands (org-download-enable)
  :config
  (setq org-download-timestamp "")
  (setq-default org-download-image-dir "./images")
  (setq org-download-method 'directory)
  (setq org-download-heading nil)
  (setq org-startup-with-inline-images nil)

  (defun kimim/org-download-annotate (link)
    "Annotate LINK with the time of download."
    (format "#+NAME: fig:%s\n#+CAPTION: %s\n"
            (file-name-base link) (file-name-base link)))
  (setq org-download-annotate-function #'kimim/org-download-annotate)
  (setq org-download-display-inline-images nil)
  (setq image-file-name-extensions
        (quote
         ("png" "jpeg" "jpg" "gif" "tiff" "tif" "xbm"
          "xpm" "pbm" "pgm" "ppm" "pnm" "svg" "pdf" "bmp")))
  (defun org-download--dir-2 () "."))
  (use-package org
    :config
    (use-package org-download)
    (use-package pangu-spacing)
    (setq org-hide-leading-stars t)
    (setq org-footnote-auto-adjust t)
    (setq org-footnote-define-inline nil)
    (define-key org-mode-map (kbd "C-c C-x h") (lambda ()
                                                 (interactive)
                                                 (insert "^{()}")
                                                 (backward-char 2)))
    (define-key org-mode-map (kbd "C-c C-x l") (lambda ()
                                                 (interactive)
                                                 (insert "_{}")
                                                 (backward-char 1))))

23.4 org with source code

  (use-package org
    :config
    (use-package poly-org)
    (org-babel-do-load-languages
     'org-babel-load-languages
     '((clojure . t)
       (shell . t)
       (python . t)))
    (setq org-src-window-setup 'current-window)
    (setq org-src-fontify-natively t)
    (setq org-src-preserve-indentation t)
    (setq org-edit-src-content-indentation 0)
    (setq org-confirm-babel-evaluate nil)
    (add-hook 'org-babel-after-execute-hook 'org-display-inline-images))

Polymode 15 is a framework for multiple major modes (MMM) inside a single Emacs buffer. It is comfortable to enable it during literating program.

(use-package poly-org
  :ensure t)

23.5 org exporting

When exporting, do not export with author and date.

  (use-package org
    :bind ("C-c C-'" . org-insert-structure-template)
    :config
    (setq org-export-allow-BIND t)
    (setq org-export-creator-string "")
    (setq org-export-html-validation-link nil)
    (setq org-export-with-sub-superscripts '{})
    (setq org-export-with-author nil)
    (setq org-export-with-date nil))

23.5.1 org to pdf

LaTeX is required to convert org-mode to PDF.

For MacOS:

brew cask install mactex-no-gui

For Windows, download and install CTEX from http://www.ctex.org

apt-cyg install texlive-collection-xetex texlive-collection-latex texlive-collection-fontsrecommended

For Linux:

Download texlive install pacakge from: http://mirror.ctan.org/systems/texlive/tlnet/install-tl-unx.tar.gz

tar zxvf install-tl-unx.tar.gz
cd install-tl-20200908/
sudo ./install-tl

Then for all the OS platforms, use tlmgr to install user level tex packages:

tlmgr init-usertree
tlmgr --usermode install ctex titlesec enumitem ms fontspec abstract \
                         zhnumber fandol lastpage pdftexcmds infwarerr \
                         minted fvextra etoolbox fancyvrb upquote \
                         lineno catchfile xstring framed float \
                         grffile wrapfig ulem lettrine minifp \
                         capt-of xcolor svg koma-script trimspaces \
                         titling layaureo parskip extsizes pgf \
                         moderncv microtype
fmtutil-sys --all

To export org-mode to PDF, with code style highlight, you need to install python and pygments. Because pygmentize from pygments is used to generate latex markups for font highlighting.

For MacOS, the OS shipped python2.7 does not accompanied with pip package management script. So you need to install pip, and then add pygments, acc. https://pip.pypa.io/en/stable/installing/ , pygmentize will be installed under $HOME/Library/Python/2.7/bin, which is added to exec-path and PATH in section 5.1.

curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py
python get-pip.py

Get pygments with pip:

pip install pygments

For Ubuntu Linux:

sudo apt install python3-pygments
  (use-package ox-latex
    :ensure org
    :bind ("<C-f7>" . org-latex-export-to-pdf)
    :commands (org-latex-publish-to-pdf)
    :config
    (require 'ox-latex)
    (setq org-latex-listings 'minted)
    (setq org-latex-minted-options
    '(("frame" "single") ("fontsize" "\\small")))

    (setq org-latex-pdf-process
          `(,(let ((ref (concat kimim/path-ref "references.bib")))
               (if (file-exists-p ref)
                   (concat "cp -f \"" ref "\" .")
                 ""))
            "xelatex -shell-escape %f"
            "bibtex %b"
            "xelatex -shell-escape %f"
            "xelatex -shell-escape %f"
            "mv -f references.bib references.back.bib"))

    ;;; Nicolas Goaziou, http://article.gmane.org/gmane.emacs.orgmode/67692
    (defun org-latex-ignore-heading-filter-headline (headline backend info)
      "Strip headline from HEADLINE. Ignore BACKEND and INFO."
      (when (and (org-export-derived-backend-p backend 'latex)
                 (string-match "\\`.*ignoreheading.*\n" headline))
        (replace-match "" nil nil headline)))
    (add-to-list 'org-export-filter-headline-functions
                 'org-latex-ignore-heading-filter-headline)

    ;; most of the time, I do not need table of contents
    (setq org-latex-toc-command nil)
    ;; https://www.tuicool.com/articles/ZnAnym
    ;; remove error: ! LaTeX Error: Command \nobreakspace unavailable in encoding T1.
    ;; add: \DeclareRobustCommand\nobreakspace{\leavevmode\nobreak\ }
    (setq org-latex-classes
          '(("biz-report"
             "\\documentclass[15pt]{ctexart}
  \\usepackage{geometry}
  \\usepackage{titlesec}
  \\usepackage{titling}
  \\posttitle{\\par\\end{center}\\vskip -60pt}
  \\let\\titleoriginal\\title
  \\renewcommand{\\title}[1]{
    \\titleoriginal{\\LARGE{\\heiti{#1}}\\vspace{-4em}}
    }
  \\let\\maketitleorig\\maketitle
  \\renewcommand{\\maketitle}{
    \\maketitleorig
    \\Large
    }
  \\setlength{\\droptitle}{-60pt}
  \\usepackage{enumitem}
  \\usepackage{abstract}
  \\renewcommand{\\abstractname}{摘要}
  \\renewcommand\\refname{参考文献}
  \\usepackage{fancyhdr, lastpage}
  \\fancypagestyle{plain}{
      \\fancyhf{}
      \\fancyfoot[C]{{\\thepage}/\\pageref*{LastPage}}
      \\renewcommand{\\headrulewidth}{0pt}
  }
  \\usepackage{hyperref}
  \\hypersetup{hidelinks}
  \\hypersetup{colorlinks = true, urlcolor = blue, linkcolor = blue, citecolor = blue}
  \\pagestyle{plain}
  \\setlist[1]{labelindent=\\parindent,nosep,leftmargin= *}
  \\geometry{a4paper,scale=0.8}
  \\geometry{a4paper,left=2.5cm,right=2.5cm,top=3cm,bottom=3cm}
  \\setlength{\\baselineskip}{20pt}
  \\setlength{\\parskip}{5pt}
  \\DeclareRobustCommand\\nobreakspace{\\leavevmode\\nobreak\\ }"
             ("\\section{%s}" . "\\section*{%s}")
             ("\\subsection{%s}" . "\\subsection*{%s}")
             ("\\subsubsection{%s}" . "\\subsubsection*{%s}")
             ("\\paragraph{%s}" . "\\paragraph*{%s}")
             ("\\subparagraph{%s}" . "\\subparagraph*{%s}"))

             ("cn-article"
             "\\documentclass[a4paper,UTF8]{ctexart}
  \\usepackage{geometry}
  \\usepackage{titlesec}
  \\usepackage{enumitem}
  \\usepackage{abstract}
  \\renewcommand{\\abstractname}{摘要}
  \\renewcommand\\refname{参考文献}
  \\CTEXsetup[format={\\Large\\bfseries}]{section}
  \\renewcommand\\thesection{\\chinese{section}、}
  \\renewcommand\\thesubsection{\\arabic{section}.\\arabic{subsection}.}
  \\renewcommand\\thesubsubsection{\\arabic{section}.\\arabic{subsection}.\\arabic{subsubsection}}
  \\usepackage{fancyhdr, lastpage}
  \\fancypagestyle{plain}{
      \\fancyhf{}
      \\fancyfoot[C]{{\\thepage}/\\pageref*{LastPage}}
      \\renewcommand{\\headrulewidth}{0pt}
  }
  \\usepackage{hyperref}
  \\hypersetup{hidelinks}
  \\hypersetup{colorlinks = true, urlcolor = blue, linkcolor = blue, citecolor = blue}
  \\pagestyle{plain}
  \\setlist[1]{labelindent=\\parindent,nosep,leftmargin= *}
  \\geometry{a4paper,scale=0.8}
  \\geometry{a4paper,left=2.5cm,right=2.5cm,top=3cm,bottom=3cm}
  \\setlength{\\baselineskip}{20pt}
  \\setlength{\\parskip}{5pt}
  \\DeclareRobustCommand\\nobreakspace{\\leavevmode\\nobreak\\ }"
             ("\\section{%s}" . "\\section*{%s}")
             ("\\subsection{%s}" . "\\subsection*{%s}")
             ("\\subsubsection{%s}" . "\\subsubsection*{%s}")
             ("\\paragraph{%s}" . "\\paragraph*{%s}")
             ("\\subparagraph{%s}" . "\\subparagraph*{%s}"))

            ("cn-book"
             "\\documentclass[a4paper,UTF8]{ctexbook}
  \\usepackage{enumitem}
  \\usepackage{abstract}
  \\renewcommand{\\abstractname}{摘要}
  \\renewcommand\\refname{参考文献}
  \\usepackage{fancyhdr, lastpage}
  \\fancypagestyle{plain}{
      \\fancyhf{}
      \\fancyfoot[C]{{\\thepage}/\\pageref*{LastPage}}
      \\renewcommand{\\headrulewidth}{0pt}
  }
  \\usepackage{hyperref}
  \\hypersetup{hidelinks}
  \\hypersetup{colorlinks = true, urlcolor = blue, linkcolor = blue, citecolor = blue}
  \\pagestyle{plain}
  \\setlist[1]{labelindent=\\parindent,nosep,leftmargin= *}
  \\setlength{\\baselineskip}{20pt}
  \\setlength{\\parskip}{5pt}
  \\DeclareRobustCommand\\nobreakspace{\\leavevmode\\nobreak\\ }"
             ("\\section{%s}" . "\\section*{%s}")
             ("\\subsection{%s}" . "\\subsection*{%s}")
             ("\\subsubsection{%s}" . "\\subsubsection*{%s}")
             ("\\paragraph{%s}" . "\\paragraph*{%s}")
             ("\\subparagraph{%s}" . "\\subparagraph*{%s}"))

            ("article"
             "\\documentclass{article}
  \\usepackage[UTF8]{ctex}
  \\usepackage{geometry}
  \\usepackage{titlesec}
  \\usepackage{enumitem}
  \\usepackage{fancyhdr, lastpage}
  \\usepackage{hyperref}
  \\hypersetup{hidelinks}
  \\hypersetup{colorlinks = true, urlcolor = blue, linkcolor = blue, citecolor = blue}
  \\fancypagestyle{plain}{
      \\fancyhf{}
      \\fancyfoot[C]{{\\thepage}/\\pageref*{LastPage}}
      \\renewcommand{\\headrulewidth}{0pt}
  }
  \\pagestyle{plain}
  \\setlength{\\parindent}{0em}
  \\setlist[1]{labelindent=\\parindent,nosep,leftmargin= *}
  \\geometry{a4paper,scale=0.8}
  \\geometry{a4paper,left=2.5cm,right=2.5cm,top=3cm,bottom=3cm}
  \\setlength{\\baselineskip}{20pt}
  \\setlength{\\parskip}{5pt}"
             ("\\section{%s}" . "\\section*{%s}")
             ("\\subsection{%s}" . "\\subsection*{%s}")
             ("\\subsubsection{%s}" . "\\subsubsection*{%s}")
             ("\\paragraph{%s}" . "\\paragraph*{%s}")
             ("\\subparagraph{%s}" . "\\subparagraph*{%s}"))

            ("article2c"
             "\\documentclass[twocolumn]{article}
  \\usepackage[UTF8]{ctex}
  \\usepackage{geometry}
  \\usepackage{titlesec}
  \\usepackage{enumitem}
  \\usepackage{fancyhdr, lastpage}
  \\fancypagestyle{plain}{
      \\fancyhf{}
      \\fancyfoot[C]{{\\thepage}/\\pageref*{LastPage}}
      \\renewcommand{\\headrulewidth}{0pt}
  }
  \\usepackage{hyperref}
  \\hypersetup{hidelinks}
  \\hypersetup{colorlinks = true, urlcolor = blue, linkcolor = blue, citecolor = blue}
  \\pagestyle{plain}
  \\setlist[1]{labelindent=\\parindent,nosep,leftmargin= *}
  \\geometry{a4paper,scale=0.8}
  \\geometry{a4paper,left=2.5cm,right=2.5cm,top=2cm,bottom=2cm}
  \\setlength{\\baselineskip}{20pt}
  \\setlength{\\parskip}{5pt}"
             ("\\section{%s}" . "\\section*{%s}")
             ("\\subsection{%s}" . "\\subsection*{%s}")
             ("\\subsubsection{%s}" . "\\subsubsection*{%s}")
             ("\\paragraph{%s}" . "\\paragraph*{%s}")
             ("\\subparagraph{%s}" . "\\subparagraph*{%s}"))

            ("IEEEtran"
             "\\documentclass[conference]{IEEEtran}
  \\IEEEoverridecommandlockouts
  \\usepackage{cite}
  \\usepackage{amsmath,amssymb,amsfonts}
  \\usepackage{algorithmic}
  \\usepackage{xcolor}
  \\usepackage{hyperref}
  \\def\\BibTeX{{\\rm B\\kern-.05em{\\sc i\\kern-.025em b}\\kern-.08em
    T\\kern-.1667em\\lower.7ex\\hbox{E}\\kern-.125emX}}")))

    (setq org-latex-default-class "article")
    ;; remove fontenc, and AUTO in front of inputenc,
    ;; then francais can be processed
    (setq org-latex-default-packages-alist
          (quote
           (("" "inputenc" t ("pdflatex"))
            ("" "minted" t nil)
            ("" "graphicx" t nil)
            ("" "grffile" t nil)
            ("" "longtable" nil nil)
            ("" "wrapfig" nil nil)
            ("" "rotating" nil nil)
            ("normalem" "ulem" t nil)
            ("" "amsmath" t nil)
            ("" "textcomp" t nil)
            ("" "lettrine" t nil)
            ("" "capt-of" nil nil)))))

23.5.2 org to html page

  (use-package ox-html
    :ensure org
    :commands (org-html-publish-to-html)
    :config
    (setq org-html-validation-link nil)
    (defadvice org-html-paragraph (before fsh-org-html-paragraph-advice
                                          (paragraph contents info) activate)
      "Join consecutive Chinese lines into a single long line without
  unwanted space when exporting org-mode to html."
      (let ((fixed-contents)
            (orig-contents (ad-get-arg 1))
            (reg-han "[[:multibyte:]]"))
        (setq fixed-contents (replace-regexp-in-string
                              (concat "\\(" reg-han "\\) *\n *\\(" reg-han "\\)")
                              "\\1\\2" orig-contents))
        (ad-set-arg 1 fixed-contents)
        ))

    (defun org-babel-result-to-file (result &optional description)
      "Convert RESULT into an `org-mode' link with optional DESCRIPTION.
  If the `default-directory' is different from the containing
  file's directory then expand relative links."
      (when (stringp result)
        (if (string= "svg" (file-name-extension result))
            (progn
              (with-temp-buffer
                (if (file-exists-p (concat result ".html"))
                    (delete-file (concat result ".html")))
                (rename-file result (concat result ".html"))
                (insert-file-contents (concat result ".html"))
                (message (concat result ".html"))
                (format "#+BEGIN_HTML
  <div style=\"text-align: center;\">
  %s
  </div>
  #+END_HTML"
                        (buffer-string)
                        )))
          (progn
            (format "[[file:%s]%s]"
                    (if (and default-directory
                             buffer-file-name
                             (not (string= (expand-file-name default-directory)
                                           (expand-file-name
                                            (file-name-directory buffer-file-name)))))
                        (expand-file-name result default-directory)
                      result)
                    (if description (concat "[" description "]") "")))))))

23.6 org to html slide

  (use-package org-re-reveal
    :bind ("C-x r v" . org-re-reveal-export-to-html-and-browse)
    :config
    (use-package htmlize :ensure t)
    (setq org-re-reveal-root "https://cdn.jsdelivr.net/npm/reveal.js@3.9.2/")
    (setq org-re-reveal-theme "none")
    (setq org-re-reveal-width 1000)
    (setq org-re-reveal-height 750)
    (setq org-re-reveal-transition "none")
    (setq org-re-reveal-hlevel 2)
    (setq org-re-reveal-extra-css "./kimim.css"))

23.7 org with diagram

That's fun to draw UML with ob-plantuml inside orgmode:

  1. install graphviz in cygwin setup tool
  2. download plantuml.jar from https://plantuml.com/download, and put it to (concat kimim/path-kimikit "plantuml/plantuml.jar")
(use-package plantuml-mode
  :config
  (setq plantuml-default-exec-mode 'jar))

(use-package ob-plantuml
  :ensure org
  :config
  (use-package plantuml-mode)
  (require 'ob-plantuml)
  ;;(setenv "GRAPHVIZ_DOT" (concat kimim/path-root "usr/bin/dot"))
  (setq org-plantuml-jar-path (concat kimim/path-kimikit "plantuml/plantuml.jar"))
  (defun org-babel-execute:plantuml (body params)
    "Execute a block of plantuml code with org-babel.
This function is called by `org-babel-execute-src-block'."
    (let* ((out-file (or (cdr (assq :file params))
                         (error "PlantUML requires a \":file\" header argument")))
           (cmdline (cdr (assq :cmdline params)))
           (in-file (org-babel-temp-file "plantuml-"))
           (java (or (cdr (assq :java params)) ""))
           (full-body (org-babel-plantuml-make-body body params))
           (cmd (if (string= "" org-plantuml-jar-path)
                    (error "`org-plantuml-jar-path' is not set")
                  (concat "java " java " -jar `cygpath -wp "
                          (shell-quote-argument
                           (expand-file-name org-plantuml-jar-path))
                          " ` "
                          " -charset UTF-8 "
                          (if (string= (file-name-extension out-file) "png")
                              " -tpng" "")
                          (if (string= (file-name-extension out-file) "svg")
                              " -tsvg" "")
                          (if (string= (file-name-extension out-file) "eps")
                              " -teps" "")
                          (if (string= (file-name-extension out-file) "pdf")
                              " -tpdf" "")
                          (if (string= (file-name-extension out-file) "tex")
                              " -tlatex" "")
                          (if (string= (file-name-extension out-file) "vdx")
                              " -tvdx" "")
                          (if (string= (file-name-extension out-file) "xmi")
                              " -txmi" "")
                          (if (string= (file-name-extension out-file) "scxml")
                              " -tscxml" "")
                          (if (string= (file-name-extension out-file) "html")
                              " -thtml" "")
                          (if (string= (file-name-extension out-file) "txt")
                              " -ttxt" "")
                          (if (string= (file-name-extension out-file) "utxt")
                              " -utxt" "")
                          " -p " cmdline " < "
                          (org-babel-process-file-name in-file)
                          " > "
                          (org-babel-process-file-name out-file)))))
      (unless (file-exists-p org-plantuml-jar-path)
        (error "Could not find plantuml.jar at %s" org-plantuml-jar-path))
      (with-temp-file in-file (insert full-body))
      (message "%s" cmd) (org-babel-eval cmd "")
      nil)))

23.8 org as GTD system

(use-package org
  :commands (org-toggle-office org-toggle-home org-toggle-home-or-office)
  :bind (:map org-mode-map
         :map org-agenda-mode-map
         ("C-c C-k" . org-agenda-kill-files)
         ("<C-left>"  . org-agenda-do-date-earlier)
         ("<C-right>" . org-agenda-do-date-later)
         ("<S-left>" . (lambda ()
                         (interactive)
                         (org-agenda-todo 'left)))
         ("<S-right>" . (lambda ()
                          (interactive)
                          (org-agenda-todo 'right))))
  :config
  (require 'org-agenda)
  (add-hook 'kill-emacs-hook
            (lambda ()
              (org-clock-out nil t nil)
              (org-save-all-org-buffers)))
  (setq org-todo-keywords
        '(
          ;; for tasks
          (sequence "TODO(t!)" "SCHED(s)" "|" "DONE(d@/!)")
          ;; for risks, actions, problems
          (sequence "OPEN(o!)" "WAIT(w@/!)" "|" "CLOSE(c@/!)")
          (sequence "|" "SOMEDAY(m)")
          (sequence "|" "ABORT(a@/!)")
          (sequence "REPEAT(r)" "|")))

  (setq org-tag-alist
        '(("@office" . ?o) ("@home" . ?h)
          ("team" . ?t) ("leader" . ?l) ("boss" . ?b)
          ("risk" . ?k) ("sync" . ?s) ("followup" . ?f)
          ("reading" . ?r) ("writing" . ?w)
          ("project" . ?p) ("category" . ?c)
          ("habit" . ?H)
          ("next" . ?n)))

  (setq org-tags-exclude-from-inheritance '("project" "category"))

  (diminish 'auto-fill-function)

  (add-hook 'org-mode-hook
            (lambda ()
              ;;(auto-fill-mode)
              ;;(drag-stuff-mode -1)
              ))

  (setq org-stuck-projects
        '("+LEVEL>=2-category-habit-info"
          ("TODO" "SCHED"  "DONE"
           "OPEN" "WAIT" "CLOSE"
           "ABORT" "SOMEDAY" "REPEAT")
          nil nil))

  (setq org-refile-targets
        '(;; refile to maxlevel 2 of current file
          (nil . (:maxlevel . 1))
          ;; refile to maxlevel 1 of org-refile-files
          (org-refile-files :maxlevel . 1)
          ;; refile to item with 'project' tag in org-refile-files
          (org-refile-files :tag . "project")
          (org-refile-files :tag . "category")))

  (defadvice org-schedule (after add-todo activate)
    (if (or (string= "OPEN" (org-get-todo-state))
            (string= "WAIT" (org-get-todo-state))
            (string= "CLOSE" (org-get-todo-state)))
        (org-todo "WAIT")
      (org-todo "SCHED")))

  (defadvice org-deadline (after add-todo activate)
    (if (or (string= "OPEN" (org-get-todo-state))
            (string= "WAIT" (org-get-todo-state))
            (string= "CLOSE" (org-get-todo-state)))
        (org-todo "WAIT")
      (org-todo "SCHED")))

  (setq org-log-done t)
  (setq org-todo-repeat-to-state "REPEAT")

  ;; settings for org-agenda-view
  (setq org-agenda-span 2)
  (setq org-agenda-skip-scheduled-if-done t)
  (setq org-agenda-skip-deadline-if-done t)
  (setq org-deadline-warning-days 2)
  (add-hook 'org-agenda-after-show-hook 'org-narrow-to-subtree)
  (setq org-agenda-custom-commands
        '(("t" todo "TODO|OPEN"
           ((org-agenda-sorting-strategy '(priority-down))))
          ("w" todo "SCHED|WAIT"
           ((org-agenda-sorting-strategy '(priority-down))))
          ;; all task should be done or doing
          ("d" todo "TODO|SCHED|OPEN|WAIT"
           ((org-agenda-sorting-strategy '(priority-down))))
          ("b" tags "boss/-ABORT-CLOSE-DONE"
           ((org-agenda-sorting-strategy  '(priority-down))))
          ("f" todo "SOMEDAY"
           ((org-agenda-sorting-strategy '(priority-down))))
          ("h" tags "habit/-ABORT-CLOSE"
           ((org-agenda-sorting-strategy '(todo-state-down))))
          ("c" tags "clock"
           ((org-agenda-sorting-strategy '(priority-down))))))

  (setq org-directory kimim/path-org)

  (setq org-capture-templates
        '(("c" "Capture" entry (file+headline "capture.org" "Inbox")
           "* %?\n:PROPERTIES:\n:CAPTURED: %U\n:END:\n")
          ("t" "TODO Task"    entry (file+headline "capture.org" "Inbox")
           "* TODO %?\n:PROPERTIES:\n:CAPTURED: %U\n:END:\n")
          ("s" "SCHED Task"    entry (file+headline "capture.org" "Inbox")
           "* SCHED %?\nSCHEDULED: %t\n:PROPERTIES:\n:CAPTURED: %U\n:END:\n")
          ("o" "OPEN Issue"  entry (file+headline "capture.org" "Inbox")
           "* OPEN %?\n:PROPERTIES:\n:CAPTURED: %U\n:END:\n")
          ("w" "WAIT Task"    entry (file+headline "capture.org" "Inbox")
           "* WAIT %?\nSCHEDULED: %t\n:PROPERTIES:\n:CAPTURED: %U\n:END:\n")
          ("h" "Habit"   entry (file+headline "global.org"   "Habit")
           "* %?  :habit:\n:PROPERTIES:\n:CAPTURED: %U\n:END:\n")))

  (use-package ivy) ; use ivy to complete refile files
  (setq org-agenda-files
        (file-expand-wildcards (concat kimim/path-org "*.org")))
  (setq org-refile-files
        (file-expand-wildcards (concat kimim/path-org "*.org")))
  (defun org-agenda-kill-files ()
    (interactive)
    (org-agenda-kill-all-agenda-buffers)
    (mapcar (lambda (file)
              (if-let (buf (get-file-buffer file))
                  (kill-buffer buf)))
            org-agenda-files)))

23.9 org link: match

New link to use everything to locate a file with unique ID:

  (use-package org
    :config
    (org-link-set-parameters "match"
                             :follow #'org-match-open)

    (defun org-match-open (path)
      "Visit the match search on PATH.
       PATH should be a topic that can be thrown at everything/?."
      (w32-shell-execute
       "open" "Everything" (concat "-search " path))))

23.10 org link: onenote

New link to use everything to locate a file with unique ID:

  (use-package org
    :config
    (org-link-set-parameters "onenote"
                             :follow #'org-onenote-open)

    (defun org-onenote-open (path)
      "Visit the match search on PATH.
       PATH should be a topic that can be thrown at everything/?."
      (cond
       ((eq system-type 'windows-nt)
        (progn
          (w32-shell-execute
           "open" (concat "onenote:" path))))
        ((eq window-system 'ns)
         (shell-command
          (replace-regexp-in-string
           "&" "\\\\&" (format "open onenote:%s" path)))))))

23.11 org link: deft

C-x l keychord can store deft links in deft mode, but cannot fetch the link from deft note. Below defines a function to fetch a deft style link, which can be used to paste directly in other org files, such as work journal. Buffer file name handling function can be found from emacs manual16.

  (use-package org
    :bind
    (("C-x m d" . kimim/deft-store-link))
    :config
    (defun kimim/deft-store-link()
      "get deft link of current note file."
      (interactive)
      (unless (buffer-file-name)
        (error "No file for buffer %s" (buffer-name)))
      (let ((msg (format "[[deft:%s]]"
                         (file-name-nondirectory (buffer-name)))))
        (kill-new msg)
        (message msg))))

23.12 org publish to jekyll

  (use-package org
    :commands (jekyll)
    :config
    ;; file in jekyll base will also be uploaded to github
    (defvar path-jekyll-base "~/kimi.im/_notes/_posts")
    ;; in order to sync draft with cloud sync driver
    (defvar path-jekyll-draft (concat kimim/path-sync "kimim/_draft/"))
    ;; file in jekyll base will also be uploaded to github

    (setq org-publish-project-alist
          '(
            ("org-blog-content"
             ;; Path to your org files.
             :base-directory "~/kimi.im/_notes"
             :base-extension "org"
             ;; Path to your jekyll project.
             :publishing-directory "~/kimi.im/"
             :recursive t
             :publishing-function org-html-publish-to-html
             :headline-levels 4
             :section-numbers t
             :html-extension "html"
             :body-only t ;; Only export section between <body></body>
             :with-toc nil
             )
            ("org-blog-static"
             :base-directory "~/kimi.im/_notes/"
             :base-extension "css\\|js\\|png\\|jpg\\|gif\\|pdf\\|mp3\\|ogg\\|swf\\|php\\|svg"
             :publishing-directory "~/kimi.im/"
             :recursive t
             :publishing-function org-publish-attachment)
            ("blog" :components ("org-blog-content" "org-blog-static"))))

    (use-package ivy)

    (defun jekyll-post ()
      "Post current buffer to kimi.im"
      (interactive)
      ;; get categories
      ;; get buffer file name
      (let ((category (jekyll-get-category))
            (filepath (file-name-directory buffer-file-name))
            (filename (file-name-nondirectory buffer-file-name))
            newfilename)
        (if (not (string-match-p (expand-file-name path-jekyll-base) filepath))
            (progn
              (setq newfilename (concat
                                 path-jekyll-base "/"
                                 category "/"
                                 (format-time-string "%Y-%m-%d-") filename))
              (rename-file buffer-file-name newfilename)
              (switch-to-buffer (find-file-noselect newfilename)))
          ;; execute org-publish-current-file
          (org-publish-current-file)
          (magit-status-setup-buffer))))

    (defun jekyll-tag ()
      "add new tags"
      (interactive)
      ;; find "tags: [" and replace with "tags: [new-tag, "
      (let (tag)
        (goto-char (point-min))
        ;;  (search-forward "tags: [")
        (re-search-forward "tags: \\[" nil t)
        (setq tag (ivy-read "tags: " '(
                                       "Deutsch" "Français" "English"
                                       "emacs" "org-mode"
                                       "Windows" "macOS" "Linux"
                                       "industry" "edge-computing"
                                       "travel" "photography"
                                       "leadership"
                                       "x"
                                       )))
        (if (string= "x" tag)
            (insert "")
          (insert tag ", "))
        tag))

    (defun jekyll-header()
      "Insert jekyll post headers,
  catergories and tags are generated from exisiting posts"
      (interactive)
      (let (tag)
        (insert "#+BEGIN_EXPORT html\n---\nlayout: post\ntitle: ")
        (insert (read-string "Title: "))
        (insert "\ncategories: [")
        (insert (ivy-read "categories: " '(
                                           "technology"
                                           "productivity" "leadership"
                                           "psychology" "language"
                                           "education" "photography"
                                           )))
        (insert "]")
        (insert "\ntags: [")
        (while (progn
                 (setq tag (jekyll-tag))
                 (not (string= "x" tag))))
        (move-end-of-line 1)
        (backward-delete-char 2)
        (insert "]\n---\n#+END_EXPORT\n\n")))

    (defun jekyll ()
      (interactive)
      (find-file (concat path-jekyll-draft "/"
                         (replace-regexp-in-string
                          " " "-" (read-string "Filename: ")) ".org"))
      (jekyll-header)
      (save-buffer))

    (defun jekyll-get-category ()
      (interactive)
      (goto-char (point-min))
      (re-search-forward "^categories: \\[\\([a-z-]*\\)\\]$" nil t)
      (match-string 1))

    (defun jekyll-test ()
      (interactive)
      (org-open-file (org-html-export-to-html nil))))

24 Note Taking Tools

24.1 Deft

  (use-package deft
    :bind
    (("C-x d" . deft-find-file)
     ("C-x C-d" . deft))
    :config
    (use-package ivy)
    (setq deft-extensions '("txt" "org" "md"))
    (setq deft-directory kimim/path-notes)
    (setq deft-recursive t)
    ;; disable auto save
    (setq deft-auto-save-interval 0)
    (setq deft-file-naming-rules '((noslash . "_")))
    (setq deft-text-mode 'org-mode)
    (setq deft-use-filter-string-for-filename t)
    (setq deft-org-mode-title-prefix t)
    (setq deft-use-filename-as-title nil)
    (setq deft-strip-summary-regexp
          (concat "\\("
                  "[\n\t]" ;; blank
                  "\\|^#\\+[[:upper:]_]+:.*$" ;; org-mode metadata
                  "\\|^#\\+[[:alnum:]_]+:.*$" ;; org-mode metadata
                  "\\)"))

    ;;advise deft-open-file to replace spaces in file names with _
    (require 'kimim)
    (defun kimim/deft-open-file-advice (orig-fun &rest args)
      (let (name title)
        (setq name (pop args))
        (if (file-exists-p name)
            (progn
              (push name args)
              (apply orig-fun args))
          (progn
            (setq title (file-name-sans-extension
                         (file-name-nondirectory name)))
            (setq name (concat
                        (file-name-directory name)
                        (kimim/genfile-timestamp)
                        (downcase
                         (replace-regexp-in-string
                          " " "_" (file-name-nondirectory name)))
                        (if (not (file-name-extension name))
                            ".txt")))
            (push name args)
            (apply orig-fun args)
            (insert (concat "#+TITLE: " title "\n\n"))))))

    (advice-add 'deft-open-file
                :around #'kimim/deft-open-file-advice)

    (defun kimim/deft-new-file-named-advice (orig-fun &rest args)
      (let (name title)
        (setq name (pop args))
        (setq title name)
        (setq name (concat
                    (kimim/genfile-timestamp)
                    (downcase
                     (replace-regexp-in-string
                      " " "_" name))))
        (push name args)
        (apply orig-fun args)
        (insert (concat "#+TITLE: " title "\n\n"))))

    (advice-add 'deft-new-file-named
                :around #'kimim/deft-new-file-named-advice))

24.2 Org-roam

Org-roam implements zettelkasten method 17 used by famous German socialogist Niklas Luhmann18.

First you should install sqlite3, which is used to index the links:

apt-cyg install sqlite3
(use-package org-roam
  :ensure t
  :custom
  (org-roam-directory kimim/path-notes)
  (org-roam-file-extensions '("txt" "org"))
  (org-roam-capture-templates
   (quote
    (("d" "default" plain
      (function org-roam-capture--get-point)
      "%?" :file-name "%<%Y_%m%d>_${slug}"
      :head "#+TITLE: ${title}\n\n" :unnarrowed t))))
  :bind (:map org-roam-mode-map
         (("C-c n l" . org-roam)
          ("C-c n f" . org-roam-find-file)
          ("C-c n g" . org-roam-graph))
         :map org-mode-map
         (("C-c n i" . org-roam-insert)
          ("C-c n I" . org-roam-insert-immediate))))

24.3 zetteldeft

(use-package zetteldeft
  :after deft
  :config
  (zetteldeft-set-classic-keybindings)
  (setf zetteldeft-id-regex "[0-9]\\{8\\}\\([A-Z]\\{2,\\}\\)"))

25 Markdown mode

Markdown is widely used as plain text file format.

  (use-package markdown-mode
    :bind(:map markdown-mode-map
               ("M-<up>" . markdown-move-subtree-up)
               ("M-<down>" . markdown-move-subtree-down)))

26 Reference management

  (use-package org-ref
    :after org
    :demand t
    :config
    (setq reftex-default-bibliography ())
    (add-to-list 'reftex-default-bibliography (concat kimim/path-ref "references.bib"))
    (setq org-ref-bibliography-notes (concat kimim/path-notes "org-ref-notes.txt")
          org-ref-pdf-directory kimim/path-ref)
    (setq org-ref-default-bibliography ())
    (add-to-list 'org-ref-default-bibliography (concat kimim/path-ref "references.bib"))
    (setq bibtex-completion-bibliography (concat kimim/path-ref "references.bib")
          bibtex-completion-library-path org-ref-pdf-directory
          bibtex-completion-notes-path org-ref-bibliography-notes)

    ;; open pdf with system pdf viewer
    (setq bibtex-completion-pdf-open-function
          (lambda (fpath)
            (kimim/open-in-external-app fpath)))

    (defun kimim/org-ref-get-pdf-filename (key)
      "Return the pdf filename associated with a bibtex KEY.
  This searches recursively for the pattern KEY*.pdf. If one result
  is found it is returned, but if multiple results are found,
  e.g. there are related files to the KEY you are prompted for
  which one you want."
      (if org-ref-pdf-directory
          (let ((pdfs
                 (-flatten
                  (--map (file-expand-wildcards
                          (f-join it (format "%s*.pdf" key)))
                         (-flatten
                          (append (list org-ref-pdf-directory)
                                  (directory-files-recursively
                                   org-ref-pdf-directory "" t)))))))
            (cond
             ((= 0 (length pdfs))
              (expand-file-name (format "%s.pdf" key) org-ref-pdf-directory))
             ((= 1 (length pdfs))
              (car pdfs))
             ((> (length pdfs) 1)
              (completing-read "Choose: " pdfs))))
        ;; No org-ref-pdf-directory defined so return just a file name.
        (format "%s.pdf" key)))

    (setq org-ref-get-pdf-filename-function 'kimim/org-ref-get-pdf-filename))

There is a built-in bibtex-mode to manage references. We can extend it to support more functions from org-ref:

  (use-package bibtex
    :after org
    :demand t
    :ensure nil
    :bind (:map bibtex-mode-map
                ("C-x m p" . org-ref-open-bibtex-pdf)
                ("C-c C-z" . org-ref-open-bibtex-notes))
    :config
    (use-package org-ref))

27 Dictionary

27.1 Youdao dictionary

Search dictionary with Ctrl+F3 by youdao dictionary.

  (use-package youdao-dictionary
    :bind (
           ("<f12>" . youdao-dictionary-def-copied)
           ("C-<f3>" . youdao-dictionary-search-at-point+)
           :map youdao-dictionary-mode-map
           ("<mouse-3>" . youdao-dictionary-def-copied)
           ("f" . youdao-dictionary-search-from-input))
    :config
    (defun youdao-dictionary-def-copied ()
      (interactive)
      (youdao-dictionary-search (gui-get-selection)))
    )

28 Mail and Contacts

28.1 EBDB - a replacement for BBDB, as contact management

  (use-package ebdb
    :commands (ebdb ebdb-mail-aliases)
    :config
    (setq ebdb-sources (concat kimim/path-sync-emacs "ebdb"))
    ;; do not pop *EBDB-Gnus* window
    (setq ebdb-mua-pop-up nil)
    (require 'ebdb-gnus)
    (require 'ebdb-message)
    (require 'ebdb-org)
    (add-hook 'message-setup-hook 'ebdb-mail-aliases))

28.2 erc

  ;; erc settings
  (use-package erc
    :commands (erc)
    :config
    (require 'erc-join)
    (erc-autojoin-mode 1)
    (erc-autojoin-enable)
    (setq erc-default-server "irc.freenode.net")
    (setq erc-autojoin-channels-alist
          '(("irc.freenode.net" "#emacs")))
    (setq erc-hide-list '("JOIN" "PART" "QUIT")))

28.3 GNUS dired

  (use-package gnus-dired
    :ensure nil
    :commands (turn-on-gnus-dired-mode)
    :config
    ;; make the `gnus-dired-mail-buffers' function also work on
    ;; message-mode derived modes, such as mu4e-compose-mode
    (defun gnus-dired-mail-buffers ()
      "Return a list of active message buffers."
      (let (buffers)
        (save-current-buffer
          (dolist (buffer (buffer-list t))
            (set-buffer buffer)
            (when (and (derived-mode-p 'message-mode)
                       (null message-sent-message-via))
              (push (buffer-name buffer) buffers))))
        (nreverse buffers)))
    (setq gnus-dired-mail-mode 'mu4e-user-agent))

28.4 mu4e

(use-package sendmail
  :ensure nil
  :custom ((mail-user-agent 'sendmail-user-agent)
           (mail-signature nil)
           (mail-self-blind t)
           (mail-signature-file (concat kimim/path-sync-emacs "signature.txt"))))
  (use-package mu-cite
    :commands (mu-cite-original)
    :config
    (setq mu-cite-top-format '("On " date ", " from " wrote:\n\n"))
    (setq mu-cite-prefix-format '(" > ")))
(use-package mu4e
  :ensure nil
  :custom ((mu4e-compose-reply-recipients 'sender)
           (mu4e-compose-signature-auto-include nil))
  :commands (mu4e mu4e-compose-new)
  :bind (
         :map mu4e-headers-mode-map
         ("r" . kimim/mu4e-compose-reply-sender)
         ("R" . kimim/mu4e-compose-reply-all)
         ("f" . kimim/mu4e~view-quit-buffer)
         :map mu4e-compose-mode-map
         ("<C-tab>" . message-tab)
         :map mu4e-view-mode-map
         ("<home>" . move-beginning-of-line)
         ("<end>" . move-end-of-line)
         ("r" . kimim/mu4e-compose-reply-sender)
         ("R" . kimim/mu4e-compose-reply-all))
  :load-path (lambda ()
               (cond ((eq system-type 'darwin)
                      "/usr/local/Cellar/mu/1.0_1/share/emacs/site-lisp/mu/mu4e")
                     ((eq system-type 'cygwin)
                      "/usr/local/share/emacs/site-lisp/mu4e")
                     ((eq system-type 'gnu/linux)
                      "/snap/maildir-utils/current/share/emacs/site-lisp/mu4e")))
  :config
  ;; turn html email to lighter color in dark theme
  (require 'mu4e-contrib)
  (setq mu4e-html2text-command 'mu4e-shr2text)
  (setq shr-color-visible-luminance-min 60)
  (setq shr-color-visible-distance-min 5)
  (setq shr-use-colors nil)
  (advice-add #'shr-colorize-region :around (defun shr-no-colourise-region (&rest ignore)))

  (require 'org-mu4e) ;; capture link
  (use-package sendmail)
  (add-to-list 'Info-additional-directory-list "/usr/local/share/info")
  (setq mu4e-mu-binary "/usr/local/bin/mu")
  (cond ((eq system-type 'gnu/linux)
         (setq mu4e-mu-binary "/snap/bin/mu")))
  (setq mail-user-agent 'mu4e-user-agent)
  ;; Fetch mail by offlineimap
  (setq mu4e-get-mail-command "offlineimap -c ~/.offlineimaprc -u quiet")
  ;; Fetch mail in 60 sec interval
  (setq mu4e-update-interval 300)
  ;; hide indexing messages from minibuffer
  (setq mu4e-hide-index-messages t)
  (setq mu4e-use-fancy-chars nil)
  (setq mu4e-view-show-images t)
  (setq mu4e-view-fields
        '(:subject :from :to :cc :date :mailing-list
                   :attachments :signature :decryption))
  (setq mu4e-headers-fields
        '( (:human-date    .   12)
           (:flags         .    6)
           (:from          .   22)
           (:subject       .   nil)))
  (setq mu4e-compose-cite-function 'mu-cite-original)
  (add-hook 'mu4e-view-mode-hook 'visual-line-mode)
  (add-hook 'mu4e-compose-mode-hook 'kimim/mail-setup)
  (add-hook 'mu4e-compose-mode-hook 'orgalist-mode)
  (add-hook 'mu4e-compose-mode-hook (lambda ()
                                      (auto-fill-mode -1)))
  (defun kimim/mu4e~view-quit-buffer ()
    (interactive)
    (when (get-buffer "*mu4e-view*")
      (switch-to-buffer "*mu4e-view*")
      (mu4e~view-quit-buffer)))

  (defun kimim/mu4e-compose-reply-sender ()
    (interactive)
    (set (make-local-variable 'mu4e-compose-reply-recipients) 'sender)
    (mu4e-compose-reply))

  (defun kimim/mu4e-compose-reply-all ()
    (interactive)
    (set (make-local-variable 'mu4e-compose-reply-recipients) 'all)
    (mu4e-compose-reply)))

29 Viewing Documents

doc-view-mode can view many kind of documents, such as PDF, PS and images. You should install postscript in cygwin.

(use-package doc-view
  :custom ((doc-view-continuous t)
           (doc-view-image-width 500)
           (doc-view-resolution 300)))

30 Reading News

(use-package elfeed
  :commands (elfeed)
  :bind (:map elfeed-search-mode-map
              ("<SPC>" . scroll-up-command)
              ("<backspace>" . scroll-down-command)
         :map elfeed-show-mode-map
         ("M-q" . article-fill-long-lines))
  :config
  ;; open feed link with eww
  (use-package org)
  (require 'gnus-art)
  (setq browse-url-browser-function 'browse-url-default-browser);;eww-browse-url)
  (setq elfeed-curl-extra-arguments '("--proxy" "127.0.0.1:1080"))
  (advice-add 'elfeed-show-entry :after
              (lambda (entry)
                (article-fill-long-lines)))

  (setq elfeed-feeds
        '(
          ("https://www.theguardian.com/world/china/rss" CN)
          ("http://www.chinadaily.com.cn/rss/bizchina_rss.xml" CN)
          ("https://www.lemonde.fr/rss/une.xml" FR une)
          ("http://kimi.im/atom.xml" blog))))

31 kimim utils

In Windows environment, kimim/xterm and kimim/dc will look up the program from system PATH, so you should set these to system PATH.

  (use-package kimim
    :ensure nil
    :commands (kimim/mail-setup)
    :bind
    (("C-x m m" . kimim/mail-new-empty)
     ("C-x m y" . kimim/mail-attach-files)
     ("<f9>" . kimim/xterm)
     ("S-<f9>" . kimim/cmd)
     ("C-c r" . kimim/rename-file-and-buffer)
     ("C-x m o" . kimim/open-in-external-app)
     ("C-c d" . kimim/lookinsight))
    :load-path "~/kimim-emacs/site-lisp/")

32 Key Binding

  (bind-key "<f1>" 'delete-other-windows)
  (bind-key "C-<f1>" 'nuke-other-buffers)
  (bind-key "M-<f1>" (lambda()
                       (interactive)
                       (switch-to-buffer "*scratch*") (nuke-other-buffers)))
  (bind-key "<f2>" 'other-window)
  (bind-key "<f5>" (lambda ()
                     (interactive)
                     (switch-to-buffer "*scratch*") (delete-other-windows)))
  ;;(bind-key "<f7>" 'kimim/toggle-highlight-tap)
  ;;(bind-key "<f8>" (lambda ()
  ;;                   (interactive) (list-charset-chars 'ascii)))
  (bind-key "<f7>" 'bury-buffer)
  (bind-key "<f8>" 'unbury-buffer)
  ;; (bind-key "M-<SPC>" (lambda () (interactive)
  ;;                       (insert ?_)))
  (bind-key "C-h" 'delete-backward-char)
  (bind-key "M-h" 'backward-kill-word)
  (bind-key "M-?" 'mark-paragraph)
  (bind-key "C-x k" 'kill-this-buffer)
  (bind-key "C-x C-v" 'view-file-other-window)
  (bind-key "C-c C-o" 'occur)
  (bind-key "C-z" 'set-mark-command)
  (bind-key "M-o" 'other-window)
  (bind-key "M-n" 'next-error)
  (bind-key "M-p" 'previous-error)
  ;;(define-key hs-minor-mode-map "\C-c/" 'hs-toggle-hiding)
  (bind-key "M-*" 'pop-tag-mark)

  (bind-key "C-c C-/" 'comment-or-uncomment-region)
  (bind-key "RET" 'newline-and-indent)
  ;;(define-key global-map (kbd "<M-S-mouse-1>") 'pop-tag-mark)
  ;; key bindings
  (when (eq system-type 'darwin) ;; mac specific settings
    (setq mac-option-modifier 'super)
    (setq mac-command-modifier 'meta)
    ;; sets fn-delete to be right-delete
    (global-set-key [kp-delete] 'delete-char))

  (bind-key "C-x m h" 'help)
  (bind-key "C-x m c" 'calculator)
  (bind-key "C-x m n" 'compose-mail)
  (bind-key "C-x m s" '(lambda ()
                         (interactive)
                         (set-frame-font
                          (concat "Inconsolata-" (read-string "Enter font size: ")) t)))
  (bind-key "C-x m ." 'unbury-buffer)
  (bind-key "C-x m ," 'bury-buffer)
  (bind-key "C-x m  。" 'unbury-buffer)
  (bind-key "C-x m  ," 'bury-buffer)
  (bind-key "C-x ," 'bury-buffer)
  (bind-key "C-x ." 'unbury-buffer)
  (bind-key "C-x  ," 'bury-buffer)
  (bind-key "C-x  。" 'unbury-buffer)
  (bind-key "C-x  ‘" 'hippie-expand)
  (bind-key "C-x  ’" 'hippie-expand)
  (bind-key "C-x M-s" 'eshell)

Footnotes:

Created: 2020-11-22 Sun 09:47