Add a simple emacs mode for editing valeri code
This commit is contained in:
parent
f4660b6bc1
commit
908df85c63
2 changed files with 117 additions and 0 deletions
|
@ -19,6 +19,7 @@ enum class TtyEscape {
|
|||
CtrlF = 6,
|
||||
CtrlH = 8,
|
||||
Tab = 9,
|
||||
LF = 10,
|
||||
CtrlK = 11,
|
||||
CtrlL = 12,
|
||||
Enter = 13,
|
||||
|
@ -244,6 +245,7 @@ class LineEdit {
|
|||
if (nread <= 0) return false;
|
||||
|
||||
switch (TtyEscape(c)) {
|
||||
case TtyEscape::LF:
|
||||
case TtyEscape::Enter:
|
||||
return false;
|
||||
break;
|
||||
|
|
115
valeri-mode.el
Normal file
115
valeri-mode.el
Normal file
|
@ -0,0 +1,115 @@
|
|||
;;; valeri-mode.el --- a major-mode for editing Valeri programs -*- lexical-binding: t -*-
|
||||
|
||||
|
||||
(require 'comint)
|
||||
|
||||
(defcustom valeri-default-application "valeri"
|
||||
"Default application to run in Valeri process."
|
||||
:type 'string
|
||||
:group 'valeri)
|
||||
|
||||
(defcustom valeri-default-command-switches (list)
|
||||
"Command switches for `valeri-default-application'.
|
||||
Should be a list of strings."
|
||||
:type '(repeat string)
|
||||
:group 'valeri)
|
||||
|
||||
(defcustom valeri-prompt-regexp "[^\n]*\\(valeri>[\t ]+\\)+$"
|
||||
"Regexp which matches the Valeri program's prompt."
|
||||
:type 'regexp
|
||||
:group 'valeri)
|
||||
|
||||
(defcustom valeri-traceback-line-re
|
||||
;; This regexp skips prompt and meaningless "stdin:N:" prefix when looking
|
||||
;; for actual file-line locations.
|
||||
"^\\(?:[\t ]*\\|.*>[\t ]+\\)\\(?:[^\n\t ]+:[0-9]+:[\t ]*\\)*\\(?:\\([^\n\t ]+\\):\\([0-9]+\\):\\)"
|
||||
"Regular expression that describes tracebacks and errors."
|
||||
:type 'regexp
|
||||
:group 'valeri)
|
||||
|
||||
(defvar valeri-process-init-code
|
||||
(mapconcat
|
||||
'identity
|
||||
'("")
|
||||
" "))
|
||||
|
||||
(defvar valeri-process nil
|
||||
"The active Valeri process")
|
||||
|
||||
(defvar valeri-process-buffer nil
|
||||
"Buffer used for communication with the Valeri process.")
|
||||
|
||||
(defvar valeri--repl-buffer-p nil
|
||||
"Buffer-local flag saying if this is a Valeri REPL buffer.")
|
||||
(make-variable-buffer-local 'valeri--repl-buffer-p)
|
||||
|
||||
(defun valeri-get-create-process ()
|
||||
"Return active Valeri process creating one if necessary."
|
||||
(valeri-start-process)
|
||||
valeri-process)
|
||||
|
||||
(defun valeri-send-string (str)
|
||||
"Send STR plus a newline to the Valeri process.
|
||||
|
||||
If `valeri-process' is nil or dead, start a new process first."
|
||||
(unless (string-equal (substring str -1) "\n")
|
||||
(setq str (concat str "\n")))
|
||||
(process-send-string (valeri-get-create-process) str))
|
||||
|
||||
;;;###autoload
|
||||
(define-derived-mode valeri-mode lisp-mode "Valeri"
|
||||
"Major mode for editing Valeri code."
|
||||
:group 'valeri
|
||||
)
|
||||
|
||||
;;;###autoload
|
||||
(defalias 'run-valeri #'valeri-start-process)
|
||||
|
||||
;;;###autoload
|
||||
(defun valeri-start-process (&optional name program startfile &rest switches)
|
||||
"Start a Valeri process named NAME, running PROGRAM.
|
||||
PROGRAM defaults to NAME, which defaults to `valeri-default-application'.
|
||||
When called interactively, switch to the process buffer."
|
||||
(interactive)
|
||||
(setq name (or name valeri-default-application))
|
||||
(setq program (or program valeri-default-application))
|
||||
;; don't re-initialize if there already is a Valeri process
|
||||
(unless (comint-check-proc (format "*%s*" name))
|
||||
(setq valeri-process-buffer (apply #'make-comint name program startfile
|
||||
(or switches valeri-default-command-switches)))
|
||||
(setq valeri-process (get-buffer-process valeri-process-buffer))
|
||||
(set-process-query-on-exit-flag valeri-process nil)
|
||||
(with-current-buffer valeri-process-buffer
|
||||
;; enable error highlighting in stack traces
|
||||
(require 'compile)
|
||||
(setq valeri--repl-buffer-p t)
|
||||
(make-local-variable 'compilation-error-regexp-alist)
|
||||
(setq compilation-error-regexp-alist
|
||||
(cons (list valeri-traceback-line-re 1 2)
|
||||
compilation-error-regexp-alist))
|
||||
(compilation-shell-minor-mode 1)
|
||||
(setq-local comint-prompt-regexp valeri-prompt-regexp)
|
||||
|
||||
;; Don't send initialization code until seeing the prompt to ensure that
|
||||
;; the interpreter is ready.
|
||||
;; (while (not (valeri-prompt-line))
|
||||
;; (accept-process-output (get-buffer-process (current-buffer)))
|
||||
;; (goto-char (point-max)))
|
||||
;; (valeri-send-string valeri-process-init-code)
|
||||
))
|
||||
|
||||
;; when called interactively, switch to process buffer
|
||||
(if (called-interactively-p 'any)
|
||||
(switch-to-buffer valeri-process-buffer)))
|
||||
|
||||
(defun valeri-prompt-line ()
|
||||
(save-excursion
|
||||
(save-match-data
|
||||
(forward-line 0)
|
||||
(if (looking-at comint-prompt-regexp)
|
||||
(match-end 0)))))
|
||||
|
||||
|
||||
(provide 'valeri-mode)
|
||||
|
||||
;;; valeri-mode.el ends here
|
Loading…
Reference in a new issue