// Copyright 2019 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/verbs_settings.h"

#include <ctype.h>

#include <algorithm>

#include "src/developer/debug/zxdb/client/breakpoint.h"
#include "src/developer/debug/zxdb/client/execution_scope.h"
#include "src/developer/debug/zxdb/client/filter.h"
#include "src/developer/debug/zxdb/client/session.h"
#include "src/developer/debug/zxdb/client/setting_schema.h"
#include "src/developer/debug/zxdb/client/setting_schema_definition.h"
#include "src/developer/debug/zxdb/client/thread.h"
#include "src/developer/debug/zxdb/common/adapters.h"
#include "src/developer/debug/zxdb/console/command.h"
#include "src/developer/debug/zxdb/console/command_parser.h"
#include "src/developer/debug/zxdb/console/command_utils.h"
#include "src/developer/debug/zxdb/console/console.h"
#include "src/developer/debug/zxdb/console/format_settings.h"
#include "src/developer/debug/zxdb/console/input_location_parser.h"
#include "src/developer/debug/zxdb/console/nouns.h"
#include "src/developer/debug/zxdb/console/output_buffer.h"
#include "src/developer/debug/zxdb/console/string_util.h"
#include "src/developer/debug/zxdb/console/verbs.h"
#include "src/lib/fxl/strings/string_printf.h"

namespace zxdb {

namespace {

constexpr int kValueOnlySwitch = 1;

// TODO(brettw) Some of this is very repetitive. The Check*() functions and the big block in
// GetSettingContext() duplicate getting scopes and checking stuff.
//
// It would be nice if this was expressed in more of a table form to eliminate this code. The
// Level enum could also be removed if the setting store description could be added to the
// SettingContext.

// Struct to represents all the context needed to correctly reason about the settings commands.
struct SettingContext {
  enum class Level {
    kGlobal,
    kTarget,
    kThread,
    kBreakpoint,
    kFilter,
  };

  // The SettingStore we're using. This will either be the one the user specified or the implicit
  // one deteched for the value. It will be null if the name is empty and there was no explicitly
  // specified one.
  SettingStore* store = nullptr;

  // Set when the user has explicitly set the setting store ("thread 1 set ..."). False means the
  // store was determined implicitly based on the name.
  bool explicit_store = false;

  std::string name;
  SettingValue value;

  // At what level the setting was applied.
  Level level = Level::kGlobal;

