Skip to content
Snippets Groups Projects

Resolve "Add zsh, fish, and bash shell completion helper function generation as well as the related command"

2 files
+ 84
35
Compare changes
  • Side-by-side
  • Inline

Files

import { existsSync, writeFileSync } from 'fs';
import inquirer from 'inquirer';
import CommanderCommand from '../../CommanderCommand';
import { existsSync, renameSync, writeFileSync } from 'fs';
import inquirer from 'inquirer';
import CommanderCommand from '../../CommanderCommand';
import { generateBashCompletion, getRoot } from '../../../helpers/AutoCompletionHelper';
import ora from 'ora';
import TextStyle from '../../../types/TextStyle';
import ora from 'ora';
import TextStyle from '../../../types/TextStyle';
import { homedir } from 'os';
import { join } from 'path';
async function askConfirmation(msg: string): Promise<boolean> {
return (await inquirer.prompt({
name: 'confirm',
message: msg,
type: 'confirm',
default: false
})).confirm
}
class CompletionBashCommand extends CommanderCommand {
protected commandName: string = 'bash';
private defaultFilename: string = './dojo_bash_completion.sh';
private installPath = join(homedir(), '.bash_completion')
protected defineCommand() {
this.command
.description('generate bash completion')
.option('-f, --file <filename>', `complete path of the filename where the bash completion will be stored (default to ${ this.defaultFilename }).`, this.defaultFilename)
.option('-y, --force', 'don\'t ask for file overwrite confirmation')
.action(this.commandAction.bind(this));
.description('generate bash completion')
.option('-f, --file <filename>')
.option('-y, --force', 'don\'t ask for file overwrite confirmation')
.action(this.commandAction.bind(this));
}
private writeFile(filename: string) {
const spinner: ora.Ora = ora('Writing Bash completion...').start();
private writeFile(filename: string, showInstructions: boolean) {
const spinner: ora.Ora = ora(`Writing Bash completion in ${TextStyle.CODE(filename)} ...`).start();
try {
writeFileSync(filename, generateBashCompletion(getRoot(this.command)));
spinner.succeed(`Bash completion successfully written.`);
console.log(`
The easiest way to install the completion is to append the content of the generated file to the end of the ${ TextStyle.CODE('~/.bash_completion') } file or to overwrite it, if it only contains the 'dojo' completion.
spinner.succeed(`Bash completion successfully written in ${TextStyle.CODE(filename)}`);
if (showInstructions) {
console.log(`
The easiest way to install the completion is to append the content of the generated file to the end of the ${TextStyle.CODE('~/.bash_completion')} file or to overwrite it, if it only contains the 'dojo' completion.
This can be performed by either
${ TextStyle.CODE(`
cat ${ filename } > ~/.bash_completion # overwrites .bash_completion
cat ${ filename } >> ~/.bash_completion # appends to .bash_completion
`) }
For more details: ${ TextStyle.URL('https://github.com/scop/bash-completion/blob/master/README.md') }
`);
} catch ( error ) {
spinner.fail(`Bash completion error: ${ error }.`);
${TextStyle.CODE(`
cat ${filename} > ~/.bash_completion # overwrites .bash_completion
cat ${filename} >> ~/.bash_completion # appends to .bash_completion
`)}
For more details: ${TextStyle.URL('https://github.com/scop/bash-completion/blob/master/README.md')}
`
);
}
} catch (error) {
spinner.fail(`Bash completion error: ${error}`);
}
}
protected async commandAction(options: { file: string, force: boolean }): Promise<void> {
if ( !options.force && existsSync(options.file) ) {
// File exists in path
const confirm: boolean = (await inquirer.prompt({
name : 'confirm',
message: `${ options.file } is going to be overwritten. Are you sure?`,
type : 'confirm',
default: false
})).confirm;
private renameFile(filename: string, showWarning: boolean) {
const old_filename = `${filename}.old`
const spinner: ora.Ora = ora(`Renaming ${TextStyle.CODE(filename)} in ${TextStyle.CODE(old_filename)} ...`).start();
try {
renameSync(filename, old_filename);
spinner.succeed(`Renaming success: ${TextStyle.CODE(filename)} in ${TextStyle.CODE(old_filename)}`);
if ( confirm ) {
this.writeFile(options.file);
if (showWarning) {
console.log(`${TextStyle.WARNING('Warning:')} Your ${TextStyle.CODE(filename)} was renamed ${TextStyle.CODE(old_filename)}. If this was not intended please revert this change.`);
}
} catch (error) {
spinner.fail(`Renaming failed: ${error}.`);
}
}
/* The completion command must do the following:
- if a file is provided:
- if force is not enabled:
- check if the file exists:
- if it exists, prompt the user that it will be erased
- if ok is given write the file and prompt that a backup has been created
- else create the file containing the completion
- else
- if force is not enabled:
- check if the default file exists:
- if it exists, prompt the user that it will be erased:
- if ok is given write the file and prompt that a backup has been created
- else
- create the file containing the completion
*/
protected async commandAction(options: { file: string, force: boolean }): Promise<void> {
const path = options.file ?? this.installPath
const showInstructions = !!options.file
console.log(path)
const fileExists = existsSync(path)
if (options.force) {
this.renameFile(path, !options.force)
} else {
this.writeFile(options.file);
if (fileExists) {
const confirm = await askConfirmation(`${TextStyle.CODE(path)} in ${TextStyle.CODE(path + '.old')}. Are you sure?`);
if (confirm) {
this.renameFile(path, true)
} else {
console.log(`${TextStyle.BLOCK('Completion generation interrupted.')}`)
return
}
}
}
this.writeFile(path, showInstructions);
}
}
Loading