Skip to content

Latest commit

 

History

History
1436 lines (1366 loc) · 48.9 KB

config.org

File metadata and controls

1436 lines (1366 loc) · 48.9 KB

Emacs Config For Programming And Writing (ECFPAW)

GENERATION TIME NOTICE

(current-time-string)
;; This file is a part of ECFPAW,
;; configuration was generated by Emacs Org-Mode on `<<time-notice()>>`
;; This file is a part of ECFPAW,
;; configuration was generated by Emacs Org-Mode on `<<time-notice()>>`

LICENSE NOTICE

;; The GPLv3 License (GPLv3)

;; Copyright © 2024 tusharhero

;; 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 of the License, or
;; 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.  If not, see <http://www.gnu.org/licenses/>.

CHORES [1/5]

Use use-package properly to reduce startup time.

Add more key bindings.

Add shortcut to bold, italicize, etc. in ORG-MODE.

Correct the key bindings for annot-list mode.

Divide this TODO into respective categories in their correct place.

Completely overhaul the way I do keybindings.

BOOTSTRAPPING

;; Run this script to 'bootstrap' ECFPAW from `config.org', of
;; course the only requirement it has is Emacs itself.
(message "Loading Org...")
(require 'org)
(message "Tangling config.org...")
(org-babel-tangle-file "config.org")
(message "ECFPAW has been bootstrapped!")

Startup Optimization

It took 2.7-3 seconds before these optimizations, and now it is 1 seconds.

Garbage collection

Minimize garbage collection before startup and then go back to the default value (8 MiB) after startup.

(setq gc-cons-threshold-default gc-cons-threshold)
(setq gc-cons-threshold most-positive-fixnum)
(add-hook 'emacs-startup-hook
          (lambda ()
            (setq gc-cons-threshold gc-cons-threshold-default)))

Package manager settings

I used to use Elpaca package manager. Although, it gave excellent startup times, it didn’t install the info manuals when available. And I didn’t really use any of its advanced features other than what was already available built in anyway.

(require 'package)
(package-initialize)

Make sure use-package is installed. Got this snippet from Prot’s basic emacs configuration.

(when (< emacs-major-version 29)
  (unless (package-installed-p 'use-package)
    (unless package-archive-contents
      (package-refresh-contents))
    (package-install 'use-package)))

This makes sure that Emacs installs any package that is not available.

(require 'use-package-ensure)
(setopt use-package-always-ensure t)

This informs you if any use-package declaration took longer than 0.1 seconds.

(setopt use-package-verbose t)

Of course, melpha is a community driven package archive. It has more packages than elpa.

(add-to-list 'package-archives
	     '("melpa" . "https://melpa.org/packages/"))

This stops Emacs from just loading all the packages at startup. (We use use-package to load the packages as we wish, so we don’t need this.)

(setopt package-enable-at-startup nil)

Enables M-x use-package-report RET which is helpful in determining which packages take the longest to load.

(setopt use-package-compute-statistics t)

Custom interface

Put all custom configuration into custom.el, else it will put everything in init.el which gets removed every time we tangle.

(setq custom-file (expand-file-name "custom.el" user-emacs-directory))
(if (file-exists-p custom-file)
    (load custom-file))

Emacs lisp vulnerability mitigation.

This is for CVE-2024-53920.

(setq auto-mode-alist (rassq-delete-all 'emacs-lisp-mode auto-mode-alist))
(setq auto-mode-alist (rassq-delete-all 'elisp-byte-code-mode auto-mode-alist))

Generally useful helper functions

There functions are generally useful.

(defun ECFPAW/make-cyclic-list (list)
  "Create a cyclic list."
  (when list
    (setf (cdr (last list)) list)))

DISABLE BELL

It’s very annoying to have that bell ringing all the time.

(setq visible-bell t)
(setq ring-bell-function 'ignore)

WHICH-KEY

which-key basically shows all the keybindings.

(use-package which-key :config (which-key-mode))

Custom keybindings

I will try to keep these to a minimum. Setting up custom keybindings and maintaining them is a headache.

Org

(keymap-global-set "C-c a" 'org-agenda)
(keymap-global-set "C-c c" 'org-capture)

Key Statistics

I need to get some keybinding statistics to improve my keybindings situation.

(use-package keyfreq
  :config (keyfreq-mode 1)
  (keyfreq-autosave-mode 1))

GRAPHICS

Nerd Icons

This uses nerd icons for various things inside Emacs. Since I already use Iosevka nerd font for this configuration it makes sense to use this.

This also has the advantage of working flawlessly in the terminal!

Although it shouldn’t be needed, if you see that the icons do not display, it you might have to install these icons using M-x nerd-icons-install-fonts yes RET.

I used to use all-the-icons before this, but that was inferior to nerd icons because it behaved weirdly inside the terminal.

(use-package nerd-icons)

(use-package nerd-icons-dired
  :hook
  (dired-mode . nerd-icons-dired-mode))

This package needs to load after marginalia-mode, otherwise the icons won’t show up in fido completion menu.

(use-package nerd-icons-completion
  :after marginalia
  :hook (marginalia-mode . nerd-icons-completion-marginalia-setup)
  :config
  (nerd-icons-completion-mode))

FONTS

setting the fonts face

Defining the various fonts Emacs will use.

(add-to-list 'default-frame-alist
             '(font . "Iosevka NF 14"))

GRAPHICAL USER INTERFACE TWEAKS

Let’s make GNU Emacs look a little better.

Mostly just disabling some Emacs features which are for beginners(mostly).

Disable Menu bar and Toolbars

Just too distracting.

(menu-bar-mode -1)
(tool-bar-mode -1)

Disable the scroll bar

Because they are totally unnecessary and I don’t use them. Even if I ever wanted to use my mouse, I would just use my mouse wheel instead of this.

(scroll-bar-mode -1)

Start in maximised mode

(add-to-list 'default-frame-alist '(fullscreen . maximized))

Disable comp warnings

(custom-set-variables '(warning-suppress-types '((comp))))

Spacious Padding

Oh, man this single-handedly makes ECFPAW look so much better. Thanks Prot!

(use-package spacious-padding
   :config (spacious-padding-mode t))

Pulsar

Introduction

Pulsar provides the sweet pulsing of light you see when you switch you buffers, or go to a place in the buffer. It’s super nice for knowing where you are.

Evaluate this to get a pulse 😄.

(pulsar-pulse-line)

basic setup

(use-package pulsar
  :defer nil
  :hook ((next-error . pulsar-pulse-line)
	 (minibuffer-setup . pulsar-pulse-line)
	 (imenu-after-jump . pulsar-recenter-top)
	 (imenu-after-jump . pulsar-reveal-entry))
  :custom
  (pulsar-pulse t)
  (pulsar-delay 0.2)
  (pulsar-iterations 2)
  (pulsar-face 'pulsar-magenta)
  (pulsar-highlight-face 'pulsar-yellow)
  :config
  (pulsar-global-mode 1))

THEME

I use Modus themes.

Ef-themes

(use-package ef-themes
  :defer t
  :custom (ef-themes-mixed-fonts t))

Modus-themes

(setq modus-themes-mixed-fonts t)

Easy cycling

  • [ ] Figure out a way to automatically wait for the correct package to load before running ECFPAW/cycle-theme, I tried doing it using this code, but that does not really work.
    (with-eval-after-load (car ECFPAW/themes)
      (ECFPAW/cycle-my-theme))
        
I have a custom function for loading and cycling through my preferred themes.
(defvar ECFPAW/themes (ECFPAW/make-cyclic-list
                       (list 'modus-vivendi 'modus-operandi))
  "A list of the themes I like and use.")

(setq custom-safe-themes t)
(advice-add 'load-theme
            :before (lambda (theme &optional no-confirm no-enable)
                      (disable-theme (car custom-enabled-themes))
                      (spacious-padding-mode t)))

(defun ECFPAW/cycle-my-theme ()
  "Cycle through a list of themes, `ECFPAW/themes'."
  (interactive)
  (load-theme (pop ECFPAW/themes) t))

