Skip to content
This repository has been archived by the owner on Nov 18, 2021. It is now read-only.

proposal: cue repl #356

Closed
philipdexter opened this issue Apr 21, 2020 · 6 comments
Closed

proposal: cue repl #356

philipdexter opened this issue Apr 21, 2020 · 6 comments
Labels
FeatureRequest New feature or request

Comments

@philipdexter
Copy link

Is your feature request related to a problem? Please describe.
From LISP to Python to Haskell, old and new languages alike have found that providing developers with a REPL greatly improves the relationship between the developer and the language runtime. CUE does not currently have a REPL, reducing the ease at which CUE beginners and experts alike interact with CUE.

Describe the solution you'd like
A CUE REPL :)

Describe alternatives you've considered
The current solution involves a text editor and a command line, constantly context switching between the two.

Additional context
Below is a proposal draft.

Repl proposal

Introduce cue repl.

Some exploratory work has been done at https://github.com/philipdexter/cue.

An (out of date) example of it being used can be seen at https://asciinema.org/a/xgm2BpkyOVUNr5hjqaSOMKMT3

Use

Running cue repl within a module directory should start the repl with the module loaded.
Running cue repl outside of a module will start the repl with a blank slate.

The repl should have line editing features provided in common readline libraries.

Commands

Some initial command ideas could be

  • help -- print help text
  • l/lookup <path> -- print the value at <path>
  • h/history -- print history indexed by histnums
  • p/print -- print the current value
  • r/restore <histnum> -- restore the value at <histnum>
  • s/save <where> -- save the current value into <where>

Repl commands can be invoked by prefixing a ;.

For example the print command, which prints the current structure, can be invoked with ;p or ;print.

@philipdexter philipdexter added the FeatureRequest New feature or request label Apr 21, 2020
@mpvl
Copy link
Contributor

mpvl commented Apr 24, 2020

@philipdexter I, for one, am a big fan of this proposal.

Few questions:

Running cue repl within a module directory should start the repl with the module loaded.
How would that work with different packages? I suspect it is easiest to load only one package. Alternative, there may be a command to switch packages between modules. Even so, loading all packages in a module might be heavy weight!

p/print -- print the current value

This could be an identifier, like @ or $, obviating the command. OTOH, in practice one really wants to either print an "exported" value or "schema". It may be an idea to mimic the tool commands her (def, export, vet).

l/lookup -- print the value at

I think this command is unnecessary assuming you allow expressions to be evaluated by default.

Repl commands can be invoked by prefixing a ;

Just curious, is this a common idiom?

Some possible other commands that come to mind:

  • "cd" into a path in the tree and evaluate expressions there.
  • "import" or some way to import more files. These could also be JSON/YAML.
  • a way to "add"/"embed" data manually

I guess the latter could be done with "field" declarations. So without a command, an expression would evaluate, while an field: value would include. I'm not sure, but it may be too dangerous though, as there is a thin line, syntactically, between expression and declarations. Also, the value {a: 1} could be seen as an expression to evaluate, or an embedding.

@philipdexter
Copy link
Author

;
Just curious, is this a common idiom?

No, I think it's probably better to use either : (pretty common) or % (used by ipython).

"import" or some way to import more files. These could also be JSON/YAML.

Interestingly, this already works since import "..." is a CUE statement. The only issue is that until the import is used, the print command will say "imported and not used..."

a way to "add"/"embed" data manually
guess the latter could be done with "field" declarations. So without a command, an expression would evaluate, while an field: value would include. I'm not sure, but it may be too dangerous though, as there is a thin line, syntactically, between expression and declarations. Also, the value {a: 1} could be seen as an expression to evaluate, or an embedding.

The repl currently works like: anything not starting with ; is read as a cue statement and is added to the current instance. This means something like a means to embed a. This could change though, since the most common use case might be to just type expressions and have cue evaluate them. Then, to add/embed values, maybe we have some special @ syntax or something.

@verdverm
Copy link
Contributor

This is pretty cool if you haven't tried it!

@mpvl
Copy link
Contributor

mpvl commented Apr 28, 2020

No, I think it's probably better to use either : (pretty common) or % (used by ipython).

Both work for me. I had a 2 decade-streak of using Vi, so I'm inclined to go with :. I have anticipated a declaration in the past that starts with :, so it is a bit iffy, though. Nice thing about ; is that it is less typing than either : or %, so it is certainly not a bad choice! We can keep it as a working choice.

Interestingly, this already works since import "..." is a CUE statement. The only issue is that until the import is used, the print command will say "imported and not used..."

hah! Yes that is true. It is probably okay to just filter that error. We can do something more principled later.

The repl currently works like: anything not starting with ; is read as a cue statement and is added to the current instance. This means something like a means to embed a. This could change though, since the most common use case might be to just type expressions and have cue evaluate them.

Yeah, I think that is the case. I also think this is the expected behavior of REPLs.

Then, to add/embed values, maybe we have some special @ syntax or something.

That is the tricky design part. It probably makes sense to be consistent. So, say, to add something one would always have to start with @.

Another idea is that to add one needs to do:

 Path ":" Value

That is, Value is unified with any value selected by Path. So

a.b.c : 5

would set value 5 at path a.b.c. Later, Path could be generalized to allow any query. So

a.[>"foo"].d : 5

As the use of : never results in a valid expression, it is clear we are adding something. A missing Path could mean the current value, so

: a

would then mean "embed a". Not sure how to fit in import, but that could still be import "foo" perhaps.

We probably also want to allow a: b: c: d, so not sure how to rhyme that, but I think something along these lines will work.

@philipdexter
Copy link
Author

As the use of : never results in a valid expression

Isn't {a:1} a valid expression?

Another idea is that to add one needs to do:
Path ":" Value

Yeah, that looks nice. Probably could piggyback off the query syntax implementation there.

Another thing to think about is supporting multiline statements. Perhaps ideally the repl could always detect when a statement is incomplete, and keep reading until it's completed. That hasn't been implemented yet though, so right now I've added a ;@ command which will change to multiline mode. When another ;@ is seen, the multiline mode ends and the multiline input is added.

@cueckoo
Copy link

cueckoo commented Jul 3, 2021

This issue has been migrated to cue-lang/cue#356.

For more details about CUE's migration to a new home, please see cue-lang/cue#1078.

@cueckoo cueckoo closed this as completed Jul 3, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
FeatureRequest New feature or request
Projects
None yet
Development

No branches or pull requests

4 participants