Skip to content

Fix haskell-ident-at-point uses and haskell-ident-pos-at-point behavior #603

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Apr 25, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
188 changes: 100 additions & 88 deletions haskell-commands.el
Original file line number Diff line number Diff line change
Expand Up @@ -279,23 +279,28 @@ given a prefix arg."
"Print info on the identifier at point.
If PROMPT-VALUE is non-nil, request identifier via mini-buffer."
(interactive "P")
(haskell-process-do-simple-echo
(let ((ident (replace-regexp-in-string
"^!\\([A-Z_a-z]\\)"
"\\1"
(if prompt-value
(read-from-minibuffer "Info: " (haskell-ident-at-point))
(haskell-ident-at-point))))
(modname (unless prompt-value
(haskell-utils-parse-import-statement-at-point))))
(if modname
(format ":browse! %s" modname)
(format (if (string-match "^[a-zA-Z_]" ident)
":info %s"
":info (%s)")
(or ident
(haskell-ident-at-point)))))
'haskell-mode))
(let ((at-point (haskell-ident-at-point)))
(when (or prompt-value at-point)
(let* ((ident (replace-regexp-in-string
"^!\\([A-Z_a-z]\\)"
"\\1"
(if prompt-value
(read-from-minibuffer "Info: " at-point)
at-point)))
(modname (unless prompt-value
(haskell-utils-parse-import-statement-at-point)))
(command (cond
(modname
(format ":browse! %s" modname))
((string= ident "") ; For the minibuffer input case
nil)
(t (format (if (string-match "^[a-zA-Z_]" ident)
":info %s"
":info (%s)")
(or ident
at-point))))))
(when command
(haskell-process-do-simple-echo command 'haskell-mode))))))

;;;###autoload
(defun haskell-process-do-type (&optional insert-value)
Expand Down Expand Up @@ -369,67 +374,71 @@ to to get there."
(defun haskell-process-insert-type ()
"Get the identifer at the point and insert its type, if
possible, using GHCi's :type."
(let ((process (haskell-interactive-process))
(query (let ((ident (haskell-ident-at-point)))
(format (if (string-match "^[_[:lower:][:upper:]]" ident)
":type %s"
":type (%s)")
ident))))
(haskell-process-queue-command
process
(make-haskell-command
:state (list process query (current-buffer))
:go (lambda (state)
(haskell-process-send-string (nth 0 state)
(nth 1 state)))
:complete (lambda (state response)
(cond
;; TODO: Generalize this into a function.
((or (string-match "^Top level" response)
(string-match "^<interactive>" response))
(message response))
(t
(with-current-buffer (nth 2 state)
(goto-char (line-beginning-position))
(insert (format "%s\n" (replace-regexp-in-string "\n$" "" response)))))))))))
(let ((ident (haskell-ident-at-point)))
(when ident
(let ((process (haskell-interactive-process))
(query (format (if (string-match "^[_[:lower:][:upper:]]" ident)
":type %s"
":type (%s)")
ident)))
(haskell-process-queue-command
process
(make-haskell-command
:state (list process query (current-buffer))
:go (lambda (state)
(haskell-process-send-string (nth 0 state)
(nth 1 state)))
:complete (lambda (state response)
(cond
;; TODO: Generalize this into a function.
((or (string-match "^Top level" response)
(string-match "^<interactive>" response))
(message response))
(t
(with-current-buffer (nth 2 state)
(goto-char (line-beginning-position))
(insert (format "%s\n" (replace-regexp-in-string "\n$" "" response)))))))))))))

(defun haskell-mode-find-def (ident)
"Find definition location of identifier. Uses the GHCi process
to find the location.
to find the location. Returns `nil' if it can't find the
identifier or the identifier isn't a string.

Returns:

(library <package> <module>)
(file <path> <line> <col>)
(module <name>)
nil
"
(let ((reply (haskell-process-queue-sync-request
(haskell-interactive-process)
(format (if (string-match "^[a-zA-Z_]" ident)
":info %s"
":info (%s)")
ident))))
(let ((match (string-match "-- Defined \\(at\\|in\\) \\(.+\\)$" reply)))
(when match
(let ((defined (match-string 2 reply)))
(let ((match (string-match "\\(.+?\\):\\([0-9]+\\):\\([0-9]+\\)$" defined)))
(cond
(match
(list 'file
(expand-file-name (match-string 1 defined)
(haskell-session-current-dir (haskell-interactive-session)))
(string-to-number (match-string 2 defined))
(string-to-number (match-string 3 defined))))
(t
(let ((match (string-match "`\\(.+?\\):\\(.+?\\)'$" defined)))
(if match
(list 'library
(match-string 1 defined)
(match-string 2 defined))
(let ((match (string-match "`\\(.+?\\)'$" defined)))
(if match
(list 'module
(match-string 1 defined))))))))))))))
(when (stringp ident)
(let ((reply (haskell-process-queue-sync-request
(haskell-interactive-process)
(format (if (string-match "^[a-zA-Z_]" ident)
":info %s"
":info (%s)")
ident))))
(let ((match (string-match "-- Defined \\(at\\|in\\) \\(.+\\)$" reply)))
(when match
(let ((defined (match-string 2 reply)))
(let ((match (string-match "\\(.+?\\):\\([0-9]+\\):\\([0-9]+\\)$" defined)))
(cond
(match
(list 'file
(expand-file-name (match-string 1 defined)
(haskell-session-current-dir (haskell-interactive-session)))
(string-to-number (match-string 2 defined))
(string-to-number (match-string 3 defined))))
(t
(let ((match (string-match "`\\(.+?\\):\\(.+?\\)'$" defined)))
(if match
(list 'library
(match-string 1 defined)
(match-string 2 defined))
(let ((match (string-match "`\\(.+?\\)'$" defined)))
(if match
(list 'module
(match-string 1 defined)))))))))))))))

