Skip to content

Commit 51e59b6

Browse files
committed
Improve idris-filename-to-load to return a pair of
"source dir" and "relative file path" or "work dir" and "relative file path" when idris protocol version is greater than 1. Why: In Idris2 the files are loaded relative to work directory which is a directory containing an ".ipkg" file. Relates to: idris-lang/Idris2#3310 #627
1 parent 09de86a commit 51e59b6

File tree

3 files changed

+71
-8
lines changed

3 files changed

+71
-8
lines changed

idris-commands.el

+8-8
Original file line numberDiff line numberDiff line change
@@ -168,14 +168,14 @@
168168
(defun idris-filename-to-load ()
169169
"Compute the working directory and filename to load in Idris.
170170
Returning these as a cons."
171-
(let* ((fn (buffer-file-name))
172-
(ipkg-srcdir (idris-ipkg-find-src-dir))
173-
(srcdir (or ipkg-srcdir (file-name-directory fn))))
174-
(when (and ;; check that srcdir is prefix of filename - then load relative
175-
(> (length fn) (length srcdir))
176-
(string= (substring fn 0 (length srcdir)) srcdir))
177-
(setq fn (file-relative-name fn srcdir)))
178-
(cons srcdir fn)))
171+
(let* ((ipkg-file (car-safe (idris-find-file-upwards "ipkg")))
172+
(file-name (buffer-file-name))
173+
(work-dir (directory-file-name (idris-file-name-parent-directory (or ipkg-file file-name))))
174+
(source-dir (or (idris-ipkg-find-src-dir) work-dir)))
175+
;; TODO: Update once https://github.com/idris-lang/Idris2/issues/3310 is resolved
176+
(if (> idris-protocol-version 1)
177+
(cons work-dir (file-relative-name file-name work-dir))
178+
(cons source-dir (file-relative-name file-name source-dir)))))
179179

180180
(defun idris-load-file (&optional set-line)
181181
"Pass the current buffer's file to the inferior Idris process.

idris-compat.el

+23
Original file line numberDiff line numberDiff line change
@@ -41,5 +41,28 @@ attention to case differences."
4141
(concat (apply 'concat (mapcar 'file-name-as-directory dirs))
4242
(car (reverse components))))))
4343

44+
(if (fboundp 'file-name-parent-directoryx)
45+
(defalias 'idris-file-name-parent-directory 'file-name-parent-directory)
46+
;; Extracted from Emacs 29+ https://github.com/emacs-mirror/emacs/blob/master/lisp/files.el
47+
(defun idris-file-name-parent-directory (filename)
48+
"Return the directory name of the parent directory of FILENAME.
49+
If FILENAME is at the root of the filesystem, return nil.
50+
If FILENAME is relative, it is interpreted to be relative
51+
to `default-directory', and the result will also be relative."
52+
(let* ((expanded-filename (expand-file-name filename))
53+
(parent (file-name-directory (directory-file-name expanded-filename))))
54+
(cond
55+
;; filename is at top-level, therefore no parent
56+
((or (null parent)
57+
;; `equal' is enough, we don't need to resolve symlinks here
58+
;; with `file-equal-p', also for performance
59+
(equal parent expanded-filename))
60+
nil)
61+
;; filename is relative, return relative parent
62+
((not (file-name-absolute-p filename))
63+
(file-relative-name parent))
64+
(t
65+
parent)))))
66+
4467
(provide 'idris-compat)
4568
;;; idris-compat.el ends here

test/idris-commands-test.el

+40
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,46 @@ myReverse xs = revAcc [] xs where
313313
(delete-directory mock-directory-name t)
314314
(idris-quit))))
315315

316+
(ert-deftest idris-test-idris-filename-to-load ()
317+
"Test that `idris-filename-to-load' returns expected data structure."
318+
(cl-flet ((idris-ipkg-find-src-dir-stub () src-dir)
319+
(idris-find-file-upwards-stub (_ex) ipkg-files)
320+
(buffer-file-name-stub () "/some/path/to/idris-project/src/Component/Foo.idr"))
321+
(advice-add 'idris-ipkg-find-src-dir :override #'idris-ipkg-find-src-dir-stub)
322+
(advice-add 'idris-find-file-upwards :override #'idris-find-file-upwards-stub)
323+
(advice-add 'buffer-file-name :override #'buffer-file-name-stub)
324+
(let* ((default-directory "/some/path/to/idris-project/src/Component")
325+
ipkg-files
326+
src-dir)
327+
(unwind-protect
328+
(progn
329+
(let ((result (idris-filename-to-load)))
330+
(should (equal default-directory (car result)))
331+
(should (equal "Foo.idr" (cdr result))))
332+
333+
;; When ipkg sourcedir value is set
334+
;; Then return combination of source directory
335+
;; and relative path of the file to the source directory
336+
(let* ((src-dir "/some/path/to/idris-project/src")
337+
(result (idris-filename-to-load)))
338+
(should (equal src-dir (car result)))
339+
(should (equal "Component/Foo.idr" (cdr result))))
340+
341+
;; When ipkg sourcedir value is set
342+
;; and idris-protocol-version is greater than 1
343+
;; Then return combination of work directory
344+
;; (Directory containing the first found ipkg file)
345+
;; and relative path of the file to the work directory
346+
(let* ((ipkg-files '("/some/path/to/idris-project/baz.ipkg"))
347+
(idris-protocol-version 2)
348+
(result (idris-filename-to-load)))
349+
(should (equal "/some/path/to/idris-project" (car result)))
350+
(should (equal "src/Component/Foo.idr" (cdr result)))))
351+
352+
(advice-remove 'idris-ipkg-find-src-dir #'idris-ipkg-find-src-dir-stub)
353+
(advice-remove 'idris-find-file-upwards #'idris-find-file-upwards-stub)
354+
(advice-remove 'buffer-file-name #'buffer-file-name-stub)))))
355+
316356
;; Tests by Yasuhiko Watanabe
317357
;; https://github.com/idris-hackers/idris-mode/pull/537/files
318358
(idris-ert-command-action "test-data/CaseSplit.idr" idris-case-split idris-test-eq-buffer)

0 commit comments

Comments
 (0)