浏览代码

Assistant: Add provider to run a command in a terminal

Prefix text with "$" in the Assistant text box to run a command in a
forked terminal. For example, "$ top" or "$ top -s pid".
Timothy Flynn 4 年之前
父节点
当前提交
d69691a26b

+ 29 - 1
Userland/Applications/Assistant/Providers.cpp

@@ -17,6 +17,9 @@
 #include <LibJS/Lexer.h>
 #include <LibJS/Lexer.h>
 #include <LibJS/Parser.h>
 #include <LibJS/Parser.h>
 #include <LibJS/Runtime/GlobalObject.h>
 #include <LibJS/Runtime/GlobalObject.h>
+#include <errno.h>
+#include <serenity.h>
+#include <spawn.h>
 #include <unistd.h>
 #include <unistd.h>
 
 
 namespace Assistant {
 namespace Assistant {
@@ -41,6 +44,19 @@ void FileResult::activate() const
     Desktop::Launcher::open(URL::create_with_file_protocol(title()));
     Desktop::Launcher::open(URL::create_with_file_protocol(title()));
 }
 }
 
 
+void TerminalResult::activate() const
+{
+    pid_t pid;
+    char const* argv[] = { "Terminal", "-e", title().characters(), nullptr };
+
+    if ((errno = posix_spawn(&pid, "/bin/Terminal", nullptr, nullptr, const_cast<char**>(argv), environ))) {
+        perror("posix_spawn");
+    } else {
+        if (disown(pid) < 0)
+            perror("disown");
+    }
+}
+
 void URLResult::activate() const
 void URLResult::activate() const
 {
 {
     Desktop::Launcher::open(URL::create_with_url_or_path(title()));
     Desktop::Launcher::open(URL::create_with_url_or_path(title()));
@@ -48,7 +64,7 @@ void URLResult::activate() const
 
 
 void AppProvider::query(String const& query, Function<void(Vector<NonnullRefPtr<Result>>)> on_complete)
 void AppProvider::query(String const& query, Function<void(Vector<NonnullRefPtr<Result>>)> on_complete)
 {
 {
-    if (query.starts_with("="))
+    if (query.starts_with("=") || query.starts_with('$'))
         return;
         return;
 
 
     Vector<NonnullRefPtr<Result>> results;
     Vector<NonnullRefPtr<Result>> results;
@@ -156,6 +172,18 @@ void FileProvider::build_filesystem_cache()
         return 0; }, [this](auto) { m_building_cache = false; });
         return 0; }, [this](auto) { m_building_cache = false; });
 }
 }
 
 
+void TerminalProvider::query(String const& query, Function<void(Vector<NonnullRefPtr<Result>>)> on_complete)
+{
+    if (!query.starts_with('$'))
+        return;
+
+    auto command = query.substring(1);
+
+    Vector<NonnullRefPtr<Result>> results;
+    results.append(adopt_ref(*new TerminalResult(move(command))));
+    on_complete(results);
+}
+
 void URLProvider::query(String const& query, Function<void(Vector<NonnullRefPtr<Result>>)> on_complete)
 void URLProvider::query(String const& query, Function<void(Vector<NonnullRefPtr<Result>>)> on_complete)
 {
 {
     URL url = URL(query);
     URL url = URL(query);

+ 20 - 5
Userland/Applications/Assistant/Providers.h

@@ -85,6 +85,16 @@ public:
     void activate() const override;
     void activate() const override;
 };
 };
 
 
+class TerminalResult : public Result {
+public:
+    explicit TerminalResult(String command)
+        : Result(GUI::Icon::default_icon("app-terminal").bitmap_for_size(16), move(command), "Run command in Terminal"sv, 100)
+    {
+    }
+    ~TerminalResult() override = default;
+    void activate() const override;
+};
+
 class URLResult : public Result {
 class URLResult : public Result {
 public:
 public:
     explicit URLResult(const URL& url)
     explicit URLResult(const URL& url)
@@ -99,31 +109,36 @@ class Provider {
 public:
 public:
     virtual ~Provider() = default;
     virtual ~Provider() = default;
 
 
-    virtual void query(const String&, Function<void(Vector<NonnullRefPtr<Result>>)> on_complete) = 0;
+    virtual void query(const String&, Function<void(NonnullRefPtrVector<Result>)> on_complete) = 0;
 };
 };
 
 
 class AppProvider : public Provider {
 class AppProvider : public Provider {
 public:
 public:
-    void query(String const& query, Function<void(Vector<NonnullRefPtr<Result>>)> on_complete) override;
+    void query(String const& query, Function<void(NonnullRefPtrVector<Result>)> on_complete) override;
 };
 };
 
 
 class CalculatorProvider : public Provider {
 class CalculatorProvider : public Provider {
 public:
 public:
-    void query(String const& query, Function<void(Vector<NonnullRefPtr<Result>>)> on_complete) override;
+    void query(String const& query, Function<void(NonnullRefPtrVector<Result>)> on_complete) override;
 };
 };
 
 
 class FileProvider : public Provider {
 class FileProvider : public Provider {
 public:
 public:
-    void query(String const& query, Function<void(Vector<NonnullRefPtr<Result>>)> on_complete) override;
+    void query(String const& query, Function<void(NonnullRefPtrVector<Result>)> on_complete) override;
     void build_filesystem_cache();
     void build_filesystem_cache();
 
 
 private:
 private:
-    RefPtr<Threading::BackgroundAction<Vector<NonnullRefPtr<Result>>>> m_fuzzy_match_work;
+    RefPtr<Threading::BackgroundAction<NonnullRefPtrVector<Result>>> m_fuzzy_match_work;
     bool m_building_cache { false };
     bool m_building_cache { false };
     Vector<String> m_full_path_cache;
     Vector<String> m_full_path_cache;
     Queue<String> m_work_queue;
     Queue<String> m_work_queue;
 };
 };
 
 
+class TerminalProvider : public Provider {
+public:
+    void query(String const& query, Function<void(NonnullRefPtrVector<Result>)> on_complete) override;
+};
+
 class URLProvider : public Provider {
 class URLProvider : public Provider {
 public:
 public:
     void query(String const& query, Function<void(Vector<NonnullRefPtr<Result>>)> on_complete) override;
     void query(String const& query, Function<void(Vector<NonnullRefPtr<Result>>)> on_complete) override;

+ 5 - 0
Userland/Applications/Assistant/main.cpp

@@ -139,6 +139,10 @@ public:
             recv_results(query, results);
             recv_results(query, results);
         });
         });
 
 
+        m_terminal_provider.query(query, [=, this](auto results) {
+            recv_results(query, results);
+        });
+
         m_url_provider.query(query, [=, this](auto results) {
         m_url_provider.query(query, [=, this](auto results) {
             recv_results(query, results);
             recv_results(query, results);
         });
         });
@@ -182,6 +186,7 @@ private:
     AppProvider m_app_provider;
     AppProvider m_app_provider;
     CalculatorProvider m_calculator_provider;
     CalculatorProvider m_calculator_provider;
     FileProvider m_file_provider;
     FileProvider m_file_provider;
+    TerminalProvider m_terminal_provider;
     URLProvider m_url_provider;
     URLProvider m_url_provider;
 
 
     Threading::Lock m_lock;
     Threading::Lock m_lock;