diff --git a/cider-debug.el b/cider-debug.el index 32c0f5cb4..649fbb44e 100644 --- a/cider-debug.el +++ b/cider-debug.el @@ -29,24 +29,31 @@ (require 'cider-interaction) (require 'dash) + +;;; Customization +(defgroup cider-debug nil + "Presentation and behaviour of the cider debugger." + :prefix "cider-debug-" + :package-version '(cider-debug . "0.10.0")) + (defface cider-result-overlay-face '((((class color) (background light)) :foreground "firebrick") (((class color) (background dark)) :foreground "orange red")) "Face used to display result of debug step at point." - :group 'cider + :group 'cider-debug :package-version "0.9.1") (defface cider-debug-code-overlay-face '((((class color) (background light)) :background "grey80") (((class color) (background dark)) :background "grey30")) "Face used to mark code being debugged." - :group 'cider + :group 'cider-debug :package-version "0.9.1") (defface cider-debug-prompt-face '((t :underline t :inherit font-lock-builtin-face)) "Face used to mark code being debugged." - :group 'cider + :group 'cider-debug :package-version "0.10.0") (defcustom cider-debug-use-overlays 'end-of-line @@ -57,7 +64,7 @@ Possible values are inline, end-of-line, or nil." :type '(choice (const :tag "End of line" end-of-line) (const :tag "Inline" inline) (const :tag "No overlays" nil)) - :group 'cider + :group 'cider-debug :package-version "0.9.1") @@ -103,7 +110,7 @@ is displayed at point." #'cider--make-overlay (line-beginning-position) (if (eq where 'inline) (point) (line-end-position)) - 'debug-result + type 'after-string (propertize (concat (propertize " " 'cursor 1000) cider-interactive-eval-result-prefix @@ -126,7 +133,7 @@ is displayed at point." (cider--make-result-overlay value 'debug-result cider-debug-use-overlays 'before-string cider--fringe-arrow-string) ;; Code - (cider--make-overlay (save-excursion (forward-sexp -1) (point)) + (cider--make-overlay (save-excursion (clojure-backward-logical-sexp 1) (point)) (point) 'debug-code 'face 'cider-debug-code-overlay-face ;; Higher priority than `show-paren'. @@ -146,7 +153,7 @@ Set by `cider--turn-on-debug-mode'.") "If non-nil, local variables are displayed while debugging. Can be toggled at any time with `\\[cider-debug-toggle-locals]'." :type 'boolean - :group 'cider + :group 'cider-debug :package-version '(cider . "0.10.0")) (defun cider--debug-format-locals-list (locals) @@ -274,20 +281,6 @@ ID is the id of the message that instrumented CODE." (set-buffer-modified-p nil)))) (switch-to-buffer buffer-name))) -(defun cider--forward-sexp (n) - "Move forward N logical sexps. -This will skip over sexps that don't represent objects, such as ^hints and -#reader.macros." - (while (> n 0) - ;; Non-logical sexps. - (while (progn (forward-sexp 1) - (forward-sexp -1) - (looking-at-p "\\^\\|#[[:alpha:]]")) - (forward-sexp 1)) - ;; The actual sexp - (forward-sexp 1) - (setq n (1- n)))) - (defun cider--debug-goto-keyval (key) "Find KEY in current sexp or return nil." (-when-let (limit (ignore-errors (save-excursion (up-list) (point)))) @@ -311,12 +304,12 @@ sexp." ;; String coordinates are map keys. (if (stringp next) (cider--debug-goto-keyval next) - (cider--forward-sexp next))) + (clojure-forward-logical-sexp (pop coordinates)))) ;; If that extra pop was the last coordinate, this represents the ;; entire #(...), so we should move back out. (backward-up-list))) ;; Place point at the end of instrumented sexp. - (cider--forward-sexp 1)) + (clojure-forward-logical-sexp 1)) ;; Avoid throwing actual errors, since this happens on every breakpoint. (error (message "Can't find instrumented sexp, did you edit the source?")))) diff --git a/cider-doc.el b/cider-doc.el index b2c833e9b..dff731041 100644 --- a/cider-doc.el +++ b/cider-doc.el @@ -175,10 +175,15 @@ "Open the source for the current symbol, if available." (interactive) (if cider-docview-file - (let ((buffer (and cider-docview-file - (not (cider--tooling-file-p cider-docview-file)) - (cider-find-file cider-docview-file)))) - (cider-jump-to buffer (cons cider-docview-line nil) nil)) + (-if-let (buffer (and (not (cider--tooling-file-p cider-docview-file)) + (cider-find-file cider-docview-file))) + (cider-jump-to buffer (if cider-docview-line + (cons cider-docview-line nil) + cider-docview-symbol) + nil) + (user-error + (substitute-command-keys + "Can't find the source because it wasn't defined with `cider-eval-buffer'"))) (error "No source location for %s" cider-docview-symbol))) (defun cider-docview-grimoire () diff --git a/cider-interaction.el b/cider-interaction.el index 116ccbc8b..11f44153b 100644 --- a/cider-interaction.el +++ b/cider-interaction.el @@ -631,7 +631,7 @@ When invoked with a prefix ARG the command doesn't prompt for confirmation." "Return the sexp preceding the point." (buffer-substring-no-properties (save-excursion - (backward-sexp) + (clojure-backward-logical-sexp 1) (point)) (point))) @@ -773,9 +773,12 @@ not found." (defun cider-jump-to (buffer &optional pos other-window) "Push current point onto marker ring, and jump to BUFFER and POS. -POS can be either a numeric position in BUFFER or a cons (LINE . COLUMN) -where COLUMN can be nil. If OTHER-WINDOW is non-nil don't reuse current -window." +POS can be either a number, a cons, or a symbol. +If a number, it is the character position (the point). +If a cons, it specifies the position as (LINE . COLUMN). COLUMN can be nil. +If a symbol, `cider-jump-to' searches for something that looks like the +symbol's definition in the file. +If OTHER-WINDOW is non-nil don't reuse current window." (ring-insert find-tag-marker-ring (point-marker)) (if other-window (pop-to-buffer buffer) @@ -785,14 +788,33 @@ window." (widen) (goto-char (point-min)) (cider-mode +1) - (if (consp pos) - (progn - (forward-line (1- (or (car pos) 1))) - (if (cdr pos) - (move-to-column (cdr pos)) - (back-to-indentation))) - (when pos - (goto-char pos))))) + (cond + ;; Line-column specification. + ((consp pos) + (forward-line (1- (or (car pos) 1))) + (if (cdr pos) + (move-to-column (cdr pos)) + (back-to-indentation))) + ;; Point specification. + ((numberp pos) + (goto-char pos)) + ;; Symbol or string. + (pos + ;; Try to find (def full-name ...). + (if (or (save-excursion + (search-forward-regexp (format "(def.*\\s-\\(%s\\)" (regexp-quote pos)) + nil 'noerror)) + (let ((name (replace-regexp-in-string ".*/" "" pos))) + ;; Try to find (def name ...). + (or (save-excursion + (search-forward-regexp (format "(def.*\\s-\\(%s\\)" (regexp-quote name)) + nil 'noerror)) + ;; Last resort, just find the first occurrence of `name'. + (save-excursion + (search-forward name nil 'noerror))))) + (goto-char (match-beginning 0)) + (message "Can't find %s in %s" pos (buffer-file-name)))) + (t nil)))) (defun cider-find-dwim-other-window (symbol-file) "Jump to SYMBOL-FILE at point, place results in other window." @@ -905,11 +927,12 @@ INFO object is returned by `cider-var-info' or `cider-member-info'. OTHER-WINDOW is passed to `cider-jamp-to'." (let* ((line (nrepl-dict-get info "line")) (file (nrepl-dict-get info "file")) + (name (nrepl-dict-get info "name")) (buffer (and file (not (cider--tooling-file-p file)) (cider-find-file file)))) (if buffer - (cider-jump-to buffer (cons line nil) other-window) + (cider-jump-to buffer (if line (cons line nil) name) other-window) (error "No source location")))) (defun cider--find-var-other-window (var &optional line) @@ -1692,7 +1715,7 @@ If invoked with a PREFIX argument, print the result in the current buffer." (interactive "P") (cider-interactive-eval (cider-last-sexp) (when prefix (cider-eval-print-handler)) - (save-excursion (backward-sexp 1) (point)))) + (save-excursion (clojure-backward-logical-sexp 1) (point)))) (defun cider-eval-last-sexp-and-replace () "Evaluate the expression preceding point and replace it with its result." diff --git a/cider-macroexpansion.el b/cider-macroexpansion.el index 3bd748d3c..d1de8001b 100644 --- a/cider-macroexpansion.el +++ b/cider-macroexpansion.el @@ -101,7 +101,7 @@ This variable specifies both what was expanded and the expander.") "Substitute the form preceding point with its macroexpansion using EXPANDER." (interactive) (let* ((expansion (cider-sync-request:macroexpand expander (cider-last-sexp))) - (bounds (cons (save-excursion (backward-sexp) (point)) (point)))) + (bounds (cons (save-excursion (clojure-backward-logical-sexp 1) (point)) (point)))) (cider-redraw-macroexpansion-buffer expansion (current-buffer) (car bounds) (cdr bounds)))) diff --git a/cider-stacktrace.el b/cider-stacktrace.el index debf6bba3..60263ed1e 100644 --- a/cider-stacktrace.el +++ b/cider-stacktrace.el @@ -422,12 +422,17 @@ it wraps to 0." (info (or (and var (cider-var-info var)) (and class method (cider-member-info class method)) (nrepl-dict))) - ;; stacktrace returns more accurate line numbers - (info (nrepl-dict-put info "line" (button-get button 'line))) + ;; Stacktrace returns more accurate line numbers, but if the function's + ;; line was unreliable, then so is the stacktrace by the same amount. + ;; Set `line-shift' to the number of lines from the beginning of defn. + (line-shift (- (or (button-get button 'line) 0) + (or (nrepl-dict-get info "line") 1))) ;; give priority to `info` files as `info` returns full paths. (info (nrepl-dict-put info "file" (or (nrepl-dict-get info "file") (button-get button 'file))))) - (cider--jump-to-loc-from-info info t))) + (cider--jump-to-loc-from-info info t) + (forward-line line-shift) + (back-to-indentation))) (defun cider-stacktrace-jump (&optional arg) "Like `cider-find-var', but uses the stack frame source at point, if available." diff --git a/cider.el b/cider.el index 1725bd54a..be3f7d4cd 100644 --- a/cider.el +++ b/cider.el @@ -11,7 +11,7 @@ ;; Maintainer: Bozhidar Batsov ;; URL: http://www.github.com/clojure-emacs/cider ;; Version: 0.10.0-cvs -;; Package-Requires: ((clojure-mode "4.0.0") (dash "2.4.1") (pkg-info "0.4") (emacs "24.3") (queue "0.1.1")) +;; Package-Requires: ((clojure-mode "4.2.0") (dash "2.4.1") (pkg-info "0.4") (emacs "24.3") (queue "0.1.1")) ;; Keywords: languages, clojure, cider ;; This program is free software: you can redistribute it and/or modify