Lutz Donnerhacke hat sehr gut beschrieben, wie man als Privatblogger mit der neuen EU Datenschutzverordnung umgehen muss. Ich habe mir meine Seite also äquivalent genauer angeschaut und festgestellt, dass ich - wie im Impressum bereits beschrieben - keine IP-Adressen speichere und Email-Adressen optional sind und diese wiederum auch NUR wenn man kommentieren möchte.
Da ich in letzter Zeit aber ohnehin kaum noch zum Posten komme und schon seit langer Zeit keine Kommentare mehr gepostet worden sind (Spammer wurden recht wirksam von meinen Abwehrmaßnahmen ferngehalten, falls jemand den Django Code haben möchte: einfach bei mir melden) - habe ich beschlossen, dass ich das Feature auch einfach ausschalten kann.
Gesagt, getan. Kommentare sind ab sofort abgeschaltet, vorhandene Kommentare und die Daten der Kommentierer habe ich alle gelöscht. Zack und aus. Somit speichere ich überhaupt keine personenbezogenen Daten mehr, die ich gemäß EU-DSGVO dokumentieren müsste.
Meine Datenschutzerklärung im Impressum habe ich entsprechend angepasst.
Sometime you might want to know which key was pressed last in a lisp function. I came up with this little function for this purpose:
(defun last-key () "Return the last key pressed." (car (reverse (append (recent-keys) nil))))
I use emacs for more than 20 years now. I love it, I am addicted, I can't even do anything productive without it. However, there was one problem left: the *scratch* buffer. This is a non-file buffer, which always exists always in emacs. By default it has emacs-lisp-mode enabled and you can use it to hack short elisp sexps for testing. In fact I use it for exactly this purpose.
But sometimes I hate it as well! I get a phone call and need to take a note quickly, *scratch* is already open, so I use this. But the mode doesn't really fit. So I switch to text-mode and then enter the notes. I did it this way almost since day one of my emacs usage.
A couple of months ago I came up with a "solution", I just create a *text* buffer on startup with text-mode already enabled in my .emacs. But I still need to switch to it everytime I need it. Still too annoying!
So now, here's my final solution, which tries to fix this mess once and for all: autoscratch.
This major mode is really simple. Basically it consits of an alist with instructions on how to automatically switch the *scratch* buffer mode. Enter an "(" and it switches to emacs-lisp-mode, enter "*" and it switches to org-mode, enter some letter a-z, and it switches to text-mode. You get the idea.
It also solves another problem I (and many other users according to google) have: once I set the *scratch* buffer mode to, say, *text-mode* with some text in there, I don't have an elisp *scratch* buffer left anymore. I'd need another one, but how to create a second *scratch* buffer? Obviously you'll need to rename the current text-mode buffer first and then create a new empty buffer. The emacs wiki contains lots of suggestions for this kind of solution.
No more of this! Autoscratch can just "fork" the buffer, if enabled (set autoscratch-fork-after-trigger to t which is the default). Here's how it works: type a "(" into the empty autoscratch-enabled *scratch* buffer. Autoscratch renames this buffer to *emacs-lisp-scratch*, enables emacs-lisp-mode and creates a new *scratch* buffer in the background. So, if you need some *scratch* space, it'll be there for you waiting bravely for input.
Here's the default trigger list telling autoscratch how to switch modes:
'(("[(;]" . (emacs-lisp-mode)) ("#" . (autoscratch-select '(("perl" . (cperl-mode)) ("ruby" . (ruby-mode)) ("python" . (python-mode)) ("conf" . (conf-unix-mode)) ("shell" . (shell-script-mode))))) ("[-a-zA-Z0-9]" . (text-mode)) ("/" . (c-mode)) ("*" . (progn (insert " ") (org-mode))) ("." . (fundamental-mode)))
Now if you configure autoscratch like this:
(require 'autoscratch-mode) (setq initial-major-mode 'autoscratch-mode) (setq initial-scratch-message "") (setq inhibit-startup-screen t)
then emacs will start with an empty *scratch* buffer as always, but with autoscratch mode enabled. Type in a "(" and emacs-lisp-mode will be started, the *scratch* buffer will be renamed and a new *scratch* created in the background. Or, type in a "#" and you'll be asked what to switch (the autoscratch-select function does this). You can configure almost anything here.
Oh, and just in case you need to manually create a new scratch buffer, just execute "M-x autoscratch-buffer".
You can complete this scratch buffer setup with the great persistent-scratch.el mode. Here's my config for it:
(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)
With this setup, scratch buffers will be saved on exit and restored on startup, so you never loose any cool snippet or note you have in a scratch buffer.
There was an issue with autoscratch in combination with magit, the original scratch buffer has the same problem as well. The buffer did not alter the default-directory variable. It is buffer-local and inherits the contents of the same global variable, if set to something. So, if you have some file open in a buffer and start a new autoscratch buffer from there, default-directory of this buffer will then be set to the directory of the file visited in the buffer which was last active. Now, if you close all files, except the scratch buffer, and start magit-status AND if the directory is inside of a git repo, then magit will open this repo instead of asking you which repo to open. This is not the behavior I expect from a scratch buffer, so I modified autoscratch-mode to reset the default-directory (if enabled) to $HOME.
On FreeBSD (and possibly others) the csh is the default login shell for root or default users. I always try to avoid it and use bash. However, sometimes it's not possible or dangerous to install bash (inside a jail for example).
So I decided to check if it is possible to configure csh in a way to make it less annoying. I read the docs, tried many different options and here is the result.
That's not much but helps digging around a system using csh. With this config you'll get:
- completion similar to bash
- right/lift jumping by words using CTRL-left and CTRL-right
- CTRL-up goto beginning of line, CTRL-down goto end of line
- history search using CTRL-R
- some sensible aliases
- a meaningful prompt
# sensible defaults for CSH alias h history 25 alias j jobs -l alias la ls -a alias lf ls -FA alias ll ls -lA alias l ls -laF alias lt ls -ltr alias md mkdir -p alias .. cd .. alias ... cd ../.. alias .... cd ../../../ alias vi nvi alias vim nvi # A righteous umask
umask 22 # environment config
set path = (/sbin /bin /usr/sbin /usr/bin /usr/local/sbin /usr/local/bin $HOME/bin) setenv EDITOR vi setenv PAGER more setenv BLOCKSIZE K # if interactive, configure further
if ($?prompt) then # interactive prompt
set prompt = "%N@%m:%~ %# " set promptchars = "%#" # history config
set history = 5000 set savehist = 5000 # complete case-insensitive
set complete = enhanced # print possible completions if more than 1 match
set autolist = ambiguous # enable filename completion
set filec # shut up
set nobeep # enable redirect protections
set noclobber # forbid rm *
set rmstar # mail?
set mail = (/var/mail/$USER) # convenience bindkeys, similar to emacs or inputrc
bindkey "^[^[[D" backward-word # ALT-RIGHT
bindkey "^[^[[C" forward-word # ALT-UP + HOME
bindkey "^[^[[A" beginning-of-line # ALT-DOWN + POS1
bindkey "^[^[[B" end-of-line # CTRL-R (like bash), then type
bindkey "^R" i-search-back # SHIFT-TAB cycles through possible completions, let go if good
bindkey "^[[Z" complete-word-fwd endif
From time to time I end up with raw HTML content in an emacs buffer and want to know how it looks or just want to read it properly. Until now either I opened firefox to read that file or I opened it with eww-open-file. The problem is, that sometimes there is no file, the HTML buffer is just the output of some generator or something. In such cases I needed to save the buffer as a file and then re-open it with EWW. Very annoying.
With this simple function the nightmare is over. I just use the EWW internal render function to do the job. That way I can view any HTML in emacs without even saving it to disk.
(require 'eww) (defun eww-render-current-buffer () "Render HTML in the current buffer with EWW" (interactive) (beginning-of-buffer) (eww-display-html 'utf8 (buffer-name))) (global-set-key (kbd "<C-c C-e C-w C-w>") 'eww-render-current-buffer)
Now when I'm inside a HTML buffer, I can just render it and take a look with EWW. Very handy!
Finlay is seit Dezember 2016 bei uns. Er kommt aus einer Tötungsstation im Ausland. Wir trainieren viel, Schmusen viel und sind happy mit ihm. Hier ein paar erste Bilder:
So gut muss man es haben (June 12, 2017, 9:42 a.m.)
[Tags: finlay ] [Album: ]
Ein Küschen für die (grosse!) Dame (June 12, 2017, 9:42 a.m.)
[Tags: finlay ] [Album: ]
Materail needed: Paper (I suggest photo paper which is thicker), scissors. Build instructions: trim the paper and fold it appropreately. Done. Now you can plase the token on your desk an read the numbers without taking your hands off the keyboard. Relief!
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
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)
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"))
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 (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))