Emacs: Mark, Copy and Yank Things

In a previous post I described how I copy various things at point in emacs to make my daily live easier. Meanwhile the code grew larger and larger and in the end went too large to maintain it in my emacs config.

So, I descided to put it into its own module: mark-copy-yank-things-mode. As always you can find the mode on github.

There are a couple of new features now: I created a copy-comment-block function which is able to copy comment blocks even if they are on the right side of some code. Here's a demo gif:

Also, there is now support for email addresses, ip addresses and urls. The mode provides prefix keys mappings, so, it's very easy to change the key mapping for the various functions just by modifying the prefix key.

Here's a lis of the current default key bindings provided by the mode:

COPY commands (keymap: mcyt-copy-map):

C-c c w      mcyt-copy-word 
C-c c q      mcyt-copy-quote 
C-c c k      mcyt-copy-parens 
C-c c l      mcyt-copy-line 
C-c c p      mcyt-copy-paragraph 
C-c c f      mcyt-copy-defun 
C-c c u      mcyt-copy-url 
C-c c e      mcyt-copy-email 
C-c c c      mcyt-copy-comment-block 
C-c c a      mcyt-copy-buffer 
C-c c i      mcyt-copy-ip 
C-c c s      mcyt-copy-sexp

COPY & YANK commands (keymap: mcyt-yank-map):

C-c c y y    mcyt-copy-and-yank-line
C-c c y l    mcyt-copy-and-yank-line
C-c c y p    mcyt-copy-and-yank-paragraph
C-c c y f    mcyt-copy-and-yank-defun
C-c c y a    mcyt-copy-and-yank-buffer
C-c c y w    mcyt-copy-and-yank-word
C-c c y i    mcyt-copy-and-yank-ip
C-c c y c    mcyt-copy-and-yank-comment

MARK commands (keymap: mcyt-mark-map):

C-c c a a    mcyt-mark-buffer 
C-c c a w    mcyt-mark-word 
C-c c a f    mcyt-mark-defun 
C-c c a p    mcyt-mark-paragraph 
C-c c a l    mcyt-mark-line 
C-c c a u    mcyt-mark-url 
C-c c a e    mcyt-mark-email 
C-c c a s    mcyt-mark-sexp 
C-c c a c    mcyt-mark-comment-block 
C-c c a i    mcyt-mark-ip 

Update 2017-03-28:

From time to time I stumble upon a very annoying emacs behavior: I copy some text and want to insert it into multiple positions somewhere else. However, I need to delete something on those positions before yanking. Now, this deleted stuff will be added to the kill-ring and appears first, when I execute yank the next time. So, I need to cycle through the kill-ring with M-y to reach the text I really want to yank. And everytime this text moves further away. So, this is what I type in those situations:

C-<backspace>
C-y
[..]
C-<backspace>
C-y
M-y
[..]
C-<backspace>
C-y
M-y
M-y
[..]
C-<backspace>
C-y
M-y
M-y
M-y
[..]
C-<backspace>
C-y
M-y
M-y
M-y
M-y
[..]

You see, this is very annoying. Here's how I fixed this: I just added a defadvice to my copying code of the above module, which puts the copied text into a emacs text register. And I created a new key binding to access this text register: C-v. I do not use this in emacs for cursor movement (its original binding) anyway and its the default PASTE key binding on some OS'es and applications - so I'm already somewhat used to it. Now I can always yank the last copied text and it doesn't matter how many items I added to the kill-ring since copying.

Here's the code:

(advice-add
  'mcyt--copy-thing :after
     '(lambda (&rest args)
        (with-temp-buffer
          (yank)
          (copy-to-register 'c (point-min) (point-max)))))

(defun my-insert-c-register ()
  (interactive)
  (insert-register 'c))

(global-set-key (kbd "C-v") 'my-insert-c-register)

23 March 2017 | #emacs

 

Portable Emacs Eshell Aliases

I maintain one emacs config file (.emacs) for all environments and systems whereever I use emacs. From time to time I use eShell but aliases were differing from system to system. The reason was, that they were stored in a separate file (~/.emacs.d/eshell/aliases) which I do not re-distribute.

So, my solution was to maintain eshell aliases inside my .emacs file. Here are my current alias definitions:

;; actual aliases
(+alias 'l      '(ls -laF))
(+alias 'll     '(ls -l))
(+alias 'la     '(ls -a))
(+alias 'lt     '(ls -ltr $*))
(+alias '..     '(cd ..))
(+alias '...    '(cd ../..))
(+alias '....   '(cd ../../..))
(+alias '.....  '(cd ../../../..))
(+alias 'md     '(mkdir -p))
(+alias 'emacs  '(find-file $1))
(+alias 'less   '(find-file-read-only $1))

As you can see, I use a pretty handy function +alias to create them and I use symbols, not strings which looks cleaner. For this to work, I use the following function:

(setq eshell-command-aliases-list ())

(defun +alias (al cmd)
  "handy wrapper function to convert alias symbols to alias
strings to avoid writing 4 quotes per alias. AL is a single-word
symbol naming the alias, CMD is a list symbol describing the
command."
(add-to-list 'eshell-command-aliases-list (list (symbol-name al) (mapconcat 'symbol-name cmd " "))))

So, first the aliases list will be cleared, just in case there's some aliases file left in the filesystem (which I ignore from now on). The function +alias then converts the given symbols to strings and adds them to the alias list.

I could of course use strings directly but that's too much quotes to type and looks confusing. Just for completeness, here's how the aliases list looks like after the above conversion:

(("less" "find-file-read-only-other-window $1")
 ("emacs" "find-file-other-window $1")
 ("md" "mkdir -p")
 ("....." "cd ../../../..")
 ("...." "cd ../../..")
 ("..." "cd ../..")
 (".." "cd ..")
 ("lt" "ls -ltr $*")
 ("la" "ls -a")
 ("ll" "ls -l")
 ("l" "ls -laF"))

13 March 2017 | #emacs

 

Emacs: comfortable macro recording

A couple of weeks ago I discovered elmacro mode, which is exactly what I was searching for: it turns unreadable recorded emacs macros into editable emacs lisp code. I LOVE it.

However, both the default emacs macro interface as well as the elmacro interface were not comfortable enough to me. So, I came up with this rather long solution for my macro management:

If I want to record a macro, I press F6. Then I do whatever I'd like to record and when I'm done, I press F6 again. That's it. The code below takes care of all the horrible details: while recording a macro a red indicator will be shown in my mode line. The macro will be saved to disk. Another function with the same name with -repeat appended will be saved as well. Both will be evaluated so that I can use them immediately. The -repeat version allows me to run the macro repeatedly with an interactive menu. When I press a it will be repeated til EOF, when I press ENTER it will be executed once (which can be repeated, hence the name), when I press e I can enter another macro name (with completion) and when I press q the menu will be quit. The same function will be called when I press CTRL-F6, it will present the mentioned menu, so that I can also just execute the last recorded macro.

;; always enable emacro mode
 
(require 'elmacro) (elmacro-mode) ;; var must be global so it can be shared across functions
 
(setq my-macro-name "last-macro") ;; ignore some certain events
 
(add-to-list 'elmacro-unwanted-commands-regexps "^(mouse.*)$") (add-to-list 'elmacro-unwanted-commands-regexps "^(my-start-or-stop-macro)$") ;; called when saving a macro
 
(defun my-get-macro-name() "Ask for a macro name, check for duplicates. If the given name is already
defined, ask again (and again until unique). If a buffer with the given name
exists, kill it (that is, the buffer is there but has not been saved or evaluated
yet). Return the name as string."
(interactive) (let ((done nil) (name nil) (mbuf nil) (err "")) (while (not done) (setq name (read-string (format "%s - enter macro name (last-macro): " err) nil nil "last-macro")) (if (fboundp (intern name)) (setq err (format "macro '%s is already defined" name)) (setq mbuf (format "* elmacro - %s *" name)) (if (get-buffer mbuf) (with-current-buffer mbuf (kill-buffer mbuf))) (setq done t))) name)) ;; interactive macro prompt with completion
 
(defun my-get-exec-macro-name() "Ask for a macro name to be executed" (interactive) (let ((macros ()) (N 1) (S nil) (T "")) (dolist (entry (cdr (assoc my-macro-file load-history ))) (setq S (cdr entry)) (setq T (symbol-name S)) (push (list T N) macros) (setq N (1+ N))) (completing-read "enter macro name: " macros nil t nil))) ;; the heart of my elmacro stuff: starts macro recording or
;; stops it if emacs is already recording. This way I can
;;
use 1 keybinding for start+stop
(defun my-start-or-stop-macro() "start macro or stop if started" (interactive) (if (eq defining-kbd-macro nil) (progn (elmacro-clear-command-history) (start-kbd-macro nil) (message "Recording macro. Finish with <shift-F6> ...")) (progn (call-interactively 'end-kbd-macro) (setq my-macro-name (my-get-macro-name)) (elmacro-show-last-macro my-macro-name) (message "Recording done. Execute with <C-F6>, save or <C-x C-e> buffer...")))) ;; better than the default function
(defun my-exec-last-macro(&optional ARG) "execute last macro (or ARG, if given) repeatedly after every <ret>, abort with
C-g or q, and repeat until EOF after pressing a. If macro defun is known
(i.e. because you evaluated the elmacro buffer containing the generated
defun), it will be executed. Otherwise the last kbd-macro will be executed."
(interactive) (let ((melm-count 0) (melm-all nil) (melm-abort nil) (melm-beg (eobp)) (melm-code (or ARG my-macro-name)))
 (if (eobp)
(if (yes-or-no-p "(point) is at end of buffer. Jump to top?") (goto-char (point-min)))) (while (and (not melm-abort) (not (eobp))) (when (not melm-all) (message (concat (format "Executing last macro '%s (%d). Keys:\n" melm-code melm-count) "<enter> repeat once\n" "a repeat until EOF\n" "e enter macro name to execute\n" "<C-g> or q abort ..\n ")) (setq K (read-event)) (cond ((or (eq K 'return) (eq K 'C-f6)) t) ((equal (char-to-string K) "q") (setq melm-abort t)) ((equal (char-to-string K) "a") (message "Repeating until EOF")(setq melm-all t)) ((equal (char-to-string K) "e") (setq my-macro-name (my-get-exec-macro-name))) (t (setq melm-abort t)))) (if (not melm-abort) (progn (if (fboundp (intern melm-code)) (call-interactively (intern melm-code)) (call-interactively 'call-last-kbd-macro)) (setq melm-count (1+ melm-count))))) (if (and (eq melm-count 0) (eq (point) (point-max))) (message "(point) is at end of buffer, aborted") (message (format "executed '%s %d times" melm-code melm-count))))) ;; I use my own macro file, my-lisp is defined somewhere else
(setq my-macro-file (concat my-lisp "/macros.el")) ;; load if it exists
(if (file-exists-p my-macro-file) (load-file my-macro-file)) ;; store the macro defun generated by elmacro-mode to disk
 
(defun my-macro-store() "store current macro to emacs config" (interactive) (copy-region-as-kill (point-min) (point-max)) (if (not (get-buffer "macros.el")) (find-file my-macro-file)) (with-current-buffer "macros.el" (goto-char (point-max)) (newline) (insert ";;") (newline) (insert (format ";; elmacro added on %s" (current-time-string))) (newline) (yank) (newline) (save-buffer)) (switch-to-buffer nil) (delete-window)) ;; add a repeating variant of the generated function,
;; evaluate and store both of them to disk
(defun my-macro-gen-repeater-and-save() "generate repeater and save the defun's Runs when (point)
is at 0,0 of generated defun."
(next-line) (goto-char (point-max)) (newline) (insert (format "(defun %s-repeat()\n" my-macro-name)) (insert " (interactive)\n") (insert (format " (my-exec-last-macro \"%s\"))\n" my-macro-name)) (newline) (eval-buffer) (my-macro-store)) ;; so, always evaluate generated macro code, store it to disk and
;; close the temp buffer
(advice-add 'elmacro-show-defun :after '(lambda (&rest args) (my-macro-gen-repeater-and-save))) ;; workflow: shift-F6 ... do things ... shift-F6, enter a name, new
;; buffer with macro defun appears. C-x C-e evals it. C-F6 (repeatedly)
;; executes it.
(global-set-key (kbd "<f6>") 'my-start-or-stop-macro) (global-set-key (kbd "<C-f6>") 'my-exec-last-macro) ;; face used to indicate ongoing macro recording on the mode line
(defface rec-face '((t (:background "red" :foreground "white" :weight bold))) "Flag macro recording in mode-line" :group 'my-mode-line-faces) ;; custom modeline including recording marker
(setq-default mode-line-format (list "%e" mode-line-front-space mode-line-mule-info mode-line-modified mode-line-remote " " mode-line-buffer-identification " " mode-line-position " (%m) " '(:eval (propertize (if (eq defining-kbd-macro t) "[REC]") 'face 'rec-face)) mode-line-end-spaces))

06 March 2017 | #emacs

 

Perl Moo Throwable Example

While working on a project with Moo (the first time for me) I discovered Try::Tiny. It's a great little helper and I highly recommend it. However, on my quest to make better error handling in Perl I thought it would be a good idea to have some kind of exception system.

Turns out, this already exists. In fact it is quite simple: die() accepts a reference as parameter, which could very well be an object. A couple of modules on CPAN make use of this, one of the simplest with the fewest dependencies is Throwable.

Since I could not find a good example of how to use it correctly (which I understood), I'm going to post such an example here for anyone who might be interested.

So, you need to have Moo and Throwable installed first. I'm doing these kind of experiments with perbrew, which I recommend as well! Here's my "Exception" class. It's a Moo role with two attributes (type and msg) and a class method e().

package Ex;
use Moo;
with 'Throwable';

has type => (is=>'ro');
has msg  => (is=>'ro');

sub e {
  if (ref($_) eq 'Ex') {
    return $_;
  } else {
    chomp; return Ex->new(msg => $_, type=>0);
  }
}

This Exception class will act as our wrapper to throw exceptions or convert old school perl die()'s into exceptions.

Here is a simple Moo class without any attributes which implements two methods X::Nix::tu() and X::Nix::ta(). Both of them just die. The method tu() throws an exception of type Ex - our exception class from above comes into use here. The ta() method on the other hand just dies with a good old croak() call.

package X::Nix;
use Carp;
use Ex;
use Moo; sub tu { Ex->throw({type => 1, msg => 'dont die while root'}); } sub ta { croak "death by disruptor"; }

Now let's take a look at our main script, which uses the X::Nix class and tries to catch both exceptions:

package main;
use Try::Tiny;
use X::Nix;

my $x = X::Nix->new();

try {
  $x->tu;
} catch {
  printf "died with %d and said: <%s>\n",
    Ex::e->type, Ex::e->msg;
};

try {
  $x->ta;
} catch {
  printf "died with %d and said: <%s>\n",
    Ex::e->type, Ex::e->msg;
};

It calls both methods and tries to catch them. Note how it calls Ex::e->type, though: Try::Tiny puts the exception object/message into $_. The class method Ex::e() uses $_ directly, therefore we are able to leave it in our catch{} code. This is the same thing as Ex::e($_)->type. Here's the output:

died with 1 and said: <dont die while root>
died with 0 and said: <death by disruptor at role.pl line 49.>

So, as you can see, with the help of our Ex::e() class method we can handle real exceptions and old school die()'s the same way, wo don't need to distinguish between the two. This way you can use foreign perl modules which use croak() and die() and catch those errors as if they were exceptions.

22 November 2016 | #source

 

Komische Wolken ├╝ber Fehmarn

Hab ich noch nie gesehen, Streifen quer über den ganzen Himmel:

2016-09-27 - Streifen Panorama 2:

2016-09-27 - Streifen Panorama 1:

27 September 2016 | #draussengewesen