// 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, and backslash-escape literal quotes.

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
  Set global show-stdout = true

  [zxdb] pr 3 set vector-format double
  Set process 3 vector-format = double

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

  [zxdb] set build-dirs += /tmp/build
  Set global build-dirs =
    • /home/me/build
    • /home/me/other/out
    • /tmp/build

  [zxdb] set build-dirs = /other/build/location /other/build2
  Set global build-dirs build-dirs =
    • /other/build/location
    • /other/build2

  [zxdb] set build-dirs =
  Set global build-dirs = <empty>
)";

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;

  std::string message;
  switch (setting_context.level) {
    case SettingContext::Level::kGlobal:
      out.Append("Set global");
      break;
    case SettingContext::Level::kTarget:
      out.Append("Set process ");
      out.Append(Syntax::kSpecial, std::to_string(console_context->IdForTarget(cmd.target())));
      break;
    case SettingContext::Level::kThread:
      out.Append("Set process ");
      out.Append(Syntax::kSpecial, std::to_string(console_context->IdForTarget(cmd.target())));
      out.Append(" thread ");
      out.Append(Syntax::kSpecial, std::to_string(console_context->IdForThread(cmd.thread())));
      break;
    case SettingContext::Level::kBreakpoint:
      out.Append("Set breakpoint ");
      out.Append(Syntax::kSpecial,
                 std::to_string(console_context->IdForBreakpoint(cmd.breakpoint())));
      break;
    case SettingContext::Level::kFilter:
      out.Append("Set filter ");
      out.Append(Syntax::kSpecial, std::to_string(console_context->IdForFilter(cmd.filter())));
      break;
    default:
      FX_NOTREACHED() << "Should not receive a default setting.";
  }

  out.Append(" ");
  out.Append(Syntax::kVariable, setting_name);
  out.Append(" = ");

  if (value.is_list() && !value.get_list().empty())
    out.Append("\n");  // Put list items on their own lines.
  out.Append(FormatSettingShort(console_context, setting_name, value, 2));
  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(
        "Expected a setting and a new value.\n"
        " • Type \"help set\" for usage.\n"
        " • Type \"get\" to list all settings and their current values.\n"
        " • Type \"get <setting-name>\" for documentation on a setting.");
  }

  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()) {
    // When the value is a non-list, assume input with spaces is a single literal. This allows
    // input like:
    //    bp set scope process 1
    // without quoting "process 1" which is much more intuitive. The potentially surprising side
    // effect of this rule is that if two things are quoted (triggering this condition), the quotes
    // will be literally included in the value, while if only one thing is quoted, the quotes will
    // br trimmed. But this edge case is not worth adding extra complexity here.
    parsed.value().values.clear();
    parsed.value().values.push_back(parsed.value().raw_value);
  }

  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;

  // Save the original raw value (trimming whitespace from the right).
  result.raw_value = input.substr(cur);
  while (!result.raw_value.empty() && isspace(result.raw_value.back()))
    result.raw_value.resize(result.raw_value.size() - 1);

  // 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. The thread or process could have
  // failed to resolve to objects if there is no current one.
  if (parsed.HasNoun(Noun::kThread)) {
    if (!parsed.thread())
      return Err("There is no current thread to use for the scope.");
    return ExecutionScope(parsed.thread());
  }
  if (parsed.HasNoun(Noun::kProcess)) {
    if (!parsed.target())
      return Err("There is no current process to use for the scope.");
    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
