433
return undefined;
434
}
436
>
/**
437
>
* From `fish` docs:
438
>
* > The command history is stored in the file ~/.local/share/fish/fish_history
439
>
* (or $XDG_DATA_HOME/fish/fish_history if that variable is set) by default.
440
>
*
441
>
* (https://fishshell.com/docs/current/interactive.html#history-search)
442
>
*/
443
>
const overridenDataHome = env['XDG_DATA_HOME'];
444
>
445
>
// TODO: Unchecked fish behavior:
446
>
// What if XDG_DATA_HOME was defined but somehow $XDG_DATA_HOME/fish/fish_history
447
>
// was not exist. Does fish fall back to ~/.local/share/fish/fish_history?
448
>
449
>
let folderPrefix: string | undefined;
450
>
let filePath: string;
451
>
let sourceLabel: string;
452
>
if (overridenDataHome) {
453
sourceLabel = '$XDG_DATA_HOME/fish/fish_history';
454
folderPrefix = env['XDG_DATA_HOME'];
455
filePath = 'fish/fish_history';
457
sourceLabel = '~/.local/share/fish/fish_history';
458
folderPrefix = remoteEnvironment?.userHome?.fsPath ?? env['HOME'];
459
filePath = '.local/share/fish/fish_history';
460
}
461
>
const resolvedFile = await fetchFileContents(folderPrefix, filePath, false, fileService, remoteAgentService);
history.ts
462
>
if (resolvedFile === undefined) {
463
return undefined;
464
}
466
>
/**
467
>
* These apply to `fish` v3.5.1:
468
>
* - It looks like YAML but it's not. It's, quoting, *"a broken psuedo-YAML"*.
469
>
* See these discussions for more details:
470
>
* - https://github.com/fish-shell/fish-shell/pull/6493
471
>
* - https://github.com/fish-shell/fish-shell/issues/3341
472
>
* - Every record should exactly start with `- cmd:` (the whitespace between `-` and `cmd` cannot be replaced with tab)
473
>
* - Both `- cmd: echo 1` and `- cmd:echo 1` are valid entries.
474
>
* - Backslashes are esacped as `\\`.
475
>
* - Multiline commands are joined with a `\n` sequence, hence they're read as single line commands.
476
>
* - Property `when` is optional.
477
>
* - History navigation respects the records order and ignore the actual `when` property values (chronological order).
478
>
* - If `cmd` value is multiline , it just takes the first line. Also YAML operators like `>-` or `|-` are not supported.
479
>
*/
480
>
const result: Set<string> = new Set();
481
>
const cmds = resolvedFile.content.split('\n')
482
>
.filter(x => x.startsWith('- cmd:'))
483
>
.map(x => x.substring(6).trimStart());
484
>
for (let i = 0; i < cmds.length; i++) {
485
>
const sanitized = sanitizeFishHistoryCmd(cmds[i]).trim();
486
>
if (sanitized.length > 0) {
487
>
result.add(sanitized);
488
>
}
489
>
}
490
>
return {
491
>
sourceLabel,
492
>
sourceResource: resolvedFile.resource,
493
>
commands: Array.from(result.values())
494
>
};
495
>
}
496
497
export function sanitizeFishHistoryCmd(cmd: string): string {