there's a lot of noise about super awesome features of Emacs. Be it org-mode, Gnus or C-x M-c butterfly. I've used Emacs for years, so no need to convince me.
What I personally found is that nobody talks about...actually editing text. You know that
Emacs is a nice OS but it lacks an decent editor.
joke? I didn't really get it until I grokked Vim.
Now, I wrote my thesis using Emacs as my text editor, so my heart is somehow still attached to it. I'm also super envious about org-mode. So I wondered whether there maybe actually are features I've been missing all the time?
I'm going to give you a few examples I use all the time:
o
/O
opens a new line above/below the current and puts me into insert mode no matter at which position my cursor is.ci'
deletes the contents of current/following '-string and puts me into insert mode.dat
deletes the current HTML tag. cit
would delete the contents and put me into insert mode. cstt
would let me edit the tag (eg make a <span>
into a <div>
)cs([
changes the surrounding "(" and ")" into "[" and "]".dai
would delete the current indented block, \\ai
would comment it out (\\ is an extension).Are there some super secret shortcuts but easily accessible shortcuts for stuff like this in Emacs? Sublime Text 2 has a few "expand selection" functions that go a similar way albeit not that precise--but still it's very useful.
P.S. Please don't bring up any vi emulation, just don't.
P.P.S. Also for god's sake, no Emacs vs. Vim vs. Whatever warfare, I beg you.
Since no one has said so directly, I will.
The reason emacs lacks a "decent editor" is because a large part of the point of emacs is to allow you to make the ideal editor for yourself. This is not a trivial undertaking, and there are many things that other people have written and enough people have found useful to be included in the standard distributions of it.
It's not meant to be used at the default settings, really. Really. It's not meant to be a piece of software that you poke and prod at and tweak a bit here and there so much as an editor that you can tear apart the behavior of to make into whatever you want it to be.
So, yes, yes there is either an existing equivalent of $feature
from $editor
, or assuming no one has written one yet you can be safe in the knowledge that you can implement it.
Look for this wiki page. It have a lot and lot of tricks. Most of them I found(suddenly) for myself before reading, but this article worth reading.
Try C-h k
every C-<key> M-<key>
. Something like M-c, M-l, M-u
proves useful for me, M-z
for zap-to-char
. Platinum answer would be "learn to use i-search". C-w, C-M-y, M-r
are super-useful while in i-search mode.
I don't know any packages, which helps me for editing something, that surround my point. One day I wrote one for myself, but it proved useless. If I will mind write something again, first thing I'll do - think, what should I write. What about their behavior? Shold it be N separate commands for every type of brackets, or one, but smart? How should it work? Kill for keyring use? (Discussions are welcome).
For ~lisp, I use sexp editing commands.
There is something I wrote for myself.
(defun cm-fast-step-upward () "Step 3 lines up, recenteres the screen." (interactive) (forward-line -3) (recenter)) (defun cm-fast-step-downward () "Step 3 lines down, recenteres the screen." (interactive) (forward-line 3) (recenter)) (defun cm-find-any-bracket-forward() "Search for \"_}_]_'_>_)_end forward" (interactive) (re-search-forward "[\"}'>)]\\|\\(end\\)\\|\\]")) (defun cm-find-any-bracket-backward() "Search for \"_{_[_'_<_(_begin forward" (interactive) (re-search-backward "[\"{'<(]\\|\\(begin\\)\\|\\[")) (defun cm-find-nonspace-backward() "Search for non tab, space, newline symbol backward." (interactive) (if (and (search-backward-regexp "[ ]" (point-min) t) (search-backward-regexp "[^ ]" (point-min) t)) (forward-char) (goto-char (point-min)))) (defun cm-find-nonspace-forward() "Search for non tab, space, newline symbol backward." (interactive) (if (and (search-forward-regexp "[ ]" (point-max) t) (search-forward-regexp "[^ ]" (point-max) t)) (backward-char) (goto-char (point-max)))) (defun cm-backward-delete-word(&optional arg) "DELETE word before cursor. Warning, this word cannot be yanked." (interactive "p") (let ((beg (point))) (backward-word arg) (delete-region beg (point))) ) (defun cm-delete-word(&optional arg) "DELETE word after cursor. Warning, this word cannot be yanked." (interactive "p") (let ((beg (point))) (forward-word arg) (delete-region beg (point))) ) (defun cm-delete-line(&optional arg) "DELETE line after cursor. Warning, this line cannot be yanked." (interactive "P") (if (equal arg '-) (setq arg -1)) (let ((beg (point))) (if arg (forward-line arg) (goto-char (point-at-eol))) (if (= beg (point)) (delete-char 1 nil) (delete-region beg (point))))) (defun cm-reverse-region (&optional arg) "Reverse current region, like this: \"a(bc) d\" -> \"d )cb(a\"." (interactive "P") (let ((reversed (apply 'string (reverse (string-to-list (buffer-substring-no-properties (region-beginning) (region-end))))))) (delete-region (region-beginning) (region-end)) (insert reversed))) (provide 'cmmove)
I never shared(should I?) this thing before, you are welcome to leave comments.
Default bindings use hyper-key
(global-set-key [?\H-f] 'cm-find-nonspace-forward) (global-set-key [?\H-b] 'cm-find-nonspace-backward) (global-set-key [?\H-\]] 'cm-find-any-bracket-forward) (global-set-key [?\H-\[] 'cm-find-any-bracket-backward) (global-set-key [?\H-p] 'cm-fast-step-upward) (global-set-key [?\H-n] 'cm-fast-step-downward) (global-set-key (kbd "H-t") 'cm-reverse-region)
I wish also to find out, which behavior do you like for this commands. If they fail to find something, should they message or throw error?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With