[Lldb-commits] [lldb] r134955 - in /lldb/trunk: include/lldb/Interpreter/CommandInterpreter.h include/lldb/lldb-enumerations.h source/Commands/CommandObjectCommands.cpp source/Interpreter/CommandInterpreter.cpp tools/driver/IOChannel.cpp

Jim Ingham jingham at apple.com
Mon Jul 11 20:12:18 PDT 2011


Author: jingham
Date: Mon Jul 11 22:12:18 2011
New Revision: 134955

URL: http://llvm.org/viewvc/llvm-project?rev=134955&view=rev
Log:
Added "command history" command to dump the command history.
Also made:
(lldb) !<NUM>
(lldb) !-<NUM>
(lldb) !!

work with the history.  For added benefit:

(lldb) !<NUM><TAB>

will insert the command at position <NUM> in the history into the command line to be edited.

This is only partial, I still need to sync up editline's history list with the one kept by the interpreter.

Modified:
    lldb/trunk/include/lldb/Interpreter/CommandInterpreter.h
    lldb/trunk/include/lldb/lldb-enumerations.h
    lldb/trunk/source/Commands/CommandObjectCommands.cpp
    lldb/trunk/source/Interpreter/CommandInterpreter.cpp
    lldb/trunk/tools/driver/IOChannel.cpp

Modified: lldb/trunk/include/lldb/Interpreter/CommandInterpreter.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Interpreter/CommandInterpreter.h?rev=134955&r1=134954&r2=134955&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Interpreter/CommandInterpreter.h (original)
+++ lldb/trunk/include/lldb/Interpreter/CommandInterpreter.h Mon Jul 11 22:12:18 2011
@@ -195,8 +195,11 @@
     // you want returned.  Otherwise set max_return_elements to -1.
     // If you want to start some way into the match list, then set match_start_point to the desired start
     // point.
-    // Returns the total number of completions, or -1 if the completion character should be inserted, or
+    // Returns:
+    // -1 if the completion character should be inserted
+    // -2 if the entire command line should be deleted and replaced with matches.GetStringAtIndex(0)
     // INT_MAX if the number of matches is > max_return_elements, but it is expensive to compute.
+    // Otherwise, returns the number of matches.
     //
     // FIXME: Only max_return_elements == -1 is supported at present.
 
@@ -338,6 +341,16 @@
 
     bool
     GetSynchronous ();
+    
+    void
+    DumpHistory (Stream &stream, uint32_t count) const;
+
+    void
+    DumpHistory (Stream &stream, uint32_t start, uint32_t end) const;
+    
+    const char *
+    FindHistoryString (const char *input_str) const;
+
 
 #ifndef SWIG
     void
@@ -396,6 +409,7 @@
     std::string m_repeat_command;               // Stores the command that will be executed for an empty command string.
     std::auto_ptr<ScriptInterpreter> m_script_interpreter_ap;
     char m_comment_char;
+    char m_repeat_char;
     bool m_batch_command_mode;
 };
 

Modified: lldb/trunk/include/lldb/lldb-enumerations.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/lldb-enumerations.h?rev=134955&r1=134954&r2=134955&view=diff
==============================================================================
--- lldb/trunk/include/lldb/lldb-enumerations.h (original)
+++ lldb/trunk/include/lldb/lldb-enumerations.h Mon Jul 11 22:12:18 2011
@@ -391,6 +391,7 @@
         eArgTypeThreadID,
         eArgTypeThreadIndex,
         eArgTypeThreadName,
+        eArgTypeUnsignedInteger,
         eArgTypeUnixSignal,
         eArgTypeVarName,
         eArgTypeValue,

Modified: lldb/trunk/source/Commands/CommandObjectCommands.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectCommands.cpp?rev=134955&r1=134954&r2=134955&view=diff
==============================================================================
--- lldb/trunk/source/Commands/CommandObjectCommands.cpp (original)
+++ lldb/trunk/source/Commands/CommandObjectCommands.cpp Mon Jul 11 22:12:18 2011
@@ -30,6 +30,132 @@
 // CommandObjectCommandsSource
 //-------------------------------------------------------------------------
 