  // What kind of operation this is for set commands.
  ParsedSetCommand::Operation op = ParsedSetCommand::kAssign;
};

// Fixes up user typing for a setting name by lower-casing.
std::string CanonicalizeSettingName(const std::string& input) {
  std::string output;
  output.reserve(input.size());
  for (char c : input)
    output.push_back(tolower(c));
  return output;
}

bool CheckGlobal(ConsoleContext* context, const Command& cmd, const std::string& setting_name,
                 SettingContext* out) {
  if (!context->session()->system().settings().schema()->HasSetting(setting_name))
    return false;
  out->store = &context->session()->system().settings();
  out->level = SettingContext::Level::kGlobal;
  return true;
}

bool CheckTarget(ConsoleContext* context, const Command& cmd, const std::string& setting_name,
                 SettingContext* out) {
  if (!cmd.target()->settings().schema()->HasSetting(setting_name))
    return false;
  out->store = &cmd.target()->settings();
  out->level = SettingContext::Level::kTarget;
  return true;
}

bool CheckThread(ConsoleContext* context, const Command& cmd, const std::string& setting_name,
                 SettingContext* out) {
  if (!cmd.thread() || !cmd.thread()->settings().schema()->HasSetting(setting_name))
    return false;
  out->store = &cmd.thread()->settings();
  out->level = SettingContext::Level::kThread;
  return true;
}

// Applies the hierarchical rules for getting/setting a setting and fills the give SettingContext.
// It takes into account the noun overrides.
Err GetSettingContext(ConsoleContext* context, const Command& cmd, const std::string& setting_name,
                      SettingContext* out) {
  if (!cmd.target())
    return Err("No process found. Please file a bug with a repro.");

  out->name = CanonicalizeSettingName(setting_name);

  // Handle noun overrides for getting/setting on specific objects.
  // TODO(brettw) see above for TODO about reducing this duplication.
  if (cmd.HasNoun(Noun::kThread)) {
    out->store = cmd.thread() ? &cmd.thread()->settings() : nullptr;
    out->explicit_store = true;
    out->level = SettingContext::Level::kThread;
  } else if (cmd.HasNoun(Noun::kProcess)) {
    out->store = &cmd.target()->settings();
    out->explicit_store = true;
    out->level = SettingContext::Level::kTarget;
  } else if (cmd.HasNoun(Noun::kGlobal)) {
    out->store = &context->session()->system().settings();
    out->explicit_store = true;
    out->level = SettingContext::Level::kGlobal;
  } else if (cmd.HasNoun(Noun::kBreakpoint)) {
    out->store = cmd.breakpoint() ? &cmd.breakpoint()->settings() : nullptr;
    out->explicit_store = true;
    out->level = SettingContext::Level::kBreakpoint;
  } else if (cmd.HasNoun(Noun::kFilter)) {
    out->store = cmd.filter() ? &cmd.filter()->settings() : nullptr;
    out->explicit_store = true;
    out->level = SettingContext::Level::kFilter;
  }

  // When no name is specified, there's no implicit setting store to look up.
  if (out->name.empty())
    return Err();

  if (out->store) {
    // Found an explicitly requested setting store.
    if (cmd.verb() == Verb::kSet) {
      // Use the generic definition from the schama (if any).
      if (const SettingSchema::Record* record = out->store->schema()->GetSetting(out->name))
        out->value = record->default_value;
    } else if (cmd.verb() == Verb::kGet) {
      // Use the specific value from the store.
      out->value = out->store->GetValue(out->name);
    }
    return Err();
  }

  // Didn't found an explicit specified store, so lookup in the current context. Since the
  // settings can be duplicated on different levels, we need to search in the order that makes
  // sense for the command.
  out->explicit_store = false;

  // This array encodes the order we search from the most global to most specific store. This is
  // not the same as the SettingStore fallback because "set" searches from global->specific ("get"
  // does the reverse).
  using CheckFunction =
      bool (*)(ConsoleContext*, const Command&, const std::string&, SettingContext*);
  const CheckFunction kGlobalToSpecific[] = {
      &CheckGlobal,
      &CheckTarget,
      &CheckThread,
  };

  if (cmd.verb() == Verb::kSet) {
    // When setting, choose the most global context the setting can apply to.
    for (const auto cur : kGlobalToSpecific) {
      if (cur(context, cmd, out->name, out)) {
        // Just get the default value so the type is set properly.
        out->value = out->store->schema()->GetSetting(out->name)->default_value;
        return Err();
      }
    }
  } else if (cmd.verb() == Verb::kGet) {
    // When getting, choose the most specific context the setting can apply to.
    for (const auto cur : Reversed(kGlobalToSpecific)) {
      if (cur(context, cmd, out->name, out)) {
        // Getting additionally requires that the setting be non-null. We want to find the first
        // one that might apply.
        out->value = out->store->GetValue(out->name);
        if (!out->value.is_null())
          return Err();
      }
    }
  }

  return Err("Could not find setting \"%s\".", out->name.data());
}

// get ---------------------------------------------------------------------------------------------

const char kGetShortHelp[] = "get: Prints setting values.";
const char kGetHelp[] =
    R"([ <object> ] get [ --value-only ] [ <setting-name> ]

  Prints setting values.

  Settings are hierarchical for processes and threads. This means that
  thread settings will inherit from the process if they don't exist on
  the thread, and process settings will inherit from the global settings
  if they don't exist on the process.

get

    By itself, "get" will show the global settings and the ones for the
    current thread and process.

    Example:
      get

get <setting-name>

    Prints the value of the named setting. It will search the current
    thread, followed by the current process, and then global settings.

    Examples:
      get build-dirs
      get show-stdout

<object> get

    Prints all settings from a specific object.

    Examples:
      process 1 thread 1 get
      thread get              // Uses the current thread.
      filter 2 get
      global get              // Explicitly requests only global values
                              // (processes and threads may override).

<object> get <setting-name>

    Prints a named setting from a specific object.

    Examples:
      filter 2 get pattern
      filter get pattern     // Uses the current filter.

Options

