merge(PR#11): Move bits of Emacs configuration into local packages

As requested by @wpcarro, some bits of my Emacs configuration are now in separate local packages (located at `//depot/tools/emacs-pkgs/`).

Specifically this change introduces:

* `tools.emacs-pkgs.dottime`: A package to render time in the modeline as [dottime](https://dotti.me)
* `tools.emacs-pkgs.term-switcher`: A package to quickly switch between and open new terminal instances in EXWM using ivy

My Emacs configuration is updated to accomodate these refactorings.
This commit is contained in:
Vincent Ambo 2019-12-15 22:59:43 +00:00 committed by GitHub
commit e8b184adcc
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 192 additions and 87 deletions

23
third_party/emacs/carp-mode.nix vendored Normal file
View file

@ -0,0 +1,23 @@
{ pkgs, ... }:
with pkgs.third_party;
with emacsPackagesNg;
melpaBuild rec {
pname = "carp-mode";
version = "3.0";
packageRequires = [ clojure-mode ];
recipe = builtins.toFile "recipe" ''
(carp-mode :fetcher github
:repo "carp-lang/carp"
:files ("emacs/*.el"))
'';
src = fetchFromGitHub {
owner = "carp-lang";
repo = "carp";
rev = "6954642cadee730885717201c3180c7acfb1bfa9";
sha256 = "1pz4x2qkwjbz789bwc6nkacrjpzlxawxhl2nv0xdp731y7q7xyk9";
};
}

View file

@ -0,0 +1,7 @@
{ pkgs, ... }:
pkgs.third_party.emacsPackagesNg.trivialBuild rec {
pname = "dottime";
version = "1.0";
src = ./dottime.el;
}

View file

@ -0,0 +1,59 @@
;;; dottime.el --- use dottime in the modeline
;;
;; Copyright (C) 2019 Google Inc.
;;
;; Author: Vincent Ambo <tazjin@google.com>
;; Version: 1.0
;; Package-Requires: (cl-lib)
;;
;;; Commentary:
;;
;; This package changes the display of time in the modeline to use
;; dottime (see https://dotti.me/) instead of the standard time
;; display.
;;
;; Modeline dottime display is enabled by calling
;; `dottime-display-mode' and dottime can be used in Lisp code via
;; `dottime-format'.
(require 'cl-lib)
(require 'time)
(defun dottime--format-string ()
"Creates the dottime format string for `format-time-string'
based on the local timezone."
(let* ((offset-sec (car (current-time-zone)))
(offset-hours (/ offset-sec 60 60)))
(if (/= offset-hours 0)
(concat "%m-%dT%H·%M" (format "%0+3d" offset-hours))
"%m-%dT%H·%M")))
(defun dottime--display-time-update-advice (orig)
"Function used as advice to `display-time-update' with a
rebound definition of `format-time-string' that renders all
timestamps as dottime."
(cl-letf* ((format-orig (symbol-function 'format-time-string))
((symbol-function 'format-time-string)
(lambda (&rest _)
(funcall format-orig (dottime--format-string) nil t))))
(funcall orig)))
(defun dottime-format (&optional time)
"Format the given TIME in dottime. If TIME is nil, the current
time will be used."
(format-time-string (dottime--format-string) time t))
(defun dottime-display-mode (arg)
"Enable time display as dottime. Disables dottime if called
with prefix 0 or nil."
(interactive "p")
(if (or (eq arg 0) (eq arg nil))
(advice-remove 'display-time-update #'dottime--display-time-update-advice)
(advice-add 'display-time-update :around #'dottime--display-time-update-advice))
(display-time-update))
(provide 'dottime)

View file

@ -0,0 +1,14 @@
{ pkgs, ... }:
with pkgs.third_party.emacsPackagesNg;
melpaBuild rec {
pname = "term-switcher";
version = "1.0";
src = ./term-switcher.el;
packageRequires = [ dash ivy s ];
recipe = builtins.toFile "recipe" ''
(term-switcher :fetcher github :repo "tazjin/depot")
'';
}

View file

@ -0,0 +1,72 @@
;;; term-switcher.el --- Easily switch between open X11 terminals
;;
;; Copyright (C) 2019 Google Inc.
;;
;; Author: Vincent Ambo <tazjin@google.com>
;; Version: 1.0
;; Package-Requires: (dash ivy s)
;;
;;; Commentary:
;;
;; This package adds a function that lets users quickly switch between
;; different open X11 terminals using ivy.
;;
;; It is primarily intended to be used by EXWM users who use graphical
;; terminals inside of Emacs.
;;
;; Users MUST configure the group `term-switcher' and can then bind
;; `ts/switch-to-terminal' to an appropriate key.
(require 'dash)
(require 'ivy)
(require 's)
(defgroup term-switcher nil
"Customization options for configuring `term-switcher' with the
user's terminal emulator of choice.")
(defcustom term-switcher-program "gnome-terminal"
"X11 terminal application to use."
:type '(string)
:group 'term-switcher)
(defcustom term-switcher-buffer-prefix "Term"
"String prefix for X11 terminal buffers. For example, if your
EXWM configuration renames X11 terminal buffers to
`Term</foo/bar>' you might want to use `Term' as the matching
prefix."
:type '(string)
:group 'term-switcher)
(defun ts/run-terminal-program ()
(message "Starting %s..." term-switcher-program)
(start-process-shell-command term-switcher-program nil term-switcher-program))
(defun ts/open-or-create-terminal-buffer (buffer-name)
"Switch to the buffer with BUFFER-NAME or create a new buffer
running the configured X11 terminal."
(let ((buffer (get-buffer buffer-name)))
(if (not buffer)
(ts/run-terminal-program)
(switch-to-buffer buffer))))
(defun ts/is-terminal-buffer (buffer)
"Determine whether BUFFER runs an X11 terminal."
(and (equal 'exwm-mode (buffer-local-value 'major-mode buffer))
(s-starts-with? term-switcher-buffer-prefix (buffer-name buffer))))
(defun ts/switch-to-terminal ()
"Switch to an X11 terminal buffer, or create a new one."
(interactive)
(let ((terms (-map #'buffer-name
(-filter #'ts/is-terminal-buffer (buffer-list)))))
(if terms
(ivy-read "Switch to terminal buffer: "
(cons "New terminal" terms)
:caller 'ts/switch-to-terminal
:preselect (s-concat "^" term-switcher-buffer-prefix)
:require-match t
:action #'ts/open-or-create-terminal-buffer)
(ts/run-terminal-program))))
(provide 'term-switcher)

View file

@ -148,7 +148,7 @@
(exwm-input-set-key (kbd "s-p") #'ivy-password-store)
;; Add X11 terminal selector to a key
(exwm-input-set-key (kbd "C-x t") #'counsel-switch-to-terminal)
(exwm-input-set-key (kbd "C-x t") #'ts/switch-to-terminal)
;; Toggle between line-mode / char-mode
(exwm-input-set-key (kbd "C-c C-t C-t") #'exwm-input-toggle-keyboard)

View file

@ -19,11 +19,11 @@
(use-package ace-window
:bind (("C-x o" . ace-window))
:init
:config
(setq aw-keys '(?f ?j ?d ?k ?s ?l ?a)
aw-scope 'frame))
(use-package auth-source-pass :init (auth-source-pass-enable))
(use-package auth-source-pass :config (auth-source-pass-enable))
(use-package avy
:bind (("M-j" . avy-goto-char)
@ -34,10 +34,11 @@
(use-package company
:hook ((prog-mode . company-mode))
:init (setq company-tooltip-align-annotations t))
:config (setq company-tooltip-align-annotations t))
(use-package dash)
(use-package dash-functional)
(use-package dottime :config (dottime-display-mode t))
(use-package gruber-darker-theme)
(use-package ht)
(use-package hydra)
@ -46,19 +47,19 @@
(emacs-lisp-mode . paredit-mode)))
(use-package multiple-cursors)
(use-package pinentry
:init
:config
(setq epa-pinentry-mode 'loopback)
(pinentry-start))
(use-package rainbow-delimiters :hook (prog-mode . rainbow-delimiters-mode))
(use-package rainbow-mode)
(use-package s)
(use-package smartparens :init (smartparens-global-mode))
(use-package string-edit)
(use-package telephone-line) ;; configuration happens outside of use-package
(use-package undo-tree :init (global-undo-tree-mode))
(use-package term-switcher)
(use-package undo-tree :config (global-undo-tree-mode))
(use-package uuidgen)
(use-package which-key :init (which-key-mode t))
(use-package which-key :config (which-key-mode t))
;;
;; Applications in emacs
@ -66,7 +67,7 @@
(use-package magit
:bind ("C-c g" . magit-status)
:init (setq magit-repository-directories '(("/home/vincent/projects" . 2))))
:config (setq magit-repository-directories '(("/home/vincent/projects" . 2))))
(use-package password-store)
(use-package pg)
@ -100,7 +101,7 @@
(use-package haskell-mode)
(use-package jq-mode
:init (add-to-list 'auto-mode-alist '("\\.jq\\'" . jq-mode)))
:config (add-to-list 'auto-mode-alist '("\\.jq\\'" . jq-mode)))
(use-package kotlin-mode
:hook ((kotlin-mode . (lambda ()
@ -109,7 +110,7 @@
(use-package lsp-mode)
(use-package markdown-mode
:init
:config
(add-to-list 'auto-mode-alist '("\\.txt\\'" . markdown-mode))
(add-to-list 'auto-mode-alist '("\\.markdown\\'" . markdown-mode))
(add-to-list 'auto-mode-alist '("\\.md\\'" . markdown-mode)))
@ -151,7 +152,6 @@
settings
modes
bindings
term-setup
eshell-setup))
(telephone-line-setup)
(ace-window-display-mode)

View file

@ -27,21 +27,6 @@
(font . ,font)))
(set-frame-font font t t))
;; Display modeline time in dottime (see https://dotti.me)
;;
;; This is done in a way that initially seems more complicated than
;; one would like, but this is unfortunately required due to the way
;; `format-time-string' handles timezones.
(defun format-dottime-advice (orig _ &optional _ _)
(let* ((offset-sec (car (current-time-zone)))
(offset-hours (/ offset-sec 60 60))
(dottime (if (/= offset-hours 0)
(concat "%M-%Dt%H·%M" (format "%0+3d" offset-hours))
"%m-%dT%H·%M")))
(apply orig '("%m-%dT%H·%M" nil t))))
(advice-add 'format-time-string :around #'format-dottime-advice)
;; Configure telephone-line
(defun telephone-misc-if-last-window ()
"Renders the mode-line-misc-info string for display in the

View file

@ -19,8 +19,7 @@
(show-paren-mode 1)
;; Always auto-close parantheses and other pairs
;; (replaced by smartparens)
;; (electric-pair-mode)
(electric-pair-mode)
;; Keep track of recent files
(recentf-mode)

View file

@ -1,36 +0,0 @@
;; Utilities for X11 terminal buffers.
(defvar x11-terminal-program "gnome-terminal"
"Which X11 terminal application to use.")
(defvar x11-terminal-buffer-prefix "Term"
"String prefix for X11 terminal buffer names.")
(defun open-or-create-terminal-buffer (buffer-name)
"Switch to the buffer with BUFFER-NAME or create a new buffer
running the configured X11 terminal."
(let ((buffer (get-buffer buffer-name)))
(if (not buffer)
(run-external-command x11-terminal-program)
(switch-to-buffer buffer))))
(defun is-terminal-buffer (buffer)
"Determine whether BUFFER runs an X11 terminal."
(and (equal 'exwm-mode (buffer-local-value 'major-mode buffer))
(s-starts-with? x11-terminal-buffer-prefix (buffer-name buffer))))
(defun counsel-switch-to-terminal ()
"Switch to an X11 terminal buffer, or create a new one."
(interactive)
(let ((terms (-map #'buffer-name
(-filter #'is-terminal-buffer (buffer-list)))))
(if terms
(ivy-read "Switch to terminal buffer: "
(cons "New terminal" terms)
:caller 'counsel-switch-to-terminal
:preselect (s-concat "^" x11-terminal-buffer-prefix)
:require-match t
:action #'open-or-create-terminal-buffer)
(run-external-command x11-terminal-program))))
(provide 'term-setup)

View file

@ -5,29 +5,12 @@
with pkgs;
with third_party.emacsPackagesNg;
with third_party.emacs;
let
localPackages = pkgs.tools.emacs-pkgs;
emacsWithPackages = (third_party.emacsPackagesNgGen third_party.emacs26).emacsWithPackages;
carpMode = melpaBuild {
pname = "carp-mode";
ename = "carp-mode";
version = "3.0";
recipe = builtins.toFile "recipe" ''
(carp-mode :fetcher github
:repo "carp-lang/carp"
:files ("emacs/*.el"))
'';
packageRequires = [ clojure-mode ];
src = third_party.fetchFromGitHub {
owner = "carp-lang";
repo = "carp";
rev = "6954642cadee730885717201c3180c7acfb1bfa9";
sha256 = "1pz4x2qkwjbz789bwc6nkacrjpzlxawxhl2nv0xdp731y7q7xyk9";
};
};
tazjinsEmacs = (emacsWithPackages(epkgs:
# Actual ELPA packages (the enlightened!)
(with epkgs.elpaPackages; [
@ -82,7 +65,6 @@ let
rainbow-delimiters
restclient
sly
smartparens
string-edit
swiper
telephone-line
@ -99,7 +81,7 @@ let
]) ++
# Custom packages
[ carpMode ]
[ carp-mode localPackages.dottime localPackages.term-switcher ]
));
in third_party.writeShellScriptBin "tazjins-emacs" ''
exec ${tazjinsEmacs}/bin/emacs \
@ -108,5 +90,5 @@ in third_party.writeShellScriptBin "tazjins-emacs" ''
--no-site-lisp \
--no-init-file \
--directory ${./config} \
--eval "(require 'init)"
--eval "(require 'init)" $@
''