From 839010b89d4279302579964c2054a69937466bff Mon Sep 17 00:00:00 2001 From: JT <547158+jntrnr@users.noreply.github.com> Date: Tue, 8 Aug 2023 22:47:23 +1200 Subject: [PATCH] Auto-expand table based on terminal width (#9934) # Description This PR adds back the functionality to auto-expand tables based on the terminal width, using the logic that if the terminal is over 100 columns to expand. This sets the default config value in both the Rust and the default nushell config. To do so, it also adds back the ability for hooks to be strings of code and not just code blocks. Fixed a couple tests: two which assumed that the builtin display hook didn't use a table -e, and one that assumed a hook couldn't be a string. # User-Facing Changes # Tests + Formatting # After Submitting --- crates/nu-command/src/hook.rs | 61 ++++++++++++++++++- crates/nu-protocol/src/config.rs | 5 +- .../src/sample_config/default_config.nu | 3 +- src/tests/test_custom_commands.rs | 4 +- tests/hooks/mod.rs | 10 --- 5 files changed, 67 insertions(+), 16 deletions(-) diff --git a/crates/nu-command/src/hook.rs b/crates/nu-command/src/hook.rs index 3dc299001..f07bc6263 100644 --- a/crates/nu-command/src/hook.rs +++ b/crates/nu-command/src/hook.rs @@ -87,6 +87,65 @@ pub fn eval_hook( }; match value { + Value::String { val, span } => { + let (block, delta, vars) = { + let mut working_set = StateWorkingSet::new(engine_state); + + let mut vars: Vec<(VarId, Value)> = vec![]; + + for (name, val) in arguments { + let var_id = working_set.add_variable( + name.as_bytes().to_vec(), + val.span()?, + Type::Any, + false, + ); + + vars.push((var_id, val)); + } + + let output = parse(&mut working_set, Some("hook"), val.as_bytes(), false); + if let Some(err) = working_set.parse_errors.first() { + report_error(&working_set, err); + + return Err(ShellError::UnsupportedConfigValue( + "valid source code".into(), + "source code with syntax errors".into(), + *span, + )); + } + + (output, working_set.render(), vars) + }; + + engine_state.merge_delta(delta)?; + let input = if let Some(input) = input { + input + } else { + PipelineData::empty() + }; + + let var_ids: Vec = vars + .into_iter() + .map(|(var_id, val)| { + stack.add_var(var_id, val); + var_id + }) + .collect(); + + match eval_block(engine_state, stack, &block, input, false, false) { + Ok(pipeline_data) => { + output = pipeline_data; + } + Err(err) => { + report_error_new(engine_state, &err); + } + } + + for var_id in var_ids.iter() { + stack.remove_var(*var_id); + } + } Value::List { vals, .. } => { for val in vals { eval_hook(engine_state, stack, None, arguments.clone(), val)?; @@ -274,7 +333,7 @@ pub fn eval_hook( } other => { return Err(ShellError::UnsupportedConfigValue( - "block, record, or list of records".into(), + "string, block, record, or list of commands".into(), format!("{}", other.get_type()), other.span()?, )); diff --git a/crates/nu-protocol/src/config.rs b/crates/nu-protocol/src/config.rs index 03c03c0be..fea9e8da6 100644 --- a/crates/nu-protocol/src/config.rs +++ b/crates/nu-protocol/src/config.rs @@ -42,7 +42,10 @@ impl Hooks { pre_prompt: None, pre_execution: None, env_change: None, - display_output: None, + display_output: Some(Value::string( + "if (term size).columns >= 100 { table -e } else { table }", + Span::unknown(), + )), command_not_found: None, } } diff --git a/crates/nu-utils/src/sample_config/default_config.nu b/crates/nu-utils/src/sample_config/default_config.nu index 29e856521..8f57f572c 100644 --- a/crates/nu-utils/src/sample_config/default_config.nu +++ b/crates/nu-utils/src/sample_config/default_config.nu @@ -137,7 +137,6 @@ let light_theme = { # carapace $spans.0 nushell $spans | from json # } - # The default config record. This is where much of your global configuration is setup. $env.config = { show_banner: true # true or false to enable or disable the welcome banner at startup @@ -251,7 +250,7 @@ $env.config = { env_change: { PWD: [{|before, after| null }] # run if the PWD environment is different since the last repl input } - display_output: { table } # run before the output of a command is drawn, example: `{ if (term size).columns >= 100 { table -e } else { table } }` + display_output: "if (term size).columns >= 100 { table -e } else { table }" # run to display the output of a pipeline command_not_found: { null } # return an error message when a command is not found } diff --git a/src/tests/test_custom_commands.rs b/src/tests/test_custom_commands.rs index da121a5d7..5c26c8f38 100644 --- a/src/tests/test_custom_commands.rs +++ b/src/tests/test_custom_commands.rs @@ -138,12 +138,12 @@ fn help_not_present_in_extern() -> TestResult { #[test] fn override_table() -> TestResult { - run_test(r#"def table [] { "hi" }; table"#, "hi") + run_test(r#"def table [-e] { "hi" }; table"#, "hi") } #[test] fn override_table_eval_file() { - let actual = nu!(r#"def table [] { "hi" }; table"#); + let actual = nu!(r#"def table [-e] { "hi" }; table"#); assert_eq!(actual.out, "hi"); } diff --git a/tests/hooks/mod.rs b/tests/hooks/mod.rs index bd921ef5a..57ef9f059 100644 --- a/tests/hooks/mod.rs +++ b/tests/hooks/mod.rs @@ -551,13 +551,3 @@ fn err_hook_parse_error() { assert!(actual_repl.err.contains("unsupported_config_value")); assert_eq!(actual_repl.out, ""); } - -#[test] -fn err_hook_dont_allow_string() { - let inp = &[&pre_prompt_hook(r#"'def foo [] { "got foo!" }'"#), "foo"]; - - let actual_repl = nu!(nu_repl_code(inp)); - - assert!(actual_repl.out.is_empty()); - assert!(actual_repl.err.contains("unsupported_config_value")); -}