From 0c4563cb2856159a75cc3f1fb4593c0da497f3e3 Mon Sep 17 00:00:00 2001 From: Thomas von Dein Date: Wed, 2 Sep 2020 20:44:21 +0200 Subject: [PATCH] added rust mode --- .emacs | 23 +- emacs.html | 10090 ++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 10109 insertions(+), 4 deletions(-) diff --git a/.emacs b/.emacs index 1c42d25..a8660b4 100644 --- a/.emacs +++ b/.emacs @@ -1,4 +1,4 @@ -;; Toms Emacs Config - portable - version ("20200101.01") -*-emacs-lisp-*- +;; Toms Emacs Config - portable - version ("20200902.01") -*-emacs-lisp-*- ;; * Introduction ;; This is my emacs config, it is more than twenty years old. It @@ -785,6 +785,9 @@ ;; - added smerge hydra plus alias 'merge ;; - fixed window resize hydra help +;; 20200902.01 +;; - added rust mode + ;; ** TODO ;; - check helpful https://github.com/wilfred/helpful @@ -812,7 +815,7 @@ ;; My emacs config has a version (consisting of a timestamp with a ;; serial), which I display in the mode line. So I can clearly see, if ;; I'm using an outdated config somewhere. -(defvar tvd-emacs-version "20200101.01") +(defvar tvd-emacs-version "20200902.01") ;; -------------------------------------------------------------------------------- @@ -2114,6 +2117,22 @@ col1, col2" (add-to-list 'file-coding-system-alist '("\\.vala$" . utf-8)) (add-to-list 'file-coding-system-alist '("\\.vapi$" . utf-8)) +;; -------------------------------------------------------------------------------- +;; *** rust mode +(autoload 'rust-mode "rust-mode" nil t) + +(defun rustlings-done () + "I use this with rustlings" + (interactive) + (search-backward "DONE") + (move-beginning-of-line 1) + (kill-line) + (save-buffer)) + +(setq auto-mode-alist + (append '(("\\.\\(rs\\)$" . rust-mode)) + auto-mode-alist)) + ;; -------------------------------------------------------------------------------- ;; *** python mode diff --git a/emacs.html b/emacs.html index 4200095..688a264 100644 --- a/emacs.html +++ b/emacs.html @@ -3,7 +3,7 @@ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> - + @@ -228,10 +228,10096 @@ for the JavaScript code in this tag.
+
+

Table of Contents

+
+ +
+
+

+Toms Emacs Config - portable - version ("20200902.01") -*-emacs-lisp-*- +

+
+

1 Introduction

+
+

+This is my emacs config, it is more than twenty years old. It +mostly contains stuff implemented by myself, but there are also +snippets I found here and there. The config will probably not be +usefull for anyone else but myself. +

+ +

+If you're reading the html exported version: be advised, that I do +NOT maintain my emacs config with "literate programming". Instead I +maintain a plain old .emacs file, which I use at home and work, on +windows, linux and freebsd, console or X11. I use outshine minor +mode to organize my config and I use outorg to export it to org +mode and from there to html. +

+ +

+Also I don't use any packaging mechanism, instead I download all +the required elisp files manually and update them only if +required. There's a melpa config toggle though, which I only use to +try out new modes. I distribute my .emacs config along with the +lisp directory to all systems where I need it using a Makefile and +scp. The reason is that I work on a couple of systems without +direct internet access, where packaging or git don't work. So, I +don't use these things nowhere. It's ok for me, I'm used to it. +

+ +

+Another thing you might wonder about are my key bindings or +(sometimes) the lack thereof. My problem with key bindings is that +I don't have any useful prefixes left. I am using ONLY commandline +tools, my window manager is Xmonad, I use screen, bash and +mutt. The only applications where I use the mouse is firefox and +gimp. So, it is very hard to avoid conflicts AND memoize new key +bindings. Some key bindings are so deeply wired into muscle memory +that I could use them while drunk or dying. +

+ +

+Therefore I use lots of aliases in emacs for not-so-regular used +functions, which turned out to be sometimes easier to type than an +actual key binding. +

+ +

+The html export has been created with the function +outshine-to-html, written by myself, see below. +

+
+
+ + +
+

2 Config Log, Trivia, Notes, Changes

+
+
+

2.1 Changelog

+
+

+20160420.03: +

+
    +
  • started with Changelog and outshine mode
  • +
  • fixed tabs
  • +
  • reorganized keys
  • +
  • added new goto line func
  • +
+ +

+20160421.01: +

+
    +
  • added smex
  • +
  • added show-keys()
  • +
  • added redo
  • +
  • ssh et. al. interactive in eshell
  • +
  • added recompile()
  • +
+ +

+20160421.02: +

+
    +
  • added dividers
  • +
  • using org headers
  • +
  • better show-keys()
  • +
+ +

+20160421.03: +

+
    +
  • added windows support
  • +
+ +

+20160421.04: +

+
    +
  • added elisp repl support
  • +
+ +

+20160424.01: +

+
    +
  • added custom modeline
  • +
  • added which-func-mode
  • +
  • shortened some major mode names
  • +
  • added diminish for shorter minor mode names
  • +
  • added better printing menu
  • +
+ +

+20160425.01: +

+
    +
  • fixed ielm integration
  • +
  • C-x e = eval (buffer|region)
  • +
  • C-x C-e = send (buffer|region) to ielm and eval there
  • +
+ +

+20160425.02: +

+
    +
  • fix word wrapping
  • +
+ +

+20160426.01: +

+
    +
  • fixed mode-line config 4 win emacs
  • +
  • added M-<up|down> move-region
  • +
+ +

+20160426.01: +

+
    +
  • added markdown
  • +
+ +

+20160427.01+02: +

+
    +
  • cosmetics
  • +
+ +

+20160428.01: +

+
    +
  • fringe cursor
  • +
+ +

+20160429.01: +

+
    +
  • file name completion
  • +
  • C-# finally, search for symbol at point
  • +
  • C-c C-c now comments or uncomments regios or line, whatever is current
  • +
+ +

+20160501.01: +

+
    +
  • no outshine minor in python
  • +
  • added recent files support
  • +
+ +

+20160501.02: +

+
    +
  • added margin() function, no key binding though
  • +
+ +

+20160503.01: +

+
    +
  • added C-q fill+justify paragraph macro
  • +
  • added alias 'i' for info manuals
  • +
+ +

+20160503.02: +

+
    +
  • added 'cp to create read-only buffer copy
  • +
+ +

+20160504.01: +

+
    +
  • better fringe, now also inversed with C-c i
  • +
+ +

+20160505.01: +

+
    +
  • added electric-align mode
  • +
  • better outline header colors
  • +
  • no more line numbers in sk occur buffer
  • +
+ +

+20160507.01: +

+
    +
  • disable electric-align-momde (broken), using M-x align instead
  • +
  • hightlighting TABs with extra font
  • +
+ +

+20160509.01: +

+
    +
  • fixed margin()
  • +
  • discovered that C-x 0 deletes current window, god did I miss this one!
  • +
+ +

+20160510.01: +

+
    +
  • added kill-all-buffers()
  • +
+

+20160510.02: +

+
    +
  • no more load-file
  • +
  • added C-c [wlpa]: easy copy things at point +without marking them
  • +
+ +

+20160511.01: +

+
    +
  • better buffer names with uniquify
  • +
+ +

+20160511.02: +

+
    +
  • copy-* functions now blink region
  • +
  • added del-* functions, bound to C-d: +press multiple times to delete word, line, paragraph, buffer
  • +
+ +

+20160513.01: +

+
    +
  • fixed END key func
  • +
+ +

+20160516.01: +

+
    +
  • removed C-d stuff, replaced with vikiing-mode
  • +
+ +

+20160517.01: +

+
    +
  • changed highlight face
  • +
  • enabled debug-on-error in lispmode
  • +
  • enabled IDO mode globally, I just tend to love love love it
  • +
+ +

+20160517.02: +

+
    +
  • added workgroup.el, started experimenting
  • +
  • enabled SuperL (for workgroups)
  • +
+ +

+20160519.01: +

+
    +
  • fixed write-file, now ido mode is disabled for this one.
  • +
+ +

+20160520.01: +

+
    +
  • no x-sel on windows (C-v+C-c => emacs doesn't work anymore otherwise)
  • +
  • added eldoc mode to elisp hook
  • +
+ +

+20160520.02: +

+
    +
  • added novel-mode, for better reading
  • +
+ +

+20160522.01: +

+
    +
  • added vi's % jump paren emulation
  • +
  • enhanced novel-mode
  • +
  • enabled save-place mode which is VERY useful in combination with +novel-mode
  • +
+ +

+20160523.01: +

+
    +
  • detached novel-mode into its own module, maintain on github +enabled with C-n
  • +
+ +

+20160526.01: +

+
    +
  • added toggle-melpa
  • +
+ +

+20160527.01: +

+
    +
  • added htmlize
  • +
+ +

+20160529.01: +

+
    +
  • added html-listify
  • +
+ +

+20160530.01: +

+
    +
  • added key chords
  • +
  • added open-line-above+below
  • +
+ +

+20160602.01: +

+
    +
  • C-q now fills and pressing it again un-fills
  • +
+ +

+20160606.01: +

+
    +
  • deactivated key-chords, I didn't use them and they were annoying.
  • +
+ +

+20160609.01: +

+
    +
  • added puppet mode
  • +
+ +

+20160614.01: +

+
    +
  • added rotate-text (C-t)
  • +
  • added macro math (C-x-0) (0 used as =)
  • +
+ +

+20160713.01: +

+
    +
  • fixed indent for Makefiles
  • +
+ +

+20160729.01: +

+
    +
  • rm duplicate abbr defs
  • +
+ +

+20160916.01: +

+
    +
  • enable mouse mark to copy
  • +
+ +

+20160926.01: +

+
    +
  • Dont kill-buffer, kill-this-buffer instead
  • +
+ +

+20160928.01: +

+
    +
  • change macro math C-x 0 to C-x C-0 so that C-0 is +usable again for close window
  • +
  • elisp mode: debug-on-error only on non-cygwin
  • +
+ +

+20161011.01: +

+
    +
  • added dos2unix and unix2dos
  • +
+ +

+20161014.01: +

+
    +
  • fix auto-indent in conf-mode
  • +
  • force C-c C-c comment-uncomment in conf-mode
  • +
+ +

+20161018.01: +

+
    +
  • more effective conf-mode disarming (own defun)
  • +
+ +

+20161022.01: +

+
    +
  • better paren mode
  • +
+ +

+20161024.01: +

+
    +
  • fixed org mode hook
  • +
+ +

+20161027.01: +

+
    +
  • turn off tramp stuff in kill-all-buffers as well, +so that after executing it, no more ssh prompt +appears on C-x f.
  • +
+ +

+20161106.01: +

+
    +
  • added iedit mode with C-c e
  • +
  • added file-open support to eshell (aliases: vi + emacs)
  • +
  • much better C-l behavior in eshell (eshell/clear)
  • +
+ +

+20161205.01: +

+
    +
  • added SLIME, sbcl and paredit support, only loaded when exists
  • +
+ +

+20161206.01: +

+
    +
  • elisp mode: debug-on-error finally completeley disabled
  • +
  • added alias 'table, which enables org-mode table support everywhere
  • +
+ +

+20170205.01: +

+
    +
  • started with ETAGS support
  • +
+ +

+20170212.01: +

+
    +
  • added copy-defun (C-c f) to copy whole functions as is
  • +
+ +

+20170212.02: +

+
    +
  • now using € (alt-r + e) as jump to etag
  • +
+ +

+20170215.02: +

+
    +
  • added goto-last-change (C-b)
  • +
  • +test section
  • +
  • paredit
  • +
+ +

+20170215.02: +

+
    +
  • disabled workgoups mode, don't use it, doesn't load correctly
  • +
  • fixed windows switch, no more printing popup on startup
  • +
+ +

+20170220.01: +

+
    +
  • finally disabled aggressive-indent, it annoys more than it helps
  • +
  • added some bookmark aliases (bm, to, bl, like apparix)
  • +
  • added C-c y [..] copy+yank functions so that I can copy and paste +stuff very fast with one key commbo, like yy in vi.
  • +
  • added copy-parens, copy-quote, copy-help (help message)
  • +
+ +

+20170220.02: +

+
    +
  • fixed C-c y y: indent correctly
  • +
+ +

+20170220.03: +

+
    +
  • fixed C-y+mouse-2: both use primary selection
  • +
+ +

+20170221.01: +

+
    +
  • added which-key
  • +
+ +

+20170223.01: +

+
    +
  • org-mode enhancements, C-n capture from everywhere
  • +
  • fixed org-mode todo keywords
  • +
  • fixed duplicate yank on win32 on mouse2
  • +
+ +

+20170223.01: +

+
    +
  • forgot to mv novel-mode to C-c C-n
  • +
  • better org heading faces
  • +
+ +

+20170224.01: +

+
    +
  • finally fixed C-t, now works everywhere
  • +
  • added more org short commands
  • +
+ +

+20170224.02: +

+
    +
  • fixed org-mode M-return
  • +
  • added support for windmove (WINDOWS-Key+Arrow: switch window)
  • +
+ +

+20170224.03: +

+
    +
  • better org colours
  • +
+ +

+20170224.03: +

+
    +
  • better org capture tpl (DRAFT)
  • +
  • capturing works now globally, even if no org file is open
  • +
  • using org-indent 4
  • +
+ +

+20170224.05: +

+
    +
  • fixed org tpls
  • +
+ +

+20170227.01: +

+
    +
  • fix cut/paste org subtress
  • +
  • M-o now switch buffer if 1 window, else switch window
  • +
+ +

+20170227.02: +

+
    +
  • added alias 'dp which displays everything +there is to know about point (like current face, mode, etc)
  • +
+ +

+20170228.01: +

+
    +
  • org-refile now works recursivly with completion
  • +
  • org-refile also now uses ido-mode and completes in minibuffer
  • +
  • added alias '2table which converts CSV region to table
  • +
  • added shortcut formatting defuns 'bold, 'italic, 'underline and 'code +which call 'org-emphasize respectively on current region, +including key bindings with org mode keymap (C-c b,/,c,_)
  • +
  • hide emphasized markers in org mode
  • +
  • renamed 'recompile to 'recompile-el and fixed it
  • +
  • added 'info-find-file
  • +
+ +

+20170301.01: +

+
    +
  • added 'tvd-org-left-or-level-up bound to <C-left> in org mode
  • +
  • <C-up|down> in org mode now jump up on current level and +fold current one and unfolds the target heading
  • +
  • enabled org-bullets
  • +
  • customized height of org-level faces
  • +
+ +

+20170301.02: +

+
    +
  • org mode emphasize shortcuts (C-c b…) expand region if +theres no region active.
  • +
+ +

+20170301.03: +

+
    +
  • dis line num in org (faster)
  • +
+ +

+20170303.01: +

+
    +
  • elmacro support added, incl fix for org and outshine, +F6 starts (or stops) a macro and displays the generated +defun. CTRL-F6 executes the last macro interactively, +<ret> repeats, a repeats til EOF, q aborts, e enter macro +(with completion)
  • +
  • C-x C-s on * elmacro … * buffer stores it to tvd-macro-file
  • +
+ +

+20170305.01: +

+
    +
  • added elmacro defadvice, run after done with macro, it will +be evaluated and saved along with a repeater defun.
  • +
  • display red [REC] hint on the mode-line while recording
  • +
  • added ~ shortcut for use inside IDO so I can reach $HOME +very fast from everywhere, no more editing pre-filled +current path and entering home/$user. Yeah!
  • +
  • added flip-window (bound to M-O (ALT-shift-o)
  • +
  • added cleanup-buffer (alias cb)
  • +
  • fixed C-<ret> and C-S-<ret>
  • +
+ +

+20170306.01: +

+
    +
  • re-enabled linenum mode
  • +
  • fixed custom modeline
  • +
+ +

+20170306.01: +

+
    +
  • which-func not in elisp anymore
  • +
  • added alias 'ee for 'eval-expression
  • +
  • added 'sa (show-aliases)
  • +
  • some occur enhancements for 'sk and 'sa.
  • +
  • note: inside Occur: q:quit, g:reload, e:edit (buffer must be open)
  • +
+ +

+20170307.01: +

+
    +
  • fixed 'sk and 'sa
  • +
  • added key bindings to mark things. M-a is the prefix, followed by: +a - all, p - paragraph, f - function, l - line, w - word.
  • +
  • disabled M-O (flip-windows) on console emacs
  • +
+ +

+20170309.01: +

+
    +
  • added C-c s,u,e and M-a s,u,e
  • +
+ +

+20170309.02: +

+
    +
  • re-enabled paredit, its better in ielm and slime
  • +
  • added alias 'pe to quickly enable/disable par-edit
  • +
  • added virtual eShell dev /dev/log which stores stuff in LOG
  • +
+ +

+20170313.01: +

+
    +
  • iedit to C-c C-e, so C-c e works again (copy email)
  • +
  • put eshell aliases into .emacs(here) no need for aliases file anymore
  • +
  • added copy-comment (C-c c), copy-and-yank-comment (C-c y c) and +m-mark-comment (M-a c)
  • +
+ +

+20170314.01: +

+
    +
  • enhanced copy-comment (that is, rewrote it), it now supports +indented multiline comments
  • +
+ +

+20170315.01: +

+
    +
  • fixed C-c y [cpwf]
  • +
  • fixed copy[+yank+mark] word, it now includes - _ .
  • +
  • added copy-ip (C-c i), yank-ip (C-c y i) and mark-ip (M-a i)
  • +
  • copy-url alternatively copies file-path if it's no url at point
  • +
  • added numerical arg support to yy
  • +
+ +

+20170321.01: +

+
    +
  • rewrote copy-comment stuff, now supports blocks of comment +after code etc.
  • +
+ +

+20170323.01: +

+
    +
  • moved the mark,copy,yank stuff into its own mode
  • +
+ +

+20170327.01: +

+
    +
  • added defadvice for mcyt mode, so that I can use C-v to +always yank the last thing copied.
  • +
+ +

+20170502.01: +

+
    +
  • added config for ibuffer
  • +
+ +

+20170503.01: +

+
    +
  • added ibuffer-vc support
  • +
+ +

+20170503.02: +

+
    +
  • added ibuffer-tramp support
  • +
  • disabled ibuffer tab-collaps stuff
  • +
+ +

+20170505.01: +

+
    +
  • generalized init-dir+file variables, now more portable, i hope
  • +
+ +

+20170508.01: +

+
    +
  • backup tramp files remote
  • +
  • do not backup emacs state files
  • +
+ +

+20170509.01: +

+
    +
  • version fix
  • +
+ +

+20170523.01: +

+
    +
  • commented ssh backup stuff, not working yet, destroys tramp
  • +
  • added inferior shells for perl, ruby and python (iperl, iruby, ipython) +with ansi-term
  • +
+ +

+20170610.01: +

+
    +
  • org mode: added C-c C-# to edit src blocks in an extra window
  • +
  • org mode: <ret> opens link in eww
  • +
  • ido-find-file advice: if not writable, try sudo/tramp
  • +
  • +eshell-there remote eshell (Alias: et)
  • +
  • disabled pager in eshell
  • +
  • fixed eshell/x, now uses C-d
  • +
  • org mode: DONE makes heading greyish
  • +
  • re-organized emacs config, now with subsections
  • +
  • removed lisp electric return, destroyed almost all modes
  • +
  • added POD mode with specific abbrevs and including specific outlining
  • +
  • added heading cycle code for outline mode as well
  • +
  • added outline 'n (narrow) + 'w (widen)
  • +
  • added orange fringe for narrowing (org, outline and everywhere else
  • +
  • added alias 'colors
  • +
  • added 'dl (aka describe-library to display the doc string in +COMMENTARY section of .el files
  • +
  • added "C-c t" to copy an org mode cell
  • +
  • ena org pretty entities, list: org-entities-help
  • +
  • 2table => tablify, which is now a function and uses region or whole buffer
  • +
  • added indirect narrowing buffers
  • +
  • renamed all occurences of my- to tvd- so I better know which stuff is mine
  • +
  • added table-to-* org table exporters with aliases
  • +
  • inside org mode: C-c o copy table c[o]lumn, C-c t copy [t]able cell
  • +
  • experimental: added beacon mode (blinking pointer) +(moved 'seq from exp. elpa to lisp/)
  • +
  • added render-html to render current html buffer with eww
  • +
  • added align-regexp-repeat[-left|right] wrappers
  • +
  • fixed org mode C-<down|up> jump paragraphs if not on heading
  • +
  • added 'tvd-outshine-jump (alias 'j) to directly jump to headers +with IDO completion and as sparse-tree, very cool! +mapped to C-c C-j
  • +
  • added text scratch buffer with text mode
  • +
  • added jump-paren-match-or-insert-percent, bound to %, which jumps parens +or inserts a % if not on a paren. Better than C-5, haha.
  • +
  • added 'ffxs
  • +
  • added emacs-change-log
  • +
  • removed GNUS config, not used anymore
  • +
  • restored C-d binding to viking in paredit
  • +
  • added outshine HTML exporter via org: outshine-to-html
  • +
  • fixed outshine config
  • +
  • added (my) config-general-mode
  • +
  • fixed pod format inserters
  • +
+ +

+20170629.01: +

+
    +
  • added tablist-minor-mode (+config)
  • +
  • added config for tabulated-list-mode
  • +
  • added config for help-mode
  • +
  • added default filename for outshine-to-html
  • +
  • Info mode: C-left+C-right history keys
  • +
  • added loader for el2markdown
  • +
  • removed smart-forward, it annoys me
  • +
  • made tvd-outshine-jump more portable, do not use hardcoded +regexps anymore, use outshine functions
  • +
  • added 'change-inner and ci simulators'
  • +
  • added suggest.el with my own reload function
  • +
  • modified recentf: do not provide files already visited
  • +
+ +

+20170703.01: +

+
    +
  • fixed recentf-exclude list, now REALLY ignores unreadables
  • +
  • added export for easier export and commit of dot-emacs
  • +
  • added tvd-suggest-jump to jump between input and output
  • +
+ +

+20170707.01: +

+
    +
  • added C-x 4 to split fram into 4 windows
  • +
  • fixed config-general-mode config
  • +
  • fixed 'emacs-change-log (didn't expand trees before work)
  • +
  • fix python loading
  • +
+ +

+20170711.01: +

+
    +
  • fixed outshine: only loaded with elisp
  • +
  • fixed tvd-outshine-jump: use imenu if outside outshine
  • +
  • fixed kill-all-buffers: restore scratch after killing all buffers
  • +
  • do not ask to save abbrevs on exit anymore
  • +
  • reformat changelog
  • +
  • rm open-line-below
  • +
+ +

+20170711.02: +

+
    +
  • fixed POD abbrevs, added way to move point after expansion
  • +
+ +

+20170712.01: +

+
    +
  • disabled org mode superscripts
  • +
  • + winner mode
  • +
  • org mode 'code new binding: C-c 0
  • +
  • fixed emacs-change-log
  • +
  • added tvd-outshine-end-of-section incl speed command
  • +
+ +

+20170712.02: +

+
    +
  • fixed tvd-outshine-end-of-section, it's way faster now and +works without narrowing.
  • +
+ +

+20170714.01: +

+
    +
  • fixed pod-mode abbrev cursor jumping if no jump pos exists
  • +
  • fix initial-buffer-choice
  • +
  • added mmm-mode
  • +
  • added here-doc support to config-general using mmm-mode
  • +
  • made outline faces a little bigger, added face for level 4
  • +
  • rm initial buffer, doesnt open commandline files anymore with this
  • +
  • finally initial buffer works, opens command line file or text scratch
  • +
+ +

+20170715.01: +

+
    +
  • no more MMM for C::G, destroys indent
  • +
  • incorporated my C::G customizations, Steve Purcell removed from +it because inappropriate, +see d7e8323
  • +
  • fixed autoscratch hook
  • +
  • add scratch alias
  • +
+ +

+20170718.01: +

+
    +
  • better autoscratch config
  • +
  • added persistent-scratch mode
  • +
+ +

+20170719.01: +

+
    +
  • fixed electric-indent in autoscratch config
  • +
  • use my own autoscratch triggers
  • +
  • kill-all-buffers now uses 'autoscratch-buffer
  • +
  • renamce autoscratch
  • +
  • tuned recenter-positions
  • +
+ +

+20170722.01: +

+
    +
  • added followcursor-mode
  • +
+ +

+20170724.01: +

+
    +
  • added ido completion for tramp hostnames
  • +
+ +

+20170725.01: +

+
    +
  • autoscratch lambda=>progn
  • +
  • added sort-table-ip[desc] and fixed auto-alignment so +that ip's are left aligned
  • +
  • +req org-table
  • +
+ +

+20170727.01: +

+
    +
  • +magit
  • +
  • configured magit dirs
  • +
  • +magit ido
  • +
  • fix magit info dir
  • +
+ +

+20170730.01 +

+
    +
  • +some magit navigation keys
  • +
+ +

+20170731.01 +

+
    +
  • do not load magit on w32
  • +
  • Always call `magit-status' with prefix arg
  • +
  • do bigger jumps in magit with just C-<up|down>
  • +
  • add "ls" to magit-status leading to dired
  • +
+ +

+20170801.01 +

+
    +
  • added C command to magit to switch repo
  • +
  • add : trigger for ido-find-file to begin with tramp
  • +
+ +

+20170802.01 +

+
    +
  • +table-to-excel
  • +
  • added some git wrappers to dired to add or rm files
  • +
+ +

+20170805.01 +

+
    +
  • +C-c C-c for rename files in dired
  • +
+ +

+20170807.01 +

+
    +
  • added dired config and functions
  • +
  • added dired-hacks: ranger and filters, enhanced navigation commands
  • +
+ +

+20170808.01 +

+
    +
  • (i) is now a function, not an alias anymore and more comfortable
  • +
  • added org info path
  • +
  • added info+
  • +
+ +

+20170821.01 +

+
    +
  • highlight line color light green with default bg
  • +
+ +

+20170901.01 +

+
    +
  • added :jump-to-captured to org capture templates, +didn't know about it before
  • +
+ +

+20170913.01 +

+
    +
  • disabled outline in config-general-mode
  • +
+ +

+20170924.01 +

+
    +
  • experimenting swiper
  • +
+ +

+20171201.01 +

+
    +
  • highlight TABs with ruby as well
  • +
+ +

+20171205.01 +

+
    +
  • fixed ORG template headings
  • +
+ +

+20180210.01 +

+
    +
  • added ediff config
  • +
  • fixed ob-sh to ob-shell
  • +
+ +

+20180730.01 +

+
    +
  • added autoscratch-reset-default-directory t
  • +
+ +

+20181004.01 +

+
    +
  • added projectile and config
  • +
  • added hydra and config (for org tables and projectile)
  • +
  • finished org table hydra
  • +
  • added info hydra, fixed 't bug
  • +
+ +

+20181016.01 +

+
    +
  • fixed dired under cygwin w/o git
  • +
+ +

+20181019.01 +

+
    +
  • using C-x for all hydras now: +C-x w: windows +C-x t: org table +C-y p: projectile
  • +
  • added copy org table row
  • +
  • enhanced window hyrda by resizing chords
  • +
  • changed table copy key chords (C-c t [ctr]
  • +
+ + +
    +
  • better windows hydra
  • +
  • on help close restore windows setup
  • +
  • fixed hydra hints
  • +
+ +

+20181021.01 +

+
    +
  • fixed window resizing
  • +
+ +

+20181022.01 +

+
    +
  • enhanced M-o for window switching a lot, using a hydra and the arrow keys
  • +
+ +

+20181029.01 +

+
    +
  • fixed recentf max files
  • +
+ +

+20181030.01 +

+
    +
  • fixed windows hydra flip window call
  • +
+ +

+20181105.01 +

+
    +
  • added eyebrowse with config and hydra, prefix: C-x C-x
  • +
+ +

+20181106.01 +

+
    +
  • close help windows regularly again
  • +
+ +

+20181107.01 +

+
    +
  • removed debug toggle
  • +
  • added magit status window new "q" feature which kills +all magit buffers and restores window setup
  • +
  • added magit status margin timestamps
  • +
+ +

+20181107.01 +

+
    +
  • fixed function, inserts at ()
  • +
  • added / to dired hydra
  • +
+ +

+20181110.01 +

+
    +
  • fixed % function, really
  • +
  • fixed elisp autoscratch config
  • +
+ +

+20181111.01 +

+
    +
  • fixed autoscratch elisp trigger
  • +
  • started with smartparens, first config just replaces paredit
  • +
+ +

+20181113.01 +

+
    +
  • disabled paredit, enabled smartparens
  • +
+ +

+20181115.01 +

+
    +
  • disabled smartparens strict mode, much annoying
  • +
  • map C-k to 'sp-kill-hybrid-sexp
  • +
+ +

+20181117.01 +

+
    +
  • disabled outline C-<left> it overwrote sp slurp left
  • +
  • enhanced emacs-changelog
  • +
  • fixed parens bug, added sp ti monibuffer
  • +
  • added tvd-lisp-comment
  • +
  • (re-)added electric pair mode to eval-expression
  • +
  • diret -lt
  • +
+ +

+20181121.01 +

+
    +
  • added org agenda
  • +
+ +

+20181122.01 +

+
    +
  • + new agenda o function
  • +
+ +

+20181126.01 +

+
    +
  • unlimited recentf
  • +
+ +

+20181127.01 +

+
    +
  • fixed tvd-replace-all
  • +
  • fixed agenda capture template
  • +
+ +

+20181127.02 +

+
    +
  • fixed C-up|down in agenda
  • +
+ +

+20181206.01 +

+
    +
  • added support for scheduled agenda entries and fixed tvd-replace-all +(I already had this in 20181123 but overwrote it somehow!)
  • +
+ +

+20181210.01 +

+
    +
  • fixed agenda g command
  • +
+ +

+20181212.01 +

+
    +
  • configured agenda sorting
  • +
+ +

+20181212.02 +

+
    +
  • fixed agenda sorting, must be global
  • +
+ +

+20181220.01 +

+
    +
  • added org table move cells functions
  • +
+ +

+20181222.01 +

+
    +
  • removed duplicate key bindings, added via comment
  • +
+ +

+20181227.01 +

+
    +
  • ena variable pitch w/ org, turned face config into theme
  • +
+ +

+20190108.01 +

+
    +
  • added server
  • +
+ +

+20190112.01 +

+
    +
  • added wdired cleanup function
  • +
+ +

+20190112.02 +

+
    +
  • enhanced cleaner
  • +
+ +

+20190114.01 +

+
    +
  • disabled variable pitch, annoys me
  • +
+ +

+20190214.01 +

+
    +
  • fixed C-c C-c in shell-script-mode
  • +
+ +

+20190226.01 +

+
    +
  • unbound F6 and F5 from cperl mode
  • +
+ +

+20190412.01 +

+
    +
  • added yaml mode and highlight indent mode
  • +
+ +

+20190513.01 +

+
    +
  • added scheduled task org capture template along with wrappers etc
  • +
+ +

+20190520.01 +

+
    +
  • fixed 'n' in agenda, added 'k', fixed scheduled task template
  • +
+ +

+20190521.01 +

+
    +
  • split agenda window left
  • +
+ +

+20190705.01 +

+
    +
  • added smerge hydra plus alias 'merge
  • +
  • fixed window resize hydra help
  • +
+ +

+20200902.01 +

+
    +
  • added rust mode
  • +
+
+
+ + + +
+

2.3 Parking Lot / Snippets

+
+

+Snippets which maybe of use in the future +

+
+ +
+

2.3.1 buffer-local hook

+
+

+(with-current-buffer (get-buffer "scratch") + (add-hook 'kill-buffer-hook + (lambda () (error "DENIED! don't kill my precious scratch!!")) + nil t)) +

+ +
+
+
+
+
+

2.4 .emacs config version

+
+

+My emacs config has a version (consisting of a timestamp with a +serial), which I display in the mode line. So I can clearly see, if +I'm using an outdated config somewhere. +

+
+
(defvar tvd-emacs-version "20200902.01")
+
+
+ +
+
+
+
+ +
+

3 System Specifics

+
+
+

3.1 Global init file+dir vars, portable

+
+
    +
  • added dev function which opens a new development frame
  • +
+ +

+since I always use ~/.emacs as my init file, this results in the +correct emacs dir: +

+
+
(setq user-init-dir (expand-file-name (concat user-init-file ".d")))
+
+
+ +

+FIXME: use (pwd) to determine .emacs.d, make it more portable +use different init dir on cygwin systems +

+
+
(setq tvd-win-home "C:/Cygwin/home/iz00468")
+(if (file-exists-p tvd-win-home)
+    (setq user-init-dir (expand-file-name ".emacs.d" tvd-win-home))
+  (setq tvd-win-home nil))
+
+
+ +

+all modes and extensions are located here +

+
+
(setq tvd-lisp-dir (expand-file-name "lisp" user-init-dir))
+
+
+ +
+
+
+
+

3.2 Shortcut Mode - mode specific help about my own customizations

+
+

+FIXME: complete +

+ +
+
(defun add-shortcut (mode help)
+  (add-to-list 'shortcut-alist '(mode . help)))
+
+(defun shortcut ()
+  (interactive)
+  (message (cdr (assoc major-mode 'shortcut-alist))))
+
+
+ +
+
+
+
+

3.3 Fontlock-mode - use syntax highlighting on graphical displays

+
+

+look: emacswiki +

+
+
(if window-system
+    (progn
+      (global-font-lock-mode 1)
+      (set-background-color "white")
+      (set-foreground-color "DarkBlue")))
+
+
+ +
+
+
+
+

3.4 line-cursor in console

+
+

+better visibility of cursor in console sessions +

+
+
(unless (display-graphic-p)
+  (global-hl-line-mode)
+  (set-face-background hl-line-face "DarkGray")
+  (set-face-foreground hl-line-face "Black"))
+
+
+ +
+
+
+
+

3.5 Backup Config

+
+

+I save backup files in a central location below the init dir, that +way they don't clutter productive file systems or repos. +

+ +
+
(setq tvd-backup-directory (expand-file-name "backups" user-init-dir))
+(if (not (file-exists-p tvd-backup-directory))
+    (make-directory tvd-backup-directory t))
+
+
+ +

+there's even a trash +

+
+
(setq tvd-trash-directory (expand-file-name "trash" tvd-backup-directory))
+
+
+ + +

+actual configuration of all things backup related: +

+
+
(setq make-backup-files t               ; backup of a file the first time it is saved.
+      backup-by-copying t               ; don't clobber symlinks
+      version-control t                 ; version numbers for backup files
+      delete-old-versions t             ; delete excess backup files silently
+      delete-by-moving-to-trash t
+      kept-old-versions 6               ; oldest versions to keep when a new numbered backup is made (default: 2)
+      kept-new-versions 9               ; newest versions to keep when a new numbered backup is made (default: 2)
+      auto-save-default t               ; auto-save every buffer that visits a file
+      auto-save-timeout 20              ; number of seconds idle time before auto-save (default: 30)
+      auto-save-interval 200            ; number of keystrokes between auto-saves (default: 300)
+      delete-by-moving-to-trash t
+      trash-directory tvd-trash-directory
+      backup-directory-alist `(("emacs.d/\\(recentf\\|ido.last\\|places\\)" . nil) ; do not backup state files
+                               ("." . ,tvd-backup-directory))) ; backup everything else
+
+
+ +

+However, if the file to be backed up is remote, backup +per remote directory. that way, no root owned files end +up in my home directory, ready to be read by everyone. +This is system specific and only matches special host names. +FIXME: find out programatically hostname und remote user to make this generic +

+
+
(advice-add 'make-backup-file-name-1 :before
+            '(lambda (&rest file)
+               (let ((filename (car file)))
+                 (if (string-match "\\(/ssh:.devel[0-9]+\\):/" filename)
+                     (setq backup-directory-alist `(("." . ,(concat (match-string 1 filename) ":/root/.emacs.d/backups"))))
+                   (setq backup-directory-alist `(("." . ,tvd-backup-directory)))))))
+
+
+ +

+FIXME: and/or check gnu.org +

+
    +
  • tramp-default-proxies-alist
  • +
+ +
+
+
+
+

3.6 console backspace fix

+
+

+make backspace work in console sessions +

+
+
(define-key key-translation-map [?\C-h] [?\C-?])
+
+
+ +
+
+
+
+

3.7 hide menu- and tool-bar

+
+

+I prefer a bare bones emacs window without any distractions, so turn them off. +

+
+
(menu-bar-mode -1)
+(tool-bar-mode -1)
+(setq use-dialog-box nil)
+(scroll-bar-mode 0)
+
+
+ +
+
+
+
+

3.8 stay silent on startup

+
+
+
(setq initial-scratch-message "")
+(setq inhibit-startup-message t)
+(setq inhibit-startup-screen t)
+(setq inhibit-startup-echo-area-message "scip")
+
+
+ +
+
+
+
+

3.9 y means yes

+
+

+y is shorter than yes and less error prone. +

+
+
(defalias 'yes-or-no-p 'y-or-n-p)
+
+
+ +
+
+
+
+

3.10 show col in modeline

+
+

+very useful to know current column +

+
+
(column-number-mode t)
+
+
+ +
+
+
+
+

3.11 file or buffer in title

+
+

+this can be seen in xmobar +

+
+
(setq frame-title-format '(buffer-file-name "emacs %f" ("emacs %b")))
+
+
+ + +
+
+
+
+

3.12 avoid invalid files

+
+
+
(setq require-final-newline t)
+
+
+ +
+
+
+
+

3.13 prepare load-path

+
+

+where to look for extensions: +

+
+
(add-to-list 'load-path tvd-lisp-dir)
+
+(if (null tvd-win-home)
+    (add-to-list 'load-path (expand-file-name "compat" tvd-lisp-dir)))
+
+
+ +

+modules +

+
+
(add-to-list 'load-path (concat tvd-lisp-dir "/er"))
+(add-to-list 'load-path (concat tvd-lisp-dir "/org/lisp"))
+(add-to-list 'load-path (concat tvd-lisp-dir "/ivy"))
+(add-to-list 'load-path (concat tvd-lisp-dir "/doremi"))
+(add-to-list 'load-path (concat tvd-lisp-dir "/org/contrib/lisp"))
+
+
+ +
+
+
+
+

3.14 Hydra

+
+

+Used here and there below, loaded as early as possible +

+
+
(require 'hydra)
+
+
+
+
+ +
+

3.15 byte-compile all of them, if needed

+
+

+handy function to recompile all lisp files +

+
+
(defun recompile-el()
+  (interactive)
+  (byte-recompile-directory tvd-lisp-dir 0))
+
+
+ +
+
+
+
+

3.16 increase fontsize with ctrl-+ and ctrl--

+
+

+I use those bindings everywhere (firefox, terminal, etc), and in +emacs as well. +

+ +
+
(defun tvd-global-font-size-bigger ()
+  "Make font size larger."
+  (interactive)
+  (text-scale-increase 0.5))
+
+(defun tvd-global-font-size-smaller ()
+  "Change font size back to original."
+  (interactive)
+  (text-scale-increase -0.5))
+
+(global-set-key (kbd "C-+")             'tvd-global-font-size-bigger) ; Schrift groesser
+(global-set-key (kbd "C--")             'tvd-global-font-size-smaller) ; kleiner
+
+
+ +
+
+
+
+

3.17 WINDOW management stuff

+
+
+

3.17.1 resize windows by keyboard

+
+

+Very practical: resize windows easily. +

+ +

+hit C-c C-r then use cursor keys to resize, <ret> to finish +

+
+
(require 'windresize)
+(global-set-key (kbd "C-c C-r")         'windresize) ; Split Buffer Groesse Aendern
+
+
+
+
+ +
+

3.17.2 switch windows with MS-WINDOWS key

+
+
+
(require 'windmove)
+(windmove-default-keybindings 'super)
+(setq windmove-wrap-around t)
+
+
+
+
+ +
+

3.17.3 M-o switch window or buffer

+
+

+The key M-o has different functions depending on context: +

+ +

+If there's only 1 window open, switch to the last active. +

+ +

+If there are 2 windows open, switch back and forth between the +two. In order to flip them, Use M-O (that is: ALT+shift+o). +

+ +

+And if there are more than 2 windows open, call the hydra, which +allows to switch to another window using the arrow keys. The hydra +stays for 1 second unles an arrow key has been pressed. So, I can +press multiple arrow keys in a row as long as I'm fast enough +between key presses. If I stop,the hydra disappears and I end up +whereever I was last. +

+ +

+Also, within the hydra 'o' jumps to the last active window and +'f' flips all windows. +

+ +

+from https://github.com/lukhas/buffer-move +

+
+
(require 'buffer-move)
+
+(defun tvd-previous-window (&optional ignore)
+  "Toggle between the last two selected windows."
+  (interactive)
+  (let ((win (get-mru-window t t t)))
+    (unless win (error "Last window not found."))
+    (select-window win)))
+
+
+ +

+via +whattheemacs.d: +exchange left with right buffer (or up and down), love it. +

+
+
(defun tvd-flip-windows ()
+  "Rotate your windows"
+  (interactive)
+  (cond ((not (> (count-windows)1))
+         (message "You can't rotate a single window!"))
+        (t
+         (setq i 1)
+         (setq numWindows (count-windows))
+         (while  (< i numWindows)
+           (let* (
+                  (w1 (elt (window-list) i))
+                  (w2 (elt (window-list) (+ (% i numWindows) 1)))
+                  (b1 (window-buffer w1))
+                  (b2 (window-buffer w2))
+                  (s1 (window-start w1))
+                  (s2 (window-start w2))
+                  )
+             (set-window-buffer w1  b2)
+             (set-window-buffer w2 b1)
+             (set-window-start w1 s2)
+             (set-window-start w2 s1)
+             (setq i (1+ i)))))))
+
+(defhydra hydra-switch-windows (:color pink: :timeout 2.5)
+  "
+Switch to buffer: ← ↑ → ↓   | _o_: previous | _f_: flip | MOVE: _u_: up    _d_: down   _l_: left   _r_: right"
+  ("<up>"    windmove-up    nil)
+  ("<down>"  windmove-down  nil)
+  ("<left>"  windmove-left  nil)
+  ("<right>" windmove-right nil)
+  ("o"       tvd-previous-window nil :color blue)
+  ("f"       tvd-flip-windows    nil :color blue)
+  ("u"       buf-move-up         nil :color blue)
+  ("d"       buf-move-down       nil :color blue)
+  ("l"       buf-move-left       nil :color blue)
+  ("r"       buf-move-right      nil :color blue)
+  ("q" nil nil :color red))
+
+
+ +

+via mbork +modified to call the above hydra if there are more than 2 windows +

+
+
(defun other-window-or-switch-buffer ()
+  "Call `other-window' if more than one window is visible, switch
+to next buffer otherwise."
+  (interactive)
+  (if (one-window-p)
+      (switch-to-buffer nil)
+    (progn
+      (if (= (length (window-list)) 2)
+          (other-window 1)
+        (hydra-switch-windows/body)))))
+
+(global-set-key (kbd "M-o")             'other-window-or-switch-buffer)
+
+
+ +

+M-o doesn't work when using emacs via Win->RDP->VNC->X11->Xmonad, +so fall back to C-o. +

+
+
(global-set-key (kbd "C-o")             'other-window-or-switch-buffer)
+
+
+ +

+Use only in X11 emacs - setting M-O inside console causes <up> and +<down> to stop working properly, for whatever reasons. +

+
+
(if (display-graphic-p)
+    (global-set-key (kbd "M-O")             'tvd-flip-windows))
+
+
+ +
+
+
+
+

3.17.4 Split window to 4 parts

+
+
+
(defun tvd-quarter-windows ()
+  (interactive)
+  (split-window-vertically)
+  (split-window-horizontally)
+  (windmove-down)
+  (split-window-horizontally))
+
+(global-set-key (kbd "C-x 4")           'tvd-quarter-windows)
+
+
+ +
+
+
+ +
+

3.17.5 Remember and Restore Window Configurations - winner mode

+
+
+
(winner-mode 1)
+
+
+ +

+keybindings: C-c left - winner-undo +keybindings: C-c right - winner-redo +

+
+
+
+ +
+

3.18 re-read a modified buffer

+
+

+F5 == reload file if it has been modified by another process, shift +because Xmonad +

+
+
(global-set-key (kbd "S-<f5>") ; re-read a buffer from disk (revert)
+                (lambda (&optional force-reverting)
+                  "Interactive call to revert-buffer. Ignoring the auto-save
+ file and not requesting for confirmation. When the current buffer
+ is modified, the command refuses to revert it, unless you specify
+ the optional argument: force-reverting to true."
+                  (interactive "P")
+                  ;;(message "force-reverting value is %s" force-reverting)
+                  (if (or force-reverting (not (buffer-modified-p)))
+                      (revert-buffer :ignore-auto :noconfirm)
+                    (error "The buffer has been modified"))))
+
+
+ + +
+
+
+
+

3.19 global TAB/Indent config

+
+

+I use spaces everywhere but Makefiles. If I encounter TABs I +replace them with spaces, if I encounter users entering TABs into +files, I block them. +

+ +

+FIXME: also check ethan-wspace ! +

+ +
+
(setq-default indent-tabs-mode nil)
+(setq-default tab-width 4)
+(setq indent-line-function 'insert-tab)
+(setq tab-stop-list (quote (4 8 12 16 20 24 28 32 36 40 44 48 52 56 60 64 68 72 76 80 84 88 92 96 100 104 108 112 116 120)))
+(setq tab-always-indent 'complete) ; /FIXME/: doesnt work in cperl-mode
+(setq show-trailing-whitespace t)
+
+(defun indent-buffer ()
+  ;; Author: Mathias Creutz
+  "Re-Indent every line in the current buffer."
+  (interactive)
+  (indent-region (point-min) (point-max) nil))
+
+
+ +

+Use normal tabs in makefiles +

+
+
(add-hook 'makefile-mode-hook '(lambda() (setq indent-tabs-mode t)))
+
+
+ + +
+
+
+
+

3.20 handy aliases

+
+

+M-x q r <ret> is short enough for me, no need for key bindings for +those +

+ +
+
(defalias 'qrr       'query-replace-regexp)
+(defalias 'qr        'query-replace)
+(defalias 'cr        'comment-region)
+(defalias 'ur        'uncomment-region)
+(defalias 'ir        'indent-region)
+(defalias 'dv        'describe-variable)
+(defalias 'dk        'describe-key)
+(defalias 'df        'describe-function)
+(defalias 'dp        'describe-char)
+(defalias 'dm        'describe-mode)
+(defalias 'db        'describe-bindings)
+(defalias 'dl        'finder-commentary) ; aka "describe library"
+(defalias 'repl      'ielm)
+(defalias 'ws        'window-configuration-to-register) ; save window config
+(defalias 'wr        'jump-to-register) ; restore window config
+(defalias 'rec       'rectangle-mark-mode)
+(defalias '|         'shell-command-on-region) ; apply shell command on region
+
+
+ +
+
+
+
+

3.21 various settings

+
+

+point stays while scrolling +

+
+
(setq scroll-preserve-screen-position t)
+
+
+ +

+no comment margins +

+
+
(setq-default comment-column 0)
+
+
+ +

+do not save until I hit C-x-s +

+
+
(setq auto-save-default nil)
+
+
+ +

+show all buffers in buffer menu +

+
+
(setq buffers-menu-max-size nil)
+
+
+ +

+start to wrap at 30 entries +

+
+
(setq mouse-buffer-menu-mode-mult 30)
+
+
+ +

+I'm grown up! +

+
+
(setq disabled-command-function nil)
+
+
+ +
+
+
+
+

3.22 load imenu

+
+
+
(define-key global-map [C-down-mouse-2] 'imenu)
+
+
+ +
+
+
+
+

3.23 copy/paste Config

+
+

+Related: +

+
    +
  • see also mark-copy-yank-things-mode below!
  • +
  • see also: move-region below (for M-<up|down>)
  • +
  • see also: expand-region below (for C-0)
  • +
+ +

+middle mouse button paste at click not where cursor is +

+
+
(setq mouse-yank-at-point t)
+
+
+ +

+highlight selected stuff (also allows DEL of active region) +

+
+
(setq transient-mark-mode t)
+
+
+ +

+pasting onto selection deletes it +

+
+
(delete-selection-mode t)
+
+
+ +

+delete whole lines +

+
+
(setq kill-whole-line t)
+
+
+ +

+middle-mouse and C-y use both X-selection and Emacs-clipboard +

+
+
(if (null tvd-win-home)
+    (progn  ; unix
+      (setq x-select-enable-primary t)
+      (setq x-select-enable-clipboard nil))
+  (progn    ; win
+    (global-set-key (kbd "<up-mouse-2>") 'yank)))
+
+
+ +

+marked region automatically copied, also on win +

+
+
(setq mouse-drag-copy-region t)
+
+
+ +
+
+
+
+

3.24 use more mem

+
+

+are you from the past? +

+
+
(setq gc-cons-threshold 20000000)
+
+
+ +
+
+
+
+

3.25 better file name completion

+
+

+Complete filenames case insensitive and ignore certain files during completion. +

+
+
(setq read-file-name-completion-ignore-case t)
+(setq read-buffer-completion-ignore-case t)
+
+
+ +

+via endlessparantheses +

+
+
(mapc (lambda (x)
+        (add-to-list 'completion-ignored-extensions x))
+      '(".aux" ".bbl" ".blg" ".exe"
+        ".log" ".meta" ".out" ".pdf"
+        ".synctex.gz" ".tdo" ".toc"
+        "-pkg.el" "-autoloads.el" ".elc"
+        ".dump" ".ps" ".png" ".jpg"
+        ".gz" ".tgz" ".zip"
+        "Notes.bib" "auto/"))
+
+
+ +
+
+
+
+

3.26 abbreviations

+
+

+Do I really need those anymore? Added ca 1999… +

+ +
+
(define-abbrev-table 'global-abbrev-table '(
+                                            ("oe" "&ouml;" nil 0)
+                                            ("ue" "&uuml;" nil 0)
+                                            ("ae" "&auml;" nil 0)
+                                            ("Oe" "&Ouml;" nil 0)
+                                            ("Ue" "&Uuml;" nil 0)
+                                            ("Ae" "&Auml;" nil 0)
+                                            ("<li>" "<li> </li>" nil 0)
+                                            ("<ul>" "<ul> </ul>" nil 0)
+                                            ))
+
+
+ +

+do NOT ask to save abbrevs on exit +

+
+
(setq save-abbrevs nil)
+
+
+
+
+ +
+

3.27 meaningful names for buffers with the same name

+
+

+from (prelude) +

+ +
+
(require 'uniquify)
+(setq uniquify-buffer-name-style 'forward)
+(setq uniquify-separator "/")
+(setq uniquify-after-kill-buffer-p t) ; rename after killing uniquified
+(setq uniquify-ignore-buffers-re "^\\*") ; don't muck with special buffers
+
+
+ +
+
+
+
+

3.28 packages

+
+

+I dont need it all the time and only for experimentation, so lets +only use melpa on demand +

+
+
(defun toggle-melpa()
+  (interactive)
+  (require 'package)
+  (add-to-list 'package-archives
+               '("melpa" . "http://melpa.org/packages/"))
+  (when (< emacs-major-version 24)
+    ;; For important compatibility libraries like cl-lib
+    (add-to-list 'package-archives '("gnu" . "http://elpa.gnu.org/packages/")))
+  (package-initialize)
+  (list-packages))
+
+
+ +
+
+
+
+

3.29 My own global variables

+
+

+narrowed fringe background +

+
+
(defvar tvd-fringe-narrow-bg "OrangeRed")
+
+
+ +
+
+
+
+

3.30 More scratch space

+
+
+

3.30.1 Text scratch

+
+

+Sometimes I need a text mode scratch buffer while scratch is +already in use. So let's prepare one. I also add a buffer hook so that +this never gets deleted, but cleaned instead. +

+ +
+
(with-current-buffer (get-buffer-create "*text*")
+  (text-mode))
+
+
+
+
+ +
+

3.30.2 Autoscratch

+
+

+use autoscratch otherwise +autoscratch github +

+
+
(require 'autoscratch-mode)
+(setq initial-major-mode 'autoscratch-mode)
+(add-hook 'autoscratch-mode-hook '(lambda ()
+                                    (setq autoscratch-triggers-alist
+                                          '(("[(;]"         . (progn
+                                                                (call-interactively 'emacs-lisp-mode)
+                                                                (call-interactively 'enable-paredit-mode)
+                                                                (call-interactively 'electric-pair-mode)))
+                                            ("#"            . (progn
+                                                                (call-interactively 'config-general-mode)
+                                                                (electric-indent-local-mode t)))
+                                            ("[-a-zA-Z0-9]" . (text-mode))
+                                            ("/"            . (c-mode))
+                                            ("*"            . (progn (insert " ") (org-mode)))
+                                            ("."            . (fundamental-mode)))
+                                          autoscratch-trigger-on-first-char t
+                                          autoscratch-reset-default-directory t)
+                                    (electric-indent-local-mode nil)
+                                    ))
+(defalias 'scratch 'autoscratch-buffer)
+
+
+
+
+ +
+

3.30.3 Persistent Scratch

+
+

+I also like to be scratch buffers persistent with +persistent-scratch +

+
+
(require 'persistent-scratch)
+(setq persistent-scratch-save-file (expand-file-name "scratches.el" user-init-dir))
+(persistent-scratch-setup-default)
+
+(defun tvd-autoscratch-p ()
+  "Return non-nil if the current buffer is a scratch buffer"
+  (string-match "scratch*" (buffer-name)))
+
+(setq persistent-scratch-scratch-buffer-p-function 'tvd-autoscratch-p)
+
+
+
+
+
+ +
+

3.31 Recenter config

+
+

+via abo abo +

+ +

+However, I set the first position to 1, which causes the window to +be recentered on the second line, that is, I can see one line above +the current one. It works the same with bottom, which I intend, but +I think this is a recenter calculation bug. +

+ +
+
(setq recenter-positions '(1 middle bottom))
+
+
+
+
+
+ +
+

4 Global Key Bindings

+
+
+
+
+

4.1 c-h != delete

+
+
+
(keyboard-translate ?\C-h ?\C-?)
+(keyboard-translate ?\C-? ?\C-h)
+
+
+ +
+
+
+
+

4.2 general keys (re-)mappings

+
+

+(global-set-key (kbd "C-s") 'isearch-forward-regexp) +(global-set-key (kbd "C-r") 'isearch-backward-regexp) +

+
+
(global-set-key (kbd "M-C-s")           'isearch-forward)
+(global-set-key (kbd "M-C-r")           'isearch-backward)
+(global-set-key (kbd "M-%")             'query-replace-regexp)
+(global-set-key (kbd "<backtab>")       'dabbrev-completion) ; shift-tab, inline completion
+
+(global-set-key (kbd "<f9>")            'html-mode)
+(global-set-key (kbd "<delete>")        'delete-char) ; Entf            Char loeschen
+(global-set-key (kbd "<backspace>")     'backward-delete-char) ; Shift+Backspace dito
+(global-set-key (kbd "S-<delete>")      'kill-word) ; Shift+Entf      Wort loeschen
+(global-set-key (kbd "S-<backspace>")   'backward-kill-word) ; Shift+Backspace dito
+(global-set-key (kbd "C-<delete>")      'kill-word) ; Shift+Entf      dito
+(global-set-key (kbd "C-<backspace>")   'backward-kill-word) ; Shift+Backspace dito
+(global-unset-key (kbd "C-z"))
+(global-set-key (kbd "C-x k")           'kill-this-buffer) ; C-x k  really kill current buffer w/o asking
+(global-set-key (kbd "C-x C-b")         'buffer-menu)
+
+
+ + + +
+
+
+
+

4.3 display a list of my own global key bindings and aliases

+
+

+via emacswiki +

+ +

+Inside Occur: q - quit, e - edit, g - reload +more help with: describe-function occur-mode +

+ +
+
(defun occur-mode-clean-buffer ()
+  "Removes all commentary from the *Occur* buffer, leaving the
+ unadorned lines."
+  (interactive)
+  (if (get-buffer "*Occur*")
+      (save-excursion
+        (set-buffer (get-buffer "*Occur*"))
+        (goto-char (point-min))
+        (toggle-read-only 0)
+        (if (looking-at "^[0-9]+ lines matching \"")
+            (kill-line 1))
+        (while (re-search-forward "^[ \t]*[0-9]+:"
+                                  (point-max)
+                                  t)
+          (replace-match "")
+          (forward-line 1)))
+    (message "There is no buffer named \"*Occur*\".")))
+
+(defun show-definition(REGEX)
+  (interactive)
+  (let ((dotemacs-loaded nil)
+        (occur-b "*Occur*")
+        (occur-c ""))
+    (if (get-buffer ".emacs")
+        (progn
+          (switch-to-buffer ".emacs")
+          (setq dotemacs-loaded t))
+      (find-file "~/.emacs"))
+    (occur REGEX)
+    (with-current-buffer occur-b
+      (occur-mode-clean-buffer)
+      (setq occur-c (current-buffer))
+      (let ((inhibit-read-only t)) (set-text-properties (point-min) (point-max) ()))
+      (while (re-search-forward "[0-9]*:" nil t)
+        (replace-match ""))
+      (beginning-of-buffer)
+      (kill-line)
+      (sort-lines nil (point-min) (point-max))
+      (emacs-lisp-mode)
+      (beginning-of-buffer)
+      (insert (format ";; *SHOW*:   %s\n" REGEX))
+      (highlight-regexp REGEX)
+      (beginning-of-buffer))
+    (switch-to-buffer occur-b)
+    (delete-other-windows)
+    (if (eq dotemacs-loaded nil)
+        (kill-buffer ".emacs"))))
+
+(defun show-keys()
+  (interactive)
+  (show-definition "^(global-set-key"))
+
+(defun show-aliases()
+  (interactive)
+  (show-definition "^(defalias"))
+
+(defalias 'sk        'show-keys)
+(defalias 'sa        'show-aliases)
+
+
+ +
+
+
+
+
+

5 Productivity Functions

+
+
+
+
+

5.1 goto line with tmp line numbers

+
+

+I stole this somewhere, as far as I remember, emacswiki, however, I +always had F7 for goto-line +

+ +
+
(defun goto-line-with-feedback ()
+  "Show line numbers temporarily, while prompting for the line number input"
+  (interactive)
+  (unwind-protect
+      (progn
+        (linum-mode 1)
+        (call-interactively 'goto-line))
+    (linum-mode -1)))
+
+(global-set-key (kbd "<f7>")            'goto-line-with-feedback)
+
+
+ +
+
+
+
+

5.2 invert fore- and background

+
+

+Sometimes when sitting in a very dark enviroment, my usual light +emacs frame is a too stark contrast to the environment. With this +function I can just invert my current color settings to dark +background and light foreground. +

+ +

+remember last inverse +

+
+
(defvar tvd-invert-state t)
+
+
+ +

+invert everything, reverse it when called again +

+
+
(defun tvd-invert()
+  "invert fg-bg"
+  (interactive)
+  (invert-face 'default)
+  (invert-face 'mode-line)
+  (set-face-attribute 'fringe nil :inverse-video tvd-invert-state)
+  (setq tvd-invert-state (not tvd-invert-state)) ;; cycle variable tvd-invert-state
+  )
+
+
+ +

+fast +

+
+
(global-set-key (kbd "C-c C-i")           'tvd-invert)
+
+
+ +
+
+
+
+

5.3 Some useful bindings for Home and End keys Hit the key once to

+
+

+Go to the beginning/end of a line, hit it twice in a row to go to +the beginning/end of the window, three times in a row goes to the +beginning/end of the buffer. NB that there is no timeout involved. +

+ +

+Uses a function of viking-mode to establish key repeats, see below. +

+ +
+
(defun pc-keys-home ()
+  "Go to beginning of  line/window/buffer. First hitting key goes
+to  beginning of  line,  second in  a row  goes  to beginning  of
+window, third in a row goes to beginning of buffer."
+  (interactive)
+  (let* ((key-times (viking-last-key-repeats)))
+    (cond
+     ((eq key-times 3)
+      (if mark-active
+          (goto-char (point-min))
+        (beginning-of-buffer)))
+     ((eq key-times 2)
+      (if mark-active () (push-mark))
+      (move-to-window-line 0))
+     ((eq key-times 1)
+      (beginning-of-line)))))
+
+(defun pc-keys-end ()
+  "Go to end of  line/window/buffer. First hitting key goes
+to end  of line, second  in a  row goes to  end of
+window, third in a row goes to end of buffer."
+  (interactive)
+  (let* ((key-times (viking-last-key-repeats)))
+    (cond
+     ((eq key-times 3)
+      (if mark-active
+          (goto-char (point-max))
+        (end-of-buffer)))
+     ((eq key-times 2)
+      (if mark-active () (push-mark))
+      (move-to-window-line -1)
+      (end-of-line))
+     ((eq key-times 1)
+      (end-of-line)))))
+
+
+ +

+This is the most natural use for those keys +

+
+
(global-set-key (kbd "<home>")          'pc-keys-home)
+(global-set-key (kbd "<end>")           'pc-keys-end)
+
+
+ + + +
+
+
+
+

5.4 percent function

+
+

+by Jens Heunemann: jump to percent position into current buffer +

+ +
+
(defun goto-percent (p) ;goto Prozentwert (0-100): F8
+  (interactive "nProzent: ")
+  (if (> (point-max) 80000)
+      (goto-char (* (/ (point-max) 100) p)) ;Ueberlauf vermeiden: (max/100)*p
+    (goto-char (/ (* p (point-max)) 100))) ;Rundungsfehler verm.: (max*p)/100
+  (beginning-of-line))
+
+(global-set-key (kbd "<f8>")            'goto-percent) ;F8 goto percent
+
+
+ +
+
+
+
+

5.5 Simulate vi's % (percent) function

+
+

+There's not a lot about vi[m] I like, but jumping with % to a +matching paren is one of THOSE features, I also need in emacs. +

+ +

+with ideas from emacswiki +

+ +

+If (point) is on a paren, jump to the matching paren, otherwise, +just insert a literal ?%. Only make sense if bound to %. +Does not jump in inside () though +

+
+
(defun jump-paren-match-or-insert-percent (arg)
+"Go to  the matching  parenthesis if on  parenthesis. Otherwise
+insert %. Mimics vi stle of % jumping to matching brace."
+(interactive "p")
+(cond ((looking-at "\\s\(\\|\{\\|\\[") (forward-list 1) (backward-char 1))
+      ((and (looking-at "\\s\)\\|\}\\|\\]")
+            (not (looking-back "\\s\(\\|\{\\|\\[")))
+       (forward-char 1) (backward-list 1))
+       (t (insert "%"))))
+
+
+ +

+only useful in programming modes +

+
+
(define-key prog-mode-map (kbd "%") 'jump-paren-match-or-insert-percent)
+
+
+ +
+
+
+
+

5.6 Move region

+
+

+Mark a region, then use M-up|down to move it around +via emacswiki +code from move-lines +

+ +
+
(defun move-lines--internal (n)
+  (let* ((start (point)) ;; The position of beginning of line of the first line
+         (end start) ;; The position of eol+\n of the end line
+         col-init        ;; The current column for the first line
+         (col-end (current-column)) ;; The current column for the end line
+         exchange_pm     ;; If I had exchanged point and mark
+         delete-latest-newline) ;; If I had inserted a newline at the end
+
+    ;; STEP 1: Identifying the line(s) to cut.
+    ;; ---
+    ;; If region is actives, I ensure that point always is at the end of the
+    ;; region and mark at the beginning.
+    (when (region-active-p)
+      (when (< (point) (mark))
+        (setq exchange_pm t)
+        (exchange-point-and-mark))
+      (setq start (mark)
+            end (point)
+            col-end (current-column)))
+
+    (goto-char start) (setq col-init (current-column))
+    (beginning-of-line) (setq start (point))
+
+    (goto-char end) (end-of-line)
+    ;; If point == point-max, this buffers doesn't have the trailing newline.
+    ;; In this case I have to insert a newline otherwise the following
+    ;; `forward-char' (to keep the "\n") will fail.
+    (when (= (point) (point-max))
+      (setq delete-latest-newline t)
+      (insert-char ?\n) (forward-char -1))
+    (forward-char 1) (setq end (point))
+
+    ;; STEP 2: Moving the lines.
+    ;; ---
+    ;; The region I'm cutting span from the beginning of line of the current
+    ;; line (or current region) to the end of line + 1 (newline) of the current
+    ;; line (or current region).
+    (let ((line-text (delete-and-extract-region start end)))
+      (forward-line n)
+      ;; If the current-column != 0, I have moved the region at the bottom of a
+      ;; buffer doesn't have the trailing newline.
+      (when (not (= (current-column) 0))
+        (insert-char ?\n)
+        (setq delete-latest-newline t))
+      (setq start (+ (point) col-init)) ;; Now, start is the start of new region
+      (insert line-text))
+
+    ;; STEP 3: Restoring
+    ;; ---
+    ;; I'm at the end of new region (or line) and start has setted at the
+    ;; beginning of new region (if a region is active).
+    ;; Restoring the end column.
+    (forward-line -1)
+    (forward-char col-end)
+
+    (when delete-latest-newline
+      (save-excursion
+        (goto-char (point-max))
+        (delete-char -1)))
+
+    (when (region-active-p)
+      (setq deactivate-mark nil)
+      (set-mark start)
+      (if exchange_pm
+          (exchange-point-and-mark)))))
+
+(defun move-lines-up (n)
+  "Moves the current line or, if region is actives, the lines surrounding
+region, up by N lines, or 1 line if N is nil."
+  (interactive "p")
+  (if (eq n nil)
+      (setq n 1))
+  (move-lines--internal (- n)))
+
+(defun move-lines-down (n)
+  "Moves the current line or, if region is actives, the lines surrounding
+region, down by N lines, or 1 line if N is nil."
+  (interactive "p")
+  (if (eq n nil)
+      (setq n 1))
+  (move-lines--internal n))
+
+(global-set-key (kbd "M-<up>")          'move-lines-up)
+(global-set-key (kbd "M-<down>")        'move-lines-down)
+
+
+ +
+
+
+
+

5.7 comment-uncomment region with one key binding

+
+

+via stackoverflow +

+
+
(defun comment-or-uncomment-region-or-line ()
+  "Comments or uncomments the region or the current line if there's no active region."
+  (interactive)
+  (let (beg end)
+    (if (region-active-p)
+        (setq beg (region-beginning) end (region-end))
+      (setq beg (line-beginning-position) end (line-end-position)))
+    (comment-or-uncomment-region beg end)))
+
+(global-set-key (kbd "C-c C-c")         'comment-or-uncomment-region-or-line)
+
+
+ +
+
+
+
+

5.8 search for symbol at point

+
+

+Simulate the # function of vi, marks the symbol at point, C-s then +searches for it. I use this a lot. +

+ +

+via ergomacs +

+ +
+
(defun xah-search-current-word ()
+  "Call `isearch' on current word or text selection.
+   'word' here is A to Z, a to z, and hyphen and underline, independent of syntax table.
+URL `[[http://ergoemacs.org/emacs/modernization_isearch.html'][ergomacs]]
+Version 2015-04-09"
+  (interactive)
+  (let ( xahp1 xahp2 )
+    (if (use-region-p)
+        (progn
+          (setq xahp1 (region-beginning))
+          (setq xahp2 (region-end)))
+      (save-excursion
+        (skip-chars-backward "-_A-Za-z0-9")
+        (setq xahp1 (point))
+        (right-char)
+        (skip-chars-forward "-_A-Za-z0-9")
+        (setq xahp2 (point))))
+    (setq mark-active nil)
+    (when (< xahp1 (point))
+      (goto-char xahp1))
+    (isearch-mode t)
+    (isearch-yank-string (buffer-substring-no-properties xahp1 xahp2))
+    (message "Now use C-s to search for it ...")
+    ))
+
+(global-set-key (kbd "C-#")             'xah-search-current-word)
+
+
+ +
+
+
+
+

5.9 Window Margin

+
+

+Kinda screen reader for the poor. I use this sometimes with info +or woman mode. I also use a full featured screen reader: nove-mode, +see below. +

+ +

+left+right margin on demand (but nothing else) +

+
+
(defun margin(m)
+  "set left and right margins for better readability"
+  (interactive "nEnter Margin (0 to disable) [0-9]+: ")
+  (set-window-margins (car (get-buffer-window-list (current-buffer) nil t)) m m) ;; set immediately
+  (setq left-margin-width m) ;; persist until reset
+  (setq right-margin-width m)
+  (message "To reset, change Buffer or call again with arg 0.")
+  )
+
+
+ +
+
+
+
+

5.10 Fill and justify a paragraph

+
+

+this is just a shortcut for: + C-u 70 <ret> M-x fill-paragraph +but C-q is just easier to remember +

+ +

+however, if pressed again it un-fills the paragraph, +idea via: endlessparentheses +

+
+
(defun tvd-fill-and-justify-or-unfill()
+  (interactive)
+  (let ((fill-column
+         (if (eq last-command 'tvd-fill-and-justify-or-unfill)
+             (progn (setq this-command nil)
+                    (point-max))
+           fill-column)))
+    (fill-paragraph 70)))
+
+(global-set-key (kbd "C-q")             'tvd-fill-and-justify-or-unfill) ; like M-q, which is bound to x-window-quit in xmonad: fill+justify
+
+
+ +
+
+
+
+

5.11 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. I use this in +cases where I need to re-factor a file and do lots of changes. With +the buffer copy I have a reference to compare without the need to +leave emacs and look at revision control diffs or the like, and if +a file is not maintained via VC anyway. +

+ +
+
(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) ; make read-only buffer copy
+
+
+ +
+
+
+
+

5.12 Cleanup, close all windows and kill all buffers

+
+

+From time to time I get annoyed by the many dozen buffers +opened. In such cases I like to close them all at once. +

+ +

+No key binding though, just in case I stumble upon it and kill my +setup accidentally. +

+ +
+
(defun kill-all-buffers ()
+  "Kill all buffers, clean up, close all windows"
+  (interactive)
+  (when (y-or-n-p "Close all windows and kill all buffers?")
+    (delete-other-windows)
+    (clean-buffer-list)
+    (dolist (buffer (buffer-list))
+      (kill-buffer buffer))
+    (delete-minibuffer-contents)
+    (if (fboundp 'tramp-cleanup-all-connections)
+        (tramp-cleanup-all-connections))
+    (with-current-buffer (get-buffer-create "*text*")
+      (text-mode))
+    (autoscratch-buffer)))
+
+
+ +
+
+
+
+

5.13 Cleanup current buffer

+
+

+Remove TABs, leading and trailing spaces, re-indent a buffer. +

+ +

+via whattheemacs.d +

+ +
+
(defun cleanup-buffer ()
+  "Perform a bunch of safe operations on the whitespace content of a buffer.
+Does not indent buffer, because it is used for a before-save-hook, and that
+might be bad."
+  (interactive)
+  (untabify (point-min) (point-max))
+  (delete-trailing-whitespace)
+  (save-excursion
+    (replace-regexp "^\n\\{3,\\}" "\n\n" nil (point-min) (point-max)))
+  (set-buffer-file-coding-system 'utf-8)
+  (indent-region (point-min) (point-max)))
+
+(defalias 'cb        'cleanup-buffer)
+
+
+ +

+related, I use this to cleanup directories and rename files and +directories to my liking. Sometimes I get a disk or stick from +Windows users and they use every character available on their +keyboards to name files and dirs. I can't have this shit. +

+ +
+
(defun cleanup-dired-buffer ()
+  "If inside a wdired (edit) buffer, rename everything"
+  (interactive)
+  (delete-trailing-whitespace)
+  (save-excursion
+    (replace-regexp "[\(\)'`#,_&\!]" "" nil (point-min) (point-max))
+    (replace-string " " "-" nil (point-min) (point-max))
+    (replace-regexp "--*" "-" nil (point-min) (point-max))
+    (replace-string "ä" "ae" nil (point-min) (point-max))
+    (replace-string "ö" "oe" nil (point-min) (point-max))
+    (replace-string "ü" "ue" nil (point-min) (point-max))
+    (replace-string "Ä" "Ae" nil (point-min) (point-max))
+    (replace-string "Ö" "Oe" nil (point-min) (point-max))
+    (replace-string "Ü" "Ue" nil (point-min) (point-max))
+    (replace-string "ß" "ss" nil (point-min) (point-max))
+    (replace-string ".." "." nil (point-min) (point-max))))
+
+(defun cleanup-dir()
+  "Cleanup wdired buffer in one whole step, used for emacsclient buffers"
+  (interactive)
+  (wdired-change-to-wdired-mode)
+  (cleanup-dired-buffer)
+  (wdired-finish-edit)
+  (kill-this-buffer))
+
+
+ + +
+
+
+
+

5.14 Remove Umlauts and other crab in current buffer

+
+

+converts: + Stan Lem - ein schönes Leben & sonst nix(ungekuerzte Ausgabe) +to: + StanLem-einschoenesLebensonstnixungekuerzteAusgabe +

+ +

+used in dired buffers to cleanup filenames by german windows users. +

+
+
(defun umlaute-weg()
+  (interactive)
+  (let ((umlaute '((Ü . Ue)
+                   (Ä . Ae)
+                   (Ö . Oe)
+                   (ü . ue)
+                   (ä . ae)
+                   (ö . oe)
+                   (ß . ss)))
+        (regs (list
+               '(" "       . "_")
+               '("_-_"     . "-")
+               '("[\(\)&]" . "_")
+               '("__*"     . "_")
+               '("_$"      . "")
+               )))
+    (save-excursion
+      (dolist (pair umlaute)
+        (replace-regexp (symbol-name (car pair))
+                        (symbol-name (cdr pair))
+                        nil
+                        (point-min) (point-max)))
+      (dolist (reg regs)
+        (replace-regexp (car reg) (cdr reg) nil
+                        (point-min) (point-max))))))
+
+
+ +
+
+
+
+

5.15 Better newline(s)

+
+

+Add newline and jump to indent from wherever I am in the current +line, that is it is not required to be on the end of line. +

+ +

+via whattheemacs.d +

+ +
+
(defun open-line-below ()
+  (interactive)
+  (end-of-line)
+  (newline)
+  (indent-for-tab-command))
+
+(defun open-line-above ()
+  (interactive)
+  (end-of-line)
+  (beginning-of-line)
+  (newline)
+  (forward-line -1)
+  (indent-for-tab-command))
+
+
+ +

+disabled, interferes with modes. +

+ +

+(global-set-key (kbd "<C-return>") 'open-line-below) +

+ +

+(global-set-key (kbd "<C-S-return>") 'open-line-above) +

+ +
+
+
+
+

5.16 Mouse Rectangle

+
+

+There's not much use for the mouse in emacs, but this gimick is +funny and works like a charm. +

+ +

+via stackoverflow +

+
+
(defun mouse-start-rectangle (start-event)
+  (interactive "e")
+  (deactivate-mark)
+  (mouse-set-point start-event)
+  (rectangle-mark-mode +1)
+  (let ((drag-event))
+    (track-mouse
+      (while (progn
+               (setq drag-event (read-event))
+               (mouse-movement-p drag-event))
+        (mouse-set-point drag-event)))))
+
+(global-set-key (kbd "S-<down-mouse-1>") 'mouse-start-rectangle)
+
+
+ +
+
+
+
+

5.17 DOS <=> UNIX conversion helpers

+
+
+
(defun dos2unix ()
+  (interactive)
+  (set-buffer-file-coding-system 'utf-8-unix)
+  (message (format "converted current buffer to %s" buffer-file-coding-system)))
+
+(defun unix2dos ()
+  (interactive)
+  (set-buffer-file-coding-system 'utf-8-dos)
+  (message (format "converted current buffer to %s" buffer-file-coding-system)))
+
+
+
+
+
+
+

5.18 helper do add the same thing to multiple mode hooks

+
+

+via stackoverflow +usage samples below. +

+
+
(defun add-something-to-mode-hooks (mode-list something)
+  "helper function to add a callback to multiple hooks"
+  (dolist (mode mode-list)
+    (add-hook (intern (concat (symbol-name mode) "-mode-hook")) something)))
+
+
+ +
+
+
+ +
+

5.19 helper to catch load errors

+
+

+Try to eval 'fn, catch errors, if any but make it possible for +emacs to continue undisturbed, used with SMEX, see below. +

+
+
(defmacro safe-wrap (fn &rest clean-up)
+  `(unwind-protect
+       (let (retval)
+         (condition-case ex
+             (setq retval (progn ,fn))
+           ('error
+            (message (format "Caught exception: [%s]" ex))
+            (setq retval (cons 'exception (list ex)))))
+         retval)
+     ,@clean-up))
+
+
+
+
+
+
+

5.20 Alignment Wrappers

+
+

+align-regexp is already a very usefull tool, however, sometimes I +want to repeat the alignment and I hate C-u, so here are some +wrappers to make this easier. +

+ +
+
(defun align-repeat (regex &optional alignment)
+  "Aply  REGEX  to all  columns  not  just  the first.  Align  by
+ALIGNMENT which must be 'left or 'right. The default is 'left.
+
+Right alignment:
+
+col1 ,col2
+col1 ,col2
+
+Left alignment:
+
+col1, col2
+col1, col2"
+  (interactive  "MRepeat Align Regex [ ]: ")
+  (let ((spc " ")
+        (beg (point-min))
+        (end (point-max))
+        (areg "%s\\(\\s-*\\)" ; default left aligned
+              ))
+    (when (string= regex "")
+      (setq regex spc))
+    (when (region-active-p)
+      (setq beg (region-beginning))
+      (setq end (region-end)))
+    (when (eq alignment 'right)
+        (setq areg "\\(\\s-*\\)%s"))
+    (align-regexp beg end (format areg regex) 1 1 t)))
+
+(defun align-repeat-left (regex)
+  (interactive  "MRepeat Left Align Regex [ ]: ")
+  (align-regexp-repeat regex 'left))
+
+(defun align-repeat-right (regex)
+  (interactive  "MRepeat Left Align Regex [ ]: ")
+  (align-regexp-repeat regex 'right))
+
+
+
+
+ + +
+

5.21 String Helpers

+
+

+Some helper functions I use here and there. +

+ +
+
(defun tvd-alist-keys (A)
+  "return a list of keys of alist A"
+  (let ((K ()))
+    (dolist (e A)
+            (push (car e) K)
+            )
+    K))
+
+(defun tvd-get-line ()
+  "return current line in current buffer"
+  (buffer-substring-no-properties
+   (line-beginning-position)
+   (line-end-position)))
+
+(defun tvd-starts-with (s begins)
+  "Return non-nil if string S starts with BEGINS."
+  (cond ((>= (length s) (length begins))
+         (string-equal (substring s 0 (length begins)) begins))
+        (t nil)))
+
+(defun tvd-replace-all (regex replace)
+  "Replace all matches of REGEX with REPLACE in current buffer."
+  (interactive)
+  (goto-char (point-min))
+  (while (re-search-forward regex nil t)
+    (replace-match replace)))
+
+
+
+
+
+ +
+

6 Modes

+
+
+

6.1 Programming Languages

+
+
+

6.1.1 VALA

+
+
+
(autoload 'vala-mode "vala-mode" "Major mode for editing Vala code." t)
+(add-to-list 'auto-mode-alist '("\\.vala$" . vala-mode))
+(add-to-list 'auto-mode-alist '("\\.vapi$" . vala-mode))
+(add-to-list 'file-coding-system-alist '("\\.vala$" . utf-8))
+(add-to-list 'file-coding-system-alist '("\\.vapi$" . utf-8))
+
+
+ +
+
+
+
+

6.1.2 rust mode

+
+
+
(autoload 'rust-mode "rust-mode" nil t)
+
+(defun rustlings-done ()
+  "I use this with rustlings"
+  (interactive)
+  (search-backward "DONE")
+  (move-beginning-of-line 1)
+  (kill-line)
+  (save-buffer))
+
+(setq auto-mode-alist
+      (append '(("\\.\\(rs\\)$"  . rust-mode))
+              auto-mode-alist))
+
+
+ +
+
+
+ +
+

6.1.3 python mode

+
+

+Not much configured for python, I'm happy with the defaults as it seems :) +

+
+
(require 'python)
+(autoload 'python-mode "python-mode" "Major mode for python scripts" t)
+
+(add-hook
+ 'python-mode-hook
+ (function
+  (lambda()
+    (local-set-key  [delete] 'py-electric-delete)
+    (setq-default indent-tabs-mode nil)
+    (setq mode-name "PY")
+    (outline-minor-mode 0) ;; turn off outline here. /FIXME/: find out where it's turned on!
+    )))
+
+(setq auto-mode-alist
+      (append '(("\\.\\(py\\)$"  . python-mode))
+              auto-mode-alist))
+
+
+
+
+
+
+

6.1.4 Shell-Script Mode

+
+

+C-c C-c [un-]comments everywhere, force in shell-script-mode as well +

+
+
(add-hook
+ 'sh-mode-hook
+ (function
+  (lambda()
+    (local-set-key (kbd "C-c C-c")  'comment-or-uncomment-region-or-line))))
+
+
+ +
+
+
+ +
+

6.1.5 cperl mode

+
+

+I am a perl addict. I love it, therefore, emacs must be prepared +for my addiction. Most importantly, I prefer cperl instead of the +default perl mode. I do not use the cperl version delivered with +emacs though, but the latest git version. +

+ +
+
(autoload 'cperl-mode "cperl-mode" "alternate perl mode" t)
+(defalias 'perl-mode 'cperl-mode)
+
+
+ +

+enable the most important cperl features +

+
+
(setq cperl-indent-left-aligned-comments nil)
+(setq cperl-comment-column 32)
+(setq cperl-hairy t)
+(setq cperl-electric-linefeed t)
+(setq cperl-electric-keywords t)
+(setq cperl-electric-parens t)
+(setq cperl-electric-parens-string nil)
+
+
+ +

+perl special: run, compile, debug +

+
+
(setq perl-run-out-buffer "*Async Shell Command*")
+
+(defun perl-kill ()
+  "get rid of hanging perl compile or run buffers"
+  (interactive)
+  (delete-windows-on perl-run-out-buffer)
+  (kill-buffer perl-run-out-buffer))
+
+(defun perl-run (switches parameters prefix)
+  "execute current perl buffer"
+  (interactive "sPerl-switches:\nsParameter:\nP")
+  (let ((file buffer-file-name))
+    (if (eq prefix nil)
+        (shell-command (concat "perl " switches " " file " " parameters "&"))
+      (shell-command (concat "perl -wc " switches " " file " " parameters "&")))
+    (save-excursion
+      (set-buffer perl-run-out-buffer)
+      (setq perl-error-fontified nil
+            perl-error-start nil
+            perl-error-end nil)
+      (goto-char (point-min)))
+    ))
+
+(defun perl-next-error ()
+  "jump to next perl run error, if any"
+  (interactive)
+  (let (line
+        errorfile
+        (window (get-buffer-window (buffer-name)))
+        (file buffer-file-name)
+        (buffer (buffer-name))
+        )
+    (select-window (display-buffer perl-run-out-buffer))
+    (set-buffer perl-run-out-buffer)
+    (if (eq perl-error-fontified t)
+        (progn
+          (set-text-properties perl-error-start perl-error-end ())
+          (setq perl-error-fontified nil)
+          )
+      )
+    (if (re-search-forward (concat "at \\([-a-zA-Z:0-9._~#/\\]*\\) line \\([0-9]*\\)[.,]") (point-max) t)
+        ()
+      (goto-char (point-min))
+      (message "LAST ERROR, jumping to first")
+      (re-search-forward (concat "at \\([-a-zA-Z:0-9._~#/\\]*\\) line \\([0-9]*\\)[.,]") (point-max) t)
+      )
+    (recenter)
+    (set-text-properties (match-beginning 1)
+                         (match-end 2)
+                         (list 'face font-lock-keyword-face))
+    (setq perl-error-fontified t
+          perl-error-start (match-beginning 1)
+          perl-error-end (match-end 2)
+          errorfile (buffer-substring
+                     (match-beginning 1)
+                     (match-end 1))
+          line (string-to-int (buffer-substring
+                               (match-beginning 2)
+                               (match-end 2))))
+    (select-window window)
+    (find-file errorfile)
+    (goto-line line)))
+
+
+ +

+cperl indent region +

+
+
(defun own-cperl-indent-region-or-paragraph (start end)
+  (interactive "r")
+  (if mark-active
+      (cperl-indent-region start end)
+    (save-excursion
+      (mark-paragraph)
+      (cperl-indent-region (point) (mark t))
+      )))
+
+
+ +

+and hook them into cperl +

+
+
(add-hook
+ 'cperl-mode-hook
+ (function
+  (lambda()
+    (make-variable-buffer-local 'perl-error-fontified)
+    (make-variable-buffer-local 'perl-error-start)
+    (make-variable-buffer-local 'perl-error-end)
+    (make-variable-buffer-local 'perl-old-switches)
+    (make-variable-buffer-local 'perl-old-parameters)
+    (local-set-key "\C-hF" 'cperl-info-on-current-command)
+    (local-set-key "\C-hf" 'describe-function)
+    (local-set-key "\C-hV" 'cperl-get-help)
+    (local-set-key "\C-hv" 'describe-variable)
+    (local-set-key "\C-cr" 'perl-run)
+    (local-set-key "\C-ck" 'perl-kill)
+    (local-set-key "\C-c#" 'perl-next-error)
+    (local-set-key "\M-\C-q" 'own-cperl-indent-region-or-paragraph)
+    (setq mode-name "PL")
+    )))
+
+
+ + + +
+
+
+ +
+

6.1.6 Paredit for lisp only

+
+

+13.11.2018: disabled in exchange for smartparens, which see +

+ +

+I use paredit in lisp a lot, and I'm mostly happy with the defaults. +

+ +

+(autoload 'enable-paredit-mode "paredit" "Turn on pseudo-structural editing of Lisp code." t) +

+ +

+;; However, I use it with lisp dialects only +(add-hook 'emacs-lisp-mode-hook #'enable-paredit-mode) +(add-hook 'eval-expression-minibuffer-setup-hook #'enable-paredit-mode) +(add-hook 'ielm-mode-hook #'enable-paredit-mode) +(add-hook 'lisp-mode-hook #'enable-paredit-mode) +(add-hook 'lisp-interaction-mode-hook #'enable-paredit-mode) +(add-hook 'scheme-mode-hook #'enable-paredit-mode) +(add-hook 'slime-repl-mode-hook (lambda () (paredit-mode +1))) +

+ +

+;; sometimes I need to be able to turn it off fast: +(defalias 'pe 'paredit-mode) +

+ +

+(eval-after-load 'paredit + '(progn + ;; force my own bindings for those + (define-key paredit-mode-map (kbd "C-d") nil) + (define-key paredit-mode-map (kbd "<M-up>") nil) + (define-key paredit-mode-map (kbd "<M-down>") nil))) +

+
+
+
+
+

6.1.7 Smart Parens

+
+

+I'm trying to migrate to smart-parens, since it supports all of +paredit but can do more +

+ +

+Also look at: +https://github.com/Fuco1/.emacs.d/blob/master/files/smartparens.el +https://github.com/Fuco1/smartparens/wiki +https://ebzzry.io/en/emacs-pairs/ +

+
+
(require 'smartparens-config)
+(require 'cl)
+
+(defun tvd-disable-par-and-pair()
+  "Disables Paredit and Electric-Pair-Mode if currently active.
+Used when enabling smartparens-mode."
+  (interactive)
+  (when electric-pair-mode
+    (electric-pair-mode))
+  (when (fboundp 'pparedit-mode)
+        (when paredit-mode
+          (disable-paredit-mode))))
+
+
+ +

+enable sp in minibuffer as well +maybe, see: https://github.com/Fuco1/smartparens/issues/33: +(sp-local-pair 'minibuffer-inactive-mode "'" nil :actions nil) +

+
+
(setq sp-ignore-modes-list
+      (delete 'minibuffer-inactive-mode sp-ignore-modes-list))
+
+
+ +

+automatically enable where needed +

+
+
(add-something-to-mode-hooks
+ '(emacs-lisp ielm lisp lisp-interaction scheme slime-repl ) 'smartparens-mode)
+
+
+ +

+also in some select prog modes +

+
+
(add-something-to-mode-hooks
+ '(perl ruby c c++ shell-script makefile config-general) 'smartparens-mode)
+
+
+ +

+I use my own lisp comment tool until sp#942 is fixed +

+
+
(defun tvd-lisp-comment ()
+  (interactive)
+  (if (not (looking-at "\s*\("))
+      (self-insert-command 1)
+    (let ((beg (point)))
+      (forward-list 1)
+      (when (looking-at "\s*\)")
+        (insert "\n"))
+      (comment-region beg (point))
+      (indent-for-tab-command)
+      (goto-char beg))))
+
+(eval-after-load 'smartparens
+  '(progn
+     ;; hydra via https://github.com/lunaryorn/old-emacs-configuration/blob/master/init.el
+     (defhydra hydra-smartparens (:hint nil)
+    "
+Sexps [quit with _q_, reach this hydra with 'C-x (']
+
+^Nav^                       ^Barf/Slurp^                           ^Depth^
+^---^-----------------------^----------^---------------------------^-----^-----------------
+_f_: forward  (C-M-right)   _→_:          slurp forward (C-right)  _R_: splice
+_b_: backward (C-M-left)    _←_:          barf forward  (C-left)   _r_: raise
+_u_: backward ↑             _C-<right>_:  slurp backward           _↑_: raise backward
+_d_: forward  ↓ (C-M-down)  _C-<left>_:   barf backward            _↓_: raise forward
+_p_: backward ↓
+_n_: forward  ↑ (C-M-up)
+
+^Kill^           ^Misc^                       ^Wrap^
+^----^-----------^----^-----------------------^----^------------------
+_w_: copy        _j_: join                    _(_: wrap with ( )
+_k_: kill (C-k)  _s_: split                   _{_: wrap with { }
+^^               _t_: transpose               _'_: wrap with ' '
+^^               _c_: convolute               _\"_: wrap with \" \"
+^^               _i_: indent defun
+
+"
+    ("q" nil)
+    ;; Wrapping
+    ("(" (lambda (_) (interactive "P") (sp-wrap-with-pair "(")))
+    ("{" (lambda (_) (interactive "P") (sp-wrap-with-pair "{")))
+    ("'" (lambda (_) (interactive "P") (sp-wrap-with-pair "'")))
+    ("\"" (lambda (_) (interactive "P") (sp-wrap-with-pair "\"")))
+    ;; Navigation
+    ("f" sp-forward-sexp )
+    ("b" sp-backward-sexp)
+    ("u" sp-backward-up-sexp)
+    ("d" sp-down-sexp)
+    ("p" sp-backward-down-sexp)
+    ("n" sp-up-sexp)
+    ;; Kill/copy
+    ("w" sp-copy-sexp)
+    ("k" sp-kill-sexp)
+    ;; Misc
+    ("t" sp-transpose-sexp)
+    ("j" sp-join-sexp)
+    ("s" sp-split-sexp)
+    ("c" sp-convolute-sexp)
+    ("i" sp-indent-defun)
+    ;; Depth changing
+    ("R" sp-splice-sexp)
+    ("r" sp-splice-sexp-killing-around)
+    ("<up>" sp-splice-sexp-killing-backward)
+    ("<down>" sp-splice-sexp-killing-forward)
+    ;; Barfing/slurping
+    ("<left>"     sp-forward-slurp-sexp)
+    ("<right>"    sp-forward-barf-sexp)
+    ("C-<left>"   sp-backward-barf-sexp)
+    ("C-<right>"  sp-backward-slurp-sexp))
+
+     ;; via https://ebzzry.io/en/emacs-pairs/:
+     (defmacro def-pairs (pairs)
+  "Define functions for pairing. PAIRS is an alist of (NAME . STRING)
+conses, where NAME is the function name that will be created and
+STRING is a single-character string that marks the opening character.
+
+  (def-pairs ((paren . \"(\")
+              (bracket . \"[\"))
+
+defines the functions WRAP-WITH-PAREN and WRAP-WITH-BRACKET,
+respectively."
+  `(progn
+     ,@(loop for (key . val) in pairs
+             collect
+             `(defun ,(read (concat
+                             "wrap-with-"
+                             (prin1-to-string key)
+                             "s"))
+                  (&optional arg)
+                (interactive "p")
+                (sp-wrap-with-pair ,val)))))
+     (def-pairs ((paren . "(")
+            (bracket . "[")
+            (brace . "{")
+            (single-quote . "'")
+            (double-quote . "\"")
+            (back-quote . "`")))
+
+     ;;(add-hook 'smartparens-enabled-hook #'tvd-disable-par-and-pair)
+     ;;(add-hook 'smartparens-enabled-hook #'turn-on-smartparens-strict-mode)
+
+     ;; auto wrapping w/o region
+     (define-key smartparens-mode-map (kbd "C-c (")  'wrap-with-parens)
+     (define-key smartparens-mode-map (kbd "C-c [")  'wrap-with-brackets)
+     (define-key smartparens-mode-map (kbd "C-c {")  'wrap-with-braces)
+     (define-key smartparens-mode-map (kbd "C-c '")  'wrap-with-single-quotes)
+     (define-key smartparens-mode-map (kbd "C-c \"") 'wrap-with-double-quotes)
+     (define-key smartparens-mode-map (kbd "C-c `")  'wrap-with-back-quotes)
+
+     ;; modification
+     (define-key smartparens-mode-map (kbd "C-x (")         'hydra-smartparens/body)
+     (define-key smartparens-mode-map (kbd "C-k")           'sp-kill-hybrid-sexp)
+     (define-key smartparens-mode-map (kbd "C-<left>")      'sp-forward-slurp-sexp)
+     (define-key smartparens-mode-map (kbd "C-<right>")     'sp-forward-barf-sexp)
+
+     ;; movement
+     ;; Also Check: https://github.com/Fuco1/smartparens/wiki/Working-with-expressions
+     ;; (look for "quick summary for each navigation function")
+     ;;
+     ;; Jump after  the next  balanced expression.  If inside  one and
+     ;; there is no forward exp., jump after its closing pair.
+     (define-key smartparens-mode-map (kbd "C-M-<right>") 'sp-forward-sexp)
+     ;; Jump before  the previous  balanced expression. If  inside one
+     ;; and there is no previous exp., jump before its opening pair.
+     (define-key smartparens-mode-map (kbd "C-M-<left>")  'sp-backward-sexp)
+     ;; Jump up one  level from the current  balanced expression. This
+     ;; means skipping  all the  enclosed expressions within  this and
+     ;; then jumping after the closing pair.
+     (define-key smartparens-mode-map (kbd "C-M-<up>")    'sp-up-sexp)
+     ;; Jump after the opening pair  of next balanced expression. This
+     ;; effectively  descends  one  level   down  in  the  "expression
+     ;; hierarchy".  If there  is no  expression to  descend to,  jump
+     ;; after current expression's  opening pair. This can  be used to
+     ;; quickly  navigate   to  the  beginning  of   current  balanced
+     ;; expression.
+     (define-key smartparens-mode-map (kbd "C-M-<down>")  'sp-down-sexp)
+     ;;  Jump to  the beginning  of following balanced  expression. If
+     ;;  there is no  following expression on the  current level, jump
+     ;;  one level up backward, effectively doing sp-backward-up-sexp.
+     (define-key smartparens-mode-map (kbd "C-S-<left>")  'sp-next-sexp)
+     ;; Jump to the end of  the previous balanced expression. If there
+     ;; is no previous expression on the current level, jupm one level
+     ;; up forward, effectively doing sp-up-sexp.
+     (define-key smartparens-mode-map (kbd "C-S-<right>") 'sp-previous-sexp)
+
+     ;; comment the whole sexp
+     (define-key smartparens-mode-map (kbd ";") 'tvd-lisp-comment)
+
+     ;; replace my global setting
+     ;; /FIXME/: fhceck/fix M<up+down>!
+     (define-key smartparens-mode-map (kbd "M-<right>")   'sp-forward-symbol)
+     (define-key smartparens-mode-map (kbd "M-<left>")    'sp-backward-symbol)))
+
+
+ +
+
+
+
+

6.1.8 ETAGS

+
+

+I use ETAGS for some projects. With etags I can easily jump to the +definition of a function, struct or whatever across files and +directories. +

+ +

+manually generate the tags file: +/usr/bin/ctags-exuberant -e *.c … +visit-tags-file ("TAGS" whereever ctags run) +

+ +

+then load TAGS with visit-tags-table +

+
+
(require 'etags-select)
+
+
+ +

+generate TAGS and load it +

+
+
(defun etags-create (dir-name)
+  "Create tags file."
+  (interactive "DDirectory: ")
+  (let* ((ctags "/usr/bin/ctags-exuberant")
+         (odir  (directory-file-name dir-name))
+         (ofile (concat odir "/TAGS"))
+         (langs "lisp,python,perl,c,c++,shell")
+         (shell-command
+          (format "%s -f %s -e -R --languages=%s %s" ctags ofile langs odir))
+         (visit-tags-table ofile))))
+
+
+ +

+ALTR + e (equals on de keyboard € sign): jump to tag source +

+
+
(global-set-key (kbd "€")               'etags-select-find-tag-at-point) ; alt-right + e: jump to tag definition
+
+
+ +

+Use ido to list tags, but then select via etags-select (best of both worlds!) +

+
+
(defun etags-find ()
+  "Find a tag using ido"
+  (interactive)
+  (tags-completion-table)
+  (let (tag-names)
+    (mapatoms (lambda (x)
+                (push (prin1-to-string x t) tag-names))
+              tags-completion-table)
+    (etags-select-find (ido-completing-read "Tag: " tag-names))))
+
+
+ +

+some handy aliases +

+
+
(defalias 'ec        'etags-create)
+(defalias 'ef        'etags-find)
+
+
+ +
+
+
+
+ +
+

6.2 Text Modes

+
+
+

6.2.1 sgml

+
+

+Used for XML and the likes. +

+ +
+
(setq sgml-set-face t)
+(setq sgml-balanced-tag-edit t)
+(setq sgml-omittag-transparent nil)
+(setq sgml-auto-insert-required-elements t)
+
+(setq sgml-markup-faces
+      '((start-tag . font-lock-function-name-face)
+        (end-tag . font-lock-function-name-face)
+        (comment . font-lock-comment-face)
+        (pi . font-lock-other-type-face)
+        (sgml . font-lock-variable-name-face)
+        (doctype . font-lock-type-face)
+        (entity . font-lock-string-face)
+        (shortref . font-lock-keyword-face)))
+
+
+
+
+
+ +
+

6.2.2 web-mode (JS, HTML, CSS combined)

+
+

+Web development is shit. Tech involved is a mess, and in most cases +intermixed. web-mode provides a great fix for this: it handles +HTML, CSS and Javascript in the same buffer very well. +

+ +

+See: web-mode.org +

+ +
+
(require 'web-mode)
+
+
+ +

+associate with the usual suspects +

+
+
(add-to-list 'auto-mode-alist '("\\.phtml\\'" . web-mode))
+(add-to-list 'auto-mode-alist '("\\.tpl\\.php\\'" . web-mode))
+(add-to-list 'auto-mode-alist '("\\.[agj]sp\\'" . web-mode))
+(add-to-list 'auto-mode-alist '("\\.as[cp]x\\'" . web-mode))
+(add-to-list 'auto-mode-alist '("\\.erb\\'" . web-mode))
+(add-to-list 'auto-mode-alist '("\\.mustache\\'" . web-mode))
+(add-to-list 'auto-mode-alist '("\\.djhtml\\'" . web-mode))
+(add-to-list 'auto-mode-alist '("\\.html?\\'" . web-mode))
+
+
+ +

+configure web mode +

+
+
(defun tvd-web-mode-hook ()
+  "Hooks for Web mode."
+  (setq web-mode-markup-indent-offset 2)
+  (setq web-mode-css-indent-offset 2)
+  (setq web-mode-code-indent-offset 2)
+  (setq web-mode-style-padding 1)
+  (setq web-mode-script-padding 1)
+  (setq web-mode-block-padding 0)
+  (setq web-mode-enable-auto-pairing t)
+  (setq web-mode-enable-auto-expanding t))
+(add-hook 'web-mode-hook  'tvd-web-mode-hook)
+
+
+ +

+some handy html code inserters +

+
+
(defun html-insert-p()
+  (interactive)
+  (web-mode-element-wrap "p"))
+
+(defun html-insert-li()
+  (interactive)
+  (web-mode-element-wrap "li"))
+
+(defun html-insert-ul()
+  (interactive)
+  (web-mode-element-wrap "ul"))
+
+(defun html-insert-b()
+  (interactive)
+  (web-mode-element-wrap "b"))
+
+
+ +

+convert a text list into a html list. +

+
+
(defun html-listify (beg end)
+  (interactive "r")
+  (save-excursion
+    (let* ((lines (split-string (buffer-substring beg end) "\n" t)))
+      (delete-region beg end)
+      (insert "<ul>\n")
+      (while lines
+        (insert "  <li>")
+        (insert (pop lines))
+        (insert "</li>\n"))
+      (insert "</ul>\n")
+      )))
+
+
+
+
+
+ +
+

6.2.3 Cisco Mode

+
+

+Written by myself many years ago, but I'm still using it daily to +view and prepare cisco configs. +

+ +
+
(autoload 'cisco-mode "cisco-mode" "Major mode for CISCO configs" t)
+(setq auto-mode-alist
+      (append '(("\\.\\(cfg\\)$"  . cisco-mode))
+              auto-mode-alist))
+
+
+
+
+
+ +
+

6.2.4 Markdown

+
+

+I rarely use markdown, but sometimes I stumble upon such a file and +like to view it with emacs without rendering. +Source: jblevins.org +

+ +
+
(autoload 'markdown-mode "markdown-mode"
+  "Major mode for editing Markdown files" t)
+
+(add-to-list 'auto-mode-alist '("\\.text\\'"     . markdown-mode))
+(add-to-list 'auto-mode-alist '("\\.markdown\\'" . markdown-mode))
+(add-to-list 'auto-mode-alist '("\\.md\\'"       . markdown-mode))
+
+
+ +

+parens and quotes constraints check on save +

+
+
(add-hook 'markdown-mode-hook
+          (lambda ()
+            (when buffer-file-name
+              (add-hook 'after-save-hook
+                        'check-parens
+                        nil t))
+            (modify-syntax-entry ?\" "\"" markdown-mode-syntax-table)
+            ))
+
+
+
+
+
+ +
+

6.2.5 POD mode

+
+

+I LOVE POD! POD is the documentation format of perl and there's a +solid toolset available for it. I use it to write documentation and +manual pages. It's much more powerfull than lame markdown and you +can even program great tools yourself around POD (like I did with +PodWiki years ago!) +

+ +

+Although cperl mode already has some POD support, pod mode is way +better. +

+ +

+Source: emacs-pod-mode +

+ +
+
(require 'pod-mode)
+(add-to-list 'auto-mode-alist '("\\.pod$" . pod-mode))
+(add-hook 'pod-mode-hook 'font-lock-mode)
+
+
+ +

+using expand-region: apply pod entity formatting to word at point. +

+
+
(defun tvd-outline-emphasize(CHAR)
+  "expand once if no region and apply emphasize CHAR"
+  (interactive)
+  (unless (use-region-p)
+    (er/expand-region 1))
+  (save-excursion
+    (goto-char (region-beginning))
+    (insert (format "%c<" CHAR))
+    (goto-char (region-end))
+    (insert ">")))
+
+(defun pod-bold()
+  "bold text in outline mode"
+  (interactive)
+  (tvd-outline-emphasize ?B))
+
+(defun pod-italic()
+  "italic text in outline mode"
+  (interactive)
+  (tvd-outline-emphasize ?I))
+
+(defun pod-code()
+  "verbatim text in outline mode"
+  (interactive)
+  (tvd-outline-emphasize ?C))
+
+
+ +

+enhance abbrevs and jump into expanded area to the +$ character (if it exists), which it also removes +

+
+
(setq tvd-abbrev-pos 0)
+(advice-add 'expand-abbrev :before
+            '(lambda () (setq tvd-abbrev-pos (point))))
+(advice-add 'expand-abbrev :after
+            '(lambda ()
+               (ignore-errors
+                 (when (re-search-backward "\\$" (- tvd-abbrev-pos 0))
+                   (delete-char 1)))))
+
+
+ +

+pod mode config +

+
+
(add-hook 'pod-mode-hook
+          (lambda ()
+            ;; tune syntax table
+            (modify-syntax-entry ?= "w" pod-mode-syntax-table)
+
+            ;; POD contains headers and I'm used to outlining if there are headers
+            ;; so, enable outlining
+            (setq outline-heading-alist '(("=head1" . 1)
+                                           ("=head2" . 2)
+                                            ("=head3" . 3)
+                                             ("=head4" . 4)
+                                              ("=over" . 5)
+                                               ("=item" . 6)
+                                              ("=begin" . 5)
+                                              ("=pod" . 5)
+                                          ))
+
+            ;; outline alone, however, works well
+            (outline-minor-mode)
+
+            ;; my own abbrevs for POD using mode-specific abbrev table
+            (define-abbrev-table 'pod-mode-abbrev-table '(
+                                                            ("=o" "=over\n\n=item *$\n\n=back\n\n")
+                                                            ("=i" "=item ")
+                                                            ("=h1" "=head1 ")
+                                                            ("=h2" "=head2 ")
+                                                            ("=h3" "=head3 ")
+                                                            ("=h4" "=head4 ")
+                                                            ("=c"  "=cut")
+                                                            ("=b"  "=begin")
+                                                            ("=e"  "=end")
+                                                            ("b"  "B<$>")
+                                                            ("c"  "C<$>")
+                                                            ("l"  "L<$>")
+                                                            ("i"  "I<$>")
+                                                            ("e"  "E<$>")
+                                                            ("f"  "F<$>"))
+                                    "POD mode abbreviations, see .emacs")
+
+            (abbrev-table-put pod-mode-abbrev-table :case-fixed t)
+            (abbrev-table-put pod-mode-abbrev-table :system t)
+
+            ;; enable abbreviations
+            (setq local-abbrev-table pod-mode-abbrev-table)
+            (abbrev-mode 1)
+
+            ;; POD easy formatting
+            (local-set-key (kbd "C-c b") 'pod-bold)
+            (local-set-key (kbd "C-c /") 'pod-italic)
+            (local-set-key (kbd "C-c c") 'pod-code)))
+
+
+ +
+
+
+
+

6.2.6 conf-mode

+
+

+conf-mode annoyingly overwrites the global keybinding C-c C-c with +some of its internal crab. So, force it to use my own defun. Also, +while we're at it, disable electric indent, it's annoying in +configs. Applies for derivates as well. +

+ +
+
(defun tvd-disarm-conf-mode()
+  (local-set-key  (kbd "C-c C-c") 'comment-or-uncomment-region-or-line)
+  (electric-indent-local-mode 0))
+
+(add-something-to-mode-hooks '(conf cisco fundamental conf-space pod) 'tvd-disarm-conf-mode)
+
+
+
+
+
+ +
+

6.2.7 Config::General mode

+
+
  1. Config and doc
    +

    +config-general-mode (also on Melpa). +

    + +

    +My own mode for Config::General +config files. Whenever I write some perl stuff, which needs a config file, I use +this module (and I do this a lot). Previously I used conf-mode or html-mode, but +both did not satisfy me. Now (as of 20170625) I solved this mess once and for all. +

    + +
    +
    (require 'config-general-mode)
    +(require 'sh-script)
    +
    +
    +
  2. + +
  3. Convenicence Wrappers
    +
    +
    (defun config-general-completion-at-point ()
    +  "Complete word at point using hippie-expand, if not on a comment."
    +  (interactive)
    +  (when (looking-back "[-%$_a-zA-Z0-9]")
    +    (unless (eq (get-text-property (point) 'face) 'font-lock-comment-face)
    +      (hippie-expand nil))))
    +
    +(defun config-general-do-electric-tab ()
    +  "Enter a <TAB> or goto current indentation."
    +  (interactive)
    +  (if (eq (point) (line-end-position))
    +        (indent-for-tab-command)
    +      (back-to-indentation)))
    +
    +(defun config-general-tab-or-expand ()
    +  "Do electric TAB or completion depending where point is.
    +
    +This is just a convenience function, which can be mapped
    +to `tab' by the user. .Not in use by default."
    +  (interactive)
    +  (unless (config-general-completion-at-point)
    +    (config-general-do-electric-tab)))
    +
    +
    + +

    +FIXME: Use this patched version for older emacsen and the default +for version which contain the patch (if any, ever). +

    + +

    +The original function try-expand-dabbrev-all-buffers doesn't work +correctly, it ignores a buffer-local configuration of the variables +hippie-expand-only-buffers and hippie-expand-ignore-buffers. This +is the patched version of the function. +

    + +

    +Bugreport: http://debbugs.gnu.org/cgi/bugreport.cgi?bug=27501 +

    +
    +
    (defun config-general--try-expand-dabbrev-all-buffers (old)
    +    "Try to expand word \"dynamically\", searching all other buffers.
    +The argument OLD has to be nil the first call of this function, and t
    +for subsequent calls (for further possible expansions of the same
    +string).  It returns t if a new expansion is found, nil otherwise."
    +  (let ((expansion ())
    +        (buf (current-buffer))
    +        (orig-case-fold-search case-fold-search)
    +        (heib hippie-expand-ignore-buffers)
    +        (heob hippie-expand-only-buffers)
    +        )
    +    (if (not old)
    +        (progn
    +          (he-init-string (he-dabbrev-beg) (point))
    +          (setq he-search-bufs (buffer-list))
    +          (setq he-searched-n-bufs 0)
    +          (set-marker he-search-loc 1 (car he-search-bufs))))
    +
    +    (if (not (equal he-search-string ""))
    +        (while (and he-search-bufs
    +                    (not expansion)
    +                    (or (not hippie-expand-max-buffers)
    +                        (< he-searched-n-bufs hippie-expand-max-buffers)))
    +          (set-buffer (car he-search-bufs))
    +          (if (and (not (eq (current-buffer) buf))
    +                   (if heob
    +                       (he-buffer-member heob)
    +                     (not (he-buffer-member heib))))
    +              (save-excursion
    +                (save-restriction
    +                  (if hippie-expand-no-restriction
    +                      (widen))
    +                  (goto-char he-search-loc)
    +                  (setq expansion
    +                        (let ((case-fold-search orig-case-fold-search))
    +                          (he-dabbrev-search he-search-string nil)))
    +                  (set-marker he-search-loc (point))
    +                  (if (not expansion)
    +                      (progn
    +                        (setq he-search-bufs (cdr he-search-bufs))
    +                        (setq he-searched-n-bufs (1+ he-searched-n-bufs))
    +                        (set-marker he-search-loc 1 (car he-search-bufs))))))
    +            (setq he-search-bufs (cdr he-search-bufs))
    +            (set-marker he-search-loc 1 (car he-search-bufs)))))
    +
    +    (set-buffer buf)
    +    (if (not expansion)
    +        (progn
    +          (if old (he-reset-string))
    +          ())
    +      (progn
    +        (he-substitute-string expansion t)
    +        t))))
    +
    +
    +
  4. + +
  5. Mode Hook
    +

    +I use TAB for completion AND tab and outshine. Also, the mode +enables electric indent automatically, but I disabled it for +conf-mode (see tvd-disarm-conf-mode), therefore I re-enable it here +for config-general-mode (which inherits from conf-mode). +

    +
    +
    (add-hook 'config-general-mode-hook
    +          (lambda ()
    +            (electric-indent-mode)
    +            ;; de-activate some senseless bindings
    +            (local-unset-key (kbd "C-c C-c"))
    +            (local-unset-key (kbd "C-c C-p"))
    +            (local-unset-key (kbd "C-c C-u"))
    +            (local-unset-key (kbd "C-c C-w"))
    +            (local-unset-key (kbd "C-c C-x"))
    +            (local-unset-key (kbd "C-c :"))
    +            (local-set-key (kbd "<tab>") 'config-general-tab-or-expand)
    +
    +            ;; from shell-script-mode, turn << into here-doc
    +            (sh-electric-here-document-mode 1)
    +
    +            ;; Inserting a brace or quote automatically inserts the matching pair
    +            ;; use smartparens now
    +            ;; (electric-pair-mode t)
    +            (setq-local hippie-expand-only-buffers '(config-general-mode))
    +
    +            ;; configure order of expansion functions
    +            (if (version< emacs-version "25.1")
    +                (set (make-local-variable 'hippie-expand-try-functions-list)
    +                     '(try-expand-dabbrev ;; use patched version
    +                       config-general--try-expand-dabbrev-all-buffers
    +                       try-complete-file-name-partially
    +                       try-complete-file-name))
    +              (set (make-local-variable 'hippie-expand-try-functions-list)
    +                   '(try-expand-dabbrev
    +                     try-expand-dabbrev-all-buffers
    +                     try-complete-file-name-partially
    +                     try-complete-file-name)))
    +            ;; enable
    +            (add-hook 'completion-at-point-functions 'config-general-completion-at-point)
    +            )
    +          )
    +
    +
    + +
    +
+
+
+

6.2.8 Xmodmap Mode

+
+

+the shortest mode ever, via emacswiki. +

+ +
+
(define-generic-mode 'xmodmap-mode
+  '(?!)
+  '("add" "clear" "keycode" "keysym" "pointer" "remove")
+  '(("[0-9]+" . 'font-lock-variable-name-face))
+  '("[xX]modmap\\(rc\\)?\\'")
+  nil
+  "Simple mode for xmodmap files.")
+
+
+ +

+see GenericMode for more examples. +

+
+
+ +
+

6.2.9 MMM Mode

+
+
  1. MMM configure:
    +
    +
    (add-to-list 'load-path (concat tvd-lisp-dir "/mmm-mode"))
    +
    +(require 'cl)
    +(require 'mmm-auto)
    +(require 'mmm-vars)
    +
    +(setq mmm-submode-decoration-level 2)
    +
    +
    + + +

    +mmm-mode github +see doc for class definition in var 'mmm-classes-alist +

    +
  2. + +
  3. MMM config for POD mode
    +
    +
    (mmm-add-classes
    + '((html-pod
    +    :submode html-mode ;; web-mode doesnt work this way!
    +    :delimiter-mode nil
    +    :front "=begin html"
    +    :back "=end html")))
    +
    +(mmm-add-mode-ext-class 'pod-mode nil 'html-pod)
    +
    +(add-hook 'pod-mode-hook 'mmm-mode-on)
    +
    +
    +
+
+ +
+

6.2.10 Yaml Mode

+
+
+
(require 'yaml-mode)
+(add-to-list 'auto-mode-alist '("\\.yml\\'" . yaml-mode))
+(add-to-list 'auto-mode-alist '("\\.j2\\'" . yaml-mode))
+
+(add-hook 'yaml-mode-hook
+          '(lambda ()
+             (define-key yaml-mode-map "\C-m" 'newline-and-indent)))
+
+
+
+
+
+
+

6.3 Text Manupilation

+
+
+

6.3.1 expand-region

+
+

+One of the best modes I ever discovered. Press C-= multiple times +to create a larger and larger region. I use C-0 (zero) because on a +german keyboard this is the same as C-= without pressing shift. +

+ +
+
(require 'expand-region)
+(global-set-key (kbd "C-0")             'er/expand-region) ; C-= without pressing shift on DE keyboard
+
+
+ +

+related to ER: +

+
+
+
+

6.3.2 Mark, Copy, Yank Things

+
+

+For a long time this stuff was located here in my emacs config. As +it grew larger and larger I decided to put it into its own mode: +mark-copy-yank-things-mode, which can be found on github these +days. +

+ +

+With this, you can quickly mark or copy or copy+yank things like +words, ip's, url's, lines or defun's with one key binding. I use +this permanently and couldn't live without it anymore. +

+ +

+A special feature is the copy+yanking, this is something vi offers: +go to a line, press yy, then p and the current line will be yanked +below. Prefix with a number and copy+yank more lines. This is +really cool and (in vi) often used. So, with this mode, I can use +it with emacs as well. For example, say you edit a configuration +file and added a complicated statement. Next you need to add +another very similar statement. Instead of entering it again, you +just hit <C-c y y> and the current line appears as a copy +below. Change the differences and you're done! +

+ +
+
(require 'mark-copy-yank-things-mode)
+(mark-copy-yank-things-global-mode)
+
+
+ +

+The mode has a rather impractical prefix since it's published on +github and therefore must be written in a way not to disturb other +modes. However, I myself need those simple prefixes: +

+
+
(define-key mark-copy-yank-things-mode-map (kbd "C-c")   'mcyt-copy-map)
+(define-key mark-copy-yank-things-mode-map (kbd "M-a")   'mcyt-mark-map)
+
+
+

+I use the default yank map +

+ +

+With this I put the last thing copied into a register 'c. I can +then later yank this using C-v anytime without browsing the +kill-ring if I kill things between yanking. So, C-v always inserts +the last copied thing, while C-y yanks the last thing killed, which +might be something else. +

+
+
(advice-add 'mcyt--copy-thing
+            :after
+            '(lambda (&rest args)
+               (with-temp-buffer
+                 (yank)
+                 (copy-to-register 'c (point-min) (point-max)))))
+
+(defun tvd-insert-c-register ()
+  (interactive)
+  (insert-register 'c))
+
+(global-set-key (kbd "C-v")             'tvd-insert-c-register)
+
+
+ +

+copy a real number and convert it to german punctuation upon +yanking, so I can do some calculations in 'calculator, copy the +result NNN.NN and paste it into my online banking formular, where +it appears as NNN,NN. +

+
+
(defun tvd-mcyt-copy-euro (&optional arg)
+  "Copy  euro  at point  into  kill-ring  and convert  to  german
+punctuation"
+  (interactive "P")
+  (mcyt--blink-and-copy-thing 'mcyt-beginning-of-ip 'mcyt-end-of-ip arg)
+  (with-temp-buffer
+    (yank)
+    (beginning-of-buffer)
+    (while (re-search-forward "\\." nil t)
+      (replace-match ","))
+    (kill-region (point-min) (point-max))))
+
+(eval-after-load "mark-copy-yank-things-mode"
+  '(progn
+     (add-hook 'mark-copy-yank-things-mode-hook
+               (lambda () ;; g like [G]eld
+                 (define-key mcyt-copy-map (kbd "g") 'tvd-mcyt-copy-euro)))))
+
+
+ + + +
+
+
+ +
+

6.3.3 change-inner

+
+

+I use change-inner with a prefix key and some wrappers around +mark-copy-yank-things-mode, which is related to change-inner +and expand-region. +

+ +

+github source: +

+
+
(require 'change-inner)
+
+
+ +

+first some functions: +

+ +
+
(defun tvd-ci (beg end &optional ins)
+  "change-inner simulator which works with symbols instead of strings.
+
+BEG and END must be executable elisp symbols moving (point). Everything
+in between will be killed. If INS is non-nil, it will be inserted then."
+  (interactive)
+  (let ((B nil))
+    (funcall beg)
+    (setq B (point))
+    (funcall end)
+    (kill-region B (point))
+    (when ins
+      (insert ins))))
+
+(defun tvd-ci-comment ()
+  "\"change inner\" a whole comment [block]."
+  (interactive)
+  (tvd-ci 'mcyt-beginning-of-comment-block
+          'mcyt-end-of-comment-block
+          (format "%s;# " comment-start)))
+
+(defun tvd-ci-quote ()
+  "\"change inner\" quoted text."
+  (interactive)
+  (tvd-ci 'mcyt-beginning-of-quote
+          'mcyt-end-of-quote))
+
+(defun tvd-ci-word ()
+  "\"change inner\" a word (like cw in vi)."
+  (interactive)
+  (tvd-ci 'mcyt-beginning-of-symbol
+          'mcyt-end-of-symbol))
+
+(defun tvd-ci-line ()
+  "\"change inner\" a whole line."
+  (interactive)
+  (tvd-ci 'beginning-of-line
+          'end-of-line))
+
+(defun tvd-ci-paragraph ()
+  "\"change inner\" a whole paragraph."
+  (interactive)
+  (tvd-ci 'backward-paragraph
+          'forward-paragraph))
+
+(defun tvd-ci-buffer ()
+  "\"change inner\" a whole buffer."
+  (interactive)
+  (tvd-ci 'point-min
+          'point-max))
+
+(defun tvd-ci-sexp ()
+  "\"change inner\" a whole sexp."
+  (interactive)
+  (er/mark-inside-pairs)
+  (call-interactively 'kill-region))
+
+
+ +

+Define ALTR (AltGR) + i as my prefix command for change-inner stuff. +Since I use a german keyboard, this translates to →. +I'll refrence it here now as <A-i …> +

+
+
(define-prefix-command 'ci-map)
+(global-set-key (kbd "→") 'ci-map)
+
+
+ +

+typing the prefix key twice calls the real change-inner +

+
+
(define-key ci-map (kbd "→") 'change-inner) ;; <A-i A-i>
+
+(define-key ci-map (kbd "c") 'tvd-ci-comment) ;; <A-i c>
+(define-key ci-map (kbd "¢") 'tvd-ci-comment) ;; <A-i A-c>
+
+(define-key ci-map (kbd "q") 'tvd-ci-quote) ;; <A-i q>
+(define-key ci-map (kbd "@") 'tvd-ci-quote) ;; <A-i A-q>
+
+(define-key ci-map (kbd "w") 'tvd-ci-word) ;; <A-i w>
+(define-key ci-map (kbd "ł") 'tvd-ci-word) ;; <A-i A-w>
+
+(define-key ci-map (kbd "l") 'tvd-ci-line) ;; <A-i l>
+
+(define-key ci-map (kbd "s") 'tvd-ci-sexp) ;; <A-i s>
+(define-key ci-map (kbd "ſ") 'tvd-ci-sexp) ;; <A-i A-s>
+
+(define-key ci-map (kbd "p") 'tvd-ci-paragraph) ;; <A-i p>
+(define-key ci-map (kbd "þ") 'tvd-ci-paragraph) ;; <A-i A-p>
+
+(define-key ci-map (kbd "a") 'tvd-ci-buffer) ;; <A-i a>
+(define-key ci-map (kbd "æ") 'tvd-ci-buffer) ;; <A-i A-a>
+
+
+ +
+
+
+
+

6.3.4 Rotate text

+
+

+This one is great as well, I use it to toggle flags and such stuff +in configs or code with just one key binding. +

+ +

+Source: nschum.de +

+ +
+
(autoload 'rotate-text "rotate-text" nil t)
+(autoload 'rotate-text-backward "rotate-text" nil t)
+
+
+ +

+my toggle list +

+
+
(setq rotate-text-words '(("width" "height")
+                          ("left" "right" "top" "bottom")
+                          ("ja" "nein")
+                          ("off" "on")
+                          ("true" "false")
+                          ("nil" "t")
+                          ("yes" "no")))
+
+
+ +

+C-t normally used by transpose-chars, so, unbind it first +

+
+
(global-unset-key (kbd "C-t"))
+
+
+ +

+however, we cannot re-bind it globally since then it could not be +used in org-mode for org-todo (see below) FIXME: I only use the "t" +short command anymore, so C-t would be free now, wouldn't it? +

+
+
(add-something-to-mode-hooks
+ '(c c++ cperl vala web emacs-lisp python ruby)
+ '(lambda ()
+    (local-set-key (kbd "C-t") 'rotate-text)))
+
+
+ +
+
+
+ +
+

6.3.5 Word wrapping

+
+

+same as word-wrap but without the fringe which I hate the most! +

+
+
(add-something-to-mode-hooks '(tex text eww) 'visual-line-mode)
+
+
+ +

+however, it's required when coding, so enable it globally +overwritten by visual-line-mode above for specifics +

+
+
(setq word-wrap t)
+
+
+
+
+
+ +
+

6.3.6 Viking Mode

+
+

+Delete stuff fast. Press the key multiple times - delete more +things. Inspired by expand-region. Written by myself. +

+ +
+
(require 'viking-mode)
+(viking-global-mode)
+(setq viking-greedy-kill nil)
+(define-key viking-mode-map (kbd "M-d") 'viking-repeat-last-kill)
+
+
+
+
+
+ +
+

6.3.7 HTMLize

+
+

+extracted from debian package emacs-goodies-el-35.2+nmu1, since +there's no other source left. Generates a fontified html version of +the current buffer, however it looks. +

+ +
+
(require 'htmlize)
+(setq htmlize-output-type "inline-css")
+
+
+
+
+ + +
+

6.3.8 iEdit (inline edit multiple searches)

+
+

+Edit all occurences of something at once. Great for re-factoring. +

+ +
+
(require 'iedit)
+
+(global-set-key (kbd "C-c C-e")           'iedit-mode)
+
+
+ +

+Keep buffer-undo-list as is while iedit is active, that is, as long +as I am inside iedit I can undo/redo current occurences. However, +if I leave iedit and issue the undo command, ALL changes made with +iedit are undone, whereas the default behaviour would be to go +through every change made iside iedit, which I hate. +

+ +

+iedit doesn't provide a customizable flag to configure it's undo +behavior, so, I modify it myself using defadvice. +

+ +
+
(setq tvd-buffer-undo-list nil)
+(advice-add 'iedit-mode :before '(lambda (&rest args) ;; save current
+                                   (setq tvd-buffer-undo-list buffer-undo-list)))
+
+(advice-add 'iedit-mode :after '(lambda (&rest args) ;; restore previously saved
+                                  (setq buffer-undo-list tvd-buffer-undo-list)))
+
+
+ +
+
+
+
+ +
+

6.4 Interactives

+
+
+

6.4.1 eShell stuff, or if interactive stuff is needed, use ansi-term

+
+

+I am a hardcore bash user, but from time to time eshell is good +enough. It's great when used remote when only sftp is supported. +

+ +
+
(require 'eshell)
+
+
+ +

+fac'ifier +

+
+
(defmacro with-face (str &rest properties)
+  `(propertize ,str 'face (list ,@properties)))
+
+
+ +

+custom prompt, which resembles my bash prompt +

+
+
(defun shk-eshell-prompt ()
+  (let ((header-bg "Azure"))
+    (concat
+     (with-face "\n")
+     (with-face (format-time-string
+                 "[%Y-%m-%d %H:%M] --- ["
+                 (current-time)) :background header-bg :foreground "Black")
+     (with-face (concat (eshell/pwd) "") :background header-bg :foreground "Blue")
+     (with-face "] --- " :background header-bg :foreground "Black")
+     (with-face  (or
+                  (ignore-errors (format "(%s)" (vc-responsible-backend default-directory)))
+                  "") :background header-bg)
+     (with-face "\n" :background header-bg)
+     (with-face user-login-name :foreground "blue")
+     "@"
+     (with-face "localhost" :foreground "blue")
+     (if (= (user-uid) 0)
+         (with-face " #" :foreground "red")
+       " $")
+     " ")))
+
+(setq eshell-prompt-function 'shk-eshell-prompt)
+(setq eshell-highlight-prompt nil)
+
+
+ +

+I use my own virtual loggin target /dev/log, just redirect +command output to /dev/log and it will be saved to +the LOG buffer. > inserts, >> appends +N.B: /dev/kill puts the stuff into the kill-ring. +

+
+
(defun log-comment ()
+  (with-current-buffer (get-buffer-create "*LOG*")
+    (insert (format "# %s\n" (time-stamp-string)))))
+
+(defun log-insert (string)
+  (with-current-buffer (get-buffer-create "*LOG*")
+    (delete-region (point-min) (point-max))
+    (log-comment)
+    (insert string)
+    (message "wrote output to *LOG* buffer")))
+
+(defun log-append (string)
+  (with-current-buffer (get-buffer-create "*LOG*")
+    (end-of-buffer)
+    (newline)
+    (log-comment)
+    (insert string)
+    (message "wrote output to *LOG* buffer")))
+
+
+ +

+must return a defun which gets the stuff as ARG1 +'mode is 'overwrite or 'append +

+
+
(add-to-list 'eshell-virtual-targets '("/dev/log" (lambda (mode)
+                                              (if (eq mode 'overwrite)
+                                                  'log-insert
+                                                'log-append))
+                                      t
+                                      ))
+
+
+ +

+eshell config +

+
+
(eval-after-load "eshell"
+  '(progn
+     (add-hook 'eshell-mode-hook
+               (lambda ()
+                 (local-unset-key (kbd "C-c C-r")) ; we're already using this for windresize
+                 (add-to-list 'eshell-visual-commands "tail")
+                 (add-to-list 'eshell-visual-commands "top")
+                 (add-to-list 'eshell-visual-commands "vi")
+                 (add-to-list 'eshell-visual-commands "ssh")
+                 (add-to-list 'eshell-visual-commands "tail")
+                 (add-to-list 'eshell-visual-commands "mutt")
+                 (add-to-list 'eshell-visual-commands "note")
+                 (setenv "TERM" "xterm")
+                 (local-set-key (kbd "C-l") 'eshell/clear)
+                 (define-key viking-mode-map (kbd "C-d") nil) ;; need to undef C-d first
+                 (local-set-key (kbd "C-d") 'eshell/x)
+                 (setq mode-name "ESH"
+                       eshell-hist-ignoredups t
+                       eshell-history-size 5000
+                       eshell-where-to-jump 'begin
+                       eshell-review-quick-commands nil
+                       eshell-smart-space-goes-to-end t
+                       eshell-scroll-to-bottom-on-input 'all
+                       eshell-error-if-no-glob t
+                       eshell-save-history-on-exit t
+                       eshell-prefer-lisp-functions t)))))
+
+
+ +

+exit and restore viking key binding afterwards +

+
+
(defun eshell/x (&rest args)
+  (interactive)
+  (eshell-life-is-too-much)
+  (define-key viking-mode-map (kbd "C-d") 'viking-kill-thing-at-point))
+
+
+ +

+open files in emacs, split the shell if not already splitted +open empty window if no file argument given. +

+
+
(defun eshell/emacs (&rest args)
+  "Editor commands fired from eshell will be handled by emacs, which already runs anyway."
+  (interactive)
+  (let* ((framesize (frame-width))
+         (winsize (window-body-width)))
+    (progn
+      (if (eq winsize framesize)
+          (split-window-horizontally))
+      (other-window 1)
+      (if (null args)
+          (bury-buffer)
+        (mapc #'find-file (mapcar #'expand-file-name (eshell-flatten-list (reverse args))))))))
+
+(defun eshell/clear ()
+  "Better clear  command than (recenter  0) which doesn't work  as I
+want.  This version really removes  the output of previous commands
+and puts the shell to the beginning of a really (then) empty eshell
+buffer. However,  just to be sure  that I do no  accidentally clear
+some  shell output  that might  be useful  in the  future, it  also
+copies   the   cleared   stuff   into   a   backup   buffer   named
+*eshell-log-buffer*, just in case."
+  (interactive)
+  (let ((beg (point-min))
+        (end (point-max))
+        (savebuffer "*eshell-log-buffer*")
+        (log (buffer-substring-no-properties (point-min) (point-max))))
+    (progn
+      (if (not (get-buffer savebuffer))
+          (get-buffer-create savebuffer))
+      (with-current-buffer savebuffer
+        (goto-char (point-max))
+        (insert log))
+      (delete-region beg end)
+      (eshell-emit-prompt))))
+
+(defun eshell/perldoc (&rest args)
+  "Like `eshell/man', but invoke `perldoc'."
+  (funcall 'eshell/perldoc (apply 'eshell-flatten-and-stringify args)))
+
+(defun eshell/perldoc (man-args)
+  (interactive "sPerldoc: ")
+  (require 'man)
+  (let ((manual-program "perldoc"))
+    (man man-args)))
+
+(defun eshell-here ()
+  "Opens up a new shell in the directory associated with the
+current buffer's file. The eshell is renamed to match that
+directory to make multiple eshell windows easier."
+  (interactive)
+  (let* ((parent (if (buffer-file-name)
+                     (file-name-directory (buffer-file-name))
+                   default-directory))
+         (height (/ (window-total-height) 3))
+         (name   (car (last (split-string parent "/" t)))))
+    (split-window-vertically (- height))
+    (other-window 1)
+    (eshell "new")
+    (rename-buffer (concat "*eshell: " name "*"))
+    (insert (concat "ls"))
+    (eshell-send-input)))
+
+
+ +

+via howardism +

+
+
(defun eshell-there (host)
+  "Opens a shell on a remote host using tramp."
+  (interactive "sHost: ")
+  (let ((default-directory (format "/%s:" host)))
+    (eshell host)))
+
+(defalias 'es        'eshell-here)
+(defalias 'et        'eshell-there)
+(defalias 'eshell/vi 'eshell/emacs)
+
+
+ +

+plan9 smart command, edit while exec if not silent or successful +

+
+
(require 'em-smart)
+
+
+ +

+eshell shell aliases. I set the global +defvar here so there's no need to transport +~/.emacs.d/eshell/aliases across networks +

+
+
(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 " "))))
+
+
+ +

+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))
+(+alias 'x      '(eshell/exit))
+
+
+ +

+no need for less or more, this is emacs, isn't it? +

+
+
(setenv "PAGER" "cat")
+
+
+ +
+
+
+ +
+

6.4.2 Emacs LISP interactive

+
+

+General configuration for all things elisp. +

+ +

+By using C-x-e I can push region or buffer +of lisp code (i.e. inside scratch) into +REPL where it will be evaluated +

+ +
+
(defun tvd-get-code()
+  "helper: returns marked region or the whole buffer contents"
+  ;; /FIXME/: mv to string helpers?
+  (if mark-active
+      (let (  ;; save region and buffer
+            (partb (buffer-substring-no-properties (region-beginning) (region-end)))
+            (whole (buffer-substring-no-properties (point-min) (point-max)))
+            )
+        (if (> (length partb) 0)
+            partb
+          whole
+          )
+        )
+    ;; no mark, also return everything
+    (buffer-substring-no-properties (point-min) (point-max))))
+
+(defun tvd-send-region-to-repl ()
+  "put region or buffer into elisp repl and eval"
+  (interactive)
+  (let ( ;; fetch region or buffer contents
+        (code  (tvd-get-code)))
+    (progn
+      (if (not (get-buffer "*ielm*"))
+          ;; ielm not yet running, start it in split window but stay here
+          (progn
+            (split-window-horizontally)
+            (other-window 1)
+            (ielm)
+            (other-window 1)))
+      ;; finially, paste content into ielm and evaluate it
+      ;; still we stay where we are
+      (with-current-buffer "*ielm*"
+        (goto-char (point-max))
+        (insert code)
+        (ielm-return)))))
+
+(defun tvd-elisp-eval()
+  "just eval region or buffer whatever feasible"
+  (interactive)
+  (progn
+    (if mark-active
+        (eval-region)
+      (eval-buffer))))
+
+(defun ff ()
+  "Jump to function definition at point."
+  (interactive)
+  (find-function-other-window (symbol-at-point)))
+
+(defun tvd-make-defun-links ()
+  "experimental: make function calls clickable, on click, jump to definition of it"
+  (interactive)
+  (let ((beg 0)
+        (end 0)
+        (fun nil))
+    (goto-char (point-min))
+    (while (re-search-forward "(tvd[-a-z0-9]*" nil t)
+      (setq end (point))
+      (re-search-backward "(" nil t)
+      (forward-char 1)
+      (setq beg (point))
+      (setq fun (buffer-substring-no-properties beg end))
+      (make-button beg end 'action
+                   (lambda (x)
+                     (find-function-other-window (symbol-at-point))))
+      (goto-char end))))
+
+(defun emacs-change-version (v)
+  "Change version of .emacs (must be the current buffer).
+Returns t if version changed, nil otherwise."
+  (interactive
+   (list
+    (completing-read "New config version (press TAB for old): "
+                     (list tvd-emacs-version))))
+  (if (equal v tvd-emacs-version)
+      nil
+    (save-excursion
+      (show-all)
+      (beginning-of-buffer)
+      (tvd-replace-all (format "\"%s\"" tvd-emacs-version)
+                       (format "\"%s\"" v))
+      (setq tvd-emacs-version v)
+      (message (format "New config version set: %s" v))
+      t)))
+
+(defun emacs-change-log (entry)
+  "Add a changelog entry to .emacs Changelog"
+  (interactive "Menter change log entry: ")
+  (let ((newversion (call-interactively 'emacs-change-version)))
+      (save-excursion
+        (show-all)
+        (beginning-of-buffer)
+        (re-search-forward ";; .. Changelog")
+        (next-line)
+        (tvd-outshine-end-of-section)
+        (when newversion
+          (insert (format "\n;; %s\n" tvd-emacs-version)))
+        (insert (format ";;    - %s\n" entry)))))
+
+
+ +

+elisp config +

+
+
(add-hook 'emacs-lisp-mode-hook
+          (lambda()
+            ;; non-separated x-e == eval hidden, aka current buffer
+            (local-set-key (kbd "C-x C-e")  'tvd-elisp-eval)
+            ;; separate 'e' == separate buffer
+            (local-set-key (kbd "C-x e")    'tvd-send-region-to-repl)
+            (setq mode-name "EL"
+                  show-trailing-whitespace t)
+            (eldoc-mode t)
+
+            ;; enable outline (with outshine)
+            (outline-minor-mode)
+
+            ;; enable outshine mode
+            (outshine-hook-function)
+
+            (electric-indent-mode t)))
+
+
+ +

+use UP arrow for history in ielm as well, just as C-up +

+
+
(add-hook 'comint-mode-hook
+          (lambda()
+            (define-key comint-mode-map [up] 'comint-previous-input)))
+
+
+ +

+sometimes I use lisp in minibuffer +

+
+
(defun ee()
+  (interactive)
+  (electric-pair-mode)
+  (call-interactively 'eval-expression)
+  (electric-pair-mode))
+
+
+ +

+sometimes I eval regions +

+
+
(defalias 'er        'eval-region)
+
+
+ +

+… or defuns +

+
+
(defalias 'ef        'eval-defun)
+
+
+ +

+I like to have some functions fontified differently +

+
+
(font-lock-add-keywords
+ 'emacs-lisp-mode
+ '(("(\\s-*\\(eq\\|if\\|cond\\|and\\|set\\|or\\|not\\|when\\|setq\\|let**\\|lambda\\|kbd\\|defun\\|car\\|cdr\\)\\s-+"
+    1 'font-lock-keyword-face)))
+
+
+ +

+same applies for quoted symbols +

+
+
(font-lock-add-keywords
+ 'emacs-lisp-mode
+ '(("'[-a-zA-Z_][-a-zA-Z0-9_]*\\>" 0 'font-lock-constant-face)))
+
+
+ +

+I hate it when help, debug, ielm and other peripheral buffers +litter my emacs window setup. So, this function fixes this: it +opens a new frame with all those buffers already opened and pinned. +

+ +
+
(defun dev ()
+  "Open a new emacs frame with some development peripheral buffers."
+  (interactive)
+  (let ((F (new-frame)))
+    (with-selected-frame F
+      (with-current-buffer (get-buffer-create "*Help*")
+        (help-mode))
+      (with-current-buffer (get-buffer-create "*ielm*")
+        (ielm))
+      (with-current-buffer (get-buffer-create "*suggest*")
+        (suggest))
+      (switch-to-buffer "*ielm*")
+      (split-window-horizontally)
+      (split-window-vertically)
+      (windmove-down)
+      (switch-to-buffer "*suggest*")
+      (tvd-suggest-reload)
+      (tvd-suggest-reload)
+      (windmove-right)
+      (switch-to-buffer "*Help*")
+      (split-window-vertically)
+      (windmove-down)
+      (switch-to-buffer "*scratch*")
+      (set-window-dedicated-p (selected-window) t)
+      (set-background-color "azure"))))
+
+
+ + +
+
+
+
+

6.4.3 el2markdown

+
+

+el2markdown is a module which +can be used to convert Commentary sections into markdown files. I use this to +avoid maintaining the README.md and the Commentary section in parallel. +

+ +
+
(require 'el2markdown)
+
+
+ +

+To use, call el2markdown-view-buffer and put it into the +README.md. Take care though: it doesn't convert the META section. +

+ +

+FIXME: write a wrapper to circumvent these restrictions. +

+
+
+ +
+

6.4.4 tramp mode

+
+

+Edit remote files, one of the best things in emacs. I use it every day heavily. +

+ +

+Sample: C-x-f /$host:/$file ($host as of .ssh/config or direct, $file including completion) +

+ +

+doku: gnu.org +

+
+
(setq tramp-default-method "ssh"
+      tramp-default-user nil
+      tramp-verbose 1
+      ido-enable-tramp-completion t)
+
+
+ +

+see also backup section +

+ +
+
+
+ +
+

6.4.5 org mode

+
+

+I use org mode to take notes mostly at work. I also track projects +and TODO lists etc. I do not, however, use agenda or any +scheduling whatsoever. +

+ +
+
(require 'org)
+
+
+ +

+I like custom bullets +

+
+
(require 'org-bullets)
+
+
+ +

+enable syntax highlighting for embedded source blocks +

+
+
(require 'ob-python)
+(require 'ob-perl)
+(require 'ob-shell)
+
+(setq org-bullets-bullet-list '("►" "✜" "✸" "✿" "♦"))
+
+
+ +

+capture target, os-dependend +

+
+
(if (null tvd-win-home)
+    (setq tvd-org-file (concat tvd-lisp-dir "/notizen.org")
+          org-attach-directory (concat tvd-lisp-dir "/attachments"))
+  (setq tvd-org-file (concat tvd-win-home "/notizen.org")
+        org-attach-directory (concat tvd-win-home "/attachments")))
+
+
+ +

+text formatting made easy, bound to C-c keys locally +

+
+
(defun tvd-org-emphasize(CHAR)
+  "expand once if no region and apply emphasize CHAR"
+  (interactive)
+  (unless (region-active-p)
+    (er/expand-region 1))
+  (org-emphasize CHAR))
+
+(defun bold()
+  "bold text in org mode"
+  (interactive)
+  (tvd-org-emphasize '42))
+
+(defun italic()
+  "italic text in org mode"
+  (interactive)
+  (tvd-org-emphasize '47))
+
+(defun code()
+  "verbatim text in org mode"
+  (interactive)
+  (tvd-org-emphasize '126))
+
+(defun underline()
+  "underline text in org mode"
+  (interactive)
+  (tvd-org-emphasize '95))
+
+
+ +

+my org-mode specific <C-left> and <C-right> +

+
+
(defun tvd-org-left-or-level-up()
+  "jump one word to the left if not on a org heading,
+otherwise fold current level and jump one level up."
+  (interactive)
+  (if (and (org-at-heading-p) (looking-at "*"))
+      (progn
+        (hide-subtree)
+        (outline-up-heading 1))
+    (left-word)))
+
+(defun tvd-org-heading-up()
+  "If on a heading, fold current heading, jump one level
+up and unfold it, otherwise jump paragraph as usual."
+  (interactive)
+  (if (and (org-at-heading-p) (looking-at "*"))
+      (progn
+        (hide-subtree)
+        (org-backward-heading-same-level 1)
+        (org-cycle))
+    (backward-paragraph)))
+
+(defun tvd-org-heading-down()
+  "If on a heading, fold current heading, jump one level
+down and unfold it, otherwise jump paragraph as usual."
+  (interactive)
+  (if (and (org-at-heading-p) (looking-at "*"))
+      (progn
+        (hide-subtree)
+        (org-forward-heading-same-level 1)
+        (org-cycle))
+    (forward-paragraph)))
+
+
+ +

+org-mode specific config, after load +

+
+
(eval-after-load "org"
+  '(progn
+     (add-hook 'org-mode-hook
+               (lambda ()
+                 (setq
+                  org-M-RET-may-split-line nil
+                  org-agenda-files (list tvd-org-file)
+                  org-agenda-restore-windows-after-quit t
+                  org-blank-before-new-entry (quote ((heading . auto) (plain-list-item . auto)))
+                  org-catch-invisible-edits (quote error)
+                  org-columns-default-format "%80ITEM %22Timestamp %TODO %TAGS %0PRIORITY"
+                  org-insert-heading-always-after-current (quote t)
+                  org-mouse-1-follows-link nil
+                  org-remember-store-without-prompt t
+                  org-reverse-note-order t
+                  org-startup-indented t
+                  org-startup-truncated nil
+                  org-return-follows-link t
+                  org-use-speed-commands t
+                  org-yank-adjusted-subtrees t
+                  org-refile-targets '((nil . (:maxlevel . 5)))
+                  org-refile-use-outline-path t
+                  org-outline-path-complete-in-steps nil
+                  org-completion-use-ido t
+                  org-support-shift-select t
+                  org-hide-emphasis-markers t
+                  org-fontify-done-headline t
+                  org-pretty-entities t
+                  org-use-sub-superscripts nil
+                  org-confirm-babel-evaluate nil)
+                                        ; shortcuts
+                 (setq org-speed-commands-user
+                       (quote (
+                               ("0" . ignore)
+                               ("1" . delete-other-windows)
+                               ("2" . ignore)
+                               ("3" . ignore)
+                               ("d" . org-archive-subtree-default-with-confirmation) ; delete, keep track
+                               ("v" . org-narrow-to-subtree) ; only show current heading ("view")
+                               ("q" . widen) ; close current heading and show all ("quit")
+                               (":" . org-set-tags-command) ; add/edit tags
+                               ("t" . org-todo) ; toggle todo type, same as C-t
+                               ("z" . org-refile) ; archive the (sub-)tree
+                               ("a" . org-attach) ; manage attachments
+                               )))
+                                        ; same as toggle
+                 (local-set-key (kbd "C-t") 'org-todo)
+
+                                        ; alt-enter = insert new subheading below current
+                 (local-set-key (kbd "<M-return>") 'org-insert-subheading)
+
+                                        ; search for tags (ends up in agenda view)
+                 (local-set-key (kbd "C-f") 'org-tags-view)
+
+                                        ; run presenter, org-present must be installed and loadedwhite
+                 (local-set-key (kbd "C-p") 'org-present)
+
+                                        ; todo colors
+                 (setq org-todo-keyword-faces '(
+                                                ("TODO"   . (:foreground "#b70101"     :weight bold))
+                                                ("START"  . (:foreground "blue"        :weight bold))
+                                                ("WAIT"   . (:foreground "darkorange"  :weight bold))
+                                                ("DONE"   . (:foreground "forestgreen" :weight bold))
+                                                ("CANCEL" . (:foreground "red"         :weight bold))
+                                                ))
+
+                 (local-set-key (kbd "C-c b") 'bold)
+                 (local-set-key (kbd "C-c /") 'italic)
+                 (local-set-key (kbd "C-c 0") 'code) ; aka = without shift
+                 (local-set-key (kbd "C-c _") 'underline)
+
+                                        ; edit babel src block in extra buffer:
+                                        ; default is C-c ' which is hard to type
+                                        ; brings me to src code editor buffer
+                                        ; Also note: enter <s then TAB inserts a code block
+                                        ; Next, C-c C-c executes the code, adding :results table at the
+                                        ; end of the begin line, creates a table of the output
+                 (local-set-key (kbd "C-c C-#") 'org-edit-special)
+
+                                        ; faster jumping
+                 (local-set-key (kbd "<C-up>")   'tvd-org-heading-up)
+                 (local-set-key (kbd "<C-down>") 'tvd-org-heading-down)
+
+                                        ; move word left or heading up, depending where point is
+                 (local-set-key (kbd "<C-left>") 'tvd-org-left-or-level-up)
+
+                                        ; use nicer bullets
+                 (org-bullets-mode 1)
+
+                 (org-babel-do-load-languages 'org-babel-load-languages
+                                              '((python     . t)
+                                                (emacs-lisp . t)
+                                                (shell      . t)
+                                                (perl       . t)))))))
+
+
+ +

+no more … at the end of a heading +

+
+
(setq org-ellipsis " ⤵")
+
+
+ +

+my own keywords, must be set globally, not catched correctly inside hook +

+
+
(setq org-todo-keywords
+      '((sequence "TODO" "START" "WAIT" "|" "DONE" "CANCEL")))
+
+
+ +

+I always want to be able to capture, even if no ORG is running +

+
+
(global-set-key (kbd "C-n")             (lambda () (interactive) (org-capture)))
+
+
+ +

+must be global since code edit sub buffers run their own major mode, not org +

+
+
(global-set-key (kbd "C-c C-#")         'org-edit-src-exit)
+
+
+ +

+some org mode vars must be set globally +

+
+
(setq org-default-notes-file tvd-org-file
+      org-startup-indented t
+      org-indent-indentation-per-level 4)
+
+
+ +

+my own capture templates +

+
+
(setq org-capture-templates
+      '(("n" "Project" entry (file+headline tvd-org-file "Unsorted Tasks")
+         "* TODO %^{title}\n%u\n** Kostenstelle\n** Contact Peer\n** Contact Customer\n** Aufträge\n** Daten\n** Notizen\n  %i%?\n"
+         :prepend t :jump-to-captured t)
+
+        ("t" "Todo Item" entry (file+headline tvd-org-file "Manual-Agenda-Tasks")
+         "* TODO %^{title}\n:LOGBOOK:\n%u:END:\n" :prepend t :immediate-finish t)
+
+        ("s" "Scheduled Item" entry (file+headline tvd-org-file "Scheduled-Agenda-Tasks")
+         "* TODO %^t %^{title}\n:LOGBOOK:\n%u:END:\n" :prepend t :immediate-finish t)
+
+        ("j" "Journal" entry (file+headline tvd-org-file "Kurznotizen")
+         "* TODO %^{title}\n%u\n  %i%?\n" :prepend t :jump-to-captured t)
+
+        ("c" "Copy/Paste" entry (file+headline tvd-org-file "Kurznotizen")
+         "* TODO %^{title}\n%u\n  %x\n" :immediate-finish t :prepend t :jump-to-captured t)))
+
+
+ +

+follow links using eww, if present +

+
+
(if (fboundp 'eww-browse-url)
+    (setq browse-url-browser-function 'eww-browse-url))
+
+
+ +

+mark narrowing with an orange fringe, the advice for 'widen +is in the outline section. +

+
+
(advice-add 'org-narrow-to-subtree :after
+            '(lambda (&rest args)
+               (set-face-attribute 'fringe nil :background tvd-fringe-narrow-bg)))
+
+
+ +

+always use the latest docs +

+
+
(with-eval-after-load 'info
+    (info-initialize)
+    (add-to-list 'Info-directory-list
+                 (expand-file-name "~/.emacs.d/lisp/org/doc")))
+
+
+
+
+
+
+

6.4.6 org agenda mode

+
+

+I use org mode for along time now, primarily at work, but did not +use agenda. Instead I developed the habit of maintaining one org +entry which contains just a list with all things to do today. I +just edited this list manually and it worked. However, recently I +found out that agenda provides lots of features and commands +precisely for what I already did manually. So, now, finally (as of +november 2018) I switch to using the agenda. +

+ +

+My agenda use is very simple though: I don't use any scheduling, no +priorities, no recurring events, no daily or other time based +views. I just keep a list of TODO entries and another of entries in +WAIT state, that's it. All those entries are located under a +special org entry with the title "Heute" and the category (as +property) WORK, which I use for filtering out agenda items. +

+ +

+The general workflow is as follows: I execute (agenda) which starts +directly my custom agenda view. It lists open TODO items and +waiting WAIT items below. If I press `n', I will be asked for a +title and a new TODO item appears in my agenda. I can press `d' to +mark it as DONE, it will also be archived into a subsibling below +"HEUTE". I can press `w' to move an item into WAIT state and I can +press `a' to add text to the org entry under point (like "waiting +for customer email"). +

+ +

+So, I don't use my regular org entries, which are in most cases +very large containing lots of information, as agenda items, but +only very short ones which act as reminders about what work I have +to do. However, since I have the org buffer always opened and +visible in a split buffer next to the agenda, it is no problem to +go to such a deep entry for editing or viewing. +

+ +
+
(require 'org-agenda)
+
+
+ +

+This is my one and only agenda custom view, it displays TODO items +below entries categorized as WORK and WAIT items under the same +category. The cool thing here is, that the `tags' agenda view can +be used to filter for properties as well. In order to have this +working the following property drawer must exist in an entry with +TODO siblings: +

+ +
    +
  • +START Arbeit +

    +

    +:CATEGORY: WORK +

  • +
+

+* TODO a thing to do +* WAIT a thing waiting for something +

+ +
+
(setq org-agenda-custom-commands
+      '(("o" "Daily TODO Tasks"
+         (
+          ;; a block containing only items scheduled for today, if any
+          (agenda ""
+                  ((org-agenda-span 1)
+                   (org-agenda-overriding-header "Tasks scheduled:")))
+          ;; manually created todo items due (state TODO)
+          (tags "CATEGORY=\"WORK\""
+                ((org-agenda-skip-function '(org-agenda-skip-entry-if 'todo '("CANCEL" "START" "DONE" "WAIT")))
+                 (org-agenda-overriding-header "\nTasks to do today:")
+                 (org-agenda-follow-mode t)
+                 (org-agenda-entry-text-mode t)))
+          ;; manually created todo items in wait state
+          (tags "CATEGORY=\"WORK\""
+                ((org-agenda-skip-function '(org-agenda-skip-entry-if 'todo '("CANCEL" "START" "DONE" "TODO")))
+                 (org-agenda-overriding-header "\nTasks Waiting:"))))
+         ((org-agenda-compact-blocks t)))))
+
+
+ +

+A shortcut to reach my custom view directly +

+
+
(defun agenda ()
+  "Visit my org agenda directly, splits left"
+  (interactive)
+  (org-agenda nil "o")
+  (tvd-flip-windows)
+  (other-window-or-switch-buffer))
+
+
+ +

+Add a line of text to the top of an existing TODO entry and refresh +the agenda +

+
+
(defun tvd-org-agenda-edit-entry (note)
+  "Insert a note as plain text into an entry"
+  (interactive "sEnter note: ")
+  (save-excursion
+    (org-agenda-switch-to)
+    (end-of-line)
+    (newline)
+    (insert note))
+  (switch-to-buffer "*Org Agenda*")
+  (org-agenda-redo t))
+
+
+ +

+Mark an entry as DONE, archive it to an archive sibling and refresh +the agenda +

+
+
(defun tvd-org-agenda-done()
+  (interactive)
+  (org-agenda-todo 'done)
+  (org-agenda-archive-to-archive-sibling)
+  (org-agenda-redo t))
+
+
+ +

+Mark an entry as WAIT, archive it to an archive sibling and refresh +the agenda +

+
+
(defun tvd-org-agenda-wait()
+  (interactive)
+  (org-agenda-todo "WAIT")
+  (org-agenda-redo t))
+
+
+ +

+A wrapper which executes an org capture directly. `t' is the +shortcut for the capture, defined above in org mode. +

+
+
(defun tvd-org-agenda-capture (task)
+  "Capture a task in agenda mode, using the date at point"
+  (interactive)
+  (let ((org-overriding-default-time (org-get-cursor-date)))
+    (org-capture nil task)
+    (org-agenda-redo t)))
+
+(defun tvd-org-agenda-capture-todo ()
+  "Capture a todo task in agenda mode"
+  (interactive)
+  (tvd-org-agenda-capture "t"))
+
+(defun tvd-org-agenda-capture-scheduled ()
+  "Capture a scheduled task in agenda mode"
+  (interactive)
+  (tvd-org-agenda-capture "s"))
+
+
+ + + + + +

+Sometimes it is nice to see the agenda alone, so I press +`o'. However, since follow mode is enabled, once I move point, the +org buffer re-appears. +

+
+
(defun tvd-org-agenda-solitair ()
+  (interactive)
+  (delete-other-windows)
+  (setq org-agenda-follow-mode nil)
+  (message "Org Agenda Follow Mode Disabled"))
+
+
+ +

+The original function scrolls the buffer every time when it runs a +little bit up, which is annoying, to say the least +

+
+
(defun tvd-org-agenda-redo()
+  (interactive)
+  (org-agenda-redo t)
+  (beginning-of-buffer))
+
+
+ +

+Since I learned to love hydra, I have one for my agenda as well, of course: +

+
+
(defhydra hydra-org-agenda (:color blue
+                                   :pre (setq which-key-inhibit t)
+                                   :post (setq which-key-inhibit nil)
+                                   :hint none)
+  "
+Org Agenda (_q_uit)
+
+^Tasks^                             ^Options^             ^Movement^
+-^^^^^^-------------------------------------------------------------------------------------
+_n_: create new todo task           _f_: follow =?f?      ENTER:     switch to entry
+_N_: create new scheduled task      _e_: entry  =?e?      C-<up>:    go one entry up
+_d_: mark task done and archive     _o_: one window       C-<down>:  go one entry down
+_w_: mark task waiting              ^^                    M-<up>:    move entry up
+_t_: toggle todo state              ^^                    M-<down>:  move entry down
+_z_: archive task                   ^ ^
+_+_: increase prio
+_-_: decrease prio                  ^Marking^
+_g_: refresh                        _m_: mark entry
+_s_: save org buffer(s)             _u_: un-mark entry
+_a_: add a note to the entry        _U_: un-mark all
+_k_: delete a task w/o archiving    _B_: bulk action
+
+"
+  ("a" tvd-org-agenda-edit-entry nil)
+  ("n" tvd-org-agenda-capture-todo nil)
+  ("N" tvd-org-agenda-capture-scheduled nil)
+  ("o" tvd-org-agenda-solitair nil)
+  ("g" tvd-org-agenda-redo)
+  ("t" org-agenda-todo)
+  ("d" tvd-org-agenda-done nil)
+  ("w" tvd-org-agenda-wait nil)
+  ("z" org-agenda-archive-to-archive-sibling nil)
+  ("+" org-agenda-priority-up nil)
+  ("-" org-agenda-priority-down nil)
+  ("s" org-save-all-org-buffers nil)
+  ("f" org-agenda-follow-mode
+   (format "% -3S" org-agenda-follow-mode))
+  ("e" org-agenda-entry-text-mode
+   (format "% -3S" org-agenda-entry-text-mode))
+  ("m" org-agenda-bulk-mark nil)
+  ("u" org-agenda-bulk-unmark nil)
+  ("U" org-agenda-bulk-remove-all-marks nil)
+  ("B" org-agenda-bulk-action nil)
+  ("k" org-agenda-kill nil)
+  ("q" nil nil :color red))
+
+
+ +

+Configuration and key bindings for org agenda (same as in the hydra) +

+
+
(add-hook 'org-agenda-mode-hook '(lambda () (progn
+                                              (setq org-agenda-follow-mode t
+                                                    org-log-into-drawer t
+                                                    org-agenda-entry-text-mode t
+                                                    org-agenda-sorting-strategy '(priority-down timestamp-down))
+                                              (local-set-key (kbd "n") 'tvd-org-agenda-capture-todo)
+                                              (local-set-key (kbd "N") 'tvd-org-agenda-capture-scheduled)
+                                              (local-set-key (kbd "o") 'tvd-org-agenda-solitair)
+                                              (local-set-key (kbd "a") 'tvd-org-agenda-edit-entry)
+                                              (local-set-key (kbd "d") 'tvd-org-agenda-done)
+                                              (local-set-key (kbd "w") 'tvd-org-agenda-wait)
+                                              (local-set-key (kbd "g") 'tvd-org-agenda-redo)
+                                              (local-set-key (kbd "f") 'org-agenda-follow-mode)
+                                              (local-set-key (kbd "e") 'org-agenda-entry-text-mode)
+                                              (local-set-key (kbd "k") 'org-agenda-kill)
+                                              (local-set-key (kbd "z") 'org-agenda-archive-to-archive-sibling)
+                                              (local-set-key (kbd "C-<up>") 'org-agenda-previous-item)
+                                              (local-set-key (kbd "C-<down>") 'org-agenda-next-item)
+                                              (local-set-key (kbd "?") 'hydra-org-agenda/body))))
+
+
+
+
+
+
+

6.4.7 org table mode

+
+

+I'm so used to lovely org mode tables, I need them everywhere! +

+
+
(require 'org-table)
+
+
+ + + +

+convert CSV region to table +

+
+
(defun tablify (regex)
+  "Convert a whitespace separated column list into
+an org mode table and enable orgtbl-mode. You can
+specify another regex for cell splitting."
+  (interactive "MConvert [region] to table with regex ([\t\s]+): ")
+  (let ((spc "[\t\s]+"))
+    (when (string= regex "")
+      (setq regex spc))
+    (delete-trailing-whitespace)
+    (if (org-region-active-p)
+        (org-table-convert-region (region-beginning) (region-end) regex)
+      (org-table-convert-region (point-min) (point-max) regex))
+    (when (not (eq major-mode 'org-mode))
+      (orgtbl-mode))))
+
+
+ +

+table sorting shortcuts +

+
+
(defun sort-table-numeric ()
+  "sort org table numerically by current column"
+  (interactive)
+  (org-table-sort-lines nil ?n))
+
+(defun sort-table-numeric-desc ()
+  "reverse sort org table numerically by current column"
+  (interactive)
+  (org-table-sort-lines nil ?N))
+
+(defun sort-table-alphanumeric ()
+  "sort org table charwise by current column"
+  (interactive)
+  (org-table-sort-lines nil ?a))
+
+(defun sort-table-alphanumeric-desc ()
+  "reverse sort org table charwise by current column"
+  (interactive)
+  (org-table-sort-lines nil ?A))
+
+(defun sort-table-time ()
+  "sort org table by times by current column"
+  (interactive)
+  (org-table-sort-lines nil ?t))
+
+(defun sort-table-time-desc ()
+  "reverse sort org table by times by current column"
+  (interactive)
+  (org-table-sort-lines nil ?T))
+
+
+ +

+via jcs/irreal.org +however, I renamed the actual sort wrappers to match my +naming scheme +

+
+
(defun jcs-ip-lessp (ip1 ip2 &optional op)
+  "Compare two IP addresses.
+Unless the optional argument OP is provided, this function will return T
+if IP1 is less than IP2 or NIL otherwise. The optional argument OP is
+intended to be #'> to support reverse sorting."
+  (setq cmp (or op #'<))
+  (cl-labels ((compare (l1 l2)
+                       (if (or (null l1) (null l2))
+                           nil
+                         (let ((n1 (string-to-number (car l1)))
+                               (n2 (string-to-number (car l2))))
+                           (cond
+                            ((funcall cmp n1 n2) t)
+                            ((= n1 n2) (compare (cdr l1) (cdr l2)))
+                            (t nil))))))
+    (compare (split-string ip1 "\\.") (split-string ip2 "\\."))))
+
+(defun sort-table-ip ()
+  (interactive)
+  (org-table-sort-lines nil ?f #'org-sort-remove-invisible #'jcs-ip-lessp))
+
+(defun sort-table-ip-desc ()
+  (interactive)
+  (org-table-sort-lines nil ?F #'org-sort-remove-invisible
+                        (lambda (ip1 ip2) (jcs-ip-lessp ip1 ip2 #'>))))
+
+
+ + +

+easy access for the shortcuts +

+
+
(defalias 'stn       'sort-table-numeric)
+(defalias 'stnd      'sort-table-numeric-desc)
+(defalias 'sta       'sort-table-alphanumeric)
+(defalias 'stad      'sort-table-alphanumeric-desc)
+(defalias 'stt       'sort-table-time)
+(defalias 'sttd      'sort-table-time-desc)
+(defalias 'sti       'sort-table-ip)
+(defalias 'stid      'sort-table-ip-desc)
+
+
+ +

+generic table exporter +

+
+
(defun tvd-export-org-table (fmt)
+  "export an org table using format FMT"
+  (interactive)
+  (let ((efile "/tmp/org-table-export.tmp")
+        (ebuf (format "*table-%s*" fmt)))
+    (when (file-exists-p efile)
+      (delete-file efile))
+    (org-table-export efile (format "orgtbl-to-%s" fmt))
+    (other-window 1)
+    (if (not (eq (get-buffer ebuf) nil))
+        (kill-buffer (get-buffer ebuf)))
+    (set-buffer (get-buffer-create ebuf))
+    (insert-file-contents efile)
+    (switch-to-buffer ebuf)
+    (delete-file efile)))
+
+
+ +

+FIXME: once there's an org solution to this, remove this code +format specific exporters +

+
+
(defun tvd-org-quote-csv-field (s)
+  "Quote every field."
+  (if (string-match "." s)
+      (concat "=\"" (mapconcat 'identity
+                               (split-string s "\"") "\"\"") "\"")
+    s))
+
+(defun table-to-excel ()
+  "export current org table to CSV format suitable for MS Excel."
+  (interactive)
+  ;; quote everything, map temporarily 'org-quote-csv-field
+  ;; to my version
+  (cl-letf (((symbol-function 'org-quote-csv-field)
+             #'tvd-org-quote-csv-field))
+           (tvd-export-org-table "csv")))
+
+(defun table-to-csv ()
+  "export current org table to CSV format"
+  (interactive)
+  (tvd-export-org-table "csv"))
+
+(defun table-to-latex ()
+  "export current org table to LaTeX format"
+  (interactive)
+  (tvd-export-org-table "latex"))
+
+(defun table-to-html ()
+  "export current org table to HTML format"
+  (interactive)
+  (tvd-export-org-table "html"))
+
+(defun table-to-csv-tab ()
+  "export current org table to CSV format, separated by <tab>"
+  (interactive)
+  (tvd-export-org-table "tsv"))
+
+(defun table-to-aligned ()
+  "export current org table to space-aligned columns format"
+  (interactive)
+  (tvd-export-org-table "csv")
+  (with-current-buffer "*table-csv*"
+    (align-regexp (point-min) (point-max) "\\(\\s-*\\)," 1 1 t)
+    (while (re-search-forward " ," nil t)
+      (replace-match "    "))))
+
+
+ +

+exporter shortcuts +

+
+
(defalias 'ttc      'table-to-csv)
+(defalias 'tte      'table-to-excel)
+(defalias 'ttl      'table-to-latex)
+(defalias 'tth      'table-to-html)
+(defalias 'ttt      'table-to-csv-tab)
+(defalias 'tta      'table-to-aligned)
+
+
+ +

+In org mode I sometimes want to copy the content of a table cell +

+
+
(defun tvd-beginning-of-cell (&optional arg)
+  "move (point) to the beginning of a org mode table cell"
+  (interactive)
+  (if  (re-search-backward "|" (line-beginning-position) 3 1)
+      (forward-char)))
+
+(defun tvd-end-of-cell (&optional arg)
+  "move (point) to the end of a org mode table cell"
+  (interactive)
+  (if  (re-search-forward "|" (line-end-position) 3 1)
+      (backward-char)))
+
+(defun tvd-copy-org-table-cell(&optional arg)
+  "Copy an org mode table cell to the kill ring using MCYT"
+  (interactive "P")
+  (mcyt--blink-and-copy-thing 'tvd-beginning-of-cell 'tvd-end-of-cell arg))
+
+(defun tvd-del-org-table-cell (&optional arg)
+  "Delete a cell"
+  (interactive "P")
+  (let
+      ((beg (progn (tvd-beginning-of-cell) (point)))
+       (end (progn (tvd-end-of-cell) (point))))
+    (delete-region beg end)
+    (org-table-align)))
+
+(defun tvd-del-org-table-row ()
+  "Delete a table row's contents"
+  (interactive)
+  (org-beginning-of-line 1)
+  (kill-line)
+  (org-table-insert-row nil))
+
+(defun tvd-del-org-table-col ()
+  "Delete a table column's contents, keep heading as is"
+  (interactive)
+  (let ((head (org-table-get 1 nil)))
+    (org-table-delete-column)
+    (re-search-forward "|")
+    (org-table-insert-column)
+    (tvd-org-table-goto-col-beginning)
+    (insert head)
+    (org-table-align))
+  )
+
+
+ +

+Sometimes I need to copy whole columns too: +via stackoverflow +

+ +
+
(defun tvd-org-table-goto-col-beginning ()
+  "Go to beginning of current column and return `point'."
+  (interactive)
+  (assert (org-table-p) "Not in org-table.")
+  (org-table-align)
+  (let ((col (org-table-current-column)))
+    (goto-char (org-table-begin))
+    (org-table-goto-column col))
+  (point))
+
+(defun tvd-org-table-col-beginning ()
+  "Return beginning position of current column."
+  (save-excursion
+    (tvd-org-table-goto-col-beginning)))
+
+(defun tvd-org-table-goto-col-end ()
+  "Goto end of current column and return `point'."
+  (interactive)
+  (assert (org-table-p) "Not in org-table.")
+  (org-table-align)
+  (let ((col (org-table-current-column)))
+    (goto-char (1- (org-table-end)))
+    (org-table-goto-column col)
+    (skip-chars-forward "^|"))
+  (point))
+
+(defun tvd-org-table-col-end ()
+  "Return end position of current column."
+  (save-excursion
+    (tvd-org-table-goto-col-end)))
+
+(defun tvd-org-table-select-col ()
+  "Select current column."
+  (interactive)
+  (set-mark (tvd-org-table-col-beginning))
+  (tvd-org-table-goto-col-end)
+  (rectangle-mark-mode))
+
+(defun tvd-copy-org-table-col ()
+  "Copy current column."
+  (interactive)
+  (tvd-org-table-select-col)
+  (sit-for 0.2 t)
+  (copy-region-as-kill nil nil t)
+  (with-temp-buffer
+    (yank)
+    (delete-trailing-whitespace)
+    (delete-whitespace-rectangle (point-min) (point-max))
+    (font-lock-unfontify-buffer)
+    (copy-region-as-kill (point-min) (point-max))))
+
+(defun tvd-copy-org-table-row ()
+  "Copy current row, space aligned"
+  (interactive)
+  (mcyt-copy-line)
+  (with-temp-buffer
+    (yank)
+    (goto-char (point-min))
+    (let ((spc ""))
+      (while (re-search-forward "|[ ]*" nil t)
+        (replace-match spc)
+        (setq spc " ")))
+    (delete-trailing-whitespace)
+    (copy-region-as-kill (point-min) (point-max))))
+
+
+ +

+Move single cells using C-M-up C-M-down C-M-left C-M-right +via Kauffmann +

+
+
(defun org-table-swap-cells (i1 j1 i2 j2)
+  "Swap two cells"
+  (let ((c1 (org-table-get i1 j1))
+        (c2 (org-table-get i2 j2)))
+    (org-table-put i1 j1 c2)
+    (org-table-put i2 j2 c1)
+    (org-table-align)))
+
+(defun org-table-move-single-cell (direction)
+  "Move the current cell in a cardinal direction according to the
+  parameter symbol: 'up 'down 'left 'right. Swaps contents of
+  adjacent cell with current one."
+  (unless (org-at-table-p)
+    (error "No table at point"))
+  (let ((di 0) (dj 0))
+    (cond ((equal direction 'up) (setq di -1))
+          ((equal direction 'down) (setq di +1))
+          ((equal direction 'left) (setq dj -1))
+          ((equal direction 'right) (setq dj +1))
+          (t (error "Not a valid direction, must be up down left right")))
+    (let* ((i1 (org-table-current-line))
+           (j1 (org-table-current-column))
+           (i2 (+ i1 di))
+           (j2 (+ j1 dj)))
+      (org-table-swap-cells i1 j1 i2 j2)
+      (org-table-goto-line i2)
+      (org-table-goto-column j2))))
+
+(defun org-table-move-single-cell-up ()
+  "Move a single cell up in a table; swap with anything in target cell"
+  (interactive)
+  (org-table-move-single-cell 'up))
+
+(defun org-table-move-single-cell-down ()
+  "Move a single cell down in a table; swap with anything in target cell"
+  (interactive)
+  (org-table-move-single-cell 'down))
+
+(defun org-table-move-single-cell-left ()
+  "Move a single cell left in a table; swap with anything in target cell"
+  (interactive)
+  (org-table-move-single-cell 'left))
+
+(defun org-table-move-single-cell-right ()
+  "Move a single cell right in a table; swap with anything in target cell"
+  (interactive)
+  (org-table-move-single-cell 'right))
+
+
+ +

+actual org table config +

+
+
(with-eval-after-load "org"
+  (add-hook 'org-mode-hook
+            (lambda ()
+              (local-set-key (kbd "C-c t l") 'tvd-copy-org-table-col)
+              (local-set-key (kbd "C-c t r") 'tvd-copy-org-table-row)
+              (local-set-key (kbd "C-c t c") 'tvd-copy-org-table-cell)
+              (local-set-key (kbd "C-M-<left>")  'org-table-move-single-cell-left)
+              (local-set-key (kbd "C-M-<right>") 'org-table-move-single-cell-right)
+              (local-set-key (kbd "C-M-<up>")    'org-table-move-single-cell-up)
+              (local-set-key (kbd "C-M-<down>")  'org-table-move-single-cell-down))))
+
+
+ +

+eval-after-load 'orgtbl doesn't work +

+
+
(add-hook 'orgtbl-mode-hook '(lambda ()
+                               (define-key orgtbl-mode-map (kbd "C-c t l") 'tvd-copy-org-table-col)
+                               (define-key orgtbl-mode-map (kbd "C-c t r") 'tvd-copy-org-table-row)
+                               (define-key orgtbl-mode-map (kbd "C-c t c") 'tvd-copy-org-table-cell)))
+
+
+ +

+integers, reals, positives, set via custom +

+
+
(setq org-table-number-regexp "^[-+]?\\([0-9]*\\.[0-9]+\\|[0-9]+\\.?[0-9]*\\)$")
+
+
+ +

+table hydras, maybe better than aliases?! +

+
+
(defhydra hydra-org-tables (:color blue)
+  "
+^Sort by^             ^Transform to^      ^Copy/Del what^                ^Modify^                 ^Outside Org^
+^^^^^^^^-----------------------------------------------------------------------------------------------------------------------
+_sa_:  alphanumeric   _tc_: CSV           _cl_: Copy Column (C-c t l)    _ic_: Insert Column      _ot_: Table to Org Mode
+_sA_: -alphanumeric   _te_: Excel         _cr_: Copy Row    (C-c t r)    _ir_: Insert Row         _oe_: Enable Org-Tbl Mode
+_si_:  ip             _tl_: Latex         _cc_: Copy Cell   (C-c t c)    _il_: Insert Line        _oc_: Turn region to columns
+_sI_: -ip             _th_: HTML          _dd_: Delete Cell              _tr_: Transpose Table
+_sn_:  numeric        _tt_: Tab           _dc_: Delete Column            _mr_: Move Cell right
+_sN_: -numeric        _ta_: Aligned       _dr_: Delete Row               _ml_: Move Cell left
+_st_:  time           ^^                  _kr_: Kill Row                 _mu_: Move Cell up
+_sT_: -time           ^^                  _kc_: Kill Column              _md_: Move Cell down     _q_: Cancel
+
+
+^^^^^^^^-----------------------------------------------------------------------------------------------------------------------
+Reach this hydra with <C-x t>
+^^^^^^^^-----------------------------------------------------------------------------------------------------------------------
+
+
+"
+  ("mr" org-table-move-single-cell-right)
+  ("ml" org-table-move-single-cell-left)
+  ("mu" org-table-move-single-cell-up)
+  ("md" org-table-move-single-cell-down)
+  ("sa" sort-table-alphanumeric  nil)
+  ("sA" sort-table-alphanumeric-desc nil)
+  ("si" sort-table-ip nil)
+  ("sI" sort-table-ip-desc  nil)
+  ("sn" sort-table-numeric  nil)
+  ("sN" sort-table-numeric-desc  nil)
+  ("st" sort-table-time  nil)
+  ("sT" sort-table-time-desc  nil)
+
+  ("tc" table-to-csv nil)
+  ("te" table-to-excel    nil)
+  ("tl" table-to-latex    nil)
+  ("th" table-to-html     nil)
+  ("tt" table-to-csv-tab  nil)
+  ("ta" table-to-aligned  nil)
+
+  ("cl" tvd-copy-org-table-col nil)
+  ("cr" tvd-copy-org-table-row nil)
+  ("cc" tvd-copy-org-table-cell nil)
+  ("dd" org-table-blank-field nil)
+  ("dr" tvd-del-org-table-row nil)
+  ("dc" tvd-del-org-table-col nil)
+  ("kc" org-table-delete-column nil)
+  ("kr" org-table-kill-row nil)
+
+  ("ic" org-table-insert-column nil)
+  ("ir" org-table-insert-row nil)
+  ("il" org-table-hline-and-move nil)
+  ("tr" org-table-transpose-table-at-point nil)
+
+  ("ot" tablify  nil)
+  ("oe" orgtbl-mode nil)
+  ("oc" align-repeat nil)
+
+  ("q" nil nil :color red))
+
+
+ +

+allow me to insert org tables everywhere on request +

+
+
(defalias 'table     'hydra-org-tables/body)
+(global-set-key (kbd "C-x t") 'hydra-org-tables/body)
+
+
+
+
+ +
+

6.4.8 org mode slideshows

+
+

+Making presentations within emacs with org mode is cool as well. +

+ +
+
(require 'org-present)
+(require 'darkroom) ;; hides distractions
+
+
+ +

+showtime helpers +

+
+
(defun slide-return-to-present ()
+  "wherever we are, go back to slideshow"
+  (interactive)
+  (switch-to-buffer-other-window "*slide*")
+  (delete-other-windows))
+
+(defun slide-split-to-past ()
+  "split slide show and show previous buffer next to it"
+  (interactive)
+  (split-window-horizontally)
+  (other-window 1)
+  (if (get-buffer "*eshell*")
+      ;; if there's no eshell running, start it, otherwise switch to it
+      (switch-to-buffer "*eshell*")
+    (eshell)))
+
+
+ +

+org present config +

+
+
(eval-after-load "org-present"
+  '(progn
+     (add-hook 'org-present-mode-hook
+               (lambda ()
+                 (org-present-big)
+                 (org-display-inline-images)
+                 (org-present-hide-cursor)
+                 (org-present-read-only)
+
+                 ;; some opticals
+                 (setq org-hide-emphasis-markers t)
+                 (font-lock-add-keywords 'org-mode
+                                         '(("^ +\\([-*]\\) "
+                                            (0 (prog1 () (compose-region (match-beginning 1) (match-end 1) "•"))))))
+                 ;; keys
+                 (define-key org-present-mode-keymap [down]    'org-present-next)
+                 (define-key org-present-mode-keymap [up]      'org-present-prev)
+                 (define-key org-present-mode-keymap (kbd "q") 'org-present-quit)
+                 (global-set-key (kbd "C-c p") 'slide-return-to-present) ; used inside eshell to return to slide
+                 (define-key org-present-mode-keymap (kbd "s") 'slide-split-to-past)
+                 (setq current-buffer (buffer-name)) ; remember slide buffer name
+                 (rename-buffer "*slide*")
+                 ;;(darkroom-tentative-mode)
+                 ))
+
+     (add-hook 'org-present-mode-quit-hook
+               (lambda ()
+                 (org-present-small)
+                 (org-remove-inline-images)
+                 (org-present-show-cursor)
+                 (org-present-read-write)
+                 (setq org-hide-emphasis-markers nil)
+                 (rename-buffer current-buffer)
+                 (global-unset-key (kbd "C-c p"))
+                 ;;(darkroom-tentative-mode)
+                 ))))
+
+
+ +

+Will be inserted as first help slide in a slide show +(edit table in org-mode!) +

+
+
(defun slide-header (prefix)
+  (interactive "P")
+  (save-excursion
+    (if (eq prefix nil)
+        ()
+      (goto-char (point-min)))
+    (insert "\n* ORG-MODE slide show commands
+
+  | Key   | Command                                                    |
+  +-------+------------------------------------------------------------+
+  | C-p   | start slide show                                           |
+  | q     | stop slide show                                            |
+  | s     | slit window and switchto or start eshell                   |
+  | C-c p | while in split mode, return to full screen slide show      |
+  | C-c r | enter window resize mode, use cursor keys, <ret> to finish |
+  | C--   | (CTRL and minus) shrink font size                          |
+  | C-+   | (CTRL and plus) increase font size                         |
+
+")))
+
+
+ + +
+
+
+
+

6.4.9 outshine mode

+
+

+I maintain my emacs config with outshine mode. It works a lot like +org mode, but I still have a normal emacs lisp buffer, which I can +use directly without any conversion beforehand and which works if +outshine is not installed. Also I thing "literal programming" is +bullshit. +

+ +
+
(require 'outshine)
+
+
+ +

+Generate an alist of all headings with each position in buffer and +use this later to jump to those positions with IDO. +

+
+
(make-variable-buffer-local 'tvd-headings)
+
+(defun tvd-outshine-get-level (heading)
+  "Return level of HEADING as number, or nil"
+  (if (string-match " \\(*+\\) " heading) ; normal outline heading
+      (length (match-string 1 heading))
+    (when (string-match "^;;\\(;+\\) " heading) ; else look for elisp heading
+      (length (match-string 1 heading)))))
+
+(defun tvd-outshine-cl-heading (heading)
+  (let ((regex (cadar outshine-imenu-preliminary-generic-expression)))
+    (when (string-match regex heading)
+      (match-string-no-properties 1 heading))))
+
+(defun tvd-outshine-parse-headings ()
+  "extract outshine headings of current buffer"
+  (interactive)
+  (let ((line nil))
+    (save-excursion
+      (setq tvd-headings ())
+      (beginning-of-buffer)
+      (while (not (eobp))
+        (setq line (tvd-get-line))
+        (when (outline-on-heading-p t)
+          (add-to-list 'tvd-headings (cons (tvd-outshine-cl-heading line) (point))))
+        (forward-line)))))
+
+(defun tvd-outshine-sparse-tree ()
+  "expand outline tree from current position as sparse tree"
+  (interactive)
+  (let ((done nil)
+        (pos (point))
+        (tree (list (list (point) 5)))
+        (l 0))
+    (while (not done)
+      (outline-up-heading 1)
+      (setq l (tvd-outshine-get-level (tvd-get-line)))
+      (add-to-list 'tree (list (point) l))
+      (when (eq l 1)
+        (setq done t)))
+    (outline-hide-other)
+    (dolist (pos tree)
+      (goto-char (car pos))
+      (outline-cycle))))
+
+(defun tvd-outshine-jump ()
+  "jump to an outshine heading with IDO prompt,
+update heading list if neccessary."
+  (interactive)
+  (let ((heading nil))
+    (if (string= "" outshine-normalized-outline-regexp-base)
+        (call-interactively 'imenu) ;; use imenu outside outshine
+      (when (or (not tvd-headings)
+                (buffer-modified-p))
+        (tvd-outshine-parse-headings))
+      (if (not tvd-headings)
+          (message "Could not parse headings")
+        (setq heading (ido-completing-read
+                       "Jump to heading: "
+                       (tvd-alist-keys tvd-headings)))
+        (when heading
+          (show-all)
+          (goto-char (cdr (assoc heading tvd-headings)))
+          (tvd-outshine-sparse-tree))))))
+
+
+(defun tvd-outshine-end-of-section ()
+  "Jump to the end of an outshine section."
+  (interactive)
+  (let ((end))
+    (outline-show-subtree)
+    (save-excursion
+      (outline-next-heading)
+      (when (outline-on-heading-p)
+        (backward-paragraph))
+      (setq end (point)))
+    (goto-char end)))
+
+
+ +

+outshine mode config (inside outline mode) +

+
+
(eval-after-load "outline"
+  '(progn
+     (add-hook 'outline-minor-mode-hook
+               (lambda ()
+                 (defalias 'j    'tvd-outshine-jump)
+                 (defalias 'jump 'tvd-outshine-jump)
+                 (define-key outline-minor-mode-map (kbd "C-c C-j")  'tvd-outshine-jump)
+                 (setq outshine-org-style-global-cycling-at-bob-p t
+                       outshine-use-speed-commands t
+                       outshine-speed-commands-user
+                       (quote (
+                               ("v" . outshine-narrow-to-subtree)
+                               ("q" . widen)
+                               ("e" . tvd-outshine-end-of-section))))))))
+
+
+ +

+Narrowing now works within the headline rather than requiring to be on it +

+
+
(advice-add 'outshine-narrow-to-subtree :before
+            (lambda (&rest args) (unless (outline-on-heading-p t)
+                                   (outline-previous-visible-heading 1))))
+
+
+ +

+convert outshine buffer to org buffer using outorg, which is part +of outshine. +

+
+
(defun outshine-to-org ()
+  (interactive)
+  (outorg-convert-to-org)
+  (org-mode))
+
+
+ +

+I use this to generate a HTML version of my emacs config for +posting online, which makes it way easier to read. +

+
+
(defun outshine-to-html (file)
+  (interactive
+   (list
+    (read-file-name "HTML output file: "
+                    (expand-file-name "~/D/github/dot-emacs")
+                    "emacs.html")))
+  (let ((B (current-buffer)))
+    (with-temp-buffer
+      (insert-buffer-substring B)
+      ;; remove 'sk spacings for smaller <pre>'s
+      (tvd-replace-all ")\s*;" ") ;")
+      ;; highlight at least a little
+      (tvd-replace-all "/FIXME/" "//FIXME//")
+      (emacs-lisp-mode)
+      (outshine-to-org)
+      (org-export-to-file 'html file))))
+
+(defun export (cmessage)
+  "Export .emacs to git, do not use."
+  ;; /FIXME/: generate version number, add last changelog to git
+  (interactive "sEnter Commit Message: ")
+  (outshine-to-html "~/D/github/dot-emacs/emacs.html")
+  (shell-command "cp ~/.emacs ~/D/github/dot-emacs/")
+  (shell-command (format "cd ~/D/github/dot-emacs && git ci '%s' .emacs emacs.html" cmessage))
+  (shell-command "cd ~/D/github/dot-emacs && git push"))
+
+
+ +
+
+
+ +
+

6.4.10 outline mode

+
+

+I use the very same cycle style as in org mode: when on a heading, +hide it, jump to next heading on the same level and expand that (or +vice versa). however, when NOT on a heading behave as loved: jump +paragraphs. +

+ +

+Note, that this also affects outshine mode, since that inherits +from outline. +

+ +
+
(defun tvd-outline-left-or-level-up()
+  "jump one word to the left if not on a heading,
+otherwise fold current level and jump one level up."
+  (interactive)
+  (if (outline-on-heading-p)
+      (progn
+        (hide-subtree)
+        (outline-up-heading 1))
+    (left-word)))
+
+(defun tvd-outline-heading-up()
+  "fold current heading, jump one level up and unfold it"
+  (interactive)
+  (if (not (outline-on-heading-p))
+      (backward-paragraph)
+    (hide-subtree)
+    (outline-backward-same-level 1)
+    (outline-cycle)))
+
+(defun tvd-outline-heading-down()
+  "fold current heading, jump one level down and unfold it"
+  (interactive)
+  (if (not (outline-on-heading-p))
+      (forward-paragraph)
+    (hide-subtree)
+    (outline-forward-same-level 1)
+    (outline-cycle)))
+
+
+ +

+unused, see tvd-outshine-jump +

+
+
(defun tvd-outline-jump (part)
+  "Jump interactively to next header containing PART using search."
+  (interactive "Mjump to: ")
+  (let ((done nil)
+        (pwd (point)))
+    (beginning-of-buffer)
+    (outline-show-all)
+    (when (re-search-forward (format "^;; \\*+.*%s" part) (point-max) t)
+      (when (outline-on-heading-p)
+        (beginning-of-line)
+        (setq done t)))
+    (when (not done)
+      (message (format "no heading with '%s' found" part))
+      (goto-char pwd))))
+
+
+ +

+outline mode config +

+
+
(eval-after-load "outline"
+  '(progn
+     (add-hook 'outline-minor-mode-hook
+               (lambda ()
+                 ;; narrowing, we use outshine functions, it's loaded anyway
+                 (defalias 'n 'outshine-narrow-to-subtree)
+                 (defalias 'w 'widen)
+                 (define-key outline-minor-mode-map (kbd "<C-up>")   'tvd-outline-heading-up)
+                 (define-key outline-minor-mode-map (kbd "<C-down>") 'tvd-outline-heading-down)
+                 ;;(define-key outline-minor-mode-map (kbd "<C-left>") 'tvd-outline-left-or-level-up)
+                 ))))
+
+
+ +

+orange fringe when narrowed +

+
+
(advice-add 'outshine-narrow-to-subtree :after
+            '(lambda (&rest args)
+               (set-face-attribute 'fringe nil :background tvd-fringe-narrow-bg)))
+
+
+ + +
+
+
+
+

6.4.11 narrowing (no mode but fits here)

+
+

+I use narrowing quite frequently, so here are some enhancements. +

+ +

+easier narrowing with Indirect Buffers +Source: emacswiki +

+
+
(require 'narrow-indirect)
+(defalias 'nf 'ni-narrow-to-defun-indirect-other-window)
+(defalias 'nr 'ni-narrow-to-region-indirect-other-window)
+
+
+ +

+I like to have an orange fringe background when narrowing is +active, since I forget that it is in effect otherwise sometimes. +

+ +

+via stackoverflow +

+
+
(defun tvd-narrowed-fringe-status ()
+  "Make the fringe background reflect the buffer's narrowing status."
+  (set-face-attribute
+   'fringe nil :background (if (buffer-narrowed-p)
+                               tvd-fringe-narrow-bg
+                             nil)))
+
+(add-hook 'post-command-hook 'tvd-narrowed-fringe-status)
+
+
+ +
+
+
+
+

6.4.12 ANSI-TERM (inferior shells/interpreters and REPLs)

+
+

+I use ansi term for inferior shells only. +

+ +

+via echosa +

+ +

+kill buffer when done +

+
+
(defadvice term-sentinel (around tvd-advice-term-sentinel (proc msg))
+  (if (memq (process-status proc) '(signal exit))
+      (let ((buffer (process-buffer proc)))
+        ad-do-it
+        (kill-buffer buffer))
+    ad-do-it))
+(ad-activate 'term-sentinel)
+
+
+ +

+force utf8 +

+
+
(defun tvd-term-use-utf8 ()
+  (set-buffer-process-coding-system 'utf-8-unix 'utf-8-unix))
+(add-hook 'term-exec-hook 'tvd-term-use-utf8)
+
+
+ +

+make C-y work +

+
+
(defun tvd-term-paste (&optional string)
+                      (interactive)
+                      (process-send-string
+                       (get-buffer-process (current-buffer))
+                       (if string string (current-kill 0))))
+
+
+ +

+put all term hooks in here +

+
+
(defun tvd-term-hook ()
+  (goto-address-mode)
+  (define-key term-raw-map (kbd "C-y") 'tvd-term-paste)
+  (define-key term-raw-map (kbd "C-c C-d") 'kill-this-buffer)
+  (define-key term-raw-map (kbd "C-d") 'kill-this-buffer)
+  (define-key term-raw-map (kbd "C-c C-l") 'term-line-mode)
+  (define-key term-raw-map (kbd "C-k")
+    (lambda ()
+      (interactive)
+      (term-send-raw-string "\C-k")
+      (kill-line))))
+(add-hook 'term-mode-hook 'tvd-term-hook)
+
+
+ +

+via emacswiki: +Use to supply commandline arguments to ansi-term +

+
+
(defun term-with-args (new-buffer-name cmd &rest switches)
+  (setq term-ansi-buffer-name (concat "*" new-buffer-name "*"))
+  (setq term-ansi-buffer-name (generate-new-buffer-name term-ansi-buffer-name))
+  (setq term-ansi-buffer-name (apply 'make-term term-ansi-buffer-name cmd nil switches))
+  (set-buffer term-ansi-buffer-name)
+  (term-mode)
+  (term-char-mode)
+  (message "Line mode: C-c C-l, Char mode: C-c C-k, Exit: C-c C-d")
+  (switch-to-buffer term-ansi-buffer-name))
+
+
+ +

+finally the inferior REPLs: +

+
+
(defun iperl ()
+  "interactive perl (via perlbrew if exist or global)"
+  (interactive)
+  (let ((perlbrew (expand-file-name "~/perl5/perlbrew/bin/perlbrew")))
+    (if (file-exists-p perlbrew)
+        (term-with-args "*perlbrew-de0*" perlbrew "exec" "--" "perl" "-de0")
+      (term-with-args "*perl-de0*" "perl" "-de0"))))
+
+(defun iruby ()
+  "interactive ruby"
+  (interactive)
+  (term-with-args "*ruby-irb*" "irb"))
+
+(defun ipython ()
+  "interactive python"
+  (interactive)
+  (setenv "PYTHONSTARTUP" (expand-file-name "~/.pythonrc"))
+  (term-with-args "*python-i*" "python" "-i"))
+
+(defun icalc ()
+  "interactive calc"
+  (interactive)
+  (term-with-args "*calc*" (expand-file-name "~/bin/calc")))
+
+
+ +
+
+
+ +
+

6.4.13 Puppet

+
+

+adds hook for .pp files +

+
+
(require 'puppet-mode)
+
+
+ +
+
+
+ +
+

6.4.14 Novel Mode - Screen Reader

+
+

+my own emacs screen reader, very handy to read docs on the road. +

+ +
+
(require 'novel-mode)
+(global-set-key (kbd "C-c C-n")         'novel-mode)
+
+
+ +
+
+
+ +
+

6.4.15 Macro Math

+
+

+see macro-math +

+ +

+perform elisp evaluation/caluclaton directly in the buffer. +mark something and hit C-x C-0 (which is a reminder to C-x C-= w/o the shift) +

+ +
+
(autoload 'macro-math-eval-and-round-region "macro-math" t nil)
+(autoload 'macro-math-eval-region "macro-math" t nil)
+
+(global-set-key (kbd "C-x C-0")         'macro-math-eval-region)
+
+
+ +
+
+
+ +
+

6.4.16 Common-Lisp (SLIME)

+
+

+I'm learing CL with slime, start with M-x slime. +

+ +

+INSTALL: (see: jonathanfischer.net +

+ +
+
(setq slimehelper (expand-file-name "~/quicklisp/slime-helper.el"))
+
+(if (file-exists-p slimehelper)
+    (progn
+      (load slimehelper)
+
+      ;; Replace "sbcl" with the path to your implementation
+      (setq inferior-lisp-program "sbcl")
+
+      ;; Stop SLIME's REPL from grabbing DEL,
+      ;; which is annoying when backspacing over a '('
+      (defun override-slime-repl-bindings-with-paredit ()
+        (define-key slime-repl-mode-map
+          (read-kbd-macro paredit-backward-delete-key) nil))
+      (add-hook 'slime-repl-mode-hook 'override-slime-repl-bindings-with-paredit)))
+
+
+ +
+
+
+ +
+

6.4.17 INFO Mode

+
+
+
(require 'info)
+
+
+ +

+open an info file somewhere outside %infodir% with info-mode +

+
+
(defun info-find-file (file)
+  (interactive "f")
+  (info-setup file
+              (pop-to-buffer-same-window
+               (format "*info*<%s>"
+                       (file-name-sans-extension
+                        (file-name-nondirectory file))))))
+
+
+ +

+easier navigation in Info mode, intuitive history back and forth. +

+
+
(eval-after-load "Info"
+  '(progn
+     (define-key Info-mode-map (kbd "<C-left>")  'Info-history-back)
+     (define-key Info-mode-map (kbd "<C-right>") 'Info-history-forward)
+     (require 'info+)))
+
+
+ +

+make Info great again! +based on Marcins info dispatch, +contains (interactive) code from 'info-display-manual for manual selection. +

+
+
(defun i (manual)
+    "Read documentation for MANUAL in the info system.  Name the
+buffer '*Info MANUAL*'.  If that buffer is already present, just
+switch to it.
+
+If MANUAL not given as argument, ask interactively with completion
+to select from a list of installed manuals."
+  (interactive
+   (list
+    (progn
+      (info-initialize)
+      (ido-completing-read "Manual name: "
+                       (info--manual-names current-prefix-arg)
+                       nil t))))
+  (let ((buffer (format "*Info %s*" manual)))
+    (if (get-buffer buffer)
+      (switch-to-buffer bufer)
+      (info manual buffer))))
+
+
+ +

+from examples, I love this one!, replaces the ? buffer +

+
+
(define-key Info-mode-map (kbd "?") #'hydra-info/body)
+(defhydra hydra-info (:color blue
+                      :hint nil)
+      "
+Info-mode:
+  ^^_]_ forward  (next logical node)       ^^_l_ast (←)        _u_p (↑)                             _f_ollow reference       _T_OC
+  ^^_[_ backward (prev logical node)       ^^_r_eturn (→)      _m_enu (↓) (C-u for new window)      _i_ndex                  _d_irectory
+  ^^_n_ext (same level only)               ^^_H_istory         _g_oto (C-u for new window)          _,_ next index item      _c_opy node name
+  ^^_p_rev (same level only)               _<_/_t_op           _b_eginning of buffer                virtual _I_ndex          _C_lone buffer
+  regex _s_earch (_S_ case sensitive)      ^^_>_ final         _e_nd of buffer                      ^^                       _a_propos
+
+  _1_ .. _9_ Pick first .. ninth item in the node's menu.
+
+"
+      ("]"   Info-forward-node nil)
+      ("["   Info-backward-node nil)
+      ("n"   Info-next nil)
+      ("p"   Info-prev nil)
+      ("s"   Info-search nil)
+      ("S"   Info-search-case-sensitively nil)
+
+      ("l"   Info-history-back nil)
+      ("r"   Info-history-forward nil)
+      ("H"   Info-history nil)
+      ("t"   Info-top-node nil)
+      ("<"   Info-top-node nil)
+      (">"   Info-final-node nil)
+
+      ("u"   Info-up nil)
+      ("^"   Info-up nil)
+      ("m"   Info-menu nil)
+      ("g"   Info-goto-node nil)
+      ("b"   beginning-of-buffer nil)
+      ("e"   end-of-buffer nil)
+
+      ("f"   Info-follow-reference nil)
+      ("i"   Info-index nil)
+      (","   Info-index-next nil)
+      ("I"   Info-virtual-index nil)
+
+      ("T"   Info-toc nil)
+      ("d"   Info-directory nil)
+      ("c"   Info-copy-current-node-name nil)
+      ("C"   clone-buffer nil)
+      ("a"   info-apropos nil)
+
+      ("1"   Info-nth-menu-item nil)
+      ("2"   Info-nth-menu-item nil)
+      ("3"   Info-nth-menu-item nil)
+      ("4"   Info-nth-menu-item nil)
+      ("5"   Info-nth-menu-item nil)
+      ("6"   Info-nth-menu-item nil)
+      ("7"   Info-nth-menu-item nil)
+      ("8"   Info-nth-menu-item nil)
+      ("9"   Info-nth-menu-item nil)
+
+      ("?"   Info-summary "Info summary")
+      ("h"   Info-help "Info help")
+      ("q"   Info-exit "Info exit")
+      ("C-g" nil "cancel" :color blue))
+
+
+ +
+
+
+ +
+

6.4.18 calc et al.

+
+

+emacs provides 4 ways to calculate: +

+ +

+M-x calc: +RPN calc with stack. Enter numbers, when done, operator, enter, etc +heavy duty. +

+ +

+provided by calc: +

+ +
+(defun c (expr)
+  (interactive "Mcalc:")
+  (message (format "result: %s" (calc-eval expr))))
+
+ +

+by calc as well, but with algebraic input, access last result with $ +algebraic == 1 +1 / 3. result will stored in kill-ring, use C-y to paste +

+
+
(defalias 'c         'quick-calc)
+
+
+ +

+M-x calculator +interactive, simpler than calc, but comprehensive nevertheless, input +is algebraic as well, but last result can be used just as ~/bin/calc +

+ +

+lisp can be used to calc as well: +M-x evaluate-expression <ret> (+ 1 2) <ret> +

+ +

+or, inferior perl calc: M-x icalc, see above +

+ +
+
+
+ +
+

6.4.19 MACROs

+
+

+help: emacswiki macro tricks. +

+ +

+Default keybindings: +start-kbd-macro default binding: ‘C-x (’ — Starts recording a keyboard macro. +end-kbd-macro default binding: ‘C-x )’ — Ends recording of a keyboard macro. +call-last-kbd-macro default binding: ‘C-x e’ — Executes the last keyboard macro defined. +

+ +

+however, I use elmacro. +

+ +
+
(require 'elmacro)
+(elmacro-mode)
+
+(setq tvd-macro-name "last-macro")
+
+
+ +

+ignore stuff +

+
+
(add-to-list 'elmacro-unwanted-commands-regexps "^(mouse.*)$")
+(add-to-list 'elmacro-unwanted-commands-regexps "^(tvd-start-or-stop-macro)$")
+
+(defun tvd-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))
+
+(defun tvd-get-exec-macro-name()
+  "Ask for a macro name to be executed"
+  (interactive)
+  (let ((macros ())
+        (N 1)
+        (S nil)
+        (T ""))
+    (dolist (entry (cdr (assoc tvd-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 +

+
+
(defun tvd-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 tvd-macro-name (tvd-get-macro-name))
+      (elmacro-show-last-macro tvd-macro-name)
+      (message "Recording done. Execute with <C-F6>, save or <C-x C-e> buffer..."))))
+
+
+ +

+better than the default function +

+
+
(defun tvd-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 tvd-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 tvd-macro-name (tvd-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)))))
+
+
+ +

+My macro recording workflow: +

+
    +
  • shift-F6
  • +
  • … do things …
  • +
  • shift-F6 again
  • +
  • enter a name
  • +
  • a new buffer with macro defun appears
  • +
  • C-x C-e evals it
  • +
  • C-F6 (repeatedly) executes it.
  • +
+
+
(global-set-key (kbd "<f6>")            'tvd-start-or-stop-macro)
+(global-set-key (kbd "<C-f6>")          'tvd-exec-last-macro)
+
+
+ +

+I use my own macro file +

+
+
(setq tvd-macro-file (concat tvd-lisp-dir "/macros.el"))
+
+
+ +

+but only load if in use +

+
+
(if (file-exists-p tvd-macro-file)
+    (load-file tvd-macro-file))
+
+(defun tvd-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 tvd-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))
+
+(defalias 'ms        'tvd-macro-store)
+
+(defun tvd-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" tvd-macro-name))
+  (insert "  (interactive)\n")
+  (insert (format "  (tvd-exec-last-macro \"%s\"))\n" tvd-macro-name))
+  (newline)
+  (eval-buffer)
+  (tvd-macro-store))
+
+(advice-add 'elmacro-show-defun :after '(lambda (&rest args)
+                                          (tvd-macro-gen-repeater-and-save)))
+
+
+ +
+
+
+
+

6.4.20 EWW browser stuff

+
+

+Emacs has a builtin browser, which is not too bad. +

+ +
+
(require 'eww)
+
+
+ +

+see also: shr-render-[buffer|region] ! +

+
+
(defun eww-render-current-buffer ()
+  "Render HTML in the current buffer with EWW"
+  (interactive)
+  (beginning-of-buffer)
+  (eww-display-html 'utf8 (buffer-name)))
+
+(defalias 'render-html 'eww-render-current-buffer)
+
+
+ +

+eww config +

+
+
(add-hook 'eww-mode-hook #'toggle-word-wrap)
+(add-hook 'eww-mode-hook #'visual-line-mode)
+
+
+ +

+custom short commands, see ? for the defaults +

+
+
(define-key eww-mode-map "o" 'eww) ; aka other page
+(define-key eww-mode-map "f" 'eww-browse-with-external-browser) ; aka firefox
+(define-key eww-mode-map "j" 'next-line)
+(define-key eww-mode-map "r" 'eww-reload)
+(define-key eww-mode-map "s" 'shr-save-contents)
+(define-key eww-mode-map "v" 'eww-view-source)
+(define-key eww-mode-map "b" 'eww-add-bookmark)
+(define-key eww-mode-map "p" 'eww-back-url)
+(define-key eww-mode-map "n" 'eww-forward-url)
+
+
+ +

+link short commands +

+
+
(define-key eww-link-keymap "c" 'shr-copy-url)
+(define-key eww-link-keymap "s" 'shr-save-contents)
+
+
+ +

+FIXME: latest GIT version of eww contains 'eww-readable, which +hides menus and distractions! Update emacs. +

+ + +
+
+
+
+

6.4.21 Firestarter

+
+

+experimental: do things on save buffer etc. +Source: firestarter +

+
+
+ +
+

6.4.22 Tabulated List Mode

+
+

+built-in, used by many interactive major modes +

+ +

++tablist, which provides many cool features +github source +important commands: +

+
    +
  • < shrink column
  • +
  • > enlarge column
  • +
  • s sort column
  • +
  • / prefix for filter commands +/ e edit filter, e.g. do not list auto-complete sub-packages in melpa: +/ a ! Package =~ ac- <ret>
  • +
+
+
(require 'tablist)
+
+
+ +

+we need to kill tablist's binding in order to have ours run (see below) +

+
+
(define-key tablist-minor-mode-map (kbd "q") nil)
+(define-key tablist-minor-mode-map (kbd "q") 'tvd-close-window)
+
+(defun tvd-close-window ()
+  (interactive)
+  (kill-this-buffer)
+  (delete-window))
+
+(eval-after-load "tabulated-list"
+  '(progn
+     (add-hook 'tabulated-list-mode-hook
+               (lambda ()
+                 (tablist-minor-mode)
+                 (local-set-key (kbd "Q") 'delete-other-windows)
+                 (hl-line-mode)))))
+
+
+
+
+ +
+

6.4.23 Help Mode

+
+

+I even customize help windows! … at least a little :) +

+ +
+
(defun tvd-close-help ()
+  (interactive)
+  (kill-this-buffer)
+  (winner-undo))
+
+(eval-after-load "Help"
+  '(progn
+     (add-hook 'help-mode-hook
+               (lambda ()
+                 ; doesn' work the way I like
+                 ;(local-set-key (kbd "q") 'tvd-close-help)
+                 (local-set-key (kbd "q") 'quit-window)
+                 (local-set-key (kbd "p") 'help-go-back)
+                 (local-set-key (kbd "b") 'help-go-back)
+                 (local-set-key (kbd "n") 'help-go-forward)
+                 (local-set-key (kbd "f") 'help-go-forward)
+                 (setq help-window-select t)
+                 ))))
+
+
+
+
+ +
+

6.4.24 Suggest Mode

+
+

+suggest mode is a great +elisp development tool. Execute `M-x suggest' and try it. +

+ +
+
(require 'suggest) ;; depends on dash, s, f, loop
+
+
+ +

+I use my own clearing function, since suggest doesn't provide this +

+
+
(defun tvd-suggest-reload ()
+  "Clear suggest buffer and re-paint it."
+  (interactive)
+  (let ((inhibit-read-only t))
+    (erase-buffer)
+    (suggest--insert-heading suggest--inputs-heading)
+    (insert "\n\n\n")
+    (suggest--insert-heading suggest--outputs-heading)
+    (insert "\n\n\n")
+    (suggest--insert-heading suggest--results-heading)
+    (insert "\n")
+    (suggest--nth-heading 1)
+    (forward-line 1)))
+
+(defun tvd-suggest-jump ()
+  "Jump between input and output suggest buffer."
+  (interactive)
+  (forward-line -1)
+  (if (eq (line-number-at-pos) 1)
+      (suggest--nth-heading 2)
+    (suggest--nth-heading 1))
+  (forward-line 1))
+
+(eval-after-load "suggest"
+  '(progn
+     (add-hook 'suggest-mode-hook
+               (lambda ()
+                 (local-set-key (kbd "C-l") 'tvd-suggest-reload)
+                 (local-set-key (kbd "<tab>") 'tvd-suggest-jump)))))
+
+
+
+
+ +
+

6.4.25 Followcursor Mode

+
+

+source on github +

+ +

+From time to time I need to refactor configs and the like based on +lists. For example in the left window I have a list of bgp peers +and in the right window a config file for all peers which I have to +modify based on current settings. With followcursor-mode I can put +point on an ip address and the line in the config containing this +ip address will be highlighted. If I move on to the next address +the next line on the right will be highlighted. +

+ +

+The mode is a work-in-progress… +

+ +
+
(require 'followcursor-mode)
+
+
+
+
+ + + +
+

6.4.26 Magit

+
+

+Not much to say about Magit +

+
+
(unless tvd-win-home
+  (setq tvd-magit-revision "20170725.1153")
+  (add-to-list 'load-path (concat tvd-lisp-dir (concat "/magit-" tvd-magit-revision)))
+
+  (require 'magit)
+
+  (defun tvd-magit-status ()
+    "Always call `magit-status' with prefix arg."
+    (interactive)
+    (let ((current-prefix-arg t))
+      (call-interactively 'magit-status)))
+
+  (with-eval-after-load 'info
+    (info-initialize)
+    (add-to-list 'Info-directory-list
+                 (expand-file-name (concat "~/.emacs.d/lisp/magit-"
+                                           tvd-magit-revision
+                                           "/Documentation/")))
+    (setq magit-view-git-manual-method 'woman))
+
+  (defalias 'git       'magit-status)
+  (defalias 'gitlog    'magit-log-buffer-file)
+
+  ;; configure magit
+  (with-eval-after-load 'magit
+    (dolist (dir (list (expand-file-name "~/D/github")
+                       (expand-file-name "~/dev/git")))
+      (when (file-exists-p dir)
+        (add-to-list 'magit-repository-directories (cons dir 1))))
+    (setq magit-completing-read-function 'magit-ido-completing-read)
+
+    ;; use timestamps in log buffers
+    (setq magit-log-margin '(t "%Y-%m-%d " magit-log-margin-width t 18))
+
+    ;; navigate magit buffers as I do everywhere else, I do not automatically
+    ;; cycle/decycle though, the magit defaults are absolutely sufficient.
+    (define-key magit-mode-map (kbd "<C-down>") 'magit-section-forward-sibling)
+    (define-key magit-mode-map (kbd "<C-up>")   'magit-section-backward-sibling)
+    (define-key magit-mode-map (kbd "<delete>") 'magit-delete-thing))
+
+  ;; one thing though:  on startup it bitches about git  version, but it
+  ;; works nevertheless. So I disable this specific warning.
+
+  (defun tvd-ignore-magit-warnings-if-any ()
+    (interactive)
+    (when (get-buffer "*Warnings*")
+      (with-current-buffer "*Warnings*"
+        (goto-char (point-min))
+        (when (re-search-forward "Magit requires Git >=")
+          (kill-buffer-and-window)))))
+
+  (add-hook 'after-init-hook 'tvd-ignore-magit-warnings-if-any t)
+
+  ;; now, THIS is the pure genius me: hit "ls in magit-status buffer
+  ;; and end up in a dired buffer of current repository. The default
+  ;; binding for this is C-M-i, which is not memorizable, while "ls"
+  ;; is. That is, 'l' is a prefix command leading to magit-log-popup
+  ;; and 's' is undefined, which I define here, which then jumps to
+  ;; dired.
+  (magit-define-popup-action 'magit-log-popup
+    ?s "Dired" 'magit-dired-jump)
+
+  ;; after an exhausting discussion on magit#3139 I use this function
+  ;; to (kind of) switch to another repository from inside magit-status.
+  (defun tvd-switch-magit-repo ()
+    (interactive)
+    (let ((dir (magit-read-repository)))
+      (magit-mode-bury-buffer)
+      (magit-status dir)))
+  (define-key magit-mode-map (kbd "C") 'tvd-switch-magit-repo)
+
+  (require 'magit-gh-pulls)
+  (add-hook 'magit-mode-hook 'turn-on-magit-gh-pulls)
+
+  ;; via
+  ;; http://manuel-uberti.github.io/emacs/2018/02/17/magit-bury-buffer/:
+  ;; a great  enhancement, when closing  the magit status  buffer, ALL
+  ;; other possibly  still remaining magit  buffers will be  killed as
+  ;; well AND the window setup will be restored.
+  (defun tvd-kill-magit-buffers()
+    "Restore window setup from before magit and kill all magit buffers."
+    (interactive)
+    (let ((buffers (magit-mode-get-buffers)))
+      (magit-restore-window-configuration)
+      (mapc #'kill-buffer buffers)))
+  (define-key magit-status-mode-map (kbd "q") #'tvd-kill-magit-buffers))
+
+
+ +
+
+
+
+

6.4.27 Dired

+
+

+I use dired for two things: from inside magit as a convenient way +to add or remove files from a repository. Or if I want to rename a +bunch of files using search/replace and other editing commands. +

+ +

+But as with everything else I use, it must fit and so I managed to +tune this as well. +

+ +

+More Hints +

+
+ +
  1. dired-k
    +

    +dired-k is k for dired/emacs: it colorizes files and directory by +age, that is, the older the greyer they get. And it displays flags +about the git status of each file, which is really handy. +

    + +

    +However, it only works with git installed and if enabled stops +dired to work completely. So I define an exception here and don't +load k if there's no git (e.g. on my notebook at work) +

    +
    +
    (when (string-match "version" (shell-command-to-string "git version"))
    +  (require 'dired-k)
    +  (add-hook 'dired-initial-position-hook 'dired-k)
    +  (add-hook 'dired-after-readin-hook #'dired-k-no-revert)
    +  (setq dired-k-padding 2))
    +
    +
    +
  2. + +
  3. dired-hacks
    +

    +Fuco1s dired-hacks is a +place to find the really cool stuff, I mostly use the filters. +

    +
    +
    (require 'dired-filter)
    +
    +(defun tvd-dired-quit-or-filter-pop (&optional arg)
    +  "Remove a filter from the filter stack. If none left, quit the dired buffer."
    +  (interactive "p")
    +  (if dired-filter-stack
    +      (dired-filter-pop arg)
    +    (quit-window)))
    +
    +(require 'dired-ranger)
    +
    +
    +
  4. + +
  5. dired sort helpers
    +

    +This sort function by Xah Lee +is easy to use and does what it should, great!, However, I added some -desc +sister sorts for reverse sorting. +

    +
    +
    (defun xah-dired-sort ()
    +  "Sort dired dir listing in different ways.
    +Prompt for a choice.
    +URL `http://ergoemacs.org/emacs/dired_sort.html'
    +Version 2015-07-30"
    +  (interactive)
    +  (let (sort-by arg)
    +    (setq sort-by (ido-completing-read "Sort by:" '( "date" "size" "name" "dir" "date-desc" "size-desc" "name-desc" "dir-desc" )))
    +    (cond
    +     ((equal sort-by "name") (setq arg "-Al --si --time-style long-iso "))
    +     ((equal sort-by "date") (setq arg "-Al --si --time-style long-iso -t"))
    +     ((equal sort-by "size") (setq arg "-Al --si --time-style long-iso -S"))
    +     ((equal sort-by "dir") (setq arg "-Al --si --time-style long-iso --group-directories-first"))
    +     ((equal sort-by "name-desc") (setq arg "-Al --si --time-style long-iso -r"))
    +     ((equal sort-by "date-desc") (setq arg "-Al --si --time-style long-iso -t -r"))
    +     ((equal sort-by "size-desc") (setq arg "-Al --si --time-style long-iso -S -r"))
    +     ((equal sort-by "dir-desc") (setq arg "-Al --si --time-style long-iso --group-directories-first -r"))
    +     (t (error "logic error 09535" )))
    +    (dired-sort-other arg )))
    +
    +
    +
  6. + +
  7. dired git helpers
    +

    +via bin chen: +make git commands available from dired buffer, which can be used in +those rare cases, where my wrappers below don't fit. +

    +
    +
    (defun diredext-exec-git-command-in-shell (command &optional arg file-list)
    +  "Run a shell command git COMMAND  ' on the marked files.  if no
    +files marked, always operate on current line in dired-mode"
    +  (interactive
    +   (let ((files (dired-get-marked-files t current-prefix-arg)))
    +     (list
    +      ;; Want to give feedback whether this file or marked files are used:
    +      (dired-read-shell-command "git command on %s: " current-prefix-arg files)
    +      current-prefix-arg
    +      files)))
    +  (unless (string-match "[?][ \t]\'" command)
    +    (setq command (concat command " *")))
    +  (setq command (concat "git " command))
    +  (dired-do-shell-command command arg file-list)
    +  (message command))
    +
    +
    + +

    +some git commandline wrappers which directly work on git files, +called with "hydras". +

    +
    +
    (defun tvd-dired-git-add(&optional arg file-list)
    +  "Add marked or current file to current repository (stash)."
    +  (interactive
    +    (let ((files (dired-get-marked-files t current-prefix-arg)))
    +      (list current-prefix-arg files)))
    +  (dired-do-shell-command "git add -v * " arg file-list)
    +  (revert-buffer))
    +
    +(defun tvd-dired-git-rm(&optional arg file-list)
    +  "Remove marked or current file from current repository and filesystem."
    +  (interactive
    +   (let ((files (dired-get-marked-files t current-prefix-arg)))
    +     (list current-prefix-arg files)))
    +  (dired-do-shell-command "git rm -rf * " arg file-list)
    +  (revert-buffer))
    +
    +(defun tvd-dired-git-ungit(&optional arg file-list)
    +  "Like `tvd-dired-git-rm' but keep the files in the filesystem (unstage)."
    +  (interactive
    +   (let ((files (dired-get-marked-files t current-prefix-arg)))
    +     (list current-prefix-arg files)))
    +  (dired-do-shell-command "git rm -rf --cached * " arg file-list)
    +  (revert-buffer))
    +
    +
    +
  8. + +
  9. dired navigation
    +

    +I'm used to jump around with pos1+end +

    +
    +
    (defun tvd-dired-begin ()
    +  "Move point to the first directory in the listing .."
    +  (interactive)
    +  (goto-char (point-min))
    +  (dired-next-dirline 2))
    +
    +(defun tvd-dired-end ()
    +  "Move point to the last file or directory in the listing."
    +  (interactive)
    +  (goto-char (point-max))
    +  (dired-previous-line 1))
    +
    +
    +
  10. + +
  11. dired buffer names
    +

    +This took me a long time to figure out, but I finally got it: I +really hate it how dired names its buffers, it just uses the +basename part of the current working directory as buffer name. So +when there are a couple of dozen buffers open and one of them is +named "tmp" I just can't see it. So what I do here is to rename +each dired buffer right after its creation by advising +`dired-internal-noselect'. My dired buffers have such names now: +dired: ~/tmp. I can find them easily, and I can reach all dired +buffers very fast thanks to the *dired prefix. And they are now +clearly marked as non-file buffers. In fact I consider this +behavior as a bug, but I doubt many people would agree :) +

    + +
    +
    (advice-add 'dired-internal-noselect
    +            :filter-return
    +            '(lambda (buffer)
    +               "Modify dired buffer names to this pattern: *dired: full-path*"
    +               (interactive)
    +               (with-current-buffer buffer
    +                 (rename-buffer (format "*dired: %s*" default-directory)))
    +               buffer))
    +
    +
    +
  12. + +
  13. dired config and key bindings
    +

    +and finally put everything together. +

    + +
    +
    (eval-after-load 'dired
    +  '(progn
    +     ;; dired vars
    +     (setq dired-listing-switches "-lt")
    +
    +     ;; stay  with 1  dired buffer  per instance
    +     ;; when changing directories
    +     (define-key dired-mode-map (kbd "RET") 'dired-find-alternate-file)
    +     (define-key dired-mode-map (kbd "<C-right>") 'dired-find-alternate-file)
    +     (define-key dired-mode-map (kbd "^") (lambda () (interactive) (find-alternate-file "..")))
    +     (define-key dired-mode-map (kbd "<C-left>") (lambda () (interactive) (find-alternate-file "..")))
    +
    +     ;; Xah Lee'S custom sort's
    +     (define-key dired-mode-map (kbd "s") 'xah-dired-sort)
    +
    +     ;; my git "hydras"
    +     (define-prefix-command 'tvd-dired-git-map)
    +     (define-key dired-mode-map (kbd "g") 'tvd-dired-git-map)
    +     (define-key tvd-dired-git-map (kbd "a") 'tvd-dired-git-add)
    +     (define-key tvd-dired-git-map (kbd "d") 'tvd-dired-git-rm)
    +     (define-key tvd-dired-git-map (kbd "u") 'tvd-dired-git-ungit)
    +
    +     ;; edit filenames
    +     (defalias 'edit-dired 'wdired-change-to-wdired-mode)
    +     (define-key dired-mode-map (kbd "C-c C-c") 'wdired-change-to-wdired-mode)
    +
    +     ;; dired-hacks filters
    +     (define-key dired-mode-map (kbd "f") dired-filter-map)
    +     (define-key dired-mode-map (kbd "q") 'tvd-dired-quit-or-filter-pop)
    +     (define-key dired-mode-map (kbd "Q") 'dired-filter-pop-all)
    +
    +     ;; ranger, multi file copy/move
    +     (define-prefix-command 'tvd-dired-ranger-map)
    +     (define-key dired-mode-map (kbd "r") 'tvd-dired-ranger-map)
    +     (define-key tvd-dired-ranger-map (kbd "c") 'dired-ranger-copy)
    +     (define-key tvd-dired-ranger-map (kbd "p") 'dired-ranger-paste)
    +     (define-key tvd-dired-ranger-map (kbd "m") 'dired-ranger-move)
    +
    +     ;; navigation,  use TAB  and C-TAB  to move
    +     ;; point to  next or prev dir  like in info
    +     ;; mode, and  HOME+END to reach the  end or
    +     ;; beginning of the listing.
    +     (define-key dired-mode-map (kbd "<tab>") 'dired-next-dirline)
    +     (define-key dired-mode-map (kbd "<C-tab>") 'dired-prev-dirline)
    +     (define-key dired-mode-map (kbd "<home>") 'tvd-dired-begin)
    +     (define-key dired-mode-map (kbd "<end>") 'tvd-dired-end)
    +
    +     ;; overwrite some defaults I do not use anyway
    +     (define-key dired-mode-map (kbd "n") 'dired-create-directory)))
    +
    +
    +
  14. +
  15. Dired Hydra
    +

    +FIXME: not yet customized to fit my own config +

    +
    +
    (defhydra hydra-dired (:hint nil :color pink)
    +  "
    +_+_ mkdir          _v_iew           _m_ark             _(_ details        _i_nsert-subdir    _W_dired (EDIT FILENAMES)
    +_C_opy             _O_ view other   _U_nmark all       _)_ omit-mode      _$_ hide-subdir    C-c C-c : edit
    +_D_elete           _o_pen other     _u_nmark           _l_ redisplay      _w_ kill-subdir
    +_R_ename           _M_ chmod        _t_oggle           _g_ revert buf     _e_ ediff          _q_uit
    +_Y_ rel symlink    _G_ chgrp        _E_xtension mark   _s_ort             _=_ pdiff
    +_S_ymlink          ^ ^              _F_ind marked      _._ toggle hydra   \\ flyspell
    +_r_sync            ^ ^              ^ ^                ^ ^                _?_ summary
    +_z_ compress-file  _A_ find regexp   / Filter
    +_Z_ compress       _Q_ repl regexp
    +
    +T - tag prefix
    +
    +"
    +  ("\\" dired-do-ispell nil)
    +  ("(" dired-hide-details-mode nil)
    +  (")" dired-omit-mode nil)
    +  ("+" dired-create-directory nil)
    +  ("=" diredp-ediff nil) ;; smart diff
    +  ("?" dired-summary nil)
    +  ("$" diredp-hide-subdir-nomove nil)
    +  ("A" dired-do-find-regexp nil)
    +  ("C" dired-do-copy nil) ;; Copy all marked files
    +  ("D" dired-do-delete nil)
    +  ("E" dired-mark-extension nil)
    +  ("e" dired-ediff-files nil)
    +  ("F" dired-do-find-marked-files nil)
    +  ("G" dired-do-chgrp nil)
    +  ("g" revert-buffer nil) ;; read all directories again (refresh nil)
    +  ("i" dired-maybe-insert-subdir nil)
    +  ("l" dired-do-redisplay nil) ;; relist the marked or singel directory
    +  ("M" dired-do-chmod nil)
    +  ("m" dired-mark nil)
    +  ("O" dired-display-file nil)
    +  ("o" dired-find-file-other-window nil)
    +  ("Q" dired-do-find-regexp-and-replace nil)
    +  ("R" dired-do-rename nil)
    +  ("r" dired-do-rsynch nil)
    +  ("S" dired-do-symlink nil)
    +  ("s" dired-sort-toggle-or-edit nil)
    +  ("t" dired-toggle-marks nil)
    +  ("U" dired-unmark-all-marks nil)
    +  ("u" dired-unmark nil)
    +  ("v" dired-view-file nil) ;; q to exit, s to search, = gets line #
    +  ("w" dired-kill-subdir nil)
    +  ("W" wdired-change-to-wdired-mode nil)
    +  ("Y" dired-do-relsymlink nil)
    +  ("z" diredp-compress-this-file nil)
    +  ("Z" dired-do-compress nil)
    +  ("q" nil nil)
    +  ("." nil nil :color blue))
    +
    +(define-key dired-mode-map "?" 'hydra-dired/body)
    +
    +
    +
+
+ +
+

6.4.28 Ediff Config

+
+

+Force ediff to use 1 frame (the current) and not open a new frame +for control and help. Also changing the split orientation doesnt +open a new frame. +

+ +
+
(eval-after-load "ediff"
+  '(progn
+     (setq ediff-diff-options   "-w"
+           ediff-split-window-function 'split-window-horizontally
+           ediff-window-setup-function 'ediff-setup-windows-plain)
+
+     (add-hook 'ediff-startup-hook 'ediff-toggle-wide-display)
+     (add-hook 'ediff-cleanup-hook 'ediff-toggle-wide-display)
+     (add-hook 'ediff-suspend-hook 'ediff-toggle-wide-display)
+
+     (add-hook 'ediff-mode-hook
+               (lambda ()
+                 (ediff-setup-keymap)
+                 ;; merge left to right
+                 (define-key ediff-mode-map ">" 'ediff-copy-A-to-B)
+                 ;; merge right to left
+                 (define-key ediff-mode-map "<" 'ediff-copy-B-to-A)))
+
+     ;; restore window config on quit
+     (add-hook 'ediff-after-quit-hook-internal 'winner-undo)
+     ))
+
+
+ +

+from emacswiki: +Usage: emacs -diff file1 file2 +

+
+
(defun command-line-diff (switch)
+  (let ((file1 (pop command-line-args-left))
+        (file2 (pop command-line-args-left)))
+    (ediff file1 file2)))
+(add-to-list 'command-switch-alist '("diff" . command-line-diff))
+
+
+
+
+
+
+

6.4.29 Smerge Config

+
+

+smerge-mode is being issued during editing of conflicts from magit, +however, I hate its default prefix, but don't have any practical +prefixes left AND am using it far too rare to deserve its own +prefix. So just a hydra will do. +

+ +
+
(defhydra hydra-smerge (:color blue :timeout 30.0)
+  "
+^Smerge Mode^
+^^-------------------------------------------------------
+_n_ext conflict         keep _u_pper    m_e_rge conflicts in Ediff
+_p_revious conflict     keep _l_ower    _q_uit"
+
+  ("n"  smerge-next       nil :exit nil)
+  ("p"  smerge-prev       nil :exit nil)
+  ("u"  smerge-keep-upper nil :exit nil)
+  ("l"  smerge-keep-lower nil :exit nil)
+  ("e"  smerge-ediff      nil :color red)
+  ("q"  nil               nil :color red))
+
+(defalias 'merge      'hydra-smerge/body)
+
+
+
+
+
+
+

6.4.30 Projectile

+
+
+
(require 'projectile)
+(projectile-mode +1)
+
+(defun tvd-dir-to-projectile ()
+    "drop a .projectile wherever we are"
+  (interactive)
+  (with-temp-file ".projectile"
+    (insert "-.snapshot\n-.git\n-.RCS\n"))
+  (message (format "Turned %s into projectile project" default-directory)))
+
+
+ +

+FIXME: add custom docstring +

+
+
(defhydra hydra-projectile
+  ( :color teal
+    :columns 4)
+  "Projectile (use C-p for this menu)"
+  ("s"   projectile-switch-project           "Switch Project")
+  ("f"   projectile-find-file                "Find File")
+  ("r"   projectile-recentf                  "Recent Files")
+  ("b"   projectile-ibuffer                  "Show Project Buffers")
+
+  ("g"   projectile-grep                     "Grep")
+  ("o"   projectile-multi-occur              "Multi Occur")
+  ("d"   projectile-dired                    "Project Dired")
+  ("R"   projectile-replace                  "Replace in Project")
+
+  ("C"   projectile-invalidate-cache         "Clear Cache")
+  ("t"   projectile-regenerate-tags          "Regenerate Tags")
+  ("X"   projectile-cleanup-known-projects   "Cleanup Known Projects")
+  ("n"   tvd-dir-to-projectile               "Turn current directory into Projectile")
+
+  ("c"   projectile-commander                "Commander")
+  ("k"   projectile-kill-buffers             "Kill Buffers")
+  ("q"   nil                                 "Cancel" :color blue))
+
+(global-set-key (kbd "C-x p") 'hydra-projectile/body)
+
+
+ + +
+
+
+
+

6.4.31 Occur

+
+

+https://oremacs.com/2015/01/26/occur-dwim/ +https://github.com/abo-abo/hydra/wiki/Emacs +

+
+
(defun occur-dwim ()
+  "Call `occur' with a sane default, chosen as the thing under point or selected region"
+  (interactive)
+  (push (if (region-active-p)
+            (buffer-substring-no-properties
+             (region-beginning)
+             (region-end))
+          (let ((sym (thing-at-point 'symbol)))
+            (when (stringp sym)
+              (regexp-quote sym))))
+        regexp-history)
+  (call-interactively 'occur))
+
+
+
+
+ +
+

6.4.32 Window Hydra

+
+

+brightness wrappers +

+
+
(defun tvd-bg-brighter ()
+  (interactive)
+  (doremi-increment-background-color-1 ?v -1))
+
+(defun tvd-bg-darker ()
+  (interactive)
+  (doremi-increment-background-color-1 ?v 1))
+
+(defun tvd-pre-resize ()
+  "Called as  pre execute  hook py  hydra-windows-resize/body and
+executes the called key once, so that no key press gets lost from
+hydra-windows (a,s,d,w)"
+  (interactive)
+  (let
+      ((key (car (reverse (append (recent-keys) nil)))))
+    (cond
+     ((eq key ?a)
+      (shrink-window-horizontally 1))
+     ((eq key ?d)
+      (enlarge-window-horizontally 1))
+     ((eq key ?w)
+      (shrink-window 1))
+     ((eq key ?s)
+      (enlarge-window 1)))))
+
+(defhydra hydra-windows-resize (:color pink :pre (tvd-pre-resize))
+  ;; small sub hydra  for window resizing, it leaves as  much room for
+  ;; windows as possible
+  "
+_a_ ||    _d_ |---|     _w_ ---   _s_ ="
+  ("a" shrink-window-horizontally nil)
+  ("d" enlarge-window-horizontally nil)
+  ("w" shrink-window nil)
+  ("s" enlarge-window nil)
+  ("q" nil nil :color red))
+
+(defhydra hydra-windows (:color blue)
+"
+
+^Window Management^
+^^------------------------------------------------------------------------
+_+_ Increase Font | _-_ Decrease Font      Resize     ^ ^  _w_  ^ ^
+_f_: Flip Windows    <M-O>            ^^   Current    _a_  ^ ^  _d_
+_4_: Quarter Windows <C-x 4>          ^^   Window:    ^ ^  _s_  ^ ^
+_u_: Windows Undo    <C-c left>
+_r_: Windows Redo    <C-c right>      ^^   _l_: Adjust Background brighter
+_i_: Invert Colors   <C-c C-i>        ^^   _b_: Adjust Background darker
+
+_h_: Toggle Highlight Line Mode       ^^   _e_: Eyebrowse Workspaces (C-x C-x)
+_n_: Toogle Line Number Mode
+
+^^------------------------------------------------------------------------
+Reach this hydra with <C-x w>
+^^------------------------------------------------------------------------
+
+"
+  ("+" tvd-global-font-size-bigger nil :color pink)
+  ("-" tvd-global-font-size-smaller nil :color pink)
+  ("f" tvd-flip-windows nil)
+  ("4" tvd-quarter-windows nil)
+  ("u" winner-undo nil)
+  ("r" winner-redo nil)
+  ("i" tvd-invert nil)
+  ("b" tvd-bg-darker nil :color pink)
+  ("l" tvd-bg-brighter nil :color pink)
+  ("a" hydra-windows-resize/body nil)
+  ("d" hydra-windows-resize/body nil)
+  ("w" hydra-windows-resize/body nil)
+  ("s" hydra-windows-resize/body nil)
+  ("e" hydra-eyebrowse/body nil)
+  ("h" hl-line-mode nil)
+  ("n" linum-mode nil)
+  ("q" nil nil :color red))
+
+(global-set-key (kbd "C-x w") 'hydra-windows/body)
+
+
+
+
+ + +
+

6.4.33 Eyebrowse Workspaces

+
+

+workspace configuration, like desktops. Seems to be a good implementation, w/o save though +

+ +

+"prefix key" has to be set before loading, keep in mind, that +if you change it here, you need to change it below as well! +

+
+
(setq eyebrowse-keymap-prefix (kbd "C-x C-x"))
+(global-unset-key (kbd "C-x C-x"))
+
+(require 'eyebrowse)
+
+(defun tvd-new-eyebrowse-workspace ()
+  "Create new scratch buffer and ask for a name"
+  (interactive)
+  (eyebrowse-rename-window-config (eyebrowse--get 'current-slot) (read-string "Workspace: "))
+  (autoscratch-buffer))
+
+
+ +

+always enable +

+
+
(eyebrowse-mode t)
+(setq eyebrowse-new-workspace 'tvd-new-eyebrowse-workspace
+      eyebrowse-switch-back-and-forth t
+      eyebrowse-wrap-around t
+      eyebrowse-mode-line-style t
+      eyebrowse-slot-format "%s:init")
+
+
+ +

+add a hydra, just in case, it contains hydra commands and hints +about the actual key bindings, it's also being refered from +hydra-window/body with "e" +

+
+
(defhydra hydra-eyebrowse (:color blue)
+  "
+^Eyebrowse Workspace Management^
+^^--------------------------------------
+_l_: last window      (C-x C-x C-x)
+_n_: next window      (C-x C-x <right>)
+_p_: prev window      (C-x C-x <left>)
+_x_: close workspace  (C-x C-x q)
+_t_: rename workspace (C-x C-x t)
+_c_: create workspace (C-x C-x n)
+
+Use C-x C-x to access eyebrowse directly.
+"
+  ("l" eyebrowse-last-window-config nil)
+  ("n" eyebrowse-next-window-config nil)
+  ("p" eyebrowse-prev-window-config nil)
+  ("x" eyebrowse-close-window-config nil)
+  ("t" eyebrowse-rename-window-config nil)
+  ("c" eyebrowse-create-window-config nil)
+  ("q" nil nil :color red))
+
+
+ +

+Modifying the eyebrowse keymap directly doesn't work because it's +not setup correctly. I sent a pull request to fix this: +https://github.com/wasamasa/eyebrowse/pull/94, however, vaslilly choosed +not to accept it. So, I need to configure the whole chords for every +function I use AND set the "prefix key" using the weird way above +(before loading). +

+
+
(global-set-key (kbd "C-x C-x C-x")     'eyebrowse-last-window-config)
+(global-set-key (kbd "C-x C-x <right>") 'eyebrowse-next-window-config)
+(global-set-key (kbd "C-x C-x <left>")  'eyebrowse-prev-window-config)
+(global-set-key (kbd "C-x C-x q")       'eyebrowse-close-window-config)
+(global-set-key (kbd "C-x C-x t")       'eyebrowse-rename-window-config)
+(global-set-key (kbd "C-x C-x n")       'eyebrowse-create-window-config)
+(global-set-key (kbd "C-x C-x ?")       'hydra-eyebrowse/body)
+
+
+ +

+There's also some face config, see defcustom at end of file! +

+
+
+ +
+

6.4.34 Highlighting Indentation

+
+

+provides: highlight-indentation-mode and highlight-indentation-current-column-mode +

+
+
(require 'highlight-indentation)
+
+(add-something-to-mode-hooks
+ '(yaml python ruby) 'highlight-indentation-current-column-mode)
+
+(set-face-background 'highlight-indentation-face "#e3e3d3")
+(set-face-background 'highlight-indentation-current-column-face "#c3b3b3")
+
+
+
+
+
+ +
+

6.5 Emacs Interface

+
+
+

6.5.1 Parens

+
+

+display matching braces +

+
+
(show-paren-mode 1)
+
+
+ +

+'mixed: highlight all if the other paren is invisible +'expression: highlight the whole sexp +

+
+
(setq show-paren-style 'mixed)
+
+
+
+
+ +
+

6.5.2 highlight todo keywords (such as FIXME)

+
+

+Absolutely needed! +

+ +
+
(require 'fic-mode)
+(add-something-to-mode-hooks '(c c++ cperl vala web emacs-lisp ruby python) 'turn-on-fic-mode)
+
+
+ +
+
+
+
+

6.5.3 UNDO Tree Mode

+
+

+Better undo, with redo support. +

+ +

+C-_ (`undo-tree-undo') + Undo changes. +

+ +

+C-: (`undo-tree-redo') + Redo changes. +

+ +

+more: see undo-tree.el +

+
+
(require 'undo-tree)
+
+
+ +

+use always +

+
+
(global-undo-tree-mode)
+
+
+ +

+M-_ catched by Xmonad +

+
+
(global-set-key (kbd "C-:")             'undo-tree-redo) ; C-: == REDO   C-_ == UNDO
+
+
+ +
+
+
+
+

6.5.4 Smarter M-x Mode (smex)

+
+

+This is really cool and I don't know how I could ever live without it. +

+ +

+fails @win, so wrap it +

+
+
(safe-wrap
+ (progn
+   (require 'smex)
+   (smex-initialize)
+   (global-set-key (kbd "M-x") 'smex)
+   (global-set-key (kbd "M-X") 'smex-major-mode-commands))
+ (message "ignoring unsupported smex"))
+
+
+
+
+
+ +
+

6.5.5 Smarter Search

+
+

+test, replace isearch-forward-regexp first only. +dir: ivy/ +

+
+
(require 'swiper)
+(with-eval-after-load 'swiper
+  (setq ivy-wrap t)
+  (global-set-key "\C-s" 'swiper))
+
+
+
+
+ +
+

6.5.6 Which Func

+
+

+display current function - if any - in mode line +

+
+
(add-something-to-mode-hooks
+    '(c c++ cperl vala makefile ruby shell-script python)
+    'which-func-mode)
+
+
+ +
+
+
+
+

6.5.7 Show current-line in the Fringe

+
+
+
(require 'fringe-current-line)
+(global-fringe-current-line-mode 1)
+
+
+ +

+also change the color (matching the mode line +

+
+
(set-face-attribute 'fringe nil :foreground "NavyBlue")
+
+
+ +
+
+
+
+

6.5.8 Recent Files

+
+

+You know the file you edited yesterday had "kri" in its name, but +where was it? You don't remember. But don't worry, recent files is +your friend. It shows the last N files you edited recently. +I use it permanently. +

+ +

+see also: ido-mode and smex +

+ +

+setup +

+
+
(require 'recentf)
+(require 'cl-lib)
+(setq recentf-auto-cleanup 'never) ;; avoid stat() on tramp buffers
+(recentf-mode 1)
+
+
+ +

+I like to have a longer list reaching deeper into the past +

+
+
(setq recentf-max-menu-items 200
+      recentf-max-saved-items nil)
+
+
+ +

+enable IDO completion +via emacsredux +modified to exclude already visited files +

+
+
(defun tvd-buffer-exists-p (bufname)
+  (not (eq nil (get-file-buffer bufname))))
+
+(defun recentf-ido-find-file ()
+  "Find a recent file using ido."
+  (interactive)
+  (let ((file (ido-completing-read
+               "Choose recent file: "
+               (cl-remove-if 'tvd-buffer-exists-p recentf-list) nil t)))
+    (when file
+      (find-file file))))
+
+(global-set-key (kbd "C-x C-r")         'recentf-ido-find-file) ; open recent files, same as M-x rf
+
+
+ +

+now if I incidentally closed a buffer, I can re-open it, thanks to +recent-files +

+
+
(defun undo-kill-buffer (arg)
+  "Re-open the last buffer killed.  With ARG, re-open the nth buffer."
+  (interactive "p")
+  (let ((recently-killed-list (copy-sequence recentf-list))
+        (buffer-files-list
+         (delq nil (mapcar (lambda (buf)
+                             (when (buffer-file-name buf)
+                               (expand-file-name (buffer-file-name buf)))) (buffer-list)))))
+    (mapc
+     (lambda (buf-file)
+       (setq recently-killed-list
+             (delq buf-file recently-killed-list)))
+     buffer-files-list)
+    (find-file
+     (if arg (nth arg recently-killed-list)
+       (car recently-killed-list)))))
+
+
+ +

+exclude some auto generated files +

+
+
(setq recentf-exclude (list "ido.last"
+                            "/elpa/"
+                            ".el.gz$"
+                            '(not (file-readable-p))))
+
+
+ +
+
+
+ +
+

6.5.9 IDO mode

+
+

+There are other completion enhancement packages available like ivy +for example, but I love IDO and I am so used to it, it would be +impossible to change. So, I'll stick with IDO until end of (my) +times. +

+ +

+Hint: Use C-f during file selection to switch to regular find-file +

+ +

+Basic config +

+
+
(ido-mode t)
+(ido-everywhere nil)
+(setq ido-enable-flex-matching t)
+(setq ido-use-filename-at-point nil)
+(setq ido-use-virtual-buffers t)
+(setq ido-auto-merge-work-directories-length -1)
+
+
+ +

+One thing annoys me with IDO though: when writing a new file, IDO +wants me to select from a list of existing files. Since it is +nearly impossible to disable ido mode for write-file, which I HATE, +I came up with this: +

+ +

+I added a new global variable, 'tvd-ido-disabled, which is nil by +default. Whenever I hit C-x C-w (in order to execute write-file), +it will be set to t, ido mode will be disabled and ido-write-file +will be called. Since ido mode is now disabled, it just calls the +original write-file, which is what I really want. +

+ +

+When I'm finished selecting a filename and writing, ido mode will +be turned on again and the variable will be set to nil. However, +sometimes I may abort the process using C-g. In that case ido mode +may end up being disabled because the :after advice will not be +called on C-g. +

+ +

+So, I also advice the minibuffer C-g function, which is +'abort-recursive-edit, and re-enable ido mode from here if it is +still disabled. So far I haven't seen any bad side effects of this. +

+ +
+
(defvar tvd-ido-disabled nil)
+(advice-add 'ido-write-file :before '(lambda (&rest args) (ido-mode 0) (setq tvd-ido-disabled t)))
+(advice-add 'ido-write-file :after  '(lambda (&rest args) (ido-mode 1) (setq tvd-ido-disabled nil)))
+
+(defun tvd-keyboard-quit-advice (fn &rest args)
+  (when tvd-ido-disabled
+    (ido-mode 1)
+    (setq tvd-ido-disabled nil))
+  (apply fn args))
+
+(advice-add 'abort-recursive-edit :around #'tvd-keyboard-quit-advice)
+
+
+ +

+from emacs wiki +Display ido results vertically, rather than horizontally +

+
+
(setq ido-decorations (quote ("\n-> " "" "\n   " "\n   ..." "[" "]"
+                              " [No match]" " [Matched]" " [Not readable]"
+                              " [Too big]" " [Confirm]")))
+
+(defun ido-disable-line-truncation () (set (make-local-variable 'truncate-lines) nil))
+(add-hook 'ido-minibuffer-setup-hook 'ido-disable-line-truncation)
+(defun ido-define-keys ()
+  (define-key ido-completion-map (kbd "<down>") 'ido-next-match)
+  (define-key ido-completion-map (kbd "<up>") 'ido-prev-match))
+(add-hook 'ido-setup-hook 'ido-define-keys)
+
+
+ +

+quickly go to home via ~ wherever I am +via whattheemacs.d +

+
+
(add-hook 'ido-setup-hook
+ (lambda ()
+   ;; Go straight home
+   (define-key ido-file-completion-map
+     (kbd "~")
+     (lambda ()
+       (interactive)
+       (if (looking-back "/")
+           (insert "~/")
+         (call-interactively 'self-insert-command))))
+   ;; same thing, but for ssh/tramp triggered by :
+   (define-key ido-file-completion-map
+     (kbd ":")
+     (lambda ()
+       (interactive)
+       (if (looking-back "/")
+           (progn
+             (ido-set-current-directory "/ssh:")
+             (ido-reread-directory))
+         (call-interactively 'self-insert-command))))))
+
+
+ +

+by howardism: [re]open non-writable file with sudo +

+
+
(defadvice ido-find-file (after find-file-sudo activate)
+  "Find file as root if necessary."
+  (unless (and buffer-file-name
+               (file-writable-p buffer-file-name))
+    (let* ((file-name (buffer-file-name))
+           (file-root (if (string-match "/ssh:\\([^:]+\\):\\(.*\\)" file-name)
+                          (concat "/ssh:"  (match-string 1 file-name)
+                                  "|sudo:" (match-string 1 file-name)
+                                  ":"      (match-string 2 file-name))
+                        (concat "/sudo:localhost:" file-name))))
+      (find-alternate-file file-root))))
+
+
+ +

+FIXME: add ido-ignore-files defun. +

+ +
+
+
+ +
+

6.5.10 Save cursor position

+
+

+So the next time I start emacs and open a file I were editing +previously, (point) will be in the exact places where it was +before. +

+ +
+
(if (version< emacs-version "25.0")
+    (progn
+      (require 'saveplace)
+      (setq-default save-place t))
+  (save-place-mode 1))
+
+
+ +
+
+
+ +
+

6.5.11 DoReMi experimentation

+
+

+I'm not using it a lot, sometimes I tune the background color though. +

+ +

+via emacswiki/DoReMi +cool ones: doremi-buffers, doremi-all-faces-fg+ [s, h] +

+ +
+
(require 'doremi)
+(require 'doremi-frm)
+(require 'doremi-cmd)
+
+
+ +

+FIXME: find a good key +

+
+
(defalias 'cb 'doremi-buffers+)
+
+
+ +
+
+
+
+

6.5.12 Hightligt TABs

+
+

+not a mode, but however: higlight TABs in certain modes +

+ +
+
(defface extra-whitespace-face
+  '((t (:background "pale green")))
+  "Used for tabs and such.")
+
+(defvar tvd-extra-keywords
+  '(("\t" . 'extra-whitespace-face)))
+
+(add-something-to-mode-hooks '(c c++ vala cperl emacs-lisp python shell-script ruby)
+                             (lambda () (font-lock-add-keywords nil tvd-extra-keywords)))
+
+
+ +
+
+
+ +
+

6.5.13 Browse kill-ring

+
+

+when active use n and p to browse, <ret> to select, it's the same +as <M-y> and I never really use it… +

+ +
+
(require 'browse-kill-ring)
+(setq browse-kill-ring-highlight-current-entry t
+      browse-kill-ring-highlight-inserted-item t)
+
+
+ +
+
+
+ +
+

6.5.14 goto-last-change

+
+

+Very handy, jump to last change[s]. +

+ +
+
(require 'goto-last-change)
+
+(global-set-key (kbd "C-b")             'goto-last-change)
+
+
+ +
+
+
+ +
+

6.5.15 Bookmarks

+
+

+I use the builtin bookmark feature quite a lot and am happy with +it. Especially at work, where many files are located in large +path's on remote storage systems, it great to jump quickly to such +places. +

+ +

+everytime bookmark is changed, automatically save it +

+
+
(setq bookmark-save-flag 1
+      bookmark-version-control t)
+
+
+ +

+I use the same aliases as in apparix for bash (since I'm used to them) +

+
+
(defalias 'to        'bookmark-jump)
+(defalias 'bm        'bookmark-set)
+(defalias 'bl        'bookmark-bmenu-list)
+
+
+ +
+
+
+ +
+

6.5.16 which-key

+
+

+One of the best unobstrusive modes for key help ever. Just start +entering a key chord, prefix or whatever, and it pops a small +buffer (on the right side in my case) showing the avialable keys to +press from there along with the associated functions. +

+ +
+
(require 'which-key)
+(which-key-mode)
+(which-key-setup-side-window-right)
+
+
+ +
+
+
+ +
+

6.5.17 iBuffer mode

+
+

+iBuffer is a great interactive buffer management tool included with +emacs. I use it with a couple of custom groups, my own +collapse-code (<TAB>) and formats. +

+ +
+
(require 'ibuffer)
+
+
+ +

+from github: +

+
+
(require 'ibuffer-vc)
+(require 'ibuffer-tramp)
+
+
+ +

+replace default list-buffers with ibuffer +

+
+
(global-set-key (kbd "C-x C-b")         'ibuffer)
+
+
+ +

+group name +

+
+
(setq tvd-ibuffer-filter-group-name "tvd-filters")
+
+
+ +

+filter group config +with hints from Ogbe et.al. +

+
+
(setq ibuffer-saved-filter-groups
+      (list (nreverse
+             `(
+               ("Org" (mode . org-mode))
+               ("Shell" (or (mode . term-mode)
+                            (mode . eshell-mode)
+                            (mode . shell-mode)))
+               ("Emacs-Config"  (filename . "emacs"))
+               ("Cisco-Config" (mode . cisco-mode))
+               ("Code" (or (mode . cperl-mode)
+                           (mode . c-mode)
+                           (mode . python-mode)
+                           (mode . shell-script-mode)
+                           (mode . makefile-mode)
+                           (mode . cc-mode)))
+               ("Text" (or (mode . text-mode)
+                           (filename . "\\.pod$")))
+               ("LaTeX" (mode . latex-mode))
+               ("Interactive" (or
+                               (mode . inferior-python-mode)
+                               (mode . slime-repl-mode)
+                               (mode . inferior-lisp-mode)
+                               (mode . inferior-scheme-mode)
+                               (name . "*ielm*")))
+               ("Crab" (or
+                        (name . "^\\*\\(Help\\|scratch\\|Messages\\)\\*")
+                          ))
+               ,tvd-ibuffer-filter-group-name))))
+
+
+ +

+Reverse the order of the filter groups. Kind of confusing: Since +I'm reversing the order of the groups above, this snippet ensures +that the groups are ordered in the way they are written above, with +the "Default" group on top. This advice might need to be ported to +the new advice system soon. +

+ +
+
(defadvice ibuffer-generate-filter-groups
+    (after reverse-ibuffer-groups () activate)
+  (setq ad-return-value (nreverse ad-return-value)))
+
+(defun ibuffer-add-dynamic-filter-groups ()
+  (interactive)
+  (dolist (group (ibuffer-vc-generate-filter-groups-by-vc-root))
+    (add-to-list 'ibuffer-filter-groups group))
+  (dolist (group (ibuffer-tramp-generate-filter-groups-by-tramp-connection))
+    (add-to-list 'ibuffer-filter-groups group)))
+
+(defun tvd-ibuffer-hooks ()
+  (ibuffer-auto-mode 1)
+  (ibuffer-switch-to-saved-filter-groups tvd-ibuffer-filter-group-name)
+  (ibuffer-add-dynamic-filter-groups))
+(add-hook 'ibuffer-mode-hook 'tvd-ibuffer-hooks)
+
+
+ +

+Only show groups that have active buffers +

+
+
(setq ibuffer-show-empty-filter-groups nil)
+
+
+ +

+Don't show the summary or headline +

+
+
(setq ibuffer-display-summary nil)
+
+
+ +

+do not prompt for every action +

+
+
(setq ibuffer-expert t)
+
+
+ +

+buffers to always ignore +

+
+
(add-to-list 'ibuffer-never-show-predicates "^\\*\\(Completions\\|tramp/\\)")
+
+
+ +

+Use human readable Size column instead of original one +

+
+
(define-ibuffer-column size-h
+  (:name "Size" :inline t)
+  (cond
+   ((> (buffer-size) 1000000) (format "%7.1fM" (/ (buffer-size) 1000000.0)))
+   ((> (buffer-size) 100000) (format "%7.0fk" (/ (buffer-size) 1000.0)))
+   ((> (buffer-size) 1000) (format "%7.1fk" (/ (buffer-size) 1000.0)))
+   (t (format "%8d" (buffer-size)))))
+
+
+ +

+Modify the default ibuffer-formats +

+
+
(setq ibuffer-formats
+      '((mark modified read-only " "
+              (name 20 40 :left :elide)
+              " "
+              (size-h 9 -1 :right)
+              " "
+              (mode 16 16 :left :elide)
+              " "
+              filename-and-process)))
+
+
+ +

+hide annoying groups, but keep its buffers available +

+
+
(defvar ibuffer-collapsed-groups (list "Crab"))
+
+(advice-add 'ibuffer :after '(lambda (&rest args)
+  (ignore args)
+  (save-excursion
+    (dolist (group ibuffer-collapsed-groups)
+      (ignore-errors
+        (ibuffer-jump-to-filter-group group)
+        (ibuffer-toggle-filter-group))))))
+
+
+ +

+move point to most recent buffer when entering ibuffer +

+
+
(defadvice ibuffer (around ibuffer-point-to-most-recent) ()
+           "Open ibuffer with cursor pointed to most recent (non-minibuffer) buffer name"
+           (let ((recent-buffer-name
+                  (if (minibufferp (buffer-name))
+                      (buffer-name
+                       (window-buffer (minibuffer-selected-window)))
+                    (buffer-name (other-buffer)))))
+             ad-do-it
+             (ibuffer-jump-to-buffer recent-buffer-name)))
+(ad-activate 'ibuffer)
+
+
+ +

+override ibuffer M-o binding +

+
+
(define-key ibuffer-mode-map (kbd "M-o")    'other-window-or-switch-buffer)
+
+
+ + +
+
+
+ +
+

6.5.18 Printing

+
+

+overwrites printing default menu, access via menu File => Print +or: +

+
    +
  • M-x ps-spool-buffer-with-faces
  • +
  • go to spool buffer
  • +
  • save to .ps file
  • +
  • print
  • +
+
+
(require 'printing)
+(pr-menu-bind)
+
+
+ +

+via stackoverflow +

+
+
(when (executable-find "ps2pdf")
+  (defun print-to-pdf (&optional filename)
+    "Print file in the current buffer as pdf, including font, color, and
+underline information.  This command works only if you are using a window system,
+so it has a way to determine color values.
+
+C-u COMMAND prompts user where to save the Postscript file (which is then
+converted to PDF at the same location."
+    (interactive (list (if current-prefix-arg
+                           (ps-print-preprint 4)
+                         (concat (file-name-sans-extension (buffer-file-name))
+                                 ".ps"))))
+    (ps-print-with-faces (point-min) (point-max) filename)
+    (shell-command (concat "ps2pdf " filename))
+    (delete-file filename)
+    (message "Deleted %s" filename)
+    (message "Wrote %s" (concat (file-name-sans-extension filename) ".pdf"))))
+
+
+ +
+
+
+
+

6.5.19 Beacon mode (pointer blink)

+
+

+Source: beacon mode +

+ +

+Blink the cursor shortly when moving across large text sections or +when changing windows. That way it is easier to find the current +editing position. +

+ +
+
(require 'beacon)
+
+(setq beacon-blink-duration 0.1
+      beacon-blink-when-point-moves-vertically 10
+      beacon-color 0.3)
+
+(add-hook 'beacon-dont-blink-predicates
+          (lambda () (bound-and-true-p novel-mode)))
+
+(beacon-mode)
+
+
+ +
+
+
+
+
+

6.6 mode-line setup (must be the last mode)

+
+

+I just append the current version of my emacs config and leave out +some stuff to keep the modeline short, so that everything can be +seen even if I have multiple windows open. +

+ +

+smaller pos +

+
+
(setq-default mode-line-position
+              '((-3 "%p") (size-indication-mode ("/" (-4 "%I")))
+                " "
+                (line-number-mode
+                 ("%l" (column-number-mode ":%c")))))
+
+
+ +

+when macro recording is active, signal it with coloring instead of +just a character +

+
+
(defface rec-face
+  '((t (:background "red" :foreground "white" :weight bold)))
+  "Flag macro recording in mode-line"
+  :group 'tvd-mode-line-faces)
+
+
+ +

+custom modeline +

+
+
(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) "
+
+               " [" tvd-emacs-version "] "
+
+               ; added because of eyebrowse
+               mode-line-misc-info
+
+               '(:eval (propertize
+                        (if (eq defining-kbd-macro t)
+                            "[REC]"
+                          "")
+                        'face 'rec-face))
+
+               mode-line-end-spaces))
+
+
+ +
+
+
+
+
+

7 Emacs Autoconfig / Customize group / final stuff

+
+
+
+
+

7.1 font faces

+
+

+Font color config, must always be the last thing so all hook faces are loaded. +

+ +

+show available colors: +

+
+
(defalias 'colors 'list-colors-display)
+
+
+ +

+from 20181227 I outsourced my font config into a theme, located in +.emacs.d/tom-past-century.el, so that I can load another theme +anytime I like AND switch back to my own config w/o restarting +emacs +

+
+
(add-hook 'after-init-hook (lambda () (load-theme 'tom-past-century t)))
+
+
+ +

+unless we're on windoze +

+
+
(if (not (null tvd-win-home))
+    (set-face-font 'default "Courier New"))
+
+
+ +
+
+
+
+

7.2 emacs server

+
+

+Based on this +I check both predicates, just to be sure, only one of them doesn't work. +

+ +

+FIXME: check if 'server-socket-dir/server exists as well +

+
+
(require 'server)
+(unless (or (server-running-p)
+            (and (boundp 'server-process) server-process))
+  (progn
+    (advice-add 'save-buffers-kill-terminal :before
+                (lambda (&rest args) (server-edit)))
+    (server-start)))
+
+
+ +
+
+
+
+

7.3 variables

+
+

+If I ever use custom-group to customize a mode, then I create a +manual config section for it using the values, custom has added +here. So, in normal times this should be empty, but needs to exist. +

+ +
+
(custom-set-variables
+ ;; custom-set-variables was added by Custom.
+ ;; If you edit it by hand, you could mess it up, so be careful.
+ ;; Your init file should contain only one such instance.
+ ;; If there is more than one, they won't work right.
+ '(custom-safe-themes
+   (quote
+    ("d88c43fe03ac912e35963695caf0ae54bc6ce6365c3a42da434ef639f7a37399" default)))
+ '(package-selected-packages (quote (magit)))
+ '(safe-local-variable-values (quote ((ruby-indent-level 4)))))
+
+
+
+
+ +
+

7.4 done

+
+

+Finally, this message is being displayed. If this isn't the case I +know easily that something went wrong. +

+ +
+
(message "loading done")
+(custom-set-faces
+ ;; custom-set-faces was added by Custom.
+ ;; If you edit it by hand, you could mess it up, so be careful.
+ ;; Your init file should contain only one such instance.
+ ;; If there is more than one, they won't work right.
+ )
+
+
+
+
+

Author: Tom

-

Created: 2020-01-01 Mi 13:16

+

Created: 2020-09-02 Mi 20:44

Validate