emacs-elpa-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[nongnu] elpa/haskell-tng-mode 599d4f0 283/385: import symbol at point


From: ELPA Syncer
Subject: [nongnu] elpa/haskell-tng-mode 599d4f0 283/385: import symbol at point
Date: Tue, 5 Oct 2021 23:59:49 -0400 (EDT)

branch: elpa/haskell-tng-mode
commit 599d4f0e9d1dbae34d58a7ea6d966cf796c3ea1e
Author: Tseen She <ts33n.sh3@gmail.com>
Commit: Tseen She <ts33n.sh3@gmail.com>

    import symbol at point
---
 README.md                |  2 +-
 haskell-tng-extra.el     | 12 +++++++++--
 haskell-tng-hsinspect.el | 52 ++++++++++++++++++++++++++++++++++++++++++++++++
 haskell-tng-util.el      | 18 +++++++++++++++++
 4 files changed, 81 insertions(+), 3 deletions(-)

diff --git a/README.md b/README.md
index a778405..6435488 100644
--- a/README.md
+++ b/README.md
@@ -68,7 +68,7 @@ You must install `hsinspect` for every version of `ghc` that 
you plan to use, e.
 ```
 rm -f ~/.cabal/bin/hsinspect
 for V in 8.4.4 8.6.5 ; do
-  cabal v2-install hsinspect-0.0.6 -w ghc-$V -O2 &&
+  cabal v2-install hsinspect-0.0.7 -w ghc-$V -O2 &&
   mv -f ~/.cabal/bin/hsinspect ~/.cabal/bin/hsinspect-ghc-$V
 done
 ```
diff --git a/haskell-tng-extra.el b/haskell-tng-extra.el
index 48fe0da..5f7d5ac 100644
--- a/haskell-tng-extra.el
+++ b/haskell-tng-extra.el
@@ -93,9 +93,17 @@ When in a comment and called with a prefix, the comment will 
be completed."
 ;;;###autoload
 (defun haskell-tng-goto-imports ()
   "Hack to jump to imports"
-  ;; TODO imenu navigation will replace this
   (interactive)
-  (re-search-backward (rx line-start "import" word-end)))
+  (goto-char (point-min))
+  (re-search-forward (rx line-start "import" word-end))
+  (forward-line 0))
+
+;;;###autoload
+(defun haskell-tng-import-module (module)
+  "Adds an unqualified wildcard import."
+  ;; TODO autocomplete on available imports
+  (interactive "s")
+  (haskell-tng--import-symbol module nil nil))
 
 ;;;###autoload
 (defun haskell-tng-current-module ()
diff --git a/haskell-tng-hsinspect.el b/haskell-tng-hsinspect.el
index 202fd95..45332a2 100644
--- a/haskell-tng-hsinspect.el
+++ b/haskell-tng-hsinspect.el
@@ -20,6 +20,7 @@
 ;; centric.
 
 (require 'haskell-tng-compile)
+(require 'haskell-tng-util)
 
 ;;;###autoload
 (defun haskell-tng-fqn-at-point ()
@@ -37,6 +38,46 @@ name of the symbol at point in the minibuffer."
         (error "hsinspect is not available")
       (message "<not imported>"))))
 
+;;;###autoload
+(defun haskell-tng-import-symbol-at-point ()
+  "Import the symbol at point"
+  ;; TODO import FQN as qualified module
+  ;; TODO prefix + FQN should mean use unqualified `as' import
+  ;; TODO prefix + unqualified should mean to import entire module
+  ;; TODO shortlist for FQN imports (no need to calc the index)
+  (interactive)
+  (when-let* ((index (haskell-tng--hsinspect-index))
+              (sym (haskell-tng--hsinspect-symbol-at-point)))
+    (message "Seaching for '%s' in %s modules" sym (length index))
+    (when-let ((hits (haskell-tng--hsinspect-import-candidates index sym)))
+      ;; TODO special case one hit
+      (when-let* ((entries (mapcar 'car hits)) ;; TODO include function name
+                  (selected (popup-menu* entries))
+                  (hit (seq-find (lambda (el) (equal (car el) selected)) 
hits)))
+        (haskell-tng--import-symbol (car hit) nil (cdr hit))))))
+
+(defun haskell-tng--hsinspect-import-candidates (index sym)
+  "Return a list of (module . symbol)"
+  ;; TODO threading/do syntax
+  ;; TODO alist variable binding like RecordWildcards
+  (seq-mapcat
+   (lambda (pkg-entry)
+     (let ((modules (alist-get 'modules pkg-entry))
+           (unitid (alist-get 'unitid pkg-entry)))
+       ;; (message "UNITID= %s" unitid)
+       (seq-mapcat
+        (lambda (module-entry)
+          (let ((module (alist-get 'module module-entry))
+                (ids (alist-get 'ids module-entry)))
+            ;;(message "MODULE= %s" module)
+            (seq-mapcat
+             (lambda (entry)
+               (let ((name (alist-get 'name entry)))
+                 (when (equal name sym) `(,(cons module name)))))
+             ids)))
+        modules)))
+   index))
+
 (defun haskell-tng--hsinspect-symbol-at-point ()
   "A `symbol-at-point' that includes FQN parts."
   (buffer-substring-no-properties
@@ -87,6 +128,17 @@ t means the process failed.")
     (setq haskell-tng--hsinspect-imports
           (haskell-tng--hsinspect "imports" buffer-file-name))))
 
+;; TODO this can be more efficiently cached alongside the .ghc.flags file, not 
per source file
+;; (it's also fast to load so maybe persist it in a cache dir and check 
timestamps)
+(defvar-local haskell-tng--hsinspect-index nil)
+(defun haskell-tng--hsinspect-index (&optional lookup-only)
+  (if (or lookup-only haskell-tng--hsinspect-index)
+      (unless (eq t haskell-tng--hsinspect-index)
+        haskell-tng--hsinspect-index)
+    (setq haskell-tng--hsinspect-index t) ;; avoid races
+    (setq haskell-tng--hsinspect-index
+          (haskell-tng--hsinspect "index"))))
+
 (defun haskell-tng--hsinspect (&rest params)
   (ignore-errors (kill-buffer "*hsinspect*"))
   (when-let ((ghcflags (haskell-tng--hsinspect-ghcflags))
diff --git a/haskell-tng-util.el b/haskell-tng-util.el
index 041cec6..fb9a367 100644
--- a/haskell-tng-util.el
+++ b/haskell-tng-util.el
@@ -70,5 +70,23 @@ and taking a regexp."
        (while (not (setq ,res ,test)) ,@body)
        ,res)))
 
+(defun haskell-tng--import-symbol (module as sym)
+  "Adds an import for MODULE."
+  ;; TODO outsource to `hsimport' when it does de-duping and formatting.
+  (save-excursion
+   (haskell-tng-goto-imports)
+   (insert
+    "import "
+    (cond
+     ((and (null as) (null sym))
+      module)
+     ((null as)
+      (concat module " (" sym ")"))
+     ((eq t as)
+      (concat "qualified " module))
+     (t
+      (concat "qualified " module " as " as)))
+    "\n")))
+
 (provide 'haskell-tng-util)
 ;;; haskell-tng-util.el ends here



reply via email to

[Prev in Thread] Current Thread [Next in Thread]