Emacs notes
Helper functions
Git quick commit for magit
The following function stages all unstaged changes and commits them with a commit message that only contains a list of the modified files.
Resulting commit message will look like:
changed: foo.txt, bar.txt
I use this function when updating this blog quite often, because I do a lot of small commits and do not need a hand written message for commits.
(defun my/git-quick-commit ()
"Create a commit with list of changed files as the message."
(interactive)
(let ((changed
(mapconcat
#'(lambda (x)
; Extract file part of the path
(substring x (string-match-p "\\([^\/]*\\)$" x)))
(magit-git-lines "diff" "--name-only") ", ")))
(if (string= "" changed)
(user-error "No unstaged changes"))
(magit-stage-modified)
(magit-call-git "commit" "-m" (concat "changed: " changed))
(magit-refresh)
(message "Changes committed.")))
To bind it globally, use following (I'm using M-g m q
)
(global-set-key (kbd "M-g m q") 'my/git-quick-commit)
Vterm
This function makes it possible to use counsel to quickly navigate directories in the shell running vterm buffer. I prefer this to using e.g. zsh's directory autocompletion. Requires ivy and counsel to be installed.
(defun my/vterm-cd (&optional initial-input initial-directory)
(interactive)
(let ((default-directory (or initial-directory default-directory))
(counsel--find-file-predicate #'file-directory-p))
(counsel--find-file-1 "Find directory: " initial-input
#'my/vterm-cd-action
'my/vterm-cd)))
(defun my/vterm-cd-action (dir)
(vterm-send-string (format " cd %s" dir) t)
(vterm-send-return))
To bind it to a key, use following (I'm using C-c .
)
(define-key vterm-mode-map (kbd "C-c .") 'my/vterm-cd)
Camelize string
Converts a string such as "foo bar baz" to fooBarBaz.
(defun camelize-string (str)
(let ((words (split-string str "[-_ ]+")))
(concat (downcase (car words))
(mapconcat 'capitalize (cdr words) ""))))
Does the conversion above and puts it in the kill ring.
(defun camelize-region (start end)
"Convert the region to camelCase and copy it to the kill ring."
(interactive "r")
(let ((value (buffer-substring start end)))
(kill-new (camelize-string value)))
(deactivate-mark t))
Peek in other window
Opens the current buffer in a new window in read only mode, to allow glancing other parts of the buffer without losing track of current location. 'q' quits the window. I sometimes use this to look at parts of a long function or look up function headers.
(defun my/clone-buffer-in-new-window-readonly ()
"Clone the current buffer in a new window, make it readonly, and set up a
keybinding to close the window."
(interactive)
(let ((clone-buffer (clone-indirect-buffer (buffer-name) t)))
(with-current-buffer clone-buffer
(read-only-mode t)
(let ((map (make-sparse-keymap)))
(define-key map (kbd "q") (lambda ()
(interactive)
(kill-buffer-and-window)))
(use-local-map map)))
(switch-to-buffer-other-window clone-buffer)))
To bind it globally, use following (I'm using C-x 9
)
(global-set-key (kbd "C-x 9") 'my/clone-buffer-in-new-window-readonly)
dired
Dired is pretty plain in its default configuration.
Coloring by file type by using dired-rainbow:
(use-package dired-rainbow
:config
(progn
(dired-rainbow-define-chmod directory "#6cb2eb" "d.*")
(dired-rainbow-define html "#eb5286" ("css" "less" "sass" "scss" "htm" "html" "jhtm" "mht" "eml" "mustache" "xhtml"))
(dired-rainbow-define xml "#f2d024" ("xml" "xsd" "xsl" "xslt" "wsdl" "bib" "json" "msg" "pgn" "rss" "yaml" "yml" "rdata"))
(dired-rainbow-define document "#9561e2" ("docm" "doc" "docx" "odb" "odt" "pdb" "pdf" "ps" "rtf" "djvu" "epub" "odp" "ppt" "pptx"))
(dired-rainbow-define markdown "#ffed4a" ("org" "etx" "info" "markdown" "md" "mkd" "nfo" "pod" "rst" "tex" "textfile" "txt"))
(dired-rainbow-define database "#6574cd" ("xlsx" "xls" "csv" "accdb" "db" "mdb" "sqlite" "nc"))
(dired-rainbow-define media "#de751f" ("mp3" "mp4" "MP3" "MP4" "avi" "mpeg" "mpg" "flv" "ogg" "mov" "mid" "midi" "wav" "aiff" "flac"))
(dired-rainbow-define image "#f66d9b" ("tiff" "tif" "cdr" "gif" "ico" "jpeg" "jpg" "png" "psd" "eps" "svg"))
(dired-rainbow-define log "#c17d11" ("log"))
(dired-rainbow-define shell "#f6993f" ("awk" "bash" "bat" "sed" "sh" "zsh" "vim"))
(dired-rainbow-define interpreted "#38c172" ("py" "ipynb" "rb" "pl" "t" "msql" "mysql" "pgsql" "sql" "r" "clj" "cljs" "scala" "js"))
(dired-rainbow-define compiled "#4dc0b5" ("asm" "cl" "lisp" "el" "c" "h" "c++" "h++" "hpp" "hxx" "m" "cc" "cs" "cp" "cpp" "go" "f" "for" "ftn" "f90" "f95" "f03" "f08" "s" "rs" "hi" "hs" "pyc" ".java"))
(dired-rainbow-define executable "#8cc4ff" ("exe" "msi"))
(dired-rainbow-define compressed "#51d88a" ("7z" "zip" "bz2" "tgz" "txz" "gz" "xz" "z" "Z" "jar" "war" "ear" "rar" "sar" "xpi" "apk" "xz" "tar"))
(dired-rainbow-define packaged "#faad63" ("deb" "rpm" "apk" "jad" "jar" "cab" "pak" "pk3" "vdf" "vpk" "bsp"))
(dired-rainbow-define encrypted "#ffed4a" ("gpg" "pgp" "asc" "bfe" "enc" "signature" "sig" "p12" "pem"))
(dired-rainbow-define fonts "#6cb2eb" ("afm" "fon" "fnt" "pfb" "pfm" "ttf" "otf"))
(dired-rainbow-define partition "#e3342f" ("dmg" "iso" "bin" "nrg" "qcow" "toast" "vcd" "vmdk" "bak"))
(dired-rainbow-define vc "#0074d9" ("git" "gitignore" "gitattributes" "gitmodules"))
(dired-rainbow-define-chmod executable-unix "#38c172" "-.*x.*")))