[PATCH 3/3] Add console widget to DBGPerspective
- From: Fabien Parent <parent f gmail com>
- To: nemiver-list gnome org
- Subject: [PATCH 3/3] Add console widget to DBGPerspective
- Date: Mon, 28 Oct 2013 18:47:50 +0100
* configure.ac: Check for readline dependency.
* src/persp/dbgperspective/Makefile.am: Add new files.
* src/persp/dbgperspective/menus/menus.xml: Add Console menu.
* src/persp/dbgperspective/nmv-console.cc: New APIs.
* src/persp/dbgperspective/nmv-console.h: New APIs.
* src/persp/dbgperspective/nmv-dbg-perspective.cc
(DBGPerspective::OpenCommand): New APIs.
(DBGPerspective::on_activate_console_view): New API.
(DBGPerspective::dbg_console): New API.
(DBGPerspective::console_box): New API.
(DBGPerspective::on_switch_page_signal): Notify the console of the
change of the currently focused source file.
(DBGPerspective::init_actions): Add action for console menu.
(DBGPerspective::add_views_to_layout): Add console to layout manager.
(DBGPerspective::execute_commands_from_line): Removed.
(DBGPerspective::execute_commands_from_file): Delegate the execution
of commands to the console.
(DBGPerspective::execute_commands_from_fd): Delegate the execution
of commands to the console.
* src/persp/dbgperspective/nmv-dbg-perspective.h
(ViewsIndex::CONSOLE_VIEW_INDEX): Add view index for the console.
* src/uicommon/nmv-terminal.cc (Terminal::slave_fd): New API.
* src/uicommon/nmv-terminal.h (Terminal::slave_fd): New API.
---
configure.ac | 3 +-
src/persp/dbgperspective/Makefile.am | 4 +-
src/persp/dbgperspective/menus/menus.xml | 2 +
src/persp/dbgperspective/nmv-console.cc | 440 ++++++++++++++++++++++++
src/persp/dbgperspective/nmv-console.h | 100 ++++++
src/persp/dbgperspective/nmv-dbg-perspective.cc | 219 +++++++++---
src/persp/dbgperspective/nmv-dbg-perspective.h | 4 +-
src/uicommon/nmv-terminal.cc | 6 +
src/uicommon/nmv-terminal.h | 1 +
9 files changed, 723 insertions(+), 56 deletions(-)
create mode 100644 src/persp/dbgperspective/nmv-console.cc
create mode 100644 src/persp/dbgperspective/nmv-console.h
diff --git a/configure.ac b/configure.ac
index d5d6ad5..7e219b0 100644
--- a/configure.ac
+++ b/configure.ac
@@ -378,8 +378,9 @@ dnl library dependencies for the nemiver debug perspective plugin
DEP_PERSP="gtksourceviewmm-3.0 >= $LIBGTKSOURCEVIEWMM_VERSION \
vte-2.90 >= $LIBVTE_VERSION"
+AC_CHECK_FUNCS(readline)
PKG_CHECK_MODULES(NEMIVERDBGPERSP, $DEP_UICOMMON $DEP_VFS $DEP_PERSP $DEP_MEMORYVIEW $DEP_DYNAMICLAYOUT)
-NEMIVERDBGPERSP_LIBS="$NEMIVERDBGPERSP_LIBS $CPPUNIT_LIBS"
+NEMIVERDBGPERSP_LIBS="$NEMIVERDBGPERSP_LIBS $CPPUNIT_LIBS -lreadline"
NEMIVERDBGPERSP_CFLAGS="$NEMIVERDBGPERSP_CFLAGS $CPPUNIT_CFLAGS"
AC_SUBST(NEMIVERDBGPERSP_LIBS)
diff --git a/src/persp/dbgperspective/Makefile.am b/src/persp/dbgperspective/Makefile.am
index d6913d4..e497ae5 100644
--- a/src/persp/dbgperspective/Makefile.am
+++ b/src/persp/dbgperspective/Makefile.am
@@ -75,7 +75,9 @@ $(h)/nmv-dbg-perspective-default-layout.h \
$(h)/nmv-dbg-perspective-two-pane-layout.cc \
$(h)/nmv-dbg-perspective-two-pane-layout.h \
$(h)/nmv-dbg-perspective-wide-layout.cc \
-$(h)/nmv-dbg-perspective-wide-layout.h
+$(h)/nmv-dbg-perspective-wide-layout.h \
+$(h)/nmv-console.cc \
+$(h)/nmv-console.h
if BUILD_DYNAMICLAYOUT
dynamiclayout_sources = \
diff --git a/src/persp/dbgperspective/menus/menus.xml b/src/persp/dbgperspective/menus/menus.xml
index 337838a..4f34a4d 100644
--- a/src/persp/dbgperspective/menus/menus.xml
+++ b/src/persp/dbgperspective/menus/menus.xml
@@ -47,6 +47,8 @@
name="ActivateRegistersViewMenuItem"/>
<menuitem action="ActivateExprMonitorViewMenuAction"
name="ActivateExprMonitorViewMenuItem"/>
+ <menuitem action="ActivateConsoleViewMenuAction"
+ name="ActivateConsoleViewMenuItem"/>
</menu>
<menu action="DebugMenuAction" name="DebugMenu">
<menuitem action="RunMenuItemAction" name="RunMenuItem"/>
diff --git a/src/persp/dbgperspective/nmv-console.cc b/src/persp/dbgperspective/nmv-console.cc
new file mode 100644
index 0000000..6cbcbfa
--- /dev/null
+++ b/src/persp/dbgperspective/nmv-console.cc
@@ -0,0 +1,440 @@
+//Author: Fabien Parent
+/*
+ *This file is part of the Nemiver project
+ *
+ *Nemiver is free software; you can redistribute
+ *it and/or modify it under the terms of
+ *the GNU General Public License as published by the
+ *Free Software Foundation; either version 2,
+ *or (at your option) any later version.
+ *
+ *Nemiver is distributed in the hope that it will
+ *be useful, but WITHOUT ANY WARRANTY;
+ *without even the implied warranty of
+ *MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *See the GNU General Public License for more details.
+ *
+ *You should have received a copy of the
+ *GNU General Public License along with Nemiver;
+ *see the file COPYING.
+ *If not, write to the Free Software Foundation,
+ *Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *See COPYRIGHT file copyright information.
+ */
+
+#define USE_VARARGS
+#define PREFER_STDARG
+
+#include "nmv-console.h"
+#include "common/nmv-str-utils.h"
+#include "uicommon/nmv-terminal.h"
+#include "dbgengine/nmv-cmd-interpreter.h"
+#include "dbgengine/nmv-i-debugger.h"
+#include <vector>
+#include <cstring>
+#include <fstream>
+#include <cctype>
+#include <readline/readline.h>
+#include <readline/history.h>
+#include <fcntl.h>
+
+NEMIVER_BEGIN_NAMESPACE(nemiver)
+
+const char *const CONSOLE_PROMPT = "(nemiver) ";
+
+struct Console::Priv {
+ Terminal terminal;
+ Console::Stream stream;
+ CmdInterpreter cmd_interpreter;
+ Glib::RefPtr<Glib::IOSource> io_source;
+ IDebugger &debugger;
+
+ struct readline_state console_state;
+ struct readline_state saved_state;
+
+ Priv (IDebugger &a_debugger,
+ const std::string &a_menu_file_path,
+ const Glib::RefPtr<Gtk::UIManager> &a_ui_manager) :
+ terminal (a_menu_file_path, a_ui_manager),
+ stream (terminal.slave_fd ()),
+ cmd_interpreter (a_debugger, stream),
+ io_source (Glib::IOSource::create (terminal.slave_fd (), Glib::IO_IN)),
+ debugger (a_debugger)
+ {
+ init ();
+ }
+
+ void
+ init ()
+ {
+ int fd = terminal.slave_fd ();
+ THROW_IF_FAIL (fd);
+ if (consoles ().count (fd)) {
+ THROW ("Cannot create two consoles from the same file descriptor.");
+ }
+ consoles ()[fd] = this;
+
+ cmd_interpreter.ready_signal ().connect
+ (sigc::mem_fun (*this, &Console::Priv::on_ready_signal));
+
+ io_source->connect (sigc::mem_fun (*this, &Console::Priv::read_char));
+ io_source->attach ();
+
+ rl_save_state (&saved_state);
+ rl_instream = fdopen (fd, "r");
+ rl_outstream = fdopen (fd, "w");
+ rl_bind_key ('\t', &Console::Priv::on_tab_key_pressed);
+ rl_callback_handler_install (CONSOLE_PROMPT,
+ &Console::Priv::process_command);
+ rl_already_prompted = true;
+ rl_save_state (&console_state);
+ rl_restore_state (&saved_state);
+ }
+
+ void
+ on_ready_signal ()
+ {
+ stream << CONSOLE_PROMPT;
+ }
+
+ bool
+ read_char (Glib::IOCondition)
+ {
+ NEMIVER_TRY;
+
+ if (!cmd_interpreter.ready ())
+ return false;
+
+ rl_restore_state (&console_state);
+ rl_callback_read_char ();
+ rl_save_state (&console_state);
+ rl_restore_state (&saved_state);
+
+ NEMIVER_CATCH_NOX;
+
+ return true;
+ }
+
+ void
+ do_completion (const std::string &a_completion)
+ {
+ size_t buffer_length = std::strlen (rl_line_buffer);
+ rl_extend_line_buffer (buffer_length + a_completion.size ());
+ std::memcpy (rl_line_buffer + rl_point + a_completion.size (),
+ rl_line_buffer + rl_point,
+ a_completion.size ());
+ for (size_t i = 0; i < a_completion.size(); i++) {
+ rl_line_buffer[rl_point + i] = a_completion[i];
+ }
+ rl_end += a_completion.size ();
+ rl_point += a_completion.size ();
+ }
+
+ void
+ display_message (const std::string &a_msg)
+ {
+ rl_save_prompt ();
+ rl_message ("%s%s\n",
+ CONSOLE_PROMPT,
+ std::string (rl_line_buffer, rl_end).c_str ());
+
+ std::istringstream iss (a_msg);
+ std::string line;
+ while (std::getline (iss, line)) {
+ line += '\n';
+ rl_message ("%s", line.c_str ());
+ }
+
+ rl_message ("%s", CONSOLE_PROMPT);
+ rl_restore_prompt ();
+ rl_clear_message ();
+ }
+
+ void
+ display_completion (const std::vector<std::string> &a_completions)
+ {
+ std::ostringstream msg;
+
+ for (size_t i = 0; i < a_completions.size (); i++) {
+ if ((i + 1) % 5) {
+ msg.width (16);
+ msg.fill (' ');
+ msg << std::left << a_completions[i];
+ } else {
+ msg << a_completions[i] << '\n';
+ }
+ }
+
+ if (msg.str ()[msg.str ().size () - 1] != '\n') {
+ msg << '\n';
+ }
+
+ display_message (msg.str ());
+ }
+
+ void
+ do_command_completion (const std::string &a_line)
+ {
+ const std::vector<CmdInterpreter::Command*> &commands =
+ cmd_interpreter.commands ();
+
+ std::vector<CmdInterpreter::Command*> matches;
+ for (std::vector<CmdInterpreter::Command*>::const_iterator iter =
+ commands.begin ();
+ iter != commands.end ();
+ ++iter) {
+ if (*iter && !(*iter)->name ().find (a_line)) {
+ matches.push_back (*iter);
+ }
+ }
+
+ if (!matches.size ()) {
+ return;
+ }
+
+ std::string completion = matches[0]->name ();
+ if (matches.size () > 1) {
+ std::vector<std::string> completions;
+ for (size_t i = 0; i < matches.size (); i++) {
+ size_t j = a_line.size ();
+ for (;
+ j < matches[i]->name ().size ()
+ && j < completion.size ()
+ && matches[i]->name ()[j] == completion[j];
+ j++) {
+ }
+ completion = completion.substr (0, j);
+ completions.push_back (matches[i]->name ());
+ }
+
+ display_completion (completions);
+ }
+ do_completion (completion.substr (a_line.size ()));
+ }
+
+ void
+ do_param_completion (std::vector<UString> &a_tokens)
+ {
+ if (!a_tokens.size ()) {
+ return;
+ }
+
+ const std::vector<CmdInterpreter::Command*> &commands =
+ cmd_interpreter.commands ();
+
+ CmdInterpreter::Command* command = 0;
+ for (std::vector<CmdInterpreter::Command*>::const_iterator iter =
+ commands.begin ();
+ iter != commands.end ();
+ ++iter) {
+ if (*iter && (*iter)->name () == a_tokens[0]) {
+ command = *iter;
+ break;
+ }
+ }
+
+ if (!command) {
+ return;
+ }
+
+ a_tokens.erase (a_tokens.begin ());
+ std::string line (rl_line_buffer, rl_point);
+ if (std::isspace (line[line.size () - 1])) {
+ stream << "\n";
+ command->display_usage (a_tokens, stream);
+ rl_forced_update_display ();
+ } else {
+ UString token = a_tokens.back ();
+ a_tokens.pop_back ();
+
+ std::vector<UString> completions;
+ std::vector<UString> matches;
+ command->completions (a_tokens, completions);
+ for (std::vector<UString>::iterator iter = completions.begin ();
+ iter != completions.end ();
+ ++iter) {
+ if (!iter->find (token)) {
+ matches.push_back (*iter);
+ }
+ }
+
+ if (matches.size () == 1) {
+ std::string completion = matches[0].substr (token.size ());
+ do_completion (completion);
+ } else if (matches.size () > 1) {
+ std::vector<std::string> comps;
+ UString completion = matches[0];
+ for (size_t i = 0; i < matches.size (); i++) {
+ size_t j = token.size ();
+ for (; j < matches[i].size ()
+ && j < completion.size ()
+ && matches[i][j] == completion[j];
+ j++) {
+ }
+ completion = completion.substr (0, j);
+ comps.push_back (matches[i]);
+ }
+
+ display_completion (comps);
+ do_completion (completion.substr (token.size ()));
+ } else {
+ rl_complete (0, '\t');
+ }
+ }
+ }
+
+ static int
+ on_tab_key_pressed (int, int)
+ {
+ NEMIVER_TRY;
+
+ std::string line (rl_line_buffer, rl_point);
+ std::vector<UString> tokens_raw = str_utils::split (line, " ");
+ std::vector<UString> tokens;
+ for (size_t i = 0; i < tokens_raw.size (); i++) {
+ if (tokens_raw[i].size ()) {
+ tokens.push_back (tokens_raw[i]);
+ }
+ }
+
+ if (std::isspace (line[line.size () - 1]) || tokens.size () > 1) {
+ self ().do_param_completion (tokens);
+ } else {
+ self ().do_command_completion (line);
+ }
+
+ NEMIVER_CATCH_NOX;
+
+ return 0;
+ }
+
+ static std::map<int, Console::Priv*>& consoles ()
+ {
+ static std::map<int, Console::Priv*> s_consoles;
+ return s_consoles;
+ }
+
+ static Console::Priv& self ()
+ {
+ int fd = fileno (rl_instream);
+ THROW_IF_FAIL (fd);
+ THROW_IF_FAIL (consoles ().count (fd));
+ Console::Priv *self = consoles ()[fd];
+ THROW_IF_FAIL (self);
+ return *self;
+ }
+
+ static void
+ process_command (char *a_command)
+ {
+ NEMIVER_TRY;
+
+ THROW_IF_FAIL (a_command);
+ add_history (a_command);
+ self ().cmd_interpreter.execute_command (a_command);
+
+ NEMIVER_CATCH_NOX;
+
+ free (a_command);
+ }
+};
+
+Console::Console (IDebugger &a_debugger,
+ const std::string &a_menu_file_path,
+ const Glib::RefPtr<Gtk::UIManager> &a_ui_manager) :
+ m_priv (new Priv (a_debugger, a_menu_file_path, a_ui_manager))
+{
+}
+
+Console::~Console ()
+{
+}
+
+void
+Console::execute_commands_from_file (const UString &a_file)
+{
+ std::ifstream file (a_file.c_str ());
+ while (file.good ()) {
+ std::string line;
+ std::getline (file, line);
+ execute_line (line);
+ }
+ file.close ();
+}
+
+void
+Console::execute_commands_from_fd (int a_fd)
+{
+ struct File {
+ FILE *fd;
+ char buffer[4096];
+
+ explicit File (int a_fd) :
+ fd (fdopen (dup (a_fd), "r"))
+ {
+ THROW_IF_FAIL (fd);
+ int flags = fcntl (fileno (fd), F_GETFL, 0);
+ fcntl (fileno (fd), F_SETFL, flags | O_NONBLOCK);
+ }
+
+ ~File ()
+ {
+ if (fd) {
+ fclose (fd);
+ }
+ }
+ } file (a_fd);
+
+ while (fgets (file.buffer, sizeof (file.buffer), file.fd)) {
+ execute_line (file.buffer);
+ }
+}
+
+void
+Console::execute_line (const UString &a_line)
+{
+ std::vector<UString> commands = str_utils::split (a_line, ";");
+ for (std::vector<UString>::iterator iter = commands.begin ();
+ iter != commands.end ();
+ ++iter) {
+ str_utils::chomp (*iter);
+ execute_command (*iter);
+ }
+}
+
+void
+Console::execute_command (const UString &a_command)
+{
+ THROW_IF_FAIL (m_priv);
+
+ rl_restore_state (&m_priv->console_state);
+
+ add_history (a_command.c_str ());
+ if (!m_priv->cmd_interpreter.ready ()) {
+ m_priv->stream << CONSOLE_PROMPT;
+ }
+ m_priv->stream << a_command << "\n";
+
+ rl_save_state (&m_priv->console_state);
+ rl_restore_state (&m_priv->saved_state);
+
+ m_priv->cmd_interpreter.execute_command (a_command);
+}
+
+CmdInterpreter&
+Console::command_interpreter() const
+{
+ THROW_IF_FAIL (m_priv);
+ return m_priv->cmd_interpreter;
+}
+
+Terminal&
+Console::terminal () const
+{
+ THROW_IF_FAIL (m_priv);
+ return m_priv->terminal;
+}
+
+NEMIVER_END_NAMESPACE(nemiver)
+
diff --git a/src/persp/dbgperspective/nmv-console.h b/src/persp/dbgperspective/nmv-console.h
new file mode 100644
index 0000000..225b6a0
--- /dev/null
+++ b/src/persp/dbgperspective/nmv-console.h
@@ -0,0 +1,100 @@
+//Author: Fabien Parent
+/*
+ *This file is part of the Nemiver project
+ *
+ *Nemiver is free software; you can redistribute
+ *it and/or modify it under the terms of
+ *the GNU General Public License as published by the
+ *Free Software Foundation; either version 2,
+ *or (at your option) any later version.
+ *
+ *Nemiver is distributed in the hope that it will
+ *be useful, but WITHOUT ANY WARRANTY;
+ *without even the implied warranty of
+ *MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *See the GNU General Public License for more details.
+ *
+ *You should have received a copy of the
+ *GNU General Public License along with Nemiver;
+ *see the file COPYING.
+ *If not, write to the Free Software Foundation,
+ *Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *See COPYRIGHT file copyright information.
+ */
+#ifndef __NMV_CONSOLE_H__
+#define __NMV_CONSOLE_H__
+
+#include "common/nmv-safe-ptr.h"
+#include "common/nmv-namespace.h"
+#include "common/nmv-exception.h"
+#include <gtkmm/uimanager.h>
+#include <string>
+#include <vector>
+#include <ostream>
+
+NEMIVER_BEGIN_NAMESPACE(nemiver)
+
+class IDebugger;
+class CmdInterpreter;
+class Terminal;
+
+using nemiver::common::SafePtr;
+using nemiver::common::UString;
+
+class Console {
+ //non copyable
+ Console (const Console&);
+ Console& operator= (const Console&);
+
+ struct Priv;
+ SafePtr<Priv> m_priv;
+
+ struct StreamBuf : public std::streambuf {
+ int fd;
+
+ StreamBuf () :
+ fd (0)
+ {
+ }
+
+ StreamBuf (int a_fd) :
+ fd (a_fd)
+ {
+ }
+
+ virtual std::streamsize
+ xsputn (const char *a_string, std::streamsize a_size)
+ {
+ THROW_IF_FAIL (fd);
+ return ::write (fd, a_string, a_size);
+ }
+ };
+
+public:
+ class Stream : public std::ostream {
+ StreamBuf streambuf;
+ public:
+ explicit Stream (int a_fd) :
+ std::ostream (&streambuf),
+ streambuf (a_fd)
+ {
+ }
+ };
+
+ Console (IDebugger &a_debugger,
+ const std::string &a_menu_file_path,
+ const Glib::RefPtr<Gtk::UIManager> &a_ui_manager);
+ ~Console ();
+ void execute_commands_from_file (const UString &a_file);
+ void execute_commands_from_fd (int a_fd);
+ void execute_line (const UString &a_command);
+ void execute_command (const UString &a_command);
+ CmdInterpreter& command_interpreter() const;
+ Terminal& terminal () const;
+};
+
+NEMIVER_END_NAMESPACE(nemiver)
+
+#endif /* __NMV_CONSOLE_H__ */
+
diff --git a/src/persp/dbgperspective/nmv-dbg-perspective.cc b/src/persp/dbgperspective/nmv-dbg-perspective.cc
index 669b391..b963145 100644
--- a/src/persp/dbgperspective/nmv-dbg-perspective.cc
+++ b/src/persp/dbgperspective/nmv-dbg-perspective.cc
@@ -101,6 +101,7 @@
#include "nmv-layout-manager.h"
#include "nmv-expr-monitor.h"
#include "nmv-cmd-interpreter.h"
+#include "nmv-console.h"
using namespace std;
using namespace nemiver::common;
@@ -124,6 +125,7 @@ const char *BREAKPOINTS_VIEW_TITLE = _("Breakpoints");
const char *REGISTERS_VIEW_TITLE = _("Registers");
const char *MEMORY_VIEW_TITLE = _("Memory");
const char *EXPR_MONITOR_VIEW_TITLE = _("Expression Monitor");
+const char *CONSOLE_VIEW_TITLE = _("Console");
const char *CAPTION_SESSION_NAME = "captionname";
const char *SESSION_NAME = "sessionname";
@@ -173,6 +175,77 @@ class DBGPerspective : public IDBGPerspective, public sigc::trackable {
private:
+ struct OpenCommand : public CmdInterpreter::Command {
+
+ DBGPerspective& dbg_perspective;
+ std::vector<UString> source_files;
+
+ OpenCommand (DBGPerspective& a_dbg_perspective) :
+ dbg_perspective (a_dbg_perspective)
+ {
+ init_signals ();
+ }
+
+ void
+ init_signals ()
+ {
+ IDebuggerSafePtr debugger = dbg_perspective.debugger ();
+ THROW_IF_FAIL (debugger);
+ debugger->files_listed_signal ().connect (sigc::mem_fun
+ (*this, &OpenCommand::on_files_listed_signal));
+ }
+
+ void
+ on_files_listed_signal (const std::vector<UString> &a_files,
+ const UString&)
+ {
+ source_files = a_files;
+ }
+
+ const std::string&
+ name () const
+ {
+ static const std::string &s_name = "open";
+ return s_name;
+ }
+
+ const std::vector<UString>&
+ aliases () const
+ {
+ static std::vector<UString> s_aliases;
+ if (!s_aliases.size ()) {
+ s_aliases.push_back ("o");
+ }
+ return s_aliases;
+ }
+
+ void
+ completions (const std::vector<UString>&,
+ std::vector<UString> &a_completion_vector) const
+ {
+ a_completion_vector.insert (a_completion_vector.begin (),
+ source_files.begin (),
+ source_files.end ());
+ }
+
+ bool
+ execute (const std::vector<UString> &a_argv, std::ostream&)
+ {
+ for (std::vector<UString>::const_iterator iter = a_argv.begin ();
+ iter != a_argv.end ();
+ ++iter) {
+ UString path = *iter;
+ if (path.size () && path[0] == '~') {
+ path = path.replace (0, 1, Glib::get_home_dir ());
+ }
+
+ dbg_perspective.open_file (path, -1);
+ }
+
+ return true;
+ }
+ };
+
struct SlotedButton : Gtk::Button {
UString file_path;
DBGPerspective *perspective;
@@ -431,6 +504,7 @@ private:
void on_activate_memory_view ();
#endif // WITH_MEMORYVIEW
void on_activate_expr_monitor_view ();
+ void on_activate_console_view ();
void on_activate_global_variables ();
void on_default_config_read ();
@@ -763,6 +837,10 @@ public:
Gtk::ScrolledWindow& get_local_vars_inspector_scrolled_win ();
+ Console& dbg_console ();
+
+ Gtk::Box& console_box ();
+
Terminal& get_terminal ();
Gtk::Box& get_terminal_box ();
@@ -930,7 +1008,9 @@ struct DBGPerspective::Priv {
Path2MonitorMap path_2_monitor_map;
SafePtr<LocalVarsInspector> variables_editor;
SafePtr<Gtk::ScrolledWindow> variables_editor_scrolled_win;
- SafePtr<CmdInterpreter> interpreter;
+ SafePtr<Console> dbg_console;
+ CmdInterpreter::CommandSafePtr open_command;
+ SafePtr<Gtk::Box> console_box;
SafePtr<Terminal> terminal;
SafePtr<Gtk::Box> terminal_box;
SafePtr<Gtk::ScrolledWindow> breakpoints_scrolled_win;
@@ -1840,6 +1920,17 @@ DBGPerspective::on_switch_page_signal (Gtk::Widget *a_page,
NEMIVER_TRY
m_priv->current_page_num = a_page_num;
LOG_DD ("current_page_num: " << m_priv->current_page_num);
+
+ map<int, SourceEditor*>::iterator iter, nil;
+ nil = m_priv->pagenum_2_source_editor_map.end ();
+ iter = m_priv->pagenum_2_source_editor_map.find (m_priv->current_page_num);
+ if (iter != nil) {
+ SourceEditor *editor = get_current_source_editor ();
+ if (editor) {
+ dbg_console ().command_interpreter ().current_file_path
+ (editor->get_path ());
+ }
+ }
NEMIVER_CATCH
}
@@ -2916,6 +3007,19 @@ DBGPerspective::on_activate_target_terminal_view ()
}
void
+DBGPerspective::on_activate_console_view ()
+{
+ LOG_FUNCTION_SCOPE_NORMAL_DD;
+
+ NEMIVER_TRY;
+
+ THROW_IF_FAIL (m_priv);
+ m_priv->layout ().activate_view (CONSOLE_VIEW_INDEX);
+
+ NEMIVER_CATCH;
+}
+
+void
DBGPerspective::on_activate_breakpoints_view ()
{
LOG_FUNCTION_SCOPE_NORMAL_DD;
@@ -3596,6 +3700,17 @@ DBGPerspective::init_actions ()
false
},
{
+ "ActivateConsoleViewMenuAction",
+ nil_stock_id,
+ CONSOLE_VIEW_TITLE,
+ _("Switch to Console View"),
+ sigc::mem_fun (*this,
+ &DBGPerspective::on_activate_console_view),
+ ActionEntry::DEFAULT,
+ "<alt>7",
+ false
+ },
+ {
"DebugMenuAction",
nil_stock_id,
_("_Debug"),
@@ -5149,6 +5264,9 @@ DBGPerspective::add_views_to_layout ()
m_priv->layout ().append_view (get_expr_monitor_view ().widget (),
EXPR_MONITOR_VIEW_TITLE,
EXPR_MONITOR_VIEW_INDEX);
+ m_priv->layout ().append_view (console_box (),
+ CONSOLE_VIEW_TITLE,
+ CONSOLE_VIEW_INDEX);
m_priv->layout ().do_init ();
}
@@ -5889,68 +6007,20 @@ DBGPerspective::session_manager ()
}
void
-DBGPerspective::execute_commands_from_line (const UString &a_line)
-{
- THROW_IF_FAIL (debugger ());
-
- if (!m_priv->interpreter) {
- m_priv->interpreter.reset
- (new CmdInterpreter (*debugger (), std::cout));
- }
-
- THROW_IF_FAIL (m_priv->interpreter);
-
- std::vector<UString> commands = str_utils::split (a_line, ";");
- for (std::vector<UString>::iterator iter = commands.begin ();
- iter != commands.end ();
- ++iter) {
- str_utils::chomp (*iter);
- m_priv->interpreter->execute_command (*iter);
- }
-}
-
-void
DBGPerspective::execute_commands_from_file (const UString &a_file)
{
- THROW_IF_FAIL (m_priv);
+ THROW_IF_FAIL (m_priv->dbg_console);
- std::ifstream file (a_file.c_str ());
- while (file.good ()) {
- std::string line;
- std::getline (file, line);
- execute_commands_from_line (line);
- }
- file.close ();
+ m_priv->dbg_console->execute_commands_from_file (a_file);
}
void
DBGPerspective::execute_commands_from_fd (int a_fd)
{
THROW_IF_FAIL (m_priv);
+ THROW_IF_FAIL (m_priv->dbg_console);
- struct File {
- FILE *fd;
- char buffer[4096];
-
- explicit File (int a_fd) :
- fd (fdopen (dup (a_fd), "r"))
- {
- THROW_IF_FAIL (fd);
- int flags = fcntl (fileno (fd), F_GETFL, 0);
- fcntl (fileno (fd), F_SETFL, flags | O_NONBLOCK);
- }
-
- ~File ()
- {
- if (fd) {
- fclose (fd);
- }
- }
- } file (a_fd);
-
- while (fgets (file.buffer, sizeof (file.buffer), file.fd)) {
- execute_commands_from_line (file.buffer);
- }
+ m_priv->dbg_console->execute_commands_from_fd (a_fd);
}
void
@@ -8415,6 +8485,49 @@ DBGPerspective::get_local_vars_inspector_scrolled_win ()
return *m_priv->variables_editor_scrolled_win;
}
+Console&
+DBGPerspective::dbg_console ()
+{
+ THROW_IF_FAIL (m_priv);
+ if (!m_priv->dbg_console) {
+ string relative_path = Glib::build_filename ("menus",
+ "terminalmenu.xml");
+ string absolute_path;
+ THROW_IF_FAIL (build_absolute_resource_path
+ (Glib::filename_to_utf8 (relative_path), absolute_path));
+
+ IDebuggerSafePtr dbg = debugger ();
+ THROW_IF_FAIL (dbg);
+ m_priv->dbg_console.reset
+ (new Console (*dbg, absolute_path, workbench ().get_ui_manager ()));
+ THROW_IF_FAIL (m_priv->dbg_console);
+
+ m_priv->open_command.reset (new OpenCommand (*this));
+ THROW_IF_FAIL (m_priv->open_command);
+ m_priv->dbg_console->command_interpreter
+ ().register_command (*m_priv->open_command);
+ }
+ THROW_IF_FAIL (m_priv->dbg_console);
+ return *m_priv->dbg_console;
+}
+
+Gtk::Box&
+DBGPerspective::console_box ()
+{
+ THROW_IF_FAIL (m_priv);
+ if (!m_priv->console_box) {
+ m_priv->console_box.reset (new Gtk::HBox);
+ THROW_IF_FAIL (m_priv->console_box);
+ Gtk::VScrollbar *scrollbar = Gtk::manage (new Gtk::VScrollbar);
+ m_priv->console_box->pack_end (*scrollbar, false, false, 0);
+
+ Terminal &terminal = dbg_console ().terminal ();
+ m_priv->console_box->pack_start (terminal.widget ());
+ scrollbar->set_adjustment (terminal.adjustment ());
+ }
+ THROW_IF_FAIL (m_priv->console_box);
+ return *m_priv->console_box;
+}
Terminal&
DBGPerspective::get_terminal ()
diff --git a/src/persp/dbgperspective/nmv-dbg-perspective.h b/src/persp/dbgperspective/nmv-dbg-perspective.h
index c22ed92..bf32d9b 100644
--- a/src/persp/dbgperspective/nmv-dbg-perspective.h
+++ b/src/persp/dbgperspective/nmv-dbg-perspective.h
@@ -39,6 +39,7 @@ extern const char *TARGET_TERMINAL_VIEW_TITLE;
extern const char *BREAKPOINTS_VIEW_TITLE;
extern const char *REGISTERS_VIEW_TITLE;
extern const char *MEMORY_VIEW_TITLE;
+extern const char *CONSOLE_VIEW_TITLE;
enum ViewsIndex
{
@@ -49,7 +50,8 @@ enum ViewsIndex
#ifdef WITH_MEMORYVIEW
MEMORY_VIEW_INDEX,
#endif // WITH_MEMORYVIEW
- EXPR_MONITOR_VIEW_INDEX
+ EXPR_MONITOR_VIEW_INDEX,
+ CONSOLE_VIEW_INDEX
};
class SourceEditor;
diff --git a/src/uicommon/nmv-terminal.cc b/src/uicommon/nmv-terminal.cc
index 717c094..49f136c 100644
--- a/src/uicommon/nmv-terminal.cc
+++ b/src/uicommon/nmv-terminal.cc
@@ -336,6 +336,12 @@ Terminal::feed (const UString &a_text)
vte_terminal_feed (m_priv->vte, a_text.c_str (), a_text.size ());
}
+int
+Terminal::slave_fd () const
+{
+ THROW_IF_FAIL (m_priv);
+ return m_priv->slave_pty;
+}
NEMIVER_END_NAMESPACE(nemiver)
diff --git a/src/uicommon/nmv-terminal.h b/src/uicommon/nmv-terminal.h
index d8c075d..21eff0d 100644
--- a/src/uicommon/nmv-terminal.h
+++ b/src/uicommon/nmv-terminal.h
@@ -68,6 +68,7 @@ public:
Glib::RefPtr<Gtk::Adjustment> adjustment () const;
int slave_pty () const;
UString slave_pts_name () const;
+ int slave_fd () const;
void modify_font (const Pango::FontDescription &font_desc);
void feed (const UString &a_text);
};//end class Terminal
--
1.8.4.rc3
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]