Skip to content
Switch branches/tags
Go to file
Cannot retrieve contributors at this time
1713 lines (1408 sloc) 53.2 KB

Updated: <2021-07-26 12:44:36>

This file must be tangled into init.el in the emacs configuration directory, ~/init.d/.

;; Tangle this file into init.el, then load it.
;; Output logged in *Messages* buffer
(message "Tangled and Loaded!\n  |- %s\n  |- %s\n  |- %s"

         ;; tangled file name
           (expand-file-name (concat user-emacs-directory "init.el"))

         ;; date and time of tangle
         (format-time-string "%Y-%m-%d.%H-%M-%S" (current-time))

         ;; load tangled file
         (load (concat user-emacs-directory "init.el")))

Tangle to init.el [3/4]

  • [ ] Add prompt before overwriting init.el. OR… just do it and backup old one?

my/ functions

(defun my/now ()
  "Return the current date and time appropriate for placing in Windows file names."
   (format-time-string "%Y-%m-%d--%H-%M-%S" (current-time))))

(defun my/use-first-directory (dirlist)
  "Return first valid directory that exists in `dirlist'.  If no directory is valid & exists, return nil.

  `dirlist' is a list of string paths to test with file-exists-p.
  (catch 'match-found    
    (dolist (d dirlist)
      (if (file-exists-p d) (throw 'match-found d)))))


package - REQUIRED

(package-initialize) must come before configurations of installed packages.

;; Using defaults from DOOM config
(setq gc-cons-threshold 402653184      ; default is 800,000 ... too small!
      gc-cons-percentage 0.6)   

;; Do not edit this file.  See ""
;; This file is generated from using org-babel-tangle
(setq package-enable-at-startup nil)

(when (>= emacs-major-version 24)
  (require 'package)
  ;; melpa vs elpa
  (add-to-list 'package-archives
               '("melpa" . "") t)
  ;; newer org-mode
  (add-to-list 'package-archives
               '("org" . "") t)


;; This is only needed once, near the top of the file
  ;; Following line is not needed if use-package.el is in ~/.emacs.d
  (add-to-list 'load-path "<path where use-package is installed>")
  (require 'use-package))                ; we want this instead of 'require

(setq use-package-always-ensure t)      ; ensure package is installed
(setq use-package-verbose t) 		; report config loading time in *Messages*


Load things that should be slightly more private.

;; ensure init_private.el is loaded
(setq init_private_loaded
       (concat user-emacs-directory
;; defines: my/user-dir, my/on-work-pc, my/user-name, my/computer-name, my/org-directory

Emacs - General

User - name, email

(setq user-full-name "Steven Brown")
(setq user-mail-address "")


(setq holiday-general-holidays nil)     ; Remove US defaults, add back some later

;; `calendar-holidays' initialized from multiple *holidays lists.  used in both
;; calendar and org agenda.  Once loaded, `calendar-holidays' must be modified
;; directly.
(setq holiday-local-holidays            ; Canada/BC Holidays
      '((holiday-fixed 1 1 "New Year's Day")
        (holiday-float 2 1 3 "Family Day")
        (holiday-easter-etc -2 "Good Friday")
        (holiday-easter-etc 1 "Easter Monday")
        (holiday-float 5 1 -2 "Victoria Day")
        (holiday-fixed 6 21 "Aboriginal Day")
        (holiday-fixed 7 1 "Canada Day")
        (holiday-float 8 1 1 "BC Day")
        (holiday-float 9 1 1 "Labour Day")
        (holiday-float 10 1 2 "Thanksgiving (Canadian)")
        (holiday-fixed 11 11 "Remembrance Day")
        (holiday-fixed 12 25 "Christmas")
        (holiday-fixed 12 26 "Boxing Day")))

(setq holiday-other-holidays            ; US and shared non-Stats
      '((holiday-float 1 1 3 "Martin Luther King Day (US)")
        (holiday-fixed 2 2 "Groundhog Day")
        (holiday-fixed 2 14 "Valentine's Day")
        (holiday-float 2 1 3 "President's Day (US)")
        (holiday-fixed 3 17 "St. Patrick's Day")
        (holiday-fixed 4 1 "April Fools' Day")
        (holiday-float 5 0 2 "Mother's Day")
        (holiday-float 5 1 -1 "Memorial Day (US)")
        (holiday-fixed 6 14 "Flag Day (US)")
        (holiday-float 6 0 3 "Father's Day")
        (holiday-fixed 7 4 "Independence Day (US)")
        (holiday-float 10 1 2 "Columbus Day (US)")
        (holiday-fixed 10 31 "Halloween")
        (holiday-fixed 11 11 "Veteran's Day (US)")
        (holiday-float 11 4 4 "Thanksgiving (US)")))

General - colour, lines, columns, backups, frame

(setq ansi-color-faces-vector
      [default bold shadow italic underline bold bold-italic bold])
(setq-default fill-column 80)      ; where to wrap lines; set locally with C-x f
(set-default 'truncate-lines t)    ; truncate long lines, don't wrap them
(setq column-number-mode t)        ; show column numbers in modeline
(setq inhibit-startup-screen t)    ; skip startup screen
(show-paren-mode t)                ; highlight matching parentheses
(setq show-paren-delay 0)
(setq show-paren-when-point-inside-paren t)
(setq show-paren-when-point-in-periphery t)
(setq show-paren-style 'parenthesis)    ; "mixed" and "expression" is far too obnoxious for incomplete expressions
(global-hl-line-mode t)            ; highlight current line
(setq visible-bell t)              ; blink, don't bark
(setq x-stretch-cursor t)          ; cursor width will match tab character width
(set-default 'indent-tabs-mode nil)

;;(setq uniquify-buffer-name-style (quote forward) nil (uniquify))
(setq uniquify-buffer-name-style (quote post-forward-angle-brackets))

(desktop-save-mode 0)         ; save the desktop/state of emacs' frames/buffersb

;; backups - filename.ext~
(setq backup-directory-alist `(("." . ,(expand-file-name ".backups/" user-emacs-directory)))) ; keep in clean
(setq backup-by-copying t)              ; vs renaming

