85 KiB
Emacs configuration
Set up the package archives
require 'package)
(
(add-to-list 'package-archives"gnu" . "http://elpa.gnu.org/packages/"))
'(
(add-to-list 'package-archives"melpa-stable" . "https://stable.melpa.org/packages/") t)
'(
(add-to-list 'package-archives"melpa" . "https://melpa.org/packages/") t)
'(
(add-to-list 'package-archives"marmalade" . "http://marmalade-repo.org/packages/") t)
'(
(add-to-list 'package-archives"org" . "http://orgmode.org/elpa/") t)
'( (package-initialize)
Configure use-package
and preload bind-key
unless (package-installed-p 'use-package)
(
(package-refresh-contents)
(package-install 'use-package))
setq use-package-always-ensure t
(t)
use-package-verbose
require 'use-package)
(
use-package bind-key) (
Set up my personal keymap
I set it up early so I can use it in use-package
calls immediately.
defvar gpolonkai/pers-map (make-sparse-keymap)
("My own, personal, keymap!")
(define-prefix-command 'gpolonkai/pers-map)"t" 'gpolonkai/pers-map)
(define-key ctl-x-map "C-t") 'gpolonkai/pers-map) (define-key global-map (kbd
I really don’t want to type more than I really must…
(defalias 'yes-or-no-p 'y-or-n-p)
Set UTF-8 as the default encoding
Just to make sure, although most Linux DE does this for me.
"UTF-8")
(set-language-environment -8) (set-default-coding-systems 'utf
Set personal information
Who am I?
setq user-full-name "Gergely Polonkai"
("gergely@polonkai.eu") user-mail-address
Add some directories to load-path
My own (version controlled) lisp
directory
(add-to-list 'load-path (expand-file-name"lisp/")
(convert-standard-filename
user-emacs-directory))
(add-to-list 'load-path (expand-file-name"lisp/nyan-prompt")
(convert-standard-filename user-emacs-directory))
The local site-lisp
…if it exists.
let ((site-lisp-dir "/usr/local/share/emacs/site-lisp"))
(when (file-directory-p site-lisp-dir)
(dolist (elt (directory-files site-lisp-dir))
(unless (or (string= elt ".") (string= elt ".."))
(elt site-lisp-dir)))))) (add-to-list 'load-path (expand-file-name
Load some prerequisites
Load xdg-paths
load "xdg-paths") (
Load the tango dark theme
t) (load-theme 'tango-dark
Custom commands and functions
Utility functions
Check if something is nil
or a list of strings
defun nil-or-list-of-strings-p (var)
("Return t if VAR is either nil or a list holding only strings."
or (null var)
(not (null (delq nil
(mapcar (lambda (x) (and (stringp x) x)) var)))))) (
Get the number at point
defun get-number-at-point ()
(
(interactive)"0123456789.-")
(skip-chars-backward or (looking-at "[0123456789.-]+")
(error "No number at point"))
(0))) (string-to-number (match-string
Round number at point to the given decimals
defun round-number-at-point-to-decimals (decimal-count)
("NDecimal count: ")
(interactive let ((mult (expt 10 decimal-count)))
(
(replace-match (number-to-string/
(fround
(*
(
mult
(get-number-at-point))) mult)))))
Make a backup filename under user-emacs-cache-directory
Taken from Xah’s site.
defun xah/backup-file-name (fpath)
("Return a new file path for FPATH under `user-emacs-cache-directory'"
let* ((backup-root-dir (expand-file-name "backup" user-emacs-cache-directory))
("[A-Za-z]:" "" fpath))
(file-path (replace-regexp-in-string "//" "/" (concat backup-root-dir file-path "~"))))
(backup-file-path (replace-regexp-in-string
(make-directory (file-name-directory backup-file-path) (file-name-directory backup-file-path)) backup-file-path))
Run a function on a region
defun func-region (start end func)
("Run a function over the region between START and END in current buffer."
(save-excursionlet ((text (delete-and-extract-region start end)))
(funcall func text))))) (insert (
Check if we are running under Termux
We need to do things differently, if so.
defun termux-p ()
("Check if Emacs is running under Termux."
(string-match-p"/com.termux/")
(regexp-quote "~"))) (expand-file-name
Misc text manipulation functions
Delete the current line
defun gpolonkai/delete-current-line ()
("Kill the whole line on which point is."
(interactive)
(beginning-of-line)1)) (kill-line
Duplicate current line
defun gpolonkai/duplicate-line()
("Duplicate line at point."
(interactive)
(save-excursion1)
(move-beginning-of-line
(kill-line)
(yank)1)
(open-line 1)
(forward-line (yank)))
Toggle case of character at point
Based on Xah’s toggle letter case defun version 2015-12-22
defun toggle-char-case (arg-move-point)
("Toggle the case of the char after point.
If prefix argument ARG-MOVE-POINT is non-nil, move point after the char."
"P")
(interactive let ((case-fold-search nil))
(cond
("[[:lower:]]") (upcase-region (point) (1+ (point))))
((looking-at "[[:upper:]]") (downcase-region (point) (1+ (point)))))
((looking-at cond
( (arg-move-point (right-char)))))
Open a new line below
Copied from http://whattheemacsd.com/editing-defuns.el-01.html
defun open-line-below ()
("Open a new line below point."
(interactive)
(end-of-line)
(newline) (indent-for-tab-command))
Open a new line above
defun open-line-above ()
("Open a new line above point."
(interactive)
(beginning-of-line)
(newline)1)
(forward-line - (indent-for-tab-command))
TODO Kill or copy the whole line
Got from Xah’s site (TODO is for adding a link here.)
defun æ-kill-or-copy-whole-line (kill)
("Kill or copy the whole line point is on.
If KILL is non-nil, the line gets killed. Otherwise, it gets just
copied to the kill ring."
"P")
(interactive
if kill
(
(kill-whole-line)let ((beginning (progn (beginning-of-line) (point)))
(progn (end-of-line) (point))))
(end ( (copy-region-as-kill beginning end))))
Enclose region in a specific character
defun æ-enclose-region (character &optional start end)
("Enclose region in CHARACTER. If region is empty, simply inserts
CHARACTER two times and moves point between them.
If character is present in `insert-pair-alist', this function
will enclose region in the corresponding pair. In this case,
CHARACTER must be the opening member of the pair."
"cWhat character? \nr")
(interactive
setq open character close character)
(
let ((pair (assq character insert-pair-alist)))
(if pair
(if (nth 2 pair)
(setq open (nth 1 pair) close (nth 2 pair))
(setq open (nth 0 pair) close (nth 1 pair)))))
(
unless (and open close)
(setq open character)
(setq close character))
(
unless (use-region-p)
(setq start (point) end (point)))
(
(save-excursion
(goto-char end)close)
(insert-char
(goto-char start)open))
(insert-char
unless (use-region-p)
( (forward-char)))
Convert camelCase to snakecase
defun camel-to-snake-case (arg)
("Convert a camel case (camelCase or CamelCase) word to snake case (snake_case).
If the prefix argument ARG is non-nil, convert the text to uppercase."
"p")
(interactive progn
(let ((start (region-beginning))
(
(end (region-end))nil)
(case-fold-search nil))
(had-initial-underscore
(goto-char start)when (looking-at "_") (setq had-initial-underscore t))
("\\([A-Z]\\)" end t)
(while (re-search-forward "_\\1")
(replace-match setq end (1+ end)))
(if arg
(
(upcase-region start end)
(downcase-region start end))
(goto-char start)unless had-initial-underscore (delete-char 1))))) (
Insert two spaces after specific characters
defun org-space-key (&optional arg)
("Insert two spaces after a period.
ARG will be passed down verbatim to `self-insert-command'"
"p")
(interactive
when (looking-back "[.!?…]" nil)
(
(call-interactively 'self-insert-command arg)) (call-interactively 'self-insert-command arg))
Fill or unfill a paragraph
From http://pages.sachachua.com/.emacs.d/Sacha.html
defun sachachua/fill-or-unfill-paragraph (&optional unfill region)
("Fill (or unfill, if UNFILL is non-nil) paragraph (or REGION)."
progn
(interactive (
(barf-if-buffer-read-only)list (if current-prefix-arg 'unfill) t)))
(let ((fill-column (if unfill (point-max) fill-column)))
(nil region))) (fill-paragraph
Swap occurences of strings
Copied from http://emacs.stackexchange.com/a/27170/507
defun so/query-swap-strings (from-string
(
to-string
&optional delimited start end)"Swap occurrences of FROM-STRING and TO-STRING.
DELIMITED, START, and END are passed down verbatim to `perform-replace'."
(interactivelet ((common
(
(query-replace-read-args"Query swap"
(concat if current-prefix-arg
(if (eq current-prefix-arg '-) " backward" " word")
("")
if (use-region-p) " in region" ""))
(nil)))
list (nth 0 common) (nth 1 common) (nth 2 common)
(if (use-region-p) (region-beginning))
(if (use-region-p) (region-end)))))
(
(perform-replace"\\(" (regexp-quote from-string) "\\)\\|" (regexp-quote to-string))
(concat
`(replace-eval-replacement replace-quoteif (match-string 1)
(
,to-string
,from-string))t t delimited nil nil start end))
Navigation
Move to different beginnings of the current line
Inspired by Bozhidar Batsov's solution.
defun gpolonkai/move-to-beginning-of-line ()
("Move to different beginnings of the line.
These are, in order:
- beginning of the visual line if `visual-line-mode' is active,
- the first non-whitespace (indentation),
- the actual beginning of the line.
This function will jump between the first character and the
indentation if used multiple times."
(interactive)let ((last-pos (point)))
(when visual-line-mode
(
(beginning-of-visual-line))when (= (point) last-pos)
(
(back-to-indentation))when (= (point) last-pos)
(
(beginning-of-line))when (and (eq major-mode 'org-mode)
(= (point) last-pos))
(
(org-beginning-of-line))when (= (point) last-pos)
( (back-to-indentation))))
Move to the different ends of the current line
defun gpolonkai/move-to-end-of-line ()
("Move to the end of the line.
If `visual-line-mode' is active, jump to the end of the visual
line first. Then jump to the actual end of the line."
(interactive)let ((last-pos (point)))
(when visual-line-mode
(
(end-of-visual-line))when (= (point) last-pos)
(
(end-of-line))when (and (eq major-mode 'org-mode)
(= (point) last-pos))
( (org-end-of-line))))
File manipulation
Rename the current file
Copied from http://whattheemacsd.com/file-defuns.el-01.html
defun 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)))
(if (get-buffer new-name)
(error "A buffer named '%s' already exists!" new-name)
(rename-file filename new-name 1)
(
(rename-buffer new-name)
(set-visited-file-name new-name); TODO: this is suspicious for me…
nil)
(set-buffer-modified-p "File '%s' successfully renamed to '%s'"
(message name (file-name-nondirectory new-name)))))))
Delete the current file
Copied from http://whattheemacsd.com/file-defuns.el-02.html
defun delete-current-buffer-file ()
("Remove file connected to current buffer and kill the buffer."
(interactive)
let ((filename (buffer-file-name))
(
(name (buffer-name))
(buffer (current-buffer)))if (not (and filename (file-exists-p filename)))
(
(kill-buffer buffer)when (yes-or-no-p "Are you sure you want to remove this file? ")
(delete-file filename)
(
(kill-buffer buffer)"File '%s' successfully removed" filename))))) (message
Allow reopening the previously closed file
defvar gpolonkai/last-killed-buffer-file-name
(nil
"The last killed buffer.
Used by `gpolonkai/save-killed-buffer-filename' and `gpolonkai/undo-buffer-kill'.")
defun gpolonkai/save-killed-buffer-filename ()
("Save the filename of the killed buffer in `gpolonkai/last-killed-buffer-file-name'."
let ((filename (buffer-file-name)))
(unless filename
(setq gpolonkai/last-killed-buffer-file-name (buffer-file-name)))))
(
(add-hook 'kill-buffer-hook 'gpolonkai/save-killed-buffer-filename)
defun gpolonkai/undo-buffer-kill ()
("Undo killing the last buffer.
Esentially it visits the file again."
(interactive)if gpolonkai/last-killed-buffer-file-name
(progn
(
(find-file gpolonkai/last-killed-buffer-file-name)setq gpolonkai/last-killed-buffer-file-name nil))
("The buffer last killed didn’t visit a file."))) (message
Open this file as another user
defun open-this-file-as-other-user (user)
("Edit current file as USER, using `tramp' and `sudo'.
If the current buffer is not visiting a file, prompt for a file
name."
"sEdit as user (default: root): ")
(interactive when (string= "" user)
(setq user "root"))
(let* ((filename (or buffer-file-name
(format "Find file (as %s): "
(read-file-name (user))))
format "/sudo:%s@localhost:" user) filename)))
(tramp-path (concat (if buffer-file-name
(
(find-alternate-file tramp-path) (find-file tramp-path))))
Open my own init.el
defun gpolonkai/visit-init-file ()
("Open the init file."
(interactive)"configuration.org" user-emacs-directory))) (find-file-other-window (expand-file-name
Open my Org-mode index file
defun gpolonkai/visit-org-index ()
("Visit the root of Org-mode notes."
(interactive)
(find-file-other-window (concat (file-name-as-directory org-directory)"index.org")))
Frame manipulation
Hidden modeline mode
To temporarily hide the mode line.
Copied from http://emacs-doctor.com/emacs-strip-tease.html
defvar hidden-mode-line-mode nil)
(defvar hide-mode-line nil)
(
(define-minor-mode hidden-mode-line-mode"Minor mode to hide the mode-line in the current buffer."
nil
:init-value nil
:global
:variable hidden-mode-line-mode
:group 'editing-basicsif hidden-mode-line-mode
(setq hide-mode-line mode-line-format
(nil)
mode-line-format setq mode-line-format hide-mode-line
(nil))
hide-mode-line
(force-mode-line-update)
(redraw-display)when (and (called-interactively-p 'interactive)
(
hidden-mode-line-mode)
(run-with-idle-timer0 nil 'message
"Hidden Mode Line Mode enabled. "
(concat "Use M-x hidden-mode-line-mode to make mode-line appear."))))
Window manipulation
Transpose windows
defun transpose-windows (arg)
("Transpose the buffers shown in two windows."
"p")
(interactive let ((selector (if (>= arg 0) 'next-window 'previous-window)))
(/= arg 0)
(while (let ((this-win (window-buffer))
(funcall selector))))
(next-win (window-buffer (
(set-window-buffer (selected-window) next-win)funcall selector) this-win)
(set-window-buffer (funcall selector)))
(select-window (setq arg (if (plusp arg) (1- arg) (1+ arg)))))) (
Toggle window split between horizontal and vertical
defun toggle-window-split ()
(
(interactive)if (= (count-windows) 2)
(let* ((this-win-buffer (window-buffer))
(
(next-win-buffer (window-buffer (next-window)))
(this-win-edges (window-edges (selected-window)))
(next-win-edges (window-edges (next-window)))not (and (<= (car this-win-edges)
(this-win-2nd (car next-win-edges))
(<= (cadr this-win-edges)
(cadr next-win-edges)))))
(
(splitterif (= (car this-win-edges)
(car (window-edges (next-window))))
(
'split-window-horizontally
'split-window-vertically)))
(delete-other-windows)let ((first-win (selected-window)))
(funcall splitter)
(if this-win-2nd (other-window 1))
(
(set-window-buffer (selected-window) this-win-buffer)
(set-window-buffer (next-window) next-win-buffer)
(select-window first-win)if this-win-2nd (other-window 1))))
(error "This works only for two windows!"))) (
Scroll up or down in a specific window
defun gpolonkai/scroll-window-up (window)
("Scroll WINDOW up as `scroll-up-command' would."
(interactive)
(save-selected-window
(select-window window)
(scroll-up)))
defun gpolonkai/scroll-window-down (window)
("Scroll WINDOW down as `scroll-down-command' would."
(interactive)
(save-selected-window
(select-window window) (scroll-down)))
Bury a window
defun gpolonkai/bury-window (window)
("Quit WINDOW without killing it."
(interactive)nil window)) (quit-window
c-mode
related
Copy the prototype of the current function
defun gpolonkai/copy-func-prototype ()
("Copy the current function's prototype to the kill ring."
(interactive)
(save-excursion
(beginning-of-defun)let ((protocopy-begin (point)))
(
(forward-list)let ((protocopy-end (point)))
( (kill-ring-save protocopy-begin protocopy-end)))))
Programming related
Check if we are inside a string
defun gpolonkai/prog-in-string-p ()
("Return t if point is inside a string."
nth 3 (syntax-ppss))) (
Check if we are inside a comment
defun gpolonkai/prog-in-comment-p ()
("Return t if point is inside a comment."
nth 4 (syntax-ppss))) (
python-mode
related
Add a docstring to the current thing
…be it a function, class, or a module
defun gpolonkai/python-add-docstring ()
("Add a Python docstring to the current thing.
If point is inside a function, add docstring to that. If point
is in a class, add docstring to that. If neither, add docstring
to the beginning of the file."
(interactive)
(save-restriction
(widen)
(beginning-of-defun)if (not (looking-at-p "\\(def\\|class\\) "))
(progn
(
(goto-char (point-min))
(back-to-indentation)
(forward-char)
(while (gpolonkai/prog-in-comment-p)
(forward-line)
(back-to-indentation)
(forward-char)))":")
(search-forward or (gpolonkai/prog-in-string-p)
(while (
(gpolonkai/prog-in-comment-p))":")))
(search-forward if (eq 1 (count-lines 1 (point)))
(
(open-line-above)
(open-line-below))"\"\"\"")
(insert
(open-line-below)"\"\"\"")
(insert (open-line-above)))
idm
(ID manager) related functions
Get specific fields from a record in idm
defun gpolonkai/idm-record-get-field (record field)
("Get FIELD of an id-manager RECORD."
let ((funcname (intern (concat "idm-record-" (symbol-name field)))))
(when (fboundp funcname)
(funcall funcname record))))
(
defun gpolonkai/idm-get-field-for-account (account field)
("Get id-manager password for ACCOUNT."
let ((db (idm-load-db))
(nil))
(lookup-record dolist (record (funcall db 'get-all-records) password)
(when (string= account (idm-record-name record))
(setq lookup-record (gpolonkai/idm-record-get-field record field))))
(
lookup-record))
defmacro gpolonkai/idm-get-password-for-account (account)
(
`(gpolonkai/idm-get-field-for-account ,account 'password))
defmacro gpolonkai/idm-get-id-for-account (account)
( `(gpolonkai/idm-get-field-for-account ,account 'account-id))
Jinja related
Mark a string as translatable
defun jinja-mark-translatable (begin end)
(if (use-region-p)
(interactive (list (region-beginning) (region-end))
(list (point-min) (point-max))))
(
(save-excursion
(goto-char end)"{% endtrans %}")
(insert
(goto-char begin)"{% trans %}"))) (insert
URL-ify and de-URL-ify region
These functions URL-encode/decode a text. Might be helpful when embedding/extracting data to/from HTML.
defun hex-region (start end)
("urlencode the region between START and END in current buffer."
"r")
(interactive
(func-region start end #'url-hexify-string))
defun unhex-region (start end)
("de-urlencode the region between START and END in current buffer."
"r")
(interactive (func-region start end #'url-unhex-string))
Automatically zone out after 60 seconds
defun gpolonkai/zone-enable ()
("Enable zoning out."
(interactive)60)
(zone-when-idle "I will zone out after idling for 60 seconds.")) (message
Utility functions for editing Zim wiki files
defun zim-timestamp ()
(
(with-temp-buffer"%Y-%m-%dT%H:%M:%S%z"))
(insert (format-time-string 2)
(forward-char -":")
(insert
(buffer-string)))
defun insert-zim-timestamp ()
(
(interactive)
(insert (zim-timestamp)))
defun insert-zim-header ()
(
(interactive)
(save-excursion
(goto-char (point-min))
(insert"Content-Type: text/x-zim-wiki\n"
(concat "Wiki-Format: zim 0.4\n"
"Creation-Date: " (zim-timestamp) "\n\n"))))
Utility functions for EDiff
EDiff and Org-mode files don’t play nice together
From gmane.emacs.orgmode
defun f-ediff-org-showhide (buf command &rest cmdargs)
("If buffer BUF exists and in `org-mode', execute COMMAND with CMDARGS."
when buf
(when (eq (buffer-local-value 'major-mode (get-buffer buf)) 'org-mode)
(
(save-excursion
(set-buffer buf)apply command cmdargs)))))
(
defun f-ediff-org-unfold-tree-element ()
("Unfold tree at diff location."
(f-ediff-org-showhide ediff-buffer-A 'org-reveal)
(f-ediff-org-showhide ediff-buffer-B 'org-reveal)
(f-ediff-org-showhide ediff-buffer-C 'org-reveal))
defun f-ediff-org-fold-tree ()
("Fold tree back to top level."
1)
(f-ediff-org-showhide ediff-buffer-A 'hide-sublevels 1)
(f-ediff-org-showhide ediff-buffer-B 'hide-sublevels 1)) (f-ediff-org-showhide ediff-buffer-C 'hide-sublevels
Leave isearch
at the other end of the matched string
Taken from endless parentheses
defun isearch-exit-other-end ()
("Exit isearch, at the opposite end of the string."
(interactive)
(isearch-exit) (goto-char isearch-other-end))
Mark the current match after leaving isearch
Taken from here.
defun isearch-exit-mark-match ()
("Exit isearch and mark the current match."
(interactive)
(isearch-exit)
(push-mark isearch-other-end) (activate-mark))
Make the slash (/
) key act like C-j
in some Helm views
defun gpolonkai/helm-ff-slash-dir-complete ()
("Make forward slash (/) do completion in helm."
(interactive)if (and (or
(equal "magit-status" (assoc-default 'name (helm-get-current-source)))
(equal "Find Files" (assoc-default 'name (helm-get-current-source)))
(equal "helm-mode-insert-file" (assoc-default 'name (helm-get-current-source))))
(stringp (helm-get-selection))
(
(file-directory-p (helm-get-selection)))
(helm-execute-persistent-action)"/"))) (insert
Turn the cursor to purple if Yasnippet’s TAB function would fire
Taken from Sacha Chua’s config.
;; TODO: 'cursor-color is sometimes nil, but why?
setq default-cursor-color (or (frame-parameter nil 'cursor-color) "#ffd85c"))
(setq yasnippet-can-fire-cursor-color "purple")
(
;; It will test whether it can expand, if yes, cursor color -> purple.
defun yasnippet-can-fire-p (&optional field)
("Check if the word before point can be expanded with yasnippet.
TODO: What is FIELD for?"
(interactive)setq yas--condition-cache-timestamp (current-time))
(let (templates-and-pos)
(unless (and yas-expand-only-for-last-commands
(not (member last-command yas-expand-only-for-last-commands)))
(setq templates-and-pos (if field
(
(save-restriction
(narrow-to-region (yas--field-start field)
(yas--field-end field))
(yas--templates-for-key-at-point))
(yas--templates-for-key-at-point))))and templates-and-pos (first templates-and-pos))))
(
defun sachachua/change-cursor-color-when-can-expand (&optional field)
("Change cursor color if the text before point can be expanded with yasnippet.
TODO: What is FIELD for?"
(interactive)when (eq last-command 'self-insert-command)
(if (sachachua/can-expand)
(set-cursor-color (
yasnippet-can-fire-cursor-color
default-cursor-color))))
defun sachachua/can-expand ()
("Return t if right after an expandable thing."
or (abbrev--before-point) (yasnippet-can-fire-p))) (
Filter out tasks from the Org agenda if they have a specific priority
The whole idea comes from here, which i use almost verbatim. This is also the reason it has the air-
prefix.
defun air-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)))
(* 1000 (- org-lowest-priority priority)))
(pri-value (t))))
(pri-current (org-get-priority (thing-at-point 'line if (= pri-value pri-current)
(
subtree-endnil)))
Filter out habits from the Org agenda
defun air-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-endnil)))
Filter out entries from the Org agenda with a specific state
defun gpolonkai/org-skip-subtree-if-state (state)
("Skip an agenda entry if its state is STATE."
let ((subtree-end (save-excursion (org-end-of-subtree t))))
(if (string= (org-get-todo-state) state)
(
subtree-endnil)))
Wrapper around org-agenda
to open my own custom list
defun gpolonkai/org-agenda-list (&optional arg)
("P")
(interactive "c")) (org-agenda arg
UI preferences
Tweak window chrome
Turn off the scroll bar (that’s why Nyan-cat is here), the toolbar (I don’t really use it), and the menu bar (I rarely use it, and in those rare occasions I can simply turn it on.)
Also, maximise the frame.
0)
(tool-bar-mode 0)
(menu-bar-mode when window-system
(1))
(scroll-bar-mode -
nil 'fullscreen 'maximized) (set-frame-parameter
Set the default font and configure font resizing
Before this can be used, make sure the Symbola font is installed.
defun gpolonkai/set-font-size (frame)
(t :font "Hack-12")
(set-face-attribute 'default "Hack-12" t t))
(set-frame-font
defun --set-emoji-font (frame)
("Adjust the font setting of FRAME so Emacs can display Emoji properly."
when (fboundp 'set-fontset-font)
(if (eq system-type 'darwin)
(;; For NS/Cocoa
t 'symbol
(set-fontset-font "Apple Color Emoji")
(font-spec :family
frame 'prepend);; For Linux
t 'symbol
(set-fontset-font "Symbola")
(font-spec :family
frame 'prepend))))
(add-hook 'after-make-frame-functions 'gpolonkai/set-font-size) (add-hook 'after-make-frame-functions '--set-emoji-font)
Set up global minor modes provided by Emacs
Pretty lambdas
Because we can.
t) (global-prettify-symbols-mode
And set up all the pretty symbols.
;; Add some symbols to be prettified
setq prettify-symbols-alist
("lambda" . 955) ; λ
'(("function" . 402) ; ƒ
("->" . 8594) ; →
("=>" . 8658) ; ⇒
("map" . 8614) ; ↦
("not" . 172)) ; ¬
(
;; …and some pairs to complete
;; TODO: maybe add-to-list is a better way to do it
insert-pair-alist '(40 41) ; ()
(91 93) ; []
(123 125) ; {}
(60 62) ; <>
(34 34) ; ""
(39 39) ; ''
(96 39) ; `'
(8220 8221) ; “”
(8222 8221) ; „”
(8216 8217) ; ‘’
(8249 8250) ; ‹›
(8250 8249) ; ›‹
(171 187) ; «»
(187 171)) ; »«
(
;; Set the frame title to the current file name
frame-title-format '((:eval (concat system-name": "
if (buffer-file-name)
(
(abbreviate-file-name
(buffer-file-name))"%b")))))
Treat soft line breaks as hard ones in textual modes
lambda () (visual-line-mode t))) (add-hook 'text-mode-hook (
Enable disabled commands
Because I’m a rock star like that.
nil)
(put 'downcase-region 'disabled nil)
(put 'upcase-region 'disabled nil)
(put 'erase-buffer 'disabled nil)
(put 'narrow-to-region 'disabled nil)
(put 'narrow-to-page 'disabled nil)
(put 'set-goal-column 'disabled nil)
(put 'scroll-left 'disabled nil)
(put 'dired-find-alternate-file 'disabled nil)
(put 'Info-edit 'disabled nil) (put 'list-timers 'disabled
Load some built-in libraries
thingatpt
use-package thingatpt
(nil) :ensure
Calendar
use-package calendar
(nil
:ensure
:initsetq calendar-week-start-day 1
(47.4
calendar-latitude 19.0
calendar-longitude "Budapest, Hungary"
calendar-location-name 60
calendar-time-zone "CET"
calendar-standard-time-zone-name "CEST")) calendar-daylight-time-zone-name
Add the SysAdmin day to the calendar
Because I’m a sysadmin, too.
7 5 -1 "SysAdmin Day") t)
(add-to-list 'holiday-other-holidays '(holiday-float 10 21 "Reptile Awareness Day") t) (add-to-list 'holiday-other-holidays '(holiday-fixed
nXML
use-package nxml-mode
(nil
:ensure
:configsetq nxml-attribute-indent 4
(2
nxml-child-indent 4)) nxml-outline-child-indent
recentf
use-package recentf
(nil
:ensure
:confignil (* 5 60) 'recentf-save-list)
(run-at-time "elpa"))) (add-to-list 'recentf-exclude (concat user-emacs-directory
files
use-package files
(nil
:ensure
:configsetq make-backup-file-name-function 'xah/backup-file-name)) (
whitespace
whitespace-mode
is turned on by default, and can be toggled with F10
.
defun prevent-whitespace-mode-for-magit ()
("Prevent whitespace-mode from running in magit derived modes."
not (derived-mode-p 'magit-mode)))
(
use-package whitespace
(
:demand
:config
(add-function :before-while whitespace-enable-predicate 'prevent-whitespace-mode-for-magit)1)
(global-whitespace-mode setq whitespace-line-column 100)
(
:bind
(([f10] . whitespace-mode)
([(shift f10)] . global-whitespace-mode)
:map gpolonkai/pers-map"w" . whitespace-cleanup))) (
eshell
This is a function to delete a character, or close eshell
if there’s nothing to delete. Taken from here.
defun eshell-C-d ()
("Either call `delete-char' interactively or quit."
(interactive)
(condition-case err
(call-interactively #'delete-char)error (if (and (eq (car err) 'end-of-buffer)
(nil))
(looking-back eshell-prompt-regexp
(kill-buffer)signal (car err) (cdr err)))))) (
Function to bind it locally to C-d
.
defun gpolonkai/eshell-set-c-d-locally ()
("C-d") #'eshell-C-d)) (local-set-key (kbd
Now set up eshell.
use-package eshell
(
:bind
(:map gpolonkai/pers-map"e" . eshell))
(
:hook (eshell-mode . gpolonkai/eshell-set-c-d-locally))
saveplace
;; Save place
use-package saveplace
(
:config'if (version< emacs-version "25.0")
(t)
(setq-default save-place 1))
(save-place-mode setq save-place-file (expand-file-name ".places" user-emacs-directory))) (
ID manager
Manage credentials, AKA password manager.
use-package id-manager
(
:configsetq idm-database-file (expand-file-name "idm-db.gpg" user-emacs-directory))
(
:bind
(:map gpolonkai/pers-map"i" . idm-open-list-command))) (
EDiff
use-package ediff
(
:init
(setq-default ediff-merge-split-window-function 'split-window-horizontally
ediff-split-window-function 'split-window-vertically ediff-window-setup-function 'ediff-setup-windows-plain))
Automatically revert changed files
…unless they are modified, of course.
use-package autorevert
(
:config1)) (global-auto-revert-mode
Eww
For in-Emacs browsing needs.
use-package eww
(
:configsetq eww-search-prefix "https://www.google.com/?q=")) (
Electric indent mode
use-package electric
(
:config;; This seems to be the default, but let’s make sure…
1)) (electric-indent-mode
Save history
use-package savehist
(
:config1)) (savehist-mode
Web jump
use-package webjump
(
:bind
(:map gpolonkai/pers-map"j" . webjump))) (
Which function am I in?
defun gpolonkai/activate-which-func-mode ()
(if (fboundp 'which-function-mode)
(
(which-function-mode) (which-func-mode)))
use-package which-func
(
:configsetq which-func-unknown "∅")
(
:hook (prog-mode . gpolonkai/activate-which-func-mode))
Fortune cookies
The cookies are from the Hungarian version an ancient MS-DOS based program called TAGLINE
.
use-package cookie1
(t
:demand
:configsetq cookie-file (concat user-emacs-directory "fortune-cookies.txt"))
(
:bind
(:map gpolonkai/pers-map"k" . cookie))) (
News reader
use-package newsticker
(
:demand
:configsetq newsticker-url-list '(("(or emacs irrelevant)"
("http://oremacs.com/atom.xml"
nil nil nil)
"think"
("http://batsov.com/atom.xml"
nil nil nil)
"Endless Parentheses"
("http://endlessparentheses.com/atom.xml"
nil nil nil)
"Irreal"
("http://irreal.org/blog/?feed=rss2"
nil nil nil)
;; The followint may supersede previous entries
"Planet Emacs"
("http://planet.emacsen.org/atom.xml"
nil nil nil)))
:bind
(:map gpolonkai/pers-map"n" . newsticker-show-news))) (
Browse URL functionality in Termux
when (termux-p)
(use-package browse-url
(nil
:ensure
:config
(advice-add 'browse-url-default-browser :overridelambda (url &rest args)
(
(start-process-shell-command"open-url"
nil
"am start -a android.intent.action.VIEW --user 0 -d "
(concat url))))))
Dired customisation
use-package dired
(nil
:ensure
:configsetq dired-dwim-target t)
(
:bind
(:map dired-mode-map"RET" . dired-find-alternate-file)
("^" . (lambda () (interactive) (find-alternate-file "..")))
("W" . wdired-change-to-wdired-mode)))
(
use-package dired-x
(nil) :ensure
Actionable URLs
use-package goto-addr
(
:hook ((compilation-mode . goto-address-mode)
(prog-mode . goto-address-prog-mode)
(eshell-mode . goto-address-mode)
(shell-mode . goto-address-mode))
:bind
(:map goto-address-highlight-keymap"<RET>" . goto-address-at-point)
("M-<RET>" . newline))
( :commands (goto-address-prog-mode goto-address-mode))
Do things at midnight
By default, it closes a bunch of unused buffers. I might add some more things there later.
use-package midnight
(nil
:ensure
:configsetq clean-buffer-list-kill-never-buffer-names '("*scratch*"
("*Messages*"
"*dashboard*"))
t)) (midnight-mode
Show line numbers
I don’t usually like to see them, but there are occasions when they can be useful.
use-package display-line-numbers
(
:bind
(:map gpolonkai/pers-map"C-n" . display-line-numbers-mode))) (
use-package
packages
Automatically upgrade packages every week
use-package auto-package-update
(
:configsetq auto-package-update-interval 7
(t)
auto-package-update-delete-old-versions ;; Let’s do this in after-init-hook, as use-package invocations may modify
;; the list of installed packages
:hook (after-init . auto-package-update-maybe))
Nyanyanyanyanya
Nyan-cat style position marker
use-package nyan-mode
(
:initt
(setq-default nyan-animate-nyancat t)
nyan-wavy-trail
:config20)
(customize-set-variable 'nyan-bar-length t)) (nyan-mode
Nyan prompt in EShell
use-package nyan-prompt
(nil) :ensure
Zone out with Nyancat
Unfortunately, this works only in a graphical mode.
use-package zone-nyan
(
:after
zone
:configt)
(setq-default zone-nyan-hide-progress setq zone-programs (vconcat zone-programs [zone-nyan]))) (
De-light some minor modes
use-package delight) (
Eye candy
Moody mode-line
use-package moody
(
:config
(moody-replace-mode-line-buffer-identification)
(moody-replace-vc-mode)18)
(customize-set-variable 'moody-mode-line-height nil :box nil :foreground "#7e7486")
(set-face-attribute 'mode-line nil :box nil)) (set-face-attribute 'mode-line-inactive
Minions
use-package minions
(
:config1)) (minions-mode
Spinner, e.g. to display running background tasks
use-package spinner) (
Beacon
Highlight point. Sometimes it’s not easy to see.
use-package beacon
(
:demand
:config1)
(beacon-mode
:bind
(:map gpolonkai/pers-map"b" . beacon-blink))) (
Display the status of the last command in the fringe of EShell
use-package eshell-fringe-status
(
:hook (eshell-mode . eshell-fringe-status-mode))
Extras for the EShell prompt
use-package eshell-prompt-extras
(
:config"esh-opt"
(with-eval-after-load "eshell-prompt-extras")
(autoload 'epe-theme-lambda setq eshell-highlight-prompt nil
(
eshell-prompt-function 'epe-theme-lambda)when (featurep 'nyan-prompt)
( (nyan-prompt-enable))))
Show form feeds as a horizontal line
use-package form-feed
(
:hook
(emacs-lisp-mode . form-feed-mode) (compilation-mode . form-feed-mode))
Highlight the current line
use-package hl-line
(
:configwhen window-system
( (global-hl-line-mode)))
GNU Globals
defun gpolonkai/cond-enable-ggtags-mode ()
(when (derived-mode-p 'c-mode 'c++-mode 'java-mode)
(t)))
(ggtags-mode
use-package ggtags
(
:hook (c-mode-common . gpolonkai/cond-enable-ggtags-mode))
Multiple cursors
Because one is never enough.
defun gpolonkai/no-blink-matching-paren ()
(setq blink-matching-paren nil))
(
defun gpolonkai/blink-matching-paren ()
(setq blink-matching-paren t))
(
use-package multiple-cursors
(
:initdefvar gpolonkai/mc-prefix-map (make-sparse-keymap)
("Prefix keymap for multiple-cursors")
(define-prefix-command 'gpolonkai/mc-prefix-map)"C-c m") 'gpolonkai/mc-prefix-map)
(define-key global-map (kbd
:hook
(multiple-cursors-mode-enabled . gpolonkai/no-blink-matching-paren)
(multiple-cursors-mode-disabled . gpolonkai/blink-matching-paren)
:bind (:map gpolonkai/mc-prefix-map"t" . mc/mark-all-like-this)
("m" . mc/mark-all-like-this-dwim)
("l" . mc/edit-lines)
("e" . mc/edit-ends-of-lines)
("a" . mc/edit-beginnings-of-lines)
("n" . mc/mark-next-like-this)
("p" . mc/mark-previous-like-this)
("s" . mc/mark-sgml-tag-pair)
("d" . mc/mark-all-like-this-in-defun))) (
Incremental search for multiple cursors
use-package phi-search)
(
use-package phi-search-mc
(
:config (phi-search-mc/setup-keys))
Some extras
use-package mc-extras
(
:demand
:bind
(:map mc/keymap"C-c m =" . mc/compare-chars))) (
Add extra cursors via ace-jump
use-package ace-mc
(
:bind
(:map gpolonkai/mc-prefix-map"SPC" . ace-mc-add-multiple-cursors))) (
Magit
use-package magit
(
:initsetq magit-auto-revert-mode nil
("1.4.0"
magit-last-seen-setup-instructions nil)
magit-push-always-verify
:bind
(:map ctl-x-map"g" . magit-status))
(
:hook
(git-commit-mode . turn-on-flyspell))
Zone
use-package zone
(
:demand
:config60)
(zone-when-idle
:bind
(:map gpolonkai/pers-map"zi" . gpolonkai/zone-enable)
("zq" . zone-leave-me-alone))) (
Origami
use-package origami
(
:demand
:config
(define-prefix-command 'origami-mode-map)"z") 'origami-mode-map)
(define-key ctl-x-map (kbd
(global-origami-mode)
:bind
(:map origami-mode-map"o" . origami-open-node)
("O" . origami-open-node-recursively)
("c" . origami-close-node)
("C" . origami-close-node-recursively)
("a" . origami-toggle-node)
("A" . origami-recursively-toggle-node)
("R" . origami-open-all-nodes)
("M" . origami-close-all-nodes)
("v" . origami-show-only-node)
("k" . origami-previous-fold)
("j" . origami-forward-fold)
("x" . origami-reset))) (
Smart parens
use-package smartparens
(
:demand
:configt)
(show-smartparens-global-mode
:hook
(prog-mode . turn-on-smartparens-strict-mode)
(markdown-mode . turn-on-smartparens-strict-mode)
:bind
(([f9] . smartparens-strict-mode)"C-c s u" . sp-unwrap-sexp)
("C-c s k" . sp-kill-sexp))) (
Projectile
use-package projectile
(" [" projectile-project-name "]"))
:delight '(:eval (concat
:pin melpa-stable
:configt)) (projectile-global-mode
Repository-based ToDo management with Org mode
use-package org-projectile) (
…and the same with Helm
use-package org-projectile-helm) (
Text object manipulation
From the package description:
Text objects are textual patterns like a line, a top level definition, a word, a sentence or any other unit of text. When objed-mode is enabled, certain editing commands (configurable) will activate objed and enable its modal editing features.
use-package objed
(t
:demand
:bind
(:map global-map"M-SPC" . objed-activate))) (
Ace window
Besides its standard functionality, I also make add key bindings for burying or scrolling another window.
use-package ace-window
(
:configsetq aw-background nil
(t)
aw-dispatch-always
(add-to-list 'aw-dispatch-alist" Scroll window up")
'(?s gpolonkai/scroll-window-up t)
(add-to-list 'aw-dispatch-alist" Scroll window down")
'(?S gpolonkai/scroll-window-down t)
(add-to-list 'aw-dispatch-alist" Bury (quit) window")
'(?q gpolonkai/bury-window t)
:bind
(:map ctl-x-map"o" . ace-window))) (
Avy
use-package avy
(
:demand
:config
(avy-setup-default)
(defadvice avy-goto-line (around avy-fci activate)let ((fci-was-on (if (boundp 'fci-mode) fci-mode nil)))
(when fci-was-on
(1))
(fci-mode -
ad-do-itwhen fci-was-on
(1))))
(fci-mode
:bind"M-g c" . avy-goto-char)
(("M-g C" . avy-goto-char-2)
("M-g f" . avy-goto-line)
("M-g w" . avy-goto-word-1)
("M-g e" . avy-goto-word-0))) (
Focus mode
It is similar to narrow mode, except the narrowing part; it dims everything outside of the current context.
use-package focus
(
:bind (([f8] . focus-mode)))
Command logging mode
For occasional screen casting recordings.
use-package command-log-mode) (
Emamux
For controlling tmux from within Emacs.
use-package emamux) (
Use StackExchange sites in an Emacs window
use-package sx
(
:demand
:bind
(:map gpolonkai/pers-map"qi" . sx-inbox)
("qs" . sx-search))) (
Goto last change
use-package goto-last-change
(
:bind"M-g /" . goto-last-change))) ((
Rainbow mode
To highlight colours based on their name or hex code.
use-package rainbow-mode
(
:hook
(css-mode . rainbow-mode)
(scss-mode . rainbow-mode) (sass-mode . rainbow-mode))
Zygospore
Toggle other windows for maximum focus. When focus is no longer needed, they can be toggled back. C-x 1
is conveniently bound to it.
use-package zygospore
(
:bind
(:map ctl-x-map"1" . zygospore-toggle-delete-other-windows))) (
Kanban board
use-package kanban) (
Highlight dired buffer by file size, modified time, git status
use-package dired-k
(
:bind
(:map dired-mode-map"K" . dired-k))) (
Show number of matches in the mode line while searching
use-package anzu
(
:delight
:config1)) (global-anzu-mode
Gradually expand region
use-package expand-region
(
:bind
(:map gpolonkai/pers-map"x" . er/expand-region))) (
Read and Edit MediaWiki pages in an Emacs window
use-package mediawiki
(
:after
id-manager
:config
(add-to-list 'mediawiki-site-alist"WikEmacs"
'("http://wikemacs.org/wiki/"
"WikEmacs")
(gpolonkai/idm-get-id-for-account "WikEmacs")))) (gpolonkai/idm-get-password-for-account
Display unread GitHub notification count in the mode line
use-package github-notifier
(
:after
id-manager
:configsetq github-notifier-token (gpolonkai/idm-get-password-for-account "GitHub"))
( (github-notifier-mode))
Interact with GitHub gists
use-package gist) (
An Emacs Dashboard
use-package dashboard
(
:after
projectile
:config5) t)
(add-to-list 'dashboard-items '(projects . (dashboard-setup-startup-hook))
Hungarian holidays in the Calendar
use-package hungarian-holidays
(
:config (hungarian-holidays-add))
FlySpell
For all your spell-checking needs.
use-package flyspell
(
:hook
(prog-mode . flyspell-prog-mode) (text-mode . flyspell-mode))
Delete all the whitespace
use-package hungry-delete
(
:config (global-hungry-delete-mode))
Send alerts to a notification system
use-package alert
(
:configsetq alert-default-style
(if (termux-p)
(progn
(;; TODO Remove this as soon as my PR gets merged
;; https://github.com/jwiegley/alert/pull/41
unless (fboundp 'alert-termux-notify)
("termux-notification")
(defcustom alert-termux-command (executable-find "Path to the termux-notification command.
This is found in the termux-api package, and it requires the Termux
API addon app to be installed."
:type 'file
:group 'alert)
defun alert-termux-notify (info)
("Send INFO using termux-notification.
Handles :TITLE and :MESSAGE keywords from the
INFO plist."
if alert-termux-command
(let ((args (nconc
(when (plist-get info :title)
(list "-t" (alert-encode-string (plist-get info :title))))
(list "-c" (alert-encode-string (plist-get info :message))))))
(apply #'call-process alert-termux-command nil
(list (get-buffer-create " *termux-notification output*") t)
(nil args))
(alert-message-notify info)))
"Notify using termux"
(alert-define-style 'termux :title
:notifier #'alert-termux-notify))
'termux) 'libnotify)))
Replace the GUI popup menu with something more efficient
use-package ace-popup-menu
(;; Unfortunately, avy-menu (used by this package) is not compatible with minions. I just
;; disable it for now.
t
:disabled
:config1)) (ace-popup-menu-mode
I’m an achiever!
use-package achievements
(
:demand
:config1)
(achievements-mode
:bind
(:map gpolonkai/pers-map"C-a" . achievements-list-achievements))) (
Secretaria
Because even secretaries need a secretary today.
use-package secretaria
(
:after
alert
:hook;; use this for getting a reminder every 30 minutes of those tasks
;; scheduled for today and which have no time of day defined.
(after-init . secretaria-unknown-time-always-remind-me))
The Silver Searcher
use-package ag
(
:after projectile
:bind
(:map projectile-mode-map"C-c p C-a" . ag-project))) (
A fancier narrow-mode
use-package fancy-narrow
(
:config (fancy-narrow-mode))
Undo tree
use-package undo-tree) (
All the icons!
Should the fonts be missing, run (all-the-icons-install-fonts)
. It’s not run automatically, as it requires connecting to a website and download a pretty large font file.
use-package all-the-icons) (
NeoTree, if Dired is not an option
defun gpolonkai/neo-set-theme ()
(if (display-graphic-p) 'icons 'arrow)))
(customize-set-variable 'neo-theme (
use-package neotree
(
:after
all-the-icons
:bind
(([f5] . neotree-toggle))
:hook (neo-enter . gpolonkai/neo-set-theme))
Waka-waka
This will be replaced with something self-hosted, eventually.
use-package wakatime-mode
(
:init"wakatime"))
(setq-default wakatime-cli-path (executable-find
:configt)) (global-wakatime-mode
Jump to character, word, line
use-package ace-jump-mode
(
:bind
(:map gpolonkai/pers-map"SPC" . ace-jump-mode))) (
Command frequency meter
use-package keyfreq
(
:demand
:initsetq keyfreq-file (expand-file-name
("keyfreq"
user-emacs-directory))setq keyfreq-file-lock (expand-file-name
("keyfreq.lock"
user-emacs-directory))
:config1)
(keyfreq-mode 1)
(keyfreq-autosave-mode
:bind
(:map gpolonkai/pers-map"C-f" . keyfreq-show))) (
EditorConfig
EditorConfig is a nice tool to unify, well, configuration of different editors.
use-package editorconfig
(
:configt)) (editorconfig-mode
occur-like folding in the current buffer
defun gpolonkai/toggle-loccur ()
("Toggle `loccur-mode'.
If `loccur-mode' is not active, starts it (which, in turn, will ask for the
pattern to look for). If it is active, it will disable it."
(interactive)if loccur-mode
(nil)
(loccur-mode
(call-interactively 'loccur)))
use-package loccur
(
:bind
(:map gpolonkai/pers-map"C-o" . gpolonkai/toggle-loccur))) (
More fine-tuned autosaving
First, a function that turns off auto-saving for remote files.
defun gpolonkai/dont-autosave-remote ()
(when (and buffer-file-name (not (file-remote-p buffer-file-name)))
( (real-auto-save-mode)))
Then configure real-auto-save-mode
use-package real-auto-save
(t
:demand
:hook
(text-mode . gpolonkai/dont-autosave-remote) (prog-mode . gpolonkai/dont-autosave-remote))
Help merging pacsave
and pacnew
files
use-package pacfiles-mode
( :commands pacfiles)
Mailing with mu4e
use-package mu4e
(nil
:ensure
:configsetq mu4e-contexts
(
`( ,(make-mu4e-context:name "Private"
lambda () (mu4e-message "Entering Private Context"))
:enter-func (lambda () (mu4e-message "Leaving Private Context"))
:leave-func (lambda (msg)
:match-func (when msg
(
(mu4e-message-contact-field-matches msg"gergely@polonkai.eu")))
:to "gergely@polonkai.eu")
:vars '((user-mail-address . "~/.cache/mail/Polonkai")
(mu4e-maildir . "/[Gmail].Sendur p&APM-stur")
(mu4e-sent-folder . "/[Gmail].Dr&APY-g")
(mu4e-drafts-folder . "/[Gmail].Rusl")
(mu4e-trash-folder . "/[Gmail].Dr&APY-g")))
(mu4e-refile-folder .
,(make-mu4e-context:name "GT2"
lambda () (mu4e-message "Entering GT2 Context"))
:enter-func (lambda () (mu4e-message "Leaving GT2 Context"))
:leave-func (lambda (msg)
:match-func (when msg
(or
(
(mu4e-message-contact-field-matches msg"gergo@gt2.io")
:to
(mu4e-message-contact-field-matches msg"gergo@benchmarked.games"))))
:to "gergo@benchmarked.games")
:vars '((user-mail-address . "~/.cache/mail/GT2")
(mu4e-maildir . "/[Gmail].Sent Mail")
(mu4e-sent-folder . "/[Gmail].Drafts")
(mu4e-drafts-folder . "/[Gmail].Trash")
(mu4e-trash-folder . "/[Gmail].Drafts"))))
(mu4e-refile-folder .
mu4e-context-policy 'pick-first)
:bind
(:map gpolonkai/pers-map"m m" . mu4e)
("m i" . mu4e~headers-jump-to-maildir)
("m c" . mu4e-compose-new)
("m s" . mu4e-headers-search))) (
ViM’s ci
functionality
use-package ciel
(
:bind
(:map global-map"C-c i" . ciel-ci)
("C-c o" . ciel-co))) (
Access files in Docker containers using TRAMP
use-package docker-tramp) (
Display a line at fill-column
use-package fill-column-indicator
(
:hook (prog-mode . fci-mode))
Make programming a bit easier
Electric case
Insert snake_case
and camelCase
without using the Shift key. It is automatically enabled in C mode.
use-package electric-case
(
:hook (c-mode . electric-case-c-init))
Electric operator
Automatically add spaces around operators.
use-package electric-operator
(
:config;; Apply electric-operator-mode to vala-mode, too
apply #'electric-operator-add-rules-for-mode 'vala-mode
(
(electric-operator-get-rules-for-mode 'prog-mode))
:hook (c-mode-common . electric-operator-mode))
Yasnippets
use-package yasnippet
(
:demand
:config1)
(yas-global-mode
:hook (post-command . sachachua/change-cursor-color-when-can-expand))
Extra snippets for Vala
use-package vala-snippets
(
:after yasnippet)
Miscellanous extra snippets
use-package yasnippet-snippets) (
Colourful delimiters
use-package rainbow-delimiters
(
:hook (prog-mode . rainbow-delimiters-mode))
REST Client
use-package restclient) (
Highlight current symbol
A big help during refactoring.
use-package auto-highlight-symbol
(
:configt)) (global-auto-highlight-symbol-mode
Make ReallyLongCamelCaseWords more readable
use-package glasses
(" 👓"
:delight
:hook (prog-mode . glasses-mode))
GObject boilerplate generator
use-package gobgen) (
Insert specific licenses in the current buffer
use-package xlicense
(
:bind
(:map gpolonkai/pers-map"L" . insert-license))) (
Highlight TODO, FIXME, and XXX
use-package hl-todo) (
Python related setup and use-package
calls
Because, well, that’s my job now. Of course it gets a dedicated section.
Set up pretty symbols for Python
Because they are fancy.
- not: ¬
- in: ∈
- def: ƒ
Maybe add ∉ for not in
later, if possible.
(add-hook 'python-mode-hooklambda ()
(
(add-to-list 'prettify-symbols-alist"not" . 172))
'(
(add-to-list 'prettify-symbols-alist"in" . 8712))
'(
(add-to-list 'prettify-symbols-alist"def" . 402)))) '(
Automatically load the virtualenv if there is one
use-package auto-virtualenv
(
:hook
(python-mode . auto-virtualenv-set-virtualenv) (projectile-after-switch-project . auto-virtualenv-set-virtualenv))
Anaconda mode
use-package anaconda-mode
(
:hook
(python-mode . anaconda-mode) (python-mode . anaconda-eldoc-mode))
PipEnv
Because it’s great.
use-package pipenv
(
:hook
(python-mode . pipenv-mode)
:initsetq pipenv-projectile-after-switch-function #'pipenv-projectile-after-switch-extended)) (
Automatically insert Sphinx-style docstrings
use-package sphinx-doc
(
:hook (python-mode . sphinx-doc-mode))
C mode
Because that’s still my favourite language.
Set up my own C style
(defconst my-c-stylet)
'((c-tab-always-indent . 4)
(c-comment-only-line-offset .
(c-hanging-braces-alist . ((substatement-open after)
(brace-list-open)))
(c-hanging-colons-alist . ((member-init-intro before)
(inher-intro)
(case-label after)
(label after)
(access-label after)))
(c-cleanup-list . (scope-operator
empty-defun-braces
defun-close-semi))+)
(c-offsets-alist . ((arglist-close . +)
(arglist-intro . 0)
(substatement-open . 4)
(case-label . 0)
(block-open . -)
(knr-argdecl-intro . 0)
(comment-intro . ++)))
(member-init-intro . t))
(c-echo-syntactic-information-p . "My C Programming Style.")
"PERSONAL" my-c-style) (c-add-style
Some common initialisation for C mode
(add-hook 'c-mode-common-hooklambda ()
("C-c o") 'ff-find-other-file)
(local-set-key (kbd "PERSONAL")
(c-set-style setq tab-width 4
(nil)
indent-tabs-mode 1)))
(c-toggle-auto-newline
(add-hook 'c-initialization-hooklambda ()
("C-m") 'c-context-line-break))) (define-key c-mode-base-map (kbd
Set indentation levels to the same as the tab width
(defvaralias 'c-basic-offset 'tab-width) (defvaralias 'cperl-indent-level 'tab-width)
Web development
Web mode
use-package web-mode
("\\.html?\\'"
:mode
:configsetq web-mode-enable-auto-indentation nil)
(setq web-mode-enable-engine-detection t)) (
Emmet mode
use-package emmet-mode
(
:configsetq emmet-self-closing-tag-style "")
(
:hook
(web-mode . emmet-mode) (css-mode . emmet-mode))
Query HTML tags by CSS selectors
use-package enlive) (
FlyCheck
use-package flycheck
(
:config (global-flycheck-mode))
FlyCheck for pkg-config files
use-package flycheck-pkg-config) (
Org mode
This is a big one; I use a lot of customisation here.
use-package org
(
:demand
:initrequire 'xdg-paths)
(
(defface org-checkbox-todo-textt (:inherit org-todo)))
'(("Face for the text part of an unchecked org-mode checkbox.")
(defface org-checkbox-done-textt (:inherit org-done)))
'(("Face for the text part of a checked org-mode checkbox.")
(font-lock-add-keywords
'org-mode"^[ \t]*\\(?:[-+*]\\|[0-9]+[).]\\)[ \t]+\\(\\(?:\\[@\\(?:start:\\)?[0-9]+\\][ \t]*\\)?\\[\\(?: \\|\\([0-9]+\\)/\\2\\)\\][^\n]*\n\\)" 1 'org-checkbox-todo-text prepend))
`((
'append)
(font-lock-add-keywords
'org-mode"^[ \t]*\\(?:[-+*]\\|[0-9]+[).]\\)[ \t]+\\(\\(?:\\[@\\(?:start:\\)?[0-9]+\\][ \t]*\\)?\\[\\(?:X\\|\\([0-9]+\\)/\\2\\)\\][^\n]*\n\\)" 12 'org-checkbox-done-text prepend))
`((
'append)setq org-directory (expand-file-name "NextCloud/orgmode" user-documents-directory))
("B0740C4C"
(setq-default org-crypt-key "notes.org" org-directory)
org-default-notes-file (expand-file-name
org-agenda-files `(,org-directory)"…#"
org-ellipsis
org-startup-folded 'content
org-log-done 'timet
org-src-preserve-indentation t
org-log-into-drawer 0
org-tags-column t
org-startup-indented t
org-special-ctrl-a/e t
org-return-follows-link t
org-src-fontify-natively "<%Y-%m-%d>" . "<%Y-%m-%d %H:%M>")
org-time-stamp-formats '(sequence "TODO(t)"
org-todo-keywords '(("DOING(w@/!)"
"BLOCKED(b@/!)"
"SOMEDAY(s!)"
"|"
"CANCELED(c@/!)"
"REVIEW(r@/!)"
"DONE(d@/!)"))
org-todo-keyword-faces '("SOMEDAY" . (:foreground "goldenrod"))
("CANCELED" . (:foreground "#228b22" :strike-through t)))
(
org-goto-interface 'outline-path-completion10
org-goto-max-level
org-html-checkbox-type 'unicode
org-html-checkbox-types"<span class=\"task-done\">☑</span>")
'((unicode (on . "<span class=\"task-todo\">☐</span>")
(off . "<span class=\"task-in-progress\">▣</span>")))
(trans .
org-src-window-setup 'current-windowt
org-pretty-entities t
org-pretty-entities-include-sub-superscripts t
org-use-speed-commands "m" . org-mark-subtree))
org-speed-commands-user '((t
org-hide-leading-stars t
org-enforce-todo-dependencies
org-catch-invisible-edits 'show
org-log-reschedule 'time
org-log-redeadline 'note3))
org-refile-targets '((org-agenda-files :maxlevel .
org-refile-use-outline-path 'filenil
org-outline-path-complete-in-steps
org-refile-allow-creating-parent-nodes 'confirm"c" "Simple agenda view" ((tags "PRIORITY=\"A\""
org-agenda-custom-commands '((
((org-agenda-skip-function '(org-agenda-skip-entry-if 'todo 'done))"High priority unfinished tasks")))
(org-agenda-overriding-header "")
(agenda ""
(alltodo
((org-agenda-skip-functionor (air-org-skip-subtree-if-habit)
'(
(air-org-skip-subtree-if-priority ?A)"SOMEDAY")
(gpolonkai/org-skip-subtree-if-state nil '(scheduled deadline))))
(org-agenda-skip-if "ALL normal priority tasks"))))
(org-agenda-overriding-header t)))))
((org-agenda-compact-blocks
:config;; Load the markdown exporter
require 'ox-md)
(
;; Make sure we have 'org-capture-templates` defined
unless (boundp 'org-capture-templates)
(setq org-capture-templates nil))
(
;; Set up capture templates for blog posts and GT2 related notes
(add-to-list 'org-capture-templates"p" "Blog post" entry
'(lambda () (concat org-directory "blog.org")))
(file+olp+datetree ("* %^{Title} :blog:\n :PROPERTIES:\n :on: %T\n :END:\n %i%?"))
(add-to-list 'org-capture-templates"g" "GT2 note" entry
'(lambda () (concat org-directory "gt2-notes.org")) "Captures")
(file+headline ("** %^{Title}\n :PROPERTIES:\n :on: %T\n :END:\n %i%?"))
(add-to-list 'org-capture-templates"c" "Item to current Clocked Task" item
'(
(clock)"%i%?"
1))
:empty-lines
(add-to-list 'org-capture-templates"K" "Kill-ring to Current Clocked Task" plain
'(
(clock)"%c"
t
:immediate-finish 1))
:empty-lines
(add-to-list 'org-capture-templates"R" "Region to Current Clocked Task" plain
'(
(clock)"%i"
t
:immediate-finish 1))
:empty-lines
:hook
(ediff-select . f-ediff-org-unfold-tree-element)
(ediff-unselect . f-ediff-org-fold-tree)
:bind
(:map gpolonkai/pers-map"a" . gpolonkai/org-agenda-list)
("C" . org-capture)
("l" . org-store-link)
(
:map org-mode-map"SPC" . org-space-key)
("C-c l" . org-toggle-link-display)
("C-a" . gpolonkai/move-to-beginning-of-line)
("C-e" . gpolonkai/move-to-end-of-line)
("C-c h" . outline-previous-heading)
("C-c ;" . org-toggle-timestamp-type))) (
Show a random ToDo every hour
use-package org-random-todo
(
:demand
:config;; Don’t bug me too often…
setq org-random-todo-how-often 3600)
(
:bind
(:map gpolonkai/pers-map"r" . org-random-todo))) (
Citations and cross-references for Org
use-package org-ref
(
:after
org
:configsetq org-ref-bibliography-notes (concat user-documents-directory
(
(convert-standard-filename"/orgmode/bibliography-notes"))
org-ref-default-bibliography '((concat user-documents-directory
(convert-standard-filename"/orgmode/references.bib")))
org-ref-pdf-directory (concat user-documents-directory
(convert-standard-filename"/orgmode/bibtex-pdfs"))))
And set up a function to open PDF files with the system pdf viewer, using xdg-open
.
An alternative could be
(setq bibtex-completion-pdf-open-function 'org-open-file))
setq bibtex-completion-pdf-open-function
(lambda (fpath)
("xdg-open" "*open*" "open" fpath))) (start-process
Load CalDAV entries from NextCloud
use-package org-caldav
(
:after org
:configsetq
("https://cloud.polonkai.eu/remote.php/dav/calendars/gergely"
org-caldav-url "org"
org-caldav-calendar-id "cloud-calendar.org" org-directory)
org-caldav-inbox (expand-file-name nil)) org-caldav-files
Improved list management
use-package org-autolist
(
:hook (org-mode . org-autolist-mode))
Write messages with Org-mode
use-package org-msg
(
:config"html-postamble:nil H:5 num:nil ^:{} toc:nil")
(customize-set-variable 'org-msg-options "hidestars indent inlineimages")
(customize-set-variable 'org-msg-startup "\nHello,\n\n")
(customize-set-variable 'org-msg-greeting-fmt nil)
(customize-set-variable 'org-msg-greeting-fmt-mailto "
(customize-set-variable 'org-msg-signature
Best,
#+begin_signature
-- *Gergely Polonkai* \\\\
#+end_signature")
(org-msg-mode))
Git & Co.
Git status on the fringe
In graphical modes we use git-gutter-fringe
, and git-gutter
otherwise.
;; Git gutter
;; If we are in text-only mode, there is no fringe.
let ((gitgutter-package
(if (display-graphic-p)
("git-gutter-fringe"
"git-gutter")))
eval `(use-package ,gitgutter-package
(
:demand
:configt)
(global-git-gutter-mode
:bind
(:map gpolonkai/pers-map"gg" . git-gutter:update-all-windows)
("gn" . git-gutter:next-hunk)
("gp" . git-gutter:previous-hunk))))) (
Git messenger
AKA blame current line.
use-package git-messenger
(
:bind
(:map gpolonkai/pers-map"gm" . git-messenger:popup-message))) (
Git time machine
See previous versions of the current file.
use-package git-timemachine
(
:bind (([f6] . git-timemachine-toggle)))
Company & Co.
use-package company
(" 🏢"
:delight
:configsetq company-idle-delay nil
(
company-frontends '(company-pseudo-tooltip-frontend
company-echo-metadata-frontend)nil)
company-dabbrev-downcase
(put 'company-clang-arguments 'safe-local-variable #'nil-or-list-of-strings-p) (global-company-mode))
Company completion based on local C headers
use-package company-c-headers) (
Company mode in the shell
use-package company-shell) (
REST Client completion via Company
use-package company-restclient) (
Insert Emoji with Company
use-package company-emoji
(
:after
company
:initnil)
(--set-emoji-font
:config (add-to-list 'company-backends 'company-emoji))
Anaconda backend for Company
use-package company-anaconda
(
:after
company
:config (add-to-list 'company-backends 'company-anaconda))
Web mode (web-mode
and emmet-mode
, too) backend for Company
use-package company-web
(
:configrequire 'company-web-html)) (
Helm & Co.
Helm
use-package helm
(
:initrequire 'helm-config)
(setq helm-M-x-fuzzy-match t
(t
helm-buffers-fuzzy-matching t)
helm-recentf-fuzzy-match
:configt)
(helm-mode
:bind"M-x" . helm-M-x)
((
:map ctl-x-map"C-f" . helm-find-files)
("b" . helm-mini)
(
:map helm-map"/" . gpolonkai/helm-ff-slash-dir-complete))) (
Helm-style swooping
use-package helm-swoop
(
:bind"M-i" . helm-swoop))) ((
GNU Globals with Helm
defun gpolonkai/enable-helm-gtags-mode ()
(t))
(helm-gtags-mode
use-package helm-gtags
(
:initt
(setq-default helm-gtags-auto-update t
helm-gtags-ignore-case
helm-gtags-path-style 'relative)
:hook
(c-mode . gpolonkai/enable-helm-gtags-mode)
:bind
(:map helm-gtags-mode-map"M-t" . helm-gtags-find-tag)
("M-r" . helm-gtags-find-rtag)
("M-s" . helm-gtags-find-symbol)
("M-g M-p" . helm-gtags-parse-file)
("C-c <" . helm-gtags-previous-history)
("C-c >" . helm-gtags-next-history)
("M-," . helm-gtags-pop-stack))) (
Ag with Helm
use-package helm-ag
(
:bind
(:map gpolonkai/pers-map"s" . helm-do-ag))) (
Company with Helm
use-package helm-company
(
:after
company
helm
:bind
(:map company-mode-map"C-c j" . helm-company)
(
:map company-active-map"C-c j" . helm-company))) (
Projectile with Helm
use-package helm-projectile
(
:initsetq projectile-completion-system 'helm)
(
:config (helm-projectile-on))
FlyCheck with Helm
use-package helm-flycheck) (
FlySpell with Helm
use-package helm-flyspell
(
:demand
:bind
(:map flyspell-mode-map"C-M-i" . helm-flyspell-correct))) (
Search GitHub starred repos with Helm
use-package helm-github-stars
(
:init"gergelypolonkai")) (setq-default helm-github-stars-username
Smex with Helm
use-package helm-smex
(
:bind"M-S-x" . helm-smex))) ((
Describe bindings with Helm
use-package helm-descbinds) (
Describe modes with Helm
use-package helm-describe-modes) (
REST Client with Helm
use-package restclient-helm) (
C Yasnippets with Helm
use-package helm-c-yasnippet
(t
:demand
:configsetq helm-yas-space-match-any-greedy t)
(
:bind"C-c y" . helm-yas-complete))) ((
Git hunks with Helm
use-package helm-hunks) (
PyDoc with Helm
use-package helm-pydoc) (
BibTex with Helm
use-package helm-bibtex
(
:after
org
:configsetq bibtex-completion-bibliography (concat user-documents-directory
(
(convert-standard-filename"/orgmode/references.bib"))
bibtex-completion-library-path (concat user-documents-directory
(convert-standard-filename"/orgmode/bibtex-pdfs"))
bibtex-completion-notes-path (concat user-documents-directory
(convert-standard-filename"/orgmode/bibliography/helm-bibtex-notes"))
bibtex-completion-pdf-open-function 'org-open-file))
Mode specific use-package
calls
JavaScript
use-package js2-mode
(
:pin melpa-stable"\\.js\\'") :mode
TypeScript
use-package typescript-mode
("\\.ts\\'") :mode
CoffeeScript
use-package coffee-mode
("\\.coffee\\'") :mode
JSON
use-package json-mode
("\\.json\\'") :mode
YAML
use-package yaml-mode
("\\.yml\\'" . yaml-mode)
:mode (("\\.yaml\\'" . yaml-mode))
(
:init"\\.yml\\'" . yaml-mode))) (add-to-list 'auto-mode-alist '(
Markdown
use-package markdown-mode
("\\.md\\'" . markdown-mode)
:mode (("\\.markdown\\'" . markdown-mode))) (
Less
use-package less-css-mode
("\\.less\\'") :mode
Sass
use-package sass-mode
("\\.sass\\'") :mode
Vala
use-package vala-mode
("\\.vala\\'") :mode
Dockerfile
use-package dockerfile-mode) (
.gitconfig
use-package gitconfig-mode) (
.gitignore
use-package gitignore-mode) (
po-mode
use-package po-mode
("\\.po\\'") :mode
C#
use-package csharp-mode
("\\.cs\\'") :mode
Gherkin (BDD) feature files
use-package feature-mode
("\\.feature\\'") :mode
PlantUML
Before using this, make sure the latest PlantUML JAR file is downloaded into the downloads directory. It is available from here.
use-package plantuml-mode
(
:initsetq plantuml-jar-path
(
(expand-file-name;; Make sure we have a download location even if XDG is not working
cond
("DOWNLOAD")
((xdg-user-dir "DOWNLOAD") "/plantuml.jar"))
(concat (xdg-user-dir t
("~/Downloads/plantuml.jar"))))
(defvaralias 'org-plantuml-jar-path 'plantuml-jar-path)
:config
(org-babel-do-load-languages
'org-babel-load-languagest)))) '((plantuml .
For editing CSV files
use-package csv-mode
("\\.csv\\'") :mode
The Go programming language
use-package go-mode
("\\.go\\'") :mode
Meson build system
use-package meson-mode
("\\.meson\\'") :mode
Games
Gnu Go
use-package gnugo) (
Last, but not least, key bindings!
(bind-keys
:map global-map"M-(" . æ-enclose-region)
("<C-return>" . open-line-below)
("<C-S-return>" . open-line-above)
("M-t" . nil) ;; Remove the old keybinding
("M-t c" . transpose-chars)
("M-t w" . transpose-words)
("M-t l" . transpose-lines)
("M-t e" . transpose-sexps)
("M-t s" . transpose-sentences)
("M-t p" . transpose-paragraphs)
("M-t W" . transpose-windows)
("C-a" . gpolonkai/move-to-beginning-of-line)
("C-e" . gpolonkai/move-to-end-of-line)
("M-q" . sachachua/fill-or-unfill-paragraph)
("C-c r" . round-number-at-point-to-decimals)
("C-s" . isearch-forward-regexp)
("C-r" . isearch-backward-regexp)
("C-M-s" . isearch-forward)
("C-M-r" . isearch-backward)
("C-~" . toggle-char-case)
(
:map ctl-x-map"C-y" . gpolonkai/duplicate-line)
("_" . maximize-window)
("C-r" . rename-current-buffer-file)
("C-d" . delete-current-buffer-file)
("|" . toggle-window-split)
("k" . kill-this-buffer)
("M-k" . gpolonkai/undo-buffer-kill)
("C-b" . bury-buffer)
("/" . repeat)
(
:map isearch-mode-map"<C-return>" . isearch-exit-other-end)
("<S-return>" . isearch-exit-mark-match)
(
:map gpolonkai/pers-map"h" . hidden-mode-line-mode)
("C-i e" . "gergely@polonkai.eu")
("C-i w" . "http://gergely.polonkai.eu/")
("C-p" . package-list-packages)
("o i" . gpolonkai/visit-init-file)
("o o" . gpolonkai/visit-org-index)
("u" . browse-url-at-point)
("M-C" . clean-buffer-list)
("C-c" . calc)
("c i" . org-clock-in)
("c I" . org-clock-in-last)
("c o" . org-clock-out)
("c g" . org-clock-goto)) (
TODO These fail to work using bind-keys
, but why?
"C-l") 'find-library)
(define-key 'help-command (kbd "C-f") 'find-function)
(define-key 'help-command (kbd "C-k") 'find-function-on-key)
(define-key 'help-command (kbd "C-v") 'find-variable) (define-key 'help-command (kbd
And finally, server mode
Sometimes i start an emacsclient
process, like for editing a commit message or something similar. As my startup time is pretty long, waiting for everything to complete is undesirable.
require 'server)
(unless (server-running-p)
( (server-start))