Skip to content

Instantly share code, notes, and snippets.

@shg
Last active November 8, 2020 03:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save shg/181010bd700997609d54c199e380bcd6 to your computer and use it in GitHub Desktop.
Save shg/181010bd700997609d54c199e380bcd6 to your computer and use it in GitHub Desktop.
Inferior Julia REPL using vterm
;; julia-repl-vterm.el --- A mode for Julia REPL using vterm -*- lexical-binding: t -*-
;;
;; Copyright (C) 2020 Shigeaki Nishina
;; Author: Shigeaki Nishina
;; Maintainer: Shigeaki Nishina
;; URL: https://github.com/shg/julia-repl-vterm
;; Version: 0.4
;;
;; This file is not part of GNU Emacs.
;;
;;; Commentary:
;;
;;; License:
;;
;; This program is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or (at
;; your option) any later version.
;;
;; This program is distributed in the hope that it will be useful, but
;; WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
;; General Public License for more details.
;;
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see https://www.gnu.org/licenses/.
;;
;;; Code:
(require 'julia-mode)
(require 'vterm)
;;----------------------------------------------------------------------
(defgroup inferior-julia-repl-vterm nil
"A major mode for inferior Julia REPL"
:group 'julia)
(defvar inferior-julia-repl-vterm-buffer-name "*julia-repl*")
(defvar inferior-julia-repl-vterm-program "julia")
(defvar-local inferior-julia-repl-vterm-script-buffer nil)
(defvar inferior-julia-repl-vterm-mode-map
(let ((map (make-sparse-keymap)))
(define-key map (kbd "C-c C-z") #'inferior-julia-repl-vterm-switch-to-script-buffer)
(define-key map (kbd "C-l") #'recenter-top-bottom)
(define-key map (kbd "M-k") #'inferior-julia-repl-vterm-clear-buffer)
(define-key map (kbd "C-c C-t") #'inferior-julia-repl-vterm-copy-mode)
map))
(define-derived-mode inferior-julia-repl-vterm-mode vterm-mode "Inf-Julia"
"A major mode for inferior Julia REPL."
:group 'inferior-julia-repl-vterm)
(defun inferior-julia-repl-vterm-buffer ()
"Return the inferior Julia REPL buffer `*julia-repl*`. If the buffer doesn't exist,
create one and return it. If there's already the buffer and the inferior Julia REPL
is running, return the buffer. If the buffer exists but the process is not running,
kill the buffer and create a new one."
(if-let ((buffer (get-buffer inferior-julia-repl-vterm-buffer-name))
(proc (with-current-buffer buffer vterm--process)))
buffer
(if buffer (kill-buffer buffer))
(let ((buffer (generate-new-buffer inferior-julia-repl-vterm-buffer-name))
(vterm-shell inferior-julia-repl-vterm-program))
(with-current-buffer buffer
(inferior-julia-repl-vterm-mode))
buffer)))
(defun inferior-julia-repl-vterm ()
"Create an inferior Julia REPL buffer `*julia-repl*` and open it. If there's
already one with the process alive, just open it."
(interactive)
(pop-to-buffer-same-window (inferior-julia-repl-vterm-buffer)))
(defun inferior-julia-repl-vterm-switch-to-script-buffer ()
(interactive)
(if (and (boundp 'inferior-julia-repl-vterm-script-buffer) (buffer-live-p inferior-julia-repl-vterm-script-buffer))
(switch-to-buffer-other-window inferior-julia-repl-vterm-script-buffer)
(message "The script buffer does not exist.")))
(defun inferior-julia-repl-vterm-clear-buffer ()
(interactive)
(save-excursion
(goto-char (point-min))
(vterm-clear)))
(defvar inferior-julia-repl-vterm-copy-mode-map
(let ((map (make-sparse-keymap)))
(define-key map (kbd "C-c C-t") #'inferior-julia-repl-vterm-copy-mode)
(define-key map [return] #'inferior-julia-repl-vterm-copy-mode-done)
(define-key map (kbd "RET") #'inferior-julia-repl-vterm-copy-mode-done)
(define-key map (kbd "C-c C-r") #'vterm-reset-cursor-point)
map))
(define-minor-mode inferior-julia-repl-vterm-copy-mode
"Toggle copy mode."
:group 'inferior-julia-repl-vterm
:lighter " VTermCopy"
:keymap inferior-julia-repl-vterm-copy-mode-map
(when inferior-julia-repl-vterm-copy-mode
(message "Start copy mode")
(use-local-map nil)
(vterm-send-stop)))
(defun inferior-julia-repl-vterm-copy-mode-done ()
"Save the active region to the kill ring and exit `inferior-julia-repl-vterm-copy-mode'."
(interactive)
(if (region-active-p)
(kill-ring-save (region-beginning) (region-end))
(user-error "No active region"))
(inferior-julia-repl-vterm-copy-mode -1)
(vterm-reset-cursor-point)
(use-local-map inferior-julia-repl-vterm-mode-map)
(vterm-send-start)
(message "End copy mode"))
;;----------------------------------------------------------------------
(defgroup julia-with-repl-vterm nil
"A minor mode for a Julia script buffer that interacts with an inferior Julia REPL."
:group 'julia)
(defcustom julia-with-repl-vterm-hook nil
"Hook to run after starting a Julia script buffer that interacts with an inferior Julia REPL."
:type 'hook
:group 'julia-with-repl-vterm)
(defun julia-with-repl-vterm-switch-to-repl-buffer ()
(interactive)
(let ((current-script-buffer (current-buffer))
(inferior-buffer (inferior-julia-repl-vterm-buffer)))
(with-current-buffer inferior-buffer
(setq inferior-julia-repl-vterm-script-buffer current-script-buffer)
(switch-to-buffer-other-window inferior-buffer))))
(defun julia-with-repl-vterm-send-return-key ()
(with-current-buffer (inferior-julia-repl-vterm-buffer)
(vterm-send-return)))
(defun julia-with-repl-vterm-paste-string (string)
(with-current-buffer (inferior-julia-repl-vterm-buffer)
(vterm-send-string string t)))
(defun julia-with-repl-vterm-send-current-line ()
(interactive)
(let ((current-char (char-after))
(current-line (string-trim (thing-at-point 'line t))))
(when (and current-char (not (string-empty-p current-line)))
(julia-with-repl-vterm-paste-string current-line)
(julia-with-repl-vterm-send-return-key)))
(forward-line))
(defun julia-with-repl-vterm-send-buffer ()
(interactive)
(save-excursion
(julia-with-repl-vterm-paste-string (buffer-string))))
;;;##autoload
(define-minor-mode julia-with-repl-vterm-mode
"A minor mode for a Julia script buffer that interacts with an inferior Julia REPL."
nil "⁂"
`((,(kbd "C-c C-z") . julia-with-repl-vterm-switch-to-repl-buffer)
(,(kbd "C-c C-b") . julia-with-repl-vterm-send-buffer)
(,(kbd "C-<return>") . julia-with-repl-vterm-send-current-line)))
(add-hook 'julia-mode-hook (lambda () (julia-with-repl-vterm-mode 1)))
(provide 'julia-repl-vterm)
@shg
Copy link
Author

shg commented Aug 30, 2020

@apparluk Fixed. Thank you.

@shg
Copy link
Author

shg commented Sep 3, 2020

Fixed. Thank you. The current and the previous versions of julia-with-repl-vterm-send-buffer sometimes don't work well and I am working on rewriting it. Please note.

Copy link

ghost commented Sep 12, 2020

can you add https://cirw.in/blog/bracketed-paste ? otherwise when sending a line with ']' and OhMyREPL it ends up corrupted https://discourse.julialang.org/t/nvim-send-extract-to-repl/46412

@shg
Copy link
Author

shg commented Oct 1, 2020

can you add https://cirw.in/blog/bracketed-paste ? otherwise when sending a line with ']' and OhMyREPL it ends up corrupted https://discourse.julialang.org/t/nvim-send-extract-to-repl/46412

Thank you. I confirmed this. I will see how to implement it.

Copy link

ghost commented Oct 1, 2020

Bracketed paste option (vterm-send-string string t) doesn't help me, OhMyREPL.Prompt.insert_keybindings() fixes the issue with single quote, but ] is still broken

@shg
Copy link
Author

shg commented Oct 4, 2020

Implemented bracketed paste mode.
I moved code to https://github.com/shg/julia-repl-vterm.el . This gist will not be updated anymore.

Also julia-repl.el is going to support vterm sometime soon. Those who have been interested in Julia REPL in vterm may want to check it first. https://github.com/tpapp/julia-repl .

@shg
Copy link
Author

shg commented Oct 26, 2020

This latest version of this code is now available on MELPA.

https://melpa.org/#/julia-vterm

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment