diff --git a/src/data/base.rs b/src/data/base.rs index 470a97f61..17691e24b 100644 --- a/src/data/base.rs +++ b/src/data/base.rs @@ -533,10 +533,21 @@ impl Value { ) -> Result>, ShellError> { let mut current = self; for p in path { + // note: + // This will eventually be refactored once we are able + // to parse correctly column_paths and get them deserialized + // to values for us. let value = match p.item().parse::() { - Ok(number) => current.get_data_by_index(number), - Err(_) => current.get_data_by_key(p), - }; + Ok(number) => match current { + Value::Table(_) => current.get_data_by_index(number), + Value::Row(_) => current.get_data_by_key(p), + _ => None, + }, + Err(_) => match self { + Value::Table(_) | Value::Row(_) => current.get_data_by_key(p), + _ => None, + }, + }; // end match value { Some(v) => current = v, @@ -1022,7 +1033,7 @@ mod tests { } #[test] - fn column_path_that_contains_just_a_numbers_gets_a_row_from_a_table() { + fn column_path_that_contains_just_a_number_gets_a_row_from_a_table() { let field_path = column_path(&vec![string("package"), string("authors"), string("0")]); let (_, tag) = string("Andrés N. Robalino").into_parts(); @@ -1050,6 +1061,35 @@ mod tests { ); } + #[test] + fn column_path_that_contains_just_a_number_gets_a_row_from_a_row() { + let field_path = column_path(&vec![string("package"), string("authors"), string("0")]); + + let (_, tag) = string("Andrés N. Robalino").into_parts(); + + let value = Value::row(indexmap! { + "package".into() => row(indexmap! { + "name".into() => string("nu"), + "version".into() => string("0.4.0"), + "authors".into() => row(indexmap! { + "0".into() => row(indexmap!{"name".into() => string("Andrés N. Robalino")}), + "1".into() => row(indexmap!{"name".into() => string("Jonathan Turner")}), + "2".into() => row(indexmap!{"name".into() => string("Yehuda Katz")}), + }) + }) + }); + + assert_eq!( + **value + .get_data_by_column_path(tag, &field_path, Box::new(error_callback())) + .unwrap() + .unwrap(), + Value::row(indexmap! { + "name".into() => string("Andrés N. Robalino") + }) + ); + } + #[test] fn replaces_matching_field_from_a_row() { let field_path = column_path(&vec![string("amigos")]); diff --git a/tests/command_get_tests.rs b/tests/command_get_tests.rs index a6a4dea8e..09348678b 100644 --- a/tests/command_get_tests.rs +++ b/tests/command_get_tests.rs @@ -52,10 +52,61 @@ fn fetches_by_index_from_a_given_table() { assert_eq!(actual, "Andrés N. Robalino "); }) } +#[test] +fn supports_fetching_rows_from_tables_using_columns_named_as_numbers() { + Playground::setup("get_test_3", |dirs, sandbox| { + sandbox.with_files(vec![FileWithContent( + "sample.toml", + r#" + [package] + 0 = "nu" + 1 = "0.4.1" + "#, + )]); + + let actual = nu!( + cwd: dirs.test(), h::pipeline( + r#" + open sample.toml + | get package.1 + | echo $it + "# + )); + + assert_eq!(actual, "0.4.1"); + }) +} + +#[test] +fn can_fetch_tables_or_rows_using_numbers_in_column_path() { + Playground::setup("get_test_4", |dirs, sandbox| { + sandbox.with_files(vec![FileWithContent( + "sample.toml", + r#" + [package] + 0 = "nu" + 1 = "0.4.1" + 2 = ["Yehuda Katz ", "Jonathan Turner ", "Andrés N. Robalino "] + description = "When arepas shells are tasty and fun." + "#, + )]); + + let actual = nu!( + cwd: dirs.test(), h::pipeline( + r#" + open sample.toml + | get package.2.1 + | echo $it + "# + )); + + assert_eq!(actual, "Jonathan Turner "); + }) +} #[test] fn fetches_more_than_one_column_member_path() { - Playground::setup("get_test_3", |dirs, sandbox| { + Playground::setup("get_test_5", |dirs, sandbox| { sandbox.with_files(vec![FileWithContent( "sample.toml", r#" @@ -87,9 +138,32 @@ fn fetches_more_than_one_column_member_path() { }) } +#[test] +fn errors_fetching_by_column_not_present() { + Playground::setup("get_test_6", |dirs, sandbox| { + sandbox.with_files(vec![FileWithContent( + "sample.toml", + r#" + [taconushell] + sentence_words = ["Yo", "quiero", "taconushell"] + "#, + )]); + + let actual = nu_error!( + cwd: dirs.test(), h::pipeline( + r#" + open sample.toml + | get taco + "# + )); + + assert!(actual.contains("Unknown column")); + assert!(actual.contains("did you mean 'taconushell'?")); + }) +} #[test] fn errors_fetching_by_index_out_of_bounds_from_table() { - Playground::setup("get_test_4", |dirs, sandbox| { + Playground::setup("get_test_7", |dirs, sandbox| { sandbox.with_files(vec![FileWithContent( "sample.toml", r#" @@ -114,7 +188,7 @@ fn errors_fetching_by_index_out_of_bounds_from_table() { #[test] fn requires_at_least_one_column_member_path() { - Playground::setup("get_test_5", |dirs, sandbox| { + Playground::setup("get_test_8", |dirs, sandbox| { sandbox.with_files(vec![EmptyFile("andres.txt")]); let actual = nu_error!(