Skip to content

Commit

Permalink
Persistent history
Browse files Browse the repository at this point in the history
Added basic functions to save and load the input history in a REPL
session.  Added local variables kill-buffer-hook and kill-emacs-hook
  • Loading branch information
ska2342 committed Aug 8, 2012
1 parent 43383d2 commit c900166
Showing 1 changed file with 81 additions and 7 deletions.
88 changes: 81 additions & 7 deletions nrepl.el
Expand Up @@ -148,13 +148,6 @@ joined together.")
'nrepl-output-start
'nrepl-output-end)

(defun nrepl-add-to-input-history (string)
"Add STRING to the input history.
Empty strings and duplicates are ignored."
(unless (or (equal string "")
(equal string (car nrepl-input-history)))
(push string nrepl-input-history)))

(defun nrepl-reset-markers ()
(dolist (markname '(nrepl-output-start
nrepl-output-end
Expand Down Expand Up @@ -683,6 +676,13 @@ in a macroexpansion buffer. Prefix argument forces pretty-printed output."
(nrepl-interactive-eval (nrepl-last-expression))))

;;;;; History
(defun nrepl-add-to-input-history (string)
"Add STRING to the input history.
Empty strings and duplicates are ignored."
(unless (or (equal string "")
(equal string (car nrepl-input-history)))
(push string nrepl-input-history)))

(defun nrepl-delete-current-input ()
"Delete all text after the prompt."
(interactive)
Expand Down Expand Up @@ -726,6 +726,75 @@ DIRECTION is 'forward' or 'backward' (in the history list)."
(interactive)
(nrepl-history-replace 'forward))

;;;;;;;;;;;;;;;;;;;;;;;;
;; working on persistent hist
;; make sure to move things around later
(defvar nrepl-history-size 500)
(defvar nrepl-history-file "~/.nrepl-history.eld")

(defun nrepl-history-read-filename ()
"Ask the user which file to use, defaulting `nrepl-history-file`."
(read-file-name "Use nREPL history file: "
nrepl-history-file))

(defun nrepl-history-read (filename)
"Read history from FILE and return it.
Does not yet set the input history."
(if (file-readable-p filename)
(with-temp-buffer
(insert-file-contents filename)
(read (current-buffer)))
'()))

(defun nrepl-history-load (&optional filename)
"Load history from FILENAME into current session.
FILENAME defaults to the value of `nrepl-history-file` but user
defined filenames can be used to read special history files.
The value of `nrepl-input-history` is set by this function."
(interactive (list (nrepl-history-read-filename)))
(let ((f (or filename nrepl-history-file)))
;; TODO: probably need to set nrepl-input-history-index as well.
;; in a fresh connection the newest item in the list is currently
;; not available. After sending one input, everything seems to work.
(setq nrepl-input-history (nrepl-history-read f))))

(defun nrepl-history-write (filename)
"Write history to FILENAME.
Currently coding system for writing the contents is hardwired to
utf-8-unix."
(let* ((mhist (nrepl-histories-merge nrepl-input-history nil))
;; newest items are at the beginning of the list, thus 0
(hist (subseq mhist 0 (min (length mhist) nrepl-history-size))))
(unless (file-writable-p filename)
(error (format "History file not writable: %s" filename)))
(let ((print-length nil) (print-level nil))
(with-temp-file filename
;; TODO: really set cs for output
;; TODO: does cs need to be customizable?
(insert ";; -*- coding: utf-8-unix -*-\n")
(insert ";; Automatically written history of nREPL session\n")
(insert ";; Edit at your own risk\n\n")
(prin1 (mapcar #'substring-no-properties hist) (current-buffer))))))

(defun nrepl-history-save (&optional filename)
"Save the current nREPL input history to FILENAME.
FILENAME defaults to the value of `nrepl-history-file`."
(interactive (list (nrepl-history-read-filename)))
(let* ((file (or filename nrepl-history-file)))
(nrepl-history-write file)))

(defun nrepl-history-just-save ()
"Just save the history to `nrepl-history-file`.
This function is meant to be used in hooks to avoid lambda
constructs."
(nrepl-history-save nrepl-history-file))

;; SLIME has different semantics and will not save any duplicates.
(defun nrepl-histories-merge (session-hist file-hist)
(append session-hist))

;;;
(defun nrepl-same-line-p (pos1 pos2)
"Return t if buffer positions POS1 and POS2 are on the same line."
(save-excursion (goto-char (min pos1 pos2))
Expand Down Expand Up @@ -810,6 +879,11 @@ DIRECTION is 'forward' or 'backward' (in the history list)."
major-mode 'nrepl-mode)
(set-syntax-table nrepl-mode-syntax-table)
(nrepl-eldoc-enable-in-current-buffer)
(when nrepl-history-file
(nrepl-history-load nrepl-history-file)
(make-local-variable 'kill-buffer-hook)
(add-hook 'kill-buffer-hook 'nrepl-history-just-save)
(add-hook 'kill-emacs-hook 'nrepl-history-just-save))
(run-mode-hooks 'nrepl-mode-hook))

;;; communication
Expand Down

0 comments on commit c900166

Please sign in to comment.