  --value-only
      Displays only the value of the setting without any help text or
      formatting.
)";

// Outputs the general settings in the following order: System -> Target -> Thread
Err CompleteSettingsToOutput(const Command& cmd, ConsoleContext* context, OutputBuffer* out) {
  out->Append(OutputBuffer(Syntax::kHeading, "Global\n"));
  out->Append(FormatSettingStore(context, context->session()->system().settings()));
  out->Append("\n");

  if (Target* target = cmd.target(); target && !target->settings().schema()->empty()) {
    auto title = fxl::StringPrintf("Process %d\n", context->IdForTarget(target));
    out->Append(OutputBuffer(Syntax::kHeading, std::move(title)));
    out->Append(FormatSettingStore(context, target->settings()));
    out->Append("\n");
  }

  if (Thread* thread = cmd.thread(); thread && !thread->settings().schema()->empty()) {
    auto title = fxl::StringPrintf("Thread %d\n", context->IdForThread(thread));
    out->Append(OutputBuffer(Syntax::kHeading, std::move(title)));
    out->Append(FormatSettingStore(context, thread->settings()));
    out->Append("\n");
  }

  return Err();
}

Err DoGet(ConsoleContext* console_context, const Command& cmd) {
  std::string input_name;
  if (!cmd.args().empty()) {
    if (cmd.args().size() > 1)
      return Err("Expected only one setting name");
    input_name = cmd.args()[0];
  }

  Err err;
  SettingContext setting_context;
  if (err = GetSettingContext(console_context, cmd, input_name, &setting_context); err.has_error())
    return err;
  // Use setting_context.name from here on down instead of input_name because it's canonicalized.

  OutputBuffer out;
  if (!setting_context.name.empty()) {
    // Getting one setting.
    if (setting_context.value.is_null()) {
      err = Err("Could not find setting %s", setting_context.name.c_str());
    } else if (cmd.HasSwitch(kValueOnlySwitch)) {
      out = FormatSettingValue(console_context, setting_context.value);
    } else {
      const SettingSchema::Record* record =
          setting_context.store->schema()->GetSetting(setting_context.name);
      FX_DCHECK(record);  // Should always succeed if GetSettingContext did.
      out = FormatSetting(console_context, setting_context.name, record->description,
                          setting_context.value);
    }
  } else if (setting_context.explicit_store) {
    // Getting all settings on one object. The object may not be valid (e.g. "thread get" when
    // there's no current thread).
    if (setting_context.store) {
      out.Append(FormatSettingStore(console_context, *setting_context.store));
      out.Append("\n");
    } else {
      err = Err("No current object of this type.");
    }
  } else {
    // Implcitly getting all settings, show the general global/process/thread ones.
    err = CompleteSettingsToOutput(cmd, console_context, &out);
  }

  if (err.has_error())
    return err;
  Console::get()->Output(out);
  return Err();
}

// set ---------------------------------------------------------------------------------------------

const char kSetShortHelp[] = "set: Set a setting value.";
const char kSetHelp[] =
    R"([ <object> ] set <setting-name> [ <modification-type> ] <value>*

  Sets the value of a setting.

  See which settings are available, their names and current values with
  the "get" command (see "help get").

  As a special-case, the syntax "set <setting-name> =" (with no value) will
  clear the setting back to its default value. This can also be used for thread-
  or process-specific settings to case a fallback to the global value.

Arguments

  <object>
      The object that the setting is on. If unspecified, it will search
      the current thread, process, and then the global settings for a
      match to set.

  <setting_name>
      The setting that will modified. Case-insensitive.

  <modification-type>
      Operator that indicates how to mutate a list. For non-lists only = (the
      default) is supported:

      =   Replace the current contents (the default).
      +=  Append the given value to the list.
      -=  Search for the given value and remove it.

  <value>
      The value(s) to set, add, or remove. Multiple values for list settings
      are whitespace separated. You can "quote" strings to include literal
      spaces.

Setting Types

  Each setting has a particular type.

  bool
      "0", "false" -> false
      "1", "true"  -> true

  integer
      Any string convertible to integer.

  string
      Strings can be "quoted" to include whitespace. Otherwise whitespace is
      used as a delimiter.

  list
      A list of one or more string separated by whitespace. Strings can be
      "quoted" to include literal whitespace.

Examples

  [zxdb] set show-stdout true
  New value show-stdout system-wide:
  true

  [zxdb] pr 3 set vector-format double
  New value vector-format for process 3:
  double

  [zxdb] get build-dirs
  • /home/me/build
  • /home/me/other/out

  [zxdb] set build-dirs += /tmp/build
  New value build-dirs system-wide:
  • /home/me/build
  • /home/me/other/out
  • /tmp/build

  [zxdb] set build-dirs = /other/build/location /other/build2
  New value build-dirs system-wide:
  • /other/build/location
  • /other/build2

  [zxdb] set build-dirs =
      Clears the build-dirs variable.
)";

Err SetBool(SettingStore* store, const std::string& setting_name, const std::string& value) {
  std::optional<bool> bool_val = StringToBool(value);
  if (!bool_val)
    return Err("%s expects a boolean. See \"help set\" for valid values.", setting_name.data());

  store->SetBool(setting_name, *bool_val);
  return Err();
}

Err SetInt(SettingStore* store, const std::string& setting_name, const std::string& value) {
  int out;
  Err err = StringToInt(value, &out);
  if (err.has_error()) {
    return Err("%s expects a valid int: %s", setting_name.data(), err.msg().data());
  }

  return store->SetInt(setting_name, out);
}

Err SetList(const SettingContext& setting_context, const std::vector<std::string>& values,
            SettingStore* store) {
  if (setting_context.op == ParsedSetCommand::kAssign)
    return store->SetList(setting_context.name, values);

  if (setting_context.op == ParsedSetCommand::kAppend) {
    auto list = store->GetList(setting_context.name);
    list.insert(list.end(), values.begin(), values.end());
    return store->SetList(setting_context.name, list);
  }

  if (setting_context.op == ParsedSetCommand::kRemove) {
    // Search for the elements to remove.
    auto list = store->GetList(setting_context.name);

    for (const std::string& value : values) {
      auto first_to_remove = std::remove(list.begin(), list.end(), value);
      if (first_to_remove == list.end()) {
        // Item not found.
        return Err("Could not find \"" + value + "\" to remove from setting list.");
      }
      list.erase(first_to_remove, list.end());
    }
    return store->SetList(setting_context.name, list);
  }

  FX_NOTREACHED();
  return Err();
}

Err SetExecutionScope(ConsoleContext* console_context, const SettingContext& setting_context,
                      const std::string& scope_str, SettingStore* store) {
  ErrOr<ExecutionScope> scope_or = ParseExecutionScope(console_context, scope_str);
  if (scope_or.has_error())
    return scope_or.err();

  return store->SetExecutionScope(setting_context.name, scope_or.value());
}

Err SetInputLocations(const Frame* optional_frame, const SettingContext& setting_context,
                      const std::string& input, SettingStore* store) {
  std::vector<InputLocation> locs;
  if (Err err = ParseLocalInputLocation(optional_frame, input, &locs); err.has_error())
    return err;

  return store->SetInputLocations(setting_context.name, std::move(locs));
}

// Will run the sets against the correct SettingStore:
// |setting_context| represents the required context needed to reason about the command.
// for user feedback.
// |out| is the resultant setting, which is used for user feedback.
Err SetSetting(ConsoleContext* console_context, const Frame* optional_frame,
               const SettingContext& setting_context, const std::vector<std::string>& values,
               SettingStore* store, SettingValue* out) {
  Err err;
  if (setting_context.op != ParsedSetCommand::kAssign && !setting_context.value.is_list())
    return Err("Appending/removing only works for list options.");

  if (values.empty()) {
    if (err = store->ClearValue(setting_context.name); err.has_error())
      return err;

    // When clearing, report the new value is the default reported by the store.
    *out = store->GetValue(setting_context.name);
    return Err();
  }

  switch (setting_context.value.type()) {
    case SettingType::kBoolean:
      err = SetBool(store, setting_context.name, values[0]);
      break;
    case SettingType::kInteger:
      err = SetInt(store, setting_context.name, values[0]);
      break;
    case SettingType::kString:
      err = store->SetString(setting_context.name, values[0]);
      break;
    case SettingType::kList:
      err = SetList(setting_context, values, store);
      break;
    case SettingType::kExecutionScope:
      err = SetExecutionScope(console_context, setting_context, values[0], store);
      break;
    case SettingType::kInputLocations:
      err = SetInputLocations(optional_frame, setting_context, values[0], store);
      break;
    case SettingType::kNull:
      return Err("Could not find setting %s.", setting_context.name.c_str());
  }

  if (!err.ok())
    return err;

  *out = store->GetValue(setting_context.name);
  return Err();
}