;; autosaves - #filename.ext#, when autosave mode enabled, saves unsaved changes
;; (setq auto-save-list-file-prefix (expand-file-name ".auto-saves/" user-emacs-directory))

;; lock files - .#filename.ext
;; (setq create-lockfiles nil)

(put 'narrow-to-region 'disabled nil)   ; enable narrowing C-x n n

(toggle-scroll-bar 0)
(tool-bar-mode 0)                      ; Remove clunky toolbar and icons
(global-eldoc-mode 1)                  ; highlight parameters in minibuffer
(setq reb-re-syntax 'string)           ; C-c TAB to cycle when in regexp-builder

;; see file-local variable: time-stamp-pattern, time-stamp-start, etc
(add-hook 'before-save-hook 'time-stamp) ; update timestamps of set format before saving

(setq delete-by-moving-to-trash t)     ; move files to trash instead of deleting

(add-hook 'image-mode-hook 'auto-revert-mode) ; update image buffers when files change

(setq-default python-indent-offset 4)


list-fontsets to see available installed fonts.

Some good programming fonts here.

  1. Inconsolata
  2. Fira Mono
  3. Source Code Pro
  4. Anonymous Pro
  5. M+ 1M
  6. Hack
  7. DejaVu Sans Mono
  8. Droid Sans Mono
  9. Ubuntu Mono
  10. Bitsream Vera Sans Mono
;; Test char and monospace:
;; 0123456789abcdefghijklmnopqrstuvwxyz [] () :;,. !@#$^&*
;; 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ {} <> "'`  ~-_/|\?

(setq default-font-name nil)
 ;; First choice
 ((find-font (font-spec :name "DejaVu Sans Mono"))
  (setq default-font-name "DejaVu Sans Mono")
  (setq default-font-size 12))

 ;; Second choice
 ((find-font (font-spec :name "Consolas"))
  (setq default-font-name "Consolas")
  (setq default-font-size 13))

 ;; Fallback, if we must...
 ((find-font (font-spec :name "Courier New"))
  (setq default-font-name "Courier New")
  (setq default-font-size 12))

;; variable pitch font
 ((find-font (font-spec :name "Calibri"))
  (set-face-attribute 'variable-pitch nil 
                      :family "Calibri"
                      :height (* 10 (+ 2 default-font-size))

(when default-font-name
    ;; use default font in new frames
    (add-to-list 'default-frame-alist
                 `(font . ,(format "%s-%s"
                                   (or default-font-size 12))))

    (set-face-attribute 'fixed-pitch nil
                        :family default-font-name
                        :height (* 10 default-font-size))))

;; initial frame should reasonably fit 1080p screencasts
(setq initial-frame-alist
      `((top . 10) (left . 1) (width . 120) (height . 50)))
;; new frames should be slightly smaller, but still usable
(add-to-list 'default-frame-alist
             '(width . 110))
(add-to-list 'default-frame-alist
             '(height . 50))

Try a font

Use eval-last-sexp (C-x C-e) to try the different fonts: info:emacs#Lisp Eval

(set-frame-font "Consolas-13")
(set-frame-font "Source Code Pro 12")
(set-frame-font "Liberation Mono 12")
(set-frame-font "Fira Mono 12")
(set-frame-font "Anonymous Pro 13")
(set-frame-font "DejaVu Sans Mono-12")
(set-frame-font "Lucida Console-12")
(set-frame-font "Inconsolata 12")
(set-frame-font "M+ 1m 14")
(set-frame-font "Ubuntu Mono 13")
(set-frame-font "Courier New-12")

Look at installed fonts

(x-select-font nil t)


  • Custom Themes (not color-themes) can be loaded and stacked using load-theme.
  • Loaded themes must be unloaded individually by disable-theme.
  • Both allow tab-completion for applicable themes.
;; (unless custom-enabled-themes
;;   (load-theme 'material t nil))		; load & enable theme, if nothing already set
(setq custom-theme-directory user-emacs-directory)
(load-theme 'two-fifteen t)             ; current theme, work-in-progress

(setq window-divider-default-right-width 4)
(setq window-divider-default-bottom-width 1)
(setq window-divider-default-places 'right-only)
(window-divider-mode 1)


(setq PYTHONIOENCODING "utf-8")        ;print utf-8 in shell
(prefer-coding-system 'utf-8)

;; Unicode characters cause some windows systems to hang obnoxiously
;; (Easily noticed in large org-mode files using org-bullets package.)
(when (eq system-type 'windows-nt)
  (setq inhibit-compacting-font-caches t))

ibuffer - custom filters

(define-key global-map "\C-x\C-b" 'ibuffer) ;

(setq ibuffer-saved-filter-groups
          (used-mode . dired-mode))
         ("Org Files"
          (used-mode . org-mode))
          (name . "\\*ein:.*"))
          (used-mode . python-mode))
         ("Emacs Lisp"
          (used-mode . emacs-lisp-mode))
          (used-mode . image-mode))
          (name . "\\*define-it:.*"))
          (name . "\\*Help\\*\\|\\*helpful .*"))

(setq ibuffer-saved-filters
           (mode . message-mode)
           (mode . mail-mode)
           (mode . gnus-group-mode)
           (mode . gnus-summary-mode)
           (mode . gnus-article-mode))))
           (mode . emacs-lisp-mode)
           (mode . cperl-mode)
           (mode . c-mode)
           (mode . java-mode)
           (mode . idl-mode)
           (mode . lisp-mode)))))))


