greghendershott / racket-mode

Emacs major and minor modes for Racket: edit, REPL, check-syntax, debug, profile, packages, and more.
https://www.racket-mode.com/
GNU General Public License v3.0
682 stars 93 forks source link

Error message path in REPL buffer can not be clicked when current path is too long #604

Closed chansey97 closed 2 years ago

chansey97 commented 2 years ago

I have two .rkt files in my working directory:

E:\work-pl\racket\code\racket-mode-tests\xxxxxxxxxxxxx\xxxxxxxxxxxxx\xxxxxxxxxxxxx\xxxxxxxxxxxxx\xxxxxxxxxxxxx\test-long-path.rkt
E:\work-pl\racket\code\racket-mode-tests\xxxxxxxxxxxxx\xxxxxxxxxxxxx\xxxxxxxxxxxxx\xxxxxxxxxxxxx\xxxxxxxxxxxxx\main.rkt

The two files' contain:

test-long-path.rkt

#lang racket
(provide (all-defined-out))

(define (foo)
  (bar))

main.rkt

#lang racket
(require "./test-long-path.rkt")

(foo)

Obviously, executing main.rkt will report an error, because bar in test-long-path.rkt is unbound.

So in main.rkt, executing M-x (racket-run), Racket REPL buffer will report:

; 
; Welcome to Racket v8.0 [bc].
; 
> 
; ...de-tests\xxxxxxxxxxxxx\xxxxxxxxxxxxx\xxxxxxxxxxxxx\xxxxxxxxxxxxx\xxxxxxxxxxxxx\test-long-path.rkt:5:3: bar: unbound identifier
;   in: bar
> 

That is nice. However, as you see the error message path is not complete:

; ...de-tests\xxxxxxxxxxxxx\xxxxxxxxxxxxx\xxxxxxxxxxxxx\xxxxxxxxxxxxx\xxxxxxxxxxxxx\test-long-path.rkt:5:3: bar: 

instead of

E:\work-pl\racket\code\racket-mode-tests\xxxxxxxxxxxxx\xxxxxxxxxxxxx\xxxxxxxxxxxxx\xxxxxxxxxxxxx\xxxxxxxxxxxxx\test-long-path.rkt

So when I click that link my Emacs cannot successfully open the file. Currently projectile will open a dialogue and I have to select a file manually.

Note that if the path is not too long, for example, if my working directory is E:\work-pl\racket\code\racket-mode-tests, then no problem.

