This file IS the program.
A literate README that produces an init.el
, personalized to my tastes. Uses package.el
, use-package
, and quelpa
.
All of the tangled code in this README.org
is Emacs Lisp, though there are some snippets of Bash. That is because we want to tangle to one Emacs Lisp file, init.el
.
To stop Emacs from tangling a block of code, add :tangle no
like this: #+begin_src emacs-lisp :tangle no
These may be edited out by setting :tangle no
or changing them to suit.
silversearcher-ag
needed bydumb-jump
andag
- Requirements needed for
vterm
Here’s my ~/.config/systemd/user/emacs.service
file. The path may change per Emacs installation.
[Unit] Description=Emacs text editor Documentation=info:emacs man:emacs(1) https://gnu.org/software/emacs/ [Service] Type=simple ExecStart=/usr/bin/emacs --fg-daemon ExecStop=/usr/bin/emacsclient --eval "(kill-emacs)" Environment=SSH_AUTH_SOCK=%t/keyring/ssh Restart=on-failure [Install] WantedBy=default.target
- Now you’ll want to do
systemctl --user enable emacs && systemctl --user start emacs
- To restart the Emacs server, exit all clients, and do
systemctl --user restart emacs
- To connect an Emacs client to the Emacs server, do
emacsclient
oremacsclient -t
To install, just (fork and) clone this repository somewhere locally where it can stay. If you’re not forking, then you can’t push your changes, but you can still branch locally, or fork manually later.
# If cloning directly from me
git clone https://github.com/joseph8th/literatemacs.git .
# If forking, then cloning from yourself
git clone [email protected]:YOURUSERNAME/literatemacs.git .
Use this file and Emacs’ org-babel
feature to:
- generate an
init.el
file in the same directory as this file, and - create a symbolic link from
./init.el
to$HOME/emacs.d/init.el
.
Carefully follow the instructions below to generate your first init.el
in the same directory as this file.
Before using this literate program, first backup current $HOME/emacs.d/init.el
Now edit this README.org
file to suit. That means:
- Set
:tangle no
to any blocks you want to disable, or delete them entirely, and - edit any blocks to configure Emacs differently on the first run.
Edit the following, unless you are me. This is the first thing that will be tangled.
;;; init.el --- Emacs initialization file tangled from a README.org file
;;
;; Author: Joseph Edwards VIII <jedwards8th at gmail.com>
;; URL: https://github.com/joseph8th/literatemacs
;; ============================================================================
;;; User setting
;; ----------------------------------------------------------------------------
(setq user-full-name "Joseph Edwards VIII"
user-mail-address "")
When you save, Emacs will ask if you want to “Tangle?” and then “Reload?” On first save, say “Yes” to “Tangle?” and say “No” to “Reload?”
Now the file init.el
exists in the same directory as this README.org
file.
Finally, link the ./init.el
file and required elisp/
directory into your $HOME/.emacs.d/
directory:
mv ~/.emacs.d/init.el ~/.emacs.d/init.el.bak
ln -s ./init.el ~/.emacs.d/
ln -s ./elisp ~/.emacs.d/
Now when Emacs asks if you want to “Tangle?” and “Reload?” you can say “Yes” and the updated and re-tangled init.el
will be loaded as the user-init-file
.
There are three ways to tangle this file:
- Use
M-x org-babel-tangle
(C-c C-v t
). - Position cursor inside the following code block and do
C-c C-c
:(org-babel-tangle)
- Just edit and save, and let the
after-save-hook
, defined in the Conclusion, do its thing.
To reload, just do M-: (load-file user-init-file) RET
Or, position cursor inside the following and do C-c C-c
:
(load-file user-init-file)
TL;DR: use-package and quelpa bootstrapping, some optimizations picked up here and there.
Elpa (GNU) is the default, but I add it anyway. Disabling package-enable-at-startup
is SOP to make startup a little quicker.
;;; Initialize
;; -----------------------------------------------------------------------------
(require 'package)
;; Set package archives
(setq package-check-signature nil) ; because GNU ELPA keeps choking on the sigs
(add-to-list 'package-archives '("gnu" . "http:https://elpa.gnu.org/packages/"))
(add-to-list 'package-archives '("melpa" . "http:https://melpa.org/packages/"))
(add-to-list 'package-archives '("org" . "http:https://orgmode.org/elpa/"))
(setq package-enable-at-startup nil)
(package-initialize)
(unless package-archive-contents
(package-refresh-contents))
Fire up use-package
by itself. Configured so that it will install and compile any missing dependencies on load.
;; Bootstrap use-package
(unless (package-installed-p 'use-package)
(package-install 'use-package))
(setq use-package-verbose t)
(setq use-package-always-ensure t)
(eval-when-compile (require 'use-package))
(use-package auto-compile
:config (auto-compile-on-load-mode))
(setq load-prefer-newer t)
Fire up quelpa
AND quelpa-use-package
.
;; Boostrap quelpa
(unless (package-installed-p 'quelpa)
(with-temp-buffer
(url-insert-file-contents "https://raw.githubusercontent.com/quelpa/quelpa/master/quelpa.el")
(eval-buffer)
(quelpa-self-upgrade)))
;; Bootstrap quelpa-use-package
(quelpa
'(quelpa-use-package
:fetcher git
:url "https://github.com/quelpa/quelpa-use-package.git"))
(require 'quelpa-use-package)
(add-to-list 'load-path "~/.emacs.d/elisp")
(add-to-list 'load-path "~/.emacs.d/elpa")
;; Keep custom settings in a separate file to not pollute this one
(setq custom-file "~/.emacs.d/custom-settings.el")
(load custom-file t)
This is a nice little tidbit copied directly from Jamie Collinson’s config. Bumps startup speed.
;; Increase garbage collection during startup
(setq gc-cons-threshold 10000000)
;; Restore after startup
(add-hook 'after-init-hook
(lambda ()
(setq gc-cons-threshold 1000000)
(message "gc-cons-threshold restored to %S"
gc-cons-threshold)))
Ensures environment variables in Emacs are the same as user shell.
;; Get user PATH
(use-package exec-path-from-shell
:config
(when (memq window-system '(mac ns x))
(exec-path-from-shell-initialize)))
All the miscellaneous tweaks that customize Emacs just the way I like it. Much of this was taken from “Dave’s .emacs” but the rest was just ad hoc.
;; Ask "y" or "n" instead of "yes" or "no". Yes, laziness is great.
(fset 'yes-or-no-p 'y-or-n-p)
;; Highlight corresponding parentheses when cursor is on one
(show-paren-mode t)
;; Remove useless whitespace before saving a file
(setq-default nuke-trailing-whitespace-p t)
(add-hook 'before-save-hook 'whitespace-cleanup)
(add-hook 'before-save-hook (lambda() (delete-trailing-whitespace)))
Saved me many a time. No more having to say “no” on save because the file on disk has changed since I started editing it.
;; Auto-revert to disk on file change
(global-auto-revert-mode t)
;; Set locale to UTF8
(set-language-environment 'utf-8)
(set-terminal-coding-system 'utf-8)
(setq locale-coding-system 'utf-8)
(set-default-coding-systems 'utf-8)
(set-selection-coding-system 'utf-8)
(prefer-coding-system 'utf-8)
Because, yuck!
;; hide DOS ^M line-endings
(defun remove-dos-eol ()
"Do not show ^M in files containing mixed UNIX and DOS line endings."
(interactive)
(setq buffer-display-table (make-display-table))
(aset buffer-display-table ?\^M []))
(add-hook 'text-mode-hook 'remove-dos-eol)
Couple items here taken from “Dave’s .emacs” (marked DHA)
;; truncate shell buffer to 1024 - comint-buffer-maximum-size
(setq comint-buffer-maximum-size 2048)
(add-hook 'comint-output-filter-functions
'comint-truncate-buffer)
;; Disable undo in shell
(add-hook 'shell-mode-hook 'buffer-disable-undo)
;; shell-switcher
(setq shell-switcher-mode t)
;;; [DHA] Keep a much bigger shell command history for M-p
(setq comint-input-ring-size 1000)
;; Make ibuffer default instead of list-buffers
(defalias 'list-buffers 'ibuffer)
This one is copied directly from Sacha Chua’s config:
;; Better history
(setq savehist-file "~/.emacs.d/savehist")
(savehist-mode 1)
(setq history-length t
history-delete-duplicates t
savehist-save-minibuffer-history 1)
(setq savehist-additional-variables
'(kill-ring
search-ring
regexp-search-ring))
I used to just disable backup files (very annoying in production environments), but this solution is far more elegant. Both Sacha and Jamie do something like this to keep backups in a separate location.
;; Keep backup files in their own directory
(setq backup-directory-alist '(("." . "~/.emacs.d/backups"))
backup-by-copying 1
delete-old-versions -1
version-control t
vc-make-backup-files t)
(setq auto-save-file-name-transforms '((".*" "~/.emacs.d/auto-save-list/" t)))
In case I want to go back to no backups, I move the :tangle no
to the previous block and re-tangle with this:
;; Disable backup files
(setq make-backup-files nil
backup-inhibited t
auto-save-default nil)
According to emacswiki.org, this is faster than the default scp
method:
;; Faster than the default scp
(setq tramp-default-method "ssh")
Adapted from Emacs from Scratch:
;; Better dired config
(use-package dired
:ensure nil
:commands (dired dired-jump)
:bind (("C-x C-j" . dired-jump))
:custom ((dired-listing-switches "-agho --group-directories-first")))
(use-package dired-single)
(use-package all-the-icons-dired
:hook (dired-mode . all-the-icons-dired-mode))
(use-package dired-open
:config
;; Doesn't work as expected!
;;(add-to-list 'dired-open-functions #'dired-open-xdg t)
(setq dired-open-extensions '(("png" . "feh")
("mkv" . "mpv"))))
(use-package dired-hide-dotfiles
:hook (dired-mode . dired-hide-dotfiles-mode))
Couple items here taken from “Daves .emacs”, and some were lifted out of my old custom-set-variables
.
;;; Interface
;; ----------------------------------------------------------------------------
;; [DHA] Show the time in the mode line
;; (display-time) ; how late am I?
;; [DHA] Don't show the 'startup screen'
(setq inhibit-startup-message t) ; ok I've seen the copyleft &c
;; No alarm on C-g FFS!
(setq ring-bell-function 'ignore)
I like a single maximized frame per display these days.
;; Fullscreen maximized frame in GUI mode
; (custom-set-variables
; '(initial-frame-alist (quote ((fullscreen . maximized))))
(modify-all-frames-parameters '((fullscreen . maximized)))
;; disable toolbar-mode in GUI
(tool-bar-mode -1)
;; disable scroll-bar-mode
(scroll-bar-mode -1)
;; [DHA] I *never* use the stupid thing..
(menu-bar-mode -1)
;; [JEE] I do, so mapped to a toggle keybinding
(global-set-key (kbd "<C-menu>") 'menu-bar-mode)
Good ole winner-mode
and switch-window are enough for most things, but burly has its uses.
;; Undo and redo window configurations C-c left and C-c right
(winner-mode 1)
;; Word wrap on vertical split
(setq truncate-partial-width-windows nil)
;; switch-window
(use-package switch-window)
(global-set-key (kbd "C-x o") 'switch-window)
;; split window vertically
;; (split-window-right)
Want that crazy window config for D&D back, with all 11 windows and indirect buffers open? Burly time!
(use-package burly
:quelpa (burly :fetcher github :repo "alphapapa/burly.el"))
Groovy ‘lil package popwin.el does nothin’ but put all the noise buffers like *Completions*
in an easily dismissed popup window.
(use-package popwin)
(popwin-mode 1)
Don’t forget to do M-x all-the-icons-install-fonts
for all-the-icons.
;;; Appearance
;; ----------------------------------------------------------------------------
;; Did you run all-the-icons-install-fonts?
(use-package all-the-icons)
;; Set the default face
(set-face-attribute 'default nil :font "Fira Code Retina" :height 98)
;; Set the fixed pitch face
(set-face-attribute 'fixed-pitch nil :font "Fira Code Retina" :height 98)
Move the :tangle no
from theme to theme to enable different themes on reload.
Currently using Doom themes. These are a package deal, so change the line (load-theme 'doom-dark+ t)
to whichever theme you want to try.
(use-package doom-themes
:custom-face
;; I want the background darker (TODO: tweak to perfection)
(default ((t (:inherit nil :stipple nil :background "#202023" :foreground "#ffffff" :inverse-video nil :box nil :strike-through nil :overline nil :underline nil :slant normal :weight normal :height 98 :width normal :foundry "CTDB" :family "Fira Code Retina"))))
(org-block-background ((t (background: "#121215"))))
;; Give Level 1 & 2 org headings some oomph
(org-level-1 ((t (:inherit outline-1 :background "#455A64" :box (:line-width 1 :style released-button) :weight bold :height 1.1))))
(org-level-2 ((t (:inherit outline-2 :background "#35575b" :box (:line-width 1 :style released-button) :height 1.1))))
:config
;; Global settings (defaults)
(setq doom-themes-enable-bold t ; if nil, bold is universally disabled
doom-themes-enable-italic t) ; if nil, italics is universally disabled
;; Actual load here
(load-theme 'doom-dark+ t)
;; Enable flashing mode-line on errors
(doom-themes-visual-bell-config)
;; Enable custom neotree theme (all-the-icons must be installed!)
;(doom-themes-neotree-config)
;; or for treemacs users
;(setq doom-themes-treemacs-theme "doom-colors") ; use the colorful treemacs theme
;(doom-themes-treemacs-config)
;; Corrects (and improves) org-mode's native fontification.
(doom-themes-org-config))
Used Material theme for years. Lovely.
;defface org-block-begin-line
; '((t (:underline "#A7A6AA" :foreground "#008ED1" :background "#EAEAFF")))
; "Face used for the line delimiting the begin of source blocks.")
(defface org-block-background
'((t (:background "#121212")))
"Face used for the source block background.")
;defface org-block-end-line
; '((t (:overline "#A7A6AA" :foreground "#008ED1" :background "#EAEAFF")))
; "Face used for the line delimiting the end of source blocks.")
;; Extra dark BG with bright chars
(use-package color-theme-sanityinc-tomorrow
)
;; (load-theme 'sanityinc-tomorrow-bright)
;; Material design has lots of nice features (TODO: customize)
(use-package material-theme
:custom-face
;; I want the background darker (TODO: tweak to perfection)
(default ((t (:inherit nil :stipple nil :background "#202023" :foreground "#ffffff" :inverse-video nil :box nil :strike-through nil :overline nil :underline nil :slant normal :weight normal :height 98 :width normal :foundry "PfEd" :family "DejaVu Sans Mono"))))
;; Document Info and keywords are too big in Material
(org-document-info ((t (:foreground "#81d4fa" :height 1.0))))
(org-document-info-keyword ((t (:inherit font-lock-comment-face :foreground "#8bc34a" :height 1.0))))
;; Have to set the "org-hide" face to same as background esp for hide-stars/indent
(org-hide ((t (:background "#202023" :foreground "#202023"))))
;; Material's level 1 & 2 headings are too big
(org-level-1 ((t (:inherit outline-1 :background "#455A64" :box (:line-width 1 :style released-button) :weight bold :height 1.1))))
(org-level-2 ((t (:inherit outline-2 :background "#35575b" :box (:line-width 1 :style released-button) :height 1.1))))
)
Move the :tangle no
.
Settled on Doom Modeline for a while. Many of Doom’s nice-to-haves are available this way.
;; Doom-modeline might be fun, the themes are sweet
(use-package doom-modeline
:ensure t
:init (doom-modeline-mode 1))
Used Telephone Line for years. Highly extensible stand-alone, but the Doom mode-line seems to play nice with the Doom theme, so…
;; Improved mode-line (TODO: customize)
(use-package telephone-line
:init
(setq telephone-line-primary-left-separator 'telephone-line-cubed-left
telephone-line-secondary-left-separator 'telephone-line-cubed-hollow-left
telephone-line-primary-right-separator 'telephone-line-cubed-right
telephone-line-secondary-right-separator 'telephone-line-cubed-hollow-right)
(setq telephone-line-height 24
telephone-line-evil-use-short-tag t)
:config
(telephone-line-mode 1))
I’ve grouped these so that packages with system dependencies can be ignored by adding :tangle no
.
Several later packages need these, so let’s just always require them. Here’s links for reference:
;; Websocket, webserver, and request
(use-package websocket)
(use-package web-server)
(use-package request)
General programming utility packages with no system dependencies.
Because setting indents for each language is a PITA. EditorConfig is the solution!
Here’s a link to editorconfig-emacs. This used to require a system dependency, but that no longer appears to be the case.
;;; Programming utilities
;; ----------------------------------------------------------------------------
;; Editorconfig
(use-package editorconfig
:config
(editorconfig-mode 1))
;; Autopair
(use-package autopair
:config
(autopair-global-mode))
;; Silversearcher support - faster-than-grep
(use-package ag)
Rainbow colored nested parens, etc. Colorified color references. Fill column indicator.
;; Highlight nested parentheses (from Jamie's)
(use-package rainbow-delimiters
:config
(add-hook 'prog-mode-hook 'rainbow-delimiters-mode))
;; Color comprehension
(use-package rainbow-mode
:config
(setq rainbow-x-colors nil)
(add-hook 'prog-mode-hook 'rainbow-mode))
;; Init fill-column indicator (add to mode hooks per language)
(use-package fill-column-indicator
:init
(setq-default fci-rule-column 80))
There’s about 90 billion different ways to do these things. I’m still figuring out the best way for me.
I’ve been very unhappy with auto-complete, as the popup.el
bit keeps breaking and looking ugly. But company
wasn’t doing it for me, so here I am still using it as my primary auto-completion framework.
;; Auto-complete (TODO: enable ac-company?)
(setq popup-use-optimized-column-computation nil)
(use-package auto-complete
:init
(require 'auto-complete-config)
(add-to-list 'ac-dictionary-directories "~/.emacs.d/ac-dict")
:config
(ac-config-default))
Was trying Flycheck in combination with Elpy and discovered that it’s too much noise for my taste. Might revisit later. Untangled by default.
;; Flycheck (add to mode hooks per language)
(use-package flycheck
:config
(use-package flycheck-inline
:hook (flycheck-mode . turn-on-flycheck-inline)))
Need to revisit company-mode as a possible completion framework. Untangled by default.
;; Company support - text completion
(use-package company
:config
(setq company-idle-delay 0)
(use-package company-quickhelp
:config
(company-quickhelp-mode)))
Don’t use magit as often as I should. Old habits and all that.
;; Magit, of course
(use-package magit
:bind (("C-x g" . magit-status))
:config
(use-package magit-popup))
Don’t use yasnippet as often as I could. Usually keyboard macros get me there.
;; Yasnippet
(use-package yasnippet
:init
(setq yas-snippet-dirs '("~/.emacs.d/snippets"))
:bind (:map yas-minor-mode-map
("<tab>" . nil)
("TAB" . nil)
("<C-tab>" . yas-expand)
("C-j" . yas-next-field))
:config
(yas-global-mode 1))
So very, very useful. Here’s a link.
;; Multiple-cursors
(use-package multiple-cursors
:config
(define-key mc/keymap (kbd "<return>") nil)
:bind (("C-S-c C-S-c" . mc/edit-lines)
("C->" . mc/mark-next-like-this)
("C-<" . mc/mark-previous-like-this)
("C-c C-<" . mc/mark-all-like-this)
("C-S-<mouse-1>" . mc/add-cursor-on-click)))
Say buh-bye to Postman! Say hello to restclient.el. Includes org-babel
support with the ob-restclient language backend.
;; REST Client in Emacs? But of course!
(use-package restclient
:config
(use-package ob-restclient))
Because Emacs is the best way to deal with docker
and docker-compose
, hands down.
Here’s package links, as this is a deep topic:
- docker - Manage images and containers.
- dockerfile-mode - Mode for editing a
Dockerfile
. - docker-tramp - Tramp around in running containers.
- docker-compose-mode - Mode for editing a
docker-compose.yaml
file.
;; Emacs interface to Docker
(use-package docker
:ensure t
:bind ("C-c d" . docker)
:config
(use-package dockerfile-mode)
(use-package docker-tramp)
(use-package docker-compose-mode))
Because why not? Use vagrant-tramp to easily tramp around in running Vagrant VMs.
;; Emacs interface to vagrant
(use-package
vagrant-tramp)
I could definitely leverage Projectile more than I do.
;;; Navigation and projects
;; ----------------------------------------------------------------------------
;; Projectile
(use-package projectile
:bind-keymap
("C-c p" . projectile-command-map)
:config
(projectile-mode +1))
I used to use only Ido but trying Ivy out for a while.
;; Counsel with Ivy and Swiper - config cribbed as-is from Ivy documentation
;; Add to :bind to use swiper instead of incremental search:
;; ("C-s" . swiper)
(use-package ivy
:diminish
:bind (:map ivy-minibuffer-map
("TAB" . ivy-alt-done)
("C-m" . ivy-alt-done)
("C-j" . ivy-immediate-done)
("C-c C-r" . ivy-resume)
("<f6>" . ivy-resume))
:config
(setq ivy-use-virtual-buffers t)
(setq ivy-count-format "(%d/%d) ")
(setq ivy-extra-directories nil)
(ivy-mode 1))
(use-package ivy-rich
:init
(ivy-rich-mode 1))
(use-package counsel
:bind (("M-x" . counsel-M-x)
("C-x C-f" . counsel-find-file)
("<f1> f" . counsel-describe-function)
("<f1> v" . counsel-describe-variable)
("<f1> o" . counsel-describe-symbol)
("<f1> l" . counsel-find-library)
("<f2> i" . counsel-info-lookup-symbol)
("<f2> u" . counsel-unicode-char)
("C-c g" . counsel-git)
("C-c j" . counsel-git-grep)
("C-c k" . counsel-ag)
("C-c l" . counsel-locate)
("C-S-o" . counsel-rhythmbox)
("C-M-j" . counsel-switch-buffer)
:map minibuffer-local-map
("C-r" . counsel-minibuffer-history))
:config
(counsel-mode 1))
Sticking with dumb-jump for now I guess.
;; Dumb jump
(use-package dumb-jump
:config
(add-hook 'xref-backend-functions #'dumb-jump-xref-activate)
(dumb-jump-mode))
I should use highlight-symbol more.
;; Highlight-symbol
(use-package highlight-symbol
:bind (([(control f3)] . highlight-symbol-at-point)
([f3] . highlight-symbol-next)
([(shift f3)] . highlight-symbol-prev)
([(meta f3)] . highlight-symbol-query-replace)))
Tried Posframe out for a while, and might revisit for some things later, but it changed my workflow more than I thought. Seems handy from what I’ve seen. Might need to setup some hydras later tho?
Apparently cannot be installed with use-package
, so use M-x package-list-packages
to install it and related.
Untangled by default.
;; posframe - Is very general so there is lots of setup involved
(defun my-posframe-arghandler (buffer-or-name arg-name value)
(let ((info '(:internal-border-width 10 :background-color "black")))
(or (plist-get info arg-name) value)))
(use-package posframe
:config
;; (setq posframe-arghandler #'my-posframe-arghandler)
(use-package which-key-posframe
:config
(which-key-posframe-mode))
(use-package ivy-posframe
:config
(setq ivy-posframe-parameters
'((left-fringe . 8)
(right-fringe . 8)))
;; display at `ivy-posframe-style'
(setq ivy-posframe-display-functions-alist '((t . ivy-posframe-display)))
;; (setq ivy-posframe-display-functions-alist '((t . ivy-posframe-display-at-frame-center)))
;; (setq ivy-posframe-display-functions-alist '((t . ivy-posframe-display-at-window-center)))
;; (setq ivy-posframe-display-functions-alist '((t . ivy-posframe-display-at-frame-bottom-left)))
;; (setq ivy-posframe-display-functions-alist '((t . ivy-posframe-display-at-window-bottom-left)))
;; (setq ivy-posframe-display-functions-alist '((t . ivy-posframe-display-at-frame-top-center)))
(ivy-posframe-mode 1))
)
(set-face-attribute 'ivy-posframe nil :foreground "white" :background "black")
I generally use a separate terminal emulator, but sometimes I wanna use a terminal in Emacs, and when I do, I want that emulator to be vterm.
(use-package vterm
:commands vterm
:config
(setq term-prompt-regexp "^[^#$%>\n]*[#$%>] *") ;; Set this to match your custom shell prompt
;;(setq vterm-shell "zsh") ;; Set this to customize the shell to launch
(setq vterm-max-scrollback 10000))
Access web resources and tools using Emacs as a client.
Easily write and publish blog post to GitHub Pages without ever leaving Emacs. Uses Nikola static site generator.
;;; Blogging with Nikola
;; ----------------------------------------------------------------------------
;; Nikola.el config
(use-package nikola
:config
(setq nikola-output-root-directory "~/Dev/mine/joseph8th.github.io/")
(setq nikola-verbose t)
(setq nikola-webserver-auto t)
(setq nikola-new-post-extension "org")
(setq nikola-new-page-extension "org"))
;; Custom nikola-github-deploy function
(defun nikola-github-deploy ()
"Deploys the site to GitHub using github_deploy subcommand."
(interactive)
(message "Deploying the site to GitHub pages...")
(async-start
`(lambda ()
,(async-inject-variables "\\(nikola-\\)")
(setq output nil)
(let ((default-directory nikola-output-root-directory))
(run-hook-with-args 'nikola-deploy-before-hook "")
(if (not (eq nikola-deploy-before-hook-script nil))
(setq output (shell-command-to-string
nikola-deploy-before-hook-script)))
(setq output (shell-command-to-string (concat nikola-command " github_deploy")))
(if (not (eq nikola-deploy-after-hook-script nil))
(setq output (shell-command-to-string
nikola-deploy-after-hook-script)))
(run-hook-with-args 'nikola-deploy-before-hook ""))
output)
(lambda (result)
(if (cl-search "This command needs to run inside an existing Nikola site."
result)
(if (eq nikola-verbose t)
(message "Something went wrong. You may want to set nikola-verbo\
se to t and retry it.")
(message "Something went wrong. You may want to check the *Nikola*\
buffer."))
(message "Site deployed correctly."))
(if (eq nikola-verbose t)
(save-window-excursion
(switch-to-buffer "*Nikola*")
(let ((inhibit-read-only t))
(insert result)))))))
As in, search SO from inside Emacs. Untangled by default.
;;; Integrations
;; ----------------------------------------------------------------------------
;; SO in Emacs? Uh-huh. (Thx Jamie)
(use-package sx
:config
(bind-keys :prefix "C-c s"
:prefix-map my-sx-map
:prefix-docstring "Global keymap for SX."
("q" . sx-tab-all-questions)
("i" . sx-inbox)
("o" . sx-open-link)
("u" . sx-tab-unanswered-my-tags)
("a" . sx-ask)
("s" . sx-search)))
Yes, that Slack.
Untangled by default. See here for config details.
FIRST put your private credentials in a file like .emacs.d/slack-creds.el
filling out the following (do NOT ever tangle this block, it’s just an example):
;; Example ONLY
(setq my-slack-credentials
'((name "ACCOUNT")
(client-id "XXXXXXXXXXXX.YYYYYYYYYYYYY")
(client-secret "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZ")
(token "xoxs-XXXXXXXXXXXX-AAAAAAAAAAAA-BBBBBBBBBBBB-CCCCCCCCCCCCCCCCCCC")
(subscribed-channels CHANNEL1 CHANNEL2 CHANNEL3)))
THEN tangle the following.
;; Show desktop notifications
(use-package alert
:commands (alert)
:init
(setq alert-default-style 'notifier))
;; An IRC client
(use-package circe)
;; Show emojis in Emacs
(use-package emojify)
;; Make SURE this file exists and is valid
(load ~/.emacs.d/slack-creds.el)
(use-package slack
:commands (slack-start)
:init
(setq slack-buffer-emojify t)
(setq slack-prefer-current-team t)
(slack-register-team
:name (mapconcat 'identity (alist-get 'name my-slack-credentials) " ")
:default t
:client-id (mapconcat 'identity (alist-get 'client-id my-slack-credentials) " ")
:client-secret (mapconcat 'identity (alist-get 'client-secret my-slack-credentials) " ")
:token (mapconcat 'identity (alist-get 'token my-slack-credentials) " ")
:subscribed-channels '(alist-get 'subscribed-channels my-slack-credentials)
:full-and-display-names t))
Language-specific packages and configuration.
;;; Emacs-Lisp
;; ----------------------------------------------------------------------------
(add-hook 'emacs-lisp-mode-hook 'fci-mode)
I use the iPython3 interpreter, so make sure it’s installed.
;;; Python
;; ----------------------------------------------------------------------------
;; Basic python-mode config. I've been using this for years with no problems.
(use-package python
:mode ("\\.py\\'" . python-mode)
:interpreter ("/usr/bin/python3" . python-mode)
:hook (python-mode . fci-mode)
:config
(use-package pyvenv))
Tried elpy
and, honestly, it’s overkill for me. I do like being able to execute regions in the interpreter, so I’m leaving it here to play with down the line. Maybe I’ll change my mind.
;; Elpy makes Emacs a full Python IDE. Do I want that? I dunno yet. Guess I'll try it...
(use-package py-autopep8)
(use-package elpy
:init (setq python-shell-interpreter "ipython"
python-shell-interpreter-args "-i --simple-prompt")
:hook (elpy-mode . py-autopep8-enable-on-save)
:config
(elpy-enable))
Honestly, web-mode
is the way to go with mixed language files.
;;; PHP and HTML
;; ----------------------------------------------------------------------------
(use-package web-mode)
(use-package mmm-mode
:init
(setq mmm-global-mode 'maybe)
:config
(mmm-add-mode-ext-class 'html-mode "\\.php\\'" 'html-php))
(use-package php-mode
:hook ((php-mode . editorconfig-mode)
(php-mode . fci-mode)
(php-mode . (lambda ()
(defun ywb-php-lineup-arglist-intro (langelem)
(save-excursion
(goto-char (cdr langelem))
(vector (+ (current-column) c-basic-offset))))
(defun ywb-php-lineup-arglist-close (langelem)
(save-excursion
(goto-char (cdr langelem))
(vector (current-column))))
(c-set-offset 'arglist-intro 'ywb-php-lineup-arglist-intro)
(c-set-offset 'arglist-close 'ywb-php-lineup-arglist-close)))))
;;; Markdown (from Jamie's)
;; ----------------------------------------------------------------------------
(use-package markdown-mode
:commands (markdown-mode gfm-mode)
:mode (("README\\.md\\'" . gfm-mode)
("\\.md\\'" . markdown-mode)
("\\.markdown\\'" . markdown-mode))
:init (setq markdown-command "multimarkdown"))
(use-package markdown-preview-mode
:config
(add-to-list 'markdown-preview-stylesheets "https://raw.githubusercontent.com/richleland/pygments-css/master/emacs.css"))
;;; JSON
;; ----------------------------------------------------------------------------
(use-package json-mode)
(use-package json-reformat)
(use-package jsonrpc)
;;; XML
;; ----------------------------------------------------------------------------
;; pretty print xml region
(defun pretty-print-xml-region (begin end)
"Pretty format XML markup in region. You need to have nxml-mode
http:https://www.emacswiki.org/cgi-bin/wiki/NxmlMode installed to do
this. The function inserts linebreaks to separate tags that have
nothing but whitespace between them. It then indents the markup
by using nxml's indentation rules."
(interactive "r")
(save-excursion
(nxml-mode)
(goto-char begin)
;; split <foo><foo> or </foo><foo>, but not <foo></foo>
(while (search-forward-regexp ">[ \t]*<[^/]" end t)
(backward-char 2) (insert "\n") (incf end))
;; split <foo/></foo> and </foo></foo>
(goto-char begin)
(while (search-forward-regexp "<.*?/.*?>[ \t]*<" end t)
(backward-char) (insert "\n") (incf end))
(indent-region begin end nil)
(normal-mode))
(message "All indented!"))
(eval-after-load 'nxml-mode
'(define-key nxml-mode-map (kbd "C-c C-f") 'pretty-print-xml-region))
;;; Yaml
;; ----------------------------------------------------------------------------
(use-package yaml-mode
:init
(setq indent-tabs-mode nil)
:mode "\\.yml\\'"
:bind (:map yaml-mode-map
("C-m" . newline-and-indent)))
These are all untangled, because either I don’t use them very often, or they require additional setup that I haven’t bothered to document, yet.
This is another WIP and requires that Anaconda is being used, one way or another (or manual installation).
See EIN for requirements and other caveats.
;;; Emacs iPython Notebook (EIN) with Jupyter support
;; ----------------------------------------------------------------------------
(use-package ein
:config
(use-package ein-notebook)
(use-package ein-subpackages)
(use-package ein-mumamo))
There’s a bunch of dependencies required for rust-playground
and racer-mode
to work, so the init code for those sections are not tangled by default.
;;; Rust
;; TODO: change all 'add-hook' to use use-package 'hook:'
;; ----------------------------------------------------------------------------
;; Rust lang
(add-to-list 'exec-path "~/.cargo/bin")
(use-package rust-mode
:mode "\\.rs\\'"
:config (setq rust-format-on-save t)
:init
(add-hook 'rust-mode-hook 'fci-mode))
(use-package rustic)
(use-package cargo
:init
(add-hook 'rust-mode-hook 'cargo-minor-mode)
(add-hook 'rust-mode-hook
(lambda ()
(local-set-key (kbd "C-c <tab>") #'rust-format-buffer)))
(add-hook 'toml-mode-hook 'cargo-minor-mode))
(use-package racer
:init
(add-hook 'rust-mode-hook #'racer-mode)
(add-hook 'racer-mode-hook #'eldoc-mode)
(add-hook 'racer-mode-hook #'company-mode)
:config
(use-package company-racer)
(define-key rust-mode-map (kbd "TAB") #'company-indent-or-complete-common)
(setq racer-cmd "~/.cargo/bin/racer")
(setq racer-rust-src-path "~/Dev/rust/rust/src"))
;; Flycheck for Rust
(use-package flycheck-rust
:init
(add-hook 'flycheck-mode-hook #'flycheck-rust-setup))
I don’t use Go very often, so it’s not tangled by default.
;;; Go
;; ----------------------------------------------------------------------------
(use-package go-mode)
Built-in js-mode works better for me than js2-mode or js3 in Emacs 26.
;;; Javascript
;; ----------------------------------------------------------------------------
(add-hook 'js3-mode-hook 'fci-mode)
(add-to-list 'auto-mode-alist '("\\.js\\'" . js2-mode))
(add-hook 'js-mode-hook 'js2-minor-mode)
I’ll get around to tricking out \LaTeX\ one of these days.
;;; LaTeX
;; ----------------------------------------------------------------------------
;;(load "auctex.el" nil t t)
;;(load "preview-latex.el" nil t t)
Really, really nice to have for rendering ASCII charts and embedding them in org-mode
exports. Must install ditaa.jar
and update the path for this to work.
;;; ditaa.jar
;; ----------------------------------------------------------------------------
(setq org-ditaa-jar-path "/usr/bin/ditaa")
GNUPlot can be pretty handy, but I don’t use it very often.
;;; GNUPlot
;; ----------------------------------------------------------------------------
;; move the files gnuplot.el to someplace in your lisp load-path or
;; use a line like
;; (setq load-path (append (list "/path/to/gnuplot") load-path))
;; these lines enable the use of gnuplot mode
(autoload 'gnuplot-mode "gnuplot" "gnuplot major mode" t)
(autoload 'gnuplot-make-buffer "gnuplot" "open a buffer in gnuplot mode" t)
;; this line automatically causes all files with the .gp extension to
;; be loaded into gnuplot mode
(setq auto-mode-alist (append '(("\\.gp$" . gnuplot-mode)) auto-mode-alist))
;; This line binds the function-9 key so that it opens a buffer into
;; gnuplot mode
(global-set-key [(f9)] 'gnuplot-make-buffer)
Next level PDF viewer, editor.
;;; PDF-Tools
;; ----------------------------------------------------------------------------
(use-package pdf-tools
:pin manual ;; manually update
:config
;; initialise
(pdf-tools-install)
;; open pdfs scaled to fit page
(setq-default pdf-view-display-size 'fit-page)
;; automatically annotate highlights
(setq pdf-annot-activate-created-annotations t)
;; use normal isearch
(define-key pdf-view-mode-map (kbd "C-s") 'isearch-forward))
Some basic org-mode
preferences. Mostly vanilla, except I like visual-line-mode
for org files.
Oh yeah, and have to completely override org-html-fontify-code
for export to work with fci-mode
, or get a bunch of weird extraneous characters on newline. See this thread.
;;; Org-mode
;; ----------------------------------------------------------------------------
;; Get htmlize
(use-package htmlize)
;; Install ob-php into symlinked ./elisp from GitHub
(require 'ob-php)
;; Tell Emacs where to find ditaa.jar
(setq org-ditaa-jar-path "/usr/share/ditaa/ditaa.jar")
;; Want a more local copy of org-mode so that I can override stuff if I want
(use-package org
:mode ("\\.org\\'" . org-mode)
:hook ((org-mode . visual-line-mode)
(org-mode . org-indent-mode))
:config
(setq org-confirm-babel-evaluate nil)
(setq org-todo-keywords
'((sequence "TODO" "DEV" "READY" "QA" "FAILED" "|" "DONE" "CLOSED")))
(org-babel-do-load-languages
'org-babel-load-languages
'((shell . t)
(python . t)
(ditaa . t)
(sql . t)
(restclient . t)
(php . t)
)))
;; Want to ignore headlines but not section contents if :ignore: added
;(use-package titletoc)
;(require 'ox-extra)
;(ox-extras-activate '(ignore-headlines)
;; Better subtree narrowing to indirect buffer
(defun vimacs/org-narrow-to-subtree
()
(interactive)
(let ((org-indirect-buffer-display 'current-window))
(if (not (boundp 'org-indirect-buffer-file-name))
(let ((above-buffer (current-buffer))
(org-filename (buffer-file-name)))
(org-tree-to-indirect-buffer (1+ (org-current-level)))
(setq-local org-indirect-buffer-file-name org-filename)
(setq-local org-indirect-above-buffer above-buffer))
(let ((above-buffer (current-buffer))
(org-filename org-indirect-buffer-file-name))
(org-tree-to-indirect-buffer (1+ (org-current-level)))
(setq-local org-indirect-buffer-file-name org-filename)
(setq-local org-indirect-above-buffer above-buffer)))))
(defun vimacs/org-widen-from-subtree
()
(interactive)
(let ((above-buffer org-indirect-above-buffer)
(org-indirect-buffer-display 'current-window))
(kill-buffer)
(switch-to-buffer above-buffer)))
(define-key org-mode-map (kbd "<M-tab>") 'vimacs/org-narrow-to-subtree)
(define-key org-mode-map (kbd "<M-iso-lefttab>") 'vimacs/org-widen-from-subtree)
;; Patch ox-html.el org-html-fontify-code to avoid weird newline chars with fci-mode
(eval-after-load "ox-html"
'(defun org-html-fontify-code (code lang)
"Color CODE with htmlize library.
CODE is a string representing the source code to colorize. LANG
is the language used for CODE, as a string, or nil."
(when code
(cond
;; No language. Possibly an example block.
((not lang) (org-html-encode-plain-text code))
;; Plain text explicitly set.
((not org-html-htmlize-output-type) (org-html-encode-plain-text code))
;; No htmlize library or an inferior version of htmlize.
((not (and (or (require 'htmlize nil t)
(error "Please install htmlize from \
https://github.com/hniksic/emacs-htmlize"))
(fboundp 'htmlize-region-for-paste)))
;; Emit a warning.
(message "Cannot fontify src block (htmlize.el >= 1.34 required)")
(org-html-encode-plain-text code))
(t
;; Map language
(setq lang (or (assoc-default lang org-src-lang-modes) lang))
(let* ((lang-mode (and lang (intern (format "%s-mode" lang)))))
(cond
;; Case 1: Language is not associated with any Emacs mode
((not (functionp lang-mode))
(org-html-encode-plain-text code))
;; Case 2: Default. Fontify code.
(t
;; htmlize
(setq code
(let ((output-type org-html-htmlize-output-type)
(font-prefix org-html-htmlize-font-prefix))
(with-temp-buffer
;; Switch to language-specific mode.
(funcall lang-mode)
;; BEGIN PATCH: fix fci-mode export
(when (require 'fill-column-indicator nil 'noerror)
(fci-mode -1))
;; END PATCH
(insert code)
;; Fontify buffer.
(org-font-lock-ensure)
;; Remove formatting on newline characters.
(save-excursion
(let ((beg (point-min))
(end (point-max)))
(goto-char beg)
(while (progn (end-of-line) (< (point) end))
(put-text-property (point) (1+ (point)) 'face nil)
(forward-char 1))))
(org-src-mode)
(set-buffer-modified-p nil)
;; Htmlize region.
(let ((org-html-htmlize-output-type output-type)
(org-html-htmlize-font-prefix font-prefix))
(org-html-htmlize-region-for-paste
(point-min) (point-max))))))
;; Strip any enclosing <pre></pre> tags.
(let* ((beg (and (string-match "\\`<pre[^>]*>\n?" code) (match-end 0)))
(end (and beg (string-match "</pre>\\'" code))))
(if (and beg end) (substring code beg end) code)))))))))
)
;; This is needed as of Org 9.2
(require 'org-tempo)
(add-to-list 'org-structure-template-alist '("sh" . "src shell"))
(add-to-list 'org-structure-template-alist '("el" . "src emacs-lisp"))
(add-to-list 'org-structure-template-alist '("py" . "src python"))
For my oporg
project (WIP). Untangled by default.
;;; oporg - Settings and convenience for oporg and org-ehtml
;; ----------------------------------------------------------------------------
(use-package org-ehtml
:init
(setq org-ehtml-docroot (expand-file-name "~/public_org"))
(setq org-ehtml-everything-editable t))
(defun public-org-start (approot port)
"Prompts for APPROOT and PORT to the run the web-server."
(interactive
(list
(read-string
(format "Path to app root (%s): " org-ehtml-docroot)
nil nil org-ehtml-docroot)
(read-string
(format "Port to run the web-server on (%d): " 8888)
nil nil 8888)
))
(setq org-ehtml-docroot (expand-file-name approot))
(ws-start org-ehtml-handler port))
(defun public-org-stop ()
(interactive)
(ws-stop-all))
(use-package org-d20)
Based on this post. For creative writing.
;;; Writing mode
;; ----------------------------------------------------------------------------
(use-package writeroom-mode)
(defun writing-mode ()
(interactive)
(setq buffer-face-mode-face '(:family "dejavu sans mono" :height 150))
(buffer-face-mode)
(linum-mode 0)
(writeroom-mode 1)
(blink-cursor-mode)
(visual-line-mode 1)
(setq truncate-lines nil)
(setq-default line-spacing 5)
(setq global-hl-line-mode nil)
)
;;; Standard Manuscript Format using LaTeX sffms package
;; ----------------------------------------------------------------------------
;; org mode latex standard manuscript formats
;; https://chrismaiorana.com/org-mode-standard-manuscript-format/
;;
;; For your org file heading
;; #+LaTeX_CLASS: novel (or, short, whichever)
;; #+LATEX_HEADER: \runningtitle{Shortened Title}
;; #+LATEX_HEADER: \wordcount{?}
(require 'ox-latex)
(unless (boundp 'org-latex-classes)
(setq org-latex-classes nil))
(add-to-list 'org-latex-classes
'("novel"
"\\documentclass[novel,geometry,letterpaper,courier]{sffms}
\\surname{Edwards}
\\address{7770 SW 90th St., J-10\u005C\u005C Miami, FL\u005C\u005C [email protected]}
\\disposable
\\usepackage{hyperref}
[NO-DEFAULT-PACKAGES]
[NO-PACKAGES]"
("\\chapter*{%s}")
("\\chapter*{%s}")
("\\chapter*{%s}")
("%s")
))
;; (setq org-latex-with-hyperref nil)
;; (setq org-latex-pdf-process '("pdflatex %f"))
Random functions that I have found handy at one point or another, and somehow made their way into my init.el
.
Very handy when you want to search-and-replace a lot of pairs in one go.
;;; Custom functions
;; ----------------------------------------------------------------------------
;; Search and replace pair-by-pair
(defun batch-replace-strings (replacement-alist)
"Prompt user for pairs of strings to search/replace, then do so in the current buffer"
(interactive (list (batch-replace-strings-prompt)))
(dolist (pair replacement-alist)
(save-excursion
(replace-string (car pair) (cdr pair)))))
(defun batch-replace-strings-prompt ()
"prompt for string pairs and return as an association list"
(let (from-string
ret-alist)
(while (not (string-equal "" (setq from-string (read-string "String to search (RET to stop): "))))
(setq ret-alist
(cons (cons from-string (read-string (format "Replace %s with: " from-string)))
ret-alist)))
ret-alist))
Makes the old joke about Emacs being a great OS…
EXWM is special, and I don’t always want it, or some of the customizations it necessitates, but when I do, I want it to be easy and not interfere with my existing desktop environment (if any).
The easiest thing was to tangle it to a separate file, exwm-init.el
, which I then symlink into my .emacs.d/
when I want it enabled.
This literate README works for me as both a stand-alone WM on a bare-bones Arch Linux VM with no DE, and on my laptop as an alternative window manager to the default (Pop!_OS/Gnome). I can do the ole switcheroo at login.
EXWM has its own system dependencies (like xorg-xinit
) so refer to the EXWM User Guide before tangling this section.
For now, I just used package-list-packages
to install everything default. I’ll revisit with use-package
later.
exwm
- Will install requirements as well
Optional packages:
exwm-edit
- Edit any editable element in a bufferexwm-mff
- Mouse follows focushelm-exwm
- Because sometimes helm’s the way to go, and it needs to work
To Tangle: delete :tangle no
from the block header.
;;; Load the EXWM config from a separate file if it exists
(if (file-exists-p "~/.emacs.d/exwm-init.el")
(load "~/.emacs.d/exwm-init.el"))
To Tangle: change :tangle no
to :tangle exwm-init.el
.
;;; ----------------------------------------------------------------------------
;; exwm - emacs X window manager
;; (menu-bar-mode -1)
;; (tool-bar-mode -1)
;; (scroll-bar-mode -1)
(fringe-mode 1)
;; (ido-mode 1)
;; (server-start)
(require 'exwm)
(require 'exwm-config)
(exwm-config-ido)
(setq exwm-workspace-number 4)
;; All buffers created in EXWM mode are named "*EXWM*". You may want to
;; change it in `exwm-update-class-hook' and `exwm-update-title-hook', which
;; are run when a new X window class name or title is available. Here's
;; some advice on this topic:
;; + Always use `exwm-workspace-rename-buffer` to avoid naming conflict.
;; + For applications with multiple windows (e.g. GIMP), the class names of
; all windows are probably the same. Using window titles for them makes
;; more sense.
;; In the following example, we use class names for all windows except for
;; Java applications and GIMP.
(add-hook 'exwm-update-class-hook
(lambda ()
(unless (or (string-prefix-p "sun-awt-X11-" exwm-instance-name)
(string= "gimp" exwm-instance-name))
(exwm-workspace-rename-buffer exwm-class-name))))
(add-hook 'exwm-update-title-hook
(lambda ()
(when (or (not exwm-instance-name)
(string-prefix-p "sun-awt-X11-" exwm-instance-name)
(string= "gimp" exwm-instance-name))
(exwm-workspace-rename-buffer exwm-title))))
;; Global keybindings can be defined with `exwm-input-global-keys'.
;; Here are a few examples:
(setq exwm-input-global-keys
`(
;; Bind "s-r" to exit char-mode and fullscreen mode.
([?\s-r] . exwm-reset)
;; Bind "s-w" to switch workspace interactively.
([?\s-w] . exwm-workspace-switch)
;; Bind "s-0" to "s-9" to switch to a workspace by its index.
,@(mapcar (lambda (i)
`(,(kbd (format "s-%d" i)) .
(lambda ()
(interactive)
(exwm-workspace-switch-create ,i))))
(number-sequence 0 9))
;; Bind "s-&" to launch applications ('M-&' also works if the output
;; buffer does not bother you). [?\s-&]
([?\s-&] . (lambda (command)
(interactive (list (read-shell-command "$ ")))
(start-process-shell-command command nil command)))
;; Bind "s-<f2>" to "slock", a simple X display locker.
([s-f2] . (lambda ()
(interactive)
(start-process "" nil "/usr/bin/slock")))))
;; To add a key binding only available in line-mode, simply define it in
;; `exwm-mode-map'. The following example shortens 'C-c q' to 'C-q'.
(define-key exwm-mode-map [?\C-q] #'exwm-input-send-next-key)
;; The following example demonstrates how to use simulation keys to mimic
;; the behavior of Emacs. The value of `exwm-input-simulation-keys` is a
;; list of cons cells (SRC . DEST), where SRC is the key sequence you press
;; and DEST is what EXWM actually sends to application. Note that both SRC
;; and DEST should be key sequences (vector or string).
;;(setq exwm-input-simulation-keys
;; '(
;; ;; movement
;; ([?\C-b] . [left])
;; ([?\M-b] . [C-left])
;; ([?\C-f] . [right])
;; ([?\M-f] . [C-right])
;; ([?\C-p] . [up])
;; ([?\C-n] . [down])
;; ([?\C-a] . [home])
;; ([?\C-e] . [end])
;; ([?\M-v] . [prior])
;; ([?\C-v] . [next])
;; ([?\C-d] . [delete])
;; ([?\C-k] . [S-end delete])
;; ;; cut/paste.
;; ([?\C-w] . [?\C-x])
;; ([?\M-w] . [?\C-c])
;; ([?\C-y] . [?\C-v])
;; ;; search
;; ([?\C-s] . [?\C-f])))
;; You can hide the minibuffer and echo area when they're not used, by
;; uncommenting the following line.
;(setq exwm-workspace-minibuffer-position 'bottom)
;; Multiple-screen support
;; (require 'exwm-randr)
;; (setq exwm-randr-workspace-output-plist '(0 "VGA1"))
;; (add-hook 'exwm-randr-screen-change-hook
;; (lambda ()
;; (start-process-shell-command
;; "xrandr" nil "xrandr --output VGA1 --left-of LVDS1 --auto")))
;; (exwm-randr-enable)
;;; In case we're embedded in LXDE
;; (defun exwm-logout ()
;; (interactive)
;; (recentf-save-list)
;; (save-some-buffers)
;; (start-process-shell-command "logout" nil "lxsession-logout"))
;; Do not forget to enable EXWM. It will start by itself when things are
;; ready. You can put it _anywhere_ in your configuration.
(exwm-enable)
As described in the EXWM documentation, make sure xorg-xinit
is installed on the system.
Using GDM, .xinitrc
will not interfere with the existing Gnome DE. BUT, if the .xinitrc
or .xsessions
files already exist, this will BREAK SHIT. It’s still doable but not in the scope of this README.
To Tangle: change :tangle no
to :tangle xinitrc.exwm
. Otherwise, just use as reference.
# You may need to comment out the next line to disable access control.
#xhost +SI:localuser:$USER
# Set themes, etc.
gnome-settings-daemon &
# Set fallback cursor.
xsetroot -cursor_name left_ptr
# Set keyboard repeat rate.
xset r rate 200 60
# If Emacs is started in server mode, `emacsclient` is a convenient way to
# edit files in place (used by e.g. `git commit`).
export VISUAL=emacsclient
export EDITOR="$VISUAL"
# Finally launch emacs.
#exec dbus-launch --exit-with-session emacs
#compton &
# guake &
# emacs --daemon -f exwm-enable
# exec emacsclient -a "" -c
# exec emacs -f exwm-enable
exec emacs
To use the tangled xinitrc.exwm
, copy or symlink it to $HOME/.xinitrc
.
Switch to a new TTY console. Usually tty1
is the Desktop Manager itself, and tty2
is you as you read this. To change TTY, just do C-M-F#
where “#” is the Function Key number. Ie, C-M-F3
will get tty3
.
Then just login to the console, and run startx
. Emacs should start, running as an X Window Manager.
If there is no other X Window server running on the system (ie, you logged in to the console directly, not from a graphical DM) then you can start EXWM with xinit -- vt0#
where ‘#’ is the TTY number.
EXWM may be an option from the existing DM login screen. First do: ln -s ~/.xinitrc ~/.xsessions
Then create the file /usr/share/xsessions/exwm.desktop
, like the following.
NOTE: you need to hardcode your <PATHTO>
since this is a config file not a bash script.
[Desktop Entry] Name=EXWM Comment=Emacs X Window Manager Exec=<PATHTO>/.xsessions Type=Application
Now, you should have an ‘EXWM’ option in the gear icon on the GDM login screen. If the testing went OK, then this should work, too since it’s calling the same init script.
In case I want to only load configs for this machine, not keeping it in this file.
;; Load custom init file?
(if (file-exists-p "~/.emacs.d/custom-init.el")
(load "~/.emacs.d/custom-init.el"))
Tangle on save? Reload after tangle? These hooks will ask you after every save.
;; Local Variables: ;; eval: (add-hook ‘after-save-hook (lambda ()(if (y-or-n-p “Reload?”)(load-file user-init-file))) nil t) ;; eval: (add-hook ‘after-save-hook (lambda ()(if (y-or-n-p “Tangle?”)(org-babel-tangle))) nil t) ;; End: