Explorar el Código

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.
Dov Alperin hace 5 años
padre
commit
fb67bc2f4f
Se han modificado 1 ficheros con 42 adiciones y 2 borrados
  1. 42 2
      Userland/js.cpp

+ 42 - 2
Userland/js.cpp

@@ -44,6 +44,8 @@
 #include <LibLine/Editor.h>
 #include <LibLine/Editor.h>
 #include <stdio.h>
 #include <stdio.h>
 
 
+Vector<String> repl_statements;
+
 class ReplObject : public JS::GlobalObject {
 class ReplObject : public JS::GlobalObject {
 public:
 public:
     ReplObject();
     ReplObject();
@@ -54,6 +56,7 @@ private:
     static JS::Value exit_interpreter(JS::Interpreter&);
     static JS::Value exit_interpreter(JS::Interpreter&);
     static JS::Value repl_help(JS::Interpreter&);
     static JS::Value repl_help(JS::Interpreter&);
     static JS::Value load_file(JS::Interpreter&);
     static JS::Value load_file(JS::Interpreter&);
+    static JS::Value save_to_file(JS::Interpreter&);
 };
 };
 
 
 bool dump_ast = false;
 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);
     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()
 ReplObject::ReplObject()
 {
 {
     put_native_function("exit", exit_interpreter);
     put_native_function("exit", exit_interpreter);
     put_native_function("help", repl_help);
     put_native_function("help", repl_help);
     put_native_function("load", load_file);
     put_native_function("load", load_file);
+    put_native_function("save", save_to_file);
 }
 }
 
 
 ReplObject::~ReplObject()
 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)
 JS::Value ReplObject::exit_interpreter(JS::Interpreter& interpreter)
 {
 {
     if (!interpreter.argument_count())
     if (!interpreter.argument_count())
@@ -274,7 +314,7 @@ void repl(JS::Interpreter& interpreter)
         String piece = read_next_piece();
         String piece = read_next_piece();
         if (piece.is_empty())
         if (piece.is_empty())
             continue;
             continue;
-
+        repl_statements.append(piece);
         auto program = JS::Parser(JS::Lexer(piece)).parse_program();
         auto program = JS::Parser(JS::Lexer(piece)).parse_program();
         if (dump_ast)
         if (dump_ast)
             program->dump(0);
             program->dump(0);