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.
23 KiB
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)
"
_))
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-modefor 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))