Skip to content

Commit

Permalink
rustic-babel: support wrap BODY in a fn main if none exists
Browse files Browse the repository at this point in the history
close brotzeit#267

related: brotzeit#266
  • Loading branch information
Eric Wang authored and Eric Wang committed Nov 5, 2021
1 parent 985c094 commit e0cfa1d
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 4 deletions.
27 changes: 25 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
- [:features](#features)
- [:paths](#paths)
- [:toolchain](#toolchain)
- [:main](#main)
- [Spinner](#spinner)
- [inline-documentation](#inline-documentation)
- [Prequisites](#prequisites)
Expand Down Expand Up @@ -79,7 +80,7 @@ The other files provide functionality that is similar to some of the features
of rustic, however can be considered light-weight compared to some rustic's
functionality.

The shared functions and options exist as aliases in the rust-mode and
The shared functions and options exist as aliases in the rust-mode and
rustic namespace for backwards compatability reasons(rustic has been a fork).

## Known issues
Expand Down Expand Up @@ -499,7 +500,7 @@ then a string, instead of a list, will also be accepted:
```
#+BEGIN_SRC rust :crates '((tokio . 1.0)) :features '((tokio . ("rt-multi-thread" "time")))
extern crate tokio;
fn main() {
tokio::runtime::Runtime::new()
.unwrap()
Expand Down Expand Up @@ -541,6 +542,28 @@ fn main() {
: a,b,c
```

#### :main

Auto wrap whole block body in a `fn main` function call if none exists.

Since this is very handy in most code snippets, so the default value is `yes`.
`no` if you don't want this feature(for example, you don't want regex search slow things down).

You can also set a default value by:
``` elisp
;; By setq this default to `nil`, you'll have to explict set params to ":main yes" in each block
(setq rustic-babel-auto-wrap-main nil)
```

```
#+begin_src rust :main yes
let x = vec![1, 2, 3].iter().map(|&x| x + 1).collect::<Vec<_>>();
println!("{:?}", x);
#+end_src
#+results:
: [2, 3, 4]
```

## Spinner

Expand Down
21 changes: 19 additions & 2 deletions rustic-babel.el
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@
:type 'boolean
:group 'rustic-babel)

(defcustom rustic-babel-auto-wrap-main t
"Whether to auto wrap body in 'fn main' to function call if none exists."
:type 'boolean
:group 'rustic-babel)

(defcustom rustic-babel-format-src-block t
"Whether to format a src block automatically after successful execution."
:type 'boolean
Expand Down Expand Up @@ -259,6 +264,12 @@ directory DIR."
(insert s)
(insert dependencies))))))

(defun rustic-babel-ensure-main-wrap (body)
"Wrap BODY in a 'fn main' function call if none exists."
(if (string-match "^[ \t]*[fn]+[ \t\n\r]*main[ \t]*(.*)" body)
body
(format "fn main() {\n%s\n}\n" body)))

(defun org-babel-execute:rustic (body params)
"Execute a block of Rust code with org-babel.
Expand All @@ -272,7 +283,12 @@ kill the running process."
(let* ((default-directory org-babel-temporary-directory)
(project (rustic-babel-project))
(dir (setq rustic-babel-dir (expand-file-name project)))
(main (expand-file-name "main.rs" (concat dir "/src"))))
(main-p (cdr (assq :main params)))
(main (expand-file-name "main.rs" (concat dir "/src")))
(wrap-main (cond ((string= main-p "yes") t)
((string= main-p "no") nil)
(t rustic-babel-auto-wrap-main))))

(make-directory (file-name-directory main) t)
(rustic-babel-cargo-toml dir params)
(setq rustic-info (org-babel-get-src-block-info))
Expand All @@ -286,7 +302,8 @@ kill the running process."
(let ((default-directory dir)
(toolchain (cdr (assq :toolchain params))))
(write-region
(concat "#![allow(non_snake_case)]\n" body) nil main nil 0)
(concat "#![allow(non_snake_case)]\n"
(if wrap-main (rustic-babel-ensure-main-wrap body) body)) nil main nil 0)
(rustic-babel-eval dir toolchain)
(setq rustic-babel-src-location
(set-marker (make-marker) (point) (current-buffer)))
Expand Down
32 changes: 32 additions & 0 deletions test/rustic-babel-test.el
Original file line number Diff line number Diff line change
Expand Up @@ -187,3 +187,35 @@
(with-current-buffer buf
(rustic-test-babel-execute-block buf)
(should (eq (rustic-test-babel-check-results buf) nil)))))

(ert-deftest rustic-test-babel-ensure-main-wrap-no()
(let* ((string "let x = \"fn main(){}\";")
(params ":main no")
(buf (rustic-test-get-babel-block string params)))
(with-current-buffer buf
(rustic-test-babel-execute-block buf)
(let ((re (format "error: Could not compile `%s`.\n"
(car (reverse (split-string rustic-babel-dir "/"))))))
(should (string= re (rustic-test-babel-check-results buf)))))))

(ert-deftest rustic-test-babel-ensure-main-wrap-yes-with-main()
(let* ((string "
fn main() {
let x = \"rustic\";
}")
(params ":main yes")
(buf (rustic-test-get-babel-block string params)))
(with-current-buffer buf
(rustic-test-babel-execute-block buf)
(should (eq (rustic-test-babel-check-results buf) nil)))))

(ert-deftest rustic-test-babel-ensure-main-wrap-no-with-main()
(let* ((string "
fn main() {
let x = \"rustic\";
}")
(params ":main no")
(buf (rustic-test-get-babel-block string params)))
(with-current-buffer buf
(rustic-test-babel-execute-block buf)
(should (eq (rustic-test-babel-check-results buf) nil)))))

0 comments on commit e0cfa1d

Please sign in to comment.