sigmasd / irust Goto Github PK
View Code? Open in Web Editor NEWCross Platform Rust Repl
Home Page: https://crates.io/crates/irust
License: MIT License
Cross Platform Rust Repl
Home Page: https://crates.io/crates/irust
License: MIT License
A lot of Options logic could be simplified by using serde + toml,
I didn't use them at first because I cared about compilation time and reducing dependencies number, but now irust already uses some heavy dependencies like syntect so other crates like serde and toml (which are probably already used in the dependency tree) wont change much
Hi!
This rather simple code compiles just fine with rustc
:
fn parse_troop_power(troops: &str) -> u32 {
troops.split(' ')
.map(|w| w.parse::<u32>().expect("input format"))
.fold(0, |s, x| s + x)
}
But when pasted into IRust, gives weird error:
Curiously, :load
from a scratch-file works just fine, too. But it's the whole point of a REPL โ to not have to use scratch files right?..
rustc --version
rustc 1.40.0-nightly (8431f261d 2019-09-29)
cargo --version
cargo 1.39.0-nightly (ab6fa8908 2019-09-25)
------------------------------------------------------------------------------Welcome to IRust------------------------------------------------------------------------------
In: 1thread 'main' panicked at 'IRust Out: IoError(Os { code: 32, kind: BrokenPipe, message: "Broken pipe" })', src/libcore/result.rs:1165:5
stack backtrace:
0: 0x555efef13cb4 - backtrace::backtrace::libunwind::trace::h92f4bca147eaf003
at /cargo/registry/src/github.com-1ecc6299db9ec823/backtrace-0.3.37/src/backtrace/libunwind.rs:88
1: 0x555efef13cb4 - backtrace::backtrace::trace_unsynchronized::hab0c9829cb374bd1
at /cargo/registry/src/github.com-1ecc6299db9ec823/backtrace-0.3.37/src/backtrace/mod.rs:66
2: 0x555efef13cb4 - std::sys_common::backtrace::_print_fmt::h7de186026ed9cfd7
at src/libstd/sys_common/backtrace.rs:76
3: 0x555efef13cb4 - <std::sys_common::backtrace::_print::DisplayBacktrace as core::fmt::Display>::fmt::h72c9014a6d4c17fe
at src/libstd/sys_common/backtrace.rs:60
4: 0x555efef3862c - core::fmt::write::he8debf927fa26231
at src/libcore/fmt/mod.rs:1028
5: 0x555efef10a27 - std::io::Write::write_fmt::h6c8e4c259b547329
at src/libstd/io/mod.rs:1412
6: 0x555efef168c5 - std::sys_common::backtrace::_print::ha816fdd57a919bae
at src/libstd/sys_common/backtrace.rs:64
7: 0x555efef168c5 - std::sys_common::backtrace::print::hafeee729c9a72709
at src/libstd/sys_common/backtrace.rs:49
8: 0x555efef168c5 - std::panicking::default_hook::{{closure}}::h1ef6174970e041c9
at src/libstd/panicking.rs:196
9: 0x555efef165b6 - std::panicking::default_hook::he3bfe887c04a1755
at src/libstd/panicking.rs:210
10: 0x555efef16fc5 - std::panicking::rust_panic_with_hook::h5fc80d9ca9339a9b
at src/libstd/panicking.rs:473
11: 0x555efef16b62 - std::panicking::continue_panic_fmt::hda34f456b7fc6f05
at src/libstd/panicking.rs:380
12: 0x555efef16a56 - rust_begin_unwind
at src/libstd/panicking.rs:307
13: 0x555efef350fa - core::panicking::panic_fmt::hcefc03686fff269e
at src/libcore/panicking.rs:84
14: 0x555efef351f7 - core::result::unwrap_failed::h3e69de8175c25305
at src/libcore/result.rs:1165
15: 0x555efeeb39e8 - irust::main::h26081b34c2cdf82d
16: 0x555efeeb0553 - std::rt::lang_start::{{closure}}::h0b57e810707ed2f3
17: 0x555efef169f3 - std::rt::lang_start_internal::{{closure}}::h5eb6ace3eb8dd1aa
at src/libstd/rt.rs:49
18: 0x555efef169f3 - std::panicking::try::do_call::hba48a9e439683bd0
at src/libstd/panicking.rs:292
19: 0x555efef1e1da - __rust_maybe_catch_panic
at src/libpanic_unwind/lib.rs:80
20: 0x555efef174bd - std::panicking::try::h469d0537aa9e7942
at src/libstd/panicking.rs:271
21: 0x555efef174bd - std::panic::catch_unwind::hb22bce686f9d3206
at src/libstd/panic.rs:394
22: 0x555efef174bd - std::rt::lang_start_internal::h8453f9cea0010827
at src/libstd/rt.rs:48
23: 0x555efeeb3a52 - main
24: 0x7f68ff424ee3 - __libc_start_main
25: 0x555efee8121e - _start
26: 0x0 -
install clean rust nightly and run 'cargo install racer irust'
In [1]: 1
Out[1]: 1
In [2]: 2
Out[2]: 2
In [3]:
In [3]:
But its not that simple since this part of the code is tightly coupled to the printing part
Pressing End
should accept current suggestion, like ->
key does
Currently highlighting works pretty well, but one issue remains if we paste code into the repl it becomes noticeably laggy, I'm not sure whats the best way to deal with it
1 - we can de-bounce from highlighting calls, that is if the user input very fast(like pasting) write all the input without highlighting and then highlight when the input finishes
2 - Investigate how editors (exp: accepted) that use syntect do it, I'm only using the easy module, there is probably a more correct way to highlight text
This project is cool!
Is there any plan to support custom keybindings?
During the async mode (I was using tokio
runtime), no matter what I enters, irust
just silently accepts them without printing any result, even for the most simple expression 1 + 2
.
In: let mut x = 5;
In: x = 3
Out: ()
In: x
Out: 5
In: x = 3;
In: x
Out: 3
This behavior may be surprising sometimes. I'm not sure what the right way to improve it is, but my suggestion is printing a warning between In: and Out: about it whenever someone writes a line with = but not ;
IRust can spawn a server useful for editor plugins to send input, but its currently really tailored to a custom plugin I wrote https://github.com/sigmaSd/irust-vim-plugin
-> The server currently receives input from the client and run it on the repl
I think a better way is to make this a server that listens to input and then sends back the output to the client and the client gets to decide what it wants to do with it.
This would make easily integrate-able with something like https://github.com/Olical/conjure
Another option is to wait for crossterm-rs/crossterm#711 this will allow for the repl to receive stdin with normal keys (like every other repl) and so we wouldn't need the server workaround
I have two object irust_repl
: irust_repl1
and irust_repl2
. When I call irust_repl1.eval(some_code)
and irust_repl2.eval(some_code)
at the same time, the latter has a link.exe
error. I thought it maybe because that no matter how many irust_repl
I have, they all is based on the same temp file, and so manupulating the same main.rs
at the same time.
So, if I need run the irust_repl
s at the same time, what should I do?
I saw 0.5.11 and 0.5.12 and have some thoughts about them:
incomplete_input()
should also return true when the last non-whitespace (trim()
) character is :
or .
, as it's afaik guaranteed to fail. Maybe the current code of incomplete_input()
could be refactored into function unmatched_brackets()
, but that's not a requirement.It is useful to jump over whole words. I think it could be implemented like this:
When hitting Ctrl+Left
:
In case of Ctrl+Right
, everything is the same but s/left/right
. I'm not sure if this is how it's done in other REPLs, I never paid attention to how exactly cursor jumps, but I think it would be quite sane behavior (actually more sane than some IDEs offer, when I think about it).
It would be nice if IRust had tests to help make sure that changes we make haven't modified IRust's functionality in a wrong or unintended way. In addition, it would allow us to setup Travis CI in the future.
Also, I think this issue goes along with #42; it may be a good idea to add tests for the refactored portions of the codebase as we do the things listed in that issue.
I'm not familiar enough with IRust ATM to know everything that should and shouldn't be tested, but if pointed to where tests are needed I'm happy to help with adding them. I know that cursor.rs is a place where tests would be nice, and after #44 is finished I can create a PR with some tests for that part of the codebase if that's a welcome change.
example config can be like:
input = DarkCyan
eval = Blue
show = Red
add = Green
typed characters (needs a better name) = DarkYellow
Right now commands are added to history in parse_second_order
, so commands like :show
, ::ls
etc. are left out (cannot be repeated by Up
->Enter
). It would be nice to be able to have them in history (by having self.history.push(self.buffer.drain(..).collect());
in parse
). In case someone doesn't like that design, it could be a toggle-able option - but then we run into another issue: where should REPL configuration be stored? Bash uses .bash_profile
, Python uses environmental variables.
As was pointed out in #39 (comment), it would be nice to highlight the input as the user types it in, like IPython does for example. However, the straightforward approach mentioned in that issue is too slow (and, as mentioned next, AFAIK doesn't work, since it tries to highlight each char individually).
Ideally, we could make IRust support async highlighting as the user types. This would have obvious performance benefits. I think the reason it feels (and is) slow is at least partially because IRust blocks until the highlighting is figured out. However, async may be overkill and/or difficult to implement.
An alternative is to check the typed word each time the user hits Space
, and if it is a Rust keyword, ends in a ()
, etc., highlight it (a.k.a. request the highlighting for it), and if not then do nothing. Unfortunately, this might be slow as before each time the user hits Space
. Regardless of the implementation though, we'll likely need to modify when we request the highlighting so that we request it for each word the user types (instead of each character individually, which didn't work when I tested it).
Another possibility (and one I would like to try) is to change the highlight
function to modify the IRust
struct's printer instead of creating a new one, which may save on performance (between this and changing when we request the highlight info, the speed issue may be fixed).
@sigmaSd Do you like any of the above ideas (or have more)? Once we figure out how we want to do this, I can get started on a PR (if that's necessary and okay with you).
Currently IRust code base got really missy, a lot of dead code a lot of useless abstractions (Printer!) and some optimization that doesnt make sense only make the code harder(printing each character instead of printing the whole buffer)
So a lot of things can be done and as suggested by @smlock I'll try to use this issue to keep track of the most important stuff that needs to be changed
handle_character should print the whole buffer instead of the inserted character, this allows for analysis of the buffer with each input(exp: highlighting), and for some nice abstractions to be built (exp: Buffer) fixed by #47
printer.rs and writer.rs conceptually one cant make a difference between them, we need to either merge them or change names and move functions around
Printer abstraction (used to print output) is not useful anymore, we need a better design for it
Cursor feels really complex, so match math games, I'm not really sure if there is a better way to deal with it, fixed by #44
Debouncer (used to delay racer search) can be a hit or miss, I want to improve this or looks for a new design
Add tests #45
Naming! variables, functions, some of them really have unhelpful names
Docs
Currently we have a lot of commands like :expand :asm that just wraps cargo plugins, I don't think its realistic to support all cargo plugins.
The user currently can use irust scripts for unimplemented commands but that seems to much work.
I propose adding :cargo $args
command that just invokes cargo
inside irust repl directory and forwards the user argument to it.
I think it should make things a lot better.
One implementation note, parsing user arguments should take in consideration arguments in quotes like :cargo plugin "quoted arg" arg2
Currently the user can tailor the theme to his liking by changing each item in theme.toml, but this doesn't allow predefined themes.
I propose translating to this themes structure:
--config--themes-------------|--default
|-theme.toml |---theme1
|---theme2
where theme.toml contains the theme name which is located under themes, and each theme have the items configuration.
It's up to discussion what should happen when the user use :color command, maybe it should create immediately a custom theme called customxxx1.toml with the change and the next changes during the repl session.
Ctrl+V
takes some time, as every character retriggers racer
. It'd be nice to have it running in a separate (maybe cancel-able) thread.
Checkout Ipython
history search for example (Ctrl-R)
error: there is no argument named `original_output`
--> ~/.cargo/registry/src/github.com-1ecc6299db9ec823/irust-1.50.0/src/irust/format.rs:64:205
|
64 | ...IRust/issues/new with the next text:\n\noriginal_output:\n{original_output}")
| ^^^^^^^^^^^^^^^^^
error: failed to compile `irust v1.50.0`, intermediate artifacts can be found at `/tmp/cargo-installSuKRik`
Caused by:
could not compile `irust` due to previous error
Updated 2 packages.
Failed to update irust.
I can write your factorial function in the readme and it accepts it but when I try to execute it or do just about anything, I get this error message.
The system cannot find the file specified. (os error 2)
I installed everything it asked to install on the first run. What can I try next?
I type this is in and run it and notice i've made a mistake.
In: fn factorial(n: size) -> usize {
..: match n {
..: 1 => 1,
..: n => n * factorial(n - 1),
..: }
..: }
In: :type factorial
fn item `fn([type error]) -> usize {factorial}`
In: factorial(12)
error[E0412]: cannot find type `size` in this scope
--> src\main.rs:2:17
|
2 | fn factorial(n: size) -> usize {
| ^^^^ help: a builtin type with a similar name exists: `isize`
So, I up-arrow and fix the mistake and run it again and now there are multiple definitions.
In: fn factorial(n: usize) -> usize {
..: match n {
..: 1 => 1,
..: n => n * factorial(n - 1),
..: }
..: }
In: factorial(12)
error[E0428]: the name `factorial` is defined multiple times
--> src\main.rs:8:1
|
2 | fn factorial(n: size) -> usize {
| ------------------------------ previous definition of the value `factorial` here
...
8 | fn factorial(n: usize) -> usize {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `factorial` redefined here
|
= note: `factorial` must be defined only once in the value namespace of this block
error[E0412]: cannot find type `size` in this scope
--> src\main.rs:2:17
|
2 | fn factorial(n: size) -> usize {
| ^^^^ help: a builtin type with a similar name exists: `isize`
What I meant for it to do was overwrite the first one with the second one. Not create two.
In other REPLs Ctrl+D
closes REPL if buffer is empty. Also, Ctrl+Z
can be used to send it to background (via SIGTSTP
). I noticed you are putting the terminal in raw mode, I'm not sure if it is necessary (do other REPLs do that, too?). Isn't there any other way to get Up and Down keypresses? Just asking, I genuinely don't know.
It will print Ferris ASCII art, would be great if its animated, but I accept statics too ^^
The initial issue #67
Currently we don't do any check if the input is a statement, this is so the repl feels fast for those operations at least.
But still its weird when errors only appears after using an expression.
I tested cargo check and it turns out its not that slow, so its ok to use it to check each statement,
Also this behaviour should be configurable.
Issue experienced with Bash 4.4.9 and the following terminal emulators:
To reproduce:
irust
My typed command does not display in the terminal. If I press enter, the command output is displayed; however, line breaks do not return to the start of the line.
To start with, implementation of this feature could solve #85 and possible other future errors.
It would be useful to test code for a crate to load the preexisting Cargo.toml
file, possibly with various settings that could affect crate loading, such as the current crate being a proc_macro
crate as described in the mentioned Issue, the features which a crate is loaded with, the cargo-features
in use, etc. It would also make the process of testing code for a crate faster, since we would not have to :add
each package separately, or load a preexisting file.
Recently I've been trying to test some ideas for a proc_macro
crate I'm building, and despite being able to load the proc_macro
crate through the extern crate proc_macro
, access to proc_macro
APIs is followed by this error:
Out: thread 'main' panicked at 'procedural macro API is used outside of a procedural macro'
Perhaps there could be a command to enable or disable these APIs?
Hi, thanks for making this :)
How hard would it be to make IRust useable for live scripting of a host, e.g. for music live coding in Rust?
It seems like this crate contains not only the Rust interpreter but also the code that deals with the console.
Would it be possible to use this crate as a lib and just use the interpreter part, and feed it as input the contents of a file which gets auto-reloaded from disk (via the hotwatch
crate), so that the editing could be done in one's favorite editor?
exp: Do you really want to exit ([y]/n)?
What can I do to execute the code with using release mode?
crossterm-0.26 introduce a new feature Support key release events for windows which makes irust typing twice in windows.
See
crossterm-rs/crossterm#752
helix-editor/helix#6133
And this is a fix method: helix-editor/helix#6139
pseudo code:
handle_key_up()
if cursor.is_at_first_line_of_input():
cycle_history_up()
else:
move_cursor_up()
handle_key_down()
if cursor.is_at_last_line_of_input():
cycle_history_down()
else:
move_cursor_down()
Hi! This looks like a cool project.
Have you considered using rust-anlayser
for autocompletion instead of racer
? In my experience, rust-anlayser has much better autocompletion than either racer or RLS.
The racer project isn't really actively maintained, and users are more likely to have rust-analyser installed than either RLS or racer.
As of RFC 2912, rust-analyser
is semi-official and there are plans to integrate it into dustup
.
The best solution would probably be to use a language-server client instead of depending on it directly. The [lsp-types](https://lib.rs/crates/lsp-types crate shouldn't make this too hard ๐
Also I believe evcxr depends on the rust-analyser internal API (and requires compiling it directly).
$ wget https://crates.io/api/v1/crates/irust/0.2.0/download
$ tar xf download
$ cd irust-0.2.0
$ ls -alh
total 12M
drwxr-xr-x 3 pzmarzly pzmarzly 4,0K 05-12 13:46 ./
drwxr-xr-x 4 pzmarzly pzmarzly 4,0K 05-12 13:46 ../
-rw-r--r-- 1 pzmarzly pzmarzly 899 1970-01-01 Cargo.toml
-rw-r--r-- 1 pzmarzly pzmarzly 337 05-12 11:40 Cargo.toml.orig
-rw-r--r-- 1 pzmarzly pzmarzly 641K 05-10 19:09 flamegraph.svg
-rw-r--r-- 1 pzmarzly pzmarzly 18 05-04 16:59 .gitignore
-rw-r--r-- 1 pzmarzly pzmarzly 27K 05-06 16:25 irust.png
-rw-r--r-- 1 pzmarzly pzmarzly 1,1K 05-10 19:09 LICENSE
-rw------- 1 pzmarzly pzmarzly 7,2M 05-09 21:36 perf.data
-rw------- 1 pzmarzly pzmarzly 4,1M 05-08 19:18 perf.data.old
-rw-r--r-- 1 pzmarzly pzmarzly 1,6K 05-12 11:41 README.md
drwxr-xr-x 3 pzmarzly pzmarzly 4,0K 05-12 13:46 src/
-rw-r--r-- 1 pzmarzly pzmarzly 80 05-10 19:09 t
-rw-r--r-- 1 pzmarzly pzmarzly 45 05-10 19:09 tt
-rw-r--r-- 1 pzmarzly pzmarzly 27 05-10 19:09 ttt
Consider using (and commiting) gitignore
IRust when used the first time, should check if rustfmt cargo-edit racer and feature optional dependencies and issue a one time warning about them being missing
Currently, after entering something like this into the REPL:
fn test(args: i32) -> i32 {
println!("You entered {}.", args);
return args * 3;
}
When trying to run it with test(3)
, I get an error:
In: test(3)
error[E0425]: cannot find function `test` in this scope
--> src/main.rs:3:2
|
3 | test(3)
| ^^^^ not found in this scope
If I put a semicolon at the end of test(3)
, so that it becomes test(3);
, I get no output from the REPL, and when I type :show
, I get this:
In: test(3);
In: :show
Current Repl Code:
fn main() {
test(3);
}
Is the ability to define functions within the REPL currently not a feature, or am I missing something? If it isn't a feature, is it wanted? If so, I would be happy to help with the implementation where I can.
OS: macOS
$ RUST_BACKTRACE=1 irust
-----------------------------------------------------------------------------------------------Welcome to IRust-----------------------------------------------------------------------------------------------
In: uthread 'main' panicked at 'IRust Out: Custom("No such file or directory (os error 2)")', src/libcore/result.rs:997:5
stack backtrace:
0: std::sys::unix::backtrace::tracing::imp::unwind_backtrace
1: std::sys_common::backtrace::_print
2: std::panicking::default_hook::{{closure}}
3: std::panicking::default_hook
4: std::panicking::rust_panic_with_hook
5: std::panicking::continue_panic_fmt
6: rust_begin_unwind
7: core::panicking::panic_fmt
8: core::result::unwrap_failed
9: irust::main
10: std::rt::lang_start::{{closure}}
11: std::panicking::try::do_call
12: __rust_maybe_catch_panic
13: std::rt::lang_start_internal
14: main
These settings https://github.com/sigmaSd/IRust/blob/master/crates/irust/src/irust/options.rs#L11-L24 https://github.com/sigmaSd/IRust/blob/master/crates/irust/src/irust/options.rs#L33-L34 I think belong to the themes config
I think its better to move them and the theme configuration would look something like
[rust]
keyword =
keyword2 =
...
[irust]
welcome_msg =
input_prompt =
input_color =
...
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.