#ifndef JUCI_TERMINAL_H_ #define JUCI_TERMINAL_H_ #include #include #include "gtkmm.h" #include #include #include #include #include "process.hpp" #include "dispatcher.h" #include #include class Terminal : public Gtk::TextView { public: class InProgress { friend class Terminal; public: InProgress(const std::string& start_msg); ~InProgress(); void done(const std::string& msg); void cancel(const std::string& msg); private: void start(const std::string& msg); size_t line_nr; std::atomic stop; std::thread wait_thread; }; private: Terminal(); public: static Terminal &get() { static Terminal singleton; return singleton; } int process(const std::string &command, const boost::filesystem::path &path="", bool use_pipes=true); int process(std::istream &stdin_stream, std::ostream &stdout_stream, const std::string &command, const boost::filesystem::path &path=""); void async_process(const std::string &command, const boost::filesystem::path &path="", std::function callback=nullptr, bool quiet=false); void kill_last_async_process(bool force=false); void kill_async_processes(bool force=false); size_t print(const std::string &message, bool bold=false); std::shared_ptr print_in_progress(std::string start_msg); void async_print(const std::string &message, bool bold=false); void async_print(size_t line_nr, const std::string &message); void configure(); void clear(); protected: bool on_motion_notify_event (GdkEventMotion* motion_event) override; bool on_button_press_event(GdkEventButton* button_event) override; bool on_key_press_event(GdkEventKey *event) override; private: Dispatcher dispatcher; Glib::RefPtr bold_tag; Glib::RefPtr link_tag; Glib::RefPtr link_mouse_cursor; Glib::RefPtr default_mouse_cursor; size_t deleted_lines=0; const static std::regex link_regex; void apply_link_tags(Gtk::TextIter start_iter, Gtk::TextIter end_iter); std::vector> processes; std::mutex processes_mutex; Glib::ustring stdin_buffer; std::unordered_set in_progresses; std::mutex in_progresses_mutex; }; #endif // JUCI_TERMINAL_H_