1
1
mirror of https://github.com/anoma/juvix.git synced 2025-01-05 14:34:03 +03:00

Add juvix-repl-mode for emacs (#1612)

* Adds a major mode for juvix-repl

* juvix-mode: C-c C-l loads file into REPL, if the REPL is running

* Detect ANSI support in Emacs REPL / shell by using hSupportsANSIColor API

* Disable comint echo handling. Juvix REPL does not echo

* repl: whitespace strip input to compile/eval/infer commands
This commit is contained in:
Paul Cadman 2022-11-09 15:36:40 +00:00 committed by GitHub
parent aa00d34c8c
commit 6d66d0ab13
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 60 additions and 8 deletions

View File

@ -28,7 +28,7 @@ runAppIO g root pkg = interpret $ \case
RenderStdOut t
| g ^. globalOnlyErrors -> return ()
| otherwise -> embed $ do
sup <- Ansi.hSupportsANSI stdout
sup <- Ansi.hSupportsANSIColor stdout
renderIO (not (g ^. globalNoColors) && sup) t
AskGlobalOptions -> return g
AskPackage -> return pkg

View File

@ -161,7 +161,7 @@ runCommand opts = do
<$> doEvalIO False defaultLoc (ctx ^. replContextExpContext . contextCoreResult . Core.coreResultTable) n
compileString :: Repl (Either JuvixError Core.Node)
compileString = liftIO $ compileExpressionIO' ctx (pack s)
compileString = liftIO $ compileExpressionIO' ctx (strip (pack s))
bindEither :: Monad m => m (Either e a) -> (a -> m (Either e b)) -> m (Either e b)
bindEither x f = join <$> (x >>= mapM f)
@ -172,7 +172,7 @@ runCommand opts = do
gopts <- State.gets (^. replStateGlobalOptions)
case ctx of
Just ctx' -> do
compileRes <- liftIO (compileExpressionIO' ctx' (pack input))
compileRes <- liftIO (compileExpressionIO' ctx' (strip (pack input)))
case compileRes of
Left err -> printError gopts err
Right n -> renderOut gopts (Core.ppOut (project' @GenericOptions gopts) n)
@ -184,7 +184,7 @@ runCommand opts = do
gopts <- State.gets (^. replStateGlobalOptions)
case ctx of
Just ctx' -> do
compileRes <- liftIO (inferExpressionIO' ctx' (pack input))
compileRes <- liftIO (inferExpressionIO' ctx' (strip (pack input)))
case compileRes of
Left err -> printError gopts err
Right n -> renderOut gopts (Internal.ppOut (project' @GenericOptions gopts) n)
@ -282,7 +282,7 @@ compileExpressionIO' ctx = compileExpressionIO "" (ctx ^. replContextExpContext)
render' :: (MonadIO m, P.HasAnsiBackend a, P.HasTextBackend a) => GlobalOptions -> a -> m ()
render' g t = liftIO $ do
hasAnsi <- Ansi.hSupportsANSI stdout
hasAnsi <- Ansi.hSupportsANSIColor stdout
P.renderIO (not (g ^. globalNoColors) && hasAnsi) t
renderOut :: (MonadIO m, P.HasAnsiBackend a, P.HasTextBackend a) => GlobalOptions -> a -> m ()
@ -290,5 +290,5 @@ renderOut g t = render' g t >> liftIO (putStrLn "")
printError :: MonadIO m => GlobalOptions -> JuvixError -> m ()
printError opts e = liftIO $ do
hasAnsi <- Ansi.hSupportsANSI stderr
hasAnsi <- Ansi.hSupportsANSIColor stderr
liftIO $ hPutStrLn stderr $ run (runReader (project' @GenericOptions opts) (Error.render (not (opts ^. globalNoColors) && hasAnsi) False e))

View File

@ -2,6 +2,7 @@
(require 'juvix-highlight)
(require 'juvix-input)
(require 'flycheck-juvix)
(require 'juvix-repl)
(defgroup juvix nil
"Major mode for Juvix files."
@ -56,7 +57,8 @@
(eval (read (shell-command-to-string
(concat "juvix " (if juvix-disable-embedded-stdlib "--no-stdlib " "") (if juvix-stdlib-path (concat "--stdlib-path " juvix-stdlib-path " ") "") "dev highlight "
(buffer-file-name)))))
(save-buffer))
(save-buffer)
(juvix-repl-load-file (buffer-file-name)))
(defun juvix-format-buffer ()
"Format the current buffer."

50
juvix-mode/juvix-repl.el Normal file
View File

@ -0,0 +1,50 @@
(require 'comint)
(defgroup juvix-repl nil
"Interaction mode for Juvix"
:group 'juvix)
(defvar juvix-repl-program "juvix"
"The Juvix program.")
(defvar juvix-repl-program-args '("repl")
"The argument to pass to Juvix to launch the REPL.")
(defvar juvix-repl-mode-map
(nconc (make-sparse-keymap) comint-mode-map))
(defvar juvix-repl-buffer-name "*juvix-repl*"
"The name of the buffer to use for the `juvix-repl' comint instance.")
(defun run-juvix-repl ()
"Run an inferior instance of `juvix repl' inside Emacs."
(interactive)
(let* ((juvix-program juvix-repl-program)
(juvix-program-args juvix-repl-program-args)
(buffer (get-buffer-create juvix-repl-buffer-name))
(proc-alive (comint-check-proc buffer))
(process (get-buffer-process buffer)))
(unless proc-alive
(with-current-buffer buffer
(apply 'make-comint-in-buffer "juvix-repl" buffer
juvix-program nil juvix-program-args)
(juvix-repl-mode)))
(when buffer
(pop-to-buffer buffer))))
(defun juvix-repl--initialize ()
"Helper function to initalize juvix-repl."
(setq comint-process-echoes nil))
(define-derived-mode juvix-repl-mode comint-mode "Juvix REPL" "Major mode for juvix-repl")
(add-hook 'juvix-mode-hook 'juvix-repl--initialize)
(defun juvix-repl-load-file (filename)
"Load FILENAME into the juvix-repl if it is running."
(let* ((buffer (get-buffer juvix-repl-buffer-name))
(proc-alive (comint-check-proc buffer)))
(when proc-alive
(comint-simple-send juvix-repl-buffer-name (concat ":load " filename)))))
(provide 'juvix-repl)

View File

@ -88,7 +88,7 @@ printErrorText e = renderText e >>= \txt -> embed (hPutStrLn stderr txt)
printErrorAnsiSafe :: (ToGenericError e, Members '[Embed IO, Reader GenericOptions] r) => e -> Sem r ()
printErrorAnsiSafe e =
ifM
(embed (Ansi.hSupportsANSI stderr))
(embed (Ansi.hSupportsANSIColor stderr))
(printErrorAnsi e)
(printErrorText e)