# -*- mode: org; coding: utf-8; -*- # Source: https://github.com/novoid/dot-emacs # License: This file is licensed under the GPL v3. #+TODO: ACTIVE | DISABLED #+STARTUP: indent This is the GNU/Emacs config file of Karl Voit. This file is named =config.org=. My =init.el= got some nifty Elisp code that converts/tangles (only) the Elisp blocks into the =config.el=. And [[http://karl-voit.at/2017/06/03/emacs-org][here I explained how this is done]]. This generated file is interpreted by my GNU/Emacs on startup. Note that all Elisp blocks part of a =DISABLED= heading or which are marked with =:tangle no= won't be tangled to the =config.el= file. Unfortunately, within *the Org-mode rendering of GitHub, you won't see the =DISABLED= keyword nor the =:tangle no= parameter* of the babel blocks. Please get the Org-mode file and open it in your Emacs directly. Originally, I found this process on [[https://archive.org/search.php?query=http%3A%2F%2Fwww.holgerschurig.de%2Fen%2Femacs-init-tangle%2F][this web page]]. However, I adapted its code and write additional features. Links that start with =id:= won't work for you because they link to my personal Org-mode files. * Some tasks I plan to do with my =config.org=: - [ ] FIXXME: think of merging the default dir =.emacs.d/quelpa/= with =.emacs.d/contrib/= - [ ] FIXXME: migrate existing GitHub projects to quelpa - [ ] FIXXME: check why Python "auto-complete mode" is disabled in my config - [ ] FIXXME: check why Python > Ropemacs (for refactoring) is disabled in my config - [ ] FIXXME: add a table to each package with its history in my config: | 2020-01-13 | installed because of X | | 2020-01-15 | disabled because issue Y | | 2020-01-19 | enabled again after fixing with Z | * What Solution I Am Using for Which I Consider My Main Use-Cases Corresponding to my general blog article [[https://karl-voit.at/apps-I-am-using/][What App am I Using for What and How?]] I maintain this brief overview of my most important workflows for Emacs and what package solution I am using for it. If you want to learn more about my workflows, I recommend reading and following my [[https://karl-voit.at/2019/09/25/using-orgmode/][Blog Series: Using Org Mode Features (UOMF)]]. If you want to read how my ~init.el~ is auto-generated from this Org mode file, read [[http://karl-voit.at/2017/06/03/emacs-org][this article]]. I do not maintain links to the sections below since this would be a very fragile task anyway considering the way GitHub links work for now. Therefore: if you are interested in details on a certain workflow, please do search for corresponding keywords. There are seldom multiple search hits except for separate key binding definitions or hydras. | *Workflow* | *Solution* | *Notes* | |-------------------------------------+----------------------------------------------------+----------------------------------------------------------------| | Switching to things | ~my-switch-to-thing~ | buffers, recent-files, bookmarks, eyebrowse slots, directories | | Installing software packages | ~use-package~ with packages and git repositories | | | "Window management" | ~eyebrowse~ with a decent ~hydra-buffers~ | top feature | | Remembering bindings; cheatcheat | a ~hydra~ on ~F1~ for each major mode; ~which-key~ | top feature | | Naked and full-screen Emacs | ~my-toggle-naked-emacs()~ | unclutter screen | | Getting rid of scrollbar | ~nyan-mode~ | Get more horizontal screen space | | Reducing clutter in mode line | ~smart-mode-line~, ~mode-icons~ | | | Filter Org files | sparse trees | | | Focus on Org sub-hierarchy | customized ~org-tree-to-indirect-buffer~ | | | Enhanced search/selection usability | ~swiper~, ~counsel~, ~helm~, ~helm-org-rifle~ | | | Switching buffers | ~ibuffer~ | | | Desktop notifications | ~alert~ | | | Inserting date/time-stamps | ~my-insert-timestamp()~, ~my-insert-datestamp()~, | | | Inserting characters | ~char-menu~, ~M-x insert-char~ | | | Copying region to Org property | ~my-org-region-to-property()~ | very handy for org-contacts | | Org to PDF export | normal Org mode export via LaTeX (not pandoc) | | | Passwords | ~org-crypt~ on Org mode headings | | | Coding python | ~elpy~, ~flycheck~ | | | Coding: Highlighting lines/words | ~bm~, ~highlight-symbol~ | | | Coding: Folding/unfolding | ~yafolding~ | | | Versioning files | ~magit~ | | | Snippet management | ~yankpad~ with ~yasnippet~ | [[https://karl-voit.at/2016/12/18/org-depend/][advanced workflows]] | | Spell checking | ~flyspell~ with ~aspell~ | | | Formatting paragraphs | ~my-fill-or-unfill()~ | | | Formatting headings | ~my-title-capitalization()~ | | | File management | ~dired~ with some very cool extensions | I'm still getting used to | | PDF reading | ~pdf-tools~ | I'm still getting used to | | PDF annotating | ~pdf-tools~ | I'm still getting used to | | Record screencasts | ~gif-screencast~ and non-emacs methods | | What I'm not using at the moment: - projectile or other source code project management tools - vim bindings (evil, ...) - configuration frameworks - reading and managing emails: I'd love to use ~notmuch~ but [[https://karl-voit.at/2020/01/13/thunderbird-notmuch/][I can't]] You might want to take a look at the next section where I list my most important generic hydras in contrast to the ~F1~-mapped mode hydras. * bug-hunter #+BEGIN_SRC emacs-lisp ;;; -*- lexical-binding: t; -*- ;; remove comment characters when using but-hunter to bi-sect this file: ; ------------------------------------------------------------------------------------------- ; (package-initialize) ; (defvar my-init-el-start-time (current-time) "Time when init.el was started") ; (setq my-user-emacs-directory "~/.emacs.d/") ; (add-to-list 'load-path (concat my-user-emacs-directory "contrib/org-mode/contrib/lisp")) ; (add-to-list 'load-path (concat my-user-emacs-directory "contrib/org-mode/lisp")) ; (require 'org) ; ------------------------------------------------------------------------------------------- #+END_SRC * DISABLED literate test 1 Testing the noweb principle as shown on this page: https://www.hhyu.org/posts/literate_config/ - [2021-02-05 Fri 11:09] issue: my (very fast) custom function to tangle does not handle noweb syntax and Holger's page (the original author of the tangle function) doesn't exist any more. #+BEGIN_SRC emacs-lisp :tangle no :noweb-ref nowebtest ;; nowebtest3 (setq nowebtest3 t) #+END_SRC #+BEGIN_SRC emacs-lisp :noweb yes ;; nowebtest1 <> #+END_SRC * mitigating CVE-2025-1244 ... for Emacs <30.1: https://emacsninja.com/posts/cve-2025-1244-from-emacs-url-handler-to-rce.html #+BEGIN_SRC emacs-lisp (defun my-man-interactive-check (_) (when (not (called-interactively-p 'interactive)) (error "Called from URL handler, aborting..."))) (when (or (< emacs-major-version 30) (and (= emacs-major-version 30) (< emacs-minor-version 1) )) (with-eval-after-load 'man (advice-add 'man :before #'my-man-interactive-check)) (message "Mitigating CVE-2025-1244 for Emacs < 30.1") ) #+END_SRC * Function keys Here are my function-key-mappings that are included in most hydra help screens: #+BEGIN_SRC emacs-lisp (setq my-f-key-settings (concat "⇧ Git ←change→ ┃ yp-exp yp-map ┃ Project minimap Beginner Bright " (propertize " F1 F2 F3 F4 ┃ F5 F6 F7 F8 ┃ F9 F10 F11 F12 " 'face '(:foreground "green")) " Hydra Windows run ★ ┃ spell (←) error → fix ┃ Search Menu maximize naked ")) #+END_SRC * General settings :PROPERTIES: :CREATED: [2024-06-12 Wed 18:51] :END: Here, I do set some very general settings for my GNU/Emacs. profiling: #+BEGIN_SRC emacs-lisp (defvar my-config-el-start-time (current-time) "Time when config.el was started") ;(profiler-start 'cpu);; test startup performance - create report with M-x profiler-report ;; from http://ergoemacs.org/emacs/elisp_datetime.html (setq my-config-el-start-time-iso (concat (format-time-string "%Y-%m-%dT%T") ((lambda (x) (concat (substring x 0 3) ":" (substring x 3 5))) (format-time-string "%z")))) #+END_SRC 2011-04-20: turn off backup files #+BEGIN_SRC emacs-lisp (setq-default backup-inhibited t) #+END_SRC set start of week to Monday (not sunday) http://sunsite.univie.ac.at/textbooks/emacs/emacs_33.html #+BEGIN_SRC emacs-lisp (setq-default calendar-week-start-day 1) #+END_SRC omit usage of TAB for =C-x r o=: indent-tabs-mode #+BEGIN_SRC emacs-lisp (setq-default indent-tabs-mode nil) #+END_SRC append and update time-stamps for =Time-stamp: <>= in headers: #+BEGIN_SRC emacs-lisp (add-hook 'write-file-hooks 'time-stamp) #+END_SRC set warning of opening large files to 100MB #+BEGIN_SRC emacs-lisp (setq-default large-file-warning-threshold 100000000) #+END_SRC do not add double space after periods [[http://www.reddit.com/r/emacs/comments/2l5gtz/real_sentence_in_emacs/][Real sentence in Emacs : emacs]]: #+BEGIN_SRC emacs-lisp (setq-default sentence-end-double-space nil) #+END_SRC Be careful, not using double spaces does come with a downside: https://www.reddit.com/r/emacs/comments/14oxhkv/sentences/ https://www.emacswiki.org/emacs/TruncateLines =M-x toggle-truncate-lines= #+BEGIN_SRC emacs-lisp (setq-default truncate-lines t) #+END_SRC [[http://stackoverflow.com/questions/7577614/emacs-truncate-lines-in-all-buffers][elisp - Emacs truncate lines in all buffers - Stack Overflow]] #+BEGIN_SRC emacs-lisp (setq-default global-visual-line-mode t) #+END_SRC inhibit the startup screen #+BEGIN_SRC emacs-lisp (setq inhibit-startup-screen t) #+END_SRC English time-stamps in Org-mode (instead of localized German ones): - http://lists.gnu.org/archive/html/emacs-orgmode/2011-10/msg01046.html - «system locale to use for formatting time values (e.g., timestamps in Org mode files)» - "en_US.utf8" did not work for the weekday in the agenda! #+BEGIN_SRC emacs-lisp ;; (setq system-time-locale "C") ;; disabled 2025-10-14 because I got German weekday abbrevations in date/timestamps (setq system-time-locale "en_US.UTF-8") #+END_SRC On [2025-10-11 Sat] =(getenv "LC_TIME")= did result in "de_AT.UTF-8" which caused German style date/timestamps. In order to override any wrong system settings, I define it here: #+BEGIN_SRC emacs-lisp (setenv "LANG" "en_US.UTF-8") (setenv "LC_TIME" "en_US.UTF-8") #+END_SRC [[http://pragmaticemacs.com/emacs/adaptive-cursor-width/][Adaptive cursor width | Pragmatic Emacs]]: make cursor the width of the character it is under; i.e. full width of a TAB: #+BEGIN_SRC emacs-lisp (setq x-stretch-cursor t) #+END_SRC Remember the position of a buffer and go to that position when re-opening the file: (2018-07-26 disabled because it is not always a good thing to do) #+BEGIN_SRC emacs-lisp :tangle no (setq-default save-place t) (setq save-place-file (expand-file-name ".places" user-emacs-directory)) (save-place-mode 1) #+END_SRC #+BEGIN_SRC emacs-lisp (load-file (concat my-user-emacs-directory "private.el")) #+END_SRC Tip via [[https://irreal.org/blog/?p=9027][irreal]]. I share the same rationale: I never answer anything different to "y". So I disabled it: #+BEGIN_SRC emacs-lisp (setq confirm-kill-processes nil) #+END_SRC Moves the mouse cursor out of the way when the text cursor seems to crash: [[https://www.gnu.org/software/emacs/manual/html_node/emacs/Mouse-Avoidance.html][documentation]]. Possible values: banish, exile, jump, animate, proteus #+BEGIN_SRC emacs-lisp (when (display-mouse-p) (setq mouse-avoidance-mode "animate")) #+END_SRC A tip from [[https://karthinks.com/software/batteries-included-with-emacs/][this wonderful blog article:]] map scroll-lock mode to the corresponding scroll-lock key: #+BEGIN_SRC emacs-lisp (global-set-key (kbd "") 'scroll-lock-mode) #+END_SRC To avoid "Error saving to X clipboard manager." as well as endless loop on exiting (see [[https://emacs.stackexchange.com/questions/34488/saving-clipboard-takes-forever-on-quit][this]]): #+BEGIN_SRC emacs-lisp (setq x-select-enable-clipboard-manager nil) #+END_SRC Turn off header when printing with =M-x ps-print-buffer-with-faces= and format according to [[https://www.emacswiki.org/emacs/PsPrint][this page]]: #+BEGIN_SRC emacs-lisp (setq ps-paper-type 'a4 ps-font-size 9.0 ps-print-header nil ps-landscape-mode nil ps-number-of-columns 1) #+END_SRC Open file system read-only files as read-only in Emacs as well: (via [[https://www.wisdomandwonder.com/programming/13521/automatically-open-read-only-files-in-view-mode?utm_source=rss&utm_medium=rss&utm_campaign=automatically-open-read-only-files-in-view-mode][this article]]) #+BEGIN_SRC emacs-lisp (setq view-read-only t) #+END_SRC I'm not using abbrev mode and get annoyed by its questions: #+BEGIN_SRC emacs-lisp ;(save-abbrevs 'silently) ;; Silently save abbrevs: http://ergoemacs.org/emacs/emacs_abbrev_mode_tutorial.html (setq save-abbrevs nil) ;; not saving abbrevs (setq-default abbrev-mode nil) #+END_SRC 2022-01-16: larger columns for profiler reports: 2024-11-28: DISABLED because of: =profiler-report-header-line-format: Wrong type argument: listp, " "= on =profiler-report= → format may have changed. New format seems OK and does not truncate columns too much → leave it. #+BEGIN_SRC emacs-lisp :tangle no (setq profiler-report-cpu-line-format '((70 left) (14 right ((9 right) (5 right))))) #+END_SRC 2022-01-16: This has a positive impact on the performance as long as you would not need it for consistency warnings. Re-enable it if something is fishy and you want the self-check functionality again. #+BEGIN_SRC emacs-lisp (setq org-element--cache-self-verify nil) #+END_SRC For issue, see id:2022-01-06-Emacs-Warning--emacs--Unrecognized-key-i-when-invoking-my-title-capitalization. - [2022-01-06 Thu] via Message-ID: <875yqxhx0i.fsf@localhost>: avoiding the warning: : Warning (emacs): Unrecognized key: _i_ : Warning (emacs): org-element--cache: Unregistered buffer modifications detected. Resetting. #+BEGIN_SRC emacs-lisp (setq org-element--cache-diagnostics-modifications nil) #+END_SRC ------- Introduced with Emacs 28.1: id:2022-04-06-Emacs-28-dot-1 #+BEGIN_SRC emacs-lisp (when (version< emacs-version "28.1") (setq completions-detailed t) (setq use-short-answers t) (setq next-error-message-highlight t) (setq mode-line-compact t) ) #+END_SRC ** DISABLED Guru mode #+BEGIN_SRC emacs-lisp (defun disable-guru-mode () (guru-mode -1) ) (add-hook 'prelude-prog-mode-hook 'disable-guru-mode t) #+END_SRC ** Package Configure the package manager(s) of my GNU/Emacs. *** MELPA http://www.reddit.com/r/emacs/comments/2u1bml/gnu_or_melpa_version_of_yasnippet_both_in_mx/ MELPA packages are usually built automatically from a project's repository; the GNU repository has stable releases that are explicitly submitted to it. =package-user-dir= holds the directory where Emacs package manager installs its local copies of the packages: #+BEGIN_SRC emacs-lisp (setq gnutls-algorithm-priority "NORMAL:-VERS-TLS1.3") ;; from https://irreal.org/blog/?p=8243 (setq package-user-dir (concat my-user-emacs-directory "elpa")) (require 'package) ;;2022-10-17 is called in init.el before;; (package-initialize) ;;2019-12-07;; ;;(add-to-list 'package-archives '("marmalade" . "https://marmalade-repo.org/packages/")) ;;2019-12-07;; ;;OLD:(add-to-list 'package-archives '("melpa" . "http://melpa.milkbox.net/packages/"));; moved to stable.melpa.org https://www.reddit.com/r/emacs/comments/4zqbz0/whats_up_with_melpa_stable/ ;;2019-12-07;; (add-to-list 'package-archives '("melpa" . "http://stable.melpa.org/packages/")) ;;2019-12-07;; ;;unstable;; (add-to-list 'package-archives '("melpa" . "http://melpa.org/packages/")) ;;2019-12-07;; ;;2019-12-07;; ;; 2017-03-26: from https://www.reddit.com/r/emacs/comments/61jsvy/melpa_stopped_working_over_https_for_me_any_ideas/ ;;2019-12-07;; (add-to-list 'package-archives '("org" . "http://orgmode.org/elpa/")) ;;2019-12-07;; (add-to-list 'package-archives '("gnu" . "http://elpa.gnu.org/packages/")) ;; 2019-12-07: severe issues with old package versions brings me to remove old config and start with this from docu: (setq package-archives '( ("melpa" . "https://melpa.org/packages/") ("gnu" . "https://elpa.gnu.org/packages/") )) #+END_SRC - 2020-04-16: [[https://blog.abrochard.com/melpa-stats.html][Some statistics about MELPA]] *** Elpy Add [[https://github.com/jorgenschaefer/elpy][elpy repository]]: #+BEGIN_SRC emacs-lisp (add-to-list 'package-archives '("elpy" . "https://jorgenschaefer.github.io/packages/")) #+END_SRC *** fix certificate issue Bugfixing: 2016-01-26: fix certificate issue: "gnutls.c: [0] (Emacs) fatal error: The TLS connection was non-properly terminated." - https://github.com/nicferrier/elmarmalade/issues/55#issuecomment-166271364 - 2016-11-05: got «(void-function gnutls-available-p)» on floyd (after org upgrade) #+BEGIN_SRC emacs-lisp :tangle no (if (fboundp 'gnutls-available-p) (fmakunbound 'gnutls-available-p)) (setq tls-program '("gnutls-cli --tofu -p %p %h") imap-ssl-program '("gnutls-cli --tofu -p %p %s") smtpmail-stream-type 'starttls starttls-extra-arguments '("--tofu") ) #+END_SRC *** Initialize misc packages #+BEGIN_SRC emacs-lisp ;; 2015-11-25: https://github.com/jwiegley/use-package ;(when (string-equal system-type "windows-nt") ; (add-to-list 'load-path (concat package-user-dir "/use-package-20190405.2047")) ;) (eval-when-compile (require 'use-package)) ;(require 'diminish) (require 'bind-key) ;; http://www.lunaryorn.com/2015/01/06/my-emacs-configuration-with-use-package.html (setq package-enable-at-startup nil) (unless (package-installed-p 'use-package) (package-refresh-contents) (package-install 'use-package)) (use-package f :ensure t ) (use-package ivy :ensure t :config ;; 2019-12-07: this is found in https://github.com/abo-abo/swiper/blob/master/ivy.el (Version: 0.13.0) ;; but not in the elpa package version 0.13.0 on my disk. Don't know why/how, just adding it as a workaround: (defcustom ivy-use-group-face-if-no-groups t "If t, and the expression has no subgroups, highlight whole match as a group. It will then use the second face (first of the \"group\" faces) of `ivy-minibuffer-faces'. Otherwise, always use the first face in this case." :type 'boolean) ) (use-package ht :ensure t ) #+END_SRC *** DISABLED [[https://framagit.org/steckerhalter/quelpa][Quelpa]] DISABLED because of: #+BEGIN_EXAMPLE Debugger entered--Lisp error: (file-error "Cannot open load file" "No such file or directory" "use-package-core") require(use-package-core) eval-buffer(# nil "/home/vk/.emacs.d/elpa/quelpa-use-package-20190210.1938/quelpa-use-package.el" nil t) ; Reading at buffer position 1691 load-with-code-conversion("/home/vk/.emacs.d/elpa/quelpa-use-package-20190210.1938/quelpa-use-package.el" "/home/vk/.emacs.d/elpa/quelpa-use-package-20190210.1938/quelpa-use-package.el" nil t) require(quelpa-use-package) eval-buffer(# nil "/home/vk/.emacs.d/config.el" nil t) ; Reading at buffer position 4033 load-with-code-conversion("/home/vk/.emacs.d/config.el" "/home/vk/.emacs.d/config.el" nil nil) load("/home/vk/.emacs.d/config.el" nil nil t) load-file("~/.emacs.d/config.el") #+END_EXAMPLE ... including auto-update: #+BEGIN_SRC emacs-lisp (if (require 'quelpa nil t) (quelpa-self-upgrade) (with-temp-buffer (url-insert-file-contents "https://framagit.org/steckerhalter/quelpa/raw/master/bootstrap.el") (eval-buffer))) #+END_SRC [[https://framagit.org/steckerhalter/quelpa-use-package][quelpa-use-package]]: #+BEGIN_SRC emacs-lisp (quelpa '(quelpa-use-package :fetcher git :url "https://framagit.org/steckerhalter/quelpa-use-package.git")) (require 'quelpa-use-package) #+END_SRC After that it is possible to call use-package with the :quelpa keyword: EXAMPLES: #+BEGIN_SRC emacs-lisp :tangle no ;; installs abc-mode with quelpa (use-package abc-mode :quelpa) ;; does the same (`t' is optional) (use-package abc-mode :quelpa t) ;; again... (if the package would have another name) (use-package abc-mode :quelpa abc-mode) ;; passes upgrade parameter to quelpa (use-package abc-mode :quelpa (:upgrade t)) ;; uses the given recipe (use-package abc-mode :quelpa (abc-mode :fetcher github :repo "mkjunker/abc-mode")) ;; recipe with plist arguments (use-package abc-mode :quelpa ((abc-mode :fetcher github :repo "mkjunker/abc-mode") :upgrade t)) #+END_SRC Read https://github.com/alphapapa/unpackaged.el#upgrade-a-quelpa-use-package-forms-package for upgrading quelpa packages. ** Upper/lower-case Many times, I do need to uppercase or lowercase a word. Those commands offer me quick shortcuts to do so. See: id:2014-03-04-M-l-subword #+BEGIN_SRC emacs-lisp (global-set-key [M-l] 'downcase-word) (global-set-key [M-u] 'upcase-word) (global-set-key [M-c] 'capitalize-word) #+END_SRC ** yes-or-no-p: prefer short answers (y/n) «True #Emacs Knights are lazy and hate typing yes/no - they prefer y/n instead. Use this (fset 'yes-or-no-p 'y-or-n-p) in your config.» ... from: http://twitter.com/emacs_knight/status/128339316417101825 <2025-11-13 Thu> [[https://irreal.org/blog/?p=13405][• Short Yes/No Answers | Irreal]] #+BEGIN_QUOTE Starting in Emacs 28, the variable =use-short-answers= was introduced. When non =nil= it causes =yes-or-no-p= to call =y-or-n-p= to ask the question instead of following its normal path. #+END_QUOTE #+BEGIN_SRC emacs-lisp ; (fset 'yes-or-no-p 'y-or-n-p) (setq use-short-answers t) #+END_SRC ** Deletes duplicate entries of the history of the minibuffer «If the value of this variable is t, that means when adding a new history element, all previous identical elements are deleted.» from: http://www.gnu.org/software/emacs/manual/html_node/elisp/Minibuffer-History.html #+BEGIN_SRC emacs-lisp (setq history-delete-duplicates t) #+END_SRC This is also necessary to avoid duplicate entries when searching with =helm= on Emacs 27 as [[https://github.com/emacs-helm/helm/issues/2291][shown here]]. ** Pasting with the mouse without moving the point «middle-clicking pastes at the current location instead of moving it» from: http://sachachua.com/blog/2017/04/emacs-pasting-with-the-mouse-without-moving-the-point-mouse-yank-at-point/ #+BEGIN_SRC emacs-lisp (setq mouse-yank-at-point t) #+END_SRC ** Un-setting some keys Here, I do unset some keys I don't use so that they are not in my way when I accidentially use them: #+BEGIN_SRC emacs-lisp ;; \C-v scroll up ;; \C-t transpose-chars (dolist (key '("\C-v" "\C-t")) (global-unset-key key)) #+END_SRC ** delete-trailing-whitespace before saving I don't see any use of trailing whitespace. Previously, I had a function to remove them mapped to =my-map SPC= but then I found out that adding this as a general =before-save-hook= does the job automatically: 2019-12-14: disabled because it consumed 20-40% of the time when saving large files. 22% on http://paste.grml.org/hidden/27a87675/ #+BEGIN_SRC emacs-lisp :tangle no ;;(bind-key (kbd "SPC") #'delete-trailing-whitespace my-map) ; (define-key org-mode-map (kbd "C-c C-, SPC") #'delete-trailing-whitespace);; workaround since line above doesn't work ;; 2016-02-06: https://www.reddit.com/r/emacs/comments/445w6s/whats_some_small_thing_in_your_dotemacs_that_you/ (add-hook 'before-save-hook 'delete-trailing-whitespace) #+END_SRC ** Maximize frame window Details: id:2016-03-27-maximize-window-init.el [2020-12-10 Thu] Good read: [[https://emacsredux.com/blog/2020/12/04/maximize-the-emacs-frame-on-startup/][Maximize the Emacs Frame on Startup | Emacs Redux]] #+BEGIN_SRC emacs-lisp (toggle-frame-maximized) #+END_SRC Alternative from: [[https://www.reddit.com/r/emacs/comments/9c0a4d/tip_setting_initial_frame_size_and_position/][Tip: Setting initial frame size and position]] #+BEGIN_SRC emacs-lisp :tangle no ;; Set initial frame size and position (defun my/set-initial-frame () (let* ((base-factor 0.70) (a-width (* (display-pixel-width) base-factor)) (a-height (* (display-pixel-height) base-factor)) (a-left (truncate (/ (- (display-pixel-width) a-width) 2))) (a-top (truncate (/ (- (display-pixel-height) a-height) 2)))) (set-frame-position (selected-frame) a-left a-top) (set-frame-size (selected-frame) (truncate a-width) (truncate a-height) t))) (setq frame-resize-pixelwise t) (my/set-initial-frame) #+END_SRC Also mentioned: #+BEGIN_QUOTE I believe this works both in windows and in character terminals: : (setq default-frame-alist '((left . 0) (width . 141) (fullscreen . fullheight))) (You might have to change 141 to something larger if you have a huge monitor.) #+END_QUOTE ** Window Management :PROPERTIES: :CREATED: [2018-07-23 Mon 11:27] :END: See hydra-buffers() near the end of this file for a nice summary. See [[https://github.com/karthink/popper][GitHub - karthink/popper: Emacs minor-mode to summon and dismiss buffers easily]] for defining pop-up buffers. *** my-vsplit-last-buffer() my-hsplit-last-buffer () This is using the last buffer for splitting windows instead of the current one: From [[https://github.com/mwfogleman/.emacs.d/blob/master/michael.org][this emacs config]] which stole it from [[https://github.com/sachac/.emacs.d/blob/gh-pages/Sacha.org#make-window-splitting-more-useful][Sacha]] and [[https://www.reddit.com/r/emacs/comments/25v0eo/you_emacs_tips_and_tricks/chldury][reddit]]: #+BEGIN_SRC emacs-lisp (defun my-vsplit-last-buffer () (interactive) (split-window-vertically) (other-window 1 nil) (switch-to-next-buffer)) (defun my-hsplit-last-buffer () (interactive) (split-window-horizontally) (other-window 1 nil) (switch-to-next-buffer)) (bind-key "C-x 2" 'my-vsplit-last-buffer) (bind-key "C-x 3" 'my-hsplit-last-buffer) #+END_SRC *** my-frame-is-landscape() my-frame-is-portrait() Following frame-width and frame-height values are returned when the Emacs frame (the thing which is called "window" on OS-level) is either higher or wider: #+BEGIN_SRC emacs-lisp :tangle no (frame-width) ;; portrait frame: 73; landscape frame: 190; quadratic frame: 47 (frame-height);; portrait frame: 56; landscape frame: 60 ; quadratic frame: 47 #+END_SRC In order to find out whether or not there is more space in the horizontal or in the vertical line, I divide the width by two. This is because characters (the measure returned by =(frame-width)= and =(frame-height)=) are higher than wide approximately by factor two as well: #+BEGIN_SRC emacs-lisp :tangle no (if (< (/ (frame-width) 2) (frame-height)) (message "portrait frame") (message "landscape frame") ) #+END_SRC So I define functions to check the frame aspect that return boolean values: #+BEGIN_SRC emacs-lisp (defun my-frame-is-landscape () "Return true if Emacs frame is landscape and not portrait mode" (< (/ (frame-width) 2) (frame-height)) ) ;; (if (my-frame-is-landscape) ;; (message "portrait frame") ;; (message "landscape frame") ;; ) (defun my-frame-is-portrait () "Return true if Emacs frame is portrait and not landscape mode" (not (my-frame-is-landscape)) ) (if (my-frame-is-portrait) (message "The frame is in landscape mode") (message "The frame is in portrait mode") ) #+END_SRC *** Default split direction according to frame aspect ratio On wide screens, I want my default split direction being side-by-side (vertical split). On tilted/high screens, the default split should be up/down (horizontal split). ([[https://stackoverflow.com/questions/7997590/how-to-change-the-default-split-screen-direction][Source]]) Note: this might be no good idea when you are not working with single/maximized windows like I prefer for now. The values of the thresholds on sting (30", landscape) before I started overwriting them here: : split-width-threshold ;; Its value is 9999; Original value was 160 : split-height-threshold ;; Its value is 80 #+BEGIN_SRC emacs-lisp (if (my-frame-is-landscape) (setq split-width-threshold nil);; for vertical split (setq split-width-threshold 1) ;; for horizontal split ) #+END_SRC ** bookmarks | 2021-06-05 | started to use bookmarks after watching [[https://www.youtube.com/watch?v=ajiEBK2swKo][this video]] | #+BEGIN_SRC emacs-lisp (setq bookmark-save-flag 1) ;; save bookmarks on every change (setq bookmark-default-file (concat my-user-emacs-directory "/var/bookmark-default.el")) ;; this was set somewhere else; I did not look how/why. I just set it here again to make it explicit. #+END_SRC ** modify keyboard-quit | 2025-06-09 | initial setup | - from: [[https://irreal.org/blog/?p=13032][• Improving Keyboard-quit | Irreal]] → [[https://emacsredux.com/blog/2025/06/01/let-s-make-keyboard-quit-smarter/][Let’s make keyboard-quit smarter | Emacs Redux]] #+BEGIN_SRC emacs-lisp ;; This executes C-g typed while Emacs is waiting for a command. ;; Quitting out of a program does not go through here; ;; that happens in the maybe_quit function at the C code level. (defun my-keyboard-quit () "Signal a `quit' condition. During execution of Lisp code, this character causes a quit directly. At top-level, as an editor command, this simply beeps." (interactive) ;; Avoid adding the region to the window selection. (setq saved-region-selection nil) (let (select-active-regions) (deactivate-mark)) (if (fboundp 'kmacro-keyboard-quit) (kmacro-keyboard-quit)) (when completion-in-region-mode (completion-in-region-mode -1)) ;; Force the next redisplay cycle to remove the "Def" indicator from ;; all the mode lines. (if defining-kbd-macro (force-mode-line-update t)) (setq defining-kbd-macro nil) (let ((debug-on-quit nil)) (signal 'quit nil))) (global-set-key [remap keyboard-quit] #'my-keyboard-quit) #+END_SRC * use-package and quelpa :PROPERTIES: :CREATED: [2018-07-02 Mon 11:09] :END: My setup is using John Wiegley's [[https://github.com/jwiegley/use-package][use-package]] for configuration and startup of external libraries. This has many advantages: flexibility, startup performance, readability. Bootstrap =use-package= is stolen from [[https://gitlab.com/emacsomancer/collaborative-writing-environment-emacs/-/blob/master/init.org][this file]]: #+BEGIN_SRC emacs-lisp (unless (package-installed-p 'use-package) (package-refresh-contents) (package-install 'use-package)) (eval-when-compile (require 'use-package)) (use-package use-package :ensure t ;;:pin MELPA :config (require 'use-package)) #+END_SRC Until 2020-06-30, I only used =use-package= and manually cloned git repositories I included with hard-coded path. The latter were seldomly updated (if ever). With [[https://github.com/quelpa/quelpa][quelpa]], there seems to be a much better way. #+BEGIN_SRC emacs-lisp (use-package quelpa :ensure t :config (setq quelpa-upgrade-interval 7);; upgrade all packages once a week according to https://github.com/quelpa/quelpa (add-hook #'after-init-hook #'quelpa-upgrade-all-maybe) ) #+END_SRC The =quelpa-use-package= package offers a more or less transparent bridge between sites like GitHub and the =use-package= features. #+BEGIN_SRC emacs-lisp (use-package quelpa-use-package :ensure t ) #+END_SRC ** Examples Here are some examples for future reference: A very simple example for installing a package via package management and ensure it is installed when Emacs launches: #+BEGIN_SRC emacs-lisp :tangle no (use-package dumb-jump :ensure t :defer 110 ) #+END_SRC An example of loading a /local/ package (not from Melpa or other package service): #+BEGIN_SRC emacs-lisp :tangle no (use-package define-word :if (my-system-type-is-gnu) :load-path (lambda () (expand-file-name (concat my-user-emacs-directory "contrib/mypackage/"))) :after org ) #+END_SRC Key binding example from [[https://github.com/jwiegley/use-package#key-binding][docu]]: #+BEGIN_SRC emacs-lisp :tangle no (use-package helm :bind (("M-x" . helm-M-x) ("M-" . helm-find-files) ([f10] . helm-buffers-list) ([S-f10] . helm-recentf))) #+END_SRC more binding examples: #+BEGIN_SRC emacs-lisp :tangle no :bind (:map my-map ("SPC" . yankpad-insert)) :bind (("M-f" . sp-forward-sexp) ("M-b" . sp-backward-sexp) ) OR: (bind-keys :map pdf-view-mode-map ("f9" . hydra-pdftools/body) ("" . pdf-view-scroll-down-or-next-page) ("g" . pdf-view-first-page) ("G" . pdf-view-last-page) ("l" . image-forward-hscroll) ("h" . image-backward-hscroll) ("j" . pdf-view-next-page) ("k" . pdf-view-previous-page) ("e" . pdf-view-goto-page) ("u" . pdf-view-revert-buffer) ("al" . pdf-annot-list-annotations) ("ad" . pdf-annot-delete) ("aa" . pdf-annot-attachment-dired) ("am" . pdf-annot-add-markup-annotation) ("at" . pdf-annot-add-text-annotation) ("y" . pdf-view-kill-ring-save) ("i" . pdf-misc-display-metadata) ("s" . pdf-occur) ("b" . pdf-view-set-slice-from-bounding-box) ("r" . pdf-view-reset-slice)) #+END_SRC ** Use of =:defer= =:defer= [[https://github.com/jwiegley/use-package#defer-now-accepts-an-optional-numeric-argument][also accepts an optional numeric argument]] which causes the package to be loaded after N seconds of idle time. From: https://www.gnu.org/software/emacs/manual/html_node/elisp/Idle-Timers.html #+BEGIN_QUOTE Emacs becomes /idle/ when it starts waiting for user input, and it remains idle until the user provides some input. #+END_QUOTE My GNU/Emacs 26 takes approximately 70s to start. This is very long but it includes all my many "autostart" activities that also cover visibility settings in opened Org mode files and my complex agenda. Therefore, my defer times start with 90s which is clearly after the startup. Ocurrences in =config.el= (without disabled or not tangled code): #+BEGIN_SRC sh :results output :exports both grep ":defer " ~/.emacs.d/config.el | # extract all occurrences of ":defer" from the tangled init file sed 's/;;.*//' | # remove emacs-lisp comments sed 's/ //g' | # remove all space characters to normalize strings sed 's/defer/defer /' | # add space character again only after ":defer" sort | # sort the resulting strings alphabetically uniq -c ; # uniq them and count their occurrences date # add the current time stamp in order to know how recent this output is #+END_SRC #+RESULTS: : 1 :defer 110 : 21 :defer 110 : 6 :defer 120 : 11 :defer 90 : Tue Apr 16 10:31:52 WEDT 2019 * no-littering | 2023-01-08 | moved to elpa version | From: - [[http://manuel-uberti.github.io/programming/2017/06/17/nolittering/][Manuel Uberti: Keeping your .emacs.d clean]] - https://github.com/tarsius/no-littering It sets some default paths in order to separate automatically created files and directories. #+BEGIN_SRC emacs-lisp (use-package no-littering :ensure t ) (require 'no-littering) #+END_SRC * Logging :PROPERTIES: :CREATED: [2020-01-02 Thu 17:29] :END: ** host-specific log file: =my-log-hostspecific()= Here's the idea: on every Emacs startup, a file like =~/.emacs.d/var/log/HOSTNAME.txt= is overwritten with the current time-stamp and =emacs-version=. The path scheme follows the =no-littering= package I'm using as well. While loading miscellaneous packages, I might decide to append a version string. This way, I get a list of files from all of my hosts sharing the same Emacs configuration. Each of these files hold the time of the last startup and the version strings of interesting packages. This simplifies generating bug reports and finding issues with version conflicts. Here is an example file content for one host: #+BEGIN_EXAMPLE Started on 2019-04-16T14:35:04+02:00 emacs-version 26.0.90 cygwin-mount-version 1.4.8 yas--version 0.11.0 org-version 9.1.6 plantuml-mode-version 1.2.3 magit-version 2.10.3 #+END_EXAMPLE So how is it done? Here we go. Let's define the common file name, one per host: #+BEGIN_SRC emacs-lisp (setq my-var-log-hostname-file (concat no-littering-var-directory "log/host-" system-name ".txt")) #+END_SRC At Emacs startup, overwrite the file content and initializing it with the current time stamp: #+BEGIN_SRC emacs-lisp (write-region (concat "Started on " my-config-el-start-time-iso "\n") nil my-var-log-hostname-file) #+END_SRC Define the function that is called to append lines to the file: #+BEGIN_SRC emacs-lisp (defun my-log-hostspecific (mystring mycommand) "append a string and the result of a command to the my-var-log-hostname-file file" (interactive) (write-region (concat mystring " " mycommand "\n") nil my-var-log-hostname-file t) ) #+END_SRC And let's use this new function to log the version of the GNU/Emacs that is starting: #+BEGIN_SRC emacs-lisp (my-log-hostspecific "emacs-version" emacs-version) #+END_SRC ** general log file: =my-log-misc()= I'm using a central logging file for all kind of logging messages. I started with my agenda genreation performance. Where do I log to? #+BEGIN_SRC emacs-lisp (setq my-log-file (concat no-littering-var-directory "log/misc.log")) #+END_SRC How do I log? #+BEGIN_SRC emacs-lisp (defun my-log-misc (message) (interactive) (let ((current-timestamp (concat (format-time-string "%Y-%m-%dT%T") ((lambda (x) (concat (substring x 0 3) ":" (substring x 3 5))) (format-time-string "%z"))) )) (write-region (concat (format-message "%s %s: %s\n" current-timestamp system-name message)) nil my-log-file "append")) ) #+END_SRC Example: #+BEGIN_SRC emacs-lisp :tangle no (my-log "foo bar") #+END_SRC * my-load-local-el() Using this function, I am able to easily load lisp files within my Emacs config hierarchy. It contains minimal error handling for a missing file. from: http://www.zonix.de/html40/linux/emacsgnus.html #+BEGIN_SRC emacs-lisp (defun my-load-local-el (part) "load lisp file and warn if not found" (let ((fullname (concat my-user-emacs-directory part))) (if (file-exists-p fullname) (load fullname) (message (format "Loading %s (source)...failed" fullname))))) #+END_SRC * Server mode Start Emacs as a server process: new files can be visited via =emacsclient= (instead of parallel =emacs= instances). Therefore, I don't have to run multiple instances (which occupies RAM storage) and I am able to open new files instantly. #+BEGIN_SRC emacs-lisp (server-start) #+END_SRC * my-system-is-FOOBAR Emacs config switch depending on hostname or operating system: Idea found here: [[https://sigquit.wordpress.com/2008/09/28/single-dot-emacs-file/][Single dot emacs file and per-computer configuration | SIGQUIT]] This is so cool: with those functions, I am able to maintain one single Emacs configuration for /all/ of my hosts. If there is something I want to do or do not on a specific platform or host, those functions allow me to express my restrictions easily: #+BEGIN_SRC emacs-lisp ;; Get current system's name (defun my-insert-system-name() (interactive) "Get current system's name" (insert (format "%s" system-name)) ) ;; Get current system type (defun my-insert-system-type() (interactive) "Get current system type" (insert (format "%s" system-type)) ) ;; Check if system is Darwin/Mac OS X (defun my-system-type-is-darwin () "Return true if system is darwin-based (Mac OS X)" (string-equal system-type "darwin") ) ;; Check if system is Microsoft Windows (defun my-system-type-is-windows () "Return true if system is Windows-based (at least up to Win7)" (string-equal system-type "windows-nt") ) ;; Check if system is GNU/Linux (defun my-system-type-is-gnu () "Return true if system is GNU/Linux-based" (string-equal system-type "gnu/linux") ) #+END_SRC Here are host-specific functions which I should *not* use if possible because with them, I lose some generic approach: #+BEGIN_SRC emacs-lisp (defun my-system-is-floyd-or-sting () "Return true if the system we are running on is floyd or sting" (or (string-equal system-name "floyd") (string-equal system-name "floyd.lan") (string-equal system-name "sting") (string-equal system-name "sting.lan") ) ) (defun my-system-is-sting () "Return true if the system we are running on is sting" (or (string-equal system-name "sting") (string-equal system-name "sting.lan") ) ) (defun my-system-is-floyd () "Return true if the system we are running on is floyd" (or (string-equal system-name "floyd") (string-equal system-name "floyd.lan") ) ) (defun my-system-is-jackson () "Return true if the system we are running on is floyd" (or (string-equal system-name "jackson") ) ) (defun my-system-is-blanche () "Return true if the system we are running on is blanche" (or (string-equal system-name "blanche") (string-equal system-name "blanche.lan")) ) (defun my-system-is-karl-voit-at () "Return true if the system we are running on is karl-voit.at" (string-equal system-name "friends") ) (defun my-system-is-powerplantlinux () "Return true if the system we are running on is powerplant" (or (string-equal system-name "powerplant") (string-equal system-name "powerplant.lan") ) ) #+END_SRC * System-specific paths The system PATH variable provides access to executables. However, I do tend to use programs which are not part of the PATH variable of the operating system as well. Therefore, I do extend the Emacs variable =exec-path= (further down and following headings). http://www.emacswiki.org/emacs/MacOSTweaks#toc13 #+BEGIN_SRC emacs-lisp ;; setting path so that Emacs finds aspell and such (when (my-system-type-is-darwin) (setenv "PATH" (concat (getenv "PATH") ":/Users/vk/bin:/usr/local/texlive/2010/bin/x86_64-darwin:/opt/local/bin:/opt/local/sbin")) (setq exec-path (append exec-path '("/opt/local/bin" "/usr/local/texlive/2010/bin/x86_64-darwin" "/usr/local/teTeX/bin/powerpc-apple-darwin-current" ))) (add-to-list 'load-path "/opt/local/share/emacs/site-lisp") ;; 2011-04-20: allow typing of german umlauts in OS X by Alt-u followed by u,o,a,... (setq mac-option-modifier nil) (setq org-ditaa-jar-path "~/data/hosts/blanche/config/ditaa.jar") ;; setting path to color-theme-mode.el from MacPorts (add-to-list 'load-path "/opt/local/share/emacs/site-lisp/color-theme-6.6.0") ) #+END_SRC ditaa #+BEGIN_SRC emacs-lisp (when (my-system-type-is-gnu) (setq org-ditaa-jar-path "/usr/share/ditaa/ditaa.jar") ) #+END_SRC setting path so that Emacs finds aspell and such: #+BEGIN_SRC emacs-lisp (if (my-system-type-is-windows) ;;disabled;(setenv "PATH" ;;disabled; (concat (getenv "PATH") ;;disabled; ":/Users/vk/bin:/usr/local/texlive/2010/bin/x86_64-darwin:/opt/local/bin:/opt/local/sbin")) (setq exec-path (append exec-path '("C:/Program Files (x86)/Aspell/bin" "C:/ProgramData/chocolatey/bin" ;;disabled; "/usr/local/texlive/2010/bin/x86_64-darwin" ;;disabled; "/usr/local/teTeX/bin/powerpc-apple-darwin-current" ))) ;;disabled;(add-to-list 'load-path "/opt/local/share/emacs/site-lisp") ( ;; on all other systems: ) ) #+END_SRC Where my Org mode files reside. They are used all over this config and therefore, this has to be defined early: #+BEGIN_SRC emacs-lisp (cond ((string-equal system-name "GRZN17009") (setq my-org-files-path "c:/Users/karl.voit/org/")) ((string-equal system-name "Cosmo") (setq my-org-files-path "c:/Users/John/AppData/Roaming/org/") ) (t (setq my-org-files-path (concat (expand-file-name "~") "/org/"))) ) ;;(message (format "Set \"my-org-files-path\" to: %s" my-org-files-path)) #+END_SRC Setting the system-specific path for my-webarchive-tsfile-dir-path #+BEGIN_SRC emacs-lisp ;; different hosts do have the dir at different locations: (setq my-webarchive-tsfile-dir-path (cond ((my-system-is-sting) (concat (expand-file-name "~") "/archive/backup/sting/webarchive")) ((my-system-is-jackson) (concat (expand-file-name "~") "/Downloads/webarchive")) (t (concat (expand-file-name "~") "/Downloads/"));; fallback path (should NOT be used) )) #+END_SRC ** Emax64 settings | 2019-11-09 | settings according to the emax64 default =.emacs= file | | 2023-02-06 | disabled UTF-8 stuff because of [[https://www.reddit.com/r/emacs/comments/10uj5nn/comment/j7ccyai/?utm_source=reddit&utm_medium=web2x&context=3][this]] recommendation (don't fuck with UTF-8 settings) | #+BEGIN_SRC emacs-lisp (when (my-system-type-is-windows) ;; ;; Set repositories ;; (require 'package) ;; (setq-default ;; load-prefer-newer t ;; package-enable-at-startup nil) ;; (add-to-list 'package-archives '("melpa" . "http://melpa.org/packages/") t) ;; (add-to-list 'package-archives '("org" . "http://orgmode.org/elpa/") t) ;; (setq package-user-dir "~/emax/elpa") ;; (package-initialize) ;; ;; Install dependencies ;; (unless (and (package-installed-p 'delight) ;; (package-installed-p 'use-package)) ;; (package-refresh-contents) ;; (package-install 'delight t) ;; (package-install 'use-package t)) ;; (setq-default ;; use-package-always-defer t ;; use-package-always-ensure t) ;; ;; Use latest Org ;; (use-package org ;; ;;:pin org ;; :ensure org-plus-contrib) (defvar emax-root (concat (expand-file-name "~") "/emax")) (defvar emax-bin (concat emax-root "/bin")) (defvar emax-bin64 (concat emax-root "/bin64")) (defvar emax-mingw64 (concat emax-root "/mingw64/bin")) (defvar emax-lisp (concat emax-root "/lisp")) (setq exec-path (cons emax-bin exec-path)) (setenv "PATH" (concat emax-bin ";" (getenv "PATH"))) (setq exec-path (cons emax-bin64 exec-path)) (setenv "PATH" (concat emax-bin64 ";" (getenv "PATH"))) (setq exec-path (cons emax-mingw64 exec-path)) (setenv "PATH" (concat emax-mingw64 ";" (getenv "PATH"))) (setenv "PATH" (concat "C:\\msys64\\usr\\bin;C:\\msys64\\mingw64\\bin;" (getenv "PATH"))) (dolist (dir '("~/emax/" "~/emax/bin/" "~/emax/bin64/" "~/emax/mingw64/bin/" "~/emax/lisp/" "~/emax/elpa/" "~/bin/")) (add-to-list 'load-path dir)) ;;disabled;; (set-language-environment 'utf-8) ;;disabled;; (setq locale-coding-system 'utf-8) ;;disabled;; (set-default-coding-systems 'utf-8) ;;disabled;; (set-terminal-coding-system 'utf-8) ;;disabled;; (prefer-coding-system 'utf-8) ;; Tangle configuration (org-babel-load-file (expand-file-name "~/emax/emax.org" user-emacs-directory)) ;;(garbage-collect) ) #+END_SRC from emax.org: #+BEGIN_SRC emacs-lisp (when (my-system-type-is-windows) ; (setq-default ; (defvar mp/font-family "Consolas" "The font to use.") ; ) ;; Running Windows Powershell from within Emacs ; (setq explicit-shell-file-name "c:\\windows\\system32\\WindowsPowerShell\\v1.0\\powershell.exe") ; (setq explicit-powershell.exe-args '("-Command" "-" )) ; interactive, but no command prompt ; (autoload 'powershell "powershell" "Run powershell as a shell within emacs." t) ;; Changes made for Aspell ;; (setq-default ispell-program-name "~/emax/mingw64/bin/aspell.exe") (setq-default ispell-program-name "~/bin/aspell.cmd") (setq-default ispell-extra-args '("--sug-mode=ultra")) ;; (setq ispell-dictionary "en_US") ;; Set "DICTDIR" variable (setenv "DICTDIR" (concat emax-mingw64 "/lib/aspell-0.60/")) ;; Automatically enable flyspell-mode in text-mode ;;(require 'flyspell) ;;(add-hook 'text-mode-hook 'flyspell-mode) (setq text-mode-hook '(lambda() (flyspell-mode t) )) ;;(setq text-mode-hook '(lambda() ;; (flyspell-mode t))) ;;(dolist (hook '(text-mode-hook)) ;; (add-hook hook (lambda () (flyspell-mode 1)))) ;;(dolist (hook '(change-log-mode-hook log-edit-mode-hook)) ;; (add-hook hook (lambda () (flyspell-mode -1)))) ;;(setq flyspell-issue-message-flag nil) ;;(require 'auto-dictionary) ;;(add-hook 'flyspell-mode-hook (lambda () (auto-dictionary-mode 1))) (require 'ispell) ; (setq epg-gpg-home-directory "~/emax/mingw64/bin/") ; (setq epg-gpg-program "~/emax/mingw64/bin/gpg.exe") ; (setq epg-gpgconf-program "~/emax/mingw64/bin/gpgconf.exe") ; (pdf-tools-install :no-query) ) #+END_SRC * DISABLED Cygwin Paths (Windows) | 2023-01-08 | disabled since I'm not using Windows for years | As mentioned in the chapter of system-specific paths, I do use programs which are not part of the PATH variable of the operating system. Cygwin executables (in form of [[http://babun.github.io/][babun]]) are one example of this kind of programs. Links: - http://gregorygrubbs.com/emacs/10-tips-emacs-windows/ - id:2014-01-31-cygwin-emacs - http://www.emacswiki.org/emacs/RobertAdesamConfig #+BEGIN_SRC emacs-lisp (when (and (my-system-type-is-windows) (string-equal system-name "GRZN17009")) #+END_SRC Hard-coding the cygwin install path (for [[http://babun.github.io/][babun]]): - id:2016-04-22-magit-not-working-on-windows #+BEGIN_SRC emacs-lisp (setq cygwin-root-directory "c:/Users/karl.voit/.babun/cygwin/") #+END_SRC Check if Cygwin/babun inst found on the install path given: #+BEGIN_SRC emacs-lisp (if (file-directory-p cygwin-root-directory) (progn #+END_SRC OLD method of extending the path: #+BEGIN_SRC emacs-lisp :tangle no (setenv "PATH" (concat ;;"c:\\cygwin64\\usr\\local\\bin" ";" ;; Cygwin ;;"c:\\cygwin64\\bin" ";" ;; Cygwin "C:\\Users\\karl.voit\\.babun\\cygwin\\bin" ";" "C:\\Users\\karl.voit\\.babun\\cygwin\\usr\\local\\bin" ";" "C:\\Python36\\" ";" "C:\\Program\ Files\ \(x86\)\\Java\\jre1.8.0_144\\bin" ";" (getenv "PATH"))) #+END_SRC Extending the path: #+BEGIN_SRC emacs-lisp (setq exec-path (cons (concat cygwin-root-directory "bin/") exec-path)) ;; Babun (setq exec-path (cons (concat cygwin-root-directory "usr/local/bin/") exec-path)) ;; Babun (setq exec-path (cons "C:/Program Files (x86)/Java/jre1.8.0_144/bin" exec-path)) ;; Babun #+END_SRC Adding cygwin mounts: #+BEGIN_SRC emacs-lisp :tangle no (use-package cygwin-mount) (cygwin-mount-activate) #+END_SRC Adding cygwin bash shell #+BEGIN_SRC emacs-lisp ;;(setq shell-file-name "c:/cygwin64/bin/bash") ;; Cygwin (setq shell-file-name (concat cygwin-root-directory "bin/zsh")) ;; Babun ;;(setq shell-file-name (concat cygwin-root-directory "bin/bash")) ;; Babun (setenv "SHELL" shell-file-name) (setq explicit-shell-file-name shell-file-name) (setq ediff-shell shell-file-name) (setq explicit-shell-args '("--login" "-i")) (setq w32-quote-process-args ?\") #+END_SRC id:2015-11-02-tramp-windows-babel and Docu: [[help:tramp-methods]] #+BEGIN_SRC emacs-lisp (setq tramp-default-method "plink") #+END_SRC requires: setup-cygwin.el and cygwin-mount.el in the contrib dir: #+BEGIN_SRC emacs-lisp (add-to-list 'load-path (concat my-user-emacs-directory "contrib/")) (require 'setup-cygwin) #+END_SRC END of Cygwin/babun configuration #+BEGIN_SRC emacs-lisp ) (message "»»» I could not locate the cygwin path") ) #+END_SRC end of Cygwin config #+BEGIN_SRC emacs-lisp ;;(my-log-hostspecific "cygwin-mount-version" cygwin-mount-version) );; end of if-windows #+END_SRC ** Starting GNU/Emacs on Windows First, I create a batch file which starts the =emacs.exe= with optional Org-mode files as parameters: =C:\Users\Karl.Voit\bin\windows-start-orgmode.bat= #+BEGIN_EXAMPLE REM Here, invoke some syncronization mechanism like Unison: REM "C:\Program Files\bin\unison-2.40.102-gtk.exe" grmlvrs REM As of 2017, I switched from Unison to Syncthing "C:\Program Files\emacs-24.5-bin-i686-mingw32\bin\emacs.exe" REM Re-syncing after leaving Emacs: REM "C:\Program Files\bin\unison-2.40.102-gtk.exe" grmlvrs REM End #+END_EXAMPLE This batch file is included in a Visual Basic file. This way, I am able to start my GNU/Emacs using misc app-launcher solutions: batch files are not listed in typical app-launchers whereas VBS files work at least with my [[https://autohotkey.com/docs/Hotstrings.htm][Hotstrings]]: =C:\Users\Karl.Voit\bin\orgmode.vbs= or in Cygwin =/home/karl.voit/bin/orgmode.vbs= #+BEGIN_EXAMPLE 'HideBat.vbs CreateObject("Wscript.Shell").Run "C:\Users\Karl.Voit\bin\windows-start-orgmode.bat", 0, True #+END_EXAMPLE * Looking for binaries Some Emacs configuration snippets relate to external programs such as LaTeX. Instead of (a) blindly evaluating those snippets or (b) using per-host-configuration for them, I do prefer to check whether or not those programs are installed on the local host instead. This is just the sane way of doing those things. In detail, it gets a bit dirty for Windows, since there are some tools that are installed but not listed in the PATH environment =exec-path=. See below for some workarounds for that. ** my-binary-found(binaryname) =my-binary-found(binaryname)= returns the path where a binary executable can be found within the exec-path. It also checks certain operating system/binary combinations which aren't likely in the exec-path. #+BEGIN_SRC emacs-lisp (defun my-binary-found(binaryname) "Returns the path where a binary executable can be found. It also checks certain operating system/binary combinations which aren't likely in the exec path." (cond ((and (my-system-type-is-windows) (string= binaryname "firefox")) (when (file-exists-p "C:/Program Files/Mozilla Firefox/firefox.exe") (concat "C:/Program Files/Mozilla Firefox/firefox.exe") ) ) ((and (my-system-type-is-windows) (string= binaryname "python")) (when (file-exists-p "C:/Python27/python.exe") (concat "C:/Python27/python.exe") ) ) ((and (my-system-type-is-windows) (string= binaryname "outlook")) (when (file-exists-p "C:/Program Files/Microsoft Office/Office16/OUTLOOK.EXE") (concat "C:/Program Files/Microsoft Office/Office16/OUTLOOK.EXE") ) ) ;; this is the default check for all binaries which got no special handling above: (t (locate-file binaryname exec-path exec-suffixes 1)) )) #+END_SRC *Examples:* #+BEGIN_SRC emacs-lisp :tangle no (message (concat "pdflatex found on: " (my-binary-found "pdflatex"))) (if (my-binary-found "pdflatex") (message "LaTeX found") (message "LaTeX not found") ) #+END_SRC ** my-binary-not-found-list and my-eval-if-binary-or-warn() =my-eval-if-binary-or-warn (binaryname &optional warningtext)= checks if a binary can be found in the path via my-binary-found(). If not found, a warning message is printed which can be defined as an optional parameter as well. Additionally, the not found binaries are collected in the variable my-binary-not-found-list. #+BEGIN_SRC emacs-lisp (defvar my-binary-not-found-list nil "Holds a list of binaries which could not be found via my-eval-if-binary-or-warn()" ) (defun my-eval-if-binary-or-warn (binaryname &optional warningtext) "Checks if a binary can be found in the path via my-binary-found(). If not found, a warning message is printed which can be defined as an optional parameter as well. Additionally, the not found binaries are collected in the variable my-binary-not-found-list." (or warningtext (setq warningtext (concat "»»» I could not locate the PATH-binary for: " binaryname))) (let* ((binarypath (my-binary-found binaryname))) (if binarypath ;; binary was found in exec-path (concat binarypath) (progn ;; binary NOT found in exec-path: (message warningtext) (if my-binary-not-found-list (add-to-list 'my-binary-not-found-list binaryname) (setq my-binary-not-found-list (list binaryname)) ) )))) #+END_SRC Example usages: #+BEGIN_SRC emacs-lisp :tangle no (my-eval-if-binary-or-warn "yyy" "This is a warning text for yyy") (my-eval-if-binary-or-warn "xxx") (my-eval-if-binary-or-warn "xxx" "This is a warning text for xxx") (my-eval-if-binary-or-warn "zzz" "This is a warning text for xxx") (message "Binaries not found: %s" my-binary-not-found-list) #+END_SRC ** DISABLED Example output for different hosts This heading ist just for collecting example outputs: sting output: #+BEGIN_EXAMPLE pdflatexTeX binary: /usr/bin/pdflatex python binary: /usr/bin/python firefox binary: /usr/bin/firefox chrome binary: aspell binary: /usr/bin/aspell ispell binary: pandoc binary: /usr/bin/pandoc ditaa binary: /usr/bin/ditaa gnuplot binary: /usr/bin/gnuplot git binary: /usr/bin/git Outlook binary: grep binary: /bin/grep scss binary: /usr/bin/scss ag binary: /usr/bin/ag biber binary: /usr/bin/biber #+END_EXAMPLE Windows output: #+BEGIN_EXAMPLE pdflatex binary: c:/Program Files/MiKTeX_2.9/miktex/bin/pdflatex.exe python binary: ipython binary: firefox binary: chrome binary: aspell binary: ispell binary: pandoc binary: c:/Users/karl.voit/AppData/Local/Pandoc/pandoc.exe ditaa binary: gnuplot binary: git binary: Outlook binary: grep binary: scss binary: ag binary: biber binary: c:/Program Files/MiKTeX_2.9/miktex/bin/biber.exe #+END_EXAMPLE : Binaries not found in checks above: (ag scss grep Outlook git gnuplot ditaa ispell aspell chrome firefox ipython python) After moving system-specific paths above this checks: only aspell was found: : Binaries not found in checks above: (ag scss grep Outlook git gnuplot ditaa ispell chrome firefox ipython python) ... *but* on Windows, there are following things installed: - [ ] python - [ ] ipython - [ ] firefox - [ ] chrome - [ ] (a/i?)spell - [ ] Outlook - real path: "C:\Program Files (x86)\Microsoft Office\root\Office16\OUTLOOK.EXE" - also holds for OUTLOOK.EXE and OUTLOOK - =where outlook= is also unsuccessful :-( #+BEGIN_SRC emacs-lisp (message "★★★★★★★★★★") (message (concat "pdflatex binary: " (my-binary-found "pdflatex"))) (message (concat "python binary: " (my-binary-found "python"))) (message (concat "ipython binary: " (my-binary-found "ipython"))) (message (concat "firefox binary: " (my-binary-found "firefox"))) (message (concat "chrome binary: " (my-binary-found "chrome"))) (message (concat "aspell binary: " (my-binary-found "aspell"))) (message (concat "ispell binary: " (my-binary-found "ispell"))) (message (concat "pandoc binary: " (my-binary-found "pandoc"))) (message (concat "ditaa binary: " (my-binary-found "ditaa"))) (message (concat "gnuplot binary: " (my-binary-found "gnuplot"))) (message (concat "git binary: " (my-binary-found "git"))) (message (concat "Outlook binary: " (my-binary-found "Outlook"))) (message (concat "grep binary: " (my-binary-found "grep"))) (message (concat "scss binary: " (my-binary-found "scss"))) (message (concat "ag binary: " (my-binary-found "ag"))) (message (concat "biber binary: " (my-binary-found "biber"))) (message "★★★★★★★★★★") #+END_SRC ** Test queries Here, I do probe for some tools mostly because I want to test my code above. When I am using tool-specific settings below, I do add comment characters to disable the check at this stage: #+BEGIN_SRC emacs-lisp ;;(my-eval-if-binary-or-warn "pdflatex") ;;(my-eval-if-binary-or-warn "python") (my-eval-if-binary-or-warn "ipython") ;;(my-eval-if-binary-or-warn "firefox") (my-eval-if-binary-or-warn "chrome") ;;(my-eval-if-binary-or-warn "aspell") ;;(my-eval-if-binary-or-warn "pandoc") (my-eval-if-binary-or-warn "ditaa") ;;(my-eval-if-binary-or-warn "gnuplot") ;;(my-eval-if-binary-or-warn "git") ;;(my-eval-if-binary-or-warn "outlook") (my-eval-if-binary-or-warn "grep") ;;(my-eval-if-binary-or-warn "scss") (my-eval-if-binary-or-warn "ag") (my-eval-if-binary-or-warn "biber") #+END_SRC * System-specific browse-url-browser Here, I do hard-code my preferred browser that is used when I open URLs within Emacs: http://stackoverflow.com/questions/4506249/how-to-make-emacs-org-mode-open-links-to-sites-in-google-chrome #+BEGIN_SRC emacs-lisp (setq firefox-path (my-eval-if-binary-or-warn "firefox")) (setq librewolf-path (my-eval-if-binary-or-warn "librewolf")) (setq chrome-path (my-eval-if-binary-or-warn "google-chrome")) (cond ((my-system-type-is-darwin) (setq browse-url-browser-function 'browse-url-default-macosx-browser) ) (librewolf-path (setq browse-url-browser-function 'browse-url-generic browse-url-generic-program librewolf-path) ) (firefox-path (setq browse-url-browser-function 'browse-url-generic browse-url-generic-program firefox-path) ) (chrome-path (setq browse-url-browser-function 'browse-url-generic browse-url-generic-program chrome-path) ) ) #+END_SRC http://stackoverflow.com/questions/4506249/how-to-make-emacs-org-mode-open-links-to-sites-in-google-chrome #+BEGIN_SRC emacs-lisp :tangle no (setq browse-url-browser-function 'browse-url-generic browse-url-generic-program "chromium-browser") #+END_SRC https://chrome.google.com/webstore/detail/ljobjlafonikaiipfkggjbhkghgicgoh?hl=de - Edit-server for Chrome #+BEGIN_SRC emacs-lisp :tangle no ;(use-package edit-server) (my-load-local-el "contrib/edit-server.el") ;won't work; (use-package edit-server ;won't work; :load-path "~/.emacs.d/contrib/" ;won't work; :config ;won't work; (edit-server-start) ;won't work; ) (if (locate-library "edit-server") (progn ;(use-package edit-server) (setq edit-server-new-frame nil) (edit-server-start))) #+END_SRC 2017-06-20: [[https://www.reddit.com/r/emacs/comments/6ha4tl/a_little_trick_with_eww/][A little trick with EWW : emacs]] - presents code to interactively select your browser of choice. * Styling The (sub-)headings here deal with the visual appeal of my GNU/Emacs. I like dark themes and minimized interfaces. Therefore, I hide everyting I do not use. Interesting read: http://www.tbray.org/ongoing/When/201x/2012/09/24/Typographic-notes Show current column: 2020-01-01 *disabled* because of performance impact (re-drawing modeline at each keystroke) #+BEGIN_SRC emacs-lisp :tangle no (setq column-number-mode t) #+END_SRC Cursor settings: #+BEGIN_SRC emacs-lisp ;; Prevent the cursor from blinking ;(blink-cursor-mode 0) (set-cursor-color "IndianRed") #+END_SRC Flat mode-line styling: 2014-05-24: from http://www.reddit.com/r/emacs/comments/23l9oi/flat_modeline/ #+BEGIN_SRC emacs-lisp (set-face-attribute 'mode-line nil :box nil) (set-face-attribute 'mode-line-inactive nil :box nil) #+END_SRC - Potential candidates: - A minimal mode-line: https://github.com/jessiehildebrandt/mood-line - Simple mode-line: https://github.com/gexplorer/simple-modeline via [[https://www.wisdomandwonder.com/emacs/13900/configuring-a-simple-modeline][this article]] ** DISABLED Themes | 2021-01-08 | I switch back to light theme (leuven or default) for now | Since a couple of major versions, GNU/Emacs has a built-in theme manager. This is for dealing with the themes. - [2021-01-18 Mon] [[https://www.reddit.com/r/emacs/comments/kz347f/what_parts_of_your_config_do_you_like_best/gjp9n3m/?utm_source=reddit&utm_medium=web2x&context=3][What parts of your config do you like best? : emacs]] - Cool snippet to load and unload theme(s). - [ ] play around with it myself - set color theme according to day-time: - https://github.com/hadronzoo/theme-changer #+BEGIN_SRC emacs-lisp :tangle no (setq calendar-location-name "Graz, AT") (setq calendar-latitude 47.07) (setq calendar-longitude 15.43) (use-package theme-changer) (change-theme 'whiteboard 'misterioso) ;; day and night theme #+END_SRC My favorite dark themes: wombat, misterioso, zenburn, material #+BEGIN_SRC emacs-lisp ;(load-theme 'wombat t) ;; dark theme ;; (load-theme 'misterioso t) ;; (load-theme 'zenburn t) ;; (load-theme 'material t) ;; from http://www.reddit.com/r/emacs/comments/39dk64/escaping_from_org_mode/ ;; issues with *bold* stuff in org-mode :-( #+END_SRC My favorite light themes: leuven, whiteboard, solarized-light, #+BEGIN_SRC emacs-lisp ;; (load-theme 'leuven t) ;; from http://www.reddit.com/r/emacs/comments/39dk64/escaping_from_org_mode/ ;; (load-theme 'whiteboard t) ;; (load-theme 'solarized-light t) #+END_SRC - 2017-03-29: DISABLE a theme: "M-x disable-theme" + theme - from http://emacs.stackexchange.com/questions/3112/how-to-reset-color-theme #+BEGIN_SRC emacs-lisp :tangle no (defadvice load-theme (before theme-dont-propagate activate) (mapcar #'disable-theme custom-enabled-themes)) #+END_SRC ** Only one window on startup «Make [current] WINDOW fill its frame.» - http://thornydev.blogspot.co.at/2012/08/happiness-is-emacs-trifecta.html #+BEGIN_SRC emacs-lisp (add-hook 'emacs-startup-hook 'delete-other-windows t) #+END_SRC ** Font and Font sizes :PROPERTIES: :CREATED: [2017-10-02 Mon 15:18] :END: - 2011-04-20: increase/set font size - http://www.emacswiki.org/emacs/SetFonts 2019-11-15: disabled because not used for a very long time: #+BEGIN_SRC emacs-lisp :tangle no (defun my-increase-fontsize () (interactive) "Sets the font to bigger size" (set-face-attribute 'default (selected-frame) :height 130) ) (defun my-normal-fontsize () (interactive) "Sets the font to normal size" (set-face-attribute 'default (selected-frame) :height 100) ) #+END_SRC I was using DejaVu Sans Mono a while ago: #+BEGIN_SRC emacs-lisp :tangle no (set-face-attribute 'default nil :font "DejaVu Sans Mono-10") ;(add-to-list 'default-frame-alist ; '(font . "DejaVu Sans Mono-10")) #+END_SRC - [2021-05-05 Wed] Discussion: [[https://www.reddit.com/r/emacs/comments/n3q6s4/whats_your_favorite_font_for_emacs/][What's your favorite font for emacs? : emacs]] → https://www.jetbrains.com/lp/mono/ - I'm trying JetBrains Mono for a while - [2021-05-14 Fri] disabled and moving to FantasqueSansMono-NoLoopK #+BEGIN_SRC emacs-lisp :tangle no (add-to-list 'default-frame-alist '(font . "JetBrains Mono-12")) ;; (add-to-list 'default-frame-alist '(line-spacing . 0.2)) #+END_SRC - [2021-05-14 Fri] I'm switching to FantasqueSansMono-NoLoopK because JetBrains Mono does not emphasize *boldface* boldly enough for me #+BEGIN_SRC emacs-lisp (add-to-list 'default-frame-alist '(font . "Fantasque Sans Mono-12")) #+END_SRC ------------ Host-specific font sizes: values are in 1/10pt → 100 are 10pt #+BEGIN_SRC emacs-lisp ;;(when (my-system-type-is-gnu) ;; (my-increase-fontsize);; increase fonts on some hosts by default ;; ) (when (my-system-type-is-darwin) (set-face-attribute 'default (selected-frame) :height 170);; 2011-04-20: increase/set font size http://www.emacswiki.org/emacs/SetFonts ) (when (my-system-type-is-windows) ;;(set-face-attribute 'default (selected-frame) :height 150) ;;(set-face-attribute 'default (selected-frame) :height 130);; 2016-08-19 let's test 130 after 150 seems too big (set-face-attribute 'default (selected-frame) :height 110);; 2017-09-06 detego ) (when (my-system-is-floyd) ;; (set-face-attribute 'default (selected-frame) :height 100) ;; 2020-08-20: switched back to 105 ;; (set-face-attribute 'default (selected-frame) :height 105);; until 2019-12-23 -> not working (set-face-attribute 'default nil :height 105);; 2020-08-22 new command from https://stackoverflow.com/questions/294664/how-to-set-the-font-size-in-emacs ) (when (my-system-is-sting) ;;(set-face-attribute 'default (selected-frame) :height 110) ;; before 2018-02-24 (a bit large) ;;(set-face-attribute 'default (selected-frame) :height 105) ;; before 2019-10-24: I want to try smaller font ;;(set-face-attribute 'default (selected-frame) :height 102) ;; before 2019-12-04: even smaller on reduced resolution (set-face-attribute 'default (selected-frame) :height 110) ;; 2019-12-04: bigger font on native 30" resolution ) (when (my-system-is-jackson) (set-face-attribute 'default (selected-frame) :height 110) ) #+END_SRC Different font size for mode-line (from [[https://emacs.stackexchange.com/questions/1030/how-can-i-set-different-font-sizes-for-buffers-and-for-the-mode-line][this stackexchange page]]): #+BEGIN_SRC emacs-lisp :tangle no (let ((faces '(mode-line mode-line-buffer-id mode-line-emphasis mode-line-highlight mode-line-inactive))) (mapc (lambda (face) (set-face-attribute face nil :font "DejaVu Sans Mono-8")) faces)) #+END_SRC ** DISABLED Modeline with icons :PROPERTIES: :CREATED: [2018-07-23 Mon 13:44] :END: There are two potentially nice packages in order to beautify my modeline even further: - https://github.com/dustinlacewell/eyeliner - https://github.com/domtronn/all-the-icons.el - requires fonts to be installed FIXXME: So far, I did not try them because my current modeline is beautiful enough. Maybe in the future. * UTF-8 and codings Activate UTF-8 mode: #+BEGIN_SRC emacs-lisp (setq locale-coding-system 'utf-8) (set-terminal-coding-system 'utf-8) (set-keyboard-coding-system 'utf-8) (prefer-coding-system 'utf-8) #+END_SRC When I paste from the Windows clipboard, I tend to get messed up Umlauts and special characters. This ought to fix it but I think that this does not work either: #+BEGIN_SRC emacs-lisp (cond ((my-system-type-is-windows) ;; on Windows, 'utf-8 does not work properly when system ;; clipboard gets yanked (setq selection-coding-system 'utf-16le-dos) ;; For example: =\344= instead of =ä= on Windows 7: ;;(set-selection-coding-system 'iso-latin-1-dos) ) ((my-system-type-is-gnu) (set-selection-coding-system 'utf-8) ) (t (set-selection-coding-system 'utf-8) ) ) ;; 2013-12-10 IRC #Emacs (set-clipboard-coding-system 'utf-8) ;; http://www.masteringemacs.org/articles/2012/08/09/working-coding-systems-unicode-emacs/ ;; in addition to the lines above: (set-default-coding-systems 'utf-8) ;; backwards compatibility as default-buffer-file-coding-system ;; is deprecated in 23.2. (if (boundp 'buffer-file-coding-system) ;; NOTE: default-buffer-file-coding-system is obsolete; use ;; buffer-file-coding-system if found (setq-default buffer-file-coding-system 'utf-8) (setq default-buffer-file-coding-system 'utf-8)) ;; Treat clipboard input as UTF-8 string first; compound text next, etc. ;; Disabled because of: https://www.reddit.com/r/emacs/comments/10uj5nn/comment/j7ccyai/?utm_source=reddit&utm_medium=web2x&context=3 ;(setq x-select-request-type '(UTF8_STRING COMPOUND_TEXT TEXT STRING)) #+END_SRC From: https://www.masteringemacs.org/article/working-coding-systems-unicode-emacs #+BEGIN_QUOTE […] One problem with the universal coding system argument is that it only cares about Emacs’s settings, not those of your shell or system. That’s a problem, because tools like Python use the environment variable PYTHONIOENCODING to set the coding system for the Python interpreter. I have written the following code that advises the universal-coding-system-argument function so it also, temporarily for just that command, sets a user-supplied list of environment variables to the coding system. […] #+END_QUOTE #+BEGIN_SRC emacs-lisp (defvar universal-coding-system-env-list '("PYTHONIOENCODING") "List of environment variables \\[universal-coding-system-argument] should set") (defadvice universal-coding-system-argument (around provide-env-handler activate) "Augments \\[universal-coding-system-argument] so it also sets environment variables Naively sets all environment variables specified in `universal-coding-system-env-list' to the literal string representation of the argument `coding-system'. No guarantees are made that the environment variables set by this advice support the same coding systems as Emacs." (let ((process-environment (copy-alist process-environment))) (dolist (extra-env universal-coding-system-env-list) (setenv extra-env (symbol-name (ad-get-arg 0)))) ad-do-it)) #+END_SRC ** DISABLED Entering emojis | 2021-12-20 | Idea from [[http://www.masteringemacs.org/article/inserting-emoji-input-methods][Inserting Emoji with Input Methods - Mastering Emacs]] | | 2024-07-27 | disabled because I don't use it and host kva has an issue | You need to type =C-u C-\=, enter "Emoji" (TAB-completion works) and then one of the defined emojis below such as =:P= or =:thumb:=. - [ ] add more emojis! #+BEGIN_SRC emacs-lisp (quail-define-package "Emoji" "UTF-8" "😎" t "Emoji input mode for people that really, really like Emoji" '(("\t" . quail-completion)) t t nil nil nil nil nil nil nil t) (quail-define-rules (":)" ?😀) (":P" ?😋) (":D" ?😂) (":thumb:" ?👍) (":think:" ?🤔) (":roll:" ?🙄) (":weary:" ?😩) (":wink:" ?😉) (":cry:" ?😢) (":kiss:" ?😘) (":unamused:" ?😒) ; ("::" ?) ; ("::" ?) ) #+END_SRC ---------------- With Emacs 28, Emojis are supposed to be improved. FIXXME: this might not be necessary starting with Emacs 28.1: from http://xahlee.info/emacs/emacs/emacs_set_font_emoji.html #+BEGIN_SRC emacs-lisp (progn ;; set font for emoji (if before emacs 28, should come after setting symbols. emacs 28 now has 'emoji . before, emoji is part of 'symbol) (set-fontset-font t (if (version< emacs-version "28.1") '(#x1f300 . #x1fad0) 'emoji ) (cond ((member "Apple Color Emoji" (font-family-list)) "Apple Color Emoji") ((member "Noto Color Emoji" (font-family-list)) "Noto Color Emoji") ((member "Noto Emoji" (font-family-list)) "Noto Emoji") ((member "Segoe UI Emoji" (font-family-list)) "Segoe UI Emoji") ((member "Symbola" (font-family-list)) "Symbola")))) #+END_SRC I have installed https://fonts.google.com/noto/specimen/Noto+Color+Emoji * my-map: my own keyboard shortcut prefix About defining keys: [[http://ergoemacs.org/emacs/keyboard_shortcuts.html][Emacs: How to Define Keys]] If you are not satisfied with the default setup of Emacs keyboard shortcuts, you start with defining your own keyboard shortcuts (bindings). To avoid binding conflicts with libraries/packages, it is a good habit of using a keyboard shortcut prefix no-one else is using. So if you stick to this prefix, you've got your own «name-space» where you are able to define your bindings freely. My approach is to use =my-map= as a mapping which is bound to =C-c C-,= . So my personal bindings start with =C-c C-,= such as =C-c C-, -= for decreasing the font size of GNU/Emacs. 2015-11-10: Following code was replaced by bind-key below: #+BEGIN_SRC emacs-lisp :tangle no ;; 2011-04-20, 2013-04-08: defining «C-c C-,» as my own prefix: ;; http://stackoverflow.com/questions/1024374/how-can-i-make-c-p-an-emacs-prefix-key-for-develperlysense ;; http://stackoverflow.com/questions/5682631/what-are-good-custom-keybindings-in-emacs ;; NOTE: (info "(elisp) Key Binding Conventions") warns about user prefixes other than C-c (global-unset-key (kbd "C-c C-,")); causes error: "Invalid modifier in string" ;; same as: (global-unset-key (kbd "C-c C-,")) (define-prefix-command 'my-map) #+END_SRC 2019-12-04: With Org mode version 9.2, =C-c C-,= got mapped to =org-insert-structure-template=. In order to avoid any conflict situation (also for communication with peers), I switch to a new binding: =C-c C-k= which is bound to =org-kill-note-or-show-branches= but it's a less popular function. Using the [[https://github.com/jwiegley/dot-emacs/blob/master/init.el][bind-key package]]: (OLD method without use-package:) #+BEGIN_SRC emacs-lisp :tangle no (require 'bind-key);; https://github.com/emacsattic/bind-key ;;(org-defkey org-mode-map (kbd "C-c C-,") nil);; clear binding (bind-keys :prefix-map my-map :prefix-docstring "My own keyboard map" :prefix "C-c C-," ;; 2013-03-31: http://stackoverflow.com/questions/3124844/what-are-your-favorite-global-key-bindings-in-emacs ("-" . text-scale-decrease) ("+" . text-scale-increase) ("=" . text-scale-increase);; because "+" needs "S-=" and I might forget to press shift ) #+END_SRC New method that allows overwriting of bindings (see [[https://github.com/jwiegley/use-package/issues/811#issuecomment-573314421][this comment]] using the [[https://github.com/jwiegley/use-package#loading-packages-in-sequence][after feature of use-package]]): #+BEGIN_SRC emacs-lisp (use-package bind-key :ensure t :bind (:prefix-map my-map :prefix-docstring "My own keyboard map" :prefix "C-c C-," ("-" . text-scale-decrease) ("+" . text-scale-increase) ("=" . text-scale-increase));; because "+" needs "S-=" and I might forget to press shift :after org) #+END_SRC Usage example: : (bind-key "m w" #'mark-word my-map) or: : (bind-keys : :map my-map : ("f" . forward-char) : ("b" . backward-char)) or for use-package(): : :bind (:map my-map ("8" . bm-toggle)) ------------------- Alternative tipp: in case you run out of keybinding spaces, you can take a look at hydra and the "defhydra hydra-k" method. Hydra lists a menu of options and the hydra-k offers a prefix for it. See 33min30s of the video linked in: [[http://irreal.org/blog/?p=6453][Irreal: Hydra Video]] * Misc modes/packages (part I) ** which-key - displays the available key bindings automatically :PROPERTIES: :CREATED: [2018-07-15 Sun 20:06] :END: https://github.com/justbur/emacs-which-key I got the recommendation via [[https://www.reddit.com/r/emacs/comments/8x8rz7/my_emacs_key_binding_strategy/e22x2cu/][this reddit thread]] with the arguments, that =which-key= is inferior to =guide-key= which I used before:: - more active - more features - more contributions when I do press my prefix for =my-map= and wait a bit, I get a popup buffer that tells me what bindings I am able to use. #+BEGIN_SRC emacs-lisp (use-package which-key :ensure t :defer 120 :config ;; executed after loading package (which-key-setup-side-window-right) (add-to-list 'which-key-replacement-alist '(("TAB" . nil) . ("↹" . nil))) (add-to-list 'which-key-replacement-alist '(("RET" . nil) . ("⏎" . nil))) (add-to-list 'which-key-replacement-alist '(("DEL" . nil) . ("⇤" . nil))) (add-to-list 'which-key-replacement-alist '(("SPC" . nil) . ("␣" . nil))) (which-key-mode) ) #+END_SRC Please note [[https://github.com/novoid/dot-emacs/pull/3][this pull request]] that explains why my characters are non-standard ones. It also adds a symbol for ESC. ** project | 2021-12-02 | added due to error | Recently, I got the error =and: Symbol’s value as variable is void: project-switch-commands= when running Magit. See also [[https://www.reddit.com/r/emacs/comments/okse5o/magit_not_accepting_cnp_or_updown_arrows/][this thread on reddit]]. I don't know how this was caused. However, loading the project package which was already in my Elpa directory does help. OK, so it is: #+BEGIN_SRC emacs-lisp (use-package project :ensure t ) #+END_SRC ** helm - completion and selection narrowing This is something that really pushes Emacs usability. https://github.com/emacs-helm/helm «Emacs incremental completion and selection narrowing framework https://emacs-helm.github.io/helm/» #+BEGIN_QUOTE Helm is an Emacs framework for incremental completions and narrowing selections. It helps to rapidly complete file names, buffer names, or any other Emacs interactions requiring selecting an item from a list of possible choices. Helm is a fork of anything.el, which was originally written by Tamas Patrovic and can be considered to be its successor. Helm cleans the legacy code that is leaner, modular, and unchained from constraints of backward compatibility. #+END_QUOTE #+BEGIN_SRC emacs-lisp (use-package helm :ensure t :config (helm-mode 1) ) #+END_SRC ** crux - A Collection of Ridiculously Useful eXtensions for Emacs :PROPERTIES: :ID: 2023-07-07-crux :END: | 2023-07-07 | used by https://xenodium.com/duplicate-this/ together with id:2023-07-07-dwim-shell-command | https://github.com/bbatsov/crux This package seems to offer many functions I did add to my configuration before: crux-open-with, crux-top-join-line, ... At this moment, I don't "merge" those functions (yet). FIXXME: identify crux commands that I added to my setup before and maybe replace them with crux functions. #+BEGIN_SRC emacs-lisp (use-package crux :ensure t :commands crux-open-with :bind (("C-c d" . crux-duplicate-current-line-or-region))) #+END_SRC ** DISABLED marginalia - additional info in the minibuffer | 2024-02-20 | Tip from HVR | | 2024-11-22 | disabled because of =marginalia-classify-original-category: Symbol’s function definition is void: marginalia--orig-completion-metadata-get= | - https://github.com/minad/marginalia #+BEGIN_SRC emacs-lisp ;; 2024-07-27 this package has issues on host kva (when (or (my-system-is-jackson) (my-system-is-sting)) (use-package marginalia :ensure t ; :defer 110 :config ;; To make the binding ;; available in the *Completions* buffer, add it to the ;; `completion-list-mode-map'. :init ;; Marginalia must be activated in the :init section of use-package such that ;; the mode gets enabled right away. Note that this forces loading the ;; package. (marginalia-mode) ) ) #+END_SRC * My helper functions (part I) Here I defined some functions I am using in the configuration below. ** measure-time() From time to time, I want to measure, how long an Elisp snippet ran. This can be done with following code. from: http://stackoverflow.com/questions/23622296/emacs-timing-execution-of-function-calls-in-emacs-lisp #+BEGIN_SRC emacs-lisp (defmacro measure-time (&rest body) "Measure the time it takes to evaluate BODY." `(let ((time (current-time))) ,@body (message " Execution time: %.06f" (float-time (time-since time))))) #+END_SRC ** my-region-contains-line-break-p() | 2023-05-24 | added initial version | I needed this function for =my-title-capitalization()= below in order to be able to detect when it's applied to more than one line which usually indicates an inadvertently use. #+BEGIN_SRC emacs-lisp :results none (defun my-region-contains-line-break-p () "Returns t if current region contains more than one line, nil otherwise" (save-excursion (if (not (use-region-p)) nil ;; return nil if (1) no active region or (2) empty region is found (let ;; there is an active region ( (my-region-beginning-line-number (line-number-at-pos (region-beginning))) (my-region-end-line-number (line-number-at-pos (region-end))) ) ;;(message (concat ;; "Line number start/end of current region: " ;; (number-to-string my-region-beginning-line-number) ;; " and " ;; (number-to-string my-region-end-line-number) ;; ".")) (if (eq my-region-beginning-line-number my-region-end-line-number) nil t) ) ) ) ) #+END_SRC ** my-title-capitalization(): Proper English Title Capitalization of a Marked Region → my-map C Read http://www.karl-voit.at/2015/05/25/elisp-title-capitalization/ where I wrote a verbose description of the topic and my solution. #+BEGIN_SRC emacs-lisp :results none ;; additionally to the list defined in title-capitalization: (defvar my-do-not-capitalize-words '("lazyblorg" "mutt") "My personal list of words that doesn't get capitalized in titles.") (defun title-capitalization (beg end) "Proper English title capitalization of a marked region" ;; - before: the presentation of this heading of my own from my keyboard and yet ;; - after: The Presentation of This Heading of My Own from My Keyboard and Yet ;; - before: a a a a a a a a ;; - after: A a a a a a a A (interactive "r") (save-excursion (if (my-region-contains-line-break-p) (message "The current region contains more than one line which indicates inadvertently use. I stop here.") (let* ( ;; basic list of words which don't get capitalized according to simplified rules: ;; http://karl-voit.at/2015/05/25/elisp-title-capitalization/ (do-not-capitalize-basic-words '("a" "ago" "an" "and" "as" "at" "but" "by" "for" "from" "in" "into" "it" "next" "nor" "of" "off" "on" "onto" "or" "over" "past" "so" "the" "till" "to" "up" "yet" "n" "t" "es" "s")) ;; if user has defined 'my-do-not-capitalize-words, append to basic list: (do-not-capitalize-words (if (boundp 'my-do-not-capitalize-words) (append do-not-capitalize-basic-words my-do-not-capitalize-words ) do-not-capitalize-basic-words ) ) ) ;; go to begin of first word: (goto-char beg) (capitalize-word 1) ;; go through the region, word by word: (while (< (point) end) (skip-syntax-forward "^w" end) (let ((word (thing-at-point 'word))) (if (stringp word) ;; capitalize current word except it is list member: (if (member (downcase word) do-not-capitalize-words) (downcase-word 1) (capitalize-word 1))))) ;; capitalize last word in any case: (backward-word 1) (if (and (>= (point) beg) (not (member (or (thing-at-point 'word) "s") '("n" "t" "es" "s")))) (capitalize-word 1)))) )) (ert-deftest my-title-capitalization () "Tests proper English title capitalization" (should (string= (with-temp-buffer (insert "the presentation of this heading of my own from my keyboard and yet\n") (goto-char (point-min)) (set-mark-command nil) (goto-char (point-max)) ;(transient-mark-mode 1) (title-capitalization) (buffer-string)) "The Presentation of This Heading of My Own from My Keyboard and Yet\n" ))) #+END_SRC #+BEGIN_SRC emacs-lisp (bind-key "c" #'title-capitalization my-map) #+END_SRC ** my-toggle-vertical-horizontal-split() Toggle the windows split between horizontally and vertically. I usually don't use it though. From: http://www.emacswiki.org/emacs/ToggleWindowSplit #+BEGIN_SRC emacs-lisp (defun my-toggle-vertical-horizontal-split () "Switch window split from horizontally to vertically, or vice versa. i.e. change right window to bottom, or change bottom window to right." (interactive) (require 'windmove) (let ((done)) (dolist (dirs '((right . down) (down . right))) (unless done (let* ((win (selected-window)) (nextdir (car dirs)) (neighbour-dir (cdr dirs)) (next-win (windmove-find-other-window nextdir win)) (neighbour1 (windmove-find-other-window neighbour-dir win)) (neighbour2 (if next-win (with-selected-window next-win (windmove-find-other-window neighbour-dir next-win))))) ;;(message "win: %s\nnext-win: %s\nneighbour1: %s\nneighbour2:%s" win next-win neighbour1 neighbour2) (setq done (and (eq neighbour1 neighbour2) (not (eq (minibuffer-window) next-win)))) (if done (let* ((other-buf (window-buffer next-win))) (delete-window next-win) (if (eq nextdir 'right) (split-window-vertically) (split-window-horizontally)) (set-window-buffer (windmove-find-other-window neighbour-dir) other-buf)))))))) ;(bind-key "|" 'my-toggle-split-and-single-window my-map) #+END_SRC #+RESULTS: : my-toggle-vertical-horizontal-split ** my-yank-windows → my-map y Yanking from the windows clipboard results in messed up lists. When using this special yank function, common list formatting is fixed for Org-mode syntax. - id:2016-05-22-my-yank-windows #+BEGIN_SRC emacs-lisp (when (my-system-type-is-windows) (defun my-yank-windows () "yanks from clipboard and replaces typical (list) markup" (interactive) (let ((mybegin (point))) ;; mark beginning of line as start point (clipboard-yank) (save-restriction (narrow-to-region mybegin (point)) ;; ignore everything outside of region (recode-region (point-min) (point-max) 'latin-1 'windows-1252); fix char encoding, e.g.: \366 -> ö (goto-char (point-min)) (while (search-forward "\" " nil t) (replace-match "- " nil t)) (goto-char (point-min)) (while (search-forward "o " nil t) (replace-match " - " nil t)) (while (search-forward "„" nil t) (replace-match "\"" nil t)) (while (search-forward "“" nil t) (replace-match "\"" nil t)) (while (search-forward "’" nil t) (replace-match "'" nil t)) (while (search-forward "–" nil t) (replace-match "-" nil t)) ;;(while (search-forward "1. " nil t) ;; FIXXME: replace with regex-methods for numbers in general ;; (replace-match "1. " nil t)) )) ) (bind-key "y" 'my-yank-windows my-map) ) #+END_SRC ** my-fill-or-unfill() paragraph =M-q= does fix paragraph formatting and is one of my most favorite commands in GNU/Emacs. If you need to go back to «one line per paragraph», this function offers a toggle function for =M-q=. Applied twice, it re-formats the current paragraph to one line. Very handy for copy/paste to web forms or such where you need one paragraph per line. - http://endlessparentheses.com/fill-and-unfill-paragraphs-with-a-single-key.html #+BEGIN_SRC emacs-lisp (defun my-fill-or-unfill () "Like `fill-paragraph', but unfill if used twice." (interactive) (let ((fill-column (if (eq last-command 'my-fill-or-unfill) (progn (setq this-command nil) (point-max)) fill-column))) (call-interactively 'fill-paragraph nil (vector nil t)))) (global-set-key [remap fill-paragraph] 'my-fill-or-unfill) #+END_SRC [2023-02-15 Wed] potential alternative with some functionality to ignore Org mode elements that should not be changed: https://www.emacs.dyerdwelling.family/emacs/20230214201355-emacs--my-pure-paragraph-refill/ ** my-open-in-external-app() Some times, I want to use an external application for opening a certain file instead of opening it in Emacs. This can be done using following function: - http://ergoemacs.org/emacs/emacs_dired_open_file_in_ext_apps.html - open dired file in external app (specified by the operating system) - https://www.reddit.com/r/emacs/comments/9iwnwi/w32shellexecute_explore_fails_if_file_type_hasnt/ - interesting reddit discussion with several explanations on w32explore, dired-w32explore, w32-shell-execute, and xah-show-in-desktop() #+BEGIN_SRC emacs-lisp (defun my-open-in-external-app (&optional file) "Open the current FILE or dired marked files in external app. The app is chosen from your OS's preference." (interactive) (message "%s" (concat "my-open-in-external-app called with \"" file "\" as argument")) ;; FIXXME: add check if FILE is an existing file; show error message if not (let ( doIt (myFileList (cond ((string-equal major-mode "dired-mode") (dired-get-marked-files)) ((not file) (list (buffer-file-name))) (file (list file))))) (setq doIt (if (<= (length myFileList) 5) t (y-or-n-p "Open more than 5 files? ") ) ) (when doIt (cond ((my-system-type-is-windows) (mapc (lambda (fPath) (w32-shell-execute "open" (replace-regexp-in-string "/" "\\" fPath t t)) ) myFileList)) ((string-equal system-type "darwin") (mapc (lambda (fPath) (shell-command (format "open \"%s\"" fPath)) ) myFileList) ) ((my-system-type-is-gnu) (mapc (lambda (fPath) (let ((process-connection-type nil)) (start-process "" nil "xdg-open" fPath)) ) myFileList) ) ) ) ) ) #+END_SRC ** my-buffer-exists(bufname) =my-buffer-exists(bufname)= #+BEGIN_SRC emacs-lisp (defun my-buffer-exists (bufname) (not (eq nil (get-buffer bufname))) ) #+END_SRC ** my-comment-box :PROPERTIES: :CREATED: [2019-01-11 Fri 14:36] :END: I got this code from [[http://pragmaticemacs.com/emacs/comment-boxes/][pragmaticemacs]]: #+BEGIN_SRC emacs-lisp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; example: ;; ;; from http://irreal.org/blog/?p=374 ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (defun my-comment-box (b e) "Draw a box comment around the region but arrange for the region to extend to at least the fill column. Place the point after the comment box." (interactive "r") (let ((e (copy-marker e t))) (goto-char b) (end-of-line) (insert-char ? (- fill-column (current-column))) (comment-box b e 1) (goto-char e) (set-marker e nil))) #+END_SRC ** my-scroll-up-command() my-scroll-down-command() :PROPERTIES: :CREATED: [2019-06-29 Sat 12:00] :END: Usually, =C-p= and =C-n= are mapped to =scroll-down-command= and =scroll-up-command=. Contrary to this, I like to scroll only half of a screen so that I can follow the content in a better way. The following implementation was inspired by (and copied from) https://www.emacswiki.org/emacs/HalfScrolling #+BEGIN_SRC emacs-lisp (defun my-window-half-height () (max 1 (/ (1- (window-height (selected-window))) 2))) (defun my-scroll-up-half () (interactive) (scroll-up (my-window-half-height))) (defun my-scroll-down-half () (interactive) (scroll-down (my-window-half-height))) #+END_SRC ** my-screnshot-svg | 2021-03-26 | added to my config after test looks awesome | - From [[https://www.reddit.com/r/emacs/comments/idz35e/emacs_27_can_take_svg_screenshots_of_itself/][reddit]] - [[https://www.masteringemacs.org/article/whats-new-in-emacs-27-1][mentioned by Clement on Mickey's blog post]] - [[https://gist.githubusercontent.com/alphapapa/65b0b9d4b3f55344c6e143f8f3878d7a/raw/b6fc5110a8a554bf4e75d18f1a5956e741c06a14/emacs-27-svg-screenshot.svg][example]] #+BEGIN_SRC emacs-lisp (defun my-screenshot-svg () "Save a screenshot of the current frame as an SVG image. Saves to a temp file to /tmp/ and puts the filename in the kill ring." (interactive) (let* ((filename (make-temp-file "Emacs" nil ".svg")) (data (x-export-frames nil 'svg))) (with-temp-file filename (insert data)) (kill-new filename) (message filename))) #+END_SRC Resulting image can ge opened, e.g., in inkscape. Using the context menu feature "Enter group #..." you can go as deep into the elements as you wish. It really looks amazing. ** my-find-duplicate-filetags-reformatter | 2022-06-08 | added for helping me reformat results of =rdfind= output files | Following function reformats the output of =rdfind=: : rdfind -outputname "`date +%Y-%m-%d`_find_duplicates.log" ~/path/to/subhierarchy This produces output files with content like: #+BEGIN_EXAMPLE # Automatically generated # duptype id depth size device inode priority name DUPTYPE_FIRST_OCCURRENCE 14598 5 15867904 64772 437191892 3 /home/vk/src/tagstore/2013-01-29_tagstore-migration/tagstore-ORIG/installer/needs4tagstore/python-2.7.3.msi DUPTYPE_WITHIN_SAME_TREE -14598 5 15867904 64772 437322430 3 /home/vk/src/tagstore/tagstore/research_platform/installer/needs4tagstore/python-2.7.3.msi DUPTYPE_FIRST_OCCURRENCE 14597 5 21509961 64772 437191891 3 /home/vk/src/tagstore/2013-01-29_tagstore-migration/tagstore-ORIG/installer/needs4tagstore/python-2.7-macosx10.5.dmg DUPTYPE_WITHIN_SAME_TREE -14597 5 21509961 64772 437322429 3 /home/vk/src/tagstore/tagstore/research_platform/installer/needs4tagstore/python-2.7-macosx10.5.dmg DUPTYPE_FIRST_OCCURRENCE 14593 5 28955664 64772 437191887 3 /home/vk/src/tagstore/2013-01-29_tagstore-migration/tagstore-ORIG/installer/needs4tagstore/PyQt-Py2.7-x86-gpl-4.9.4-1.exe DUPTYPE_WITHIN_SAME_TREE -14593 5 28955664 64772 437322421 3 /home/vk/src/tagstore/tagstore/research_platform/installer/needs4tagstore/PyQt-Py2.7-x86-gpl-4.9.4-1.exe # end of file #+END_EXAMPLE My process is now: 1. Remove initial and ending comment lines 2. Go to start of the file 3. =C-u 100 M-x my-find-duplicate-filetags-reformatter= - Change "100" to any number that is larger than the number of invocations necessary or invoke function multiple times. - This reformats the lines above to: #+BEGIN_EXAMPLE filetags -t "2del duplicate" "src/tagstore/2013-01-29_tagstore-migration/tagstore-ORIG/installer/needs4tagstore/python-2.7.3.msi" filetags -t "2del duplicate" "tagstore/tagstore/research_platform/installer/needs4tagstore/python-2.7.3.msi" filetags -t "2del duplicate" "src/tagstore/2013-01-29_tagstore-migration/tagstore-ORIG/installer/needs4tagstore/python-2.7-macosx10.5.dmg" filetags -t "2del duplicate" "tagstore/tagstore/research_platform/installer/needs4tagstore/python-2.7-macosx10.5.dmg" filetags -t "2del duplicate" "src/tagstore/2013-01-29_tagstore-migration/tagstore-ORIG/installer/needs4tagstore/PyQt-Py2.7-x86-gpl-4.9.4-1.exe" filetags -t "2del duplicate" "tagstore/tagstore/research_platform/installer/needs4tagstore/PyQt-Py2.7-x86-gpl-4.9.4-1.exe" #+END_EXAMPLE - This is now a shell script for invoking [[https://github.com/novoid/filetags][filetags]] that tags all duplicate files with two tags: "2del" and "duplicate". - *NOTE*: this works only for exactly two duplicates per file. If you do have more than two duplicates for a file, you need to modify your workflow or the function accordingly. 4. Go through the shell script and decide which files to keep by removing their filetags line. 5. Invoke the shell script file so that the remaining tags get applied. 6. Remove the now tagged files for deletion via: : find ~/path/to/subhierarchy -type f -name '* --* 2del*' -print0 | xargs -0 rm -f The function to reformat the =rdfind= output file is: #+BEGIN_SRC emacs-lisp (fset 'my-find-duplicate-filetags-reformatter [?\C- C-right C-right C-right C-right C-right C-right C-right C-right C-right ?\C-w ?f ?i ?l ?e ?t ?a ?g ?s ? ?- ?t ? ?\" ?2 ?d ?e ?l ? ?d ?u ?p ?l ?i ?c ?a ?t ?e ?\" ? ?\" ?\C-d ?\C-e ?\" ?\C-a down ?\C- C-right C-right C-right C-right C-right C-right C-right C-right C-right C-right ?\C-w ?f ?i ?l ?e ?t ?a ?g ?s ? ?- ?t ? ?\" ?r ?s backspace backspace ?2 ?d ?e ?l ? ?d ?u ?p ?l ?i ?c ?a ?t ?e ?\" ? ?\" ?\C-d ?\C-e ?\" return down]) #+END_SRC ** my-tear-off-window() | 2023-06-12 | copied from web to test | This code is taken [[https://stackoverflow.com/a/57318988][from stackoverflow]] and adapted by me. With this function, I may create a new separate Emacs frame with the current buffer which I may destroy any time. This might get handy for working on source code buffers where magit tends to destroy my multi-buffer setup. #+BEGIN_SRC emacs-lisp :results none (defun my-tear-off-window () "Delete the selected window, and create a new frame displaying its buffer." (interactive) (let* ((window (selected-window)) (buf (window-buffer window)) (frame (make-frame))) (select-frame frame) (switch-to-buffer buf) ;(delete-window window) )) #+END_SRC ** my-number-or-float() | 2024-03-11 | added to my config for =my-switch-to-thing()= | According to my GPT4All LLM, =number-or-float= should be part of the default Emacs setup. However, on my host(s), it isn't. So I define this here. #+BEGIN_SRC emacs-lisp (defun my-number-or-float (x) "Return a number or float, or nil if no numeric value was found." (if (numberp x) x (let ((num (string-to-number x))) (if num num nil)))) #+END_SRC * Spell checking «[[https://www.emacswiki.org/emacs/FlySpell][Flyspell]] enables on-the-fly spell checking in Emacs by the means of a minor mode.» Please do evaluate this only if "aspell" is found on the system: #+BEGIN_SRC emacs-lisp (when (my-eval-if-binary-or-warn "aspell") #+END_SRC ** General settings setting path to flyspell-mode.el from MacPorts: #+BEGIN_SRC emacs-lisp (when (my-system-type-is-darwin) (add-to-list 'load-path "/opt/local/share/emacs/lisp/textmodes") ) #+END_SRC save to user dictionary without asking: #+BEGIN_SRC emacs-lisp :tangle no (setq ispell-silently-savep t) #+END_SRC ** DISABLED flyspell flyspell.el #+BEGIN_SRC emacs-lisp :tangle no (autoload 'flyspell-mode "flyspell" "On-the-fly spelling checking" t) #+END_SRC ** Dictionary Settings - http://www.linuxfaq.de/f/cache/146.html #+BEGIN_SRC emacs-lisp ;(set-default 'ispell-local-dictionary my-german-ispell-dictionary) ;;(autoload 'flyspell-mode "flyspell" "On-the-fly ispell." t) (setq flyspell-issue-welcome-flag nil) (when (my-system-type-is-windows) (setq flyspell-default-dictionary "american") ) (when (my-system-type-is-gnu) (setq flyspell-default-dictionary "de_AT") (setq default-dictionary "de_AT") ) #+END_SRC from here to my-toggle-ispell-english-deutsch: see id:2014-01-06-aspell-issue #+BEGIN_SRC emacs-lisp (eval-after-load "ispell" '(add-to-list 'ispell-dictionary-alist '("german8" "[a-zA-ZäöüßÄÖÜ]" "[^a-zA-ZäöüßÄÖÜ]" "[']" t ("-C" "-d" "de_DE-neu.multi") "~latin1" iso-8859-1))) (when (my-system-type-is-windows) ;; use english on powerplantwin: (let ((langs '("american" "german8"))) (setq lang-ring (make-ring (length langs))) (dolist (elem langs) (ring-insert lang-ring elem))) ) (when (my-system-type-is-gnu) ;; use US english on powerplantwin: (let ((langs '("de_AT" "en_US"))) (setq lang-ring (make-ring (length langs))) (dolist (elem langs) (ring-insert lang-ring elem))) ) ;; ;; use american english on all other systems: ;; (let ((langs '("german8" "american"))) ;; (setq lang-ring (make-ring (length langs))) ;; (dolist (elem langs) (ring-insert lang-ring elem))) ;; ) #+END_SRC ** my-toggle-ispell-language() =my-toggle-ispell-language()= because I use two languages and switch between them: #+BEGIN_SRC emacs-lisp (defun my-toggle-ispell-language () (interactive) (let ((lang (ring-ref lang-ring -1))) (ring-insert lang-ring lang) (ispell-change-dictionary lang))) #+END_SRC ** DISABLED auto-dictionary-mode | 2021-06-20 | disabled since I can't remember that it did anything for me | This mode determines the dictionary language for the current buffer according to the text found. It switches language automatically when you switch the language you're typing. What a relief for bilingual people like me (German/English). - from: https://github.com/nschum/auto-dictionary-mode #+BEGIN_SRC emacs-lisp (use-package auto-dictionary :load-path (lambda () (expand-file-name (concat my-user-emacs-directory "contrib/auto-dictionary-mode/"))) ) (require 'auto-dictionary) ;;(add-hook 'text-mode-hook 'flyspell-mode) ;; according to https://github.com/nschum/auto-dictionary-mode/issues/11#issuecomment-557741953 ;;(add-hook 'flyspell-mode-hook (lambda () (auto-dictionary-mode 1))) #+END_SRC ** Spellchecking Source Code Modes for programming languages; check spelling only in comments/strings - http://www.lrde.epita.fr/cgi-bin/twiki/view/Projects/EmacsTricks #+BEGIN_SRC emacs-lisp :tangle no (add-hook 'c-mode-hook 'flyspell-prog-mode) (add-hook 'sh-mode-hook 'flyspell-prog-mode) (add-hook 'c++-mode-hook 'flyspell-prog-mode) (add-hook 'ruby-mode-hook 'flyspell-prog-mode) (add-hook 'cperl-mode-hook 'flyspell-prog-mode) (add-hook 'python-mode-hook 'flyspell-prog-mode) (add-hook 'autoconf-mode-hook 'flyspell-prog-mode) (add-hook 'autotest-mode-hook 'flyspell-prog-mode) (add-hook 'makefile-mode-hook 'flyspell-prog-mode) (add-hook 'emacs-lisp-mode-hook 'flyspell-prog-mode) #+END_SRC ** Keybindings 2018-06-19: disabled most bindings because I moved those functions to a hydra with F5 #+BEGIN_SRC emacs-lisp :tangle no (define-key global-map [(f5)] 'flyspell-mode) (bind-key "fm" 'flyspell-mode my-map);; also mapped to F5 (bind-key "fr" 'flyspell-region my-map) (bind-key "fl" 'my-toggle-ispell-language my-map);; also mapped to Shift-F5 (define-key global-map [(shift f5)] 'my-toggle-ispell-language) (bind-key "ft" 'my-toggle-ispell-language my-map);; can't remember if l(anguage) or t(oggle) (bind-key "fn" 'flyspell-goto-next-error my-map) (bind-key "ff" 'flyspell-correct-word-before-point my-map) #+END_SRC For quickly correcting text, I keep F7 (next error) and F8 (fix) for going through the findings one by one: #+BEGIN_SRC emacs-lisp (define-key global-map [(f7)] 'flyspell-goto-next-error) (define-key global-map [(f8)] 'flyspell-correct-word-before-point) #+END_SRC ** End of aspell #+BEGIN_SRC emacs-lisp );; when aspell found #+END_SRC * flycheck «[[http://www.flycheck.org/][Flycheck]] is a modern on-the-fly syntax checking extension for GNU Emacs, intended as replacement for the older Flymake extension which is part of GNU Emacs.» - http://www.flycheck.org/en/latest/guide/quickstart.html - 2016-11-05: converted to use-package according to http://www.flycheck.org/en/latest/user/installation.html#use-package #+BEGIN_SRC emacs-lisp (use-package flycheck :ensure t :init ;; (global-flycheck-mode) ;; has performance impact on non-programming buffers as well :config (setq flycheck-flake8-maximum-line-length 200); http://www.flycheck.org/manual/latest/Configuring-checkers.html#Configuring-checkers ) #+END_SRC * Snippets German blog article on snippet systems: http://www.karl-voit.at/Textbausteine/ I do recommend to use snippet systems for quickly inserting static (words/numbers, sentences, paragraphs, ...) or dynamic (current date/time) text. Most snippets, I do define in a system-wide tool so that I am able to use them in every program. Some snippets I do define and use only within Emacs. Yasnippet and yankpad offers me very advanced functionality to define and use most elaborate snippets. Those snippets vary from simple ones (e.g., check-lists for packing for vacations) to rather advanced ones (e.g., a complete lecture organization with many tasks and their dependencies). ** yasnippet [[https://github.com/joaotavora/yasnippet][Yasnippet]] is the snippet tool to use within Emacs: #+BEGIN_SRC emacs-lisp (use-package yasnippet ;:load-path (lambda () (expand-file-name (concat my-user-emacs-directory "contrib/yasnippet/"))) :demand t :mode ("/\\.emacs\\.d/etc/yasnippet/snippets/" . snippet-mode) :diminish yas-minor-mode ;;:defer 90 :config (yas-load-directory (concat my-user-emacs-directory "etc/yasnippet/snippets/")) (yas-global-mode 1) ;; http://yasnippet.googlecode.com/svn/trunk/doc/index.html ;;disabled;(my-load-local-el "contrib/yasnippet/yasnippet.el") ;;(autoload 'yas-minor-mode "yasnippet") ;;disabled 2015-04-01 - issues did not vanish;; ;; https://capitaomorte.github.io/yasnippet/faq.html#sec-4 ;;disabled 2015-04-01 - issues did not vanish;; ;; How to I use alternative keys, i.e. not TAB? ;;disabled 2015-04-01 - issues did not vanish;; ;; see id:2015-02-01-yas-expand-not-TAB ;;disabled 2015-04-01 - issues did not vanish;; (define-key yas-minor-mode-map (kbd "") nil) ;;disabled 2015-04-01 - issues did not vanish;; (define-key yas-minor-mode-map (kbd "TAB") nil) ;;disabled 2015-04-01 - issues did not vanish;; (define-key yas-minor-mode-map (kbd "") 'yas-expand) ;;(my-log-hostspecific "yas--version" yas--version) ;; disabled 2025-10-23 because it generated an error on sting: Debugger entered--Lisp error: (void-variable yas--version) ) #+END_SRC As of 2019-12-07, I moved more or less all snippets from plain yasnippet to yankpad. ** yankpad [[https://github.com/Kungsgeten/yankpad][yankpad]] is an add-on that enables easy management of yasnippet snippets within an Org-mode file. I do define Org-mode-independent snippets with the basic yasnippet methods. Any snippet that is used within Org-mode only is defined in my yankpad file. - see also: [[id:2016-08-08-yankpad-test]] #+BEGIN_SRC emacs-lisp (use-package yankpad :ensure t ;;:defer 110 :init (setq yankpad-file (concat my-org-files-path "yankpad.org")) :bind (:map my-map ("SPC" . yankpad-insert) ("y" . yankpad-expand) ) :config (bind-key "" 'yankpad-expand) (bind-key "" 'yankpad-map) (setq yankpad-default-category "org-mode") ) #+END_SRC * Programming ** company (completion) | 2021-04-04 | stolen config from https://github.com/zamansky/dot-emacs for playing with LSP | #+BEGIN_SRC emacs-lisp (use-package company :ensure t :config (setq company-idle-delay 0) (setq company-minimum-prefix-length 3) ;; (add-hook 'after-init-hook 'global-company-mode) (add-hook 'python-mode-hook 'company-mode) ;; disable company mode in org mode: (doesn't work → company was enabled all the time; disabled global company mode and enabled it only for Python) ;; (add-hook 'org-mode-hook (lambda () (company-mode -1))) ) #+END_SRC ** Git :PROPERTIES: :CREATED: [2018-09-02 Sun 10:41] :END: This is a section where all [[https://en.wikipedia.org/wiki/Git][Git]]-related configuration is happening. *** magit → my-map g «[[https://github.com/magit/magit][Magit]] is an interface to the version control system Git, implemented as an Emacs package. Magit aspires to be a complete Git porcelain. While we cannot (yet) claim that Magit wraps and improves upon each and every Git command, it is complete enough to allow even experienced Git users to perform almost all of their daily version control tasks directly from within Emacs. While many fine Git clients exist, only Magit and Git itself deserve to be called porcelains.» Some people start using Emacs just to be able to use this nifty Git interface of Magit. #+BEGIN_SRC emacs-lisp ;;2018-07-09 test when using GitHub version;;(setq with-editor-file-name-history-exclude 1) ;; https://github.com/syl20bnr/spacemacs/issues/7225 (use-package magit ;;2018-07-09 disabled because lots of errors on load;; :load-path (lambda () (expand-file-name (concat my-user-emacs-directory "contrib/magit/lisp/"))) :if (and (my-eval-if-binary-or-warn "git") (my-system-type-is-gnu)) :ensure t ;; install package if not found OR: (setq use-package-always-ensure t) :defer 20 ;;110 ;; :bind (:map magit-status-mode-map ("q" magit-quit-session)) :config ;; executed after loading package (setq magit-diff-refine-hunk 'all) ;; enable in-line diff highlighting ;; DISABLED because if used in a side-by-side setup, it kills all but one window :-( ;; 2023- 06-12 disabled ;; ;; full screen magit-status ;; 2023- 06-12 disabled ;; ;; http://whattheemacsd.com//setup-magit.el-01.html ;; 2023- 06-12 disabled ;; (defadvice magit-status (around magit-fullscreen activate) ;; 2023- 06-12 disabled ;; (window-configuration-to-register :magit-fullscreen) ;; 2023- 06-12 disabled ;; ad-do-it ;; 2023- 06-12 disabled ;; (delete-other-windows)) ;; 2023- 06-12 disabled ;; ;; 2023- 06-12 disabled ;; (defun magit-quit-session () ;; 2023- 06-12 disabled ;; "restores the previous window configuration and kills the magit buffer" ;; 2023- 06-12 disabled ;; (interactive) ;; 2023- 06-12 disabled ;; (kill-buffer) ;; 2023- 06-12 disabled ;; (jump-to-register :magit-fullscreen)) #+END_SRC #+BEGIN_SRC emacs-lisp :tangle no (bind-key "g" #'magit-status my-map) #+END_SRC [2024-05-18 Sat] [[https://irreal.org/blog/?p=12179][• Renaming Git Files With Emacs Dired | Irreal]]: #+BEGIN_SRC emacs-lisp (setq dired-vc-rename-file t) #+END_SRC I got this code from [[https://stackoverflow.com/questions/48879892/magit-status-in-a-new-frame-and-delete-frame-on-exit][that stackoverflow page]] which basically puts =magit-status= in a separate Emacs frame (and closes it): #+BEGIN_SRC emacs-lisp :results none :tangle no (bind-key "g" (lambda () """magit-status in a new frame and delete frame on exit""" (interactive) (select-frame (make-frame-command)) (magit-status) (delete-other-windows) ) my-map ) ;; close magit frame when done: (define-key magit-mode-map (kbd "q") 'delete-frame) #+END_SRC ... disabled due to error in Emacs 3x: "Wrong type argument: commandp, #[nil..." #+BEGIN_SRC emacs-lisp (defun my-magit-status-in-new-frame () "Open `magit-status` in a new frame, and delete other windows." (interactive) (select-frame (make-frame-command)) (magit-status) (delete-other-windows)) (bind-key "g" #'my-magit-status-in-new-frame my-map) #+END_SRC *** DISABLED smeargle (highlighting) Disabled 2020-01-07 because I don't use it. - smeargle - Highlighting Regions by Last Updated Time (my-map c) - https://github.com/syohex/emacs-smeargle/ - M-x smeargle - Highlight regions by last updated time. - M-x smeargle-age - Highlight regions by age of changes. - M-x smeargle-clear - Clear overlays in current buffer #+BEGIN_SRC emacs-lisp (use-package smeargle :ensure t :defer 110 :config ;; executed after loading package ;;:bind (:map my-map ("c" . smeargle)) ;; CONFLICTS with my title capitalization #+END_SRC You can set highlighted colors of smeargle by changing smeargle-colors: #+BEGIN_SRC emacs-lisp :tangle no (custom-set-variables '(smeargle-colors '((older-than-1day . "red") (older-than-3day . "green") (older-than-1week . "yellow") (older-than-2week . nil) (older-than-1month . "orange") (older-than-3month . "pink") (older-than-6month . "cyan") (older-than-1year . "grey50")))) #+END_SRC And you can also set colors of =smeargle-commits= by =smeargle-age-colors=: #+BEGIN_SRC emacs-lisp (custom-set-variables '(smeargle-age-colors '((0 . nil) (1 . "grey80") (2 . "grey70") (3 . "grey60") (4 . "grey50") (5 . "grey40") (6 . "grey30") (7 . "grey20") (8 . "grey10")))) #+END_SRC You can specify parameters until =smeargle-age-threshold=. =age= is set to =smeargle-age-threshold= if actual age of changes is older than =smeargle-age-threshold=. Default value of =smeargle-age-threshold= is 7. Misc settings: #+BEGIN_SRC emacs-lisp :tangle no (global-set-key (kbd "C-x v s") 'smeargle) (global-set-key (kbd "C-x v c") 'smeargle-commits) ;; Highlight regions at opening file (add-hook 'find-file-hook 'smeargle) ;; Updating after save buffer (add-hook 'after-save-hook 'smeargle) #+END_SRC End of smeargle: #+BEGIN_SRC emacs-lisp );; end of smeargle #+END_SRC *** DISABLED GitGutter :PROPERTIES: :CREATED: [2018-09-01 Sat 16:39] :END: 2019-12-31: DISABLED for performance reasons: https://www.reddit.com/r/orgmode/comments/e9p84n/scaling_org_better_to_use_more_medsize_files_or/fcm5bsc/ [[https://github.com/syohex/emacs-git-gutter][GitGutter]] is visualizing modified lines within the source code buffer. #+BEGIN_SRC emacs-lisp (use-package git-gutter :ensure t :config #+END_SRC Either you use the global minor mode ... #+BEGIN_SRC emacs-lisp (global-git-gutter-mode +1) ;; inactivate git-gutter-mode in asm-mode and image-mode (custom-set-variables '(git-gutter:disabled-modes '(asm-mode image-mode))) #+END_SRC ... or activate the minor mode for specific modes: #+BEGIN_SRC emacs-lisp :tangle no (add-hook 'python-mode-hook 'git-gutter-mode) (add-hook 'ruby-mode-hook 'git-gutter-mode) #+END_SRC Keyboard bindings: Jump to next/previous hunk #+BEGIN_SRC emacs-lisp (global-set-key (kbd "S-") 'git-gutter:previous-hunk) (global-set-key (kbd "S-") 'git-gutter:next-hunk) #+END_SRC More bindings: #+BEGIN_SRC emacs-lisp :tangle no (global-set-key (kbd "C-x C-g") 'git-gutter) (global-set-key (kbd "C-x v =") 'git-gutter:popup-hunk) ;; Jump to next/previous hunk (global-set-key (kbd "C-x p") 'git-gutter:previous-hunk) (global-set-key (kbd "C-x n") 'git-gutter:next-hunk) ;; Stage current hunk (global-set-key (kbd "C-x v s") 'git-gutter:stage-hunk) ;; Revert current hunk (global-set-key (kbd "C-x v r") 'git-gutter:revert-hunk) ;; Mark current hunk (global-set-key (kbd "C-x v SPC") #'git-gutter:mark-hunk) #+END_SRC If you set git-gutter:update-interval seconds larger than 0, git-gutter updates diff information in real-time by idle timer. #+BEGIN_SRC emacs-lisp :tangle no (custom-set-variables '(git-gutter:update-interval 2)) #+END_SRC Pass option to 'git diff' command: You can pass git diff option to set git-gutter:diff-option. #+BEGIN_SRC emacs-lisp ;; ignore all spaces (custom-set-variables '(git-gutter:diff-option "-w")) #+END_SRC Customize visualization: #+BEGIN_SRC emacs-lisp (custom-set-variables '(git-gutter:modified-sign "~ ") ;; two space '(git-gutter:added-sign "++") ;; multiple character is OK '(git-gutter:deleted-sign "--")) (set-face-background 'git-gutter:modified "purple") ;; background color (set-face-foreground 'git-gutter:added "green") (set-face-foreground 'git-gutter:deleted "red") #+END_SRC You can change minor-mode name in mode-line to set =git-gutter:lighter=. Default is =GitGutter=. First character should be a space. #+BEGIN_SRC emacs-lisp :tangle no (custom-set-variables '(git-gutter:lighter " GG")) #+END_SRC End of git-gutter: #+BEGIN_SRC emacs-lisp ) #+END_SRC *** DISABLED git-timemachine 2019-12-08: disabled because I was not using it. Step through historic versions: https://github.com/pidu/git-timemachine (2018-09-02: repo has been removed) [[http://emacsredux.com/blog/2014/07/22/travel-back-and-forward-in-git-history/][A page with an animated GIF]] showing its functionality. #+BEGIN_QUOTE Step through historic versions of git controlled file using everyone's favourite editor Visit a git-controlled file and issue =M-x git-timemachine= (or bind it to a keybinding of your choice). If you just need to toggle the time machine you can use =M-x git-timemachine-toggle=. Use the following keys to navigate historic version of the file | p | Visit previous historic version | | n | Visit next historic version | | w | Copy the abbreviated hash of the current historic version | | W | Copy the full hash of the current historic version | | g | Goto nth revision | | q | Exit the time machine. | | b | Run magit-blame on the currently visited revision (if magit available). | #+END_QUOTE #+BEGIN_SRC emacs-lisp (use-package git-timemachine :ensure t :defer 120 :init #+END_SRC [[http://blog.binchen.org/posts/new-git-timemachine-ui-based-on-ivy-mode.html][Source]] -> start from selected revision instead of HEAD #+BEGIN_SRC emacs-lisp (defun my-git-timemachine-show-selected-revision () "Show last (current) revision of file." (interactive) (let (collection) (setq collection (mapcar (lambda (rev) ;; re-shape list for the ivy-read (cons (concat (substring (nth 0 rev) 0 7) "|" (nth 5 rev) "|" (nth 6 rev)) rev)) (git-timemachine--revisions))) (ivy-read "commits:" collection :action (lambda (rev) (git-timemachine-show-revision rev))))) #+END_SRC Open git snapshot with the selected version. Based on ivy-mode: #+BEGIN_SRC emacs-lisp (defun my-git-timemachine () "Open git snapshot with the selected version. Based on ivy-mode." (interactive) (unless (featurep 'git-timemachine) (require 'git-timemachine)) (git-timemachine--start #'my-git-timemachine-show-selected-revision)) #+END_SRC end of git-timemachine: #+BEGIN_SRC emacs-lisp );; end of git-timemachine #+END_SRC *** magit-log--add-date-headers :PROPERTIES: :CREATED: [2019-12-17 Tue 18:48] :END: From: https://github.com/alphapapa/unpackaged.el This requires ov.el: https://github.com/emacsorphanage/ov #+BEGIN_SRC emacs-lisp (use-package ov :load-path (lambda () (expand-file-name (concat my-user-emacs-directory "contrib/ov/"))) ) #+END_SRC #+BEGIN_SRC emacs-lisp (defun unpackaged/magit-log--add-date-headers (&rest _ignore) "Add date headers to Magit log buffers." (when (derived-mode-p 'magit-log-mode) (save-excursion (ov-clear 'date-header t) (goto-char (point-min)) (cl-loop with last-age for this-age = (-some--> (ov-in 'before-string 'any (line-beginning-position) (line-end-position)) car (overlay-get it 'before-string) (get-text-property 0 'display it) cadr (s-match (rx (group (1+ digit) ; number " " (1+ (not blank))) ; unit (1+ blank) eos) it) cadr) do (when (and this-age (not (equal this-age last-age))) (ov (line-beginning-position) (line-beginning-position) 'after-string (propertize (concat " " this-age "\n") 'face 'magit-section-heading) 'date-header t) (setq last-age this-age)) do (forward-line 1) until (eobp))))) (define-minor-mode unpackaged/magit-log-date-headers-mode "Display date/time headers in `magit-log' buffers." :global t (if unpackaged/magit-log-date-headers-mode (progn ;; Enable mode (add-hook 'magit-post-refresh-hook #'unpackaged/magit-log--add-date-headers) (advice-add #'magit-setup-buffer-internal :after #'unpackaged/magit-log--add-date-headers)) ;; Disable mode (remove-hook 'magit-post-refresh-hook #'unpackaged/magit-log--add-date-headers) (advice-remove #'magit-setup-buffer-internal #'unpackaged/magit-log--add-date-headers))) #+END_SRC *** End of Git :PROPERTIES: :CREATED: [2018-09-02 Sun 10:44] :END: #+BEGIN_SRC emacs-lisp ) ;; end of magit use-package ;(my-log-hostspecific "magit-version" magit-version) ;; doesn't work (anywhere here) for some reason #+END_SRC ** highlight-symbol → my-map h This package does highlight all occurrences of a given word. Very handy when programming: visualize all occurrences of a variable/function. Note: This package here somehow overlaps with the "hover" feature of a LSP server that supports it. In that case, you should disable the =highlight-symbol-mode= below. #+BEGIN_SRC emacs-lisp (use-package highlight-symbol :ensure t :defer 110 ;;(bind-key (kbd "h") #'highlight-symbol my-map) :bind (:map my-map ("h" . highlight-symbol)) :hook (python-mode . highlight-symbol-mode) ) ;; original: (global-set-key [(control f3)] 'highlight-symbol) ;; original: (global-set-key [f3] 'highlight-symbol-next) ;; original: (global-set-key [(shift f3)] 'highlight-symbol-prev) ;; original: (global-set-key [(meta f3)] 'highlight-symbol-query-replace) #+END_SRC ** projectile | 2020-12-10 | initial setup | #+BEGIN_SRC emacs-lisp (use-package projectile :ensure t :defer 110 ) #+END_SRC ** Language Server Protocol (LSP) → C-c l | 2021-04-03 | initial setup for testing with Python/pyls | Why? Python code completion was always a bit of a drag. I don't code that often. When there was a long break between my Python sessions, somehow code completion was a fragile thing that often did not work. Because of [[https://www.reddit.com/r/emacs/comments/mj3kcr/good_completion_backends_for_python/][this thread]] I do give LSP a try. lsp-mode: #+BEGIN_SRC emacs-lisp (use-package lsp-mode :ensure t :init ;; set prefix for lsp-command-keymap (few alternatives - "C-l", "C-c l") (setq lsp-keymap-prefix "C-c l") :hook ((python-mode . lsp) ;; if you want which-key integration ;; (lsp-mode . lsp-enable-which-key-integration) ;; 2021-04-04: I'm using lsp-deferred instead ) :commands lsp ) #+END_SRC - [ ] FIXXME: maybe customize - lsp-pyls-plugins-flake8-ignore - lsp-pyls-plugins-pycodestyle-max-line-length - lsp-pyls-plugins-flake8-max-line-length lsp-ui: #+BEGIN_SRC emacs-lisp (use-package lsp-ui :ensure t :commands lsp-ui-mode :hook (lsp-mode . lsp-ui-mode) :config (setq lsp-ui-sideline-enable t) (setq lsp-ui-sideline-show-hover nil) (setq lsp-ui-doc-position 'bottom) ;; lsp config stuff (setq lsp-enable-links t) (setq lsp-signature-render-documentation t) (setq lsp-headerline-breadcrumb-enable t) (setq lsp-ui-doc-enable t) (setq lsp-completion-enable-additional-text-edit nil) (setq web-mode-enable-current-element-highlight t) (lsp-ui-doc-show) ) #+END_SRC for helm: #+BEGIN_SRC emacs-lisp (use-package helm-lsp :ensure t :commands helm-lsp-workspace-symbol) #+END_SRC others: #+BEGIN_SRC emacs-lisp :tangle no ;; ;; if you are ivy user ;; (use-package lsp-ivy :commands lsp-ivy-workspace-symbol) ;; (use-package lsp-treemacs :commands lsp-treemacs-errors-list) ;; optionally if you want to use debugger ;; watch https://www.youtube.com/watch?v=0bilcQVSlbM to get an idea ;; (use-package dap-mode :ensure t) ;; (use-package dap-python :ensure t) ;; to load the dap adapter for your language ;;;; optional if you want which-key integration ;;(use-package which-key ;; :ensure t ;; :config ;; (which-key-mode)) #+END_SRC ** Elisp This heading contains configurations for editing [[https://en.wikipedia.org/wiki/Elisp][Elisp]] code. separate color for highlightning () brackets: http://compgroups.net/comp.emacs/to-use-special-color-for-brackets-in-emacs-lisp-mo/222015 #+BEGIN_SRC emacs-lisp :tangle no ;; ###################################################### (defface paren-face '((((class color) (background dark)) (:foreground "grey30")) (((class color) (background light)) (:foreground "grey60"))) "Face used to dim parentheses.") (defun egoge-dim-parens () (font-lock-add-keywords nil '(("(\\|)" . 'paren-face)))) (add-hook 'emacs-lisp-mode-hook 'egoge-dim-parens) #+END_SRC Do not use [[https://www.emacswiki.org/emacs/AutoFillMode][Auto Fill Mode]] for Lisp mode: #+BEGIN_SRC emacs-lisp (add-hook 'emacs-lisp-mode-hook 'turn-off-auto-fill) #+END_SRC When editing code that uses parenthesis, enabling this does highlight the matching parenthesis: #+BEGIN_SRC emacs-lisp (show-paren-mode t) #+END_SRC *** DISABLED ert for using unit tests of yasnippet (see id:2013-02-07yasnippetdebuggen and yasnippet-tests.el) #+BEGIN_SRC emacs-lisp (my-load-local-el "contrib/cl-lib.el") (my-load-local-el "contrib/ert.el") (my-load-local-el "contrib/ert-x.el") #+END_SRC *** DISABLED buttercup - Elisp test suite #+BEGIN_QUOTE [[https://github.com/jorgenschaefer/emacs-buttercup][Buttercup]] is a behavior-driven development framework for testing Emacs Lisp code. It allows to group related tests so they can share common set-up and tear-down code, and allows the programmer to “spy” on functions to ensure they are called with the right arguments during testing. The framework is heavily inspired by [[https://jasmine.github.io/edge/introduction.html][Jasmine]]. #+END_QUOTE Disabled for now because I do not use it at the moment. #+BEGIN_SRC emacs-lisp (use-package buttercup :ensure t ; :if (my-system-is-floyd) :defer 110 :config ) #+END_SRC *** DISABLED smartparens - highlight corresponding parens - nice overview of different hightlight modes: http://danmidwood.com/content/2014/11/21/animated-paredit.html - nice overview: https://ebzzry.github.io/emacs-pairs.html (Dead link as of 2017-05-26) #+BEGIN_SRC emacs-lisp (use-package smartparens :init (smartparens-global-mode 1) (show-smartparens-global-mode +1) :bind (;; ("M-n" . sp-next-sexp) ;; ("M-p" . sp-previous-sexp) ("M-f" . sp-forward-sexp) ("M-b" . sp-backward-sexp) ) :config ;; Enable smartparens everywhere (use-package smartparens-config) ;; ;; Require and disable paredit because some packages rely on it. ;; (use-package paredit) ;; (disable-paredit-mode) (setq smartparens-strict-mode t sp-autoinsert-if-followed-by-word t sp-autoskip-closing-pair 'always ;;sp-base-key-bindings 'paredit sp-hybrid-kill-entire-symbol nil) ;; (sp-use-paredit-bindings) ;; (sp-with-modes '(markdown-mode gfm-mode rst-mode) ;; (sp-local-pair "*" "*" :bind "C-*") ;; (sp-local-tag "2" "**" "**") ;; (sp-local-tag "s" "```scheme" "```") ;; (sp-local-tag "<" "<_>" "" :transform 'sp-match-sgml-tags)) ;; ;; Close a backtick with another backtick in clojure-mode ;; (sp-local-pair 'clojure-mode "`" "`" :when '(sp-in-string-p)) (sp-local-pair 'emacs-lisp-mode "`" nil :when '(sp-in-string-p)) ) #+END_SRC *** s - «The long lost Emacs string manipulation library.» https://github.com/magnars/s.el #+BEGIN_SRC emacs-lisp (use-package s :ensure t :defer 90 :config ) #+END_SRC *** Elisp: → my-map er|el|ef Misc bindings for Elisp: #+BEGIN_SRC emacs-lisp (bind-key "er" #'eval-region my-map) (bind-key "el" #'find-library my-map) (bind-key "ef" #'find-function-at-point my-map) #+END_SRC *** macrostep | 2023-01-08 | moved from git to melpa; still not used actively by me | I found the [[https://github.com/joddie/macrostep][macrostep]] package through [[http://irreal.org/blog/?p=6442][the Irreal article John Wiegley and Sacha Chua on use-package]] which links [[https://www.youtube.com/watch?v=2TSKxxYEbII][2015-04-01 Emacs package highlight: use-package from YouTube]]. #+BEGIN_SRC emacs-lisp (use-package macrostep :ensure t :defer 120 :config ;; executed after loading package (define-key emacs-lisp-mode-map (kbd "C-c e") 'macrostep-expand) ) #+END_SRC From the README: #+BEGIN_QUOTE The standard keybindings in =macrostep-mode= are the following: - e, =, RET :: expand the macro form following point one step - c, u, DEL :: collapse the form following point - q, C-c C-c :: collapse all expanded forms and exit macrostep-mode - n, TAB :: jump to the next macro form in the expansion - p, M-TAB :: jump to the previous macro form in the expansion It's not very useful to enable and disable macrostep-mode directly. Instead, bind =macrostep-expand= to a key in =emacs-lisp-mode-map=, for example C-c e: : (define-key emacs-lisp-mode-map (kbd "C-c e") 'macrostep-expand) You can then enter macrostep-mode and expand a macro form completely by typing =C-c e e e ...= as many times as necessary. Exit macrostep-mode by typing =q= or =C-c C-c=, or by successively typing =c= to collapse all surrounding expansions. #+END_QUOTE *** lisp-format | 2021-07-31 | I wanted to test the Elisp formatter for formatting my code | #+BEGIN_SRC emacs-lisp (use-package elisp-format :ensure t :defer 110 ) #+END_SRC ** Python | 2021-04-04 | shift from previous elpy-based setup to a LSB-based setup | This heading contains configurations for editing [[https://en.wikipedia.org/wiki/Python_(programming_language)][Python]] code. Python is the programming language I prefer for [[https://github.com/novoid/][my private projects]]. I do like its easy-to-read syntax, providing a high level of maintainability. It also ships with a large set of libraries. Selected keyboard commands (summary): (see defined hydra for python mode!) | Key | Command | Command | |-----------+----------------------------+-----------------------| | M-h | hide/show current function | =hs-cycle= | | C-c l g g | find definition | =lsp-find-definition= | | C-c l g r | find references | =lsp-find-references= | | | function overview | | *** BEGIN of Python-related stuff The code blocks here are only executed when python is found on the current system: #+BEGIN_SRC emacs-lisp (when (my-eval-if-binary-or-warn "python") #+END_SRC *** auto-mode-list for Python files #+BEGIN_SRC emacs-lisp :tangle no (add-to-list 'auto-mode-alist '("\\.py$" . python-mode)) (add-to-list 'auto-mode-alist '("\\.py$" . company-mode)) (add-hook 'python-mode-hook (lambda () (lsp-mode) )) #+END_SRC *** pyls (LSP) - https://emacs-lsp.github.io/lsp-mode/page/lsp-pyls/ - https://github.com/palantir/python-language-server - "The base language server requires Jedi to provide Completions, Definitions, Hover, References, Signature Help, and Symbols" : sudo python3 -m pip install 'python-language-server[all]' or even better: : python3 -m pip install --user 'python-language-server[all]' Optional: : sudo python3 -m pip install pyls-mypy On [2021-08-27 Fri] my Emacs wrote: : Warning (emacs): The palantir python-language-server (pyls) is unmaintained; a maintained fork is the python-lsp-server (pylsp) project; you can install it with pip via: pip install python-lsp-server Disable showing Disable logging So I did: : sudo python3 -m pip uninstall 'python-language-server[all]' : sudo python3 -m pip install python-lsp-server *** DISABLED jedi (LSP) [2021-04-04 Sun 16:56] disabled: I want to test pure pyls Setup according to https://github.com/zamansky/dot-emacs #+BEGIN_SRC emacs-lisp :tangle no (use-package lsp-jedi :ensure t :config (with-eval-after-load "lsp-mode" (add-to-list 'lsp-disabled-clients 'pyls) (add-to-list 'lsp-enabled-clients 'jedi))) (setq lsp-ui-doc-show-with-cursor nil) #+END_SRC *** Switch to ipython (NOT YET TESTED) From [[https://www.reddit.com/r/emacs/comments/70chy1/emacs_ipython_completion/][this reddit]] and [[https://emacs.stackexchange.com/questions/24453/weird-shell-output-when-using-ipython-5][this solution]]: NOT TESTED YET! (2017-10-02) 2019-01-20: [[https://www.reddit.com/r/emacs/comments/ahuvm6/how_can_i_switch_my_python_interpreter_to_use/][this reddit]] thread suggests overwriting =python-shell-interpreter= in order to switch to Python 3. (not tested/confirmed yet) #+BEGIN_SRC emacs-lisp (if (my-eval-if-binary-or-warn "ipython3") (setq python-shell-interpreter "ipython3" python-shell-interpreter-args "--simple-prompt -i") ;; else: (when (my-eval-if-binary-or-warn "python3") (setq python-shell-interpreter "python3") ) ) #+END_SRC Note: Org mode babel is using =org-babel-python-command= which is set elsewhere (to =python3= as of 2019-03-05). *** flymake, flycheck | 2021-04-04 | I'm unsure if this is still necessary after switching to LSP/pyls | #+BEGIN_QUOTE [[https://www.emacswiki.org/emacs/FlyMake][FlyMake]] performs on-the-fly syntax checks on the files being edited using the external syntax check tool (usually the compiler). Highlights erroneous lines and displays associated error messages. Unfortunately, this project is outdated and last change was 3 years ago. For a modern alternative, check out Flycheck. #+END_QUOTE - fix flymake (PEP8): ignore E501 (long lines) - see id:2015-04-04-flymake and http://stackoverflow.com/a/1393590 - looks similar: http://people.cs.uct.ac.za/~ksmith/2011/better-python-flymake-integration-in-emacs.html #+BEGIN_SRC emacs-lisp :tangle no (when (load "flymake" t) (defun flymake-pyflakes-init () (let* ((temp-file (flymake-init-create-temp-buffer-copy 'flymake-create-temp-inplace)) (local-file (file-relative-name temp-file (file-name-directory buffer-file-name)))) (list "~/bin/pycheckers" (list local-file)))) (add-to-list 'flymake-allowed-file-name-masks '("\\.py\\'" flymake-pyflakes-init))) #+END_SRC better than flymake (and maintained): http://stackoverflow.com/a/1621489 [[https://www.emacswiki.org/emacs/Flycheck][Flycheck]] #+BEGIN_SRC emacs-lisp (add-hook 'python-mode-hook (lambda () (unless (eq buffer-file-name nil) (flymake-mode 1)) ;dont invoke flymake on temporary buffers for the interpreter (local-set-key [f6] 'flymake-goto-prev-error) (local-set-key [f7] 'flymake-goto-next-error) (flycheck-mode 1) ;; instead of global )) #+END_SRC *** hideshow-orgmode | 2023-01-08 | still not on *elpa | I found [[https://github.com/logangrado/hideshow-orgmode][hideshow-orgmode]] via [[https://www.reddit.com/r/emacs/comments/795u0o/hideshoworgmode/][this reddit thread]]. It provides (Python) code outlining similar to Org-mode =TAB= visibility cycling. This is a very nice thing to have. So far, I used yafolding-mode for it. This needs the hideshow minor mode =M-x hideshow-minor-mode= enabled to work. #+BEGIN_SRC emacs-lisp (use-package hideshow-orgmode :load-path (lambda () (expand-file-name (concat my-user-emacs-directory "contrib/hideshow-orgmode"))) :config (add-hook 'python-mode-hook (lambda () (hs-minor-mode 1) ;;(hs-cycle-all) (global-set-key (kbd "M-h") 'hs-cycle) (global-set-key (kbd "M-H") 'hs-cycle-all) )) ) #+END_SRC *** sphinx-doc.el :PROPERTIES: :CREATED: [2018-08-27 Mon 17:45] :END: | 2023-01-08 | moved to elpa version | Source: https://github.com/naiquevin/sphinx-doc.el #+BEGIN_QUOTE =sphinx-doc= is an emacs minor mode for inserting docstring skeleton for Python functions and methods. The structure of the docstring is as per the requirement of the [[http://sphinx-doc.org/index.html][Sphinx documentation generator]]. #+END_QUOTE #+BEGIN_SRC emacs-lisp (use-package sphinx-doc :ensure t :config (add-hook 'python-mode-hook (lambda () (require 'sphinx-doc) (sphinx-doc-mode t))) ) #+END_SRC Issue: : let: Symbol’s value as variable is void: sphinx-doc-python-indent ... when applied. I could not find anything related. *** elpygen → C-c i :PROPERTIES: :CREATED: [2017-12-26 Tue 10:49] :END: | 2023-01-08 | moved from git repo to elpa | From [[https://github.com/vkazanov/elpygen][GitHub]]: "Generate Python function/method stub for a call-like symbol under point" Just write =a_function_call(first_named, 2, second_named)=, invoke the command =elpygen-implement= and elpygen either jumps to the existing function or it generates a stub for a new one. The example above results in =def a_function_call(first_named, arg1, second_named):\npass=. #+BEGIN_SRC emacs-lisp (use-package elpygen :ensure t :config (require 'elpygen) (define-key python-mode-map (kbd "C-c i") 'elpygen-implement) ) #+END_SRC *** pylookup | 2023-01-08 | somehow this got lost: re-added via local package as I've found no *elpa | #+BEGIN_SRC emacs-lisp (use-package pylookup :load-path (lambda () (expand-file-name (concat my-user-emacs-directory "contrib/pylookup/"))) ;:ensure t :defer 110 ) #+END_SRC *** END of Python-related stuff #+BEGIN_SRC emacs-lisp );; if python binary found #+END_SRC ** JavaScript *** js-beautify | 2022-10-20 | I had to review JS code which was "optimized" and searched for a beautifyer | [2022-10-20 Thu] I found https://sethmason.com/2011/04/28/beautify-your-javascript-in-emacs.html which points to https://beautifier.io/ and https://github.com/beautify-web/js-beautify. On Debian-based systems, you can install it via: =apt install jsbeautifier= #+BEGIN_SRC emacs-lisp :results none ;;; js-beautify.el -- beautify some js code ;;; copied from https://sethmason.com/2011/04/28/beautify-your-javascript-in-emacs.html (defgroup js-beautify nil "Use jsbeautify to beautify some js" :group 'editing) (defcustom js-beautify-args "--jslint-happy --brace-style=end-expand --keep-array-indentation" "Arguments to pass to jsbeautify script" :type '(string) :group 'js-beautify) (defcustom js-beautify-path "/usr/bin/js-beautify" "Path to jsbeautifier python file" :type '(string) :group 'js-beautify) (defun js-beautify () "Beautify a region of javascript using the code from jsbeautify.org" (interactive) (let ((orig-point (point))) (unless (mark) (mark-defun)) (shell-command-on-region (point) (mark) (concat "python3 " js-beautify-path " --stdin " js-beautify-args) nil t) (goto-char orig-point))) (provide 'js-beautify) ;;; js-beautify.el ends here #+END_SRC ** Nix | 2023-06-01 | initial setup for my Nix(OS) test | #+BEGIN_SRC emacs-lisp (use-package nix-mode :ensure t :defer 110 ) #+END_SRC * dired Usually, I do file management in [[http://karl-voit.at/2015/12/14/screen-to-tmux/][tmux]] and zsh. There are my aliases, my functions, the features I like. Having a file manager in Emacs does have some advantages. [[http://ergoemacs.org/emacs/emacs_dired_tips.html][Dired tipps from ergoemacs]]. [[https://www.masteringemacs.org/article/dired-shell-commands-find-xargs-replacement][Mastering Emacs on Dired]]. Here are some minor tweaks related to file management in Emacs with dired. From [[http://emacsrocks.com/e16.html][Emacsrocks #16]]: two window file management. From the documentation: #+BEGIN_QUOTE If non-nil, Dired tries to guess a default target directory. This means: if there is a Dired buffer displayed in the next window, use its current directory, instead of this Dired buffer’s current directory. #+END_QUOTE #+BEGIN_SRC emacs-lisp (setq dired-dwim-target t) ;;(setq dired-listing-switches "-al --group-directories-first") #+END_SRC from: [[http://mbork.pl/2018-12-10_Lesser_known_Dired_stuff][Marcin Borkowski: 2018-12-10 Lesser known Dired stuff]]: create parent directories when slashes are used when renaming files: #+BEGIN_SRC emacs-lisp ;(setq wdired-create-parent-directories t) FIXXME: enable when my old installation gets an update #+END_SRC ** dired-garbage-files-regexp - define garbage file regex :PROPERTIES: :CREATED: [2018-07-05 Thu 17:39] :END: In dired, you can press =%&= which calls =dired-flag-garbage-files()=. By default, it uses the regular expression ="\\(?:\\.\\(?:aux\\|bak\\|dvi\\|log\\|orig\\|rej\\|toc\\)\\)\\'"= which does not include miscelaneous file extensions I am working with. Therefore, I overwrite the regex with my own values: #+BEGIN_SRC emacs-lisp (setq dired-garbage-files-regexp "\\(?:\\.\\(?:aux\\|bak\\|bbl\\|bcf\\|dvi\\|log\\|rej\\|toc\\)\\)\\'") #+END_SRC ** dired-details → ( - [ ] FIXXME 2018-07-06: think of switching to [[https://www.emacswiki.org/emacs/DiredDetails][dired-details+]] (which offers some functionality I currently do not use). Also from [[http://emacsrocks.com/e16.html][Emacsrocks #16]]: hide and show file details with =(= and =)=: #+BEGIN_SRC emacs-lisp (use-package dired-details :load-path (lambda () (expand-file-name (concat my-user-emacs-directory "contrib/"))) ;;:defer 90 :config (setq-default dired-details-hidden-string "… ") ) #+END_SRC ** dired-x, dired+, dired-icon Enabling already pre-insalled dired-x: #+BEGIN_SRC emacs-lisp (require 'dired-x) #+END_SRC Dired+ has [[https://www.emacswiki.org/emacs/DiredPlus][lots of useful features]] - Dired plus is not available on MELPA: [[https://www.reddit.com/r/emacs/comments/84thzd/what_happened_to_dired_package/][reddit thread]]. It needs to be fetched via https://www.emacswiki.org/emacs/download/dired%2b.el. I wrote an update shell script for it. #+BEGIN_SRC emacs-lisp (use-package dired+ :load-path (lambda () (expand-file-name (concat my-user-emacs-directory "contrib/dired-plus/"))) ;; :ensure t ;;:defer 90 :config (diredp-toggle-find-file-reuse-dir 1) ;; https://www.emacswiki.org/emacs/DiredReuseDirectoryBuffer (remove-hook 'dired-after-readin-hook 'diredp-nb-marked-in-mode-name) ;; better performance on dired buffer start (remove-hook 'dired-mode-hook 'diredp-nb-marked-in-mode-name) ;; better performance on dired buffer start (setq diredp-image-preview-in-tooltip 400) ;; 2024-03-23: somehow, it only shows a black rectangle without content although I've loaded dired-image+ below ) #+END_SRC 2019-02-05: disabled because loading a new dired buffer took very long with it although it really looked nicely: #+BEGIN_SRC emacs-lisp :tangle no (use-package dired-icon :ensure t ;;:defer 110 :config (add-hook 'dired-mode-hook 'dired-icon-mode) ) #+END_SRC Bind backspace to visit higher level directory: #+BEGIN_SRC emacs-lisp (define-key dired-mode-map (kbd "") 'diredp-up-directory-reuse-dir-buffer) #+END_SRC ** helm-dired-history - [ ] ivy-dired-history is an alternative to: #+BEGIN_SRC emacs-lisp (use-package helm-dired-history :ensure t :config (require 'savehist) (add-to-list 'savehist-additional-variables 'helm-dired-history-variable) (savehist-mode 1) (with-eval-after-load 'dired (require 'helm-dired-history) (define-key dired-mode-map "," 'dired)) ) #+END_SRC ** dired-recent → C-z :PROPERTIES: :CREATED: [2018-06-28 Thu 13:39] :END: This is one of the killer-features of (any) file-browser application: offer a quick search of recently visited directories. I never maintain any directory bookmarks any more. I use a similar feature in my [[https://en.wikipedia.org/wiki/Z_shell][zsh]] via [[https://github.com/rupa/z][z]]. You might also look into =GoTo= (on steroids) of [[http://fman.io/][fman]]. - https://github.com/vifon/dired-recent.el - from [[https://www.reddit.com/r/emacs/comments/8u8slx/dired_quickly_jumping_to_previously_visited/e1e2iew/?context=3][this reddit context]] "Press =C-x C-d= to select a previously visited directory to open." #+BEGIN_SRC emacs-lisp (use-package dired-recent :ensure t ;;:defer 90 :config (require 'dired-recent) (dired-recent-mode 1) (setq dired-recent-max-directories nil) ;; nil means to remember all ) #+END_SRC Make better use of =dired-recent-open= using ivy: #+BEGIN_SRC emacs-lisp (defun my-dired-recent-dirs () "Present a list of recently used directories and open the selected one in dired" (interactive) (let ((dir (ivy-read "Directory: " dired-recent-directories :re-builder #'ivy--regex :sort nil :initial-input nil))) (dired dir))) (global-set-key (kbd "C-z") 'my-dired-recent-dirs) #+END_SRC Maybe, this can be optimized by using [[http://melpa.org/#/frecentf][frecency for scoring entries]] (like in [[https://fman.io/][fman]] or [[http://www.forum.freecommander.com/viewtopic.php?f=20&t=8371][this feature-request for FreeCommander]]). So far, I'm quite happy with the current feature. ** dired-narrow → / :PROPERTIES: :CREATED: [2018-06-29 Fri 20:49] :END: From http://pragmaticemacs.com/emacs/dynamically-filter-directory-listing-with-dired-narrow/ with https://github.com/Fuco1/dired-hacks It narrows down the list of files using a pattern. =g= resets the view. #+BEGIN_SRC emacs-lisp (use-package dired-narrow :load-path (lambda () (expand-file-name (concat my-user-emacs-directory "contrib/dired-hacks/"))) ;;:defer 90 :bind (:map dired-mode-map ("/" . dired-narrow))) #+END_SRC ** dired-open :PROPERTIES: :CREATED: [2018-06-29 Fri 20:49] :END: From https://github.com/Fuco1/dired-hacks Provides: - =dired-open-xdg= try to open the file using =xdg-open= - =dired-open-guess-shell-alist= try to open the file by launching applications from =dired-guess-shell-alist-user= - =dired-open-call-function-by-extension= call an elisp function based on extension. #+BEGIN_SRC emacs-lisp (use-package dired-open ;;:defer 90 :load-path (lambda () (expand-file-name (concat my-user-emacs-directory "contrib/dired-hacks/"))) ) #+END_SRC ** dired-collapse :PROPERTIES: :CREATED: [2018-06-29 Fri 20:49] :END: From https://github.com/Fuco1/dired-hacks#dired-collapse Provides: - =dired-open-xdg= try to open the file using =xdg-open= - =dired-open-guess-shell-alist= try to open the file by launching applications from =dired-guess-shell-alist-user= - =dired-open-call-function-by-extension= call an elisp function based on extension. #+BEGIN_SRC emacs-lisp (use-package dired-collapse :load-path (lambda () (expand-file-name (concat my-user-emacs-directory "contrib/dired-hacks/"))) ;;:defer 90 :config ;(dired-collapse-mode) ) #+END_SRC ** image-dired+ :PROPERTIES: :CREATED: [2018-06-29 Fri 12:58] :END: Image-dired extensions: https://www.emacswiki.org/emacs/ImageDired - Non-blocking thumbnail creating - Adjust image to window - https://www.youtube.com/watch?v=NrY3t3W0_cM → image-dired demo - basic usage - open externally - tag images [[https://www.gnu.org/software/emacs/manual/html_node/emacs/Image_002dDired.html][Emacs manual]]: #+BEGIN_QUOTE To enter Image-Dired, mark the image files you want to look at in the Dired buffer, using =m= as usual. Then type =C-t d= (=image-dired-display-thumbs=). This creates and switches to a buffer containing image-dired, corresponding to the marked files. You can also enter Image-Dired directly by typing =M-x image-dired=. This prompts for a directory; specify one that has image files. This creates thumbnails for all the images in that directory, and displays them all in the thumbnail buffer. This takes a long time if the directory contains many image files, and it asks for confirmation if the number of image files exceeds =image-dired-show-all-from-dir-max-files=. #+END_QUOTE FIXXME: 2018-06-30: There is a issue on floyd. I get following error when I mark files and invoke =C-t d=: #+BEGIN_EXAMPLE [...] error in process sentinel: image-diredx--invoke-process: Wrong type argument: processp, [nil 23351 46922 931735 nil image-dired-thumb-queue-run nil nil 787000] error in process sentinel: Wrong type argument: processp, [nil 23351 46922 931735 nil image-dired-thumb-queue-run nil nil 787000] [...] Marking files... 377 files newly marked image-diredx--invoke-process: Wrong type argument: processp, [nil 23351 47004 248326 nil image-dired-thumb-queue-run nil nil 669000] [...] #+END_EXAMPLE #+BEGIN_SRC emacs-lisp (use-package image-dired+ :ensure t :defer 110 :config (require 'image-dired+) (image-diredx-async-mode 1) (image-diredx-adjust-mode 1) (define-key image-dired-thumbnail-mode-map "\C-n" 'image-diredx-next-line) (define-key image-dired-thumbnail-mode-map "\C-p" 'image-diredx-previous-line) (define-key image-dired-thumbnail-mode-map "g" 'revert-buffer);; revert all thumbnails if `image-diredx-async-mode' is on (define-key image-dired-thumbnail-mode-map "x" 'image-diredx-flagged-delete);; Delete confirmation prompt with thumbnails (setq image-dired-track-movement nil) ;; Suppress unknown cursor movements (setq image-dired-external-viewer "/usr/bin/geeqie") ;; FIXXME: configure different for Windows ) #+END_SRC ** dired-ranger → M-c; M-v; M-m :PROPERTIES: :CREATED: [2018-06-29 Fri 20:49] :END: From https://github.com/Fuco1/dired-hacks: - https://github.com/Fuco1/dired-hacks#dired-ranger #+BEGIN_QUOTE With the multi-stage operations, you can gather files from /multiple/ dired buffers into a single "clipboard", then copy or move all of them to the target location. Another huge advantage is that if the target dired buffer is already opened, switching to it via ido or ibuffer is often faster than selecting the path. Call =dired-ranger-copy= to add marked files (or the file under point if no files are marked) to the "clipboard". With non-nil prefix argument, add the marked files to the current clipboard. Past clipboards are stored in =dired-ranger-copy-ring= so you can repeat the past pastes. Call =dired-ranger-paste= or =dired-ranger-move= to copy or move the files in the current clipboard to the current dired buffer. With raw prefix argument (usually C-u), the clipboard is not cleared, so you can repeat the copy operation in another dired buffer. #+END_QUOTE #+BEGIN_SRC emacs-lisp (use-package dired-ranger :load-path (lambda () (expand-file-name (concat my-user-emacs-directory "contrib/dired-hacks/"))) :defer 110 ;; has to be after dired+ in able to overwrite its bindings below :config (define-key dired-mode-map (kbd "M-c") 'dired-ranger-copy) ;; overwrites: diredp-capitalize-this-file (define-key dired-mode-map (kbd "M-v") 'dired-ranger-paste) ;; overwrites: scroll-down-command (define-key dired-mode-map (kbd "M-m") 'dired-ranger-move) ;; overwrites: back-to-indentation ) #+END_SRC ** dired-isearch :PROPERTIES: :CREATED: [2018-07-03 Tue 18:08] :END: Via [[https://www.emacswiki.org/emacs/DiredIsearch][EmacsWiki]] and download from http://www.emacswiki.org/emacs/download/dired-isearch.el #+BEGIN_SRC emacs-lisp :tangle no (use-package dired-isearch :load-path (lambda () (expand-file-name (concat my-user-emacs-directory "contrib/"))) :defer 110 :config ) #+END_SRC *Not necessary* any more. There is built-in functionality which I just have to re-map to =C-s= (because I don't need reverse or RegEx search): #+BEGIN_SRC emacs-lisp (define-key dired-mode-map (kbd "C-s") 'dired-isearch-filenames) #+END_SRC ** looking for: filetags, date2name, appendfilename :PROPERTIES: :CREATED: [2020-04-19 Sun 15:35] :END: #+BEGIN_SRC emacs-lisp (setq my-filetags-file (my-binary-found "filetags")) (when (and (not my-filetags-file) (my-system-type-is-gnu)) (progn (message "using manual src path for \"filetags\"") (setq my-filetags-file (my-binary-found (concat (expand-file-name "~") "/src/filetags/filetags/__init__.py"))) ) ) (setq my-date2name-file (my-binary-found "date2name")) (when (and (not my-date2name-file) (my-system-type-is-gnu)) (progn (message "using manual src path for \"date2name\"") (setq my-date2name-file (my-binary-found (concat (expand-file-name "~") "/src/date2name/date2name/__init__.py"))) ) ) (setq my-appendfilename-file (my-binary-found "appendfilename")) (when (and (not my-appendfilename-file) (my-system-type-is-gnu)) (progn (message "using manual src path for \"appendfilename\"") (setq my-appendfilename-file (my-binary-found (concat (expand-file-name "~") "/src/appendfilename/appendfilename/__init__.py"))) ) ) #+END_SRC ** my-dired-filetags → M-t :PROPERTIES: :CREATED: [2018-06-29 Fri 21:35] :END: #+BEGIN_SRC emacs-lisp (defun my-dired-filetags () "Run \"filetags\" on current or marked files" (interactive) (let* ((marked-files (f-uniquify (dired-get-marked-files)))) ;; apply to single file or marked files (when (string-equal system-name "GRZN17009") ;;works (let ((proc (start-process "cmd" nil "cmd.exe" "/C" "start" "cmd.exe" "/K" "echo \"Hello\""))) ;;(message (concat "CALLING: c:/Users/karl.voit/bin/filetags.bat -sv " marked-files)) (let ((proc (start-process "cmd" nil "cmd.exe" "/C" "start" "cmd.exe" "/C" "c:/Users/karl.voit/bin/filetags.bat -sv" (shell-quote-argument marked-files))) (set-process-query-on-exit-flag proc nil))) ;;(dired-do-shell-command "cmd.exe /K c:/Users/karl.voit/bin/filetags.bat *" nil marked-files) ) (when (string-equal system-name "cosmo") (let ((proc (start-process "cmd" nil "cmd.exe" "/C" "start" "cmd.exe" "/C" "C:/Users/John/AppData/Roaming/filetags.bat -sv" (shell-quote-argument marked-files))) (set-process-query-on-exit-flag proc nil))) ) (when (my-system-type-is-gnu) ;; FIXXME: maybe add check for binary: (when (my-eval-if-binary-or-warn "xfce4-terminal") ;; --disable-server → provides a blocking terminal window (instead of a non-blocking one which swallows the revert-buffer afterward) (dired-do-shell-command (concat "xfce4-terminal --disable-server --geometry=100x20+330+5 --hide-menubar -x " my-filetags-file " --interactive *") nil marked-files) ) (revert-buffer nil t t) ;; refresh listing of files ) ) (define-key dired-mode-map (kbd "M-t") 'my-dired-filetags) #+END_SRC ** my-dired-appendfilename → M-a :PROPERTIES: :CREATED: [2018-06-29 Fri 21:36] :END: #+BEGIN_SRC emacs-lisp (defun my-dired-appendfilename () "Run \"appendfilename\" on current or marked files" (interactive) (let* ((marked-files (f-uniquify (dired-get-marked-files)))) ;; apply to single file or marked files (when (my-system-type-is-windows) (dired-do-shell-command "FIXXME xfce4-terminal --geometry=100x20+330+5 --hide-menubar -x /home/vk/bin/filetags --interactive *" nil marked-files) ) (when (my-system-type-is-gnu) ;; FIXXME: maybe add check for binary: (when (my-eval-if-binary-or-warn "xfce4-terminal") ;; --disable-server → provides a blocking terminal window (instead of a non-blocking one which swallows the revert-buffer afterward) (dired-do-shell-command (concat "xfce4-terminal --disable-server --geometry=90x5+330+5 --hide-menubar -x " my-appendfilename-file " *") nil marked-files) ) ) (revert-buffer nil t t) ) (define-key dired-mode-map (kbd "M-a") 'my-dired-appendfilename) #+END_SRC ** my-dired-filetags-filter → F1 :PROPERTIES: :CREATED: [2018-06-30 Sat 19:31] :END: #+BEGIN_SRC emacs-lisp (defun my-dired-filetags-filter () "Run \"filetags --filter\" on current or marked files" (interactive) (let* ((marked-files (f-uniquify (dired-get-marked-files)))) ;; apply to single file or marked files (when (my-system-type-is-windows) (dired-do-shell-command "FIXXME xfce4-terminal --geometry=100x20+330+5 --hide-menubar -x /home/vk/bin/filetags --interactive *" nil marked-files) ) (when (my-system-type-is-gnu) ;; FIXXME: maybe add check for binary: (when (my-eval-if-binary-or-warn "xfce4-terminal") (dired-do-shell-command (concat "xfce4-terminal --geometry=90x5+330+5 --hide-menubar -x " my-filetags-file " --filter *") nil marked-files) ) ) ) #+END_SRC ** my-dired-filetags-filter-recursive → F1 :PROPERTIES: :CREATED: [2018-06-30 Sat 19:31] :END: #+BEGIN_SRC emacs-lisp (defun my-dired-filetags-filter-recursive () "Run \"filetags --filter --recursive\" on current or marked files" (interactive) (let* ((marked-files (f-uniquify (dired-get-marked-files)))) ;; apply to single file or marked files (when (my-system-type-is-windows) (dired-do-shell-command "FIXXME xfce4-terminal --geometry=100x20+330+5 --hide-menubar -x /home/vk/bin/filetags --interactive *" nil marked-files) ) (when (my-system-type-is-gnu) ;; FIXXME: maybe add check for binary: (when (my-eval-if-binary-or-warn "xfce4-terminal") (dired-do-shell-command (concat "xfce4-terminal --geometry=90x5+330+5 --hide-menubar -x " my-filetags-file " --filter --recursive *") nil marked-files) ) ) ) #+END_SRC ** my-dired-tagtrees → F1 :PROPERTIES: :CREATED: [2018-06-30 Sat 19:32] :END: #+BEGIN_SRC emacs-lisp (defun my-dired-tagtrees () "Run \"filetags --tagtrees\" on current or marked files" (interactive) (let* ((marked-files (f-uniquify (dired-get-marked-files)))) ;; apply to single file or marked files (when (my-system-type-is-windows) (dired-do-shell-command "filetags --tagtrees --tagtrees-handle-no-tag no-tags" nil marked-files) ) (when (my-system-type-is-gnu) ;; FIXXME: maybe add check for binary: (when (my-eval-if-binary-or-warn "xfce4-terminal") (dired-do-shell-command (concat "xfce4-terminal --geometry=90x5+330+5 --hide-menubar -x " my-filetags-file " --tagtrees --tagtrees-handle-no-tag no-tags *") nil marked-files) ) ) ) #+END_SRC ** my-dired-tagtrees-recursive → F1 :PROPERTIES: :CREATED: [2018-06-30 Sat 19:32] :END: #+BEGIN_SRC emacs-lisp (defun my-dired-tagtrees-recursive () "Run \"filetags --tagtrees --recursive\" on current or marked files" (interactive) (let* ((marked-files (f-uniquify (dired-get-marked-files)))) ;; apply to single file or marked files (when (my-system-type-is-windows) (dired-do-shell-command "C:\\Python36\\Scripts\\filetags.exe --tagtrees --recursive --tagtrees-handle-no-tag no-tags *" nil marked-files) ) (when (my-system-type-is-gnu) ;; FIXXME: maybe add check for binary: (when (my-eval-if-binary-or-warn "xfce4-terminal") (dired-do-shell-command (concat "xfce4-terminal --geometry=90x5+330+5 --hide-menubar -x " my-filetags-file " --tagtrees --recursive --tagtrees-handle-no-tag no-tags *") nil marked-files) ) ) ) #+END_SRC ** my-dired-date2name → F1 :PROPERTIES: :CREATED: [2018-06-30 Sat 19:32] :END: #+BEGIN_SRC emacs-lisp (defun my-dired-date2name () "Run \"time2name\" on current or marked files" (interactive) (let* ((marked-files (f-uniquify (dired-get-marked-files)))) ;; apply to single file or marked files (dired-do-shell-command (concat my-date2name-file " *") nil marked-files) ) (revert-buffer nil t t) ;; refresh listing of files ) #+END_SRC ** my-dired-time2name → F1 :PROPERTIES: :CREATED: [2018-06-30 Sat 19:32] :END: #+BEGIN_SRC emacs-lisp (defun my-dired-time2name () "Run \"date2name --withtime\" on current or marked files" (interactive) (let* ((marked-files (f-uniquify (dired-get-marked-files)))) ;; apply to single file or marked files (dired-do-shell-command (concat my-date2name-file " --withtime *") nil marked-files) ) (revert-buffer nil t t) ;; refresh listing of files ) #+END_SRC ** my-open-in-external-app → C-c C-o :PROPERTIES: :CREATED: [2018-07-01 Sun 10:19] :END: from http://ergoemacs.org/emacs/emacs_dired_open_file_in_ext_apps.html #+BEGIN_SRC emacs-lisp (defun my-dired-open-in-external-app () "Open the current file or dired marked files in external app. The app is chosen from your OS's preference. URL `http://ergoemacs.org/emacs/emacs_dired_open_file_in_ext_apps.html' Version 2016-10-15" (interactive) (let* ( ($file-list (if (string-equal major-mode "dired-mode") (dired-get-marked-files) (list (buffer-file-name)))) ($do-it-p (if (<= (length $file-list) 5) t (y-or-n-p "Open more than 5 files? ")))) (when $do-it-p (cond ((string-equal system-type "windows-nt") (mapc (lambda ($fpath) (w32-shell-execute "open" (replace-regexp-in-string "/" "\\" $fpath t t))) $file-list)) ((string-equal system-type "darwin") (mapc (lambda ($fpath) (shell-command (concat "open " (shell-quote-argument $fpath)))) $file-list)) ((string-equal system-type "gnu/linux") (mapc (lambda ($fpath) (let ((process-connection-type nil)) (start-process "" nil "xdg-open" $fpath))) $file-list)))))) #+END_SRC #+BEGIN_SRC emacs-lisp (define-key dired-mode-map (kbd "C-c C-o") 'my-dired-open-in-external-app) #+END_SRC Alternative: =openwith= from [[https://github.com/jpkotta/openwith/tree/1dc89670822966fab6e656f6519fdd7f01e8301a][this GitHub page]] mentioned by [[https://cestlaz.github.io/post/using-emacs-71-openwith/][Using Emacs 71 Openwith]]. ** my-dired-open-in-file-manager → F1 :PROPERTIES: :CREATED: [2018-07-01 Sun 10:29] :END: This is =xah-show-in-desktop()= from http://ergoemacs.org/emacs/emacs_dired_open_file_in_ext_apps.html and adapted a bit: - file-truename() to translate relative paths to absolute - thunar as default manager on Linux - [ ] FIXXME: OS switching commands #+BEGIN_SRC emacs-lisp (defun my-dired-open-in-file-manager () "Show current file in desktop. (Mac Finder, Windows Explorer, Linux file manager) This command can be called when in a file or in `dired'. URL `http://ergoemacs.org/emacs/emacs_dired_open_file_in_ext_apps.html' Version 2018-01-13 adapted by Karl Voit 2018-07-01" (interactive) (let (($path (file-truename (if (buffer-file-name) (buffer-file-name) default-directory )))) (cond ((string-equal system-type "windows-nt") (w32-shell-execute "explore" (replace-regexp-in-string "/" "\\" $path t t))) ((string-equal system-type "darwin") (if (eq major-mode 'dired-mode) (let (($files (dired-get-marked-files ))) (if (eq (length $files) 0) (shell-command (concat "open " (shell-quote-argument default-directory))) (shell-command (concat "open -R " (shell-quote-argument (car (dired-get-marked-files ))))))) (shell-command (concat "open -R " $path)))) ((string-equal system-type "gnu/linux") (let ( (process-connection-type nil) (openFileProgram (if (file-exists-p "/usr/bin/thunar") "/usr/bin/thunar" "/usr/bin/xdg-open"))) (start-process "" nil openFileProgram $path)) ;; (shell-command "xdg-open .") ;; 2013-02-10 this sometimes froze emacs till the folder is closed. eg with nautilus )))) #+END_SRC ** my-dired-mark-images-and-thumbnail → F1 :PROPERTIES: :CREATED: [2018-07-01 Sun 10:48] :END: #+BEGIN_SRC emacs-lisp (defun my-dired-mark-images-and-thumbnail () "Mark all image files in dired (png, PNG, jpg, JPG, jpeg, JPEG) and start image-dired+." (interactive) (dired-mark-extension '("png" "jpg" "PNG" "JPG" "jpeg" "JPEG" "tif" "tiff" "TIF" "TIFF" "gif" "GIF")) (image-dired-display-thumbs) ) #+END_SRC #+RESULTS: : my-dired-mark-images-and-thumbnail ** my-dired-copy-filename-as-absolute-link → F1 :PROPERTIES: :CREATED: [2018-07-05 Thu 18:27] :END: I often link files in Org mode documents with their full path such as : [[file:c:/Users/karl.voit/2del/2018-07-04T15.35.42 Outlook - changing recurring events deletes all exceptions -- screenshots.png]] This would require 1. select a file 2. copy the absolute path name in dired via =M-0 w= 3. switch to the Org buffer 4. type : [[file: 5. yank the kill ring element containing the absolute path 6. finish the link with =]]= Following function avoids human error and reduces this process to: 1. select a file 2. call the function below via my hydra 3. switch to a Org buffer 4. yank the working link from the kill ring #+BEGIN_SRC emacs-lisp (defun my-dired-copy-filename-as-absolute-link (&optional arg) "Copy current file name with absolute path as [[file:]] link. If the universal argument is given, the path is omitted in the link description." (interactive "P") (dired-copy-filename-as-kill 0) ;; current absolute path to kill ring (let* ((path (current-kill 0))) ;; get topmost kill ring element (if (equal arg '(4)) ;; universal argument is set: (kill-new (concat "[[file:" path "][" (helm-basename path) "]]")) ;; write back new/modified kill ring element ;; universal argument is not set: (kill-new (concat "[[file:" path "]]")) ;; write back new/modified kill ring element ) ) ) #+END_SRC ** my-dired-copy-filename-as-tsfile-link → F1 :PROPERTIES: :CREATED: [2018-07-05 Thu 18:28] :END: Same explanation as =my-dired-copy-filename-as-absolute-link= holds but with the result being a =tsfile:= link I use to link to Memacs-indexed files (see Org Mode customized links): #+BEGIN_SRC emacs-lisp (defun my-dired-copy-filename-as-tsfile-link () "Copy current file name with its basename as [[tsfile:]] custom org-mode link." (interactive) (dired-copy-filename-as-kill) ;; current file name to kill ring (let* ((filename (current-kill 0))) ;; get topmost kill ring element (kill-new (concat "[[tsfile:" filename "]]")) ;; write back new/modified kill ring element ) ) #+END_SRC ** my-dired-copy-filename-as-lfile-link → F1 :PROPERTIES: :CREATED: [2023-08-25 Fri 16:27] :END: Same explanation as =my-dired-copy-filename-as-tsfile-link= holds but with the result being a =tfile:= link I use to [[https://karl-voit.at/2022/02/10/lfile/][link to locate-indexed files]]: #+BEGIN_SRC emacs-lisp (defun my-dired-copy-filename-as-lfile-link () "Copy current file name with its basename as [[lfile:]] custom org-mode link." (interactive) (dired-copy-filename-as-kill) ;; current file name to kill ring (let* ((filename (current-kill 0))) ;; get topmost kill ring element (kill-new (concat "[[lfile:" filename "][" filename "]]")) ;; write back new/modified kill ring element ) ) #+END_SRC ** my-dired-open-here-in-tmux-shell :PROPERTIES: :CREATED: [2018-09-04 Tue 18:44] :END: Sometimes, I need the current directory showed in my [[https://en.wikipedia.org/wiki/Tmux][tmux]] session running in background. This is how it's done. - [ ] FIXXME: find a working solution for Windows 10 #+BEGIN_SRC emacs-lisp (defun my-dired-open-here-in-tmux-shell() (interactive) (cond ((my-system-type-is-windows) (message (concat "NOT Opening current dir in Windows/Cygwin tmux (NOT IMPLEMENTED AND TESTED YET): " dired-directory)) ;; see id:2018-09-02-open-dir-in-tmux for details on the development and Windows issues ;;(mapc (lambda (fPath) (w32-shell-execute "open" (replace-regexp-in-string "/" "\\" fPath t t)) ) myFileList) ) ((string-equal system-type "darwin") (message (concat "NOT Opening current dir in macOS tmux (NOT IMPLEMENTED AND TESTED YET): " dired-directory)) ) ((my-system-type-is-gnu) (message (concat "Opening current dir in linux tmux: " dired-directory)) ;; OLD: (shell-command (concat "tmux new-window 'cd \"" dired-directory "\"; pwd; zsh -i'")) (dired-smart-shell-command "xfce4-terminal --execute tmux") ) ) ) #+END_SRC ** orly :PROPERTIES: :CREATED: [2020-04-13 Mon 16:44] :END: | 2020-04-13 | setup for testing | | 2023-01-08 | still no *elpa; updated git | This package got recommended for a specific [[https://github.com/abo-abo/oremacs/issues/27][issue I faced using interactive Python scripts]]. #+BEGIN_SRC emacs-lisp (use-package orly ;;:if (my-system-type-is-gnu) :load-path (lambda () (expand-file-name (concat my-user-emacs-directory "contrib/orly/"))) ;;:defer 110 :after org ) #+END_SRC ** filetags.el → F1 :PROPERTIES: :CREATED: [2018-07-04 Wed 15:43] :END: | 2023-01-08 | switched to melpa version | https://github.com/beutelma/filetags.el provides =filetags-dired-update-tags()= which is an Elisp-native re-implementation of my [[https://github.com/novoid/filetags/][filetags]]: #+BEGIN_SRC emacs-lisp (use-package filetags :ensure t :config (setq filetags-enforce-controlled-vocabulary nil) ;; let me invent new tags on the fly (might not be a good idea anyway!) (setq filetags-load-controlled-vocabulary-from-file t) ;; read CV from .filetags files within same or upper directories ;;ignored;; (setq filetags-controlled-vocabulary '("confidential" "restricted" "public" "internal" "internaluse" ;;ignored;; "license" "demos" "proposals" "flipcharts" "data" "draft" "final" "screenshots" "travel" ;;ignored;; "templates" "contracts" "processes")) ) #+END_SRC ** date2name → F1 :PROPERTIES: :CREATED: [2018-07-08 Sun 15:55] :END: | 2023-01-08 | switched to use-package melpa version, still not using it actively | https://github.com/beutelma/date2name.el provides =date2name-dired-add-date-to-name()= which is an Elisp-native re-implementation of my [[https://github.com/novoid/date2name][date2name]]: #+BEGIN_SRC emacs-lisp (use-package date2name :ensure t :config (setq date2name-enable-smart-separation-character-chooser t) ;; 2018-07-21: https://github.com/DerBeutlin/date2name.el/issues/1#issuecomment-406787333 (defun file-attribute-modification-time (attributes) "extracts the modification time from ATTRIBUTES" (nth 5 attributes)) ) #+END_SRC - [ ] FIXXME: replace date2name.py with it if it is well tested - [ ] FIXXME: map to a direct key - [ ] FIXXME: add to cheatsheet (hydra): ask for day when used with universal prefix - [ ] FIXXME: do for time2name as well ** dwim-shell-command :PROPERTIES: :ID: 2023-07-07-dwim-shell-command :END: | 2023-07-07 | used by https://xenodium.com/duplicate-this/ together with id:2023-07-07-crux and id:2023-07-07-dwim-shell-commands-duplicate | #+BEGIN_SRC emacs-lisp (use-package dwim-shell-command :ensure t :bind (:map dired-mode-map ("C-c d" . dwim-shell-commands-duplicate)) :config ;; Loads all my own dwim shell commands. (require 'dwim-shell-commands)) #+END_SRC #+BEGIN_SRC emacs-lisp :tangle no (use-package dwim-shell-command :ensure t ) #+END_SRC ** dwim-shell-commands-duplicate :PROPERTIES: :ID: 2023-07-07-dwim-shell-commands-duplicate :END: | 2023-07-07 | used by https://xenodium.com/duplicate-this/ together with id:2023-07-07-crux | #+BEGIN_SRC emacs-lisp (defun dwim-shell-commands-duplicate () "Duplicate file(s)." (interactive) (dwim-shell-command-on-marked-files "Duplicate file(s)." "cp -R '<>' '<>'" :utils "cp")) #+END_SRC ** dired-preview | 2023-09-24 | inital setup for trying | #+BEGIN_SRC emacs-lisp (use-package dired-preview :ensure t :defer 110 :config (setq dired-preview-delay 0.7) (setq dired-preview-max-size (expt 2 20)) (setq dired-preview-ignored-extensions-regexp (concat "\\." "\\(mkv\\|webm\\|mp4\\|mp3\\|ogg\\|m4a" "\\|gz\\|zst\\|tar\\|xz\\|rar\\|zip" "\\|iso\\|epub\\|pdf\\)")) ;; Enable `dired-preview-mode' in a given Dired buffer or do it ;; globally: (dired-preview-global-mode 1) ;; my up/down keys are mapped to different commands than default, as it seams: (add-to-list 'dired-preview-trigger-commands 'diredp-previous-line) (add-to-list 'dired-preview-trigger-commands 'diredp-next-line) ) #+END_SRC ** DISABLED casual-dired | 2024-05-11 | testing | - I've read http://yummymelon.com/devnull/announcing-casual-dired---an-opinionated-porcelain-for-the-emacs-file-manager.html and found https://github.com/kickingvegas/casual-dired pretty cool. I'll add it to my hydra for now. - *requires Emacs 29.1* → re-try later - [ ] add =casual-dired-tmenu= to my dired hydra #+BEGIN_SRC emacs-lisp (use-package casual-dired :ensure t :defer 110 ) #+END_SRC ** DISABLED dired-show-readme :PROPERTIES: :CREATED: [2020-04-11 Sat 10:43] :END: | 2020-04-11 | installed for testing purposes | | 2020-04-11 | disabled because it did not work on my README.org files | From [[https://www.reddit.com/r/emacs/comments/fyfpad/diredshowreadme_show_readme_in_dired_like_github/][this reddit thread]] I found [[https://gitlab.com/kisaragi-hiu/dired-show-readme][dired-show-readme]] which displays README files of various formats (using pandoc conversion) within the directory they are located. Although I don't need this particular function, I set it up to test it. #+BEGIN_SRC emacs-lisp (use-package dired-show-readme :load-path (lambda () (expand-file-name (concat my-user-emacs-directory "contrib/dired-show-readme/"))) ;:defer 110 ;:after dired :config (setq dired-show-readme-position "bottom") ;; (setq dired-show-readme-pandoc-executable "/usr/bin/pandoc");; on sting, this is the default (add-hook 'dired-mode-hook 'dired-show-readme-mode) ) #+END_SRC ** locate | 2024-05-29 | Maybe I like to use "locate" within Emacs from time to time | Make =locate= command case insensitive: https://www.emacswiki.org/emacs/locate #+BEGIN_SRC emacs-lisp (defun my-locate-make-command-line (search-string) "Make an insensitive locate command line" (list locate-command "-i" search-string)) (when (my-system-type-is-gnu) (setq locate-make-command-line 'my-locate-make-command-line)) #+END_SRC * Email :PROPERTIES: :CREATED: [2019-12-19 Thu 14:37] :END: ** DISABLED isync + notmuch | 2021-02-13 | disabled since I can't use business email with Emacs | | 2023-01-08 | still not on *elpa; no newer version (unmaintained?) | This is my email setup for [[https://notmuchmail.org/notmuch-emacs/][notmuch]] I use together with isync/mbsync/ #+BEGIN_SRC emacs-lisp (use-package notmuch :if (my-system-type-is-gnu) :config (load-library "smtpmail") (setq smtpmail-default-smtp-server my-business-mail-server smtpmail-local-domain my-business-mail-server) (setq send-mail-function 'smtpmail-send-it smtpmail-smtp-server my-business-mail-server smtpmail-stream-type 'starttls smtpmail-smtp-service 587 mail-host-address my-business-mail-host-address) ;; Somehow, this variable gets overwritten by something to 'message-send-mail-with-outlook ;; and therefore it's been set in "custom variables" as well. (setq message-send-mail-function 'message-smtpmail-send-it) (setq notmuch-message-headers '("Subject" "To" "Cc" "Date" "Reply-To")) (setq notmuch-mua-cite-function 'message-cite-original-without-signature) (setq notmuch-saved-searches '((:name "inbox" :query "tag:inbox" :key "i") (:name "unread" :query "tag:unread" :key "u") (:name "flagged" :query "tag:flagged" :key "f") (:name "sent" :query "tag:sent" :key "t") (:name "drafts" :query "tag:draft" :key "d") (:name "all mail" :query "*" :key "a") (:name "Sent" :query "folder:archive"))) (setq message-default-headers "Reply-to: \nCC: \nBCC: \n") (setq notmuch-fcc-dirs "archive") ;;(when (my-system-is-jackson) ;; (setq notmuch-command "notmuch.cmd") ;;) (add-hook 'notmuch-message-mode-hook #'footnote-mode) (add-hook 'notmuch-message-mode-hook #'auto-dictionary-mode) (add-hook 'notmuch-message-mode-hook #'flyspell-mode) ;; ignore email header for flyspell (and thus dictionary mode): ;; https://www-sop.inria.fr/members/Manuel.Serrano/flyspell/flyspell-1.7q.el ;; as of 2019-12-21: doesn't work as it uses in German emails the English one :-( (add-hook 'notmuch-message-mode-hook '(lambda () (setq flyspell-generic-check-word-p 'mail-mode-flyspell-verify))) (defun my-notmuch-sync-and-update-index-and-buffer () "Update the index after sync." (interactive) (call-process (concat my-user-emacs-directory "bin/mbsync_notmuch.sh") nil nil t "");; necessary to untag my own emails with -new (notmuch-poll) (notmuch-refresh-this-buffer)) ; (when (not (my-system-is-jackson)) (define-key notmuch-hello-mode-map "g" 'my-notmuch-sync-and-update-index-and-buffer) ; ) ) #+END_SRC switch to open notmuch biffer or open new one: #+BEGIN_SRC emacs-lisp (defun my-notmuch (&optional arg) "Opens the already opened notmuch buffer or opens new one instead." (interactive "P") (when (my-system-type-is-gnu) (my-notmuch-sync-and-update-index-and-buffer) (if (my-buffer-exists "*notmuch-hello*") (switch-to-buffer "*notmuch-hello*") (notmuch) ) ) ) ;; (bind-key "n" 'my-notmuch my-map) → within "Key bindings" heading since binding overwrites a standard Org mode binding #+END_SRC from: https://gist.github.com/fedxa/fac592424473f1b70ea489cc64e08911 Provides Org mode links to notmuch emails: copy with =C-c l= (org-notmuch-store-link) + paste with =C-c C-l= #+BEGIN_SRC emacs-lisp (use-package org-notmuch :if (my-system-type-is-gnu) :load-path (lambda () (expand-file-name (concat my-user-emacs-directory "contrib/"))) ) #+END_SRC Adding a key mapping for "d" to add "deleted" tag and remove "inbox" and "unread": [[https://notmuchmail.org/emacstips/#index5h2][Source]] #+BEGIN_SRC emacs-lisp (define-key notmuch-search-mode-map "d" (lambda () "mark message as deleted" (interactive) (notmuch-show-tag (list "+deleted" "-inbox" "-unread")))) (define-key notmuch-show-mode-map "d" (lambda () "mark message as deleted" (interactive) (notmuch-show-tag (list "+deleted" "-inbox" "-unread")))) (define-key notmuch-tree-mode-map "d" (lambda () "mark message as deleted" (interactive) (notmuch-show-tag (list "+deleted" "-inbox" "-unread")))) #+END_SRC Open the current email in Thunderbird: #+BEGIN_SRC emacs-lisp (define-key notmuch-search-mode-map "T" (lambda () "open in Thunderbird" (interactive) ;; FIXXME: I can't find the appropriate method to get current message ID in search results: (my-open-message-id-in-thunderbird (notmuch-show-get-message-ids-for-open-messages t)) )) (define-key notmuch-show-mode-map "T" (lambda () "open in Thunderbird" (interactive) (my-open-message-id-in-thunderbird (notmuch-show-get-message-id t)) )) #+END_SRC As of 2021-01-07, I stop using notmuch (again) because of: - Thunderbird is good enough for now - I still need Thunderbird in parallel → I prefer to avoid the switching back and forth effort + additional Maildir data for notmuch - no appointment inviation handling on receiving - not being able to create standard appointment invitations - no HTML or rendering HTML content takes some time - notmuch does not offer an out-of-the-box possibility to delete emails: https://www.reddit.com/r/emacs/comments/6wqfp3/notmuch_delete_mail/ - [[https://web.archive.org/web/20190615040045/http://www.holgerschurig.de:80/en/notmuch-polling-with-mbsync/][workaround]] FIXXME: https://www.reddit.com/r/emacs/comments/kqixcg/notmuch_how_to_get_messageid_open_current_email/ #+BEGIN_QUOTE In search you are normally looking at threads, not individual messages—that's why you have notmuch-search-find-thread-id. But if you write a function that picks an appropriate ID from the result of notmuch-search-find-stable-query that should be the easiest way to go. #+END_QUOTE FIXXME: https://www.reddit.com/r/emacs/comments/kqixcg/notmuch_how_to_get_messageid_open_current_email/gi64fu2/?context=3 #+BEGIN_QUOTE As /u/oritron explained, in default search view, you get results not in form of message ids, but in form on thread ids, even if there is a single message in that thread. However, if you use notmuch-tree (see M-x notmuch-tree), you will get message ids, because threads will be represented as a tree. To access message id for highlighted/selected mail, see notmuch-show-stash-message-id function. For or certain (Confluence notification) emails, rendering the HTML content takes 20-30 seconds, blocking my Emacs instance which is very upsetting at last to me My approach is to use lynx for rendering html, because it is really fast. If I need to look it further, I open that message part in browser (go with cursor to text/html box, hit . o and notmuch will ask you for viewer. Enter firefox or chromium... You can't beat html rendering with the real browser :D To set lynx as default html renderer use this: (setq mm-text-html-renderer 'lynx) or check other options. #+END_QUOTE ** DISABLED Thunderbird | 2021-02-26 | With an unintended upgrade from Thunderbird 68 to 78, the original =thunderlink= is broken. | | 2021-02-28 | Setup of [[https://camiel.bouchier.be/en/cb_thunderlink][cb_thunderlink]] as a TB 78.x replacement | | 2021-05-26 | Moved from Thunderbird to GNOME Evolution, disabling this | I got this workflow from https://vxlabs.com/2019/04/20/link-thunderbird-emails-from-emacs-orgmode/ Internal notes: id:2020-01-09-link-emails-from-to-Thunderbird-Org Helper function to open any given message-id in Thunderbird: #+BEGIN_SRC emacs-lisp ;; modify this for your system (setq thunderbird-program "/usr/bin/thunderbird") (defun my-open-message-id-in-thunderbird (message-id) "open an email with a given message-ID in Thunderbird" (interactive) (start-process (concat "thunderlink: " message-id) nil thunderbird-program "-thunderlink" (concat "thunderlink://messageid=" message-id) ) ) #+END_SRC #+BEGIN_SRC emacs-lisp ;; modify this for your system (setq thunderlink-program (concat (expand-file-name "~") "/cb_thunderlink/cb_thunderlink")) (defun my-open-message-id-in-thunderbird (message-id) "open an email with a given message-ID in Thunderbird" (interactive) (start-process (concat "thunderlink: " message-id) nil thunderlink-program (concat "thunderlink://messageid=" message-id) ) ) #+END_SRC #+BEGIN_SRC emacs-lisp ;; with org-mac-link message:// links are handed over to the macOS system, ;; which has built-in handling. On Windows and Linux, we can use thunderlink! (when (not (string-equal system-type "darwin")) (defun org-message-thunderlink-open (slash-message-id) "Handler for org-link-set-parameters that converts a standard message:// link into a thunderlink and then invokes thunderbird." ;; remove any / at the start of slash-message-id to create real message-id (let ((message-id (replace-regexp-in-string (rx bos (* ":")) "" slash-message-id))) (my-open-message-id-in-thunderbird message-id) )) ;; on message://aoeu link, this will call handler with //aoeu (org-link-set-parameters "messageid" :follow #'org-message-thunderlink-open) ) #+END_SRC Note that the link colors are set via =my-set-linkcolors=. - test link for testing color: [[messageid:this-is-a-test@example.com][2020-07-27T15:57:45.000Z First Last: Subject]] Installation: 1. install "Thunderlink" add-on in Thunderbird 2. close Thunderbird 3. manually add the snippet below to the =prefs.js= of the Thunderbird profile 4. activate the Elisp code above within Emacs 5. start Thunderbird #+BEGIN_EXAMPLE user_pref("extensions.thunderlink.custom-tl-string-1-title", "Org mode message-ID"); user_pref("extensions.thunderlink.custom-tl-string-1", "[[messageid:][