Add the basics of programming languages to the configuration
This commit copies over the very basic requirements of using programming languages in Emacs from Prot's configuration.
This commit is contained in:
parent
d6ce41dccd
commit
270d2d3afe
3 changed files with 327 additions and 9 deletions
2
init.el
2
init.el
|
@ -53,4 +53,4 @@
|
|||
;; (require 'unravel-window)
|
||||
;; (require 'unravel-git)
|
||||
;; (require 'unravel-org)
|
||||
;; (require 'unravel-langs)
|
||||
(require 'unravel-langs)
|
||||
|
|
|
@ -15,20 +15,19 @@ This configuration is inspired from the work of [[https://github.com/protesilaos
|
|||
Here is what the generated directory structure should look like:
|
||||
|
||||
#+begin_src sh :dir ~/src/prototypes/emacs-up :results raw
|
||||
tree -aF
|
||||
tree -F
|
||||
#+end_src
|
||||
|
||||
#+RESULTS:
|
||||
./
|
||||
├── early-init.el
|
||||
├── init.el
|
||||
└── unravel-emacs.org
|
||||
├── unravel-emacs.org
|
||||
└── unravel-modules/
|
||||
├── unravel-langs.el
|
||||
└── unravel-theme.el
|
||||
|
||||
1 directory, 3 files
|
||||
./
|
||||
└── unravel-emacs.org
|
||||
|
||||
1 directory, 1 file
|
||||
2 directories, 5 files
|
||||
|
||||
To make a change to this Emacs configuration, edit this file and then type =C-c C-v C-t= (=M-x org-babel-tangle=) to republish all the relevant files.
|
||||
|
||||
|
@ -181,7 +180,7 @@ Now we are ready to load our per-module configuration files:
|
|||
;; (require 'unravel-window)
|
||||
;; (require 'unravel-git)
|
||||
;; (require 'unravel-org)
|
||||
;; (require 'unravel-langs)
|
||||
(require 'unravel-langs)
|
||||
|
||||
#+end_src
|
||||
|
||||
|
@ -540,3 +539,202 @@ Prot is the lead developer and maintainer.
|
|||
#+begin_src emacs-lisp :tangle "unravel-modules/unravel-theme.el"
|
||||
(provide 'unravel-theme)
|
||||
#+end_src
|
||||
|
||||
* The ~unravel-langs.el~ module
|
||||
|
||||
** Controlling the behaviour of the TAB key
|
||||
|
||||
#+begin_src emacs-lisp :tangle "unravel-modules/unravel-langs.el" :mkdirp yes
|
||||
;;;; Tabs, indentation, and the TAB key
|
||||
(use-package emacs
|
||||
:ensure nil
|
||||
:demand t
|
||||
:config
|
||||
(setq tab-always-indent 'complete)
|
||||
(setq tab-first-completion 'word-or-paren-or-punct) ; Emacs 27
|
||||
(setq-default tab-width 4
|
||||
indent-tabs-mode nil))
|
||||
#+end_src
|
||||
|
||||
** ~show-paren-mode~ for highlighting matching parens
|
||||
|
||||
The built-in ~show-paren-mode~ highlights the parenthesis on the opposite end of the current symbolic expression. It also highlights matching terms of control flow in programming languages that are not using parentheses like Lisp: for instance, in a ~bash~ shell script it highlights the ~if~ and ~fi~ keywords. This mode also works for prose and I use it globally. Simple and effective!
|
||||
|
||||
#+begin_src emacs-lisp :tangle "unravel-modules/unravel-langs.el"
|
||||
;;;; Parentheses (show-paren-mode)
|
||||
(use-package paren
|
||||
:ensure nil
|
||||
:hook (prog-mode . show-paren-local-mode)
|
||||
:config
|
||||
(setq show-paren-style 'mixed)
|
||||
(setq show-paren-when-point-in-periphery nil)
|
||||
(setq show-paren-when-point-inside-paren nil)
|
||||
(setq show-paren-context-when-offscreen 'overlay)) ; Emacs 29
|
||||
#+end_src
|
||||
|
||||
** Settings for ~eldoc~: Emacs Live Documentation Feedback
|
||||
|
||||
The built-in ~eldoc~ feature is especially useful in programming modes. While we are in a function call, it produces an indicator in the echo area (where the minibuffer appears upon invocation) that shows the name of the function, the arguments it takes, if any, and highlights the current argument we are positioned at. This way, we do not have to go back to review the signature of the function just to remember its arity. Same principle for variables, where ~eldoc-mode~ puts the first line of their documentation string in the echo area.
|
||||
|
||||
#+begin_src emacs-lisp :tangle "unravel-modules/unravel-langs.el"
|
||||
;;;; Eldoc (Emacs live documentation feedback)
|
||||
(use-package eldoc
|
||||
:ensure nil
|
||||
:hook (prog-mode . eldoc-mode)
|
||||
:config
|
||||
(setq eldoc-message-function #'message)) ; don't use mode line for M-x eval-expression, etc.
|
||||
#+end_src
|
||||
|
||||
** Settings for ~eglot~ (LSP client)
|
||||
:PROPERTIES:
|
||||
:CUSTOM_ID: h:92258aa8-0d8c-4c12-91b4-5f44420435ce
|
||||
:END:
|
||||
|
||||
The built-in ~eglot~ feature, developed and maintained by João Távora, is Emacs' own client for the Language Server Protocol (LSP). The LSP technology is all about enhancing the ability of a text editor to work with a given programming language. This works by installing a so-called "language server" on your computer, which the "LSP client" (i.e. ~eglot~) will plug into. A typical language server provides the following capabilities:
|
||||
|
||||
- Code completion :: This can be visualised for in-buffer automatic expansion of function calls, variables, and the like.
|
||||
|
||||
- Code linting :: To display suggestions, warnings, or errors. These are highlighted in the buffer, usually with an underline, and can also be displayed in a standalone buffer with the commands ~flymake-show-buffer-diagnostics~, ~flymake-show-project-diagnostics~
|
||||
|
||||
- Code navigation and cross-referencing :: While over a symbol, use a command to jump directly to its definition. The default key bindings for going forth and then back are =M-.= (~xref-find-definitions~) and =M-,= (~xref-go-back~).
|
||||
|
||||
Assuming the language server is installed, to start using the LSP client in a given file, do =M-x eglot=.
|
||||
|
||||
#+begin_src emacs-lisp :tangle "unravel-modules/unravel-langs.el"
|
||||
;;;; Eglot (built-in client for the language server protocol)
|
||||
(use-package eglot
|
||||
:ensure nil
|
||||
:functions (eglot-ensure)
|
||||
:commands (eglot)
|
||||
:config
|
||||
(setq eglot-sync-connect nil)
|
||||
(setq eglot-autoshutdown t))
|
||||
#+end_src
|
||||
|
||||
** Settings for ~markdown-mode~
|
||||
|
||||
The ~markdown-mode~ lets us edit Markdown files. We get syntax highlighting and several extras, such as the folding of headings and navigation between them. The mode actually provides lots of added functionality for GitHub-flavoured Markdown and to preview a Markdown file's HTML representation on a web page. Though I only use it for basic text editing.
|
||||
|
||||
#+begin_src emacs-lisp :tangle "unravel-modules/unravel-langs.el"
|
||||
;;; Markdown (markdown-mode)
|
||||
(use-package markdown-mode
|
||||
:ensure t
|
||||
:defer t
|
||||
:config
|
||||
(setq markdown-fontify-code-blocks-natively t))
|
||||
#+end_src
|
||||
|
||||
** Settings for ~csv-mode~
|
||||
|
||||
The package ~csv-mode~ provides support for =.csv= files. I do need this on occasion, even though my use-case is pretty basic. For me, the killer feature is the ability to create a virtual tabulated listing with the command ~csv-align-mode~: it hides the field delimiter (comma or space) and shows a tab stop in its stead.
|
||||
|
||||
#+begin_src emacs-lisp :tangle "unravel-modules/unravel-langs.el"
|
||||
;;; csv-mode
|
||||
(use-package csv-mode
|
||||
:ensure t
|
||||
:commands (csv-align-mode))
|
||||
#+end_src
|
||||
|
||||
** Settings for spell checking (~flyspell~)
|
||||
|
||||
#+begin_src emacs-lisp :tangle "unravel-modules/unravel-langs.el"
|
||||
;;; Flyspell
|
||||
(use-package flyspell
|
||||
:ensure nil
|
||||
:bind
|
||||
( :map flyspell-mode-map
|
||||
("C-;" . nil)
|
||||
:map flyspell-mouse-map
|
||||
("<mouse-3>" . flyspell-correct-word))
|
||||
:config
|
||||
(setq flyspell-issue-message-flag nil)
|
||||
(setq flyspell-issue-welcome-flag nil)
|
||||
(setq ispell-program-name "aspell")
|
||||
(setq ispell-dictionary "en_GB"))
|
||||
#+end_src
|
||||
|
||||
** Settings for code linting (~flymake~)
|
||||
|
||||
The built-in ~flymake~ feature defines an interface for viewing the output of linter programs. A "linter" parses a file and reports possible notes/warnings/errors in it. With ~flymake~ we get these diagnostics in the form of a standalone buffer as well as inline highlights (typically underlines combined with fringe indicators) for the portion of text in question. The linter report is displayed with the command ~flymake-show-buffer-diagnostics~, or ~flymake-show-project-diagnostics~. Highlights are shown in the context of the file.
|
||||
|
||||
The built-in ~eglot~ feature uses ~flymake~ internally to handle the LSP linter output ([[#h:92258aa8-0d8c-4c12-91b4-5f44420435ce][Settings for ~eglot~]]).
|
||||
|
||||
As for what I have in this configuration block, the essentials for me are the user options ~flymake-start-on-save-buffer~ and ~flymake-start-on-flymake-mode~ as they make the linter update its report when the buffer is saved and when ~flymake-mode~ is started, respectively. Otherwise, we have to run it manually, which is cumbersome.
|
||||
|
||||
The ~package-lint-flymake~ package by Steve Purcell adds the glue code to make ~flymake~ report issues with Emacs Lisp files for the purposes of packaging.
|
||||
|
||||
#+begin_src emacs-lisp :tangle "unravel-modules/unravel-langs.el"
|
||||
;;; Flymake
|
||||
(use-package flymake
|
||||
:ensure nil
|
||||
:bind
|
||||
(:map flymake-mode-map
|
||||
("C-c ! s" . flymake-start)
|
||||
("C-c ! l" . flymake-show-buffer-diagnostics) ; Emacs28
|
||||
("C-c ! L" . flymake-show-project-diagnostics) ; Emacs28
|
||||
("C-c ! n" . flymake-goto-next-error)
|
||||
("C-c ! p" . flymake-goto-prev-error))
|
||||
:config
|
||||
(setq flymake-fringe-indicator-position 'left-fringe)
|
||||
(setq flymake-suppress-zero-counters t)
|
||||
(setq flymake-no-changes-timeout nil)
|
||||
(setq flymake-start-on-flymake-mode t)
|
||||
(setq flymake-start-on-save-buffer t)
|
||||
(setq flymake-proc-compilation-prevents-syntax-check t)
|
||||
(setq flymake-wrap-around nil)
|
||||
(setq flymake-mode-line-format
|
||||
'("" flymake-mode-line-exception flymake-mode-line-counters))
|
||||
;; NOTE 2023-07-03: `prot-modeline.el' actually defines the counters
|
||||
;; itself and ignores this.
|
||||
(setq flymake-mode-line-counter-format
|
||||
'("" flymake-mode-line-error-counter
|
||||
flymake-mode-line-warning-counter
|
||||
flymake-mode-line-note-counter ""))
|
||||
(setq flymake-show-diagnostics-at-end-of-line nil)) ; Emacs 30
|
||||
|
||||
;;; Elisp packaging requirements
|
||||
(use-package package-lint-flymake
|
||||
:ensure t
|
||||
:after flymake
|
||||
:config
|
||||
(add-hook 'flymake-diagnostic-functions #'package-lint-flymake))
|
||||
#+end_src
|
||||
|
||||
** Settings for ~outline-minor-mode~
|
||||
|
||||
#+begin_src emacs-lisp :tangle "unravel-modules/unravel-langs.el"
|
||||
;;; General configurations for prose/writing
|
||||
|
||||
;;;; `outline' (`outline-mode' and `outline-minor-mode')
|
||||
(use-package outline
|
||||
:ensure nil
|
||||
:bind
|
||||
("<f10>" . outline-minor-mode)
|
||||
:config
|
||||
(setq outline-minor-mode-highlight nil) ; emacs28
|
||||
(setq outline-minor-mode-cycle t) ; emacs28
|
||||
(setq outline-minor-mode-use-buttons nil) ; emacs29---bless you for the nil option!
|
||||
(setq outline-minor-mode-use-margins nil)) ; as above
|
||||
#+end_src
|
||||
|
||||
** Settings for ~dictionary~
|
||||
|
||||
Use the entry point ~M-x dictionary-search~
|
||||
|
||||
|
||||
#+begin_src emacs-lisp :tangle "unravel-modules/unravel-langs.el"
|
||||
;;;; `dictionary'
|
||||
(use-package dictionary
|
||||
:ensure nil
|
||||
:config
|
||||
(setq dictionary-server "dict.org"
|
||||
dictionary-default-popup-strategy "lev" ; read doc string
|
||||
dictionary-create-buttons nil
|
||||
dictionary-use-single-buffer t))
|
||||
#+end_src
|
||||
|
||||
** Finally, we provide ~unravel-langs.el~ module
|
||||
|
||||
#+begin_src emacs-lisp :tangle "unravel-modules/unravel-langs.el"
|
||||
(provide 'unravel-langs)
|
||||
#+end_src
|
||||
|
|
120
unravel-modules/unravel-langs.el
Normal file
120
unravel-modules/unravel-langs.el
Normal file
|
@ -0,0 +1,120 @@
|
|||
;;;; Tabs, indentation, and the TAB key
|
||||
(use-package emacs
|
||||
:ensure nil
|
||||
:demand t
|
||||
:config
|
||||
(setq tab-always-indent 'complete)
|
||||
(setq tab-first-completion 'word-or-paren-or-punct) ; Emacs 27
|
||||
(setq-default tab-width 4
|
||||
indent-tabs-mode nil))
|
||||
|
||||
;;;; Parentheses (show-paren-mode)
|
||||
(use-package paren
|
||||
:ensure nil
|
||||
:hook (prog-mode . show-paren-local-mode)
|
||||
:config
|
||||
(setq show-paren-style 'mixed)
|
||||
(setq show-paren-when-point-in-periphery nil)
|
||||
(setq show-paren-when-point-inside-paren nil)
|
||||
(setq show-paren-context-when-offscreen 'overlay)) ; Emacs 29
|
||||
|
||||
;;;; Eldoc (Emacs live documentation feedback)
|
||||
(use-package eldoc
|
||||
:ensure nil
|
||||
:hook (prog-mode . eldoc-mode)
|
||||
:config
|
||||
(setq eldoc-message-function #'message)) ; don't use mode line for M-x eval-expression, etc.
|
||||
|
||||
;;;; Eglot (built-in client for the language server protocol)
|
||||
(use-package eglot
|
||||
:ensure nil
|
||||
:functions (eglot-ensure)
|
||||
:commands (eglot)
|
||||
:config
|
||||
(setq eglot-sync-connect nil)
|
||||
(setq eglot-autoshutdown t))
|
||||
|
||||
;;; Markdown (markdown-mode)
|
||||
(use-package markdown-mode
|
||||
:ensure t
|
||||
:defer t
|
||||
:config
|
||||
(setq markdown-fontify-code-blocks-natively t))
|
||||
|
||||
;;; csv-mode
|
||||
(use-package csv-mode
|
||||
:ensure t
|
||||
:commands (csv-align-mode))
|
||||
|
||||
;;; Flyspell
|
||||
(use-package flyspell
|
||||
:ensure nil
|
||||
:bind
|
||||
( :map flyspell-mode-map
|
||||
("C-;" . nil)
|
||||
:map flyspell-mouse-map
|
||||
("<mouse-3>" . flyspell-correct-word))
|
||||
:config
|
||||
(setq flyspell-issue-message-flag nil)
|
||||
(setq flyspell-issue-welcome-flag nil)
|
||||
(setq ispell-program-name "aspell")
|
||||
(setq ispell-dictionary "en_GB"))
|
||||
|
||||
;;; Flymake
|
||||
(use-package flymake
|
||||
:ensure nil
|
||||
:bind
|
||||
(:map flymake-mode-map
|
||||
("C-c ! s" . flymake-start)
|
||||
("C-c ! l" . flymake-show-buffer-diagnostics) ; Emacs28
|
||||
("C-c ! L" . flymake-show-project-diagnostics) ; Emacs28
|
||||
("C-c ! n" . flymake-goto-next-error)
|
||||
("C-c ! p" . flymake-goto-prev-error))
|
||||
:config
|
||||
(setq flymake-fringe-indicator-position 'left-fringe)
|
||||
(setq flymake-suppress-zero-counters t)
|
||||
(setq flymake-no-changes-timeout nil)
|
||||
(setq flymake-start-on-flymake-mode t)
|
||||
(setq flymake-start-on-save-buffer t)
|
||||
(setq flymake-proc-compilation-prevents-syntax-check t)
|
||||
(setq flymake-wrap-around nil)
|
||||
(setq flymake-mode-line-format
|
||||
'("" flymake-mode-line-exception flymake-mode-line-counters))
|
||||
;; NOTE 2023-07-03: `prot-modeline.el' actually defines the counters
|
||||
;; itself and ignores this.
|
||||
(setq flymake-mode-line-counter-format
|
||||
'("" flymake-mode-line-error-counter
|
||||
flymake-mode-line-warning-counter
|
||||
flymake-mode-line-note-counter ""))
|
||||
(setq flymake-show-diagnostics-at-end-of-line nil)) ; Emacs 30
|
||||
|
||||
;;; Elisp packaging requirements
|
||||
(use-package package-lint-flymake
|
||||
:ensure t
|
||||
:after flymake
|
||||
:config
|
||||
(add-hook 'flymake-diagnostic-functions #'package-lint-flymake))
|
||||
|
||||
;;; General configurations for prose/writing
|
||||
|
||||
;;;; `outline' (`outline-mode' and `outline-minor-mode')
|
||||
(use-package outline
|
||||
:ensure nil
|
||||
:bind
|
||||
("<f10>" . outline-minor-mode)
|
||||
:config
|
||||
(setq outline-minor-mode-highlight nil) ; emacs28
|
||||
(setq outline-minor-mode-cycle t) ; emacs28
|
||||
(setq outline-minor-mode-use-buttons nil) ; emacs29---bless you for the nil option!
|
||||
(setq outline-minor-mode-use-margins nil)) ; as above
|
||||
|
||||
;;;; `dictionary'
|
||||
(use-package dictionary
|
||||
:ensure nil
|
||||
:config
|
||||
(setq dictionary-server "dict.org"
|
||||
dictionary-default-popup-strategy "lev" ; read doc string
|
||||
dictionary-create-buttons nil
|
||||
dictionary-use-single-buffer t))
|
||||
|
||||
(provide 'unravel-langs)
|
Loading…
Reference in a new issue