Ejacsのjs-consoleの履歴を保存する
EmacsでJavaScriptが実行できるEjacsのjs-consoleに感動しつつ、js-console上でシェルやgdbのように履歴を保存できないのが不満だったので、ちょこっと作ってみた。なんてことはない。ただのスタックだ。履歴を遡るだけなら1個でいいのだが、履歴を遡っている途中で逆方向に戻りたくなった場合、もう1つスタックが必要だったので、2段構えになっている。
--- js-console.el.old 2008-11-19 00:03:53.000000000 +0900 +++ js-console.el 2008-11-18 23:58:01.000000000 +0900 @@ -44,6 +44,58 @@ (defvar js-console-last-parsed-input nil) (make-variable-buffer-local 'js-console-last-parsed-input) +;; expression history +(defvar js-console-prev-history '()) +(defvar js-console-next-history '()) + +(defun js-console-restore-history () + "Restore input-expression history" + (setq js-console-prev-history + (append (reverse js-console-next-history) + js-console-prev-history)) + (setq js-console-next-history '())) + +(defun js-console-push-prev-expression-history (exp) + "Add input-expression to history" + (setq js-console-prev-history (cons exp js-console-prev-history))) + +(defun js-console-push-next-expression-history (exp) + "Add previous expression to history for next expression" + (setq js-console-next-history (cons exp js-console-next-history))) + +(defun js-console-pop-prev-expression-history () + "Pop previous expression from history" + (let ((prev-exp (car js-console-prev-history))) + (setq js-console-prev-history (cdr js-console-prev-history)) + (js-console-push-next-expression-history prev-exp) + prev-exp)) + +(defun js-console-pop-next-expression-history () + "Pop next expression from next expression history" + (let ((prev-exp (car js-console-next-history)) + (next-exp (cadr js-console-next-history))) + (setq js-console-next-history (cdr js-console-next-history)) + (js-console-push-prev-expression-history prev-exp) + next-exp)) + +(defun js-console-prev-evaluated-expression () + "Insert prev expression into console." + (interactive) + (if (null (car js-console-prev-history)) + (progn (kill-region js-console-input-start (point-max)) + (message "history is empty.")) + (progn (kill-region js-console-input-start (point-max)) + (insert (js-console-pop-prev-expression-history))))) + +(defun js-console-next-evaluated-expression () + "Insert next expression into console." + (interactive) + (if (null (cadr js-console-next-history)) + (progn (kill-region js-console-input-start (point-max)) + (message "history is empty.")) + (progn (kill-region js-console-input-start (point-max)) + (insert (js-console-pop-next-expression-history))))) + (defmacro with-js-runtime (&rest body) "Execute BODY with a new JavaScript runtime and execution context. BODY is a lisp expression - this function is not for evaluating @@ -101,6 +153,9 @@ (define-key js-console-mode-map [(control a)] 'js-console-bol) + (define-key js-console-mode-map [(meta p)] 'js-console-prev-evaluated-expression) + (define-key js-console-mode-map [(meta n)] 'js-console-next-evaluated-expression) + (js-console-init-interpreter) (set (make-local-variable 'max-lisp-eval-depth) @@ -157,6 +212,8 @@ (js-console-exec-input input) (error (js-console-handle-error err))) + (js-console-restore-history) + (js-console-push-prev-expression-history input) (js-console-exec-input input)))) (defun js-console-exec-input (input) @@ -392,7 +449,6 @@ ;; These two are for Narcissus. (js-define-builtin global "snarf" 'js-console-js-snarf 'no-wrap) (js-define-builtin global "evaluate" 'js-console-js-evaluate 'no-wrap)) - (provide 'js-console)