Files
dotfiles/Emacs/.config/emacs/lang.org
Aryadev Chavali d998ae45cf (Emacs/*)~disable a lot of packages
Don't use them most of the time so what's the need?

If I'm ever in the situation where I need to use these I hope I have
internet connection.
2024-05-08 01:30:04 +05:30

23 KiB
Raw Blame History

Programming language configuration

Makefile

Defines an auto-insert for Makefiles. Assumes C but it's very easy to change it for C++.

(use-package emacs
  :auto-insert
  (("[mM]akefile\\'" . "Makefile skeleton")
   ""
   "CC=gcc
CFLAGS=-Wall -Wextra -Werror -Wswitch-enum -ggdb -fsanitize=address -fsanitize=undefined -std=c11
LIBS=

ARGS=
OUT=main.out

SRC=src
DIST=build
CODE=$(addprefix $(SRC)/, ) # add source files here
OBJECTS=$(CODE:$(SRC)/%.c=$(DIST)/%.o)
DEPDIR:=$(DIST)/dependencies
DEPFLAGS=-MT $@ -MMD -MP -MF
DEPS:=$(CODE:$(SRC)/%.c=$(DEPDIR):%.d) $(DEPDIR)/main.d

.PHONY: all
all: $(OUT)

$(OUT): $(DIST)/$(OUT)

$(DIST)/$(OUT): $(OBJECTS) $(DIST)/main.o | $(DIST)
	$(CC) $(CFLAGS) $^ -o $@ $(LIBS)

$(DIST)/%.o: $(SRC)/%.c | $(DIST) $(DEPDIR)
	$(CC) $(CFLAGS) $(DEPFLAGS) $(DEPDIR)/$*.d -c $< -o $@ $(LIBS)

.PHONY: run
run: $(DIST)/$(OUT)
	./$^ $(ARGS)

.PHONY:
clean:
	rm -rfv $(DIST)/*

$(DIST):
	mkdir -p $(DIST)

$(DEPDIR):
	mkdir -p $(DEPDIR)

-include $(DEPS)
"
   _))

PDF

I use PDFs mostly for reading reports or papers. Though Emacs isn't my preferred application for viewing PDFs (I highly recommend 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 viewer within Emacs that I can open on another pane.

WAIT PDF tools

pdf-tools provides the necessary functionality for viewing PDFs. There is no proper PDF viewing without this package. evil-collection provides a setup for this mode, so use that.

(use-package pdf-tools
  :mode ("\\.[pP][dD][fF]\\'" . pdf-view-mode)
  :straight t
  :display
  ("^.*pdf$"
   (display-buffer-same-window)
   (inhibit-duplicate-buffer . t))
  :config
  (pdf-tools-install-noverify)
  (with-eval-after-load "evil-collection"
    (evil-collection-pdf-setup)))

WAIT PDF grep

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.

(use-package pdfgrep
  :after pdf-tools
  :hook (pdf-view-mode-hook . pdfgrep-mode)
  :general
  (nmap
    :keymaps 'pdf-view-mode-map
    "M-g"    #'pdfgrep))

WAIT SQL

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.

(use-package sql
  :defer t
  :straight nil
  :init
  (setq sql-display-sqli-buffer-function nil))

WAIT Ada

Check out 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.

(use-package ada-mode
  :straight nil
  :load-path "elisp/"
  :defer t
  :config
  (with-eval-after-load "eglot"
    (add-hook 'ada-mode-hook #'eglot)))

NHexl

Hexl-mode is the inbuilt package within Emacs to edit hex and binary format buffers. There are a few problems with hexl-mode though, including an annoying prompt on revert-buffer.

Thus, nhexl-mode! It comes with a few other improvements. Check out the page yourself.

(use-package nhexl-mode
  :straight t
  :mode ("\\.bin" "\\.out"))

C/C++

Setup for C and C++ modes, using Emacs' default package: cc-mode.

cc-mode

Tons of stuff, namely:

  • auto-fill-mode for 80 char limit
  • Some keybindings to make evil statement movement is easy
  • Lots of pretty symbols
  • Indenting options and a nice (for me) code style for C (though aggressive indent screws with this a bit)
  • Auto inserts to get a C file going
(use-package cc-mode
  :defer t
  :hook
  (c-mode-hook   . auto-fill-mode)
  (c++-mode-hook . auto-fill-mode)
  :general
  (:keymaps '(c-mode-map c++-mode-map)
   :states '(normal motion visual)
   "(" #'c-beginning-of-statement
   ")" #'c-end-of-statement)
  :pretty
  (c-mode-hook
   ("puts"    . "φ")
   ("fputs"   . "ϕ")
   ("printf"  . "ω")
   ("fprintf" . "Ω")
   ("NULL"    . "Ø")
   ("true"    . "⊨")
   ("false"   . "⊭")
   ("!"       . "¬")
   ("&&"      . "∧")
   ("||"      . "")
   ("for"     . "∀")
   ("return"  . "⟼"))
  (c++-mode-hook
   ("nullptr" . "Ø")
   ("string"  . "𝕊")
   ("vector"  . "")
   ("puts"    . "φ")
   ("fputs"   . "ϕ")
   ("printf"  . "ω")
   ("fprintf" . "Ω")
   ("NULL"    . "Ø")
   ("true"    . "⊨")
   ("false"   . "⊭")
   ("!"       . "¬")
   ("&&"      . "∧")
   ("||"      . "")
   ("for"     . "∀")
   ("return"  . "⟼"))
  :init
  (setq-default c-basic-offset 2)
  (setq-default c-auto-newline nil)
  (setq-default c-default-style '((other . "user")))
  (defun +cc/copyright-notice ()
    (let* ((lines (split-string (+license/copyright-notice) "\n"))
           (copyright-line (car lines))
           (rest (cdr lines)))
      (concat
       "* "
       copyright-line
       "\n"
       (mapconcat
        #'(lambda (x)
            (if (string= x "")
                ""
              (concat " * " x)))
        rest
        "\n"))))

  :auto-insert
  (("\\.c\\'" . "C skeleton")
   ""
   "/" (+cc/copyright-notice) "\n\n"
   " * Created: " (format-time-string "%Y-%m-%d") "\n"
   " * Author: " user-full-name "\n"
   " * Description: " _ "\n"
   " */\n"
   "\n")
  (("\\.cpp\\'" "C++ skeleton")
   ""
   "/" (+cc/copyright-notice) "\n\n"
   " * Created: " (format-time-string "%Y-%m-%d") "\n"
   " * Author: " user-full-name "\n"
   " * Description: " _ "\n"
   " */\n"
   "\n")
  (("\\.\\([Hh]\\|hh\\|hpp\\|hxx\\|h\\+\\+\\)\\'" . "C / C++ header")
   (replace-regexp-in-string "[^A-Z0-9]" "_"
                             (string-replace "+" "P"
                                             (upcase
                                              (file-name-nondirectory buffer-file-name))))
   "/" (+cc/copyright-notice) "\n\n"
   " * Created: " (format-time-string "%Y-%m-%d") "\n"
   " * Author: " user-full-name "\n"
   " * Description: " _ "\n"
   " */\n\n"
   "#ifndef " str n "#define " str "\n\n" "\n\n#endif")
  :config
  (c-add-style
   "user"
   '((c-basic-offset . 2)
     (c-comment-only-line-offset . 0)
     (c-hanging-braces-alist (brace-list-open)
                             (brace-entry-open)
                             (substatement-open after)
                             (block-close . c-snug-do-while)
                             (arglist-cont-nonempty))
     (c-cleanup-list brace-else-brace)
     (c-offsets-alist
      (statement-block-intro . +)
      (substatement-open . 0)
      (access-label . -)
      (inline-open  . 0)
      (label . 0)
      (statement-cont . +)))))

