From 0adb872fafdb58d7115994ced8e7233bc3de9733 Mon Sep 17 00:00:00 2001 From: Aryadev Chavali Date: Mon, 27 Mar 2023 15:41:10 +0100 Subject: (Emacs)~rearranged and better documented --- Emacs/.config/emacs/config.org | 917 +++++++++++++++++++++-------------------- 1 file changed, 468 insertions(+), 449 deletions(-) (limited to 'Emacs/.config/emacs/config.org') diff --git a/Emacs/.config/emacs/config.org b/Emacs/.config/emacs/config.org index 4ddeee4..229aaa7 100644 --- a/Emacs/.config/emacs/config.org +++ b/Emacs/.config/emacs/config.org @@ -239,16 +239,153 @@ the borders for Emacs. :config (fringe-mode 0)) #+end_src -* Core packages +** Mode line +A mode line in an editor can provide a LOT of information, or very +little. I customised the Emacs modeline to give me a bit of info, +~telephone-line~ to give me a lot. + +Currently I use the default mode line with some customisation; +simplicity is above all. +*** Emacs Mode-line +Firstly, declare a variable for the separator between each module +#+begin_src emacs-lisp +(defconst +modeline/separator " " "Separator between modules.") +#+end_src + +Then declare a variable for the number of separators between each +module in the modeline. +#+begin_src emacs-lisp +(defconst +modeline/sep-count 4 + "Number of +modline/separator instances separating modules.") +#+end_src + +Then, declare a list of reserved characters for which the previously +declared seperator won't be applied when placed at the end of a module +string. +#+begin_src emacs-lisp +(defconst +modeline/reserved-chars (list "[" "(") + "Characters that, when at the end of a module string, won't + have the separator applied to them.") +#+end_src + +Now declare a function that applies the separator with respect to the +reserved characters to any one string. +#+begin_src emacs-lisp +(defun +modeline/handle-string (STR) + (condition-case nil + (progn + (string-blank-p STR) + (if (cl-member (car (last (split-string STR "" t))) +modeline/reserved-chars :test #'string=) + STR + (concat STR (cl-reduce #'concat (cl-loop for i from 1 to +modeline/sep-count collect +modeline/separator))))) + (error STR))) +#+end_src + +Finally, set the mode-line-format. +#+begin_src emacs-lisp +(setq-default + mode-line-format + (mapcar #'+modeline/handle-string + (list "%l:%c" + "%p[" + '(:eval (upcase + (substring + (format "%s" (if (bound-and-true-p evil-state) + evil-state + "")) + 0 1))) + "]" + "%+%b(" + '(:eval (format "%s" major-mode)) + ")" + "%I" + vc-mode + " " + mode-line-misc-info + mode-line-end-spaces))) +#+end_src +*** Telephone-line +:PROPERTIES: +:header-args:emacs-lisp: :tangle no +:END: +Telephone-line is a mode-line package for Emacs which prioritises +extensibility. It also looks much nicer than the default mode line +with colouring and a ton of presentations to choose from. +#+begin_src emacs-lisp +(use-package telephone-line + :init + (defface +telephone/position-face '((t (:foreground "red" :background "grey10"))) "") + (defface +telephone/mode-face '((t (:foreground "white" :background "dark green"))) "") + (defface +telephone/file-info-face '((t (:foreground "white" :background "Dark Blue"))) "") + :custom + (telephone-line-faces + '((evil . telephone-line-modal-face) + (modal . telephone-line-modal-face) + (ryo . telephone-line-ryo-modal-face) + (accent . (telephone-line-accent-active . telephone-line-accent-inactive)) + (nil . (mode-line . mode-line-inactive)) + (position . (+telephone/position-face . mode-line-inactive)) + (mode . (+telephone/mode-face . mode-line-inactive)) + (file-info . (+telephone/file-info-face . mode-line-inactive)))) + (telephone-line-primary-left-separator 'telephone-line-halfcos-left) + (telephone-line-secondary-left-separator 'telephone-line-halfcos-hollow-left) + (telephone-line-primary-right-separator 'telephone-line-identity-right) + (telephone-line-secondary-right-separator 'telephone-line-identity-hollow-right) + (telephone-line-height 24) + (telephone-line-evil-use-short-tag nil) + :config + (telephone-line-defsegment +telephone/buffer-or-filename () + (cond + ((buffer-file-name) + (if (and (fboundp 'projectile-project-name) + (fboundp 'projectile-project-p) + (projectile-project-p)) + (list "" + (funcall (telephone-line-projectile-segment) face) + (propertize + (concat "/" + (file-relative-name (file-truename (buffer-file-name)) + (projectile-project-root))) + 'help-echo (buffer-file-name))) + (buffer-file-name))) + (t (buffer-name)))) + + (telephone-line-defsegment +telephone/get-position () + `(,(concat "%lL:%cC" + (if (not mark-active) + "" + (format " | %dc" (- (+ 1 (region-end)) (region-beginning))))))) + (setq-default + telephone-line-lhs '((mode telephone-line-major-mode-segment) + (file-info telephone-line-input-info-segment) + (position +telephone/get-position) + (accent +telephone/buffer-or-filename + telephone-line-process-segment)) + telephone-line-rhs '((accent telephone-line-flycheck-segment telephone-line-misc-info-segment + telephone-line-projectile-segment) + (file-info telephone-line-filesize-segment) + (evil telephone-line-evil-tag-segment))) + (telephone-line-mode)) +#+end_src +* Core packages +Packages that are absolutely necessary for the rest of the +configuration. These yield core functionality such as keybinding, +modal editing, completion, auto typing to name a few. ** General -A good package for defining key bindings. In this case, I generate a -new definer for the "LEADER" keys. Leader is bound to ~SPC~ and it's -functionally equivalent to the doom/spacemacs leader. Local leader is -bound to ~SPC ,~ and it's similar to doom/spacemacs leader but doesn't -try to fully assimilate the local-leader map, instead just picking -stuff I think is useful. I also create defines for general root -bindings. +General provides a great solution for binding keys. It has evil and +use-package support so it fits nicely into configuration. In this +case, I define a "definer" for the "LEADER" keys. Leader is bound to +~SPC~ and it's functionally equivalent to the doom/spacemacs leader. +Local leader is bound to ~SPC ,~ and it's similar to doom/spacemacs +leader but doesn't try to fully assimilate the local-leader map, +instead just picking stuff I think is useful. This forces me to learn +only as many bindings as I find necessary; no more, no less. + +I also define prefix leaders for differing applications. These are +quite self explanatory by their name and provide a nice way to +visualise all bindings under a specific heading just by searching the +code. #+begin_src emacs-lisp (use-package general :demand t @@ -335,9 +472,8 @@ bindings. (general-evil-setup t)) #+end_src - -*** Some default binds in Emacs -Bindings for core functionality +*** Some binds in Emacs +Some bindings that I couldn't fit elsewhere easily. #+begin_src emacs-lisp (use-package emacs :straight nil @@ -382,20 +518,17 @@ Bindings for core functionality (search-leader "i" #'imenu)) #+end_src ** Evil -Evil (Emacs VI Layer) is a package that brings the Vi experience to -Emacs. Packaged with it by default are: -- The modal system -- EX -- Vi mapping functions - -This provides a lot of stuff for the average vim user moving to Emacs. -However there are many other packages surrounding evil that port even -greater functionality from vim to Emacs. Surround, commenting, -multiple cursors and further support to other packages are configured -here. +My editor journey started off with Vim rather than Emacs, so my brain +has imprinted on its style. Thankfully Emacs is super extensible so +there exists a package (more of a supreme system) for porting Vim's +modal editing style to Emacs, called Evil (Emacs Vi Layer). + +However there are a lot of packages in Vim that provide greater +functionality, for example 'vim-surround'. Emacs, by default, has +these capabilities but there are further packages which integrate them +into Evil. *** Evil core Setup the evil package, with some opinionated keybindings: - - Switch ~evil-upcase~ and ~evil-downcase~ because I use ~evil-upcase~ more - Switch ~evil-goto-mark~ and ~evil-goto-mark-line~ as I'd rather have @@ -439,6 +572,7 @@ Setup the evil package, with some opinionated keybindings: (fset #'evil-window-vsplit #'make-frame)) #+end_src *** Evil surround +Evil surround is a port for vim-surround. #+begin_src emacs-lisp (use-package evil-surround :after evil @@ -446,6 +580,7 @@ Setup the evil package, with some opinionated keybindings: (global-evil-surround-mode)) #+end_src *** Evil commentary +Allows generalised commenting of objects easily. #+begin_src emacs-lisp (use-package evil-commentary :after evil @@ -489,133 +624,30 @@ keymap because it uses 'gr' as its prefix, which I don't like. #+end_src *** Evil collection -Setup evil collection, but don't turn on the mode. Instead, I'll turn -on setups for specific modes I think benefit from it. +Provides a community based set of keybindings for most modes in +Emacs. I don't necessarily like all my modes having these bindings +though, as I may disagree with some. So I use it in a mode to mode basis. #+begin_src emacs-lisp (use-package evil-collection :after evil) #+end_src ** Completion -Emacs is a text based interface. Though the standard model of -completion may be desirable to some it can be modernised through the -use of 'completion frameworks'. - -These frameworks handle input and present output from the user for -common commands, providing a differing interface to the one Emacs -comes with. Most of these completion frameworks provide a text based -menu that is actively filtered as more input is provided (progressive -input filtering). Along with these frameworks come added -functionality and applications to integrate into the Emacs environment -further. - -One may say that when using a completion framework there is no point -in using any other framework as they encompasses so much of the -default functionality. This is wrong: I'd argue that with a bit of -management and Emacs lisp it's totally possible to pick and mix your -options. For small number selections (like finding files) use -something like Ido and for something larger like searching buffers use -ivy. - -Along with frameworks, there is a configuration for the -completions-list, which is actually the original and default method of -completion within Emacs. When you first install Emacs without a -config, any 'completing-read' function leverages the completions-list when -~TAB~ is used. - -Though I believe Ido is a better completion system than the -completions-list, it still has it's place and can be used in tandem -with ido. -*** Amx -Amx is a fork of Smex that works to enhance the -execute-extended-command interface. It also provides support for ido -or ivy (though I'm likely to use ido here) and allows you to switch -between them. - -It provides a lot of niceties such as presenting the key bind when -looking for a command. - -#+begin_src emacs-lisp -(use-package amx - :config - (amx-mode)) -#+end_src -*** Orderless -Orderless sorting method for completion, probably one of the best -things ever. -#+begin_src emacs-lisp -(use-package orderless - :after (ivy ido) - :config - (setf (alist-get t ivy-re-builders-alist) 'orderless-ivy-re-builder)) -#+end_src -*** Ido -:PROPERTIES: -:header-args:emacs-lisp: :tangle no -:END: -Ido is a very old completion package that still works great to this -day. Though it is limited in its scope (and may thus be called a -completion add-on rather than a full on framework), it is still a very -powerful package. With the use of ido-completing-read+, it may be used -similarly to a fully fledged completion framework. - -#+begin_src emacs-lisp -(use-package ido - :demand t - :general - (general-def - :keymaps '(ido-buffer-completion-map - ido-file-completion-map - ido-file-dir-completion-map - ido-common-completion-map) - (kbd "M-j") #'ido-next-match - (kbd "M-k") #'ido-prev-match - (kbd "C-x o") #'evil-window-up) - :init - (setq ido-decorations - (list "{" "}" " \n" " ..." "[" "]" " [No match]" " [Matched]" - " [Not readable]" " [Too big]" " [Confirm]") - completion-styles '(flex partial-completion intials emacs22)) - (setq-default ido-enable-flex-matching t - ido-enable-dot-prefix t - ido-enable-regexp nil) - (with-eval-after-load "magit" - (setq magit-completing-read-function 'magit-ido-completing-read)) - :config - (ido-mode) - (ido-everywhere)) -#+end_src -**** Ido ubiquitous -Ido completing-read+ is a package that extends the ido package to work -with more text based functions. -#+begin_src emacs-lisp -(use-package ido-completing-read+ - :after ido - :config - (ido-ubiquitous-mode +1)) -#+end_src -*** Completions-list -#+begin_src emacs-lisp -(use-package simple - :straight nil - :general - (nmmap - :keymaps 'completion-list-mode-map - "l" #'next-completion - "h" #'previous-completion - "ESC" #'delete-completion-window - "q" #'quit-window - "RET" #'choose-completion) - :config - (with-eval-after-load "evil" - (setq evil-emacs-state-modes (cl-remove-if - #'(lambda (x) (eq 'completions-list-mode x)) - evil-emacs-state-modes)) - (add-to-list 'evil-normal-state-modes 'completions-list-mode))) -#+end_src +Emacs is a text based interface. Completion is its bread and butter +in providing good user experience. By default Emacs provides +'completions-list' which produces a buffer of options which can be +searched and selected. We can take this further though! + +Ido and Icomplete are packages distributed with Emacs to provide +greater completion interfaces. They utilise the minibuffer to create +a more interactive experience, allowing incremental searches and +option selection. + +Ivy and Helm provide more modern interfaces, though Helm is quite +heavy. Ivy, on the other hand, provides an interface similar to Ido +with less clutter and better customisation options. *** Ivy -Ivy is a completion framework for Emacs, and my preferred (sometimes -second favourite) one. It has a great set of features with little to -no pain with setting up. +Ivy is a completion framework for Emacs, and my preferred one. It has +a great set of features with little to no pain with setting up. **** Ivy Core Setup for ivy, in preparation for counsel. Turn on ivy-mode just after init. @@ -651,9 +683,6 @@ selection list). #+end_src **** Counsel Setup for counsel. Load after ivy and helpful. - -Along with that, set the help function and variable functions to their -helpful counterparts. #+begin_src emacs-lisp (use-package counsel :after ivy @@ -705,6 +734,8 @@ Counsel etags allows me to search generated tag files for tags. I already have a function defined to generate the tags, so it's just searching them which I find to be a bit of a hassle, and where this package comes in. + +This has been replaced by [[*xref][xref]] which is inbuilt. #+begin_src emacs-lisp (use-package counsel-etags :after counsel @@ -712,6 +743,95 @@ package comes in. (search-leader "t" #'counsel-etags-find-tag)) #+end_src +*** Ido +:PROPERTIES: +:header-args:emacs-lisp: :tangle no +:END: +Ido is a very old completion package that still works great to this +day. Though it is limited in its scope (and may thus be called a +completion add-on rather than a full on framework), it is still a very +powerful package. With the use of ido-completing-read+, it may be used +similarly to a fully fledged completion framework. + +#+begin_src emacs-lisp +(use-package ido + :demand t + :general + (general-def + :keymaps '(ido-buffer-completion-map + ido-file-completion-map + ido-file-dir-completion-map + ido-common-completion-map) + (kbd "M-j") #'ido-next-match + (kbd "M-k") #'ido-prev-match + (kbd "C-x o") #'evil-window-up) + :init + (setq ido-decorations + (list "{" "}" " \n" " ..." "[" "]" " [No match]" " [Matched]" + " [Not readable]" " [Too big]" " [Confirm]") + completion-styles '(flex partial-completion intials emacs22)) + (setq-default ido-enable-flex-matching t + ido-enable-dot-prefix t + ido-enable-regexp nil) + (with-eval-after-load "magit" + (setq magit-completing-read-function 'magit-ido-completing-read)) + :config + (ido-mode) + (ido-everywhere)) +#+end_src +**** Ido ubiquitous +Ido completing-read+ is a package that extends the ido package to work +with more text based functions. +#+begin_src emacs-lisp +(use-package ido-completing-read+ + :after ido + :config + (ido-ubiquitous-mode +1)) +#+end_src +*** Amx +Amx is a fork of Smex that works to enhance the +execute-extended-command interface. It also provides support for ido +or ivy (though I'm likely to use ido here) and allows you to switch +between them. + +It provides a lot of niceties such as presenting the key bind when +looking for a command. + +#+begin_src emacs-lisp +(use-package amx + :config + (amx-mode)) +#+end_src +*** Orderless +Orderless sorting method for completion, probably one of the best +things ever. +#+begin_src emacs-lisp +(use-package orderless + :after (ivy ido) + :config + (setf (alist-get t ivy-re-builders-alist) 'orderless-ivy-re-builder)) +#+end_src +*** Completions-list +In case I ever use the completions list, some basic commands to look +around. +#+begin_src emacs-lisp +(use-package simple + :straight nil + :general + (nmmap + :keymaps 'completion-list-mode-map + "l" #'next-completion + "h" #'previous-completion + "ESC" #'delete-completion-window + "q" #'quit-window + "RET" #'choose-completion) + :config + (with-eval-after-load "evil" + (setq evil-emacs-state-modes (cl-remove-if + #'(lambda (x) (eq 'completions-list-mode x)) + evil-emacs-state-modes)) + (add-to-list 'evil-normal-state-modes 'completions-list-mode))) +#+end_src *** Company Company is the auto complete system I use. I don't like having heavy setups for company as it only makes it slower to use. In this case, @@ -732,23 +852,13 @@ just setup some evil binds for company. #+end_src ** Pretty symbols Prettify symbols mode allows for users to declare 'symbols' that -replace text within certain modes. For example, you may replace the -'for' word in c-mode for [[https://en.wikipedia.org/wiki/Universal_quantification][universal quantification]]. Though this may -seem like useless eye candy, it has aided my comprehension and speed -of recognition (recognising symbols is easier than words). +replace text within certain modes. Though this may seem like useless +eye candy, it has aided my comprehension and speed of recognition +(recognising symbols is easier than words). -Here I provide a macro +pretty/set-alist. This macro works pretty -simply: given a mode hook, as well as a list of pairs typed (text to -substitute, symbol to replace with). Then I add a hook to the given -mode, setting the prettify-symbols-alist to the symbols given. - -I've declared it high up into my config so that the rest of my -packages can leverage it. Furthermore I've added a use-package -keyword which makes declaring this for language modes incredibly easy. -Checkout my [[C/C++][C/C++]] configuration for an example. - -2023-03-08: I've removed the +pretty/set-alist macro and corresponding -function as the use-package declaration is really enough. +Essentially a use-package keyword which makes declaring pretty symbols +for language modes incredibly easy. Checkout my [[C/C++][C/C++]] configuration +for an example. #+begin_src emacs-lisp (use-package prog-mode :straight nil @@ -779,8 +889,8 @@ function as the use-package declaration is really enough. forms))))) #+end_src -Here's a collection of symbols I have currently that may be used -later. +Here's a collection of keywords and their associated symbols, for a +pseudo language. #+begin_example ("null" . "Ø") ("list" . "ℓ") @@ -799,15 +909,12 @@ later. ("lambda" . "λ") #+end_example ** Window management -Window management is really important. I find the default window -handling of Emacs incredibly annoying: sometimes consuming my windows, -sometimes creating new ones. Of course, anything and everything is -adaptable in Emacs, this behavior is no different. - -Here I create a use-package extension that manages the whole ordeal of -adding a new record to the display-buffer-alist, a useful abstraction -that makes it easy to manage the various buffers created by packages. -I also provide bindings for buffer management. +Emacs' default window management is quite bad, eating other windows +and not particularly caring for the current window setup. Thankfully +you can change this via the ~display-buffer-alist~ which matches +buffer names with how the window for the buffer should be displayed. +I add a use-package keyword to make ~display-buffer-alist~ records +within use-package. #+begin_src emacs-lisp (use-package window :straight nil @@ -837,7 +944,7 @@ I also provide bindings for buffer management. (setq arg (cdr arg))) forms))))) #+end_src -*** Setup some display records +*** Some display records Using the ~:display~ keyword, setup up some ~display-buffer-alist~ records. This is mostly for packages that aren't really configured (like [[info:woman][woman]]) or packages that were configured before (like [[Ivy][Ivy]]). @@ -868,23 +975,20 @@ records. This is mostly for packages that aren't really configured (window-height . 0.25))) #+end_src ** Auto typing -Snippets are a system by which pieces of code can be inserted via -prefixes. For example, an 'if' snippet would work by first inserting -the word 'if' then pressing some _expansion key_ such as TAB. This -will insert a set of text that may be have some components that need -to be further filled by the user. - -The popular solution is Yasnippet. Yasnippet is a great package for -snippets, which I use heavily in programming and org-mode. I setup -here the global mode for yasnippet and a collection of snippets for -ease of use. - -However, Emacs provides its own 'auto typing' facilities. Abbrevs and -skeletons make up the popular solution within Emacs default. Abbrevs -are for simple expressions wherein there is only one user input (say, -getting today's time which only requires you asking for it). They -provide a lot of inbuilt functionality and are quite useful. -Skeletons, on the other hand, are for higher level insertions +Snippets are a pretty nice way of automatically inserting code. Emacs +provides a ton of packages by default to do this, but there are great +packages to install as well. + +Abbrevs and skeletons make up a popular solution within Emacs default. +Abbrevs are for simple expressions wherein the only input is the key, +and the output is some Elisp function. They provide a lot of inbuilt +functionality and are quite useful. Skeletons, on the other hand, are +for higher level insertions + +The popular external solution is Yasnippet. Yasnippet is a great +package for snippets, which I use heavily in programming and org-mode. +I setup here the global mode for yasnippet and a collection of +snippets for ease of use. *** Abbrevs Just define a few abbrevs for various date-time operations. Also define a macro that will assume a function for the expansion, helping @@ -949,6 +1053,9 @@ as well. ',skeleton-name))))) #+end_src *** Auto insert +Allows inserting text on creating of a new buffer with a given name. +Supports skeletons for inserting text. Here I define an HTML skeleton +and a Makefile skeleton. #+begin_src emacs-lisp (use-package autoinsert :straight nil @@ -1015,7 +1122,7 @@ memcheck: $(OUT) _))) #+end_src *** Yasnippet default -Setup global mode after evil mode has been loaded +Look at the snippets [[file:.config/yasnippet/snippets/][folder]] for all snippets I've got. #+begin_src emacs-lisp (use-package yasnippet :after evil @@ -1028,165 +1135,11 @@ Setup global mode after evil mode has been loaded :config (yas-load-directory (no-littering-expand-etc-file-name "yasnippet/snippets"))) #+end_src -** Mode line -A mode line in an editor can provide a LOT of information, or very -little. I customised the Emacs modeline to give me a bit of info, -~telephone-line~ to give me a lot. - -Currently I use the default mode line with some customisation; -simplicity is above all. -*** Emacs Mode-line -Firstly, declare a variable for the separator between each module -#+begin_src emacs-lisp -(defconst +modeline/separator " " "Separator between modules.") -#+end_src - -Then declare a variable for the number of separators between each -module in the modeline. -#+begin_src emacs-lisp -(defconst +modeline/sep-count 4 - "Number of +modline/separator instances separating modules.") -#+end_src - -Then, declare a list of reserved characters for which the previously -declared seperator won't be applied when placed at the end of a module -string. -#+begin_src emacs-lisp -(defconst +modeline/reserved-chars (list "[" "(") - "Characters that, when at the end of a module string, won't - have the separator applied to them.") -#+end_src - -Now declare a function that applies the separator with respect to the -reserved characters to any one string. -#+begin_src emacs-lisp -(defun +modeline/handle-string (STR) - (condition-case nil - (progn - (string-blank-p STR) - (if (cl-member (car (last (split-string STR "" t))) +modeline/reserved-chars :test #'string=) - STR - (concat STR (cl-reduce #'concat (cl-loop for i from 1 to +modeline/sep-count collect +modeline/separator))))) - (error STR))) -#+end_src - -Finally, set the mode-line-format. -#+begin_src emacs-lisp -(setq-default - mode-line-format - (mapcar #'+modeline/handle-string - (list "%l:%c" - "%p[" - '(:eval (upcase - (substring - (format "%s" (if (bound-and-true-p evil-state) - evil-state - "")) - 0 1))) - "]" - "%+%b(" - '(:eval (format "%s" major-mode)) - ")" - "%I" - vc-mode - " " - mode-line-misc-info - mode-line-end-spaces))) -#+end_src -*** Telephone-line -:PROPERTIES: -:header-args:emacs-lisp: :tangle no -:END: -Telephone-line is a mode-line package for Emacs which prioritises -extensibility. It also looks much nicer than the default mode line -with colouring and a ton of presentations to choose from. -#+begin_src emacs-lisp -(use-package telephone-line - :init - (defface +telephone/position-face '((t (:foreground "red" :background "grey10"))) "") - (defface +telephone/mode-face '((t (:foreground "white" :background "dark green"))) "") - (defface +telephone/file-info-face '((t (:foreground "white" :background "Dark Blue"))) "") - :custom - (telephone-line-faces - '((evil . telephone-line-modal-face) - (modal . telephone-line-modal-face) - (ryo . telephone-line-ryo-modal-face) - (accent . (telephone-line-accent-active . telephone-line-accent-inactive)) - (nil . (mode-line . mode-line-inactive)) - (position . (+telephone/position-face . mode-line-inactive)) - (mode . (+telephone/mode-face . mode-line-inactive)) - (file-info . (+telephone/file-info-face . mode-line-inactive)))) - (telephone-line-primary-left-separator 'telephone-line-halfcos-left) - (telephone-line-secondary-left-separator 'telephone-line-halfcos-hollow-left) - (telephone-line-primary-right-separator 'telephone-line-identity-right) - (telephone-line-secondary-right-separator 'telephone-line-identity-hollow-right) - (telephone-line-height 24) - (telephone-line-evil-use-short-tag nil) - :config - (telephone-line-defsegment +telephone/buffer-or-filename () - (cond - ((buffer-file-name) - (if (and (fboundp 'projectile-project-name) - (fboundp 'projectile-project-p) - (projectile-project-p)) - (list "" - (funcall (telephone-line-projectile-segment) face) - (propertize - (concat "/" - (file-relative-name (file-truename (buffer-file-name)) - (projectile-project-root))) - 'help-echo (buffer-file-name))) - (buffer-file-name))) - (t (buffer-name)))) - - (telephone-line-defsegment +telephone/get-position () - `(,(concat "%lL:%cC" - (if (not mark-active) - "" - (format " | %dc" (- (+ 1 (region-end)) (region-beginning))))))) - - (setq-default - telephone-line-lhs '((mode telephone-line-major-mode-segment) - (file-info telephone-line-input-info-segment) - (position +telephone/get-position) - (accent +telephone/buffer-or-filename - telephone-line-process-segment)) - telephone-line-rhs '((accent telephone-line-flycheck-segment telephone-line-misc-info-segment - telephone-line-projectile-segment) - (file-info telephone-line-filesize-segment) - (evil telephone-line-evil-tag-segment))) - (telephone-line-mode)) -#+end_src -** Olivetti -Olivetti provides a focus mode for Emacs, which makes it look a bit -nicer with fringes. I also define ~+olivetti-mode~ which will -remember and clear up any window configurations on the frame, then -when turned off will reinsert them - provides a nice way to quickly -focus on a buffer. -#+begin_src emacs-lisp -(use-package olivetti - :commands (+olivetti-mode) - :general - (mode-leader - "o" #'+olivetti-mode) - :init - (setq-default olivetti-body-width 0.6) - (setq olivetti-style nil) - (add-hook 'olivetti-mode-on-hook (proc (interactive) (text-scale-increase 1))) - (add-hook 'olivetti-mode-off-hook (proc (interactive) (text-scale-decrease 1))) - :config - (defun +olivetti-mode () - (interactive) - (if (not olivetti-mode) - (progn - (window-configuration-to-register 1) - (delete-other-windows) - (olivetti-mode t)) - (jump-to-register 1) - (olivetti-mode 0)))) -#+end_src * Small packages ** ISearch +ISearch is the default incremental search application in Emacs. I use +~evil-search-forward~ so I don't interact with isearch that much, but +I may need it occasionally. #+begin_src emacs-lisp (use-package isearch :straight nil @@ -1195,6 +1148,8 @@ focus on a buffer. "M-s" #'isearch-repeat-forward)) #+end_src ** Info +Info is GNU's attempt at better man pages. Most Emacs packages have +info pages so I'd like nice navigation options. #+begin_src emacs-lisp (use-package info :straight nil @@ -1208,9 +1163,10 @@ focus on a buffer. "L" #'Info-history-forward)) #+end_src ** Display line numbers -I don't like using this mode by default, but I'd like to configure it -if possible. Line numbers are a necessary evil a lot of times, and -it's useful for presentations. +I don't really like line numbers, I find them similar to [[*Fringes][fringes]] as +useless space, but at least it provides some information. Sometimes +it can help with doing repeated commands so a toggle option is +necessary. #+begin_src emacs-lisp (use-package display-line-numbers :straight nil @@ -1221,22 +1177,26 @@ it's useful for presentations. :init (setq-default display-line-numbers-type 'relative)) #+end_src -** esup (profiling) +** esup I used to be able to just use [[file:elisp/profiler-dotemacs.el][profile-dotemacs.el]], when my Emacs config was smaller, but now it tells me very little information about -where my setup is inefficient. Just found this ~esup~ thing and it -works perfectly, exactly how I would prefer getting this kind of -information. +where my setup is inefficient due to the literate config. Just found +this ~esup~ thing and it works perfectly, exactly how I would prefer +getting this kind of information. It runs an external Emacs instance +and collects information from it, so it doesn't require restarting +Emacs to profile. #+begin_src emacs-lisp (use-package esup :defer t) #+end_src ** xref -Find definitions, references using tags for free! Such an underrated -utility, particularly now that I'm not using Eglot (in some sense, -returning to the nature of Emacs). All you need is a way of -generating tags, probably a make recipe. +Find definitions, references and general objects using tags without +external packages. Provided by default in Emacs and just requires a +way of generating a =TAGS= file for your project. Helps with minimal +setups for programming without heavier packages like [[*Eglot][Eglot]]. + +[[*Projectile][Projectile]] provides a nice way to generate tags. #+begin_src emacs-lisp (use-package xref :straight nil @@ -1262,21 +1222,24 @@ generating tags, probably a make recipe. "q" #'quit-window)) #+end_src ** Hl-line -Hl-line is a useful tool, best line indicator in the game. +Highlights the current line, much better than a blinking cursor. #+begin_src emacs-lisp (use-package hl-line :defer t :hook (text-mode-hook . hl-line-mode)) #+end_src ** Recentf -Recentf makes it easy to +Recentf provides a method of keeping track of recently opened files. #+begin_src emacs-lisp (use-package recentf :straight nil :hook (emacs-startup-hook . recentf-mode)) #+end_src ** Projectile -Setup projectile, along with the tags command. +Projectile is a project management package which integrates with Emacs +very well. It essentially provides alternative Emacs commands scoped +to the current 'project', based on differing signs that a directory is +a 'project'. #+begin_src emacs-lisp (use-package projectile :after evil @@ -1287,8 +1250,7 @@ Setup projectile, along with the tags command. (setq projectile-tags-command "ctags -Re -f \"%s\" %s \"%s\"")) #+end_src *** Counsel projectile -Counsel projectile provides the ivy interface to projectile commands, -which is really useful. +Counsel integration for projectile commands, very nice. #+begin_src emacs-lisp (use-package counsel-projectile :after (projectile counsel) @@ -1303,17 +1265,16 @@ need to use it. (use-package avy :after evil :general - (search-leader - "l" #'avy-goto-line) (nmmap - (kbd "C-s") #'avy-goto-char-timer - (kbd "M-s") #'isearch-forward)) + "C-s" #'avy-goto-char-timer + "M-s" #'isearch-forward) + (search-leader + "l" #'avy-goto-line)) #+end_src ** Ace window Though evil provides a great many features in terms of window -management, much greater than what's easily available in Emacs, ace -window can provide some nicer chords for higher management of windows -(closing, switching, etc). +management, ace window can provide some nicer chords for higher +management of windows (closing, switching, etc). #+begin_src emacs-lisp (use-package ace-window @@ -1325,8 +1286,9 @@ window can provide some nicer chords for higher management of windows [remap evil-window-next] #'ace-window)) #+end_src ** Helpful -Basic setup that replaces commands and configures -~display-buffer-alist~ for helpful. +Helpful provides a modernised interface for some common help +commands. I replace ~describe-function~, ~describe-variable~ and +~describe-key~ by their helpful counterparts. #+begin_src emacs-lisp (use-package helpful :after ivy @@ -1345,7 +1307,8 @@ Basic setup that replaces commands and configures (evil-define-key 'normal helpful-mode-map "q" #'quit-window)) #+end_src ** Which-key -Pretty simple, just activate after init. +Which key uses the minibuffer when performing a keybind to provide +possible options for the next key. #+begin_src emacs-lisp (use-package which-key :config @@ -1353,7 +1316,7 @@ Pretty simple, just activate after init. #+end_src ** Keychord Keychord is only really here for this one chord I wish to define: "jk" -for exiting insert state. Otherwise, I don't really need it. +for exiting insert state. #+begin_src emacs-lisp (use-package key-chord :after evil @@ -1362,35 +1325,27 @@ for exiting insert state. Otherwise, I don't really need it. (key-chord-mode)) #+end_src ** (Rip)grep -Grep is likely one of the most important programs ever invented; a -must-have tool for any Linux users inventory. It is a searching -utility that allows one to search files for certain regex patterns. -The fact that there have been so many attempts to replace grep (with -limited success) only goes to show how important its general function -is to people. - -Ripgrep is a grep-like utility written in Rust. It subsumes not only -the ability to search a given file but also to search multiple files -within a directory (which is usually only done by composing the -program find with grep to search multiple files). It is incredibly -fast by virtue of its regex optimisations and the use of ignore files -such as ~.gitignore~ to filter files when searching. - -Grep has default Emacs utilities that use a ~compilation~ style buffer -to search a variety of differing data sets. ~grep~ searches files, -~rgrep~ searches in a directory using the ~find~ binary and ~zgrep~ -searches archives. This is a great solution for most computer -environments as basically all of them will have grep and find -installed. Even when you ~ssh~ into a remote machine, they're likely -to have these tools. - -The ripgrep package provides utilities to ripgrep projects and files -for strings via the rg binary. Though [[*Ivy][ivy]] comes with ~counsel-rg~ -using it makes me dependent on the ivy framework, and this -configuration is intentionally built to be modular and switchable. Of -course, this requires installing the rg binary which is available in -most repositories nowadays. +Grep is a great piece of software, a necessary tool in any Linux +user's inventory. By default Emacs has a family of functions to use +grep, presenting results in a ~compilation~ style. ~grep~ searches +files, ~rgrep~ searches in a directory using the ~find~ program and +~zgrep~ searches archives. This is a great solution for a general +computer environment; essentially all Linux installs will have ~grep~ +and ~find~ installed. + +Ripgrep is a Rust program that attempts to perform better than grep, +and it actually does. This is because of a set of optimisations, such +as checking the =.gitignore= to exclude certain files from being +searched. The ripgrep package provides utilities to ripgrep projects +and files for strings. Though [[*Ivy][ivy]] comes with ~counsel-rg~, it uses +Ivy's completion framework rather than the ~compilation~ style +buffers, which sometimes proves very useful. + +Of course, this requires installing the rg binary which is available +in most repositories nowadays. *** Grep +I have no use for standard 'grep'; ~counsel-swiper~ does the same +thing faster and within Emacs lisp. ~rgrep~ is useful though. #+begin_src emacs-lisp (use-package grep :display @@ -1423,6 +1378,34 @@ most repositories nowadays. rg-default-alias-fallback "all" rg-buffer-name "*ripgrep*")) #+end_src +** Olivetti +Olivetti provides a focus mode for Emacs, which makes it look a bit +nicer with fringes. I also define ~+olivetti-mode~ which will +remember and clear up any window configurations on the frame, then +when turned off will reinsert them - provides a nice way to quickly +focus on a buffer. +#+begin_src emacs-lisp +(use-package olivetti + :commands (+olivetti-mode) + :general + (mode-leader + "o" #'+olivetti-mode) + :init + (setq-default olivetti-body-width 0.6) + (setq olivetti-style nil) + (add-hook 'olivetti-mode-on-hook (proc (interactive) (text-scale-increase 1))) + (add-hook 'olivetti-mode-off-hook (proc (interactive) (text-scale-decrease 1))) + :config + (defun +olivetti-mode () + (interactive) + (if (not olivetti-mode) + (progn + (window-configuration-to-register 1) + (delete-other-windows) + (olivetti-mode t)) + (jump-to-register 1) + (olivetti-mode 0)))) +#+end_src ** All the Icons Nice set of icons with a great user interface to manage them. #+begin_src emacs-lisp @@ -1457,9 +1440,13 @@ at last. (save-place-mode)) #+end_src * Applications +Applications are greater than packages; they provide a set of +functionality to create an interface in Emacs. Emacs comes with +applications and others may be installed. ** Dashboard Dashboard creates a custom dashboard for Emacs that replaces the -initial startup screen in default Emacs. +initial startup screen in default Emacs. It has a lot of customising +options. #+begin_src emacs-lisp (use-package dashboard :straight t @@ -1499,18 +1486,24 @@ initial startup screen in default Emacs. (dashboard-setup-startup-hook)) #+end_src ** EWW +Emacs Web Wowser is the inbuilt text based web browser for Emacs. It +can render images and basic CSS styles but doesn't have a JavaScript +engine, which makes sense as it's primarily a text interface. #+begin_src emacs-lisp (use-package eww :defer t + :general + (app-leader + "w" #'eww) :straight nil :config (with-eval-after-load "evil-collection" (evil-collection-eww-setup))) #+end_src ** Calendar -Calendar is a simple inbuilt application within Emacs that helps with -date functionalities. I add functionality to copy dates from the -calendar to the kill ring and bind it to "Y". +Calendar is a simple inbuilt application that helps with date +functionalities. I add functionality to copy dates from the calendar +to the kill ring and bind it to "Y". #+begin_src emacs-lisp (use-package calendar :straight nil @@ -2016,6 +2009,9 @@ don't need to write everything myself. (display-buffer-same-window)) :general (leader "g" '(magit-status :which-key "Magit")) + (nmmap + :keymaps 'magit-status-mode-map + "TAB" #'magit-section-toggle) :init (setq vc-follow-symlinks t) (with-eval-after-load "autoinsert" @@ -2025,6 +2021,8 @@ don't need to write everything myself. (read-string "Enter simple description: ") "\n\n" _))) :config + (with-eval-after-load "evil" + (evil-set-initial-state 'magit-status-mode 'motion)) (with-eval-after-load "evil-collection" (evil-collection-magit-setup))) #+end_src @@ -2165,8 +2163,13 @@ Of course Emacs has a cool screensaver software. Colourising the compilation buffer so ANSI colour codes get computed. #+begin_src emacs-lisp (use-package compile - :defer t :straight nil + :general + (code-leader + "j" #'next-error + "k" #'previous-error + "c" #'compile + "C" #'recompile) :display ("\\*compilation\\*" (display-buffer-at-bottom) @@ -2179,10 +2182,9 @@ Colourising the compilation buffer so ANSI colour codes get computed. (ansi-color-apply-on-region (point-min) (point-max)))) (add-hook 'compilation-filter-hook #'+compile/colourise)) #+end_src -* Major modes, programming and text -Setups for common major modes and languages. -** Text Configuration -Standard packages and configurations for the text-mode. +* Text modes +Standard packages and configurations for text-mode and its derived +modes. *** Flyspell Flyspell allows me to quickly spell check text documents. I use flyspell primarily in org mode, as that is my preferred prose writing @@ -2239,7 +2241,9 @@ limit), so set it for specific modes need the help. whitespace-line-column 80)) #+end_src *** Set auto-fill-mode for all text-modes -Auto fill mode is nice for most text modes, 80 char limit is great. +Auto fill mode automatically newlines text on 80 characters, which +looks nice and integrates well with Evil's sentence and paragraph text +objects. #+begin_src emacs-lisp (add-hook 'text-mode-hook #'auto-fill-mode) #+end_src @@ -2270,8 +2274,10 @@ context and easier to use. (sp-local-pair sp-lisp-modes "(" ")" :unless '(:rem sp-point-before-same-p)) (require 'smartparens-config)) #+end_src -** Programming Configuration -*** Eldoc +* Programming modes +Packages that help with programming in general, providing IDE like +capabilities. +** Eldoc Eldoc presents documentation to the user upon placing ones cursor upon any symbol. This is very useful when programming as it: - presents the arguments of functions while writing calls for them @@ -2292,10 +2298,17 @@ in the minibuffer. A lot cleaner. (setq eldoc-box-position-function #'eldoc-box--default-upper-corner-position-function eldoc-box-clear-with-C-g t)) #+end_src -*** Eglot -Eglot is a library of packages to communicate with LSP servers for -better programming capabilities. Interactions with a server provide -results to the client, done through JSON. +** Eglot +Eglot is package to communicate with LSP servers for better +programming capabilities. Interactions with a server provide results +to the client, done through JSON. + +NOTE: Emacs 28.1 comes with better JSON parsing, which makes Eglot +much faster. + +2023-03-26: I've found Eglot to be useful sometimes, but many of the +projects I work on don't require a heavy server setup to efficiently +edit and check for errors; Emacs provides a lot of functionality. #+begin_src emacs-lisp (use-package eglot :after project @@ -2310,10 +2323,9 @@ results to the client, done through JSON. ;; :init ;; (setq eglot-stay-out-of '(flymake)) :config - (add-to-list 'eglot-server-programs '((c++-mode c-mode) "clangd")) - (add-to-list 'eglot-server-programs `(csharp-mode "~/.local/src/omnisharp-roslyn/run" "-lsp"))) + (add-to-list 'eglot-server-programs '((c++-mode c-mode) "clangd"))) #+end_src -*** Flycheck +** Flycheck Flycheck is the checking system for Emacs. I don't necessarily like having all my code checked all the time, so I haven't added a hook to prog-mode as it would be better for me to decide when I want checking @@ -2337,7 +2349,7 @@ and when I don't. (with-eval-after-load "evil-collection" (evil-collection-flycheck-setup))) #+end_src -*** Tabs and spaces +** Tabs and spaces By default, turn off tabs and set the tab width to two. #+begin_src emacs-lisp (setq-default indent-tabs-mode nil @@ -2350,11 +2362,11 @@ However, if necessary later, define a function that may activate tabs locally. (interactive) (setq-local indent-tabs-mode t)) #+end_src -*** Highlight todo items -TODO items are highlighted in org buffers, but not necessarily in -every buffer. This minor mode highlights all TODO like items via a -list of strings to match. It also configures faces to use when -highlighting. +** Highlight todo items +TODO items are highlighted in org-mode, but not necessarily in every +mode. This minor mode highlights all TODO like items via a list of +strings to match. It also configures faces to use when highlighting. +I hook it to prog-mode. #+begin_src emacs-lisp (use-package hl-todo @@ -2364,20 +2376,20 @@ highlighting. (setq hl-todo-keyword-faces '(("TODO" . "#E50000") ("WAIT" . "#00CC00") - ("FIXME" . "#d02090"))) - ) + ("FIXME" . "#d02090")))) #+end_src -*** Hide-show mode -Turn on ~hs-minor-mode~ for all prog-mode. +** Hide-show mode +Turn on ~hs-minor-mode~ for all prog-mode. This provides folds for +free. #+begin_src emacs-lisp (use-package hideshow :straight nil :hook (prog-mode-hook . hs-minor-mode)) #+end_src -*** Aggressive indenting -Essentially my dream editing experience, when I type stuff in try and -indent it for me on the fly. Just checkout the [[https://github.com/Malabarba/aggressive-indent-mode][page]], any way I -describe it won't do it justice. +** Aggressive indenting +Essentially my dream editing experience: when I type stuff in, try and +indent it for me on the fly. Just checkout the [[https://github.com/Malabarba/aggressive-indent-mode][page]], any description +I give won't do it justice. #+begin_src emacs-lisp (use-package aggressive-indent @@ -2386,11 +2398,13 @@ describe it won't do it justice. :hook (prog-mode-hook . aggressive-indent-mode)) #+end_src +* Languages +Configuration for specific languages or file formats. ** PDF -I use PDFs mostly for reading reports or papers, providing great -formatting options. Though Emacs isn't my favourite application for -viewing PDFs (I highly recommend [[https://pwmt.org/projects/zathura/][Zathura]]), similar to most things with -Emacs, having a PDF viewer builtin can be a very useful asset. +I use PDFs mostly for reading reports or papers. Though Emacs isn't +my preferred application for viewing PDFs (I highly recommend +[[https://pwmt.org/projects/zathura/][Zathura]]), similar to most things with Emacs, having a PDF viewer +builtin can be a very useful asset. For example if I were editing an org document which I was eventually compiling into a PDF, my workflow would be much smoother with a PDF @@ -2414,8 +2428,10 @@ There is no proper PDF viewing without this package. (evil-collection-pdf-setup))) #+end_src *** PDF grep -PDF grep is a Linux tool that allows for searches against PDFs similar -to standard grep (but for PDFs!). +PDF grep is a Linux tool that allows for searches against the text +inside of PDFs similar to standard grep. This cannot be performed by +standard grep due to how PDFs are encoded; they are not a clear text +format. #+begin_src emacs-lisp (use-package pdfgrep :after pdf-tools @@ -2426,8 +2442,10 @@ to standard grep (but for PDFs!). "M-g" #'pdfgrep)) #+end_src ** SQL -SQL package, with support for connecting to common database types -(sqlite, mysql, etc) for auto completion and query execution. +The default SQL package provides support for connecting to common +database types (sqlite, mysql, etc) for auto completion and query +execution. I don't use SQL currently but whenever I need it it's +there. #+begin_src emacs-lisp (use-package sql :straight nil @@ -2438,9 +2456,9 @@ SQL package, with support for connecting to common database types :PROPERTIES: :header-args:emacs-lisp: :tangle no :END: -Check out [[file:elisp/ada-mode.el][ada-mode*]], my custom ~ada-mode~ that replaces the default one. -This mode just colourises stuff, and uses eglot to do the important -stuff. +Check out [[file:elisp/ada-mode.el][ada-mode]], my custom ~ada-mode~ that replaces the default +one. This mode just colourises stuff, and uses eglot and a language +server to do the hard work. #+begin_src emacs-lisp (use-package ada-mode @@ -2464,6 +2482,7 @@ the [[https://elpa.gnu.org/packages/nhexl-mode.html][page]] yourself. :mode "\\.bin") #+end_src ** Org +Org mode *** Org Core Variables Tons of variables for org-mode, including a ton of latex ones. Can't really explain because it sets up quite a lot of local stuff. Also I -- cgit v1.2.3-13-gbd6f