diff --git a/pkg/yqlib/doc/File Operators.md b/pkg/yqlib/doc/File Operators.md index c7182ee5..07865acb 100644 --- a/pkg/yqlib/doc/File Operators.md +++ b/pkg/yqlib/doc/File Operators.md @@ -1,9 +1,11 @@ File operators are most often used with merge when needing to merge specific files together. Note that when doing this, you will need to use `eval-all` to ensure all yaml documents are loaded into memory before performing the merge (as opposed to `eval` which runs the expression once per document). +Note that the `fileIndex` operator has a short alias of `fi`. + ## Merging files Note the use of eval-all to ensure all documents are loaded into memory. ```bash -yq eval-all 'select(fileIndex == 0) * select(filename == "file2.yaml")' file1.yaml file2.yaml +yq eval-all 'select(fi == 0) * select(filename == "file2.yaml")' file1.yaml file2.yaml ``` ## Get filename Given a sample.yml file of: @@ -33,3 +35,17 @@ will output 0 ``` +## Get file index alias +Given a sample.yml file of: +```yaml +a: cat +``` +then +```bash +yq eval 'fi' sample.yml +``` +will output +```yaml +0 +``` + diff --git a/pkg/yqlib/doc/headers/File Operators.md b/pkg/yqlib/doc/headers/File Operators.md index 394a0bc4..baa80755 100644 --- a/pkg/yqlib/doc/headers/File Operators.md +++ b/pkg/yqlib/doc/headers/File Operators.md @@ -1,7 +1,9 @@ File operators are most often used with merge when needing to merge specific files together. Note that when doing this, you will need to use `eval-all` to ensure all yaml documents are loaded into memory before performing the merge (as opposed to `eval` which runs the expression once per document). +Note that the `fileIndex` operator has a short alias of `fi`. + ## Merging files Note the use of eval-all to ensure all documents are loaded into memory. ```bash -yq eval-all 'select(fileIndex == 0) * select(filename == "file2.yaml")' file1.yaml file2.yaml +yq eval-all 'select(fi == 0) * select(filename == "file2.yaml")' file1.yaml file2.yaml ``` \ No newline at end of file diff --git a/pkg/yqlib/operator_file_test.go b/pkg/yqlib/operator_file_test.go index a4735cef..72b3ff4e 100644 --- a/pkg/yqlib/operator_file_test.go +++ b/pkg/yqlib/operator_file_test.go @@ -21,6 +21,14 @@ var fileOperatorScenarios = []expressionScenario{ "D0, P[], (!!int)::0\n", }, }, + { + description: "Get file index alias", + document: `{a: cat}`, + expression: `fi`, + expected: []string{ + "D0, P[], (!!int)::0\n", + }, + }, } func TestFileOperatorsScenarios(t *testing.T) { diff --git a/pkg/yqlib/operators_test.go b/pkg/yqlib/operators_test.go index 46565916..c8881bb5 100644 --- a/pkg/yqlib/operators_test.go +++ b/pkg/yqlib/operators_test.go @@ -137,105 +137,116 @@ func documentScenarios(t *testing.T, title string, scenarios []expressionScenari for _, s := range scenarios { if !s.skipDoc { - - writeOrPanic(w, fmt.Sprintf("## %v\n", s.description)) - - if s.subdescription != "" { - writeOrPanic(w, s.subdescription) - writeOrPanic(w, "\n\n") - } - formattedDoc := "" - formattedDoc2 := "" - command := "eval" - if s.document != "" { - if s.dontFormatInputForDoc { - formattedDoc = s.document + "\n" - } else { - formattedDoc = formatYaml(s.document, "sample.yml") - } - - writeOrPanic(w, "Given a sample.yml file of:\n") - writeOrPanic(w, fmt.Sprintf("```yaml\n%v```\n", formattedDoc)) - - files := "sample.yml" - - if s.document2 != "" { - if s.dontFormatInputForDoc { - formattedDoc2 = s.document2 + "\n" - } else { - formattedDoc2 = formatYaml(s.document2, "another.yml") - } - - writeOrPanic(w, "And another sample another.yml file of:\n") - writeOrPanic(w, fmt.Sprintf("```yaml\n%v```\n", formattedDoc2)) - files = "sample.yml another.yml" - command = "eval-all" - } - - writeOrPanic(w, "then\n") - if s.expression != "" { - writeOrPanic(w, fmt.Sprintf("```bash\nyq %v '%v' %v\n```\n", command, s.expression, files)) - } else { - writeOrPanic(w, fmt.Sprintf("```bash\nyq %v %v\n```\n", command, files)) - } - } else { - writeOrPanic(w, "Running\n") - writeOrPanic(w, fmt.Sprintf("```bash\nyq %v --null-input '%v'\n```\n", command, s.expression)) - } - - writeOrPanic(w, "will output\n") - - var output bytes.Buffer - var err error - printer := NewPrinter(bufio.NewWriter(&output), false, true, false, 2, true) - - node, err := treeCreator.ParsePath(s.expression) - if err != nil { - t.Error(fmt.Errorf("Error parsing expression %v of %v: %v", s.expression, s.description, err)) - return - } - - inputs := list.New() - - if s.document != "" { - inputs, err = readDocuments(strings.NewReader(formattedDoc), "sample.yml", 0) - if err != nil { - t.Error(err, s.document, s.expression) - return - } - if s.document2 != "" { - moreInputs, err := readDocuments(strings.NewReader(formattedDoc2), "another.yml", 1) - if err != nil { - t.Error(err, s.document, s.expression) - return - } - inputs.PushBackList(moreInputs) - } - } else { - candidateNode := &CandidateNode{ - Document: 0, - Filename: "", - Node: &yaml.Node{Tag: "!!null"}, - FileIndex: 0, - } - inputs.PushBack(candidateNode) - - } - - results, err := treeNavigator.GetMatchingNodes(inputs, node) - if err != nil { - t.Error(err, s.expression) - } - - err = printer.PrintResults(results) - if err != nil { - t.Error(err, s.expression) - } - - writeOrPanic(w, fmt.Sprintf("```yaml\n%v```\n\n", output.String())) - + documentScenario(t, w, s) } - } w.Flush() } + +func documentScenario(t *testing.T, w *bufio.Writer, s expressionScenario) { + writeOrPanic(w, fmt.Sprintf("## %v\n", s.description)) + + if s.subdescription != "" { + writeOrPanic(w, s.subdescription) + writeOrPanic(w, "\n\n") + } + + formattedDoc, formattedDoc2 := documentInput(w, s) + + writeOrPanic(w, "will output\n") + + documentOutput(t, w, s, formattedDoc, formattedDoc2) +} + +func documentInput(w *bufio.Writer, s expressionScenario) (string, string) { + formattedDoc := "" + formattedDoc2 := "" + command := "eval" + if s.document != "" { + if s.dontFormatInputForDoc { + formattedDoc = s.document + "\n" + } else { + formattedDoc = formatYaml(s.document, "sample.yml") + } + + writeOrPanic(w, "Given a sample.yml file of:\n") + writeOrPanic(w, fmt.Sprintf("```yaml\n%v```\n", formattedDoc)) + + files := "sample.yml" + + if s.document2 != "" { + if s.dontFormatInputForDoc { + formattedDoc2 = s.document2 + "\n" + } else { + formattedDoc2 = formatYaml(s.document2, "another.yml") + } + + writeOrPanic(w, "And another sample another.yml file of:\n") + writeOrPanic(w, fmt.Sprintf("```yaml\n%v```\n", formattedDoc2)) + files = "sample.yml another.yml" + command = "eval-all" + } + + writeOrPanic(w, "then\n") + if s.expression != "" { + writeOrPanic(w, fmt.Sprintf("```bash\nyq %v '%v' %v\n```\n", command, s.expression, files)) + } else { + writeOrPanic(w, fmt.Sprintf("```bash\nyq %v %v\n```\n", command, files)) + } + } else { + writeOrPanic(w, "Running\n") + writeOrPanic(w, fmt.Sprintf("```bash\nyq %v --null-input '%v'\n```\n", command, s.expression)) + } + return formattedDoc, formattedDoc2 +} + +func documentOutput(t *testing.T, w *bufio.Writer, s expressionScenario, formattedDoc string, formattedDoc2 string) { + var output bytes.Buffer + var err error + printer := NewPrinter(bufio.NewWriter(&output), false, true, false, 2, true) + + node, err := treeCreator.ParsePath(s.expression) + if err != nil { + t.Error(fmt.Errorf("Error parsing expression %v of %v: %v", s.expression, s.description, err)) + return + } + + inputs := list.New() + + if s.document != "" { + inputs, err = readDocuments(strings.NewReader(formattedDoc), "sample.yml", 0) + if err != nil { + t.Error(err, s.document, s.expression) + return + } + if s.document2 != "" { + moreInputs, err := readDocuments(strings.NewReader(formattedDoc2), "another.yml", 1) + if err != nil { + t.Error(err, s.document, s.expression) + return + } + inputs.PushBackList(moreInputs) + } + } else { + candidateNode := &CandidateNode{ + Document: 0, + Filename: "", + Node: &yaml.Node{Tag: "!!null"}, + FileIndex: 0, + } + inputs.PushBack(candidateNode) + + } + + results, err := treeNavigator.GetMatchingNodes(inputs, node) + if err != nil { + t.Error(err, s.expression) + } + + err = printer.PrintResults(results) + if err != nil { + t.Error(err, s.expression) + } + + writeOrPanic(w, fmt.Sprintf("```yaml\n%v```\n\n", output.String())) +} diff --git a/pkg/yqlib/path_tokeniser.go b/pkg/yqlib/path_tokeniser.go index 9a6b1edc..1cf3d93c 100644 --- a/pkg/yqlib/path_tokeniser.go +++ b/pkg/yqlib/path_tokeniser.go @@ -200,6 +200,7 @@ func initLexer() (*lex.Lexer, error) { lexer.Add([]byte(`alias`), opAssignableToken(GetAlias, AssignAlias)) lexer.Add([]byte(`filename`), opToken(GetFilename)) lexer.Add([]byte(`fileIndex`), opToken(GetFileIndex)) + lexer.Add([]byte(`fi`), opToken(GetFileIndex)) lexer.Add([]byte(`path`), opToken(GetPath)) lexer.Add([]byte(`lineComment`), opTokenWithPrefs(GetComment, AssignComment, &CommentOpPreferences{LineComment: true}))