Posts on tag: emacs
Table of contents
Portable Emacs Eshell Aliases
I maintain one emacs config file (.emacs) for all environments and systems whereever I use emacs. From time to time I use eShell but aliases were differing from system to system. The reason was, that they were stored in a separate file (~/.emacs.d/eshell/aliases) which I do not re-distribute.
So, my solution was to maintain eshell aliases inside my .emacs file. Here are my current alias definitions:
;; actual aliases (+alias 'l '(ls -laF)) (+alias 'll '(ls -l)) (+alias 'la '(ls -a)) (+alias 'lt '(ls -ltr $*)) (+alias '.. '(cd ..)) (+alias '... '(cd ../..)) (+alias '.... '(cd ../../..)) (+alias '..... '(cd ../../../..)) (+alias 'md '(mkdir -p)) (+alias 'emacs '(find-file $1)) (+alias 'less '(find-file-read-only $1))
As you can see, I use a pretty handy function +alias to create them and I use symbols, not strings which looks cleaner. For this to work, I use the following function:
(setq eshell-command-aliases-list ())(defun +alias (al cmd) “handy wrapper function to convert alias symbols to alias
strings to avoid writing 4 quotes per alias. AL is a single-word
symbol naming the alias, CMD is a list symbol describing the
command." (add-to-list ’eshell-command-aliases-list (list (symbol-name al) (mapconcat ‘symbol-name cmd ” “))))
So, first the aliases list will be cleared, just in case there's some aliases file left in the filesystem (which I ignore from now on). The function +alias then converts the given symbols to strings and adds them to the alias list.
I could of course use strings directly but that's too much quotes to type and looks confusing. Just for completeness, here's how the aliases list looks like after the above conversion:
(("less" "find-file-read-only-other-window $1") ("emacs" "find-file-other-window $1") ("md" "mkdir -p") ("....." "cd ../../../..") ("...." "cd ../../..") ("..." "cd ../..") (".." "cd ..") ("lt" "ls -ltr $*") ("la" "ls -a") ("ll" "ls -l") ("l" "ls -laF"))
Emacs: comfortable macro recording
A couple of weeks ago I discovered elmacro mode, which is exactly what I was searching for: it turns unreadable recorded emacs macros into editable emacs lisp code. I LOVE it.
However, both the default emacs macro interface as well as the elmacro interface were not comfortable enough to me. So, I came up with this rather long solution for my macro management:
If I want to record a macro, I press F6
. Then I do whatever I'd like to record and when I'm done, I press F6
again. That's it. The code below takes care of all the horrible details: while recording a macro a red indicator will be shown in my mode line. The macro will be saved to disk. Another function with the same name with -repeat
appended will be saved as well. Both will be evaluated so that I can use them immediately. The -repeat
version allows me to run the macro repeatedly with an interactive menu. When I press a
it will be repeated til EOF, when I press ENTER
it will be executed once (which can be repeated, hence the name), when I press e
I can enter another macro name (with completion) and when I press q
the menu will be quit. The same function will be called when I press CTRL-F6
, it will present the mentioned menu, so that I can also just execute the last recorded macro.
;; always enable emacro mode
(require 'elmacro) (elmacro-mode);; var must be global so it can be shared across functions
(setq my-macro-name “last-macro”);; ignore some certain events
(add-to-list ’elmacro-unwanted-commands-regexps "^(mouse.*)$") (add-to-list ’elmacro-unwanted-commands-regexps "^(my-start-or-stop-macro)$");; called when saving a macro
(defun my-get-macro-name() “Ask for a macro name, check for duplicates. If the given name is already
defined, ask again (and again until unique). If a buffer with the given name
exists, kill it (that is, the buffer is there but has not been saved or evaluated
yet). Return the name as string." (interactive) (let ((done nil) (name nil) (mbuf nil) (err ”")) (while (not done) (setq name (read-string (format "%s - enter macro name (last-macro): “ err) nil nil “last-macro”)) (if (fboundp (intern name)) (setq err (format “macro ‘%s is already defined” name)) (setq mbuf (format ”* elmacro - %s *" name)) (if (get-buffer mbuf) (with-current-buffer mbuf (kill-buffer mbuf))) (setq done t))) name));; interactive macro prompt with completion
(defun my-get-exec-macro-name() “Ask for a macro name to be executed” (interactive) (let ((macros ()) (N 1) (S nil) (T "")) (dolist (entry (cdr (assoc my-macro-file load-history ))) (setq S (cdr entry)) (setq T (symbol-name S)) (push (list T N) macros) (setq N (1+ N))) (completing-read “enter macro name: “ macros nil t nil)));; the heart of my elmacro stuff: starts macro recording or
;; stops it if emacs is already recording. This way I can
;; use 1 keybinding for start+stop
(defun my-start-or-stop-macro() “start macro or stop if started” (interactive) (if (eq defining-kbd-macro nil) (progn (elmacro-clear-command-history) (start-kbd-macro nil) (message “Recording macro. Finish with <shift-F6> …")) (progn (call-interactively ’end-kbd-macro) (setq my-macro-name (my-get-macro-name)) (elmacro-show-last-macro my-macro-name) (message “Recording done. Execute with <C-F6>, save or <C-x C-e> buffer…"))));; better than the default function
(defun my-exec-last-macro(&optional ARG) “execute last macro (or ARG, if given) repeatedly after every <ret>, abort with
C-g or q, and repeat until EOF after pressing a. If macro defun is known
(i.e. because you evaluated the elmacro buffer containing the generated
defun), it will be executed. Otherwise the last kbd-macro will be executed." (interactive) (let ((melm-count 0) (melm-all nil) (melm-abort nil) (melm-beg (eobp)) (melm-code (or ARG my-macro-name)))
(if (eobp)
(if (yes-or-no-p "(point) is at end of buffer. Jump to top?") (goto-char (point-min)))) (while (and (not melm-abort) (not (eobp))) (when (not melm-all) (message (concat (format “Executing last macro ‘%s (%d). Keys:\n” melm-code melm-count) "<enter> repeat once\n” “a repeat until EOF\n” “e enter macro name to execute\n” "<C-g> or q abort ..\n “)) (setq K (read-event)) (cond ((or (eq K ‘return) (eq K ‘C-f6)) t) ((equal (char-to-string K) “q”) (setq melm-abort t)) ((equal (char-to-string K) “a”) (message “Repeating until EOF”)(setq melm-all t)) ((equal (char-to-string K) “e”) (setq my-macro-name (my-get-exec-macro-name))) (t (setq melm-abort t)))) (if (not melm-abort) (progn (if (fboundp (intern melm-code)) (call-interactively (intern melm-code)) (call-interactively ‘call-last-kbd-macro)) (setq melm-count (1+ melm-count))))) (if (and (eq melm-count 0) (eq (point) (point-max))) (message "(point) is at end of buffer, aborted”) (message (format “executed ‘%s %d times” melm-code melm-count)))));; I use my own macro file, my-lisp is defined somewhere else
(setq my-macro-file (concat my-lisp "/macros.el”));; load if it exists
(if (file-exists-p my-macro-file) (load-file my-macro-file));; store the macro defun generated by elmacro-mode to disk
(defun my-macro-store() “store current macro to emacs config” (interactive) (copy-region-as-kill (point-min) (point-max)) (if (not (get-buffer “macros.el”)) (find-file my-macro-file)) (with-current-buffer “macros.el” (goto-char (point-max)) (newline) (insert ”;;") (newline) (insert (format ”;; elmacro added on %s” (current-time-string))) (newline) (yank) (newline) (save-buffer)) (switch-to-buffer nil) (delete-window));; add a repeating variant of the generated function,
;; evaluate and store both of them to disk
(defun my-macro-gen-repeater-and-save() “generate repeater and save the defun’s Runs when (point)
is at 0,0 of generated defun." (next-line) (goto-char (point-max)) (newline) (insert (format "(defun %s-repeat()\n” my-macro-name)) (insert " (interactive)\n") (insert (format " (my-exec-last-macro "%s"))\n" my-macro-name)) (newline) (eval-buffer) (my-macro-store));; so, always evaluate generated macro code, store it to disk and
;; close the temp buffer
(advice-add ’elmacro-show-defun :after ‘(lambda (&rest args) (my-macro-gen-repeater-and-save)));; workflow: shift-F6 … do things … shift-F6, enter a name, new
;; buffer with macro defun appears. C-x C-e evals it. C-F6 (repeatedly)
;; executes it.
(global-set-key (kbd "<f6>") ‘my-start-or-stop-macro) (global-set-key (kbd "<C-f6>") ‘my-exec-last-macro);; face used to indicate ongoing macro recording on the mode line
(defface rec-face ‘((t (:background “red” :foreground “white” :weight bold))) “Flag macro recording in mode-line” :group ‘my-mode-line-faces);; custom modeline including recording marker
(setq-default mode-line-format (list "%e" mode-line-front-space mode-line-mule-info mode-line-modified mode-line-remote " “ mode-line-buffer-identification ” “ mode-line-position ” (%m) “'(<span style="color: #8a2be2;">:eval</span> (propertize (<span style="color: #0000ff;">if</span> (eq defining-kbd-macro t) <span style="color: #ff0000;">"[REC]"</span>) 'face 'rec-face)) mode-line-end-spaces))</pre>
Emacs: read-only copy of current buffer
Very often I split the emacs frame into two windows with the same buffer in both. For example on the left side I have a class definition and on the right side I implement it (so that part of the buffer is below the definition). While this works like a charm, sometimes I stumble upon an obstacle: if I want to change the class definition for testing, I cannot see the old definition for comparision. It has changed after all.
So I wrote this function which creates a copy of the current buffer, names it appropriately, makes it read-only, splits the current window and places the read-only copy on the right. Now I can see the old implementation while changing the current one, I can copy parts of the old stuff back into the current (because UNDO might remove some of the new things I want to keep) and so on. I bound this to C-c C-p, which you might want to change.
Here's the code. Put into .emacs to try it out:
;; ** Make a read-only copy of the current buffer
;; I just create a new read-only buffer and copy the contents of the
;; current one into it, which can be used as backup
(defvar copy-counter 0)(defun get-copy-buffer-name() “return unique copy buffer name” (let ( (name (concat "*COPY “ (buffer-name (current-buffer)) ” (RO)")) ) (if (not (get-buffer name)) (progn (setq copy-counter (1+ copy-counter)) (concat name "<" (number-to-string copy-counter) ">") ) (concat name) )))
(defun copy-buffer-read-only() “Create a read-only copy of the current buffer” (interactive) (let ( (old-buffer (current-buffer)) (new-buffer-name (get-copy-buffer-name)) ) (progn (delete-other-windows) (split-window-horizontally) (other-window 1) (if (not (eq (get-buffer new-buffer-name) nil)) (kill-buffer (get-buffer new-buffer-name)) ) (set-buffer (get-buffer-create new-buffer-name)) (insert-buffer-substring old-buffer) (read-only-mode) (switch-to-buffer new-buffer-name) (other-window 1) )))
(defalias ‘cp ‘copy-buffer-read-only)
(global-set-key (kbd “C-c C-p”) ‘copy-buffer-read-only)
There's even a screenshot (the read-only copy can be seen on the right):
Emacs: copy things at point without marking
This emacs config snippet is the predecessor to viking-mode: it allows me to copy thing at point without marking it beforehand. I just press a prefix key followed by an abbreviation of the thing to copy:
- C-c w copy word
- C-c l copy line
- C-c p copy paragraph
- C-c a copy all (the whole buffer)
Like viking-mode the copied thing is being highlighted shortly for visual feedback.
Put this into your .emacs config to try it out:
;; ** Easily copy word, line, paragraph or buffer without marking
;; with ideas from:
;; http://emacs.stackexchange.com/questions/1051/copy-region-from-emacs-without-newlines
;; https://www.emacswiki.org/emacs/CopyWithoutSelection (defun my-blink(begin end) "blink a region. used for copy and delete" (interactive) (let* ((rh (make-overlay begin end))) (progn (overlay-put rh 'face '(:background "DodgerBlue" :foreground "White")) (sit-for 0.2 t) (delete-overlay rh) )))(defun get-point (symbol &optional arg) “get the point” (funcall symbol arg) (point) )
(defun copy-thing (begin-of-thing end-of-thing &optional arg) “Copy thing between beg & end into kill ring. Remove leading and
trailing whitespace while we’re at it. Also, remove whitespace before
column, if any. Also, font-lock will be removed, if any. Also, the
copied region will be highlighted shortly (it ‘blinks’)." (save-excursion (let* ((beg (get-point begin-of-thing 1)) (end (get-point end-of-thing arg))) (progn (copy-region-as-kill beg end) (with-temp-buffer (yank) (goto-char 1) (while (looking-at ”[ \t\n\r]") (delete-char 1)) (delete-trailing-whitespace) (delete-whitespace-rectangle (point-min) (point-max)) ;; del column \s, hehe
(font-lock-unfontify-buffer) ;; reset font lock
(kill-region (point-min) (point-max)) ) ))))(defun copy-word (&optional arg) “Copy word at point into kill-ring” (interactive “P”) (my-blink (get-point ‘backward-word 1) (get-point ‘forward-word 1)) (copy-thing ‘backward-word ‘forward-word arg) (message “word at point copied”))
(defun copy-line (&optional arg) “Copy line at point into kill-ring, truncated” (interactive “P”) (my-blink (get-point ‘beginning-of-line 1) (get-point ’end-of-line 1)) (copy-thing ‘beginning-of-line ’end-of-line arg) (message “line at point copied”))
(defun copy-paragraph (&optional arg) “Copy paragraph at point into kill-ring, truncated” (interactive “P”) (my-blink (get-point ‘backward-paragraph 1) (get-point ‘forward-paragraph 1)) (copy-thing ‘backward-paragraph ‘forward-paragraph arg) (message “paragraph at point copied”))
(defun copy-buffer(&optional arg) “Copy the whole buffer into kill-ring, as-is” (interactive “P”) (progn (my-blink (point-min) (point-max)) (copy-region-as-kill (point-min) (point-max)) (message “buffer copied”)))
;; “speaking” bindings CTRL-[c]opy [w]ord, etc…
(global-set-key (kbd “C-c w”) ‘copy-word)
(global-set-key (kbd “C-c l”) ‘copy-line) (global-set-key (kbd “C-c p”) ‘copy-paragraph) (global-set-key (kbd “C-c a”) ‘copy-buffer)
Update 2017-02-12:
Sometimes during programming in emacs I need to copy a whole function. If a function contains empty lines, copy-paragraph is insuffcient. So, I added copy-defun, which copies the whole function (at point, that is, point must be inside the function). This works with almost all programming modes, as long as it implementsbeginning-of-defun
and end-of-defun
.
<pre>
(defun copy-defun (&optional arg) “Copy function at point into kill-ring” (interactive “P”) (my-blink (get-point ‘beginning-of-defun) (get-point ’end-of-defun)) (kill-ring-save (get-point ‘beginning-of-defun) (get-point ’end-of-defun)) (message “function at point copied”))
(global-set-key (kbd “C-c f”) ‘copy-defun)
Emacs screen reader - novel mode
I'm using Xah's novel function for a couple of weeks and found myself enhancing it time and again. Today - yet another day on my way south using the train - I took the opportunity and made a separate mode of the stuff. The result is novel-mode and I'm quite satisfied with it so far.
Novel mode is a minor mode. It makes the current buffer quasi read-only, disabled all distractions (like widgets, mode-line etc), enlarges the font size, line spacing, adds a margin left and right and adds an one key key-map which makes it possible to make dynamic adjustments. There's a GIF demo on the github page. Here are some screenshots:
Bare bones emacs before novel mode is active:
Novel mode activated:
After pressing "h" or "?"
After pressing [right] a couple of times: margins increased
After pressing [+] a couple of times: font size increased
After pressing "i": video display inverted