Skip to content

Commit 9b3f2a6

Browse files
jasonrobotgrafov
authored andcommitted
Updated to use cargo instead of rustc (#5)
* Reworked this since it didnt work for me at all. Now uses 'cargo run' and proper crate dir structure, with a cargo.toml file. * fixed up deletion to be more robust * commented out debug message * removed a bunch of unused and commented out code * more cleanup, also -rm wasnt using the new snippet base dir function * added a macro to wrap interactive commands, to warn and exit if not in a playground * changed those big blocks of text to custom vars * finally got the keymap working * cleaned up the file header/template * remembered that 'unless' exists * killed dead code, added a comment * Made template work in cargo.toml. Fixed places where 'unless doesnt work. * fixed up the -rm function, now it actually kills all buffers related to the snippet (basically) * corrected comment * moved a function up for readability, updated Commentary documentation section, restored README.md, deleted unused upload/download code (rust playground on the web just uses gists on github) * wasnt ever using the rust-playground-compile-command custom, so used that * updated the startup screenshot to show the new stuff * made use of some of the functions I defined, DRY
1 parent cbb8a32 commit 9b3f2a6

File tree

3 files changed

+141
-113
lines changed

3 files changed

+141
-113
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<!--*- mode:markdown;mode:orgtbl;fill-column:99 -*-->
1+
<!-- *- mode:markdown;mode:orgtbl;fill-column:99 -* -->
22
# rust-playground [![MELPA Stable](https://stable.melpa.org/packages/rust-playground-badge.svg)](https://stable.melpa.org/#/rust-playground) [![MELPA](https://melpa.org/packages/rust-playground-badge.svg)](https://melpa.org/#/rust-playground)
33

44
*It works. But development still in progress!*

rust-playground-after-start.png

22.9 KB
Loading

rust-playground.el

Lines changed: 140 additions & 112 deletions
Original file line numberDiff line numberDiff line change
@@ -24,38 +24,28 @@
2424
;;; Commentary:
2525

2626
;; Local playground for the Rust programs similar to play.rust-lang.org.
27-
;; `M-x rust-playground` and type you rust code then make&run it with `C-Return`.
27+
;; `M-x rust-playground` and type you rust code then make&run it with `C-c C-c`.
28+
;; Toggle between Cargo.toml and main.rs with `C-c b`
29+
;; Delete the current playground and close all buffers with `C-c k`
2830

2931
;; Playground works in conjunction with `rust-mode` and requires
3032
;; preconfigured environment for Rust language.
3133

3234
;; It is port of github.com/grafov/go-playground for Go language.
3335

34-
;; You may push code to play.rust-lang.org with rust-mode' function `rust-playpen-buffer`.
35-
36-
;;
37-
3836
;;; Code:
3937

40-
(require 'rust-mode)
4138
(require 'compile)
4239
(require 'time-stamp)
4340

44-
; I think it should be defined in rust-mode.
45-
(defcustom rust-playground-bin "rustc"
46-
"The ’rust’ command."
47-
:type 'string
48-
:group 'rust-mode)
49-
5041
(defgroup rust-playground nil
5142
"Options specific to Rust Playground."
5243
:group 'rust-mode)
5344

54-
(defcustom rust-playground-ask-file-name nil
55-
"Non-nil means we ask for a name for the snippet.
56-
57-
By default it will be created as snippet.go"
58-
:type 'boolean
45+
;; I think it should be defined in rust-mode.
46+
(defcustom rust-playground-run-command "cargo run"
47+
"The ’rust’ command."
48+
:type 'string
5949
:group 'rust-playground)
6050

6151
(defcustom rust-playground-confirm-deletion t
@@ -70,120 +60,158 @@ By default confirmation required."
7060
:type 'file
7161
:group 'rust-playground)
7262

73-
(defvar-local rust-playground-current-snippet-file "snippet.rs"
74-
"The current snippet file.")
63+
(defcustom rust-playground-cargo-toml-template
64+
"[package]
65+
name = \"foo\"
66+
version = \"0.1.0\"
67+
authors = [\"Rust Example <[email protected]>\"]
68+
69+
[dependencies]"
70+
"When creating a new playground, this will be used as the Cargo.toml file")
71+
72+
(defcustom rust-playground-main-rs-template
73+
"fn main() {
74+
75+
println!(\"Results:\")
76+
}"
77+
"When creating a new playground, this will be used as the body of the main.rs file")
7578

7679
(define-minor-mode rust-playground-mode
77-
"A place for playing with golang code and export it in short snippets."
80+
"A place for playing with Rust code and export it in short snippets."
7881
:init-value nil
7982
:lighter "Play(Rust)"
80-
:keymap '(([C-return] . rust-playground-exec)))
81-
82-
(defun rust-playground-snippet-file-name(&optional snippet-name)
83-
(setq-local rust-playground-current-snippet-file
84-
(let ((file-name
85-
(cond (snippet-name)
86-
(rust-playground-ask-file-name
87-
(read-string "Rust Playground filename: ")) ("snippet"))))
88-
(concat (rust-playground-snippet-unique-dir file-name) "/" file-name ".rs"))))
83+
:keymap (let ((map (make-sparse-keymap)))
84+
(define-key map (kbd "C-c C-c") 'rust-playground-exec)
85+
(define-key map (kbd "C-c b") 'rust-playground-switch-between-cargo-and-main)
86+
(define-key map (kbd "C-c k") 'rust-playground-rm)
87+
map))
88+
89+
(defun rust-playground-dir-name (&optional snippet-name)
90+
"Get the name of the directory where the snippet will exist, with SNIPPET-NAME as part of the directory name."
91+
(file-name-as-directory (concat (file-name-as-directory rust-playground-basedir)
92+
(time-stamp-string "at-%:y-%02m-%02d-%02H%02M%02S"))))
93+
94+
(defun rust-playground-snippet-main-file-name (basedir)
95+
"Get the snippet main.rs file from BASEDIR."
96+
(concat basedir (file-name-as-directory "src") "main.rs"))
97+
98+
(defun rust-playground-toml-file-name (basedir)
99+
"Get the cargo.toml filename from BASEDIR."
100+
(concat basedir "Cargo.toml"))
101+
102+
(defun rust-playground-get-snippet-basedir (&optional path)
103+
"Get the path of the dir containing this snippet.
104+
Start from PATH or the path of the current buffer's file, or NIL if this is not a snippet."
105+
(unless path
106+
(setq path (buffer-file-name)))
107+
(if (not path)
108+
nil
109+
(if (not (string= path "/"))
110+
(let ((base "/home/jason/.emacs.d/rust-playground")
111+
(path-parent (file-name-directory (directory-file-name path))))
112+
(if (string= (file-name-as-directory base)
113+
(file-name-as-directory path-parent))
114+
path
115+
(rust-playground-get-snippet-basedir path-parent)))
116+
nil)))
117+
118+
;; I think the proper way to check for this is to test if the minor mode is active
119+
;; TODO base this check off the minor mode, once that mode gets set on all files
120+
;; in a playground
121+
(defmacro in-rust-playground (&rest forms)
122+
"Execute FORMS if current buffer is part of a rust playground.
123+
Otherwise message the user that they aren't in one."
124+
`(if (not (rust-playground-get-snippet-basedir))
125+
(message "You aren't in a Rust playground.")
126+
,@forms))
89127

90128
(defun rust-playground-exec ()
91129
"Save the buffer then run Rust compiler for executing the code."
92130
(interactive)
93-
(make-local-variable 'compile-command)
94-
(let ((snippet-file buffer-file-name))
95-
(save-buffer t)
96-
(compile "cargo build")))
131+
(in-rust-playground
132+
(save-buffer t)
133+
(compile rust-playground-run-command)))
97134

98135
;;;###autoload
99136
(defun rust-playground ()
100137
"Run playground for Rust language in a new buffer."
101138
(interactive)
102-
(let ((snippet-file-name (rust-playground-snippet-file-name)))
103-
(switch-to-buffer (create-file-buffer snippet-file-name))
104-
(add-hook 'kill-buffer-hook 'rust-playground-on-buffer-kill nil t)
105-
(rust-playground-insert-template-head "snippet of code")
106-
(insert "fn main() {
107-
108-
println!(\"Results:\")
109-
110-
}")
111-
(backward-char 3)
112-
(rust-mode)
139+
;; get the dir name
140+
(let* ((snippet-dir (rust-playground-dir-name))
141+
(snippet-file-name (rust-playground-snippet-main-file-name snippet-dir))
142+
(snippet-cargo-toml (rust-playground-toml-file-name snippet-dir)))
143+
;; create a buffer for Cargo.toml and switch to it
144+
(make-directory snippet-dir)
145+
(set-buffer (create-file-buffer snippet-cargo-toml))
146+
(set-visited-file-name snippet-cargo-toml t)
113147
(rust-playground-mode)
114-
(set-visited-file-name snippet-file-name t)))
115-
116-
; remove compiled binary from snippet dir but not touch source files ;
117-
(defun rust-playground-on-buffer-kill ()
118-
(if (string-match-p (file-truename rust-playground-basedir) (file-truename (buffer-file-name)))
119-
(delete-file (concat (file-name-directory (buffer-file-name)) "snippet"))))
120-
121-
(defun rust-playground-insert-template-head (description)
122-
(insert "// -*- mode:rust;mode:rust-playground -*-
123-
// " description " @ " (time-stamp-string "%:y-%02m-%02d %02H:%02M:%02S") "
124-
125-
// === Rust Playground ===
126-
// Execute the snippet with Ctl-Return
127-
// Remove the snippet completely with its dir and all files M-x `rust-playground-rm`
128-
129-
"))
148+
(rust-playground-insert-template-head "snippet of code" snippet-dir)
149+
(insert rust-playground-cargo-toml-template)
150+
(save-buffer)
151+
;;now do src/main.rs
152+
(make-directory (concat snippet-dir "src"))
153+
(switch-to-buffer (create-file-buffer snippet-file-name))
154+
(set-visited-file-name snippet-file-name t)
155+
(rust-playground-insert-template-head "snippet of code" snippet-dir)
156+
(insert rust-playground-main-rs-template)
157+
;; back up to a good place to edit from
158+
(backward-char 27)
159+
(rust-playground-mode)))
160+
161+
(defun rust-playground-switch-between-cargo-and-main ()
162+
"Change buffers between the main.rs and Cargo.toml files for the current snippet."
163+
(interactive)
164+
(in-rust-playground
165+
(let ((basedir (rust-playground-get-snippet-basedir)))
166+
;; If you're in a rust snippet, but in some file other than main.rs,
167+
;; then just switch to main.rs
168+
(cond
169+
;; how to switch to existing or create new, given filename?
170+
((string= "main.rs" (file-name-nondirectory buffer-file-name))
171+
(find-file (rust-playground-toml-file-name basedir)))
172+
(t
173+
(find-file (rust-playground-snippet-main-file-name basedir)))))))
174+
175+
(defun rust-playground-insert-template-head (description basedir)
176+
"Inserts a template about the snippet into the file."
177+
(let ((starting-point (point)))
178+
(insert (format
179+
"%s @ %s
180+
181+
=== Rust Playground ===
182+
This snippet is in: %s
183+
184+
Execute the snippet: C-c C-c
185+
Delete the snippet completely: C-c k
186+
Toggle between main.rs and Cargo.toml: C-c b
187+
188+
" description (time-stamp-string "%:y-%02m-%02d %02H:%02M:%02S") basedir))
189+
(comment-region starting-point (point))))
190+
191+
(defun rust-playground-get-all-buffers ()
192+
"Get all the buffers visiting Cargo.toml or any *.rs file under src/."
193+
(in-rust-playground
194+
(let* ((basedir (rust-playground-get-snippet-basedir))
195+
(srcdir (concat basedir (file-name-as-directory "src"))))
196+
;; now get the fullpath of cargo.toml, and the fullpath of every file under src/
197+
(remove 'nil (seq-map 'find-buffer-visiting
198+
(cons (concat basedir "Cargo.toml")
199+
(directory-files srcdir t ".*\.rs")))))))
130200

131201
;;;###autoload
132202
(defun rust-playground-rm ()
133203
"Remove files of the current snippet together with directory of this snippet."
134204
(interactive)
135-
(if (rust-playground-inside)
136-
(if (or (not rust-playground-confirm-deletion)
137-
(y-or-n-p (format "Do you want delete whole snippet dir %s? "
138-
(file-name-directory (buffer-file-name)))))
139-
(progn
140-
(save-buffer)
141-
(delete-directory (file-name-directory (buffer-file-name)) t t)
142-
(remove-hook 'kill-buffer-hook 'rust-playground-on-buffer-kill t)
143-
(kill-buffer)))
144-
(message "Won't delete this! Because %s is not under the path %s. Remove the snippet manually!"
145-
(buffer-file-name) rust-playground-basedir)))
146-
147-
;; ;;;###autoload
148-
;; (defun rust-playground-download (url)
149-
;; "Download a paste from the play.golang.org and insert it in a new local playground buffer.
150-
;; Tries to look for a URL at point."
151-
;; (interactive (list (read-from-minibuffer "Playground URL: " (ffap-url-p (ffap-string-at-point 'url)))))
152-
;; (with-current-buffer
153-
;; (let ((url-request-method "GET") url-request-data url-request-extra-headers)
154-
;; (url-retrieve-synchronously (concat url ".go")))
155-
;; (let* ((snippet-file-name (rust-playground-snippet-file-name)) (buffer (create-file-buffer snippet-file-name)))
156-
;; (goto-char (point-min))
157-
;; (re-search-forward "\n\n")
158-
;; (copy-to-buffer buffer (point) (point-max))
159-
;; (kill-buffer)
160-
;; (with-current-buffer buffer
161-
;; (goto-char (point-min))
162-
;; (rust-playground-insert-template-head (concat url " imported"))
163-
;; (rust-mode)
164-
;; (rust-playground-mode)
165-
;; (set-visited-file-name snippet-file-name t)
166-
;; (switch-to-buffer buffer)))))
167-
168-
;; (defun rust-playground-upload ()
169-
;; "Upload the current buffer to play.rust-lang.org and return the short URL of the playground."
170-
;; (interactive)
171-
;; (goto-char (point-min))
172-
;; (forward-line)
173-
;; (insert (rust-playpen-buffer)))
174-
175-
(defun rust-playground-snippet-unique-dir (prefix)
176-
"Get unique directory under `rust-playground-basedir`."
177-
(let ((dir-name (concat rust-playground-basedir "/"
178-
(if (and prefix rust-playground-ask-file-name) (concat prefix "-"))
179-
(time-stamp-string "at-%:y-%02m-%02d-%02H%02M%02S"))))
180-
(make-directory dir-name t)
181-
dir-name))
182-
183-
(defun rust-playground-inside ()
184-
"It checks that minor mode is rusl-playground and buffer file placed under default directory."
185-
(if (string-match-p (file-truename rust-playground-basedir) (file-truename (buffer-file-name)))
186-
(bound-and-true-p rust-playground-mode)))
205+
(in-rust-playground
206+
(let ((playground-basedir (rust-playground-get-snippet-basedir)))
207+
(if playground-basedir
208+
(when (or (not rust-playground-confirm-deletion)
209+
(y-or-n-p (format "Do you want delete whole snippet dir %s? "
210+
playground-basedir)))
211+
(dolist (buf (rust-playground-get-all-buffers))
212+
(kill-buffer buf))
213+
(delete-directory playground-basedir t t))
214+
(message "Won't delete this! Because %s is not under the path %s. Remove the snippet manually!" (buffer-file-name) rust-playground-basedir)))))
187215

188216
(provide 'rust-playground)
189217
;;; rust-playground.el ends here

0 commit comments

Comments
 (0)