MHFTGEZMCZ3BPPPX7WGTGCCT7U6GFJPMNLG3XKMEWAB6ICDEQU6AC #-*- mode: org -*-#+TITLE: Emacs Setup for Programming Languages#+AUTHOR: Volker Edelmann#+EMAIL: vedelmann@gmx.de#+STARTUP: indent#+OPTIONS: toc:nil#+OPTIONS: ^:{}src emacs-lisp;; -*- coding: utf-8; lexical-binding: t -*-#+end_src* Introduction- REPL- editing- editing paradigm- code completion- templates- moving- selecting- code folding- static syntax checking- compilation- debugging- project-management** UIA General Local Leader Map is setup to provide a common/similar UIother all programming languages used.The Prefix is C-S-<space>. The ~which-key~ Package provides help on the keys.If there is need for a modal interface, a Major-Mode-Hydra can be defined.Bind in mayor-mode keymap to:#+begin_example:bind ( :map KEYMAP("M-SPC" . major-mode-hydra))#+end_exampleAlso, repeat-maps can help for movement and marking.** Lisp-like (s-expression) languages- emacs-lisp- clojure- [guile (scheme)]- [hy]** Languages with Tree-sitter grammars*** Exploring- combobulate- Built-In commands: treesit-explore-mode*** Tree-sitterstore grammars in a common location#+begin_src emacs-lisp(setq treesit-extra-load-path (list (concat emacsen-dir "treesit/grammars/") ))#+end_src#+begin_src emacs-lisp(use-package emacs:mode (("\\.tsx\\'" . tsx-ts-mode)):preface(defun mp-setup-install-grammars ()"Install Tree-sitter grammars if they are absent."(interactive)(dolist (grammar'((css . ("https://github.com/tree-sitter/tree-sitter-css" "v0.20.0"))(html . ("https://github.com/tree-sitter/tree-sitter-html" "v0.20.1"))(javascript . ("https://github.com/tree-sitter/tree-sitter-javascript" "v0.20.1" "src"))(json . ("https://github.com/tree-sitter/tree-sitter-json" "v0.20.2"))(python . ("https://github.com/tree-sitter/tree-sitter-python" "v0.20.4"))(toml "https://github.com/tree-sitter/tree-sitter-toml")(tsx . ("https://github.com/tree-sitter/tree-sitter-typescript" "v0.20.3" "tsx/src"))(typescript . ("https://github.com/tree-sitter/tree-sitter-typescript" "v0.20.3" "typescript/src"))(yaml . ("https://github.com/ikatyang/tree-sitter-yaml" "v0.5.0"))))(add-to-list 'treesit-language-source-alist grammar);; Only install `grammar' if we don't already have it;; installed. However, if you want to *update* a grammar then;; this obviously prevents that from happening.(unless (treesit-language-available-p (car grammar))(treesit-install-language-grammar (car grammar)))));; Optional, but recommended. Tree-sitter enabled major modes are;; distinct from their ordinary counterparts.;;;; You can remap major modes with `major-mode-remap-alist'. Note;; that this does *not* extend to hooks! Make sure you migrate them;; also(dolist (mapping'((python-mode . python-ts-mode)(css-mode . css-ts-mode)(typescript-mode . typescript-ts-mode)(js2-mode . js-ts-mode)(bash-mode . bash-ts-mode)(css-mode . css-ts-mode)(json-mode . json-ts-mode)(js-json-mode . json-ts-mode)))(add-to-list 'major-mode-remap-alist mapping)):config(mp-setup-install-grammars);; Do not forget to customize Combobulate to your liking:;;;; M-x customize-group RET combobulate RET;;)#+end_src**** Additional GrammarsRepos, where grammars are found:#+begin_src emacs-lisp(setq treesit-language-source-alist'((awk "https://github.com/Beaglefoot/tree-sitter-awk")(bash "https://github.com/tree-sitter/tree-sitter-bash")(c . ("https://github.com/tree-sitter/tree-sitter-c"))(cpp . ("https://github.com/tree-sitter/tree-sitter-cpp"))(cmake . ("https://github.com/uyha/tree-sitter-cmake"))(d . ("https://github.com/gdamore/tree-sitter-d"))(julia "https://github.com/tree-sitter/tree-sitter-julia")(kotlin "https://github.com/fwcd/tree-sitter-kotlin")(lua . ("https://github.com/Azganoth/tree-sitter-lua"))(make "https://github.com/alemuller/tree-sitter-make")(markdown "https://github.com/ikatyang/tree-sitter-markdown")(perl "https://github.com/tree-sitter-perl/tree-sitter-perl")(php . ("https://github.com/tree-sitter/tree-sitter-php"))(sql "https://github.com/m-novikov/tree-sitter-sql")(scala "https://github.com/tree-sitter/tree-sitter-scala")))#+end_srcCheck if a grammar is available:(treesit-language-available-p 'd)* Visuals** Parentheses, brackets, ...#+begin_src emacs-lisp(require 'elec-pair)#+end_src** Project Browser*** DISCARDED dired-sidebarcannot display fd-dired queries* Folding* EditingIn Lisp-like modes, there are perhaps better alternatives:- lispy- paredit- smartparens** vim-Styleusing viper-modeBackup: viper mode can temporarily activated** DONE Puniwrong direction* Project Management#+begin_src emacs-lisp(put 'compile-command 'safe-local-variable t)(setq enable-local-variables :safe)#+end_src* Static Checkers/LintersAlthough flymake is an Emacs built-in, flycheck has more checkers and often works without further configuration when a checker/linter is available vi the OS path settings.** Builtin: flymakeDiagnostics: flymake-show-buffer-diagnostics#+begin_src emacs-lisp(require 'flymake)(use-package emacs:config(setq flymake-mode-line-lighter t))#+end_src* Finding and referencing symbols** Language Servershttps://langserver.org/*** Built-In eglot#+begin_src emacs-lisp(use-package eglot:custom(eglot-autoshutdown t)(eglot-events-buffer-size 0)(eglot-extend-to-xref nil)(eglot-ignored-server-capabilities'(:hoverProvider:documentHighlightProvider:documentFormattingProvider:documentRangeFormattingProvider:documentOnTypeFormattingProvider:colorProvider:foldingRangeProvider))(eglot-stay-out-of '(yasnippet tempel)))#+end_src* References#+begin_src emacs-lisp(use-package xref:pin gnu:custom(xref-auto-jump-to-first-xref t)(xref-file-name-display 'project-relative)(xref-search-program 'ripgrep):config(setq xref-show-xrefs-function #'consult-xrefxref-show-definitions-function #'consult-xref))#+end_src* Documentation#+begin_src emacs-lisp(use-package eldoc:pin gnu:diminish:bind ("s-d" . #'eldoc):custom(eldoc-echo-area-prefer-doc-buffer t)(eldoc-echo-area-use-multiline-p t))#+end_src* FoldingDepending on the mode, hideshow may be a good solution:#+begin_src emacs-lisp(use-package hideshow)(defun toggle-fold ()(interactive)(save-excursion(end-of-line)(hs-toggle-hiding)))#+end_src#+begin_src emacs-lisp;;; programming-common-setup.el ends here#+end_src
* XML- REPL- tree-sitter- Language-Server** Tree-sitterThere is no nxml-ts-mode yet.- moving around: nxml-modeForward elementC-M nBackward elementC-M pUP elementC-M uDown elementC-M d- selections:- expreg- evil-textobj-tree-sitter- folding- hideshow** LinterBuild into nxml-mode (needs a schema).https://lgfang.github.io/mynotes/emacs/emacs-xml.html#sec-3** Formatter#+begin_src emacs-lisp#+end_src** Auto Completionnxml-modehttps://www.gnu.org/software/emacs/manual/html_node/nxml-mode/Completion.html** Konfiguration#+begin_src emacs-lisp(require 'nxml-mode)(require 'sgml-mode)(require 'nxml-mode)(add-to-list 'hs-special-modes-alist'(nxml-mode"<!--\\|<[^/>]*[^/]>""-->\\|</[^/>]*[^/]>""<!--"sgml-skip-tag-forwardnil))(use-package emacs:pin gnu:bind (:map nxml-mode-map("C-+" . expreg-expand)("C--" . expreg-contract)("C-c h" . hs-toggle-hiding)):hook(nxml-mode . hs-minor-mode)(nxml-mode . yas-minor-mode)(nxml-mode . flycheck-mode):config)#+end_srcThere is a Hydra defined for ts-movement, open with <f5>.** Language Server*** void-Linux*** Windows#+begin_src sh#+end_src** UI*** General local leaderPrefix is C-S-<space>#+begin_src emacs-lisp(local-leader nxml-mode-map"+" '(yas-insert-snippet :wk "code snippets");; "j" '(hydra-tree-sitter-move/body :wk "movement hydra")"m" '(:ignore t :which-key "mark/select")"mp" '(mark-paragraph :wk "paragraph")"f" '(hydra-fold/body :wk "Folding");; "h" '(hs-toggle-hiding :wk "Folding: toggle"))#+end_src
#-*- mode: org -*-#+TITLE: Emacs Setup for the TCL/TK Programming Language#+AUTHOR: Volker Edelmann#+EMAIL: vedelmann@gmx.de#+STARTUP: indent#+OPTIONS: toc:nil#+OPTIONS: ^:{}#+begin_src emacs-lisp;; -*- coding: utf-8; lexical-binding: t -*-#+end_src* TCL/TKCategory: OthersA TCL program follows very simple grammatical rules. It is very easy towrite a parser.There is no language-server or tree-sitter grammar available as there seems to be noneed for it.a TCL is considered a homoiconic language.** REPL** Selections#+begin_src emacs-lisp(use-package expand-region:config;; patch expand-region for TCL(defun er/add-tcl-mode-expansions ()(make-variable-buffer-local 'er/try-expand-list)(setq er/try-expand-list (appender/try-expand-list'(er/mark-worder/mark-defuner/mark-paragraph))))(er/enable-mode-expansions 'tcl-mode 'er/add-tcl-mode-expansions))#+end_src** FoldingBest option is to use the built-in hideshow package.I would like the namespaces to be left unfolded if hs-fold-all is executed.#+begin_src emacs-lisp(use-package hideshow:custom(hs-isearch-open t))#+end_src** Static Checkerflycheck uses nagelfar. Put it on the PATH.#+begin_src emacs-lisp(add-to-list 'display-buffer-alist`(,(rx bos "*Flycheck errors*" eos)(display-buffer-reuse-windowdisplay-buffer-in-side-window)(side . bottom)(reusable-frames . visible)(window-height . 0.33)))#+end_src** TCL/TK#+begin_src emacs-lisp(use-package tcl:mode (("\\.tcl\\'" . tcl-mode)("\\.tcons\\'" . tcl-mode)("\\.svcf\\'" . tcl-mode)("\\.exp\\'" . tcl-mode)):bind(:map tcl-mode-map("C-c C-z" . inferior-tcl)("C-+" . er/expand-region)("C-<return>" . ve/tcl-eval-region-or-line)("C-S-<return>" . tcl-eval-defun)("<tab>" . completion-at-point)("C-c C-t" . nil)):init(env-setup "tcl")(defun ve/tcl-eval-buffer ()(interactive)(message "buffer")(tcl-eval-region (point-min) (point-max))(keyboard-quit))(defun ve/tcl-eval-region-or-line ()(interactive)(if (region-active-p)(tcl-eval-region (region-beginning) (region-end))(tcl-eval-region (progn(beginning-of-line) (point))(progn(end-of-line) (point))))(keyboard-quit))(defun ve/tcl-mode-customization ()"My customization for `tcl-mode'."(add-to-list 'completion-at-point-functions #'cape-keyword)(add-to-list 'completion-at-point-functions #'cape-dabbrev))(defun ve/outline-tcl ()"Fold only definitions for TCL buffers."(setq outline-regexp(rx (or;; Definitions(group (group (* space)) bow (or "proc" "namespace") eow);; Decorators(group (group (* space)) "@"))))(my/outline-overview)):config(setq tcl-indent-level 4tcl-continued-indent-level 8)(setq tcl-application "tclsh") ;; jimsh tclsh wish(setq flycheck-check-syntax-automatically '(save mode-enabled))(setq tcl-help-directory-list '("/usr/lib/tclx8.6/help"))(add-hook 'tcl-mode-hook #'ve/tcl-mode-customization)(add-hook 'tcl-mode-hook #'ve/outline-tcl)(add-hook 'tcl-mode-hook #'electric-pair-mode)(add-hook 'tcl-mode-hook #'electric-indent-mode):hook (tcl-mode . yas-minor-mode)(tcl-mode . flycheck-mode)(tcl-mode . hs-minor-mode)(tcl-mode . outline-minor-mode))#+end_src** UI#+begin_src emacs-lisp(local-leader tcl-mode-map"C-z" '(inferior-tcl :wk "REPL")"l" '(list-flycheck-errors :wk "diagnostics")"+" '(yas-insert-snippet :wk "code snippets")"b" '(ve/tcl-eval-buffer :wk "eval buffer")"s" '(:ignore t :which-key "mark/select")"sb" '(mark-whole-buffer :wk "buffer")"sf" '(mark-function :wk "function")"sp" '(mark-paragraph :wk "paragraph")"sw" '(er/mark-word :wk "word")"sc" '(er/mark-comment :wk "comment")"f" '(:ignore t :which-key "folding")"f>" '(hs-show-block :wk "show block")"f<" '(hs-hide-block :wk "hide block")"ft" '(hs-toggle-hiding :wk "toggle block visibility")"fs" '(hs-show-all :wk "show all")"fl" '(hs-hide-level :wk "hide level"))#+end_src"t" '(:ignore t :which-key "tags")"tf" '(ggtags-find-tag :wk "find tag")"tF" '(ggtags-find-tag-dwim :wk "find tag dwim")"t$" '(ggtags-find-tag-regexp :wk "find tag regexp")"td" '(ggtags-find-definition :wk "find definition")"tr" '(ggtags-find-reference :wk "find reference")"tg" '(ggtags-grep :wk "search db")"t%" '(ggtags-query-replace :wk "replace")"tu" '(ggtags-update-tags :wk "update db")* TODO Expect
* SQL- REPL- tree-sitter- Language-Server- Linter** Tree-sitterThere is no sql-ts-mode yet.- moving around: ts-movement- selections:- expreg- evil-textobj-tree-sitter- folding** TODO pgformatNo great value** sqlfluffinstalled as a command line tool- linter- formatter- template engineunfortunately not working with emacs** LinterUses sqlint ruby gem from Steve Purcell#+begin_src emacs-lisp(require 'sql)(require 'flycheck)#+end_src** Formatter#+begin_src emacs-lisp(use-package sqlup-mode)#+end_src#+begin_src emacs-lisp(require 'sql-indent);; Update indentation rules, select, insert, delete and update keywords;; are aligned with the clause start(defvar my-sql-indentation-offsets-alist`((select-clause 0)(insert-clause 0)(delete-clause 0)(update-clause 0),@sqlind-default-indentation-offsets-alist))(add-hook 'sqlind-minor-mode-hook(lambda ()(setq sqlind-indentation-offsets-alistmy-sql-indentation-offsets-alist)))#+end_src** Konfiguration#+begin_src emacs-lisp(require 'sql)(use-package emacs:pin gnu:bind (:map sql-mode-map("C-+" . expreg-expand)("C--" . expreg-contract)("S-<return>" . sql-send-string)("C-<return>" . sql-send-region)("M-<return>" . sql-send-paragraph)):hook(sql-mode . yas-minor-mode)(sql-mode . flycheck-mode)(sql-mode . sqlup-mode):config)#+end_srcThere is a Hydra defined for ts-movement, open with <f5>.** Language Server*** void-Linux*** WindowsUsing MSYS2:#+begin_src sh#+end_src** UI*** General local leaderPrefix is C-S-<space>#+begin_src emacs-lisp(local-leader sql-mode-map;; "c" '(sql-connect :wk "connect to database");; "p" '(python-shell-switch-to-shell :wk "py-shell")"+" '(yas-insert-snippet :wk "code snippets")"j" '(hydra-tree-sitter-move/body :wk "movement hydra")"x" '(:ignore t :which-key "execute in REPL")"xb" '(sql-send-buffer :wk "buffer")"xp" '(sql-send-paragraph :wk "paragraph")"xs" '(sql-send-string :wk "string")"m" '(:ignore t :which-key "mark/select")"mp" '(mark-paragraph :wk "paragraph")"mf" '(mark-defun :wk "function")"mF" '((evil-textobj-tree-sitter-get-textobj "function.outer") :wk "function")"f" '(hydra-fold/body :wk "Folding"))#+end_src
* PythonPython gehort zu den popularsten Sprachen (Stand 2023). Viele Leute entwicklen mit Emacs.Daher ist die Unterstutzung der Sprache sehr gut. Eine Tree-Sitter-Grammatik undmehrere LSP-Server sind verfugbar.** Tree-sitter#+begin_src emacs-lisp(push '(python-mode . python-ts-mode) major-mode-remap-alist)#+end_src- moving around: ts-movement- selections:- expreg- ts-movement Hydra- evil-textobj-tree-sitter- folding** Konfiguration#+begin_src emacs-lisp(use-package python:pin gnu:bind (:map python-ts-mode-map("C-+" . expreg-expand)("C--" . expreg-contract)("S-<return>" . python-shell-send-statement)("C-<return>" . python-shell-send-region)("M-<return>" . nil)):hook(python-ts-mode . ts-movement-mode)(python-ts-mode . yas-minor-mode):config(when (executable-find "ipython3")(setq python-shell-interpreter "ipython3"python-shell-interpreter-args "--simple-prompt --classic")))#+end_srcThere is a Hydra defined for ts-movement, open with C-.** Language ServerVerwende den jedi-Server, da er auf allen Plattformen zur Verfügung stand.#+begin_src emacs-lisp(defun my/eglot-python-setup ()(eglot-ensure);; eglot wipes out the flymake functions; re-add(setq-local python-flymake-command '("flake8" "--max-line-length=100" "-"))(add-hook 'eglot-managed-mode-hook(lambda ()(add-hook 'flymake-diagnostic-functions #'python-flymake t t))nil t))(add-hook 'python-mode-hook 'my/eglot-python-setup)(add-hook 'python-ts-mode-hook 'my/eglot-python-setup)#+end_srcPrerequisites:*** void-Linux#+begin_src shdoas xbps-install -Sy jedidoas xbps-install -Sy flake8doas xbps-install -Sy blackpip install -U jedi-language-server#+end_src*** WindowsUsing MSYS2:#+begin_src shpacman -Sy mingw-w64-python-jedipacman -Sy mingw-w64-x86_64-python-ipythonpacman -Sy mingw-w64-x86_64-python-blackpacman -Sy mingw-w64-x86_64-python-flake8pacman -Sy mingw-w64-x86_64-python-pippip install -U jedi-language-server#+end_src** UI*** General local leader(defun elpy-shell-switch-to-shell ()"Switch to inferior Python process buffer."(interactive)(setq elpy--shell-last-py-buffer (buffer-name))(pop-to-buffer (process-buffer (elpy-shell-get-or-create-process))))Prefix is C-S-<space>#+begin_src emacs-lisp(local-leader python-ts-mode-map"C-p" '(run-python :wk "start py-shell")"p" '(python-shell-switch-to-shell :wk "py-shell")"+" '(yas-insert-snippet :wk "code snippets")"b" '(python-shell-send-buffer :wk "eval buffer")"F" '(python-shell-send-function :wk "eval function")"f" '(hydra-fold/body :wk "Folding")"m" '(hydra-tree-sitter-move/body :wk "movement hydra")"s" '(:ignore t :which-key "mark/select")"sp" '(mark-paragraph :wk "paragraph")"sf" '(mark-defun :wk "function")"sF" '((evil-textobj-tree-sitter-get-textobj "function.outer") :wk "function"))#+end_src
#-*- mode: org -*-#+TITLE: Emacs Setup for Julia Programming Language#+AUTHOR: Volker Edelmann#+EMAIL: vedelmann@gmx.de#+STARTUP: indent#+OPTIONS: toc:nil#+OPTIONS: ^:{}#+begin_src emacs-lisp;; -*- coding: utf-8; lexical-binding: t -*-#+end_src* Tree-sitter#+begin_src emacs-lisp(push '(julia-mode . julia-ts-mode) major-mode-remap-alist)#+end_src- moving around: ts-movement- selections:- expreg- paragraph-selections, if blank lines are used to structure the code* Folding*origami* funktioniert gut f"ur Julia* Julia#+begin_src emacs-lisp(use-package eglot-jl:commands eglot-jl-init:config(setq eglot-connect-timeout 300)(setq eglot-jl-julia-command julia-program))#+end_src#+begin_src emacs-lisp(use-package julia-ts-mode:after eglot:init (setenv "JULIA_NUM_THREADS" "6"):bind (:map julia-ts-mode-map("C-c p" . er/mark-paragraph)("C-c f" . er/mark-defun)("C-c s" . er/mark-symbol)("C-+" . expreg-expand)("C--" . expreg-contract)("<tab>" . completion-at-point)):hook(julia-ts-mode . julia-snail-mode)(julia-ts-mode . eglot-ensure)(julia-ts-mode . eglot-jl-init);; (julia-ts-mode . ts-movement-mode)(julia-ts-mode . yas-minor-mode))#+end_src|---------+---------------------------------+----------------------------------------------------------------------------------------------------------------------------------------|| key | command | description ||---------+---------------------------------+----------------------------------------------------------------------------------------------------------------------------------------|| C-c C-z | julia-snail | start a REPL; flip between REPL and source || C-c C-a | julia-snail-package-activate | activate the project using Project.toml || C-c C-d | julia-snail-doc-lookup | display the docstring of the identifier at point || C-c C-l | julia-snail-send-line | evaluate current line in the current module (or in Main with prefix arg; or copy directly to REPL with two prefix args) || C-c C-r | julia-snail-send-region | evaluate active region in the current module (or in Main with prefix arg; or copy directly to REPL with two prefix args) || C-c C-e | julia-snail-send-dwim | if region active, evaluate it in current module; else if on top-level block, evaluate it in current module; else evaluate current line || C-c C-c | julia-snail-send-top-level-form | evaluate end-terminated block around the point in the current module || C-M-x | julia-snail-send-top-level-form | ditto || C-c C-R | julia-snail-update-module-cache | update module-nested include cache (mainly for Revise) || C-c C-k | julia-snail-send-buffer-file | include() the current buffer’s file ||---------+---------------------------------+----------------------------------------------------------------------------------------------------------------------------------------|#+begin_src emacs-lisp(use-package julia-snail:after julia-ts-mode:custom(julia-snail-terminal-type :eat):config(setq julia-snail-use-emoji-mode-lighter t)(setq julia-snail-popup-display-eval-results nil)(setq julia-snail-repl-display-eval-results t)(setq julia-snail-show-error-window t)(setq julia-snail-doc-lookup t)(setq julia-snail-multimedia-buffer-style :single-reuse)(setq julia-snail/ob-julia-mirror-output-in-repl t)(setq julia-snail/ob-julia-capture-io t);; :init ;; Setup completion at point;; (add-hook 'julia-snail-mode-hook;; (lambda ();; (remove-hook 'completion-at-point-functions #'julia-snail-repl-completion-at-point t);; );; ):bind (:map julia-snail-mode-map("S-<return>" . julia-snail-send-line)("C-<return>" . julia-snail-send-region)("M-<return>" . julia-snail-send-dwim)("C-M-x" . nil):map julia-snail-repl-mode-map("M-o" . ace-window)))#+end_srcnot working (call function manually when repl is running)::hook(julia-snail-multimedia-toggle-display-in-emacs)** Formattinguse snail extension** TODO Linting** TODO Debugging** UI*** General local leaderPrefix is C-S-<space>#+begin_src emacs-lisp(local-leader julia-ts-mode-map"C-z" '(julia-snail :wk "REPL")"+" '(yas-insert-snippet :wk "code snippets")"b" '(julia-snail-send-buffer-file :wk "eval buffer")"f" '(hydra-fold/body :wk "Folding")"m" '(hydra-tree-sitter-move/body :wk "movement hydra")"s" '(:ignore t :which-key "mark/select")"sp" '(mark-paragraph :wk "paragraph")"sf" '(mark-defun :wk "function"))#+end_srcCategories not yet used:"Debug"(())Test"(("t" ert "prompt")("T" (ert t) "all")("F" (ert :failed) "failed"))"Doc"(("i" info-lookup-symbol "info lookup"))
* Javascript, Typescript, JSON, YAML, Vega-Lite- moving around: ts-movement- selections:- expreg- ts-movement Hydra- evil-textobj-tree-sitter- folding* JSON** Navigator#+begin_src emacs-lisp(use-package json-navigator)#+end_src** Tree-sitter#+begin_src emacs-lisp(dolist (mapping'( (json-mode . json-ts-mode)(js-json-mode . json-ts-mode)))(add-to-list 'major-mode-remap-alist mapping))#+end_src** Lintinguse "jq".** Formattinguse "jq":#+begin_examplejq . --indent 2 File.jsonjq --color-output . file1.json file1.json | less -Rcommand_with_json_output | jq .jq # stdin/"interactive" mode, just enter some JSONjq <<< '{ "foo": "lorem", "bar": "ipsum" }'#+end_exampleThere is also a --sort-keys option"jq ." is great as a pretty-printer, but it comes with a caveat: jq (up to and including jq version 1.5) will alter the values of very large andvery small numbers because it parses numeric values as IEEE 754 64-bit values. To check whether your favorite pretty-printer has the same issue,try this value: 1e1000.** Language Server* Prerequisites*** Node.jssome packages are deprecatedsudo npm install -g vega vega-lite vega-clisudo npm install -g vscode-json-languageserver#+end_src*** Configuration#+begin_src elisp(use-package json-ts-mode:pin gnu:bind (:map json-ts-mode-map("M-<return>" . nil)):hook (;; (json-ts-mode . ts-movement-mode)(json-ts-mode . yas-minor-mode)(json-ts-mode . flycheck-mode)):config(add-hook 'json-ts-mode-hook (lambda () (eglot-ensure))))#+end_src*** Configuration#+begin_src emacs-lisp(use-package vegalite-mode:load-path ("ve"):hook ((vegalite-mode . flycheck-mode)(vegalite-mode . abbrev-mode)):config(setq treesit-font-lock-level 2)(add-hook 'vegalite-mode-hook (lambda () (eglot-ensure))))(require 'vegalite-mode)#+end_src
* Tree-sitter#+begin_src emacs-lisp(require 'java-ts-mode)(push '(java-mode . java-ts-mode) major-mode-remap-alist)#+end_src- selections:- expreg- expand-region (er/...)* Folding* Language ServerAlthough there are 3 language servers for Java listed on https://langserver.org/,installation on Linux is a pain and on Windows I was not able to get it working.* Gnu GlobalI consider a better alternative to a language-server to be the use ofGnu Global (explicit support for Java) or ctags.The use of CEDET/EDE/senator/semantic-db was avoided because of the complexity itintroduces.#+begin_src emacs-lisp(require 'ggtags)#+end_src* SnippetsAdditional YaSnippets#+begin_src emacs-lisp(use-package java-snippets)#+end_src* Linting** Syntax CheckUse Checkstyle with sun-rules.#+begin_src emacs-lisp(require 'flycheck)(flycheck-define-checker java-checkstyle" a java checker ":command ("java""-jar"(eval (concat emacsen-dir "java\\checkstyle-9.0.1-all.jar"))"-c" "sun_checks.xml""-f" "xml"source):error-parser flycheck-parse-checkstyle;; :standard-input:modes (java-mode java-ts-mode))#+end_src* Konfiguration#+begin_src emacs-lisp(use-package java-ts-mode:ensure nil:config(defun ve/java-mode-hook ()(add-to-list 'completion-at-point-functions #'ggtags-completion-at-point)):bind (:map java-ts-mode-map("C-+" . expreg-expand)("C--" . expreg-contract)("C-c f" . er/mark-defun)):hook(java-ts-mode . ve/java-mode-hook)(java-ts-mode . ggtags-mode)(java-ts-mode . flycheck-mode)(java-ts-mode . yas-minor-mode)(java-ts-mode . eldoc-mode))#+end_src* General local leaderPrefix is C-S-<space>#+begin_src emacs-lisp(local-leader java-ts-mode-map"+" '(yas-insert-snippet :wk "code snippets")"l" '(flycheck-list-errors :wk "linter window")"f" '(hydra-fold/body :wk "Folding")"m" '(hydra-tree-sitter-move/body :wk "movement hydra");; try combobulate - ts-movement mode not useful"b" '(:ignore t :which-key "TODO: build/run/debug")"t" '(:ignore t :which-key "tags")"tf" '(ggtags-find-tag :wk "find tag")"tF" '(ggtags-find-tag-dwim :wk "find tag dwim")"t$" '(ggtags-find-tag-regexp :wk "find tag regexp")"td" '(ggtags-find-definition :wk "find definition")"tr" '(ggtags-find-reference :wk "find reference")"tg" '(ggtags-grep :wk "search db")"t%" '(ggtags-query-replace :wk "replace")"tu" '(ggtags-update-tags :wk "update db")"d" '(:ignore t :which-key "doc")"s" '(:ignore t :which-key "mark/select");; make this a hydra"sp" '(mark-paragraph :wk "paragraph")"sf" '(er/mark-defun :wk "function")"ss" '(er/mark-symbol-with-prefix :wk "symbol")"s+" '(expreg-expand :wk "expand region")"s-" '(expreg-contract :wk "unexpand region"))#+end_src
* Tree-sitter#+begin_src emacs-lisp(push '(kotlin-mode . kotlin-ts-mode) major-mode-remap-alist)#+end_src- folding ?- movement ?- selections ?* Language ServerFeature list* Symbol Look up- eglot* Linting- flycheck* Snippets- tempel- yasnippets* Konfiguration#+begin_src emacs-lisp(use-package d-mode:pin gnu:config(defun ve/d-mode-hook ()(add-to-list 'eglot-stay-out-of 'flymake)):config(add-to-list 'eglot-server-programs `((d-mode d-ts-mode) . ("serve-d"))):bind (:map d-mode-map):hook(d-mode . flycheck-mode)(d-mode . eglot-ensure)(d-mode . yas-minor-mode)(d-mode . hs-minor-mode)(d-mode . ve/d-mode-hook))#+end_src* UIPrefix is C-S-<space>#+begin_src emacs-lisp(local-leader <mode>-ts-mode-map"+" '(yas-insert-snippet :wk "code snippets")"l" '(flycheck-list-errors :wk "linter window")"f" '(hydra-fold/body :wk "Folding");; try combobulate - ts-movement mode not useful"b" '(:ignore t :which-key "TODO: build/run/debug")"d" '(:ignore t :which-key "doc")"s" '(:ignore t :which-key "mark/select"))#+end_src
* movement- avy- isearch* selections- emacs + my key-bindings- expreg (tree-sitter) or expand-region* in-buffer completion* folding- hide-show (hs-minor-mode)- outline-minor-mode* Narrowing* Documentation* Debugging* REPL* Linting- flycheck- flymake* Snippets- tempel- yasnippets* Symbol Look up- dump-jump- tags- ggtags- (semantic)* Tree-sitter#+begin_src emacs-lisp(push '(<lang>-mode . <lang>-ts-mode) major-mode-remap-alist)#+end_src* Language ServerFeature list* Konfiguration#+begin_src emacs-lisp(use-package <lang>-mode:pin gnu:config(defun ve/<lang>-mode-hook ();; (add-to-list 'completion-at-point-functions #'ggtags-completion-at-point)):bind (:map <lang>-ts-mode-map):hook(<lang>-ts-mode . ve/<lang>-mode-hook)(<lang>-ts-mode . flycheck-mode)(<lang>-ts-mode . yas-minor-mode)(<lang>-ts-mode . hs-minor-mode)(<lang>-ts-mode . outline-minor-mode))#+end_src* UIPrefix is C-S-<space>#+begin_src emacs-lisp(local-leader <mode>-ts-mode-map"+" '(yas-insert-snippet :wk "code snippets")"p" '(project-map :wk "project")"l" '(flycheck-list-errors :wk "linter window");; "l" '(flycheck-list-errors :wk "linter window")"f" '(hydra-fold/body :wk "Folding/Narrowing")"m" '(hydra-tree-sitter-move/body :wk "movement hydra");; try combobulate - ts-movement mode not useful"b" '(:ignore t :which-key "TODO: build/run/debug")"d" '(:ignore t :which-key "doc")"s" '(:ignore t :which-key "mark/select"))#+end_src
* Tree-sitter#+begin_src emacs-lisp(push '(kotlin-mode . kotlin-ts-mode) major-mode-remap-alist)#+end_src- selections:- expreg- evil-textobj-tree-sitter* TODO Language Serverhas a bad reputation* Linting* SnippetsAdditional YaSnippets#+begin_src emacs-lisp(use-package java-snippets)#+end_src* Syntax Check#+begin_src emacs-lisp(require 'flycheck)(flycheck-define-checker java-checkstyle" a java checker ":command ("java""-jar"(eval (concat emacsen-dir "java\\checkstyle-9.0.1-all.jar"))"-c" "sun_checks.xml""-f" "xml"source):error-parser flycheck-parse-checkstyle;; :standard-input:modes (java-mode java-ts-mode))#+end_src* Konfiguration#+begin_src emacs-lisp(use-package emacs:pin gnu:config(defun ve/java-mode-hook ()(add-to-list 'completion-at-point-functions #'ggtags-completion-at-point)):bind (:map java-ts-mode-map):hook(java-ts-mode . ve/java-mode-hook)(java-ts-mode . ggtags-mode)(java-ts-mode . flycheck-mode)(java-ts-mode . yas-minor-mode)(java-ts-mode . eldoc-mode))#+end_src* UIPrefix is C-S-<space>#+begin_src emacs-lisp(local-leader kotlin-ts-mode-map"+" '(yas-insert-snippet :wk "code snippets")"p" '(projectile-map :wk "project")"l" '(flycheck-list-errors :wk "linter window")"f" '(hydra-fold/body :wk "Folding")"m" '(hydra-tree-sitter-move/body :wk "movement hydra");; try combobulate - ts-movement mode not useful"b" '(:ignore t :which-key "TODO: build/run/debug")"d" '(:ignore t :which-key "doc")"s" '(:ignore t :which-key "mark/select");; make this a hydra"sp" '(mark-paragraph :wk "paragraph")"sf" '(mark-defun :wk "function")"sF" '((evil-textobj-tree-sitter-get-textobj "function.outer") :wk "function")"s+" '(expreg-expand :wk "expand region")"s-" '(expreg-contract :wk "unexpand region"))#+end_src
;;; package settings for the various environments;;; code:(defun windows-eps-setup ()"setup for EPS network with zscaler"(progn(setq org-agenda-files(list (concat org-directory "aufgaben.org")))));; -----(defun linux-ved-setup ()(progn(add-to-list 'exec-path "/opt/bin")(add-to-list 'exec-path (concat (getenv "HOME") "/.local/bin"))(setq org-agenda-files(list (concat org-directory "studium.org")(concat org-directory "aufgaben.org")(concat org-directory "privat.org")))))(defun open-sample-dir ()"Open this very file."(interactive)(find-file (concat user-emacs-directory "/../testfiles/emacs_testfiles/")))(bind-key "C-c F" #'open-sample-dir)(cond (sys/win32p(progn(if (string= "EPS_WIN" (getenv "MY_ENV"))(windows-eps-setup))))(sys/linuxp(linux-ved-setup)));;; ends here
* Functions#+begin_src emacs-lisp(defun ve/desc-completion-functions ()"desc functions buffer completions."(interactive)(describe-variable 'completion-at-point-functions))(defun ve/show-value-of-variable (symbol)(message (format "The value of '%s' is %S" symbol (symbol-value symbol))))(defun ve/show-completion-functions ()"show functions buffer completions."(interactive)(ve/show-value-of-variable 'completion-at-point-functions))#+end_src#+begin_src emacs-lisp(defun switch-to-scratch-buffer ()"Switch to the current session's scratch buffer."(interactive)(switch-to-buffer "*scratch*"))#+end_src#+begin_src emacs-lisp(defun ve/indent-buffer ()"indent buffer with indent-region."(interactive)(indent-region (point-min) (point-max)))(defun my/bookmark-jump-other-tab (bookmark)"Jump to BOOKMARK in another tab. See `bookmark-jump' for more."(interactive(bookmark-jump bookmark 'switch-to-buffer-other-tab)))#+end_src~keyboard-quit~ sometimes isn't enough, especially if the minibuffer is open, so here's a beefed-up version.#+begin_src emacs-lisp(defun ve/abort ()"Remove auxiliary buffers."(interactive)(ignore-errors (exit-recursive-edit))(call-interactively #'keyboard-quit))#+end_srcCompletion systems make ~kill-buffer~ give you a list of possible results, which isn't generally what I want.#+begin_src emacs-lisp(defun kill-this-buffer ()"Kill the current buffer."(interactive)(kill-buffer nil))#+end_src* More modifier keysOn windows, I installed sharp-keys.I disabled CAPS-Lock and defined <f13> = <Rollen> and <f14> = <Pause>.#+begin_src emacs-lisp#+end_src* General: Leader Map("Highlight";; ("h l" global-hl-line-mode "line" :toggle t);; ("h s" symbol-overlay-mode "symbol" :toggle t);; ("h r" rainbow-mode "rainbow" :toggle t);; ("h d" rainbow-delimiters-mode "delimiter" :toggle t);; ("h i" highlight-indent-guides-mode "indent" :toggle t);; ("Program";; ("p" smartparens-mode "smart parenthesis" :toggle t);; ("E" toggle-debug-on-error "debug on error" :toggle (default-value 'debug-on-error));; ("v" global-diff-hl-mode "gutter" :toggle t);; ("V" diff-hl-flydiff-mode "live gutter" :toggle t);; ("M" diff-hl-margin-mode "margin gutter" :toggle t);; ("D" diff-hl-dired-mode "dired gutter" :toggle t)#+begin_src emacs-lisp(use-package general:config(defun rename-file-and-buffer ()"Rename the current buffer and file it is visiting."(interactive)(let ((filename (buffer-file-name)))(if (not (and filename (file-exists-p filename)))(message "Buffer is not visiting a file!")(let ((new-name (read-file-name "New name: " filename)))(cond((vc-backend filename) (vc-rename-file filename new-name))(t(rename-file filename new-name t)(set-visited-file-name new-name t t)))))))(leader"" nil"t" '(:ignore t :which-key "toggle features")"tt" '(modus-themes-toggle :wk "change theme" :toggle t)"tw" '(whitespace-mode :wk "whitespaces" :toggle t)"tl" '(global-page-break-lines-mode :wk "page break lines" :toggle t)"tp" '(show-paren-mode :wk "parenthesis" :toggle t)"t_" '(subword-mode :wk "subword" :toggle t)"tv" '(viper-mode :wk "vi-mode" :toggle t)"tW" '(which-function-mode :wk "which function" :toggle t)"E" '(eshell :wk "eshell")"d" '(hydra-desktop/body :wk "desktop management")"g" '(rg :wk "ripgrep")"G" '(rg-dwim :wk "ripgrep dwim")"l" '(recenter :wk "center cursor pos")"L" '(recenter-top-bottom :wk "center/top/bottom cursor pos")"a" '(avy-goto-char-timer :wk "avy")"m" '(hydra-move/body :wk "movement")"R" '(hydra-rectangle/body :wk "rectangle editing")"T" '(hydra-tab-bar/body :wk "tab management")"w" '(hydra-window/body :wk "window management")"W" '(hydra-web-search/body :wk "web search")"e" '(:ignore t :which-key "embark")"ea" '(embark-act :wk "act")"eA" '(embark-act-all :wk "act on all candidates")"ee" '(embark-export :wk "export")"e." '(embark-dwim :wk "dwim")"s" '(:ignore t :which-key "search")"ss" '(isearch-forward :wk "isearch →")"sr" '(isearch-backward :wk "isearch ←")"sg" '(rg-dwim :wk "ripgrep dwm")"sG" '(rg-menu :wk "ripgrep menu")"sS" '(isearch-forward-regexp :wk "regexp search →")"sR" '(isearch-backward-regexp :wk "regexp search ←")"sl" '(consult-line :wk "consult line")"so" '(occur :wk "show lines matching ... (occur)")"p" '(:ignore t :which-key "Project management")"pp" '(project-switch-project :wk "switch project")"pd" '(project-dired :wk "dired")"pf" '(project-find-file :wk "find file")"pg" '(project-find-regexp :wk "regexp search")"pG" '(rg-project :wk "ripgrep")"pr" '(project-query-replace-regexp :wk "query/replace")"pc" '(project-compile :wk "compile")"pv" '(project-vc-dir :wk "version control")"c" '(:ignore t :which-key "consult (minibuffer)")"cb" '(consult-buffer :wk "buffer(b)/recent file(f)/bookmark(m)/project(p)")"cB" '(consult-bookmark :wk "bookmark")"cf" '(consult-fd :wk "find (fd)")"co" '(consult-line :wk "search file (occur)")"cr" '(consult-recent-file :wk "recent file")"cg" '(consult-ripgrep :wk "ripgrep")"." '(:ignore t :which-key "insert/complete at point")"./" '(cape-dabbrev :wk "dynamic abbreviation")".w" '(cape-dict :wk "dictionary")".t" '(complete-tag :wk "complete tag")".e" '(cape-elisp-symbol :wk "elisp symbol")".\\" '(cape-tex :wk "tex symbol")".&" '(cape-sgml :wk "sgml symbol")".r" '(cape-rfc1345 :wk "symbol defined in RFC1345")".h" '(cape-history :wk "from history")".f" '(cape-file :wk "filename")".u" '(hydra-unicode/body :wk "Unicode Char Hydra")"q" '(:ignore t :which-key "kill/exit")"qz" '(kill-emacs :wk "exit Emacs")"qw" '(delete-window :wk "kill window")"qq" '(kill-this-buffer :wk "kill buffer")"qq" '(delete-frame :wk "kill frame")"b" '(:ignore t :which-key "buffer")"bi" '(ibuffer :wk "I-Buffer");; "bN" '(evil-buffer-new :wk "new")"bn" '(next-buffer :wk "next")"bp" '(previous-buffer :wk "previous")"bb" '(switch-to-buffer :wk "switch buffer")"br" '(revert-buffer :wk "revert")"bm" '(switch-to-messages-buffer :wk "*Messages*")"bs" '(switch-to-scratch-buffer :wk "*scratch*")"b0" '(kill-this-buffer :wk "kill buffer")"bq" '(kill-buffer-and-window :wk "kill window & buffer")"bR" '(rename-file-and-buffer :wk "rename buffer & file")"f" '(:ignore t :which-key "files")"fj" '(dired-jump :wk "open dired for visited file")"fl" '(find-file-literally :wk "open file/no conversion")"fo" '(find-file :wk "open file")"fr" '(recentf-open-files :wk "open recent ...")"fR" '(rename-file-and-buffer :wk "rename buffer & file")"fw" '(write-file :wk "save as ...")"r" '(:ignore t :which-key "Register commands")"rl" '(list-registers :wk "Show registers")"rs" '(point-to-register :wk "Save point")"rj" '(jump-to-register :wk "Jump to register")"ry" '(copy-to-register :wk "Copy to register")"rp" '(insert-register :wk "Insert from register")"rn" '(number-to-register :wk "Number to register")"r+" '(increment-register :wk "Increment number in register")"rw" '(window-configuration-to-register :wk "save window config")"k" '(:ignore t :which-key "keyboard macros")"kb" '(kmacro-start-macro-or-insert-counter :wk "start")"ke" '(kmacro-end-macro :wk "end")"ks" '(kmacro-to-register :wk "save to register")"kn" '(kmacro-name-last-macro :wk "name for later usage")"kr" '((apply-macro-to-region-lines nil) :wk "apply to region")"h" '(:ignore t :which-key "help")"h." '(helpful-at-point :wk "at cursor")"hy" '(describe-personal-keybindings :wk "personal key bindings")"hk" '(helpful-key :wk "for key")"hK" '(describe-keymap :wk "for keymap")"hf" '(helpful-callable :wk "for function")"hv" '(helpful-variable :wk "for variable")"hs" '(helpful-symbol :wk "for symbol")"hc" '(helpful-command :wk "for command")"he" '(embark-bindings :wk "embark bindings")"hl" '(find-library :wk "library")"hL" '(finder-commentary :wk "commentary section")))#+end_src* Global Keymap#+begin_src emacs-lisp(require 'bind-key)(bind-key* (kbd "<f5>") #'ve/desc-completion-functions)(bind-key* (kbd "<f8>") #'toggle-viper-mode)(bind-key* (kbd "C-<f8>") #'viper-go-away)(bind-key* (kbd "C-+") 'er/expand-region)(bind-key* (kbd "C--") 'er/contract-region)(bind-key* (kbd "C-x C-f") 'find-file)(bind-key* (kbd "C-c p") 'proced)(bind-key* (kbd "C-S-g") 've/abort)(bind-key* (kbd "C-M-g") 'top-level)(bind-key* (kbd "C-x x") 'eval-defun)(bind-key* (kbd "C-k") 'kill-line)(bind-key* (kbd "C-S-k") 'kill-whole-line)(bind-key* (kbd "C-S-<right>") 'tab-next)(bind-key* (kbd "C-S-<left>") 'tab-previous);; (bind-key* (kbd "M-.") 'set-mark-command)(bind-key* (kbd "M-o") 'ace-window)(bind-key* (kbd "C-.") 'embark-act)#+end_src** Remap Commands... and associated keybindings.#+begin_src emacs-lisp(require 'pp)(bind-key* [remap eval-last-sexp] 'pp-eval-last-sexp)#+end_src** On Windows only#+begin_src emacs-lisp(if sys/win32p(progn(bind-key* (kbd "M-<f4>") 'run-cmd)))#+end_src* Hydrassee: stealfrom: centaurbetter: https://github.com/abo-abo/hydra/wiki/** Quick sort dired buffers via hydrasee basic-setup** Movement Hydra#+begin_src emacs-lisp(pretty-hydra-define hydra-move (:title "move":foreign-keys warn:quit-key "q")("search" (("j" avy-goto-char-timer "goto char")("n" avy-next "avy next")("p" avy-prev "avy prev"))"forward" ((">" end-of-buffer "last line")("$" end-of-line "EOL")("}" forward-paragraph "paragraph")("v" scroll-down "page"))"backward" (("<" beginning-of-buffer "first line")("0" beginning-of-line "beginning of line")("{" backward-paragraph "paragraph")("V" scroll-up "page"))"Others" (("|" move-to-column "→ column")("l" goto-line "→ line"))))#+end_src** Completion Hydra#+begin_src emacs-lisp(pretty-hydra-define hydra-complete (:title "complete" :exit t)("Abbreviation" (("/" cape-dabbrev "dynamic abbreviation")("w" cape-dict "dictionary"))"Symbol" (("t" complete-tag "complete tag")("s" cape-lisp-symbol "symbol")("\\" cape-tex "tex symbol")("&" cape-sgml "sgml symbol")("r" cape-rfc1345 "symbol defined in RFC1345"))"Others" (("h" cape-history "from history")("f" cape-file "filename"))))#+end_src** Desktop Hydra#+begin_src emacs-lisp(pretty-hydra-define hydra-desktop (:title "Desktop Operations":color blue)("Load/Save"(("l" desktop-read "load default desktop")("s" desktop-save "save")("b" bmkp-set-desktop-bookmark "save as bookmark"))"Misc"(("c" desktop-clear "clear")("d" desktop-change-dir "dir")("r" desktop-revert "revert"))))#+end_src** Tabbar#+begin_src emacs-lisp(pretty-hydra-define hydra-tab-bar (:title "Tab Bar Operations":foreign-keys warn:quit-key "q")("Creation"(("t" tab-new "Create a new tab")("d" dired-other-tab "Open Dired in another tab")("f" find-file-other-tab "Find file in another tab")("x" tab-window-detach "move window to tab")("0" tab-close "Close current tab"))"Management"(("m" tab-move "Move current tab")("r" tab-rename "Rename Tab"))"Navigation"(("<return>" tab-bar-select-tab-by-name "Select tab by name")("n" tab-next "Next Tab")("p" tab-previous "Previous Tab"))))#+end_src** Windows#+begin_src emacs-lisp(require 'winner)(require 'ace-window)#+end_src#+begin_src emacs-lisp(pretty-hydra-define hydra-window (:title "Window Management":foreign-keys warn:quit-key "q")("Actions"(("TAB" other-window "switch")("x" delete-window "delete")("m" delete-other-windows "maximize")("s" ace-swap-window "swap")("a" ace-select-window "select")("u" (progn(winner-undo)(setq this-command 'winner-undo)) "undo change")("r" winner-redo "redo change"))"Resize"(("h"(enlarge-window-horizontally -1) "←")("j"(enlarge-window -1) "↓")("k"(enlarge-window 1) "↑")("l"(enlarge-window-horizontally 1) "→")("n" balance-windows "balance")("f" toggle-frame-fullscreen "toggle fullscreen"))"Split"(("|" (lambda ()(interactive)(split-window-right)(windmove-right)) "horizontally")("-" (lambda ()(interactive)(split-window-below)(windmove-down)) "vertically"))"Font size"(("M-+" text-scale-increase "bigger")("M--" text-scale-decrease "smaller")("0" (text-scale-adjust 0) "reset to default"))))#+end_src** Rectangle#+begin_src emacs-lisp(defun my/ex-point-mark ()(interactive)(if rectangle-mark-mode(exchange-point-and-mark)(let ((mk (mark)))(rectangle-mark-mode 1)(goto-char mk))))(defun my/reset-rectangle ()(interactive)(if (region-active-p)(progn(rectangle-exchange-point-and-mark)(deactivate-mark)))(rectangle-mark-mode 1))(pretty-hydra-define hydra-rectangle (:title "Rectangle Editing":foreign-keys run:pre (rectangle-mark-mode 1):post (deactivate-mark):quit-key "q")("Select" (("h" rectangle-backward-char "left")("l" rectangle-forward-char "right")("k" rectangle-previous-line "up")("j" rectangle-next-line "down")("e" my/ex-point-mark "exchange mark with point"))"Act" (("p" kill-rectangle "kill")("c" copy-rectangle-as-kill "copy")("R" copy-rectangle-to-register "copy to register")("y" yank-rectangle "yank" :color blue)("s" string-rectangle "type to replace"))"Undo ..." (("x" my/reset-rectangle "reset and start again")("u" undo "undo")("r" redo "redo"))))#+end_src** Websearchstolen from aboabo and adapted#+begin_src emacs-lisp(defun ora-search-query (fmt)(let ((query (if (region-active-p)(buffer-substring-no-properties (region-beginning) (region-end))(read-from-minibuffer "Search for: "))))(browse-url (format fmt query))))(defhydra hydra-web-search (:exit t)("w" (ora-search-query "https://en.wikipedia.org/w/index.php?search=%s") "wiki")("g" (ora-search-query "https://github.com/search?ref=simplesearch&q=%s") "github")("m" (ora-search-query "https://www.google.com/maps/search/%s?hl=en&source=opensearch") "maps")("r" (ora-search-query "https://www.reddit.com/search?q=%s") "reddit")("y" (ora-search-query "https://www.youtube.com/results?search_query=%s&page={startPage?}&utm_source=opensearch") "youtube")("SPC" nil "quit"))#+end_src** Unicode#+begin_src emacs-lisp(defun my/insert-unicode (unicode-name)"Same as: C-x 8 Enter UNICODE-NAME."(insert-char (gethash unicode-name (ucs-names))))(pretty-hydra-define hydra-unicode (:title "Unicode" :exit t)("Sets" (("N" (insert-char 8469) "ℕ") ;; natural numbers("R" (insert-char 8477) "ℝ") ;; real numbers("Z" (insert-char 8484) "ℤ") ;; real numbers)"Operators" (("e" (insert-char 948) "∈")("a" (my/insert-unicode "ALMOST EQUAL TO") "≈")("p" (insert-char 8706) "∂ (partial diff)"))"Statistics" (("m" (my/insert-unicode "MICRO SIGN") "µ")("s" (insert-char 963) "σ")("v" (progn (insert-char 963)(insert-char 178)) "σ²"))"Letters" (("d" (my/insert-unicode "GREEK SMALL LETTER DELTA") "δ"))"Misc" (("o" (my/insert-unicode "DEGREE SIGN") "°")("E" (my/insert-unicode "EURO SIGN") "€")(">" (my/insert-unicode "RIGHTWARDS ARROW") "→"))))#+end_src* Unused KeysFrom the package description:Show free bindings in current buffer.To use, call the command free-keys. This package takes into account the major mode bindings as well as any bindings occupied by minor modes active in current buffer. If called with prefix argument C-u, you can specify a prefix map to be used, such as C-c or C-c C-x (these are specified as a string).#+begin_src emacs-lisp(use-package free-keys)#+end_src* Bye#+begin_src emacs-lisp;;; keybindings.el ends here#+end_src
;;; init.el -*- lexical-binding: t; -*-;;; Volker Edelmann, based on Patrick Thomson's Emacs setup.;;;;; Commentary:;; This file loads use-package, org-mode and compiles and executes;; my emacs org configuration;;;;; Code:;;(load-file (concat user-emacs-directory "/environment-setup.el"))(require 'package)(add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/") t)(setq package-native-compile t)(setq use-package-always-ensure nil)(package-initialize)(eval-when-compile(require 'use-package)(require 'ob-tangle))(defun reload-config ()"Reload the literate config from several files"(interactive)(message "Reloading my configuration")(toggle-debug-on-error)(org-babel-load-file (concat user-emacs-directory "/basic-setup.org"))(org-babel-load-file (concat user-emacs-directory "/programming-setup.org"))(org-babel-load-file (concat user-emacs-directory "/proglang-elisp-setup.org"))(org-babel-load-file (concat user-emacs-directory "/proglang-clojure-setup.org"))(org-babel-load-file (concat user-emacs-directory "/proglang-js-setup.org"))(org-babel-load-file (concat user-emacs-directory "/proglang-julia-setup.org"))(org-babel-load-file (concat user-emacs-directory "/proglang-tcltk-setup.org"))(org-babel-load-file (concat user-emacs-directory "/proglang-python-setup.org"));; (org-babel-load-file (concat user-emacs-directory "/proglang-java-setup.org"));; (org-babel-load-file (concat user-emacs-directory "/proglang-kotlin-setup.org"));; (org-babel-load-file (concat user-emacs-directory "/proglang-groovy-setup.org"))(org-babel-load-file (concat user-emacs-directory "/proglang-sql-setup.org"))(org-babel-load-file (concat user-emacs-directory "/proglang-xml-setup.org"))(org-babel-load-file (concat user-emacs-directory "/proglang-d-setup.org"))(org-babel-load-file (concat user-emacs-directory "/proglang-rudimentary-setup.org"))(org-babel-load-file (concat user-emacs-directory "/text_gtd-setup.org"))(org-babel-load-file (concat user-emacs-directory "/tool-ai-setup.org"))(org-babel-load-file (concat user-emacs-directory "/keybindings.org"))(load-file (concat user-emacs-directory "/post-init.el")))(add-to-list 'load-path (concat user-emacs-directory "ve"))(let ((default-directory (concat user-emacs-directory "ve")))(normal-top-level-add-subdirs-to-load-path))(add-to-list 'load-path (concat (getenv "HOME") "/secrets"))(print "Load Path:")(princ (mapconcat #'identity load-path "\n"))(reload-config)(with-demoted-errors "Error (personal info): %S"(load-library "personal")(setq user-full-name my-full-name)(setq user-mail-address my-email-address))(require 'server)(unless (server-running-p)(server-start));; show bookmarks(require 'bookmark+)(bookmark-bmenu-list);;(setq initial-buffer-choice (lambda () (get-buffer "*Bookmark List*")))(provide 'init);;; init.el ends here
;;; early-init.el --- Early initialization. -*- lexical-binding: t -*-;; Copyright (C) 2019-2022 Vincent Zhang;; Author: Vincent Zhang <seagle0128@gmail.com>;; URL: https://github.com/seagle0128/.emacs.d;; This file is not part of GNU Emacs.;;;; This program is free software; you can redistribute it and/or;; modify it under the terms of the GNU General Public License as;; published by the Free Software Foundation; either version 3, or;; (at your option) any later version.;;;; This program is distributed in the hope that it will be useful,;; but WITHOUT ANY WARRANTY; without even the implied warranty of;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU;; General Public License for more details.;;;; You should have received a copy of the GNU General Public License;; along with this program; see the file COPYING. If not, write to;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth;; Floor, Boston, MA 02110-1301, USA.;;;;; Commentary:;;;; Emacs 27 introduces early-init.el, which is run before init.el,;; before package and UI initialization happens.;;;;; Code:;; Defer garbage collection further back in the startup process(setq gc-cons-threshold most-positive-fixnumgc-cons-percentage 1.0);; Prevent unwanted runtime compilation for gccemacs (native-comp) users;;; packages are compiled ahead-of-time when they are installed and site files;; are compiled when gccemacs is installed.(setq native-comp-deferred-compilation nil);; Package initialize occurs automatically, before `user-init-file' is;; loaded, but after `early-init-file'. We handle package;; initialization, so we must prevent Emacs from doing it early!(setq package-enable-at-startup nil);; In noninteractive sessions, prioritize non-byte-compiled source files to;; prevent the use of stale byte-code. Otherwise, it saves us a little IO time;; to skip the mtime checks on every *.elc file.(setq load-prefer-newer noninteractive);; Inhibit resizing frame(setq frame-inhibit-implied-resize t);; Faster to disable these here (before they've been initialized)(push '(tool-bar-lines . 0) default-frame-alist)(when (featurep 'ns)(push '(ns-transparent-titlebar . t) default-frame-alist))(defconst sys/win32p(eq system-type 'windows-nt)"Are we running on a WinTel system?")(defconst sys/linuxp(eq system-type 'gnu/linux)"Are we running on a GNU/Linux system?")(defconst sys/linux-x-p(and (display-graphic-p) sys/linuxp)"Are we running under X on a GNU/Linux system?")(defconst emacs/>=27p(>= emacs-major-version 27)"Emacs is 27 or above.")(defconst emacs/>=28p(>= emacs-major-version 28)"Emacs is 28 or above.")(defconst emacs/>=29p(>= emacs-major-version 29)"Emacs is 29 or above.")(setq this-emacs "vemacs")(setq emacsen-dir (concat (getenv "HOME") "/emacsen/"))(setq user-init-file (concat user-emacs-directory "init.el"))(print user-init-file)(setq package-user-dir (concat user-emacs-directory "elpa/"))(setq package-gnupghome-dir (concat package-user-dir "gnupg/"))(setq native-comp-eln-load-path nil)(add-to-list 'native-comp-eln-load-path (expand-file-name "eln-cache/" emacsen-dir))(setq server-auth-dir (getenv "EMACS_SERVER_DIR"))(setq server-name (concat "server-" this-emacs))(load-file user-init-file);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; early-init.el ends here
#-*- mode: org -*-#+TITLE: basic setup of Emacs#+AUTHOR: Volker Edelmann#+EMAIL: vedelmann@gmx.de#+STARTUP: indent#+OPTIONS: toc:nil#+OPTIONS: ^:{}* PreliminariesWe have to be sure to set *lexical-binding* in the file header to opt into Emacs lexical scope.#+begin_src emacs-lisp;; -*- coding: utf-8; lexical-binding: t -*-#+end_src* Fixing defaultsFixing Emacs's defaults is a nontrivial problem. We'll start with UI concerns.#+begin_src emacs-lisp(setq;; No need to see GNU agitprop.inhibit-startup-screen t;; No need to remind me what a scratch buffer is.initial-scratch-message nil;; Never ding at me, ever.ring-bell-function 'ignore;; Save existing clipboard text into the kill ring before replacing it.save-interprogram-paste-before-kill t;; Prompts should go in the minibuffer, not in a GUI.use-dialog-box nil;; accept 'y' or 'n' instead of yes/no;; the documentation advises against setting this variable;; the documentation can get bent imouse-short-answers t;; my source directorydefault-directory "~/";; prefer newer elisp filesload-prefer-newer t;; if native-comp is having trouble, there's not very much I can donative-comp-async-report-warnings-errors 'silent;; unicode ellipses are bettertruncate-string-ellipsis "…";; I want to close these fast, so switch to it so I can just hit 'q'help-window-select t;; don't keep duplicate entries in kill ringkill-do-not-save-duplicates trequire-final-newline t;; when opening a new fileconfirm-nonexistent-file-or-buffer nil;; kill buffer and attached process without askingkill-buffer-query-functions(remq 'process-kill-buffer-query-functionkill-buffer-query-functions);; do not ask when reverting bufferauto-revert-verbose nilrevert-without-query '(".*"))#+end_src#+RESULTS:It's good that Emacs supports the wide variety of file encodings it does, but UTF-8 should be the default.#+begin_src emacs-lisp(set-charset-priority 'unicode)(prefer-coding-system 'utf-8-unix)#+end_srcTurn on a few modes to have behavior that's even remotely modern.#+begin_src emacs-lisp(delete-selection-mode t)(global-display-line-numbers-mode t)(column-number-mode t)(savehist-mode t)(context-menu-mode t) ;; right mouse click shows commands(global-goto-address-mode) ;; URLs should be highlighted and linkified.(global-hl-line-mode t);; very convenient(repeat-mode t)(winner-mode t)(setq x-select-enable-clipboard t)(setq yank-pop-change-selection t)(setq mouse-drag-copy-region t)#+end_srcEmacs is super fond of littering filesystems with backups and autosaves, since it was built with the assumption that multiple users could be using the same Emacs instance on the same filesystem. This was valid in 1980. It is no longer the case.#+begin_src emacs-lisp(setqmake-backup-files nilauto-save-default nilcreate-lockfiles nil)#+end_srcBy default, Emacs stores any configuration you make through its UI by writing ~custom-set-variables~ invocations to your init file, or to the file specified by ~custom-file~. Though this is convenient, it's also an excellent way to cause aggravation when the variable you keep trying to modify is being set in some ~custom-set-variables~ invocation. We can disable this by mapping it to a temporary file. (I used to map this to ~/dev/null~, but this started causing a bunch of inane save dialogues.)#+begin_src emacs-lisp(setq custom-file (make-temp-name "/tmp/"))#+end_srcEmacs is also in love with showing you its NEWS file; it's bound to like four different keybindings.Overriding the function makes it a no-op.#+begin_src emacs-lisp(defalias 'view-emacs-news 'ignore)(defalias 'describe-gnu-project 'ignore)(defalias 'describe-copying 'ignore)#+end_src** Keyboard macrosFixing inconsistency in naming:#+begin_src emacs-lisp(require 'kmacro)(defalias 'kmacro-insert-macro 'insert-kbd-macro)(define-key kmacro-keymap (kbd "I") #'kmacro-insert-macro)#+end_src** Quickly access config-directory#+begin_src emacs-lisp(defun open-init-dir ()"Open this very file."(interactive)(find-file user-emacs-directory))(bind-key "C-c E" #'open-init-dir)#+end_src* Improving Help** Better Help#+begin_src emacs-lisp(use-package helpful:defer t:bind (("C-h ." . helpful-at-point)([remap display-local-help] . helpful-at-point)([remap describe-function] . helpful-callable)([remap describe-variable] . helpful-variable)([remap describe-symbol] . helpful-symbol)([remap describe-key] . helpful-key)([remap describe-command] . helpful-command)("C-h C-l" . find-library) ;; source code file("C-h C-c" . finder-commentary) ;; Display file commentary section("C-h K" . describe-keymap)("C-h y" . describe-personal-keybindings)("C-h <help>" . nil)("C-h <f1>" . nil)("C-h C-h" . nil)("C-h C-f" . nil)("C-h C-n" . nil)("C-h C-W" . nil)("C-h C-\\" . nil)("C-h g" . nil)("C-h C-o" . nil)("C-h C-p" . nil)("C-h C-t" . nil)("C-h h" . nil)("C-h n" . nil)))#+end_src** Help on available keys#+begin_src emacs-lisp(use-package which-key:ensure t:diminish:custom(which-key-idle-delay 0.5)(which-key-enable-extended-define-key t)(which-key-sort-order 'which-key-description-order)(which-key-show-prefix nil):config(which-key-mode t);;(which-key-setup-side-window-bottom)(which-key-setup-side-window-right)(setq which-key-side-window-max-width 0.8);; (setq which-key-popup-type 'minibuffer))#+end_src** Minibuffer annotationsRich annotations using the Marginalia package:#+begin_src emacs-lisp(use-package marginalia:ensure t;; Bind `marginalia-cycle' locally in the minibuffer. To make the binding;; available in the *Completions* buffer, add it to the `completion-list-mode-map'.:bind (:map minibuffer-local-map("M-A" . marginalia-cycle)):init(marginalia-mode))#+end_src* User Interface - Key Bindings** General#+begin_src emacs-lisp(use-package general:config(general-auto-unbind-keys);; (general-override-mode 1)(general-create-definer leader:keymaps 'override:prefix "C-SPC");; local leader key SPC similar to spacemacs(general-create-definer local-leader:keymaps 'override:prefix "M-SPC"))#+end_src** Repeat -ModeSee Karthinks "It bears repeating" https://karthinks.com/software/it-bears-repeating/#+begin_src emacs-lisp(use-package repeat-help:hook (repeat-mode . repeat-help-mode):config(setq repeat-help-auto trepeat-help-popup-type 'which-key))#+end_src#+begin_src emacs-lisp(require 'define-repeat-map)#+end_srcExample of the definition of a repeat-map(define-repeat-map case("c" capitalize-word"u" upcase-word"l" downcase-word)(:continue "f" forward-word"b" backward-word)(:enter downcase-dwimupcase-dwimcapitalize-dwim))** Persistent Prefix Keymapshttps://karthinks.com/software/persistent-prefix-keymaps-in-emacs/After pressing the prefix, press C-h for help.#+begin_src emacs-lisp(defun repeated-prefix-help-command ()(interactive)(when-let* ((keys (this-command-keys-vector))(prefix (seq-take keys (1- (length keys))))(orig-keymap (key-binding prefix 'accept-default))(keymap (copy-keymap orig-keymap))(exit-func (set-transient-map keymap t #'which-key-abort)))(define-key keymap [remap keyboard-quit](lambda () (interactive) (funcall exit-func)))(which-key--create-buffer-and-show nil keymap)))(setq prefix-help-command #'repeated-prefix-help-command)#+end_src** Hydras#+begin_src emacs-lisp(use-package hydra:ensure t:hook (emacs-lisp-mode . hydra-add-imenu))#+end_src#+begin_src emacs-lisp(use-package pretty-hydra:ensure t)#+end_src#+begin_src emacs-lisp(use-package major-mode-hydra:ensure t)#+end_src** Hercules- reuse existing keymaps- which-key#+begin_src emacs-lisp(use-package hercules:config(hercules-def:show-funs #'which-key-show-top-level:hide-funs '(keyboard-quit keyboard-escape-quit)))#+end_src* Windows#+begin_src emacs-lisp(use-package ace-window:config(setq aw-keys '(?a ?s ?d ?f ?g ?h ?j ?k ?l)):bind (("M-o" . ace-window)))#+end_src* VisualsEvery Emacs window should, by default occupy all the screen space it can.#+begin_src emacs-lisp(add-to-list 'default-frame-alist '(fullscreen . maximized))#+end_srcWindow chrome both wastes space and looks unappealing.#+begin_src emacs-lisp(when (window-system)(menu-bar-mode t)(tool-bar-mode -1)(scroll-bar-mode t)(tooltip-mode -1)(pixel-scroll-mode t))#+end_src** Titlebar#+begin_src emacs-lisp(setq frame-title-format '("" "%b - " this-emacs "@" system-name))#+end_src** ModelineMost major modes pollute the modeline, so we pull in diminish.el to quiesce them.#+begin_src emacs-lisp(use-package diminish:config(diminish 'visual-line-mode))#+end_src** Display colors#+begin_src emacs-lisp(use-package rainbow-mode:ensure t:config(add-hook 'text-mode-hook #'rainbow-mode)(add-hook 'prog-mode-hook #'rainbow-mode)(diminish 'rainbow-mode ""))#+end_src** Thememodus-(vivendi|operandi)#+begin_src emacs-lisp(use-package emacs:init;; customization prior to loading the themes(setq modus-themes-italic-constructs tmodus-themes-bold-constructs tmodus-themes-region '(bg-only no-extend)):config(load-theme 'modus-operandi))#+end_src** Icons for Listings and Menuesuse glyphs for symbol types (instead of images when using kind-icons))#+begin_src emacs-lisp(use-package nerd-icons:diminish nerd-icons-dired-mode "" nerd-icons-ibuffer-mode "")#+end_src* EditingQuickly activate viper: <f8>#+begin_src emacs-lisp(setq viper-custom-file-name "~/.viper")(setq viper-mode nil)(require 'viper)#+end_src* Search#+begin_src emacs-lisp(setq isearch-lazy-count t)(setq lazy-count-prefix-format nil)(setq lazy-count-suffix-format " (%s/%s)")#+end_src* Dired#+begin_src emacs-lisp(require 'dired)#+end_src** Built-In Extensions#+begin_src emacs-lisp(require 'dired-x)#+end_src#+begin_src emacs-lisp(require 'wdired)#+end_src** Packaged ExtensionsDepends on nerd-the-icons -install font#+begin_src emacs-lisp(use-package nerd-icons-dired:diminish dired-mode:after dired:hook (dired-mode . nerd-icons-dired-mode))#+end_src#+begin_src emacs-lisp(use-package dired-filter:ensure t:after dired)#+end_src#+begin_src emacs-lisp(use-package dired-open:ensure t:after dired)#+end_src#+begin_src emacs-lisp(use-package diredfl:ensure t:after dired:hook (dired-mode . diredfl-mode))#+end_srcA key is bound to "S". On windows, we need the path for "ls".Otherwise, a lisp library is used for the listing, that does notprovide the means for sorting with this package.#+begin_src emacs-lisp(use-package dired-quick-sort:ensure t:config(setq dired-quick-sort-suppress-setup-warning nil)(if sys/win32p(setq ls-lisp-use-insert-directory-program "/usr/bin/ls"))(dired-quick-sort-setup):after dired)#+end_src** Dired and fast-findCreate dired-buffers from find commands.#+begin_src emacs-lisp(use-package fd-dired:ensure t:after dired)#+end_src** Configuration#+begin_src emacs-lisp(use-package emacs:init(setqdired-dwim-target t ;; copy and move filesdired-create-destination-dirs 'askdired-kill-when-opening-new-dired-buffer tdired-auto-revert-buffer tdired-recursive-deletes 'alwaysdired-recursive-copies 'alwaysdired-mark-region tdired-listing-switches "-aBhl --group-directories-first")(put 'dired-find-alternate-file 'disabled nil):bind (:map dired-mode-map (("#" . wdired-change-to-wdired-mode)("C-<return>" . dired-open-xdg);; emacs default: ("s" . dired-sort-toggle-or-edit)("S-s" . hydra-dired-quick-sort/body)("-" . dired-hide-details-mode))):hook (dired-mode . dired-hide-details-mode)(dired-mode . dired-filter-mode))#+end_src* Buffer List (ibuffer)** Group by version control#+begin_src emacs-lisp(require 'ibuffer)(use-package ibuffer-vc:config(setq ibuffer-expert t)(setq ibuffer-auto-mode t)(setq ibuffer-display-summary nil)(setq ibuffer-use-header-line t)(setq ibuffer-show-empty-filter-groups nil)(setq ibuffer-default-sorting-mode 'filename/process)(setq ibuffer-saved-filter-groups'(("VED"("Unsaved" (modified)) ; All unsaved buffers("Dired" (mode . dired-mode)) ; Filter by mode("Org" (filename . ".org")) ; By filename("notes" (directory . "~/notes*")) ; By directory("*buffer*" (starred-name)) ; Group *starred*))):hook (ibuffer-mode . ibuffer-vc-set-filter-groups-by-vc-root):bind (([remap list-buffers]. ibuffer):map ibuffer-mode-map (("\M-o" . nil)("C-v" . ibuffer-vc-set-filter-groups-by-vc-root)("C-r" . (lambda ()(interactive) (ibuffer-switch-to-saved-filter-groups "VED"))))))#+end_src** Icons#+begin_src emacs-lisp(use-package nerd-icons-ibuffer:ensure t:config(setq nerd-icons-ibuffer-color-icon t) ;; default(setq nerd-icons-ibuffer-icon-size 1.0) ;; default:hook (ibuffer-mode . nerd-icons-ibuffer-mode))#+end_src* Recent FilesBy default, the list of recent files gets cluttered up with the contents of downloaded packages.#+begin_src emacs-lisp(use-package recentf:after dash:custom(recentf-exclude '("\\elpa"))(recentf-max-saved-items 100)(recentf-max-menu-items 50):config (recentf-mode))#+end_src* BookmarksLeave M-o for ace-window#+begin_src emacs-lisp(require 'bookmark+)(define-key bookmark-bmenu-mode-map "\M-o" nil)#+end_src* ediffSetup recommended by Prot. Stavrou.#+begin_src emacs-lisp(require 'ediff)(setq ediff-make-buffers-readonly-at-startup nil)(setq ediff-split-window-function 'split-window-horizontally)(setq ediff-window-setup-function 'ediff-setup-windows-plain)#+end_src* Quality-of-life improvements** Augment use-packageWith this auxiliary package for ~use-package~, we can instruct Emacs that a given package depends on the presence of a system tool. It will even install this tool with the system's recommended package manager.#+begin_src emacs-lisp(use-package use-package-ensure-system-package)#+end_src** Locations in FilesRemembers your location in a file when saving files#+begin_src emacs-lisp(use-package saveplace:config(setq save-place-file (expand-file-name "saveplace" emacsen-dir));; activate it for all buffers(setq-default save-place t))#+end_src** History of CommandsPersist history of commands over Emacs restarts. Vertico sorts by history position.#+begin_src emacs-lisp(use-package savehist:config(setq savehist-additional-variables;; search entries'(search-ring regexp-search-ring);; save every minutesavehist-autosave-interval 60;; keep the home cleansavehist-file (expand-file-name "savehist" emacsen-dir))(savehist-mode +1))#+end_src** Augment UndoFrom Prelude config:#+begin_src emacs-lisp(use-package vundo:ensure t:commands (vundo):config(setq vundo-compact-display t)(setq vundo-glyph-alist vundo-unicode-symbols);; Better contrasting highlight.(custom-set-faces'(vundo-node ((t (:foreground "#808080"))))'(vundo-stem ((t (:foreground "#808080"))))'(vundo-highlight ((t (:foreground "#FFFF00")))));; Use `HJKL` VIM-like motion, also Home/End to jump around.(define-key vundo-mode-map (kbd "l") #'vundo-forward)(define-key vundo-mode-map (kbd "h") #'vundo-backward)(define-key vundo-mode-map (kbd "j") #'vundo-next)(define-key vundo-mode-map (kbd "k") #'vundo-previous)(define-key vundo-mode-map (kbd "<home>") #'vundo-stem-root)(define-key vundo-mode-map (kbd "<end>") #'vundo-stem-end)(define-key vundo-mode-map (kbd "q") #'vundo-quit)(define-key vundo-mode-map (kbd "C-g") #'vundo-quit)(define-key vundo-mode-map (kbd "RET") #'vundo-confirm))#+end_src** Writable grep#+begin_src emacs-lisp(use-package wgrep:ensure t:config(setq wgrep-change-readonly-file t)(setq wgrep-auto-save-buffer t):bind ( :map grep-mode-map("e" . wgrep-change-to-wgrep-mode):map wgrep-mode-map("e" . wgrep-exit)("c" . wgrep-finish-edit)("d" . wgrep-mark-deletion)("r" . wgrep-remove-change)("R" . wgrep-remove-all-change)))#+end_src## Usage:You can edit the text in the *grep* buffer after typing `C-c C-p` .After that the changed text is highlighted.The following keybindings are defined:*** Key Bindings- `C-c C-u`: All changes are unmarked and ignored.- `C-c C-d`: Mark as delete to current line (including newline).- `C-c C-r`: Remove the changes in the region (these changes are notapplied to the files. Of course, the remainingchanges can still be applied to the files.)- `C-c C-p`: Toggle read-only area.- `C-c C-k`: Discard all changes and exit.- `C-x C-q`: Exit wgrep mode.*** Functions- To save all buffers that wgrep has changed, runM-x wgrep-save-all-buffers- To save buffer automatically when `wgrep-finish-edit'.(setq wgrep-auto-save-buffer t)- You can change the default key binding to switch to wgrep.(setq wgrep-enable-key "r")- To apply all changes regardless of whether or not buffer is read-only.(setq wgrep-change-readonly-file t)** ripgrep#+begin_src emacs-lisp(use-package rg:ensure-system-package rg:config(setq rg-command-line-flags (list "-C=2"))(setq rg-hide-command nil))(require 'rg-isearch)(define-key isearch-mode-map "\M-sr" 'rg-isearch-menu)(rg-define-search rg-word:format literal:flags ("--word-regexp"):menu ("Custom" "w" "Word"))#+end_src* Desktop management#+begin_src emacs-lisp(require 'desktop)#+end_src* Tab-Bar#+begin_src emacs-lisp(use-package tab-bar:hook (after-init . tab-bar-mode):config(setq tab-bar-show ttab-bar-close-button-show niltab-bar-tab-hints t):general("C-<tab>" nil)("S-C-<tab>" nil))#+end_src(unbind-key "C-<tab>" global-map)(unbind-key "S-C-<tab>" global-map)* Search** BuffersOccur, ripgrep** TODO Filesfd* Completion and input** Narrow the candidate listOrderless is a valuable addition to completion-styles.After narrowing the candidate list by builtin completion styles, it provides avery flexible interface for quickly finding the best candidate.Best reference:Search with *rg "\(styles" emacsen/steal-from/- Prots Emacs: prot/prot-emacs-modules/prot-emacs-completion.el- Lunarymacs: lunarymacs/star/completion.el- josh_moller-mara/jmm-emacs.org#+begin_src emacs-lisp;; from Prots config(use-package orderless:ensure t:demand t:after minibuffer:config;; check 'completion-styles' and 'completion-category-overrides'.(setq orderless-matching-styles '(orderless-prefixes orderless-regexp));; SPC should never complete: use it for 'orderless' groups.;; '?' is a regexp construct.:bind ( :map minibuffer-local-completion-map("SPC" . nil)("?" . nil)))#+end_src** Minibuffer#+begin_src emacs-lisp(use-package emacs:custom;; (completion-styles '(basic substring partial-completion initials flex orderless))(completion-styles '(basic partial-completion orderless))(completion-category-defaults nil)(completion-category-overrides '((file (styles . (basic initials orderless)))(buffer (styles . (orderless)));; (bookmark (styles . (orderless)));; (eglot (styles . (substring orderless)));;(library (styles . (basic substring)));; (embark-keybinding (styles . (basic substring)));; (imenu (styles . (basic substring orderless)));; (consult-location (styles . (basic substring orderless)));; (kill-ring (styles . (emacs22 orderless)));; (eglot (styles . (flex basic)));; (xref-location (styles . (orderless substring)));;(unicode-name (styles . (orderless basic substring)));; (project-file (styles . (orderless substring)));; (info-menu (styles . (orderless basic substring)));; (symbol-help (styles . (orderless basic shorthand substring)))))(completion-auto-select nil)(read-file-name-completion-ignore-case t)(read-buffer-completion-ignore-case t)(completion-ignore-case t))#+end_src*** completion-styles*** completion-category-overrides**** fileFrom the *orderless* documentation (https://github.com/oantolin/orderless ):Furthermore the ~basic~ completion style needs to be tried first (not as a fallback) for TRAMP hostname completion to work.In addition, the partial-completion style allows you to use wildcards for file completion and partial paths, e.g., /u/s/l for /usr/share/local.*** completion categoriesA non-exhaustive list:- bookmark- buffer- charset- coding-system- color- command (M-x)- customize-group- environment-variable- expression- face- file- function (the 'describe-function' command bound to 'C-h f')- info-menu- imenu- input-method- kill-ring- library- minor-mode- multi-category- package- project-file- symbol (the 'describe-symbol' command bound to 'C-h o')- theme- unicode-name (the 'insert-char' command bound to 'C-x 8 RET')- variable (the 'describe-variable' command bound to 'C-h v')- consult-grep- consult-isearch- consult-kmacro- consult-location- embark-keybinding*** Modern minibuffer completion: verticominibuffer-complete-word#+begin_src emacs-lisp(use-package vertico:init(vertico-mode 1)(vertico-multiform-mode 1)(vertico-reverse-mode 1)(defun ve/vertico-smart-tab ()(interactive)(if (= vertico--total 1)(vertico-insert)(minibuffer-complete)))(setq vertico-multiform-categories'((consult-buffer unobtrusive)))(setq vertico-multiform-commands'(("flyspell-correct-*" grid)(consult-yank-pop indexed)(consult-ripgrep buffer)(consult-fd buffer)(consult-imenu buffer)(consult-flycheck buffer)(consult-flymake buffer))):custom(vertico-count (if window-system 16 10))(vertico-buffer-display-action '(display-buffer-same-window));; enable cycling for 'vertico-next' and 'vertico-previous'.(vertico-cycle t):bind (:map vertico-map("<deletechar>" . vertico-directory-delete-char)("C-<tab>" . ve/vertico-smart-tab);; ("<tab>" . vertico-insert)("M-<return>" . vertico-exit-input)("M-q" . vertico-quick-jump)("C-M-r" . consult-history)))#+end_srcChanged <tab> and C-<tab> to match built-in behaviour.** Buffer completion#+begin_src emacs-lisp;; A few more useful configurations...(use-package emacs:init;; Emacs 28: Hide commands in M-x which do not apply to the current mode.;; Corfu commands are hidden, since they are not supposed to be used via M-x.(setq read-extended-command-predicate #'command-completion-default-include-p)(setq-default tab-always-indent 'complete))#+end_src*** AbbreviationsAbbreviations are used for solely for auto-correction and text expansion.For Source Code template engines are preferred.#+begin_src emacs-lisp(defun dont-insert-expansion-char () t)(put 'dont-insert-expansion-char 'no-self-insert t)(use-package emacs:config(setq abbrev-file-name (concat emacsen-dir "abbreviations/abbrev_defs.el"))(setq only-global-abbrevs nil)(setq save-abbrevs nil))#+end_src*** Corfu!Modern completion#+begin_src emacs-lisp(use-package corfu;; :disabled:bind (:map corfu-map("C-g" . corfu-quit)("<return>" . corfu-insert)("M-n" . corfu-next)("M-p" . corfu-previous)("M-m" . corfu-move-to-minibuffer)("M-d" . corfu-show-documentation)("M-l" . corfu-show-location)):custom(corfu-cycle t) ;; Enable cycling for 'corfu-next/previous'(corfu-auto nil) ;; Enable auto completion(corfu-preselect-first nil)(corfu-echo-documentation t)(corfu-separator ?\s) ;; Orderless field separator(corfu-quit-at-boundary 'separator) ;; Never quit at completion boundary(corfu-preview-current nil) ;; Disable current candidate preview(corfu-on-exact-match 'insert) ;; Configure handling of exact matches(corfu-excluded-modes nil) ;; add modes where corfu is disabled(corfu-popupinfo-mode nil):init;; (global-corfu-mode))#+end_src#+begin_src emacs-lisp(use-package nerd-icons-corfu:config(add-to-list 'corfu-margin-formatters #'nerd-icons-corfu-formatter))#+end_src*** capeCompletion sources:#+begin_src emacs-lisp(use-package cape:config(add-to-list 'completion-at-point-functions #'cape-dabbrev):custom(cape-dabbrev-check-other-buffers nil))#+end_src;; Alternative prefix keys: C-c p, M-p, M-+, ...("C-c p t" . complete-tag) ;; etags("C-c p d" . cape-dabbrev) ;; dabbrev-completion("C-c p h" . cape-history) ;; shell("C-c p f" . cape-file)("C-c p k" . cape-keyword) ;; mode-specific keyword lists - is that useful?("C-c p s" . cape-elisp-symbol)("C-c p e" . cape-elisp-block)("C-c p a" . cape-abbrev) ;; do not use("C-c p l" . cape-line)("C-c p w" . cape-dict) ;; text-mode("C-c p :" . cape-emoji)("C-c p ^" . cape-tex) ;; julia("C-c p &" . cape-sgml) ;; html, julia("C-c p r" . cape-rfc1345))*** Dynamic Abbreviatons#+begin_src emacs-lisp(use-package emacs:config(setq dabbrev-abbrev-char-regexp "\\sw\\|\\s_")(setq dabbrev-abbrev-skip-leading-regexp "[$*/=~']")(setq dabbrev-backward-only nil)(setq dabbrev-case-distinction 'case-replace)(setq dabbrev-case-fold-search nil)(setq dabbrev-case-replace 'case-replace)(setq dabbrev-check-other-buffers nil)(setq dabbrev-eliminate-newlines t)(setq dabbrev-upcase-means-case-search t))#+end_src** Templatesprefer tempo/tempel to yasnippets!*** tempel/temposee https://github.com/minad/tempel- no abbrev-mode triggering- used as a capf for completion-at-point (in buffer-completion)#+begin_src emacs-lisp(use-package tempel;; Require trigger prefix before template name when completing.:custom(tempel-trigger-prefix "<"):config(setq tempel-path (concat emacsen-dir "templates/tempel/ve-templates"));; (add-to-list 'tempel-template-sources 'my-global-templates)):init;; Setup completion at point(defun tempel-setup-capf ();; Add the Tempel Capf to 'completion-at-point-functions'.;; 'tempel-expand' only triggers on exact matches. Alternatively use;; 'tempel-complete' if you want to see all matches, but then you;; should also configure 'tempel-trigger-prefix', such that Tempel;; does not trigger too often when you don't expect it. NOTE: We add;; 'tempel-expand' *before* the main programming mode Capf, such;; that it will be tried first.(setq-local completion-at-point-functions(cons #'tempel-completecompletion-at-point-functions)))#+end_srcA community curated list of templates.#+begin_src emacs-lisp(use-package tempel-collection:after tempel)#+end_src*** Yasnippetsimportant commands:- yas-*expand- yas-insert-snippetThere is no trigger key (like TempEL has).That functionality is activated via yas-minor mode#+begin_src emacs-lisp(use-package yasnippet:defer 15 ;; takes a while to load, so do it async:diminish yas-minor-mode "yas":config(setq yas-alias-to-yas/prefix-p nil)(setq yas-snippet-dirs (list (concat emacsen-dir "/templates/yas"))):custom (yas-prompt-functions '(yas-completing-prompt)):bind (:map yas-minor-mode-map (("M-+" . yas-insert-snippet)("<tab>" . nil))))#+end_srcnur so funktioniert es:(setq yas-snippet-dirs '("~/emacs.d/mysnippets""~/Downloads/interesting-snippets"));; OR, keeping YASnippet defaults try out ~/Downloads/interesting-snippets(setq yas-snippet-dirs (append yas-snippet-dirs'("~/Downloads/interesting-snippets")))funktioniert nicht!(add-to-list 'yas-snippet-dirs (concat emacsen-dir "templates/yas"))*** Snippet Collection#+begin_src emacs-lisp(use-package yasnippet-snippets)#+end_src*** Completion At Point#+begin_src emacs-lisp(use-package yasnippet-capf:disabled:after cape:init ;; Setup completion at point(defun yas-setup-capf ()(setq-local completion-at-point-functions(cons #'yasnippet-capfcompletion-at-point-functions)))(add-hook 'conf-mode-hook 'yas-setup-capf)(add-hook 'prog-mode-hook 'yas-setup-capf)(add-hook 'text-mode-hook 'yas-setup-capf))#+end_src*** File Headers#+begin_src emacs-lisp(require 'autoinsert)(setq auto-insert-mode t)(setq auto-insert-query t)(setq auto-insert-directory (concat emacsen-dir "templates/header"))(setq auto-insert-alist '((julia-mode . julia-skeleton)(vegalite-mode . vegalite-skeleton)(java-mode . "java.template")(clojure-mode . "clojure.template")(gnuplot-mode . "gnuplot.template")(asy-mode . "asymptote.template")(org-mode . "org.template")(python-mode . "python.template")))(add-hook 'find-file-hook 'auto-insert)(define-skeleton julia-skeleton"Inserts a skeletal Julia file"nil"# author: " (user-full-name) \n"# created: " (current-time-string) \n"# project: "(setq project (skeleton-read "Project (Return to discard)? "))(if projectproject)\n \n)(define-skeleton vegalite-skeleton"Inserts a skeletal"nil"{\"$schema\": \"https://vega.github.io/schema/vega-lite/v5.json\",\"description\": \"\",\"data\": {},\"mark\": {\"type\": \"\"},\"encoding\": {}}"\n)#+end_src* TODO Consult: Search and Navigation for completionConsult provides search and navigation commands based on the Emacs completion function completing-read.#+begin_src emacs-lisp(use-package consult:custom(consult-narrow-key (kbd ";"))(completion-in-region-function #'consult-completion-in-region)(xref-show-xrefs-function #'consult-xref)(xref-show-definitions-function #'consult-xref)(consult-preview-key '(:debounce 0.25 any)))(use-package consult-dir:ensure t:bind (("C-x C-d" . consult-dir)("C-x b" . consult-buffer):map vertico-map("C-x C-d" . consult-dir)("C-x C-j" . consult-dir-jump-file)))#+end_src* TODO Embark: Discover actionssee https://karthinks.com/software/fifteen-ways-to-use-embark/#+begin_src emacs-lisp(use-package embark:bind(;; ("." . embark-dwim)("C-." . embark-act)("C-S-." . embark-act-all)("C-e" . embark-export);; ("C->" . embark-become)("C-?" . embark-bindings) ;; alternative for 'describe-bindings'):init;; replace the key help with a completing-read interface(setq prefix-help-command #'embark-prefix-help-command):config;; Hide the mode line of the Embark live/completions buffers(add-to-list 'display-buffer-alist'("\\`\\*Embark Collect \\(Live\\|Completions\\)\\*"nil(window-parameters (mode-line-format . none)))))#+end_srcGlue for consult and embark.#+begin_src emacs-lisp(use-package embark-consult:ensure t:after (embark consult):config(add-to-list'embark-exporters-alist'(consult-flymake-error . embark-export-flymake))(defun embark-export-flymake (_errors)(flymake-show-buffer-diagnostics));; TODO: flycheck:bind (:map embark-file-map("x" . embark-open-externally)):demand t ; necessary for consult previews (hook!):hook(embark-collect-mode . consult-preview-at-point-mode))#+end_srclots of actions:** File: karthink/lisp/setup-embark.el(define-key embark-file-map (kbd "o") (my/embark-ace-action find-file));; (use-package embark-vc;; :after embark)* Quick Movement: avy can do anything#+begin_src emacs-lisp(use-package avy:config(defun my/avy-goto-char-this-window (&optional arg)"Goto char in this window with hints."(interactive "P")(let ((avy-all-windows nil)(current-prefix-arg (if arg 4)))(call-interactively 'avy-goto-char-timer)))(setq avy-timeout-seconds 0.75)(setq avy-single-candidate-jump nil)(setq avy-background t)(defun avy-action-embark (pt)(unwind-protect(save-excursion(goto-char pt)(embark-act))(select-window(cdr (ring-ref avy-ring 0))))t)(setf (alist-get ?. avy-dispatch-alist) 'avy-action-embark):bind (("C-M-j" . avy-resume)("C-j" . my/avy-goto-char-this-window)("M-j" . avy-goto-char-timer):map isearch-mode-map ("M-j" . avy-isearch)))#+end_src** File: karthink/lisp/setup-avy.el* TODO Regular Expressions* Terminal** ELisp Terminal emulationCurrently(2023-06-30) not running on Windows.#+begin_src emacs-lisp(use-package eat:if sys/linuxp:custom(eat-kill-buffer-on-exit t):config(eat-eshell-mode)(setq eshell-visual-commands '()))#+end_src* Emac Shellhttps://howardism.org/Technical/Emacs/piper-presentation.htmlHoward Abrahams configuration:#+BEGIN_SRC elisp(use-package eshell:init(setq eshell-buffer-shorthand teshell-scroll-to-bottom-on-input 'alleshell-error-if-no-glob teshell-hist-ignoredups teshell-save-history-on-exit teshell-prefer-lisp-functions nileshell-destroy-buffer-when-process-dies t))#+END_SRC** Visuals*** Prompt#+begin_src emacs-lisp(use-package eshell-prompt-extras:ensure t:config(with-eval-after-load "esh-opt"(autoload 'epe-theme-lambda "eshell-prompt-extras")(setq eshell-highlight-prompt nileshell-prompt-function 'epe-theme-lambda)))#+end_src*** Syntax Highlighting#+begin_src emacs-lisp(use-package eshell-syntax-highlighting:ensure t:after eshell-mode:config(eshell-syntax-highlighting-global-mode +1))#+end_src** Help#+begin_src emacs-lisp(use-package esh-help:ensure t:after eshell-mode:config(setup-esh-help-eldoc))#+end_src** Change Directories quicklyfrom https://karthinks.com/software/jumping-directories-in-eshell/replaces Melpa Package eshell-z#+begin_src emacs-lisp(defun eshell/z (&optional regexp)"Navigate to a previously visited directory in eshell, or toany directory proferred by 'consult-dir'."(let ((eshell-dirs (delete-dups(mapcar 'abbreviate-file-name(ring-elements eshell-last-dir-ring)))))(cond((and (not regexp) (featurep 'consult-dir))(let* ((consult-dir--source-eshell `(:name "Eshell":narrow ?e:category file:face consult-file:items ,eshell-dirs))(consult-dir-sources (cons consult-dir--source-eshellconsult-dir-sources)))(eshell/cd (substring-no-properties(consult-dir--pick "Switch directory: ")))))(t (eshell/cd (if regexp (eshell-find-previous-directory regexp)(completing-read "cd: " eshell-dirs)))))))#+end_src* Bye#+begin_src emacs-lisp;;; basic-setup.el ends here#+end_src