blob: e68c5d93513416719f60e715509121516b5c34ef [file] [log] [blame]
// Copyright 2020 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/developer/debug/zxdb/console/commands/verb_display.h"
#include "src/developer/debug/zxdb/client/session.h"
#include "src/developer/debug/zxdb/client/setting_schema_definition.h"
#include "src/developer/debug/zxdb/client/system.h"
#include "src/developer/debug/zxdb/console/command.h"
#include "src/developer/debug/zxdb/console/command_utils.h"
#include "src/developer/debug/zxdb/console/console.h"
#include "src/developer/debug/zxdb/console/output_buffer.h"
#include "src/developer/debug/zxdb/console/print_command_utils.h"
#include "src/developer/debug/zxdb/console/verbs.h"
namespace zxdb {
namespace {
const char kDisplayShortHelp[] = "display: Print an expression on every stop.";
const char kDisplayHelp[] =
R"(display <expression>
Adds the given expression to the global list that will be evaluated and
printed for every stop.
The "display" setting
This command is syntactic sugar for the settings system where the setting
named "display" keeps this information. Use the settings system to view or
remove expressions (there is no "undisplay" command).
The settings system is hierarchical (see "help get" for more) so there are
global, process, and thread-specific display lists. The most specific nonempty
list will be used when a thread stops.
For more complex ways to modify the display list, use the settings system (see
"help set"). Note that expressions with spaces will need to be quoted when
used with the settings system, but this is not necessary when using the
"display" verb since it can only add one expression at a time.
Examples
display foo->bar
set display += "foo->bar"
global set display += "foo->bar"
These commands are equivalent to add the expression to the global
"display" list.
get display
Prints the current thread's "display" list. This will fall back on the
process' list, and then on the global list if unset.
set display=
Clears all variables from the global display list.
set display -= "foo->bar"
Removes the given expression from the display list, keeping others the
same.
thread set display += i
thread get display
thread set display -= i
thread set display =
Adds, prints, removes, and clears the thread-specific display list. These
are the same as the above examples but with "thread" added to the
beginning. If there is a thread-specific display list, it will take effect
whenever that thread stops instead of process or global ones.
process set display = i j "foo->bar"
Overwrites all contents of the process-specific display list to print the
given three expressions. The process list will take effect when the
process stops and there is no thread-specific one.
)";
const char kCommandHelp[] =
" • View current list: get display\n"
" • Remove one: set display -= your_var\n"
" • Clear list: set display =\n";
Err RunVerbDisplay(ConsoleContext* context, const Command& cmd) {
if (cmd.args().size() != 1) {
// We could print the current list fo stuff to display here like GDB, but would prefer that
// people learn to interact with the settings system since they'll need that to remove values
// anyway.
return Err(
"The \"display\" verb is syntactic sugar for the settings system's \"display\"\n"
"setting. It's a shortcut to add expressions to display, but otherwise use the\n"
"settings commands:\n" +
std::string(kCommandHelp));
}
// The thing to watch. Note that we can't actually validate this here because the expression might
// only be valid in a different context.
const std::string& new_expression = cmd.args()[0];
SettingStore* store = &context->session()->system().settings();
// Be nice and avoid duplicating an expression.
std::vector<std::string> list = store->GetList(ClientSettings::Thread::kDisplay);
for (const auto& existing : list) {
if (new_expression == existing)
return Err("Already watching expression \"" + new_expression + "\".");
}
list.push_back(new_expression);
store->SetList(ClientSettings::Thread::kDisplay, list);
OutputBuffer out("Added to display for every stop: ");
out.Append(Syntax::kHeading, new_expression);
out.Append("\n");
out.Append(Syntax::kComment, kCommandHelp);
Console::get()->Output(out);
// Output the new expression right away.
ConsoleFormatOptions options;
options.verbosity = ConsoleFormatOptions::Verbosity::kMinimal;
options.wrapping = ConsoleFormatOptions::Wrapping::kSmart;
options.pointer_expand_depth = 2;
Console::get()->Output(
FormatExpressionsForConsole({new_expression}, options, GetEvalContextForCommand(cmd)));
return Err();
}
} // namespace
VerbRecord GetDisplayVerbRecord() {
VerbRecord record(&RunVerbDisplay, {"display"}, kDisplayShortHelp, kDisplayHelp,
CommandGroup::kQuery);
record.param_type = VerbRecord::kOneParam; // Allows arbitrary unquoted input.
return record;
}
} // namespace zxdb