Skip to content

Commit b2eeea0

Browse files
authored
Merge pull request #1463 from jfaz1/recent
Add recent file history
2 parents 86d3840 + a893d2e commit b2eeea0

File tree

2 files changed

+67
-17
lines changed

2 files changed

+67
-17
lines changed

src/commands/file.lisp

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,10 @@
2020
:change-directory
2121
:current-directory
2222
:prompt-for-files-recursively
23-
:format-current-buffer)
23+
:format-current-buffer
24+
:file-history
25+
:find-history-file
26+
:*file-history-limit*)
2427
#+sbcl
2528
(:lock t))
2629
(in-package :lem-core/commands/file)
@@ -29,6 +32,7 @@
2932
(define-key *global-keymap* "C-x C-r" 'read-file)
3033
(define-key *global-keymap* "C-x C-s" 'save-current-buffer)
3134
(define-key *global-keymap* "C-x C-w" 'write-file)
35+
(define-key *global-keymap* "C-x C-h" 'find-history-file)
3236
(define-key *global-keymap* "C-x Tab" 'insert-file)
3337
(define-key *global-keymap* "C-x s" 'save-some-buffers)
3438

@@ -391,3 +395,40 @@ With prefix argument INSERT, insert the directory of the active buffer at point.
391395
392396
Supported modes include: c-mode with clang-format, go-mode with gofmt, js-mode and json-mode with prettier, and lisp-mode. Additionally rust-mode uses rustfmt."
393397
(format-buffer))
398+
399+
(defvar *files-history*)
400+
(defvar *file-history-limit* 10
401+
"The maximum number of files to keep in the file history.")
402+
403+
(defun file-history ()
404+
"Return or create the files' history struct.
405+
The history file is saved on (lem-home)/history/files"
406+
(unless (boundp '*files-history*)
407+
(let* ((pathname (merge-pathnames "history/files" (lem-home)))
408+
(history (lem/common/history:make-history :pathname pathname :limit *file-history-limit*)))
409+
(setf *files-history* history)))
410+
*files-history*)
411+
412+
(defun add-to-file-history (buffer)
413+
"Add the buffer's filename to the file history."
414+
(let ((filename (buffer-filename buffer)))
415+
(when filename
416+
(lem/common/history:add-history (file-history)
417+
(namestring filename)
418+
:allow-duplicates nil)
419+
(lem/common/history:save-file (file-history)))))
420+
421+
(add-hook *find-file-hook* 'add-to-file-history)
422+
423+
(define-command find-history-file () ()
424+
"Prompt for a file from the file history and open it."
425+
(let* ((history (file-history))
426+
(candidates (lem/common/history:history-data-list history)))
427+
(if candidates
428+
(let ((filename (prompt-for-string
429+
"File: "
430+
:completion-function (lambda (x) (completion-strings x (reverse candidates)))
431+
:test-function (lambda (name) (member name candidates :test #'string=)))))
432+
(when filename
433+
(find-file filename)))
434+
(editor-error "No file history."))))

src/common/history.lisp

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@
2020
pathname
2121
data
2222
index
23-
edit-string)
23+
edit-string
24+
limit)
2425

2526
(defun history-data-list (history)
2627
"Return the history data as a list (and not a vector)."
@@ -31,15 +32,16 @@
3132
(and (not (equal input last-input))
3233
(not (equal input ""))))
3334

34-
(defun make-history (&key pathname)
35+
(defun make-history (&key pathname limit)
3536
(let* ((initial-contents
3637
(when (and pathname (uiop:file-exists-p pathname))
3738
(uiop:read-file-form pathname)))
3839
(num-contents (length initial-contents)))
3940
(%make-history
4041
:pathname pathname
4142
:data (make-array num-contents :fill-pointer num-contents :adjustable t :initial-contents initial-contents)
42-
:index num-contents)))
43+
:index num-contents
44+
:limit limit)))
4345

4446
(defun save-file (history)
4547
(when (history-pathname history)
@@ -59,19 +61,26 @@
5961
"Add this input to the history.
6062
6163
Don't add the same input as the previous one.
62-
If allow-duplicates is non t, don't add duplicates at all."
63-
(cond
64-
((not allow-duplicates)
65-
(when (not (find input (history-data history) :test test))
66-
(vector-push-extend input (history-data history))))
67-
((require-additions-to-history-p input
68-
(last-history history))
69-
(vector-push-extend input (history-data history)))
70-
(t
71-
nil))
72-
73-
(setf (history-index history)
74-
(length (history-data history)))
64+
If allow-duplicates is non t, don't add duplicates at all.
65+
If limit is set, overwrite oldest entry when reached."
66+
(when (or allow-duplicates
67+
(not (find input (history-data history) :test test)))
68+
(when (require-additions-to-history-p input (last-history history))
69+
(let ((limit (history-limit history)))
70+
(cond
71+
((and limit (>= (length (history-data history)) limit))
72+
;; Shift by 1, overwriting the oldest
73+
(replace (history-data history)
74+
(history-data history)
75+
:start1 0
76+
:start2 1
77+
:end2 limit)
78+
(setf (aref (history-data history) (1- limit)) input))
79+
(t
80+
;; Add new element normally
81+
(vector-push-extend input (history-data history)))))
82+
(setf (history-index history)
83+
(length (history-data history)))))
7584
input)
7685

7786
(defun remove-history (history input)

0 commit comments

Comments
 (0)