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.
822 lines
23 KiB
Org Mode
822 lines
23 KiB
Org Mode
#+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 -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)
|
||
"
|
||
_))
|
||
#+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.
|
||
** WAIT PDF tools
|
||
:PROPERTIES:
|
||
:header-args:emacs-lisp: :tangle no
|
||
:END:
|
||
~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
|
||
** WAIT PDF grep
|
||
:PROPERTIES:
|
||
:header-args:emacs-lisp: :tangle no
|
||
:END:
|
||
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
|
||
* WAIT SQL
|
||
:PROPERTIES:
|
||
:header-args:emacs-lisp: :tangle no
|
||
:END:
|
||
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
|
||
* WAIT 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" "\\.out"))
|
||
#+end_src
|
||
* 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
|
||
#+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)
|
||
;;; 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))))
|
||
#+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
|
||
* WAIT 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
|
||
* WAIT Rust
|
||
:PROPERTIES:
|
||
:header-args:emacs-lisp: :tangle no
|
||
:END:
|
||
#+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
|
||
* WAIT Racket
|
||
:PROPERTIES:
|
||
:header-args:emacs-lisp: :tangle no
|
||
:END:
|
||
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
|
||
* WAIT 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
|
||
* WAIT Java
|
||
:PROPERTIES:
|
||
:header-args:emacs-lisp: :tangle no
|
||
:END:
|
||
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 '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")))
|
||
#+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" #'run-python)
|
||
:display
|
||
("\\*Python\\*"
|
||
(display-buffer-at-bottom)
|
||
(window-height . 0.25)))
|
||
#+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")
|
||
""
|
||
"<!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>"))
|
||
#+end_src
|
||
** WAIT Typescript
|
||
:PROPERTIES:
|
||
:header-args:emacs-lisp: :tangle no
|
||
:END:
|
||
A child language of javascript which compiles to it.
|
||
#+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.
|
||
|
||
** WAIT Sly
|
||
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))
|
||
: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))
|
||
#+end_src
|
||
** Emacs lisp
|
||
#+begin_src 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))
|
||
#+end_src
|
||
** WIP Hydra like Lispy
|
||
:PROPERTIES:
|
||
:header-args:emacs-lisp: :tangle no
|
||
:END:
|
||
A [[file:core.org::*Hydra][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.
|
||
#+begin_src emacs-lisp
|
||
(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))
|
||
#+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
|
||
: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
|