Thoughts on Emacs
Configuration
Emacs is all about configuration and configuration is all about lisp. I try to keep configurations to a minimum and avoid putting things into .emacs.d/init.el that I don’t fully understand. Learning emacs lisp provides a unified tutorial on lisp programming with an emphasis on emacs configuration that is also available as an org file.
Setting up emacs for coding in React JSX and javascript
I wanted to set up syntax highlighting, automated indenting and syntax error checking (linting) etc when editing javascript containing JSX (React) extensions. Emacs-flycheck-eslint covers this but is a bit out of date. I used that page as a rough guide and came up with the installation procedure that follows. I started by installing eslint and plug-ins with npm
sudo npm install -g eslint babel-eslint eslint-plugin-react
and created a file ~/.eslintrc
with contents
{
"parser": "babel-eslint",
"plugins": [ "react" ],
"env": {
"browser": true,
"es6": true,
"node": true
},
"ecmaFeatures": {
"arrowFunctions": true,
"blockBindings": true,
"classes": true,
"defaultParams": true,
"destructuring": true,
"forOf": true,
"generators": true,
"modules": true,
"spread": true,
"templateStrings": true,
"jsx": true
},
"rules": {
"consistent-return": [0],
"key-spacing": [0],
"quotes": [0],
"new-cap": [0],
"no-multi-spaces": [0],
"no-shadow": [0],
"no-unused-vars": [1],
"no-use-before-define": [2, "nofunc"],
"react/jsx-no-undef": 1,
"react/jsx-uses-react": 1,
"react/jsx-uses-vars": 1
}
}
I then installed the rjsx-mode
and flymake
packages in emacs and added the following lines to
~/.emacs.d/init.el
;; setting for programming
(add-to-list 'auto-mode-alist '("\\.js\\'" . rjsx-mode)) ;; use react jsx extension mode for javascript files
;; http://www.flycheck.org/manual/latest/index.html
(require 'flycheck)
;; turn on flychecking globally
(add-hook 'after-init-hook #'global-flycheck-mode)
;; disable jshint since we prefer eslint checking
(setq-default flycheck-disabled-checkers
(append flycheck-disabled-checkers
'(javascript-jshint)))
;; use eslint with rjsx-mode for js files
(flycheck-add-mode 'javascript-eslint 'rjsx-mode)
;; customize flycheck temp file prefix
(setq-default flycheck-temp-prefix ".flycheck")
;; disable json-jsonlist checking for json files
(setq-default flycheck-disabled-checkers
(append flycheck-disabled-checkers
'(json-jsonlist)))
When editing a js file in rjsx-mode using C-c ! <char>
executes a
flycheck command in the buffer. For example C-c ! l
give a full list
of syntax errors in the buffer. The full list of commands are
available at flycheck quickstart.
Org mode A really useful package for creating project notebooks with checklists, timestamps, executable code and so on. What is Org mode about? provides an org mode tutorial that you can follow using the org file org-mode-tutorial.org
Embedding plantuml figures in org
The plantuml software is a java library for displaying uml diagrams. The
diagrams can be rendered in an emacs buffer as well and
in a code block in an org document. The language specification is
here. On a mac you use brew
to first install plantuml
brew install plant uml
then install the two emacs packages plantuml-mode
and
flycheck-plantuml
(syntax checking). Then edit ~/.emacs.d/init.el
and add the following lines
(add-to-list
'org-src-lang-modes '("plantuml" . plantuml))
(setq plantuml-jar-path "/usr/local/Cellar/plantuml/1.2019.3/libexec/plantuml.jar")
The adding a code block like
#+BEGIN_SRC plantuml
@startuml
Alice -> Bob: test
@enduml
#+END_SRC
and typing C-c '
in the block will render a diagram in an emacs buffer. Cool.
Gnus mail Reading gmail in emacs is a bit complicated. I thought about Wanderlust but was disuaded by the lack of documentation. Finally settled on the mu/mu4e and offlineimap combination. Emacs as email client with offlineimap and mu4e provides a good tutorial on how to set these up in OS X. I provide a quick summary here of what worked for me. First, install offlineimap using brew
brew install offlineimap
Then create the configuration file ~/.offlineimaprc
with contents
[general]
ui=TTYUI
accounts = Gmail
autorefresh = 5
[Account Gmail]
localrepository = Gmail-Local
remoterepository = Gmail-Remote
[Repository Gmail-Local]
type = Maildir
localfolders = ~/.Mail/me@gmail.com
[Repository Gmail-Remote]
type = Gmail
remotehost = imap.gmail.com
remoteuser = me@gmail.com
remotepass = <password>
realdelete = no
ssl = yes
sslcacertfile = /usr/local/etc/openssl/cert.pem
maxconnections = 1
folderfilter = lambda folder: folder not in ['[Gmail]/Trash',
'[Gmail]/Spam',
'[Gmail]/All Mail',
'[Gmail]/Important',
'[Gmail]/Starred',
'Archive',
'Notes',
]
I filtered out most of the mailboxes as I only wanted to download INBOX and Sent and Draft mail. Then type
offlineimap
and the mail will be downloaded. The mu/mu4e programs are then installed
brew install mu
and the following command is run to index the mail files
mu index --maildir=~/.Mail
The init.el file is then edited to incorporate some mu4e configurations
;; Settings for mu4e mail client
(require 'mu4e)
(setq mail-user-agent 'mu4e-user-agent)
(setq mu4e-maildir "~/.Mail")
(setq mu4e-drafts-folder "/me@gmail.com/[Gmail].Drafts")
(setq mu4e-sent-folder "/me@gmail.com/[Gmail].Sent Mail")
;; don't save message to Sent Messages, Gmail/IMAP takes care of this
(setq mu4e-sent-messages-behavior 'delete)
;; allow for updating mail using 'U' in the main view:
(setq mu4e-get-mail-command "offlineimap")
;; shortcuts
(setq mu4e-maildir-shortcuts
'( ("/me@gmail.com/INBOX" . ?i)
("/me@gmail.com/[Gmail].Drafts" . ?d)
("/me@gmail.com/[Gmail].Sent Mail" . ?s)))
;; something about ourselves
(setq
user-mail-address "lk@pepperspray.org"
user-full-name "Full Name"
mu4e-compose-signature
(concat
"Me\n"
"Organization\n"))
Mail will be sent using smtpmail so that is configured in init.el as well
;; configuration for sending mail
(setq message-send-mail-function 'smtpmail-send-it
smtpmail-stream-type 'starttls
smtpmail-default-smtp-server "smtp.gmail.com"
smtpmail-smtp-server "smtp.gmail.com"
smtpmail-smtp-service 587)
If it is not already installed gnutls should be installed
brew gnutls
Finally, create an ~/.authinfo
file with the following contents:
machine smtp.gmail.com login <gmail username> password <gmail password>
and encrypt the above file by running:
gpg --output ~/.authinfo.gpg --symmetric ~/.authinfo
All done. Now in emacs type M-x mu4e
to start using mu4e for email.
Reading your google calendars in the emacs calendar
I like keeping all my appointments in several Google calendars and I am happy going to
the Google calendar to create new events, but then I want to be able to pull up my schedule
in the native calendar within emacs. I also want the daily tides in Benicia (which are available as
a public ical) to be displayed in my emacs calendar (helpful for sailing). My solution was first set up private
calendar sharing in Google
to provide a web address for an ical version of each of my calendars. I then wrote a shell
script called getical with the following contents (where <privateaddress>
will be specific to your calendar)
#!/bin/bash
rm ~/calendar/*.ics
wget -c https://calendar.google.com/calendar/ical/<privateaddress>/basic.ics -O ~/calendar/work.ics
wget -c https://calendar.google.com/calendar/ical/<privateaddress>/basic.ics -O ~/calendar/dailyschedule.ics
wget -c https://calendar.google.com/calendar/ical/<privateaddress>/basic.ics -O ~/calendar/reminders.ics
wget -c https://calendar.google.com/calendar/ical/<privateaddress>/basic.ics -O ~/calendar/tides.ics
rm -f ~/.emacs.d/ical-diary
emacs --batch -l ~/bin/importical.el
and created a calendar subdirectory in my home directory. The last line in the script runs a the lisp file
importical.el
which contains the following code
(icalendar-import-file "~/calendar/work.ics" "~/.emacs.d/ical-diary")
(icalendar-import-file "~/calendar/dailyschedule.ics" "~/.emacs.d/ical-diary")
(icalendar-import-file "~/calendar/reminders.ics" "~/.emacs.d/ical-diary")
(icalendar-import-file "~/calendar/tides.ics" "~/.emacs.d/ical-diary")
which imports all my calendars into a single emacs calendar called ical-diary.
The final step was to create a file ~/.emacs.d/diary
with the contents
#include "~/.emacs.d/ical-diary"
so that the ical-diary is opened by default by the emacs calendar program.
Typing M-x calendar
in emacs now brings up a calendar with all the events
from all my calendars.
After making changes to my Google calendar I simply run the getical script to update
the emacs diary.
Getting that ugly DOS ^M newline character out of your text files
I collaborate with quite a few people who use Windows and seem to be unaware that their Windows text editor is littering our shared text files with ^M DOS style carriage returns. Here is a useful emacs command to strip all the ^M characters out replacing them with a unix newline:
M-x replace-string RET C-q C-m RET C-q C-j RET
Enjoy Reading This Article?
Here are some more articles you might like to read next: