1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 18:47:34 +00:00

Userland/JS: Add the 'save("file")' repl command

Calling save("file") in a repl saves all the typed lines so far
into the specified file. It currently does not have great support for
multilined functions since those get turned into one line.
This commit is contained in:
Dov Alperin 2020-04-02 11:52:40 -04:00 committed by Andreas Kling
parent 56ca91b9f8
commit fb67bc2f4f

View file

@ -44,6 +44,8 @@
#include <LibLine/Editor.h>
#include <stdio.h>
Vector<String> repl_statements;
class ReplObject : public JS::GlobalObject {
public:
ReplObject();
@ -54,6 +56,7 @@ private:
static JS::Value exit_interpreter(JS::Interpreter&);
static JS::Value repl_help(JS::Interpreter&);
static JS::Value load_file(JS::Interpreter&);
static JS::Value save_to_file(JS::Interpreter&);
};
bool dump_ast = false;
@ -210,17 +213,54 @@ StringView strip_shebang(AK::ByteBuffer file_contents)
return StringView((const char*)file_contents.data() + i, file_contents.size() - i);
}
bool write_to_file(const StringView& path)
{
int fd = open_with_path_length(path.characters_without_null_termination(), path.length(), O_WRONLY | O_CREAT | O_TRUNC, 0666);
for (size_t i = 0; i < repl_statements.size(); i++) {
auto line = repl_statements[i];
if (line.length() && i != repl_statements.size() - 1) {
ssize_t nwritten = write(fd, line.characters(), line.length());
if (nwritten < 0) {
close(fd);
return false;
}
}
if (i != repl_statements.size() - 1) {
char ch = '\n';
ssize_t nwritten = write(fd, &ch, 1);
if (nwritten != 1) {
perror("write");
close(fd);
return false;
}
}
}
close(fd);
return true;
}
ReplObject::ReplObject()
{
put_native_function("exit", exit_interpreter);
put_native_function("help", repl_help);
put_native_function("load", load_file);
put_native_function("save", save_to_file);
}
ReplObject::~ReplObject()
{
}
JS::Value ReplObject::save_to_file(JS::Interpreter& interpreter)
{
if (!interpreter.argument_count())
return JS::Value(false);
String save_path = interpreter.argument(0).to_string();
StringView path = StringView(save_path.characters());
if (write_to_file(path)) {
return JS::Value(true);
}
return JS::Value(false);
}
JS::Value ReplObject::exit_interpreter(JS::Interpreter& interpreter)
{
if (!interpreter.argument_count())
@ -274,7 +314,7 @@ void repl(JS::Interpreter& interpreter)
String piece = read_next_piece();
if (piece.is_empty())
continue;
repl_statements.append(piece);
auto program = JS::Parser(JS::Lexer(piece)).parse_program();
if (dump_ast)
program->dump(0);