On using emacs

[back]


General usage

If you need to work with multiple files, {gnu emacs} is an editor with a graphical user interface. When using emacs, it is advised to launch it as a daemon with server-start and keep it running during the entire session. This allows you to open other files from the command line through the emacsclient command. Files will open in the emacs window that is already open.

Hippie Expand

When activated, {Hippie Expand} provides low-overhead autocompletion, based on text in open buffers. Start typing a word, and then invoke autocompletion with M-/. Hippie Expand completes the word by cycling through different autocompletion mechanisms that can be specified in the configuration file—see below. If the correct expansion of the word has been passed by accident, use C-/ to cycle back.

Keyboard macros

emacs lets you record a series of commands, which are called {keyboard macro}s. We use C-x ( to start and C-x ) to end the recording. Once recorded, the macro can be executed repeatedly through C-x e. This is useful if the same action has to be performed repeatedly, but there is no good pattern to capture the location. This allows more general structural editing than the regular expression-based workflow in {gnu ed(1)}.

gnus

{gnus} is a news and email reader that ships with emacs. It lets you "subscribe" to email inboxes and, for example, RSS feeds.

gnus hides emails that have been read. To view these older emails, use /o, which displays all email. This can be changed in the configuration file, but I’m OK with the defaults.

gnus stores login credentials in: ${HOME}/.authinfo

Underrated functionalities

Configuration

Dependencies

I use {ESS} to get R language support.

init.el

Older versions of emacs used to be configured through a file called .emacs, placed in your ${HOME}. While modern versions still support this, it's recommended to write configuration into ${HOME}/.emacs.d/init.el instead. For example, my init.el reads:

    
	(require 'package)
	(add-to-list 'package-archives
	         '("melpa-stable" . "https://stable.melpa.org/packages/") t)
	(package-initialize)
	
	;; dired
	
	(put 'dired-find-alternate-file 'disabled nil)
	(setq delete-by-moving-to-trash t)
	
	;; hippie expand
	
	(global-set-key (kbd "M-/") 'hippie-expand)
	(setq hippie-expand-try-functions-list '(try-expand-dabbrev
	                     try-expand-dabbrev-all-buffers
	                     try-expand-dabbrev-from-kill
	                     try-complete-file-name-partially
	                     try-complete-file-name
	                     try-expand-all-abbrevs
	                     try-expand-list
	                     try-expand-line
	                     try-complete-lisp-symbol-partially
	                     try-complete-lisp-symbol))
	
	;; ido
	
	(require 'ido)
	(setq ido-enable-flex-matching t)
	(setq ido-everywhere t)
	(ido-mode t)
	
	;; eww
	
	(setq browse-url-browser-function 'eww-browse-url)
	(setq eww-search-prefix "https://wiby.org/?q=")
	
	;; calendar and diary
	
	(appt-activate t)
	
	;; org
	
	(org-babel-do-load-languages
	   'org-babel-load-languages
	   '((calc . t)
	     (gnuplot . t)
	     (C . t)))
	
	;;
	;; -- custom functions
	;;
	
	(load "~/.emacs.d/elisp/custom-functions.el")
	
	;;
	;; -- third party library
	;;
	
	(load "ess-autoloads")
    
  

.gnus.el

It’s pretty easy to set up a basic email reader. At this moment, I don’t need any more advanced functionality. The configuration file .gnus.el goes in the ${HOME} directory.

    
      (setq user-full-name "Ilhan Ozgen-Xian"
      user-mail-address "user@example.what")
      
      (setq message-send-mail-function 'smtpmail-send-it
      smtpmail-default-smtp-server "example.domain.what"
      smtpmail-smtp-service 587
      smtpmail-local-domain "name-of-pc")
      
      (setq gnus-select-method '(nnnil ""))
      (setq gnus-secondary-select-methods '((nnml "")
      (nnimap "example.domain.what"
      (nnimap-address "example.domain.what")
      (nnimap-server-port 993)
      (nnimap-stream ssl)
      (nnmail-expiry-wait 90))))
      
      (setq gnus-message-archive-method '(nnimap "example.domain.what")
      gnus-message-archive-group "Sent")
      (setq gnus-gcc-mark-as-read t)
    
  

Notes

Hack solutions

Some hack solutions for academic needs. These are placed in custom-functions.el, loaded in the init.el above. Elisp doesn't have namespaces, so it is recommended to use a custom prefix—here I use "il"—to avoid accidentally overwriting other functions.

Pomodoro

This allows you to call the set-timer function through M-x. You provide the function an interval of X minutes. After X minutes have passed, the function flash-mode-line is called. The mode line flashes, reminding you to take a break.

    
      (defun il-flash-mode-line (str)
	  (invert-face 'mode-line)
	  (run-with-timer 1.0 nil #'invert-face 'mode-line)
	  (message str))
	
	(defun il-set-timer (interval)
	  (interactive "s > set interval: ")
	  (run-at-time (format "%s min" interval) nil #'il-flash-mode-line " > time for a break.")
	  (message (format " > will alert in %s min." interval)))
    
  

Switch between dark and light themes

Tries to invert the color scheme. Works well with the default theme. I haven’t tested it with custom color themes.

    
      (defun il-switch-colors ()
	  (interactive)
	  (invert-face 'default)
	  )
    
  

Get bibtex citation by DOI

This has two implementations, which may give different results. The first one is a pure elisp implementation, the second one calls the external curl program. The original pure elisp implementation is from {P. Iosad}.

    
      (defun il-doi-to-bib-elisp (doi)
	  "modified from iosad (https://www.anghyflawn.net/blog/2014/emacs-give-a-doi-get-a-bibtex-entry/)"
	  (interactive "Mdoi: ")
	  (get-buffer-create "*doi2bib-el*")
	  (switch-to-buffer "*doi2bib-el*")
	  (let ((url-mime-accept-string "text/bibliography;style=bibtex"))
	    (with-current-buffer 
	    (url-retrieve-synchronously (format "http://dx.doi.org/%s" doi))
	      (switch-to-buffer (current-buffer))
	      (goto-char (point-max))
	      (setq bibtex-entry (buffer-substring (string-match "@" (buffer-string)) (point)))
	      (kill-buffer (current-buffer))))
	  (insert (decode-coding-string bibtex-entry 'utf-8))
	  (bibtex-fill-entry))
	
	(defun il-doi-to-bib-bash (doi)
	  (interactive "Mdoi: ")
	  (shell-command (format "curl -LH \"Accept: application/x-bibtex\" http://dx.doi.org/%s" doi)))
    
  

ed(1)-like shell escape

In {ed(1)}, when executing a shell command, the character "%" expands to the current file name. This can be achieved in emacs as well. Original implementation by {R. Grau}.

    
      (defun il-shell-execute ()
      (interactive)
      (let ((file-buffer (buffer-file-name))
	(command (read-shell-command "Shell command: " nil nil
				     (let ((filename
					    (cond
					     (buffer-file-name)
					     ((eq major-mode 'dired-mode)
					      (dired-get-filename nil t)))))
			  (and filename (file-relative-name filename))))))
      (shell-command (replace-regexp-in-string "%" file-buffer command))))
    
  

Resources

The best resource to look stuff up is {the official manual}. A good curation of articles and news can be found at {Planet Emacslife}.


Last updated: Fri Jun 11 13:58:13 2021