Day and night switching

This is used to make theme switch to the light theme at day and the dark theme at night.

(use-package circadian
  :custom (circadian-themes '(("6:00" . modus-operandi)
                              ("18:00" . modus-vivendi)))
  :config
  (circadian-setup))

TRANSPARENCY

With Emacs version 29, true transparency has been added.

Setting initial transparency

(add-to-list 'default-frame-alist '(alpha-background . 100)) ; For all new frames henceforth

Function to change the transparency of the current frame.

Wayland

This works only on Wayland, So disable it and enable the block above.

(defun ECFPAW/change-current-transparency-to (alpha-val)
  "Change the transparency to the given value"
  (interactive "nChange transparency: ")
  (set-frame-parameter (selected-frame) 'alpha-background alpha-val))

MODE-LINE

I am going to make my own mode-line, I followed Prot’s tutorial.

Mode-line-helpers

(defmacro ECFPAW/def-mode-line-constr (constr-name val docstring)
  "Define CONSTR-NAME as a mode-line construct with value VAL.
DOCSTRING is used a docstring."
  `(progn (defvar-local ,constr-name ,val ,docstring)
         (put ',constr-name 'risky-local-variable t)))

Mode-line formats

I used to copy this format manually.

(defvar ECFPAW/mode-line/default-format
  (default-value 'mode-line-format)
  "The vanilla default Emacs mode line format.")

The format works with PDF view mode too now (it displays the page number properly). Also removed some cosmetic noise from here.

(defvar ECFPAW/mode-line/format
  '(""
    mode-line-front-space
    ECFPAW/mode-line/major-mode
    " "
    mode-line-buffer-identification
    " "
    mode-line-position
    " "
    mode-line-misc-info
    " "
    mode-line-format-right-align
    ECFPAW/mode-line/time
    mode-line-end-spaces
    )
  "ECFPAW's mode line format."
  )

Mode-line constructs

(ECFPAW/def-mode-line-constr
 ECFPAW/mode-line/major-mode
 '(:eval
   (propertize (symbol-name major-mode) 'face 'modus-line))
 "Mode line construct to display the major mode.")

(ECFPAW/def-mode-line-constr
 ECFPAW/mode-line/time
 '(:eval
   (propertize
    (format-time-string "%R %a %d-%b-%y")))
 "Mode line construct to display the time")

Default mode-line, and cycling.

(setq-default mode-line-format ECFPAW/mode-line/format)
(defvar ECFPAW/mode-line/formats
  '(ECFPAW/mode-line/format
    ECFPAW/mode-line/default-format)
  "A list of all the modelines available.")

(defun ECFPAW/mode-line/switch-to-format (format)
  "Switch to mode-line `FORMAT'."
  (interactive
   (list (eval
	  (intern (completing-read
		   "Switch to mode-line format: "
    		   ECFPAW/mode-line/formats)))))
  (setq mode-line-format  format)
  (force-mode-line-update))

Diminish modes

Hide some minor modes.

(use-package diminish
  :defer t
  :config
  (diminish 'which-key-mode))

LINE NUMBERS

I am using this function because sometimes absolute line number is better than relative. And I have decided to NOT enable these by default because they are super distracting.

(defvar ECFPAW/line-number-list
  (ECFPAW/make-cyclic-list (list 'relative 'absolute))
  "list of line numbers")

(defun ECFPAW/cycle-line-number-type ()
  "Cycle through line number types"
  (interactive)
  (setq display-line-numbers (pop ECFPAW/line-number-list)))

FUN

Things that have no practical utility but are fun anyway.

Zone out

This does fun things where you stop using Emacs for a while.

functions

(setq zone-programs [
                     zone-pgm-putz-with-case
                     zone-pgm-dissolve
                     zone-pgm-explode
                     zone-pgm-whack-chars
                     zone-pgm-rotate
                     zone-pgm-drip
                     zone-pgm-five-oclock-swan-dive
                     zone-pgm-martini-swan-dive
                     zone-pgm-rat-race
                     zone-pgm-paragraph-spaz
                     zone-pgm-stress
                     zone-pgm-stress-destress
                     zone-pgm-random-life
                     ])

Jokes

So here are some Emacs related jokes, which are strategically used wherever possible in Emacs.

(defvar ECFPAW/jokes (list
                   "What is like the org-mode? What can make war against it?"
                   "I teach Quantum Mechanics to toddlers."
                   "STOP HAVING FUN !!! 😠"
                   "Why did the Emacs user switch to Vim? Because they wanted to be able to exit the editor."
                   "Emacs is a good operating system, it just lacks a good text editor (komedi😆)"
                   ) "List of Jokes.")

Random commands

Adapted from Sacha Chua’s config. I just get the symbol, don’t open the documentation.

(defun ECFPAW/get-random-command ()
  "Get the symbol of a random command.
     Consider only documented, non-obsolete commands."
  (interactive)
  (let (result)
    (mapatoms
     (lambda (symbol)
       (when (and (commandp symbol)
		  (documentation symbol t)
		  (null (get symbol 'byte-obsolete-info)))
	 (setq result (cons symbol result)))))
    (elt result (random (length result)))))

LLM-SUPPORT

I like to use Ollama on my local(and remote) computers 😄.

Ollama management

I find myself needing to manage my ollama instances.

Get request for emacs

I need a requests library because url is too much of a pain to use.

(use-package plz :defer t)

Get a list of Ollama instances

(defun ECFPAW/ollama-get-model-names (ollama-host)
    "Gets the names of models available in OLLAMA-HOST as a list."
    (require 'plz)
    (mapcar (lambda (model) (alist-get 'name model))
            (alist-get 'models
                       (plz 'get
                         (format "http://%s/api/tags" ollama-host)
                         :as #'json-read))))

Add Ollama models

  • [ ] Fix this function as currently, it just calls the API waits for the first response and then immediately.
(defun ECFPAW/ollama-pull-model (ollama-host model-name)
  "Pull model named MODEL-NAME in OLLAMA-HOST."
  (interactive "MOllama host: \nMModel name: ")
  (require 'plz)
  (plz 'post (format "http://%s/api/pull" ollama-host)
    :headers '(("Content-Type" . "application/json"))
    :body (json-encode '(("name" . model-name)))
    :as #'json-read))

GPTEL

Configuration

I currently just use Ollama, I have 2 backends defined one of them is the local Ollama backend which uses the port 11434, the other one is the remote backend, which uses the port 11435. You are supposed use ssh redirection to redirect your remote ollama server to the port 11435.

To redirect any port from a remote machine, use the following command:

ssh -L local_port:remote_address:remote_port username@server.com
(use-package gptel
  :defer t
  :custom (gptel-backend nil)
  :hook (gptel-mode . ECFPAW/load-models)
  :hook (gptel-post-response . gptel-end-of-response)
  :hook (gptel-mode . olivetti-mode)
  :hook (gptel-mode . (lambda nil (auto-fill-mode -1)))
  :config
  (defun ECFPAW/load-models ()
    (interactive)
    (let* ((host "localhost:11434")
           (models (condition-case nil
                       (ECFPAW/ollama-get-model-names host)
                     (plz-error nil))))
      (setq-default gptel-model (car models)
                    gptel-backend (gptel-make-ollama "Ollama"
                                    :host host
                                    :stream t
                                    :models models)))
    (let ((host "localhost:11435"))
      (gptel-make-ollama "Ollama(remote)"
        :host host
        :stream t
        :models (condition-case nil
                    (ECFPAW/ollama-get-model-names host)
                  (plz-error nil)))))
  (ECFPAW/load-models))

System Prompts

  • [X] Perhaps write elisp code extract this info from an org-tree instead.
We will just set the directives by taking them from Prompts.
`(setq gptel-directives 
',(mapcar
 (lambda (prompt)
   `(,(intern (car prompt)) . ,(cadr prompt)))
 (cdr (org-map-entries
       (lambda ()
         `(,(substring-no-properties
             (org-get-heading))
           ,(format "\"%s\"" (substring-no-properties
             (org-agenda-get-some-entry-text (point-marker) most-positive-fixnum)))))
       "prompts"))))
<<prompts()>>

Prompts

This org-tree contains the actual prompts.

default

You are a large language model living in Emacs and a helpful assistant Respond concisely.

nobullshit

To assist: Be terse Do not offer unprompted advice or clarifications. Speak in specific, topic relevant terminology Do NOT hedge or qualify. Do not waffle. Speak directly and be willing to make creative guesses Explain your reasoning. if you don’t know, say you don’t know

Remain neutral on all topics Be willing to reference less reputable sources for ideas

Never apologize Ask questions when unsure.

writing

You are a large language model and a writing assistant Respond concisely.

chat

You are a large language model and a conversation partner Respond concisely.

programmer

You are a careful programmer Provide code and only code as output without any additional text, prompt or note

cliwhiz

You are a command line helper Generate command line commands that do what is requested, without any additional description or explanation Generate ONLY the command, I will edit it myself before running

emacser

You are an Emacs maven Reply only with the most appropriate built-in Emacs command for the task I specify Do NOT generate any additional description or explanation

explain

Explain what this code does to a novice programmer

overtlyrational

You are rationalAI, an extremely rational chatbot You will always take the side of evidence and reason You will reject any ideas which are irrational You only care about being rational and nothing else. You will not give any explanations or clarifications for your position, you will talk to the point You will not claim to hold no position, You will hold a position in accordance with reason and evidence ONLY You will NOT write word salads, you will only talk sense

gitcoomitor

Read the prompt calmly and read each addition, deletion and no-changed line carefully. Focus on changes, not only last or first, figure out the main idea of the input. If complex, break it down into smaller parts to organize your thoughts. Then, craft a good commit message based on the input context. Write a commit message based on the git diff. Read the diff below and write a commit message that describes the changes made.

Overlay

Overlays are like text properties but for the buffer instead of the string.

Just some helper functions to use them easily.

(defun ECFPAW/get-starting-ending-points (string)
  "Get starting and ending point of `STRING'."
  (save-excursion
  (search-forward string)
  `(,(match-beginning 0) ,(match-end 0))))

(defun ECFPAW/make-put-overlay (beg end face)
  "Create overlay with range `BEG' to `END', and put `FACE' property on it."
  (overlay-put (make-overlay beg end) 'face face))

(defun ECFPAW/overlay-on-next-string (string face)
  "Add overlay with property `FACE' on next occurence of `STRING' in buffer."
  (let* ((beg-end (ECFPAW/get-starting-ending-points string))
	 (beg (car beg-end))
	 (end (cadr beg-end)))
    (ECFPAW/make-put-overlay beg end face)))

(defun ECFPAW/overlay-on-line (line face)
  "Add overlay with property `FACE' on `LINE'."
  (save-excursion
    (goto-char (point-min))
    (forward-line (1- line))
    (ECFPAW/make-put-overlay (pos-bol) (pos-eol) face)))

SCRATCH

Make Scratch buffer the initial buffer

I am using the scratch buffer to emulate what I used the dashboard mostly for anyway (think cool startup screen).

(setq initial-buffer-choice t)

Fancy initial scratch message

Disable the initial scratch buffer message and instead insert custom manually instead. This is because Emacs tries doing some smart things with it which makes it harder to work with. Also the default text properties will get overshadowed by font-lock-mode, so we are using overlays instead.

(setq initial-scratch-message nil)

(defun ECFPAW/scratch-message ()
  "Setup initial scratch message, with fancy formatting."
  (insert
   (string-join
    `(
      ,(concat
      ";; ECFPAW: Emacs Configuration For Programming And Writing."
      " -*- lexical-binding: t; -*-"
      )
      ,(emacs-init-time ";; Initialized in %f seconds.")
      ,(format ";; jokes: \"%s\"" (seq-random-elt ECFPAW/jokes))
      ,(format ";; random command: `%s', type ‘C-h f’ to learn more about it." (ECFPAW/get-random-command))
      "\n;; This is the Scratch buffer."
      "\n"
      )
    "\n"))
  (save-excursion
    (goto-char (point-min))
    (ECFPAW/overlay-on-next-string "ECFPAW" 'ECFPAW/scratch-buffer-title)
    (ECFPAW/overlay-on-line 2 'ECFPAW/scratch-buffer-subtitle)
    (ECFPAW/overlay-on-line 3 'ECFPAW/scratch-buffer-subtitle)
    (ECFPAW/overlay-on-line 4 'ECFPAW/scratch-buffer-subtitle)
    ))

(add-hook 'lisp-interaction-mode-hook 'ECFPAW/scratch-message)

Just for a little fanciness.

(defface ECFPAW/scratch-buffer-title '((t :height 2.0 :slant italic :weight heavy))
  "Face used for fancy title in scratch buffer.")
(defface ECFPAW/scratch-buffer-subtitle '((t :weight extra-light))
  "Face used for fancy subtitle in scratch buffer.")

PROJECT

I was using projectile before but then I realized that I don’t use most of its functionality(Basically it was bloated for me). That is why I have decided to switch to project.el, the builtin project management functionality of Emacs.

(setq project-switch-commands 'project-find-dir)

DIRED

Dired is a file manager within Emacs. It comes builtin.

Basic tweaks

I am disabling the display additional info by default because I get overwhelmed.

(add-hook 'dired-mode-hook 'dired-hide-details-mode)

Add human readable directory sizes in the directory listing, because, well, I AM A HUMAN!

(setopt dired-listing-switches (concat dired-listing-switches "h"))

Enable hl-line-mode

(add-hook 'dired-mode-hook 'hl-line-mode)

COMPLETION

Fido

  • [ ] Add support for spell checking with Fido and ispell.

Friendship ended with Helm, Fido is my new friend.

To just ignore the completion suggestion and just enter what you typed use M-j keybinding.

(fido-vertical-mode)

Marginalia

This package provides useful annotations(information on the side) for Fido completions.

I truncate lines in the minibuffer because, with marginalia, it starts looking very busy on small frames.

(use-package marginalia
  :hook (minibuffer-setup . (lambda () (setq truncate-lines t)))
  :init (marginalia-mode))

Corfu

  • [X] Fix this corfu error
Error running timer ‘corfu--auto-complete-deferred’: (wrong-number-of-arguments #<subr evil-normalize-keymaps> 4)

Fixed by removing evil!

  • [ ] Setup the cape extensions properly
  • [X] Foreshadowing completion support for most cases… Basically I need this package , https://code.bsdgeek.org/adam/corfu-candidate-overlay I need to do a bit more research though because a lot of stuff uses my TAB key.
  • [ ] Fix it for use without evil.
I used to use Company but that had some issue like, dictionary disabling all the other symbols.

To complete, please use C-<tab>

The following configuration was copied from this config, although now I have removed most of what I had copied. (They helped me with this setup :) )

(use-package corfu)

(use-package corfu-terminal
  :unless window-system
  :hook (corfu-mode . corfu-terminal-mode))

  (use-package cape
  :preface
  (defun setup-cape-extensions ()
    (dolist (cape-fn '(dict emoji)) ;; keyword file  dabbrev tex emoji elisp-symbol))
      (add-to-list 'completion-at-point-functions (intern (format "cape-%s" cape-fn)))))
  :hook (corfu-mode . setup-cape-extensions))

(use-package corfu-candidate-overlay
  :after corfu
  :config
  (corfu-candidate-overlay-mode t))

TEXT

Some stuff which are for text editing in general.

Miscellaneous

Sentences mostly end with a single space nowadays, but Emacs text editing commands (like M-a and M-e) only treat sentences ending with two spaces as sentences by default, this is annoying.

(setq sentence-end-double-space nil)

Electric

Electric pairs

Adds the next pair for ( automatically.

(electric-pair-mode 1)

Enable auto-fill mode by default

I love auto-fill mode, it basically wraps the line at 80 characters for you. So that the line is not too big and readable.

(add-hook 'text-mode-hook 'auto-fill-mode)

Prettify mode

enabling it globally

(setq prettify-symbols-unprettify-at-point t)
(global-prettify-symbols-mode)

Create symbol packs

Marco for creating symbol pack

This macro will create a function which can then be hooked to the mode you want to hook them to 💀. My mind is struggling to comprehend that.

(defmacro ECFPAW/def-pretty-sym-pack (name symbols-alist)
  "A macro to create a function NAME to apply symbols in SYMBOLS-ALIST.
The generated function can be hooked to any mode."
  `(progn
     (defun ,name ()
       (setq prettify-symbols-alist (append prettify-symbols-alist
                                            ',symbols-alist
                                            )))))

Function for adding pretty symbols pack to a mode

(defun ECFPAW/add-pretty-sym-pack (mode-hook pack-list)
  "Add all the packs present in PACK-LIST to MODE-HOOK."
  (dolist (pack pack-list)
    (add-hook mode-hook pack)))

Symbol packs themselves

(ECFPAW/def-pretty-sym-pack
 ECFPAW/prettify-symbols-pack/belong-symbols
 (("in"     . #x2208)
  ("not in" . #x2209)))

(ECFPAW/def-pretty-sym-pack
 ECFPAW/prettify-symbols-pack/in-equalities
 (("<="     .  "" )
  (">="     .  "" )
  ("=="     .  "" )
  ("!="     .  "" )))

(ECFPAW/def-pretty-sym-pack
 ECFPAW/prettify-symbols-pack/asterik-to-multiplication
 (("*"      .   "×")))

(ECFPAW/def-pretty-sym-pack
 ECFPAW/prettify-symbols-pack/lambda
 (("lambda" .  955 )))

(ECFPAW/def-pretty-sym-pack
 ECFPAW/prettify-symbols-pack/function
 (("def"    .  "𝒻")))

(ECFPAW/def-pretty-sym-pack
 ECFPAW/prettify-symbols-pack/pointers
 (("->"     . "")
  ("=>"     . "")
  ("<-"     . "")))

(ECFPAW/def-pretty-sym-pack
 ECFPAW/prettify-symbols-pack/redirections
 (("<<"     . "")
  (">>"     . "")
  ("<<"     . "")
  (">>"     . "")))

Enable narrow to region

(put 'narrow-to-region 'disabled nil)

For focused writing

(use-package olivetti
  :defer t
  :custom (olivetti-body-width 80))

Enable spell checking by default

(add-hook 'text-mode-hook 'flyspell-mode)

MANUALS

This will solve any issues I have with documentation.

Texinfo

Add info manual from a custom location.

(push
 (expand-file-name
  "info/"
  user-emacs-directory)
 Info-default-directory-list)

DOC-VIEW

I use Doc-View to view documents within Emacs.

(custom-set-variables
 '(doc-view-continuous t))

PDF-Tools MODE

WARNING: I have hack here, which just changes the definition of the key map directly. I should do it more properly. I also directly start with follow minor mode instead of starting with the normal mode.

(use-package pdf-tools :init (pdf-loader-install)
  :demand t
  :mode ("\\.vpdf\\'" . pdf-virtual-edit-mode)
  :bind (:map pdf-view-mode-map ("C-c p" . ECFPAW/pdf-page-number-to-scratch))
  :hook (pdf-annot-list-mode . pdf-annot-list-follow-minor-mode)
  :hook (pdf-virtual-view-mode . (lambda () (breadcrumb-local-mode -1)))
  :config
  (setq pdf-annot-list-mode-map
	(let ((km (make-sparse-keymap)))
	  (define-key km (kbd "C-c C-f") #'pdf-annot-list-follow-minor-mode)
	  (define-key km (kbd "C-<return>") #'pdf-annot-list-display-annotation-from-id)
	  km))
  <<page-scratch>>)

I use this to quickly create virtual PDFs. I might refine it further in the future. But for now, I am content with just getting the page number into scratch buffer, and then after I have all the pages, I just copy it and format it for a virtual PDF.

(defun ECFPAW/pdf-page-number-to-scratch ()
  "Insert current PDF page number into the scratch buffer."
  (interactive)
  (let ((page (number-to-string (pdf-view-current-page))))
    (scratch-buffer)
    (insert page)))

CASUAL

Casual is like magit but for other things as well.

It excellent for discoverability, the only reason I am able to use:

  • calc
  • calendar

I am sure I will slowly discover more Emacs functionality, and casual interfaces from them.

(use-package casual
  :after calc
  :config
  (keymap-set calc-mode-map "C-c l" #'casual-calc-tmenu)
  (keymap-set calendar-mode-map "C-c l" #'casual-calendar))

ORG-MODE

… What is like the org-mode? What can make war against it? …

Inserting time and date

Here I will make a custom function which will help me insert time and date.

(defun ECFPAW/insert-now-timestamp()
  "Insert org mode timestamp at point with current date and time."
  (interactive)
  (org-insert-time-stamp (current-time) t))

Hide emphasis markers

I decided that I don’t like to see emphasis markers in org-mode.

(setq org-hide-emphasis-markers t)

Enabling modern

I used to use org superstar, but apparently org modern is better.

(use-package org-modern
  :hook (org-mode . org-modern-mode)
  :hook (org-mode . org-indent-mode)
  :hook (org-agenda-finalize . org-modern-agenda)
  :custom
  (org-modern-star 'replace)
  (org-modern-block-fringe nil))

Enabling org-tempo

This packages allows shortcuts for source blocks etc.

(require 'org-tempo)

Fix electric-mode inhibiting tempo.

(add-hook 'org-mode-hook (lambda ()
           (setq-local electric-pair-inhibit-predicate
                   `(lambda (c)
                  (if (char-equal c ?<) t (,electric-pair-inhibit-predicate c))))))

Journal and Task

Agenda and capturing

(setq org-capture-templates
      `(("t" "Todo" entry (file+headline
                           ,(concat goals-directory "tasks.org") "Tasks")
         "* TODO %?\n  %i\n  %a")
        ("j" "Journal" entry (file+datetree
                              ,(concat goals-directory "journal.org"))
         "* %?\nEntered on %U\n  %i\n  %a")))
(setq org-agenda-files `(,(concat goals-directory "tasks.org")
                         ,(concat goals-directory "journal.org")))

Add breadcrumbs because I get confused about which task I am looking at.

(setq org-agenda-prefix-format
      '((agenda . " %i %-12:b%?-12t% s") (todo . " %i %-12:c")
  	(tags . " %i %-12:c") (search . " %i %-12:c")))
(setq org-agenda-clockreport-parameter-plist '(:link t :maxlevel 5))

Its just annoying to look at this point.

(setq org-agenda-show-future-repeats nil)

And enable habit module!

(add-to-list 'org-modules 'habit t)

Babel

Babel allows you execute programming languages from within org-mode.

languages

Enable babel execution for Python too.

(org-babel-do-load-languages
 'org-babel-load-languages
 '((emacs-lisp . t)
   (python . t)))

Org-Download

This extension allows drag and drop of images.

(use-package org-download
  :hook (dired-mode . org-download-enable))

Org custom cookies

Cookies basically give you information about the list.

  • [-] Things that need to implemented [4/5]
    • [X] C-c C-c support for custom cookies
      • [X] Stop other org-ctrl-c-ctrl-c functions from running if our function has already run.
    • [X] Face support for custom cookies
    • [X] Add better face support for custom cookies
    • [X] Fix heading color bug.
    • [ ] A custom percentage [%] statistic cookie
      • Here is a regex for that,
        "\\[?\\(?:[0-9]*\\)?\\!%]"
                    

        It will use the [!%] symbol to avoid conflicts with [%].

(use-package org-custom-cookies
  :after org
  :custom (org-custom-cookies-enable-cookie-face t)
  :config
  (advice-add 'org-update-statistics-cookies :after
              'org-custom-cookies--update-all-cookies-current-heading)
  (push '("\\[[.0-9]+\\]"
          . ECFPAW/org-custom-cookies--direct-descendant-subentries)
        org-custom-cookies-alist)
  (add-hook 'org-ctrl-c-ctrl-c-hook
            'org-custom-cookies--update-cookie-ctrl-c-ctrl-c))

Subheading counting

It will help me get the number of direct sub-entries in the list. Through a cookie, to use it, [D:] needs to be put at the heading.

(defun ECFPAW/org-number-of-subentries (&optional pos match scope level)
  "Return number of subentries for entry at POS. MATCH and SCOPE are
the same as for `org-map-entries', but SCOPE defaults to 'tree. By
default, all subentries are counted; restrict with LEVEL."
  (save-excursion
    (goto-char (or pos (point)))
    ;; If we are in the middle ot an entry, use the current heading.
    (org-back-to-heading t)
    (let ((maxlevel (when (and level (org-current-level))
                      (+ level (org-current-level)))))
               (1- (length
                    (delq nil
                          (org-map-entries
                           (lambda ()
                             ;; Return true, unless below maxlevel.
                             (or (not maxlevel)
                                 (<= (org-current-level) maxlevel)))
                           match (or scope 'tree))))))))
(defun ECFPAW/org-number-of-direct-descendant-subentries (&optional pos match scope)
  "Return number of subentries for entry at POS. MATCH and SCOPE are
the same as for `org-map-entries', but SCOPE defaults to 'tree. By
default, only the direct descendant subentries are counted."
  (ECFPAW/org-number-of-subentries pos match scope 1))
(defun ECFPAW/org-custom-cookies--direct-descendant-subentries ()
  "Return the total number of direct discendants."
  (format "[%s]" (ECFPAW/org-number-of-direct-descendant-subentries)))

NEWS-TICKER

newsticker is a feed reader for Emacs.

Loading feeds

To keep the feeds private, I have the feeds listed in a file called feeds.el.

To remove this from your git tracking use this,

git update-index --assume-unchanged feed.el
(load-file
 (expand-file-name
  "feed.el"
  user-emacs-directory))

Making eww the default

(setq browse-url-browser-function 'eww-browse-url)

GIT

Git is the best version control system(The only one I have ever used). You can use it for anything BTW, not just programming. For instance when writing stories, its convenient to have Git manage the versions for you.

MAGIT

Magit (Maggot , magic IDK) is a git client for Emacs.

(use-package transient :defer t)
(use-package magit :defer t)

PINENTRY

For getting support for GPG(GNU Privacy Guard).

(use-package pinentry :config (pinentry-start))

To use, add allow-emacs-pinentry to ~/.gnupg/gpg-agent.conf, reload the configuration with gpgconf --reload gpg-agent.

To enable gpgsigning for a repository, run this.

git config --local commit.gpgsign true

DIFF

EDIFF

I never realized how useful ediff was. And I think its because the defaults suck. I got this from Prot’s config.

(use-package ediff
  :ensure nil
  :commands (ediff-buffers ediff-files ediff-buffers3 ediff-files3)
  :init
  (setq ediff-split-window-function 'split-window-horizontally)
  (setq ediff-window-setup-function 'ediff-setup-windows-plain)
  :config
  (setq ediff-keep-variants nil)
  (setq ediff-make-buffers-readonly-at-startup t)
  (setq ediff-merge-revisions-with-ancestor t)
  (setq ediff-show-clashes-only t))

FLYCHECK

Flycheck can do a lot of stuff including,

  • Showing errors in programs,
  • Showing spelling errors.
(use-package flycheck
  :defer t
  :init (global-flycheck-mode))

PROGRAMMING

ENVRC/DIRENV

I used to use Direnv and then I decided to switch to Guix shell, I was literally starting an Emacs instance per project by launching Emacs from inside a Guix shell. But after reading this post it seems that I need envrc so that I can automatically switch to the Guix shell when I open a project.

(use-package envrc
  :config (envrc-global-mode))

You of course need direnv and if you want to use Guix shell. You need to make file similar to this. You need this in your .envrc in project root.

eval $(guix shell --search-paths)

And this at the end of your .bashrc.

eval "$(direnv hook bash)"

Creating a Guix manifest

For Emacs to automatically setup a Guix shell environment for your project you need to have a manifest.scm in the project root. To generate this you may use the following command.

guix shell --export-manifest package1 package2 package3 ... > manifest.scm

Highlighting Indent Guides

Its helpful to keep track indentation. Since I am trying to reduce the amount of indentation I do.

(use-package highlight-indentation
  :defer t
  :config
  (setq highlight-indentation-set-offset 4))

Breadcrumbs

Breadcrumbs are the little thingies at the top which show in which part of the document you are in and in which directory.

(use-package breadcrumb
  :config (breadcrumb-mode t))

Compilation mode

Enable colors

(add-hook 'compilation-filter-hook #'ansi-color-compilation-filter)

Rainbow delimiters

This color codes () so that you never miss them.

(use-package rainbow-delimiters
  :hook (prog-mode . rainbow-delimiters-mode))

Dev web server

(defun ECFPAW/start-python-web-server (port directory)
  "Start a Webserver using Python's http.server module.
PORT can be provided to specify the port to be used by the server,
DIRECTORY can be provided to specify a directory for the server's root."
  (interactive "Mport: \nMdirectory: ")
  (async-shell-command
   (format "python -m http.server -d %s" directory)))

Rainbow mode

Show the colors!

(use-package rainbow-mode :hook (prog-mode . rainbow-mode))

LANGUAGE MODES

Markdown mode

I still use markdown files for README and stuff, (sorry *ORG-MODE).

(use-package markdown-mode :defer t)

Python

Eglot
  • [ ] The required packages to emacs-pkgbuild.
(setq-default eglot-workspace-configuration
              '((:pylsp . (:configurationSources ["flake8"]
                           :plugins (
                                     :flake8 (:enabled :json-false
                                              :maxLineLength 88)
                                     :black (:enabled t
                                             :line_length 80
                                             :cache_config t))))))
Prettify mode symbols
(ECFPAW/add-pretty-sym-pack 'python-mode-hook '(ECFPAW/prettify-symbols-pack/in-equalities
                                                ECFPAW/prettify-symbols-pack/asterik-to-multiplication
                                                ECFPAW/prettify-symbols-pack/lambda
                                                ECFPAW/prettify-symbols-pack/pointers))
(ECFPAW/add-pretty-sym-pack 'python-ts-mode-hook '(ECFPAW/prettify-symbols-pack/in-equalities
                                                   ECFPAW/prettify-symbols-pack/asterik-to-multiplication
                                                   ECFPAW/prettify-symbols-pack/lambda
                                                   ECFPAW/prettify-symbols-pack/pointers))

C

Prettify mode symbols
(ECFPAW/add-pretty-sym-pack 'c-mode-hook
                            '(ECFPAW/prettify-symbols-pack/in-equalities
                              ECFPAW/prettify-symbols-pack/pointers))

C++

Prettify mode symbols
(ECFPAW/add-pretty-sym-pack 'c++-mode-hook
                            '(ECFPAW/prettify-symbols-pack/in-equalities
                              ECFPAW/prettify-symbols-pack/pointers
                              'ECFPAW/prettify-symbols-pack/redirections))

Go

(use-package go-mode :defer t)

Zig

(use-package zig-mode :defer t)
outline mode regexps
(add-hook
 'zig-mode-hook
 (lambda nil
   (setq-local

    outline-regexp
    (rx
     (and (* " ")
          (or "_"
	   "pub" "const"
           "var" "fn"
           "if" "else"
           "while" "for"
           "inline" "switch")))

    outline-heading-end-regexp
    (rx  (or ";" "}" "\n")))))
Prettify mode symbols
(ECFPAW/add-pretty-sym-pack 'zig-mode-hook '(ECFPAW/prettify-symbols-pack/in-equalities
                                             ECFPAW/prettify-symbols-pack/pointers))

Code Folding

(add-hook 'prog-mode-hook 'outline-minor-mode)

tree-sit

install language grammar

use this SRC block to install support for more languages (You can also just call it using M-x)

(treesit-install-language-grammar "python")

SUDO EDIT

sudo-edit gives us the ability to open files with sudo privileges or switch over to editing with sudo privileges if we initially opened the file without such privileges.

(use-package sudo-edit :defer t)

TRAMP

Tramp allows you to remote into other machines from within Emacs.

(custom-set-variables
 '(tramp-default-method "ssh")
 '(tramp-default-user "tusharhero"))

ESHELL

I use Eshell most of the I need a shell inside Emacs.

Prompt configuration

I made a small but tasteful change to my Eshell prompt.

(setq eshell-prompt-function
      (lambda ()
        (require 'magit)
        (concat
         (abbreviate-file-name (eshell/pwd))
         " "
         (let ((branch (magit-get-current-branch)))
           (if branch
               (concat
                (propertize (format "%s" branch)
                            'face 'magit-branch)
                " ")))
         (unless (eshell-exit-success-p)
           (format " [%d]" eshell-last-command-status))
         (if (= (file-user-uid) 0) "#" "") " ")))

Alias

The clear command doesn’t work like you would expect it to. It turns out I need to alias it to clear-scrollback!

alias clear clear-scrollback
alias ff 'find-file $1'

Emacs Everywhere

It allows you to use Emacs everywhere. Kdotools and Ydotool are needed for KDE.

(use-package emacs-everywhere)