163 lines
5.7 KiB
Org Mode
163 lines
5.7 KiB
Org Mode
|
#+TITLE: Clojure Programming
|
|||
|
#+AUTHOR: Howard X. Abrams
|
|||
|
#+DATE: 2022-04-05
|
|||
|
#+FILETAGS: :emacs:
|
|||
|
|
|||
|
A literate programming file for programming in Clojure.
|
|||
|
|
|||
|
#+begin_src emacs-lisp :exports none
|
|||
|
;;; ha-programming-clojure --- programming in Clojure. -*- lexical-binding: t; -*-
|
|||
|
;;
|
|||
|
;; © 2022 Howard X. Abrams
|
|||
|
;; Licensed under a Creative Commons Attribution 4.0 International License.
|
|||
|
;; See http://creativecommons.org/licenses/by/4.0/
|
|||
|
;;
|
|||
|
;; Author: Howard X. Abrams <http://gitlab.com/howardabrams>
|
|||
|
;; Maintainer: Howard X. Abrams
|
|||
|
;; Created: April 5, 2022
|
|||
|
;;
|
|||
|
;; This file is not part of GNU Emacs.
|
|||
|
;;
|
|||
|
;; *NB:* Do not edit this file. Instead, edit the original literate file at:
|
|||
|
;; ~/other/hamacs/ha-programming-clojure.org
|
|||
|
;; And tangle the file to recreate this one.
|
|||
|
;;
|
|||
|
;;; Code:
|
|||
|
#+end_src
|
|||
|
I like [[http://clojure.org][Clojure]] as a /modern Lisp/, but I don’t get to play with it much.
|
|||
|
The following instructions create a fully blinged-out Emacs-Clojure setup.
|
|||
|
* Introduction
|
|||
|
To get Clojure working on a new system, try the following on a Mac:
|
|||
|
#+begin_src sh
|
|||
|
brew install clojure/tools/clojure
|
|||
|
#+end_src
|
|||
|
|
|||
|
And make sure it works:
|
|||
|
#+begin_src sh
|
|||
|
clojure --help
|
|||
|
#+end_src
|
|||
|
|
|||
|
Or by starting a REPL:
|
|||
|
#+begin_src sh
|
|||
|
clj
|
|||
|
#+end_src
|
|||
|
|
|||
|
Also, download this script:
|
|||
|
#+begin_src sh
|
|||
|
curl -o ~/bin/lein https://raw.githubusercontent.com/technomancy/leiningen/stable/bin/lein
|
|||
|
chmod u+x ~/bin/lein
|
|||
|
#+end_src
|
|||
|
|
|||
|
Then for each project, create the project directory with this command:
|
|||
|
#+begin_src sh
|
|||
|
lein new app fresh-app
|
|||
|
#+end_src
|
|||
|
* Emacs Support
|
|||
|
We begin with using [[https://github.com/clojure-emacs/clojure-mode/][clojure-mode]]:
|
|||
|
#+begin_src emacs-lisp
|
|||
|
(use-package clojure-mode
|
|||
|
:init
|
|||
|
(add-to-list 'org-babel-load-languages '(clojure . t))
|
|||
|
|
|||
|
:config
|
|||
|
(defun ha-prettify-clojure ()
|
|||
|
"Make the Clojure syntax prettier."
|
|||
|
(push '("fn" . ?𝝀) prettify-symbols-alist)
|
|||
|
(push '("__" . ?⁈) prettify-symbols-alist)
|
|||
|
(prettify-symbols-mode))
|
|||
|
|
|||
|
:hook (clojure-mode . ha-prettify-clojure))
|
|||
|
#+end_src
|
|||
|
|
|||
|
Need the IDE feature of [[https://github.com/clojure-emacs/cider][Cider]]:
|
|||
|
#+begin_src emacs-lisp
|
|||
|
(use-package cider
|
|||
|
:commands (cider cider-connect cider-jack-in)
|
|||
|
:init
|
|||
|
(setq cider-auto-select-error-buffer nil
|
|||
|
cider-repl-pop-to-buffer-on-connect nil
|
|||
|
cider-repl-use-clojure-font-lock t
|
|||
|
cider-repl-wrap-history t
|
|||
|
cider-repl-history-size 1000
|
|||
|
cider-show-error-buffer t
|
|||
|
nrepl-hide-special-buffers t
|
|||
|
;; Stop error buffer from popping up while working in buffers other than the REPL:
|
|||
|
nrepl-popup-stacktraces nil))
|
|||
|
#+end_src
|
|||
|
Read the entire [[https://docs.cider.mx/][CIDER manual]].
|
|||
|
** Linting
|
|||
|
Using [[https://github.com/jonase/eastwood#emacs--cider][Eastwood]] with the [[https://github.com/clojure-emacs/squiggly-clojure][Squiggly Clojure]] project to add lint warnings to [[file:emacs.org::*Flycheck][Flycheck]]:
|
|||
|
#+begin_src elisp
|
|||
|
(use-package flycheck-clojure
|
|||
|
:after flycheck
|
|||
|
:config
|
|||
|
(flycheck-clojure-setup))
|
|||
|
#+end_src
|
|||
|
** Snippets
|
|||
|
|
|||
|
For clojure-specific templates for [[https://github.com/capitaomorte/yasnippet][yasnippets]], clone David Nolen's [[http://github.com/swannodette/clojure-snippets][clojure-snippets]] repository into my =snippets= directory:
|
|||
|
#+begin_src sh :tangle no
|
|||
|
git clone http://github.com/swannodette/clojure-snippets ~/.emacs/snippets/clojure-mode
|
|||
|
#+end_src
|
|||
|
|
|||
|
Or install it as a package:
|
|||
|
#+begin_src elisp
|
|||
|
(use-package clojure-snippets)
|
|||
|
#+end_src
|
|||
|
** Refactoring
|
|||
|
The [[https://github.com/clojure-emacs/clj-refactor.el][clj-refactor]] project:
|
|||
|
#+begin_src elisp
|
|||
|
(use-package clj-refactor
|
|||
|
:hook
|
|||
|
(clojure-mode . clj-refactor-mode)
|
|||
|
:config
|
|||
|
;; Configure the Clojure Refactoring prefix:
|
|||
|
(cljr-add-keybindings-with-prefix "C-c .")
|
|||
|
:diminish clj-refactor-mode)
|
|||
|
#+end_src
|
|||
|
|
|||
|
The advanced refactorings require the [[https://github.com/clojure-emacs/refactor-nrepl][refactor-nrepl middleware]], which should explain why we added the =refactor-nrepl= to the =:plugins= section in the =~/.lein/profiles.clj= file (see below).
|
|||
|
|
|||
|
The /real problem/ is trying to remember all the [[https://github.com/clojure-emacs/clj-refactor.el/wiki][refactoring options]]. Remember: =C-c . h h=
|
|||
|
** Org Babel
|
|||
|
And of course, we want to put this with org blocks:
|
|||
|
#+begin_src emacs-lisp
|
|||
|
(use-package ob-clojure
|
|||
|
:straight (:type built-in)
|
|||
|
:custom
|
|||
|
(org-babel-clojure-backend 'cider)
|
|||
|
:config
|
|||
|
(add-to-list 'org-babel-load-languages '(clojure . t)))
|
|||
|
#+end_src
|
|||
|
|
|||
|
Does this now work?
|
|||
|
#+begin_src clojure :results raw replace
|
|||
|
(format "The answer is %d" (+ (* 4 10) 2))
|
|||
|
#+end_src
|
|||
|
|
|||
|
#+RESULTS:
|
|||
|
"The answer is 42"
|
|||
|
* LSP, a WIP
|
|||
|
Check out the goodies in [[https://emacs-lsp.github.io/lsp-mode/tutorials/clojure-guide/][this essay]] for hooking Clojure to LSP. Haven’t done this yet.
|
|||
|
#+begin_src emacs-lisp :tangle no
|
|||
|
(add-hook 'clojure-mode-hook 'lsp)
|
|||
|
(add-hook 'clojurescript-mode-hook 'lsp)
|
|||
|
(add-hook 'clojurec-mode-hook 'lsp)
|
|||
|
#+end_src
|
|||
|
* Technical Artifacts :noexport:
|
|||
|
Let's =provide= a name so we can =require= this file:
|
|||
|
#+begin_src emacs-lisp :exports none
|
|||
|
(provide 'ha-programming-clojure)
|
|||
|
;;; ha-programming-clojure.el ends here
|
|||
|
#+end_src
|
|||
|
|
|||
|
#+DESCRIPTION: programming in Clojure.
|
|||
|
|
|||
|
#+PROPERTY: header-args:sh :tangle no
|
|||
|
#+PROPERTY: header-args:emacs-lisp :tangle yes
|
|||
|
#+PROPERTY: header-args :results none :eval no-export :comments no mkdirp yes
|
|||
|
|
|||
|
#+OPTIONS: num:nil toc:nil todo:nil tasks:nil tags:nil date:nil
|
|||
|
#+OPTIONS: skip:nil author:nil email:nil creator:nil timestamp:nil
|
|||
|
#+INFOJS_OPT: view:nil toc:nil ltoc:t mouse:underline buttons:0 path:http://orgmode.org/org-info.js
|