Skip to content

Commit 2b40c44

Browse files
committed
Add lua-send-string-max-size and lua-send-region-chunked
1 parent 52cc3e4 commit 2b40c44

File tree

2 files changed

+87
-2
lines changed

2 files changed

+87
-2
lines changed

lua-mode.el

Lines changed: 50 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,11 @@ Should be a list of strings."
257257
:type 'boolean
258258
:group 'lua)
259259

260+
(defcustom lua-send-string-max-size (if (string-equal system-type "darwin") 512 nil)
261+
"Maximum size of string that can be sent to inferior shell."
262+
:type '(choice nil string)
263+
:group 'lua)
264+
260265
(defcustom lua-documentation-function 'browse-url
261266
"Function used to fetch the Lua reference manual."
262267
:type `(radio (function-item browse-url)
@@ -1686,8 +1691,13 @@ This function just searches for a `end' at the beginning of a line."
16861691
"end")
16871692
" "))
16881693

1694+
(defun lua--send-process-init-code ()
1695+
"Send initialization code to REPL."
1696+
;; XXX: send in chunks if initialization code exceeds send-string-max-size
1697+
(lua-send-string lua-process-init-code))
1698+
16891699
(defun lua-make-lua-string (str)
1690-
"Convert string to Lua literal."
1700+
"Convert string STR to Lua literal."
16911701
(save-match-data
16921702
(with-temp-buffer
16931703
(insert str)
@@ -1769,6 +1779,8 @@ When called interactively, switch to the process buffer."
17691779
"Send STR plus a newline to the Lua process.
17701780
17711781
If `lua-process' is nil or dead, start a new process first."
1782+
(when (and lua-send-string-max-size (> (length str) lua-send-string-max-size))
1783+
(error (format "Cannot send string of length %s (max length=%s)" (length str) lua-send-string-max-size)))
17721784
(unless (string-equal (substring str -1) "\n")
17731785
(setq str (concat str "\n")))
17741786
(process-send-string (lua-get-create-process) str))
@@ -1830,9 +1842,45 @@ Otherwise, return START."
18301842
(lua-make-lua-string region-str)
18311843
(lua-make-lua-string lua-file)
18321844
lineno)))
1833-
(lua-send-string command)
1845+
(if (or (null lua-send-string-max-size) (<= (length command) lua-send-string-max-size))
1846+
(lua-send-string command)
1847+
(lua-send-region-chunked region-str lua-file lineno lua-send-string-max-size))
18341848
(when lua-always-show (lua-show-process-buffer))))
18351849

1850+
(defun lua--split-string-into-lua-literals (str literal-max-length &optional func)
1851+
(let* (lua-literals
1852+
(func (or func (lambda (s) (setq lua-literals (cons s lua-literals)))))
1853+
chunk-begin chunk-end chunk chunk-as-lua-string)
1854+
(with-temp-buffer
1855+
(insert str)
1856+
(goto-char (point-min))
1857+
(while (< (point) (point-max))
1858+
(setq chunk-begin (point)
1859+
chunk-end (+ (point) literal-max-length))
1860+
;; For every special character that has to be quoted with a backslash,
1861+
;; decrease payload to account for the extra character.
1862+
(while (and (< (point) (min (point-max) chunk-end))
1863+
(re-search-forward "[\"'\\\t\\\n]" chunk-end 'noerror))
1864+
(setq chunk-end (1- chunk-end)))
1865+
(goto-char chunk-end)
1866+
(setq chunk (buffer-substring-no-properties chunk-begin (point)))
1867+
(funcall func (lua-make-lua-string chunk))))
1868+
(nreverse lua-literals)))
1869+
1870+
(defun lua-send-region-chunked (region-str lua-file lineno max-size)
1871+
"Send REGION-STR from LUA-FILE at LINENO in chunks of no more than MAX-SIZE."
1872+
;; XXX: make enable/disable-prompt-commands customizable
1873+
(let* ((disable-prompt-command "_PROMPT = ''; _PROMPT2 = ''")
1874+
(enable-prompt-command "_PROMPT = nil; _PROMPT2 = nil")
1875+
(between-quotes-max-size (- max-size 4)))
1876+
(lua-send-string disable-prompt-command)
1877+
(lua-send-string "print(''); luamode_loadstring(\"\"")
1878+
(lua--split-string-into-lua-literals
1879+
region-str between-quotes-max-size
1880+
(lambda (s) (lua-send-string (format "..%s" s))))
1881+
(lua-send-string (format ",%s,%d)" (lua-make-lua-string lua-file) lineno))
1882+
(lua-send-string enable-prompt-command)))
1883+
18361884
(defun lua-prompt-line ()
18371885
(save-excursion
18381886
(save-match-data

test/test-inferior-process.el

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,43 @@
4040
(expect comint-prompt-regexp :to-equal "^"))
4141
(expect comint-prompt-regexp :to-equal "^")))
4242

43+
(describe "Splitting Lua code into literals of specified size"
44+
(it "splits strings into same-size Lua literals"
45+
(expect (lua--split-string-into-lua-literals "foobarbaz" 3)
46+
:to-equal '("'foo'" "'bar'" "'baz'")))
47+
48+
(it "leaves last lua literal shorter if necessary"
49+
(expect (lua--split-string-into-lua-literals "foobarba" 3)
50+
:to-equal '("'foo'" "'bar'" "'ba'"))
51+
(expect (lua--split-string-into-lua-literals "foobarb" 3)
52+
:to-equal '("'foo'" "'bar'" "'b'"))
53+
(expect (lua--split-string-into-lua-literals "foobar" 3)
54+
:to-equal '("'foo'" "'bar'")))
55+
56+
(it "escapes special characters and does not exceed max-length"
57+
(expect (lua--split-string-into-lua-literals "foo\nbar" 3)
58+
:to-equal '("'foo'" "'\\nb'" "'ar'")))
59+
60+
(it "cuts literal short if it cannot fit a special character"
61+
(expect (lua--split-string-into-lua-literals "fo\nbar" 3)
62+
:to-equal '("'fo'" "'\\nb'" "'ar'"))))
63+
64+
(describe "Sending region chunked"
65+
(it "does that"
66+
(with-lua-buffer
67+
(insert "x = '|01234567890|1234567890|1234567890|'")
68+
(lua-start-process)
69+
(let ((lua-string-max-size 20))
70+
(lua-send-buffer))
71+
(lua-send-string "print(x)")
72+
(while (accept-process-output (lua-get-create-process) 0 200))
73+
(with-current-buffer lua-process-buffer
74+
(let* ((buf (buffer-substring-no-properties (point-min) (point-max)))
75+
(buf-lines (cdr (split-string buf "\n" nil))))
76+
(expect (nth 1 (nreverse buf-lines))
77+
:to-equal "> |01234567890|1234567890|1234567890|"))))))
78+
79+
4380

4481
(require 'compile)
4582
(if (fboundp 'compilation--loc->file-struct)

0 commit comments

Comments
 (0)