diff --git a/src/app/app.component.html b/src/app/app.component.html index 5985fbb2..ac306e45 100644 --- a/src/app/app.component.html +++ b/src/app/app.component.html @@ -559,6 +559,24 @@ + + + + + + + + + + + + diff --git a/src/app/app.component.ts b/src/app/app.component.ts index db48a43a..21049543 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -146,6 +146,7 @@ export class AppComponent implements OnInit { theme: new FormControl<'light' | 'dark' | 'system' | null>(null, [ Validators.required, ]), + bashbrawl_enabled: new FormControl(false), }); ngOnInit() { @@ -280,6 +281,7 @@ export class AppComponent implements OnInit { ctr_enabled = true, theme = 'light', divider_position = 40, + bashbrawl_enabled = false, }) => { this.settingsForm.setValue({ terminal_theme, @@ -287,6 +289,7 @@ export class AppComponent implements OnInit { ctr_enabled, theme, divider_position, + bashbrawl_enabled, }); this.fetchingSettings = false; }, diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 4ac9b527..0a845676 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -8,6 +8,7 @@ import { RootComponent } from './root.component'; import { HomeComponent } from './home.component'; import { ScenarioComponent } from './scenario/scenario.component'; import { TerminalComponent } from './scenario/terminal.component'; +import { BashbrawlterminalComponent } from './scenario/bashbrawl/bashbrawlterminal.component'; import { JwtModule, JWT_OPTIONS } from '@auth0/angular-jwt'; import { HttpClientModule } from '@angular/common/http'; import { LoginComponent } from './login/login.component'; @@ -44,6 +45,8 @@ import { GuacTerminalComponent } from './scenario/guacTerminal.component'; import { IdeWindowComponent } from './scenario/ideWindow.component'; import { ContextService } from './services/context.service'; import { TypedSettingsService } from './services/typedSettings.service'; +import { LanguageCommandService } from './scenario/bashbrawl/languages/language-command.service'; +import { ScoreService } from './services/score.service'; import { VerificationService } from './services/verification.service'; import { TaskProgressComponent } from './scenario/task-progress/task-progress.component'; import { TaskModalComponent } from './scenario/task-modal/task-modal.component'; @@ -80,6 +83,7 @@ import { eyeHideIcon, clockIcon, copyIcon, + terminalIcon, } from '@cds/core/icon'; import { QuizLabelComponent } from './quiz/quiz-label.component'; @@ -112,6 +116,7 @@ ClarityIcons.addIcons( eyeHideIcon, clockIcon, copyIcon, + terminalIcon, ); export function tokenGetter() { @@ -153,6 +158,7 @@ export function jwtOptionsFactory() { HomeComponent, ScenarioComponent, TerminalComponent, + BashbrawlterminalComponent, GuacTerminalComponent, LoginComponent, ScenarioCardComponent, @@ -222,6 +228,8 @@ export function jwtOptionsFactory() { ContextService, TypedSettingsService, VerificationService, + LanguageCommandService, + ScoreService, { provide: APP_INITIALIZER, useFactory: appInitializerFn, diff --git a/src/app/scenario/bashbrawl/README.md b/src/app/scenario/bashbrawl/README.md new file mode 100644 index 00000000..52e2820e --- /dev/null +++ b/src/app/scenario/bashbrawl/README.md @@ -0,0 +1,11 @@ +# Bashbrawl + +## BashBrawl Standalone + +github.com/jggoebel/bashbrawl + +## original idea + +Thanks to [clh-bash](https://github.com/CommandLineHeroes/clh-bash/) for giving me the idea. Some language files were taken from there, the other code was newly written. + +Language files are (as the LICENSE file indicates) under diff --git a/src/app/scenario/bashbrawl/bashbrawlterminal.component.html b/src/app/scenario/bashbrawl/bashbrawlterminal.component.html new file mode 100644 index 00000000..4ef73766 --- /dev/null +++ b/src/app/scenario/bashbrawl/bashbrawlterminal.component.html @@ -0,0 +1 @@ +
diff --git a/src/app/scenario/bashbrawl/bashbrawlterminal.component.scss b/src/app/scenario/bashbrawl/bashbrawlterminal.component.scss new file mode 100644 index 00000000..787e6b4f --- /dev/null +++ b/src/app/scenario/bashbrawl/bashbrawlterminal.component.scss @@ -0,0 +1,12 @@ +.terminal-div { + height: calc(100% - 1.8rem); + width: 100%; +} + +.xterm { + padding-bottom: 84px; +} + +.xterm-viewport { + overflow: hidden !important; +} diff --git a/src/app/scenario/bashbrawl/bashbrawlterminal.component.ts b/src/app/scenario/bashbrawl/bashbrawlterminal.component.ts new file mode 100644 index 00000000..78a0bd5c --- /dev/null +++ b/src/app/scenario/bashbrawl/bashbrawlterminal.component.ts @@ -0,0 +1,958 @@ +import { + Component, + ViewChild, + ElementRef, + ViewEncapsulation, + AfterViewInit, + OnInit, + EventEmitter, + Output, + Input, +} from '@angular/core'; +import { Terminal } from 'xterm'; +import { FitAddon } from 'xterm-addon-fit'; +import { HostListener } from '@angular/core'; +import { themes } from '../terminal-themes/themes'; +import { SettingsService } from '../../services/settings.service'; +import { CanvasAddon } from 'xterm-addon-canvas'; +import { Keycodes } from './keycodes'; +import { sleep } from '@cds/core/internal'; +import { LanguageCommandService } from './languages/language-command.service'; +import { ScoreService } from '../../services/score.service'; +import { firstValueFrom } from 'rxjs'; + +export class Score { + name: string; + score: number; + code: string; +} + +export class Leaderboard { + language: string; + scores: Score[]; +} + +export class LeaderboardWithLocalPlacement { + language: string; + scores: Score[]; + placement: number; + localscores: Score[]; +} + +// eslint-disable-next-line no-control-regex +const stripAnsi = (str: string) => str.replace(/\x1b\[[0-9;]*m/g, ''); + +@Component({ + selector: 'app-bashbrawl-terminal', + templateUrl: './bashbrawlterminal.component.html', + styleUrls: ['bashbrawlterminal.component.scss'], + encapsulation: ViewEncapsulation.None, +}) +export class BashbrawlterminalComponent implements OnInit, AfterViewInit { + @Input() + code = ''; + + @Output() + gameEnded = new EventEmitter(); + + @Output() + gameStarted = new EventEmitter(); + + private term: Terminal; + private fitAddon: FitAddon = new FitAddon(); + private firstTabChange = true; + private isVisible = false; + public mutationObserver: MutationObserver; + + private command = ''; + private commandFn: (command: string, params: string) => void = + this.menuCommandsFn; + private inputFn: (command: string) => void = this.handleCommandWithNewline; + private cursorPosition = 0; + private DEFAULT_FONT_SIZE = 16; + private DEFAULT_TERMINAL_THEME = 'default'; + private DEFAULT_TERMINAL_SYMBOL = '#'; + + private terminalSymbol = '#'; + private input_blocked = true; + private interrupted = false; + private TERMINAL_CHAR_DELAY = 40; + private TERMINAL_WHITESPACE_DELAY = 2; + + // Game related + private DEFAULT_GAME_TIME = 60; + private gameLanguage: string; + private gameRunning = false; + private commandsEntered: string[] = []; + private commandsEnteredAtTimepoint: number[] = []; + private streak = 0; + private highestStreak = 0; + private gameTime = 0; + private score = 0; + + // Leaderboards maps a list of score entries to the language they competed in. + private leaderboard: Leaderboard; + + @ViewChild('terminal', { static: true }) terminalDiv: ElementRef; + + constructor( + private settingsService: SettingsService, + private languageCommandService: LanguageCommandService, + private scoreService: ScoreService, + ) {} + + @HostListener('window:resize') + public resize() { + const newDimensions = this.fitAddon.proposeDimensions(); + if (this.isVisible && newDimensions) { + this.fitAddon.fit(); + } + } + + private buildTerminal() { + // Check if current browser is firefox by useragent and use "duck-typing" as a fallback. + const regExp = /firefox|fxios/i; + const isFirefox: boolean = + regExp.test(navigator.userAgent.toLowerCase()) || + 'InstallTrigger' in window; + this.term = new Terminal({ + fontFamily: 'monospace', + fontSize: this.DEFAULT_FONT_SIZE, + letterSpacing: 1.1, + cursorBlink: true, + }); + if (!isFirefox) { + // The default renderer is the dom renderer + // Use the more performant canvas renderer if the current browser is not Firefox + this.term.loadAddon(new CanvasAddon()); + } + this.settingsService.settings$.subscribe( + ({ terminal_theme = this.DEFAULT_TERMINAL_THEME }) => { + this.setTerminalTheme(terminal_theme); + }, + ); + this.settingsService.settings$.subscribe( + ({ terminal_fontSize = this.DEFAULT_FONT_SIZE }) => { + this.setFontSize(terminal_fontSize); + }, + ); + this.term.loadAddon(this.fitAddon); + this.term.open(this.terminalDiv.nativeElement); + + this.term.focus(); + this.resize(); + + this.resetToDefaultShell(); + this.term.write(` ${this.terminalSymbol} `); + + this.term.onData((e) => { + if (e === Keycodes.CTR_C) { + //this.resetToDefaultShell(); + //this.interrupted = true; + //if (this.gameRunning) { + // this.gameEnded.emit(); + //} + + return; + } + + if (this.input_blocked) { + return; + } + + if (e === Keycodes.ENTER) { + this.cursorPosition = 0; + this.inputFn(this.command.trim()); + this.command = ''; // Reset command buffer + } else if (e === Keycodes.BACKSPACE) { + if (this.command.length > 0) { + const beforeChar = this.command.slice(0, this.cursorPosition - 1); + const afterChar = this.command.slice(this.cursorPosition); + this.term.write( + '\b' + afterChar + ' \b' + '\b'.repeat(afterChar.length), + ); // Move cursor back, erase character, move cursor back again + this.command = beforeChar + afterChar; + // Remove last character from command buffer + this.cursorPosition -= 1; + } + } else if (e === Keycodes.DELETE) { + if (this.command.length > 0) { + if (this.cursorPosition >= this.command.length) { + //We are one position behind the command, we can not delete something + return; + } + const beforeChar = this.command.slice(0, this.cursorPosition); + const afterChar = this.command.slice(this.cursorPosition + 1); + this.term.write(afterChar + ' \b' + '\b'.repeat(afterChar.length)); // Move cursor back, erase character, move cursor back again + this.command = beforeChar + afterChar; + } + } else if (e === Keycodes.LEFT_ARROW) { + if (this.cursorPosition > 0) { + this.cursorPosition -= 1; + this.term.write(Keycodes.LEFT_ARROW); + } + } else if (e === Keycodes.RIGHT_ARROW) { + if (this.cursorPosition < this.command.length) { + this.cursorPosition += 1; + this.term.write(Keycodes.RIGHT_ARROW); + } + } else if (e === Keycodes.UP_ARROW) { + // TODO implement some weird logic here + console.log('UP'); + } else if (e === Keycodes.DOWN_ARROW) { + // TODO implement some weird logic here + console.log('DOWN'); + } else { + const beforeChar = this.command.slice(0, this.cursorPosition); + const afterChar = this.command.slice(this.cursorPosition); + this.term.write(e + afterChar + '\b'.repeat(afterChar.length)); + this.cursorPosition += 1; + //this.term.write(e); // Echo the typed character + this.command = beforeChar + e + afterChar; // Add typed character to command buffer + } + }); + } + + async helpGame() { + await this.term.writeln( + 'Start the game with one of the following option modes:', + ); + + await this.term.writeln('\nUsage:'); + await this.writeMatrix([ + ['brawl play', 'Play with all languages'], + ['brawl play [language]', 'Play selected language'], + ['brawl lang', 'View all available languages'], + ['brawl top', 'View the leaderboard'], + ]); + } + async startGame(option: string) { + if (option && option != '') { + await this.selectGameOption(option, ''); + return; + } else { + await this.helpGame(); + } + } + + async confirmBeginGame(language: string) { + this.gameStarted.emit(); + if (language == 'all') { + await this.writeDelayed( + 'You have ' + + this.DEFAULT_GAME_TIME + + ' seconds to input commands from:', + true, + ); + await this.displayAvailableLanguages(false); + } else { + await this.writeDelayed( + 'You have ' + + this.DEFAULT_GAME_TIME + + ' seconds to input commands from ' + + this.languageCommandService.getLanguageNameById(language), + true, + ); + } + + this.gameLanguage = language; + + this.input_blocked = false; + this.terminalSymbol = `Press Enter to start!`; + this.commandFn = this.confirmBeginGameFn; + } + + async confirmBeginGameFn() { + this.input_blocked = true; + this.beginGame(); + } + + async beginGame() { + // set language array here; + this.score = 0; + this.streak = 0; + this.highestStreak = 0; + this.commandsEntered = []; + this.commandsEnteredAtTimepoint = []; + this.gameTime = this.DEFAULT_GAME_TIME; + + this.clearTerminal(); + await this.writeScore(); + + this.terminalSymbol = '>'; + await this.moveToInputLine(); + + await this.writeDelayed('Prepare yourself ... ', false); + await sleep(1000); + this.term.write('3 '); + await sleep(1000); + this.term.write('2 '); + await sleep(1000); + this.term.write('1'); + await sleep(1000); + + if (this.interrupted) { + this.term.write('\r\n'); + this.gameEnded.emit(); + return; + } + + this.gameRunning = true; + this.commandFn = this.gameCommand; + this.input_blocked = false; + + if (this.interrupted) { + this.gameEnded.emit(); + return; + } + + await this.moveToInputLine(); + + this.term.write(` ${this.terminalSymbol} `); + + while (this.gameTime > 0) { + if (this.interrupted) { + return; + } + await sleep(1000); + this.gameTime -= 1; + await this.writeScore(); + } + + this.gameRunning = false; + this.input_blocked = true; + this.command = ''; + this.cursorPosition = 0; + //this.inputFn = this.handleCommandWithNewline; + this.commandFn = this.noop; + await this.saveScore(); + } + + async writeScore() { + if (this.interrupted) { + return; + } + // Save the current cursor position before making any changes + this.term.write('\x1b[s'); + + // Move to the first line of the viewport + this.term.write('\x1b[1;1H'); // CSI H moves the cursor to the specified position (1;1 is top left) + + // Clear the first line + this.term.write('\x1b[2K'); // CSI K clears part of the line. '2' clears the entire line. + + const strScore = '' + this.score; + let scoreFormatted = strScore; + if (strScore.length < 8) { + scoreFormatted = ' '.repeat(8 - strScore.length) + strScore; + } + + // Write the new scoreboard text + this.term.write(' SCORE: ' + scoreFormatted); + this.term.write(' TIME LEFT: ' + this.gameTime); + this.term.write( + ' LANGUAGE: ' + + this.languageCommandService.getLanguageNameById(this.gameLanguage), + ); + + // write empty line below score line and clear the row + this.term.write('\x1b[2;1H\x1b[2K'); + + // Restore the previously saved cursor position + this.term.write('\x1b[u'); + } + + async saveScore() { + this.term.write('\r\n'); + await this.writeDelayed('Time is up!'); + await this.writeDelayed('You scored ' + this.score + '!'); + await this.writeDelayed( + 'Your highest Streak was ' + this.highestStreak + '.', + ); + + await this.writeDelayed('Enter your name:', true); + this.terminalSymbol = 'Name:'; + this.term.write(` ${this.terminalSymbol} `); + + this.commandFn = this.enterNameForLeaderboard; + this.input_blocked = false; + } + + async enterNameForLeaderboard(name: string, args: string) { + name = stripAnsi(name); + args = stripAnsi(args); + + if (!name || name == '') { + await this.writeDelayed('Please enter your Name:'); + return; + } + + let fullName = name; + if (args) { + fullName += ' ' + args; + } + + if (fullName.length > 20) { + await this.writeDelayed('Maximum length is 20 chars: Enter again:'); + return; + } + + const score: Score = { name: fullName, score: this.score, code: this.code }; + + const leaderboardWithLocalPlacement: LeaderboardWithLocalPlacement = + await firstValueFrom( + this.scoreService.setScoreForLanguage(this.gameLanguage, score), + ); + + if ( + leaderboardWithLocalPlacement.placement < 10 && + leaderboardWithLocalPlacement.placement > 0 + ) { + await this.writeDelayed(`TOP SCORE!`); + } else if (leaderboardWithLocalPlacement.placement == 0) { + await this.writeDelayed(`🔥 HIGHSCORE🔥`); + } + + // Add ANSI Escape Codes to format the name for the leaderboard so the current run shows in bold letters + score.name = '>>\x1b[1;31m ' + score.name + ' \x1b[0m<<'; // \x1b[1;31m makes the text bold (1) and red (31), \x1b[0m clears all effects + + await this.writeDelayed(`Thank you for playing, ${fullName}!`); + await this.writeDelayed(`Let's view the Leaderboard.`); + + await this.displayLeaderboard( + this.gameLanguage, + leaderboardWithLocalPlacement, + score, + ); + + this.terminalSymbol = `Press Enter to continue!`; + + this.commandFn = this.endGame; + } + + async endGame(command: string, params: string) { + this.input_blocked = true; + this.resetToDefaultShell(); + this.gameEnded.emit(); + } + + async displayLeaderboard( + language: string, + leaderboardWithLocalPlacement: LeaderboardWithLocalPlacement, + score: Score, + ) { + if (!language || language == '') { + language = 'all'; + } + if ( + !leaderboardWithLocalPlacement || + leaderboardWithLocalPlacement.language == '' || + leaderboardWithLocalPlacement.scores.length == 0 + ) { + await this.term.writeln(`No Leaderboard for this language present.`); + return; + } + + const langName = this.languageCommandService.getLanguageNameById(language); + + await this.term.writeln( + '-------------' + '-'.repeat(langName.length) + '-', + ); + await this.term.writeln('LEADERBOARD (' + langName + ')'); + await this.term.writeln( + '-------------' + '-'.repeat(langName.length) + '-', + ); + + // If we show the leaderboard after a game add the score to the placements leaderboard and sort it so that the score is displayed at the correct position + if (score && score.score && score.name != '') { + if (leaderboardWithLocalPlacement.placement < 10) { + leaderboardWithLocalPlacement.scores.push(score); + leaderboardWithLocalPlacement.scores = + leaderboardWithLocalPlacement.scores.sort( + (a, b) => b.score - a.score, + ); + } else { + leaderboardWithLocalPlacement.localscores.push(score); + leaderboardWithLocalPlacement.localscores = + leaderboardWithLocalPlacement.localscores.sort( + (a, b) => b.score - a.score, + ); + } + } + + let scores = [['', 'NAME', 'SCORE']]; // Table heading for scoreboard + scores = scores.concat( + leaderboardWithLocalPlacement.scores + .slice(0, 10) + .map((score, index) => [ + '' + (index + 1) + '.', + score.name, + score.score.toString(), + ]), + ); + + if ( + leaderboardWithLocalPlacement && + leaderboardWithLocalPlacement.placement >= 10 + ) { + scores.push(['...', '...', '...']); + const scoreIndex = leaderboardWithLocalPlacement.localscores.findIndex( + (localScore) => + score.name === localScore.name && + localScore.score === localScore.score, + ); + + scores = scores.concat( + leaderboardWithLocalPlacement.localscores.map((score, index) => [ + '' + + (leaderboardWithLocalPlacement.placement + index - scoreIndex + 1) + + '.', + score.name, + score.score.toString(), + ]), + ); + } + + const longestScore = scores[1][2]?.length ?? 0; // First score entry has the highest score so it is the longest, + scores.forEach((scoreEntry, index) => { + const pad = Math.max(longestScore - scoreEntry[2].length, 0); + scores[index][2] = ' '.repeat(pad) + scoreEntry[2]; + }); + + await this.writeMatrix(scores, false); + } + + async displayAvailableLanguages(incluedAll: boolean = true) { + let languages = this.languageCommandService + .getLanguageKeys() + .sort((a, b) => { + return a.toLowerCase() > b.toLowerCase() ? 1 : -1; + }); + + if (incluedAll) { + languages = ['all'].concat(languages); + } + + const matrix = this.convertToMatrix(languages, 7); + await this.writeMatrix(matrix, false); + //await this.writeMatrix(this.convertToMatrix(newLang, 4), false); + } + + async gameCommand(cmd: string, args: string) { + const r = this.languageCommandService.find(cmd, this.gameLanguage); + + let score: { + base: number; + fire: number; + streak: number; + streakPoints: number; + total: number; + } = { + base: 0, + fire: 0, + streak: 0, + streakPoints: 0, + total: 0, + }; + let outputString; + + const timePassed = this.DEFAULT_GAME_TIME - this.gameTime; + + if (r.found && !this.commandsEntered.includes(r.cmd)) { + this.commandsEntered.push(r.cmd); + this.streak += 1; + this.highestStreak = Math.max(this.highestStreak, this.streak); + + if (this.commandsEnteredAtTimepoint[timePassed]) { + this.commandsEnteredAtTimepoint[timePassed] += 1; + } else { + this.commandsEnteredAtTimepoint[timePassed] = 1; + } + + score = this.getCommandScore(); + this.score += score.total; + + outputString = ' ✔ ' + r.cmd; + + if (this.gameLanguage == 'all') { + outputString += ' | (' + r.lang.join(', ') + ')'; + } + + outputString += ' | + ' + score.total; + + if (score.fire > 0) { + outputString += ' 🔥x' + score.fire; + } + } else if (this.commandsEntered.includes(r.cmd)) { + this.commandsEnteredAtTimepoint = []; // Reset so the streak gets lost + this.streak = 0; + outputString = ' ✘ ' + cmd + ' | Duplicate to "' + r.cmd + '"'; + } else { + this.commandsEnteredAtTimepoint = []; // Reset so the streak gets lost + this.streak = 0; + outputString = ' ✘ ' + cmd; + } + + const totalRows = this.term.rows; // Total number of rows in the terminal + const commandsAreaEnd = totalRows - 2; // The last line before the fixed input line + + // Write new command in the line just above the fixed input area + this.term.write(`\x1b[${commandsAreaEnd};1H`); // Moves cursor and clears the line + + this.term.writeln(outputString); // Write the new command + //this.term.writeln(''); // Write the new command + // Update the scoreboard or perform other updates + await this.writeScore(); + + // Ensure the fixed input line is clean and the cursor is placed correctly + this.term.write(`\x1b[${totalRows - 1};1H\x1b[2K`); // Optionally clear the input line + await this.moveToInputLine(); + } + + // Calculate score based on the average count of commands over the last 5 seconds. + getCommandScore() { + const result: { + base: number; + fire: number; + streak: number; + streakPoints: number; + total: number; + } = { + base: 128, + fire: 0, + streak: 0, + streakPoints: 0, + total: 0, + }; + + const timeSinceStart = this.DEFAULT_GAME_TIME - this.gameTime; + const commandsInLastSeconds = + this.commandsInLastSeconds( + this.commandsEnteredAtTimepoint, + timeSinceStart, + 7, + ) - 3; + + const growthFactor = 2; + let fireMultiplier = 1; + if (commandsInLastSeconds >= 0) { + fireMultiplier = Math.pow(growthFactor, commandsInLastSeconds + 1); + result.fire = fireMultiplier; + } + + result.streak = this.streak; + result.streakPoints = result.base * (this.streak - 1); + result.total = (result.base + result.streakPoints) * fireMultiplier; + + return result; + } + + commandsInLastSeconds( + commandsArray: number[], + currentTimeIndex: number, + seconds: number, + ): number { + let sum = 0; + // Start from the current time index, go back up to 5 seconds if available + for ( + let i = currentTimeIndex; + i > currentTimeIndex - seconds && i >= 0; + i-- + ) { + sum += commandsArray[i] ?? 0; + } + return sum; + } + + async moveToInputLine() { + // Calculate the position for the new command line, which should be one line above the current input line + const inputLinePosition = + this.term.rows + this.term.buffer.active.viewportY - 1; // Position of the input line + // Move back to the input line position + this.term.write(`\x1b[${inputLinePosition + 1};1H`); + this.term.write('\x1b[2K'); // Clear the line again to ensure it's clean for new input + } + + async selectGameOption(input: string, _args: string) { + const args = input.split(' '); + const command = args[0]; + const params = args.slice(1).join(' '); + + switch (command) { + case 'help': + await this.helpGame(); + break; + case 'play': + await this.selectLanguage(params, ''); + break; + case 'lang': + case 'languages': + await this.displayAvailableLanguages(); + break; + case 'leaderboard': + case 'top': { + const leaderboard = await firstValueFrom( + this.scoreService.getLeaderboard(params), + ); + await this.displayLeaderboard(params, leaderboard, {} as Score); + break; + } + default: + await this.term.writeln('Invalid Option: ' + input); + await this.helpGame(); + } + } + + async selectLanguage(language: string, args: string) { + let languages = this.languageCommandService.getLanguageKeys(); + languages = languages.map((el) => { + return el.toLowerCase(); + }); + if (languages.includes(language.toLowerCase())) { + await this.confirmBeginGame(language.toLowerCase()); + } else if (language == '') { + await this.confirmBeginGame('all'); + } else { + await this.term.writeln('Invalid language. Available languages are: '); + await this.displayAvailableLanguages(); + } + } + + async menuCommandsFn(command: string, args: string) { + switch (command) { + case '': + break; + case 'ls': + await this.writeMatrix([['\x1b[1;32mbrawl\x1b[0m']]); + break; + case 'echo': + this.term.writeln(args); + break; + case 'clear': + this.clearTerminal(); + break; + case 'brawl': + await this.startGame(args); + break; + case 'exit': + this.endGame('', ''); + break; + default: + this.term.writeln(`Command not found: ${command}`); + } + } + async handleCommand(input: string) { + const args = input.split(' '); + const command = args[0]; + const params = args.slice(1).join(' '); + + this.input_blocked = true; + this.interrupted = false; + + await this.commandFn(command, params); + + this.term.write(` ${this.terminalSymbol} `); + this.interrupted = false; + this.input_blocked = false; + } + + async handleCommandWithNewline(input: string) { + this.term.write('\r\n'); + await this.handleCommand(input); + } + + resetToDefaultShell() { + this.terminalSymbol = this.DEFAULT_TERMINAL_SYMBOL; + + if (!this.input_blocked) { + // We are inside a shell. Abort + this.term.write(`\r\n ${this.terminalSymbol} `); + } + + this.command = ''; + this.cursorPosition = 0; + this.input_blocked = false; + this.inputFn = this.handleCommandWithNewline; + this.commandFn = this.menuCommandsFn; + } + + async noop(command: string, args: string) { + // none + } + + async writeMatrix(text: string[][], writeDelayed: boolean = false) { + const maxColumns = text.reduce((max, row) => Math.max(max, row.length), 0); + // Calculate the longest string in each column + const maxLengths: number[] = Array(maxColumns).fill(0); + text.forEach((row) => { + row.forEach((item, index) => { + if (index < maxColumns) { + // Ensure we don't exceed the number of columns + maxLengths[index] = Math.max( + maxLengths[index], + stripAnsi(item).length, + ); + } + }); + }); + + // Generate and write each row of the matrix + for (const row of text) { + let rowString = ''; + row.forEach((item, index) => { + if (index < maxColumns) { + // Ensure we don't exceed the number of columns + + const paddingLength = maxLengths[index] - stripAnsi(item).length; + rowString += `${item}${' '.repeat(paddingLength + 2)}`; // 2 spaces as gutter + } + }); + + // Write the formatted row to the terminal + if (writeDelayed) { + await this.writeDelayed(' ' + rowString); + } else { + this.term.writeln(' ' + rowString); + } + } + } + + // Simply convert a flat list to a matrix with numColumns + // for advanced matrixes view convertToMatrixWithTerminalWidth + convertToMatrix(list: T[], numColumns: number): T[][] { + const matrix: T[][] = []; + for (let i = 0; i < list.length; i += numColumns) { + matrix.push(list.slice(i, i + numColumns)); + } + return matrix; + } + + async writeDelayed( + text: string, + newline: boolean = true, + offset: number = 0, + ) { + if (text.length == offset || this.interrupted) { + if (newline && offset != 0) { + this.term.write(`\r\n`); + } + return; + } + + const chars = text.split(''); + this.term.write(chars[offset]); + const nextIsWhitespace = + chars.length > offset + 1 && chars[offset + 1].match(/\s/); + await sleep( + nextIsWhitespace + ? this.TERMINAL_WHITESPACE_DELAY + : this.TERMINAL_CHAR_DELAY, + ); + await this.writeDelayed(text, newline, offset + 1); + } + + ngOnInit() { + this.buildTerminal(); + } + + ngAfterViewInit(): void { + // Options for the observer (which mutations to observe) + const config: MutationObserverInit = { + attributes: true, + childList: true, + subtree: true, + }; + + // Callback function to execute when mutations are observed + const callback: MutationCallback = (mutationsList: MutationRecord[]) => { + mutationsList.forEach((mutation) => { + // After the first start of the scenario, wait until the visible terminal element is added to the DOM. + if (mutation.type === 'childList') { + if ( + this.term && + this.term.element && + this.term.element.offsetParent && + !this.isVisible + ) { + this.isVisible = true; + this.firstTabChange = false; + this.resize(); + } else if ( + !( + this.term && + this.term.element && + this.term.element.offsetParent + ) && + this.isVisible + ) { + this.isVisible = false; + } + } else if (mutation.type === 'attributes') { + // Is triggered if aria-selected changes (on tab button) and terminal should be visible. + // Should only be called after the first tab change. + if ( + this.term && + this.term.element && + this.term.element.offsetParent && + !this.isVisible && + !this.firstTabChange + ) { + this.isVisible = true; + this.resize(); + + // After the first switch between tabs, do not change the terminal's visibility before the (xterm) canvas element attributes are changed. + // The terminal is now visible and the xterm.fit() function can be called without throwing errors. + } else if ( + this.term && + this.term.element && + this.term.element.offsetParent && + !this.isVisible && + mutation.target.nodeName == 'CANVAS' + ) { + this.isVisible = true; + this.firstTabChange = false; + this.resize(); + + // Is triggered if aria-selected changes (on tab button) and terminal should not be visible anymore. + } else if ( + !( + this.term && + this.term.element && + this.term.element.offsetParent + ) && + this.isVisible + ) { + this.isVisible = false; + } + } + }); + }; + // Create an observer instance linked to the callback function + this.mutationObserver = new MutationObserver(callback); + + this.mutationObserver.observe( + this.terminalDiv.nativeElement.offsetParent, + config, + ); + } + + private setTerminalTheme(themeId: string) { + if (!this.term) return; + const theme = themes.find((t) => t.id === themeId) || themes[0]; + this.term.options.theme = theme.styles; + } + + private setFontSize(size: number) { + if (!this.term) return; + this.term.options.fontSize = size ?? this.DEFAULT_FONT_SIZE; + this.resize(); + } + + public clearTerminal() { + this.term.clear(); + } + + public focusTerminal() { + this.term.focus(); + } +} diff --git a/src/app/scenario/bashbrawl/keycodes.ts b/src/app/scenario/bashbrawl/keycodes.ts new file mode 100644 index 00000000..90d48bac --- /dev/null +++ b/src/app/scenario/bashbrawl/keycodes.ts @@ -0,0 +1,13 @@ +export const Keycodes = { + ENTER: '\r', + SPACE: 32, + ESCAPE: 27, + CTRL: 17, + CTR_C: '', + BACKSPACE: '\x7F', + DELETE: '[3~', + LEFT_ARROW: '', + RIGHT_ARROW: '', + UP_ARROW: '', + DOWN_ARROW: '', +}; diff --git a/src/app/scenario/bashbrawl/languages/LICENSE b/src/app/scenario/bashbrawl/languages/LICENSE new file mode 100644 index 00000000..e72bfdda --- /dev/null +++ b/src/app/scenario/bashbrawl/languages/LICENSE @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. \ No newline at end of file diff --git a/src/app/scenario/bashbrawl/languages/README.md b/src/app/scenario/bashbrawl/languages/README.md new file mode 100644 index 00000000..b059f6e7 --- /dev/null +++ b/src/app/scenario/bashbrawl/languages/README.md @@ -0,0 +1,46 @@ +# Adding languages + +1. Create a `.ts` file (for the syntax view one of the other files) +2. add the file to `language-command.service.ts` +3. Enjoy the game + +# Thanks to [clh-bash](https://github.com/CommandLineHeroes/clh-bash/) + +The maintainers of clr-bash already created + +- bash +- python +- html +- javascript + +
+ +# Building a shell command database + +We pull from several sources to populate the command database. + +_Note: all commands to be run from this directory, `assets/commands/`._ + +## From \$PATH (Fedora) + +Get all executables from the \$PATH and all built-in bash functions. + + compgen -bc > from-path-fedora.txt + +Get all DNF packages (this does not get executable names). + + dnf list all + +## JavaScript + +A few types of JS code are accepted. + +- all [keywords](https://tc39.github.io/ecma262/#sec-keywords) +- some [literals](https://tc39.github.io/ecma262/#sec-ecmascript-language-lexical-grammar-literals) + - literals to include: `null`, `true`, `false` +- all [properties of the global object](https://tc39.github.io/ecma262/#sec-global-object) +- all objects listed in [chapters 19-26](https://tc39.github.io/ecma262/#sec-fundamental-objects) + - for example, the subchapters of chapter 19 are "Object Objects", "Function Objects", "Boolean Objects", "Symbol Objects", and "Error Objects", so `object`, `function`, `boolean`, `symbol`, and `error` should be used. +- additional [built-in properties of the global object](https://tc39.github.io/ecma262/#sec-additional-properties-of-the-global-object) +- `async` should be added. it won't appear in the above lists because it is not a proper keyword (it's only a keyword in certain contexts but can still be used as a variable name, etc). +- `window`, `document`, `navigator` I can't find in any spec but should be included diff --git a/src/app/scenario/bashbrawl/languages/bash.ts b/src/app/scenario/bashbrawl/languages/bash.ts new file mode 100644 index 00000000..c86e3ba0 --- /dev/null +++ b/src/app/scenario/bashbrawl/languages/bash.ts @@ -0,0 +1,3575 @@ +/** Taken from https://github.com/CommandLineHeroes/clh-bash/tree/master/assets/cmds **/ + +/** Generated from generateBashCmds.js **/ +import { LanguageConfig } from './language-config.interface'; +export const bashConfig: LanguageConfig = { + name: 'bash', + cmds: [ + [''], + ['!'], + ['.'], + ['411toppm'], + [':'], + ['GET'], + ['HEAD'], + ['Mail'], + ['ModemManager'], + ['NetworkManager'], + ['POST'], + ['VBoxClient'], + ['VBoxClient-all'], + ['VBoxControl'], + ['VBoxService'], + ['VGAuthService'], + ['WebKitWebDriver'], + ['X'], + ['Xephyr'], + ['Xorg'], + ['Xvnc'], + ['Xwayland'], + ['['], + ['[['], + [']]'], + ['__HOSTNAME'], + ['__SIZE'], + ['__SLAVEURL'], + ['__VOLNAME'], + ['__expand_tilde_by_ref'], + ['__get_cword_at_cursor_by_ref'], + ['__grub_dir'], + ['__grub_get_last_option'], + ['__grub_get_options_from_help'], + ['__grub_get_options_from_usage'], + ['__grub_list_menuentries'], + ['__grub_list_modules'], + ['__grubcomp'], + ['__load_completion'], + ['__ltrim_colon_completions'], + ['__parse_options'], + ['__reassemble_comp_words_by_ref'], + ['__vte_osc7'], + ['__vte_prompt_command'], + ['__vte_ps1'], + ['__vte_urlencode'], + ['_allowed_groups'], + ['_allowed_users'], + ['_apport-bug'], + ['_apport-cli'], + ['_apport-collect'], + ['_apport-unpack'], + ['_apport_parameterless'], + ['_apport_symptoms'], + ['_available_fcoe_interfaces'], + ['_available_interfaces'], + ['_cd'], + ['_cd_devices'], + ['_command'], + ['_command_offset'], + ['_complete_as_root'], + ['_completion_loader'], + ['_configured_interfaces'], + ['_count_args'], + ['_dkms'], + ['_dog'], + ['_dog_benchmark'], + ['_dog_benchmark_io'], + ['_dog_cluster'], + ['_dog_cluster_alter-copy'], + ['_dog_cluster_check'], + ['_dog_cluster_format'], + ['_dog_cluster_info'], + ['_dog_cluster_recover'], + ['_dog_cluster_reweight'], + ['_dog_cluster_shutdown'], + ['_dog_cluster_snapshot'], + ['_dog_node'], + ['_dog_node_format'], + ['_dog_node_info'], + ['_dog_node_kill'], + ['_dog_node_list'], + ['_dog_node_log'], + ['_dog_node_md'], + ['_dog_node_recovery'], + ['_dog_node_stat'], + ['_dog_node_vnodes'], + ['_dog_upgrade'], + ['_dog_upgrade_config-convert'], + ['_dog_upgrade_epoch-convert'], + ['_dog_upgrade_inode-convert'], + ['_dog_upgrade_object-location'], + ['_dog_vdi'], + ['_dog_vdi_alter-copy'], + ['_dog_vdi_backup'], + ['_dog_vdi_check'], + ['_dog_vdi_clone'], + ['_dog_vdi_create'], + ['_dog_vdi_delete'], + ['_dog_vdi_getattr'], + ['_dog_vdi_graph'], + ['_dog_vdi_list'], + ['_dog_vdi_lock'], + ['_dog_vdi_object'], + ['_dog_vdi_read'], + ['_dog_vdi_resize'], + ['_dog_vdi_restore'], + ['_dog_vdi_rollback'], + ['_dog_vdi_setattr'], + ['_dog_vdi_snapshot'], + ['_dog_vdi_track'], + ['_dog_vdi_tree'], + ['_dog_vdi_write'], + ['_dvd_devices'], + ['_expand'], + ['_fcoeadm_options'], + ['_fcoemon_options'], + ['_filedir'], + ['_filedir_xspec'], + ['_filename_parts'], + ['_fstypes'], + ['_get_comp_words_by_ref'], + ['_get_cword'], + ['_get_first_arg'], + ['_get_pword'], + ['_gids'], + ['_gluster_completion'], + ['_gluster_does_match'], + ['_gluster_form_list'], + ['_gluster_goto_child'], + ['_gluster_goto_end'], + ['_gluster_handle_list'], + ['_gluster_parse'], + ['_gluster_pop'], + ['_gluster_push'], + ['_gluster_throw'], + ['_grub_editenv'], + ['_grub_install'], + ['_grub_mkconfig'], + ['_grub_mkfont'], + ['_grub_mkimage'], + ['_grub_mkpasswd_pbkdf2'], + ['_grub_mkrescue'], + ['_grub_probe'], + ['_grub_script_check'], + ['_grub_set_entry'], + ['_grub_setup'], + ['_have'], + ['_included_ssh_config_files'], + ['_init_completion'], + ['_installed_modules'], + ['_ip_addresses'], + ['_kernel_versions'], + ['_kernels'], + ['_known_hosts'], + ['_known_hosts_real'], + ['_lldpad_options'], + ['_lldptool_options'], + ['_longopt'], + ['_mac_addresses'], + ['_minimal'], + ['_module'], + ['_module_avail'], + ['_module_long_arg_list'], + ['_module_not_yet_loaded'], + ['_module_raw'], + ['_module_savelist'], + ['_modules'], + ['_ncpus'], + ['_parse_help'], + ['_parse_usage'], + ['_pci_ids'], + ['_pgids'], + ['_pids'], + ['_pnames'], + ['_quote_readline_by_ref'], + ['_realcommand'], + ['_rl_enabled'], + ['_root_command'], + ['_scl'], + ['_service'], + ['_services'], + ['_shells'], + ['_signals'], + ['_split_longopt'], + ['_subdirectories'], + ['_sysvdirs'], + ['_terms'], + ['_tilde'], + ['_uids'], + ['_upvar'], + ['_upvars'], + ['_usb_ids'], + ['_user_at_host'], + ['_usergroup'], + ['_userland'], + ['_variables'], + ['_xfunc'], + ['_xinetd_services'], + ['aa-enabled'], + ['aa-exec'], + ['aa-remove-unknown'], + ['aa-status'], + ['ab'], + ['abrt-action-analyze-backtrace'], + ['abrt-action-analyze-c'], + ['abrt-action-analyze-ccpp-local'], + ['abrt-action-analyze-core'], + ['abrt-action-analyze-java'], + ['abrt-action-analyze-oops'], + ['abrt-action-analyze-python'], + ['abrt-action-analyze-vmcore'], + ['abrt-action-analyze-vulnerability'], + ['abrt-action-analyze-xorg'], + ['abrt-action-check-oops-for-alt-component'], + ['abrt-action-check-oops-for-hw-error'], + ['abrt-action-find-bodhi-update'], + ['abrt-action-generate-backtrace'], + ['abrt-action-generate-core-backtrace'], + ['abrt-action-install-debuginfo'], + ['abrt-action-list-dsos'], + ['abrt-action-notify'], + ['abrt-action-perform-ccpp-analysis'], + ['abrt-action-save-package-data'], + ['abrt-action-trim-files'], + ['abrt-applet'], + ['abrt-auto-reporting'], + ['abrt-bodhi'], + ['abrt-cli'], + ['abrt-configuration'], + ['abrt-dbus'], + ['abrt-dump-journal-core'], + ['abrt-dump-journal-oops'], + ['abrt-dump-journal-xorg'], + ['abrt-dump-oops'], + ['abrt-dump-xorg'], + ['abrt-handle-upload'], + ['abrt-harvest-pstoreoops'], + ['abrt-harvest-vmcore'], + ['abrt-install-ccpp-hook'], + ['abrt-merge-pstoreoops'], + ['abrt-retrace-client'], + ['abrt-server'], + ['abrt-watch-log'], + ['abrtd'], + ['ac'], + ['accept'], + ['accessdb'], + ['accton'], + ['aconnect'], + ['acpi'], + ['acpi_available'], + ['acpi_listen'], + ['acpid'], + ['adcli'], + ['add-apt-repository'], + ['add-shell'], + ['add.modules'], + ['addgnupghome'], + ['addgroup'], + ['addpart'], + ['addr2line'], + ['adduser'], + ['adsl-start'], + ['adsl-stop'], + ['afs5log'], + ['agetty'], + ['akmods'], + ['akmods-shutdown'], + ['akmodsbuild'], + ['alert'], + ['alias'], + ['alsa'], + ['alsa-info'], + ['alsa-info.sh'], + ['alsabat'], + ['alsabat-test'], + ['alsactl'], + ['alsaloop'], + ['alsamixer'], + ['alsatplg'], + ['alsaucm'], + ['alsaunmute'], + ['alternatives'], + ['amidi'], + ['amixer'], + ['amuFormat.sh'], + ['anaconda'], + ['anaconda-cleanup'], + ['anaconda-disable-nm-ibft-plugin'], + ['anacron'], + ['analog'], + ['animate'], + ['animate-im6'], + ['animate-im6.q16'], + ['annocheck'], + ['anytopnm'], + ['apachectl'], + ['apg'], + ['apgbfm'], + ['aplay'], + ['aplaymidi'], + ['apm_available'], + ['apparmor_parser'], + ['apparmor_status'], + ['applycal'], + ['applydeltarpm'], + ['applygnupgdefaults'], + ['apport-bug'], + ['apport-cli'], + ['apport-collect'], + ['apport-unpack'], + ['appres'], + ['appstream-compose'], + ['appstream-util'], + ['appstreamcli'], + ['apropos'], + ['apt'], + ['apt-add-repository'], + ['apt-cache'], + ['apt-cdrom'], + ['apt-config'], + ['apt-extracttemplates'], + ['apt-ftparchive'], + ['apt-get'], + ['apt-key'], + ['apt-mark'], + ['apt-sortpkgs'], + ['aptd'], + ['aptdcon'], + ['apturl'], + ['apturl-gtk'], + ['ar'], + ['arch'], + ['arecord'], + ['arecordmidi'], + ['arm2hpdl'], + ['arp'], + ['arpaname'], + ['arpd'], + ['arping'], + ['as'], + ['asciitopgm'], + ['aseqdump'], + ['aseqnet'], + ['aserver'], + ['aspell'], + ['aspell-autobuildhash'], + ['aspell-import'], + ['at'], + ['atd'], + ['atktopbm'], + ['atobm'], + ['atq'], + ['atrm'], + ['atrun'], + ['attr'], + ['audit2allow'], + ['audit2why'], + ['auditctl'], + ['auditd'], + ['augenrules'], + ['aulast'], + ['aulastlog'], + ['aureport'], + ['ausearch'], + ['ausyscall'], + ['authconfig'], + ['authselect'], + ['auvirt'], + ['avahi-autoipd'], + ['avahi-browse'], + ['avahi-browse-domains'], + ['avahi-daemon'], + ['avahi-publish'], + ['avahi-publish-address'], + ['avahi-publish-service'], + ['avahi-resolve'], + ['avahi-resolve-address'], + ['avahi-resolve-host-name'], + ['avahi-set-host-name'], + ['avcstat'], + ['average'], + ['awk'], + ['axfer'], + ['b2sum'], + ['b43-fwcutter'], + ['badblocks'], + ['baobab'], + ['base32'], + ['base64'], + ['basename'], + ['bash'], + ['bashbug'], + ['bashbug-64'], + ['batch'], + ['bc'], + ['bcache-status'], + ['bcache-super-show'], + ['bccmd'], + ['bdftopcf'], + ['bdftruncate'], + ['bg'], + ['bind'], + ['bioradtopgm'], + ['biosdecode'], + ['bitmap'], + ['blivet-gui'], + ['blivet-gui-daemon'], + ['blkdeactivate'], + ['blkdiscard'], + ['blkid'], + ['blkmapd'], + ['blkzone'], + ['blockdev'], + ['bluemoon'], + ['bluetooth-sendto'], + ['bluetoothctl'], + ['bluetoothd'], + ['bmptopnm'], + ['bmptoppm'], + ['bmtoa'], + ['boltctl'], + ['bond2team'], + ['bootctl'], + ['brctl'], + ['break'], + ['bridge'], + ['brltty'], + ['brltty-atb'], + ['brltty-config'], + ['brltty-ctb'], + ['brltty-ktb'], + ['brltty-lsinc'], + ['brltty-setup'], + ['brltty-trtxt'], + ['brltty-ttb'], + ['brltty-tune'], + ['broadwayd'], + ['brotli'], + ['browse'], + ['brushtopbm'], + ['bsd-from'], + ['bsd-write'], + ['btattach'], + ['btmgmt'], + ['btmon'], + ['btrfs'], + ['btrfs-convert'], + ['btrfs-find-root'], + ['btrfs-image'], + ['btrfs-map-logical'], + ['btrfs-select-super'], + ['btrfsck'], + ['btrfstune'], + ['built-by'], + ['builtin'], + ['bumblebee-bugreport'], + ['bumblebeed'], + ['bunzip2'], + ['busctl'], + ['busybox'], + ['bwrap'], + ['bzcat'], + ['bzcmp'], + ['bzdiff'], + ['bzegrep'], + ['bzexe'], + ['bzfgrep'], + ['bzgrep'], + ['bzip2'], + ['bzip2recover'], + ['bzless'], + ['bzmore'], + ['c++filt'], + ['c89'], + ['c99'], + ['c_rehash'], + ['ca-legacy'], + ['cache_check'], + ['cache_dump'], + ['cache_metadata_size'], + ['cache_repair'], + ['cache_restore'], + ['cache_writeback'], + ['cairo-sphinx'], + ['cal'], + ['calendar'], + ['calibrate_ppa'], + ['caller'], + ['canberra-boot'], + ['canberra-gtk-play'], + ['cancel'], + ['cancel.cups'], + ['capsh'], + ['captoinfo'], + ['case'], + ['cat'], + ['catchsegv'], + ['catman'], + ['cautious-launcher'], + ['cb2ti3'], + ['cbq'], + ['cc'], + ['cctiff'], + ['ccttest'], + ['ccxxmake'], + ['cd'], + ['cd-convert'], + ['cd-create-profile'], + ['cd-drive'], + ['cd-fix-profile'], + ['cd-iccdump'], + ['cd-info'], + ['cd-it8'], + ['cd-paranoia'], + ['cd-read'], + ['cdda-player'], + ['celtdec051'], + ['celtenc051'], + ['cfdisk'], + ['cgdisk'], + ['chacl'], + ['chage'], + ['chardet3'], + ['chardetect3'], + ['chartread'], + ['chat'], + ['chattr'], + ['chcat'], + ['chcon'], + ['chcpu'], + ['check-abi'], + ['check-language-support'], + ['checkisomd5'], + ['checkmodule'], + ['checkpolicy'], + ['checksctp'], + ['cheese'], + ['chfn'], + ['chgpasswd'], + ['chgrp'], + ['chkconfig'], + ['chmem'], + ['chmod'], + ['chown'], + ['chpasswd'], + ['chrome-gnome-shell'], + ['chronyc'], + ['chronyd'], + ['chroot'], + ['chrt'], + ['chsh'], + ['chvt'], + ['cifs.idmap'], + ['cifs.upcall'], + ['cifscreds'], + ['cifsdd'], + ['ciptool'], + ['cisco-decrypt'], + ['ckbcomp'], + ['cksum'], + ['clear'], + ['clear_console'], + ['clock'], + ['clockdiff'], + ['cmp'], + ['cmuwmtopbm'], + ['codepage'], + ['col'], + ['colcrt'], + ['collink'], + ['colormgr'], + ['colprof'], + ['colrm'], + ['column'], + ['colverify'], + ['combinedeltarpm'], + ['combinediff'], + ['comm'], + ['command'], + ['command_not_found_handle'], + ['compare'], + ['compare-im6'], + ['compare-im6.q16'], + ['compgen'], + ['complete'], + ['compopt'], + ['compose'], + ['composite'], + ['composite-im6'], + ['composite-im6.q16'], + ['conjure'], + ['conjure-im6'], + ['conjure-im6.q16'], + ['consolehelper'], + ['consoletype'], + ['continue'], + ['convert'], + ['convert-im6'], + ['convert-im6.q16'], + ['convertquota'], + ['coproc'], + ['coredumpctl'], + ['corelist'], + ['coverage-3.7'], + ['coverage3'], + ['cp'], + ['cpan'], + ['cpan5.26-x86_64-linux-gnu'], + ['cpgr'], + ['cpio'], + ['cpp'], + ['cpp-8'], + ['cppw'], + ['cpustat'], + ['cracklib-check'], + ['cracklib-format'], + ['cracklib-packer'], + ['cracklib-unpacker'], + ['crc32'], + ['crda'], + ['create-cracklib-dict'], + ['createmodule.py'], + ['createmodule.sh'], + ['createrepo'], + ['createrepo_c'], + ['cron'], + ['crond'], + ['cronnext'], + ['crontab'], + ['cryptsetup'], + ['csplit'], + ['csslint-0.6'], + ['cstool'], + ['ctrlaltdel'], + ['ctstat'], + ['cups-browsed'], + ['cups-calibrate'], + ['cups-genppd.5.2'], + ['cups-genppdupdate'], + ['cupsaccept'], + ['cupsaddsmb'], + ['cupsctl'], + ['cupsd'], + ['cupsdisable'], + ['cupsenable'], + ['cupsfilter'], + ['cupsreject'], + ['cupstestdsc'], + ['cupstestppd'], + ['curl'], + ['cut'], + ['cvt'], + ['cvtsudoers'], + ['dash'], + ['date'], + ['dazzle-list-counters'], + ['db_archive'], + ['db_checkpoint'], + ['db_deadlock'], + ['db_dump'], + ['db_dump185'], + ['db_hotbackup'], + ['db_load'], + ['db_log_verify'], + ['db_printlog'], + ['db_recover'], + ['db_replicate'], + ['db_stat'], + ['db_tuner'], + ['db_upgrade'], + ['db_verify'], + ['dbus-binding-tool'], + ['dbus-cleanup-sockets'], + ['dbus-daemon'], + ['dbus-launch'], + ['dbus-monitor'], + ['dbus-run-session'], + ['dbus-send'], + ['dbus-test-tool'], + ['dbus-update-activation-environment'], + ['dbus-uuidgen'], + ['dbwrap_tool'], + ['dbxtool'], + ['dc'], + ['dcbtool'], + ['dconf'], + ['dd'], + ['ddns-confgen'], + ['ddstdecode'], + ['deallocvt'], + ['deb-systemd-helper'], + ['deb-systemd-invoke'], + ['debconf'], + ['debconf-apt-progress'], + ['debconf-communicate'], + ['debconf-copydb'], + ['debconf-escape'], + ['debconf-set-selections'], + ['debconf-show'], + ['debugfs'], + ['declare'], + ['dehtmldiff'], + ['deja-dup'], + ['delgroup'], + ['delpart'], + ['deluser'], + ['delv'], + ['depmod'], + ['dequote'], + ['desktop-file-edit'], + ['desktop-file-install'], + ['desktop-file-validate'], + ['devdump'], + ['devlink'], + ['df'], + ['dfu-tool'], + ['dh_bash-completion'], + ['dh_perl_openssl'], + ['dhclient'], + ['dhclient-script'], + ['diff'], + ['diff3'], + ['diffstat'], + ['dig'], + ['dir'], + ['dircolors'], + ['dirmngr'], + ['dirmngr-client'], + ['dirname'], + ['dirs'], + ['dirsplit'], + ['disown'], + ['dispcal'], + ['display'], + ['display-im6'], + ['display-im6.q16'], + ['dispread'], + ['dispwin'], + ['distro'], + ['dkms'], + ['dm_dso_reg_tool'], + ['dmesg'], + ['dmevent_tool'], + ['dmeventd'], + ['dmfilemapd'], + ['dmidecode'], + ['dmraid'], + ['dmraid.static'], + ['dmsetup'], + ['dmstats'], + ['dnf'], + ['dnf-3'], + ['dnsdomainname'], + ['dnsmasq'], + ['dnssec-checkds'], + ['dnssec-coverage'], + ['dnssec-dsfromkey'], + ['dnssec-importkey'], + ['dnssec-keyfromlabel'], + ['dnssec-keygen'], + ['dnssec-keymgr'], + ['dnssec-revoke'], + ['dnssec-settime'], + ['dnssec-signzone'], + ['dnssec-verify'], + ['do'], + ['do-release-upgrade'], + ['dog'], + ['domainname'], + ['done'], + ['dos2unix'], + ['dosfsck'], + ['dosfslabel'], + ['dotlockfile'], + ['dpkg'], + ['dpkg-deb'], + ['dpkg-divert'], + ['dpkg-maintscript-helper'], + ['dpkg-preconfigure'], + ['dpkg-query'], + ['dpkg-reconfigure'], + ['dpkg-split'], + ['dpkg-statoverride'], + ['dpkg-trigger'], + ['dracut'], + ['driverless'], + ['du'], + ['dump-acct'], + ['dump-utmp'], + ['dumpe2fs'], + ['dumpiso'], + ['dumpkeys'], + ['dvcont'], + ['dvipdf'], + ['dwp'], + ['dwz'], + ['e2freefrag'], + ['e2fsck'], + ['e2image'], + ['e2label'], + ['e2mmpstatus'], + ['e2undo'], + ['e4crypt'], + ['e4defrag'], + ['eapol_test'], + ['easy_install-3.7'], + ['ebtables'], + ['ebtables-legacy'], + ['ebtables-restore'], + ['ebtables-save'], + ['echo'], + ['ed'], + ['edid-decode'], + ['edit'], + ['editdiff'], + ['editor'], + ['editres'], + ['edquota'], + ['efibootdump'], + ['efibootmgr'], + ['egrep'], + ['eject'], + ['elfedit'], + ['elif'], + ['else'], + ['enable'], + ['enc2xs'], + ['enca'], + ['encguess'], + ['enchant'], + ['enchant-2'], + ['enchant-lsmod'], + ['enchant-lsmod-2'], + ['enconv'], + ['env'], + ['envml'], + ['envsubst'], + ['eog'], + ['epiphany'], + ['eps2eps'], + ['eqn'], + ['era_check'], + ['era_dump'], + ['era_invalidate'], + ['era_restore'], + ['esac'], + ['esc-m'], + ['escputil'], + ['esmtp'], + ['esmtp-wrapper'], + ['espdiff'], + ['espeak-ng'], + ['ether-wake'], + ['ethtool'], + ['eu-addr2line'], + ['eu-ar'], + ['eu-elfcmp'], + ['eu-elfcompress'], + ['eu-elflint'], + ['eu-findtextrel'], + ['eu-make-debug-archive'], + ['eu-nm'], + ['eu-objdump'], + ['eu-ranlib'], + ['eu-readelf'], + ['eu-size'], + ['eu-stack'], + ['eu-strings'], + ['eu-strip'], + ['eu-unstrip'], + ['eutp'], + ['eval'], + ['evince'], + ['evince-previewer'], + ['evince-thumbnailer'], + ['evmctl'], + ['evolution'], + ['ex'], + ['exec'], + ['exempi'], + ['exit'], + ['exiv2'], + ['expand'], + ['expiry'], + ['export'], + ['exportfs'], + ['expr'], + ['extlinux'], + ['extracticc'], + ['extractttag'], + ['eyuvtoppm'], + ['factor'], + ['faillock'], + ['faillog'], + ['fakeCMY'], + ['faked'], + ['faked-sysv'], + ['faked-tcp'], + ['fakeread'], + ['fakeroot'], + ['fakeroot-sysv'], + ['fakeroot-tcp'], + ['fallocate'], + ['false'], + ['fatlabel'], + ['fc'], + ['fc-cache'], + ['fc-cache-64'], + ['fc-cat'], + ['fc-conflist'], + ['fc-list'], + ['fc-match'], + ['fc-pattern'], + ['fc-query'], + ['fc-scan'], + ['fc-validate'], + ['fcgistarter'], + ['fcnsq'], + ['fcoeadm'], + ['fcoemon'], + ['fcping'], + ['fcrls'], + ['fdformat'], + ['fdisk'], + ['fg'], + ['fgconsole'], + ['fgrep'], + ['fi'], + ['fiascotopnm'], + ['file'], + ['file-roller'], + ['file2brl'], + ['filefrag'], + ['filterdiff'], + ['fincore'], + ['find'], + ['findfs'], + ['findmnt'], + ['findsmb'], + ['fips-finish-install'], + ['fips-mode-setup'], + ['fipscheck'], + ['fipshmac'], + ['fipvlan'], + ['firefox'], + ['firewall-cmd'], + ['firewall-offline-cmd'], + ['firewalld'], + ['fitstopnm'], + ['fix-info-dir'], + ['fix-qdf'], + ['fixcvsdiff'], + ['fixfiles'], + ['fixparts'], + ['flatpak'], + ['flatpak-bisect'], + ['flatpak-coredumpctl'], + ['flipdiff'], + ['flock'], + ['fmt'], + ['fold'], + ['fonttosfnt'], + ['foo2ddst'], + ['foo2ddst-wrapper'], + ['foo2hbpl2'], + ['foo2hbpl2-wrapper'], + ['foo2hiperc'], + ['foo2hiperc-wrapper'], + ['foo2hp'], + ['foo2hp2600-wrapper'], + ['foo2lava'], + ['foo2lava-wrapper'], + ['foo2oak'], + ['foo2oak-wrapper'], + ['foo2qpdl'], + ['foo2qpdl-wrapper'], + ['foo2slx'], + ['foo2slx-wrapper'], + ['foo2xqx'], + ['foo2xqx-wrapper'], + ['foo2zjs'], + ['foo2zjs-icc2ps'], + ['foo2zjs-pstops'], + ['foo2zjs-wrapper'], + ['foomatic-addpjloptions'], + ['foomatic-cleanupdrivers'], + ['foomatic-combo-xml'], + ['foomatic-compiledb'], + ['foomatic-configure'], + ['foomatic-datafile'], + ['foomatic-extract-text'], + ['foomatic-fix-xml'], + ['foomatic-getpjloptions'], + ['foomatic-kitload'], + ['foomatic-nonumericalids'], + ['foomatic-perl-data'], + ['foomatic-ppd-options'], + ['foomatic-ppd-to-xml'], + ['foomatic-ppdfile'], + ['foomatic-preferred-driver'], + ['foomatic-printermap-to-gutenprint-xml'], + ['foomatic-printjob'], + ['foomatic-replaceoldprinterids'], + ['foomatic-rip'], + ['foomatic-searchprinter'], + ['for'], + ['fpaste'], + ['fprintd-delete'], + ['fprintd-enroll'], + ['fprintd-list'], + ['fprintd-verify'], + ['free'], + ['fribidi'], + ['from'], + ['fros'], + ['fsadm'], + ['fsck'], + ['fsck.btrfs'], + ['fsck.cramfs'], + ['fsck.ext2'], + ['fsck.ext3'], + ['fsck.ext4'], + ['fsck.fat'], + ['fsck.hfs'], + ['fsck.hfsplus'], + ['fsck.minix'], + ['fsck.msdos'], + ['fsck.ntfs'], + ['fsck.vfat'], + ['fsck.xfs'], + ['fsfreeze'], + ['fstab-decode'], + ['fstopgm'], + ['fstrim'], + ['ftp'], + ['function'], + ['funzip'], + ['fuse2fs'], + ['fuser'], + ['fusermount'], + ['fusermount-glusterfs'], + ['fwupdmgr'], + ['g13'], + ['g13-syshelp'], + ['g3topbm'], + ['gamma4scanimage'], + ['gapplication'], + ['gatttool'], + ['gawk'], + ['gawklibpath_append'], + ['gawklibpath_default'], + ['gawklibpath_prepend'], + ['gawkpath_append'], + ['gawkpath_default'], + ['gawkpath_prepend'], + ['gcalccmd'], + ['gcc'], + ['gcc-ar'], + ['gcc-nm'], + ['gcc-ranlib'], + ['gcm-calibrate'], + ['gcm-import'], + ['gcm-inspect'], + ['gcm-picker'], + ['gcm-viewer'], + ['gconf-merge-tree'], + ['gconftool-2'], + ['gcore'], + ['gcov'], + ['gcov-dump'], + ['gcov-tool'], + ['gcr-viewer'], + ['gdb'], + ['gdb-add-index'], + ['gdbserver'], + ['gdbtui'], + ['gdbus'], + ['gdialog'], + ['gdisk'], + ['gdk-pixbuf-csource'], + ['gdk-pixbuf-pixdata'], + ['gdk-pixbuf-query-loaders-64'], + ['gdk-pixbuf-thumbnailer'], + ['gdm'], + ['gdm-screenshot'], + ['gdm3'], + ['gdmflexiserver'], + ['gedit'], + ['gemtopbm'], + ['gemtopnm'], + ['gencat'], + ['gendiff'], + ['genhomedircon'], + ['genhostid'], + ['genisoimage'], + ['genl'], + ['genl-ctrl-list'], + ['genrandom'], + ['geoiplookup'], + ['geoiplookup6'], + ['geqn'], + ['getcap'], + ['getcifsacl'], + ['getconf'], + ['geteltorito'], + ['getenforce'], + ['getent'], + ['getfacl'], + ['getfattr'], + ['gethostip'], + ['getkeycodes'], + ['getopt'], + ['getopts'], + ['getpcaps'], + ['getsebool'], + ['gettext'], + ['gettext.sh'], + ['gettextize'], + ['getty'], + ['getweb'], + ['ghostscript'], + ['giftopnm'], + ['ginstall-info'], + ['gio'], + ['gio-launch-desktop'], + ['gio-querymodules'], + ['gio-querymodules-64'], + ['gipddecode'], + ['git'], + ['git-receive-pack'], + ['git-shell'], + ['git-upload-archive'], + ['git-upload-pack'], + ['gjs'], + ['gjs-console'], + ['gkbd-keyboard-display'], + ['glib-compile-schemas'], + ['glreadtest'], + ['gluster'], + ['glusterfs'], + ['glusterfsd'], + ['glxgears'], + ['glxinfo'], + ['glxinfo64'], + ['glxspheres64'], + ['gmake'], + ['gneqn'], + ['gnome-abrt'], + ['gnome-boxes'], + ['gnome-calculator'], + ['gnome-calendar'], + ['gnome-characters'], + ['gnome-clocks'], + ['gnome-contacts'], + ['gnome-control-center'], + ['gnome-disk-image-mounter'], + ['gnome-disks'], + ['gnome-documents'], + ['gnome-font-viewer'], + ['gnome-help'], + ['gnome-keyring'], + ['gnome-keyring-3'], + ['gnome-keyring-daemon'], + ['gnome-language-selector'], + ['gnome-logs'], + ['gnome-mahjongg'], + ['gnome-maps'], + ['gnome-menus-blacklist'], + ['gnome-mines'], + ['gnome-photos'], + ['gnome-power-statistics'], + ['gnome-screenshot'], + ['gnome-session'], + ['gnome-session-custom-session'], + ['gnome-session-inhibit'], + ['gnome-session-properties'], + ['gnome-session-quit'], + ['gnome-session-remmina'], + ['gnome-shell'], + ['gnome-shell-extension-prefs'], + ['gnome-shell-extension-tool'], + ['gnome-shell-perf-tool'], + ['gnome-software'], + ['gnome-software-editor'], + ['gnome-sudoku'], + ['gnome-system-monitor'], + ['gnome-terminal'], + ['gnome-terminal.real'], + ['gnome-terminal.wrapper'], + ['gnome-text-editor'], + ['gnome-thumbnail-font'], + ['gnome-todo'], + ['gnome-tweaks'], + ['gnome-weather'], + ['gnome-www-browser'], + ['gnroff'], + ['gold'], + ['google-chrome'], + ['google-chrome-stable'], + ['gouldtoppm'], + ['gpasswd'], + ['gpg'], + ['gpg-agent'], + ['gpg-connect-agent'], + ['gpg-error'], + ['gpg-wks-server'], + ['gpg-zip'], + ['gpg2'], + ['gpgconf'], + ['gpgme-json'], + ['gpgparsemail'], + ['gpgsm'], + ['gpgsplit'], + ['gpgv'], + ['gpgv2'], + ['gpic'], + ['gprof'], + ['gpu-manager'], + ['gr2fonttest'], + ['grep'], + ['grepdiff'], + ['gresource'], + ['greytiff'], + ['grilo-test-ui-0.3'], + ['grl-inspect-0.3'], + ['grl-launch-0.3'], + ['groff'], + ['grog'], + ['grops'], + ['grotty'], + ['groupadd'], + ['groupdel'], + ['groupmems'], + ['groupmod'], + ['groups'], + ['grpck'], + ['grpconv'], + ['grpunconv'], + ['grub-bios-setup'], + ['grub-editenv'], + ['grub-file'], + ['grub-fstest'], + ['grub-glue-efi'], + ['grub-install'], + ['grub-kbdcomp'], + ['grub-macbless'], + ['grub-menulst2cfg'], + ['grub-mkconfig'], + ['grub-mkdevicemap'], + ['grub-mkfont'], + ['grub-mkimage'], + ['grub-mklayout'], + ['grub-mknetdir'], + ['grub-mkpasswd-pbkdf2'], + ['grub-mkrelpath'], + ['grub-mkrescue'], + ['grub-mkstandalone'], + ['grub-mount'], + ['grub-ntldr-img'], + ['grub-probe'], + ['grub-reboot'], + ['grub-render-label'], + ['grub-script-check'], + ['grub-set-default'], + ['grub-syslinux2cfg'], + ['grub2-bios-setup'], + ['grub2-editenv'], + ['grub2-file'], + ['grub2-fstest'], + ['grub2-get-kernel-settings'], + ['grub2-glue-efi'], + ['grub2-install'], + ['grub2-kbdcomp'], + ['grub2-macbless'], + ['grub2-menulst2cfg'], + ['grub2-mkconfig'], + ['grub2-mkfont'], + ['grub2-mkimage'], + ['grub2-mklayout'], + ['grub2-mknetdir'], + ['grub2-mkpasswd-pbkdf2'], + ['grub2-mkrelpath'], + ['grub2-mkrescue'], + ['grub2-mkstandalone'], + ['grub2-ofpathname'], + ['grub2-probe'], + ['grub2-reboot'], + ['grub2-render-label'], + ['grub2-rpm-sort'], + ['grub2-script-check'], + ['grub2-set-bootflag'], + ['grub2-set-default'], + ['grub2-set-password'], + ['grub2-setpassword'], + ['grub2-sparc64-setup'], + ['grub2-switch-to-blscfg'], + ['grub2-syslinux2cfg'], + ['grubby'], + ['gs'], + ['gsbj'], + ['gsdj'], + ['gsdj500'], + ['gsettings'], + ['gsettings-data-convert'], + ['gsf-office-thumbnailer'], + ['gslj'], + ['gslp'], + ['gsnd'], + ['gsoelim'], + ['gsound-play'], + ['gssproxy'], + ['gst-device-monitor-1.0'], + ['gst-discoverer-1.0'], + ['gst-inspect-1.0'], + ['gst-launch-1.0'], + ['gst-play-1.0'], + ['gst-stats-1.0'], + ['gst-typefind-1.0'], + ['gstack'], + ['gstreamer-codec-install'], + ['gtar'], + ['gtbl'], + ['gtf'], + ['gtk-builder-tool'], + ['gtk-launch'], + ['gtk-query-immodules-2.0-64'], + ['gtk-query-immodules-3.0-64'], + ['gtk-query-settings'], + ['gtk-update-icon-cache'], + ['gtroff'], + ['guild'], + ['guile'], + ['guile-tools'], + ['guile2'], + ['guile2-tools'], + ['gunzip'], + ['gupnp-dlna-info-2.0'], + ['gupnp-dlna-ls-profiles-2.0'], + ['gvfs-cat'], + ['gvfs-copy'], + ['gvfs-info'], + ['gvfs-less'], + ['gvfs-ls'], + ['gvfs-mime'], + ['gvfs-mkdir'], + ['gvfs-monitor-dir'], + ['gvfs-monitor-file'], + ['gvfs-mount'], + ['gvfs-move'], + ['gvfs-open'], + ['gvfs-rename'], + ['gvfs-rm'], + ['gvfs-save'], + ['gvfs-set-attribute'], + ['gvfs-trash'], + ['gvfs-tree'], + ['gzexe'], + ['gzip'], + ['h2ph'], + ['h2xs'], + ['halt'], + ['handle-sshpw'], + ['hangul'], + ['hardened'], + ['hardlink'], + ['hash'], + ['hbpldecode'], + ['hciattach'], + ['hciconfig'], + ['hcidump'], + ['hcitool'], + ['hd'], + ['hdparm'], + ['head'], + ['help'], + ['helpztags'], + ['hex2hcd'], + ['hexdump'], + ['hfs-bless'], + ['highlight'], + ['hipercdecode'], + ['hipstopgm'], + ['history'], + ['host'], + ['hostid'], + ['hostname'], + ['hostnamectl'], + ['hp-align'], + ['hp-check'], + ['hp-clean'], + ['hp-colorcal'], + ['hp-config_usb_printer'], + ['hp-diagnose_plugin'], + ['hp-diagnose_queues'], + ['hp-doctor'], + ['hp-fab'], + ['hp-firmware'], + ['hp-info'], + ['hp-levels'], + ['hp-logcapture'], + ['hp-makeuri'], + ['hp-pkservice'], + ['hp-plugin'], + ['hp-plugin-ubuntu'], + ['hp-probe'], + ['hp-query'], + ['hp-scan'], + ['hp-sendfax'], + ['hp-setup'], + ['hp-testpage'], + ['hp-timedate'], + ['hp-unload'], + ['hpcups-update-ppds'], + ['hpijs'], + ['htcacheclean'], + ['htdbm'], + ['htdigest'], + ['htpasswd'], + ['httpd'], + ['httxt2dbm'], + ['hunspell'], + ['hwclock'], + ['hwe-support-status'], + ['hypervfcopyd'], + ['hypervkvpd'], + ['hypervvssd'], + ['i386'], + ['ibus'], + ['ibus-daemon'], + ['ibus-setup'], + ['ibus-table-createdb'], + ['iccdump'], + ['iccgamut'], + ['icclu'], + ['icctest'], + ['iceauth'], + ['ico'], + ['icontopbm'], + ['iconv'], + ['iconvconfig'], + ['id'], + ['identify'], + ['identify-im6'], + ['identify-im6.q16'], + ['idiag-socket-details'], + ['idn'], + ['iecset'], + ['if'], + ['ifcfg'], + ['ifconfig'], + ['ifdown'], + ['ifenslave'], + ['ifquery'], + ['ifrename'], + ['ifstat'], + ['ifup'], + ['iio-sensor-proxy'], + ['ijs_pxljr'], + ['ilbmtoppm'], + ['illumread'], + ['im-config'], + ['im-launch'], + ['imagetops'], + ['imgtoppm'], + ['implantisomd5'], + ['import'], + ['import-im6'], + ['import-im6.q16'], + ['in'], + ['info'], + ['infobrowser'], + ['infocmp'], + ['infotocap'], + ['init'], + ['inputattach'], + ['insmod'], + ['install'], + ['install-info'], + ['install-printerdriver'], + ['installkernel'], + ['instmodsh'], + ['instperf'], + ['intel-virtual-output'], + ['interdiff'], + ['invoke-rc.d'], + ['invprofcheck'], + ['ionice'], + ['ip'], + ['ip6tables'], + ['ip6tables-apply'], + ['ip6tables-legacy'], + ['ip6tables-legacy-restore'], + ['ip6tables-legacy-save'], + ['ip6tables-restore'], + ['ip6tables-save'], + ['ipcalc'], + ['ipcmk'], + ['ipcrm'], + ['ipcs'], + ['ipmaddr'], + ['ipod-read-sysinfo-extended'], + ['ipod-time-sync'], + ['ippfind'], + ['ippserver'], + ['ipptool'], + ['ippusbxd'], + ['ipset'], + ['iptables'], + ['iptables-apply'], + ['iptables-legacy'], + ['iptables-legacy-restore'], + ['iptables-legacy-save'], + ['iptables-restore'], + ['iptables-save'], + ['iptables-xml'], + ['iptc'], + ['iptstate'], + ['iptunnel'], + ['irqbalance'], + ['irqbalance-ui'], + ['isc-hmac-fixup'], + ['ischroot'], + ['iscsi-iname'], + ['iscsiadm'], + ['iscsid'], + ['iscsistart'], + ['iscsiuio'], + ['isdv4-serial-debugger'], + ['isdv4-serial-inputattach'], + ['iso-info'], + ['iso-read'], + ['isodebug'], + ['isodump'], + ['isohybrid'], + ['isoinfo'], + ['isosize'], + ['isovfy'], + ['ispell-autobuildhash'], + ['ispell-wrapper'], + ['iucode-tool'], + ['iucode_tool'], + ['iw'], + ['iwconfig'], + ['iwevent'], + ['iwgetid'], + ['iwlist'], + ['iwpriv'], + ['iwspy'], + ['jackd'], + ['jackrec'], + ['java'], + ['jimsh'], + ['jjs'], + ['jobs'], + ['join'], + ['journalctl'], + ['jpegtopnm'], + ['jpgicc'], + ['json_pp'], + ['json_reformat'], + ['json_verify'], + ['jwhois'], + ['kbd_mode'], + ['kbdinfo'], + ['kbdrate'], + ['kbxutil'], + ['kdumpctl'], + ['kernel-install'], + ['kerneloops'], + ['kerneloops-submit'], + ['kexec'], + ['key.dns_resolver'], + ['keyctl'], + ['keyring'], + ['keytool'], + ['kill'], + ['killall'], + ['killall5'], + ['kmod'], + ['kmodsign'], + ['kmodtool'], + ['kodak2ti3'], + ['kpartx'], + ['l'], + ['l.'], + ['l2ping'], + ['l2test'], + ['la'], + ['laptop-detect'], + ['last'], + ['lastb'], + ['lastcomm'], + ['lastlog'], + ['lavadecode'], + ['lcf'], + ['lchage'], + ['lchfn'], + ['lchsh'], + ['ld'], + ['ld.bfd'], + ['ld.gold'], + ['ldattach'], + ['ldconfig'], + ['ldconfig.real'], + ['ldd'], + ['leaftoppm'], + ['less'], + ['lessecho'], + ['lessfile'], + ['lesskey'], + ['lesspipe'], + ['lesspipe.sh'], + ['let'], + ['lexgrog'], + ['lgroupadd'], + ['lgroupdel'], + ['lgroupmod'], + ['libieee1284_test'], + ['libinput'], + ['libnetcfg'], + ['libreoffice'], + ['libtar'], + ['libvirtd'], + ['libwacom-list-local-devices'], + ['lid'], + ['link'], + ['linkicc'], + ['lintian'], + ['lintian-info'], + ['lintian-lab-tool'], + ['linux-boot-prober'], + ['linux-check-removal'], + ['linux-update-symlinks'], + ['linux-version'], + ['linux32'], + ['linux64'], + ['lispmtopgm'], + ['listres'], + ['liveinst'], + ['ll'], + ['lldpad'], + ['lldptool'], + ['ln'], + ['lnewusers'], + ['lnstat'], + ['load_policy'], + ['loadkeys'], + ['loadunimap'], + ['local'], + ['localc'], + ['locale'], + ['locale-check'], + ['locale-gen'], + ['localectl'], + ['localedef'], + ['locate'], + ['lockdev'], + ['lodraw'], + ['loffice'], + ['lofromtemplate'], + ['logger'], + ['login'], + ['loginctl'], + ['logname'], + ['logout'], + ['logresolve'], + ['logrotate'], + ['logsave'], + ['loimpress'], + ['lomath'], + ['look'], + ['lorder'], + ['losetup'], + ['loweb'], + ['lowntfs-3g'], + ['lowriter'], + ['lp'], + ['lp.cups'], + ['lp_solve'], + ['lpadmin'], + ['lpasswd'], + ['lpc'], + ['lpc.cups'], + ['lpinfo'], + ['lpmove'], + ['lpoptions'], + ['lpq'], + ['lpq.cups'], + ['lpr'], + ['lpr.cups'], + ['lprm'], + ['lprm.cups'], + ['lpstat'], + ['lpstat.cups'], + ['ls'], + ['lsattr'], + ['lsb_release'], + ['lsblk'], + ['lscpu'], + ['lsdiff'], + ['lshw'], + ['lsinitramfs'], + ['lsinitrd'], + ['lsipc'], + ['lslocks'], + ['lslogins'], + ['lsmem'], + ['lsmod'], + ['lsns'], + ['lsof'], + ['lspci'], + ['lspcmcia'], + ['lspgpot'], + ['lsusb'], + ['lsusb.py'], + ['ltrace'], + ['lua'], + ['luac'], + ['luit'], + ['luseradd'], + ['luserdel'], + ['lusermod'], + ['lvchange'], + ['lvconvert'], + ['lvcreate'], + ['lvdisplay'], + ['lvextend'], + ['lvm'], + ['lvmconf'], + ['lvmconfig'], + ['lvmdiskscan'], + ['lvmdump'], + ['lvmetad'], + ['lvmpolld'], + ['lvmsadc'], + ['lvmsar'], + ['lvreduce'], + ['lvremove'], + ['lvrename'], + ['lvresize'], + ['lvs'], + ['lvscan'], + ['lwp-download'], + ['lwp-dump'], + ['lwp-mirror'], + ['lwp-request'], + ['lxpolkit'], + ['lz'], + ['lz4'], + ['lz4c'], + ['lz4cat'], + ['lzcat'], + ['lzcmp'], + ['lzdiff'], + ['lzegrep'], + ['lzfgrep'], + ['lzgrep'], + ['lzless'], + ['lzma'], + ['lzmainfo'], + ['lzmore'], + ['lzop'], + ['m17n-conv'], + ['m2300w'], + ['m2300w-wrapper'], + ['m2400w'], + ['m4'], + ['mac2unix'], + ['machinectl'], + ['macptopbm'], + ['mail'], + ['mailq'], + ['mailx'], + ['make'], + ['make-bcache'], + ['make-dummy-cert'], + ['make-ssl-cert'], + ['makedb'], + ['makedeltarpm'], + ['makedumpfile'], + ['man'], + ['mandb'], + ['manpath'], + ['mapfile'], + ['mapscrn'], + ['matchpathcon'], + ['mattrib'], + ['mawk'], + ['mbadblocks'], + ['mbim-network'], + ['mbimcli'], + ['mcat'], + ['mcd'], + ['mcelog'], + ['mcheck'], + ['mclasserase'], + ['mcomp'], + ['mcookie'], + ['mcopy'], + ['mcpp'], + ['md5sum'], + ['md5sum.textutils'], + ['mdadm'], + ['mdatopbm'], + ['mdel'], + ['mdeltree'], + ['mdig'], + ['mdir'], + ['mdmon'], + ['mdu'], + ['memdiskfind'], + ['memtest-setup'], + ['mergerepo'], + ['mergerepo_c'], + ['mesg'], + ['meshctl'], + ['mformat'], + ['mgrtopbm'], + ['migrate-pubring-from-classic-gpg'], + ['mii-diag'], + ['mii-tool'], + ['mimeopen'], + ['mimetype'], + ['min12xxw'], + ['minfo'], + ['mk_modmap'], + ['mkdict'], + ['mkdir'], + ['mkdosfs'], + ['mkdumprd'], + ['mke2fs'], + ['mkfifo'], + ['mkfontdir'], + ['mkfontscale'], + ['mkfs'], + ['mkfs.bfs'], + ['mkfs.btrfs'], + ['mkfs.cramfs'], + ['mkfs.ext2'], + ['mkfs.ext3'], + ['mkfs.ext4'], + ['mkfs.fat'], + ['mkfs.hfsplus'], + ['mkfs.minix'], + ['mkfs.msdos'], + ['mkfs.ntfs'], + ['mkfs.vfat'], + ['mkfs.xfs'], + ['mkhomedir_helper'], + ['mkhybrid'], + ['mkinitramfs'], + ['mkinitrd'], + ['mkisofs'], + ['mklost+found'], + ['mkmanifest'], + ['mknod'], + ['mkntfs'], + ['mkrfc2734'], + ['mkroot'], + ['mksquashfs'], + ['mkswap'], + ['mktemp'], + ['mkzftree'], + ['mlabel'], + ['mlocate'], + ['mmc-tool'], + ['mmcli'], + ['mmd'], + ['mmount'], + ['mmove'], + ['modifyrepo'], + ['modifyrepo_c'], + ['modinfo'], + ['modprobe'], + ['module'], + ['modulecmd'], + ['modulemd-validator-v1'], + ['mogrify'], + ['mogrify-im6'], + ['mogrify-im6.q16'], + ['mokutil'], + ['monitor-sensor'], + ['montage'], + ['montage-im6'], + ['montage-im6.q16'], + ['more'], + ['mount'], + ['mount.cifs'], + ['mount.fuse'], + ['mount.glusterfs'], + ['mount.lowntfs-3g'], + ['mount.nfs'], + ['mount.nfs4'], + ['mount.ntfs'], + ['mount.ntfs-3g'], + ['mount.ntfs-fuse'], + ['mount.zfs'], + ['mountpoint'], + ['mountstats'], + ['mousetweaks'], + ['mpage'], + ['mpartition'], + ['mpathconf'], + ['mpathpersist'], + ['mppcheck'], + ['mpplu'], + ['mppprof'], + ['mpris-proxy'], + ['mrd'], + ['mren'], + ['mscompress'], + ['msexpand'], + ['msgattrib'], + ['msgcat'], + ['msgcmp'], + ['msgcomm'], + ['msgconv'], + ['msgen'], + ['msgexec'], + ['msgfilter'], + ['msgfmt'], + ['msggrep'], + ['msginit'], + ['msgmerge'], + ['msgunfmt'], + ['msguniq'], + ['mshortname'], + ['mshowfat'], + ['mt'], + ['mt-gnu'], + ['mtools'], + ['mtoolstest'], + ['mtr'], + ['mtr-packet'], + ['mtvtoppm'], + ['mtype'], + ['multipath'], + ['multipathd'], + ['mutter'], + ['mv'], + ['mvxattr'], + ['mxtar'], + ['mzip'], + ['nail'], + ['named-checkzone'], + ['named-compilezone'], + ['namei'], + ['nameif'], + ['nano'], + ['nautilus'], + ['nautilus-autorun-software'], + ['nautilus-desktop'], + ['nautilus-sendto'], + ['nawk'], + ['nc'], + ['nc.openbsd'], + ['ncal'], + ['ncat'], + ['ndctl'], + ['ndptool'], + ['neotoppm'], + ['neqn'], + ['netcat'], + ['netkit-ftp'], + ['netplan'], + ['netstat'], + ['nettest'], + ['networkctl'], + ['networkd-dispatcher'], + ['new-kernel-pkg'], + ['newgidmap'], + ['newgrp'], + ['newuidmap'], + ['newusers'], + ['nf-ct-add'], + ['nf-ct-list'], + ['nf-exp-add'], + ['nf-exp-delete'], + ['nf-exp-list'], + ['nf-log'], + ['nf-monitor'], + ['nf-queue'], + ['nfnl_osf'], + ['nfsconf'], + ['nfsdcltrack'], + ['nfsidmap'], + ['nfsiostat'], + ['nfsstat'], + ['nft'], + ['ngettext'], + ['nice'], + ['nisdomainname'], + ['nl'], + ['nl-addr-add'], + ['nl-addr-delete'], + ['nl-addr-list'], + ['nl-class-add'], + ['nl-class-delete'], + ['nl-class-list'], + ['nl-classid-lookup'], + ['nl-cls-add'], + ['nl-cls-delete'], + ['nl-cls-list'], + ['nl-fib-lookup'], + ['nl-link-enslave'], + ['nl-link-ifindex2name'], + ['nl-link-list'], + ['nl-link-name2ifindex'], + ['nl-link-release'], + ['nl-link-set'], + ['nl-link-stats'], + ['nl-list-caches'], + ['nl-list-sockets'], + ['nl-monitor'], + ['nl-neigh-add'], + ['nl-neigh-delete'], + ['nl-neigh-list'], + ['nl-neightbl-list'], + ['nl-pktloc-lookup'], + ['nl-qdisc-add'], + ['nl-qdisc-delete'], + ['nl-qdisc-list'], + ['nl-route-add'], + ['nl-route-delete'], + ['nl-route-get'], + ['nl-route-list'], + ['nl-rule-list'], + ['nl-tctree-list'], + ['nl-util-addr'], + ['nm'], + ['nm-applet'], + ['nm-connection-editor'], + ['nm-online'], + ['nmblookup'], + ['nmcli'], + ['nmtui'], + ['nmtui-connect'], + ['nmtui-edit'], + ['nmtui-hostname'], + ['node'], + ['nohup'], + ['nologin'], + ['notify-send'], + ['npm'], + ['nproc'], + ['npx'], + ['nroff'], + ['nsec3hash'], + ['nsenter'], + ['nslookup'], + ['nstat'], + ['nsupdate'], + ['ntfs-3g'], + ['ntfs-3g.probe'], + ['ntfscat'], + ['ntfsck'], + ['ntfsclone'], + ['ntfscluster'], + ['ntfscmp'], + ['ntfscp'], + ['ntfsdecrypt'], + ['ntfsdump_logfile'], + ['ntfsfallocate'], + ['ntfsfix'], + ['ntfsinfo'], + ['ntfslabel'], + ['ntfsls'], + ['ntfsmftalloc'], + ['ntfsmount'], + ['ntfsmove'], + ['ntfsrecover'], + ['ntfsresize'], + ['ntfssecaudit'], + ['ntfstruncate'], + ['ntfsundelete'], + ['ntfsusermap'], + ['ntfswipe'], + ['numad'], + ['numfmt'], + ['nvidia-bug-report.sh'], + ['nvidia-detector'], + ['nvidia-settings'], + ['oLschema2ldif'], + ['oakdecode'], + ['obexctl'], + ['objcopy'], + ['objdump'], + ['oclock'], + ['od'], + ['oddjob_request'], + ['oddjobd'], + ['oeminst'], + ['oldrdist'], + ['on_ac_power'], + ['oocalc'], + ['oodraw'], + ['ooffice'], + ['ooimpress'], + ['oomath'], + ['ooviewdoc'], + ['oowriter'], + ['open'], + ['openconnect'], + ['openoffice.org'], + ['openssl'], + ['openvpn'], + ['openvt'], + ['opldecode'], + ['optirun'], + ['orc-bugreport'], + ['orca'], + ['orca-dm-wrapper'], + ['os-prober'], + ['osinfo-db-export'], + ['osinfo-db-import'], + ['osinfo-db-path'], + ['osinfo-db-validate'], + ['osinfo-detect'], + ['osinfo-install-script'], + ['osinfo-query'], + ['ostree'], + ['ownership'], + ['p11-kit'], + ['pacat'], + ['pack200'], + ['packer'], + ['pacmd'], + ['pactl'], + ['padsp'], + ['padsp-32'], + ['pager'], + ['palmtopnm'], + ['pam-auth-update'], + ['pam_console_apply'], + ['pam_extrausers_chkpwd'], + ['pam_extrausers_update'], + ['pam_getenv'], + ['pam_tally'], + ['pam_tally2'], + ['pam_timestamp_check'], + ['pamcut'], + ['pamdeinterlace'], + ['pamdice'], + ['pamfile'], + ['pamoil'], + ['pamon'], + ['pamstack'], + ['pamstretch'], + ['pamstretch-gen'], + ['panelctl'], + ['pango-list'], + ['pango-view'], + ['paperconf'], + ['paperconfig'], + ['paplay'], + ['paps'], + ['parec'], + ['parecord'], + ['parsechangelog'], + ['parted'], + ['partprobe'], + ['partx'], + ['passwd'], + ['paste'], + ['pasuspender'], + ['patch'], + ['pathchk'], + ['pathplot'], + ['pax'], + ['pax11publish'], + ['pbmclean'], + ['pbmlife'], + ['pbmmake'], + ['pbmmask'], + ['pbmpage'], + ['pbmpscale'], + ['pbmreduce'], + ['pbmtext'], + ['pbmtextps'], + ['pbmto10x'], + ['pbmtoascii'], + ['pbmtoatk'], + ['pbmtobbnbg'], + ['pbmtocmuwm'], + ['pbmtoepsi'], + ['pbmtoepson'], + ['pbmtog3'], + ['pbmtogem'], + ['pbmtogo'], + ['pbmtoicon'], + ['pbmtolj'], + ['pbmtomacp'], + ['pbmtomda'], + ['pbmtomgr'], + ['pbmtonokia'], + ['pbmtopgm'], + ['pbmtopi3'], + ['pbmtoplot'], + ['pbmtoppa'], + ['pbmtopsg3'], + ['pbmtoptx'], + ['pbmtowbmp'], + ['pbmtox10bm'], + ['pbmtoxbm'], + ['pbmtoybm'], + ['pbmtozinc'], + ['pbmupc'], + ['pccardctl'], + ['pcimodules'], + ['pcxtoppm'], + ['pdata_tools'], + ['pdb3'], + ['pdb3.6'], + ['pdf2dsc'], + ['pdf2ps'], + ['pdfdetach'], + ['pdffonts'], + ['pdfimages'], + ['pdfinfo'], + ['pdfseparate'], + ['pdfsig'], + ['pdftocairo'], + ['pdftohtml'], + ['pdftoppm'], + ['pdftops'], + ['pdftotext'], + ['pdfunite'], + ['peekfd'], + ['perl'], + ['perl5.26-x86_64-linux-gnu'], + ['perl5.26.2'], + ['perl5.28.1'], + ['perlbug'], + ['perldoc'], + ['perli11ndoc'], + ['perlivp'], + ['perlthanks'], + ['pf2afm'], + ['pfbtopfa'], + ['pftp'], + ['pgmbentley'], + ['pgmcrater'], + ['pgmedge'], + ['pgmenhance'], + ['pgmhist'], + ['pgmkernel'], + ['pgmnoise'], + ['pgmnorm'], + ['pgmoil'], + ['pgmramp'], + ['pgmslice'], + ['pgmtexture'], + ['pgmtofs'], + ['pgmtolispm'], + ['pgmtopbm'], + ['pgmtoppm'], + ['pgrep'], + ['pi1toppm'], + ['pi3topbm'], + ['pic'], + ['pico'], + ['piconv'], + ['pidof'], + ['pigz'], + ['pinentry'], + ['pinentry-curses'], + ['pinentry-gnome3'], + ['pinentry-gtk'], + ['pinentry-gtk-2'], + ['pinentry-x11'], + ['pinfo'], + ['ping'], + ['ping4'], + ['ping6'], + ['pinky'], + ['pip-3'], + ['pip-3.7'], + ['pip3'], + ['pip3.7'], + ['pipewire'], + ['pitchplay'], + ['pivot_root'], + ['pjtoppm'], + ['pkaction'], + ['pkcheck'], + ['pkcon'], + ['pkexec'], + ['pkg-config'], + ['pkgconf'], + ['pkill'], + ['pkla-admin-identities'], + ['pkla-check-authorization'], + ['pkmon'], + ['pkttyagent'], + ['pl2pm'], + ['pldd'], + ['plipconfig'], + ['plistutil'], + ['plog'], + ['pluginviewer'], + ['plymouth'], + ['plymouth-set-default-theme'], + ['plymouthd'], + ['pmap'], + ['pngtopnm'], + ['pnm2ppa'], + ['pnmalias'], + ['pnmarith'], + ['pnmcat'], + ['pnmcolormap'], + ['pnmcomp'], + ['pnmconvol'], + ['pnmcrop'], + ['pnmcut'], + ['pnmdepth'], + ['pnmenlarge'], + ['pnmfile'], + ['pnmflip'], + ['pnmgamma'], + ['pnmhisteq'], + ['pnmhistmap'], + ['pnmindex'], + ['pnminterp'], + ['pnminterp-gen'], + ['pnminvert'], + ['pnmmargin'], + ['pnmmontage'], + ['pnmnlfilt'], + ['pnmnoraw'], + ['pnmnorm'], + ['pnmpad'], + ['pnmpaste'], + ['pnmpsnr'], + ['pnmquant'], + ['pnmremap'], + ['pnmrotate'], + ['pnmscale'], + ['pnmscalefixed'], + ['pnmshear'], + ['pnmsmooth'], + ['pnmsplit'], + ['pnmtile'], + ['pnmtoddif'], + ['pnmtofiasco'], + ['pnmtofits'], + ['pnmtojpeg'], + ['pnmtopalm'], + ['pnmtoplainpnm'], + ['pnmtopng'], + ['pnmtops'], + ['pnmtorast'], + ['pnmtorle'], + ['pnmtosgi'], + ['pnmtosir'], + ['pnmtotiff'], + ['pnmtotiffcmyk'], + ['pnmtoxwd'], + ['pod2html'], + ['pod2man'], + ['pod2text'], + ['pod2usage'], + ['podchecker'], + ['podselect'], + ['poff'], + ['pon'], + ['popcon-largest-unused'], + ['popd'], + ['popularity-contest'], + ['post-grohtml'], + ['poweroff'], + ['ppdc'], + ['ppdhtml'], + ['ppdi'], + ['ppdmerge'], + ['ppdpo'], + ['pphs'], + ['ppm3d'], + ['ppmbrighten'], + ['ppmchange'], + ['ppmcie'], + ['ppmcolormask'], + ['ppmcolors'], + ['ppmdim'], + ['ppmdist'], + ['ppmdither'], + ['ppmfade'], + ['ppmflash'], + ['ppmforge'], + ['ppmhist'], + ['ppmlabel'], + ['ppmmake'], + ['ppmmix'], + ['ppmnorm'], + ['ppmntsc'], + ['ppmpat'], + ['ppmquant'], + ['ppmquantall'], + ['ppmqvga'], + ['ppmrainbow'], + ['ppmrelief'], + ['ppmshadow'], + ['ppmshift'], + ['ppmspread'], + ['ppmtoacad'], + ['ppmtobmp'], + ['ppmtoeyuv'], + ['ppmtogif'], + ['ppmtoicr'], + ['ppmtoilbm'], + ['ppmtojpeg'], + ['ppmtoleaf'], + ['ppmtolj'], + ['ppmtomap'], + ['ppmtomitsu'], + ['ppmtompeg'], + ['ppmtoneo'], + ['ppmtopcx'], + ['ppmtopgm'], + ['ppmtopi1'], + ['ppmtopict'], + ['ppmtopj'], + ['ppmtopuzz'], + ['ppmtorgb3'], + ['ppmtosixel'], + ['ppmtotga'], + ['ppmtouil'], + ['ppmtowinicon'], + ['ppmtoxpm'], + ['ppmtoyuv'], + ['ppmtoyuvsplit'], + ['ppmtv'], + ['ppp-watch'], + ['pppconfig'], + ['pppd'], + ['pppdump'], + ['pppoe'], + ['pppoe-connect'], + ['pppoe-discovery'], + ['pppoe-relay'], + ['pppoe-server'], + ['pppoe-setup'], + ['pppoe-sniff'], + ['pppoe-start'], + ['pppoe-status'], + ['pppoe-stop'], + ['pppoeconf'], + ['pppstats'], + ['pptp'], + ['pptpsetup'], + ['pr'], + ['pre-grohtml'], + ['precat'], + ['preconv'], + ['preunzip'], + ['prezip'], + ['prezip-bin'], + ['primusrun'], + ['print'], + ['printafm'], + ['printcal'], + ['printenv'], + ['printer-profile'], + ['printerbanner'], + ['printf'], + ['printtarg'], + ['prlimit'], + ['profcheck'], + ['prove'], + ['prtstat'], + ['ps'], + ['ps2ascii'], + ['ps2epsi'], + ['ps2pdf'], + ['ps2pdf12'], + ['ps2pdf13'], + ['ps2pdf14'], + ['ps2pdfwr'], + ['ps2ps'], + ['ps2ps2'], + ['ps2txt'], + ['psfaddtable'], + ['psfgettable'], + ['psfstriptable'], + ['psfxtable'], + ['psicc'], + ['psidtopgm'], + ['pslog'], + ['pstack'], + ['pstopnm'], + ['pstree'], + ['pstree.x11'], + ['ptar'], + ['ptardiff'], + ['ptargrep'], + ['ptx'], + ['pulseaudio'], + ['pushd'], + ['pvchange'], + ['pvck'], + ['pvcreate'], + ['pvdisplay'], + ['pvmove'], + ['pvremove'], + ['pvresize'], + ['pvs'], + ['pvscan'], + ['pwck'], + ['pwconv'], + ['pwd'], + ['pwdx'], + ['pwhistory_helper'], + ['pwmake'], + ['pwqcheck'], + ['pwqgen'], + ['pwscore'], + ['pwunconv'], + ['py3clean'], + ['py3compile'], + ['py3versions'], + ['pydoc3'], + ['pydoc3.6'], + ['pydoc3.7'], + ['pygettext3'], + ['pygettext3.6'], + ['pyjwt3'], + ['python3'], + ['python3-chardetect'], + ['python3-coverage'], + ['python3-mako-render'], + ['python3-pyinotify'], + ['python3.6'], + ['python3.6m'], + ['python3.7'], + ['python3.7m'], + ['python3m'], + ['pyvenv'], + ['pyvenv-3.7'], + ['pzstd'], + ['qb-blackbox'], + ['qdbus'], + ['qemu-ga'], + ['qemu-img'], + ['qemu-io'], + ['qemu-keymap'], + ['qemu-kvm'], + ['qemu-nbd'], + ['qemu-pr-helper'], + ['qemu-system-i386'], + ['qemu-system-x86_64'], + ['qmi-firmware-update'], + ['qmi-network'], + ['qmicli'], + ['qpdf'], + ['qpdldecode'], + ['qrttoppm'], + ['quirks-handler'], + ['quot'], + ['quota'], + ['quotacheck'], + ['quotaoff'], + ['quotaon'], + ['quotastats'], + ['quotasync'], + ['quote'], + ['quote_readline'], + ['radvd'], + ['radvdump'], + ['raid-check'], + ['ranlib'], + ['rapper'], + ['rasttopnm'], + ['raw'], + ['rawtopgm'], + ['rawtoppm'], + ['rb'], + ['rbash'], + ['rcp'], + ['rctest'], + ['rdfproc'], + ['rdisc'], + ['rdist'], + ['rdistd'], + ['rdma'], + ['rdma-ndd'], + ['read'], + ['readarray'], + ['readelf'], + ['readlink'], + ['readmult'], + ['readonly'], + ['readprofile'], + ['realm'], + ['realpath'], + ['reboot'], + ['recode-sr-latin'], + ['recountdiff'], + ['red'], + ['rediff'], + ['redland-db-upgrade'], + ['refine'], + ['regdbdump'], + ['regdiff'], + ['regpatch'], + ['regshell'], + ['regtree'], + ['reject'], + ['remmina'], + ['remmina-gnome'], + ['remove-default-ispell'], + ['remove-default-wordlist'], + ['remove-shell'], + ['rename'], + ['rename.ul'], + ['rendercheck'], + ['renew-dummy-cert'], + ['renice'], + ['report-cli'], + ['report-gtk'], + ['reporter-bugzilla'], + ['reporter-kerneloops'], + ['reporter-print'], + ['reporter-systemd-journal'], + ['reporter-upload'], + ['reporter-ureport'], + ['repquota'], + ['request-key'], + ['reset'], + ['resize2fs'], + ['resizecons'], + ['resizepart'], + ['resolvconf'], + ['resolvectl'], + ['restorecon'], + ['restorecon_xattr'], + ['return'], + ['rev'], + ['revfix'], + ['rfcomm'], + ['rfkill'], + ['rgb3toppm'], + ['rgrep'], + ['rhythmbox'], + ['rhythmbox-client'], + ['rletopnm'], + ['rlogin'], + ['rm'], + ['rmdir'], + ['rmid'], + ['rmiregistry'], + ['rmmod'], + ['rmt'], + ['rmt-tar'], + ['rnano'], + ['rngd'], + ['rngtest'], + ['rofiles-fuse'], + ['roqet'], + ['rotatelogs'], + ['route'], + ['routef'], + ['routel'], + ['rpc.gssd'], + ['rpc.idmapd'], + ['rpc.mountd'], + ['rpc.nfsd'], + ['rpc.statd'], + ['rpcbind'], + ['rpcclient'], + ['rpcdebug'], + ['rpcinfo'], + ['rpm'], + ['rpm2archive'], + ['rpm2cpio'], + ['rpmargs'], + ['rpmbuild'], + ['rpmdb'], + ['rpmdev-bumpspec'], + ['rpmdev-checksig'], + ['rpmdev-cksum'], + ['rpmdev-diff'], + ['rpmdev-extract'], + ['rpmdev-md5'], + ['rpmdev-newinit'], + ['rpmdev-newspec'], + ['rpmdev-packager'], + ['rpmdev-rmdevelrpms'], + ['rpmdev-setuptree'], + ['rpmdev-sha1'], + ['rpmdev-sha224'], + ['rpmdev-sha256'], + ['rpmdev-sha384'], + ['rpmdev-sha512'], + ['rpmdev-sort'], + ['rpmdev-sum'], + ['rpmdev-vercmp'], + ['rpmdev-wipetree'], + ['rpmdumpheader'], + ['rpmelfsym'], + ['rpmfile'], + ['rpminfo'], + ['rpmkeys'], + ['rpmls'], + ['rpmpeek'], + ['rpmquery'], + ['rpmsodiff'], + ['rpmsoname'], + ['rpmspec'], + ['rpmverify'], + ['rsh'], + ['rstart'], + ['rstartd'], + ['rsync'], + ['rsyslogd'], + ['rtacct'], + ['rtcwake'], + ['rtkitctl'], + ['rtmon'], + ['rtpr'], + ['rtstat'], + ['run-mailcap'], + ['run-on-binaries-in'], + ['run-parts'], + ['run-with-aspell'], + ['runcon'], + ['runlevel'], + ['runuser'], + ['rvi'], + ['rview'], + ['rx'], + ['rxe_cfg'], + ['rygel'], + ['rygel-preferences'], + ['rz'], + ['sa'], + ['samba-regedit'], + ['sandbox'], + ['sane-find-scanner'], + ['saned'], + ['saslauthd'], + ['sasldblistusers2'], + ['saslpasswd2'], + ['satyr'], + ['savelog'], + ['sb'], + ['sbattach'], + ['sbcdec'], + ['sbcenc'], + ['sbcinfo'], + ['sbigtopgm'], + ['sbkeysync'], + ['sbsiglist'], + ['sbsign'], + ['sbvarsign'], + ['sbverify'], + ['scanimage'], + ['scanin'], + ['scl'], + ['scl_enabled'], + ['scl_source'], + ['scp'], + ['scp-dbus-service'], + ['screendump'], + ['script'], + ['scriptreplay'], + ['sctp_darn'], + ['sctp_status'], + ['sctp_test'], + ['sdiff'], + ['sdptool'], + ['seahorse'], + ['secon'], + ['secret-tool'], + ['sed'], + ['sedismod'], + ['sedispol'], + ['see'], + ['sefcontext_compile'], + ['selabel_digest'], + ['selabel_lookup'], + ['selabel_lookup_best_match'], + ['selabel_partial_match'], + ['select'], + ['select-default-ispell'], + ['select-default-iwrap'], + ['select-default-wordlist'], + ['select-editor'], + ['selinux_check_access'], + ['selinuxconlist'], + ['selinuxdefcon'], + ['selinuxenabled'], + ['selinuxexeccon'], + ['semanage'], + ['semodule'], + ['semodule_expand'], + ['semodule_link'], + ['semodule_package'], + ['semodule_unpackage'], + ['sendiso'], + ['sendmail'], + ['sensible-browser'], + ['sensible-editor'], + ['sensible-pager'], + ['seq'], + ['service'], + ['session-migration'], + ['sessreg'], + ['sestatus'], + ['set'], + ['setarch'], + ['setcap'], + ['setcifsacl'], + ['setenforce'], + ['setfacl'], + ['setfattr'], + ['setfiles'], + ['setfont'], + ['setkeycodes'], + ['setleds'], + ['setlogcons'], + ['setmetamode'], + ['setpci'], + ['setpriv'], + ['setquota'], + ['setregdomain'], + ['setsebool'], + ['setsid'], + ['setterm'], + ['setup-nsssysinit'], + ['setup-nsssysinit.sh'], + ['setupcon'], + ['setvesablank'], + ['setvtrgb'], + ['setxkbmap'], + ['sfdisk'], + ['sftp'], + ['sg'], + ['sgdisk'], + ['sgitopnm'], + ['sgpio'], + ['sh'], + ['sh.distrib'], + ['sha1hmac'], + ['sha1sum'], + ['sha224hmac'], + ['sha224sum'], + ['sha256hmac'], + ['sha256sum'], + ['sha384hmac'], + ['sha384sum'], + ['sha512hmac'], + ['sha512sum'], + ['shadowconfig'], + ['sharesec'], + ['shasum'], + ['sheep'], + ['sheepfs'], + ['shepherd'], + ['shift'], + ['shopt'], + ['shotwell'], + ['showconsolefont'], + ['showkey'], + ['showmount'], + ['showrgb'], + ['shred'], + ['shuf'], + ['shutdown'], + ['simple-scan'], + ['simpprof'], + ['sirtopnm'], + ['size'], + ['skdump'], + ['skill'], + ['sktest'], + ['slabtop'], + ['slattach'], + ['sldtoppm'], + ['sleep'], + ['slogin'], + ['slxdecode'], + ['sm-notify'], + ['smbcacls'], + ['smbclient'], + ['smbcquotas'], + ['smbget'], + ['smbspool'], + ['smbtar'], + ['smbtree'], + ['smproxy'], + ['snap'], + ['snapctl'], + ['snapfuse'], + ['sndfile-resample'], + ['snice'], + ['soelim'], + ['soffice'], + ['software-properties-gtk'], + ['sol'], + ['sort'], + ['sosreport'], + ['sotruss'], + ['soundstretch'], + ['source'], + ['spax'], + ['spctoppm'], + ['spd-conf'], + ['spd-say'], + ['speak-ng'], + ['speaker-test'], + ['spec2cie'], + ['specplot'], + ['spectool'], + ['speech-dispatcher'], + ['spellintian'], + ['spellout'], + ['spice-vdagent'], + ['spice-vdagentd'], + ['splain'], + ['split'], + ['splitdiff'], + ['splitfont'], + ['splitti3'], + ['spotread'], + ['sprof'], + ['sputoppm'], + ['sqlite3'], + ['sqliterepo_c'], + ['ss'], + ['ssh'], + ['ssh-add'], + ['ssh-agent'], + ['ssh-argv0'], + ['ssh-copy-id'], + ['ssh-keygen'], + ['ssh-keyscan'], + ['sshd'], + ['sshpass'], + ['sss_cache'], + ['sss_ssh_authorizedkeys'], + ['sss_ssh_knownhostsproxy'], + ['sssd'], + ['st4topgm'], + ['start-pulseaudio-x11'], + ['start-statd'], + ['start-stop-daemon'], + ['startx'], + ['stat'], + ['static-sh'], + ['stdbuf'], + ['strace'], + ['strace-log-merge'], + ['stream'], + ['stream-im6'], + ['stream-im6.q16'], + ['strings'], + ['strip'], + ['stty'], + ['stunbdc'], + ['stund'], + ['su'], + ['sudo'], + ['sudoedit'], + ['sudoreplay'], + ['sulogin'], + ['sum'], + ['sushi'], + ['suspend'], + ['swaplabel'], + ['swapoff'], + ['swapon'], + ['switch_root'], + ['switcheroo-control'], + ['switchml'], + ['sx'], + ['symcryptrun'], + ['symlinks'], + ['sync'], + ['synthcal'], + ['synthread'], + ['sysctl'], + ['syslinux'], + ['syslinux-legacy'], + ['system-config-abrt'], + ['system-config-printer'], + ['system-config-printer-applet'], + ['systemctl'], + ['systemd'], + ['systemd-analyze'], + ['systemd-ask-password'], + ['systemd-cat'], + ['systemd-cgls'], + ['systemd-cgtop'], + ['systemd-delta'], + ['systemd-detect-virt'], + ['systemd-escape'], + ['systemd-firstboot'], + ['systemd-hwdb'], + ['systemd-inhibit'], + ['systemd-machine-id-setup'], + ['systemd-mount'], + ['systemd-notify'], + ['systemd-nspawn'], + ['systemd-path'], + ['systemd-resolve'], + ['systemd-run'], + ['systemd-socket-activate'], + ['systemd-stdio-bridge'], + ['systemd-sysusers'], + ['systemd-tmpfiles'], + ['systemd-tty-ask-password-agent'], + ['systemd-umount'], + ['sz'], + ['t1ascii'], + ['t1asm'], + ['t1binary'], + ['t1disasm'], + ['t1mac'], + ['t1unmac'], + ['tabs'], + ['tac'], + ['tail'], + ['tar'], + ['tarcat'], + ['targen'], + ['taskset'], + ['tbl'], + ['tc'], + ['tcbench'], + ['tclsh'], + ['tclsh8.6'], + ['tcpdump'], + ['tcpslice'], + ['tcptraceroute'], + ['tcsd'], + ['teamd'], + ['teamdctl'], + ['teamnl'], + ['tee'], + ['telinit'], + ['telnet'], + ['telnet.netkit'], + ['tempfile'], + ['test'], + ['testlibraw'], + ['testsaslauthd'], + ['tgatoppm'], + ['tgz'], + ['then'], + ['thermald'], + ['thin_check'], + ['thin_delta'], + ['thin_dump'], + ['thin_ls'], + ['thin_metadata_size'], + ['thin_repair'], + ['thin_restore'], + ['thin_rmap'], + ['thin_trim'], + ['thinkjettopbm'], + ['thunderbird'], + ['tic'], + ['tiffgamut'], + ['tifftopnm'], + ['tificc'], + ['time'], + ['timedatectl'], + ['timedatex'], + ['timeout'], + ['times'], + ['tipc'], + ['tload'], + ['tmux'], + ['toe'], + ['top'], + ['totem'], + ['totem-video-thumbnailer'], + ['touch'], + ['tpm2-abrmd'], + ['tpm2_activatecredential'], + ['tpm2_certify'], + ['tpm2_create'], + ['tpm2_createpolicy'], + ['tpm2_createprimary'], + ['tpm2_dictionarylockout'], + ['tpm2_encryptdecrypt'], + ['tpm2_evictcontrol'], + ['tpm2_getcap'], + ['tpm2_getmanufec'], + ['tpm2_getpubak'], + ['tpm2_getpubek'], + ['tpm2_getrandom'], + ['tpm2_hash'], + ['tpm2_hmac'], + ['tpm2_listpersistent'], + ['tpm2_load'], + ['tpm2_loadexternal'], + ['tpm2_makecredential'], + ['tpm2_nvdefine'], + ['tpm2_nvlist'], + ['tpm2_nvread'], + ['tpm2_nvreadlock'], + ['tpm2_nvrelease'], + ['tpm2_nvwrite'], + ['tpm2_pcrevent'], + ['tpm2_pcrextend'], + ['tpm2_pcrlist'], + ['tpm2_quote'], + ['tpm2_rc_decode'], + ['tpm2_readpublic'], + ['tpm2_rsadecrypt'], + ['tpm2_rsaencrypt'], + ['tpm2_send'], + ['tpm2_sign'], + ['tpm2_startup'], + ['tpm2_takeownership'], + ['tpm2_unseal'], + ['tpm2_verifysignature'], + ['tput'], + ['tr'], + ['tracepath'], + ['tracepath6'], + ['traceroute'], + ['traceroute6'], + ['traceroute6.iputils'], + ['tracker'], + ['transicc'], + ['transmission-gtk'], + ['transset'], + ['trap'], + ['tree'], + ['troff'], + ['true'], + ['truncate'], + ['trust'], + ['tset'], + ['tsig-keygen'], + ['tsort'], + ['ttfread'], + ['tty'], + ['tune2fs'], + ['txt2ti3'], + ['type'], + ['typeset'], + ['tzconfig'], + ['tzselect'], + ['u-d-c-print-pci-ids'], + ['ua'], + ['ubuntu-advantage'], + ['ubuntu-bug'], + ['ubuntu-core-launcher'], + ['ubuntu-drivers'], + ['ubuntu-report'], + ['ubuntu-software'], + ['ubuntu-support-status'], + ['ucf'], + ['ucfq'], + ['ucfr'], + ['ucs2any'], + ['udevadm'], + ['udisksctl'], + ['ufw'], + ['ul'], + ['ulimit'], + ['ulockmgr_server'], + ['umask'], + ['umax_pp'], + ['umount'], + ['umount.nfs'], + ['umount.nfs4'], + ['umount.udisks2'], + ['unalias'], + ['uname'], + ['uname26'], + ['unattended-upgrade'], + ['unattended-upgrades'], + ['unbound-anchor'], + ['uncompress'], + ['unexpand'], + ['unicode_start'], + ['unicode_stop'], + ['uniq'], + ['unity-scope-loader'], + ['unix2dos'], + ['unix2mac'], + ['unix_chkpwd'], + ['unix_update'], + ['unlink'], + ['unlz4'], + ['unlzma'], + ['unmkinitramfs'], + ['unoconv'], + ['unopkg'], + ['unpack200'], + ['unpigz'], + ['unset'], + ['unshare'], + ['unsquashfs'], + ['until'], + ['unwrapdiff'], + ['unxz'], + ['unzip'], + ['unzipsfx'], + ['unzstd'], + ['update-alternatives'], + ['update-ca-certificates'], + ['update-ca-trust'], + ['update-cracklib'], + ['update-crypto-policies'], + ['update-default-aspell'], + ['update-default-ispell'], + ['update-default-wordlist'], + ['update-desktop-database'], + ['update-dictcommon-aspell'], + ['update-dictcommon-hunspell'], + ['update-fonts-alias'], + ['update-fonts-dir'], + ['update-fonts-scale'], + ['update-grub'], + ['update-grub-gfxpayload'], + ['update-grub2'], + ['update-gsfontmap'], + ['update-gtk-immodules'], + ['update-icon-caches'], + ['update-inetd'], + ['update-info-dir'], + ['update-initramfs'], + ['update-locale'], + ['update-manager'], + ['update-mime'], + ['update-mime-database'], + ['update-notifier'], + ['update-passwd'], + ['update-pciids'], + ['update-perl-sax-parsers'], + ['update-rc.d'], + ['update-secureboot-policy'], + ['update-usbids'], + ['updatedb'], + ['updatedb.mlocate'], + ['upgrade-from-grub-legacy'], + ['upower'], + ['uptime'], + ['usb-creator-gtk'], + ['usb-devices'], + ['usb_modeswitch'], + ['usb_modeswitch_dispatcher'], + ['usb_printerid'], + ['usbhid-dump'], + ['usbmuxd'], + ['useradd'], + ['userdel'], + ['userhelper'], + ['usermod'], + ['users'], + ['usleep'], + ['utmpdump'], + ['uuidd'], + ['uuidgen'], + ['uuidparse'], + ['uz'], + ['validlocale'], + ['vconfig'], + ['vcstime'], + ['vdir'], + ['vdptool'], + ['vgcfgbackup'], + ['vgcfgrestore'], + ['vgchange'], + ['vgck'], + ['vgconvert'], + ['vgcreate'], + ['vgdisplay'], + ['vgexport'], + ['vgextend'], + ['vgimport'], + ['vgimportclone'], + ['vglclient'], + ['vglconfig'], + ['vglconnect'], + ['vglgenkey'], + ['vgllogin'], + ['vglrun'], + ['vglserver_config'], + ['vglxinfo'], + ['vgmerge'], + ['vgmknodes'], + ['vgreduce'], + ['vgremove'], + ['vgrename'], + ['vgs'], + ['vgscan'], + ['vgsplit'], + ['vi'], + ['via_regs_dump'], + ['view'], + ['viewgam'], + ['viewres'], + ['vigr'], + ['vim.tiny'], + ['vipw'], + ['virtfs-proxy-helper'], + ['virtlockd'], + ['virtlogd'], + ['visudo'], + ['vlock'], + ['vm-support'], + ['vmcore-dmesg'], + ['vmhgfs-fuse'], + ['vmstat'], + ['vmtoolsd'], + ['vmware-checkvm'], + ['vmware-guestproxycerttool'], + ['vmware-hgfsclient'], + ['vmware-namespace-cmd'], + ['vmware-rpctool'], + ['vmware-toolbox-cmd'], + ['vmware-user'], + ['vmware-user-suid-wrapper'], + ['vmware-vgauth-cmd'], + ['vmware-vmblock-fuse'], + ['vmware-xferlogs'], + ['vmwarectrl'], + ['vncconfig'], + ['vncpasswd'], + ['volname'], + ['vpddecode'], + ['vpnc'], + ['vpnc-disconnect'], + ['vstp'], + ['w'], + ['w.procps'], + ['wait'], + ['wall'], + ['watch'], + ['watchgnupg'], + ['wavpack'], + ['wbmptopbm'], + ['wc'], + ['wdctl'], + ['weak-modules'], + ['wget'], + ['whatis'], + ['whereis'], + ['which'], + ['while'], + ['whiptail'], + ['who'], + ['whoami'], + ['whois'], + ['whoopsie'], + ['whoopsie-preferences'], + ['winicontoppm'], + ['wipefs'], + ['withsctp'], + ['wnck-urgency-monitor'], + ['word-list-compress'], + ['wpa_action'], + ['wpa_cli'], + ['wpa_passphrase'], + ['wpa_supplicant'], + ['write'], + ['wvgain'], + ['wvtag'], + ['wvunpack'], + ['x-session-manager'], + ['x-terminal-emulator'], + ['x-window-manager'], + ['x-www-browser'], + ['x11perf'], + ['x11perfcomp'], + ['x86_64'], + ['x86_64-linux-gnu-addr2line'], + ['x86_64-linux-gnu-ar'], + ['x86_64-linux-gnu-as'], + ['x86_64-linux-gnu-c++filt'], + ['x86_64-linux-gnu-cpp'], + ['x86_64-linux-gnu-cpp-8'], + ['x86_64-linux-gnu-dwp'], + ['x86_64-linux-gnu-elfedit'], + ['x86_64-linux-gnu-gold'], + ['x86_64-linux-gnu-gprof'], + ['x86_64-linux-gnu-ld'], + ['x86_64-linux-gnu-ld.bfd'], + ['x86_64-linux-gnu-ld.gold'], + ['x86_64-linux-gnu-nm'], + ['x86_64-linux-gnu-objcopy'], + ['x86_64-linux-gnu-objdump'], + ['x86_64-linux-gnu-ranlib'], + ['x86_64-linux-gnu-readelf'], + ['x86_64-linux-gnu-size'], + ['x86_64-linux-gnu-strings'], + ['x86_64-linux-gnu-strip'], + ['x86_64-redhat-linux-gcc'], + ['x86_64-redhat-linux-gcc-8'], + ['x86_64-redhat-linux-gnu-pkg-config'], + ['xargs'], + ['xauth'], + ['xbiff'], + ['xbmtopbm'], + ['xbrlapi'], + ['xcalc'], + ['xclipboard'], + ['xclock'], + ['xcmsdb'], + ['xconsole'], + ['xcursorgen'], + ['xcutsel'], + ['xdg-desktop-icon'], + ['xdg-desktop-menu'], + ['xdg-email'], + ['xdg-icon-resource'], + ['xdg-mime'], + ['xdg-open'], + ['xdg-screensaver'], + ['xdg-settings'], + ['xdg-user-dir'], + ['xdg-user-dirs-gtk-update'], + ['xdg-user-dirs-update'], + ['xditview'], + ['xdpyinfo'], + ['xdriinfo'], + ['xedit'], + ['xev'], + ['xeyes'], + ['xfd'], + ['xfontsel'], + ['xfs_admin'], + ['xfs_bmap'], + ['xfs_copy'], + ['xfs_db'], + ['xfs_estimate'], + ['xfs_freeze'], + ['xfs_fsr'], + ['xfs_growfs'], + ['xfs_info'], + ['xfs_io'], + ['xfs_logprint'], + ['xfs_mdrestore'], + ['xfs_metadump'], + ['xfs_mkfile'], + ['xfs_ncheck'], + ['xfs_quota'], + ['xfs_repair'], + ['xfs_rtcp'], + ['xfs_scrub'], + ['xfs_scrub_all'], + ['xfs_spaceman'], + ['xgamma'], + ['xgc'], + ['xgettext'], + ['xhost'], + ['xicclu'], + ['ximtoppm'], + ['xinit'], + ['xinput'], + ['xkbbell'], + ['xkbcomp'], + ['xkbevd'], + ['xkbprint'], + ['xkbvleds'], + ['xkbwatch'], + ['xkeystone'], + ['xkill'], + ['xload'], + ['xlogo'], + ['xlsatoms'], + ['xlsclients'], + ['xlsfonts'], + ['xmag'], + ['xman'], + ['xmessage'], + ['xmlcatalog'], + ['xmllint'], + ['xmlsec1'], + ['xmlwf'], + ['xmodmap'], + ['xmore'], + ['xpmtoppm'], + ['xprop'], + ['xqmstats'], + ['xqxdecode'], + ['xrandr'], + ['xrdb'], + ['xrefresh'], + ['xset'], + ['xsetmode'], + ['xsetpointer'], + ['xsetroot'], + ['xsetwacom'], + ['xsltproc'], + ['xsm'], + ['xstdcmap'], + ['xsubpp'], + ['xtables-legacy-multi'], + ['xtables-multi'], + ['xvidtune'], + ['xvinfo'], + ['xvminitoppm'], + ['xwd'], + ['xwdtopnm'], + ['xwininfo'], + ['xwud'], + ['xxd'], + ['xz'], + ['xzcat'], + ['xzcmp'], + ['xzdec'], + ['xzdiff'], + ['xzegrep'], + ['xzfgrep'], + ['xzgrep'], + ['xzless'], + ['xzmore'], + ['ybmtopbm'], + ['yelp'], + ['yes'], + ['ypdomainname'], + ['yum'], + ['yuvsplittoppm'], + ['yuvtoppm'], + ['zcat'], + ['zcmp'], + ['zdb'], + ['zdiff'], + ['zdump'], + ['zegrep'], + ['zeisstopnm'], + ['zeitgeist-daemon'], + ['zenity'], + ['zfgrep'], + ['zforce'], + ['zfs'], + ['zfs-fuse'], + ['zfs-fuse-helper'], + ['zgrep'], + ['zic'], + ['zip'], + ['zipcloak'], + ['zipdetails'], + ['zipgrep'], + ['zipinfo'], + ['zipnote'], + ['zipsplit'], + ['zjsdecode'], + ['zless'], + ['zlib-flate'], + ['zmore'], + ['znew'], + ['zpool'], + ['zramctl'], + ['zramstart'], + ['zramstop'], + ['zsoelim'], + ['zstd'], + ['zstdcat'], + ['zstdgrep'], + ['zstdless'], + ['zstdmt'], + ['zstreamdump'], + ['ztest'], + ['{'], + ['}'], + ['vim'], + ['htop'], + ], +}; diff --git a/src/app/scenario/bashbrawl/languages/generateBashCmds.js b/src/app/scenario/bashbrawl/languages/generateBashCmds.js new file mode 100644 index 00000000..8f065310 --- /dev/null +++ b/src/app/scenario/bashbrawl/languages/generateBashCmds.js @@ -0,0 +1,52 @@ +// This file will generate and write the bash.ts file. +// It this takes a set of text files that are generated from "compgen -bc > file.txt" as input +// Sorts, removes duplicates, and unions the files together then writes bash.ts +// This makes it possible to combine different linux distros together e.g. Fedora, Ubuntu, RHEL +// Example Usage: +// node generateBashCmds.js from-path-fedora.txt from-path-ubuntu.txt + +'use strict'; + +let fs = require('fs'); + +let allCmds = []; + +// First load the files from command line arguments +for (let i = 2; i < process.argv.length; i++) { + let fileName = process.argv[i]; + console.log('Loading file: ' + fileName); + + let fileContents = fs.readFileSync(fileName, 'ascii'); + let linesArray = fileContents.split('\n'); + + allCmds = allCmds.concat(linesArray); + + console.log('command count: ', linesArray.length); +} + +console.log('all commands count: ', allCmds.length); + +// Sort +allCmds.sort(); + +// Remove duplicates +let uniqueCmds = allCmds.filter(function (elem, index, self) { + return index === self.indexOf(elem); +}); + +console.log('unique commands count: ', uniqueCmds.length); + +// Write to file +console.log('Writing to: bash.ts'); +let outFileContent = '/** Generated from generateBashCmds.js **/\n'; +outFileContent += 'export default [\n'; +uniqueCmds.forEach((value) => { + outFileContent += '"' + value + '",\n'; +}); +outFileContent += '];\n'; + +try { + fs.writeFileSync('./bash.ts', outFileContent); +} catch (err) { + console.error(err); +} diff --git a/src/app/scenario/bashbrawl/languages/html.ts b/src/app/scenario/bashbrawl/languages/html.ts new file mode 100644 index 00000000..7c33c1a0 --- /dev/null +++ b/src/app/scenario/bashbrawl/languages/html.ts @@ -0,0 +1,132 @@ +/** Taken from https://github.com/CommandLineHeroes/clh-bash/tree/master/assets/cmds **/ + +import { LanguageConfig } from './language-config.interface'; +export const htmlConfig: LanguageConfig = { + name: 'HTML5', + cmds: [ + ['html'], + ['head'], + ['title'], + ['base'], + ['link'], + ['meta'], + ['style'], + ['body'], + ['article'], + ['section'], + ['nav'], + ['aside'], + ['h1'], + ['h2'], + ['h3'], + ['h4'], + ['h5'], + ['h6'], + ['header'], + ['footer'], + ['p'], + ['address'], + ['hr'], + ['pre'], + ['blockquote'], + ['ol'], + ['ul'], + ['li'], + ['dl'], + ['dt'], + ['dd'], + ['figure'], + ['figcaption'], + ['main'], + ['div'], + ['a'], + ['em'], + ['strong'], + ['small'], + ['s'], + ['cite'], + ['q'], + ['dfn'], + ['abbr'], + ['ruby'], + ['rb'], + ['rt'], + ['rtc'], + ['rp'], + ['data'], + ['time'], + ['code'], + ['var'], + ['samp'], + ['kbd'], + ['sub'], + ['sup'], + ['i'], + ['b'], + ['u'], + ['mark'], + ['bdi'], + ['bdo'], + ['span'], + ['br'], + ['wbr'], + ['ins'], + ['del'], + ['picture'], + ['source'], + ['img'], + ['iframe'], + ['embed'], + ['object'], + ['param'], + ['video'], + ['audio'], + ['track'], + ['map'], + ['area'], + ['table'], + ['caption'], + ['colgroup'], + ['col'], + ['tbody'], + ['thead'], + ['tfoot'], + ['tr'], + ['td'], + ['th'], + ['form'], + ['label'], + ['input'], + ['button'], + ['select'], + ['datalist'], + ['optgroup'], + ['option'], + ['textarea'], + ['output'], + ['progress'], + ['meter'], + ['fieldset'], + ['legend'], + ['details'], + ['summary'], + ['dialog'], + ['script'], + ['noscript'], + ['template'], + ['canvas'], + ['slot'], + ['hr'], + ['fieldset'], + ['legend'], + ['button'], + ['details'], + ['summary'], + ['marquee'], + ['meter'], + ['progress'], + ['select'], + ['textarea'], + ['marquee'], + ], +}; diff --git a/src/app/scenario/bashbrawl/languages/javascript.ts b/src/app/scenario/bashbrawl/languages/javascript.ts new file mode 100644 index 00000000..c81befce --- /dev/null +++ b/src/app/scenario/bashbrawl/languages/javascript.ts @@ -0,0 +1,340 @@ +/** + * This is a list of JavaScript keywords, "standard library" objects, etc. + * + * See the README in this directory for more on how this list is assembled. + * + * There are duplicates, and that's okay. But if you are removing items, be sure to look for multiple entries! + */ +import { LanguageConfig } from './language-config.interface'; +export const javascriptConfig: LanguageConfig = { + name: 'javascript', + cmds: [ + // keywords + ['await'], + ['break'], + ['case'], + ['catch'], + ['class'], + ['const'], + ['continue'], + ['debugger'], + ['default'], + ['delete'], + ['do'], + ['else'], + ['export'], + ['extends'], + ['finally'], + ['for'], + ['function'], + ['if'], + ['import'], + ['in'], + ['instanceof'], + ['new'], + ['return'], + ['super'], + ['switch'], + ['this'], + ['throw'], + ['try'], + ['typeof'], + ['var'], + ['void'], + ['while'], + ['with'], + ['yield'], + // some literals + ['null'], + ['true'], + ['false'], + // global object properties + ['Infinity'], + ['NaN'], + ['undefined'], + ['eval'], + ['isFinite'], + ['isNaN'], + ['parseFloat'], + ['parseInt'], + ['decodeURI'], + ['decodeURIComponent'], + ['encodeURI'], + ['encodeURIComponent'], + ['Array'], + ['ArrayBuffer'], + ['Boolean'], + ['DataView'], + ['Date'], + ['Error'], + ['EvalError'], + ['Float32Array'], + ['Float64Array'], + ['Function'], + ['Int8Array'], + ['Int16Array'], + ['Int32Array'], + ['Map'], + ['Number'], + ['Object'], + ['Promise'], + ['Proxy'], + ['RangeError'], + ['ReferenceError'], + ['RegExp'], + ['Set'], + ['SharedArrayBuffer'], + ['String'], + ['Symbol'], + ['SyntaxError'], + ['TypeError'], + ['Uint8Array'], + ['Uint8ClampedArray'], + ['Uint16Array'], + ['Uint32Array'], + ['URIError'], + ['WeakMap'], + ['WeakSet'], + // fundamental objects (ch 19) + ['Object'], + ['Function'], + ['Boolean'], + ['Symbol'], + ['Error'], + // numbers and dates (ch 20) + ['Number'], + ['Math'], + ['Date'], + // text processing (ch 21) + ['String'], + ['RegExp'], + // indexed collections (ch 22) + ['Array'], + // keyed collections (ch 23) + ['Map'], + ['Set'], + ['WeakMap'], + ['WeakSet'], + // structured data (ch 24) + ['ArrayBuffer'], + ['SharedArrayBuffer'], + ['DataView'], + ['Atomics'], + ['JSON'], + // control abstraction objects (ch 25) + ['Generator'], + ['AsyncGenerator'], + ['Promise'], + // reflection (ch 26) + ['Reflect'], + ['Proxy'], + // some curiously hard to find ones in the spec + ['async'], + ['let'], + ['static'], + ['else'], + ['document'], + ['window'], + ['navigator'], + ['then'], + ['set'], + ['get'], + ['of'], + // Object.keys(window) in chrome + ['postMessage'], + ['blur'], + ['focus'], + ['close'], + ['parent'], + ['opener'], + ['top'], + ['length'], + ['frames'], + ['closed'], + ['location'], + ['self'], + ['window'], + ['document'], + ['name'], + ['customElements'], + ['history'], + ['locationbar'], + ['menubar'], + ['personalbar'], + ['scrollbars'], + ['statusbar'], + ['toolbar'], + ['status'], + ['frameElement'], + ['navigator'], + ['origin'], + ['external'], + ['screen'], + ['innerWidth'], + ['innerHeight'], + ['scrollX'], + ['pageXOffset'], + ['scrollY'], + ['pageYOffset'], + ['visualViewport'], + ['screenX'], + ['screenY'], + ['outerWidth'], + ['outerHeight'], + ['devicePixelRatio'], + ['clientInformation'], + ['screenLeft'], + ['screenTop'], + ['defaultStatus'], + ['defaultstatus'], + ['styleMedia'], + ['onanimationend'], + ['onanimationiteration'], + ['onanimationstart'], + ['onsearch'], + ['ontransitionend'], + ['onwebkitanimationend'], + ['onwebkitanimationiteration'], + ['onwebkitanimationstart'], + ['onwebkittransitionend'], + ['isSecureContext'], + ['onabort'], + ['onblur'], + ['oncancel'], + ['oncanplay'], + ['oncanplaythrough'], + ['onchange'], + ['onclick'], + ['onclose'], + ['oncontextmenu'], + ['oncuechange'], + ['ondblclick'], + ['ondrag'], + ['ondragend'], + ['ondragenter'], + ['ondragleave'], + ['ondragover'], + ['ondragstart'], + ['ondrop'], + ['ondurationchange'], + ['onemptied'], + ['onended'], + ['onerror'], + ['onfocus'], + ['oninput'], + ['oninvalid'], + ['onkeydown'], + ['onkeypress'], + ['onkeyup'], + ['onload'], + ['onloadeddata'], + ['onloadedmetadata'], + ['onloadstart'], + ['onmousedown'], + ['onmouseenter'], + ['onmouseleave'], + ['onmousemove'], + ['onmouseout'], + ['onmouseover'], + ['onmouseup'], + ['onmousewheel'], + ['onpause'], + ['onplay'], + ['onplaying'], + ['onprogress'], + ['onratechange'], + ['onreset'], + ['onresize'], + ['onscroll'], + ['onseeked'], + ['onseeking'], + ['onselect'], + ['onstalled'], + ['onsubmit'], + ['onsuspend'], + ['ontimeupdate'], + ['ontoggle'], + ['onvolumechange'], + ['onwaiting'], + ['onwheel'], + ['onauxclick'], + ['ongotpointercapture'], + ['onlostpointercapture'], + ['onpointerdown'], + ['onpointermove'], + ['onpointerup'], + ['onpointercancel'], + ['onpointerover'], + ['onpointerout'], + ['onpointerenter'], + ['onpointerleave'], + ['onselectstart'], + ['onselectionchange'], + ['onafterprint'], + ['onbeforeprint'], + ['onbeforeunload'], + ['onhashchange'], + ['onlanguagechange'], + ['onmessage'], + ['onmessageerror'], + ['onoffline'], + ['ononline'], + ['onpagehide'], + ['onpageshow'], + ['onpopstate'], + ['onrejectionhandled'], + ['onstorage'], + ['onunhandledrejection'], + ['onunload'], + ['performance'], + ['stop'], + ['open'], + ['alert'], + ['confirm'], + ['prompt'], + ['print'], + ['queueMicrotask'], + ['requestAnimationFrame'], + ['cancelAnimationFrame'], + ['captureEvents'], + ['releaseEvents'], + ['requestIdleCallback'], + ['cancelIdleCallback'], + ['getComputedStyle'], + ['matchMedia'], + ['moveTo'], + ['moveBy'], + ['resizeTo'], + ['resizeBy'], + ['getSelection'], + ['find'], + ['webkitRequestAnimationFrame'], + ['webkitCancelAnimationFrame'], + ['fetch'], + ['btoa'], + ['atob'], + ['setTimeout'], + ['clearTimeout'], + ['setInterval'], + ['clearInterval'], + ['createImageBitmap'], + ['scroll'], + ['scrollTo'], + ['scrollBy'], + ['onappinstalled'], + ['onbeforeinstallprompt'], + ['crypto'], + ['ondevicemotion'], + ['ondeviceorientation'], + ['ondeviceorientationabsolute'], + ['indexedDB'], + ['webkitStorageInfo'], + ['sessionStorage'], + ['localStorage'], + ['chrome'], + ['speechSynthesis'], + ['webkitRequestFileSystem'], + ['webkitResolveLocalFileSystemURL'], + ['openDatabase'], + ], +}; diff --git a/src/app/scenario/bashbrawl/languages/kubernetes.ts b/src/app/scenario/bashbrawl/languages/kubernetes.ts new file mode 100644 index 00000000..0dfd3872 --- /dev/null +++ b/src/app/scenario/bashbrawl/languages/kubernetes.ts @@ -0,0 +1,273 @@ +import { LanguageConfig } from './language-config.interface'; +export const kubernetesConfig: LanguageConfig = { + name: 'Kubernetes', + cmds: [ + // Basics + ['kubectl', 'k'], + ['crictl'], + // API Methods + ['get'], + ['list'], + ['watch'], + ['update'], + ['patch'], + ['delete'], + ['create'], + // kubectl commands + ['edit'], + ['config'], + ['apply'], + ['explain'], + ['describe'], + ['diff'], + ['rollout'], + ['set'], + ['label'], + ['replace'], + ['annotate'], + ['autoscale'], + ['scale'], + ['logs'], + ['attach'], + ['port-forward'], + ['exec'], + ['debug'], + ['top'], + ['cp'], + ['cordon'], + ['drain'], + ['uncordon'], + ['cluster-info'], + ['taint'], + + // API Versions and Manifests + ['v1'], + ['v1alpha1'], + ['v1beta1'], + ['apps/v1'], + ['apps'], + ['batch/v1'], + ['batch'], + ['k8s.io'], + ['apiVersion'], + ['kind'], + ['name'], + ['label'], + ['apigroup'], + ['verb'], + ['verbs'], + ['meta'], + ['metadata'], + ['spec'], + ['annotations'], + ['annotation'], + ['status'], + + // API Resources + ['binding', 'bindings'], + ['componentstatus', 'componentstatuses', 'cs'], + ['configmap', 'configmaps', 'cm'], + ['deployment', 'deployments', 'deploy'], + ['endpoint', 'endpoints', 'ep'], + ['event', 'events', 'ev'], + ['limitrange', 'limitranges', 'limit'], + ['namespace', 'namespaces', 'ns'], + ['node', 'nodes', 'no'], + ['persistentvolumeclaim', 'persistentvolumeclaims', 'pvc'], + ['persistentvolume', 'persistentvolumes', 'pv'], + ['pod', 'pods', 'po'], + ['podtemplate', 'podtemplates'], + ['replicationcontroller', 'replicationcontrollers', 'rc'], + ['resourcequota', 'resourcequotas', 'quota'], + ['secret', 'secrets'], + ['serviceaccounts', 'serviceaccount', 'sa'], + ['svc', 'services', 'service'], + ['mutatingwebhookconfiguration', 'mutatingwebhookconfigurations'], + ['validatingwebhookconfiguration', 'validatingwebhookconfigurations'], + ['customresourcedefinition', 'customresourcedefinitions', 'crd', 'crds'], + ['controllerrevision', 'controllerrevisions'], + ['daemonset', 'daemonsets', 'ds'], + ['replicaset', 'replicasets', 'rs'], + ['statefulset', 'statefulsets', 'sts'], + ['tokenreview', 'tokenreviews'], + ['localsubjectaccesreview', 'localsubjectaccesreviews'], + ['selfsubjectaccessreview', 'selfsubjectaccessreviews'], + ['selfsubjectrulesreview', 'selfsubjectrulesreviews'], + ['subjectaccessreview', 'subjectaccessreviews'], + [ + 'horizontalpodautoscaler', + 'horizontalpodautoscalers', + 'hpa', + 'autoscaler', + ], + ['cronjob', 'cronjobs', 'cj'], + ['job', 'jobs'], + ['endpointslice', 'endpointslices'], + ['crontab', 'crontabs', 'ct'], + ['ingressclass', 'ingressclasses'], + ['ingress', 'ingresses', 'ing'], + ['networkpolicy', 'netpol', 'networkpolicies'], + ['runtimeclass', 'runtimeclasses'], + ['poddisruptionbudget', 'poddisruptionbudgets', 'pdb'], + ['clusterrolebinding', 'clusterrolebindings'], + ['clusterrole', 'clusterroles'], + ['rolebinding', 'rolebindings'], + ['role', 'roles'], + ['priorityclass', 'priorityclasses'], + ['csidriver', 'csidrivers'], + ['csinode', 'csinodes'], + ['csistoragecapacitiy', 'csistoragecapacities'], + ['storageclass', 'storageclasses', 'sc'], + ['volumeattachement', 'volumeattachements'], + + // Fields + ['data'], + ['type'], + ['creationtimestamp'], + ['selector'], + ['rollingupdate'], + ['strategytype'], + ['condition'], + ['state'], + ['mounts'], + ['backend'], + ['path'], + ['paths'], + ['http'], + ['https'], + ['protocol'], + ['port'], + ['loadbalancer'], + ['loadbalancers'], + ['uid'], + ['resourceversion'], + ['ClusterIP'], + ['NodePort'], + ['LoadBalancer'], + ['ExternalName'], + ['headless'], + ['egress'], + ['matchlabel'], + ['matchlabels'], + ['podselector'], + ['namespaceselector'], + ['ipBlock'], + ['policyTypes'], + ['routing'], + ['router'], + ['routingrule'], + ['scope'], + ['affinity'], + ['affinities'], + ['probe'], + ['crio'], + ['cri-o'], + // Companies, + ['cncf'], + ['tanzu'], + ['gke'], + ['aks'], + ['rke'], + ['rancher'], + ['rke2'], + ['openshift'], + ['kubermatic'], + ['k8c'], + ['eks'], + ['k0s'], + ['k3d'], + ['microk8s'], + ['traefik'], + ['nginx'], + ['minikube'], + // other, + ['image'], + ['container'], + ['containers'], + ['cluster'], + ['clusters'], + ['runtime'], + ['controller'], + ['controllers'], + ['docker'], + ['dockershim'], + ['ephemeral'], + ['finalizer'], + ['yaml'], + ['manifest'], + ['yml'], + ['grpc'], + ['webhook'], + ['autoscaler'], + ['rbac'], + ['rule'], + ['hostname'], + ['wildcard'], + ['workload'], + ['workloads'], + ['csi'], + ['cni'], + ['interface'], + ['storage'], + ['servicemesh'], + ['microservice'], + ['microservices'], + ['sig'], + ['init'], + ['initcontainer'], + ['sidecar'], + ['healthcheck'], + ['static'], + ['toleration'], + ['eviction'], + ['cgroup'], + ['cgroups'], + ['containerd'], + ['dockerd'], + ['kubeadm'], + ['sysctl'], + ['kubeinvaders'], + // other tools + ['k9s'], + ['loki'], + ['thanos'], + ['grafana'], + ['istio'], + ['helm'], + ['chart'], + ['helmchart'], + ['lens'], + ['catalog'], + ['kompose'], + ['portainer'], + ['KEDA'], + ['vcluster'], + ['Jaeger'], + ['Kiali'], + ['ELK'], + ['fluentbit'], + ['fluentd'], + ['promtail'], + ['terraform'], + ['ansible'], + ['Jaeger'], + ['tekton'], + ['argo'], + ['arcocd'], + ['kyverno'], + ['falco'], + ['vault'], + ['calico'], + ['cilium'], + ['canico'], + ['metallb'], + ['kong'], + ['longhorn'], + ['trivy'], + ['rook'], + ['ebs'], + ['openebs'], + ['knative'], + // Kubernetes release names + ], +}; diff --git a/src/app/scenario/bashbrawl/languages/language-command.service.ts b/src/app/scenario/bashbrawl/languages/language-command.service.ts new file mode 100644 index 00000000..b46f5897 --- /dev/null +++ b/src/app/scenario/bashbrawl/languages/language-command.service.ts @@ -0,0 +1,83 @@ +// language-command.service.ts +import { Injectable } from '@angular/core'; +import { htmlConfig } from './html'; +import { kubernetesConfig } from './kubernetes'; +import { bashConfig } from './bash'; +import { pythonConfig } from './python'; +import { LanguageConfig } from './language-config.interface'; +import { javascriptConfig } from './javascript'; + +@Injectable({ + providedIn: 'root', +}) +export class LanguageCommandService { + private commands: { [key: string]: LanguageConfig } = { + html: htmlConfig, + kubernetes: kubernetesConfig, + bash: bashConfig, + python: pythonConfig, + javascript: javascriptConfig, + // other languages can be added here + }; + + find( + cmd: string, + language: string, + ): { cmd: string; lang: string[]; found: boolean } { + const result: { cmd: string; lang: string[]; found: boolean } = { + cmd: '', + lang: [], + found: false, + }; + cmd = cmd.trim(); // Trim the command once outside the loop + + if (language && language != 'all') { + // Only one language specified + this.getLanguageById(language).cmds.forEach((command) => { + // If command is an array, check if the trimmed command matches any command in the array + if (command.includes(cmd)) { + result.cmd = command[0]; // Set result.cmd to the first command in the array + result.lang.push(language); + result.found = true; + } + }); + } else { + // Loop through each language's command list + for (const lang in this.commands) { + // Iterate over each command or command array in the command list + this.getLanguageById(lang).cmds.forEach((command) => { + // If command is an array, check if the trimmed command matches any command in the array + if (command.includes(cmd)) { + result.cmd = command[0]; // Set result.cmd to the first command in the array + result.lang.push(lang); + result.found = true; + } + }); + } + } + + return result; + } + + getLanguageNames(): string[] { + const languages: string[] = []; + Object.values(this.commands).forEach((element) => { + languages.push(element.name); + }); + return languages; + } + + getLanguageKeys() { + return Object.keys(this.commands); + } + + getLanguageById(language: string) { + return this.commands[language] ?? {}; + } + + getLanguageNameById(language: string) { + return this.getLanguageKeys().includes(language) + ? this.getLanguageById(language).name + : language.toUpperCase(); + } +} diff --git a/src/app/scenario/bashbrawl/languages/language-config.interface.ts b/src/app/scenario/bashbrawl/languages/language-config.interface.ts new file mode 100644 index 00000000..8c3f3359 --- /dev/null +++ b/src/app/scenario/bashbrawl/languages/language-config.interface.ts @@ -0,0 +1,5 @@ +// language-config.interface.ts +export interface LanguageConfig { + name: string; + cmds: string[][]; +} diff --git a/src/app/scenario/bashbrawl/languages/python.ts b/src/app/scenario/bashbrawl/languages/python.ts new file mode 100644 index 00000000..d0497db2 --- /dev/null +++ b/src/app/scenario/bashbrawl/languages/python.ts @@ -0,0 +1,189 @@ +/** Taken from https://github.com/CommandLineHeroes/clh-bash/tree/master/assets/cmds **/ + +/** + * This is a list of Python3+ keywords and built in functions + * + * See the README in this directory for more on how this list is assembled. + * + * There are duplicates, and that's okay. But if you are removing items, be sure to look for multiple entries! + */ +import { LanguageConfig } from './language-config.interface'; +export const pythonConfig: LanguageConfig = { + name: 'Python', + cmds: [ + // keywords + ['False'], + ['class'], + ['finally'], + ['is'], + ['return'], + ['None'], + ['continue'], + ['for'], + ['lambda'], + ['try'], + ['True'], + ['def'], + ['from'], + ['nonlocal'], + ['while'], + ['and'], + ['del'], + ['global'], + ['not'], + ['with'], + ['as'], + ['elif'], + ['if'], + ['or'], + ['yield'], + ['assert'], + ['else'], + ['import'], + ['pass'], + ['break'], + ['except'], + ['in'], + ['raise'], + // funtions + ['abs()'], + ['delattr()'], + ['hash()'], + ['memoryview()'], + ['set()'], + ['all()'], + ['dict()'], + ['help()'], + ['min()'], + ['setattr()'], + ['any()'], + ['dir()'], + ['hex()'], + ['next()'], + ['slice()'], + ['ascii()'], + ['divmod()'], + ['id()'], + ['object()'], + ['sorted()'], + ['bin()'], + ['enumerate()'], + ['input()'], + ['oct()'], + ['staticmethod()'], + ['bool()'], + ['eval()'], + ['int()'], + ['open()'], + ['str()'], + ['breakpoint()'], + ['exec()'], + ['isinstance()'], + ['ord()'], + ['sum()'], + ['bytearray()'], + ['filter()'], + ['issubclass()'], + ['pow()'], + ['super()'], + ['bytes()'], + ['float()'], + ['iter()'], + ['print()'], + ['tuple()'], + ['callable()'], + ['format()'], + ['len()'], + ['property()'], + ['type()'], + ['chr()'], + ['frozenset()'], + ['list()'], + ['range()'], + ['vars()'], + ['classmethod()'], + ['getattr()'], + ['locals()'], + ['repr()'], + ['zip()'], + ['compile()'], + ['globals()'], + ['map()'], + ['reversed()'], + ['__import__()'], + ['complex()'], + ['hasattr()'], + ['max()'], + ['round()'], + // functions without parens + ['abs'], + ['delattr'], + ['hash'], + ['memoryview'], + ['set'], + ['all'], + ['dict'], + ['help'], + ['min'], + ['setattr'], + ['any'], + ['dir'], + ['hex'], + ['next'], + ['slice'], + ['ascii'], + ['divmod'], + ['id'], + ['object'], + ['sorted'], + ['bin'], + ['enumerate'], + ['input'], + ['oct'], + ['staticmethod'], + ['bool'], + ['eval'], + ['int'], + ['open'], + ['str'], + ['breakpoint'], + ['exec'], + ['isinstance'], + ['ord'], + ['sum'], + ['bytearray'], + ['filter'], + ['issubclass'], + ['pow'], + ['super'], + ['bytes'], + ['float'], + ['iter'], + ['print'], + ['tuple'], + ['callable'], + ['format'], + ['len'], + ['property'], + ['type'], + ['chr'], + ['frozenset'], + ['list'], + ['range'], + ['vars'], + ['classmethod'], + ['getattr'], + ['locals'], + ['repr'], + ['zip'], + ['compile'], + ['globals'], + ['map'], + ['reversed'], + ['__import__'], + ['complex'], + ['hasattr'], + ['max'], + ['round'], + ], +}; diff --git a/src/app/scenario/step.component.html b/src/app/scenario/step.component.html index b4aa16e6..41d6d2af 100644 --- a/src/app/scenario/step.component.html +++ b/src/app/scenario/step.component.html @@ -6,95 +6,122 @@ #divider > -