Skip to content
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
6 changes: 0 additions & 6 deletions .github/workflows/CI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,6 @@ jobs:
fail-fast: false
matrix:
emacs_version:
- 25.1
- 25.2
- 25.3
- 26.1
- 26.2
- 26.3
- 27.1
- 27.2
- 28.1
Expand Down
12 changes: 11 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ It is recommended that you use this minor mode with [julia-mode](https://github.

## Installation and loading

**Please make sure you have at least Emacs 25**. The `term` code changed a bit since Emacs 24, and the package does not support that and earlier versions. For example, Ubuntu has had Emacs 25 since 18.04LTS.
**Please make sure you have at least Emacs 27.1**, as the package does not support earlier versions.

Place this in your **Emacs initialization files** (eg `.emacs`):
```emacs-lisp
Expand Down Expand Up @@ -181,6 +181,16 @@ Cygwin may require some rewriting of paths for `include` to work. After loading
```
as a reasonable default, or write custom rules for `julia-repl-path-rewrites`.

## Clickable error locations

Error locations in the inferior buffer should be clickable, implemented with `compilation-shell-minor-mode`.

The error printing syntax changed over time, and legacy forms are not included, they are not needed if you are using Julia 1.6 or later. To get them back, use
```emacs-lisp
(setq julia-repl-compilation-location-legacy t)
```
If you find that a Julia error (warning, info, etc) message location is not clickable in Emacs, please open an issue.

## Limitations

See the [issues](https://github.com/tpapp/julia-repl/issues).
Expand Down
30 changes: 26 additions & 4 deletions julia-repl-tests.el
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
;;; julia-repl-tests.el --- -*- lexical-binding: t; -*-

Check warning on line 1 in julia-repl-tests.el

View workflow job for this annotation

GitHub Actions / check (snapshot, false)

Possibly using local file with different prefix `julia-repl.el'

;; Copyright (C) 2019 Tamas Papp
;; Author: Tamas Papp <[email protected]>
Expand Down Expand Up @@ -40,7 +40,29 @@

(ert-deftest julia-repl-location-rx ()
(let ((str "@ Foo ~/code/Foo/src/Foo.jl:100"))
(string-match julia-repl--rx-at str)
(equal (match-string 1 str) "Foo")
(equal (match-string 2 str) "~/code/Foo/src/Foo.jl")
(equal (match-string 3 str) "100")))
(should (string-match julia-repl--CR-at str))
(should (equal (match-string 1 str) "Foo"))
(should (equal (match-string 2 str) "~/code/Foo/src/Foo.jl"))
(should (equal (match-string 3 str) "100"))))

(ert-deftest julia-repl-error-locations ()
;; module name, absolute path
(should
(equal
(cdr (s-match julia-repl--CR-at " @ Main.MyModule /tmp/tmp.jl:3"))
'("Main.MyModule" "/tmp/tmp.jl" "3")))
;; tilde in path
(should
(equal
(cdr (s-match julia-repl--CR-at " @ Foo ~/tmp.jl:99"))
'("Foo" "~/tmp.jl" "99")))
;; underscore
(should
(equal
(cdr (s-match julia-repl--CR-at " @ Main.test_loops ~/tmp.jl:7"))
'("Main.test_loops" "~/tmp.jl" "7")))
;; no module
(should
(equal
(cdr (s-match julia-repl--CR-at " @ ~/tmp.jl:7"))
'(nil "~/tmp.jl" "7"))))
74 changes: 47 additions & 27 deletions julia-repl.el
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
;; Copyright (C) 2016–2024 Tamas K. Papp
;; Author: Tamas Papp <[email protected]>
;; Keywords: languages
;; Version: 1.4.0
;; Package-Requires: ((emacs "25.1")(s "1.12"))
;; Version: 1.5.0
;; Package-Requires: ((emacs "27.1")(s "1.12"))
;; URL: https://github.com/tpapp/julia-repl

;;; Usage:
Expand Down Expand Up @@ -47,7 +47,6 @@
(require 'seq)
(require 'subr-x)


;;
;; customizations
;;
Expand Down Expand Up @@ -266,30 +265,40 @@ When PASTE-P, “bracketed paste” mode will be used. When RET-P, terminate wit
(when ret-p
(eat-term-send-string eat-terminal "\^M")))))

(defconst julia-repl--CR-at
(rx "@" space
(? (group (one-or-more (or (any "._") alnum))) space) ; group 1: module name
(group (+ (not (any space ">" "<" "(" ")" "\t" "\n" "," "'" "\"" ";" ":")))) ; group 2: path
":"
(group (+ num)) ; group 3: line number
)
"Matches “@ Foo ~/code/Foo/src/Foo.jl:100”. This is what is used in Julia >= 1.6")

(defconst julia-repl--CR-filename
(rx (one-or-more (not (any " ><()\t\n,'\";:"))))
"An attempt to match filenames in error, info, and warning messages printed by Julia.")

(defconst julia-repl--CR-load-error
(rx
"while loading "
(group (regexp julia-repl--CR-filename))
", in expression starting on line "
(group (one-or-more digit)))
"Compilation regexp matching “while loading /tmp/Foo.jl, in expression starting on line 2”.")

(defconst julia-repl--CR-around
(rx
(or "around" "at" "Revise")
" "
(group (regexp julia-repl--CR-filename))
":"
(group (one-or-more digit)))
"Compilation regexp matching “around /tmp/Foo.jl:2”, also starting with “at or “Revise”")

;;
;; global variables
;;

(defconst julia-repl--rx-at
(rx (seq "@" (syntax whitespace)
(? (group (+ alnum)) space) ; package name
(group (+ (not (any space ">" "<" "(" ")" "\t" "\n" "," "'" "\"" ";" ":")))) ; path
":" (group (+ num)))) ; line
"Matches “@ Foo ~/code/Foo/src/Foo.jl:100”")

(defvar julia-repl--compilation-regexp-alist
`(;; matches "while loading /tmp/Foo.jl, in expression starting on line 2"
(julia-load-error . ("while loading \\([^ ><()\t\n,'\";:]+\\), in expression starting on line \\([0-9]+\\)" 1 2))
;; matches "around /tmp/Foo.jl:2", also starting with "at" or "Revise"
(julia-loc . ("\\(around\\|at\\|Revise\\) \\([^ ><()\t\n,'\";:]+\\):\\([0-9]+\\)" 2 3))
;; matches "omitting file /tmp/Foo.jl due to parsing error near line 2", from Revise.parse_source!
(julia-warn-revise . ("omitting file \\([^ ><()\t\n,'\";:]+\\) due to parsing error near line \\([0-9]+\\)" 1 2))
(julia-error-at . (,julia-repl--rx-at 2 3))
)
"Specifications for highlighting error locations.

Uses function ‘compilation-shell-minor-mode’.")

(defvar julia-repl--terminal-backend
(make-julia-repl--buffer-ansi-term)
"Terminal backend, for internal use. Set using `julia-repl-set-terminal-backend'.")
Expand Down Expand Up @@ -374,6 +383,20 @@ generate a buffer name.")
Valid values are NIL or a string. These take effect the next time
a new Julia process is started.")

(defvar julia-repl-compilation-location-legacy nil
"Whether to include recognize various legacy error messages in compilation output.
Mainly useful if you are using Julia <1.6.")

(defun julia-repl--compilation-regexp-alist ()
"Return an alist suitable for use in `compilation-error-regexp-alist' for recognizing Julia error locations.

Cf `julia-repl-compilation-location-legacy'."
(let ((regexp-alist `((,julia-repl--CR-at 2 3))))
(if julia-repl-compilation-location-legacy
(cons regexp-alist
`((,julia-repl--CR-load-error 1 2) (,julia-repl--CR-around 1 2)))
regexp-alist)))

;;
;; REPL buffer creation and setup
;;
Expand Down Expand Up @@ -446,10 +469,7 @@ prevent further attempts."

BASEDIR is used for resolving relative paths."
(with-current-buffer inferior-buffer
(setq-local compilation-error-regexp-alist-alist
julia-repl--compilation-regexp-alist)
(setq-local compilation-error-regexp-alist
(mapcar #'car compilation-error-regexp-alist-alist))
(setq-local compilation-error-regexp-alist (julia-repl--compilation-regexp-alist))
(when basedir
(setq-local compilation-search-path (list basedir)))
(compilation-shell-minor-mode 1)))
Expand Down
Loading