This file is best viewed in org-mode in emacs as github doesn’t do a good job of parsing links which use the ID Property
:tangle yes
This allows me to run org-babel-tangle
in the org file to generate the el file without having to restart emacs and rely on org-babel-load-file
:comments both
This adds all the non-code related text as comments in the tangled file. It also adds comments wrappers with links back to the heading in the original Org mode file.
- YouTube: Mike Zamansky - Using Emacs
- YouTube: Uncle Dave - Emacs Tutorial
- YouTube: Yisrael Dov - Emacs is Great
- Curated list of “nice” config files
- Wolfe’s Literate Emacs Config
- Emacs from scratch
- AngryBacon
- Toon’s Literate Dotfiles
- https://brainlessdeveloper.com/2017/12/27/making-emacs-work-like-my-vim-setup/
Use C-u C-M-x
with the point over the function to debug. This puts us into debugging minor mode in which the following bindings are useful
SPC | Step next |
b | Set breakpoint |
g | Go (run) |
h | Goto here |
i | Step into |
q | Quit |
Setting this gives a backtrace
(setq debug-on-error t)
Yisrael Dov - Emacs is Great ep. 11
;; This is a tangled file. Do not make any changes here. All changes should preferably be made in the original Org file.
;; Use =org-babel-tangle-jump-back-to-org= to jump back to it from any code block.
;; If any changes are made here, use =org-babel-detangle= to add it back to the original Org mode file.
There are two ways I go about it:
- The first way is to specify
:noweb-ref NAME
in the source block’s header-args eg.I can then use this in another block like this
<<MY_BLK_NAME>>
- The other way is by specifying an explicit name for the source block
#+name: MY_BLK_NAME
and it can be used in the same way. However, this has the added advantage of allowing me to create links to it:
[[MY_BLK_NAME][Link to block called MY_BLK_NAME]]
<<:ensure>> | Install packages automatically if set to nil or t. Passing anything else allows mm to use a different package than the one named in use-package eg. |
<<:pin>> | Allows installing a package from a specific archive |
It doesn’t install packages by itself and defers that task to a package manager like package.el and straight.el. I’m currently using both.
straight.el allows me to install packages directly from the source repository and package.el because I haven’t figured out how to emulate the :pin
functionality which I use to get the latest version of org instead of the bundled version.
Initialize the packaging system and add the Melpa and Org respositories to get latest versions of packages
(require 'package)
(setq-default load-prefer-newer t
package-enable-at-startup nil)
(add-to-list 'package-archives '("melpa" . "http://melpa.org/packages/") t)
(add-to-list 'package-archives '("org" . "http://orgmode.org/elpa/") t)
(package-initialize)
Install packages automatically
(setq-default use-package-always-ensure t)
(defvar bootstrap-version)
(let ((bootstrap-file
(expand-file-name "straight/repos/straight.el/bootstrap.el" user-emacs-directory))
(bootstrap-version 5))
(unless (file-exists-p bootstrap-file)
(with-current-buffer
(url-retrieve-synchronously
"http://raw.githubusercontent.com/raxod502/straight.el/develop/install.el"
'silent 'inhibit-cookies)
(goto-char (point-max))
(eval-print-last-sexp)))
(load bootstrap-file nil 'nomessage))
and install use-package as well
(straight-use-package 'use-package)
Install packages by default
(setq straight-use-package-by-default t)
(straight-use-package 'el-patch)
or
(use-package el-patch
:straight t)
(straight-use-package
'(el-patch :type git :host github :repo "raxod502/el-patch")
or
(use-package el-patch
:straight (el-patch :type git :host github :repo "raxod502/el-patch"))
(straight-use-package
'(el-patch :type git :host github :repo "raxod502/el-patch"
:fork (:host github :repo "your-name/el-patch")))
or
(use-package el-patch
:straight (el-patch :type git :host github :repo "raxod502/el-patch"
:fork (:host github :repo "your-name/el-patch")))
(setq-default custom-file (expand-file-name "custom.el" user-emacs-directory))
(load custom-file t)
(bind-keys* :prefix-map my-fuzzy-jumper-command-map
:prefix-docstring "This map is used to put all keybindings that I use to jump around eg. open files, buffers etc."
:prefix "C-c f")
(bind-keys* :prefix-map my-auto-completion-map
:prefix-docstring "This map is used to put all auto-completion related keybindings"
:prefix "C-c c")
(bind-keys* :prefix-map my-goto-map
:prefix-docstring "This map is used to put all movement related keybindings"
:prefix "C-c g")
(bind-keys* :prefix-map my-s-bindings-map
:prefix-docstring "This map is used to group together all s-mnemonic bindings such as substitution, sizing etc."
:prefix "C-c s")
I think the following would be handy
[
- Enable setting
t
- Toggle setting
]
- Disable setting
Original use of C-c [
and C-c ]
is to manipulate org-agenda-files
. Since I don’t use either of these, might as well put them to better use.
(bind-keys* :prefix-map my-settings-enable-map
:prefix-docstring "This map is used to enable settings ala vim-unimpaired"
:prefix "C-c [")
(bind-keys* :prefix-map my-settings-disable-map
:prefix-docstring "This map is used to disable settings ala vim-unimpaired"
:prefix "C-c ]")
(bind-keys* :prefix-map my-settings-toggle-map
:prefix-docstring "This map is used to toggle settings"
:prefix "C-c t")
To delete existing bindings, use (unbind-key ...)
(bind-key* "C-h B" 'describe-personal-keybindings)
By default C-h c
is bound to describe-key-briefly
which seems wasted with describe-key
doing a better job.
(bind-key* "C-h c" 'describe-char)
By default C-x = is bound to what-cursor-position
. With evil binding g a
and g 8
to the same function, it is wasted. Might as well bind it to calc
(bind-key* "C-x =" 'calc)
In general, if the same binding exists for a key both with and without a modifier, then I try to remap only the one without the modifier.
The mnemonic is that Emacs leaves [a-z]
(under the C-c
prefix) free for the user. Thus, [a-z]
without a modifier are my bindings eg. as seen here and here
key-translation-map
can be used to map one set of keys to another eg.
(defun my-revert-buffer-no-confirm ()
"Revert buffer without confirmation."
(interactive)
(revert-buffer :ignore-auto :noconfirm))
(bind-key* "<f5>" 'my-revert-buffer-no-confirm)
(defun my-describe-keymap (keymap)
"Describe a keymap using `substitute-command-keys'."
(interactive
(list (completing-read
"Keymap: " (let (maps)
(mapatoms (lambda (sym)
(and (boundp sym)
(keymapp (symbol-value sym))
(push sym maps))))
maps)
nil t)))
(with-output-to-temp-buffer (format "*keymap: %s*" keymap)
(princ (format "%s\n\n" keymap))
(princ (substitute-command-keys (format "\\{%s}" keymap)))
(with-current-buffer standard-output ;; temp buffer
(setq help-xref-stack-item (list #'my-describe-keymap keymap)))))
(bind-key "K" 'my-describe-keymap help-map)
eg. (my-describe-keymap 'evil-window-map)
Change default location of backups to avoid littering PWD
(defvar backup-directory (concat user-emacs-directory "/tmp/backups"))
(unless (file-exists-p backup-directory)
(make-directory backup-directory t))
(setq backup-directory-alist `(("." . ,backup-directory)))
(setq make-backup-files t) ; backup of a file the first time it is saved.
(setq backup-by-copying t) ; don't clobber symlinks
(setq version-control t) ; version numbers for backup files
(setq delete-old-versions t) ; delete excess backup files silently
(setq delete-by-moving-to-trash t)
(setq kept-old-versions 6) ; oldest versions to keep when a new numbered backup is made (default: 2)
(setq kept-new-versions 9) ; newest versions to keep when a new numbered backup is made (default: 2)
Change default location of autosaves to avoid littering PWD
(defvar autosave-directory (concat user-emacs-directory "tmp/autosaves/"))
(if (not (file-exists-p autosave-directory)) (make-directory autosave-directory t))
;; (setq auto-save-file-name-transforms `(("." ,autosave-directory t)))
(setq auto-save-default t) ; auto-save every buffer that visits a file
Delete identical history entries
(setq history-delete-duplicates t)
Save mini-buffer history
(use-package savehist
:init
(setq savehist-file (concat user-emacs-directory "tmp/history.el")
history-length 100)
:config
(savehist-mode t))
(setq inhibit-startup-message t)
(setq initial-scratch-message "")
(menu-bar-mode 0)
(tool-bar-mode 0)
(scroll-bar-mode 0)
We can also put something like this into ~/.Xresources
to enable/disable certain things as soon as Emacs starts
Emacs.verticalScrollBars: off Emacs.toolBar: off
(setq-default
mouse-wheel-follow-mouse t ; Mouse-wheel acts on the hovered window instead of where the typing focus is
echo-keystrokes 0.1 ; Let emacs react faster to keystrokes
confirm-kill-emacs 'y-or-n-p ; Confirm before quitting
ring-bell-function 'ignore ; Disable anoying beep
redisplay-dont-pause t ; Improve rendering performance
indicate-empty-lines t ; Display a special glyph in the fringe of each empty line at the end of the buffer
help-window-select t ; Jump to the help window when it's opened.
right-margin-width 1
uniquify-buffer-name-style 'forward ; Better unique buffer names
window-combination-resize t ; Resize windows proportionally
x-stretch-cursor t) ; Stretch cursor to the glyph width
(column-number-mode t) ; Show column no. in mode-line
(global-visual-line-mode t) ; Enable editing by visual lines
(fset 'yes-or-no-p 'y-or-n-p) ; Simpler y/n answers
Undo and Redo changes in window configuration. Use C-c right
, C-c left
(default bindings) to switch between different layouts.
This is useful when I close a window by mistake to undo it and restore the window layout.
(winner-mode 1)
More intuitive keybindings defined after evil is loaded
From Pragmatic Emacs
(use-package ediff
:config
(setq ediff-window-setup-function 'ediff-setup-windows-plain ; Don't start another frame
ediff-split-window-function 'split-window-horizontally) ; Put windows side by side
(add-hook 'ediff-after-quit-hook-internal 'winner-undo)) ; Revert windows on exit (needs winner mode)
A daemon can be started from the shell
emacs --daemon=SERVERNAME
or from within emacs:
(setq server-name "SERVERNAME")
(server-start)
The downside of this is that this seems to restart the server instead of creating multiple instances
Once a daemon is started, a client can be started with
emacsclient --alternate-editor="" --create-frame --quiet --socket-name=SERVERNAME
This will launch emacsclient if a daemon is already running and create one if not. Note that alternate-editor has been left blank. This forces it to create a daemon.
To check whether a server is running, we can use
(server-running-p "SERVERNAME")
A complete list of all running servers can be found under /tmp/emacs$UID but it’s a little more complicated than that.
So, let’s just start a server if one isn’t running. A downside of this is that it won’t persist once emacs is killed
(use-package server
:ensure nil
:defer 5
:config
(unless (server-running-p server-name)
(server-start)))
Font madness in Emacs: https://idiocy.org/emacs-fonts-and-fontsets.html Test Drive Programming Fonts; I settled on Iosevka
Scale font size usingC-x C-+
and C-x C--
. C-x C-0
resets it.
text-scale-mode-step
controls the scaling factor. For obvious reasons, don’t set it to 1 else it won’t change at all
(setq-default text-scale-mode-step 1.1
line-spacing 1)
After installing a new font refresh the font cache by running
fc-cache -fv
(defun my-set-font-if-exists (type font)
"Check if FONT exists and set TYPE if it does."
(when (and (display-graphic-p)(x-list-fonts font))
(set-face-attribute type nil :font font)
t)) ; This is required so that we can use this function in a cond block below
(defun my-set-fonts()
(my-set-font-if-exists 'default "Iosevka-10")
(my-set-font-if-exists 'fixed-pitch "Iosevka-10")
(my-set-font-if-exists 'variable-pitch "Iosevka-10")
;; (cond ((eq system-type 'gnu/linux) (my-set-font-if-exists 'variable-pitch "Ubuntu Condensed-9"))
;; ((eq system-type 'windows-nt) (my-set-font-if-exists 'variable-pitch "Iosevka SS05-9")))
)
(my-set-fonts)
(setq locale-coding-system 'utf-8)
(set-terminal-coding-system 'utf-8)
(set-keyboard-coding-system 'utf-8)
(set-selection-coding-system 'utf-8)
(set-language-environment "UTF-8")
(prefer-coding-system 'utf-8)
From endless parentheses
(defun my-narrow-or-widen-dwim (p)
"Widen if buffer is narrowed, narrow-dwim otherwise.
Dwim means: region, org-src-block, org-subtree, or defun, whichever applies first.
Narrowing to org-src-block actually calls `org-edit-src-code'.
With prefix P, don't widen, just narrow even if buffer is already narrowed."
(interactive "P")
(declare (interactive-only))
(cond ((and (buffer-narrowed-p) (not p)) (widen))
((region-active-p)
(narrow-to-region (region-beginning)
(region-end)))
((derived-mode-p 'org-mode)
;; `org-edit-src-code' is not a real narrowing command.
;; Remove this first conditional if you don't want it.
(cond ((ignore-errors (org-edit-src-code) t)
(delete-other-windows))
((ignore-errors (org-narrow-to-block) t))
(t (org-narrow-to-subtree))))
((derived-mode-p 'latex-mode)
(LaTeX-narrow-to-environment))
(t (narrow-to-defun))))
;; This line actually replaces Emacs' entire narrowing keymap.
(bind-key "n" 'my-narrow-or-widen-dwim ctl-x-map)
(bind-key "c" 'global-hl-line-mode my-settings-toggle-map)
(electric-pair-mode t)
(show-paren-mode 1)
(setq show-paren-delay 0)
;; (setq show-paren-style 'expression)
Replaces the text lambda with λ. Full list of prettified symbols can be found in prettify-symbols-alist
The inhibit-compacting-font-caches
stops garbage collect from trying to handle font caches making things a lot faster
(global-prettify-symbols-mode t)
(setq inhibit-compacting-font-caches t)
(setq prettify-symbols-unprettify-at-point 'right-edge)
Default symbols that must be applied to all modes. NOTE: Some symbols occupy less space and may affect indendation. In order to avoid this: (From endlessparentheses)
(defun my-pretty-symbols-default()
(mapc (lambda(pair) (push pair prettify-symbols-alist))
'(("!=" . (?\s (Br . Bl) ?\s (Bc . Bc) ?≠))
("<=" . (?\s (Br . Bl) ?\s (Bc . Bc) ?≤))
(">=" . (?\s (Br . Bl) ?\s (Bc . Bc) ?≥)))))
(add-hook 'prog-mode-hook (lambda() (my-pretty-symbols-default)))
C/C++ specific symbols
(add-hook 'c++-mode-hook
(lambda() (mapc (lambda(pair) (push pair prettify-symbols-alist))
'(("->" . (?- (Br . Bc) ?- (Br . Bc) ?>))))))
Prettier checkboxes in org-mode (From reddit). Disabled as it doesn’t look good with Solarized theme.
(add-hook 'org-mode-hook (lambda ()
"Beautify Org Checkbox Symbol"
(push '("[ ]" . "☐") prettify-symbols-alist)
(push '("[X]" . "☑" ) prettify-symbols-alist)
(push '("[-]" . "❍" ) prettify-symbols-alist)
(prettify-symbols-mode)))
(setq-default indent-tabs-mode nil
show-trailing-whitespace nil
sh-basic-offset 2)
(setq sentence-end-double-space nil) ; Count 1 space after a period as the end of a sentence, instead of 2
;; (bind-key "RET" 'newline-and-indent)
Since these are buffer-local variables, I have to use setq-default
(defun my-toggle-trailing-whitespace ()
"Toggle trailing whitespace"
(interactive) ; Allows to be called as a command via M-x
(setq-default show-trailing-whitespace (not show-trailing-whitespace)))
(bind-key "SPC" 'my-toggle-trailing-whitespace my-settings-toggle-map)
Enable it only in some modes
(dolist (hook '(prog-mode-hook text-mode-hook))
(add-hook hook (lambda() (setq show-trailing-whitespace t))))
Automatically while saving (from emacswiki)
(add-hook 'before-save-hook 'delete-trailing-whitespace)
Use C-c s SPC
to delete trailing whitespace manually
(bind-key "SPC" 'delete-trailing-whitespace my-s-bindings-map)
(bind-key "w" 'toggle-truncate-lines my-settings-toggle-map)
Specify the shell to use to avoid prompt. From Uncle Dave’s video
(defvar my-term-shell "/bin/bash")
(defadvice ansi-term (before force-bash)
(interactive (list my-term-shell)))
(ad-activate 'ansi-term)
Launch
(bind-key* "<s-return>" 'ansi-term)
Misc info:
list-faces-display
- List all faces with colors and sample text
list-colors-display
- List all colors with their names
- State “TODO” from [2019-01-24 Thu 22:22]
(defun my-disable-all-themes ()
(interactive)
(mapc #'disable-theme custom-enabled-themes))
Emacs doesn’t have a native hook that is called after a theme has loaded. So we’ve to create one. (from reddit)
(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))
(add-hook 'after-load-theme-hook (lambda() (message "Theme loaded")))
(add-hook 'after-load-theme-hook
(lambda()
"Update fringe background color once a theme is loaded"
(set-face-attribute 'fringe nil :background (face-attribute 'highlight :background))))
(use-package solarized-theme
:init
(setq solarized-distinct-fringe-background t
solarized-use-variable-pitch nil)
:custom
(evil-normal-state-cursor '("#859900" box))
(evil-visual-state-cursor '("#b58900" box))
(evil-insert-state-cursor '("#268bd2" bar))
(evil-replace-state-cursor '("#dc322f" bar))
(evil-operator-state-cursor '("#dc322f" hollow))
(evil-emacs-state-cursor '("#839496" bar))
:config
(load-theme 'solarized-light t))
Frame parameters for all frames, regardless of window-system.
(setq default-frame-alist
'((tool-bar-lines 0)
(left-fringe . nil)
(right-fringe . 0)
(menu-bar-lines . 0)
(vertical-scroll-bars . nil)))
Set frame size programatically
(bind-keys :map my-s-bindings-map
("l" . (lambda () "Set emacs frame size to fit the left desktop monitor"
(interactive)
(set-frame-position (selected-frame) 0 0)
(set-frame-size (selected-frame) 1914 1165 t)))
("r" . (lambda () "Set emacs frame size to fit the right desktop monitor"
(interactive)
(set-frame-position (selected-frame) 1920 0)
(set-frame-size (selected-frame) 1914 1165 t))))
IRC using rcirc
(use-package rcirc
:commands rcirc
:custom
(rcirc-time-format "[%H:%M] ")
(rcirc-fill-column 'window-text-width)
(rcirc-default-nick "kshenoy")
(rcirc-server-alist '(("irc.freenode.net" :channels ("#emacs" "#vim"))))
(rcirc-prompt "%t> ")
I should probably make this a part of the theme but I’m going to keep it here for now
:custom-face
(rcirc-other-nick ((t (:foreground "#268bd2"))))
(rcirc-bright-nick ((t (:foreground "#d33682"))))
(rcirc-dim-nick ((t (:foreground "#93a1a1"))))
(rcirc-my-nick ((t (:foreground "#cb4b16"))))
(rcirc-nick-in-message ((t (:inherit rcirc-my-nick))))
(rcirc-nick-in-message-full-line ((t (:slant italic))))
(rcirc-server ((t (:foreground "#859900"))))
(rcirc-server-prefix ((t (:inherit rcirc-server))))
(rcirc-prompt ((t (:inherit rcirc-my-nick))))
(rcirc-url ((t (:inherit org-link))))
:config
(defun irc ()
"Simple wrapper which opens rcirc in a predefined window layout using eyebrowse"
(interactive)
(eyebrowse-switch-to-window-config 9)
(eyebrowse-rename-window-config 9 "IRC")
(delete-other-windows)
(rcirc nil))
(defvar rcirc-hide-names-on-join t
"Non-nil if nick names list should be hidden when joining a channel.")
(defadvice rcirc-handler-353 (around my-aad-rcirc-handler-353 activate)
"Do not render NICK list on join when `rcirc-hide-names-on-join' is non-nil.
RPL_NAMREPLY."
(when (not rcirc-hide-names-on-join)
ad-do-it))
(defadvice rcirc-handler-366 (around my-aad-rcirc-handler-366 activate)
"Do not render NICK list on join when `rcirc-hide-names-on-join' is non-nil.
RPL_ENDOFNAMES."
(when (not rcirc-hide-names-on-join)
ad-do-it))
(defadvice rcirc-handler-JOIN (around my-before-ad-rcirc-handler-join-no-names activate)
"Set `rcirc-hide-names-on-join' to `t'."
ad-do-it
(setq rcirc-hide-names-on-join t))
(defadvice rcirc-cmd-names (before my-ad-rcirc-cmd-names-no-list activate)
"Reset rcirc-hide-names-on-join to nil after the JOIN step."
(setq rcirc-hide-names-on-join nil)))
(featurep 'FEATURE)
can be used to determine if the package has been loaded or not.
eg. if we do C-h f ivy-mode
, it says it’s defined in ivy.el and at the bottom of the file, we see (provide 'ivy)
Thus, ivy is the feature-name.
Other examples:
- rainbow-mode is a mode provided by the file rainbow-mode.el and the feature is also called rainbow-mode
- yas-minor-mode is a mode provided by the file yasnippet.el and the feature is called yasnippet
- State “TODO” from [2019-01-31 Thu 07:55]
(use-package aggressive-indent
:hook (emacs-lisp-mode . aggressive-indent-mode))
(use-package all-the-icons
:straight
(:host github :repo "domtronn/all-the-icons.el"))
This needs to be run only after the first install
(all-the-icons-install-fonts)
(use-package all-the-icons-ivy
:after (all-the-icons ivy)
:config
(all-the-icons-ivy-setup))
(use-package all-the-icons-dired
:after all-the-icons
:hook (dired-mode . all-the-icons-dired-mode))
C-'
instead of creating a binding in my-goto-map
as that’s the default binding used in an ivy-minibuffer
Also, I’m rebinding M-g g
from goto-line
as using a number with avy-goto-line
makes it behave like goto-line
anyway.
Besides, M-g M-g
is still bound to goto-line
by default as well as the <N>G
binding from evil.
(use-package avy
:after evil
:bind* (("C-'" . avy-goto-char-timer)
("M-g g" . avy-goto-line))
:bind (:map my-goto-map ("o" . avy-org-goto-heading-timer)))
(use-package beacon
:custom
(beacon-blink-when-focused t)
(beacon-blink-when-window-scrolls t)
(beacon-size 80)
(beacon-color "#eee8d5")
:config
(beacon-mode 1)
(add-hook 'after-load-theme-hook
(lambda()
"Update beacon's background color once a theme is loaded"
(setq beacon-color (face-attribute 'fringe :background)))))
Provides auto-completion. References:
- Uncle Dave’s video for an introduction.
- reddit:How to use company as a completion framework
(use-package company
:custom
(company-idle-delay 0.1)
(company-minimum-prefix-length 2)
(company-show-numbers t) ; Show numbers in the drop-down menu to simplify selection
(company-selection-wrap-around t)
:config
(global-company-mode)
Explicitly trigger yasnippet
(bind-key "&" 'company-yasnippet my-auto-completion-map)
Replace Meta bindings with Ctrl
(unbind-key "M-n" company-active-map)
(unbind-key "M-p" company-active-map)
(bind-keys :map company-active-map
("C-n" . company-select-next)
("C-p" . company-select-previous))
The intent of this section is to make company as unobtrusive as possible; I want company to show me completions as I type but I want complete control over if I want to accept it or not. By default, when the completion menu pops-up, the company-active-map
is activated and it stays open while any key in it is pressed. However, what I find annoying is that it hijacks some bindings making them unavailable for regular use till I’ve either accepted a completion or explicitly rejected it using C-g.
To fix this, I’m going to start by unsetting company-require-match
which shows the menu but doesn’t select an entry which allows me to keep typing.
(setq company-require-match nil)
Next, I’m going to use company-tng (tab-n-go) as the frontend which allows showing the menu with no entry selected.
(require 'company-tng)
(setq company-frontends '(company-tng-frontend
company-pseudo-tooltip-frontend
company-echo-metadata-frontend))
I’m going to call this state as not-explicitly-interacted-with-company and while in this state, I want to reduce the
number of keys bound in company-active-map
to minimize my chances of needing to kill it to just be able to continue typing.
Unbinding keys from company-active-map allows me to use them for emacs’ actions rather than for company’s.
(unbind-key "C-h" company-active-map)
(unbind-key "C-s" company-active-map)
(unbind-key "C-M-s" company-active-map)
(unbind-key "C-w" company-active-map)
(unbind-key "RET" company-active-map)
(unbind-key "TAB" company-active-map)
(unbind-key "<f1>" company-active-map)
(unbind-key "<up>" company-active-map)
(unbind-key "<down>" company-active-map)
(unbind-key "<return>" company-active-map)
(unbind-key "<tab>" company-active-map)
(<return>
and <tab>
are for windowed emacs while RET
and TAB
are for terminal)
All done! Now, while I type, company shows me a list of completions but doesn’t highlight any of them till I select one. Also, I can use almost all keys to continue typing with the exception of C-n
, C-p
and M-[0-9]
which I use to interact with company. Pressing C-n
or C-p
selects the first or last entry from the completion menu and highlights it.
Once I’ve explicitly interacted with the completion menu, I can cycle through the entries using C-n
and C-p.
A selected entry is automatically inserted and there’s no need to confirm the selection. At any time I can abort the completion using C-g
and it restores the text to its state before completion.
This does not use a lot of company’s fancy features such as searching and filtering but it’s less intrusive and I’m willing to make that trade-off
(from emacs.stackexchange) Keeping this at the end to be run after we’ve added all backends
(defun company-mode/backend-with-yas (backend)
(if (and (listp backend) (member 'company-yasnippet backend))
backend
(append (if (consp backend) backend (list backend))
'(:with company-yasnippet))))
(setq company-backends (mapcar #'company-mode/backend-with-yas company-backends))
)
Getting started guide: https://github.com/noctuid/evil-guide
evil can be toggled using C-z
(use-package evil
:init
(setq evil-want-C-w-in-emacs-state t
evil-want-Y-yank-to-eol t)
:config
(evil-mode t)
Mode specific states
(dolist (mode '(git-rebase-mode org-toc-mode))
(evil-set-initial-state mode 'emacs))
(evil-set-initial-state 'term-mode 'insert)
evil-set-initial-state
works only for major modes. Thus for minor modes I have to use an explicit hook. Refer this github issue for details
(dolist (hook '(org-capture-mode-hook))
(add-hook hook 'evil-insert-state))
(dolist (hook '(edebug-mode-hook))
(add-hook hook 'evil-emacs-state))
(defun my-unimpaired-insert-line-before ()
"Insert blank line line before the current one"
(interactive)
(beginning-of-line)(open-line 1))
(defun my-unimpaired-insert-line-after ()
"Insert blank line line after the current one"
(interactive)
(end-of-line)(newline))
(bind-keys :map evil-normal-state-map
("] SPC" . my-unimpaired-insert-line-after)
("[ SPC" . my-unimpaired-insert-line-before)
("] b" . next-buffer)
("[ b" . previous-buffer)
("] q" . next-error)
("[ q" . previous-error)
("[ Q" . first-error))
(add-hook 'org-mode-hook (lambda() (bind-key "z v" 'org-reveal evil-normal-state-map)))
<<Make Escape quit everything>>
(define-key key-translation-map (kbd "ESC") (kbd "C-g"))
(bind-keys :map evil-window-map
("s" . (lambda() (interactive) (evil-window-split)(other-window 1)))
("v" . (lambda() (interactive) (evil-window-vsplit)(other-window 1))))
Note this is not a complete solution since it doesn’t work when combined with operators (eg. dj
)
(bind-keys :map evil-motion-state-map
("j" . evil-next-visual-line)
("gj" . evil-next-line)
("k" . evil-previous-visual-line)
("gk" . evil-previous-line)
("$" . evil-end-of-line)
("g$" . evil-end-of-visual-line))
(define-key key-translation-map (kbd "C-w C-h") (kbd "C-w h"))
(define-key key-translation-map (kbd "C-w C-j") (kbd "C-w j"))
(define-key key-translation-map (kbd "C-w C-k") (kbd "C-w k"))
(define-key key-translation-map (kbd "C-w C-l") (kbd "C-w l"))
(define-key key-translation-map (kbd "C-w C-s") (kbd "C-w s"))
(define-key key-translation-map (kbd "C-w C-v") (kbd "C-w v"))
(bind-key "U" 'redo evil-normal-state-map)
More intuitive keybindings for winner-mode
(bind-keys :map evil-window-map
("u" . winner-undo)
("U" . winner-redo))
)
(use-package evil-args
:after evil
:bind (:map evil-inner-text-objects-map
("," . evil-inner-arg)
:map evil-outer-text-objects-map
("," . evil-outer-arg)
:map evil-normal-state-map
("] ," . evil-forward-arg)
("[ ," . evil-backward-arg)
:map evil-motion-state-map
("] ," . evil-forward-arg)
("[ ," . evil-backward-arg)))
(use-package evil-commentary
:after evil
:bind (:map evil-normal-state-map
("g c" . evil-commentary)
:map evil-visual-state-map
("g c" . evil-commentary)))
(use-package evil-exchange
:after evil
:config (evil-exchange-cx-install))
(use-package evil-matchit
:after evil
:config
(global-evil-matchit-mode 1))
(use-package evil-numbers
:after evil
:bind (:map evil-normal-state-map
("C-c +" . evil-numbers/inc-at-pt)
("C-c -" . evil-numbers/dec-at-pt)
:map evil-visual-state-map
("C-c +" . evil-numbers/inc-at-pt)
("C-c -" . evil-numbers/dec-at-pt)))
Provides g~
operator to cycle between snake_case → SCREAMING_SNAKE_CASE → TitleCase → CamelCase → kebab-case
(use-package evil-string-inflection
:after evil
:bind (:map evil-normal-state-map
("g ~" . evil-operator-string-inflection)
:map evil-visual-state-map
("g ~" . evil-operator-string-inflection)))
(use-package evil-surround
:after evil
:config (global-evil-surround-mode))
(use-package evil-visualstar
:after evil
:config (global-evil-visualstar-mode))
- State “TODO” from [2019-01-25 Fri 17:44]
gt
and gT
but there are some buffers which are better used in emacs-state and, these won’t work there so I’m going to stick with C-c w
for the moment.
(use-package eyebrowse
:init
(setq eyebrowse-keymap-prefix (kbd "C-c w"))
:custom
(eyebrowse-wrap-around t)
:config
(eyebrowse-mode t)
(bind-keys :map eyebrowse-mode-map
("C-c w w" . eyebrowse-last-window-config)))
I thought about using a hydra instead of the default keybindings but the default keybindings work just fine. They’re similar to tmux’s bindings making it easy to remember. Besides, the trouble with hydra is if I just want to switch quickly, the hydra display still pops up for a bit which is kinda distracting.
(bind-key* "C-c w" 'hydra-eyebrowse/body)
(defhydra hydra-eyebrowse (:color blue :hint nil)
"
Edit ^^^^| Cycle ^^^^| Switch
-------------^^^^+-------------^^^^+----------
_c_reate ^^| _n_ext ^^| _._: _s_witch
_C_lose ^^| _p_revious ^^| [_0_-_9_]
_,_: _r_ename | _'_/_w_: last |
"
;; Edit
("c" eyebrowse-create-window-config)
("C" eyebrowse-close-window-config)
("," eyebrowse-rename-window-config)
("r" eyebrowse-rename-window-config)
;; Cycle
("n" eyebrowse-next-window-config :color pink)
("p" eyebrowse-prev-window-config :color pink)
("'" eyebrowse-last-window-config)
("w" eyebrowse-last-window-config)
;; Switch
("." eyebrowse-switch-to-window-config)
("s" eyebrowse-switch-to-window-config)
("0" eyebrowse-switch-to-window-config-0)
("1" eyebrowse-switch-to-window-config-1)
("2" eyebrowse-switch-to-window-config-2)
("3" eyebrowse-switch-to-window-config-3)
("4" eyebrowse-switch-to-window-config-4)
("5" eyebrowse-switch-to-window-config-5)
("6" eyebrowse-switch-to-window-config-6)
("7" eyebrowse-switch-to-window-config-7)
("8" eyebrowse-switch-to-window-config-8)
("9" eyebrowse-switch-to-window-config-9))
References:
Also disable some checks when in org-src-mode
(use-package flycheck
:hook ((prog-mode . flycheck-mode)
(org-src-mode . (lambda() (setq-local flycheck-disabled-checkers '(emacs-lisp-checkdoc)))))
:custom
(flycheck-gcc-language-standard "c++14")
(flycheck-clang-language-standard "c++14"))
(use-package flyspell
:defer t
Find aspell and hunspell automatically. Try to find hunspell first and, if hunspell does NOT exist use aspell
:config
(cond
((executable-find "hunspell")
(setq ispell-program-name "hunspell")
(setq ispell-dictionary "en_US"))
((executable-find "aspell")
(setq ispell-program-name "aspell")
;; Please note ispell-extra-args contains ACTUAL parameters passed to aspell
(setq ispell-extra-args '("--sug-mode=ultra" "--lang=en_US")))))
Also see: Using multiple dictionaries with hunspell
Code-folding. From https://github.com/mwfogleman/.emacs.d/blob/master/michael.org#cold-folding and reddit(use-package hideshow
:hook ((prog-mode . hs-minor-mode))
:config
(defun my-toggle-fold ()
(interactive)
(save-excursion
(end-of-line)
(hs-toggle-hiding)))
(bind-key "f" 'my-toggle-fold my-settings-toggle-map))
(use-package hydra)
More ideas in https::/github.com/kana/vim-submode
(use-package ivy
:custom
(ivy-virtual-abbreviate 'abbreviate "Show abbreviated path in addition to the filename")
:config
(ivy-mode 1)
(setq ivy-count-format "%d/%d "
ivy-height 12
ivy-extra-directories nil)
Do not add a ^
(beginning of line anchor) while completing. Refer this and this.
(setq ivy-initial-inputs-alist nil)
(bind-key* "C-c C-r" 'ivy-resume)
Binding | Description |
---|---|
M-n | Insert symbol at point. By default M-p and M-n go back and forward in history. |
However, starting with M-n we move the minibuffer history into the future, which can be thought of as a “dwim” choice. | |
M-q | Query replace. Start a substitution using the search pattern |
C-c C-o | ivy-occur. Launch occur using current input |
There is a variable ivy-use-virtual-buffers
that does this. However, it is static and when set, dumps everything in ivy-switch-buffer
.
As a result, by default I have to choose one or the other; I can’t have both. This fixes that.
C-c j j
will show buffers, recent files and bookmarks while C-c j b
will only show buffers
(defun my-ivy-switch-virtual-buffer ()
"Show recent files and bookmarks in the buffer list"
(interactive)
(let* ((ivy-use-virtual-buffers t))
(ivy-switch-buffer)))
(defun my-counsel-p4 (&optional initial-input)
"Find file in the current Perforce repository.
INITIAL-INPUT can be given as the initial minibuffer input."
(interactive)
(counsel-require-program counsel-p4-cmd)
(let* ((default-directory (expand-file-name (counsel-locate-p4-root)))
(cands (split-string
(shell-command-to-string counsel-p4-cmd)
"\n"
t)))
(ivy-read "Find file: " cands
:initial-input initial-input
:action #'counsel-git-action
:caller 'my-counsel-p4)))
(defun my-file-finder ()
"Context based file finding"
(interactive)
(cond ((locate-dominating-file default-directory ".git") (counsel-git))
((locate-dominating-file default-directory "P4CONFIG") (my-counsel-p4))
(t (counsel-fzf))))
(bind-keys :map my-fuzzy-jumper-command-map
("b" . ivy-switch-buffer)
("f" . my-file-finder)
("j" . my-ivy-switch-virtual-buffer))
)
(use-package ivy-hydra
:after (ivy hydra)
:config
Provides some vim-ish movements and calling methods. From here eg. To kill multiple buffers
C-x b
to open the buffer listC-o
to open the hydra menu- Select the ‘kill’ action by pressing
o k
or select it by cycling through the actions usingw
ands
- Once the ‘kill’ action has been selected, select the buffer to kill using the movement keys and press
f
to execute the action - Pressing
f
keeps the hydra menu open to allow selecting other buffers to execute the selected action
(bind-key "C-o"
(defhydra hydra-ivy (:hint nil :color pink)
"
Move ^^^^^^^^^^| Call ^^| Cancel ^^| Options ^^| Action _w_/_s_ _a_: %s(ivy-action-name)
---------------^^^^^^^^^^+-----------------^^+----------^^+-----------^^+-------------------------------
_g_ ^ ^ _k_ ^ ^ _u_ | e_x_ecute | _i_nsert | _c_alling: %-7s(if ivy-calling \"on\" \"off\") _C_ase-fold: %-10`ivy-case-fold-search
^↕^ _h_ ^+^ _l_ ^↕^ | _RET_: done | _q_uit | _m_atcher: %-7s(ivy--matcher-desc)^^^^^^^^^^^^ _t_runcate: %-11`truncate-lines
_G_ ^ ^ _j_ ^ ^ _d_ | _TAB_: alt-done | ^^| _<_/_>_: shrink/grow
^^^^^^^^^^| _o_ccur | ^^|
"
;; arrows
("j" ivy-next-line)
("k" ivy-previous-line)
("l" ivy-alt-done)
("h" ivy-backward-delete-char)
("g" ivy-beginning-of-buffer)
("G" ivy-end-of-buffer)
("d" ivy-scroll-up-command)
("u" ivy-scroll-down-command)
("e" ivy-scroll-down-command)
;; actions
("q" keyboard-escape-quit :exit t)
("C-g" keyboard-escape-quit :exit t)
("<escape>" keyboard-escape-quit :exit t)
("C-o" nil)
("i" nil)
("TAB" ivy-alt-done :exit nil)
("C-j" ivy-alt-done :exit nil)
;; ("d" ivy-done :exit t)
("RET" ivy-done :exit t)
("C-m" ivy-done :exit t)
("x" ivy-call)
("c" ivy-toggle-calling)
("m" ivy-toggle-fuzzy)
(">" ivy-minibuffer-grow)
("<" ivy-minibuffer-shrink)
("w" ivy-prev-action)
("s" ivy-next-action)
("a" ivy-read-action)
("t" (setq truncate-lines (not truncate-lines)))
("C" ivy-toggle-case-fold)
("o" ivy-occur :exit t))
ivy-minibuffer-map)
)
(use-package swiper
:after ivy
:bind* (("C-s" . swiper-isearch)
("C-M-s" . swiper-all))
:config
(when (executable-find "rg")
(setq counsel-grep-base-command
"rg --smart-case --max-columns 240 --no-heading --line-number --color never '%s' %s")))
NOTE: I’m deferring loading using :commands
for those commands for which I cannot use :bind
here
counsel-org-tag
binding is defined only after org is loaded so I’m defining it there instead.
counsel-org-goto
is set conditionally only if we’re in org-mode
Also, I’m explicitly binding each command to its counsel variant to get it to work with ivy-rich.
eg. the default flavor of M-x
will still have all fuzzy searching goodness that ivy brings. However,
using counsel-M-x
causes ivy-rich to put a docstring in there which it doesn’t do with the default flavor of M-x
NOTE: I’m deferring loading by using the commands
keyword for counsel-org-tag
because the binding for it,
C-c C-q
is found in org-mode-map
which hasn’t been defined yet.
(use-package counsel
:after ivy
:commands (counsel-org-tag counsel-org-goto counsel-semantic-or-imenu)
:init
(defun my-counsel-imenu ()
"Use mode-specific commands if available else fallback to counsel-semantic-or-imenu"
(interactive)
(if (string= major-mode "org-mode")
(counsel-org-goto)
(counsel-semantic-or-imenu)))
:bind* ("M-x" . counsel-M-x)
:bind (:map help-map
("a" . counsel-apropos)
("f" . counsel-describe-function)
("v" . counsel-describe-variable)
:map my-fuzzy-jumper-command-map
("/" . counsel-rg)
("k" . counsel-bookmark)
("o" . my-counsel-imenu)
:map my-s-bindings-map
("v" . counsel-set-variable)))
(use-package magit
:bind* ("C-x g" . magit-status))
(use-package modern-cpp-font-lock
:hook (c++-mode . modern-c++-font-lock-mode))
- get the latest version of org
- use contributed packages such as org-expiry, org-drill and org-id
I do this by leveraging :ensure and :pin
Resources: Organize Your Life in Plain Text, Customization guide, Extensions
(use-package org
:ensure org-plus-contrib
:pin org
:init
(setq org-directory "~/Documents/Notes/")
(setq org-default-notes-file (expand-file-name "Inbox.org" org-directory))
(setq org-M-RET-may-split-line '((item) (default . t)))
;; (setq org-special-ctrl-a/e t)
;; (setq org-return-follows-link nil)
(setq org-use-speed-commands nil)
;; (setq org-speed-commands-user nil)
(setq org-startup-align-all-tables nil)
(setq org-use-property-inheritance t)
(setq org-tags-column -100)
(setq org-hide-emphasis-markers t) ; Hide markers for bold/italics etc.
(setq org-blank-before-new-entry '((heading . t) (plain-list-item . nil)))
(setq org-link-search-must-match-exact-headline nil)
(setq org-startup-with-inline-images t)
(setq org-imenu-depth 10)
Enable syntax highlighting within the source blocks and keep the editing popup window within the same window. Also, strip leading and trailing empty lines if any. org-src-preserve-indentation will not add an extra level of indentation to the source code
(setq org-src-fontify-natively t
org-src-window-setup 'current-window
org-src-strip-leading-and-trailing-blank-lines t
;; org-src-preserve-indentation t
org-src-tab-acts-natively t)
Languages which can be evaluated in Org-mode buffers.
(org-babel-do-load-languages 'org-babel-load-languages
(append org-babel-load-languages
'((python . t)
(ruby . t)
(perl . t)
(dot . t)
(C . t))))
Ask for confirmation before evaluating? NO!
(defun my-org-babel-evaluate-silent (lang body)
"Do not ask for confirmation to evaluate these languages."
(not (or (string= lang "emacs-lisp"))))
(setq org-confirm-babel-evaluate 'my/org-babel-evaluate-silent)
On second thought it’s better not to do this because of the security implications. A safer way to go about it is by enabling it on a file-by-file basis using the following modeline
-*- org-confirm-babel-evaluate: nil -*-
(setq org-startup-indented t)
(setq org-hide-leading-stars t)
(setq org-odd-level-only nil)
;; others: ▼, ↴, ⬎, ⤷, …, ⋱
(setq org-ellipsis " ▼")
From Emacs StackExchange At the moment, it hides not just the angle braces but also the text between them.
(defcustom org-hidden-links-additional-re "<<[<]?[[:alnum:]]+>>[>]?"
"Regular expression that matches strings where the invisible-property is set to org-link."
:type '(choice (const :tag "Off" nil) regexp)
:group 'org-link)
(make-variable-buffer-local 'org-hidden-links-additional-re)
(defun org-activate-hidden-links-additional (limit)
"Put invisible-property org-link on strings matching `org-hide-links-additional-re'."
(if org-hidden-links-additional-re
(re-search-forward org-hidden-links-additional-re limit t)
(goto-char limit)
nil))
(add-hook 'org-font-lock-set-keywords-hook (lambda ()
(add-to-list 'org-font-lock-extra-keywords
'(org-activate-hidden-links-additional
(0 '(face org-target invisible org-link))))))
(defun org-show-emphasis-markers-at-point ()
(save-match-data
(if (and (org-in-regexp org-emph-re 2)
(>= (point) (match-beginning 3))
(<= (point) (match-end 4))
(member (match-string 3) (mapcar 'car org-emphasis-alist)))
(with-silent-modifications
(remove-text-properties
(match-beginning 3) (match-beginning 5)
'(invisible org-link)))
(apply 'font-lock-flush (list (match-beginning 3) (match-beginning 5))))))
(add-hook 'post-command-hook 'org-show-emphasis-markers-at-point nil t)
Custom keywords
(setq org-todo-keywords '((sequence "TODO(t!)" "WAITING(w@/!)" "|" "DONE(d@/!)" "DEFER(f@/!)" "CANCEL(c@)")))
;; (setq org-todo-keyword-faces
;; (quote (("TODO" :foreground "red" :weight bold)
;; ("WAITING" :foreground "orange" :weight bold)
;; ("DONE" :foreground "forest green" bold)
;; ("CANCEL" :foreground "forest green" bold))))
@
- Log timestamp and note
!
- Log timestamp only
x/y
- x
takes affect when entering the state and
y
takes affect when exiting if the state being entered doesn’t have any logging
Refer Tracking-TODO-state-changes for details
Add logging when task state changes
(setq org-log-done nil ; Not required as state changes are logged in the LOGBOOK
org-log-redeadline 'note
org-log-into-drawer t ; Save state changes into LOGBOOK drawer instead of in the body
org-treat-insert-todo-heading-as-state-change t
org-enforce-todo-dependencies t) ; Prevent parent task from being marked complete till all child TODOS are marked as complete
Change from any todo state to any other state using C-c C-t KEY
(setq org-use-fast-todo-selection t)
This frees up S-left and S-right which I can then use to cycles through the todo states but skip setting timestamps and entering notes which is very convenient when all I want to do is change the status of an entry without changing its timestamps
(setq org-treat-S-cursor-todo-selection-as-state-change nil)
:config
(setq org-clock-idle-time nil)
;; (set-face-attribute 'org-block nil :inherit 'fixed-pitch)
?
in each string controls where the point will be placed after expansion
(add-to-list 'org-structure-template-alist '("sc" "#+begin_src C++\n?\n#+end_src"))
(add-to-list 'org-structure-template-alist '("sl" "#+begin_src emacs-lisp\n?\n#+end_src\n"))
(add-to-list 'org-structure-template-alist '("sp" "#+begin_src python\n?\n#+end_src\n"))
;; (add-to-list 'org-structure-template-alist '("sd" "#+begin_src dot :file /tmp/out.png\n?\n#+end_src\n"))
(add-to-list 'org-structure-template-alist '("ss" "#+begin_src bash\n?\n#+end_src\n"))
For org-version >= 9.2, we have to use this. C-c C-,
was also added in 9.2 and provides a menu to select an easy-template
(add-to-list 'org-structure-template-alist '("sc" . "src C++"))
(add-to-list 'org-structure-template-alist '("sl" . "src emacs-lisp"))
(add-to-list 'org-structure-template-alist '("ss" . "src bash"))
Thus to get it to work as before using <sc
, we have to add org-tempo
to org-modules
(add-to-list 'org-modules 'org-tempo)
This is the counterpart to org-insert-link
. From here.
(defun my-org-flatten-link (&optional replace-with-description)
"Replace an org link with its description if REPLACE-WITH-DESCRIPTION is true. If not or if description doesn't exist, replace with its url"
(interactive)
(if (org-in-regexp org-bracket-link-regexp 1)
(let ((remove (list (match-beginning 0) (match-end 0)))
(description (if (match-end 3)
(org-match-string-no-properties 3)
(org-match-string-no-properties 1))))
(apply 'delete-region remove)
(insert description))))
(defun my-org-set-align-tags (p)
"Set tags by calling counsel-org-tags and align tags as well.
If called with a prefix, only align tags"
(interactive "P")
(unless p (counsel-org-tag))
(org-align-all-tags))
- State “TODO” from [2019-05-21 Tue 10:41]
C-c .
and C-c !
to create active and inactive timestamps respectively.
However, I also have flycheck installed which conflicts with the C-c !
binding.
This allows me to use C-c .
to insert a timestamp and when prompted to enter the date+time in the minibuffer, use !
to toggle between active and inactive timestamps.
From Emacs StackExchange. Also see Custom timestamp keymap.
(defun org-toggle-time-stamp-activity ()
"Toggle activity of time stamp or range at point."
(interactive)
(let ((pt (point)))
(when (org-at-timestamp-p t)
(goto-char (match-beginning 0))
(when-let ((el (org-element-timestamp-parser))
(type (org-element-property :type el))
(type-str (symbol-name type))
(begin (org-element-property :begin el))
(end (org-element-property :end el)))
(setq type-str
(if (string-match "inactive" type-str)
(replace-regexp-in-string "inactive" "active" type-str)
(replace-regexp-in-string "active" "inactive" type-str)))
(org-element-put-property el :type (intern type-str))
(goto-char end)
(skip-syntax-backward "-")
(delete-region begin (point))
(insert (org-element-timestamp-interpreter el nil))
(goto-char pt)))))
(defvar-local calendar-previous-buffer nil
"Buffer been active when `calendar' was called.")
(defun calendar-save-previous-buffer (oldfun &rest args)
"Save buffer been active at `calendar' in `calendar-previous-buffer'."
(let ((buf (current-buffer)))
(apply oldfun args)
(setq calendar-previous-buffer buf)))
(advice-add #'calendar :around #'calendar-save-previous-buffer)
(defvar-local my-org-time-stamp-toggle nil
"Make time inserted time stamp inactive after inserting with `my-org-time-stamp'.")
(defun org-time-stamp-toggle ()
"Make time stamp active at the end of `my-org-time-stamp'."
(interactive)
(when-let ((win (minibuffer-selected-window))
(buf (window-buffer win)))
(when (buffer-live-p buf)
(with-current-buffer buf
(when (buffer-live-p calendar-previous-buffer)
(set-buffer calendar-previous-buffer))
(setq my-org-time-stamp-toggle (null my-org-time-stamp-toggle))
(setq org-read-date-inactive my-org-time-stamp-toggle)))))
(define-key org-read-date-minibuffer-local-map "!" #'org-time-stamp-toggle)
(defun my-org-time-stamp (arg)
"Like `org-time-stamp' with ARG but toggle activity with character !."
(interactive "P")
(setq my-org-time-stamp-toggle nil)
(org-time-stamp arg)
(when my-org-time-stamp-toggle
(backward-char)
(org-toggle-time-stamp-activity)
(forward-char)))
(bind-key "C-c ." 'my-org-time-stamp org-mode-map)
Resources:
By /u/awalker4 on reddit. Show upto 3 levels of headings from the current file and two levels of headings from all agenda files
(setq org-refile-targets
'((nil . (:maxlevel . 9))
(org-agenda-files . (:maxlevel . 5))))
Each element of the list generates a set of possible targets. nil indicates that all the headings in the current buffer will be considered.
Following are from Aaron Bieber’s post Organizing Notes with Refile
Creating new parents - To create new heading, add /HeadingName
to the end when using refile (C-c C-w
)
(setq org-refile-allow-creating-parent-nodes 'confirm)
(setq org-refile-use-outline-path 'file)
(setq org-outline-path-complete-in-steps nil)
Store the timestamp when an entry is refiled
(setq org-log-refile 'time)
Why would I want to refile something work-related under Softwares etc. A way to do it is by writing a function that sets org-refile-targets in a let binding making it local. eg. implementation by abo-abo: worf-refile-other
(load-library "find-lisp")
(defun my-org-refile-targets ()
"Refile the current heading to another heading.
The other heading can be in the current file or in a file that resides
anywhere below the directory the current file resides in.
The intent is to move to a similar file. If I'm in work-related file,
I almost never have to refile something to a personal file."
(interactive "p")
(let* ((org-refile-targets '((nil . (:maxlevel . 9)))))
(org-refile)))
(bind-key* "C-c C-w" 'my-org-refile)
(bind-key "C-c C-w" 'my-org-refile org-mode-map)
eg. https://emacs-china.org/t/topic/3622
Some org-babel recipes
(setq org-babel-default-header-args
'((:results . "verbatim replace")))
(cond ((executable-find "clang++") (setq org-babel-C++-compiler "clang++"))
((executable-find "g++") (setq org-babel-C++-compiler "g++")))
(setq org-babel-default-header-args:C++
'((:flags . "-std=c++14 -Wall -Wextra -Werror ${BOOST_HOME:+-L ${BOOST_HOME}/lib -I ${BOOST_HOME}/include} -L${HOME}/.local/lib -I${HOME}/.local/include -Wl,${BOOST_HOME:+-rpath ${BOOST_HOME}/lib}")))
(setq org-babel-default-header-args:perl
'((:results . "output")))
(setq org-babel-python-command "python3")
From Emacs StackExchange
(defvar org-babel-eval-verbose t
"A non-nil value makes `org-babel-eval' display")
(defun org-babel-eval (cmd body)
"Run CMD on BODY.
If CMD succeeds then return its results, otherwise display
STDERR with `org-babel-eval-error-notify'."
(let ((err-buff (get-buffer-create " *Org-Babel Error*")) exit-code)
(with-current-buffer err-buff (erase-buffer))
(with-temp-buffer
(insert body)
(setq exit-code
(org-babel--shell-command-on-region
(point-min) (point-max) cmd err-buff))
(if (or (not (numberp exit-code)) (> exit-code 0)
(and org-babel-eval-verbose (> (buffer-size err-buff) 0))) ; new condition
(progn
(with-current-buffer err-buff
(org-babel-eval-error-notify exit-code (buffer-string)))
nil)
(buffer-string)))))
(setq org-babel-eval-verbose t)
From https://emacs.stackexchange.com/a/9813/9690
(defun my-fix-inline-images ()
(when org-inline-image-overlays
(org-redisplay-inline-images)))
(add-hook 'org-babel-after-execute-hook 'my-fix-inline-images)
org-babel-goto-src-block-head
jumps to the beginning of a source block. This is super useful! Why restrict it only to source blocks?
(defun my-org-babel-goto-block-corner (p)
"Go to the beginning of the current block.
If called with a prefix, go to the end of the block"
(interactive "P")
(let* ((element (org-element-at-point)))
(when (or (eq (org-element-type element) 'example-block)
(eq (org-element-type element) 'src-block) )
(let ((begin (org-element-property :begin element))
(end (org-element-property :end element)))
;; Ensure point is not on a blank line after the block.
(beginning-of-line)
(skip-chars-forward " \r\t\n" end)
(when (< (point) end)
(goto-char (if p end begin))
(when p
(skip-chars-backward " \r\t\n")
(beginning-of-line)))))))
Show hierarchical headlines when refiling instead of flattening it out Show all the hierarchical headlines instead of having to step down them
From Using Emacs 23 - Capture 1 and Using Emacs 24 - Capture 2
(setq org-capture-templates
'(("t" "TODO" entry
(file org-default-notes-file)
"* TODO %?\n:LOGBOOK:\n- State \"TODO\" from %U\n:END:"
:jump-to-captured t :empty-lines 1)
("r" "Recommendation" item (file "Personal/Recommendations.org") "" :jump-to-captured t)
("x" "Misc etc." entry
(file org-default-notes-file)
"* %?"
:jump-to-captured t :empty-lines 1)
("s" "Snippets")
("se" "Emacs snippets" entry
(file "Software/emacs.org")
"* %?"
:jump-to-captured t :empty-lines 1)
("ss" "Shell snippets" entry
(file "Software/shell.org")
"* %?"
:jump-to-captured t :empty-lines 1)
("sv" "Vim snippets" entry
(file "Software/vim.org")
"* %?"
:jump-to-captured t :empty-lines 1)))
NOTE:
- When using several keys, keys using the same prefix key must be sequential in the list and preceded by a 2-element entry explaining the prefix key. Template elements, Template expansion
- Quick notes related to current state can be taken using
C-c C-z
and get added to theLOGBOOK
(add-hook 'org-capture-prepare-finalize-hook
(lambda() (org-expiry-insert-created)(org-id-get-create)))
(credit: here)
(use-package noflet
:config
(defun my-make-capture-frame ()
"Create a new frame and run org-capture."
(interactive)
(select-frame-by-name "capture")
(delete-other-windows)
(noflet ((switch-to-buffer-other-window (buf) (switch-to-buffer buf)))
(counsel-org-capture))))
(defadvice org-capture-finalize
(after delete-capture-frame activate)
"Advise capture-finalize to close the frame"
(if (equal "capture" (frame-parameter nil 'name))
(delete-frame)))
(defadvice org-capture-destroy
(after delete-capture-frame activate)
"Advise capture-destroy to close the frame"
(if (equal "capture" (frame-parameter nil 'name))
(delete-frame)))
This can then be used to create a capture frame
emacsclient --alternate-editor="" --create-frame --no-wait --socket-name=capture --frame-parameters='(quote (name . "capture"))' --eval "(my-make-capture-frame)"
- State “TODO” from [2019-01-30 Wed 09:53]
(bind-keys :prefix-map my-org-bindings-map
:prefix-docstring "This map is used to group together all org-mode settings"
:prefix "C-c o"
("a" . org-agenda)
("c" . counsel-org-capture))
;; :bind (("c" . calendar))
<<Custom timestamp keymap>>. Also see Using ! to toggle timestamp type
(bind-key "C-c C-q" 'my-org-set-align-tags org-mode-map)
Delete the result block using C-c C-v C-k
where C-c C-v
is the org-babel-key-prefix
(define-key key-translation-map (kbd "C-c C-v C-k") (kbd "C-c C-v k"))
Repurpose C-c C-v u
to jump to beginning/end of any block. C-c C-v C-u
is left untouched to only jump to top of src blocks
(bind-key "u" 'my-org-babel-goto-block-corner org-babel-map)
)
Archive subtrees under the same hierarchy as the original in the archive files https://gist.github.com/Fuco1/e86fb5e0a5bb71ceafccedb5ca22fcfb https://fuco1.github.io/2017-04-20-Archive-subtrees-under-the-same-hierarchy-as-original-in-the-archive-files.html
Syntax highlighting when exporting to HTML? Yes, please!
(use-package htmlize
:disabled
:after org)
(use-package org-agenda
:after org
:ensure nil
:init
(setq org-agenda-files
(seq-filter (lambda (x)
(and 'file-exists-p
(not (string= "Spanish.org" x))
(not (string-match-p "Orgzly" x))))
(mapcar (lambda (x) (expand-file-name x org-directory))
'("Inbox.org" "Software/" "Personal/"))))
:config
This sets up how I want my org-agenda to be displayed - I want it to be the only thing visible. I’m using eyebrowse to switch window layouts. One of the layouts is just org-agenda so I don’t care about restoring the windows after quitting.
(setq org-agenda-window-setup 'only-window
;; org-agenda-restore-windows-after-quit t
org-agenda-compact-blocks t)
Force agenda to start on a Monday as a week starts on a Monday. Sat and Sun are called week-ends for a reason :) Also, by default, the agenda only shows the next 7 days. I want to see the last two 7 days as well just in case I missed something. Hence, these combined will show entries starting from the previous Monday. Source
(setq org-agenda-start-day "-7d"
org-agenda-start-on-weekday 1
org-agenda-span 14)
I don’t want to see completed tasks
(setq org-agenda-skip-scheduled-if-done t) ; Why isn't this default?
(setq org-agenda-skip-deadline-if-done t)
These are some helper functions Based on Aaron Bieber: An agenda for life with org-mode
(defun my-org-skip-subtree-if-habit ()
"Skip an agenda entry if it has a STYLE property equal to \"habit\"."
(let ((subtree-end (save-excursion (org-end-of-subtree t))))
(if (string= (org-entry-get nil "STYLE") "habit")
subtree-end
nil)))
(defun my-org-skip-subtree-if-priority (priority)
"Skip an agenda subtree if it has a priority of PRIORITY.
PRIORITY may be one of the characters ?A, ?B, or ?C."
(let ((subtree-end (save-excursion (org-end-of-subtree t)))
(pri-value (* 1000 (- org-lowest-priority priority)))
(pri-current (org-get-priority (thing-at-point 'line t))))
(if (= pri-value pri-current)
subtree-end
nil)))
Note that I’m using a noweb-ref here to insert the custom-commands. This allows me to construct each custom-command separately and describe it at length.
(setq org-agenda-custom-commands
'(
<<org-agenda-daily>>
<<org-agenda-work>>
))
("d" "Daily agenda and all TODOs"
(
- All the high priority tasks that are still pending
(tags "PRIORITY=\"A\""
((org-agenda-overriding-header "High-priority unfinished tasks:")
(org-agenda-skip-function '(org-agenda-skip-entry-if 'todo 'done))))
- An agenda showing the previous as well as the current week which I’ve configured above.
(agenda "")
- All the remaining todos (minus the high priority ones because why repeat it)
(alltodo ""
((org-agenda-overriding-header "ALL normal priority tasks:")
(org-agenda-skip-function '(or (my-org-skip-subtree-if-habit)
(my-org-skip-subtree-if-priority ?A)
(org-agenda-skip-if nil '(scheduled deadline))))))
))
Maybe I’ll split the last one later into two sections - normal and low priority but this is good for now
My work agenda is very similar to my daily agenda but it only uses my work related org files as source.("w" "Daily agenda and all TODOs for Work"
(
- All the high priority tasks that are still pending
(tags "PRIORITY=\"A\""
((org-agenda-overriding-header "High-priority unfinished tasks:")
(org-agenda-skip-function '(org-agenda-skip-entry-if 'todo 'done))))
- An agenda showing the previous as well as the next two weeks. This is different from my daily agenda and I have to specify the span explicitly.
(agenda "" ((org-agenda-span 21)))
- All the remaining todos (minus the high priority ones because why repeat it)
(alltodo ""
((org-agenda-overriding-header "ALL normal priority tasks:")
(org-agenda-skip-function '(or (my-org-skip-subtree-if-habit)
(my-org-skip-subtree-if-priority ?A)
(org-agenda-skip-if nil '(scheduled deadline))))))
These settings will apply to all the cmd-types in this custom-command so all 3 sections will only pull from my work org files
)
((org-agenda-files (list (expand-file-name "Work/" org-directory)))
))
General org keybindings Open the custom “Daily agenda and all TODOs” directly. Based on Emacs StackExchange.
(bind-key* "<f12>" '(lambda (&optional arg) (interactive "P")(org-agenda arg "w")))
)
Other bullets to consider: Default: “◉ ○ ✸ ✿” Large: ♥ ● ◇ ✚ ✜ ☯ ◆ ♠ ♣ ♦ ☢ ❀ ◆ ◖ ▶ Small: ► • ★ ▸
(use-package org-bullets
:after org
:hook (org-mode . (lambda() (org-bullets-mode 1)))
:custom (org-bullets-bullet-list '("✜")))
A good way to find more characters is to use M-x insert-char
org-drill is provided by the org-plus-contrib from the org repo. Hence I use :ensure and :pin to grab it from there.
(use-package org-drill
:after org
:ensure org-plus-contrib
:pin org
:commands org-drill
:init
(setq org-drill-learn-fraction 0.4)
:config
(add-to-list 'org-modules 'org-drill)
(setq org-drill-add-random-noise-to-intervals-p t)
(setq org-drill-hide-item-headings-p t))
(use-package org-drill-table
:after org-drill
:disabled
:straight
(:host github :repo "kshenoy/org-drill-table"))
org-expiry is provided by the org-plus-contrib from the org repo. Hence I use :ensure and :pin to grab it from there.
This allows me to add a CREATED
property everytime I create a new org-heading. From here.
(use-package org-expiry
:after org
:ensure org-plus-contrib
:pin org
:init
(setq org-expiry-inactive-timestamps t) ; Don't have everything in the agenda view
:config
(org-expiry-insinuate))
I want to grab org-id from the org-plus-contrib package from org repo which I do by by specifying :ensure and :pin
(use-package org-id
:after org
:ensure org-plus-contrib
:pin org
:init
(setq org-id-link-to-org-use-id 'create-if-interactive-and-no-custom-id)
:config
To effectively use custom ID, refer this.
Note that org-id
has been updated since then and now supports a method org-id-get-create
which creates an ID if one is not present.
Also, it uses the identifier ID instead of CUSTOM_ID
(add-hook 'org-insert-heading-hook 'org-id-get-create)
C-c C-l
and select id:
as type and completion should trigger.
org-id-get-with-outline-path-completion
returns the ID of the selected heading and creates it if it doesn’t have one already.
Details at Emacs StackExchange
(defun org-id-complete-link (&optional arg)
"Create an id: link using completion"
(concat "id:" (org-id-get-with-outline-path-completion org-refile-targets)))
(eval-after-load 'org '(org-link-set-parameters "id" :complete 'org-id-complete-link))
Example on Emacs StackExchange
(setq org-id-track-globally t)
(setq org-id-extra-files '("~/.emacs.d/config.org"))
)
From /u/Irkry on reddit
(use-package pcre2el
:config (pcre-mode t))
Use M-y
to show a list of all killed/yanked text to paste at the cursor location
(use-package popup-kill-ring
:bind ("M-y" . popup-kill-ring))
Use brighter colors
(use-package rainbow-delimiters
:bind (:map my-settings-toggle-map ("r" . rainbow-delimiters-mode))
:config
(set-face-attribute 'rainbow-delimiters-depth-1-face nil :foreground "dark orange")
(set-face-attribute 'rainbow-delimiters-depth-2-face nil :foreground "deep pink")
(set-face-attribute 'rainbow-delimiters-depth-3-face nil :foreground "chartreuse")
(set-face-attribute 'rainbow-delimiters-depth-4-face nil :foreground "deep sky blue")
(set-face-attribute 'rainbow-delimiters-depth-5-face nil :foreground "yellow")
(set-face-attribute 'rainbow-delimiters-depth-6-face nil :foreground "orchid")
(set-face-attribute 'rainbow-delimiters-depth-7-face nil :foreground "spring green")
(set-face-attribute 'rainbow-delimiters-depth-8-face nil :foreground "sienna1"))
When a color is specified as a hex code or with its name, set the background of the face to the value of the color itself
(use-package rainbow-mode
:defer t)
(use-package try
:commands (try try-and-refresh))
This lets us visually walk through the changes we’ve made, undo back to a certain point (or redo), and go down different branches.
Default binding is C-x u
(use-package undo-tree
:bind (:map my-settings-enable-map
("U" . undo-tree-visualize)
:map my-settings-disable-map
("U" . undo-tree-visualizer-quit))
:custom
(undo-tree-visualizer-timestamps t)
(undo-tree-visualizer-diff t))
Shows which keys can be pressed next.
eg. if you press C-x
and wait a few seconds, a window pops up with all the key bindings following the currently entered incomplete command.
(use-package which-key
:config (which-key-mode))
Use C-d
to clear the field without accepting the default field name
(use-package yasnippet
:commands (yas-reload-all yas-minor-mode)
:init
(add-hook 'c++-mode-hook (lambda() (yas-reload-all)(yas-minor-mode)))
(setq-default yas-snippet-dirs (list (concat user-emacs-directory "snippets")))
(setq yas-wrap-around-region t) ; Automatically insert selected text at $0, if any
:config
(bind-keys :map yas-minor-mode-map
("C-c & n" . yas-new-snippet)
("C-c & s" . yas-insert-snippet)
("C-c & v" . yas-visit-snippet-file)
("C-c & r" . yas-reload-all)
("C-c & &" . yas-describe-tables)))
NOTE:
- Normally, I would’ve used
:hook
to defer loading. However, just runningyas-minor-mode
isn’t sufficient and yasnippet requires that I runyas-reload-all
before it. As a result, I’ve to do it in a round-about manner by adding a hook. - I can’t use
:bind
here to defer loading because I’m adding bindings to a map which doesn’t exist till the plugin is loaded. I could use:bind-keymap
here instead but as explained above, I need to doyas-reload-all
as well and I don’t know how to do that with:bind-keymap
. Also, I want to avoid confusion when I read this 3 months later wondering how it works.
Placing at end to be called after all packages are loaded
(use-package delight
:config
(delight '((abbrev-mode nil t)
(aggressive-indent-mode nil aggressive-indent)
(beacon-mode nil beacon)
(company-mode nil company)
(flycheck-mode nil flycheck)
;; (irony-mode nil irony)
(ivy-mode nil ivy)
(org-indent-mode nil org-indent)
(pcre-mode nil pcre2el)
(rainbow-mode)
(undo-tree-mode nil undo-tree)
(yas-minor-mode nil yasnippet)
(which-key-mode nil which-key))))
(when (or (and (eq system-type 'gnu/linux) (string-match-p "atlibex" (system-name)))
(and (eq system-type 'windows-nt) (string-match-p "MHDC" (system-name))))
(load (expand-file-name "work.el" user-emacs-directory) t))
Use add-file-local-variable
or add-file-local-variable-prop-line
instead of adding these manually
Auto-tangle on save - Not using it because it was too aggressive for at least this file considering how often I tinker with it