12. Emacs vs. Vi vs. Eclipse vs. anyIDE

The pro’s and con’s in the religious editor war.

12.1. How to install latest stable Emacs in Ubuntu

Prerequisites:

apt-get install apel

For latest emacs stable releases on ubuntu (also recommended by How to Install GNU Emacs 26.1 in Ubuntu):

add-apt-repository ppa:kelleyk/emacs

apt-get update && \
apt-get install emacs26 emacs26-el && \
update-alternatives --set emacs /usr/bin/emacs26

12.1.1. Setup for emacsen-common

Integration with emacsen-common is not so hard:

touch /var/lib/emacsen-common/state/flavor/installed/emacs26

mkdir -p /etc/emacs26/site-start.d
mkdir -p /usr/share/emacs26/site-lisp
mv /usr/share/emacs/26.2/site-lisp/* /usr/share/emacs26/site-lisp/

rm -rf /usr/share/emacs/26.2/site-lisp
ln -s ../../emacs26/site-lisp  /usr/share/emacs/26.2/

Since subdirs.el is loaded before site-init is inhibited, it can be used as replacement for startup.el. Create /usr/share/emacs26/site-lisp/subdirs.el:

;; |:here:|
cat <<'EOF' >/usr/share/emacs26/site-lisp/subdirs.el
(defvar package--builtin-versions
  ;; Mostly populated by loaddefs.el via autoload-builtin-package-versions.
  (purecopy `((emacs . ,(version-to-list emacs-version))))
  "Alist giving the version of each versioned builtin package.
I.e. each element of the list is of the form (NAME . VERSION) where
NAME is the package name as a symbol, and VERSION is its version
as a list.")

(defun package--description-file (dir)
  (concat (let ((subdir (file-name-nondirectory
                         (directory-file-name dir))))
            (if (string-match "\\([^.].*?\\)-\\([0-9]+\\(?:[.][0-9]+\\|\\(?:pre\\|beta\\|alpha\\)[0-9]+\\)*\\)" subdir)
                (match-string 1 subdir) subdir))
          "-pkg.el"))

(defconst debian-emacs-flavor 'emacs26
  "A symbol representing the particular debian flavor of emacs running.
Something like 'emacs20, 'xemacs20, etc.")

(if (fboundp 'normal-top-level-add-subdirs-to-load-path)
    (normal-top-level-add-subdirs-to-load-path))

(let ((local-site-lisp "/usr/local/share/emacs/26.2/site-lisp/"))
  (make-directory local-site-lisp t)
  (if (not (member local-site-lisp load-path))
      (setq load-path (cons local-site-lisp load-path))))
EOF
;; |:here:| `

Now add the debian specific startup to /usr/share/emacs26/site-lisp/site-start.el:

;; |:here:|
cat <<'EOF' >/usr/share/emacs26/site-lisp/site-start.el
(if (load "debian-startup" t t nil)
    (debian-startup debian-emacs-flavor))
EOF
;; |:here:| `

12.1.2. Obsolete packages

Remove these packages, since they do not work:

apt-get purge prolog-el
apt-get purge dash-el

12.1.3. Modify/repair packages

If necessary (Ubuntu 16.04/18.04):

grep '(("\\\\\\\\\[Ss]ubref{\\\\(\[^{}\\n\\r\\\\%,\]\*\\\\)" 1 LaTeX-label-list "}")))' /usr/share/emacs/site-lisp/auctex/style/subfigure.el

apply auctex patch manually (obviously this will not work with patch(1), since TABs are lost):

--- /usr/share/emacs/site-lisp/auctex/style/subfigure.el-000 2015-11-19 15:26:11.000000000 +0100
+++ /usr/share/emacs/site-lisp/auctex/style/subfigure.el     2019-09-03 21:03:22.354599330 +0200
@@ -47,8 +47,8 @@
    ;; Install completion for labels:
    (setq TeX-complete-list
         (append
-      '(("\\\\[Ss]ubref{\\([^{}\n\r\\%,]*\\)" 1 LaTeX-label-list "}")))
-      TeX-complete-list)
+      '(("\\\\[Ss]ubref{\\([^{}\n\r\\%,]*\\)" 1 LaTeX-label-list "}"))
+      TeX-complete-list))

    ;; Fontification
    (when (and (featurep 'font-latex)

Before installing the new emacs, repair package apel. If necessary (Ubuntu 16.04):

grep '[^\][\]N' /usr/share/emacs/site-lisp/apel/poe.el

replace \N in doc strings of /usr/share/emacs/site-lisp/apel/poe.el with \\N:

vi /usr/share/emacs/site-lisp/apel/poe.el
:
1,$s,\\N,\\\\N,g

Hint: the substitution command works also fine in sed(1).

12.1.4. Activate packages

Add emacs26 to packages depending on emacs flavor:

/bin/grep --color -nH -e 'emacs2[45]' /usr/lib/emacsen-common/packages/*/*