Clang format

Clang format comes inbuilt with clang, so download that before using this. Formats C/C++ files depending on a format (checkout the Clang format config file in my dotfiles).

(use-package clang-format
  :straight nil
  :load-path "/usr/share/clang/"
  :after cc-mode
  :commands (+code/clang-format-region-or-buffer
             clang-format-mode)
  ;;; 2024-04-24: disabled as it's annoying on projects where a
  ;;; .clang-format isn't defined.  Furthermore, does it make sense
  ;;; for *every* file you open and edit to have a format function run
  ;;; right after?  seems a bit slow.
  ;; :hook
  ;; (c-mode-hook . clang-format-mode)
  ;; (c++-mode-hook . clang-format-mode)
  :general
  (code-leader
    :keymaps '(c-mode-map c++-mode-map)
    "f" #'+code/clang-format-region-or-buffer)
  :config
  (define-minor-mode clang-format-mode
    "On save formats the current buffer via clang-format."
    :lighter nil
    (let ((save-func (proc (interactive)
                           (clang-format-buffer))))
      (if clang-format-mode
          (add-hook 'after-save-hook save-func nil t)
        (remove-hook 'after-save-hook save-func t))))
  (defun +code/clang-format-region-or-buffer ()
    (interactive)
    (if (mark)
        (clang-format-region (region-beginning) (region-end))
      (clang-format-buffer))))

cc org babel

To ensure org-babel executes language blocks of C/C++, I need to load it as an option in org-babel-load-languages.

(use-package org
  :after cc-mode
  :init
  (org-babel-do-load-languages
   'org-babel-load-languages
   '((C . t))))

WAIT D

D is a systems level programming language with C-style syntax. I think it has some interesting ideas such as a toggleable garbage collector. Here I just install the D-mode package, enable org-babel execution of d-mode blocks and alias D-mode with d-mode.

(use-package d-mode
  :defer t
  :straight t
  :config
  (fset 'D-mode 'd-mode)
  (with-eval-after-load "org-mode"
    (setf (alist-get 'd org-babel-load-languages) t)))

WAIT Rust

(use-package rust-mode
  :straight t
  :general
  (code-leader
    :keymaps 'rust-mode-map
    "f" #'rust-format-buffer)
  (local-leader
    :keymaps 'rust-mode-map
    "c" #'rust-run-clippy)
  :init
  (setq rust-format-on-save t)
  (with-eval-after-load "eglot"
    (add-to-list 'eglot-server-programs '(rust-mode "rust-analyzer"))))

WAIT Racket

A scheme with lots of stuff inside it. Using it for a language design book so it's useful to have some Emacs binds for it.

(use-package racket-mode
  :straight t
  :hook (racket-mode-hook . racket-xp-mode)
  :display
  ("\\*Racket.*"
   (display-buffer-at-bottom)
   (window-height . 0.25))
  :init
  (setq racket-documentation-search-location 'local)
  :general
  (nmap
    :keymaps 'racket-describe-mode-map
    "q" #'quit-window)
  (nmap
    :keymaps 'racket-mode-map
    "gr" #'racket-eval-last-sexp)
  (local-leader
    :keymaps '(racket-mode-map racket-repl-mode-map)
    "d" #'racket-repl-describe)
  (local-leader
    :keymaps 'racket-mode-map
    "r" #'racket-run
    "i" #'racket-repl
    "e" #'racket-send-definition
    "sr" #'racket-send-region
    "sd" #'racket-send-definition))

WAIT CSharp

Haven't used C# in a while, but Emacs is alright for it with omnisharp.

(use-package csharp-mode
  :defer t
  :pretty
  (csharp-mode-hook
   ("null"      . "∅")
   ("string"    . "𝕊")
   ("List"      . "")
   ("WriteLine" . "φ")
   ("Write"     . "ω")
   ("true"      . "⊨")
   ("false"     . "⊭")
   ("!"         . "¬")
   ("&&"        . "∧")
   ("||"        . "")
   ("for"       . "∀")
   ("return"    . "⟼")))

WAIT Java

I kinda dislike Java, but if necessary I will code in it. Just setup a style and some pretty symbols. You can use LSP to get cooler features to be fair.

(use-package ob-java
  :straight nil
  :defer t
  :pretty
  (java-mode-hook
   ("println" . "φ")
   ("printf"  . "ω")
   ("null"    . "Ø")
   ("true"    . "⊨")
   ("false"   . "⊭")
   ("!"       . "¬")
   ("&&"      . "∧")
   ("||"      . "")
   ("for"     . "∀")
   ("return"  . "⟼"))
  :config
  (with-eval-after-load "cc-mode"
    (c-add-style
     "java"
     '((c-basic-offset . 4)
       (c-comment-only-line-offset 0 . 0)
       (c-offsets-alist
        (inline-open . 0)
        (topmost-intro-cont . +)
        (statement-block-intro . +)
        (knr-argdecl-intro . 5)
        (substatement-open . 0)
        (substatement-label . +)
        (label . +)
        (statement-case-open . +)
        (statement-cont . +)
        (arglist-intro . c-lineup-arglist-intro-after-paren)
        (arglist-close . c-lineup-arglist)
        (brace-list-intro first c-lineup-2nd-brace-entry-in-arglist c-lineup-class-decl-init-+ +)
        (access-label . 0)
        (inher-cont . c-lineup-java-inher)
        (func-decl-cont . c-lineup-java-throws))))
    (add-to-list 'c-default-style '(java-mode . "java")))

  (with-eval-after-load "abbrev"
    (define-abbrev-table 'java-mode-abbrev-table nil)
    (add-hook 'java-mode-hook
              (proc (setq-local local-abbrev-table java-mode-abbrev-table)))))

Haskell

Haskell is a static lazy functional programming language (what a mouthful). It's quite a beautiful language and really learning it will change the way you think about programming. However, my preferred functional language is still unfortunately Lisp so no extra brownie points there.

Here I configure the REPL for Haskell via the haskell-interactive-mode. I also load my custom package haskell-multiedit which allows a user to create temporary haskell-mode buffers that, upon completion, will run in the REPL. Even easier than making your own buffer.

(use-package haskell-mode
  :hook
  (haskell-mode-hook . haskell-indentation-mode)
  (haskell-mode-hook . interactive-haskell-mode)
  :custom
  (haskell-interactive-prompt "[λ] ")
  (haskell-interactive-prompt-cont "{λ} ")
  (haskell-interactive-popup-errors nil)
  (haskell-stylish-on-save nil)
  (haskell-process-type 'auto)
  :general
  (shell-leader
    "h" #'haskell-interactive-bring)
  (local-leader
    :keymaps 'haskell-mode-map
    "l" #'haskell-process-load-or-reload
    "t" #'haskell-process-do-type)
  (local-leader
    :keymaps 'haskell-interactive-mode-map
    "c" #'haskell-interactive-mode-clear)
  (imap
    :keymaps 'haskell-interactive-mode-map
    "M-k" #'haskell-interactive-mode-history-previous
    "M-j" #'haskell-interactive-mode-history-next)
  :display
  ("\\*haskell.**\\*"
   (display-buffer-at-bottom)
   (window-height . 0.25))
  :config
  (load (concat user-emacs-directory "elisp/haskell-multiedit.el")))

Python

Works well for python. If you have pyls it should be on your path, so just run eglot if you need. But an LSP server is not necessary for a lot of my time in python. Here I also setup org-babel for python source code blocks.

(use-package python
  :defer t
  :straight nil
  :pretty
  (python-mode-hook
   ("None"   . "Ø")
   ("list"   . "")
   ("List"   . "")
   ("str"    . "𝕊")
   ("True"   . "⊨")
   ("False"  . "⊭")
   ("!"      . "¬")
   ("&&"     . "∧")
   ("||"     . "")
   ("for"    . "∀")
   ("print"  . "φ")
   ("lambda" . "λ")
   ("return" . "⟼")
   ("yield"  . "⟻"))
  :init
  (setq python-indent-offset 4)
  :config
  (with-eval-after-load "org-mode"
    (setf (alist-get 'python org-babel-load-languages) t)))

Python shell

Setup for python shell, including a toggle option

(use-package python
  :straight nil
  :commands +python/toggle-repl
  :general
  (shell-leader
    "p" #'run-python)
  :display
  ("\\*Python\\*"
   (display-buffer-at-bottom)
   (window-height . 0.25)))

YAML

YAML is a data language which is useful for config files.

(use-package yaml-mode
  :straight t)

HTML/CSS/JS

Firstly, web mode for consistent colouring of syntax.

(use-package web-mode
  :mode ("\\.html" . web-mode)
  :mode ("\\.js"   . web-mode)
  :mode ("\\.css"  . web-mode)
  :custom
  ((web-mode-code-indent-offset 2)
   (web-mode-markup-indent-offset 2)
   (web-mode-css-indent-offset 2)))

Emmet

Emmet for super speed code writing.

(use-package emmet-mode
  :hook (web-mode-hook . emmet-mode)
  :general
  (imap
    :keymaps 'emmet-mode-keymap
    "TAB" #'emmet-expand-line
    "M-j" #'emmet-next-edit-point
    "M-k" #'emmet-prev-edit-point))

HTML Auto insert

(use-package web-mode
  :defer t
  :auto-insert
  (("\\.html\\'" . "HTML Skeleton")
   ""
   "<!doctype html>
<html lang=''>
  <head>
    <meta charset='utf-8'>
    <meta http-equiv='x-ua-compatible' content='ie=edge'>
    <title>"(read-string "Enter title: ") | """</title>
    <meta name='description' content='" (read-string "Enter description: ") | "" "'>
    <meta name='author' content='"user-full-name"'/>
    <meta name='viewport' content='width=device-width, initial-scale=1'>

    <link rel='apple-touch-icon' href='/apple-touch-icon.png'>
    <link rel='shortcut icon' href='/favicon.ico'/>
    <!-- Place favicon.ico in the root directory -->

  </head>
  <body>
    <!--[if lt IE 8]>
      <p class='browserupgrade'>
      You are using an <strong>outdated</strong> browser. Please
      <a href='http://browsehappy.com/'>upgrade your browser</a> to improve
      your experience.
      </p>
    <![endif]-->
"
   _
   "     </body>
</html>"))

WAIT Typescript

A child language of javascript which compiles to it.

(use-package typescript-mode
  :defer t
  :init
  (setq typescript-indent-level 2))

Common Lisp

Common Lisp is a dialect of Lisp, the most common one around. Emacs comes with builtin Lisp support of course, but a REPL would be nice.

WAIT Sly

Enter SLY. Sly is a fork of SLIME and is mandatory for lisp development on Emacs.

(use-package sly
  :straight t
  :init
  (setq inferior-lisp-program "sbcl")
  :display
  ("\\*sly-db"
   (display-buffer-at-bottom)
   (window-height . 0.5))
  ("\\*sly-"
   (display-buffer-at-bottom)
   (window-height . 0.25))
  :config
  (evil-set-initial-state 'sly-db-mode 'emacs)
  (with-eval-after-load "org"
    (setq-default org-babel-lisp-eval-fn #'sly-eval))
  (with-eval-after-load "company"
    (add-hook 'sly-mrepl-hook #'company-mode))
  :general
  (shell-leader
    "s" #'sly-mrepl)
  (nmap
    :keymaps '(lisp-mode-map sly-mrepl-mode-map)
    "gr" #'sly-eval-buffer
    "gd" #'sly-edit-definition
    "gR" #'sly-who-calls)
  (local-leader
    :keymaps '(lisp-mode-map sly-mrepl-mode-map)
    "s" #'+shell/toggle-sly
    "c" #'sly-compile-file
    "a" #'sly-apropos
    "d" #'sly-describe-symbol
    "D" #'sly-documentation-lookup
    "S" #'sly-mrepl-sync
    "E" #'sly-eval-defun)
  (local-leader
    :keymaps 'lisp-mode-map
    :infix "e"
    "b" #'sly-eval-buffer
    "e" #'sly-eval-last-expression
    "f" #'sly-eval-defun
    "r" #'sly-eval-region)
  (nmap
    :keymaps 'sly-inspector-mode-map
    "q" #'sly-inspector-quit))

Emacs lisp

(use-package elisp-mode
  :straight nil
  :pretty
  (lisp-mode-hook
   ("lambda" . "λ")
   ("t"      . "⊨")
   ("nil"    . "Ø")
   ("and"    . "∧")
   ("or"     . "")
   ("defun"  . "ƒ")
   ("for"    . "∀")
   ("mapc"   . "∀")
   ("mapcar" . "∀"))
  (emacs-lisp-mode-hook
   ("lambda" . "λ")
   ("t"      . "⊨")
   ("nil"    . "Ø")
   ("and"    . "∧")
   ("or"     . "")
   ("defun"  . "ƒ")
   ("for"    . "∀")
   ("mapc"   . "∀")
   ("mapcar" . "∀"))
  :general
  (:states '(normal motion visual)
   :keymaps '(emacs-lisp-mode-map lisp-mode-map)
   ")" #'sp-next-sexp
   "(" #'sp-previous-sexp)
  (nmmap
    :keymaps '(emacs-lisp-mode-map lisp-interaction-mode-map)
    "gr" #'eval-last-sexp)
  (vmap
    :keymaps '(emacs-lisp-mode-map lisp-interaction-mode-map)
    "gr" #'eval-region))

WIP Hydra like Lispy

A Hydra which uses the Lispy package (by abo-abo) to create a set of motions that allow movement around a lisp file easily.

2024-04-18: Still working on this, quite rough around the edges.

(use-package lispy
  :after (lisp-mode elisp-mode)
  :hydra
  (hydra-lispy
   nil "Move around quickly in Lisp"
   ("h" #'lispy-left)
   ("j" ("t" #'lispy-teleport)
    #'lispy-down)
   ("k" #'lispy-up)
   ("l" #'lispy-right)
   ("d" #'lispy-different)
   ("u" #'lispy-flow)
   ("o" #'lispy-oneline)
   ("m" #'lispy-multiline)
   ("N" #'lispy-narrow)
   ("W" #'lispy-widen)
   ("c" #'lispy-clone)
   ("fp" #'lispy-ace-paren)
   ("fs" #'lispy-ace-symbol :exit t)
   ("H" #'lispy-slurp)
   ("L" #'lispy-barf)
   ("M-h" #'lispy-move-left)
   ("M-j" #'lispy-move-down)
   ("M-k" #'lispy-move-up)
   ("M-l" #'lispy-move-right)
   ("C-g" nil))
  :general
  (nmmap
    :keymaps '(emacs-lisp-mode-map lisp-mode-map)
    "." #'hydra-lispy/body))

Lisp indent function

Add a new lisp indent function which indents newline lists more appropriately.

(use-package lisp-mode
  :straight nil
  :config
  (defun +oreo/lisp-indent-function (indent-point state)
    (let ((normal-indent (current-column))
          (orig-point (point)))
      (goto-char (1+ (elt state 1)))
      (parse-partial-sexp (point) calculate-lisp-indent-last-sexp 0 t)
      (cond
       ;; car of form doesn't seem to be a symbol, or is a keyword
       ((and (elt state 2)
             (or (not (looking-at "\\sw\\|\\s_"))
                 (looking-at ":")))
        (if (not (> (save-excursion (forward-line 1) (point))
                    calculate-lisp-indent-last-sexp))
            (progn (goto-char calculate-lisp-indent-last-sexp)
                   (beginning-of-line)
                   (parse-partial-sexp (point)
                                       calculate-lisp-indent-last-sexp 0 t)))
        ;; Indent under the list or under the first sexp on the same
        ;; line as calculate-lisp-indent-last-sexp.  Note that first
        ;; thing on that line has to be complete sexp since we are
        ;; inside the innermost containing sexp.
        (backward-prefix-chars)
        (current-column))
       ((and (save-excursion
               (goto-char indent-point)
               (skip-syntax-forward " ")
               (not (looking-at ":")))
             (save-excursion
               (goto-char orig-point)
               (looking-at ":")))
        (save-excursion
          (goto-char (+ 2 (elt state 1)))
          (current-column)))
       (t
        (let ((function (buffer-substring (point)
                                          (progn (forward-sexp 1) (point))))
              method)
          (setq method (or (function-get (intern-soft function)
                                         'lisp-indent-function)
                           (get (intern-soft function) 'lisp-indent-hook)))
          (cond ((or (eq method 'defun)
                     (and (null method)
                          (> (length function) 3)
                          (string-match "\\`def" function)))
                 (lisp-indent-defform state indent-point))
                ((integerp method)
                 (lisp-indent-specform method state
                                       indent-point normal-indent))
                (method
                 (funcall method indent-point state))))))))
  (setq-default lisp-indent-function #'+oreo/lisp-indent-function))