OutputBuffer FormatSetFeedback(ConsoleContext* console_context,
                               const SettingContext& setting_context,
                               const std::string& setting_name, const Command& cmd,
                               const SettingValue& value) {
  OutputBuffer out;
  out.Append("New value ");
  out.Append(Syntax::kVariable, setting_name);

  std::string message;
  switch (setting_context.level) {
    case SettingContext::Level::kGlobal:
      out.Append(" system-wide:\n");
      break;
    case SettingContext::Level::kTarget: {
      int target_id = console_context->IdForTarget(cmd.target());
      out.Append(fxl::StringPrintf(" for process %d:\n", target_id));
      break;
    }
    case SettingContext::Level::kThread: {
      int target_id = console_context->IdForTarget(cmd.target());
      int thread_id = console_context->IdForThread(cmd.thread());
      out.Append(fxl::StringPrintf(" for thread %d of process %d:\n", thread_id, target_id));
      break;
    }
    case SettingContext::Level::kBreakpoint: {
      out.Append(fxl::StringPrintf(" for breakpoint %d:\n",
                                   console_context->IdForBreakpoint(cmd.breakpoint())));
      break;
    }
    case SettingContext::Level::kFilter: {
      out.Append(
          fxl::StringPrintf(" for filter %d:\n", console_context->IdForFilter(cmd.filter())));
      break;
    }
    default:
      FX_NOTREACHED() << "Should not receive a default setting.";
  }

  out.Append(FormatSettingShort(console_context, setting_name, value));
  return out;
}

Err DoSet(ConsoleContext* console_context, const Command& cmd) {
  // The command parser will provide everything as one argument.
  if (cmd.args().size() != 1)
    return Err("Wrong amount of Arguments. See \"help set\".");

  ErrOr<ParsedSetCommand> parsed = ParseSetCommand(cmd.args()[0]);
  if (parsed.has_error())
    return parsed.err();

  // See where this setting would be stored.
  SettingContext setting_context;
  Err err = GetSettingContext(console_context, cmd, parsed.value().name, &setting_context);
  if (err.has_error())
    return err;
  setting_context.op = parsed.value().op;

  // Validate that the operations makes sense.
  if (parsed.value().op != ParsedSetCommand::kAssign && !setting_context.value.is_list())
    return Err("List modification (+=, -=) used on a non-list option.");

  if (parsed.value().values.size() > 1u && !setting_context.value.is_list()) {
    return Err(
        "Multiple values on a non-list option. Use \"quotes\" to include literal whitespace.");
  }

  SettingValue out_value;  // Used for showing the new value.
  err = SetSetting(console_context, cmd.frame(), setting_context, parsed.value().values,
                   setting_context.store, &out_value);
  if (!err.ok())
    return err;

  // Be sure to use the canonicalized name in the setting_context for the output.
  Console::get()->Output(
      FormatSetFeedback(console_context, setting_context, setting_context.name, cmd, out_value));
  return Err();
}

// Equivalend to isalpha with no C local complexity.
bool IsSettingNameAlpha(const char c) { return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'); }

// Setting names are only letters and hyphens.
//
// The "name" is annoying to parse because it can't end in a "-" and we have to differentiate that
// from a "name-=..." command which requires lookahead. As a result, this takes the full string
// and the index of the character to check.
bool IsSettingNameChar(const std::string& input, size_t i) {
  if (IsSettingNameAlpha(input[i]))
    return true;  // Normal letter.

  if (input[i] == '-') {
    // Disambiguate internal hyphens from "-=".
    if (i + 1 < input.size() && IsSettingNameAlpha(input[i + 1]))
      return true;  // More name to come.
  }

  return false;
}

void CompleteSet(const Command& cmd, const std::string& prefix,
                 std::vector<std::string>* completions) {
  // Find the end of the setting name. The argument is a whole expression as one string, so if we're
  // past the setting name we're past the part we know how to complete.
  size_t cur;
  for (cur = 0; cur < prefix.size() && IsSettingNameChar(prefix, cur); ++cur)
    ;

  if (cur == prefix.size()) {
    for (const auto& [name, _] : System::GetSchema()->settings()) {
      if (!name.compare(0, prefix.size(), prefix)) {
        completions->push_back(name);
      }
    }

    for (const auto& [name, _] : Target::GetSchema()->settings()) {
      if (!name.compare(0, prefix.size(), prefix)) {
        completions->push_back(name);
      }
    }

    for (const auto& [name, _] : Thread::GetSchema()->settings()) {
      if (!name.compare(0, prefix.size(), prefix)) {
        completions->push_back(name);
      }
    }
  }

  // TODO: We need to refactor parsing a bit if we want to complete options.
}

}  // namespace