/usr/lib/emacsen-common/packages/install/auctex:116:    (emacs24|emacs25|emacs26|emacs-snapshot)
/usr/lib/emacsen-common/packages/install/psgml:50:    emacs26 | emacs25 | emacs24)
/usr/lib/emacsen-common/packages/remove/auctex:60:    (emacs24|emacs25|emacs-snapshot)
/usr/lib/emacsen-common/packages/remove/psgml:52:    emacs21 | emacs22 | emacs23 | emacs24 | emacs25 | emacs-snapshot)

|:todo:| do it manually a couple of times, then write a script (python(1) or sed(1))

12.1.5. Optional packages

If dvc is installed, put this at the start of /etc/emacs/site-start.d/50dvc.el to activate the ewoc system package.

;; |:here:| `
(condition-case err
    (let ((load-path (reverse load-path)))
      ;; search system libraries first
      (require 'ewoc))
  (error (message "error: %s" (error-message-string err))))
;; |:here:| `

12.1.6. Integrate emacs into emacsen-common

Now update site-lisp with the intstalled debian packages:

/usr/lib/emacsen-common/emacs-install emacs26

12.2. Kill-Ring

C-k - kill to end of line
C-w - kill region
M-w - copy region to kill ring
C-y + yank last kill item
M-y + (directly after a C-y) replace inserted kill item by previous kill item
C-u - M-y + replace inserted kill item by next kill item

12.3. Undo

  • The Emacs undo semantics is lossless.
  • Vi has a lossless (and persistent) undo tree and so does Emacs (Emacs: Undo Tree package)

12.3.1. Standard Undo Function

The standard undo semantics of adding edits, undo some and – with the next edit – loose everything that was undone is just silly.

Step Action Description
Edit 4 chunks added a, b, c, d
Undo 2 chunks removed d, c
Edit 2 chunks added e, f
Undo 2 chunks removed f, e
  Undo 1 chunk removed b

digraph graph0 { subgraph cluster_graph0 { n0 [label="1",shape=circle;fontsize=10,widht=0.4,height=0.4;fixedsize=true]; a0 [label="a"]; b0 [label="b"]; c0 [label="c"]; d0 [label="d"]; edge [style=solid,dir=forward,color=green]; a0 -> b0 -> c0 -> d0; } subgraph cluster_graph1 { n1 [label="2",shape=circle;fontsize=10,widht=0.4,height=0.4;fixedsize=true]; a1 [label="a"]; b1 [label="b"]; c1 [label="c"]; d1 [label="d"]; edge [style=dashed,dir=none,color=green]; a1 -> b1 -> c1 -> d1; edge [style=solid,dir=forward,color=red]; d1 -> c1 -> b1; } subgraph cluster_graph2 { n2 [label="3",shape=circle;fontsize=10,widht=0.4,height=0.4;fixedsize=true]; a2 [label="a"]; b2 [label="b"]; c2 [label="c",style=invis]; d2 [label="d",style=invis]; e2 [label="e"]; f2 [label="f"]; edge [style=dashed,dir=none,color=green]; a2 -> b2; edge [style=invis,dir=none,color=red]; b2 -> c2 -> d2 -> c2 -> b2; edge [style=solid,dir=forward,color=green]; b2 -> e2 -> f2; } subgraph cluster_graph3 { n3 [label="4",shape=circle;fontsize=10,widht=0.4,height=0.4;fixedsize=true]; a3 [label="a"]; b3 [label="b"]; c3 [label="c",style=invis]; d3 [label="d",style=invis]; e3 [label="e"]; f3 [label="f"]; edge [style=dashed,dir=none,color=green]; a3 -> b3; edge [style=invis,dir=none,color=red]; b3 -> c3 -> d3 -> c3 -> b3; edge [style=dashed,dir=none,color=green]; b3 -> e3 -> f3; edge [style=solid,dir=forward,color=red]; f3 -> e3 -> b3 -> a3; } }

12.3.2. Emacs Undo Function

For Emacs an undo that removes a previous edit is just another action that can be undone later.

Step Action Description
Edit 4 chunks added a, b, c, d
Undo 2 chunks removed d, c
Edit 2 chunks added e, f
Undo 2 chunks removed f, e
  Undo 2 chunks added c, d

