X-Git-Url: https://git.shemshak.org/gitweb.cgi/~bandali/configs/blobdiff_plain/f27d607ecaf376361aa07ccd4bda48f7a37f42fd..0deee78815aa4815a091eee335e6358df545a333:/init.org diff --git a/init.org b/init.org index 1062c17..181dac7 100644 --- a/init.org +++ b/init.org @@ -931,9 +931,20 @@ TODO: break this giant source block down into individual org sections. (setq undo-tree-mode-lighter "")) #+end_src +* Syntax and spell checking +#+begin_src emacs-lisp +(use-package flycheck + :hook (prog-mode . flycheck-mode) + :config + ;; Use the load-path from running Emacs when checking elisp files + (setq flycheck-emacs-lisp-load-path 'inherit) + + ;; Only flycheck when I actually save the buffer + (setq flycheck-check-syntax-automatically '(mode-enabled save))) +#+end_src * Programming modes -** Lean mode +** [[https://github.com/leanprover/lean-mode][Lean]] #+begin_src emacs-lisp (use-package lean-mode @@ -941,6 +952,196 @@ TODO: break this giant source block down into individual org sections. ("S-SPC" . company-complete))) #+end_src +** Haskell + +*** [[https://github.com/haskell/haskell-mode][haskell-mode]] + +#+begin_src emacs-lisp +(use-package haskell-mode + :config + (setq haskell-indentation-layout-offset 4 + haskell-indentation-left-offset 4 + flycheck-checker 'haskell-hlint + flycheck-disabled-checkers '(haskell-stack-ghc haskell-ghc))) +#+end_src + +*** [[https://github.com/mpickering/hlint-refactor-mode][hlint-refactor]] + +Emacs bindings for [[https://github.com/ndmitchell/hlint][hlint]]'s refactor option. This requires the refact +executable from [[https://github.com/mpickering/apply-refact][apply-refact]]. + +#+begin_src emacs-lisp +(use-package hlint-refactor + :bind (:map hlint-refactor-mode-map + ("C-c l b" . hlint-refactor-refactor-buffer) + ("C-c l r" . hlint-refactor-refactor-at-point)) + :hook (haskell-mode . hlint-refactor-mode)) +#+end_src + +*** [[https://github.com/flycheck/flycheck-haskell][flycheck-haskell]] + +#+begin_src emacs-lisp +(use-package flycheck-haskell) +#+end_src + +*** [[https://github.com/ndmitchell/hlint/blob/20e116a043f2073c57b17b24ae6364b5e433ba7e/data/hs-lint.el][hs-lint.el]] +:PROPERTIES: +:header-args+: :tangle lisp/hs-lint.el :mkdirp yes +:END: + +Currently using =flycheck-haskell= with the =haskell-hlint= checker +instead. + +#+begin_src emacs-lisp :tangle no +;;; hs-lint.el --- minor mode for HLint code checking + +;; Copyright 2009 (C) Alex Ott +;; +;; Author: Alex Ott +;; Keywords: haskell, lint, HLint +;; Requirements: +;; Status: distributed under terms of GPL2 or above + +;; Typical message from HLint looks like: +;; +;; /Users/ott/projects/lang-exp/haskell/test.hs:52:1: Eta reduce +;; Found: +;; count1 p l = length (filter p l) +;; Why not: +;; count1 p = length . filter p + + +(require 'compile) + +(defgroup hs-lint nil + "Run HLint as inferior of Emacs, parse error messages." + :group 'tools + :group 'haskell) + +(defcustom hs-lint-command "hlint" + "The default hs-lint command for \\[hlint]." + :type 'string + :group 'hs-lint) + +(defcustom hs-lint-save-files t + "Save modified files when run HLint or no (ask user)" + :type 'boolean + :group 'hs-lint) + +(defcustom hs-lint-replace-with-suggestions nil + "Replace user's code with suggested replacements" + :type 'boolean + :group 'hs-lint) + +(defcustom hs-lint-replace-without-ask nil + "Replace user's code with suggested replacements automatically" + :type 'boolean + :group 'hs-lint) + +(defun hs-lint-process-setup () + "Setup compilation variables and buffer for `hlint'." + (run-hooks 'hs-lint-setup-hook)) + +;; regex for replace suggestions +;; +;; ^\(.*?\):\([0-9]+\):\([0-9]+\): .* +;; Found: +;; \s +\(.*\) +;; Why not: +;; \s +\(.*\) + +(defvar hs-lint-regex + "^\\(.*?\\):\\([0-9]+\\):\\([0-9]+\\): .*[\n\C-m]Found:[\n\C-m]\\s +\\(.*\\)[\n\C-m]Why not:[\n\C-m]\\s +\\(.*\\)[\n\C-m]" + "Regex for HLint messages") + +(defun make-short-string (str maxlen) + (if (< (length str) maxlen) + str + (concat (substring str 0 (- maxlen 3)) "..."))) + +(defun hs-lint-replace-suggestions () + "Perform actual replacement of suggestions" + (goto-char (point-min)) + (while (re-search-forward hs-lint-regex nil t) + (let* ((fname (match-string 1)) + (fline (string-to-number (match-string 2))) + (old-code (match-string 4)) + (new-code (match-string 5)) + (msg (concat "Replace '" (make-short-string old-code 30) + "' with '" (make-short-string new-code 30) "'")) + (bline 0) + (eline 0) + (spos 0) + (new-old-code "")) + (save-excursion + (switch-to-buffer (get-file-buffer fname)) + (goto-char (point-min)) + (forward-line (1- fline)) + (beginning-of-line) + (setf bline (point)) + (when (or hs-lint-replace-without-ask + (yes-or-no-p msg)) + (end-of-line) + (setf eline (point)) + (beginning-of-line) + (setf old-code (regexp-quote old-code)) + (while (string-match "\\\\ " old-code spos) + (setf new-old-code (concat new-old-code + (substring old-code spos (match-beginning 0)) + "\\ *")) + (setf spos (match-end 0))) + (setf new-old-code (concat new-old-code (substring old-code spos))) + (remove-text-properties bline eline '(composition nil)) + (when (re-search-forward new-old-code eline t) + (replace-match new-code nil t))))))) + +(defun hs-lint-finish-hook (buf msg) + "Function, that is executed at the end of HLint execution" + (if hs-lint-replace-with-suggestions + (hs-lint-replace-suggestions) + (next-error 1 t))) + +(define-compilation-mode hs-lint-mode "HLint" + "Mode for check Haskell source code." + (set (make-local-variable 'compilation-process-setup-function) + 'hs-lint-process-setup) + (set (make-local-variable 'compilation-disable-input) t) + (set (make-local-variable 'compilation-scroll-output) nil) + (set (make-local-variable 'compilation-finish-functions) + (list 'hs-lint-finish-hook)) + ) + +(defun hs-lint () + "Run HLint for current buffer with haskell source" + (interactive) + (save-some-buffers hs-lint-save-files) + (compilation-start (concat hs-lint-command " \"" buffer-file-name "\"") + 'hs-lint-mode)) + +(provide 'hs-lint) +;;; hs-lint.el ends here +#+end_src + +#+begin_src emacs-lisp :tangle no +(use-package hs-lint + :load-path "lisp/" + :bind (:map haskell-mode-map + ("C-c l l" . hs-lint))) +#+end_src +* Emacs Enhancements + +** [[https://github.com/justbur/emacs-which-key][which-key]] + +#+begin_quote +Emacs package that displays available keybindings in popup +#+end_quote + +#+begin_src emacs-lisp +(use-package which-key + :defer 1 + :config (which-key-mode)) +#+end_src + * Post initialization :PROPERTIES: :CUSTOM_ID: post-initialization