From 17ee0e400bef47c371afcae76037f9ea6a44ad13 Mon Sep 17 00:00:00 2001 From: William Carroll Date: Mon, 10 Sep 2018 14:51:14 -0400 Subject: Support Vim, Tmux, Emacs with Stow After moving off of Meta, Dotfiles has a greater responsibility to manage configs. Vim, Tmux, and Emacs are now within Stow's purview. --- .../haskell-align-imports.el | 231 +++++++++++++++++++++ 1 file changed, 231 insertions(+) create mode 100644 configs/shared/emacs/.emacs.d/elpa/haskell-mode-20180601.143/haskell-align-imports.el (limited to 'configs/shared/emacs/.emacs.d/elpa/haskell-mode-20180601.143/haskell-align-imports.el') diff --git a/configs/shared/emacs/.emacs.d/elpa/haskell-mode-20180601.143/haskell-align-imports.el b/configs/shared/emacs/.emacs.d/elpa/haskell-mode-20180601.143/haskell-align-imports.el new file mode 100644 index 000000000000..694ee259295b --- /dev/null +++ b/configs/shared/emacs/.emacs.d/elpa/haskell-mode-20180601.143/haskell-align-imports.el @@ -0,0 +1,231 @@ +;;; haskell-align-imports.el --- Align the import lines in a Haskell file -*- lexical-binding: t -*- + +;; Copyright (C) 2010 Chris Done + +;; Author: Chris Done + +;; This file is not part of GNU Emacs. + +;; This program is free software: you can redistribute it and/or +;; modify it under the terms of the GNU General Public License as +;; published by the Free Software Foundation, either version 3 of +;; the License, or (at your option) any later version. + +;; This program is distributed in the hope that it will be +;; useful, but WITHOUT ANY WARRANTY; without even the implied +;; warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +;; PURPOSE. See the GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public +;; License along with this program. If not, see +;; . + +;;; Commentary: + +;; Consider the following imports list: +;; +;; import One +;; import Two as A +;; import qualified Three +;; import qualified Four as PRELUDE +;; import Five (A) +;; import Six (A,B) +;; import qualified Seven (A,B) +;; import "abc" Eight +;; import "abc" Nine as TWO +;; import qualified "abc" Ten +;; import qualified "defg" Eleven as PRELUDE +;; import "barmu" Twelve (A) +;; import "zotconpop" Thirteen (A,B) +;; import qualified "z" Fourteen (A,B) +;; import Fifteen hiding (A) +;; import Sixteen as TWO hiding (A) +;; import qualified Seventeen hiding (A) +;; import qualified Eighteen as PRELUDE hiding (A) +;; import "abc" Nineteen hiding (A) +;; import "abc" Twenty as TWO hiding (A) +;; +;; When haskell-align-imports is run within the same buffer, the +;; import list is transformed to: +;; +;; import "abc" Eight +;; import qualified Eighteen as PRELUDE hiding (A) +;; import qualified "defg" Eleven as PRELUDE +;; import Fifteen hiding (A) +;; import Five (A) +;; import qualified Four as PRELUDE +;; import qualified "z" Fourteen (A,B) +;; import "abc" Nine as TWO +;; import "abc" Nineteen hiding (A) +;; import One +;; import qualified Seven (A,B) +;; import qualified Seventeen hiding (A) +;; import Six (A,B) +;; import Sixteen as TWO hiding (A) +;; import qualified "abc" Ten +;; import "zotconpop" Thirteen (A,B) +;; import qualified Three +;; import "barmu" Twelve (A) +;; import "abc" Twenty as TWO hiding (A) +;; import Two as A +;; +;; If you want everything after module names to be padded out, too, +;; customize `haskell-align-imports-pad-after-name', and you'll get: +;; +;; import One +;; import Two as A +;; import qualified Three +;; import qualified Four as PRELUDE +;; import Five (A) +;; import Six (A,B) +;; import qualified Seven (A,B) +;; import "abc" Eight +;; import "abc" Nine as TWO +;; import qualified "abc" Ten +;; import qualified "defg" Eleven as PRELUDE +;; import "barmu" Twelve (A) +;; import "zotconpop" Thirteen (A,B) +;; import qualified "z" Fourteen (A,B) +;; import Fifteen hiding (A) +;; import Sixteen as TWO hiding (A) +;; import qualified Seventeen hiding (A) +;; import qualified Eighteen as PRELUDE hiding (A) +;; import "abc" Nineteen hiding (A) +;; import "abc" Twenty as TWO hiding (A) + +;;; Code: + +(require 'cl-lib) + +(defvar haskell-align-imports-regexp + (concat "^\\(import[ ]+\\)" + "\\(qualified \\)?" + "[ ]*\\(\"[^\"]*\" \\)?" + "[ ]*\\([A-Za-z0-9_.']+\\)" + "[ ]*\\([ ]*as [A-Z][^ ]*\\)?" + "[ ]*\\((.*)\\)?" + "\\([ ]*hiding (.*)\\)?" + "\\( -- .*\\)?[ ]*$") + "Regex used for matching components of an import.") + +(defcustom haskell-align-imports-pad-after-name + nil + "Pad layout after the module name also." + :type 'boolean + :group 'haskell-interactive) + +;;;###autoload +(defun haskell-align-imports () + "Align all the imports in the buffer." + (interactive) + (when (haskell-align-imports-line-match) + (save-excursion + (goto-char (point-min)) + (let* ((imports (haskell-align-imports-collect)) + (padding (haskell-align-imports-padding imports))) + (mapc (lambda (x) + (goto-char (cdr x)) + (delete-region (point) (line-end-position)) + (insert (haskell-align-imports-chomp + (haskell-align-imports-fill padding (car x))))) + imports)))) + nil) + +(defun haskell-align-imports-line-match () + "Try to match the current line as a regexp." + (let ((line (buffer-substring-no-properties (line-beginning-position) + (line-end-position)))) + (if (string-match "^import " line) + line + nil))) + +(defun haskell-align-imports-collect () + "Collect a list of mark / import statement pairs." + (let ((imports '())) + (while (not (or (equal (point) (point-max)) (haskell-align-imports-after-imports-p))) + (let ((line (haskell-align-imports-line-match-it))) + (when line + (let ((match + (haskell-align-imports-merge-parts + (cl-loop for i from 1 to 8 + collect (haskell-align-imports-chomp (match-string i line)))))) + (setq imports (cons (cons match (line-beginning-position)) + imports))))) + (forward-line)) + imports)) + +(defun haskell-align-imports-merge-parts (l) + "Merge together parts of an import statement that shouldn't be separated." + (let ((parts (apply #'vector l)) + (join (lambda (ls) + (cl-reduce (lambda (a b) + (concat a + (if (and (> (length a) 0) + (> (length b) 0)) + " " + "") + b)) + ls)))) + (if haskell-align-imports-pad-after-name + (list (funcall join (list (aref parts 0) + (aref parts 1) + (aref parts 2))) + (aref parts 3) + (funcall join (list (aref parts 4) + (aref parts 5) + (aref parts 6))) + (aref parts 7)) + (list (funcall join (list (aref parts 0) + (aref parts 1) + (aref parts 2))) + (funcall join (list (aref parts 3) + (aref parts 4) + (aref parts 5) + (aref parts 6) + (aref parts 7))))))) + +(defun haskell-align-imports-chomp (str) + "Chomp leading and tailing whitespace from STR." + (if str + (replace-regexp-in-string "\\(^[[:space:]\n]*\\|[[:space:]\n]*$\\)" "" + str) + "")) + +(defun haskell-align-imports-padding (imports) + "Find the padding for each part of the import statements." + (if (null imports) + imports + (cl-reduce (lambda (a b) (cl-mapcar #'max a b)) + (mapcar (lambda (x) (mapcar #'length (car x))) + imports)))) + +(defun haskell-align-imports-fill (padding line) + "Fill an import line using the padding worked out from all statements." + (mapconcat #'identity + (cl-mapcar (lambda (pad part) + (if (> (length part) 0) + (concat part (make-string (- pad (length part)) ? )) + (make-string pad ? ))) + padding + line) + " ")) + +(defun haskell-align-imports-line-match-it () + "Try to match the current line as a regexp." + (let ((line (buffer-substring-no-properties (line-beginning-position) + (line-end-position)))) + (if (string-match haskell-align-imports-regexp line) + line + nil))) + +(defun haskell-align-imports-after-imports-p () + "Are we after the imports list?" + (save-excursion + (goto-char (line-beginning-position)) + (let ((case-fold-search nil)) + (not (not (search-forward-regexp "\\( = \\|\\\\| :: \\| ∷ \\)" + (line-end-position) t 1)))))) + +(provide 'haskell-align-imports) + +;;; haskell-align-imports.el ends here -- cgit 1.4.1