digraph graph0 { subgraph cluster_graph0 { n0 [label="1",shape=circle;fontsize=10,widht=0.4,height=0.4;fixedsize=true]; a0 [label="a"]; b0 [label="b"]; c0 [label="c"]; d0 [label="d"]; // edge [style=invis]; // n0 -> a0; edge [style=solid,dir=forward,color=green]; a0 -> b0 -> c0 -> d0; } subgraph cluster_graph1 { n1 [label="2",shape=circle;fontsize=10,widht=0.4,height=0.4;fixedsize=true]; a1 [label="a"]; b1 [label="b"]; c1 [label="c"]; d1 [label="d"]; edge [style=dashed,dir=none,color=green]; a1 -> b1 -> c1 -> d1; edge [style=solid,dir=forward,color=red]; d1 -> c1 -> b1; } subgraph cluster_graph2 { n2 [label="3",shape=circle;fontsize=10,widht=0.4,height=0.4;fixedsize=true]; a2 [label="a"]; b2 [label="b"]; c2 [label="c"]; d2 [label="d"]; e2 [label="e"]; f2 [label="f"]; edge [style=dashed,dir=none,color=green]; a2 -> b2 -> c2 -> d2; edge [style=dashed,dir=none,color=red]; d2 -> c2 -> b2; edge [style=solid,dir=forward,color=green]; b2 -> e2 -> f2; } subgraph cluster_graph3 { n3 [label="4",shape=circle;fontsize=10,widht=0.4,height=0.4;fixedsize=true]; a3 [label="a"]; b3 [label="b"]; c3 [label="c"]; d3 [label="d"]; e3 [label="e"]; f3 [label="f"]; edge [style=dashed,dir=none,color=green]; a3 -> b3 -> c3 -> d3; edge [style=dashed,dir=none,color=red]; d3 -> c3 -> b3; edge [style=dashed,dir=none,color=green]; b3 -> e3 -> f3; edge [style=solid,dir=forward,color=red]; f3 -> e3 -> b3; edge [style=solid,dir=forward,color=green]; b3 -> c3 -> d3; } }

12.3.3. Emacs Undo Tree

The Emacs: Undo Tree package realizes the previously described tree structure removing the recursion from branches. It offers a visual interface (C-x u) for easy navigation and fancy display of diffs .

C-/ undo-tree-undo
C-_ undo-tree-undo
C-? undo-tree-redo
C-x u undo-tree-visualize

12.4. Dynamic Abbreviation Expansion

M-/ = Alt+Shift+7

Start typing a word, e.g. dy, then press M-/ repeatedly. All open buffers (not just project files) are searched for a matching expansion:

dynamic
dylan
dyl
dylan-console
dylan-repl
dylanlid
dylan-lid
dy

This is extremely useful for using long identifiers in programs:

VERY_LONG_IDENTIFIERS_WHICH_NOBODY_WANTS_TO_TYPE = "value"

...

VE RY_LONG_IDENTIFIERS_WHICH_NOBODY_WANTS_TO_TYPE

Eclipse only has a very limited functionality for mainly strongly typed, object oriented languages:

object. <popup>

12.5. Key Sequences

Not sure about Vi.

It seems possible to define key sequences in Eclipse: Eclipse - Bindings.

12.6. Extensions

Vi has a macro language.

Eclipse extensions are realized via Java plugins. The extension points can then be assigned to key sequences. In order to create a plugin, an entire Eclipse Java package must to be created and all kinds of non-evident manual actions have to be executed. EASE makes it better with Rhino (Javascript) and Jython integration. Python is supposedly fully integrated since 2017 (not verfied, not investigated). See also section 7.7.1, Integrated Development Environment.

The equivalent of a “package” in Emacs is just a simple file (conventionally with the extension .el (but not necessarily)).

Let’s put it in ~/.emacs.d as ~/.emacs.d/my-file.el. The file contains an interactive function, suitable for assignment to a key sequence:

(defun my-func (arg)
 "Help".
 (interactive "sText: ")
 (insert (concat "//" arg "//"))
 )

To “install” this “package”, add the following code to your .emacs file:

(load-file "~/.emacs.d/my-file.el")

To assign the function my-func() to a key sequence, add the following to your .emacs file:

(global-set-key "C-c uet" 'my-func)

You can also put this in my-file.el for auto-installation of the key sequence shortcut :).

That’s it folks!

12.7. Useful packages

12.7.1. Table editing

Emacs comes with table.el, which allows editing ASCII tables in a WYSIWYG manner.

To recognize tables in a document, enter M-x table-recognize RET. Besides the Table menu there are shortcuts accessible inside table cells with the prefix C-c C-c. C-c C-c C-h inside a table cell show the key bindings.

|:todo:| vi: tables ?? |:todo:| eclipse: tables ??

12.8. Symbol tags

vi supports colon-delimited tags: :tag: (I just don’t know how)

For emacs a generalized tagging, tag navigation and tag search package is available.

M-h set here tag to here.

C-h m shows mode help. In help buffer move to section about symbol-tag minor-mode.

C-h k M-<down> shows help for key bound to next-symbol-tag()

C-h b shows current key bindings. M-x occur RET -symbol-tag RET in buffer *Help* shows keys for symbol tag movement.