@nu-art/commando
Version:
Shell command execution framework with interactive sessions, CLI parameter resolution, and plugin system for building and executing shell scripts programmatically
125 lines (124 loc) • 4.27 kB
JavaScript
/*
* commando provides shell command execution framework with interactive sessions and plugin system
*
* Copyright (C) 2020 Adam van der Kruk aka TacB0sS
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* Default options for CommandBuilder class instances.
*/
const defaultOptions = {
newlineDelimiter: '\n',
indentation: 2,
};
/**
* Builds shell commands with indentation and formatting support.
*
* Accumulates commands in an array and formats them with proper indentation.
* Supports custom newline delimiters and indentation levels. Commands can
* be split across multiple lines using the newline delimiter.
*
* **Behavior**:
* - Commands are trimmed before adding
* - Empty commands are preserved (for spacing)
* - Indentation is applied per line when commands contain newlines
* - `reset()` returns the accumulated command and clears the builder
*/
export class CommandBuilder {
initialCommands = [];
/** Array of accumulated command strings */
commands;
/** Current indentation level (number of indent steps) */
indentation = 0;
/** Configuration options for formatting */
option = defaultOptions;
/**
* Constructs a CommandBuilder instance with given options.
* @param {Partial<Options>} [options=defaultOptions] - Configuration options for the CommandBuilder instance.
*/
constructor(options = defaultOptions) {
this.option = options;
this.commands = [...this.initialCommands];
}
/**
* Generates a string of spaces for indentation based on the current indentation level.
* @returns {string} - A string containing spaces for the current indentation level.
*/
getIndentation = () => {
return ' '.repeat(this.option.indentation * this.indentation);
};
setMark() {
this.initialCommands = [...this.commands];
}
/**
* Increases the current indentation level by one.
*/
indentIn = () => {
this.indentation++;
};
/**
* Decreases the current indentation level by one.
*/
indentOut = () => {
this.indentation--;
};
/**
* Appends an empty line to the command list for readability.
* @returns {this} - The CommandBuilder instance for method chaining.
*/
emptyLine() {
this.append('');
return this;
}
/**
* Appends a command to the command list with proper indentation.
*
* **Behavior**:
* - Splits the command by the newline delimiter (allows multi-line commands)
* - Trims each line
* - Applies current indentation to non-empty lines
* - Preserves empty lines as-is (for spacing)
*
* @param command - Command string to append (can contain newlines)
* @returns This instance for method chaining
*/
append = (command) => {
const commands = command.split(this.option.newlineDelimiter);
for (const _command of commands) {
const command = _command.trim();
if (command.length === 0)
this.commands.push(command);
else
this.commands.push(`${this.getIndentation()}${command}`);
}
return this;
};
/**
* Retrieves the full command list as a single string.
* @returns {string} - The full command list.
*/
getCommand() {
return this.commands.join(this.option.newlineDelimiter);
}
/**
* Resets the command list and returns the previously accumulated commands.
* @returns {string} - The previously accumulated commands.
*/
reset() {
const command = this.getCommand();
this.commands.length = 0;
this.commands.push(...this.initialCommands);
return command;
}
}