From cdc3f11a81fc099bcaf0b02ca73786bf1e338bfe Mon Sep 17 00:00:00 2001 From: Aryadev Chavali Date: Tue, 16 Apr 2024 22:29:01 +0630 Subject: (Emacs/config) Languages section -> lang.org Almost 700 lines of content, might as well move it. --- Emacs/.config/emacs/lang.org | 749 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 749 insertions(+) create mode 100644 Emacs/.config/emacs/lang.org (limited to 'Emacs/.config/emacs/lang.org') diff --git a/Emacs/.config/emacs/lang.org b/Emacs/.config/emacs/lang.org new file mode 100644 index 0000000..ce4e6de --- /dev/null +++ b/Emacs/.config/emacs/lang.org @@ -0,0 +1,749 @@ +#+title: Programming language configuration +#+author: Aryadev Chavali +#+description: Description +#+date: 2024-04-16 +#+property: header-args:emacs-lisp :tangle lang.el :comments link :results none +#+options: toc:nil +#+startup: noindent + +* Makefile +Defines an auto-insert for Makefiles. Assumes C but it's very easy to +change it for C++. +#+begin_src emacs-lisp +(use-package emacs + :auto-insert + (("[mM]akefile\\'" . "Makefile skeleton") + "" + "CC=gcc +CFLAGS=-Wall -Wextra -Werror -Wswitch-enum -ggdb -fsanitize=address -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) $(SRC)/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) +" + _)) +#+end_src +* PDF +I use PDFs mostly for reading reports or papers. Though Emacs isn't +my preferred application for viewing PDFs (I highly recommend +[[https://pwmt.org/projects/zathura/][Zathura]]), similar to most +things with Emacs, having a PDF viewer builtin can be a very useful +asset. + +For example if I were editing an org document which I was eventually +compiling into a PDF, my workflow would be much smoother with a PDF +viewer within Emacs that I can open on another pane. +** 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. +#+begin_src emacs-lisp +(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))) +#+end_src +** 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. +#+begin_src emacs-lisp +(use-package pdfgrep + :after pdf-tools + :hook (pdf-view-mode-hook . pdfgrep-mode) + :general + (nmap + :keymaps 'pdf-view-mode-map + "M-g" #'pdfgrep)) +#+end_src +* 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. +#+begin_src emacs-lisp +(use-package sql + :defer t + :straight nil + :init + (setq sql-display-sqli-buffer-function nil)) +#+end_src +* WIP Ada +:PROPERTIES: +:header-args:emacs-lisp: :tangle no +:END: +Check out [[file:elisp/ada-mode.el][ada-mode]], my custom ~ada-mode~ +that replaces the default one. This mode just colourises stuff, and +uses eglot and a language server to do the hard work. + +#+begin_src emacs-lisp +(use-package ada-mode + :straight nil + :load-path "elisp/" + :defer t + :config + (with-eval-after-load "eglot" + (add-hook 'ada-mode-hook #'eglot))) +#+end_src +* 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 [[https://elpa.gnu.org/packages/nhexl-mode.html][page]] yourself. +#+begin_src emacs-lisp +(use-package nhexl-mode + :straight t + :mode "\\.bin") +#+end_src +* C/C++ +Setup for C and C++ modes via the cc-mode package. C and C++ are +great languages for general purpose programming. My preferred choice +when I want greater control over memory management. +** 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 +#+begin_src emacs-lisp +(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 . +))))) +#+end_src +** 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 [[file:~/Dotfiles/ClangFormat/.clang-format][config file]] in +my dotfiles). + +#+begin_src emacs-lisp +(use-package clang-format + :straight nil + :load-path "/usr/share/clang/" + :after cc-mode + :commands (+code/clang-format-region-or-buffer + clang-format-mode) + :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)))) +#+end_src +** 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~. +#+begin_src emacs-lisp +(use-package org + :after cc-mode + :init + (org-babel-do-load-languages + 'org-babel-load-languages + '((C . t)))) +#+end_src +* WIP D +:PROPERTIES: +:header-args:emacs-lisp: :tangle no +:END: +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~. + +#+begin_src emacs-lisp +(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))) +#+end_src +* Rust +#+begin_src emacs-lisp +(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")))) +#+end_src +* 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. +#+begin_src emacs-lisp +(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)) +#+end_src +* WIP CSharp +:PROPERTIES: +:header-args:emacs-lisp: :tangle no +:END: +Haven't used C# in a while, but Emacs is alright for it with +omnisharp. +#+begin_src emacs-lisp +(use-package csharp-mode + :defer t + :pretty + (csharp-mode-hook + ("null" . "∅") + ("string" . "𝕊") + ("List" . "ℓ") + ("WriteLine" . "φ") + ("Write" . "ω") + ("true" . "⊨") + ("false" . "⊭") + ("!" . "¬") + ("&&" . "∧") + ("||" . "∨") + ("for" . "∀") + ("return" . "⟼"))) +#+end_src +* 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. +#+begin_src emacs-lisp +(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))))) +#+end_src +* 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 +[[file:elisp/haskell-multiedit.el][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. +#+begin_src emacs-lisp +(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 'stack-ghci) + :general + (shell-leader + "h" #'+shell/toggle-haskell-repl) + :display + ("\\*haskell.**\\*" + (display-buffer-at-bottom) + (window-height . 0.25)) + :config + (load (concat user-emacs-directory "elisp/haskell-multiedit.el")) + (+oreo/create-toggle-function + +shell/toggle-haskell-repl + "*haskell*" + haskell-interactive-bring + nil)) +#+end_src +* 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. +#+begin_src emacs-lisp +(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))) +#+end_src +** Python shell +Setup for python shell, including a toggle option +#+begin_src emacs-lisp +(use-package python + :straight nil + :commands +python/toggle-repl + :general + (shell-leader + "p" #'+shell/python-toggle-repl) + :display + ("\\*Python\\*" + (display-buffer-at-bottom) + (window-height . 0.25)) + :config + (+oreo/create-toggle-function + +shell/python-toggle-repl + "*Python*" + run-python + nil)) +#+end_src +* YAML +YAML is a data language which is useful for config files. +#+begin_src emacs-lisp +(use-package yaml-mode + :straight t) +#+end_src +* HTML/CSS/JS +Firstly, web mode for consistent colouring of syntax. +#+begin_src emacs-lisp +(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))) +#+end_src +** Emmet +Emmet for super speed code writing. +#+begin_src emacs-lisp +(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)) +#+end_src +** HTML Auto insert +#+begin_src emacs-lisp +(use-package web-mode + :defer t + :auto-insert + (("\\.html\\'" . "HTML Skeleton") + "" + " + + + + + "(read-string "Enter title: ") | """ + + + + + + + + + + + +" + _ + " +")) +#+end_src +* Typescript +Kinda expressive, interesting. +#+begin_src emacs-lisp +(use-package typescript-mode + :defer t + :init + (setq typescript-indent-level 2)) +#+end_src +* 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. + +Enter /SLY/. Sly is a fork of /SLIME/ and is *mandatory* for lisp +development on Emacs. + +#+begin_src emacs-lisp +(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)) + (+oreo/create-toggle-function + +shell/toggle-sly + "*sly-mrepl for sbcl*" + sly-mrepl + nil) + :general + (shell-leader + "s" #'+shell/toggle-sly) + (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)) +#+end_src +** Lisp indent function +Add a new lisp indent function which indents newline lists more +appropriately. +#+begin_src emacs-lisp +(use-package lisp-mode + :straight nil + :pretty + (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) + :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)) +#+end_src +** Emacs lisp +#+begin_src emacs-lisp +(use-package elisp-mode + :straight nil + :general + (vmap + :keymaps '(emacs-lisp-mode-map lisp-interaction-mode-map) + "gr" #'eval-region)) +#+end_src -- cgit v1.2.3-13-gbd6f