+class CommandObjectCommandsHistory : public CommandObject
+{
+private:
+
+    class CommandOptions : public Options
+    {
+    public:
+
+        CommandOptions (CommandInterpreter &interpreter) :
+            Options (interpreter)
+        {
+        }
+
+        virtual
+        ~CommandOptions (){}
+
+        virtual Error
+        SetOptionValue (uint32_t option_idx, const char *option_arg)
+        {
+            Error error;
+            char short_option = (char) m_getopt_table[option_idx].val;
+            bool success;
+            
+            switch (short_option)
+            {
+                case 'c':
+                    m_end_idx = Args::StringToUInt32(option_arg, UINT_MAX, 0, &success);
+                    if (!success)
+                        error.SetErrorStringWithFormat("Invalid value for count: %s.\n", option_arg);
+                    if (m_end_idx != 0)
+                        m_end_idx--;
+                    m_start_idx = 0;
+                    break;
+                case 'e':
+                    m_end_idx = Args::StringToUInt32(option_arg, 0, 0, &success);
+                    if (!success)
+                        error.SetErrorStringWithFormat("Invalid value for end index: %s.\n", option_arg);
+                    break;
+                case 's':
+                    m_start_idx = Args::StringToUInt32(option_arg, 0, 0, &success);
+                    if (!success)
+                        error.SetErrorStringWithFormat("Invalid value for start index: %s.\n", option_arg);
+                    break;
+                default:
+                    error.SetErrorStringWithFormat ("Unrecognized option '%c'.\n", short_option);
+                    break;
+            }
+            
+            return error;
+        }
+
+        void
+        OptionParsingStarting ()
+        {
+            m_start_idx = 0;
+            m_end_idx = UINT_MAX;
+        }
+
+        const OptionDefinition*
+        GetDefinitions ()
+        {
+            return g_option_table;
+        }
+
+        // Options table: Required for subclasses of Options.
+
+        static OptionDefinition g_option_table[];
+
+        // Instance variables to hold the values for command options.
+
+        uint32_t m_start_idx;
+        uint32_t m_end_idx;
+    };
+    
+    CommandOptions m_options;
+    
+    virtual Options *
+    GetOptions ()
+    {
+        return &m_options;
+    }
+
+public:
+    CommandObjectCommandsHistory(CommandInterpreter &interpreter) :
+        CommandObject (interpreter,
+                       "command history",
+                       "Dump the history of commands in this session.",
+                       NULL),
+        m_options (interpreter)
+    {
+    }
+
+    ~CommandObjectCommandsHistory ()
+    {
+    }
+
+    bool
+    Execute
+    (
+        Args& args,
+        CommandReturnObject &result
+    )
+    {
+        
+        m_interpreter.DumpHistory (result.GetOutputStream(),
+                                   m_options.m_start_idx, 
+                                   m_options.m_end_idx);
+        return result.Succeeded();
+
+    }
+};
+
+OptionDefinition
+CommandObjectCommandsHistory::CommandOptions::g_option_table[] =
+{
+{ LLDB_OPT_SET_1, false, "count", 'c', required_argument, NULL, 0, eArgTypeUnsignedInteger,        "How many history commands to print."},
+{ LLDB_OPT_SET_1, false, "start-index", 's', required_argument, NULL, 0, eArgTypeUnsignedInteger,  "Index at which to start printing history commands."},
+{ LLDB_OPT_SET_1, false, "end-index", 'e', required_argument, NULL, 0, eArgTypeUnsignedInteger,    "Index at which to stop printing history commands."},
+{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
+};
+
+
+//-------------------------------------------------------------------------
+// CommandObjectCommandsSource
+//-------------------------------------------------------------------------
+
 class CommandObjectCommandsSource : public CommandObject
 {
 private:
@@ -1020,6 +1146,7 @@
     LoadSubCommand ("alias",   CommandObjectSP (new CommandObjectCommandsAlias (interpreter)));
     LoadSubCommand ("unalias", CommandObjectSP (new CommandObjectCommandsUnalias (interpreter)));
     LoadSubCommand ("regex",   CommandObjectSP (new CommandObjectCommandsAddRegex (interpreter)));
+    LoadSubCommand ("history",   CommandObjectSP (new CommandObjectCommandsHistory (interpreter)));
 }
 
 CommandObjectMultiwordCommands::~CommandObjectMultiwordCommands ()

Modified: lldb/trunk/source/Interpreter/CommandInterpreter.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Interpreter/CommandInterpreter.cpp?rev=134955&r1=134954&r2=134955&view=diff
==============================================================================
--- lldb/trunk/source/Interpreter/CommandInterpreter.cpp (original)
+++ lldb/trunk/source/Interpreter/CommandInterpreter.cpp Mon Jul 11 22:12:18 2011
@@ -70,6 +70,7 @@
     m_skip_lldbinit_files (false),
     m_script_interpreter_ap (),
     m_comment_char ('#'),
+    m_repeat_char ('!'),
     m_batch_command_mode (false)
 {
     const char *dbg_name = debugger.GetInstanceName().AsCString();
@@ -929,6 +930,7 @@
     std::string next_word;
     bool wants_raw_input = false;
     std::string command_string (command_line);
+    std::string original_command_string (command_line);
     
     LogSP log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_COMMANDS));
     Host::SetCrashDescriptionWithFormat ("HandleCommand(command = \"%s\")", command_line);
@@ -959,6 +961,19 @@
             empty_command = true;
         else if (command_string[non_space] == m_comment_char)
              comment_command = true;
