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 @@
Settings
+
+
+
+
+
+
+
+
+
+
+
+
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: '[D',
+ RIGHT_ARROW: '[C',
+ UP_ARROW: '[A',
+ DOWN_ARROW: '[B',
+};
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
>
-