diff --git a/Userland/js.cpp b/Userland/js.cpp index 951f866041..22f2e2245c 100644 --- a/Userland/js.cpp +++ b/Userland/js.cpp @@ -44,6 +44,8 @@ #include #include +Vector 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);