+        else if (command_string[non_space] == m_repeat_char)
+        {
+            const char *history_string = FindHistoryString (command_string.c_str() + non_space);
+            if (history_string == NULL)
+            {
+                result.AppendErrorWithFormat ("Could not find entry: %s in history", command_string.c_str());
+                result.SetStatus(eReturnStatusFailed);
+                return false;
+            }
+            add_to_history = false;
+            command_string = history_string;
+            original_command_string = history_string;
+        }
     }
     
     if (empty_command)
@@ -975,6 +990,7 @@
             {
                 command_line = m_repeat_command.c_str();
                 command_string = command_line;
+                original_command_string = command_line;
                 if (m_repeat_command.empty())
                 {
                     result.AppendErrorWithFormat("No auto repeat.\n");
@@ -1119,9 +1135,11 @@
             if (repeat_command != NULL)
                 m_repeat_command.assign(repeat_command);
             else
-                m_repeat_command.assign(command_line);
+                m_repeat_command.assign(original_command_string.c_str());
             
-            m_command_history.push_back (command_line);
+            // Don't keep pushing the same command onto the history...
+            if (m_command_history.size() == 0 || m_command_history.back() != original_command_string) 
+                m_command_history.push_back (original_command_string);
         }
         
         command_string = revised_command_line.GetData();
@@ -1276,6 +1294,29 @@
     Args parsed_line(current_line, last_char - current_line);
     Args partial_parsed_line(current_line, cursor - current_line);
 
+    // Don't complete comments, and if the line we are completing is just the history repeat character, 
+    // substitute the appropriate history line.
+    const char *first_arg = parsed_line.GetArgumentAtIndex(0);
+    if (first_arg)
+    {
+        if (first_arg[0] == m_comment_char)
+            return 0;
+        else if (first_arg[0] == m_repeat_char)
+        {
+            const char *history_string = FindHistoryString (first_arg);
+            if (history_string != NULL)
+            {
+                matches.Clear();
+                matches.InsertStringAtIndex(0, history_string);
+                return -2;
+            }
+            else
+                return 0;
+
+        }
+    }
+    
+    
     int num_args = partial_parsed_line.GetArgumentCount();
     int cursor_index = partial_parsed_line.GetArgumentCount() - 1;
     int cursor_char_position;
@@ -2154,3 +2195,60 @@
     }
 }
 
+void
+CommandInterpreter::DumpHistory (Stream &stream, uint32_t count) const
+{
+    DumpHistory (stream, 0, count - 1);
+}
+
+void
+CommandInterpreter::DumpHistory (Stream &stream, uint32_t start, uint32_t end) const
+{
+    size_t num_history_elements = m_command_history.size();
+    if (start > num_history_elements)
+        return;
+    for (uint32_t i = start; i < num_history_elements && i <= end; i++)
+    {
+        if (!m_command_history[i].empty())
+        {
+            stream.Indent();
+            stream.Printf ("%4d: %s\n", i, m_command_history[i].c_str());
+        }
+    }
+}
+
+const char *
+CommandInterpreter::FindHistoryString (const char *input_str) const
+{
+    if (input_str[0] != m_repeat_char)
+        return NULL;
+    if (input_str[1] == '-')
+    {
+        bool success;
+        uint32_t idx = Args::StringToUInt32 (input_str+2, 0, 0, &success);
+        if (!success)
+            return NULL;
+        if (idx > m_command_history.size())
+            return NULL;
+        idx = m_command_history.size() - idx;
+        return m_command_history[idx].c_str();
+            
+    }
+    else if (input_str[1] == m_repeat_char)
+    {
+        if (m_command_history.empty())
+            return NULL;
+        else
+            return m_command_history.back().c_str();
+    }
+    else
+    {
+        bool success;
+        uint32_t idx = Args::StringToUInt32 (input_str+1, 0, 0, &success);
+        if (!success)
+            return NULL;
+        if (idx >= m_command_history.size())
+            return NULL;
+        return m_command_history[idx].c_str();
+    }
+}

Modified: lldb/trunk/tools/driver/IOChannel.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/driver/IOChannel.cpp?rev=134955&r1=134954&r2=134955&view=diff
==============================================================================
--- lldb/trunk/tools/driver/IOChannel.cpp (original)
+++ lldb/trunk/tools/driver/IOChannel.cpp Mon Jul 11 22:12:18 2011
@@ -85,6 +85,12 @@
         el_insertstr (m_edit_line, m_completion_key);
         return CC_REDISPLAY;
     }
+    else if (num_completions == -2)
+    {
+        el_deletestr (m_edit_line, line_info->cursor - line_info->buffer);
+        el_insertstr (m_edit_line, completions.GetStringAtIndex(0));
+        return CC_REDISPLAY;
+    }
 
     // If we get a longer match display that first.
     const char *completion_str = completions.GetStringAtIndex(0);





More information about the lldb-commits mailing list