From d3b313a8be9974a213cdf13f8dabae222f56a6e5 Mon Sep 17 00:00:00 2001 From: Ramakrishnan Muthukrishnan Date: Tue, 17 Feb 2015 12:00:35 +0530 Subject: [PATCH] misc changes, hlint --- hs-lint/hs-lint.el | 126 +++++++++++++++++++++++++++++++++++++++++++++ init.el | 12 +++-- 2 files changed, 134 insertions(+), 4 deletions(-) create mode 100644 hs-lint/hs-lint.el diff --git a/hs-lint/hs-lint.el b/hs-lint/hs-lint.el new file mode 100644 index 0000000..f69ef0c --- /dev/null +++ b/hs-lint/hs-lint.el @@ -0,0 +1,126 @@ +;;; 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-line 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 diff --git a/init.el b/init.el index c954fbc..5a29e5e 100644 --- a/init.el +++ b/init.el @@ -1,5 +1,3 @@ -; Prevent the cursor from blinking -(blink-cursor-mode 0) (show-paren-mode 1) ;; y-or-n instead of yes-or-no (defalias 'yes-or-no-p 'y-or-n-p) @@ -40,7 +38,7 @@ (package-refresh-contents)) ;; make sure my list of packages are installed -(setq package-list '(rust-mode haskell-mode go-mode monokai-theme ghc restclient)) +(setq package-list '(rust-mode haskell-mode clojure-mode monokai-theme ghc restclient)) ; install the missing packages (dolist (package package-list) @@ -57,7 +55,7 @@ (erc-autojoin-mode t) (setq erc-autojoin-channels-alist - '((".*\\.freenode.net" "#tahoe-lafs" "#haskell-beginners") + '((".*\\.freenode.net" "#tahoe-lafs") (".*\\.oftc.net" "#LeastAuthority"))) ;; check channels @@ -115,3 +113,9 @@ (setq c-default-style "k&r" c-basic-offset 4) +;; hlint +(add-to-list 'load-path "~/.emacs.d/hs-lint") +(require 'hs-lint) +(defun my-haskell-mode-hook () + (local-set-key "\C-cl" 'hs-lint)) +(add-hook 'haskell-mode-hook 'my-haskell-mode-hook) -- 2.37.2