* Emacs configuration
** Configure ~use-package~ and preload ~bind-key~
#+BEGIN_SRC emacs-lisp
(unless (package-installed-p 'use-package)
(package-refresh-contents)
(package-install 'use-package))
(setq use-package-always-ensure t
use-package-verbose t)
(require 'use-package)
(use-package bind-key)
#+END_SRC
** Set up my personal keymap
I set it up early so I can use it in ~use-package~ calls immediately.
#+BEGIN_SRC emacs-lisp
(defvar gpolonkai/pers-map (make-sparse-keymap)
"My own, personal, keymap!")
(define-prefix-command 'gpolonkai/pers-map)
(define-key ctl-x-map "t" 'gpolonkai/pers-map)
(define-key global-map (kbd "C-t") 'gpolonkai/pers-map)
#+END_SRC
** I really don’t want to type more than I really must…
#+BEGIN_SRC emacs-lisp
(defalias 'yes-or-no-p 'y-or-n-p)
#+END_SRC
** Set UTF-8 as the default encoding
Just to make sure, although most Linux DE does this for me.
#+BEGIN_SRC emacs-lisp
(set-language-environment "UTF-8")
(set-default-coding-systems 'utf-8)
#+END_SRC
* Set personal information
** Who am I?
#+BEGIN_SRC emacs-lisp
(setq user-full-name "Gergely Polonkai"
user-mail-address "gergely@polonkai.eu")
#+END_SRC
* Add ~lisp/~ to ~load-path~
#+BEGIN_SRC emacs-lisp
(add-to-list 'load-path (expand-file-name
(convert-standard-filename "lisp/")
user-emacs-directory))
(add-to-list 'load-path (expand-file-name
(convert-standard-filename "lisp/nyan-prompt")
user-emacs-directory))
#+END_SRC
** Load ~xdg-paths~
#+BEGIN_SRC emacs-lisp
(load "xdg-paths")
#+END_SRC
* Custom commands and functions
** Utility functions
*** Check if something is ~nil~ or a list of strings
#+BEGIN_SRC emacs-lisp
(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))))))
#+END_SRC
*** Get the number at point
#+BEGIN_SRC emacs-lisp
(defun get-number-at-point ()
(interactive)
(skip-chars-backward "0123456789.-")
(or (looking-at "[0123456789.-]+")
(error "No number at point"))
(string-to-number (match-string 0)))
#+END_SRC
*** Round number at point to the given decimals
#+BEGIN_SRC emacs-lisp
(defun round-number-at-point-to-decimals (decimal-count)
(interactive "NDecimal count: ")
(let ((mult (expt 10 decimal-count)))
(replace-match (number-to-string
(/
(fround
(*
mult
(get-number-at-point)))
mult)))))
#+END_SRC
*** Make a backup filename under ~user-emacs-cache-directory~
Taken from [[http://ergoemacs.org/emacs/emacs_set_backup_into_a_directory.html][Xah’s site]].
#+BEGIN_SRC emacs-lisp
(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))
(file-path (replace-regexp-in-string "[A-Za-z]:" "" fpath))
(backup-file-path (replace-regexp-in-string "//" "/" (concat backup-root-dir file-path "~"))))
(make-directory (file-name-directory backup-file-path) (file-name-directory backup-file-path))
backup-file-path))
#+END_SRC
** Check if we are running under Termux
We need to do things differently, if so.
#+BEGIN_SRC emacs-lisp
(defun termux-p ()
"Check if Emacs is running under Termux."
(string-match-p
(regexp-quote "/com.termux/")
(expand-file-name "~")))
#+END_SRC
** Misc text manipulation functions
*** Delete the current line
#+BEGIN_SRC emacs-lisp
(defun gpolonkai/delete-current-line ()
"Kill the whole line on which point is."
(interactive)
(beginning-of-line)
(kill-line 1))
#+END_SRC
*** Duplicate current line
#+BEGIN_SRC emacs-lisp
(defun gpolonkai/duplicate-line()
"Duplicate line at point."
(interactive)
(save-excursion
(move-beginning-of-line 1)
(kill-line)
(yank)
(open-line 1)
(forward-line 1)
(yank)))
#+END_SRC
*** Toggle case of character at point
Based on [[http://ergoemacs.org/emacs/modernization_upcase-word.html][Xah’s toggle letter case defun version 2015-12-22]]
#+BEGIN_SRC emacs-lisp
(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."
(interactive "P")
(let ((case-fold-search nil))
(cond
((looking-at "[[:lower:]]") (upcase-region (point) (1+ (point))))
((looking-at "[[:upper:]]") (downcase-region (point) (1+ (point)))))
(cond
(arg-move-point (right-char)))))
#+END_SRC
*** Open a new line below
Copied from http://whattheemacsd.com/editing-defuns.el-01.html
#+BEGIN_SRC emacs-lisp
(defun open-line-below ()
"Open a new line below point."
(interactive)
(end-of-line)
(newline)
(indent-for-tab-command))
#+END_SRC
*** Open a new line above
#+BEGIN_SRC emacs-lisp
(defun open-line-above ()
"Open a new line above point."
(interactive)
(beginning-of-line)
(newline)
(forward-line -1)
(indent-for-tab-command))
#+END_SRC
*** TODO Kill or copy the whole line
Got from Xah’s site (TODO is for adding a link here.)
#+BEGIN_SRC emacs-lisp
(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."
(interactive "P")
(if kill
(kill-whole-line)
(let ((beginning (progn (beginning-of-line) (point)))
(end (progn (end-of-line) (point))))
(copy-region-as-kill beginning end))))
#+END_SRC
*** Enclose region in a specific character
#+BEGIN_SRC emacs-lisp
(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."
(interactive "cWhat character? \nr")
(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)
(insert-char close)
(goto-char start)
(insert-char open))
(unless (use-region-p)
(forward-char)))
#+END_SRC
*** Convert camelCase to snake_case
#+BEGIN_SRC emacs-lisp
(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."
(interactive "p")
(progn
(let ((start (region-beginning))
(end (region-end))
(case-fold-search nil)
(had-initial-underscore nil))
(goto-char start)
(when (looking-at "_") (setq had-initial-underscore t))
(while (re-search-forward "\\([A-Z]\\)" end t)
(replace-match "_\\1")
(setq end (1+ end)))
(if arg
(upcase-region start end)
(downcase-region start end))
(goto-char start)
(unless had-initial-underscore (delete-char 1)))))
#+END_SRC
*** Insert two spaces after specific characters
#+BEGIN_SRC emacs-lisp
(defun org-space-key (&optional arg)
"Insert two spaces after a period.
ARG will be passed down verbatim to `self-insert-command'"
(interactive "p")
(when (looking-back "[.!?…]" nil)
(call-interactively 'self-insert-command arg))
(call-interactively 'self-insert-command arg))
#+END_SRC
*** Fill or unfill a paragraph
From http://pages.sachachua.com/.emacs.d/Sacha.html
#+BEGIN_SRC emacs-lisp
(defun sachachua/fill-or-unfill-paragraph (&optional unfill region)
"Fill (or unfill, if UNFILL is non-nil) paragraph (or REGION)."
(interactive (progn
(barf-if-buffer-read-only)
(list (if current-prefix-arg 'unfill) t)))
(let ((fill-column (if unfill (point-max) fill-column)))
(fill-paragraph nil region)))
#+END_SRC
*** Swap occurences of strings
Copied from http://emacs.stackexchange.com/a/27170/507
#+BEGIN_SRC emacs-lisp
(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'."
(interactive
(let ((common
(query-replace-read-args
(concat "Query swap"
(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
(concat "\\(" (regexp-quote from-string) "\\)\\|" (regexp-quote to-string))
`(replace-eval-replacement replace-quote
(if (match-string 1)
,to-string
,from-string))
t t delimited nil nil start end))
#+END_SRC
** Navigation
*** Move to different beginnings of the current line
Inspired by Bozhidar Batsov's [[http://emacsredux.com/blog/2013/05/22/smarter-navigation-to-the-beginning-of-a-line/][solution]].
#+BEGIN_SRC emacs-lisp
(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))))
#+END_SRC
*** Move to the different ends of the current line
#+BEGIN_SRC emacs-lisp
(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))))
#+END_SRC
** File manipulation
*** Rename the current file
Copied from http://whattheemacsd.com/file-defuns.el-01.html
#+BEGIN_SRC emacs-lisp
(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…
(set-buffer-modified-p nil)
(message "File '%s' successfully renamed to '%s'"
name (file-name-nondirectory new-name)))))))
#+END_SRC
*** Delete the current file
Copied from http://whattheemacsd.com/file-defuns.el-02.html
#+BEGIN_SRC emacs-lisp
(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)
(message "File '%s' successfully removed" filename)))))
#+END_SRC
*** Allow reopening the previously closed file
#+BEGIN_SRC emacs-lisp
(defvar gpolonkai/last-killed-buffer-file-name
nil
"The last killed buffer.
Used by `gpolonkai/kill-this-buffer' and `gpolonkai/undo-buffer-kill'.")
(defun gpolonkai/kill-this-buffer ()
"Kill the current buffer, but save the buffer file name so it can be undone."
(interactive)
(setq gpolonkai/last-killed-buffer-file-name (buffer-file-name))
(kill-this-buffer))
(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))
(message "The buffer last killed didn’t visit a file.")))
#+END_SRC
*** Open this file as another user
#+BEGIN_SRC emacs-lisp
(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."
(interactive "sEdit as user (default: root): ")
(when (string= "" user)
(setq user "root"))
(let* ((filename (or buffer-file-name
(read-file-name (format "Find file (as %s): "
user))))
(tramp-path (concat (format "/sudo:%s@localhost:" user) filename)))
(if buffer-file-name
(find-alternate-file tramp-path)
(find-file tramp-path))))
#+END_SRC
*** Open my own ~init.el~
#+BEGIN_SRC emacs-lisp
(defun gpolonkai/visit-init-file ()
"Open the init file."
(interactive)
(find-file-other-window (expand-file-name "configuration.org" user-emacs-directory)))
#+END_SRC
*** Open my Org-mode index file
#+BEGIN_SRC emacs-lisp
(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")))
#+END_SRC
** Frame manipulation
*** Hidden modeline mode
To temporarily hide the mode line.
Copied from http://emacs-doctor.com/emacs-strip-tease.html
#+BEGIN_SRC emacs-lisp
(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."
:init-value nil
:global nil
:variable hidden-mode-line-mode
:group 'editing-basics
(if hidden-mode-line-mode
(setq hide-mode-line mode-line-format
mode-line-format nil)
(setq mode-line-format hide-mode-line
hide-mode-line nil))
(force-mode-line-update)
(redraw-display)
(when (and (called-interactively-p 'interactive)
hidden-mode-line-mode)
(run-with-idle-timer
0 nil 'message
(concat "Hidden Mode Line Mode enabled. "
"Use M-x hidden-mode-line-mode to make mode-line appear."))))
#+END_SRC
** Window manipulation
*** Transpose windows
#+BEGIN_SRC emacs-lisp
(defun transpose-windows (arg)
"Transpose the buffers shown in two windows."
(interactive "p")
(let ((selector (if (>= arg 0) 'next-window 'previous-window)))
(while (/= arg 0)
(let ((this-win (window-buffer))
(next-win (window-buffer (funcall selector))))
(set-window-buffer (selected-window) next-win)
(set-window-buffer (funcall selector) this-win)
(select-window (funcall selector)))
(setq arg (if (plusp arg) (1- arg) (1+ arg))))))
#+END_SRC
*** Toggle window split between horizontal and vertical
#+BEGIN_SRC emacs-lisp
(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)))
(this-win-2nd (not (and (<= (car this-win-edges)
(car next-win-edges))
(<= (cadr this-win-edges)
(cadr next-win-edges)))))
(splitter
(if (= (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!")))
#+END_SRC
*** Scroll up or down in a specific window
#+BEGIN_SRC emacs-lisp
(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)))
#+END_SRC
*** Bury a window
#+BEGIN_SRC emacs-lisp
(defun gpolonkai/bury-window (window)
"Quit WINDOW without killing it."
(interactive)
(quit-window nil window))
#+END_SRC
*** Kill current buffer and delete its window
#+BEGIN_SRC emacs-lisp
(defun gpolonkai/kill-this-buffer-delete-this-window ()
"Kill the buffer in the current window, and then try to delete
the current window."
(interactive)
(kill-this-buffer)
(delete-window))
#+END_SRC
** ~c-mode~ related
*** Copy the prototype of the current function
#+BEGIN_SRC emacs-lisp
(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)))))
#+END_SRC
** Programming related
*** Check if we are inside a string
#+BEGIN_SRC emacs-lisp
(defun gpolonkai/prog-in-string-p ()
"Return t if point is inside a string."
(nth 3 (syntax-ppss)))
#+END_SRC
*** Check if we are inside a comment
#+BEGIN_SRC emacs-lisp
(defun gpolonkai/prog-in-comment-p ()
"Return t if point is inside a comment."
(nth 4 (syntax-ppss)))
#+END_SRC
** ~python-mode~ related
*** Add a docstring to the current thing
…be it a function, class, or a module
#+BEGIN_SRC emacs-lisp
(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 ":")
(while (or (gpolonkai/prog-in-string-p)
(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)))
#+END_SRC
** EShell related
*** Delete a character, or close ~eshell~ if nothing to delet
Copied from https://ryuslash.org/posts/C-d-to-close-eshell.html
#+BEGIN_SRC emacs-lisp
(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)
(looking-back eshell-prompt-regexp nil))
(kill-buffer)
(signal (car err) (cdr err))))))
#+END_SRC
** ~idm~ (ID manager) related functions
*** Get specific fields from a record in ~idm~
#+BEGIN_SRC emacs-lisp
(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))
(lookup-record nil))
(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))
#+END_SRC
** Automatically zone out after 60 seconds
#+BEGIN_SRC emacs-lisp
(defun gpolonkai/zone-enable ()
"Enable zoning out."
(interactive)
(zone-when-idle 60)
(message "I will zone out after idling for 60 seconds."))
#+END_SRC
** Utility functions for editing Zim wiki files
#+BEGIN_SRC emacs-lisp
(defun zim-timestamp ()
(with-temp-buffer
(insert (format-time-string "%Y-%m-%dT%H:%M:%S%z"))
(forward-char -2)
(insert ":")
(buffer-string)))
(defun insert-zim-timestamp ()
(interactive)
(insert (zim-timestamp)))
(defun insert-zim-header ()
(interactive)
(save-excursion
(goto-char (point-min))
(insert
(concat "Content-Type: text/x-zim-wiki\n"
"Wiki-Format: zim 0.4\n"
"Creation-Date: " (zim-timestamp) "\n\n"))))
#+END_SRC
** Utility functions for EDiff
EDiff and Org-mode files don’t play nice together
From [[http://article.gmane.org/gmane.emacs.orgmode/75222][gmane.emacs.orgmode]]
#+BEGIN_SRC emacs-lisp
(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."
(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 1))
#+END_SRC
** Leave ~isearch~ at the other end of the matched string
Taken from [[http://endlessparentheses.com/leave-the-cursor-at-start-of-match-after-isearch.html][endless parentheses]]
#+BEGIN_SRC emacs-lisp
(defun isearch-exit-other-end ()
"Exit isearch, at the opposite end of the string."
(interactive)
(isearch-exit)
(goto-char isearch-other-end))
#+END_SRC
** Mark the current match after leaving ~isearch~
Taken from [[http://emacs.stackexchange.com/a/31321/507][here]].
#+BEGIN_SRC emacs-lisp
(defun isearch-exit-mark-match ()
"Exit isearch and mark the current match."
(interactive)
(isearch-exit)
(push-mark isearch-other-end)
(activate-mark))
#+END_SRC
** Make the slash (~/~) key act like ~C-j~ in some Helm views
#+BEGIN_SRC emacs-lisp
(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))))
(stringp (helm-get-selection))
(file-directory-p (helm-get-selection)))
(helm-execute-persistent-action)
(insert "/")))
#+END_SRC
** Turn the cursor to purple if Yasnippet’s TAB function would fire
Taken from [[http://pages.sachachua.com/.emacs.d/Sacha.html][Sacha Chua’s config]].
#+BEGIN_SRC emacs-lisp
;; 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)
(set-cursor-color (if (sachachua/can-expand)
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)))
#+END_SRC
* 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.
#+BEGIN_SRC emacs-lisp
(tool-bar-mode 0)
(menu-bar-mode 0)
(when window-system
(scroll-bar-mode -1))
(set-frame-parameter nil 'fullscreen 'maximized)
#+END_SRC
** Set the default font and configure font resizing
Before this can be used, make sure the [[https://zhm.github.io/symbola/][Symbola]] font is installed.
#+BEGIN_SRC emacs-lisp
(set-face-attribute 'default t :font "Hack-10")
(set-frame-font "Hack-10" nil t)
(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
(set-fontset-font t 'symbol
(font-spec :family "Apple Color Emoji")
frame 'prepend)
;; For Linux
(set-fontset-font t 'symbol
(font-spec :family "Symbola")
frame 'prepend))))
#+END_SRC
* Set up global minor modes provided by Emacs
** Pretty lambdas
Because we can.
#+BEGIN_SRC emacs-lisp
(global-prettify-symbols-mode t)
#+END_SRC
And set up all the pretty symbols.
#+BEGIN_SRC emacs-lisp
;; 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")))))
#+END_SRC
** Treat soft line breaks as hard ones in textual modes
#+BEGIN_SRC emacs-lisp
;; text-mode settings
(add-hook 'text-mode-hook (lambda () (visual-line-mode t)))
#+END_SRC
* Enable disabled commands
Because I’m a rock star like that.
#+BEGIN_SRC emacs-lisp
(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)
#+END_SRC
* Load some built-in libraries
** ~thingatpt~
#+BEGIN_SRC emacs-lisp
(use-package thingatpt
:ensure nil)
#+END_SRC
** Calendar
#+BEGIN_SRC emacs-lisp
(use-package calendar
:ensure nil
:init
(setq calendar-week-start-day 1
calendar-latitude 47.4
calendar-longitude 19.0
calendar-location-name "Budapest, Hungary"
calendar-time-zone 60
calendar-standard-time-zone-name "CET"
calendar-daylight-time-zone-name "CEST"))
#+END_SRC
*** Add the SysAdmin day to the calendar
Because I’m a sysadmin, too.
#+BEGIN_SRC emacs-lisp
(add-to-list 'holiday-other-holidays '(holiday-float 7 5 -1 "SysAdmin Day") t)
(add-to-list 'holiday-other-holidays '(holiday-fixed 10 21 "Reptile Awareness Day") t)
#+END_SRC
** nXML
#+BEGIN_SRC emacs-lisp
(use-package nxml-mode
:ensure nil
:config
(setq nxml-attribute-indent 4
nxml-child-indent 2
nxml-outline-child-indent 4))
#+END_SRC
** ~recentf~
#+BEGIN_SRC emacs-lisp
(use-package recentf
:ensure nil
:config
(run-at-time nil (* 5 60) 'recentf-save-list)
(add-to-list 'recentf-exclude (concat user-emacs-directory "elpa")))
#+END_SRC
** ~files~
#+BEGIN_SRC emacs-lisp
(use-package files
:ensure nil
:config
(setq make-backup-file-name-function 'xah/backup-file-name))
#+END_SRC
** ~whitespace~
~whitespace-mode~ is turned on by default, and can be toggled with ~F10~.
#+BEGIN_SRC emacs-lisp
(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)
(global-whitespace-mode 1)
(setq whitespace-line-column 100)
:bind
(([f10] . whitespace-mode)
([(shift f10)] . global-whitespace-mode)
:map gpolonkai/pers-map
("w" . whitespace-cleanup)))
#+END_SRC
** ~eshell~
#+BEGIN_SRC emacs-lisp
(use-package eshell
:config
(add-hook 'eshell-mode-hook
(lambda () (local-set-key (kbd "C-d") #'eshell-C-d)))
:bind
(:map gpolonkai/pers-map
("e" . eshell)))
#+END_SRC
** ~saveplace~
#+BEGIN_SRC emacs-lisp
;; Save place
(use-package saveplace
:config'
(if (version< emacs-version "25.0")
(setq-default save-place t)
(save-place-mode 1))
(setq save-place-file (expand-file-name ".places" user-emacs-directory)))
#+END_SRC
** ID manager
Manage credentials, AKA password manager.
#+BEGIN_SRC emacs-lisp
(use-package id-manager
:config
(setq idm-database-file (expand-file-name "idm-db.gpg" user-emacs-directory))
:bind
(:map gpolonkai/pers-map
("i" . idm-open-list-command)))
#+END_SRC
** EDiff
#+BEGIN_SRC emacs-lisp
(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))
#+END_SRC
** Automatically revert changed files
…unless they are modified, of course.
#+BEGIN_SRC emacs-lisp
(use-package autorevert
:config
(global-auto-revert-mode 1))
#+END_SRC
** Eww
For in-Emacs browsing needs.
#+BEGIN_SRC emacs-lisp
(use-package eww
:config
(setq eww-search-prefix "https://www.google.com/?q="))
#+END_SRC
** Electric indent mode
#+BEGIN_SRC emacs-lisp
(use-package electric
:config
;; This seems to be the default, but let’s make sure…
(electric-indent-mode 1))
#+END_SRC
** Save history
#+BEGIN_SRC emacs-lisp
(use-package savehist
:config
(savehist-mode 1))
#+END_SRC
** Web jump
#+BEGIN_SRC emacs-lisp
(use-package webjump
:bind
(:map gpolonkai/pers-map
("j" . webjump)))
#+END_SRC
** Which function am I in?
#+BEGIN_SRC emacs-lisp
(use-package which-func
:config
(add-hook 'prog-mode-hook
(lambda ()
(if (fboundp 'which-function-mode)
(which-function-mode)
(which-func-mode))))
(setq which-func-unknown "∅"))
#+END_SRC
** Fortune cookies
The cookies are from the Hungarian version an ancient MS-DOS based program called ~TAGLINE~.
#+BEGIN_SRC emacs-lisp
(use-package cookie1
:demand t
:config
(setq cookie-file (concat user-emacs-directory "fortune-cookies.txt"))
:bind
(:map gpolonkai/pers-map
("k" . cookie)))
#+END_SRC
** News reader
#+BEGIN_SRC emacs-lisp
(use-package newsticker
:demand
:config
(setq 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)))
#+END_SRC
** Browse URL functionality in Termux
#+BEGIN_SRC emacs-lisp
(when (termux-p)
(use-package browse-url
:ensure nil
:config
(advice-add 'browse-url-default-browser :override
(lambda (url &rest args)
(start-process-shell-command
"open-url"
nil
(concat "am start -a android.intent.action.VIEW --user 0 -d "
url))))))
#+END_SRC
** Dired customisation
#+BEGIN_SRC emacs-lisp
(use-package dired
:ensure nil
:config
(setq dired-dwim-target t)
:bind
(:map dired-mode-map
("RET" . dired-find-alternate-file)
("^" . (lambda () (interactive) (find-alternate-file "..")))))
(use-package dired-x
:ensure nil)
#+END_SRC
* ~use-package~ packages
** Automatically upgrade packages every week
#+BEGIN_SRC emacs-lisp
(use-package auto-package-update
:config
(setq auto-package-update-interval 7
auto-package-update-delete-old-versions t)
;; Let’s do this in after-init-hook, as use-package invocations may modify
;; the list of installed packages
(add-hook 'after-init-hook 'auto-package-update-maybe))
#+END_SRC
** Nyanyanyanyanya
*** Nyan-cat style position marker
#+BEGIN_SRC emacs-lisp
(use-package nyan-mode
:init
(setq-default nyan-animate-nyancat t
nyan-wavy-trail t)
:config
(nyan-mode t))
#+END_SRC
*** Nyan prompt in EShell
#+BEGIN_SRC emacs-lisp
(when (display-graphic-p)
(use-package nyan-prompt
:ensure nil
:config
(add-hook 'eshell-load-hook 'nyan-prompt-enable)))
#+END_SRC
*** Zone out with Nyancat
Unfortunately, this works only in a graphical mode.
#+BEGIN_SRC emacs-lisp
(when (display-graphic-p)
(use-package zone-nyan
:after
zone
:config
(setq-default zone-nyan-hide-progress t)
(setq zone-programs (vconcat zone-programs [zone-nyan]))))
#+END_SRC
** Eye candy
*** Smart mode-line
#+BEGIN_SRC emacs-lisp
(use-package smart-mode-line
:after
org
:config
(add-to-list 'sml/replacer-regexp-list
'("^~/Projects/" ":Proj:")
t)
(add-to-list 'sml/replacer-regexp-list
'("^~/Projektek/" ":Proj:")
t)
(add-to-list 'sml/replacer-regexp-list
(list (concat "^" (regexp-quote user-documents-directory))
":Doc:")
t)
(add-to-list 'sml/replacer-regexp-list
'("^:Proj:jekyll/gergelypolonkai.github.io/" ":Blog:")
t)
(add-to-list 'sml/replacer-regexp-list
(list "^:Proj:python/" ":Proj:Py:")
t)
(sml/setup)
(require 'cl-lib)
(setq-default header-line-format
'(""
mode-line-mule-info
mode-line-client
mode-line-modified
mode-line-remote
mode-line-frame-identification
mode-line-buffer-identification
sml/pos-id-separator
(vc-mode vc-mode)
mode-line-position))
(delete '(vc-mode vc-mode) mode-line-format)
(delete 'mode-line-frame-identification mode-line-format)
(delete 'mode-line-buffer-identification mode-line-format)
(delete 'mode-line-position mode-line-format)
(delete 'mode-line-mule-info mode-line-format)
(delete 'mode-line-modified mode-line-format)
(delete 'mode-line-client mode-line-format)
(delete 'mode-line-remote mode-line-format)
;; Add sml/pre-id-separator after mode-line-front-space
(let* ((front-space-position (1+ (cl-position 'mode-line-front-space mode-line-format)))
(mode-line-rest (nthcdr front-space-position mode-line-format))
(mode-line-beg (cl-subseq mode-line-format 0 front-space-position)))
(setq-default mode-line-format (nconc mode-line-beg
(list sml/pre-id-separator)
mode-line-rest))))
#+END_SRC
*** Powerline theme for ~smart-mode-line~
#+BEGIN_SRC emacs-lisp
(use-package smart-mode-line-powerline-theme
:init
(setq-default sml/theme 'powerline))
#+END_SRC
*** Spinner, e.g. to display running background tasks
#+BEGIN_SRC emacs-lisp
(use-package spinner)
#+END_SRC
*** Beacon
Highlight point. Sometimes it’s not easy to see.
#+BEGIN_SRC emacs-lisp
(use-package beacon
:demand
:config
(beacon-mode 1)
:bind
(:map gpolonkai/pers-map
("b" . beacon-blink)))
#+END_SRC
*** Display the status of the last command in the fringe of EShell
#+BEGIN_SRC emacs-lisp
(when (display-graphic-p)
(use-package eshell-fringe-status
:config
(add-hook 'eshell-mode-hook 'eshell-fringe-status-mode)))
#+END_SRC
*** Extras for the EShell prompt
#+BEGIN_SRC emacs-lisp
(use-package eshell-prompt-extras
:config
(with-eval-after-load "esh-opt"
(autoload 'epe-theme-lambda "eshell-prompt-extras")
(setq eshell-highlight-prompt nil
eshell-prompt-function 'epe-theme-lambda)))
#+END_SRC
*** Show form feeds as a horizontal line
#+BEGIN_SRC emacs-lisp
(use-package form-feed
:config
(add-hook 'emacs-lisp-mode-hook 'form-feed-mode))
#+END_SRC
** Highlight the current line
#+BEGIN_SRC emacs-lisp
(use-package hl-line
:config
(when window-system
(global-hl-line-mode)))
#+END_SRC
** Hide certain modes from the mode line
#+BEGIN_SRC emacs-lisp
(use-package diminish
:defer t)
#+END_SRC
** GNU Globals
#+BEGIN_SRC emacs-lisp
(use-package ggtags
:config
(add-hook 'c-mode-hook
(lambda ()
(ggtags-mode t)))
(add-hook 'c-mode-common-hook
(lambda ()
(when (derived-mode-p 'c-mode 'c++-mode 'java-mode)
(ggtags-mode t)))))
#+END_SRC
** Multiple cursors
Because one is never enough.
#+BEGIN_SRC emacs-lisp
(use-package multiple-cursors
:init
(defvar gpolonkai/mc-prefix-map (make-sparse-keymap)
"Prefix keymap for multiple-cursors")
(define-prefix-command 'gpolonkai/mc-prefix-map)
(define-key global-map (kbd "C-c m") 'gpolonkai/mc-prefix-map)
:config
(add-hook 'multiple-cursors-mode-enabled-hook
(lambda ()
(setq blink-matching-paren nil)))
(add-hook 'multiple-cursors-mode-disabled-hook
(lambda ()
(setq blink-matching-paren t)))
: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)))
#+END_SRC
*** Incremental search for multiple cursors
#+BEGIN_SRC emacs-lisp
(use-package phi-search)
(use-package phi-search-mc
:config
(phi-search-mc/setup-keys))
#+END_SRC
*** Some extras
#+BEGIN_SRC emacs-lisp
(use-package mc-extras
:demand
:bind
(:map mc/keymap
("C-c m =" . mc/compare-chars)))
#+END_SRC
*** Add extra cursors via ~ace-jump~
#+BEGIN_SRC emacs-lisp
(use-package ace-mc
:bind
(:map gpolonkai/mc-prefix-map
("SPC" . ace-mc-add-multiple-cursors)))
#+END_SRC
** Magit
#+BEGIN_SRC emacs-lisp
(use-package magit
:init
(setq magit-auto-revert-mode nil
magit-last-seen-setup-instructions "1.4.0"
magit-push-always-verify nil)
:bind
(:map ctl-x-map
("g" . magit-status)))
#+END_SRC
I also want FlySpell to be enabled during Git commit message editing.
#+BEGIN_SRC emacs-lisp
(add-hook 'git-commit-mode-hook 'turn-on-flyspell)
#+END_SRC
** Zone
#+BEGIN_SRC emacs-lisp
(use-package zone
:demand
:config
(zone-when-idle 60)
:bind
(:map gpolonkai/pers-map
("zi" . gpolonkai/zone-enable)
("zq" . zone-leave-me-alone)))
#+END_SRC
** Origami
#+BEGIN_SRC emacs-lisp
(use-package origami
:demand
:config
(define-prefix-command 'origami-mode-map)
(define-key ctl-x-map (kbd "z") 'origami-mode-map)
(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)))
#+END_SRC
** Smart parens
#+BEGIN_SRC emacs-lisp
(use-package smartparens
:demand
:config
(show-smartparens-global-mode t)
(add-hook 'prog-mode-hook
'turn-on-smartparens-strict-mode)
(add-hook 'markdown-mode-hook
'turn-on-smartparens-strict-mode)
:bind
(([f9] . smartparens-strict-mode)
("C-c s u" . sp-unwrap-sexp)
("C-c s k" . sp-kill-sexp)))
#+END_SRC
** Projectile
#+BEGIN_SRC emacs-lisp
(use-package projectile
:pin melpa-stable
:config
(projectile-global-mode t))
#+END_SRC
*** Repository-based ToDo management with Org mode
#+BEGIN_SRC emacs-lisp
(use-package org-projectile)
#+END_SRC
** Drag stuff
To move lines around.
#+BEGIN_SRC emacs-lisp
(use-package drag-stuff
:config
(drag-stuff-global-mode t)
(drag-stuff-define-keys))
#+END_SRC
** Ace window
Besides its standard functionality, I also make add key bindings for burying or scrolling another
window.
#+BEGIN_SRC emacs-lisp
(use-package ace-window
:config
(setq aw-background nil
aw-dispatch-always t)
(add-to-list 'aw-dispatch-alist
'(?s gpolonkai/scroll-window-up " Scroll window up")
t)
(add-to-list 'aw-dispatch-alist
'(?S gpolonkai/scroll-window-down " Scroll window down")
t)
(add-to-list 'aw-dispatch-alist
'(?q gpolonkai/bury-window " Bury (quit) window")
t)
:bind
(:map ctl-x-map
("o" . ace-window)))
#+END_SRC
** Avy
#+BEGIN_SRC emacs-lisp
(use-package avy
:demand
:config
(avy-setup-default)
:bind
(("M-g c" . avy-goto-char)
("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)))
#+END_SRC
** Focus mode
It is similar to narrow mode, except the narrowing part; it dims everything outside of the current
context.
#+BEGIN_SRC emacs-lisp
(use-package focus
:bind
(([f8] . focus-mode)))
#+END_SRC
** Command logging mode
For occasional screen casting recordings.
#+BEGIN_SRC emacs-lisp
(use-package command-log-mode)
#+END_SRC
** Emamux
For controlling tmux from within Emacs.
#+BEGIN_SRC emacs-lisp
(use-package emamux)
#+END_SRC
** Use StackExchange sites in an Emacs window
#+BEGIN_SRC emacs-lisp
(use-package sx
:demand
:bind
(:map gpolonkai/pers-map
("qi" . sx-inbox)
("qs" . sx-search)))
#+END_SRC
** Goto last change
#+BEGIN_SRC emacs-lisp
(use-package goto-last-change
:bind
(("M-g /" . goto-last-change)))
#+END_SRC
** Rainbow mode
To highlight colours based on their name or hex code.
#+BEGIN_SRC emacs-lisp
(use-package rainbow-mode
:config
(add-hook 'css-mode-hook 'rainbow-mode)
(add-hook 'scss-mode-hook 'rainbow-mode)
(add-hook 'sass-mode 'rainbow-mode))
#+END_SRC
** 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.
#+BEGIN_SRC emacs-lisp
(use-package zygospore
:bind
(:map ctl-x-map
("1" . zygospore-toggle-delete-other-windows)))
#+END_SRC
** Kanban board
#+BEGIN_SRC emacs-lisp
(use-package kanban)
#+END_SRC
** Highlight dired buffer by file size, modified time, git status
#+BEGIN_SRC emacs-lisp
(use-package dired-k
:bind
(:map dired-mode-map
("K" . dired-k)))
#+END_SRC
** Show number of matches in the mode line while searching
#+BEGIN_SRC emacs-lisp
(use-package anzu
:config
(global-anzu-mode 1))
#+END_SRC
** Gradually expand region
#+BEGIN_SRC emacs-lisp
(use-package expand-region
:bind
(:map gpolonkai/pers-map
("x" . er/expand-region)))
#+END_SRC
** Read and Edit MediaWiki pages in an Emacs window
#+BEGIN_SRC emacs-lisp
(use-package mediawiki
:after
id-manager
:config
(add-to-list 'mediawiki-site-alist
'("WikEmacs"
"http://wikemacs.org/wiki/"
(gpolonkai/idm-get-id-for-account "WikEmacs")
(gpolonkai/idm-get-password-for-account "WikEmacs"))))
#+END_SRC
** Display unread GitHub notification count in the mode line
#+BEGIN_SRC emacs-lisp
(use-package github-notifier
:after
id-manager
:config
(setq github-notifier-token (gpolonkai/idm-get-password-for-account "GitHub"))
(github-notifier-mode))
#+END_SRC
** Interact with GitHub gists
#+BEGIN_SRC emacs-lisp
(use-package gist)
#+END_SRC
** An Emacs Dashboard
#+BEGIN_SRC emacs-lisp
(use-package dashboard
:after
projectile
:config
(add-to-list 'dashboard-items '(projects . 5) t)
(dashboard-setup-startup-hook))
#+END_SRC
** Hungarian holidays in the Calendar
#+BEGIN_SRC emacs-lisp
(use-package hungarian-holidays
:config
(hungarian-holidays-add))
#+END_SRC
** FlySpell
For all your spell-checking needs.
#+BEGIN_SRC emacs-lisp
(use-package flyspell
:config
(add-hook 'prog-mode-hook
'flyspell-prog-mode)
(add-hook 'text-mode-hook
'flyspell-mode))
#+END_SRC
** Delete all the whitespace
#+BEGIN_SRC emacs-lisp
(use-package hungry-delete
:config
(global-hungry-delete-mode))
#+END_SRC
** Send alerts to a notification system
#+BEGIN_SRC emacs-lisp
(use-package alert
:config
(setq 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)
(defcustom alert-termux-command (executable-find "termux-notification")
"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)))
(alert-define-style 'termux :title "Notify using termux"
:notifier #'alert-termux-notify))
'termux)
'libnotify)))
#+END_SRC
** Replace the GUI popup menu with something more efficient
#+BEGIN_SRC emacs-lisp
(use-package ace-popup-menu
:config
(ace-popup-menu-mode 1))
#+END_SRC
** I’m an achiever!
#+BEGIN_SRC emacs-lisp
(use-package achievements
:config
(achievements-mode 1))
#+END_SRC
** Secretaria
Because even secretaries need a secretary today.
#+BEGIN_SRC emacs-lisp
(use-package secretaria
:after
alert
:config
;; use this for getting a reminder every 30 minutes of those tasks
;; scheduled for today and which have no time of day defined.
(add-hook 'after-init-hook
#'secretaria-today-unknown-time-appt-always-remind-me))
#+END_SRC
** The Silver Searcher
#+BEGIN_SRC emacs-lisp
(use-package ag
:after projectile
:bind
(:map projectile-mode-map
("C-c p C-a" . ag-project)))
#+END_SRC
** A fancier ~narrow-mode~
#+BEGIN_SRC emacs-lisp
(use-package fancy-narrow
:config
(fancy-narrow-mode))
#+END_SRC
** Undo tree
#+BEGIN_SRC emacs-lisp
(use-package undo-tree)
#+END_SRC
** 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.
#+BEGIN_SRC emacs-lisp
(use-package all-the-icons)
#+END_SRC
** NeoTree, if Dired is not an option
#+BEGIN_SRC emacs-lisp
(use-package neotree
:after
all-the-icons
:config
(setq neo-theme (if (display-graphic-p) 'icons 'arrow))
:bind
(([f5] . neotree-toggle)))
#+END_SRC
** Waka-waka
This will be replaced with something self-hosted, eventually.
#+BEGIN_SRC emacs-lisp
(use-package wakatime-mode
:init
(setq-default wakatime-cli-path (executable-find "wakatime"))
:config
(global-wakatime-mode t))
#+END_SRC
** Jump to character, word, line
#+BEGIN_SRC emacs-lisp
(use-package ace-jump-mode
:bind
(:map gpolonkai/pers-map
("SPC" . ace-jump-mode)))
#+END_SRC
** Command frequency meter
#+BEGIN_SRC emacs-lisp
(use-package keyfreq
:config
(keyfreq-mode 1)
(keyfreq-autosave-mode 1))
#+END_SRC
* Make programming a bit easier
** Electric case
Insert snake_case and camelCase without using the Shift key. It is automatically enabled in C
mode.
#+BEGIN_SRC emacs-lisp
(use-package electric-case
:config
(add-hook 'c-mode-hook 'electric-case-c-init))
#+END_SRC
** Electric operator
Automatically add spaces around operators.
#+BEGIN_SRC emacs-lisp
(use-package electric-operator
:config
(add-hook 'c-mode-common-hook 'electric-operator-mode)
;; Apply electric-operator-mode to vala-mode, too
(apply #'electric-operator-add-rules-for-mode 'vala-mode
electric-operator-prog-mode-rules))
#+END_SRC
** Yasnippets
#+BEGIN_SRC emacs-lisp
(use-package yasnippet
:demand
:config
(yas-global-mode 1)
(add-hook 'post-command-hook 'sachachua/change-cursor-color-when-can-expand))
#+END_SRC
*** Extra snippets for Vala
#+BEGIN_SRC emacs-lisp
(use-package vala-snippets
:after
yasnippet)
#+END_SRC
*** Miscellanous extra snippets
#+BEGIN_SRC emacs-lisp
(use-package yasnippet-snippets)
#+END_SRC
** Colourful delimiters
#+BEGIN_SRC emacs-lisp
(use-package rainbow-delimiters
:config
(add-hook 'prog-mode-hook
#'rainbow-delimiters-mode))
#+END_SRC
** REST Client
#+BEGIN_SRC emacs-lisp
(use-package restclient)
#+END_SRC
** Highlight current symbol
A big help during refactoring.
#+BEGIN_SRC emacs-lisp
(use-package auto-highlight-symbol
:config
(global-auto-highlight-symbol-mode t))
#+END_SRC
** Make ReallyLongCamelCaseWords more readable
#+BEGIN_SRC emacs-lisp
(use-package glasses
:config
(add-hook 'prog-mode-hook 'glasses-mode))
#+END_SRC
** GObject boilerplate generator
#+BEGIN_SRC emacs-lisp
(use-package gobgen)
#+END_SRC
** Insert specific licenses in the current buffer
#+BEGIN_SRC emacs-lisp
(use-package xlicense
:bind
(:map gpolonkai/pers-map
("L" . insert-license)))
#+END_SRC
** Highlight TODO, FIXME, and XXX
#+BEGIN_SRC emacs-lisp
(use-package hl-todo)
#+END_SRC
* 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.
#+BEGIN_SRC emacs-lisp
(add-hook 'python-mode-hook
(lambda ()
(add-to-list 'prettify-symbols-alist
'("not" . 172))
(add-to-list 'prettify-symbols-alist
'("in" . 8712))
(add-to-list 'prettify-symbols-alist
'("def" . 402))))
#+END_SRC
** Automatically load the virtualenv if there is one
#+BEGIN_SRC emacs-lisp
(use-package auto-virtualenv
:config
(add-hook 'python-mode-hook 'auto-virtualenv-set-virtualenv)
(add-hook 'projectile-after-switch-project-hook
'auto-virtualenv-set-virtualenv))
#+END_SRC
** Anaconda mode
#+BEGIN_SRC emacs-lisp
(use-package anaconda-mode
:config
(add-hook 'python-mode-hook 'anaconda-mode)
(add-hook 'python-mode-hook 'anaconda-eldoc-mode))
#+END_SRC
** PipEnv
Because it’s great.
#+BEGIN_SRC emacs-lisp
(use-package pipenv
:hook (python-mode . pipenv-mode)
:init
(setq pipenv-projectile-after-switch-function #'pipenv-projectile-after-switch-extended))
#+END_SRC
* C mode
Because that’s still my favourite language.
** Set up my own C style
#+BEGIN_SRC emacs-lisp
(defconst my-c-style
'((c-tab-always-indent . t)
(c-comment-only-line-offset . 4)
(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 . +)
(substatement-open . 0)
(case-label . 4)
(block-open . 0)
(knr-argdecl-intro . -)
(comment-intro . 0)
(member-init-intro . ++)))
(c-echo-syntactic-information-p . t))
"My C Programming Style.")
(c-add-style "PERSONAL" my-c-style)
#+END_SRC
** Some common initialisation for C mode
#+BEGIN_SRC emacs-lisp
(add-hook 'c-mode-common-hook
(lambda ()
(local-set-key (kbd "C-c o") 'ff-find-other-file)
(c-set-style "PERSONAL")
(setq tab-width 4
indent-tabs-mode nil)
(c-toggle-auto-newline 1)))
(add-hook 'c-initialization-hook
(lambda ()
(define-key c-mode-base-map (kbd "C-m") 'c-context-line-break)))
#+END_SRC
** Set indentation levels to the same as the tab width
#+BEGIN_SRC emacs-lisp
(defvaralias 'c-basic-offset 'tab-width)
(defvaralias 'cperl-indent-level 'tab-width)
#+END_SRC
* Web development
** Web mode
#+BEGIN_SRC emacs-lisp
(use-package web-mode
:mode "\\.html?\\'"
:config
(setq web-mode-enable-auto-indentation nil)
(setq web-mode-enable-engine-detection t))
#+END_SRC
** Emmet mode
#+BEGIN_SRC emacs-lisp
(use-package emmet-mode
:config
(setq emmet-self-closing-tag-style "")
(add-hook 'web-mode 'emmet-mode)
(add-hook 'css-mode 'emmet-mode))
#+END_SRC
** Query HTML tags by CSS selectors
#+BEGIN_SRC emacs-lisp
(use-package enlive)
#+END_SRC
* FlyCheck
#+BEGIN_SRC emacs-lisp
(use-package flycheck
:config
(global-flycheck-mode))
#+END_SRC
** FlyCheck for pkg-config files
#+BEGIN_SRC emacs-lisp
(use-package flycheck-pkg-config)
#+END_SRC
* Org mode
This is a big one; I use a lot of customisation here.
#+BEGIN_SRC emacs-lisp
(use-package org
:demand
:init
(require 'xdg-paths)
(setq-default org-crypt-key "B0740C4C"
org-default-notes-file (concat user-documents-directory
(convert-standard-filename
"/orgmode/notes.org"))
org-directory (concat user-documents-directory
(convert-standard-filename "/orgmode/"))
org-agenda-files (concat user-documents-directory
(convert-standard-filename
"/orgmode/agenda_files"))
org-ellipsis "…#"
org-startup-folded 'content
org-mobile-directory (concat user-documents-directory
(convert-standard-filename
"/orgmode/mobile/"))
org-mobile-inbox-for-pull (concat
user-documents-directory
(convert-standard-filename
"/orgmode/from-mobile.org"))
org-log-done 'time
org-src-preserve-indentation t
org-log-into-drawer t
org-tags-column 0
org-startup-indented t
org-special-ctrl-a/e t)
:config
(require 'ox-md)
(unless (boundp 'org-capture-templates)
(setq org-capture-templates nil))
(add-to-list 'org-capture-templates
'("p" "Blog post"
entry (file+olp+datetree (concat org-directory "blog.org"))
"* %^{Title} :blog:\n :PROPERTIES:\n :on: %T\n :END:\n %i%?"))
(add-to-list 'org-capture-templates
'("g" "GT2 note"
entry (file+headline (concat org-directory "gt2-notes.org")
"Captures")
"** %^{Title}\n :PROPERTIES:\n :on: %T\n :END:\n %i%?"))
(setq org-time-stamp-formats '("<%Y-%m-%d>" . "<%Y-%m-%d %H:%M>")
org-todo-keywords '((sequence "TODO(t)"
"DOING(w@/!)"
"BLOCKED(b@/!)"
"|"
"CANCELED(c@/!)"
"REVIEW(r@/!)"
"DONE(d@/!)"))
org-goto-interface 'outline-path-completion
org-goto-max-level 10
org-html-checkbox-type 'unicode
org-html-checkbox-types
'((unicode (on . "☑")
(off . "☐")
(trans . "▣")))
org-src-window-setup 'current-window)
(add-hook 'ediff-select-hook 'f-ediff-org-unfold-tree-element)
(add-hook 'ediff-unselect-hook 'f-ediff-org-fold-tree)
:bind
(:map gpolonkai/pers-map
("a" . 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)))
#+END_SRC
** Org bullets
To display fancy bullets in graphics mode.
#+BEGIN_SRC emacs-lisp
(use-package org-bullets
:init
(add-hook 'org-mode-hook
(lambda ()
(if (display-graphic-p) org-bullets-mode))))
#+END_SRC
** Show a random ToDo every hour
#+BEGIN_SRC emacs-lisp
(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)))
#+END_SRC
** Citations and cross-references for Org
#+BEGIN_SRC emacs-lisp
(use-package org-ref
:after
org
:config
(setq 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"))))
#+END_SRC
And set up a function to open PDF files with the system pdf viewer, using ~xdg-open~.
An alternative could be
#+BEGIN_EXAMPLE
(setq bibtex-completion-pdf-open-function 'org-open-file))
#+END_EXAMPLE
#+BEGIN_SRC emacs-lisp
(setq bibtex-completion-pdf-open-function
(lambda (fpath)
(start-process "xdg-open" "*open*" "open" fpath)))
#+END_SRC
* Git & Co.
** Git status on the fringe
In graphical modes we use ~git-gutter-fringe~, and ~git-gutter~ otherwise.
#+BEGIN_SRC emacs-lisp
;; 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
:config
(global-git-gutter-mode t)
:bind
(:map gpolonkai/pers-map
("gg" . git-gutter:update-all-windows)
("gn" . git-gutter:next-hunk)
("gp" . git-gutter:previous-hunk)))))
#+END_SRC
** Git messenger
AKA blame current line.
#+BEGIN_SRC emacs-lisp
(use-package git-messenger
:bind
(:map gpolonkai/pers-map
("gm" . git-messenger:popup-message)))
#+END_SRC
** Git time machine
See previous versions of the current file.
#+BEGIN_SRC emacs-lisp
(use-package git-timemachine
:bind
(([f6] . git-timemachine-toggle)))
#+END_SRC
* Company & Co.
#+BEGIN_SRC emacs-lisp
(use-package company
:config
(setq company-idle-delay nil
company-frontends '(company-pseudo-tooltip-frontend
company-echo-metadata-frontend)
company-dabbrev-downcase nil)
(put 'company-clang-arguments 'safe-local-variable #'nil-or-list-of-strings-p)
(global-company-mode))
#+END_SRC
** Company completion based on local C headers
#+BEGIN_SRC emacs-lisp
(use-package company-c-headers)
#+END_SRC
** Company mode in the shell
#+BEGIN_SRC emacs-lisp
(use-package company-shell)
#+END_SRC
** REST Client completion via Company
#+BEGIN_SRC emacs-lisp
(use-package company-restclient)
#+END_SRC
** Insert Emoji with Company
#+BEGIN_SRC emacs-lisp
(use-package company-emoji
:after
company
:init
(--set-emoji-font nil)
:config
(add-to-list 'company-backends 'company-emoji)
(add-hook 'after-make-frame-functions
'--set-emoji-font))
#+END_SRC
** Anaconda backend for Company
#+BEGIN_SRC emacs-lisp
(use-package company-anaconda
:after
company
:config
(add-to-list 'company-backends 'company-anaconda))
#+END_SRC
** Web mode (~web-mode~ and ~emmet-mode~, too) backend for Company
#+BEGIN_SRC emacs-lisp
(use-package company-web
:config
(require 'company-web-html))
#+END_SRC
* Helm & Co.
** Helm
#+BEGIN_SRC emacs-lisp
(use-package helm
:init
(require 'helm-config)
(setq helm-M-x-fuzzy-match t
helm-buffers-fuzzy-matching t
helm-recentf-fuzzy-match t)
:config
(helm-mode t)
: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)))
#+END_SRC
** Helm-style swooping
#+BEGIN_SRC emacs-lisp
(use-package helm-swoop
:bind
(("M-i" . helm-swoop)))
#+END_SRC
** GNU Globals with Helm
#+BEGIN_SRC emacs-lisp
(use-package helm-gtags
:init
(setq-default helm-gtags-auto-update t
helm-gtags-ignore-case t
helm-gtags-path-style 'relative)
:config
(add-hook 'c-mode-hook
(lambda ()
(helm-gtags-mode t)))
: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)))
#+END_SRC
** Ag with Helm
#+BEGIN_SRC emacs-lisp
(use-package helm-ag
:bind
(:map gpolonkai/pers-map
("s" . helm-do-ag)))
#+END_SRC
** Company with Helm
#+BEGIN_SRC emacs-lisp
(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)))
#+END_SRC
** Projectile with Helm
#+BEGIN_SRC emacs-lisp
(use-package helm-projectile
:init
(setq projectile-completion-system 'helm)
:config
(helm-projectile-on))
#+END_SRC
** FlyCheck with Helm
#+BEGIN_SRC emacs-lisp
(use-package helm-flycheck)
#+END_SRC
** FlySpell with Helm
#+BEGIN_SRC emacs-lisp
(use-package helm-flyspell
:demand
:bind
(:map flyspell-mode-map
("C-M-i" . helm-flyspell-correct)))
#+END_SRC
** Search GitHub starred repos with Helm
#+BEGIN_SRC emacs-lisp
(use-package helm-github-stars
:init
(setq-default helm-github-stars-username "gergelypolonkai"))
#+END_SRC
** Smex with Helm
#+BEGIN_SRC emacs-lisp
(use-package helm-smex
:bind
(("M-S-x" . helm-smex)))
#+END_SRC
** Describe bindings with Helm
#+BEGIN_SRC emacs-lisp
(use-package helm-descbinds)
#+END_SRC
** Describe modes with Helm
#+BEGIN_SRC emacs-lisp
(use-package helm-describe-modes)
#+END_SRC
** REST Client with Helm
#+BEGIN_SRC emacs-lisp
(use-package restclient-helm)
#+END_SRC
** C Yasnippets with Helm
#+BEGIN_SRC emacs-lisp
(use-package helm-c-yasnippet
:demand t
:config
(setq helm-yas-space-match-any-greedy t)
:bind
(("C-c y" . helm-yas-complete)))
#+END_SRC
** Git hunks with Helm
#+BEGIN_SRC emacs-lisp
(use-package helm-hunks)
#+END_SRC
** PyDoc with Helm
#+BEGIN_SRC emacs-lisp
(use-package helm-pydoc)
#+END_SRC
** BibTex with Helm
#+BEGIN_SRC emacs-lisp
(use-package helm-bibtex
:after
org
:config
(setq 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))
#+END_SRC
* Mode specific ~use-package~ calls
** JavaScript
#+BEGIN_SRC emacs-lisp
(use-package js2-mode
:pin melpa-stable
:mode "\\.js\\'")
#+END_SRC
** TypeScript
#+BEGIN_SRC emacs-lisp
(use-package typescript-mode
:mode "\\.ts\\'")
#+END_SRC
** CoffeeScript
#+BEGIN_SRC emacs-lisp
(use-package coffee-mode
:mode "\\.coffee\\'")
#+END_SRC
** JSON
#+BEGIN_SRC emacs-lisp
(use-package json-mode
:mode "\\.json\\'")
#+END_SRC
** YAML
#+BEGIN_SRC emacs-lisp
(use-package yaml-mode
:mode (("\\.yml\\'" . yaml-mode)
("\\.yaml\\'" . yaml-mode))
:init
(add-to-list 'auto-mode-alist '("\\.yml\\'" . yaml-mode)))
#+END_SRC
** Markdown
#+BEGIN_SRC emacs-lisp
(use-package markdown-mode
:mode (("\\.md\\'" . markdown-mode)
("\\.markdown\\'" . markdown-mode)))
#+END_SRC
** Less
#+BEGIN_SRC emacs-lisp
(use-package less-css-mode
:mode "\\.less\\'")
#+END_SRC
** Sass
#+BEGIN_SRC emacs-lisp
(use-package sass-mode
:mode "\\.sass\\'")
#+END_SRC
** Vala
#+BEGIN_SRC emacs-lisp
(use-package vala-mode
:mode "\\.vala\\'")
#+END_SRC
** Dockerfile
#+BEGIN_SRC emacs-lisp
(use-package dockerfile-mode)
#+END_SRC
** ~.gitconfig~
#+BEGIN_SRC emacs-lisp
(use-package gitconfig-mode)
#+END_SRC
** ~.gitignore~
#+BEGIN_SRC emacs-lisp
(use-package gitignore-mode)
#+END_SRC
** ~po-mode~
#+BEGIN_SRC emacs-lisp
(use-package po-mode
:mode "\\.po\\'")
#+END_SRC
** C#
#+BEGIN_SRC emacs-lisp
(use-package csharp-mode
:mode "\\.cs\\'")
#+END_SRC
** Gherkin (BDD) feature files
#+BEGIN_SRC emacs-lisp
(use-package feature-mode
:mode "\\.feature\\'")
#+END_SRC
** PlantUML
Before using this, make sure the latest PlantUML JAR file is downloaded into the downloads
directory. It is available from [[http://plantuml.com/download][here]].
#+BEGIN_SRC emacs-lisp
(use-package plantuml-mode
:init
(setq plantuml-jar-path
(expand-file-name
;; Make sure we have a download location even if XDG is not working
(cond
((xdg-user-dir "DOWNLOAD")
(concat (xdg-user-dir "DOWNLOAD") "/plantuml.jar"))
(t
"~/Downloads/plantuml.jar"))))
(defvaralias 'org-plantuml-jar-path 'plantuml-jar-path)
:config
(org-babel-do-load-languages
'org-babel-load-languages
'((plantuml . t))))
#+END_SRC
* Games
** Gnu Go
#+BEGIN_SRC emacs-lisp
(use-package gnugo)
#+END_SRC
* Last, but not least, key bindings!
#+BEGIN_SRC emacs-lisp
;; Custom key bindings
(bind-keys
:map global-map
("M-(" . æ-enclose-region)
("" . open-line-below)
("" . 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" . gpolonkai/kill-this-buffer)
("M-c" . gpolonkai/kill-this-buffer-delete-this-window)
("M-k" . gpolonkai/undo-buffer-kill)
("C-b" . bury-buffer)
("/" . repeat)
:map isearch-mode-map
("" . isearch-exit-other-end)
("" . isearch-exit-mark-match)
:map gpolonkai/pers-map
("m" . 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)
("C" . clean-buffer-list))
#+END_SRC
** TODO These fail to work using ~bind-keys~, but why?
#+BEGIN_SRC emacs-lisp
(define-key 'help-command (kbd "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)
#+END_SRC