If there is a compile error, or “tar not found,” try package-refresh-contents to refresh the package database.


(use-package plantuml-mode :ensure t)


  • S-<mouse2> and C-c @ C-t also work; C-c @ C-a to toggle all.
  • C-c C-j to jump (imenu)
(add-hook 'python-mode-hook 'hs-minor-mode)
(eval-after-load "python"
  '(define-key python-mode-map (kbd "<C-tab>") 'hs-toggle-hiding))


Use for demoing emacs; keystrokes get logged into a designated buffer, along with the command bound to them.

(use-package command-log-mode)


Instead of wrapping lines at the window edge, which is the standard behaviour of `visual-line-mode’, it wraps lines at `fill-column’. Must be enabled after enabling visual-line-mode. I leave it off by default, but want it available depending on the situation.

(use-package visual-fill-column
  :ensure t)

elfeed - RSS reader

(unless my/on-work-pc
  (use-package elfeed
    :defer t
    ;; (setq elfeed-feeds
    ;;       '("" ""))
    (define-key elfeed-show-mode-map (kbd "j") 'shr-next-link)
    (define-key elfeed-show-mode-map (kbd "k") 'shr-previous-link)
    (define-key elfeed-show-mode-map (kbd "e") 'eww)

    (add-hook 'elfeed-show-mode-hook
              (lambda ()
                  (visual-line-mode t)
                  (when (fboundp 'visual-fill-column-mode)
                    (visual-fill-column-mode t))
                  (text-scale-increase 1)

  (use-package elfeed-org
    :after (elfeed)
    :defer t
    (setq rmh-elfeed-org-files (list (concat my/org-directory "")))


quickly browse, filter, and edit plain text notes

(use-package deft
  (setq deft-directory my/org-directory)

erc - IRC client

  • info:erc#Top

god-mode, objed - modal navigation and editing

Modal editing in an emacs-y way.

(use-package god-mode :ensure nil :defer t)
(use-package objed :ensure nil :defer t)


Place to put themes 100% decided on.

(use-package material-theme :ensure t :defer t)
(use-package leuven-theme :ensure t :defer t)
;; (use-package spacemacs-theme
;;   :ensure t
;;   :defer t
;;   ;; :init (load-theme 'spacemacs-dark t)
;;   )


Hides or renames minor modes.

(use-package diminish :ensure t)

smartparens - Minor mode to work with pairs

(use-package smartparens
  :ensure t
  :defer t
  (setq sp-smartparens-bindings "sp")

which-key - Comand popup

  • Gentle reminders and added discoverability.
(use-package which-key
  :ensure t
  :diminish which-key-mode

company - Auto-completion front-end

(use-package company
  :ensure t
  :diminish company-mode
  ;; (add-hook 'ein:connect-mode-hook 'ein:jedi-setup)
  ;; (add-hook 'ein:connect-mode-hook 'company-mode) ; Can't figure out company-jedi + ein

  (setq company-idle-delay 0.5)
  (setq company-minimum-prefix-length 1)
  (global-company-mode 1)

(use-package company-quickhelp
  :ensure t
  :defer 2
  (company-quickhelp-mode 1)
  (setq company-quickhelp-delay 1.5)

;; Reduce noise in candidate suggestions
(push (apply-partially
       (lambda (c)
         (or (string-match-p "[^\x00-\x7F]+" c) ;non-ansii candidates
             (string-match-p "0-9+" c)        ;candidates containing numbers
             (if (equal major-mode "org")       ;
                 (>= (length c) 15))))) ; candidates >= 15 chars in org-mode

iedit - Simple refactoring

(use-package iedit
  :ensure t)

language server - lsp-mode or eglot

Trying lsp-mode and eglot instead of anaconda-mode. lsp-mode seems to require Emacs 27 (recommended ~15x faster).

(use-package eglot)

Trying to manage system-level packages with conda, not pip

  • pip uninstall python-language-server (if installed)
  • conda install python-language-server
  • [ ] maybe use ms python language server?
(use-package lsp-mode
  :hook ((python-mode . lsp-deferred)
         ;; which-key integration
         (lsp-mode . lsp-enable-which-key-integration))
  :commands (lsp lsp-deferred)
  (setq lsp-keymap-prefix "c-s-l")

;; optional
(use-package lsp-ui :commands lsp-ui-mode) ;automatically activated by lsp-mode
(use-package lsp-ivy :commands lsp-ivy-workspace-symbol)

esup - Emacs Start Up Profiler

  • M-x esup
  • C-u M-x esup to use custom file
  • HOME PC:
    Total User Startup Time: 0.285sec     Total Number of GC Pauses: 8     Total GC Time: 0.047sec
    • HOME Laptop, battery:
      Total User Startup Time: 20.273sec    Total Number of GC Pauses: 12    Total GC Time: 0.511sec
      ein-connect.elc:15  6.680sec   32% (x2)
      gnus-sum.elc:16  1.953sec   9%
      anaconda-mode.elc:16  1.742sec   8%
      • WORK Laptop:
      Total User Startup Time: 81.152sec     Total Number of GC Pauses: 17     Total GC Time: 0.504sec
      ein-connect.elc:15  21.581sec   26% (x2)
      anaconda-mode.elc:16  15.036sec   18%
      use-package.elc:15  2.944sec   3% (x2)
(use-package esup
  :ensure nil
  :defer t

smartscan - Simple word-instance jumping

  • easily move between like-symbols
  • NOTE: currently conflicts with ein checkpoint bindings.
(use-package smartscan
  :ensure nil
  :defer 1
  ;; :bind (("M-n" . smartscan-symbol-go-forward)
  ;;        ("M-p" . smartscan-symbol-go-backward))

org2blog - Blog to wordpress from org

(use-package org2blog
  :ensure nil
  :defer 1
  ;; see init_private.el

beacon - Highlight cursor when switching windows

  • animated indicator of cursor location when switching windows
(use-package beacon
  :ensure t
  (beacon-mode 0))                    ; causes slow updates on some comps

doom-modeline - Clean minimal modeline

(use-package doom-modeline
  :ensure t
  (setq doom-modeline-icon nil)
  (after-init . doom-modeline-mode)

origami - Code folding

(use-package origami
  :ensure nil
  :defer t

flycheck - Syntax-checking

(use-package flycheck
  :ensure t
  :defer t
  ;; :config
  ;; (global-flycheck-mode) <-- too noisy, enable when needed

diff-hl - Highlight diffs

(use-package diff-hl
  :ensure t
  :defer t
                                        ;(global-diff-hl-mode)  ;; slow on lesser computers

avy - Jump to visible text

(use-package avy :ensure t
  :bind ("C-:" . avy-goto-char-2))

Ivy, Counsel, Swiper - Minibuffer completion suite

Suite of completion tools. counsel will install others, as it requires swiper which requires ivy.

(use-package counsel                    ; requires swiper, which requires ivy
  :ensure t
  (setq ivy-use-virtual-buffers t)
  (setq ivy-count-format "%d/%d ")      ; current/total match number
  (setq enable-recursive-minibuffers t)
  (setq ivy-re-builders-alist 
        '((t . ivy--regex-plus)))
                                        ;'((t . ivy--regex-fuzzy ))) ; try fuzzy matching
  ;; use ivy completion on any command using 'completing-read-function'
  (ivy-mode 1)
  (counsel-mode 1) ; use counsel equivalents of existing Emacs functions

  (diminish 'ivy-mode)
  (diminish 'counsel-mode)

  :bind (("C-s" . swiper)               ; Replace isearch-forward
         ("M-s s" . isearch-forward)
         ("C-h v" . counsel-describe-variable)
         ("C-h f" . counsel-describe-function)
         ("C-h S" . counsel-info-lookup-symbol)
         ("C-x u" . counsel-unicode-char)


More description to ivy display.

(use-package ivy-rich
  :ensure t
  :after ivy
  (ivy-rich-mode 1)

try - try package before installing

Try is a package that allows you to try out Emacs packages without installing them.

(use-package try
  :ensure t 
  :defer t

rainbow-mode - Set bg to colour of #00000 string

(use-package rainbow-mode :ensure t)

expand-region - Select “up”

Example of how use-package can replace require and global-set-key.

(use-package expand-region
  :ensure t
  :defer 1
  :bind ("C-=" . er/expand-region))

wrap-region - Wrap region in matching characters

(use-package wrap-region
  :ensure t
   '(("*" "*" nil org-mode)
     ("~" "~" nil org-mode)
     ("/" "/" nil org-mode)
     ("=" "=" ":" org-mode) ; Avoid conflict with expand-region, use ':'
     ("+" "+" "+" org-mode)
     ("_" "_" nil org-mode)))
  ;; ("$" "$" nil (org-mode latex-mode))
  (add-hook 'org-mode-hook 'wrap-region-mode))
(diminish 'wrap-region-mode)

org-bullets - Unicode org-mode bullets

(use-package org-bullets
  :ensure t
  (add-hook 'org-mode-hook (lambda () (org-bullets-mode t)))
  ;;  (setq org-bullets-bullet-list '("◉" "◎" "○" "►" "◇"))

ace-window - DWIM window switcher

  • Note: aw-scope defaults to global (all frames). Toggle by setting to frame
  • swap window: C-u ace-window
  • delete window: C-u C-u ace-window

    At the dispatcher (3 or more windows unless aw-dispatch-always = t):

    • x : delete window
    • m : swap windows
    • M : move window
    • j : select buffer
    • n : select the previous window
    • u : select buffer in the other window
    • c : split window fairly, either vertically or horizontally
    • v : split window vertically
    • b : split window horizontally
    • o : maximize current window
    • ? : show these command bindings
(use-package ace-window
  :ensure t
  :bind ("M-o" . ace-window )           ; replace facemenu-keymap binding
(setq aw-scope 'frame)                  ; Only consider current frame's windows

transpose-frame - transpose windows in frame

This program provides some interactive functions which allows users to transpose windows arrangement in currently selected frame:

`transpose-frame’ … Swap x-direction and y-direction

————————+ —————-——–+

A ————
C=> ——–——-+ D

————————+ | B | C | |


————————- ——–——-+——–+

`flip-frame’ … Flip vertically

————————+ ————————+

A ———— ————————+

————————+ | A ————


————————- ————————+

`flop-frame’ … Flop horizontally

————————+ ————————+

A ———— ———— A

————————+ ————————+


————————- ————————-

`rotate-frame’ … Rotate 180 degrees

————————+ ————————-

A ———— ————————+

————————+ ———— A |


————————- ————————+

`rotate-frame-clockwise’ … Rotate 90 degrees clockwise

————————+ ——-—————–+

A ————
C=>D ——–——–+

————————+ | | B | C |


————————- ——-——–+——–+

`rotate-frame-anticlockwise’ … Rotate 90 degrees anti-clockwise

————————+ ——–——–+——-+

A ————
C=> ——–——–+ D

————————+ | A | |


————————- —————–——-+

(use-package transpose-frame
  :ensure t
(setq aw-scope 'frame)                  ; Only consider current frame's windows


magit - Git integration

A Git version control interface.

Recommended: ssh-keygen, add key to git host, ensure .ssh/ directory is in HOME directory (C:/Users/Username/AppData/Roaming/ on Windows 10)

(use-package magit
  :ensure t
  :defer t
  :bind ("C-x g" . magit-status)


  • Do we really need the thousands of snippets from yasnippet-snippets?
  • [ ] Cherry pick a few, put into custom directory.
(use-package yasnippet
  :ensure nil
  :defer t
;; add generic fundamental-mode snippets across all modes
(add-hook 'yas-minor-mode-hook (lambda ()
                                 (yas-activate-extra-mode 'fundamental-mode)))

neotree - File tree explorer bound to <F8>

(use-package neotree
  :ensure t
  :bind ("<f8>" . neotree-toggle)


M-UP and M-DOWN to move lines/regions

(use-package move-text
  :ensure t)


Major mode for editing markdown.

(use-package markdown-mode
  :ensure t)

helpful - adding more info to emacs help

(use-package helpful
  :ensure t

  ;; replace default help functions
  :bind (("C-h f" . helpful-callable)
         ("C-h v" . helpful-variable)
         ("C-h k" . helpful-key)

         ;; additional
         ("C-c C-d" . helpful-at-point) ;
         ;; ("C-h F" . helpful-function) ; replace
         ;; ("C-h C" . helpful-command) ; 


(use-package multiple-cursors
  :ensure t
  :defer t
  :bind (
         ("C-|" . 'mc/edit-lines)
         ("C->" . 'mc/mark-next-like-this)
         ("C-<" . 'mc/mark-previous-like-this)
         ("C-c C-<" . 'mc/mark-all-like-this)
         ("C-S-<mouse-1>" . 'mc/add-cursor-on-click)


(use-package pyvenv
  :ensure t
  :defer t
  (setenv "WORKON_HOME"
            (concat my/user-dir


Define, translate, wiki the word

(use-package define-it :ensure t :defer t
  (setq define-it-show-google-translate nil)              ; Disable translate by default
  (setq google-translate-default-source-language "auto")  ; Auto detect language.
  (setq google-translate-default-target-language "en")    ; Set your target language.

ein - Emacs iron python notebook (Jupyter)

  • Jupyter Notebooks in emacs! Added [2017-10-19 Thu]
  • Slow. Include only when needed or designated configs
;; Jupyter python  ;added 2017-10-17
(use-package ein
  :ensure t
  :defer t
  ;; :backends ein:company-backend
  (require 'ein-connect)     ; not sure why this is needed suddenly..?

  ;; Fix Null value passed to ein:get-ipython-major-version #work pc
  ;; (ein:force-ipython-version-check)

  ;; (advice-add 'request--netscape-cookie-parse :around #'fix-request-netscape-cookie-parse)
  (setq ein:completion-backend 'ein:use-company-backend)


(use-package projectile
  :ensure t				; ensure package is downloaded
  :defer t
  :init					; pre-load config
  (setq projectile-enable-caching t)	; resolve missing projects
  ;; (projectile-mode +1)			; global projectil mode
  :config nil				; post-load config

(use-package org-gcal
  :ensure nil)
;;  See init_private.el for setup

org-gcal Usage

  • org-gcal-sync: Sync between Org and Gcal. before syncing, execute org-gcal-fetch
  • org-gcal-fetch: Fetch Google calendar events and populate org-gcal-file-alist locations. The org files in org-gcal-file-alist should be blank or all of their headlines should have timestamps.
  • org-gcal-post-at-point: Post/edit org block at point to Google calendar.
  • org-gcal-delete-at-point: Delete Gcal event at point.
  • org-gcal-refresh-token: Refresh the OAuth token. OAuth token expired in 3600 seconds, You should refresh token on a regular basis.

ob-ipython - jupyter for org-mode

;; INCREDIBLY slow startup time.  Disabled, run when needed.
(use-package ob-ipython
  :ensure t
  (add-hook 'ob-ipython-mode-hookp
            (lambda ()
              (company-mode 1)))
   '((ipython . t)
     ;; other languages..
  (add-to-list 'company-backends 'company-ob-ipython)

ob-async - asynchronous execution of org-babel src blocks
;; INCREDIBLY slow startup time.  Disabled until needed.
(use-package ob-async
  :ensure t)

Packages that have been superceded

spaceline - (Powerline) modeline

Ditched in favour of doom-modeline
(use-package spaceline
  :ensure t
  (require 'spaceline-config)
  (setq powerline-default-separator 'wave)
  (spaceline-spacemacs-theme))          ; quickly makes modeline pretty

anzu - Count isearch matches

(use-package anzu
  :ensure nil
  (global-anzu-mode +1))

smex - Fuzzy M-x function matching

(use-package smex
  :ensure t
  :bind (;("M-x" . smex) replaced w/counsel
         ("M-X" . smex-major-mode-commands)
         ("C-c C-c M-x" . execute-extended-command)))

[#B] selected-packages

Superceded by use-package

package-selected-packages is used by package-autoremove to whitelist packages explicity installed by the user. But use-package does not update package-selected-packages, so cannot really be used in combination with use-package.

You can use it to (re)install packages on other machines by running ‘package-install-selected-packages’.

See currently activated packages with package-activated-list.

(setq package-selected-packages
       (org-bullets tangotango-theme leuven-theme eziam-theme alect-themes
                    atom-one-dark-theme borland-blue-theme material-theme
                    helm helm-projectile expand-region org-projectile
                    projectile web-mode)))

paredit - Intense parentheses mode (not enabled)

(use-package paredit
  :ensure t
  :defer t)


Let dired try to guess target (copy and rename ops) directory when two dired buffers open.

Super useful!

  • wdired-mode:

In WDired mode, you can edit the names of the files in the buffer, the target of the links, and the permission bits of the files. After typing C-c C-c, Emacs modifies the files and directories to reflect your edits.

(setq dired-dwim-target t)		; guess target directory
(define-key dired-mode-map (kbd "C-c w") 'wdired-change-to-wdired-mode)
(add-hook 'dired-load-hook
          (lambda ()
            ;; Use dired-x-find-file over find-file
            (setq dired-x-hands-off-my-keys nil) ; must be done before loading dired-x
            ;; Set dired-x global variables here.  For example:
            ;; (setq dired-guess-shell-gnutar "gtar")
(load "dired-x")
(add-hook 'dired-mode-hook
          (lambda ()
            ;; Set dired-x buffer-local variables here.  For example:
            (dired-omit-mode 1)
(autoload 'dired-jump "dired-x"
  "Jump to Dired buffer corresponding to current buffer." t)

(autoload 'dired-jump-other-window "dired-x"
  "Like \\[dired-jump] (dired-jump) but in other window." t)

(define-key global-map "\C-x\C-j" 'dired-jump)
(define-key global-map "\C-x4\C-j" 'dired-jump-other-window)

Org Mode


(setq org-export-initial-scope 'subtree)
(setq org-use-subsuperscripts '{})      ; require {} wrapper for ^super/_sub scripts
;; postamble
(setq org-html-postamble 't)
(setq org-html-postamble-format
      '(("en" "<p class=\"author\">%a</p> <p class=\"date\">%T</p>")))


;; (add-to-list 'load-path "~/../or
;; my/org-directory defined in init_private.el
(setq org-agenda-files (list
                        (concat my/org-directory "")    ; Home/Learn/Everything
                        (concat my/org-directory "")     ; Work
                        (concat my/org-directory "")))  ; Life Stuff - rename to 'personal'?

(setq org-default-notes-file (concat my/org-directory "")) ; Unsorted  Notes


(setq org-capture-templates
      `(("t"				; key
         "Task (work)"                  ; description
         entry				; type
         ;; heading type and title
         (file+headline ,(concat my/org-directory "") "Inbox") ; target
         "* TODO %?\n%i\n%a\n\n"	; template
         ;; optional property list  ; properties
         :prepend t                     ; insert at head of list
        ("T"				; key
         "Task (general)"               ; description
         entry				; type
         ;; heading type and title
         (file+headline org-default-notes-file "Tasks") ; target
         "* TODO %?\n%i\n%a\n\n"                      ; template
         ;; optional property list  ; properties
         :prepend t                     ; insert at head of list
        ("m"				; key
         "Meeting (work)"               ; description
         entry                          ; type
         ;; heading type and title
         (file+headline ,(concat my/org-directory "") "MINUTES & MEETINGS") ; target
         "* %?\n%^T  (entered %U from %a)\n%i\n\n" ; template
         :prepend t
         "Daily Log (work)"
         (file+olp+datetree ,(concat my/org-directory "") "Daily")
         "1. %<%H:%M> %^{prompt}  %K - %a\n   - %?\n"  ; ?? Use %<...> instead of %U
         :prepend nil
         :unnarrowed t
         :empty-lines-before 0
         :empty-lines-after 0
         "Learning Journal"
         (file+olp+datetree org-default-notes-file "Learning Journal")
         "* %?\nEntered on %U\n- Active Region: %i\n- Created while at: %a\n\n" ; %a stores link, %i is active region


(setq org-ellipsis "")			;⤵, ▐, ►, ▽, ◿, ◹, », ↵, ≋, …, ⋞, ⊡, ⊹, ⊘

;; fontify (pretty formating) code in code blocks
(setq org-src-fontify-natively t)	; important for !
(setq org-hide-emphasis-markers t)      ; hide italic,bold,monospace text
                                        ; formatters

(setq org-fontify-quote-and-verse-blocks t) ; fontify quote and verse blocks

;; org-refile (C-c C-w)
(setq org-refile-targets (quote ((nil :maxlevel . 5)
                                 (org-agenda-files :maxlevel . 5))))
(setq org-outline-path-complete-in-steps nil) ; prevent org interfering w/ivy
(setq org-refile-use-outline-path 'file) ; refile paths begin with the file name
(setq org-refile-allow-creating-parent-nodes 'confirm) ; confirm creation of new headings
(setq org-reverse-note-order t)         ; new notes at top of file or entry

;; org-mode customization
(setq org-log-done 'time)         ; add time stamp when task moves to DONE state
(setq org-todo-keywords           ; default TODO keywords
      '((sequence "TODO(t)" "STARTD(s)" "WAITING(w)" "|" "DONE(d)" "DELEGATED(e)" "CANCELLED(c)")))

                                        ;org-mode keybindings
(define-key global-map "\C-cc" 'org-capture)    ; todo: move to use-package :bind ?
(define-key global-map "\C-ca" 'org-agenda)     ;
(define-key global-map "\C-cl" 'org-store-link) ;

;; Add python to list of languages for org-babel to load
 '((emacs-lisp . t)
   (python . t)
   ;; (ipython . t) ;; requires ob-ipython
   (ditaa . t)
   (plantuml . t)
   (shell . t)

;; Don't prompt before running org code blocks w/C-c C-c
(setq org-confirm-babel-evaluate nil)

;; Fix an incompatibility between the ob-async and ob-ipython packages
(setq ob-async-no-async-languages-alist '("ipython"))

;; Enable single-key commands at beginning of headers
(setq org-use-speed-commands t)

;; <s TAB completion for SRC scode block
(require 'org-tempo nil 'noerror)       ; required for org >= 9.2

;; Try org-indirect-buffer-display options
(setq org-indirect-buffer-display 'new-frame)
(setq org-src-window-setup 'other-frame)

;; Alphabetical plain list options!
(setq org-list-allow-alphabetical t)

;; Use org-specific beginning-of-line/end-of-line, before true ^/$
(setq org-special-ctrl-a/e 'reversed)

(setq org-startup-indented t)         ; visual indent only
;;(setq org-src-preserve-indentation t)
(setq org-edit-src-content-indentation 0) ; don't indent src blocks
(setq org-src-tab-acts-natively t)
(setq org-hide-leading-stars t)

;; Default bullet when demoting item or creating new sub-list
(setq org-list-demote-modify-bullet
        ("+" . "-")
        ("-" . "+")
        ("*" . "+")
        ("1." . "a)")
        ("1)" . "a.")
        ("a)" . "-")
        ("A)" . "-")
        ("a." . "-")
        ("A." . "-")


(setq org-agenda-skip-scheduled-if-deadline-is-shown t)
;; Don't remind me of weekly tasks immediately after completion
(setq org-deadline-warning-days 5)
;; Add more depth to agenda clock report: "v R" from agenda view
(setq org-agenda-clockreport-parameter-plist '(:link t :maxlevel 4))



Note: this seems to not be necessary with version 26.1+….

Some things, eww (libxml), inline images (libpng) require libraries not shipped with emacs on Windows. Get those from and install them to the /emacs/bin/ directory.

Tramp / Putty

Install PuTTY and use plink. Trying to use Tramp with ssh on windows causes emacs to hang.

(when (eq window-system 'w32)
  (setq tramp-default-method "plink"))

ie. find-file /plink:user@host:/home/dir/

Optional: Generate a key, upload to remote host, add to .ssh/allowed_keys, then connect with just plink mysession for passwordless login.

find-file /plink:mysession:/home/dir/

Task Bar shortcut

runemacs.exe will hide the terminal window, but if you pin the shortcut to the taskbar, it will be emacs.exe. The following steps ensures emacs icon can be used to launch emacs and browse open windows.

  1. Run runemacs.exe with no pre-existing icon in the taskbar.
  2. Right click on the running Emacs icon in the taskbar, and click on “pin this program to taskbar.”
  3. Close Emacs
  4. Shift right-click on the pinned Emacs icon on the taskbar, click on Properties, and change the target from emacs.exe to runemacs.exe.

External Programs

Open with default Windows app (w32-browser)

(when (eq 'windows-nt system-type)
  (defun w32-browser (doc) (w32-shell-execute 1 doc))
  ;; Ctrl-ENT to open with default application
  (eval-after-load "dired"
    '(define-key dired-mode-map [C-return]
       (lambda ()
         (w32-browser (dired-replace-in-string "/" "\\" (dired-get-filename)))))))

Spelling & Dictionaries (aspell/ispell/hunspell)

(setenv "LANG" "en_CA.UTF-8")
(setq-default ispell-program-name "hunspell")
(setq ispell-dictionary "en_CA")


;; Sets your shell to use cygwin's bash, if Emacs finds it's running
;; under Windows and c:\cygwin exists. Assumes that C:\cygwin\bin is
;; not already in your Windows Path (it generally should not be).

(if (string-match-p (regexp-quote "steven.brown") (getenv "USERPROFILE"))
    (setq my/env "work")
  (setq my/env "personal"))

(let* ((cygwin-root (if (string-equal my/env "work")
                        "c:/Users/steven.brown/Apps/cygwin64" ; work
                      "c:/Program Files/cygwin64"))	      ; home
       (cygwin-bin (concat cygwin-root "/bin")))
  (when (and (eq 'windows-nt system-type)
             (file-readable-p cygwin-root))

    (setq exec-path (cons cygwin-bin exec-path))
    (setenv "PATH" (concat cygwin-bin ";" (getenv "PATH")))

    ;; By default use the Windows HOME. (userdir/AppData/Roaming/.emacs.d)
    ;; (setenv "HOME" (getenv "USERPROFILE"))
    ;; Otherwise, uncomment below to set a HOME
    ;;      (setenv "HOME" (concat cygwin-root "/home/eric")) ;TODO: Customize by environment

    ;; NT-emacs assumes a Windows shell. Change to bash.
    (setq shell-file-name "bash")
    (setenv "SHELL" shell-file-name)
    (setq explicit-shell-file-name shell-file-name)

    ;; This removes unsightly ^M characters that would otherwise
    ;; appear in the output of java applications.
    (add-hook 'comint-output-filter-functions 'comint-strip-ctrl-m)

    ;; explicitly set dictionary path
    (setq ispell-hunspell-dict-paths-alist
          `(("en_CA" ,(concat (file-name-as-directory cygwin-root) "usr/share/myspell/en_CA.aff"))
            ("en_US" ,(concat (file-name-as-directory cygwin-root) "usr/share/myspell/en_US.aff"))
            ("en_GB" ,(concat (file-name-as-directory cygwin-root) "usr/share/myspell/en_GB.aff"))

    ;; DESKTOP MOD (not tested on other plats
    ;; not sure why, but this was required after upgrading at some point.
    ;; hunspell was being called with -i NIL, instead of -i utf-8
    ;; ERROR MSG:
    ;; ispell-get-decoded-string: No data for dictionary "en_CA" in
    ;; ‘ispell-local-dictionary-alist’ or ‘ispell-dictionary-alist’
    (setq ispell-dictionary-alist
          '(("en_CA" "[[:alpha:]]" "[^[:alpha:]]" "[']" nil
             ("-d" "en_CA") nil utf-8))

PlantUML & Ditaa Diagramming (Java)

Look for Java JAR files, set variables if found. Currently keep location simple across all setups. PlantUML requires graphviz, which can be installed on Cygwin on Windows.

(let* ((plantuml-filepath (expand-file-name "~/plantuml.jar"))
       (ditaa-filepath (expand-file-name "~/ditaa0_9.jar")))
  (when (file-readable-p plantuml-filepath)
    (setq org-plantuml-jar-path plantuml-filepath)
    (setq plantuml-default-exec-mode 'jar))
  (when (file-readable-p ditaa-filepath)
    (setq org-ditaa-jar-path ditaa-filepath))


;; Keep any easy-customizations in a separate file
(setq custom-file
       (concat user-emacs-directory "my-custom.el")))
(if (file-exists-p custom-file) (load custom-file))


After environment setup is complete, do any remaining things like opening files and setting key maps.

;; Open a couple files and buffers

;; dired filtered to .org files in org
(if (file-exists-p my/org-directory)
    (dired (concat my/org-directory "*.org")))

;; open init config
(if (file-exists-p (concat my/user-dir "Projects/dotemacs/"))
    (find-file (concat my/user-dir "Projects/dotemacs/")))
(if (file-exists-p "~/.emacs.d/init_private.el")
    (find-file "~/.emacs.d/init_private.el"))

;; open org file directory
(if my/on-work-pc
    (if (file-exists-p (concat my/org-directory ""))
        (find-file (concat my/org-directory "")))
  (if (file-exists-p (concat my/org-directory ""))
      (find-file (concat my/org-directory ""))))

;; Reset garbage collection threshold
;; (add-hook 'emacs-startup-hook
;;           (lambda ()
;;             (setq gc-cons-threshold 16777216 ;16MB
;;                   gc-cons-percentage 0.1)))

;; Recommended settings for performant lsp-mode, trying.
(setq gc-cons-threshold 100000000)      ;100MB
(when (boundp 'read-process-output-max)         ; Emacs27 req'd to support
  (setq read-process-output-max (* 1024 1024))) ; 1mb


Navigating links and buttons easily and consistently between different special modes.

If moving this block before modes are initialized, (derived-mode-init-mode-variables 'Info-mode) should be called before each mapping.

;; l = back (last), r (reverse?) = forward

;; Info-mode
(derived-mode-init-mode-variables 'Info-mode)
(define-key Info-mode-map (kbd "u") 'Info-up)
(define-key Info-mode-map (kbd "j") 'Info-next-reference)
(define-key Info-mode-map (kbd "k") 'Info-prev-reference)

;; help-mode
(derived-mode-init-mode-variables 'help-mode)
(define-key help-mode-map (kbd "j") 'forward-button)
(define-key help-mode-map (kbd "k") 'backward-button)

;; apropos-mode
(derived-mode-init-mode-variables 'apropos-mode)
(define-key apropos-mode-map (kbd "j") 'forward-button)
(define-key apropos-mode-map (kbd "k") 'backward-button)

;; helpful-mode
(derived-mode-init-mode-variables 'helpful-mode)
(define-key helpful-mode-map (kbd "j") 'forward-button)
(define-key helpful-mode-map (kbd "k") 'backward-button)


C-c ’narrow on code block in sibling window (and return)
C-c C-v ttangle
C-c C-v ftangle into specific filename, like “init.el”
C-c C-v norg-babel-next-src-block
C-c C-v porg-babel-previous-src-block

Converting from .emacs or init.el

 '(my-variable value)
 '(column-number-mode t)
 ; ...



(setq column-number-mode t)