Skip to content

Commit 5e96cd0

Browse files
authored
Merge pull request #544 from isvilen/run-interactive
Support running interactive programs
2 parents e54bbae + 947ebf9 commit 5e96cd0

File tree

6 files changed

+109
-17
lines changed

6 files changed

+109
-17
lines changed

.gitignore

+3-1
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,6 @@
22
*-autoloads.el
33
/rust-mode-pkg.el
44
.eask
5-
/dist
5+
/dist
6+
test-project/Cargo.lock
7+
test-project/target/

Makefile

+1
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ compile:
2828

2929
test:
3030
$(EASK) test ert rust-mode-tests.el
31+
$(EASK) test ert rust-cargo-tests.el
3132

3233
checkdoc:
3334
$(EASK) lint checkdoc

README.md

+3
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,9 @@ By default these are bound to:
173173
- <kbd>C-c C-c C-t</kbd> `rust-test`
174174
- <kbd>C-c C-c C-r</kbd> `rust-run`
175175

176+
To run programs requiring user input use universal argument when invoking
177+
`rust-run` (<kbd>C-u C-c C-c C-r</kbd>).
178+
176179
### Clippy
177180

178181
`rust-run-clippy` runs

rust-cargo-tests.el

+53
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
;;; rust-cargo-tests.el --- ERT tests for rust-cargo.el -*- lexical-binding: t; -*-
2+
(require 'rust-cargo)
3+
(require 'ert)
4+
5+
(defun rust-test--wait-process-exit ()
6+
"Wait for comint process for current buffer to exit."
7+
(let ((proc (get-buffer-process (current-buffer))))
8+
(while (not (eq (process-status proc) 'exit))
9+
(sit-for 0.2))))
10+
11+
(defun rust-test--send-process-string (string)
12+
"Send STRING to comint process for current buffer."
13+
(let ((proc (get-buffer-process (current-buffer))))
14+
(comint-send-string proc string)))
15+
16+
(defmacro rust-test--with-main-file-buffer (expr)
17+
`(let* ((test-dir (expand-file-name "test-project/" default-directory))
18+
(main-file (expand-file-name "src/main.rs" test-dir)))
19+
(save-current-buffer
20+
(find-file main-file)
21+
,expr)))
22+
23+
(defun rust-test--find-string (string)
24+
"Find STRING in current buffer."
25+
(goto-char (point-min))
26+
(not (null (search-forward string nil t))))
27+
28+
29+
(ert-deftest rust-test-compile ()
30+
(skip-unless (executable-find rust-cargo-bin))
31+
(setq rust-cargo-default-arguments "")
32+
(rust-test--with-main-file-buffer
33+
(with-current-buffer (rust-compile)
34+
(rust-test--wait-process-exit)
35+
(should (rust-test--find-string "Compilation finished")))))
36+
37+
(ert-deftest rust-test-run ()
38+
(skip-unless (executable-find rust-cargo-bin))
39+
(setq rust-cargo-default-arguments "")
40+
(rust-test--with-main-file-buffer
41+
(with-current-buffer (rust-run)
42+
(rust-test--wait-process-exit)
43+
(should (rust-test--find-string "***run not interactive")))))
44+
45+
(ert-deftest rust-test-run-interactive ()
46+
(skip-unless (executable-find rust-cargo-bin))
47+
(setq rust-cargo-default-arguments "interactive")
48+
(rust-test--with-main-file-buffer
49+
;; '(4) is default value when called interactively with universal argument
50+
(with-current-buffer (rust-run '(4))
51+
(rust-test--send-process-string "1234\n")
52+
(rust-test--wait-process-exit)
53+
(should (rust-test--find-string "***run interactive: 1234")))))

rust-cargo.el

+24-16
Original file line numberDiff line numberDiff line change
@@ -67,46 +67,54 @@
6767

6868
;;; Internal
6969

70-
(defun rust--compile (format-string &rest args)
70+
(defun rust--compile (comint format-string &rest args)
7171
(when (null rust-buffer-project)
7272
(rust-update-buffer-project))
7373
(let ((default-directory
7474
(or (and rust-buffer-project
7575
(file-name-directory rust-buffer-project))
76-
default-directory)))
77-
(compile (apply #'format format-string args))))
76+
default-directory))
77+
;; make sure comint is a boolean value
78+
(comint (not (not comint))))
79+
(compile (apply #'format format-string args) comint)))
7880

7981
;;; Commands
8082

8183
(defun rust-check ()
8284
"Compile using `cargo check`"
8385
(interactive)
84-
(rust--compile "%s check %s" rust-cargo-bin rust-cargo-default-arguments))
86+
(rust--compile nil "%s check %s" rust-cargo-bin rust-cargo-default-arguments))
8587

8688
(defun rust-compile ()
8789
"Compile using `cargo build`"
8890
(interactive)
89-
(rust--compile "%s build %s" rust-cargo-bin rust-cargo-default-arguments))
91+
(rust--compile nil "%s build %s" rust-cargo-bin rust-cargo-default-arguments))
9092

9193
(defun rust-compile-release ()
9294
"Compile using `cargo build --release`"
9395
(interactive)
94-
(rust--compile "%s build --release" rust-cargo-bin))
96+
(rust--compile nil "%s build --release" rust-cargo-bin))
9597

96-
(defun rust-run ()
97-
"Run using `cargo run`"
98-
(interactive)
99-
(rust--compile "%s run %s" rust-cargo-bin rust-cargo-default-arguments))
98+
(defun rust-run (&optional comint)
99+
"Run using `cargo run`
100100
101-
(defun rust-run-release ()
102-
"Run using `cargo run --release`"
103-
(interactive)
104-
(rust--compile "%s run --release" rust-cargo-bin))
101+
If optional arg COMINT is t or invoked with universal prefix arg,
102+
output buffer will be in comint mode, i.e. interactive."
103+
(interactive "P")
104+
(rust--compile comint "%s run %s" rust-cargo-bin rust-cargo-default-arguments))
105+
106+
(defun rust-run-release (&optional comint)
107+
"Run using `cargo run --release`
108+
109+
If optional arg COMINT is t or invoked with universal prefix arg,
110+
output buffer will be in comint mode, i.e. interactive."
111+
(interactive "P")
112+
(rust--compile comint "%s run --release" rust-cargo-bin))
105113

106114
(defun rust-test ()
107115
"Test using `cargo test`"
108116
(interactive)
109-
(rust--compile "%s test %s" rust-cargo-bin rust-cargo-default-arguments))
117+
(rust--compile nil "%s test %s" rust-cargo-bin rust-cargo-default-arguments))
110118

111119
(defun rust-run-clippy ()
112120
"Run `cargo clippy'."
@@ -118,7 +126,7 @@
118126
;; set `compile-command' temporarily so `compile' doesn't
119127
;; clobber the existing value
120128
(compile-command (mapconcat #'shell-quote-argument args " ")))
121-
(rust--compile compile-command)))
129+
(rust--compile nil compile-command)))
122130

123131
;;; _
124132
(provide 'rust-cargo)

test-project/src/main.rs

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
use std::{env, io};
2+
3+
fn main() {
4+
let mut args = env::args();
5+
6+
if args.len() == 1 {
7+
println!("***run not interactive");
8+
} else {
9+
match args.nth(1).unwrap().as_str() {
10+
"interactive" => {
11+
let mut line = String::new();
12+
13+
io::stdin()
14+
.read_line(&mut line)
15+
.expect("Failed to read line");
16+
17+
println!("***run interactive: {line}");
18+
}
19+
20+
_ => {
21+
panic!("unexpected argument");
22+
}
23+
}
24+
}
25+
}

0 commit comments

Comments
 (0)