Datacomb

Table of Contents

OCCU
[ early alpha ] Themes: 𝙲𝙾𝙽𝚃𝙰𝙲𝚃 blue⟨at⟩occu.cc
OCCU
Cyberculture
Cartography
Unit
OCCU 22 A Philosophy. Computer Science. Cyberpunk
and Cyberculture Zine

blu3’s Emacs Configuration

Package setup

(require 'package)


(setq package-archives
      '(("gnu" . "https://elpa.gnu.org/packages/")
        ;;        ("gnu-cn"   . "http://mirrors.cloud.tencent.com/elpa/gnu/")
        ("nongnu" . "http://elpa.nongnu.org/nongnu/")
        ;;      ("cselpa" . "https://elpa.thecybershadow.net/packages/")
        ("melpa" . "http://melpa.org/packages/")
        ;;        ("melpa-cn" . "http://mirrors.cloud.tencent.com/elpa/melpa/")
        ))

Misc Configuration

The debug-on-error variable if set to a non-nil value, will make Emacs open a
debugger when a error is evoked.

(setq debug-on-error nil)

Disable tabs

The indent-tabs-mode variable if set to nil, will disable the insertion of tabs when indenting.

(setq indent-tabs-mode nil)

All The Icons

The all-the-icons package is a package which adds various forms of
icons to Emacs. There are additional packages, which adds icons to
dired, ivy etc.

(use-package all-the-icons :ensure t
  :config (all-the-icons-install-fonts 'install-without-asking))

(use-package all-the-icons-dired
  :ensure t
  :config (add-hook 'dired-mode-hook #'all-the-icons-dired-mode))

(use-package all-the-icons-ivy
  :ensure t)

(use-package all-the-icons-completion
  :ensure t)

(use-package all-the-icons-ivy-rich
  :ensure t
  :config (all-the-icons-ivy-rich-mode))

Quicker Yes/No Prompts

This will change the function which is responsible for yes/no prompts,
where as previously you had to explicitly type “yes” or “no”, which
the function changed you only have to type “y” or “n”.

;; change all prompts to y or n
(fset 'yes-or-no-p 'y-or-n-p)

Enable All Functions

This will enable all ‘possibly confusing commands’, such as helpful
and “narrow-to-region” [ C-x n n ].

(setq-default disabled-command-function nil)

Prettify Symbols

The prettify-symbols-mode is a minor-mode which visually will
display strings as prettier Unicode characters. This can be symbols
like Greek letters in LaTeX syntax, such as replacing lambda with
“λ”. Note that this is just visually, and does not change the contents
of the file.

To add custom rules you add a pair containing the string to be
matched, and the symbol to visually display in its place.

(push '(">=" . ?≥) prettify-symbols-alist)
(push '("->" . ?⭢) prettify-symbols-alist)
(push '("<-" . ?⭠) prettify-symbols-alist)
(push '("<==" . ?⟸) prettify-symbols-alist)
(push '("==>" . ?⟹) prettify-symbols-alist)
(push '("<=>" . ?⟺) prettify-symbols-alist)

Enabling prettify-symbols-mode for all programming languages can be
done by adding a hook to prog-mode-hook which is run when editing
programming languages.

(add-hook 'prog-mode-hook #'prettify-symbols-mode)

This can be very useful when programming in various LISP languages, since
nesting lambda functions can look very cluttered.

((lambda (f)
   (lambda (x)
     (lambda (y)
       (lambda (z)
         (+ (f x) (f y) (f z))))))
(lambda (x)
  (* x x)))

With prettify-symbols-mode set to a non-nil value it would look like this.

((λ (f)
   (λ (x)
     (λ (y)
       (λ (z)
         (+ (f x) (f y) (f z))))))
(λ (x)
  (* x x)))

Rectangle Insert

A really useful feature i have implemented and regularly use is
333/rectangle-inject, which will insert a string inside of a
rectangle selection. This is particularly useful when making ASCII art
or when programming in general. Once you start using it, you will use
it all the time. This will bind the function to C-c a i, which you
call after using rectangle select C-x <SPC>. It is important that
you call it with a rectangular selection for it to work, hence i
recommend you only use it together with rectangle select. A tip is
that when selecting rows normally then invoking the function, is that
the inserted text will be in the beginning of the lines, this can be
used to (for example) comment out or indent lines.

(defun 333/rectangle-inject ()
  (interactive)

  (let* ((d  (rectangle-dimensions (region-beginning) (region-end)))
         (l  '())
         (chr (read-string "Fill string:")))

    (dotimes (x (cdr d))
      (setq l (append l `(,chr))))

    (goto-char (region-beginning))

    (insert-rectangle l)))

(global-set-key (kbd "C-c a i") #'333/rectangle-inject)

Occur

Occur will search for a string, and then bring up a buffer containing
all the matching lines. In the buffer you can click on links to jump
to the line in question, you can also run occur-edit-mode, which
will allow you to edit all of the lines directly in that buffer. After
you’re done, you call C-c C-c to apply the changes. I have it bound
to C-c o (my mnemonic is C-c “Occur” o). Pressing <tab> while in
isearch-mode will run occur on the query using the configuration below.

(global-set-key (kbd "C-c o") #'occur)

(define-key isearch-mode-map (kbd "<tab>") #'isearch-occur)

Emacs LISP

I have bound launching the Emacs LISP interpreter ielm to C-z C-z
in emacs-lisp-mode.

(global-set-key  (kbd "C-z C-z") #'ielm)

Form Feed Lines

Replace the form feed character with a horizontal line ^L (will look
like the <hr> in HTML). To type the form feed char, type C-q C-l
on the beginning of a line. Having the character in your source code,
does not effect evaluation, since the char is ignored like
whitespace. If you look at old Emacs LISP source code, you can often
find the form feed line being used. I find this very useful when
organizing my source code.

(use-package form-feed :ensure t
  :config
  (add-hook 'prog-mode-hook 'form-feed-mode)
  (add-hook 'org-mode-hook 'form-feed-mode)
  (add-hook 'text-mode-hook 'form-feed-mode))

Font Spacing

You can set the spacing between lines using the font-spacing
variable, this is useful if you want to make text more readable by
adding some space between rows, or making text more compact by
lessening the spacing (when (for example) making ASCII art).

(setq font-spacing 0.8)

Tab Bar

The major-mode tab-bar-mode will enable a tab bar at the top of the
Emacs frame. This is very useful and will make Emacs behave a little
like other modern IDE’s. I use C-c t n to create a new tab (since
C-t is bound to transpose-char), and C-c t w to close the
current tab (since C-w is bound to kill-region), this will not
close the buffer, just the displaying of the tab. Further more i use
C-c t t to toggle the displaying of the tab bar. To switch between
tabs i use the keybindings M-1, M-2M-9 which will switch to
the tab with that index, or create a new tab if there shouldn’t exist
one with that index. This is done by a custom function i created
called tab-bar-switch-to-or-create.

(defun tab-bar-switch-to-or-create (number)
  "Create or Switch to tab `number'."
  (if (> number (length (funcall tab-bar-tabs-function)))
      (tab-bar-new-tab-to number)
    (tab-bar-select-tab number)))
(tab-bar-mode t)

(setq tab-bar-new-tab-choice "temporary"
      tab-bar-position t
      tab-bar-select-tab-modifiers '(alt meta) ;; Enable ALT as a modifier
      tab-bar-show t
      tab-bar-tab-hints t
      tab-bar-tab-name-function 'tab-bar-tab-name-current-with-count)

Keybindings for closing / adding tabs or toggling the tab bar.

(global-set-key  (kbd "C-c t n") #'tab-new)
(global-set-key  (kbd "C-c t w") #'tab-close)
(global-set-key  (kbd "C-c t t")  #'toggle-tab-bar-mode-from-frame)

Keybindings for switching tabs

(global-set-key  (kbd "M-1")  #'(lambda () (interactive) (tab-bar-switch-to-or-create 1)))
(global-set-key  (kbd "M-2")  #'(lambda () (interactive) (tab-bar-switch-to-or-create 2)))
(global-set-key  (kbd "M-3")  #'(lambda () (interactive) (tab-bar-switch-to-or-create 3)))
(global-set-key  (kbd "M-4")  #'(lambda () (interactive) (tab-bar-switch-to-or-create 4)))
(global-set-key  (kbd "M-5")  #'(lambda () (interactive) (tab-bar-switch-to-or-create 5)))
(global-set-key  (kbd "M-6")  #'(lambda () (interactive) (tab-bar-switch-to-or-create 6)))
(global-set-key  (kbd "M-7")  #'(lambda () (interactive) (tab-bar-switch-to-or-create 7)))
(global-set-key  (kbd "M-8")  #'(lambda () (interactive) (tab-bar-switch-to-or-create 8)))

Unicode Characters

Often the font you use will not support a lot of Unicode chars, but
you can install the package unicode-fonts, which will auto detect
other fonts which can display Unicode and use those fonts for
displaying the other Unicode chars, this is extremely useful since i
often use monospace / coding fonts, which don’t display most Unicode
characters.

(use-package unicode-fonts :ensure t
  :config (unicode-fonts-setup))

Undo Tree

Undo tree for me is a must-have. It adds a undo system which will
display a tree for the undo history instead of a linear undo
system. For example when you undo something, and then edit something,
that change would normally alter the undo history making the original
change hard to reach. Undoing will also only use one keybinding C-x u,
where as a tree will be displayed in a temporary buffer where you
navigate back (undoing) using p, forward (redoing) using n, and
change different branches in the undo history using f and p.

  ;; Allow tree-semantics for undo operations.
  (use-package undo-tree
    :diminish                       ;; Don't show an icon in the modeline
    :bind ("C-x u" . undo-tree-visualize)
    :hook (org-mode . undo-tree-mode) ;; For some reason, I need this. FIXME.
    :config

      ;; Always have it on
      (global-undo-tree-mode)

      ;; Each node in the undo tree should have a timestamp.
      (setq undo-tree-visualizer-timestamps t)

      ;; Show a diff window displaying changes between undo nodes.
      (setq undo-tree-visualizer-diff t))
  ;; Execute (undo-tree-visualize) then navigate along the tree to witness
  ;; changes being made to your file live!

Yasnippet

The package Yasnippet or yas is a package which allows for dynamic
snippets. A snippet is a type of completion where you can type a
keyword, and then expand that keyword into code. I use C-c y n to
create a new snippet, C-c y t to globally toggle YAS, also C-c y y
to expand a snippet (even when yas is disabled).

  (use-package yasnippet :ensure t
    :config

    (yas-global-mode t)

    (global-set-key  (kbd "C-c y n") #'yas-new-snippet)
    (global-set-key  (kbd "C-c y t") #'yas-global-mode)
    (global-set-key  (kbd "C-c y Y") #'yas-expand-from-trigger-key)
    (global-set-key  (kbd "C-c y y")
                      #'(lambda () (interactive)
                         (yas-minor-mode +1)
                         (yas-expand)
                         (yas-minor-mode -1)))


    ;; Set the directory where snippets are stored 
    (setq yas/root-directory '("~/.emacs.d/snippets"))    
    (yas-load-directory (car yas/root-directory))
    
    (setq yas-also-auto-indent-first-line t)
    (setq yas-wrap-around-region t
          yas-good-grace t
          yas-triggers-in-field nil))

Ace Jump

The package ace-jump-mode allows for extremely quick
navigation. Using a keybinding (in my case M-j (mnemonic is M
“Jump” -j). it will display a character in the front of all lines in
all visible buffers, upon typing the char (or chain of chars if there
are lots of lines) the cursor will jump to said line. In the beginning
it will take some time to get used to this, but it will change your
life when you get used to it.

(use-package ace-jump-mode :ensure t
  :config (global-set-key  (kbd "M-j") 'ace-jump-line-mode))

Auto Completion using Company Mode

Here is my configuration for company-mode, which is a completion framework.

(use-package company :ensure t
  :diminish
  :config
  (global-company-mode 1)

  (setq ;; Only 2 letters required for completion to activate.
   company-minimum-prefix-length 2

   ;; Search other buffers for compleition candidates
   company-dabbrev-other-buffers t
   company-dabbrev-code-other-buffers t

   ;; Show candidates according to importance, then case, then in-buffer frequency
   company-transformers '(company-sort-by-backend-importance
                          company-sort-prefer-same-case-prefix
                          company-sort-by-occurrence)

   ;; Flushright any annotations for a compleition;
   ;; e.g., the description of what a snippet template word expands into.
   company-tooltip-align-annotations t

   ;; Allow (lengthy) numbers to be eligible for completion.
   company-complete-number t

   ;; M-⟪num⟫ to select an option according to its number.
   company-show-numbers t

   ;; Show 10 items in a tooltip; scrollbar otherwise or C-s ^_^
   company-tooltip-limit 20

   ;; Edge of the completion list cycles around.
   company-selection-wrap-around t

   ;; Do not downcase completions by default.
   company-dabbrev-downcase nil

   ;; Even if I write something with the ‘wrong’ case,
   ;; provide the ‘correct’ casing.
   company-dabbrev-ignore-case nil

   ;; Immediately activate completion.
   company-idle-delay 0.5)

  ;; Use C-/ to manually start company mode at point. C-/ is used by undo-tree.
  ;; Override all minor modes that use C-/; bind-key* is discussed below.
  (bind-key  (kbd "C-c <tab>") #'company-manual-begin)

  ;; Bindings when the company list is active.
  :bind (:map company-active-map
              ("C-d" . company-show-doc-buffer) ;; In new temp buffer
              ("<ret>" . company-complete-selection)
              ("C-g" . company-abort)
              ("C-o" . counsel-company)
              ;; Use C-n,p for navigation in addition to M-n,p
              ("C-v" . (lambda () (interactive) (company-complete-common-or-cycle 5)))
              ("M-v" . (lambda () (interactive) (company-complete-common-or-cycle -5)))
              ("C-n" . (lambda () (interactive) (company-complete-common-or-cycle 1)))
              ("C-p" . (lambda () (interactive) (company-complete-common-or-cycle -1)))))

Spelling Correction Using flyspell

The package flyspell is a great package for general spelling, both
in programming (in the comments) and in text modes like
org-mode. Here is my config, which allows for correction of text by
right-clicking on misspelled words with the mouse.

(use-package flyspell
  :diminish
  :hook ((prog-mode . flyspell-prog-mode)
         ((org-mode text-mode) . flyspell-mode)))


(eval-after-load "flyspell"
  ' (progn
     (define-key flyspell-mouse-map [down-mouse-3] #'flyspell-correct-word)
     (define-key flyspell-mouse-map [mouse-3] #'undefined)))

Developing Using Treemacs

There is a package called treemacs for Emacs which allows for a
sidebar containing all files of the current directory. treemacs
comes with pretty icons by default, collapsible directories and
synchronization with lsp-mode.

(use-package treemacs :ensure t
  :config
  
    (add-hook 'treemacs-mode-map
              #'treemacs-project-follow-mode)

    (add-hook 'treemacs-mode-map
              #'treemacs-fringe-indicator-mode)

    (add-hook 'treemacs-mode-map
              #'treemacs-icons-dired-mode)

    (add-hook 'treemacs-mode-map
              #'treemacs-filewatch-mode)

    (add-hook 'treemacs-mode-map
              #'treemacs-follow-mode)

    (global-set-key (kbd "<f8>") #'treemacs)
    (global-set-key (kbd "C-+>") #'treemacs-add-or-display-current-project)

    (define-key treemacs-mode-map  (kbd "e")
      #'treemacs-edit-workspaces)    
    )


(use-package treemacs-icons-dired :ensure t
  :config (treemacs-icons-dired-mode))

Set Custom Font

You can set the font of a specific face using set-face-font.
Changing the default face, will set the default font.

(set-face-font 'default "Nono Sans Mono")

Move Selected Text

The package move-text can move selected text / the marked region
using M-<up> or M-<down>.

(use-package move-text
  :config (move-text-default-bindings))

Inline Result of Evaluation

The package eros will display a popup of the answers of evaluations,
which is very convenient and useful when coding or configuring in
Emacs LISP.

(use-package eros :ensure t)

Displaying Documentation in Company Completion

The package company-quickhelp will add the documentation of the
auto-completed function in the candidates list. Setting
company-quickhelp-delay can change how long you have to hover over
the option to show the documentation, which can be useful if you
experience any changes in speed. Pressing M-! while on one of the
candidates will open the function documentation.

(use-package company-quickhelp :ensure t
 :config
   (setq company-quickhelp-delay 0.1)
   (company-quickhelp-mode)
   (bind-key "M-!" #'company-show-doc-buffer 'prog-mode-map))

Highlight Numbers

The package highlight-numbers will highlight numbers when
programming. It is only enabled in programming modes since
highlighting numbers looks really bad in text mores.

(use-package highlight-numbers :ensure t
  :hook ((prog-mode) . highlight-numbers-mode))

Demos for Emacs LISP Documentation

When looking up a function definition with C-h f or variable
definition using C-h v it can be very useful to see different
examples of how to use a function. The package elisp-demos does
this. It adds various examples to a large set of the Emacs LISP
functions.

(use-package elisp-demos
  :config
  ;; Show demos when I do a `C-h o'.
  (advice-add 'helpful-update :after #'elisp-demos-advice-helpful-update)
  ;; Show demos in tooltips when I pause to select a completion, in Emacs Lisp mode.
  (advice-add 'describe-function-1 :after #'elisp-demos-advice-describe-function-1))

Highlighting Keywords in Comments and Code

In the package hl-todo you can define keywords which will be
highlighted, this is very useful. By default there are some keywords
which are highlighted, but below is an example configuration which
adds some more keywords in different colors.

           ;; NOTE that the highlighting works even in comments.
           (use-package hl-todo :ensure t
             ;; I want todo-words highlighted in prose, not just in code fragements.
             :hook (org-mode . hl-todo-mode)
             :config

             ;; Adding new keywords
             (cl-loop for kw in '("HACK" "WTF" "???" "FUCKY")
                      do (add-to-list 'hl-todo-keyword-faces (cons kw "brown1")))

             ;; Adding new keywords
             (cl-loop for kw in '("FINISHED" "DONE" "WORKING")
                      do (add-to-list 'hl-todo-keyword-faces (cons kw "ForestGreen")))

             ;; Adding new keywords
             (cl-loop for kw in '("TODO" "!!!" "HERE" "BUG" "FIX" "BROKEN")
                      do (add-to-list 'hl-todo-keyword-faces (cons kw "yellow2")))

             ;; Adding new keywords
             (cl-loop for kw in '(";;;" "###" "***" "===" "+++" "¨¨¨")
                      do (add-to-list 'hl-todo-keyword-faces (cons kw "LimeGreen")))


             (cl-loop for kw in '(("ENCRYPTED" . "red") ("DECRYPTED" . "green")
                                  ("PRIVATE" . "orange"))
                      do (add-to-list 'hl-todo-keyword-faces kw))

             ;; Enable it everywhere.
             (global-hl-todo-mode))

Acting on Selection With embark

The package embark will allow you to act on your current selection.
Invoking C-. will popup a prompt with a lot of different options such as
capitalizing, indenting the region etc.

(use-package embark
    :ensure t

    :bind
    (("C-c C-e" . embark-act)         ;; pick some comfortable binding
     ("C-h B" . embark-bindings)) ;; alternative for `describe-bindings'

    :init

    ;; Optionally 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)))))