// Grammar:
//   command := <name> [ <whitespace> ] [ <operator> <whitespace> ] [ <value> * ]
//   name := ('A' - 'Z') | ('a' - 'z') | '-'  // See IsSettingNameChar() for qualifications.
//   operator := "=" | '+=' | '-='
//
// A "value" is a possibly quoted string parsed as a command token. The whole thing can't be parsed
// as a command because we want to handle "name value" as well as "name = value" and "name=value".
ErrOr<ParsedSetCommand> ParseSetCommand(const std::string& input) {
  ParsedSetCommand result;
  size_t cur = 0;

  // Name.
  while (cur < input.size() && IsSettingNameChar(input, cur)) {
    result.name.push_back(input[cur]);
    ++cur;
  }
  if (result.name.empty())
    return Err("Expected a setting name to set.");

  // Require whitespace or an operator after the name to prevent "name$" from being valid.
  bool has_name_terminator = false;

  // Whitespace.
  while (cur < input.size() && isspace(input[cur])) {
    has_name_terminator = true;
    ++cur;
  }

  // Special-case the error message for no value to be more helpful. To clear the value we require
  // "=" so the command is more explicit ("set foo" may be typed by somebody who doesn't know what
  // they're doing).
  if (cur == input.size())
    return Err("Expecting a value to set. Use \"set setting-name setting-value\".");

  // Optional operator.
  if (cur < input.size() && input[cur] == '=') {
    has_name_terminator = true;
    result.op = ParsedSetCommand::kAssign;
    ++cur;
  } else if (cur < input.size() - 1 && input[cur] == '+' && input[cur + 1] == '=') {
    has_name_terminator = true;
    result.op = ParsedSetCommand::kAppend;
    cur += 2;
  } else if (cur < input.size() - 1 && input[cur] == '-' && input[cur + 1] == '=') {
    has_name_terminator = true;
    result.op = ParsedSetCommand::kRemove;
    cur += 2;
  }

  // Check for the name terminator.
  if (!has_name_terminator)
    return Err("Invalid setting name.");

  // Whitespace.
  while (cur < input.size() && isspace(input[cur]))
    ++cur;

  // Value(s) parsed as a command token. This handles the various types of escaping and quoting
  // supported by the interactive command line.
  //
  // The value can be omitted for sets which clears the value to the default.
  std::vector<CommandToken> value_tokens;
  if (Err err = TokenizeCommand(input.substr(cur), &value_tokens); err.has_error())
    return err;
  if (result.op != ParsedSetCommand::kAssign && value_tokens.empty())
    return Err("Expected a value to add/remove.");

  for (const auto& token : value_tokens)
    result.values.push_back(std::move(token.str));
  return result;
}

ErrOr<ExecutionScope> ParseExecutionScope(ConsoleContext* console_context,
                                          const std::string& input) {
  // Use the command parser to get the scope.
  Command parsed;
  if (Err err = ParseCommand(input, &parsed); err.has_error())
    return err;

  const char kScopeHelp[] =
      "Scope not valid, expecting \"global\", \"process\", or \"thread\" only.";

  // We accept the "global", "process", and "thread" nouns, and no verbs or switches.
  if (parsed.verb() != Verb::kNone)
    return Err(kScopeHelp);
  if (parsed.ValidateNouns({Noun::kGlobal, Noun::kProcess, Noun::kThread}).has_error())
    return Err(kScopeHelp);
  if (!parsed.args().empty())
    return Err(kScopeHelp);

  // Convert the nouns to objects.
  if (Err err = console_context->FillOutCommand(&parsed); err.has_error())
    return err;

  // Valid, convert to scope based on what nouns were specified.
  if (parsed.HasNoun(Noun::kThread))
    return ExecutionScope(parsed.thread());
  if (parsed.HasNoun(Noun::kProcess))
    return ExecutionScope(parsed.target());
  return ExecutionScope();
}

void AppendSettingsVerbs(std::map<Verb, VerbRecord>* verbs) {
  VerbRecord get(&DoGet, {"get"}, kGetShortHelp, kGetHelp, CommandGroup::kGeneral);
  get.switches.emplace_back(kValueOnlySwitch, false, "value-only");
  (*verbs)[Verb::kGet] = std::move(get);

  VerbRecord set(&DoSet, &CompleteSet, {"set"}, kSetShortHelp, kSetHelp, CommandGroup::kGeneral);
  set.param_type = VerbRecord::kOneParam;
  (*verbs)[Verb::kSet] = std::move(set);
}

}  // namespace zxdb
