Browse Source

Terminal now handles input, although only the most basic keys are handled.

merge-requests/365/head
eidheim 10 years ago
parent
commit
de23e8c864
  1. 102
      src/terminal.cc
  2. 13
      src/terminal.h
  3. 3
      src/window.cc
  4. 1
      src/window.h

102
src/terminal.cc

@ -102,17 +102,15 @@ void Terminal::InProgress::cancel(const std::string& msg) {
} }
Terminal::Terminal() { Terminal::Terminal() {
text_view.set_editable(false); set_editable(false);
scrolled_window.add(text_view);
add(scrolled_window); signal_size_allocate().connect([this](Gtk::Allocation& allocation){
auto end=get_buffer()->create_mark(get_buffer()->end());
text_view.signal_size_allocate().connect([this](Gtk::Allocation& allocation){ scroll_to(end);
auto end=text_view.get_buffer()->create_mark(text_view.get_buffer()->end()); get_buffer()->delete_mark(end);
text_view.scroll_to(end);
text_view.get_buffer()->delete_mark(end);
}); });
bold_tag=text_view.get_buffer()->create_tag(); bold_tag=get_buffer()->create_tag();
bold_tag->property_weight()=PANGO_WEIGHT_BOLD; bold_tag->property_weight()=PANGO_WEIGHT_BOLD;
async_print_dispatcher.connect([this](){ async_print_dispatcher.connect([this](){
async_print_strings_mutex.lock(); async_print_strings_mutex.lock();
@ -188,10 +186,11 @@ void Terminal::async_execute(const std::string &command, const boost::filesystem
cd_path_and_command=command; cd_path_and_command=command;
int stdin, stdout, stderr; int stdin, stdout, stderr;
async_execute_pids_mutex.lock(); async_executes_mutex.lock();
stdin_buffer.clear();
auto pid=popen3(cd_path_and_command.c_str(), stdin, stdout, stderr); auto pid=popen3(cd_path_and_command.c_str(), stdin, stdout, stderr);
async_execute_pids.emplace_back(pid); async_executes.emplace_back(pid, stdin);
async_execute_pids_mutex.unlock(); async_executes_mutex.unlock();
if (pid<=0) { if (pid<=0) {
async_print("Error: Failed to run command: " + command + "\n"); async_print("Error: Failed to run command: " + command + "\n");
@ -225,17 +224,18 @@ void Terminal::async_execute(const std::string &command, const boost::filesystem
int exit_code; int exit_code;
waitpid(pid, &exit_code, 0); waitpid(pid, &exit_code, 0);
async_execute_pids_mutex.lock(); async_executes_mutex.lock();
for(auto it=async_execute_pids.begin();it!=async_execute_pids.end();it++) { for(auto it=async_executes.begin();it!=async_executes.end();it++) {
if(*it==pid) { if(it->first==pid) {
async_execute_pids.erase(it); async_executes.erase(it);
break; break;
} }
} }
async_execute_pids_mutex.unlock(); stdin_buffer.clear();
close(stdin); close(stdin);
close(stdout); close(stdout);
close(stderr); close(stderr);
async_executes_mutex.unlock();
if(callback) if(callback)
callback(exit_code); callback(exit_code);
@ -245,43 +245,45 @@ void Terminal::async_execute(const std::string &command, const boost::filesystem
} }
void Terminal::kill_last_async_execute(bool force) { void Terminal::kill_last_async_execute(bool force) {
async_execute_pids_mutex.lock(); async_executes_mutex.lock();
if(force) if(async_executes.size()>0) {
kill(-async_execute_pids.back(), SIGTERM); if(force)
else kill(-async_executes.back().first, SIGTERM);
kill(-async_execute_pids.back(), SIGINT); else
async_execute_pids_mutex.unlock(); kill(-async_executes.back().first, SIGINT);
}
async_executes_mutex.unlock();
} }
void Terminal::kill_async_executes(bool force) { void Terminal::kill_async_executes(bool force) {
async_execute_pids_mutex.lock(); async_executes_mutex.lock();
for(auto &pid: async_execute_pids) { for(auto &async_execute: async_executes) {
if(force) if(force)
kill(-pid, SIGTERM); kill(-async_execute.first, SIGTERM);
else else
kill(-pid, SIGINT); kill(-async_execute.first, SIGINT);
} }
async_execute_pids_mutex.unlock(); async_executes_mutex.unlock();
} }
int Terminal::print(const std::string &message, bool bold){ int Terminal::print(const std::string &message, bool bold){
INFO("Terminal: PrintMessage"); INFO("Terminal: PrintMessage");
if(bold) if(bold)
text_view.get_buffer()->insert_with_tag(text_view.get_buffer()->end(), message, bold_tag); get_buffer()->insert_with_tag(get_buffer()->end(), message, bold_tag);
else else
text_view.get_buffer()->insert(text_view.get_buffer()->end(), message); get_buffer()->insert(get_buffer()->end(), message);
return text_view.get_buffer()->end().get_line(); return get_buffer()->end().get_line();
} }
void Terminal::print(int line_nr, const std::string &message, bool bold){ void Terminal::print(int line_nr, const std::string &message, bool bold){
INFO("Terminal: PrintMessage at line " << line_nr); INFO("Terminal: PrintMessage at line " << line_nr);
auto iter=text_view.get_buffer()->get_iter_at_line(line_nr); auto iter=get_buffer()->get_iter_at_line(line_nr);
while(!iter.ends_line()) while(!iter.ends_line())
iter++; iter++;
if(bold) if(bold)
text_view.get_buffer()->insert_with_tag(iter, message, bold_tag); get_buffer()->insert_with_tag(iter, message, bold_tag);
else else
text_view.get_buffer()->insert(iter, message); get_buffer()->insert(iter, message);
} }
std::shared_ptr<Terminal::InProgress> Terminal::print_in_progress(std::string start_msg) { std::shared_ptr<Terminal::InProgress> Terminal::print_in_progress(std::string start_msg) {
@ -299,3 +301,35 @@ void Terminal::async_print(const std::string &message, bool bold) {
if(dispatch) if(dispatch)
async_print_dispatcher(); async_print_dispatcher();
} }
bool Terminal::on_key_press_event(GdkEventKey *event) {
async_executes_mutex.lock();
if(async_executes.size()>0) {
get_buffer()->place_cursor(get_buffer()->end());
auto unicode=gdk_keyval_to_unicode(event->keyval);
char chr=(char)unicode;
if(unicode>=32 && unicode<=126) {
stdin_buffer+=chr;
get_buffer()->insert_at_cursor(stdin_buffer.substr(stdin_buffer.size()-1));
scroll_to(get_buffer()->get_insert());
}
else if(event->keyval==GDK_KEY_BackSpace) {
if(stdin_buffer.size()>0 && get_buffer()->get_char_count()>0) {
auto iter=get_buffer()->end();
iter--;
stdin_buffer.pop_back();
get_buffer()->erase(iter, get_buffer()->end());
scroll_to(get_buffer()->get_insert());
}
}
else if(event->keyval==GDK_KEY_Return) {
stdin_buffer+='\n';
write(async_executes.back().second, stdin_buffer.c_str(), stdin_buffer.size());
get_buffer()->insert_at_cursor(stdin_buffer.substr(stdin_buffer.size()-1));
stdin_buffer.clear();
scroll_to(get_buffer()->get_insert());
}
}
async_executes_mutex.unlock();
return true;
}

13
src/terminal.h

@ -9,7 +9,7 @@
#include <atomic> #include <atomic>
#include <list> #include <list>
class Terminal : public Gtk::HBox { class Terminal : public Gtk::TextView {
public: public:
class InProgress { class InProgress {
public: public:
@ -35,17 +35,18 @@ public:
void print(int line_nr, const std::string &message, bool bold=false); void print(int line_nr, const std::string &message, bool bold=false);
std::shared_ptr<InProgress> print_in_progress(std::string start_msg); std::shared_ptr<InProgress> print_in_progress(std::string start_msg);
void async_print(const std::string &message, bool bold=false); void async_print(const std::string &message, bool bold=false);
protected:
bool on_key_press_event(GdkEventKey *event);
private: private:
Gtk::TextView text_view;
Gtk::ScrolledWindow scrolled_window;
Glib::Dispatcher async_print_dispatcher; Glib::Dispatcher async_print_dispatcher;
std::vector<std::pair<std::string, bool> > async_print_strings; std::vector<std::pair<std::string, bool> > async_print_strings;
std::mutex async_print_strings_mutex; std::mutex async_print_strings_mutex;
Glib::RefPtr<Gtk::TextTag> bold_tag; Glib::RefPtr<Gtk::TextTag> bold_tag;
std::mutex async_execute_pids_mutex; std::mutex async_executes_mutex;
std::list<pid_t> async_execute_pids; std::list<std::pair<pid_t, int> > async_executes;
std::string stdin_buffer;
}; };
#endif // JUCI_TERMINAL_H_ #endif // JUCI_TERMINAL_H_

3
src/window.cc

@ -32,7 +32,8 @@ Window::Window() : box(Gtk::ORIENTATION_VERTICAL), notebook(directories), compil
vpaned.set_position(300); vpaned.set_position(300);
vpaned.pack1(directory_and_notebook_panes, true, false); vpaned.pack1(directory_and_notebook_panes, true, false);
terminal_vbox.pack_start(*Singleton::terminal()); terminal_scrolled_window.add(*Singleton::terminal());
terminal_vbox.pack_start(terminal_scrolled_window);
status_hbox.pack_end(*Singleton::status(), Gtk::PACK_SHRINK); status_hbox.pack_end(*Singleton::status(), Gtk::PACK_SHRINK);
terminal_vbox.pack_end(status_hbox, Gtk::PACK_SHRINK); terminal_vbox.pack_end(status_hbox, Gtk::PACK_SHRINK);
vpaned.pack2(terminal_vbox, true, true); vpaned.pack2(terminal_vbox, true, true);

1
src/window.h

@ -22,6 +22,7 @@ private:
Gtk::Paned directory_and_notebook_panes; Gtk::Paned directory_and_notebook_panes;
Gtk::VBox notebook_vbox; Gtk::VBox notebook_vbox;
Gtk::VBox terminal_vbox; Gtk::VBox terminal_vbox;
Gtk::ScrolledWindow terminal_scrolled_window;
Gtk::HBox status_hbox; Gtk::HBox status_hbox;
EntryBox entry_box; EntryBox entry_box;
Menu menu; Menu menu;

Loading…
Cancel
Save