Skip to content

Commit 1ab32e6

Browse files
committed
merge
2 parents e391978 + aed7bba commit 1ab32e6

File tree

4 files changed

+191
-30
lines changed

4 files changed

+191
-30
lines changed

pub/vi/nix/default.nix

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,16 @@ in
112112
unst.vimPlugins.minuet-ai-nvim
113113
unst.vimPlugins.codecompanion-nvim
114114
unst.vimPlugins.codecompanion-spinner-nvim
115+
(
116+
builtins.getFlake (
117+
toString ../../../rust
118+
)
119+
)
120+
.packages
121+
.${
122+
builtins.currentSystem
123+
}
124+
.rustell-wasm-nvim
115125
]
116126
else []
117127
);

rust/flake.nix

Lines changed: 57 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,58 @@
4747
mkdir -p $out/lib
4848
cp target/${buildTarget}/release/*.wasm $out/lib/
4949
'';
50-
# Disable checks if they only work for WASM
51-
# doCheck = false;
50+
};
51+
mkRustellNvim = exe:
52+
pkgs.vimUtils.buildVimPlugin {
53+
name = "rustell-nvim";
54+
src = pkgs.writeTextDir "plugin/rustell.vim" ''
55+
augroup rust.vim.PreWrite
56+
autocmd!
57+
augroup END
58+
59+
augroup rustell_PreWrite
60+
autocmd!
61+
autocmd BufWritePre *.rs call s:RustellPreWrite()
62+
augroup END
63+
64+
function! s:RustellPreWrite()
65+
if !filereadable(expand('%'))
66+
return
67+
endif
68+
69+
" Read buffer
70+
let l:input = join(getline(1, '$'), "\n")
71+
72+
" --- run rustell first ---
73+
let l:rustell_out = system('${exe}', l:input)
74+
if v:shell_error
75+
echohl ErrorMsg | echom 'rustell failed: ' . l:rustell_out | echohl None
76+
return
77+
endif
78+
79+
" --- now feed result into rustfmt ---
80+
let l:rustfmt_cmd = 'rustfmt'
81+
if exists('g:rustfmt_command')
82+
let l:rustfmt_cmd = g:rustfmt_command
83+
endif
84+
if exists('g:rustfmt_options')
85+
let l:rustfmt_cmd .= ' ' . g:rustfmt_options
86+
endif
87+
88+
let l:rustfmt_out = system(l:rustfmt_cmd, l:rustell_out)
89+
if v:shell_error
90+
echohl ErrorMsg | echom 'rustfmt failed: ' . l:rustfmt_out | echohl None
91+
return
92+
endif
93+
94+
" Replace buffer with formatted output
95+
let l:out_lines = split(l:rustfmt_out, "\n")
96+
call setline(1, l:out_lines)
97+
if line('$') > len(l:out_lines)
98+
execute len(l:out_lines)+1 . ',$delete _'
99+
endif
100+
endfunction
101+
'';
52102
};
53103
in {
54104
devShells.default = pkgs.mkShell {
@@ -64,9 +114,13 @@
64114
wasmtime
65115
];
66116
};
67-
packages = {
117+
packages = rec {
68118
rustell = mkRustPkg "rustell";
119+
rustell-nvim = mkRustellNvim "${rustell}/bin/rustell";
69120
rustell-wasm = mkRustPkgWasm "rustell";
121+
rustell-wasm-nvim = mkRustellNvim "${
122+
pkgs.wasmtime
123+
}/bin/wasmtime ${rustell-wasm}/bin/rustell.wasm";
70124
default = self.packages.${system}.rustell;
71125
};
72126
}

rust/rustell/src/decode.rs

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -89,18 +89,6 @@ fn expr_raw<'a>() -> impl Decode<'a, Expr<'a>> {
8989
.map(Expr::Raw)
9090
}
9191

92-
fn token<'a>(
93-
tok: impl Decode<'a, &'a str> + Clone,
94-
) -> impl Decode<'a, &'a str> + Clone {
95-
whitespace().or_not().ignore_then(tok)
96-
}
97-
98-
fn lexeme<'a>(
99-
seq: &'a str,
100-
) -> impl Decode<'a, &'a str> + Clone {
101-
token(just(seq))
102-
}
103-
10492
fn keyword<'a>() -> impl Decode<'a, &'a str> + Clone {
10593
keyword_except(&[])
10694
}
@@ -130,3 +118,15 @@ fn keyword_except<'a>(
130118
.collect::<Vec<_>>(),
131119
)
132120
}
121+
122+
fn token<'a>(
123+
tok: impl Decode<'a, &'a str> + Clone,
124+
) -> impl Decode<'a, &'a str> + Clone {
125+
whitespace().or_not().ignore_then(tok)
126+
}
127+
128+
fn lexeme<'a>(
129+
seq: &'a str,
130+
) -> impl Decode<'a, &'a str> + Clone {
131+
token(just(seq))
132+
}

rust/rustell/tests/integration.rs

Lines changed: 112 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,79 @@ use rustell::encode;
33
use rustell::*;
44

55
#[test]
6-
fn test_parser() {
6+
fn mod_declaration() {
7+
let lhs = "mod hello;";
8+
let rhs = vec![Expr::Mod("hello")];
9+
assert_eq!(decode(lhs), rhs);
10+
assert_eq!(decode(&sloppy(lhs)), rhs);
11+
assert_eq!(decode(&encode(&rhs)), rhs)
12+
}
13+
14+
#[test]
15+
fn mod_then_use_statement() {
16+
let lhs = "mod hello; use std::io;";
17+
let rhs = vec![
18+
Expr::Mod("hello"),
19+
Expr::Raw(" "),
20+
Expr::Use(ExprUse::Item {
21+
module: "std",
22+
rename: None,
23+
nested: Some(Box::new(ExprUse::Item {
24+
module: "io",
25+
rename: None,
26+
nested: None,
27+
})),
28+
}),
29+
];
30+
assert_eq!(decode(lhs), rhs);
31+
assert_eq!(decode(&sloppy(lhs)), rhs);
32+
assert_eq!(decode(&encode(&rhs)), rhs)
33+
}
34+
35+
#[test]
36+
fn raw_code_then_mod() {
37+
let lhs = r#"
38+
fn test() {
39+
println!("Hello")
40+
}
41+
mod hello;"#;
42+
let rhs = vec![
43+
Expr::Raw(
44+
r#"
45+
fn test() {
46+
println!("Hello")
47+
}
48+
"#,
49+
),
50+
Expr::Mod("hello"),
51+
];
52+
assert_eq!(decode(lhs), rhs);
53+
assert_eq!(decode(&sloppy(lhs)), rhs);
54+
assert_eq!(decode(&encode(&rhs)), rhs)
55+
}
56+
57+
#[test]
58+
fn mod_then_raw_code() {
59+
let lhs = "mod hello;
60+
fn test() {
61+
println!(\"Hello\")
62+
}";
63+
let rhs = vec![
64+
Expr::Mod("hello"),
65+
Expr::Raw(
66+
"
67+
fn test() {
68+
println!(\"Hello\")
69+
}",
70+
),
71+
];
72+
assert_eq!(decode(lhs), rhs);
73+
assert_eq!(decode(&sloppy(lhs)), rhs);
74+
assert_eq!(decode(&encode(&rhs)), rhs)
75+
}
76+
77+
#[test]
78+
fn simple_use_statement() {
779
let lhs = "use std::io::Read;";
880
let rhs = vec![Expr::Use(ExprUse::Item {
981
module: "std",
@@ -24,7 +96,7 @@ fn test_parser() {
2496
}
2597

2698
#[test]
27-
fn test_parser_many() {
99+
fn multiple_use_items() {
28100
let lhs = "use std::{io::Read, fs::File};";
29101
let rhs = vec![Expr::Use(ExprUse::Item {
30102
module: "std",
@@ -56,7 +128,7 @@ fn test_parser_many() {
56128
}
57129

58130
#[test]
59-
fn test_parser_glob() {
131+
fn use_glob_pattern() {
60132
let lhs = "use std::io::*;";
61133
let rhs = vec![Expr::Use(ExprUse::Item {
62134
module: "std",
@@ -73,7 +145,7 @@ fn test_parser_glob() {
73145
}
74146

75147
#[test]
76-
fn test_parser_rename() {
148+
fn use_with_rename() {
77149
let lhs = "use std::io::Read as Readable;";
78150
let rhs = vec![Expr::Use(ExprUse::Item {
79151
module: "std",
@@ -94,7 +166,7 @@ fn test_parser_rename() {
94166
}
95167

96168
#[test]
97-
fn test_parser_complex() {
169+
fn complex_use_statement() {
98170
let lhs = "use std::{io::Read as Readable, fs::*};";
99171
let rhs = vec![Expr::Use(ExprUse::Item {
100172
module: "std",
@@ -122,7 +194,7 @@ fn test_parser_complex() {
122194
}
123195

124196
#[test]
125-
fn test_parser_crate() {
197+
fn use_crate_path() {
126198
let lhs = "use crate::module::Type;";
127199
let rhs = vec![Expr::Use(ExprUse::Item {
128200
module: "crate",
@@ -143,7 +215,7 @@ fn test_parser_crate() {
143215
}
144216

145217
#[test]
146-
fn test_parser_raw_then_use() {
218+
fn raw_code_then_use() {
147219
let lhs = r#"
148220
fn test() {
149221
println!("Hello")
@@ -177,7 +249,7 @@ fn test_parser_raw_then_use() {
177249
}
178250

179251
#[test]
180-
fn test_parser_multiple() {
252+
fn multiple_separate_uses() {
181253
let lhs = r#"
182254
use std::io;
183255
use std::fs;
@@ -211,7 +283,7 @@ fn test_parser_multiple() {
211283
}
212284

213285
#[test]
214-
fn test_parser_multiple_with_raw() {
286+
fn multiple_uses_with_raw_code() {
215287
let lhs = r#"
216288
use std::io;
217289
fn test() {
@@ -254,7 +326,7 @@ fn test_parser_multiple_with_raw() {
254326
}
255327

256328
#[test]
257-
fn test_parser_mixed_all_cases() {
329+
fn mixed_use_and_raw_cases() {
258330
let lhs = r#"
259331
use std::{
260332
io::{self, Read as R},
@@ -326,11 +398,36 @@ fn test_parser_mixed_all_cases() {
326398
}
327399

328400
#[test]
329-
fn test_rountrip_lib() {
330-
let src =
331-
std::fs::read_to_string("./src/lib.rs").unwrap();
332-
let ast = decode(&src);
333-
assert_eq!(decode(&encode(&ast)), ast);
401+
fn roundtrip_source_files() {
402+
get_rust_files("./").into_iter().for_each(|path| {
403+
let lhs = std::fs::read_to_string(&path).unwrap();
404+
let rhs = decode(&lhs);
405+
assert_eq!(
406+
decode(&encode(&rhs)),
407+
rhs,
408+
"Roundtrip failed for the file: {}",
409+
path
410+
);
411+
});
412+
}
413+
414+
fn get_rust_files(dir: &str) -> Vec<String> {
415+
std::fs::read_dir(dir)
416+
.unwrap()
417+
.flat_map(|item| {
418+
let path = item.unwrap().path();
419+
let name = path.to_str().unwrap();
420+
if path.is_dir() {
421+
get_rust_files(name)
422+
} else if path.is_file()
423+
&& name.ends_with(".rs")
424+
{
425+
vec![name.to_string()]
426+
} else {
427+
vec![]
428+
}
429+
})
430+
.collect()
334431
}
335432

336433
fn sloppy(src: &str) -> String {

0 commit comments

Comments
 (0)