This is my emacs configuration file. I use org-mode to organize it and then “tangle” the file using org-babel. You can find a helpful discussion of this method here.
I use emacs for all my academic work. The configuration tends in that direction. It also uses vim keybindings. I used vim (or neovim) previously. I think vim’s modal editing is the best way to use a text-editor. If you like vim bindings but don’t tend to want to think about configuring emacs, I strongly recommend spacemacs as a way of managing your configuration. For a more traditional emacs feel there are also the configurations of purcell and batsov (prelude). For a minimally sane setup you might also look at some sensible defaults.
On OS X, which I use, homebrew is an easy way to install emacs. Starting out
on OS X I would recommend using the emacs mac port version of emacs, which has
a variety of options set that make for smoother running on OS X. The one
downside is that it loads a bit slower than regular GNU emacs. For more info
on the various configurations available for OS X use brew info
.
Here’s what some example parameters mean.
--with-cocoa
- installs emacs with the OS X GUI version
--with-imagemagick
- installs emacs with imagemagick support for image processing
--with-gnutls
- installs emacs with GnuTLS to utilize encrypted SSL and TLS connections
For emacs-mac
use:
brew install emacs-mac --with-gnutls --with-imagemagick --with-librsvg
For GNU emacs 25
use the following:
brew install emacs --with-cocoa --HEAD --with-gnutls --with-imagemagick --with-librsvg
If you use homebrew cask you can install an emacs binary from emacs for mac, like so:
brew cask install emacs
This is the bootstrap code for getting the literate configuration file
in config.org
up and running. The original source for much of this code
is from sriramkswamy/dotemacs. I’ve also been inspired by Sacha Chua’s
configuration. There are also many other sources from around the
Internet whose names I’ve forgotten. Thanks to all of you for making
your configurations public! This config is fed into the init file.
Org mode is installed if not already present, as is use-package. There
is no need for any other package management.
These settings constitute those settings I regard as essential to normal emacs operation.
Let’s use sane defaults. Sources for this section include Magnars Sveen and Sacha Chua.
Make sure emacs correctly sets up your PATH.
(defvar cpm-local-bin (concat (getenv "HOME") "/bin") "Local execs.")
(defvar usr-local-bin "/usr/local/bin")
(setenv "PATH" (concat usr-local-bin ":" (getenv "PATH") ":" cpm-local-bin))
(setq exec-path (append exec-path (list cpm-local-bin usr-local-bin)))
No bells and no visible “bell” either!
(setq visible-bell nil) ;; The default
(setq ring-bell-function 'ignore)
;; Silence warnings generated by a function's being redefine by =defadvice=.
(setq ad-redefinition-action 'accept)
;; Change the echo message
(defun display-startup-echo-area-message ()
(message ""))
(put 'downcase-region 'disabled nil)
(put 'upcase-region 'disabled nil)
(put 'narrow-to-region 'disabled nil)
(put 'dired-find-alternate-file 'disabled nil)
(defalias 'yes-or-no-p 'y-or-n-p)
(setq locale-coding-system 'utf-8)
(set-terminal-coding-system 'utf-8)
(set-keyboard-coding-system 'utf-8)
(set-selection-coding-system 'utf-8)
(prefer-coding-system 'utf-8)
(setq uniquify-buffer-name-style 'forward)
;; (setq insert-directory-program "gls" dired-use-ls-dired t)
;; stop asking about recurisve actions
(setq dired-recursive-copies 'always)
(setq dired-recursive-deletes 'always)
;; Keep focus while navigating help buffers
(setq help-window-select 't)
;; Save whatever’s in the current (system) clipboard before
;; replacing it with the Emacs’ text.
;; https://github.com/dakrone/eos/blob/master/eos.org
(setq save-interprogram-paste-before-kill t)
Make all files POSIX compliant for newlines
;; Make sure your text files end in a newline
(setq require-final-newline t)
Start up with a clean scratch buffer.
(setq inhibit-splash-screen t)
(setq inhibit-startup-message t)
(setq initial-scratch-message "")
;; And bury the scratch buffer, don't kill it
(defadvice kill-buffer (around kill-buffer-around-advice activate)
(let ((buffer-to-kill (ad-get-arg 0)))
(if (equal buffer-to-kill "*scratch*")
(bury-buffer)
ad-do-it)))
Useful to get a faster Emacs load time because it avoids autoloads of elisp modes or other minor modes
(setq initial-major-mode 'fundamental-mode)
(blink-cursor-mode 0)
(defconst user-cache-directory
(expand-file-name (concat user-emacs-directory ".cache/"))
"My emacs storage area for persistent files.")
;; create the `user-cache-directory' if it doesn't exist
(make-directory user-cache-directory t)
(let ((backup-dir (concat user-cache-directory "backup")))
;; Move backup file to `~/.emacs.d/.cache/backup'
(setq backup-directory-alist `(("." . ,backup-dir)))
;; Makesure backup directory exist
(when (not (file-exists-p backup-dir))
(make-directory backup-dir t)))
(setq make-backup-files t ; backup of a file the first time it is saved.
backup-by-copying t ; don't clobber symlinks
version-control t ; version numbers for backup files
delete-old-versions t ; delete excess backup files silently
delete-by-moving-to-trash t
kept-old-versions 6 ; oldest versions to keep when a new numbered backup is made
kept-new-versions 6 ; newest versions to keep when a new numbered backup is made
)
(setq vc-make-backup-files t) ;; backup versioned files, which Emacs does not do by default
Traverse backups with backup-walker
(use-package backup-walker)
I make sure Emacs auto-saves often but the result is that it messes up my file tree. So, let’s ask Emacs to store its backups in the cache directory.
(setq auto-save-list-file-prefix
(concat user-cache-directory "auto-save-list/.saves-"))
(setq auto-save-default t ; auto-save every buffer that visits a file
auto-save-timeout 20 ; number of seconds idle time before auto-save (default: 30)
auto-save-interval 200 ; number of keystrokes between auto-saves (default: 300)
auto-save-visited-file-name nil
delete-auto-save-files t
create-lockfiles nil)
I also make emacs just outright save all buffers.
(defun full-auto-save ()
(interactive)
(save-excursion
(dolist (buf (buffer-list))
(set-buffer buf)
(if (and (buffer-file-name) (buffer-modified-p))
(basic-save-buffer)))))
(add-hook 'auto-save-hook 'full-auto-save)
Set up the customize file to its own separate file, instead of saving customize settings in init.el.
(setq custom-file (expand-file-name "custom.el" user-emacs-directory))
(when (file-exists-p custom-file)
(load custom-file))
(setq desktop-dirname (concat user-cache-directory "desktop")
desktop-base-file-name "emacs.desktop"
desktop-base-lock-name "lock"
desktop-path (list desktop-dirname)
desktop-save 'ask-if-new
desktop-files-not-to-save (concat "^$" ".*magit$")
desktop-restore-eager 10
desktop-load-locked-desktop t)
(setq desktop-buffers-not-to-save
(concat "\\("
"^nn\\.a[0-9]+\\|\\.log\\|(ftp)\\|^tags\\|^TAGS"
"\\|\\.emacs.*\\|\\.diary\\|\\.newsrc-dribble\\|\\.bbdb"
"\\)$"))
(desktop-save-mode 0)
(defun my-desktop ()
"Load the desktop and enable autosaving"
(interactive)
(let ((desktop-load-locked-desktop "ask"))
(desktop-read)
(desktop-save-mode 1)))
(defun save-desktop-save-buffers-kill-emacs ()
"Save buffers and current desktop every time when quitting emacs."
(interactive)
(desktop-save-in-desktop-dir)
(save-buffers-kill-emacs))
;; better session management
(use-package desktop+
:ensure t
:commands (desktop+-create desktop+-load)
:config
(setq desktop+-base-dir (concat user-cache-directory "desktop"))
(defun my/desktop-frame-title-function (desktop-name)
(list (concat "%f | [" desktop-name "]")))
(setq desktop+-frame-title-function
'my/desktop-frame-title-function)
)
There is some configuration to do when running Emacs on OS X (hence the “darwin” system-type check).
(let ((is-mac (string-equal system-type "darwin")))
(when is-mac
;; make fonts look better with anti-aliasing
(setq mac-allow-anti-aliasing t)
;; delete files by moving them to the trash
(setq delete-by-moving-to-trash t)
(setq trash-directory "~/.Trash")
;; Don't make new frames when opening a new file with Emacs
(setq ns-pop-up-frames nil)
;; non-lion fullscreen
(setq ns-use-native-fullscreen nil)
;; Set modifier keys
(setq mac-option-modifier 'meta) ;; Bind meta to ALT
(setq mac-command-modifier 'super) ;; Bind apple/command to super if you want
(setq mac-function-modifier 'hyper) ;; Bind function key to hyper if you want
(setq mac-right-option-modifier 'none) ;; unbind right key for accented input
;; Make forward delete work
(global-set-key (kbd "<H-backspace>") 'delete-forward-char)
;; Keybindings
(global-set-key (kbd "s-=") 'scale-up-font)
(global-set-key (kbd "s--") 'scale-down-font)
(global-set-key (kbd "s-0") 'reset-font-size)
(global-set-key (kbd "s-q") 'save-buffers-kill-terminal)
(global-set-key (kbd "s-v") 'yank)
(global-set-key (kbd "s-c") 'evil-yank)
(global-set-key (kbd "s-a") 'mark-whole-buffer)
(global-set-key (kbd "s-x") 'kill-region)
(global-set-key (kbd "s-w") 'delete-window)
(global-set-key (kbd "s-W") 'delete-frame)
(global-set-key (kbd "s-n") 'make-frame)
(global-set-key (kbd "s-z") 'undo-tree-undo)
(global-set-key (kbd "s-s")
(lambda ()
(interactive)
(call-interactively (key-binding "\C-x\C-s"))))
(global-set-key (kbd "s-Z") 'undo-tree-redo)
(global-set-key (kbd "C-s-f") 'toggle-frame-fullscreen)
;; Emacs sometimes registers C-s-f as this weird keycode
(global-set-key (kbd "<C-s-268632070>") 'toggle-frame-fullscreen)
))
(defun open-dir-in-iterm ()
"Open the current directory of the buffer in iTerm."
(interactive)
(let* ((iterm-app-path "/Applications/iTerm.app")
(iterm-brew-path "/opt/homebrew-cask/Caskroom/iterm2/2.1.4/iTerm.app")
(iterm-path (if (file-directory-p iterm-app-path)
iterm-app-path
iterm-brew-path)))
(shell-command (concat "open -a " iterm-path " ."))))
(global-set-key (kbd "C-x t") 'open-dir-in-iterm)
;; Not going to use these commands
(put 'ns-print-buffer 'disabled t)
(put 'suspend-frame 'disabled t)
(setq
time-stamp-active t ; do enable time-stamps
time-stamp-line-limit 10 ; check first 10 buffer lines for Time-stamp:
time-stamp-format "Last modified on %04y-%02m-%02d %02H:%02M:%02S (%U)") ; date format
(add-hook 'write-file-hooks 'time-stamp) ; update when saving
General Text settings and hooks
;; Single space between sentences is more widespread than double
(setq-default sentence-end-double-space nil)
Use flyspell and aspell
(use-package ispell
:defer 10
:config
;; Save a new word to personal dictionary without asking
(setq ispell-silently-savep t)
(setq-default ispell-program-name "aspell")
(setq-default ispell-list-command "list"))
(use-package flyspell
:diminish flyspell-mode
:defer 11
;; :commands (flyspell-mode flyspell-prog-mode)
:init
(progn
;; Below variables need to be set before `flyspell' is loaded.
(setq flyspell-use-meta-tab nil))
:config
;; Save a new word to personal dictionary without asking
(setq flyspell-issue-welcome-flag nil))
Use abbrev-mode as my autocorrect. Via Endless Parentheses.
(define-key ctl-x-map "\C-i"
#'endless/ispell-word-then-abbrev)
(defun endless/simple-get-word ()
(car-safe (save-excursion (ispell-get-word nil))))
(defun endless/ispell-word-then-abbrev (p)
"Call `ispell-word', then create an abbrev for it.
With prefix P, create local abbrev. Otherwise it will
be global.
If there's nothing wrong with the word at point, keep
looking for a typo until the beginning of buffer. You can
skip typos you don't want to fix with `SPC', and you can
abort completely with `C-g'."
(interactive "P")
(let (bef aft)
(save-excursion
(while (if (setq bef (endless/simple-get-word))
;; Word was corrected or used quit.
(if (ispell-word nil 'quiet)
nil ; End the loop.
;; Also end if we reach `bob'.
(not (bobp)))
;; If there's no word at point, keep looking
;; until `bob'.
(not (bobp)))
(backward-word)
(backward-char))
(setq aft (endless/simple-get-word)))
(if (and aft bef (not (equal aft bef)))
(let ((aft (downcase aft))
(bef (downcase bef)))
(define-abbrev
(if p local-abbrev-table global-abbrev-table)
bef aft)
(message "\"%s\" now expands to \"%s\" %sally"
bef aft (if p "loc" "glob")))
(user-error "No typo at or before point"))))
(setq save-abbrevs 'silently)
(use-package abbrev-mode
:ensure nil
:commands (abbrev-mode))
Flyspell is in elisp mode. And this in turn loads flyspell directly after launching emacs, which is a bit unfortunate.
(defun my-flyspell-prog-mode ()
(interactive)
(unless (string= (buffer-name) "*scratch*")
(flyspell-prog-mode)))
(add-hook 'prog-mode-hook #'my-flyspell-prog-mode)
(add-hook 'text-mode-hook #'flyspell-mode)
(add-hook 'org-mode-hook #'flyspell-mode)
(add-hook 'latex-mode-hook #'flyspell-mode)
(add-hook 'LaTeX-mode-hook #'flyspell-mode)
(setq-default indent-tabs-mode nil)
(setq-default tab-width 4)
(setq-default indicate-empty-lines nil)
(global-visual-line-mode)
(setq line-move-visual t) ;; move via visual lines
(setq-default fill-column 78)
This is the good old search and replace as opposed to the fancy alternatives such as iedit and multiple cursors. You search for a word in the buffer/region, type in the replacement and confirm each one by pressing y
or n
or just press !
to apply this to everything.
(use-package visual-regexp
:commands (vr/query-replace)
:config
(use-package visual-regexp-steroids
:commands (vr/select-query-replace)))
Show matching brackets, parenthesis, etc.
(show-paren-mode t)
async, s, dash, and cl-lib are libraries for asynchronous processing, string manipulation, list manipulation and backward compatibility respectively.
(use-package async :commands (async-start))
(use-package cl-lib :defer t)
(use-package dash :defer t)
(use-package s :defer t)
Various useful functions and macros I’ve written or pilfered from others.
A collection of ridiculously useful extensions. Indeed.
(use-package crux :defer 2)
(defun goto-init.el ()
"Open init.el file"
(interactive)
(find-file "~/.emacs.d/init.el"))
(defun goto-custom.el ()
"Open custom.el file"
(interactive)
(find-file "~/.emacs.d/custom.el"))
(defun goto-config.org ()
"Open config.org file"
(interactive)
(find-file "~/.emacs.d/config.org"))
(defun load-config ()
"Load config "
(interactive)
(load-file "~/.emacs.d/init.el"))
Duplicate a file in dired or deer
(defun cpm/duplicate-file ()
(interactive)
(dired-do-copy-regexp "\\(.*\\)\\.\\(.*\\)" "\\1 (copy).\\2"))
(defun switch-to-previous-buffer ()
(interactive)
(switch-to-buffer (other-buffer (current-buffer) 1)))
Create a directory – or a hierarchy of them – while finding a file in a nonexistent directory. From mbork.
(defun make-parent-directory ()
"Make sure the directory of `buffer-file-name' exists."
(make-directory (file-name-directory buffer-file-name) t))
(add-hook 'find-file-not-found-functions #'make-parent-directory)
A helpful function I found here for wrapping text in a block template.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; function to wrap blocks of text in org templates ;;
;; e.g. latex or src etc ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defun org-block-wrap ()
"Make a template at point."
(interactive)
(if (org-at-table-p)
(call-interactively 'org-table-rotate-recalc-marks)
(let* ((choices '(
("a" . "ASCII")
("c" . "COMMENT")
("C" . "CENTER")
("e" . "EXAMPLE")
("E" . "SRC emacs-lisp")
("h" . "HTML")
("l" . "LaTeX")
("n" . "NOTES")
("q" . "QUOTE")
("s" . "SRC")
("v" . "VERSE")
))
(key
(key-description
(vector
(read-key
(concat (propertize "Template type: " 'face 'minibuffer-prompt)
(mapconcat (lambda (choice)
(concat (propertize (car choice) 'face 'font-lock-type-face)
": "
(cdr choice)))
choices
", ")))))))
(let ((result (assoc key choices)))
(when result
(let ((choice (cdr result)))
(cond
((region-active-p)
(let ((start (region-beginning))
(end (region-end)))
(goto-char end)
(insert "#+END_" choice "\n")
(goto-char start)
(insert "#+BEGIN_" choice "\n")))
(t
(insert "#+BEGIN_" choice "\n")
(save-excursion (insert "#+END_" choice))))))))))
Via the always resourceful John Kitchin.
(defun formatted-copy ()
"Export region to HTML, and copy it to the clipboard."
(interactive)
(save-window-excursion
(let* ((buf (org-export-to-buffer 'html "*Formatted Copy*" nil nil t t))
(html (with-current-buffer buf (buffer-string))))
(with-current-buffer buf
(shell-command-on-region
(point-min)
(point-max)
"textutil -stdin -format html -convert rtf -stdout | pbcopy"))
(kill-buffer buf))))
(global-set-key (kbd "H-w") 'formatted-copy)
(defun org-remove-headlines (backend)
"Remove headlines with :no_title: tag."
(org-map-entries (lambda () (let ((beg (point)))
(outline-next-visible-heading 1)
(backward-char)
(delete-region beg (point))))
"no_export" tree)
(org-map-entries (lambda () (delete-region (point-at-bol) (point-at-eol)))
"no_title"))
;; the following isn't currently working with org-mode 9
;; (add-hook 'org-export-before-processing-hook #'org-remove-headlines)
(defun move-file ()
"Write this file to a new location, and delete the old one."
(interactive)
(let ((old-location (buffer-file-name)))
(call-interactively #'write-file)
(when old-location
(delete-file old-location))))
(defun cpm/org-to-markdown ()
"convert clipboard contents from org to markdown and paste"
(interactive)
(kill-new (shell-command-to-string "osascript -e 'the clipboard as unicode text' | pandoc -f org -t markdown"))
(yank))
(defun cpm/markdown-to-org ()
"convert clipboard contents from markdown to org and paste"
(interactive)
(kill-new (shell-command-to-string "osascript -e 'the clipboard as unicode text' | pandoc -f markdown -t org"))
(yank))
(defun cpm/tex-to-org ()
"convert clipboard contents from markdown to org and paste"
(interactive)
(kill-new (shell-command-to-string "osascript -e 'the clipboard as unicode text' | pandoc -f latex -t org"))
(yank))
(defun cpm/tex-to-markdown ()
"convert clipboard contents from markdown to org and paste"
(interactive)
(kill-new (shell-command-to-string "osascript -e 'the clipboard as unicode text' | pandoc -f latex -t markdown"))
(yank))
(defun last-search-buffer ()
"open last helm-ag or hgrep buffer."
(interactive)
(cond ((get-buffer "*helm ag results*")
(switch-to-buffer-other-window "*helm ag results*"))
((get-buffer "*helm-ag*")
(helm-resume "*helm-ag*"))
((get-buffer "*hgrep*")
(switch-to-buffer-other-window "*hgrep*"))
(t
(message "No previous search buffer found"))))
;; from magnars modified by ffevotte for dedicated windows support
(defun rotate-windows (count)
"Rotate your windows.
Dedicated windows are left untouched. Giving a negative prefix
argument takes the kindows rotate backwards."
(interactive "p")
(let* ((non-dedicated-windows (remove-if 'window-dedicated-p (window-list)))
(num-windows (length non-dedicated-windows))
(i 0)
(step (+ num-windows count)))
(cond ((not (> num-windows 1))
(message "You can't rotate a single window!"))
(t
(dotimes (counter (- num-windows 1))
(let* ((next-i (% (+ step i) num-windows))
(w1 (elt non-dedicated-windows i))
(w2 (elt non-dedicated-windows next-i))
(b1 (window-buffer w1))
(b2 (window-buffer w2))
(s1 (window-start w1))
(s2 (window-start w2)))
(set-window-buffer w1 b2)
(set-window-buffer w2 b1)
(set-window-start w1 s2)
(set-window-start w2 s1)
(setq i next-i)))))))
(defun rotate-windows-backward (count)
"Rotate your windows backward."
(interactive "p")
(spacemacs/rotate-windows (* -1 count)))
(defun goto-projects ()
"Open projects dir"
(interactive)
(require 'ranger)
(find-file "~/projects"))
(defun browse-file-directory ()
"Open the current file's directory however the OS would."
(interactive)
(if default-directory
(browse-url-of-file (expand-file-name default-directory))
(error "No `default-directory' to open")))
(defun cpm/helm-files-do-ag (&optional dir)
"Search in files with `ag' using a default input."
(interactive)
(helm-do-ag dir))
I got this from the spacemacs config. Useful for navigating in tagged buffers.
(defun jump-in-buffer ()
(interactive)
(cond
((eq major-mode 'org-mode)
(call-interactively 'helm-org-in-buffer-headings))
(t
(call-interactively 'helm-semantic-or-imenu))))
(defun forward-or-backward-sexp (&optional arg)
"Go to the matching parenthesis character if one is adjacent to point."
(interactive "^p")
(cond ((looking-at "\\s(") (forward-sexp arg))
((looking-back "\\s)" 1) (backward-sexp arg))
;; Now, try to succeed from inside of a bracket
((looking-at "\\s)") (forward-char) (backward-sexp arg))
((looking-back "\\s(" 1) (backward-char) (forward-sexp arg))))
(defun goto-journal ()
(interactive)
(find-file "/Users/Roambot/Dropbox/journal.org"))
Kill all the buffers except *scratch*
buffer
(defun kill-other-buffers ()
"Kill all other buffers."
(interactive)
(mapc 'kill-buffer (delq (current-buffer) (buffer-list))))
;; (defun nuke-all-buffers ()
;; "Kill all buffers, leaving *scratch* only."
;; (interactive)
;; (mapcar (lambda (x) (kill-buffer x)) (buffer-list))
;; (delete-other-windows))
(defun eval-buffer-until-error ()
"Evaluate emacs buffer until error occured."
(interactive)
(goto-char (point-min))
(while t (eval (read (current-buffer)))))
The code below sets the correct value for system-time-locale, and binds keys for insert-date/long and insert-date/short. Courtesy of emacs-hacks.
(defun format-date (format)
(let ((system-time-locale "en_US.UTF-8"))
(insert (format-time-string format))))
(defun insert-date ()
(interactive)
(format-date "%A, %B %d %Y"))
(defun insert-date-and-time ()
(interactive)
(format-date "%Y-%m-%d %H:%M:%S"))
(defun reveal-to-pdf ()
"print reveal.js slides to pdf"
(interactive)
(async-shell-command "phantomjs /Users/Roambot/bin/print-pdf.js 'file:///Users/Roambot/projects/phil101/content/slides/lecture_outline.html?print-pdf'"))
Most of these are from the spacemacs distribution.
;; Regexp for useful and useless buffers for smarter buffer switching, from spacemacs
(defvar spacemacs-useless-buffers-regexp '("*\.\+")
"Regexp used to determine if a buffer is not useful.")
(defvar spacemacs-useful-buffers-regexp '("\\*\\(scratch\\|terminal\.\+\\|ansi-term\\|eshell\\)\\*")
"Regexp used to define buffers that are useful despite matching
`spacemacs-useless-buffers-regexp'.")
(defun spacemacs/useless-buffer-p (buffer)
"Determines if a buffer is useful."
(let ((buf-paren-major-mode (get (with-current-buffer buffer
major-mode)
'derived-mode-parent))
(buf-name (buffer-name buffer)))
;; first find if useful buffer exists, if so returns nil and don't check for
;; useless buffers. If no useful buffer is found, check for useless buffers.
(unless (cl-loop for regexp in spacemacs-useful-buffers-regexp do
(when (or (eq buf-paren-major-mode 'comint-mode)
(string-match regexp buf-name))
(return t)))
(cl-loop for regexp in spacemacs-useless-buffers-regexp do
(when (string-match regexp buf-name)
(return t))))))
(defun spacemacs/next-useful-buffer ()
"Switch to the next buffer and avoid special buffers."
(interactive)
(let ((start-buffer (current-buffer)))
(next-buffer)
(while (and (spacemacs/useless-buffer-p (current-buffer))
(not (eq (current-buffer) start-buffer)))
(next-buffer))))
(defun spacemacs/previous-useful-buffer ()
"Switch to the previous buffer and avoid special buffers."
(interactive)
(let ((start-buffer (current-buffer)))
(previous-buffer)
(while (and (spacemacs/useless-buffer-p (current-buffer))
(not (eq (current-buffer) start-buffer)))
(previous-buffer))))
;; from magnars
(defun spacemacs/rename-current-buffer-file ()
"Renames current buffer and file it is visiting."
(interactive)
(let ((name (buffer-name))
(filename (buffer-file-name)))
(if (not (and filename (file-exists-p filename)))
(error "Buffer '%s' is not visiting a file!" name)
(let ((new-name (read-file-name "New name: " filename)))
(cond ((get-buffer new-name)
(error "A buffer named '%s' already exists!" new-name))
(t
(let ((dir (file-name-directory new-name)))
(when (and (not (file-exists-p dir)) (yes-or-no-p (format "Create directory '%s'?" dir)))
(make-directory dir t)))
(rename-file filename new-name 1)
(rename-buffer new-name)
(set-visited-file-name new-name)
(set-buffer-modified-p nil)
(when (fboundp 'recentf-add-file)
(recentf-add-file new-name)
(recentf-remove-if-non-kept filename))
(message "File '%s' successfully renamed to '%s'" name (file-name-nondirectory new-name))))))))
;; from magnars
(defun spacemacs/delete-current-buffer-file ()
"Removes file connected to current buffer and kills buffer."
(interactive)
(let ((filename (buffer-file-name))
(buffer (current-buffer))
(name (buffer-name)))
(if (not (and filename (file-exists-p filename)))
(ido-kill-buffer)
(when (yes-or-no-p "Are you sure you want to delete this file? ")
(delete-file filename t)
(kill-buffer buffer)
(message "File '%s' successfully removed" filename)))))
;; found at http://emacswiki.org/emacs/KillingBuffers
(defun spacemacs/kill-other-buffers ()
"Kill all other buffers."
(interactive)
(when (yes-or-no-p (format "Killing all buffers except \"%s\"? " (buffer-name)))
(mapc 'kill-buffer (delq (current-buffer) (buffer-list)))
(message "Buffers deleted!")))
;; http://camdez.com/blog/2013/11/14/emacs-show-buffer-file-name/
(defun spacemacs/show-and-copy-buffer-filename ()
"Show the full path to the current file in the minibuffer."
(interactive)
(let ((file-name (buffer-file-name)))
(if file-name
(progn
(message file-name)
(kill-new file-name))
(error "Buffer not visiting a file"))))
(defun spacemacs/new-empty-buffer ()
"Create a new buffer called untitled(<n>)"
(interactive)
(let ((newbuf (generate-new-buffer-name "untitled")))
(switch-to-buffer newbuf)))
;; from https://github.com/gempesaw/dotemacs/blob/emacs/dg-defun.el
(defun spacemacs/kill-matching-buffers-rudely (regexp &optional internal-too)
"Kill buffers whose name matches the specified REGEXP. This
function, unlike the built-in `kill-matching-buffers` does so
WITHOUT ASKING. The optional second argument indicates whether to
kill internal buffers too."
(interactive "sKill buffers matching this regular expression: \nP")
(dolist (buffer (buffer-list))
(let ((name (buffer-name buffer)))
(when (and name (not (string-equal name ""))
(or internal-too (/= (aref name 0) ?\s))
(string-match regexp name))
(kill-buffer buffer)))))
;; http://stackoverflow.com/a/10216338/4869
(defun spacemacs/copy-whole-buffer-to-clipboard ()
"Copy entire buffer to clipboard"
(interactive)
(clipboard-kill-ring-save (point-min) (point-max)))
(defun spacemacs/copy-clipboard-to-whole-buffer ()
"Copy clipboard and replace buffer"
(interactive)
(delete-region (point-min) (point-max))
(clipboard-yank)
(deactivate-mark))
(defun spacemacs/copy-file ()
"Write the file under new name."
(interactive)
(call-interactively 'write-file))
These are a few useful macros I got from hlissner’s “doom” .emacs.d
(defmacro after! (feature &rest forms)
"A smart wrapper around `with-eval-after-load', that supresses warnings
during compilation."
(declare (indent defun) (debug t))
`(,(if (or (not (boundp 'byte-compile-current-file))
(not byte-compile-current-file)
(if (symbolp feature)
(require feature nil :no-error)
(load feature :no-message :no-error)))
'progn
(message "after: cannot find %s" feature)
'with-no-warnings)
(with-eval-after-load ',feature ,@forms)))
(defmacro add-hook! (hook &rest func-or-forms)
"A convenience macro for `add-hook'.
HOOK can be one hook or a list of hooks. If the hook(s) are not quoted, -hook is
appended to them automatically. If they are quoted, they are used verbatim.
FUNC-OR-FORMS can be a quoted symbol, a list of quoted symbols, or forms. Forms will be
wrapped in a lambda. A list of symbols will expand into a series of add-hook calls.
Examples:
(add-hook! 'some-mode-hook 'enable-something)
(add-hook! some-mode '(enable-something and-another))
(add-hook! '(one-mode-hook second-mode-hook) 'enable-something)
(add-hook! (one-mode second-mode) 'enable-something)
(add-hook! (one-mode second-mode) (setq v 5) (setq a 2))"
(declare (indent defun) (debug t))
(unless func-or-forms
(error "add-hook!: FUNC-OR-FORMS is empty"))
(let* ((val (car func-or-forms))
(quoted (eq (car-safe hook) 'quote))
(hook (if quoted (cadr hook) hook))
(funcs (if (eq (car-safe val) 'quote)
(if (cdr-safe (cadr val))
(cadr val)
(list (cadr val)))
(list func-or-forms)))
(forms '()))
(mapc
(lambda (f)
(let ((func (cond ((symbolp f) `(quote ,f))
(t `(lambda (&rest _) ,@func-or-forms)))))
(mapc
(lambda (h)
(push `(add-hook ',(if quoted h (intern (format "%s-hook" h))) ,func) forms))
(-list hook)))) funcs)
`(progn ,@forms)))
;;;###autoload
(defmacro def-popup! (&rest params)
`(push ',params shackle-rules))
A convenient way to bind keys. Compatible with evil. For helpful discussion of setting up evil with general see this post.
(use-package general
:config
(general-create-definer cpm-leader1
:states '(normal insert visual motion emacs)
:keymaps 'global
:prefix "SPC"
:non-normal-prefix "C-SPC"))
I’m coming from vim, and want modal keybidings in emacs. There are other, less radical ways of getting modal editing in emacs. For example, modalka is a nice package for modal editing (see also ryo-modal). But nothing beats full vim keybindings. And that is what evil is for.
The essential stuff
(use-package evil
:ensure t
:config
(progn
;; Cursor shape and color
(defcustom dotemacs-evil/emacs-cursor
"red"
"The color of the cursor when in Emacs state."
:type 'color
:group 'dotemacs-evil)
(defcustom dotemacs-evil/emacs-insert-mode
nil
"If non-nil, insert mode will act as Emacs state."
:type 'boolean
:group 'dotemacs-evil)
(setq evil-search-module 'evil-search)
(setq evil-magic 'very-magic)
(setq evil-emacs-state-cursor `(,dotemacs-evil/emacs-cursor box))
(setq evil-normal-state-cursor '("DarkGoldenrod2" box))
(setq evil-visual-state-cursor '("gray" box))
(setq evil-insert-state-cursor '("chartreuse3" (bar . 2)))
(setq evil-replace-state-cursor '("red" hbar))
(setq evil-operator-state-cursor '("red" hollow))
(setq evil-visual-state-tag "VISUAL")
;; evil-normal-state is preferred, so revert when idle
(run-with-idle-timer 20 t 'evil-normal-state)
;; don't echo evil state
(setq evil-echo-state nil)
;; evil everywhere
(evil-mode 1)))
Use a key sequence for escaping.
(use-package evil-escape
:ensure t
:diminish ""
:init
(evil-escape-mode)
;; use "fd" for escape
(setq-default evil-escape-key-sequence "fd"))
There are some other useful setup packages for evil
(general-define-key
:states '(normal visual)
"j" 'evil-next-visual-line
"k" 'evil-previous-visual-line)
(use-package evil-indent-textobject :commands (evil-indent))
(use-package evil-numbers
:ensure t
:commands (evil-numbers/inc-at-pt evil-numbers/dec-at-pt)
:init
(general-define-key
:states '(normal visual insert emacs)
"H-s" 'evil-numbers/inc-at-pt
"H-a" 'evil-numbers/dec-at-pt))
(defun my-send-string-to-terminal (string)
(unless (display-graphic-p) (send-string-to-terminal string)))
(defun my-evil-terminal-cursor-change ()
(when (string= (getenv "TERM_PROGRAM") "iTerm.app")
(add-hook 'evil-insert-state-entry-hook (lambda () (my-send-string-to-terminal "\e]50;CursorShape=1\x7")))
(add-hook 'evil-insert-state-exit-hook (lambda () (my-send-string-to-terminal "\e]50;CursorShape=0\x7"))))
(when (and (getenv "TMUX") (string= (getenv "TERM_PROGRAM") "iTerm.app"))
(add-hook 'evil-insert-state-entry-hook (lambda () (my-send-string-to-terminal "\ePtmux;\e\e]50;CursorShape=1\x7\e\\")))
(add-hook 'evil-insert-state-exit-hook (lambda () (my-send-string-to-terminal "\ePtmux;\e\e]50;CursorShape=0\x7\e\\")))))
(add-hook 'after-make-frame-functions (lambda (frame) (my-evil-terminal-cursor-change)))
(my-evil-terminal-cursor-change)
(use-package evil-terminal-cursor-changer
:ensure t
:disabled t
:defer t
:init
(unless (display-graphic-p)
(require 'evil-terminal-cursor-changer)
(progn
(setq evil-visual-state-cursor '("red" box)); █
(setq evil-insert-state-cursor '("green" bar)); ⎸
(setq evil-emacs-state-cursor '("blue" hbar)); _
)))
(use-package evil-surround
:ensure t
;; :defer 2
:commands (evil-surround-region evil-surround-change)
:init
(general-define-key
:states '(visual)
"s" 'evil-surround-region
"S" 'evil-substitute)
:config (global-evil-surround-mode 1))
(use-package embrace
:ensure t)
(use-package evil-embrace
:ensure t
:config
(evil-embrace-enable-evil-surround-integration)
(setq evil-embrace-show-help-p nil)
(add-hook 'org-mode-hook 'embrace-org-mode-hook)
(add-hook 'text-mode-hook
(lambda ()
(embrace-add-pair ?$ "$" "$")))
(add-hook 'LaTeX-mode-hook
(lambda ()
(embrace-add-pair ?a "`" "'")
(embrace-add-pair ?e "\\emph{" "}"))))
Use evil motions with avy
(use-package evil-avy
:after avy
)
(use-package evil-commentary
:commands (evil-commentary evil-commentary-line)
:diminish evil-commentary-mode
:config
(evil-commentary-mode))
(use-package undo-tree
:commands (undo-tree-undo undo-tree-visualize)
:init
;; (global-undo-tree-mode)
(setq undo-tree-visualizer-timestamps t)
(setq undo-tree-visualizer-diff t)
(let ((undo-dir (concat user-cache-directory "undo")))
(setq undo-tree-history-directory-alist '((".*" . ,undo-dir)))))
;; (use-package undo-tree
;; :ensure t
;; :init
;; (progn
;; (global-undo-tree-mode)
;; (setq undo-tree-mode-lighter "")
;; ;; (setq undo-tree-auto-save-history t)
;; (setq undo-tree-visualizer-timestamps t)
;; (setq undo-tree-visualizer-diff t)
;; (let ((undo-dir (concat user-cache-directory "undo")))
;; (setq undo-tree-history-directory-alist `((".*" . ,undo-dir)))))
;; )
Make the content of the scratch buffer persist between settings
(use-package persistent-scratch
:config
(setq persistent-scratch-backup-directory (concat user-cache-directory "scratch-backups"))
(setq persistent-scratch-save-file (concat user-cache-directory "persistent-scratch"))
;; keep backups not older than a month
(setq persistent-scratch-backup-filter
(persistent-scratch-keep-backups-not-older-than
(days-to-time 90)))
(persistent-scratch-setup-default)
(persistent-scratch-autosave-mode)
)
(use-package projectile
;; :commands (projectile-ack
;; projectile-ag
;; projectile-compile-project
;; projectile-dired
;; projectile-find-dir
;; projectile-find-file
;; projectile-find-tag
;; projectile-find-test-file
;; projectile-grep
;; projectile-invalidate-cache
;; projectile-kill-buffers
;; projectile-multi-occur
;; projectile-project-p
;; projectile-project-root
;; projectile-recentf
;; projectile-regenerate-tags
;; projectile-replace
;; projectile-run-async-shell-command-in-root
;; projectile-run-shell-command-in-root
;; projectile-switch-project
;; projectile-switch-to-buffer
;; projectile-vc)
:init
;; save projectile-known-projects-file in cache folder
(setq projectile-known-projects-file
(concat user-cache-directory "projectile-bookmarks.eld"))
(setq projectile-cache-file
(concat user-cache-directory "projectile.cache"))
(setq projectile-enable-caching t)
:config
(projectile-global-mode t))
(use-package restart-emacs
:commands restart-emacs)
Better dired navigation using ranger-like settings
(use-package ranger
:commands (ranger deer deer-jump-other-window)
:init
(setq ranger-override-dired t
ranger-cleanup-eagerly t)
;; set up image-dired to allow picture resize
(setq image-dired-dir (concat user-cache-directory "image-dir"))
(unless (file-directory-p image-dired-dir)
(make-directory image-dired-dir))
:config
(setq ranger-dont-show-binary t
ranger-excluded-extensions '("mkv" "iso" "mp4")
ranger-max-preview-size 25
ranger-preview-file t
ranger-show-dotfiles t
ranger-width-parents 0.25
ranger-width-preview 0.55
))
;; (defun deer-jump-other-window (&optional path)
;; "Launch dired in a minimal ranger window in other window."
;; (interactive)
;; (switch-to-buffer-other-window (current-buffer))
;; (deer path))
(use-package recentf
:defer 2
:init
(setq recentf-save-file (expand-file-name "recentf" user-cache-directory)))
Helm is a robust and well-designed completion framework. It can do quite a lot.
(use-package helm
:diminish (helm-mode . "")
:defer 1
:init
(setq helm-locate-fuzzy-match nil
helm-locate-command "locate %s -e -A --regex %s")
:config
(progn
;; Use helm to provide :ls, unless ibuffer is used
(evil-ex-define-cmd "buffers" 'helm-buffers-list)
(setq helm-M-x-fuzzy-match t ;; Use fuzzy match in helm
helm-apropos-fuzzy-match t
helm-buffers-fuzzy-matching t
helm-imenu-fuzzy-match t
helm-recentf-fuzzy-match t
helm-prevent-escaping-from-minibuffer t
helm-bookmark-show-location t
helm-ff-file-name-history-use-recentf t
helm-find-files-sort-directories t
helm-display-header-line nil
helm-move-to-line-cycle-in-source nil
helm-always-two-windows t
helm-split-window-in-side-p nil
;; helm-split-window-default-side 'other
helm-echo-input-in-header-line t)
;;keybindings
(general-define-key "M-x" 'helm-M-x)
;;; helm vim-bindings in buffer ;;
(define-key helm-map (kbd "C-a") (kbd "RET"))
(general-define-key :keymaps 'helm-map
"TAB" 'helm-execute-persistent-action ; rebind tab to do persistent action
"C-i" 'helm-execute-persistent-action ; make TAB works in terminal
"C-z" 'helm-select-action ; list actions using C-z
"C-j" 'helm-next-line
"C-k" 'helm-previous-line
"C-h" 'helm-next-source
"C-l" 'helm-previous-source
"C-S-h" 'describe-key)
(setq helm-boring-buffer-regexp-list '("\\*SPEEDBAR" "\\*magit" "\\*Sunshine" "\\*Help" "\\*Shell Command Output" "\\*Flycheck error message" "\\*Compile-Log" "\\` " "\\*helm" "\\*helm-mode" "\\*Echo Area" "\\*Minibuf"))
(helm-autoresize-mode 1)
(setq helm-autoresize-max-height 40)
(setq helm-autoresize-min-height 35)
;; helm selection faces
;; (set-face-attribute 'helm-selection nil
;; :foreground "#f7f438"
;; :background "#64b5ea"
;; :underline nil
;; :weight 'bold))
(helm-mode 1)
))
Hide modelines of other windows while helm is open, again from https://github.com/hatschipuh/better-helm.
(defvar my-helm-bottom-buffers nil
"List of bottom buffers before helm session.
Its element is a pair of `buffer-name' and `mode-line-format'.")
(defun my-helm-bottom-buffers-init ()
(setq-local mode-line-format (default-value 'mode-line-format))
(setq my-helm-bottom-buffers
(cl-loop for w in (window-list)
when (window-at-side-p w 'bottom)
collect (with-current-buffer (window-buffer w)
(cons (buffer-name) mode-line-format)))))
(defun my-helm-bottom-buffers-hide-mode-line ()
(setq-default cursor-in-non-selected-windows nil)
(mapc (lambda (elt)
(with-current-buffer (car elt)
(setq-local mode-line-format nil)))
my-helm-bottom-buffers))
(defun my-helm-bottom-buffers-show-mode-line ()
(setq-default cursor-in-non-selected-windows t)
(when my-helm-bottom-buffers
(mapc (lambda (elt)
(with-current-buffer (car elt)
(setq-local mode-line-format (cdr elt))))
my-helm-bottom-buffers)
(setq my-helm-bottom-buffers nil)))
(defun my-helm-keyboard-quit-advice (orig-func &rest args)
(my-helm-bottom-buffers-show-mode-line)
(apply orig-func args))
(add-hook 'helm-before-initialize-hook #'my-helm-bottom-buffers-init)
(add-hook 'helm-after-initialize-hook #'my-helm-bottom-buffers-hide-mode-line)
(add-hook 'helm-exit-minibuffer-hook #'my-helm-bottom-buffers-show-mode-line)
(add-hook 'helm-cleanup-hook #'my-helm-bottom-buffers-show-mode-line)
(advice-add 'helm-keyboard-quit :around #'my-helm-keyboard-quit-advice)
Hide minibuffer while helm is active
(defun my-helm-hide-minibuffer-maybe ()
(when (with-helm-buffer helm-echo-input-in-header-line)
(let ((ov (make-overlay (point-min) (point-max) nil nil t)))
(overlay-put ov 'window (selected-window))
(overlay-put ov 'face (let ((bg-color (face-background 'default nil)))
`(:background ,bg-color :foreground ,bg-color)))
(setq-local cursor-type nil))))
(add-hook 'helm-minibuffer-set-up-hook #'helm-hide-minibuffer-maybe)
(use-package helm-ag
:commands (helm-ag helm-ag-buffers helm-ag-this-file helm-do-ag helm-ag-project-root)
:config
(setq helm-ag-base-command "rg --no-heading")
(setq helm-ag-fuzzy-match t))
(use-package helm-descbinds
:defer t
:config
(setq helm-descbinds-window-style 'same-window)
(add-hook 'helm-mode-hook 'helm-descbinds-mode))
(use-package helm-ls-git :defer t)
(use-package helm-hunks
:commands helm-hunks)
Search on steroids
(use-package helm-swoop
:commands (helm-swoop helm-swoop-back-to-last-point helm-multi-swoop helm-multi-swoop-all)
:config
(setq helm-swoop-use-fuzzy-match t)
(setq helm-swoop-split-with-multiple-windows t))
Use helm with flyspell
(use-package helm-flyspell
:if (not noninteractive)
:ensure t
:commands helm-flyspell-correct
:config
(bind-key "C-;" 'helm-flyspell-correct flyspell-mode-map)
)
(use-package helm-flx
:after helm
:config
(setq helm-flx-for-helm-find-files t ;; t by default
helm-flx-for-helm-locate t) ;; nil by default
)
Recent directories
(use-package helm-dired-recent-dirs
:defer t)
(use-package helm-files
:ensure nil
:config
(setq helm-ff-skip-boring-files t)
(setq helm-idle-delay 0.05)
(setq helm-input-idle-delay 0.05)
(setq helm-ff-file-name-history-use-recentf t)
(setq helm-boring-file-regexp-list
'("\\.git$" "\\.hg$" "\\.svn$" "\\.CVS$" "\\._darcs$" "\\.la$" "\\.o$" "~$"
"\\.so$" "\\.a$" "\\.elc$" "\\.fas$" "\\.fasl$" "\\.pyc$" "\\.pyo$")))
(use-package helm-projectile
:commands (helm-projectile-switch-to-buffer
helm-projectile-find-dir
helm-projectile-dired-find-dir
helm-projectile-recentf
helm-projectile-find-file
helm-projectile-grep
helm-projectile
helm-projectile-switch-project)
:init
(setq projectile-switch-project-action 'helm-projectile))
(use-package helm-themes
:commands helm-themes)
(defadvice helm-themes--load-theme (after helm-themes--load-theme-after activate) (require 'powerline) (powerline-reset))
;; (ad-unadvise 'helm-themes--load-theme)
Numbered window shortcuts for Emacs
(use-package window-numbering
:ensure t
:config
(defun window-numbering-install-mode-line (&optional position)
"Do nothing, the display is handled by the powerline.")
(setq window-numbering-auto-assign-0-to-minibuffer nil)
(cpm-leader1
"0" 'select-window-0
"1" 'select-window-1
"2" 'select-window-2
"3" 'select-window-3
"4" 'select-window-4
"5" 'select-window-5)
;; "6" 'select-window-6
;; "7" 'select-window-7
;; "8" 'select-window-8
;; "9" 'select-window-9)
(window-numbering-mode 1)
;; make sure neotree is always 0
(defun spacemacs//window-numbering-assign ()
"Custom number assignment for neotree."
(when (and (boundp 'neo-buffer-name)
(string= (buffer-name) neo-buffer-name)
;; in case there are two neotree windows. Example: when
;; invoking a transient state from neotree window, the new
;; window will show neotree briefly before displaying the TS,
;; causing an error message. the error is eliminated by
;; assigning 0 only to the top-left window
(eq (selected-window) (window-at 0 0)))
0))
;; using lambda to work-around a bug in window-numbering, see
;; https://github.com/nschum/window-numbering.el/issues/10
(setq window-numbering-assign-func
(lambda () (spacemacs//window-numbering-assign))))
;; (defun spacemacs//window-numbering-assign (windows)
;; "Custom number assignment for special buffers."
;; (mapc (lambda (w)
;; (when (and (boundp 'neo-global--window)
;; (eq w neo-global--window))
;; (window-numbering-assign w 0)))
;; windows))
;; (add-hook 'window-numbering-before-hook 'spacemacs//window-numbering-assign)
;; (add-hook 'neo-after-create-hook '(lambda (w) (window-numbering-update)))
(use-package windmove
:commands (windmove-up windmove-down windmove-left windmove-right)
:config
(defun split-window-right-and-focus ()
"Split the window horizontally and focus the new window."
(interactive)
(split-window-right)
(windmove-right))
(defun split-window-below-and-focus ()
"Split the window vertically and focus the new window."
(interactive)
(split-window-below)
(windmove-down))
;; add edit mode keybindings
(global-set-key (kbd "<H-up>") 'windmove-up)
(global-set-key (kbd "<H-down>") 'windmove-down)
(global-set-key (kbd "<H-left>") 'windmove-left)
(global-set-key (kbd "<H-right>") 'windmove-right)
)
Auto-revert buffers of changed files
(use-package autorevert
:defer 2
:ensure nil
:init
(global-auto-revert-mode 1)
:config
(progn
(setq auto-revert-verbose nil ; Shut up, please!
revert-without-query '(".*") ;; disable revert query
;; Revert Dired buffers, too
global-auto-revert-non-file-buffers t)))
Various settings to make Emacs (mostly the GUI version) look better or make interaction smoother.
I like the frame centered and approximately 2/3 of a 13inch laptop screen.
;; Set Frame width/height
(setq default-frame-alist
'((top . 25) (left . 275) (width . 105) (height . 60)))
Show the filepath in the frame title.
(setq frame-title-format
'(" "
(buffer-file-name "%f"
(dired-directory dired-directory "%b"))))
Turn off all of the GUI cruft.
;; Turn off mouse interface early in startup to avoid momentary display
(when (display-graphic-p)
(menu-bar-mode -1)
(tool-bar-mode -1)
(scroll-bar-mode -1)
(tooltip-mode -1))
Ditto for the terminal.
(when (not (display-graphic-p))
(menu-bar-mode -1))
Inconsolata is a nice monospaced font.
To install it on OS X, you can use Homebrew with Homebrew Cask.
# You may need to run these two lines if you haven't set up Homebrew
# Cask and its fonts formula.
brew install caskroom/cask/brew-cask
brew tap caskroom/fonts
brew cask install font-inconsolata
And here’s how we tell Emacs to use the font we want to use.
;; deal with fonts [[https://github.com/rolandwalker/dynamic-fonts][dynamically]].
(use-package dynamic-fonts
:config (dynamic-fonts-setup)
:init
(progn (setq dynamic-fonts-preferred-proportional-fonts
'("Cantarell" "Source Sans Pro" "Helvetica"))
(setq dynamic-fonts-preferred-monospace-fonts
'("Inconsolata LGC for Powerline" "Source Code Pro" "Monaco" "Consolas" "Menlo"
"DejaVu Sans Mono" "Droid Sans Mono Pro" "Droid Sans Mono")))
)
(global-set-key (kbd "C-+") 'text-scale-increase)
(global-set-key (kbd "C--") 'text-scale-decrease)
;; C-x C-0 restores the default font size
This is a really nice powerline-ish modeline.
(use-package spaceline
:ensure t
:init
(progn
;; size of modeline
(setq powerline-height 21)
(setq spaceline-highlight-face-func 'spaceline-highlight-face-evil-state)
;; (setq-default powerline-default-separator nil)
;; (setq-default powerline-default-separator 'utf-8)
;; (setq powerline-utf-8-separator-left #xe0b0)
;; (setq powerline-utf-8-separator-right #xe0b2)
;; (set-face-attribute 'mode-line nil :font "Source Code Pro-14")
;; small triangles
;; (setq powerline-utf-8-separator-left #x25ba)
;; (setq powerline-utf-8-separator-right #x25c4)
;; (setq powerline-text-scale-factor .3)
;; half circles
;; (setq powerline-utf-8-separator-left 9687
;; powerline-utf-8-separator-right 9686)
;; slant (requires srbg support)
(setq-default powerline-default-separator 'slant)
(setq spaceline-separator-dir-left '(right . right))
(setq spaceline-separator-dir-right '(right . right))
;; fancy git icon for the modeline
(defadvice vc-mode-line (after strip-backend () activate)
(when (stringp vc-mode)
(let ((gitlogo (replace-regexp-in-string "^ Git." ":" vc-mode)))
(setq vc-mode gitlogo)))))
:config
(require 'spaceline-config)
(spaceline-toggle-buffer-size-off)
(spaceline-spacemacs-theme)
(setq spaceline-buffer-encoding-abbrev-p nil
spaceline-window-numbers-unicode t
spaceline-line-column-p nil
spaceline-buffer-id-p nil
spaceline-minor-modes-separator " "))
(powerline-reset)
;; nil - don't use srgb & get proper powerline faces
(setq ns-use-srgb-colorspace t)
(use-package fancy-battery
:init
(fancy-battery-mode)
:config
(setq-default battery-update-interval 10))
;; :config
;; (set-face-attribute 'fancy-battery-charging nil
;; :foreground "dark blue" :weight 'bold)
;; (set-face-attribute 'fancy-battery-discharging nil
;; :foreground "dark magenta" :weight 'bold)
;; (set-face-attribute 'fancy-battery-critical nil
;; :foreground "dark red" :weight 'bold))
(setq display-time-format " %a %b %d | %H:%M |")
(display-time-mode)
Hide mode line. From http://bzg.fr/emacs-hide-mode-line.html
(defvar-local hidden-mode-line-mode nil)
(defvar-local hide-mode-line nil)
(define-minor-mode hidden-mode-line-mode
"Minor mode to hide the mode-line in the current buffer."
:init-value nil
:global t
:variable hidden-mode-line-mode
:group 'editing-basics
(if hidden-mode-line-mode
(setq hide-mode-line mode-line-format
mode-line-format nil)
(setq mode-line-format hide-mode-line
hide-mode-line nil))
(force-mode-line-update)
;; Apparently force-mode-line-update is not always enough to
;; redisplay the mode-line
(redraw-display)
(when (and (called-interactively-p 'interactive)
hidden-mode-line-mode)
(run-with-idle-timer
0 nil 'message
(concat "Hidden Mode Line Mode enabled. "
"Use M-x hidden-mode-line-mode to make the mode-line appear."))))
The best low-contrast theme out there.
(use-package solarized-theme
:ensure t
:if (display-graphic-p)
:init
(progn
;; don't make the fringe stand out from the background
(setq solarized-distinct-fringe-background nil)
;; change the font for some headings and titles
(setq solarized-use-variable-pitch t)
;; make the modeline high contrast
(setq solarized-high-contrast-mode-line t)
;; Use bolding
(setq solarized-use-less-bold nil)
;; Use more italics
(setq solarized-use-more-italic t)
;; Use colors for indicators such as git:gutter, flycheck and similar
(setq solarized-emphasize-indicators t)
;; Don't change size of org-mode headlines (but keep other size-changes)
(setq solarized-scale-org-headlines t)
;; don't italicize line numbers
;; (add-hook 'after-make-frame-functions
;; (lambda (frame)
;; (select-frame frame)
;; (if (display-graphic-p)
;; (set-face-attribute 'linum frame
;; :background (face-attribute 'default :background)
;; :foreground (face-attribute 'linum :foreground) :slant 'normal))))
;; Theme toggle
(setq active-theme 'solarized-dark)
(defun toggle-dark-light-theme ()
(interactive)
(if (eq active-theme 'solarized-light)
(setq active-theme 'solarized-dark)
(setq active-theme 'solarized-light))
(load-theme active-theme)
(powerline-reset))
)
:config
(progn
(defvar after-load-theme-hook nil
"Hook run after a color theme is loaded using `load-theme'.")
(defadvice load-theme (after run-after-load-theme-hook activate)
"Run `after-load-theme-hook'."
(run-hooks 'after-load-theme-hook))
(defun customize-solarized-dark ()
"Customize solarized theme"
(if (member 'solarized-dark custom-enabled-themes)
(custom-theme-set-faces
'solarized-dark
;; org faces
'(org-block ((t (:foreground "#2E8B57"))))
'(org-block-begin-line ((t (:foreground "#74a8a4" :weight bold :slant normal))))
'(org-level-1 ((t (:inherit variable-pitch :foreground "#268bd2" :height 1.5))))
'(org-level-2 ((t (:inherit variable-pitch :foreground "medium sea green" :height 1.3))))
'(org-level-3 ((t (:inherit variable-pitch :foreground "#cb4b16" :height 1.2))))
'(org-level-8 ((t (:inherit variable-pitch :foreground "#9e1e86" :height 1.1))))
'(org-quote ((t (:inherit org-block :slant normal :weight normal))))
;; markdown faces
'(markdown-comment-face ((t (:weight normal :slant italic :strike-through nil))))
'(markdown-header-face-1 ((t (:inherit variable-pitch :foreground "#268bd2" :height 1.75))))
'(markdown-header-face-2 ((t (:inherit variable-pitch :foreground "medium sea green" :height 1.45))))
'(markdown-header-face-3 ((t (:inherit variable-pitch :foreground "#cb4b16" :height 1.2))))
;; helm faces
'(helm-selection ((t (:foreground "#f7f438" :background "#64b5ea" :underline nil :weight bold))))
;; line highlighting
'(linum-highlight-face ((t (:inherit default :foreground "goldenrod1"))))
;; battery faces
'(fancy-battery-charging ((t (:foreground "dark blue" :weight bold))))
'(fancy-battery-critical ((t (:foreground "dark red" :weight bold))))
'(fancy-battery-discharging ((t (:foreground "dark magenta" :weight bold)))))))
(add-hook 'after-load-theme-hook 'customize-solarized-dark)
(defun customize-solarized-light ()
"Customize solarized theme"
(if (member 'solarized-light custom-enabled-themes)
(custom-theme-set-faces
'solarized-light
;; org faces
'(org-block ((t (:foreground "#2E8B57"))))
'(org-block-begin-line ((t (:foreground "#74a8a4" :weight bold :slant normal))))
'(org-level-1 ((t (:inherit variable-pitch :foreground "#268bd2" :height 1.3))))
'(org-level-2 ((t (:inherit variable-pitch :foreground "medium sea green" :height 1.2))))
'(org-level-3 ((t (:inherit variable-pitch :foreground "#cb4b16" :height 1.15))))
'(org-level-8 ((t (:inherit variable-pitch :foreground "#9e1e86" :height 1.1))))
'(org-quote ((t (:inherit org-block :slant normal :weight normal))))
;; markdown faces
'(markdown-comment-face ((t (:weight normal :slant italic :strike-through nil))))
'(markdown-header-face-1 ((t (:inherit variable-pitch :foreground "#268bd2" :height 1.75))))
'(markdown-header-face-2 ((t (:inherit variable-pitch :foreground "medium sea green" :height 1.45))))
'(markdown-header-face-3 ((t (:inherit variable-pitch :foreground "#cb4b16" :height 1.2))))
;; helm faces
'(helm-selection ((t (:foreground "#f7f438" :background "#64b5ea" :underline nil :weight bold))))
;; line highlighting
'(linum-highlight-face ((t (:inherit default :foreground "#002b36"))))
;; battery faces
'(fancy-battery-charging ((t (:foreground "dark blue" :weight bold))))
'(fancy-battery-critical ((t (:foreground "dark red" :weight bold))))
'(fancy-battery-discharging ((t (:foreground "dark magenta" :weight bold)))))))
(add-hook 'after-load-theme-hook 'customize-solarized-light)
)
(load-theme 'solarized-dark t)
)
;; Avoid all font-size changes
;; (setq solarized-height-minus-1 1)
;; (setq solarized-height-plus-1 1)
;; (setq solarized-height-plus-2 1)
;; (setq solarized-height-plus-3 1)
;; (setq solarized-height-plus-4 1))
;; An alternative solarized theme
(use-package color-theme-sanityinc-solarized
:ensure t
:disabled t
:init
(progn
(load-theme 'sanityinc-solarized-dark t)))
This is a great general-purpose theme. Use it in terminal.
(use-package gruvbox-theme
:ensure t
:if (not (display-graphic-p))
:config
(load-theme 'gruvbox t))
Nice dark theme with custom modeline
(use-package zerodark-theme
:if (display-graphic-p)
:config
(custom-set-faces
'(org-block-begin-line ((t (:background "#282c34" :foreground "#98be65" :height 0.9))))
'(org-block-end-line ((t (:background "#282c34" :foreground "#98be65" :height 0.9)))))
(zerodark-setup-modeline-format)
;; (load-theme 'zerodark t)
)
Make sure that other themes I like are downloaded and available
(defvar packages-appearance
'(monokai-theme solarized-theme zenburn-theme molokai-theme darktooth-theme
tango-2-theme gotham-theme sublime-themes
waher-theme ample-theme material-theme zerodark-theme
color-theme-modern leuven-theme spacemacs-theme gruvbox-theme
forest-blue-theme flatland-theme afternoon-theme
cyberpunk-theme madhat2r-theme kaolin-theme darkmine-theme tao-theme darkokai-theme jazz-theme suscolors-theme omtose-phellack-theme)
"A list of themes to ensure are installed at launch.")
(defun appearance-packages-installed-p ()
(loop for p in packages-appearance
when (not (package-installed-p p)) do (return nil)
finally (return t)))
(unless (appearance-packages-installed-p)
;; check for new packages (package versions)
(message "%s" "Emacs is now refreshing its package themes...")
(package-refresh-contents)
(message "%s" " done.")
;; install the missing packages
(dolist (p packages-appearance)
(when (not (package-installed-p p))
(package-install p))))
(provide 'packages-appearance)
(use-package rees-themes
:ensure nil
:load-path "~/.emacs.d/elisp/rees-themes"
:defer t
)
;; line number spacing
(setq-default linum-format "%4d ")
;; Highlight current line number
(use-package hlinum
:commands hlinum-mode
:config
(custom-set-faces
'(linum-highlight-face ((t (:inherit default :foreground "goldenrod1")))))
:init
(add-hook 'linum-mode-hook 'hlinum-activate))
Highlight numbers in source code
(use-package highlight-numbers
:ensure t
:defer t
:init
(add-hook 'prog-mode-hook #'highlight-numbers-mode))
highlight TODO statements in comments
(use-package hl-todo
:ensure t
:defer t
:config
(setq global-hl-todo-mode t))
Tidy Up modeline modes.
(use-package diminish :defer 2)
(diminish 'visual-line-mode)
(eval-after-load "flyspell" '(diminish 'flyspell-mode "Ⓢ"))
(eval-after-load "abbrev" '(diminish 'abbrev-mode "Ⓐ"))
(eval-after-load "lispy" '(diminish 'lispy-mode ""))
(eval-after-load "lispyville" '(diminish 'lispyville-mode "Ⓛ"))
(eval-after-load "centered-window-mode" '(diminish 'centered-window-mode "⦿"))
(eval-after-load "org-indent" '(diminish 'org-indent-mode))
(eval-after-load "simple" '(diminish 'auto-fill-function "Ⓕ"))
(eval-after-load "pandoc-mode" '(diminish 'pandoc-mode "Ⓟ"))
(eval-after-load "git-gutter+" '(diminish 'git-gutter+-mode))
(eval-after-load "company" '(diminish 'company-mode "Ⓒ"))
(eval-after-load "cm-mode" '(diminish 'cm-mode "ⓒ"))
(eval-after-load "reftex" '(diminish 'reftex-mode "ⓡ"))
(eval-after-load "autorevert" '(diminish 'auto-revert-mode "Ⓡ"))
(eval-after-load "simple" '(diminish 'auto-revert-mode "Ⓡ"))
(eval-after-load "aggressive-indent" '(diminish 'aggressive-indent-mode "Ⓘ"))
(eval-after-load "auto-indent-mode" '(diminish 'auto-indent-mode "ⓘ"))
(eval-after-load "smartparens" '(diminish 'smartparens-mode "ⓟ"))
(eval-after-load "org-zotxt" '(diminish 'org-zotxt-mode ""))
(eval-after-load "back-button" '(diminish 'back-button-mode ""))
;; (eval-after-load "undo-tree" '(diminish 'undo-tree-mode "Ⓤ"))
(eval-after-load "undo-tree" '(diminish 'undo-tree-mode ""))
(eval-after-load "projectile" '(diminish 'projectile-mode ""))
(eval-after-load "helm" '(diminish 'helm-mode ""))
Like the title says…
(use-package all-the-icons :defer t :diminish "")
;; icons for dired
(use-package all-the-icons-dired
:diminish ""
:commands (deer deer-jump-other-window all-the-icons-dired-mode dired-mode ranger)
:init
(add-hook 'dired-mode-hook 'all-the-icons-dired-mode))
Useful for letting you know where the cursor is
(use-package beacon
:ensure t
:diminish beacon-mode
:init (beacon-mode 1)
:config
(add-to-list 'beacon-dont-blink-major-modes 'eshell-mode))
Use helm
(bind-key "C-h a" 'helm-apropos)
Keep the cursor centered in the screen
(use-package centered-cursor-mode
:diminish centered-cursor-mode
:commands (centered-cursor-mode
global-centered-cursor-mode)
:config
(progn
(setq ccm-recenter-at-end-of-file t
ccm-ignored-commands '(mouse-drag-region
mouse-set-point
widget-button-click
scroll-bar-toolkit-scroll
evil-mouse-drag-region))))
I use a lot of keybindings, with <SPC> as my “leader” key.
(cpm-leader1
"a" '(:ignore t :which-key "Applications")
"ac" '(:ignore t :which-key "Cmus")
"ad" 'deer
"ae" 'eshell
"am" 'multi-term
"ar" 'ranger
"as" 'sane-term
"aw" 'wttrin
)
(cpm-leader1
"b" '(:ignore t :which-key "Buffers")
"bb" 'helm-mini
"bc" 'spacemacs/new-empty-buffer
"bD" 'kill-buffer-and-window
"bd" 'kill-this-buffer
"bf" 'browse-file-directory
"bj" 'jump-in-buffer
"bk" 'evil-delete-buffer
"bK" 'spacemacs/kill-other-buffers
"bn" 'spacemacs/new-empty-buffer
;; "bN" 'crux-kill-other-buffers
"br" 'revert-buffer
"bR" 'spacemacs/rename-current-buffer-file
"bt" 'open-dir-in-iterm
)
(cpm-leader1
"c" '(:ignore t :which-key "Commenting")
"cb" 'org-block-wrap
"cc" 'evil-commentary
"cl" 'evil-commentary-line
"cy" 'evil-commentary-yank-line
)
(cpm-leader1
"C" '(:ignore t :which-key "Config")
"Cc" 'goto-config.org
"Cl" 'load-config
"Ci" 'goto-init.el
"Cs" 'goto-custom.el
)
(cpm-leader1
"f" '(:ignore t :which-key "Files")
"fd" 'fzf-directory
"ff" 'helm-find-files
;; "ff" 'counsel-find-files
;; "fl" 'counsel-locate
"fl" 'helm-locate
"fo" 'crux-open-with
"fs" 'save-buffer
"fr" 'helm-recentf
;; "fr" 'counsel-recentf
"fy" 'spacemacs/show-and-copy-buffer-filename
"fz" 'fzf
)
(cpm-leader1
"A" 'helm-apropos
"?" 'helm-descbinds
;; "?" 'counsel-descbinds
"<SPC>" 'helm-M-x
;; "<SPC>" 'counsel-M-x
"d" 'deer
"D" 'deer-jump-other-window
"e" 'server-edit
"G" 'general-describe-keybindings
"h" 'helm-resume
;; "r" 'ivy-resume
"j" 'avy-goto-char
"k" 'helm-show-kill-ring
"N" 'research-notes
"n" 'big-notes
"M" 'woman
"'" 'shell-pop
"." 'quick-commit
";" 'evil-commentary-line
"[" 'spacemacs/previous-useful-buffer
"]" 'spacemacs/next-useful-buffer
"TAB" 'switch-to-previous-buffer)
(defun my-markdown-config ()
"Modify keymaps in markdown mode"
(cpm-leader1
"m" '(:ignore t :which-key "Markdown")
"mc" '(:ignore t :which-key "command")
"mh" '(:ignore t :which-key "insert")
"mi" '(:ignore t :which-key "lists")
"mx" '(:ignore t :which-key "text")
;; Movement
"m{" 'markdown-backward-paragraph
"m}" 'markdown-forward-paragraph
;; Completion, and Cycling
"m]" 'markdown-complete
;; Indentation
"m>" 'markdown-indent-region
"m<" 'markdown-exdent-region
;; Buffer-wide commands
"mc]" 'markdown-complete-buffer
"mcc" 'markdown-check-refs
"mce" 'markdown-export
"mcm" 'markdown-other-window
"mcn" 'markdown-cleanup-list-numbers
"mco" 'markdown-open
"mcp" 'markdown-preview
"mcv" 'markdown-export-and-preview
"mcw" 'markdown-kill-ring-save
;; headings
"mhi" 'markdown-insert-header-dwim
"mhI" 'markdown-insert-header-setext-dwim
"mh1" 'markdown-insert-header-atx-1
"mh2" 'markdown-insert-header-atx-2
"mh3" 'markdown-insert-header-atx-3
"mh4" 'markdown-insert-header-atx-4
"mh5" 'markdown-insert-header-atx-5
"mh6" 'markdown-insert-header-atx-6
"mh!" 'markdown-insert-header-setext-1
"mh@" 'markdown-insert-header-setext-2
;; Insertion of common elements
"m-" 'markdown-insert-hr
"mif" 'markdown-insert-footnote
"mii" 'markdown-insert-image
"mik" 'spacemacs/insert-keybinding-markdown
"miI" 'markdown-insert-reference-image
"mil" 'markdown-insert-link
"miL" 'markdown-insert-reference-link-dwim
"miw" 'markdown-insert-wiki-link
"miu" 'markdown-insert-uri
;; Element removal
"mk" 'markdown-kill-thing-at-point
;; List editing
"mli" 'markdown-insert-list-item
;; region manipulation
"mxb" 'markdown-insert-bold
"mxi" 'markdown-insert-italic
"mxc" 'markdown-insert-code
"mxC" 'markdown-insert-gfm-code-block
"mxq" 'markdown-insert-blockquote
"mxQ" 'markdown-blockquote-region
"mxp" 'markdown-insert-pre
"mxP" 'markdown-pre-region
;; Following and Jumping
"mN" 'markdown-next-link
"mf" 'markdown-follow-thing-at-point
"mP" 'markdown-previous-link
"<RET>" 'markdown-jump
))
;; (which-key-add-major-mode-key-based-replacements 'markdown-mode
;; "C-c C-a" "insert"
;; "C-c C-c" "export"
;; "C-c TAB" "images"
;; "C-c C-s" "text"
;; "C-c C-t" "header"
;; "C-c C-x" "move"
;; )
;; Show which-key top-level bindings
(global-set-key (kbd "H-k") 'which-key-show-top-level)
;; override evil insert for kill line
(general-define-key :states '(insert) "C-k" 'kill-line)
Keybindings for org mode
(cpm-leader1
"o" '(:ignore t :which-key "Org")
"oh" '(:ignore t :which-key "headers")
"oi" '(:ignore t :which-key "insert")
"oS" '(:ignore t :which-key "subtree")
"ot" '(:ignore t :which-key "tables")
"or" '(:ignore t :which-key "org-reveal")
"oj" 'cpm/org-journal
"oc" 'org-capture
"oe" '(:ignore t :which-key "export")
"oep" 'org-pandoc-export-to-latex-pdf
"oeP" 'org-pandoc-export-to-latex-pdf-and-open
"of" 'org-footnote-action
"oP" 'org-set-property
;; "P" 'org-publish-current-project
"op" 'org-publish-current-file
"o:" 'org-set-tags
"oa" 'org-agenda
"ob" 'org-tree-to-indirect-buffer
"oA" 'org-archive-subtree
"ol" 'org-open-at-point
"oT" 'org-show-todo-tree
"orr" 'org-reveal-export-to-html-and-browse
"ors" 'org-reveal-export-current-subtree
"orp" 'reveal-to-pdf
"o." 'org-time-stamp
"o!" 'org-time-stamp-inactive
;; headings
"ohi" 'org-insert-heading-after-current
"ohI" 'org-insert-heading
;; More cycling options (timestamps, headlines, items, properties)
"oL" 'org-shiftright
"oH" 'org-shiftleft
"oJ" 'org-shiftdown
"oK" 'org-shiftup
;; Subtree editing
"oSl" 'org-demote-subtree
"oSh" 'org-promote-subtree
"oSj" 'org-move-subtree-down
"oSk" 'org-move-subtree-up
;; tables
"ota" 'org-table-align
"otb" 'org-table-blank-field
"otc" 'org-table-convert
"otdc" 'org-table-delete-column
"otdr" 'org-table-kill-row
"ote" 'org-table-eval-formula
"otE" 'org-table-export
"oth" 'org-table-previous-field
"otH" 'org-table-move-column-left
"otic" 'org-table-insert-column
"otih" 'org-table-insert-hline
"otiH" 'org-table-hline-and-move
"otir" 'org-table-insert-row
"otI" 'org-table-import
"otj" 'org-table-next-row
"otJ" 'org-table-move-row-down
"otK" 'org-table-move-row-up
"otl" 'org-table-next-field
"otL" 'org-table-move-column-right
"otn" 'org-table-create
"otN" 'org-table-create-with-table.el
"otr" 'org-table-recalculate
"ots" 'org-table-sort-lines
"ottf" 'org-table-toggle-formula-debugger
"otto" 'org-table-toggle-coordinate-overlays
"otw" 'org-table-wrap-region
;; Multi-purpose keys
;; "o*" 'org-ctrl-c-star
;; "oRET" 'org-ctrl-c-ret
"o-" 'org-ctrl-c-minus
"o^" 'org-sort
"o/" 'org-sparse-tree
"oI" 'org-clock-in
"on" 'org-narrow-to-subtree
"oN" 'widen
"oO" 'org-clock-out
"oq" 'org-clock-cancel
"oR" 'org-refile
"os" 'org-schedule
;; insertion of common elements
"oil" 'org-insert-link
"oif" 'org-footnote-new
)
Keybindings for managing packages
(cpm-leader1
"P" '(:ignore t :which-key "Packages")
"Pl" 'paradox-list-packages
"Pu" 'paradox-upgrade-packages
)
(cpm-leader1
"p" '(:ignore t :which-key "Projects")
"p!" 'projectile-run-shell-command-in-root
"p&" 'projectile-run-async-shell-command-in-root
"pa" 'projectile-toggle-between-implementation-and-test
"pb" 'helm-projectile-switch-to-buffer
"pc" 'projectile-compile-project
"pd" 'helm-projectile-find-dir
"pD" 'projectile-dired
"pf" 'helm-projectile-find-file
"pg" 'goto-projects
"ph" 'helm-projectile
"pG" 'projectile-regenerate-tags
"pI" 'projectile-invalidate-cache
"pk" 'projectile-kill-buffers
"pl" 'desktop+-load
"po" 'projectile-multi-occur
"pp" 'helm-projectile-switch-project
"pr" 'helm-projectile-recentf
"pR" 'projectile-replace
;; "ps" 'bmkp-set-desktop-bookmark
"ps" 'desktop+-create
"pS" 'bmkp-desktop-jump
"pT" 'projectile-find-test-file
"pv" 'projectile-vc
"py" 'projectile-find-tag
)
(cpm-leader1
"q" '(:ignore t :which-key "Quit")
"qq" 'save-desktop-save-buffers-kill-emacs
"qQ" 'evil-quit-all
"qr" 'restart-emacs)
(cpm-leader1
"s" '(:ignore t :which-key "Search")
"sd" 'helm-do-ag ;; search with directory prompt
"sb" 'helm-ag-buffers
"sf" 'helm-do-ag-this-file
"sj" 'forward-or-backward-sexp
"sk" 'helm-show-kill-ring
"sl" 'last-search-buffer
"so" 'helm-occur
"sp" 'helm-ag-project-root
"ss" 'helm-swoop-without-pre-input ;; search in file
"/" 'helm-ag ;; search in directory with word prompt
)
(cpm-leader1
"t" '(:ignore t :which-key "Toggles")
"ta" 'company-mode
"tb" 'fancy-battery-mode
"tB" 'beacon-mode
"tc" 'centered-cursor-mode
"tC" 'centered-window-mode
"td" 'distraction-free
"tf" 'toggle-serif
"tF" 'toggle-frame-fullscreen
"tg" 'git-gutter-mode
"th" 'hl-line-mode
"te" 'toggle-indicate-empty-lines
"tE" 'eldoc-mode
"tm" 'hidden-mode-line-mode
"tM" 'spaceline-toggle-minor-modes
"tn" 'linum-mode
"to" 'org-toggle-link-display
"tp" 'smartparens-mode
"tP" 'show-paren-mode
"tr" 'rainbow-identifiers-mode
"ts" 'toggle-dark-light-theme
"tt" 'helm-themes
"tT" 'neotree-toggle
"tw" 'writeroom-mode
"tz" 'zone
;; "tt" 'counsel-load-theme
)
(cpm-leader1
"u" '(:ignore t :which-key "User")
"um" 'cpm/org-to-markdown
"uc" 'pandoc-convert-to-pdf
"uo" 'cpm/markdown-to-org
"up" 'run-pandoc
"uP" 'pandoc-pdf-open
"us" 'sb-expand-current-file
"uS" 'just-one-space
"ud" 'distraction-free
"uD" 'my-desktop
"uj" 'goto-journal
;; "op" 'pandoc-convert-to-pdf
"uw" 'count-words
"uW" 'osx-dictionary-search-input
"ux" 'helm-bibtex
)
(cpm-leader1
"g" '(:ignore t :which-key "Git")
"gb" 'magit-blame
"gc" 'magit-commit
"gd" 'magit-diff
"gl" 'magit-log
"gn" 'git-gutter:next-hunk
"gp" 'git-gutter:previous-hunk
"gr" 'magit-reflog
"gs" 'magit-status
)
(cpm-leader1
"w" '(:ignore t :which-key "Windows")
"wc" 'delete-window
"w-" 'evil-window-split
"w_" 'split-window-below-and-focus
"wr" 'rotate-windows
"wR" 'rotate-windows-backward
"wv" 'split-window-right-and-focus
"wV" 'evil-window-vsplit
"wm" 'delete-other-windows
)
(cpm-leader1
"W" '(:ignore t :which-key "Wiki")
"Wd" 'org-wiki-dired-all
"Wk" 'org-wiki-close
"Wh" 'org-wiki-helm
"WH" 'org-wiki-help
"WI" 'org-wiki-index
"Wi" 'org-wiki-insert
"Wl" 'org-wiki-link
"Wv" 'org-wiki-server-toggle
"We" 'org-wiki-export-html
"Wp" 'org-wiki-panel
"Ws" 'org-wiki-search
)
(use-package which-key
:defer 2
:diminish ""
:config
(setq which-key-special-keys nil)
;; Set the time delay (in seconds) for the which-key popup to appear.
(setq which-key-idle-delay .2)
(which-key-mode))
Package that puts an end to popped up buffers not behaving they way you’d like them to.
(use-package shackle
:config
;; make helm pop-ups behave
(setq helm-display-function #'pop-to-buffer)
(setq shackle-rules '(("\\`\\*helm.*?\\*\\'" :regexp t :align t :ratio 0.46)))
(shackle-mode 1))
;;;; define commands for controlling cmus from emacs
;;; utility (non-interactive) functions
(defun cmus-status ()
"Return the current cmus status."
(split-string
(shell-command-to-string "cmus-remote -Q")
"\n"))
(defun cmus-get-status-property (status property)
"Search the status for the requested property."
(replace-regexp-in-string property ""
(car
(delq nil
(mapcar (lambda (prop-line)
(if (string-match property prop-line)
prop-line
nil))
status)))))
(defun cmus-get-artist (status)
"Return the currently playing track."
(cmus-get-tag status "artist"))
(defun cmus-get-album (status)
"Return the album for the current track."
(cmus-get-tag status "album"))
(defun cmus-get-title (status)
"Return the track title for the current track"
(cmus-get-tag status "title"))
(defun cmus-get-tag (status tag)
"Return the matching tag from the status."
(let ((tag-match (concat "^tag " tag " ")))
(cmus-get-status-property status tag-match)))
(defun cmus-playingp ()
"Returns true if cmus is currently playing."
(let ((status (cmus-get-status-property (cmus-status) "status ")))
(if (equal status "playing")
(progn
(message "playing")
t)
(progn
(message "paused")
nil))))
;;; interactive functions
(defun cmus-next-track ()
"Play the next track in cmus."
(interactive)
(shell-command-to-string "cmus-remote -n"))
(defun cmus-prev-track ()
"Go back a track in cmus."
(interactive)
(shell-command-to-string "cmus-remote -r"))
(defun cmus-play-pause ()
"If cmus is playing, pause it. If it is paused or stopped, start playing."
(interactive)
(if (cmus-playingp)
(progn
(message "Pausing..")
(shell-command-to-string "cmus-remote --pause"))
(progn
(message "Playing.")
(shell-command-to-string "cmus-remote --play"))))
(defun cmus-stop ()
"Stop cmus."
(interactive)
(shell-command-to-string "cmus-remote --stop"))
(defun cmus-now-playing ()
"Show the currently playing track."
(interactive)
(let ((status (cmus-status)))
(let ((artist (cmus-get-artist status))
(album (cmus-get-album status))
(title (cmus-get-title status))
(status (cmus-get-status-property status "status ")))
(message (concat artist " - " title " (" album ")")))))
(defun cmus-set-volume (volume)
"Set the current volume in cmus"
(interactive (let ((volume (read-string "Volume: ")))
(list volume)))
(let ((volume (if (stringp volume) volume (car volume))))
(shell-command-to-string (concat "cmus-remote -v " volume "%"))))
(defun cmus-toggle-shuffle ()
"Toggle playing shuffle."
(interactive)
(shell-command-to-string "cmus-remote -S")
(message
(concat "shuffle is "
(if (equal "true" (cmus-get-status-property (cmus-status) "set shuffle "))
"on"
"off"))))
(defun cmus-toggle-repeat ()
"Toggle playing repeat."
(interactive)
(shell-command-to-string "cmus-remote -R")
(message
(concat "repeat is "
(if (equal "true" (cmus-get-status-property (cmus-status) "set repeat "))
"on"
"off"))))
(defun cmus-toggle-mode ()
"Toggle between artist, album and all modes."
(interactive)
(shell-command-to-string "cmus-remote -C \"toggle aaa_mode\"")
(message
(concat "current mode: "
(cmus-get-status-property (cmus-status) "set aaa_mode "))))
(cpm-leader1
"acx" 'cmus-play-pause
"acn" 'cmus-next-track
"acp" 'cmus-prev-track
"ack" 'cmus-stop
"acs" 'cmus-now-playing
"acv" 'cmus-set-volume
"ach" 'cmus-toggle-shuffle
"acr" 'cmus-toggle-repeat
"acm" 'cmus-toggle-mode)
(use-package url
:ensure nil
:defer t
:config
(setq url-configuration-directory
(file-name-as-directory
(concat user-cache-directory "url"))))
(use-package avy
:commands (avy-goto-char))
(use-package bookmark+
;; :commands bmkp-set-desktop-bookmark
:init
(setq bookmark-default-file
(concat user-cache-directory "bookmarks"))
(setq bmkp-last-as-first-bookmark-file "~/.emacs.d/.cache/bookmarks")
)
(use-package hydra
:defer 4
:config
;; hydra for TODOs
(defhydra hydra-todo (:pre
(hl-todo-mode 1)
:post
(hl-todo-mode -1))
"Todo"
("n" hl-todo-next "Next")
("p" hl-todo-previous "Previous")
("o" hl-todo-occur "Occur")
("q" nil "Quit" :color blue :exit t))
)
(use-package neotree
:commands (neotree neotree-toggle)
:config
(setq neo-theme (if (display-graphic-p) 'icons 'arrow))
(setq neo-window-fixed-size t)
(setq neo-window-width 32)
(cpm-leader1
;; "T" '(:ignore t :which-key "Neotree")
"T" 'neotree-toggle)
;; (setq projectile-switch-project-action 'neotree-projectile-action)
(add-hook 'neotree-mode-hook
(lambda ()
(define-key evil-normal-state-local-map (kbd "q") 'neotree-hide)
(define-key evil-normal-state-local-map (kbd "I") 'neotree-hidden-file-toggle)
(define-key evil-normal-state-local-map (kbd "z") 'neotree-stretch-toggle)
(define-key evil-normal-state-local-map (kbd "R") 'neotree-refresh)
(define-key evil-normal-state-local-map (kbd "m") 'neotree-rename-node)
(define-key evil-normal-state-local-map (kbd "c") 'neotree-create-node)
(define-key evil-normal-state-local-map (kbd "d") 'neotree-delete-node)
(define-key evil-normal-state-local-map (kbd "s") 'neotree-enter-vertical-split)
(define-key evil-normal-state-local-map (kbd "S") 'neotree-enter-horizontal-split)
(define-key evil-normal-state-local-map (kbd "RET") 'neotree-enter)))
)
(use-package recentf
:defer 2
:init
(setq recentf-save-file (expand-file-name "recentf" user-cache-directory)))
;; :config
;; (recentf-mode 1))
(use-package saveplace
:init
(save-place-mode 1)
:config
(setq save-place-file "~/.emacs.d/.cache/saved-places")
;; (setq save-place-forget-unreadable-files nil)
)
A file tree and outliner
(use-package sr-speedbar
:commands sb-expand-current-file
:config
(progn
(setq sr-speedbar-width 60)
(setq sr-speedbar-max-width 60)
(setq sr-speedbar-right-side nil)
;; Auto expand
(defun sb-expand-current-file ()
"Expand current file in speedbar buffer"
(interactive)
(setq current-file (buffer-file-name))
(sr-speedbar-toggle)
(speedbar-find-selected-file current-file)
(speedbar-toggle-line-expansion))
;; Switch to window
(defun speedbar-edit-line-and-switch-to-window ()
(interactive)
(speedbar-edit-line)
(other-window 1))
;; other settings
(setq speedbar-hide-button-brackets-flag t
speedbar-show-unknown-files t
speedbar-directory-button-trim-method 'trim
speedbar-use-images nil
speedbar-indentation-width 2
speedbar-use-imenu-flag t
speedbar-tag-hierarchy-method nil ;; No grouping
speedbar-file-unshown-regexp "flycheck-.*"
speedbar-directory-unshown-regexp "^\\(CVS\\|RCS\\|SCCS\\|\\.\\.*$\\)\\'"
speedbar-smart-directory-expand-flag t)
;; Add markdown support
(speedbar-add-supported-extension ".md")
(speedbar-add-supported-extension ".org")
;; More familiar keymap settings.
(add-hook 'speedbar-reconfigure-keymaps-hook
'(lambda ()
(define-key speedbar-mode-map [tab] 'speedbar-toggle-line-expansion)
(define-key speedbar-mode-map [return] 'speedbar-edit-line-and-switch-to-window)))))
(use-package ag
:defer t
:config
(progn
(defun ag/jump-to-result-if-only-one-match ()
"Jump to the first ag result if that ag search came up with just one match."
(let (only-one-match)
(when (member "--stats" ag-arguments)
(save-excursion
(goto-char (point-min))
(setq only-one-match (re-search-forward "^1 matches\\s-*$" nil :noerror)))
(when only-one-match
(next-error)
(kill-buffer (current-buffer))
(message (concat "ag: Jumping to the only found match and "
"killing the *ag* buffer."))))))
(add-hook 'ag-search-finished-hook #'ag/jump-to-result-if-only-one-match)
;; Set default ag arguments
;; It looks like the ~/.agignore is used when launching ag from emacs too.
;; So the ignores from ~/.agignore don't have to be set here again.
(setq ag-highlight-search t)
;; By default, ag.el will open results in a different window in the frame, so
;; the results buffer is still visible. You can override this so the results
;; buffer is hidden and the selected result is shown in its place:
(setq ag-reuse-window nil)
;; reuse the same *ag* buffer for all your searches
(setq ag-reuse-buffers t)
;; ;; To save buffer automatically when `wgrep-finish-edit'
;; (setq wgrep-auto-save-buffer t)
(with-eval-after-load 'projectile
;; Override the default function to use the projectile function instead
(defun ag/project-root (file-path)
(let ((proj-name (projectile-project-root)))
(if proj-name
proj-name ; return `projectile-project-root' if non-nil
;; Else condition is same as the `ag/project-root' definition
;; from ag.el
(if ag-project-root-function
(funcall ag-project-root-function file-path)
(or (ag/longest-string
(vc-git-root file-path)
(vc-svn-root file-path)
(vc-hg-root file-path))
file-path))))))))
(use-package rg
:commands rg)
Sane settings for ansi-term
(use-package sane-term
:commands sane-term
:init
;; shell to use for sane-term
(setq sane-term-shell-command "/usr/bin/zsh")
;; sane-term will create first term if none exist
(setq sane-term-initial-create t)
;; `C-d' or `exit' will kill the term buffer.
(setq sane-term-kill-on-exit t)
;; After killing a term buffer, not cycle to another.
(setq sane-term-next-on-kill nil))
A popup shell
(use-package shell-pop
:commands shell-pop
:init
(setq shell-pop-term-shell "/usr/bin/zsh")
(setq shell-pop-shell-type '("eshell" "*eshell*" (lambda nil (eshell))))
:config
(defun ansi-term-handle-close ()
"Close current term buffer when `exit' from term buffer."
(when (ignore-errors (get-buffer-process (current-buffer)))
(set-process-sentinel (get-buffer-process (current-buffer))
(lambda (proc change)
(when (string-match "\\(finished\\|exited\\)" change)
(kill-buffer (when (buffer-live-p (process-buffer proc)))
(delete-window))))))
(add-hook 'shell-pop-out-hook 'kill-this-buffer)
(add-hook 'term-mode-hook (lambda () (linum-mode -1) (ansi-term-handle-close)))))
Other useful shell settings
;; basic settings
(setq explicit-shell-file-name "/usr/bin/zsh")
;; don't add newline in long lines
(setq-default term-suppress-hard-newline t)
;; kill process buffers without query
(setq kill-buffer-query-functions (delq 'process-kill-buffer-query-function kill-buffer-query-functions))
(global-set-key (kbd "C-x k") 'kill-this-buffer)
;; kill ansi-buffer on exit
(defadvice term-sentinel (around my-advice-term-sentinel (proc msg))
(if (memq (process-status proc) '(signal exit))
(let ((buffer (process-buffer proc)))
ad-do-it
(kill-buffer buffer))
ad-do-it))
(ad-activate 'term-sentinel)
;; clickable links & no highlight of line
(defun my-term-hook ()
(goto-address-mode) (global-hl-line-mode 0))
(add-hook 'term-mode-hook 'my-term-hook)
;; paste and navigation
(defun term-send-tab ()
"Send tab in term mode."
(interactive)
(term-send-raw-string "\t"))
;; Emacs doesn’t handle less well, so use cat instead for the shell pager
(setenv "PAGER" "cat")
;; hack to fix pasting issue, the paste micro-state won't work in term
(general-define-key :states '(normal) :keymaps 'term-raw-map
"p" 'term-paste
"C-k" 'term-send-up
"C-j" 'term-send-down)
(general-define-key :states '(insert) :keymaps 'term-raw-map
"C-c C-d" 'term-send-eof
"C-c C-z" 'term-stop-subjob
"<tab>" 'term-send-tab
"s-v" 'term-paste
"C-k" 'term-send-up
"C-j" 'term-send-down)
Whenever I run compile
, the buffer stays even after a successful compilation. Let’s make it close automatically if the compilation is successful.
(setq compilation-finish-functions
(lambda (buf str)
(if (null (string-match ".*exited abnormally.*" str))
;;no errors, make the compilation window go away in a few seconds
(progn
(run-at-time "0.4 sec" nil
(lambda ()
(select-window (get-buffer-window (get-buffer-create "*compilation*")))
(switch-to-buffer nil)))
(message "No Compilation Errors!")))))
Kill the completion buffer
;; Remove completion buffer when done
(add-hook 'minibuffer-exit-hook
'(lambda ()
(let ((buffer "*Completions*"))
(and (get-buffer buffer)
(kill-buffer buffer)))))
Get 256 colors instead of 8
(use-package xterm-color
:init
;; comint install
(progn (add-hook 'comint-preoutput-filter-functions 'xterm-color-filter)
(setq comint-output-filter-functions (remove 'ansi-color-process-output comint-output-filter-functions)))
;; comint uninstall
(progn (remove-hook 'comint-preoutput-filter-functions 'xterm-color-filter)
(add-to-list 'comint-output-filter-functions 'ansi-color-process-output))
;; For M-x shell, also set TERM accordingly (xterm-256color)
)
(use-package virtualenvwrapper
:defer 2
:config
(venv-initialize-interactive-shells) ;; if you want interactive shell support
(venv-initialize-eshell) ;; if you want eshell support
(setq venv-location "~/bin/virtualenvs")
(setq venv-project-home "~/Dropbox/Work/projects/")
(add-hook 'venv-postactivate-hook (lambda () (workon-venv))))
(defcustom venv-project-home
(expand-file-name (or (getenv "PROJECT_HOME") "~/projects/"))
"The location(s) of your virtualenv projects."
:group 'virtualenvwrapper)
(defun workon-venv ()
"change directory to project in eshell"
(eshell/cd (concat venv-project-home venv-current-name)))
Eshell is an elisp shell. It has its own configuration parameters, distinct from those of shell or ansi-terminal.
Basic settings
(use-package eshell
:commands eshell
;; :bind ("C-x e" . eshell)
:init
;; (use-package em-cmpl :ensure nil)
;; (use-package em-prompt :ensure nil)
;; (use-package em-term :ensure nil)
(setq
eshell-highlight-prompt nil
eshell-buffer-shorthand t
eshell-cmpl-ignore-case t
eshell-cmpl-cycle-completions nil
eshell-history-size 500
;; auto truncate after 12k lines
eshell-buffer-maximum-lines 12000
eshell-hist-ignoredups t
eshell-error-if-no-glob t
eshell-glob-case-insensitive t
eshell-scroll-to-bottom-on-input 'all
eshell-list-files-after-cd t
eshell-aliases-file (concat user-emacs-directory "eshell/alias")
eshell-banner-message ""
;; eshell-banner-message "What would you like to do?\n\n"
)
;; Visual commands
(setq eshell-visual-commands '("vi" "screen" "top" "less" "more" "lynx"
"ncftp" "pine" "tin" "trn" "elm" "vim"
"nmtui" "alsamixer" "htop" "el" "elinks"
))
(setq eshell-visual-subcommands '(("git" "log" "diff" "show")))
(defun my/truncate-eshell-buffers ()
"Truncates all eshell buffers"
(interactive)
(save-current-buffer
(dolist (buffer (buffer-list t))
(set-buffer buffer)
(when (eq major-mode 'eshell-mode)
(eshell-truncate-buffer)))))
;; After being idle for 5 seconds, truncate all the eshell-buffers if
;; needed. If this needs to be canceled, you can run `(cancel-timer
;; my/eshell-truncate-timer)'
(setq my/eshell-truncate-timer
(run-with-idle-timer 5 t #'my/truncate-eshell-buffers))
(when (not (functionp 'eshell/rgrep))
(defun eshell/rgrep (&rest args)
"Use Emacs grep facility instead of calling external grep."
(eshell-grep "rgrep" args t)))
)
(defun my/setup-eshell ()
(interactive)
;; turn off semantic-mode in eshell buffers
(semantic-mode -1)
;; turn off hl-line-mode
(hl-line-mode -1)
(define-key eshell-mode-map (kbd "M-l")
'helm-eshell-history))
(add-hook 'eshell-mode-hook
(lambda ()
(my/setup-eshell)
(eshell-cmpl-initialize)))
Make the prompt display more useful info. I got a lot of help from looking at bling’s eshell config as well as the package eshell-prompt-extras.
(defcustom dotemacs-eshell/prompt-git-info
t
"Turns on additional git information in the prompt."
:group 'dotemacs-eshell
:type 'boolean)
;; (epe-colorize-with-face "abc" 'font-lock-comment-face)
(defmacro epe-colorize-with-face (str face)
`(propertize ,str 'face ,face))
(defface epe-venv-face
'((t (:inherit font-lock-comment-face)))
"Face of python virtual environment info in prompt."
:group 'epe)
(setq eshell-prompt-function
(lambda ()
(concat (propertize (abbreviate-file-name (eshell/pwd)) 'face 'eshell-prompt)
(when (and dotemacs-eshell/prompt-git-info
(fboundp #'vc-git-branches))
(let ((branch (car (vc-git-branches))))
(when branch
(concat
(propertize " [" 'face 'font-lock-keyword-face)
(propertize branch 'face 'font-lock-function-name-face)
(let* ((status (shell-command-to-string "git status --porcelain"))
(parts (split-string status "\n" t " "))
(states (mapcar #'string-to-char parts))
(added (count-if (lambda (char) (= char ?A)) states))
(modified (count-if (lambda (char) (= char ?M)) states))
(deleted (count-if (lambda (char) (= char ?D)) states)))
(when (> (+ added modified deleted) 0)
(propertize (format " +%d ~%d -%d" added modified deleted) 'face 'font-lock-comment-face)))
(propertize "]" 'face 'font-lock-keyword-face)))))
(when (and (boundp #'venv-current-name) venv-current-name)
(concat
(epe-colorize-with-face " [" 'epe-venv-face)
(propertize venv-current-name 'face `(:foreground "#2E8B57" :slant italic))
(epe-colorize-with-face "]" 'epe-venv-face)))
(propertize " $ " 'face 'font-lock-constant-face))))
Useful for switching between multiple instances of eshell. But you can configure for any shell that you use.
(use-package shell-switcher
:defer 2
:init
(add-hook 'eshell-mode-hook 'shell-switcher-manually-register-shell)
:config
(setq shell-switcher-mode t))
Make eshell act like a standard unix terminal.
(defun eshell-clear-buffer ()
"Clear terminal"
(interactive)
(let ((inhibit-read-only t))
(erase-buffer)
(eshell-send-input)))
(add-hook 'eshell-mode-hook
'(lambda()
(local-set-key (kbd "C-l") 'eshell-clear-buffer)))
(defun eshell/magit ()
"Function to open magit-status for the current directory"
(interactive)
(magit-status default-directory)
nil)
(use-package paradox
:commands (paradox-list-packages paradox-upgrade-packages)
:config
(add-to-list 'evil-emacs-state-modes 'paradox-menu-mode)
(setq paradox-execute-asynchronously nil
;; Show all possible counts
paradox-display-download-count t
paradox-display-star-count t
;; Don't star automatically
paradox-automatically-star nil))
This package provides gl and gL align operators: gl MOTION CHAR and right-align gL MOTION CHAR
(use-package evil-lion
:defer 4
:config
(evil-lion-mode))
(use-package rainbow-delimiters
:commands rainbow-delimiters-mode
:init
(add-hook 'prog-mode-hook 'rainbow-delimiters-mode))
(use-package rainbow-identifiers
:commands rainbow-identifiers-mode
:init
(add-hook 'prog-mode-hook 'rainbow-identifiers-mode))
(use-package rainbow-mode
:commands rainbow-mode)
(use-package yasnippet
:commands (yas-expand yas-minor-mode)
:diminish (yas-minor-mode . " Ⓨ")
:init
(progn
(add-hook 'prog-mode-hook #'yas-minor-mode)
(add-hook 'org-mode-hook #'yas-minor-mode)
(add-hook 'markdown-mode-hook #'yas-minor-mode)
;; snippet directory
(setq yas-snippet-dirs (concat user-cache-directory "snippets"))
(unless (file-directory-p yas-snippet-dirs)
(make-directory yas-snippet-dirs))
;; (add-hook 'term-mode-hook (lambda()
;; (setq yas-dont-activate t)))
)
:config
(yas-reload-all))
(use-package yankpad
:defer 10
:init
(setq yankpad-file (concat user-cache-directory "yankpad.org"))
;; create file if it does not exist
(when (not (file-exists-p yankpad-file))
(shell-command (concat "touch " yankpad-file)))
:config
;; If you want to complete snippets using company-mode
;; (add-to-list 'company-backends #'company-yankpad)
)
(use-package company
:commands (company-mode)
:init
(progn
;; (add-hook 'after-init-hook 'global-company-mode)
(add-hook 'prog-mode-hook 'company-mode)
(add-hook 'org-mode-hook 'company-mode)
(add-hook 'markdown-mode-hook 'company-mode)
(setq company-idle-delay 0.3
company-minimum-prefix-length 4
company-require-match nil
company-dabbrev-ignore-case nil
company-dabbrev-downcase nil))
:config
(progn
;; latex
(add-to-list 'company-backends #'company-latex-commands)
;; key bindings
(let ((map company-active-map))
(define-key map (kbd "C-/") 'company-search-candidates)
(define-key map (kbd "C-M-/") 'company-filter-candidates)
(define-key map (kbd "C-d") 'company-show-doc-buffer)
(define-key map (kbd "C-j") 'company-select-next)
(define-key map (kbd "C-k") 'company-select-previous)
(define-key map (kbd "C-l") 'company-complete-selection))
;; Nicer looking faces
(custom-set-faces
'(company-tooltip-common
((t (:inherit company-tooltip :weight bold :underline nil))))
'(company-tooltip-common-selection
((t (:inherit company-tooltip-selection :weight bold :underline nil)))))
))
(use-package company-auctex
:after latex-mode
)
(use-package company-math
:defer t
:init
(with-eval-after-load 'company
;; Add backends for math characters
(add-to-list 'company-backends 'company-math-symbols-unicode)
(add-to-list 'company-backends 'company-math-symbols-latex))
)
(use-package electric-pair
:ensure nil
:commands electric-pair-mode
:init
(add-hook 'prog-mode-hook 'electric-pair-mode)
(add-hook 'org-mode-hook 'electric-pair-mode)
(add-hook 'markdown-mode-hook 'electric-pair-mode)
)
Smarter autopairing
(use-package smartparens
:defer t
:config
(require 'smartparens-config)
;; :init
;; (add-hook 'prog-mode-hook 'smartparens-mode)
;; (add-hook 'org-mode-hook 'smartparens-mode)
;; (add-hook 'markdown-mode-hook 'smartparens-mode)
)
(use-package evil-smartparens
:diminish ""
:defer t
;; :init
;; (add-hook 'smartparens-enabled-hook #'evil-smartparens-mode)
)
(use-package elisp-slime-nav
:ensure t
:defer t)
(use-package eldoc
:diminish eldoc-mode
:commands eldoc-mode)
(add-hook 'emacs-lisp-mode-hook (lambda ()
(setq show-trailing-whitespace t)
(prettify-symbols-mode)
(eldoc-mode)
(yas-minor-mode)
(company-mode)
(rainbow-delimiters-mode)))
(use-package haskell-mode
:commands haskell-mode)
(use-package web-mode
:commands (web-mode)
:ensure t
:init
(add-to-list 'auto-mode-alist '("\\.html?\\'" . web-mode))
:config
(setq web-mode-engines-alist
'(("django" . "\\.html\\'")))
(setq web-mode-ac-sources-alist
'(("css" . (ac-source-css-property))
("html" . (ac-source-words-in-buffer ac-source-abbrev))))
(setq web-mode-enable-auto-closing t)
(setq web-mode-enable-auto-quoting t)) ; this fixes the quote problem I mentioned
(use-package lua-mode
:commands lua-mode
:init
(dolist (pattern '("\\.lua\\'"))
(add-to-list 'auto-mode-alist (cons pattern 'lua-mode))))
(use-package php-mode
:commands php-mode
:init
(dolist (pattern '("\\.php\\'"))
(add-to-list 'auto-mode-alist (cons pattern 'php-mode))))
(use-package sh-script
:commands sh-script-mode
:init
(progn
;; Use sh-mode when opening `.zsh' files, and when opening Prezto runcoms.
(dolist (pattern '("\\.zsh\\'"
"zlogin\\'"
"zlogout\\'"
"zpreztorc\\'"
"zprofile\\'"
"zshenv\\'"
"zshrc\\'"))
(add-to-list 'auto-mode-alist (cons pattern 'sh-mode)))))
(defun spacemacs//setup-shell ()
(when (and buffer-file-name
(string-match-p "\\.zsh\\'" buffer-file-name))
(sh-set-shell "zsh")))
(add-hook 'sh-mode-hook 'spacemacs//setup-shell)
(use-package yaml-mode
:commands yaml-mode
:config
(add-to-list 'auto-mode-alist '("\\.yml$" . yaml-mode))
(add-to-list 'auto-mode-alist '("\\.yaml$" . yaml-mode))
(add-hook 'yaml-mode-hook (lambda () (run-hooks 'prog-mode-hook)))
)
(use-package vimrc-mode
:commands vimrc-mode)
Magit is a great interface for git projects. It’s much more pleasant to use than the standard git interface on the command line. I’ve set up some easy keybindings to access magit and related packages.
(use-package magit
:commands
(magit-blame-mode
magit-commit
magit-diff
magit-log
magit-status)
:init
(add-hook 'git-commit-mode-hook 'turn-on-flyspell)
:config
(setq vc-follow-symlinks t)
;; make magit go fullscreen
;; (setq magit-display-buffer-function #'magit-display-buffer-fullframe-status-v1)
(setq magit-diff-refine-hunk 'all)
(global-git-commit-mode t) ; use emacs as editor for git commits
(setq magit-push-always-verify nil)
)
Evil bindings for magit
(use-package evil-magit
:defer t
:after magit
;; (with-eval-after-load 'magit (require 'evil-magit))
)
(use-package git-timemachine ; Go back in Git time
:commands git-timemachine
)
(use-package git-gutter-fringe)
Git gutter is great for giving visual feedback on changes, but it doesn’t play well with org-mode using org-indent. So I don’t use it globally.
(use-package git-gutter
:commands (git-gutter-mode)
:diminish ""
:init
(add-hook! (markdown-mode prog-mode conf-mode) 'git-gutter-mode)
:config
(require 'git-gutter-fringe)
(def-popup! "^\\*git-gutter.\\*$" :align below :size 15 :noselect t :regexp t)
;; NOTE If you want the git gutter to be on the outside of the margins (rather
;; than inside), `fringes-outside-margins' should be non-nil.
;; colored fringe "bars"
(define-fringe-bitmap 'git-gutter-fr:added
[224 224 224 224 224 224 224 224 224 224 224 224 224 224 224 224 224 224 224 224 224 224 224 224 224]
nil nil 'center)
(define-fringe-bitmap 'git-gutter-fr:modified
[224 224 224 224 224 224 224 224 224 224 224 224 224 224 224 224 224 224 224 224 224 224 224 224 224]
nil nil 'center)
(define-fringe-bitmap 'git-gutter-fr:deleted
[0 0 0 0 0 0 0 0 0 0 0 0 0 128 192 224 240 248]
nil nil 'center)
;; Refreshing git-gutter
(advice-add 'evil-force-normal-state :after 'git-gutter)
(add-hook 'focus-in-hook 'git-gutter:update-all-windows))
(defun quick-commit ()
"make a quick commit from the mini-buffer"
(interactive)
(evil-ex '"!Git add % && Git commit -m '" ))
I use emacs primarily for writing and doing research. These are some of the packages that are most helpful for this.
This simulates programs like writeroom that provide a distraction-free mode of writing.
(use-package writeroom-mode
:commands (writeroom-mode)
:config
(setq writeroom-width 85)
)
(defun distraction-free ()
"distraction free writing"
(interactive)
(git-gutter-mode 0)
(linum-mode 0)
(centered-cursor-mode)
(writeroom-mode)
)
Org-mode is really why most people use emacs. Here are some basic settings and packages.
(use-package org
:defer t
:config
;; Allow's electric-pair-mode to surround things with = and ~ in org-mode
;; (modify-syntax-entry ?~ "(~" org-mode-syntax-table)
;; (modify-syntax-entry ?= "(=" org-mode-syntax-table)
;; don't underline indents
(defface org-dont-underline-indents '((t :underline nil))
"Avoid underlining of indentation.")
(defun org-dont-underline-indents ()
"Remove underlining at indents."
(add-to-list 'org-font-lock-extra-keywords '("^[[:space:]]+" 0 'org-dont-underline-indents t) 'append))
(add-hook 'org-font-lock-set-keywords-hook #'org-dont-underline-indents 'append)
(setq org-src-fontify-natively t ;; better looking source code
org-return-follows-link t ;; make RET follow links
org-list-allow-alphabetical t ;; allow alphabetical list
org-hide-emphasis-markers t ;; hide markers
org-pretty-entities t ;; make latex look good
org-fontify-quote-and-verse-blocks t ;; make quotes stand out
org-table-export-default-format "orgtbl-to-csv" ;; export for org-tables to csv
;; org-ellipsis "↷" ;; nicer elipses "↴" "▼"
org-confirm-babel-evaluate nil ;; evaluate src block without confirmation
org-startup-indented t ;; start in indent mode
; org-src-preserve-indentation nil
; org-edit-src-content-indentation t
org-imenu-depth 8
imenu-auto-rescan t)
:init
(add-hook 'org-mode-hook
(lambda ()
(turn-on-auto-fill)
(flyspell-mode 1)
(global-git-gutter-mode 0)
(imenu-add-to-menubar "Imenu")))
;; normal state shortcuts
(general-define-key :states '(normal) :keymaps 'org-mode-map
"RET" 'org-open-at-point ;; Open with return in evil
"gh" 'outline-up-heading
"gp" 'outline-previous-heading
"gj" (if (fboundp 'org-forward-same-level) ;to be backward compatible with older org version
'org-forward-same-level
'org-forward-heading-same-level)
"gk" (if (fboundp 'org-backward-same-level)
'org-backward-same-level 'org-backward-heading-same-level)
"gl" 'outline-next-visible-heading
"L" 'org-shiftright
"H" 'org-shiftleft
"$" 'org-end-of-line
"^" 'org-beginning-of-line
"<" 'org-metaleft
">" 'org-metaright
"-" 'org-cycle-list-bullet)
;; normal & insert state shortcuts.
(general-define-key :states '(normal insert) :keymaps 'org-mode-map
"TAB" 'org-cycle
"s-l" 'org-metaright
"s-h" 'org-metaleft
"s-k" 'org-metaup
"s-j" 'org-metadown
"s-L" 'org-shiftmetaright
"s-H" 'org-shiftmetaleft
"s-K" 'org-shiftmetaup
"s-J" 'org-shiftmetadown
"s-o" '(lambda () (interactive)
(evil-org-eol-call
'(lambda()
(org-insert-heading)
(org-metaright))))
"s-t" '(lambda () (interactive)
(evil-org-eol-call
'(lambda()
(org-insert-todo-heading nil)
(org-metaright)))))
;; Use tab in insert mode
(general-define-key :states '(insert) :keymaps 'org-mode-map "\t" nil))
(use-package ox-pandoc
:defer 1
:config
;; default options for all output formats
;; (setq org-pandoc-command (expand-file-name "~/.local/bin/pandoc"))
(setq org-pandoc-options '((standalone . t)))
;; cancel above settings only for 'docx' format
(setq org-pandoc-options-for-docx '((standalone . nil)))
;; special settings for beamer-pdf and latex-pdf exporters
(setq org-pandoc-options-for-beamer-pdf '((latex-engine . "xelatex")))
(setq org-pandoc-options-for-latex-pdf '((latex-engine . "xelatex"))))
Other useful org packages
(use-package htmlize :after org :ensure t)
(use-package org-inlinetask :ensure nil :commands org-inlinetask-insert-task)
(use-package toc-org
:init
(progn
(setq toc-org-max-depth 10)
(add-hook 'org-mode-hook 'toc-org-enable)))
;; ignore export of headlines marked with :ignore: tag
(use-package ox-extra
:ensure nil
:after org
:config
(ox-extras-activate '(ignore-headlines)))
(use-package ox-reveal
:ensure t
:commands (org-reveal-export-current-subtree org-reveal-export-to-html-and-browse)
:config
(setq org-reveal-root (concat "file://" (getenv "HOME") "/bin/reveal.js")
org-reveal-theme "moon"
org-reveal-default-frag-style "roll-in"
org-reveal-hlevel 2
))
(setq org-capture-templates
'(
("j" "Journal entry" plain
(file+datetree "~/Dropbox/journal.org")
"**** %<%H:%M>\n%?")
;; other entries
))
(defun cpm/org-journal ()
(interactive) (org-capture nil "j"))
(use-package org-journal
:ensure t
:disabled t
:defer t
:init
(setq org-journal-dir "~/Dropbox/journal/")
(setq org-journal-date-format "%Y-%b-%d (%A)"))
I got all of these from Howard Abrams’ great config file.
(defun get-journal-file-today ()
"Return filename for today's journal entry."
(let ((daily-name (format-time-string "%Y%m%d")))
(expand-file-name (concat org-journal-dir daily-name))))
(defun journal-file-today ()
"Create and load a journal file based on today's date."
(interactive)
(find-file (get-journal-file-today)))
(defun get-journal-file-yesterday ()
"Return filename for yesterday's journal entry."
(let ((daily-name (format-time-string "%Y%m%d" (time-subtract (current-time) (days-to-time 1)))))
(expand-file-name (concat org-journal-dir daily-name))))
(defun journal-file-yesterday ()
"Creates and load a file based on yesterday's date."
(interactive)
(find-file (get-journal-file-yesterday)))
(defun journal-last-year-file ()
"Returns the string corresponding to the journal entry that
happened 'last year' at this same time (meaning on the same day
of the week)."
(let* ((last-year-seconds (- (float-time) (* 365 24 60 60)))
(last-year (seconds-to-time last-year-seconds))
(last-year-dow (nth 6 (decode-time last-year)))
(this-year-dow (nth 6 (decode-time)))
(difference (if (> this-year-dow last-year-dow)
(- this-year-dow last-year-dow)
(- last-year-dow this-year-dow)))
(target-date-seconds (+ last-year-seconds (* difference 24 60 60)))
(target-date (seconds-to-time target-date-seconds)))
(format-time-string "%Y%m%d" target-date)))
(defun journal-last-year ()
"Loads last year's journal entry, which is not necessary the
same day of the month, but will be the same day of the week."
(interactive)
(let ((journal-file (concat org-journal-dir (journal-last-year-file))))
(find-file journal-file)))
;;; Org-publish settings
(setq org-publish-project-alist
'(
("testing"
:base-directory "~/test/source"
:base-extension "org"
:publishing-directory "~/test/output"
:publishing-function (org-pandoc-publish-to-markdown)
:org-pandoc-table-of-contents t
:org-pandoc-bibliography "/Users/Roambot/Dropbox/Work/Master.bib"
:org-pandoc-toc-depth 2)
("notebook"
;; Path to org files
:base-directory "~/projects/notebook/content/org_notes"
:base-extension "org"
;; Path to pelican project
:publishing-directory "~/projects/notebook/content/notes"
;; settings
:author "Colin McLear"
:email "mclear@unl.edu"
:recursive t
:auto-preamble nil ;; Don't add any kind of html before the content
:export-with-tags nil
:with-timestamps nil
:time-stamp-file nil
:with-creator nil
:auto-postamble nil ;; Don't add any kind of html after the content
:html-postamble nil ;; same thing
;; :publishing-function (org-html-publish-to-html)
;; :publishing-function (org-md-publish-to-md)
:publishing-function (org-org-publish-to-org)
:org-pandoc-bibliography "/Users/Roambot/Dropbox/Work/Master.bib"
;; :publishing-function (org-pandoc-publish-to-html)
)
("big-notes"
;; Path to org files
:base-directory "~/Dropbox/Notes/"
:base-extension "org"
;; Path to pelican project
:publishing-directory "~/projects/notebook/content/notes"
;; settings
:author "Colin McLear"
:email "mclear@unl.edu"
:recursive t
:auto-preamble nil ;; Don't add any kind of html before the content
:export-with-tags nil
:with-timestamps nil
:time-stamp-file nil
:with-creator nil
:auto-postamble nil ;; Don't add any kind of html after the content
:html-postamble nil ;; same thing
;; :publishing-function (org-html-publish-to-html)
;; :publishing-function (org-md-publish-to-md)
:publishing-function (org-org-publish-to-org)
;; :publishing-function (org-pandoc-publish-to-html)
)
("test"
:base-directory "~/test/source"
:base-extension "org"
:publishing-directory "~/test/output"
;; settings
:author "Colin McLear"
:email "mclear@unl.edu"
:publishing-function (org-org-publish-to-org)
)
))
;; (defun org-pandoc-publish-to-html (plist filename pub-dir)
;; "Publish an org file to html using ox-pandoc. Return output file name."
;; (org-publish-org-to 'org-pandoc-export-to-html filename ".html" plist pub-dir))
;; Pandoc publishing functions
(defun org-pandoc-publish-to (format plist filename pub-dir)
(setq org-pandoc-format format)
(let ((tempfile
(org-publish-org-to
'pandoc filename (concat (make-temp-name ".tmp") ".org") plist pub-dir))
(outfile (format "%s.%s"
(concat
pub-dir
(file-name-sans-extension (file-name-nondirectory filename)))
(assoc-default format org-pandoc-extensions))))
(org-pandoc-put-options (org-pandoc-plist-to-alist plist))
(let ((process
(org-pandoc-run tempfile outfile format 'org-pandoc-sentinel
org-pandoc-option-table))
(local-hook-symbol
(intern (format "org-pandoc-after-processing-%s-hook" format))))
(process-put process 'files (list tempfile))
(process-put process 'output-file filename)
(process-put process 'local-hook-symbol local-hook-symbol))))
;; helper functions
(defun org-pandoc-publish-to-html5 (p f pd)
(org-pandoc-publish-to 'html5 p f pd))
(defun org-pandoc-publish-to-org (p f pd)
(org-pandoc-publish-to 'org p f pd))
(defun org-pandoc-publish-to-markdown (p f pd)
(org-pandoc-publish-to 'markdown p f pd))
(defun org-pandoc-pan-to-pub (o)
(intern (format ":org-pandoc-%s" o)))
(defun org-pandoc-pub-to-pan (o)
(intern (substring (symbol-name o) 12)))
;; (defconst org-pandoc-publish-options
;; (mapcar 'org-pandoc-pan-to-pub
;; (append org-pandoc-valid-options org-pandoc-colon-separated-options
;; org-pandoc-file-options)))
(defun org-pandoc-plist-to-alist (plist)
(let ((alist '()))
(while plist
(let ((p (car plist)) (v (cadr plist)))
(when (member p org-pandoc-publish-options)
(add-to-list 'alist (cons (org-pandoc-pub-to-pan p) v))))
(setq plist (cddr plist)))
alist))
Helps with time tracking
(use-package org-pomodoro
:commands org-pomodoro
:ensure t
:init
(progn
(setq org-pomodoro-audio-player "/usr/bin/afplay")))
Open exported docx files in Word/Open Office rather than emacs
(setq org-file-apps
'(("\\.docx\\'" . default)
("\\.mm\\'" . default)
("\\.x?html?\\'" . default)
("\\.pdf\\'" . default)
(auto-mode . emacs)))
Appearance settings for Org-mode
(use-package org-bullets
:defer t
:ensure t
:init (add-hook 'org-mode-hook 'org-bullets-mode)
:config
(setq org-bullets-bullet-list '("❂" "⁑" "⁂" "⁘" "⁙" "✶" "✵" "⁜" "✫" "⌾" "⁕" "✪" "⊢" "╏" "╞" "┇" "╠" "┋" "⁖" "⋮" "⋱" "⋯" ))
)
Make source blocks look better.
(with-eval-after-load 'org
(defvar-local rasmus/org-at-src-begin -1
"Variable that holds whether last position was a ")
(defvar rasmus/ob-header-symbol ?☰
"Symbol used for babel headers")
(defun rasmus/org-prettify-src--update ()
(let ((case-fold-search t)
(re "^[ \t]*#\\+begin_src[ \t]+[^ \f\t\n\r\v]+[ \t]*")
found)
(save-excursion
(goto-char (point-min))
(while (re-search-forward re nil t)
(goto-char (match-end 0))
(let ((args (org-trim
(buffer-substring-no-properties (point)
(line-end-position)))))
(when (org-string-nw-p args)
(let ((new-cell (cons args rasmus/ob-header-symbol)))
(cl-pushnew new-cell prettify-symbols-alist :test #'equal)
(cl-pushnew new-cell found :test #'equal)))))
(setq prettify-symbols-alist
(cl-set-difference prettify-symbols-alist
(cl-set-difference
(cl-remove-if-not
(lambda (elm)
(eq (cdr elm) rasmus/ob-header-symbol))
prettify-symbols-alist)
found :test #'equal)))
;; Clean up old font-lock-keywords.
(font-lock-remove-keywords nil prettify-symbols--keywords)
(setq prettify-symbols--keywords (prettify-symbols--make-keywords))
(font-lock-add-keywords nil prettify-symbols--keywords)
(while (re-search-forward re nil t)
(font-lock-flush (line-beginning-position) (line-end-position))))))
(defun rasmus/org-prettify-src ()
"Hide src options via `prettify-symbols-mode'.
`prettify-symbols-mode' is used because it has uncollpasing. It's
may not be efficient."
(let* ((case-fold-search t)
(at-src-block (save-excursion
(beginning-of-line)
(looking-at "^[ \t]*#\\+begin_src[ \t]+[^ \f\t\n\r\v]+[ \t]*"))))
;; Test if we moved out of a block.
(when (or (and rasmus/org-at-src-begin
(not at-src-block))
;; File was just opened.
(eq rasmus/org-at-src-begin -1))
(rasmus/org-prettify-src--update))
;; Remove composition if at line; doesn't work properly.
;; (when at-src-block
;; (with-silent-modifications
;; (remove-text-properties (match-end 0)
;; (1+ (line-end-position))
;; '(composition))))
(setq rasmus/org-at-src-begin at-src-block)))
(defun rasmus/org-prettify-symbols ()
(mapc (apply-partially 'add-to-list 'prettify-symbols-alist)
(cl-reduce 'append
(mapcar (lambda (x) (list x (cons (upcase (car x)) (cdr x))))
`(("#+begin_src" . ?╦) ;; ➤ 🖝 ➟ ➤ ✎ ✎
("#+end_src" . ?╩) ;; □
("#+header:" . ,rasmus/ob-header-symbol)
("#+begin_comment" . ?✎)
("#+end_comment" . ?✎)
("#+begin_notes" . ?➤)
("#+end_notes" . ?➤)
("#+begin_quote" . ?»)
("#+end_quote" . ?«)))))
(turn-on-prettify-symbols-mode)
(add-hook 'post-command-hook 'rasmus/org-prettify-src t t))
(add-hook 'org-mode-hook #'rasmus/org-prettify-symbols))
Searching Org-mode with search tools.
(use-package org-seek
:ensure t
:commands (org-seek-string org-seek-regexp org-seek-headlines)
)
(use-package org-wiki
:ensure nil
:commands (org-wiki-open org-wiki-helm org-wiki-dired org-wiki-index)
:init
(setq org-wiki-location "~/Dropbox/Work/wiki")
)
(defun org-wiki-export-html-sync ()
"Export all pages to html in synchronous mode."
(interactive)
(let ((org-html-htmlize-output-type 'css)
(org-html-htmlize-font-prefix "org-")
)
(org-publish
`("html"
:base-directory ,org-wiki-location
:base-extension "org"
:publishing-directory "~/Dropbox/Work/wiki/html"
;; :publishing-function org-html-publish-to-html
:publishing-function (org-pandoc-publish-to-html5)
:org-pandoc-table-of-contents t
:org-pandoc-bibliography "/Users/Roambot/Dropbox/Work/Master.bib"
)
t
)))
(defun org-wiki-header ()
"Insert a header at the top of the file."
(interactive)
(save-excursion
(goto-char (point-min))
(insert (format
(string-trim "
#+TITLE: %s
#+DESCRIPTION:
#+KEYWORDS:
#+SETUPFILE: ~/.emacs.d/elisp/org-html-themes/setup/theme-bigblow.setup
#+STARTUP: overview
Related:
[[wiki:index][Index]]")
(file-name-base (buffer-file-name))
))))
;; (defun org-wiki-export-html-sync ()
;; "Export all pages to html in synchronous mode."
;; (interactive)
;; (let ((org-html-htmlize-font-prefix "org-")
;; )
;; (defun org-wiki-export-html-sync ()
;; "Export all pages to html in synchronous mode."
;; (interactive)
;; (let ((org-html-htmlize-output-type 'css)
;; (org-html-htmlize-font-prefix "org-")
;; )
;; (org-publish
;; `("html"
;; :base-directory ,org-wiki-location
;; :base-extension "org"
;; :publishing-directory "~/Dropbox/work/wiki/html"
;; :publishing-function org-twbs-publish-to-html
;; ;; settings
;; :author "Colin McLear"
;; :email "mclear@unl.edu"
;; :toc nil
;; :with-timestamps nil
;; :time-stamp-file nil
;; :timestamp nil
;; ;; :org-pandoc-bibliography "~/Dropbox/Work/Master.bib"
;; ;; :org-pandoc-csl "~/.pandoc/styles/chicago-author-date.csl"
;; )
;; t
;; )))
;; (defun org-wiki-export-html ()
;; "Export all pages to html.
;; Note: This function doesn't freeze Emacs since it starts another Emacs process."
;; (interactive)
;; (compile (mapconcat 'identity
;; `(,org-wiki-emacs-path
;; "--batch"
;; "-l" ,user-init-file
;; "-f" "org-wiki-export-html-sync"
;; "--kill"
;; )
;; " "
;; )))
A knowledge base using org-mode
(use-package org-brain
:ensure nil
:load-path "~/.emacs.d/elisp/org-brain"
:config
(setq org-brain-path "~/projects/notebook/content/org_notes")
)
Publish using twitter bootstrap css
(use-package ox-twbs
:commands org-twbs-export-to-html)
(add-to-list 'org-structure-template-alist
'("E" "#+BEGIN_SRC emacs-lisp\n?\n#+END_SRC"))
(add-to-list 'org-structure-template-alist
'("n" "#+BEGIN_NOTES\n?\n#+END_NOTES"))
(add-to-list 'org-structure-template-alist
'("t" "#+BEGIN_COMMENT TODO: ? #+END_COMMENT"))
(add-to-list 'org-structure-template-alist
'("b" "#+REVEAL: split?"))
(add-to-list 'org-structure-template-alist
'("f" "#+ATTR_REVEAL: :frag (appear)?"))
Some advice to automatically switch to a new indirect buffer upon creation
(defadvice org-tree-to-indirect-buffer (after org-tree-to-indirect-buffer-after activate) (other-window 1))
Some useful org-specific functions
Functions to calculate apt offsets and call regular org fill stuff. There’s a useful stack overflow thread on this.
(defun calc-offset-on-org-level ()
"Calculate offset (in chars) on current level in org mode file."
(* (or (org-current-level) 0) org-indent-indentation-per-level))
(defun my-org-fill-paragraph (&optional JUSTIFY)
"Calculate apt fill-column value and fill paragraph."
(let* ((fill-column (- fill-column (calc-offset-on-org-level))))
(org-fill-paragraph JUSTIFY)))
(defun my-org-auto-fill-function ()
"Calculate apt fill-column value and do auto-fill"
(let* ((fill-column (- fill-column (calc-offset-on-org-level))))
(org-auto-fill-function)))
(defun my-org-mode-hook ()
(setq fill-paragraph-function 'my-org-fill-paragraph
normal-auto-fill-function 'my-org-auto-fill-function))
(add-hook 'org-load-hook 'my-org-mode-hook)
(add-hook 'org-mode-hook 'my-org-mode-hook)
Functions to advance forwards or backwards through narrowed tree
(defun org-advance ()
(interactive)
(when (buffer-narrowed-p)
(beginning-of-buffer)
(widen)
(org-forward-heading-same-level 1))
(org-narrow-to-subtree))
(defun org-retreat ()
(interactive)
(when (buffer-narrowed-p)
(beginning-of-buffer)
(widen)
(org-backward-heading-same-level 1))
(org-narrow-to-subtree))
Great for managing citations and notes
(use-package helm-bibtex
:ensure t
:commands helm-bibtex
:config
(setq bibtex-completion-bibliography "/Users/roambot/Dropbox/Work/Master.bib"
bibtex-completion-library-path "/Users/roambot/Dropbox/Work/MasterLib/"
bibtex-completion-pdf-field nil
bibtex-completion-notes-path "/Users/Roambot/projects/notebook/content/org_notes"
bibtex-completion-additional-search-fields '(keywords)
bibtex-completion-notes-extension ".org"
helm-bibtex-full-frame nil)
;; Set insert citekey with markdown citekeys for org-mode
(setq bibtex-completion-format-citation-functions
'((org-mode . bibtex-completion-format-citation-pandoc-citeproc)
(latex-mode . bibtex-completion-format-citation-cite)
(markdown-mode . bibtex-completion-format-citation-pandoc-citeproc)
(default . bibtex-completion-format-citation-default)))
(setq bibtex-completion-display-formats
'((t . "${author:36} ${title:*} ${year:4} ${=has-pdf=:1}${=has-note=:1} ${=type=:7}")))
;; Set default action for helm-bibtex as inserting citation
(helm-delete-action-from-source "Insert citation" helm-source-bibtex)
(helm-add-action-to-source "Insert citation" 'helm-bibtex-insert-citation helm-source-bibtex 0)
(setq bibtex-completion-pdf-symbol "⌘")
(setq bibtex-completion-notes-symbol "✎")
)
;; Set global shortcut for calling helm-bibtex
(general-define-key "H-b" 'helm-bibtex)
(use-package markdown-mode
:defer t
:mode (("\\.markdown\\'" . markdown-mode)
("\\.md\\'" . markdown-mode))
:init
;; markdown hooks
(add-hook 'markdown-mode-hook
'(lambda ()
(turn-on-auto-fill) (linum-mode) (centered-cursor-mode) (set-fill-column 78) (flyspell-mode 1) (pandoc-mode) (hl-todo-mode) (git-gutter-mode t)))
(setq markdown-command "pandoc"
markdown-enable-math t
markdown-nested-imenu-heading-index t
markdown-open-command "/Users/Roambot/bin/scripts/mark.sh"
)
;; add keybindings to hook
:config
;; remove strikout comment face
(set-face-attribute 'markdown-comment-face nil
:weight 'bold :strike-through nil)
;; Header navigation in normal state movements
(general-define-key :states '(normal) :keymaps 'markdown-mode-map
"TAB" 'markdown-cycle
"gj" 'outline-forward-same-level
"gk" 'outline-backward-same-level
"gh" 'outline-up-heading
;; next visible heading is not exactly what we want but close enough
"gl" 'outline-next-visible-heading)
;; "<return>" 'markdown-jump
;; Promotion, Demotion
(general-define-key :states '(normal insert emacs) :keymaps 'markdown-mode-map
"M-h" 'markdown-promote
"M-j" 'markdown-move-down
"M-k" 'markdown-move-up
"M-l" 'markdown-demote
;; fix wrong emacs keybindings
"C-c C-j" 'markdown-jump
"C-c C-l" 'markdown-insert-list-item
)
(add-hook 'markdown-mode-hook #'my-markdown-config)
)
Pandoc mode for markdown conversion
(use-package pandoc-mode
:defer t
:config
(progn
(defun run-pandoc ()
"Start pandoc for the buffer and open the menu"
(interactive)
(pandoc-mode)
(pandoc-main-hydra/body))
(add-hook 'pandoc-mode-hook 'pandoc-load-default-settings)
(defun pandoc-pdf-open ()
"Open created PDF file"
(interactive)
(find-file (concat (file-name-sans-extension buffer-file-name) ".pdf")))
)
:init
(progn
(setq pandoc-data-dir "~/.emacs.d/pandoc-mode/")
;; help pandoc find xelatex
(setenv "PATH" (concat (getenv "PATH") ":/Library/TeX/texbin"))))
(use-package cm-mode
:defer t
:ensure t
:disabled t ;; causes font-lock error in markdown mode
:init
(add-hook 'markdown-mode-hook 'cm-mode))
(use-package deft
:commands (deft deft-find-file cpm/deft)
:init
(progn
;; start in insert mode
(add-to-list 'evil-insert-state-modes 'deft-mode)
(setq deft-extensions '("org" "md" "txt")
deft-directory "~/projects/notebook/content/org_notes"
deft-text-mode 'org-mode
deft-use-filter-string-for-filename t ;; use filter string as filename
deft-org-mode-title-prefix t ;; add #+TITLE prefix
deft-recursive t ;; search recursively in folders
deft-use-filename-as-title t)
:config
(progn
(general-define-key :states '(insert) :keymaps 'deft-mode-map
"C-j" 'next-line
"C-k" 'previous-line)
(general-define-key :states '(normal) :keymaps 'deft-mode-map
"d" 'deft-delete-file
"I" 'deft-toggle-incremental-search
"n" 'deft-new-file
"r" 'deft-rename-file))))
;; Make sure titles have no spaces: from [[http://pragmaticemacs.com/category/deft/][pragmaticemacs]]
;;advise deft-new-file-named to replace spaces in file names with -
(defun bjm-deft-strip-spaces (args)
"Replace spaces with - in the string contained in the first element of the list args. Used to advise deft's file naming function."
(list (replace-regexp-in-string " " "-" (car args)))
)
(advice-add 'deft-new-file-named :filter-args #'bjm-deft-strip-spaces)
;;function to run deft in specified directory
(defun any-deft (dir)
"Run deft in directory DIR"
(setq deft-directory dir)
(switch-to-buffer "*Deft*")
(kill-this-buffer)
(require 'org)
(deft)
)
(defun big-notes ()
"Goto main notes with deft"
(interactive)
(any-deft "~/Dropbox/Notes")
(kill-this-buffer)
(any-deft "~/Dropbox/Notes")
)
(defun research-notes ()
"Goto research notes"
(interactive)
(any-deft "~/projects/notebook/content/org_notes"))
Useful when taking notes
(use-package interleave
:commands interleave)
Make arbitrary blocks or sentences of text.
(use-package lorem-ipsum
:ensure t
:defer t
:config
(lorem-ipsum-use-default-bindings)
)
(use-package palimpsest
:defer t
:diminish palimpsest-mode
:init
(add-hook 'markdown-mode-hook 'palimpsest-mode)
(add-hook 'org-mode-hook 'palimpsest-mode))
;; Basic settings
(use-package auctex
:ensure t
:defer t
:mode ("\\.tex\\'" . latex-mode)
:commands (latex-mode LaTeX-mode plain-tex-mode)
:init
(progn
(add-hook 'LaTeX-mode-hook #'LaTeX-preview-setup)
(add-hook 'LaTeX-mode-hook #'flyspell-mode)
(add-hook 'LaTeX-mode-hook #'turn-on-reftex)
(setq-default TeX-engine 'xetex)
(setq TeX-auto-save t
TeX-parse-self t
TeX-save-query nil
TeX-PDF-mode t)
(setq-default TeX-master nil)))
(use-package preview
:ensure nil
:after auctex
:commands LaTeX-preview-setup
:init
(progn
(setq-default preview-scale 1.4
preview-scale-function '(lambda () (* (/ 10.0 (preview-document-pt)) preview-scale)))))
(use-package reftex
:commands turn-on-reftex
:init
(progn
(setq reftex-plug-into-AUCTeX t)))
(use-package bibtex
:defer t
:mode ("\\.bib" . bibtex-mode)
:init
(progn
(setq bibtex-align-at-equal-sign t)
(add-hook 'bibtex-mode-hook (lambda () (set-fill-column 120)))))
;; Auto-fill for LaTeX
(defun schnouki/latex-auto-fill ()
"Turn on auto-fill for LaTeX mode."
(turn-on-auto-fill)
(set-fill-column 80)
(setq default-justification 'left))
(add-hook 'LaTeX-mode-hook #'schnouki/latex-auto-fill)
;; Compilation command
(add-hook 'LaTeX-mode-hook (lambda () (setq compile-command "latexmk -pdflatex=xelatex -f -pdf %f")))
;; Prevent ispell from verifying some LaTeX commands
;; http://stat.genopole.cnrs.fr/dw/~jchiquet/fr/latex/emacslatex
(defvar schnouki/ispell-tex-skip-alists
'("cite" "nocite"
"includegraphics"
"author" "affil"
"ref" "eqref" "pageref"
"label"))
(setq ispell-tex-skip-alists
(list
(append (car ispell-tex-skip-alists)
(mapcar #'(lambda (cmd) (list (concat "\\\\" cmd) 'ispell-tex-arg-end)) schnouki/ispell-tex-skip-alists))
(cadr ispell-tex-skip-alists)))
;; Indentation with align-current in LaTeX environments
(defvar schnouki/LaTeX-align-environments '("tabular" "tabular*"))
(add-hook 'LaTeX-mode-hook
(lambda ()
(require 'align)
(setq LaTeX-indent-environment-list
;; For each item in the list...
(mapcar (lambda (item)
;; The car is an environment
(let ((env (car item)))
;; If this environment is in our list...
(if (member env schnouki/LaTeX-align-environments)
;; ...then replace this item with a correct one
(list env 'align-current)
;; else leave it alone
item)))
LaTeX-indent-environment-list))))
;; Use dvipdfmx to convert DVI files to PDF in AUCTeX
(eval-after-load 'tex
'(add-to-list 'TeX-command-list
'("DVI to PDF" "dvipdfmx %d" TeX-run-command t t) t))
;; SyncTeX (http://www.emacswiki.org/emacs/AUCTeX#toc19)
(defun synctex/un-urlify (fname-or-url)
"A trivial function that replaces a prefix of file:/// with just /."
(if (string= (substring fname-or-url 0 8) "file:///")
(substring fname-or-url 7)
fname-or-url))
(use-package doc-view
:defer t
:init
(fset 'doc-prev "\C-xo\C-x[\C-xo")
(fset 'doc-next "\C-xo\C-x]\C-xo")
(global-set-key (kbd "M-[") 'doc-prev)
(global-set-key (kbd "M-]") 'doc-next)
(evil-set-initial-state 'doc-view-mode 'normal)
(evil-define-key 'normal doc-view-mode-map
"/" 'spacemacs/doc-view-search-new-query
"?" 'spacemacs/doc-view-search-new-query-backward
"gg" 'doc-view-first-page
"G" 'doc-view-last-page
"gt" 'doc-view-goto-page
"h" 'doc-view-previous-page
"j" 'doc-view-next-line-or-next-page
"k" 'doc-view-previous-line-or-previous-page
"K" 'doc-view-kill-proc-and-buffer
"l" 'doc-view-next-page
"n" 'doc-view-search
"N" 'doc-view-search-backward
(kbd "C-d") 'doc-view-scroll-up-or-next-page
(kbd "C-k") 'doc-view-kill-proc
(kbd "C-u") 'doc-view-scroll-down-or-previous-page)
:config
(progn
(defun spacemacs/doc-view-search-new-query ()
"Initiate a new query."
(interactive)
(doc-view-search 'newquery))
(defun spacemacs/doc-view-search-new-query-backward ()
"Initiate a new query."
(interactive)
(doc-view-search 'newquery t))
(defcustom doc-view-autofit-timer-start 1.0
"Initial value (seconds) for the timer that delays the fitting when
`doc-view-autofit-fit' is called (Which is when a window
configuration change occurs and a document needs to be fitted)."
:type 'number
:group 'doc-view)
(defcustom doc-view-autofit-timer-inc 0.02
"Value to increase (seconds) the timer (see `doc-view-autofit-timer-start')
by, if there is another window configuration change occuring, before
it runs out."
:type 'number
:group 'doc-view)
(defcustom doc-view-autofit-default-fit 'width
"The fitting type initially used when mode is enabled.
Valid values are: width, height, page."
:type 'symbol
:group 'doc-view)
(defvar doc-view-autofit-mode-map
(let ((map (make-sparse-keymap)))
(define-key map (kbd "C-c W") 'doc-view-autofit-width)
(define-key map (kbd "C-c H") 'doc-view-autofit-height)
(define-key map (kbd "C-c P") 'doc-view-autofit-page)
map)
"Keymap used by `doc-view-autofit-mode'.")
(defun doc-view-autofit-set (type)
"Set autofitting to TYPE for current buffer."
(when doc-view-autofit-mode
(setq doc-view-autofit-type type)
(doc-view-autofit-fit)))
(defun doc-view-autofit-width ()
"Set autofitting to width for current buffer."
(interactive) (doc-view-autofit-set 'width))
(defun doc-view-autofit-height ()
"Set autofitting to height for current buffer."
(interactive) (doc-view-autofit-set 'height))
(defun doc-view-autofit-page ()
"Set autofitting to page for current buffer."
(interactive) (doc-view-autofit-set 'page))
(defun doc-view-autofit-fit ()
"Fits the document in the selected window's buffer
delayed with a timer, so multiple calls in succession
don't cause as much overhead."
(lexical-let
((window (selected-window)))
(if (equal doc-view-autofit-timer nil)
(setq doc-view-autofit-timer
(run-with-timer
doc-view-autofit-timer-start nil
(lambda ()
(if (window-live-p window)
(save-selected-window
(select-window window)
(cancel-timer doc-view-autofit-timer)
(setq doc-view-autofit-timer nil)
(cond
((equal 'width doc-view-autofit-type)
(doc-view-fit-width-to-window))
((equal 'height doc-view-autofit-type)
(doc-view-fit-height-to-window))
((equal 'page doc-view-autofit-type)
(doc-view-fit-page-to-window))))))))
(timer-inc-time doc-view-autofit-timer doc-view-autofit-timer-inc))))
(define-minor-mode doc-view-autofit-mode
"Minor mode for automatic (timer based) fitting in DocView."
:lighter " AFit" :keymap doc-view-autofit-mode-map :group 'doc-view
(when doc-view-autofit-mode
(set (make-local-variable 'doc-view-autofit-type)
doc-view-autofit-default-fit)
(set (make-local-variable 'doc-view-autofit-timer) nil)
(add-hook 'window-configuration-change-hook
'doc-view-autofit-fit nil t)
(doc-view-autofit-fit))
(when (not doc-view-autofit-mode)
(remove-hook 'window-configuration-change-hook
'doc-view-autofit-fit t)
(when doc-view-autofit-timer
(cancel-timer doc-view-autofit-timer)
(setq doc-view-autofit-timer nil))
(setq doc-view-autofit-type nil)))
(add-hook 'doc-view-mode-hook 'doc-view-autofit-mode)
;; reload when file changes
(add-hook 'doc-view-mode-hook 'auto-revert-mode)
;; continuous scroll mode
(setq doc-view-continuous t)
))
Better than doc-view, but doesn’t render well on retina screens :(
(use-package pdf-tools
:ensure t
:defer t
:mode (("\\.pdf$" . pdf-view-mode))
:config
(progn
(pdf-tools-install)
(evil-set-initial-state 'pdf-view-mode 'normal)
(evil-set-initial-state 'pdf-outline-buffer-mode 'normal)
(evil-define-key 'normal pdf-view-mode-map
;; Navigation
"j" 'pdf-view-next-line-or-next-page
"k" 'pdf-view-previous-line-or-previous-page
"l" 'pdf-view-next-page
"h" 'pdf-view-previous-page
"J" 'image-forward-hscroll
"K" 'image-backward-hscroll
"gg" 'pdf-view-first-page
"G" 'pdf-view-last-page
"gt" 'pdf-view-goto-page
"gl" 'pdf-view-goto-label
"u" 'pdf-view-scroll-down-or-previous-page
"d" 'pdf-view-scroll-up-or-next-page
"-" 'pdf-view-shrink
"+" 'pdf-view-enlarge
"=" 'pdf-view-fit-page-to-window
(kbd "C-u") 'pdf-view-scroll-down-or-previous-page
(kbd "C-d") 'pdf-view-scroll-up-or-next-page
(kbd "``") 'pdf-history-backward
;; Search
"/" 'isearch-forward
"?" 'isearch-backward
;; Actions
"r" 'pdf-view-revert-buffer
"o" 'pdf-links-action-perform
"O" 'pdf-outline
)
(evil-define-key 'insert pdf-view-mode-map
"y" 'pdf-view-kill-ring-save )
))
;; for annotation and jumping to file
;; (add-to-list 'org-file-apps '("\\.pdf\\'" . org-pdfview-open))
;; (add-to-list 'org-file-apps '("\\.pdf::\\([[:digit:]]+\\)\\'" . org-pdfview-open)))
;; (eval-after-load 'org '(require 'org-pdfview))
;; (use-package org-pdfview
;; ;; :commands (org-pdfview-open)
;; :after org
;; :ensure t
;; :config
;; (add-to-list 'org-file-apps
;; '("\\.pdf\\'" . (lambda (file link)
;; (org-pdfview-open link)))))
(use-package pdf-tools-org
:ensure nil
:commands (pdf-tools-org-export-to-org pdf-tools-org-import-from-org)
:init
(add-to-list 'load-path "/Users/Roambot/.emacs.d/pdf-tools-org/"))
;; Extracting annotations using pdf-tools
;; modified from https://github.com/politza/pdf-tools/pull/133
;; taken from http://matt.hackinghistory.ca/2015/11/11/note-taking-with-pdf-tools/
(defun mwp/pdf-multi-extract (sources)
"Helper function to print highlighted text from a list of pdf's, with one org header per pdf,
and links back to page of highlight."
(let (
(output ""))
(dolist (thispdf sources)
(setq output (concat output (pdf-annot-markups-as-org-text thispdf nil level ))))
(princ output))
)
(defun cpm/pdf-summary-extract (sources)
"Helper function to print underlined text from a list of pdf's, with one org header per pdf,
and links back to page of highlight."
(let (
(output ""))
(dolist (thispdf sources)
(setq output (concat output (pdf-annot-summary-as-org-text thispdf nil level ))))
(princ output))
)
;; this is stolen from https://github.com/pinguim06/pdf-tools/commit/22629c746878f4e554d4e530306f3433d594a654
(defun pdf-annot-edges-to-region (edges)
"Attempt to get 4-entry region \(LEFT TOP RIGHT BOTTOM\) from several edges.
We need this to import annotations and to get marked-up text, because annotations
are referenced by its edges, but functions for these tasks need region."
(let ((left0 (nth 0 (car edges)))
(top0 (nth 1 (car edges)))
(bottom0 (nth 3 (car edges)))
(top1 (nth 1 (car (last edges))))
(right1 (nth 2 (car (last edges))))
(bottom1 (nth 3 (car (last edges))))
(n (safe-length edges)))
;; we try to guess the line height to move
;; the region away from the boundary and
;; avoid double lines
(list left0
(+ top0 (/ (- bottom0 top0) 2))
right1
(- bottom1 (/ (- bottom1 top1) 2 )))))
(defun pdf-annot-markups-as-org-text (pdfpath &optional title level)
"Acquire highligh annotations as text, and return as org-heading"
(interactive "fPath to PDF: ")
(let* ((outputstring "") ;; the text to be returned
(title (or title (replace-regexp-in-string "-" " " (file-name-base pdfpath ))))
(level (or level (1+ (org-current-level)))) ;; I guess if we're not in an org-buffer this will fail
(levelstring (make-string level ?*)) ;; set headline to proper level
(annots (sort (pdf-info-getannots nil pdfpath) ;; get and sort all annots
'pdf-annot-compare-annotations)))
;; create the header
(setq outputstring (concat levelstring " Quotes From " title "\n\n")) ;; create heading
;; extract text
(mapc
(lambda (annot) ;; traverse all annotations
(if (eq 'highlight (assoc-default 'type annot))
(let* ((page (assoc-default 'page annot))
;; use pdf-annot-edges-to-region to get correct boundaries of annotation
(real-edges (pdf-annot-edges-to-region
(pdf-annot-get annot 'markup-edges)))
(text (or (assoc-default 'subject annot) (assoc-default 'content annot)
(replace-regexp-in-string "\n" " " (pdf-info-gettext page real-edges nil pdfpath))))
(height (nth 1 real-edges)) ;; distance down the page
;; use pdfview link directly to page number
(linktext (concat "[[pdfview:" pdfpath "::" (number-to-string page)
"++" (number-to-string height) "][" title "]]" )))
(setq outputstring (concat outputstring text " ("
linktext ", " (number-to-string page) ")\n\n"))
))
(if (eq 'text (assoc-default 'type annot))
(let* ((page (assoc-default 'page annot))
;; use pdf-annot-edges-to-region to get correct boundaries of annotation
(real-edges (pdf-annot-edges-to-region
(pdf-annot-get annot 'markup-edges)))
(text (or (assoc-default 'subject annot) (assoc-default 'content annot)
(replace-regexp-in-string "\n" " " (pdf-info-gettext page real-edges nil pdfpath))))
(height (nth 1 real-edges)) ;; distance down the page
;; use pdfview link directly to page number
(linktext (concat "[[pdfview:" pdfpath "::" (number-to-string page)
"++" (number-to-string height) "][" title "]]" )))
(setq outputstring (concat outputstring text " ("
linktext ", " (number-to-string page) ")\n\n"))
))
(if (eq 'underline (assoc-default 'type annot))
(let* ((page (assoc-default 'page annot))
;; use pdf-annot-edges-to-region to get correct boundaries of highlight
(real-edges (pdf-annot-edges-to-region
(pdf-annot-get annot 'markup-edges)))
(text (or (assoc-default 'subject annot) (assoc-default 'content annot)
(replace-regexp-in-string "\n" " " (pdf-info-gettext page real-edges nil pdfpath))))
(height (nth 1 real-edges)) ;; distance down the page
;; use pdfview link directly to page number
(linktext (concat "[[pdfview:" pdfpath "::" (number-to-string page)
"++" (number-to-string height) "][" title "]]" )))
(setq outputstring (concat outputstring text " ("
linktext ", " (number-to-string page) ")\n\n"))
))
)
annots)
outputstring ;; return the header
)
)
(defun pdf-annot-summary-as-org-text (pdfpath &optional title level)
"Acquire underlined annotations as text, and return as org-heading"
(interactive "fPath to PDF: ")
(let* ((outputstring "") ;; the text to be returned
(title (or title (replace-regexp-in-string "-" " " (file-name-base pdfpath ))))
(level (or level (1+ (org-current-level)))) ;; I guess if we're not in an org-buffer this will fail
(levelstring (make-string level ?*)) ;; set headline to proper level
(annots (sort (pdf-info-getannots nil pdfpath) ;; get and sort all annots
'pdf-annot-compare-annotations)))
;; create the header
(setq outputstring (concat levelstring " Summary from " title "\n\n")) ;; create heading
;; extract text
(mapc
(lambda (annot) ;; traverse all annotations
(if (eq 'underline (assoc-default 'type annot))
(let* ((page (assoc-default 'page annot))
;; use pdf-annot-edges-to-region to get correct boundaries of annotation
(real-edges (pdf-annot-edges-to-region
(pdf-annot-get annot 'markup-edges)))
(text (or (assoc-default 'subject annot) (assoc-default 'content annot)
(replace-regexp-in-string "\n" " " (pdf-info-gettext page real-edges nil pdfpath))))
(height (nth 1 real-edges)) ;; distance down the page
;; use pdfview link directly to page number
(linktext (concat "[[pdfview:" pdfpath "::" (number-to-string page)
"++" (number-to-string height) "][" title "]]" )))
(setq outputstring (concat outputstring text " ("
linktext ", " (number-to-string page) ")\n\n"))
))
)
annots)
outputstring ;; return the header
)
)
Interface with Zotero.
(use-package zotxt
:diminish (org-zoxt zotxt org-zotxt-mode)
:config
;; (setq zotxt-default-bibliography-style "mkbehr-short")
;; Activate org-zotxt-mode in org-mode buffers
(add-hook 'org-mode-hook (lambda () (org-zotxt-mode 1)))
;; Activate in markdown
(add-hook 'markdown-mode-hook (lambda () (zotxt-easykey-mode 0))))
(defun proselint ()
(interactive)
(flycheck-mode)
(flycheck-select-checker 'proselint))
(defvar serif-preserve-default-list nil
"A list holding the faces that preserve the default family and
height when TOGGLE-SERIF is used.")
(setq serif-preserve-default-list
'(;; LaTeX markup
font-latex-math-face
font-latex-sedate-face
font-latex-warning-face
;; org markup
org-latex-and-related
org-meta-line
org-verbatim
org-block-begin-line
;; syntax highlighting using font-lock
font-lock-builtin-face
font-lock-comment-delimiter-face
font-lock-comment-face
font-lock-constant-face
font-lock-doc-face
font-lock-function-name-face
font-lock-keyword-face
font-lock-negation-char-face
font-lock-preprocessor-face
font-lock-regexp-grouping-backslash
font-lock-regexp-grouping-construct
font-lock-string-face
font-lock-type-face
font-lock-variable-name-face
font-lock-warning-face))
(defun toggle-serif ()
"Change the default face of the current buffer to use a serif family."
(interactive)
(when (display-graphic-p) ;; this is only for graphical emacs
;; the serif font familiy and height, save the default attributes
(let ((serif-fam "Minion Pro")
(serif-height 150)
(default-fam (face-attribute 'default :family))
(default-height (face-attribute 'default :height)))
(if (not (bound-and-true-p default-cookie))
(progn (make-local-variable 'default-cookie)
(make-local-variable 'preserve-default-cookies-list)
(setq preserve-default-cookies-list nil)
;; remap default face to serif
(setq default-cookie
(face-remap-add-relative
'default :family serif-fam :height serif-height))
;; keep previously defined monospace fonts the same
(dolist (face serif-preserve-default-list)
(add-to-list 'preserve-default-cookies-list
(face-remap-add-relative
face :family default-fam :height default-height)))
(message "Turned on serif writing font."))
;; undo changes
(progn (face-remap-remove-relative default-cookie)
(dolist (cookie preserve-default-cookies-list)
(face-remap-remove-relative cookie))
(setq default-cookie nil)
(setq preserve-default-cookies-list nil)
(message "Restored default fonts."))))))
(let ((private (expand-file-name "private.el" user-cache-directory)))
(if (file-exists-p private)
(load-file private)))
Dashboard depends on this.
(use-package page-break-lines
:diminish "")
Startup with a dashboard listing recent files, bookmarks, and projects.
(use-package dashboard
:config
(setq dashboard-items '((recents . 10)
(bookmarks . 10)
(projects . 10)))
(setq dashboard-startup-banner "/home/mclear/.emacs.d/icons/128x128.png")
;; Set the title
;; (setq dashboard-banner-logo-title "The past is a foreign country. They do things differently there. -- L.P. Hartly, The Go-Between")
(setq dashboard-banner-logo-title (message "Emacs initialized in %.2fs" (float-time (time-subtract (current-time) my-start-time))))
(dashboard-setup-startup-hook)
(general-define-key :states '(normal) :keymaps 'dashboard-mode-map
"TAB" 'widget-forward
"C-i" 'widget-forward
"backtab" 'widget-backward
"RET" 'widget-button-press
"down-mouse-1" 'widget-button-click
"g" #'dashboard-insert-startupify-lists
"r" (dashboard-insert-shortcut "r" "Recent Files:")
"m" (dashboard-insert-shortcut "m" "Bookmarks:")
"p" (dashboard-insert-shortcut "p" "Projects:")
))
Start server
(use-package server
:defer 2
:config
(if (display-graphic-p)
(unless (or (daemonp) (server-running-p))
(message "Starting server..")
(server-start)))
)
;; (eshell)
Below are various things I want to perfect or try out in the config.
- [X] Fix load time of
config.org
file - [X] Fix visual surround delete/change of various characters (org markup, dollar signs)
- [X] Fix bookmark/desktop save
- [X] Fix Helm locate so it loads faster (problem with bash alias setting)
- [X] Fix load time of Projectile (make cache persist across sessions)