Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Babel: Toolchain support via :toolchain #279

Merged
merged 4 commits into from
Oct 12, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 28 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -431,7 +431,6 @@ If specific crate features are required then these can be specified
with the `:features` argument. Note that if it is just a single feature
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;
Expand All @@ -446,7 +445,34 @@ then a string, instead of a list, will also be accepted:
#+END_SRC
```

Supported org babel parameters:
Similarly, to depend on local Rust crates, you can set the `:paths` argument:

```
#+BEGIN_SRC rust :crates '((foo . 1.0)) :paths '((foo . "/home/you/code/foo"))
use foo::Foo;

fn main() {
// Your code.
}
#+END_SRC
```

You can also specify the `:toolchain`. Remember to quote the value!

```
#+begin_src rust :toolchain 'nightly
fn main() {
let foo: String = vec!["a", "b", "c"].into_iter().intersperse(",").collect();

println!("{}", foo);
}
#+end_src

#+RESULTS:
: a,b,c
```

Other supported org babel parameters:

Write to file `:results file :file ~/babel-output`

Expand Down
64 changes: 36 additions & 28 deletions rustic-babel.el
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,14 @@

(defvar rustic-babel-spinner nil)

(defun rustic-babel-eval (dir)
(defun rustic-babel-eval (dir toolchain-kw)
"Start a rust babel compilation process in directory DIR."
(let* ((err-buff (get-buffer-create rustic-babel-compilation-buffer-name))
(default-directory dir)
(params '("cargo" "build" "--quiet"))
(toolchain (cond ((eq toolchain-kw 'nightly) "+nightly")
((eq toolchain-kw 'beta) "+beta")
(t "+stable")))
Comment on lines -57 to +59
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This only allows nightly/beta/stable channels by keyword.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As opposed to?

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah I see the issue. We could expand the accepted format of toolchain-kw to allow for more free-form strings, and pass those as-is (or parse them?) down to the cargo line.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does d71fbf5 work for you ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That should do the trick.

(params (list "cargo" toolchain "build" "--quiet"))
(inhibit-read-only t))
(rustic-compilation-setup-buffer err-buff dir 'rustic-compilation-mode)
(when rustic-babel-display-compilation-buffer
Expand All @@ -64,9 +67,9 @@
:buffer err-buff
:command params
:filter #'rustic-compilation-filter
:sentinel #'rustic-babel-build-sentinel)))
:sentinel (lambda (proc output) (rustic-babel-build-sentinel toolchain proc output)))))

(defun rustic-babel-build-sentinel (proc _output)
(defun rustic-babel-build-sentinel (toolchain proc _output)
"Sentinel for rust babel compilation process PROC.
If `rustic-babel-format-src-block' is t, format src-block after successful
execution with rustfmt."
Expand Down Expand Up @@ -94,7 +97,7 @@ execution with rustfmt."

;; run project
(let* ((err-buff (get-buffer-create rustic-babel-compilation-buffer-name))
(params '("cargo" "run" "--quiet"))
(params (list "cargo" toolchain "run" "--quiet"))
(inhibit-read-only t))
(rustic-make-process
:name rustic-babel-process-name
Expand Down Expand Up @@ -208,30 +211,33 @@ Otherwise create it with `rustic-babel-generate-project'."
(put-text-property beg end 'project (make-symbol new))
new)))))

(defun crate-dependencies (name version features)
(defun crate-dependencies (name version features path)
"Generate a Cargo.toml [dependencies] entry for a crate given a version and features."
(let ((version-string (concat "version = \"" version "\""))
(features-string
(if features
(concat "features = [" (mapconcat (lambda (s) (concat "\"" s "\"")) features ", ") "]")
nil)))
(let ((toml-entry (string-join (remove nil (list version-string features-string)) ", ")))
(concat name " = {" toml-entry "}"))))

(defun cargo-toml-dependencies (crate-versions crate-features)
(let* ((version-string (concat "version = \"" version "\""))
(features-string
(when features
(concat "features = [" (mapconcat (lambda (s) (concat "\"" s "\"")) features ", ") "]")))
(path-string
(when path
(concat "path = \"" path "\"")))
(toml-entry (string-join (remove nil (list version-string features-string path-string)) ", ")))
(concat name " = {" toml-entry "}")))

(defun cargo-toml-dependencies (crate-versions crate-features crate-paths)
"Generate the [dependencies] section of a Cargo.toml file given crates and their versions & features."
(let ((dependencies ""))
(dolist (crate-and-version crate-versions)
(let ((name (car crate-and-version))
(version (cdr crate-and-version)))
(let ((features (cdr (assoc name crate-features))))
(setq name (symbol-name name))
(when (numberp version)
(setq version (number-to-string version)))
(when (not (listp features))
(setq features (list features)))
(let ((cargo-toml-entry (crate-dependencies name version features)))
(setq dependencies (concat dependencies cargo-toml-entry "\n"))))))
(let* ((name (car crate-and-version))
(version (cdr crate-and-version))
(features (cdr (assoc name crate-features)))
(path (cdr (assoc name crate-paths))))
(setq name (symbol-name name))
(when (numberp version)
(setq version (number-to-string version)))
(when (not (listp features))
(setq features (list features)))
(let ((cargo-toml-entry (crate-dependencies name version features path)))
(setq dependencies (concat dependencies cargo-toml-entry "\n")))))
(setq dependencies (concat "[dependencies]\n" dependencies))))

(defun rustic-babel-cargo-toml (dir params)
Expand All @@ -240,8 +246,9 @@ Use org-babel parameter crates from PARAMS and add them to the project in
directory DIR."
(let ((crates (cdr (assq :crates params)))
(features (cdr (assq :features params)))
(paths (cdr (assq :paths params)))
(toml (expand-file-name "Cargo.toml" dir)))
(let ((dependencies (cargo-toml-dependencies crates features)))
(let ((dependencies (cargo-toml-dependencies crates features paths)))
(make-directory (file-name-directory toml) t)
(with-temp-file toml
(condition-case nil
Expand Down Expand Up @@ -276,10 +283,11 @@ kill the running process."
'(rustic-babel-spinner (":Executing " (:eval (spinner-print rustic-babel-spinner))))
(spinner-start rustic-babel-spinner))

(let ((default-directory dir))
(let ((default-directory dir)
(toolchain (cdr (assq :toolchain params))))
(write-region
(concat "#![allow(non_snake_case)]\n" body) nil main nil 0)
(rustic-babel-eval dir)
(rustic-babel-eval dir toolchain)
(setq rustic-babel-src-location
(set-marker (make-marker) (point) (current-buffer)))
project)))))
Expand Down