diff --git a/src/core/config/OperationConfig.js b/src/core/config/OperationConfig.js index 16f6f1b7..777f21f3 100755 --- a/src/core/config/OperationConfig.js +++ b/src/core/config/OperationConfig.js @@ -3196,7 +3196,69 @@ const OperationConfig = { outputType: "html", args: [ ] - } + }, + "Head": { + description: [ + "Like the UNIX head utility.", + "
", + "Gets the first $Number of lines.", + "
", + "Optionally you can select all but the last $Number of lines.", + "
", + "The delimiter can be changed so that instead of lines, fields (i.e. commas) are selected instead.", + ].join("\n"), + run: StrUtils.runHead, + inputType: "string", + outputType: "string", + args: [ + { + name: "Delimiter", + type: "option", + value: StrUtils.DELIMITER_OPTIONS + }, + { + name: "Number", + type: "number", + value: 10, + }, + { + name: "All but last $Number of lines", + type: "boolean", + value: false, + }, + ] + }, + "Tail": { + description: [ + "Like the UNIX tail utility.", + "
", + "Gets the last $Number of lines.", + "
", + "Optionally you can select all lines after line $Number.", + "
", + "The delimiter can be changed so that instead of lines, fields (i.e. commas) are selected instead.", + ].join("\n"), + run: StrUtils.runTail, + inputType: "string", + outputType: "string", + args: [ + { + name: "Delimiter", + type: "option", + value: StrUtils.DELIMITER_OPTIONS + }, + { + name: "Number", + type: "number", + value: 10, + }, + { + name: "Start from line $Number", + type: "boolean", + value: false, + }, + ] + }, }; export default OperationConfig; diff --git a/src/core/operations/StrUtils.js b/src/core/operations/StrUtils.js index 816d4abc..4ba0b18e 100755 --- a/src/core/operations/StrUtils.js +++ b/src/core/operations/StrUtils.js @@ -537,6 +537,61 @@ const StrUtils = { return output; }, + /** + * Head lines operation. + * + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + runHead: function(input, args) { + let delimiter = args[0], + number = args[1], + allBut = args[2]; + + delimiter = Utils.charRep[delimiter]; + let splitInput = input.split(delimiter); + + return splitInput + .filter((line, lineIndex) => { + lineIndex += 1; + + if (allBut) { + return lineIndex <= splitInput.length - number; + } else { + return lineIndex <= number; + } + }) + .join(delimiter); + }, + + /** + * Tail lines operation. + * + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + runTail: function(input, args) { + let delimiter = args[0], + number = args[1], + allBut = args[2]; + + delimiter = Utils.charRep[delimiter]; + let splitInput = input.split(delimiter); + + return splitInput + .filter((line, lineIndex) => { + lineIndex += 1; + + if (allBut) { + return lineIndex >= number; + } else { + return lineIndex > splitInput.length - number; + } + }) + .join(delimiter); + }, }; export default StrUtils; diff --git a/test/tests/operations/StrUtils.js b/test/tests/operations/StrUtils.js index ada89137..d1af9dd8 100644 --- a/test/tests/operations/StrUtils.js +++ b/test/tests/operations/StrUtils.js @@ -34,4 +34,224 @@ TestRegister.addTests([ } ], }, + { + name: "Head 0", + input: [1, 2, 3, 4, 5, 6].join("\n"), + expectedOutput: [].join("\n"), + recipeConfig: [ + { + "op": "Head", + "args": ["Line feed", 0, false] + } + ], + }, + { + name: "Head 1", + input: [1, 2, 3, 4, 5, 6].join("\n"), + expectedOutput: [1].join("\n"), + recipeConfig: [ + { + "op": "Head", + "args": ["Line feed", 1, false] + } + ], + }, + { + name: "Head 2", + input: [1, 2, 3, 4, 5, 6].join("\n"), + expectedOutput: [1, 2].join("\n"), + recipeConfig: [ + { + "op": "Head", + "args": ["Line feed", 2, false] + } + ], + }, + { + name: "Head 6", + input: [1, 2, 3, 4, 5, 6].join("\n"), + expectedOutput: [1, 2, 3, 4, 5, 6].join("\n"), + recipeConfig: [ + { + "op": "Head", + "args": ["Line feed", 6, false] + } + ], + }, + { + name: "Head big", + input: [1, 2, 3, 4, 5, 6].join("\n"), + expectedOutput: [1, 2, 3, 4, 5, 6].join("\n"), + recipeConfig: [ + { + "op": "Head", + "args": ["Line feed", 100, false] + } + ], + }, + { + name: "Head all but 0", + input: [1, 2, 3, 4, 5, 6].join("\n"), + expectedOutput: [1, 2, 3, 4, 5, 6].join("\n"), + recipeConfig: [ + { + "op": "Head", + "args": ["Line feed", 0, true] + } + ], + }, + { + name: "Head all but 1", + input: [1, 2, 3, 4, 5, 6].join("\n"), + expectedOutput: [1, 2, 3, 4, 5].join("\n"), + recipeConfig: [ + { + "op": "Head", + "args": ["Line feed", 1, true] + } + ], + }, + { + name: "Head all but 2", + input: [1, 2, 3, 4, 5, 6].join("\n"), + expectedOutput: [1, 2, 3, 4].join("\n"), + recipeConfig: [ + { + "op": "Head", + "args": ["Line feed", 2, true] + } + ], + }, + { + name: "Head all but 6", + input: [1, 2, 3, 4, 5, 6].join("\n"), + expectedOutput: [].join("\n"), + recipeConfig: [ + { + "op": "Head", + "args": ["Line feed", 6, true] + } + ], + }, + { + name: "Head all but big", + input: [1, 2, 3, 4, 5, 6].join("\n"), + expectedOutput: [].join("\n"), + recipeConfig: [ + { + "op": "Head", + "args": ["Line feed", 100, true] + } + ], + }, + { + name: "Tail 0", + input: [1, 2, 3, 4, 5, 6].join("\n"), + expectedOutput: [].join("\n"), + recipeConfig: [ + { + "op": "Tail", + "args": ["Line feed", 0, false] + } + ], + }, + { + name: "Tail 1", + input: [1, 2, 3, 4, 5, 6].join("\n"), + expectedOutput: [6].join("\n"), + recipeConfig: [ + { + "op": "Tail", + "args": ["Line feed", 1, false] + } + ], + }, + { + name: "Tail 2", + input: [1, 2, 3, 4, 5, 6].join("\n"), + expectedOutput: [5, 6].join("\n"), + recipeConfig: [ + { + "op": "Tail", + "args": ["Line feed", 2, false] + } + ], + }, + { + name: "Tail 6", + input: [1, 2, 3, 4, 5, 6].join("\n"), + expectedOutput: [1, 2, 3, 4, 5, 6].join("\n"), + recipeConfig: [ + { + "op": "Tail", + "args": ["Line feed", 6, false] + } + ], + }, + { + name: "Tail big", + input: [1, 2, 3, 4, 5, 6].join("\n"), + expectedOutput: [1, 2, 3, 4, 5, 6].join("\n"), + recipeConfig: [ + { + "op": "Tail", + "args": ["Line feed", 100, false] + } + ], + }, + { + name: "Tail all but 0", + input: [1, 2, 3, 4, 5, 6].join("\n"), + expectedOutput: [1, 2, 3, 4, 5, 6].join("\n"), + recipeConfig: [ + { + "op": "Tail", + "args": ["Line feed", 0, true] + } + ], + }, + { + name: "Tail all but 1", + input: [1, 2, 3, 4, 5, 6].join("\n"), + expectedOutput: [1, 2, 3, 4, 5, 6].join("\n"), + recipeConfig: [ + { + "op": "Tail", + "args": ["Line feed", 1, true] + } + ], + }, + { + name: "Tail all but 2", + input: [1, 2, 3, 4, 5, 6].join("\n"), + expectedOutput: [2, 3, 4, 5, 6].join("\n"), + recipeConfig: [ + { + "op": "Tail", + "args": ["Line feed", 2, true] + } + ], + }, + { + name: "Tail all but 6", + input: [1, 2, 3, 4, 5, 6].join("\n"), + expectedOutput: [6].join("\n"), + recipeConfig: [ + { + "op": "Tail", + "args": ["Line feed", 6, true] + } + ], + }, + { + name: "Tail all but big", + input: [1, 2, 3, 4, 5, 6].join("\n"), + expectedOutput: [].join("\n"), + recipeConfig: [ + { + "op": "Tail", + "args": ["Line feed", 100, true] + } + ], + }, ]);