((alist-get 'racket-mode package-alist))
((emacs-version "27.2")
 (system-type windows-nt)
 (x-gtk-use-system-tooltips UNDEFINED)
 (major-mode racket-mode)
 (racket--el-source-dir "c:/Users/Chansey/AppData/Roaming/.emacs.d/site-lisp/racket-mode-20220216.1917/")
 (racket--rkt-source-dir "c:/Users/Chansey/AppData/Roaming/.emacs.d/site-lisp/racket-mode-20220216.1917/racket/")
 (racket-program "C:\\Program Files\\Racket\\Racket.exe")
 (racket-command-timeout 10)
 (racket-path-from-emacs-to-racket-function UNDEFINED)
 (racket-path-from-racket-to-emacs-function UNDEFINED)
 (racket-browse-url-function racket-browse-url-using-temporary-file)
 (racket-documentation-search-location "https://docs.racket-lang.org/search/index.html?q=%s")
 (racket-xp-after-change-refresh-delay 1)
 (racket-xp-mode-lighter
  (:eval
   (racket--xp-mode-lighter)))
 (racket-xp-highlight-unused-regexp "^[^_]")
 (racket-repl-buffer-name-function nil)
 (racket-submodules-to-run
  ((test)
   (main)))
 (racket-memory-limit 2048)
 (racket-error-context medium)
 (racket-repl-history-directory "~/.emacs.d/racket-mode/")
 (racket-history-filter-regexp "\\`\\s *\\'")
 (racket-images-inline t)
 (racket-imagemagick-props nil)
 (racket-images-keep-last 100)
 (racket-images-system-viewer "display")
 (racket-pretty-print t)
 (racket-use-repl-submit-predicate nil)
 (racket-pretty-print t)
 (racket-indent-curly-as-sequence t)
 (racket-indent-sequence-depth 0)
 (racket-pretty-lambda nil)
 (racket-smart-open-bracket-enable nil)
 (racket-module-forms "\\s(\\(?:module[*+]?\\|library\\)")
 (racket-logger-config
  ((cm-accomplice . warning)
   (GC . info)
   (module-prefetch . warning)
   (optimizer . info)
   (racket/contract . error)
   (sequence-specialization . info)
   (* . fatal)))
 (racket-show-functions
  (racket-show-pseudo-tooltip)))
(enabled-minor-modes
 (auto-composition-mode)
 (auto-compression-mode)
 (auto-encryption-mode)
 (auto-fill-mode)
 (auto-save-mode)
 (back-button-mode)
 (blink-cursor-mode)
 (cl-old-struct-compat-mode)
 (column-number-mode)
 (company-mode)
 (company-quickhelp-local-mode)
 (company-quickhelp-mode)
 (cua-mode)
 (delete-selection-mode)
 (desktop-save-mode)
 (electric-indent-mode)
 (file-name-shadow-mode)
 (font-lock-mode)
 (global-auto-revert-mode)
 (global-company-mode)
 (global-eldoc-mode)
 (global-font-lock-mode)
 (global-hl-line-mode)
 (global-linum-mode)
 (global-page-break-lines-mode)
 (global-symbol-overlay-mode)
 (global-undo-tree-mode)
 (goto-address-prog-mode)
 (hs-minor-mode)
 (ivy-mode)
 (line-number-mode)
 (linum-mode)
 (menu-bar-mode)
 (mode-icons-mode)
 (mouse-wheel-mode)
 (paredit-mode)
 (popwin-mode)
 (projectile-mode)
 (racket-xp-mode)
 (recentf-mode)
 (save-place-mode)
 (savehist-mode)
 (semantic-minor-modes-format)
 (shell-dirtrack-mode)
 (show-paren-mode)
 (symbol-overlay-mode)
 (tabbar-mode)
 (tabbar-mwheel-mode)
 (tool-bar-mode)
 (tooltip-mode)
 (transient-mark-mode)
 (treemacs-filewatch-mode)
 (treemacs-fringe-indicator-mode)
 (undo-tree-mode)
 (yas-global-mode)
 (yas-minor-mode))
(disabled-minor-modes
 (abbrev-mode)
 (ace-window-display-mode)
 (ace-window-mode)
 (auto-fill-function)
 (auto-revert-mode)
 (auto-revert-tail-mode)
 (auto-save-visited-mode)
 (avy-linum-mode)
 (buffer-face-mode)
 (buffer-read-only)
 (company-search-mode)
 (compilation-minor-mode)
 (compilation-shell-minor-mode)
 (completion-in-region-mode)
 (counsel-mode)
 (defining-kbd-macro)
 (dired-hide-details-mode)
 (drag-stuff-global-mode)
 (drag-stuff-mode)
 (eldoc-mode)
 (electric-layout-mode)
 (electric-quote-mode)
 (flymake-mode)
 (global-prettify-symbols-mode)
 (global-semantic-highlight-edits-mode)
 (global-semantic-highlight-func-mode)
 (global-semantic-show-parser-state-mode)
 (global-semantic-show-unmatched-syntax-mode)
 (global-semantic-stickyfunc-mode)
 (global-visual-line-mode)
 (goto-address-mode)
 (haskell-indentation-mode)
 (hl-line-mode)
 (horizontal-scroll-bar-mode)
 (ibuffer-auto-mode)
 (isearch-mode)
 (jit-lock-debug-mode)
 (next-error-follow-minor-mode)
 (outline-minor-mode)
 (overwrite-mode)
 (page-break-lines-mode)
 (paragraph-indent-minor-mode)
 (prettify-symbols-mode)
 (racket-smart-open-bracket-mode)
 (semantic-highlight-edits-mode)
 (semantic-highlight-func-mode)
 (semantic-mode)
 (semantic-show-parser-state-mode)
 (semantic-show-unmatched-syntax-mode)
 (semantic-stickyfunc-mode)
 (sh-electric-here-document-mode)
 (show-smartparens-global-mode)
 (show-smartparens-mode)
 (size-indication-mode)
 (smartparens-global-mode)
 (smartparens-global-strict-mode)
 (smartparens-mode)
 (smartparens-strict-mode)
 (sql-upcase-mode)
 (tab-bar-history-mode)
 (tab-bar-mode)
 (tabbar-local-mode)
 (temp-buffer-resize-mode)
 (text-scale-mode)
 (treemacs-follow-mode)
 (treemacs-git-mode)
 (treemacs-tag-follow-mode)
 (undo-tree-visualizer-selection-mode)
 (unify-8859-on-decoding-mode)
 (unify-8859-on-encoding-mode)
 (url-handler-mode)
 (use-hard-newlines)
 (view-mode)
 (visible-mode)
 (visual-line-mode)
 (window-divider-mode)
 (xref-etags-mode))
greghendershott commented 2 years ago

What if you use command-line Racket:

> racket.exe E:\work-pl\racket\code\racket-mode-tests\xxxxxxxxxxxxx\xxxxxxxxxxxxx\xxxxxxxxxxxxx\xxxxxxxxxxxxx\xxxxxxxxxxxxx\main.rkt

Do you see the same truncated path in the error message?

Racket Mode already tries pretty hard to avoid "lossy" paths in error messages, for example trying to "undo" things like <pkgs>/path/to/file.rkt, trying to change relative paths into absolute/complete paths, and so on. There a few tactics like this in error.rkt.

But the paths starting with ... I think are elided in a way where it's probably impossible to recover the information?

chansey97 commented 2 years ago

What if you use command-line Racket:

It returned the truncated path in the error message:

C:\Users\Chansey>racket.exe E:\work-pl\racket\code\racket-mode-tests\xxxxxxxxxxxxx\xxxxxxxxxxxxx\xxxxxxxxxxxxx\xxxxxxxxxxxxx\xxxxxxxxxxxxx\main.rkt
...de-tests\xxxxxxxxxxxxx\xxxxxxxxxxxxx\xxxxxxxxxxxxx\xxxxxxxxxxxxx\xxxxxxxxxxxxx\test-long-path.rkt:5:3: bar: unbound identifier
  in: bar
  location...:
   ...de-tests\xxxxxxxxxxxxx\xxxxxxxxxxxxx\xxxxxxxxxxxxx\xxxxxxxxxxxxx\xxxxxxxxxxxxx\test-long-path.rkt:5:3

But if I run the main.rkt in the DrRacket, it can correctly open test-long-path.rkt, although in DrRacket's REPL there is neither complete path nor truncated path, it is just a test-long-path.rkt:5:3.

greghendershott commented 2 years ago

But if I run the main.rkt in the DrRacket, it can correctly open test-long-path.rkt, although in DrRacket's REPL there is neither complete path nor truncated path, it is just a test-long-path.rkt:5:3.

That's interesting. I was leaning toward believing it's not possible for Racket Mode to handle this. But if DrR can do it, I accept the challenge to figure out how. :smile:

greghendershott commented 2 years ago

Well I'm having trouble reproducing this.

On Linux and using Racket built from source around the time of the 8.4 release, I get the full path:

; 
; Welcome to Racket v8.3.0.11 [cs].
; 
> 
; /var/tmp/test/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/other.rkt:3:15: bar: unbound identifier
;   in: bar
; Context (plain; to see better errortrace context, re-run with C-u prefix):
;   /home/greg/src/elisp/racket-mode/racket/syntax.rkt:66:0
;   /home/greg/src/elisp/racket-mode/racket/syntax.rkt:66:0
>

And the path in the REPL is working link, with a click or moving point there and pressing ENTER.

I'll take another look at this when I have a bit more time to fire up a Windows PC with Racket 8.0 BC, like you're using.

chansey97 commented 2 years ago

I have another Racket (v8.2 cs) installed in my VMWare (also windows 7). I just tried it and it is no problem. This "... path problem" may have been fixed in v8.2 or later. I may have to upgrade Racket to v8.4 bc.

chansey97 commented 2 years ago

The test results:

  1. Racket v8.4 cs has no problem.
  2. Racket v8.4 bc has still the same problem.

I created a issue in racket repo, https://github.com/racket/racket/issues/4183

greghendershott commented 2 years ago

Interesting that it's unique to BC.

As I just commented there, I doubt this will change for BC.

As to how DrR handles this when Racket Mode doesn't, maybe it is getting the srcloc from the exn, i.e. in a "structured" way, and that is not truncated even on BC. Whereas Racket Mode simply prints the error message as-is, and relies on the Emacs front end doing its usual find-next-error regexp matching.

Possibly I could have Racket Mode do the "structured" thing, and try to replace truncated paths in error message strings...? But that might create its own bugs.

greghendershott commented 2 years ago

So I just pushed a commit d805a3a to a issue-604 topic branch.

I'm not sure whether I should merge it.

Anyway if you're curious please see the commit message:

Handle truncated error message paths on Racket BC; fixes #604

On Racket BC, error messages can show truncated paths when the paths
are too long. The paths are truncated from the start, and begin with a
"..." prefix.

This doesn't work well with Emacs compilation-mode (to visit error
locations) because the path doesn't exist.

So first of all, adjust the compilation-mode regexp to ignore paths
starting with "...".

Furthermore, on BC have the back end always include the first source
location from exn:srclocs-accessor. Normally we omit this for certain
known exceptions, because it's redundant with the path already
displayed in exn-message; showing it twice is just noise. But accept
the noise on BC since the srcloc path may turn out to be the only
non-truncated, useful path.

Note: This of course is a kludge to stick with the approach of using
Emacs compilation-mode and regexp matching. I think that's acceptable
because Racket CS works fine in this regard and it's the future; also
there is value to going with the Emacs approach. Having said all that,
we could throw this all way and do something from scratch, where we
ignore exn-message for location purposes, and always use the srclocs.
This would be closer IIUC to how Dr Racket handles this.

(Note: I'm not necessarily asking you to try this. If you normally install from MELPA, and don't want to muck around with building Racket Mode from a git branch? That's OK -- don't bother! Consider this commit just me "thinking out loud".)

greghendershott commented 2 years ago

I merged this to the main branch.