Brittany-Reid / node_code_query

13 stars 3 forks source link

Editor mode #28

Open Brittany-Reid opened 4 years ago

Brittany-Reid commented 4 years ago

The REPL design of read-eval-print-loop is confusing and difficult to use when programming. For example, user's cannot remove or modify specific lines of code. While the node.js REPL contains a save and load functionality, to write to and load from files, it doesn't have a way to view the previously written lines within the REPL.

It would be a great idea to integrate an improved editor mode that bridges the gap between REPL and code editor. Not forcing user's to put their code into an external editor means we can have a more comprehensive tool, and be able to use the user's code to help recommend snippets.

The node.js REPL already has the .editor command which is used for multiline input, but doesn't show what code has already been processed. I think for now I will just overwrite this.

I will need to make a new prompt that functions more like an editor. We could in the future allow a custom command like vim, but for now it will just be a prompt with modified keybindings and UI because that's the simplest.

The only caveat is that it appears loading in a file into the REPL runs it again, so this will need to be documented. I don't think there will be any avoiding this, as the REPL must run code to maintain it's context. And as per the general read-eval-print-loop design, this happens every line.

User Story

I been using the REPL to try out different file reading packages. I save the REPL, which is the only way I can see what code snippets I've tried besides my terminal history, but the file is messy:

const package1 = require("package1")
var result;

//#1 how to read files
result = package1.readFile("text.txt");

//#2 how to read files with a specified encoding
result = package1.readFile("text.txt", {encoding: "utf-8"});

const package2 = require("package2")

//#3 get an array of lines from a file
var result2 = package2.readLines("text.txt");

I have decided I want to use code snippet2 from package1, so I no longer need package2. However, I now want to see how package1 goes reading a larger file, and then maybe try out some other things in NCQ, so I don't want the unwanted code interfering or slowing things down.

I don't want to start a new REPL and I don't want to clear the REPL and get rid of my snippets. I just want to make changes to the lines I've already submitted.

I can't use an external editor then the .load command, as this only appends onto my existing REPL context. I would have to use .clear beforehand. And I don't really want to open up my editor just to change a few lines.

So I would enter some command like the node.js REPL editor command that already exists:

.editor

And a new prompt would open, showing me my code, and allowing me to edit it.

< NCQ EDITOR >
================================
const package1 = require("package1")
var result;

//#1 how to read files
result = package1.readFile("text.txt");

//#2 how to read files with a specified encoding
result = package1.readFile("text.txt", {encoding: "utf-8"});

const package2 = require("package2")

//#3 get an array of lines from a file
var result2 = package2.readLines("text.txt"); 
===============================
fn | Save | fn | Exit

I could press a button to save and a button to cancel out. I save the file as:

const package1 = require("package1")
var result;

//#2 how to read files with a specified encoding
result = package1.readFile("largeFile.txt", {encoding: "utf-8"});

Then, when I return to the REPL, this updated code will run. If I type:

console.log(result2);

The variable will now be undefined. If I looked for snippets, any snippets containing a variable result2 would no longer conflict with my code and cause errors (meaning they could be ranked higher than previously). The REPL now more accurately represents the environment I will be using this code in later.

Brittany-Reid commented 4 years ago

Okay I have added an editor mode and built an editor style prompt with commit a410a47. You would open the application, then enter the REPL:

image

Then, you could write some commands to the REPL:

image

Then you could use the .editor command to switch to editor mode:

image

And it will load showing even incorrect lines I wrote, or the function a() I defined twice.

image

Then if you remove the commands you didn't want and add some function calls:

image

Then press f11 to save, which will load these into the REPL, execute the code and return the REPL prompt: image

I could now call a() again:

image

If I view the file in my editor, it will be saved (but without the second a() because I didn't save this):

image

And if I wanted to save that new call, I would just use the built in .save command node.js provides.

@damorimRG is this what you were thinking?

Things to do before I close this:

There is a bug when backspacing at start of text, likely because there is no "NCQ>" prompt to check for. I will fix this. The .editor command is also not consistent with our other commands. If we were to make them consistent I would argue for the . style, as currently our function() commands are accessible to the user (part of the REPL instances code). It would be a security issue I imagine if we were to ever hook into any external system, as user's could overwrite the functions. But it is low on the list of things to do.

Brittany-Reid commented 4 years ago

I can't reproduce the backspace issue consistently. I had a similar bug in the prompt when getting samples("a package") from the history, then deleting samples to write install, but also couldn't reproduce again. I've had a look at the delete function and I can't figure out how the cursor is able to escape at all.

Anyway, the next thing to do is add a line delete button.

Brittany-Reid commented 4 years ago

I have added deleting of lines and deleting of words 👍

The line deletion is straight forward, if you are on a line, that line is deleted in entirety. The editor has f6 mapped, otherwise you can use the apparently according to wikipedia ^u character (ctrl+u) to delete lines.

You can also delete words by pressing ctrl+backspace. I based this off VScode, so the line:

async function(){

Can be seperated into 3 words:

[ "async ", "function", "(){"]

A bit fancy but I like it for a code editor.

This one doesn't have a function key binding in editor mode because I'm not so sure about it yet.

Both work outside the editor (except for line deletion on the cli, as it is single line, though it could just be an alias for clear).

The line deletion should work immediately, but I need to test the non-function key bindings for Linux.

Brittany-Reid commented 4 years ago

Ah, the word deletion is not triggered the same way in Linux. it is ctrl+w.

The line deletion works fine for both ctrl+u and the f6 button in the editor.