;;;###autoload
(defun haskell-mode-jump-to-def (ident)
Expand Down Expand Up @@ -612,26 +621,29 @@ command from GHCi."
(interactive "P")
(let ((ty (haskell-mode-type-at))
(orig (point)))
(if insert-value
(let ((ident-pos (haskell-ident-pos-at-point)))
(cond
((region-active-p)
(delete-region (region-beginning)
(region-end))
(insert "(" ty ")")
(goto-char (1+ orig)))
((= (line-beginning-position) (car ident-pos))
(goto-char (line-beginning-position))
(insert (haskell-fontify-as-mode ty 'haskell-mode)
"\n"))
(t
(save-excursion
(goto-char (car ident-pos))
(let ((col (current-column)))
(save-excursion (insert "\n")
(indent-to col))
(insert (haskell-fontify-as-mode ty 'haskell-mode)))))))
(message "%s" (haskell-fontify-as-mode ty 'haskell-mode)))))
(unless (= (aref ty 0) ?\n)
;; That seems to be what happens when `haskell-mode-type-at` fails
(if insert-value
(let ((ident-pos (or (haskell-ident-pos-at-point)
(cons (point) (point)))))
(cond
((region-active-p)
(delete-region (region-beginning)
(region-end))
(insert "(" ty ")")
(goto-char (1+ orig)))
((= (line-beginning-position) (car ident-pos))
(goto-char (line-beginning-position))
(insert (haskell-fontify-as-mode ty 'haskell-mode)
"\n"))
(t
(save-excursion
(goto-char (car ident-pos))
(let ((col (current-column)))
(save-excursion (insert "\n")
(indent-to col))
(insert (haskell-fontify-as-mode ty 'haskell-mode)))))))
(message "%s" (haskell-fontify-as-mode ty 'haskell-mode))))))

;;;###autoload
(defun haskell-process-generate-tags (&optional and-then-find-this-tag)
Expand Down
2 changes: 1 addition & 1 deletion haskell-doc.el
Original file line number Diff line number Diff line change
Expand Up @@ -1677,7 +1677,7 @@ If `haskell-doc-use-inf-haskell' is non-nil, this function will consult
the inferior Haskell process for type/kind information, rather than using
the haskell-doc database."
(if haskell-doc-use-inf-haskell
(unless (string= "" sym)
(unless (or (null sym) (string= "" sym))
(let* ((message-log-max nil)
(result (ignore-errors
(unwind-protect
Expand Down
18 changes: 9 additions & 9 deletions haskell-mode.el
Original file line number Diff line number Diff line change
Expand Up @@ -486,19 +486,18 @@ Run M-x describe-variable haskell-mode-hook for a list of such modes."))
May return a qualified name."
(let ((reg (haskell-ident-pos-at-point)))
(when reg
(unless (= (car reg) (cdr reg))
(buffer-substring-no-properties (car reg) (cdr reg))))))
(buffer-substring-no-properties (car reg) (cdr reg)))))

(defun haskell-spanable-pos-at-point ()
"Like `haskell-ident-pos-at-point', but includes any surrounding backticks."
(save-excursion
(let ((pos (haskell-ident-pos-at-point)))
(if pos
(cl-destructuring-bind (start . end) pos
(if (and (eq ?` (char-before start))
(eq ?` (char-after end)))
(cons (- start 1) (+ end 1))
(cons start end)))))))
(when pos
(cl-destructuring-bind (start . end) pos
(if (and (eq ?` (char-before start))
(eq ?` (char-after end)))
(cons (- start 1) (+ end 1))
(cons start end)))))))

(defun haskell-ident-pos-at-point ()
"Return the span of the identifier under point, or nil if none found.
Expand Down Expand Up @@ -536,7 +535,8 @@ May return a qualified name."
(looking-at "[[:upper:]]"))
(setq start (point)))
;; This is it.
(cons start end)))))
(unless (= start end)
(cons start end))))))

(defun haskell-delete-indentation (&optional arg)
"Like `delete-indentation' but ignoring Bird-style \">\"."
Expand Down
8 changes: 4 additions & 4 deletions haskell.el
Original file line number Diff line number Diff line change
Expand Up @@ -299,11 +299,11 @@
(insert (cdr mapping)))
(insert module)))
(haskell-mode-format-imports)))
((not (string= "" (save-excursion (forward-char -1) (haskell-ident-at-point))))
(t
(let ((ident (save-excursion (forward-char -1) (haskell-ident-at-point))))
(insert " ")
(haskell-process-do-try-info ident)))
(t (insert " ")))))
(when ident
(haskell-process-do-try-info ident)))))))

;;;###autoload
(defun haskell-mode-jump-to-tag (&optional next-p)
Expand All @@ -312,7 +312,7 @@
(let ((ident (haskell-ident-at-point))
(tags-file-name (haskell-session-tags-filename (haskell-session)))
(tags-revert-without-query t))
(when (not (string= "" (haskell-string-trim ident)))
(when (and ident (not (string= "" (haskell-string-trim ident))))
(cond ((file-exists-p tags-file-name)
(find-tag ident next-p))
(t (haskell-process-generate-tags ident))))))
Expand Down
10 changes: 5 additions & 5 deletions inf-haskell.el
Original file line number Diff line number Diff line change
Expand Up @@ -490,7 +490,7 @@ in the buffer. This can be done interactively with the \\[universal-argument] p
The returned info is cached for reuse by `haskell-doc-mode'."
(interactive
(let ((sym (haskell-ident-at-point)))
(list (read-string (if (> (length sym) 0)
(list (read-string (if sym
(format "Show type of (default %s): " sym)
"Show type of: ")
nil nil sym)
Expand Down Expand Up @@ -526,7 +526,7 @@ The returned info is cached for reuse by `haskell-doc-mode'."
"Query the haskell process for the kind of the given expression."
(interactive
(let ((type (haskell-ident-at-point)))
(list (read-string (if (> (length type) 0)
(list (read-string (if type
(format "Show kind of (default %s): " type)
"Show kind of: ")
nil nil type))))
Expand All @@ -539,7 +539,7 @@ The returned info is cached for reuse by `haskell-doc-mode'."
"Query the haskell process for the info of the given expression."
(interactive
(let ((sym (haskell-ident-at-point)))
(list (read-string (if (> (length sym) 0)
(list (read-string (if sym
(format "Show info of (default %s): " sym)
"Show info of: ")
nil nil sym))))
Expand All @@ -552,7 +552,7 @@ The returned info is cached for reuse by `haskell-doc-mode'."
"Attempt to locate and jump to the definition of the given expression."
(interactive
(let ((sym (haskell-ident-at-point)))
(list (read-string (if (> (length sym) 0)
(list (read-string (if sym
(format "Find definition of (default %s): " sym)
"Find definition of: ")
nil nil sym))))
Expand Down Expand Up @@ -771,7 +771,7 @@ see if this is newer than `haskell-package-conf-file' every time
we load it."
(interactive
(let ((sym (haskell-ident-at-point)))
(list (read-string (if (> (length sym) 0)
(list (read-string (if sym
(format "Find documentation of (default %s): " sym)
"Find documentation of: ")
nil nil sym))))
Expand Down
Loading