mirror of
https://github.com/nushell/nushell.git
synced 2025-08-23 04:31:26 +02:00
explore: remove :config
, :show-config
, :tweak
commands (#10259)
More trimming of underused `explore` functionality. The `explore` command has subcommands that can be run like `:config` or `:try` or whatnot. This PR removes the `:config`, `:show-config`, and `:tweak` commands which are all for viewing+modifying config. These are interesting commands and they were cool experiments, but ultimately I don't think they fit with our plans for a simplified `explore`. They'd need a lot more polish if we want to keep them and I don't think we do. Happy to discuss if I've missed a good reason to keep these. cc @fdncred
This commit is contained in:
@@ -1,172 +0,0 @@
|
||||
use std::io::Result;
|
||||
|
||||
use nu_protocol::{
|
||||
engine::{EngineState, Stack},
|
||||
record, Value,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
nu_common::{nu_str, NuSpan},
|
||||
registry::Command,
|
||||
views::{configuration, ConfigurationView, Preview},
|
||||
};
|
||||
|
||||
use super::{default_color_list, ConfigOption, HelpManual, ViewCommand};
|
||||
|
||||
#[derive(Default, Clone)]
|
||||
pub struct ConfigCmd {
|
||||
commands: Vec<Command>,
|
||||
groups: Vec<ConfigOption>,
|
||||
}
|
||||
|
||||
impl ConfigCmd {
|
||||
pub const NAME: &'static str = "config";
|
||||
|
||||
pub fn from_commands(commands: Vec<Command>) -> Self {
|
||||
Self {
|
||||
commands,
|
||||
groups: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn register_group(&mut self, group: ConfigOption) {
|
||||
self.groups.push(group);
|
||||
}
|
||||
}
|
||||
|
||||
impl ViewCommand for ConfigCmd {
|
||||
type View = ConfigurationView;
|
||||
|
||||
fn name(&self) -> &'static str {
|
||||
Self::NAME
|
||||
}
|
||||
|
||||
fn usage(&self) -> &'static str {
|
||||
""
|
||||
}
|
||||
|
||||
fn help(&self) -> Option<HelpManual> {
|
||||
let config_options = vec![
|
||||
ConfigOption::new(
|
||||
":config options",
|
||||
"A border color of menus",
|
||||
"config.border_color",
|
||||
default_color_list(),
|
||||
),
|
||||
ConfigOption::new(
|
||||
":config options",
|
||||
"Set a color of entries in a list",
|
||||
"config.list_color",
|
||||
default_color_list(),
|
||||
),
|
||||
ConfigOption::new(
|
||||
":config options",
|
||||
"Set a color of a chosen entry in a list",
|
||||
"config.cursor_color",
|
||||
default_color_list(),
|
||||
),
|
||||
];
|
||||
|
||||
Some(HelpManual {
|
||||
name: Self::NAME,
|
||||
description:
|
||||
"Interactive configuration manager.\nCan be used to set various explore settings.\n\nLike an interactive version of :tweak",
|
||||
config_options,
|
||||
arguments: vec![],
|
||||
examples: vec![],
|
||||
input: vec![],
|
||||
})
|
||||
}
|
||||
|
||||
fn parse(&mut self, _: &str) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn display_config_option(&mut self, _: String, _: String, _: String) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
fn spawn(
|
||||
&mut self,
|
||||
engine_state: &EngineState,
|
||||
stack: &mut Stack,
|
||||
_: Option<Value>,
|
||||
) -> Result<Self::View> {
|
||||
let mut options = vec![];
|
||||
|
||||
let default_table = create_default_value();
|
||||
for cmd in &self.commands {
|
||||
let cmd = match cmd {
|
||||
Command::Reactive(_) => continue,
|
||||
Command::View { cmd, .. } => cmd,
|
||||
};
|
||||
|
||||
let help = match cmd.help() {
|
||||
Some(help) => help,
|
||||
None => continue,
|
||||
};
|
||||
|
||||
for opt in help.config_options {
|
||||
let mut values = vec![];
|
||||
for value in opt.values {
|
||||
let mut cmd = cmd.clone();
|
||||
|
||||
let can_be_displayed = cmd.display_config_option(
|
||||
opt.group.clone(),
|
||||
opt.key.clone(),
|
||||
value.example.to_string(),
|
||||
);
|
||||
let view = if can_be_displayed {
|
||||
cmd.spawn(engine_state, stack, Some(default_table.clone()))?
|
||||
} else {
|
||||
Box::new(Preview::new(&opt.description))
|
||||
};
|
||||
|
||||
let option = configuration::ConfigOption::new(value.example.to_string(), view);
|
||||
values.push(option);
|
||||
}
|
||||
|
||||
let group = configuration::ConfigGroup::new(opt.key, values, opt.description);
|
||||
options.push((opt.group, group));
|
||||
}
|
||||
}
|
||||
|
||||
for opt in &self.groups {
|
||||
let mut values = vec![];
|
||||
for value in &opt.values {
|
||||
let view = Box::new(Preview::new(&opt.description));
|
||||
|
||||
let option = configuration::ConfigOption::new(value.example.to_string(), view);
|
||||
values.push(option);
|
||||
}
|
||||
|
||||
let group =
|
||||
configuration::ConfigGroup::new(opt.key.clone(), values, opt.description.clone());
|
||||
options.push((opt.group.clone(), group));
|
||||
}
|
||||
|
||||
options.sort_by(|(group1, opt1), (group2, opt2)| {
|
||||
group1.cmp(group2).then(opt1.group().cmp(opt2.group()))
|
||||
});
|
||||
|
||||
let options = options.into_iter().map(|(_, opt)| opt).collect();
|
||||
|
||||
Ok(ConfigurationView::new(options))
|
||||
}
|
||||
}
|
||||
|
||||
fn create_default_value() -> Value {
|
||||
let span = NuSpan::unknown();
|
||||
|
||||
let record = |i: usize| {
|
||||
Value::record(
|
||||
record! {
|
||||
"key" => nu_str(format!("key-{i}")),
|
||||
"value" => nu_str(format!("{i}")),
|
||||
},
|
||||
span,
|
||||
)
|
||||
};
|
||||
|
||||
Value::list(vec![record(0), record(1), record(2)], span)
|
||||
}
|
@@ -1,180 +0,0 @@
|
||||
use nu_protocol::{
|
||||
engine::{EngineState, Stack},
|
||||
record, Value,
|
||||
};
|
||||
use ratatui::layout::Rect;
|
||||
use std::collections::HashMap;
|
||||
use std::io::Result;
|
||||
|
||||
use crate::{
|
||||
nu_common::{try_build_table, NuSpan},
|
||||
pager::Frame,
|
||||
util::map_into_value,
|
||||
views::{Layout, Preview, View, ViewConfig},
|
||||
};
|
||||
|
||||
use super::{HelpExample, HelpManual, ViewCommand};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct ConfigShowCmd {
|
||||
format: ConfigFormat,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
enum ConfigFormat {
|
||||
Table,
|
||||
Nu,
|
||||
}
|
||||
|
||||
impl ConfigShowCmd {
|
||||
pub fn new() -> Self {
|
||||
ConfigShowCmd {
|
||||
format: ConfigFormat::Table,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ConfigShowCmd {
|
||||
pub const NAME: &'static str = "config-show";
|
||||
}
|
||||
|
||||
impl ViewCommand for ConfigShowCmd {
|
||||
type View = ConfigView;
|
||||
|
||||
fn name(&self) -> &'static str {
|
||||
Self::NAME
|
||||
}
|
||||
|
||||
fn usage(&self) -> &'static str {
|
||||
""
|
||||
}
|
||||
|
||||
fn help(&self) -> Option<HelpManual> {
|
||||
Some(HelpManual {
|
||||
name: Self::NAME,
|
||||
description:
|
||||
"Show the current `explore` configuration.\nSome default fields might be missing.",
|
||||
arguments: vec![HelpExample::new("nu", "Use a nuon format instead")],
|
||||
config_options: vec![],
|
||||
input: vec![],
|
||||
examples: vec![],
|
||||
})
|
||||
}
|
||||
|
||||
fn display_config_option(&mut self, _: String, _: String, _: String) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
fn parse(&mut self, args: &str) -> Result<()> {
|
||||
if args.trim() == "nu" {
|
||||
self.format = ConfigFormat::Nu;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn spawn(&mut self, _: &EngineState, _: &mut Stack, _: Option<Value>) -> Result<Self::View> {
|
||||
Ok(ConfigView {
|
||||
preview: Preview::new(""),
|
||||
format: self.format.clone(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ConfigView {
|
||||
preview: Preview,
|
||||
format: ConfigFormat,
|
||||
}
|
||||
|
||||
impl View for ConfigView {
|
||||
fn draw(&mut self, f: &mut Frame, area: Rect, cfg: ViewConfig<'_>, layout: &mut Layout) {
|
||||
self.preview.draw(f, area, cfg, layout)
|
||||
}
|
||||
|
||||
fn handle_input(
|
||||
&mut self,
|
||||
engine_state: &EngineState,
|
||||
stack: &mut Stack,
|
||||
layout: &Layout,
|
||||
info: &mut crate::pager::ViewInfo,
|
||||
key: crossterm::event::KeyEvent,
|
||||
) -> Option<crate::pager::Transition> {
|
||||
self.preview
|
||||
.handle_input(engine_state, stack, layout, info, key)
|
||||
}
|
||||
|
||||
fn setup(&mut self, config: ViewConfig<'_>) {
|
||||
let text = self.create_output_string(config);
|
||||
|
||||
self.preview = Preview::new(&text);
|
||||
self.preview
|
||||
.set_value(map_into_value(config.config.clone()));
|
||||
}
|
||||
|
||||
fn exit(&mut self) -> Option<Value> {
|
||||
self.preview.exit()
|
||||
}
|
||||
|
||||
fn collect_data(&self) -> Vec<crate::nu_common::NuText> {
|
||||
self.preview.collect_data()
|
||||
}
|
||||
|
||||
fn show_data(&mut self, i: usize) -> bool {
|
||||
self.preview.show_data(i)
|
||||
}
|
||||
}
|
||||
|
||||
impl ConfigView {
|
||||
fn create_output_string(&mut self, config: ViewConfig) -> String {
|
||||
match self.format {
|
||||
ConfigFormat::Table => {
|
||||
let mut m = config.config.clone();
|
||||
convert_styles(&mut m);
|
||||
|
||||
let value = map_into_value(m);
|
||||
try_build_table(None, config.nu_config, config.style_computer, value)
|
||||
}
|
||||
ConfigFormat::Nu => nu_json::to_string(&config.config).unwrap_or_default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn convert_styles(m: &mut HashMap<String, Value>) {
|
||||
for value in m.values_mut() {
|
||||
convert_styles_value(value);
|
||||
}
|
||||
}
|
||||
|
||||
fn convert_styles_value(value: &mut Value) {
|
||||
match value {
|
||||
Value::String { val, .. } => {
|
||||
if let Some(v) = convert_style_from_string(val) {
|
||||
*value = v;
|
||||
}
|
||||
}
|
||||
Value::List { vals, .. } => {
|
||||
for value in vals {
|
||||
convert_styles_value(value);
|
||||
}
|
||||
}
|
||||
Value::Record { val, .. } => {
|
||||
for value in &mut val.vals {
|
||||
convert_styles_value(value);
|
||||
}
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
fn convert_style_from_string(s: &str) -> Option<Value> {
|
||||
let style = nu_json::from_str::<nu_color_config::NuStyle>(s).ok()?;
|
||||
|
||||
Some(Value::record(
|
||||
record! {
|
||||
"bg" => Value::string(style.bg.unwrap_or_default(), NuSpan::unknown()),
|
||||
"fg" => Value::string(style.fg.unwrap_or_default(), NuSpan::unknown()),
|
||||
"attr" => Value::string(style.attr.unwrap_or_default(), NuSpan::unknown()),
|
||||
},
|
||||
NuSpan::unknown(),
|
||||
))
|
||||
}
|
@@ -60,10 +60,6 @@ impl ViewCommand for ExpandCmd {
|
||||
})
|
||||
}
|
||||
|
||||
fn display_config_option(&mut self, _: String, _: String, _: String) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
fn parse(&mut self, _: &str) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
@@ -104,10 +104,6 @@ impl ViewCommand for HelpCmd {
|
||||
})
|
||||
}
|
||||
|
||||
fn display_config_option(&mut self, _: String, _: String, _: String) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
fn parse(&mut self, args: &str) -> Result<()> {
|
||||
self.input_command = args.trim().to_owned();
|
||||
|
||||
|
@@ -13,19 +13,13 @@ mod nu;
|
||||
mod quit;
|
||||
mod table;
|
||||
mod r#try;
|
||||
mod tweak;
|
||||
|
||||
pub mod config;
|
||||
mod config_show;
|
||||
|
||||
pub use config_show::ConfigShowCmd;
|
||||
pub use expand::ExpandCmd;
|
||||
pub use help::HelpCmd;
|
||||
pub use nu::NuCmd;
|
||||
pub use quit::QuitCmd;
|
||||
pub use r#try::TryCmd;
|
||||
pub use table::TableCmd;
|
||||
pub use tweak::TweakCmd;
|
||||
|
||||
pub trait SimpleCommand {
|
||||
fn name(&self) -> &'static str;
|
||||
@@ -56,8 +50,6 @@ pub trait ViewCommand {
|
||||
|
||||
fn parse(&mut self, args: &str) -> Result<()>;
|
||||
|
||||
fn display_config_option(&mut self, group: String, key: String, value: String) -> bool;
|
||||
|
||||
fn spawn(
|
||||
&mut self,
|
||||
engine_state: &EngineState,
|
||||
|
@@ -64,10 +64,6 @@ impl ViewCommand for NuCmd {
|
||||
})
|
||||
}
|
||||
|
||||
fn display_config_option(&mut self, _: String, _: String, _: String) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
fn parse(&mut self, args: &str) -> Result<()> {
|
||||
self.command = args.trim().to_owned();
|
||||
|
||||
|
@@ -1,7 +1,6 @@
|
||||
use std::io::Result;
|
||||
|
||||
use nu_ansi_term::Style;
|
||||
use nu_color_config::lookup_ansi_color_style;
|
||||
use nu_protocol::{
|
||||
engine::{EngineState, Stack},
|
||||
Value,
|
||||
@@ -122,51 +121,6 @@ impl ViewCommand for TableCmd {
|
||||
})
|
||||
}
|
||||
|
||||
fn display_config_option(&mut self, _group: String, key: String, value: String) -> bool {
|
||||
match key.as_str() {
|
||||
"table.orientation" => self.settings.orientation = orientation_from_str(&value),
|
||||
"table.line_head_top" => self.settings.line_head_top = bool_from_str(&value),
|
||||
"table.line_head_bottom" => self.settings.line_head_bottom = bool_from_str(&value),
|
||||
"table.line_shift" => self.settings.line_shift = bool_from_str(&value),
|
||||
"table.line_index" => self.settings.line_index = bool_from_str(&value),
|
||||
"table.show_cursor" => {
|
||||
self.settings.show_cursor = bool_from_str(&value);
|
||||
self.settings.turn_on_cursor_mode = true;
|
||||
}
|
||||
"table.split_line" => {
|
||||
self.settings.split_line_s = Some(lookup_ansi_color_style(&value));
|
||||
self.settings.turn_on_cursor_mode = true;
|
||||
}
|
||||
"table.selected_cell" => {
|
||||
self.settings.selected_cell_s = Some(lookup_ansi_color_style(&value));
|
||||
self.settings.turn_on_cursor_mode = true;
|
||||
}
|
||||
"table.selected_row" => {
|
||||
self.settings.selected_row_s = Some(lookup_ansi_color_style(&value));
|
||||
self.settings.turn_on_cursor_mode = true;
|
||||
}
|
||||
"table.selected_column" => {
|
||||
self.settings.selected_column_s = Some(lookup_ansi_color_style(&value));
|
||||
self.settings.turn_on_cursor_mode = true;
|
||||
}
|
||||
"table.padding_column_left" => {
|
||||
self.settings.padding_column_left = usize_from_str(&value);
|
||||
}
|
||||
"table.padding_column_right" => {
|
||||
self.settings.padding_column_right = usize_from_str(&value);
|
||||
}
|
||||
"table.padding_index_left" => {
|
||||
self.settings.padding_index_left = usize_from_str(&value);
|
||||
}
|
||||
"table.padding_index_right" => {
|
||||
self.settings.padding_index_right = usize_from_str(&value);
|
||||
}
|
||||
_ => return false,
|
||||
}
|
||||
|
||||
true
|
||||
}
|
||||
|
||||
fn parse(&mut self, _: &str) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
@@ -257,25 +211,3 @@ impl ViewCommand for TableCmd {
|
||||
Ok(view)
|
||||
}
|
||||
}
|
||||
|
||||
fn bool_from_str(s: &str) -> Option<bool> {
|
||||
match s {
|
||||
"true" => Some(true),
|
||||
"false" => Some(false),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn usize_from_str(s: &str) -> Option<usize> {
|
||||
s.parse::<usize>().ok()
|
||||
}
|
||||
|
||||
fn orientation_from_str(s: &str) -> Option<Orientation> {
|
||||
match s {
|
||||
"left" => Some(Orientation::Left),
|
||||
"right" => Some(Orientation::Right),
|
||||
"top" => Some(Orientation::Top),
|
||||
"bottom" => Some(Orientation::Bottom),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
@@ -67,10 +67,6 @@ impl ViewCommand for TryCmd {
|
||||
})
|
||||
}
|
||||
|
||||
fn display_config_option(&mut self, _: String, _: String, _: String) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
fn parse(&mut self, args: &str) -> Result<()> {
|
||||
self.command = args.trim().to_owned();
|
||||
|
||||
|
@@ -1,92 +0,0 @@
|
||||
use std::io::{self, Result};
|
||||
|
||||
use nu_protocol::{
|
||||
engine::{EngineState, Stack},
|
||||
Value,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
nu_common::NuSpan,
|
||||
pager::{Pager, Transition},
|
||||
};
|
||||
|
||||
use super::{HelpExample, HelpManual, SimpleCommand};
|
||||
|
||||
#[derive(Default, Clone)]
|
||||
pub struct TweakCmd {
|
||||
path: Vec<String>,
|
||||
value: Value,
|
||||
}
|
||||
|
||||
impl TweakCmd {
|
||||
pub const NAME: &'static str = "tweak";
|
||||
}
|
||||
|
||||
impl SimpleCommand for TweakCmd {
|
||||
fn name(&self) -> &'static str {
|
||||
Self::NAME
|
||||
}
|
||||
|
||||
fn usage(&self) -> &'static str {
|
||||
""
|
||||
}
|
||||
|
||||
fn help(&self) -> Option<HelpManual> {
|
||||
Some(HelpManual {
|
||||
name: "tweak",
|
||||
description: "Set `explore` settings.\nLike a non-interactive version of :config",
|
||||
arguments: vec![],
|
||||
examples: vec![
|
||||
HelpExample::new(":tweak table.show_index false", "Don't show index anymore"),
|
||||
HelpExample::new(":tweak table.show_head false", "Don't show header anymore"),
|
||||
HelpExample::new(
|
||||
":tweak try.border_color {bg: '#FFFFFF', fg: '#F213F1'}",
|
||||
"Make a different color for borders in :try",
|
||||
),
|
||||
],
|
||||
config_options: vec![],
|
||||
input: vec![],
|
||||
})
|
||||
}
|
||||
|
||||
fn parse(&mut self, input: &str) -> Result<()> {
|
||||
let input = input.trim();
|
||||
|
||||
let args = input.split_once(' ');
|
||||
let (key, value) = args.ok_or_else(|| {
|
||||
io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
"expected to get 2 arguments 'key value'",
|
||||
)
|
||||
})?;
|
||||
|
||||
self.value = parse_value(value);
|
||||
|
||||
self.path = key
|
||||
.split_terminator('.')
|
||||
.map(|s| s.to_string())
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn react(
|
||||
&mut self,
|
||||
_: &EngineState,
|
||||
_: &mut Stack,
|
||||
p: &mut Pager<'_>,
|
||||
_: Option<Value>,
|
||||
) -> Result<Transition> {
|
||||
p.set_config(&self.path, self.value.clone());
|
||||
|
||||
Ok(Transition::Ok)
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_value(value: &str) -> Value {
|
||||
match value {
|
||||
"true" => Value::bool(true, NuSpan::unknown()),
|
||||
"false" => Value::bool(false, NuSpan::unknown()),
|
||||
s => Value::string(s.to_owned(), NuSpan::unknown()),
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user