@microsoft/inshellisense 0.0.1-rc.1 → 0.0.1-rc.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/CODE_OF_CONDUCT.md +9 -9
  2. package/LICENSE +21 -21
  3. package/README.md +114 -55
  4. package/SECURITY.md +41 -41
  5. package/SUPPORT.md +13 -13
  6. package/build/commands/complete.js +16 -0
  7. package/build/commands/root.js +23 -31
  8. package/build/commands/uninstall.js +11 -0
  9. package/build/index.js +16 -7
  10. package/build/isterm/commandManager.js +270 -0
  11. package/build/isterm/index.js +4 -0
  12. package/build/isterm/pty.js +298 -0
  13. package/build/runtime/generator.js +23 -10
  14. package/build/runtime/parser.js +2 -2
  15. package/build/runtime/runtime.js +44 -27
  16. package/build/runtime/suggestion.js +47 -21
  17. package/build/runtime/template.js +33 -18
  18. package/build/runtime/utils.js +42 -12
  19. package/build/ui/suggestionManager.js +153 -0
  20. package/build/ui/ui-root.js +132 -63
  21. package/build/ui/ui-uninstall.js +9 -0
  22. package/build/ui/utils.js +56 -0
  23. package/build/utils/ansi.js +33 -0
  24. package/build/utils/config.js +109 -0
  25. package/build/utils/log.js +30 -0
  26. package/build/utils/shell.js +101 -0
  27. package/package.json +86 -59
  28. package/shell/bash-preexec.sh +380 -0
  29. package/shell/shellIntegration-env.zsh +9 -0
  30. package/shell/shellIntegration-login.zsh +4 -0
  31. package/shell/shellIntegration-profile.zsh +4 -0
  32. package/shell/shellIntegration-rc.zsh +58 -0
  33. package/shell/shellIntegration.bash +94 -0
  34. package/shell/shellIntegration.fish +19 -0
  35. package/shell/shellIntegration.nu +28 -0
  36. package/shell/shellIntegration.ps1 +24 -0
  37. package/shell/shellIntegration.xsh +29 -0
  38. package/build/commands/bind.js +0 -12
  39. package/build/ui/input.js +0 -55
  40. package/build/ui/suggestions.js +0 -84
  41. package/build/ui/ui-bind.js +0 -64
  42. package/build/utils/bindings.js +0 -144
  43. package/build/utils/cache.js +0 -21
  44. package/shell/key-bindings-powershell.ps1 +0 -27
  45. package/shell/key-bindings-pwsh.ps1 +0 -27
  46. package/shell/key-bindings.bash +0 -7
  47. package/shell/key-bindings.fish +0 -8
  48. package/shell/key-bindings.zsh +0 -10
@@ -0,0 +1,94 @@
1
+ if [ -r ~/.bashrc ]; then
2
+ . ~/.bashrc
3
+ fi
4
+
5
+ if [ -r ~/.inshellisense/bash-preexec.sh ]; then
6
+ . ~/.inshellisense/bash-preexec.sh
7
+ fi
8
+
9
+ __is_prompt_start() {
10
+ builtin printf '\e]6973;PS\a'
11
+ }
12
+
13
+ __is_prompt_end() {
14
+ builtin printf '\e]6973;PE\a'
15
+ }
16
+
17
+ __is_escape_value() {
18
+ # Process text byte by byte, not by codepoint.
19
+ builtin local LC_ALL=C str="${1}" i byte token out=''
20
+
21
+ for (( i=0; i < "${#str}"; ++i )); do
22
+ byte="${str:$i:1}"
23
+
24
+ # Escape backslashes and semi-colons
25
+ if [ "$byte" = "\\" ]; then
26
+ token="\\\\"
27
+ elif [ "$byte" = ";" ]; then
28
+ token="\\x3b"
29
+ else
30
+ token="$byte"
31
+ fi
32
+
33
+ out+="$token"
34
+ done
35
+
36
+ builtin printf '%s\n' "${out}"
37
+ }
38
+
39
+ __is_update_cwd() {
40
+ builtin printf '\e]6973;CWD;%s\a' "$(__is_escape_value "$PWD")"
41
+ }
42
+
43
+ if [[ -n "${bash_preexec_imported:-}" ]]; then
44
+ precmd_functions+=(__is_precmd)
45
+ fi
46
+
47
+ __is_precmd() {
48
+ __is_update_cwd
49
+ __is_update_prompt
50
+ }
51
+
52
+ __is_update_prompt() {
53
+ if [[ "$__is_custom_PS1" == "" || "$__is_custom_PS1" != "$PS1" ]]; then
54
+ __is_original_PS1=$PS1
55
+ if [[ $ISTERM_TESTING == "1" ]]; then
56
+ __is_original_PS1="> "
57
+ fi
58
+ __is_custom_PS1="\[$(__is_prompt_start)\]$__is_original_PS1\[$(__is_prompt_end)\]"
59
+ PS1="$__is_custom_PS1"
60
+ fi
61
+ }
62
+
63
+ __is_prompt_cmd_original() {
64
+ for cmd in "${__is_original_prompt_command[@]}"; do
65
+ eval "${cmd:-}"
66
+ done
67
+ __is_precmd
68
+ }
69
+
70
+ # handles when a user's PROMPT_COMMAND resets their prompt after the precmd hook is triggered
71
+ __is_prompt_cmd_safe() {
72
+ for cmd in "${__is_original_prompt_command[@]}"; do
73
+ eval "${cmd:-}"
74
+ done
75
+ if [[ "$PS1" != "$__is_safe_PS1" ]]; then
76
+ __is_precmd
77
+ __is_safe_PS1="$PS1"
78
+ fi
79
+ }
80
+
81
+ __is_original_prompt_command=${PROMPT_COMMAND:-}
82
+ if [[ -z "${bash_preexec_imported:-}" ]]; then
83
+ if [[ -n "${__is_original_prompt_command:-}" && "${__is_original_prompt_command:-}" != "__is_precmd" ]]; then
84
+ PROMPT_COMMAND=__is_prompt_cmd_original
85
+ else
86
+ PROMPT_COMMAND=__is_precmd
87
+ fi
88
+ else
89
+ if [[ -n "${__is_original_prompt_command:-}" && "${__is_original_prompt_command:-}" != "__is_precmd" ]]; then
90
+ PROMPT_COMMAND=__is_prompt_cmd_safe
91
+ fi
92
+ fi
93
+
94
+ __is_precmd
@@ -0,0 +1,19 @@
1
+ function __is_copy_function; functions $argv[1] | sed "s/^function $argv[1]/function $argv[2]/" | source; end
2
+ function __is_prompt_start; printf '\e]6973;PS\a'; end
3
+ function __is_prompt_end; printf '\e]6973;PE\a'; end
4
+
5
+ function __is_escape_value
6
+ echo $argv \
7
+ | string replace --all '\\' '\\\\' \
8
+ | string replace --all ';' '\\x3b' \
9
+ ;
10
+ end
11
+ function __is_update_cwd --on-event fish_prompt; set __is_cwd (__is_escape_value "$PWD"); printf "\e]6973;CWD;$__is_cwd\a"; end
12
+
13
+ __is_copy_function fish_prompt is_user_prompt
14
+
15
+ if [ "$ISTERM_TESTING" = "1" ]
16
+ function is_user_prompt; printf '> '; end
17
+ end
18
+
19
+ function fish_prompt; printf (__is_prompt_start); printf (is_user_prompt); printf (__is_prompt_end); end
@@ -0,0 +1,28 @@
1
+ let __is_escape_value = {|x| $x | str replace --all "\\" "\\\\" | str replace --all ";" "\\x3b" }
2
+
3
+ let __is_update_cwd = {
4
+ let pwd = do $__is_escape_value $env.PWD
5
+ $"\e]6973;CWD;($pwd)\a"
6
+ }
7
+ let __is_original_PROMPT_COMMAND = if 'PROMPT_COMMAND' in $env { $env.PROMPT_COMMAND } else { "" }
8
+ let __is_custom_PROMPT_COMMAND = {
9
+ let promptCommandType = $__is_original_PROMPT_COMMAND | describe
10
+ mut cmd = if $promptCommandType == "closure" { do $__is_original_PROMPT_COMMAND } else { $__is_original_PROMPT_COMMAND }
11
+ let pwd = do $__is_update_cwd
12
+ if 'ISTERM_TESTING' in $env {
13
+ $cmd = ""
14
+ }
15
+ $"\e]6973;PS\a($cmd)($pwd)"
16
+ }
17
+ $env.PROMPT_COMMAND = $__is_custom_PROMPT_COMMAND
18
+
19
+ let __is_original_PROMPT_INDICATOR = if 'PROMPT_INDICATOR' in $env { $env.PROMPT_INDICATOR } else { "" }
20
+ let __is_custom_PROMPT_INDICATOR = {
21
+ let indicatorCommandType = $__is_original_PROMPT_INDICATOR | describe
22
+ mut ind = if $indicatorCommandType == "closure" { do $__is_original_PROMPT_INDICATOR } else { $__is_original_PROMPT_INDICATOR }
23
+ if 'ISTERM_TESTING' in $env {
24
+ $ind = "> "
25
+ }
26
+ $"($ind)\e]6973;PE\a"
27
+ }
28
+ $env.PROMPT_INDICATOR = $__is_custom_PROMPT_INDICATOR
@@ -0,0 +1,24 @@
1
+ $Global:__IsOriginalPrompt = $function:Prompt
2
+
3
+ function Global:__IsTestingPrompt() {
4
+ return "PS > "
5
+ }
6
+ if ($env:ISTERM_TESTING -eq "1") {
7
+ $Global:__IsOriginalPrompt = $function:__IsTestingPrompt
8
+ }
9
+
10
+ function Global:__IS-Escape-Value([string]$value) {
11
+ [regex]::Replace($value, '[\\\n;]', { param($match)
12
+ -Join (
13
+ [System.Text.Encoding]::UTF8.GetBytes($match.Value) | ForEach-Object { '\x{0:x2}' -f $_ }
14
+ )
15
+ })
16
+ }
17
+
18
+ function Global:Prompt() {
19
+ $Result = "$([char]0x1b)]6973;PS`a"
20
+ $Result += $Global:__IsOriginalPrompt.Invoke()
21
+ $Result += "$([char]0x1b)]6973;PE`a"
22
+ $Result += if ($pwd.Provider.Name -eq 'FileSystem') { "$([char]0x1b)]6973;CWD;$(__IS-Escape-Value $pwd.ProviderPath)`a" }
23
+ return $Result
24
+ }
@@ -0,0 +1,29 @@
1
+ import os
2
+
3
+ def __is_prompt_start() -> str:
4
+ return "\001" + "\x1b]6973;PS\x07"
5
+
6
+
7
+ def __is_prompt_end() -> str:
8
+ return "\001" + "\x1b]6973;PE\x07" + "\002"
9
+
10
+
11
+ def __is_escape_value(value: str) -> str:
12
+ byte_list = [bytes([byte]).decode("utf-8") for byte in list(value.encode("utf-8"))]
13
+ return "".join(
14
+ [
15
+ "\\x3b" if byte == ";" else "\\\\" if byte == "\\" else byte
16
+ for byte in byte_list
17
+ ]
18
+ )
19
+
20
+ def __is_update_cwd() -> str:
21
+ return f"\x1b]6973;CWD;{__is_escape_value(os.getcwd())}\x07" + "\002"
22
+
23
+ $PROMPT_FIELDS['__is_prompt_start'] = __is_prompt_start
24
+ $PROMPT_FIELDS['__is_prompt_end'] = __is_prompt_end
25
+ $PROMPT_FIELDS['__is_update_cwd'] = __is_update_cwd
26
+ if 'ISTERM_TESTING' in ${...}:
27
+ $PROMPT = "> "
28
+
29
+ $PROMPT = "{__is_prompt_start}{__is_update_cwd}" + $PROMPT + "{__is_prompt_end}"
@@ -1,12 +0,0 @@
1
- // Copyright (c) Microsoft Corporation.
2
- // Licensed under the MIT License.
3
- import { Command } from "commander";
4
- import { supportedShells } from "../utils/bindings.js";
5
- import { render } from "../ui/ui-bind.js";
6
- const action = async () => {
7
- await render();
8
- };
9
- const cmd = new Command("bind");
10
- cmd.description(`adds keybindings to the selected shell: ${supportedShells.join(", ")}`);
11
- cmd.action(action);
12
- export default cmd;
package/build/ui/input.js DELETED
@@ -1,55 +0,0 @@
1
- // Copyright (c) Microsoft Corporation.
2
- // Licensed under the MIT License.
3
- import React, { useState, useEffect } from "react";
4
- import { useInput, Text } from "ink";
5
- import chalk from "chalk";
6
- const BlinkSpeed = 530;
7
- const CursorColor = "#FFFFFF";
8
- export default function Input({ value, setValue, prompt, activeSuggestion, tabCompletionDropSize, }) {
9
- const [cursorLocation, setCursorLocation] = useState(value.length);
10
- const [cursorBlink, setCursorBlink] = useState(true);
11
- useEffect(() => {
12
- setTimeout(() => {
13
- setCursorBlink(!cursorBlink);
14
- }, BlinkSpeed);
15
- }, [cursorBlink]);
16
- // TODO: arrow key navigation shortcuts (emacs & vim modes)
17
- useInput((input, key) => {
18
- // TODO: handle delete better on unix systems: https://github.com/vadimdemedes/ink/issues/634
19
- const windows = process.platform === "win32";
20
- const backspaceKey = windows ? key.backspace : key.backspace || key.delete;
21
- const deleteKey = windows ? key.delete : false;
22
- if (backspaceKey) {
23
- setValue([...value].slice(0, Math.max(cursorLocation - 1, 0)).join("") + [...value].slice(cursorLocation).join(""));
24
- setCursorLocation(Math.max(cursorLocation - 1, 0));
25
- }
26
- else if (deleteKey) {
27
- setValue([...value].slice(0, cursorLocation).join("") + [...value].slice(Math.min(value.length, cursorLocation + 1)).join(""));
28
- }
29
- else if (key.leftArrow) {
30
- setCursorLocation(Math.max(cursorLocation - 1, 0));
31
- }
32
- else if (key.rightArrow) {
33
- setCursorLocation(Math.min(cursorLocation + 1, value.length));
34
- }
35
- else if (key.tab) {
36
- if (activeSuggestion) {
37
- // TOOD: support insertValue
38
- const newValue = [...value].slice(0, cursorLocation - tabCompletionDropSize).join("") + activeSuggestion.name + " ";
39
- setValue(newValue);
40
- setCursorLocation(newValue.length);
41
- }
42
- }
43
- else if (input) {
44
- setValue([...value].slice(0, cursorLocation).join("") + input + [...value].slice(cursorLocation).join(""));
45
- setCursorLocation(cursorLocation + input.length);
46
- }
47
- });
48
- const cursoredCommand = value + " ";
49
- const cursoredText = [...cursoredCommand].slice(0, cursorLocation).join("") +
50
- (cursorBlink ? chalk.bgHex(CursorColor).inverse([...cursoredCommand].at(cursorLocation)) : [...cursoredCommand].at(cursorLocation)) +
51
- [...cursoredCommand].slice(cursorLocation + 1).join("");
52
- return (React.createElement(Text, null,
53
- prompt,
54
- cursoredText));
55
- }
@@ -1,84 +0,0 @@
1
- // Copyright (c) Microsoft Corporation.
2
- // Licensed under the MIT License.
3
- import React, { useState, useCallback, useEffect } from "react";
4
- import { Text, useInput, Box, measureElement } from "ink";
5
- import wrapAnsi from "wrap-ansi";
6
- const MaxSuggestions = 5;
7
- const SuggestionWidth = 40;
8
- const DescriptionWidth = 30;
9
- const DescriptionMaxHeight = 6;
10
- const BorderWidth = 2;
11
- const ActiveSuggestionBackgroundColor = "#7D56F4";
12
- function Description({ description }) {
13
- wrapAnsi(description, DescriptionWidth, { hard: true });
14
- if (description.length !== 0) {
15
- return (React.createElement(Box, { flexDirection: "column" },
16
- React.createElement(Box, { borderStyle: "single", width: DescriptionWidth },
17
- React.createElement(Text, null, truncateDescription(description, DescriptionMaxHeight)))));
18
- }
19
- }
20
- function truncateDescription(description, maxHeight) {
21
- const wrappedText = wrapAnsi(description, DescriptionWidth - BorderWidth, {
22
- trim: false,
23
- hard: true,
24
- });
25
- const lines = wrappedText.split("\n");
26
- const truncatedLines = lines.slice(0, maxHeight);
27
- if (lines.length > maxHeight) {
28
- truncatedLines[maxHeight - 1] = [...truncatedLines[maxHeight - 1]].slice(0, -1).join("") + "…";
29
- }
30
- return truncatedLines.join("\n");
31
- }
32
- function SuggestionList({ suggestions, activeSuggestionIdx }) {
33
- return (React.createElement(Box, { flexDirection: "column" },
34
- React.createElement(Box, { borderStyle: "single", width: SuggestionWidth, flexDirection: "column" }, suggestions
35
- .map((suggestion, idx) => {
36
- const bgColor = idx === activeSuggestionIdx ? ActiveSuggestionBackgroundColor : undefined;
37
- return (React.createElement(Box, { key: idx },
38
- React.createElement(Text, { backgroundColor: bgColor, wrap: "truncate-end" }, `${suggestion.icon} ${suggestion.name}`.padEnd(SuggestionWidth - BorderWidth, " "))));
39
- })
40
- .filter((node) => node !== undefined))));
41
- }
42
- export default function Suggestions({ leftPadding, setActiveSuggestion, suggestions, }) {
43
- const [activeSuggestionIndex, setActiveSuggestionIndex] = useState(0);
44
- const [windowWidth, setWindowWidth] = useState(500);
45
- const page = Math.floor(activeSuggestionIndex / MaxSuggestions) + 1;
46
- const pagedSuggestions = suggestions.filter((_, idx) => idx < page * MaxSuggestions && idx >= (page - 1) * MaxSuggestions);
47
- const activePagedSuggestionIndex = activeSuggestionIndex % MaxSuggestions;
48
- const activeDescription = pagedSuggestions.at(activePagedSuggestionIndex)?.description || "";
49
- const wrappedPadding = leftPadding % windowWidth;
50
- const maxPadding = activeDescription.length !== 0 ? windowWidth - SuggestionWidth - DescriptionWidth : windowWidth - SuggestionWidth;
51
- const swapDescription = wrappedPadding > maxPadding;
52
- const swappedPadding = swapDescription ? Math.max(wrappedPadding - DescriptionWidth, 0) : wrappedPadding;
53
- const clampedLeftPadding = Math.min(Math.min(wrappedPadding, swappedPadding), maxPadding);
54
- useEffect(() => {
55
- setActiveSuggestion(suggestions[activeSuggestionIndex]);
56
- }, [activeSuggestionIndex, suggestions]);
57
- useEffect(() => {
58
- if (suggestions.length <= activeSuggestionIndex) {
59
- setActiveSuggestionIndex(Math.max(suggestions.length - 1, 0));
60
- }
61
- }, [suggestions]);
62
- useInput((_, key) => {
63
- if (key.upArrow) {
64
- setActiveSuggestionIndex(Math.max(0, activeSuggestionIndex - 1));
65
- }
66
- if (key.downArrow) {
67
- setActiveSuggestionIndex(Math.min(activeSuggestionIndex + 1, suggestions.length - 1));
68
- }
69
- });
70
- const measureRef = useCallback((node) => {
71
- if (node !== null) {
72
- const { width } = measureElement(node);
73
- setWindowWidth(width);
74
- }
75
- }, []);
76
- if (suggestions.length === 0)
77
- return React.createElement(React.Fragment, null);
78
- return (React.createElement(Box, { ref: measureRef },
79
- React.createElement(Box, { paddingLeft: clampedLeftPadding }, swapDescription ? (React.createElement(React.Fragment, null,
80
- React.createElement(Description, { description: activeDescription }),
81
- React.createElement(SuggestionList, { suggestions: pagedSuggestions, activeSuggestionIdx: activePagedSuggestionIndex }))) : (React.createElement(React.Fragment, null,
82
- React.createElement(SuggestionList, { suggestions: pagedSuggestions, activeSuggestionIdx: activePagedSuggestionIndex }),
83
- React.createElement(Description, { description: activeDescription }))))));
84
- }
@@ -1,64 +0,0 @@
1
- // Copyright (c) Microsoft Corporation.
2
- // Licensed under the MIT License.
3
- import React, { useEffect, useState } from "react";
4
- import { Box, Text, render as inkRender, useInput, useApp } from "ink";
5
- import chalk from "chalk";
6
- import { availableBindings, bind, supportedShells } from "../utils/bindings.js";
7
- let uiResult = "";
8
- function UI() {
9
- const { exit } = useApp();
10
- const [selectionIdx, setSelectionIdx] = useState(0);
11
- const [availableShells, setAvailableShells] = useState([]);
12
- useEffect(() => {
13
- availableBindings().then((bindings) => {
14
- if (bindings.length == 0) {
15
- exit();
16
- }
17
- setAvailableShells(bindings);
18
- });
19
- }, []);
20
- useInput(async (_, key) => {
21
- if (key.upArrow) {
22
- setSelectionIdx(Math.max(0, selectionIdx - 1));
23
- }
24
- else if (key.downArrow) {
25
- setSelectionIdx(Math.min(availableShells.length - 1, selectionIdx + 1));
26
- }
27
- else if (key.return) {
28
- await bind(availableShells[selectionIdx]);
29
- uiResult = availableShells[selectionIdx];
30
- exit();
31
- }
32
- });
33
- return (React.createElement(Box, { flexDirection: "column" },
34
- React.createElement(Box, null,
35
- React.createElement(Text, { bold: true }, "Select your desired shell for keybinding creation")),
36
- React.createElement(Box, { flexDirection: "column" },
37
- availableShells.map((shell, idx) => {
38
- if (idx == selectionIdx) {
39
- return (React.createElement(Text, { color: "cyan", underline: true, key: idx },
40
- ">",
41
- " ",
42
- shell));
43
- }
44
- return (React.createElement(Text, { key: idx },
45
- " ",
46
- shell));
47
- }),
48
- supportedShells
49
- .filter((s) => !availableShells.includes(s))
50
- .map((shell, idx) => (React.createElement(Text, { color: "gray", key: idx },
51
- " ",
52
- shell,
53
- " (already bound)"))))));
54
- }
55
- export const render = async () => {
56
- const { waitUntilExit } = inkRender(React.createElement(UI, null));
57
- await waitUntilExit();
58
- if (uiResult.length !== 0) {
59
- process.stdout.write("\n" + chalk.green("✓") + " successfully created new bindings \n");
60
- }
61
- else {
62
- process.stdout.write("\n");
63
- }
64
- };
@@ -1,144 +0,0 @@
1
- // Copyright (c) Microsoft Corporation.
2
- // Licensed under the MIT License.
3
- import os from "node:os";
4
- import path from "node:path";
5
- import fsAsync from "node:fs/promises";
6
- import fs from "node:fs";
7
- import process from "node:process";
8
- import url from "node:url";
9
- const __filename = url.fileURLToPath(import.meta.url);
10
- const __dirname = path.dirname(__filename);
11
- const cacheFolder = ".inshellisense";
12
- export var Shell;
13
- (function (Shell) {
14
- Shell["Bash"] = "bash";
15
- Shell["Powershell"] = "powershell";
16
- Shell["Pwsh"] = "pwsh";
17
- Shell["Zsh"] = "zsh";
18
- Shell["Fish"] = "fish";
19
- })(Shell || (Shell = {}));
20
- export const supportedShells = [Shell.Bash, Shell.Powershell, Shell.Pwsh, Shell.Zsh, Shell.Fish];
21
- const bashScriptCommand = () => {
22
- return `[ -f ~/${cacheFolder}/key-bindings.bash ] && source ~/${cacheFolder}/key-bindings.bash`;
23
- };
24
- const zshScriptCommand = () => {
25
- return `[ -f ~/${cacheFolder}/key-bindings.zsh ] && source ~/${cacheFolder}/key-bindings.zsh`;
26
- };
27
- const fishScriptCommand = () => {
28
- return `[ -f ~/${cacheFolder}/key-bindings.fish ] && source ~/${cacheFolder}/key-bindings.fish`;
29
- };
30
- const powershellScriptCommand = () => {
31
- const bindingsPath = path.join(os.homedir(), cacheFolder, "key-bindings-powershell.ps1");
32
- return `if(Test-Path '${bindingsPath}' -PathType Leaf){. ${bindingsPath}}`;
33
- };
34
- const pwshScriptCommand = () => {
35
- const bindingsPath = path.join(os.homedir(), cacheFolder, "key-bindings-pwsh.ps1");
36
- return `if(Test-Path '${bindingsPath}' -PathType Leaf){. ${bindingsPath}}`;
37
- };
38
- const pwshConfigPath = () => {
39
- switch (process.platform) {
40
- case "win32":
41
- return path.join(os.homedir(), "Documents", "Powershell", "Microsoft.PowerShell_profile.ps1");
42
- case "linux":
43
- case "darwin":
44
- return path.join(os.homedir(), ".config", "powershell", "Microsoft.PowerShell_profile.ps1");
45
- default:
46
- throw new Error("Unsupported platform");
47
- }
48
- };
49
- export const availableBindings = async () => {
50
- const cliConfigPath = path.join(os.homedir(), cacheFolder);
51
- if (!fs.existsSync(cliConfigPath)) {
52
- await fsAsync.mkdir(cliConfigPath);
53
- }
54
- const bindings = [];
55
- const bashConfigPath = path.join(os.homedir(), ".bashrc");
56
- if (!fs.existsSync(bashConfigPath)) {
57
- bindings.push(Shell.Bash);
58
- }
59
- else {
60
- const bashConfigContent = fsAsync.readFile(bashConfigPath, { encoding: "utf-8" });
61
- if (!(await bashConfigContent).includes(bashScriptCommand())) {
62
- bindings.push(Shell.Bash);
63
- }
64
- }
65
- const zshConfigPath = path.join(os.homedir(), ".zshrc");
66
- if (!fs.existsSync(zshConfigPath)) {
67
- bindings.push(Shell.Zsh);
68
- }
69
- else {
70
- const zshConfigContent = fsAsync.readFile(zshConfigPath, { encoding: "utf-8" });
71
- if (!(await zshConfigContent).includes(zshScriptCommand())) {
72
- bindings.push(Shell.Zsh);
73
- }
74
- }
75
- const fishConfigPath = path.join(os.homedir(), ".config", "fish", "config.fish");
76
- if (!fs.existsSync(fishConfigPath)) {
77
- bindings.push(Shell.Fish);
78
- }
79
- else {
80
- const fishConfigContent = fsAsync.readFile(fishConfigPath, { encoding: "utf-8" });
81
- if (!(await fishConfigContent).includes(fishScriptCommand())) {
82
- bindings.push(Shell.Fish);
83
- }
84
- }
85
- const powershellConfigPath = path.join(os.homedir(), "Documents", "WindowsPowershell", "Microsoft.PowerShell_profile.ps1");
86
- if (!fs.existsSync(powershellConfigPath)) {
87
- bindings.push(Shell.Powershell);
88
- }
89
- else {
90
- const powershellConfigContent = fsAsync.readFile(powershellConfigPath, { encoding: "utf-8" });
91
- if (!(await powershellConfigContent).includes(powershellScriptCommand())) {
92
- bindings.push(Shell.Powershell);
93
- }
94
- }
95
- if (!fs.existsSync(pwshConfigPath())) {
96
- bindings.push(Shell.Pwsh);
97
- }
98
- else {
99
- const pwshConfigContent = fsAsync.readFile(pwshConfigPath(), { encoding: "utf-8" });
100
- if (!(await pwshConfigContent).includes(pwshScriptCommand())) {
101
- bindings.push(Shell.Pwsh);
102
- }
103
- }
104
- return bindings;
105
- };
106
- export const bind = async (shell) => {
107
- const cliConfigPath = path.join(os.homedir(), cacheFolder);
108
- if (!fs.existsSync(cliConfigPath)) {
109
- await fsAsync.mkdir(cliConfigPath);
110
- }
111
- switch (shell) {
112
- case Shell.Bash: {
113
- const bashConfigPath = path.join(os.homedir(), ".bashrc");
114
- await fsAsync.appendFile(bashConfigPath, `\n${bashScriptCommand()}`);
115
- await fsAsync.copyFile(path.join(__dirname, "..", "..", "shell", "key-bindings.bash"), path.join(os.homedir(), cacheFolder, "key-bindings.bash"));
116
- break;
117
- }
118
- case Shell.Zsh: {
119
- const zshConfigPath = path.join(os.homedir(), ".zshrc");
120
- await fsAsync.appendFile(zshConfigPath, `\n${zshScriptCommand()}`);
121
- await fsAsync.copyFile(path.join(__dirname, "..", "..", "shell", "key-bindings.zsh"), path.join(os.homedir(), cacheFolder, "key-bindings.zsh"));
122
- break;
123
- }
124
- case Shell.Fish: {
125
- const fishConfigDirectory = path.join(os.homedir(), ".config", "fish");
126
- const fishConfigPath = path.join(fishConfigDirectory, "config.fish");
127
- await fsAsync.mkdir(fishConfigDirectory, { recursive: true });
128
- await fsAsync.appendFile(fishConfigPath, `\n${fishScriptCommand()}`);
129
- await fsAsync.copyFile(path.join(__dirname, "..", "..", "shell", "key-bindings.fish"), path.join(os.homedir(), cacheFolder, "key-bindings.fish"));
130
- break;
131
- }
132
- case Shell.Powershell: {
133
- const powershellConfigPath = path.join(os.homedir(), "Documents", "WindowsPowershell", "Microsoft.PowerShell_profile.ps1");
134
- await fsAsync.appendFile(powershellConfigPath, `\n${powershellScriptCommand()}`);
135
- await fsAsync.copyFile(path.join(__dirname, "..", "..", "shell", "key-bindings-powershell.ps1"), path.join(os.homedir(), cacheFolder, "key-bindings-powershell.ps1"));
136
- break;
137
- }
138
- case Shell.Pwsh: {
139
- await fsAsync.appendFile(pwshConfigPath(), `\n${pwshScriptCommand()}`);
140
- await fsAsync.copyFile(path.join(__dirname, "..", "..", "shell", "key-bindings-pwsh.ps1"), path.join(os.homedir(), cacheFolder, "key-bindings-pwsh.ps1"));
141
- break;
142
- }
143
- }
144
- };
@@ -1,21 +0,0 @@
1
- // Copyright (c) Microsoft Corporation.
2
- // Licensed under the MIT License.
3
- import os from "node:os";
4
- import path from "node:path";
5
- import fsAsync from "node:fs/promises";
6
- import fs from "node:fs";
7
- const cacheFolder = ".inshellisense";
8
- const folderPath = path.join(os.homedir(), cacheFolder);
9
- const cachePath = path.join(os.homedir(), cacheFolder, "inshellisense.cache");
10
- export const saveCommand = async (command) => {
11
- if (!fs.existsSync(folderPath)) {
12
- await fsAsync.mkdir(folderPath);
13
- }
14
- await fsAsync.writeFile(cachePath, command.map((c, idx) => `${idx.toString().padStart(5)} ${c}`).join("\n"));
15
- };
16
- export const loadCommand = async () => {
17
- if (!fs.existsSync(folderPath)) {
18
- await fsAsync.mkdir(folderPath);
19
- }
20
- return fsAsync.readFile(cachePath, { encoding: "utf-8" });
21
- };
@@ -1,27 +0,0 @@
1
- Set-PSReadLineKeyHandler -Chord 'Ctrl+a' -ScriptBlock {
2
- $command = $null
3
- [Microsoft.PowerShell.PSConsoleReadLine]::GetBufferState([ref]$command, [ref]$null)
4
-
5
- $oldPrompt = $function:prompt
6
- function prompt { "`r" }
7
- [Microsoft.PowerShell.PSConsoleReadLine]::InvokePrompt()
8
- $prompt = $oldPrompt
9
-
10
- [Microsoft.PowerShell.PSConsoleReadLine]::ClearKillRing()
11
- [Microsoft.PowerShell.PSConsoleReadLine]::BeginningOfLine()
12
- [Microsoft.PowerShell.PSConsoleReadLine]::KillLine()
13
- [Microsoft.PowerShell.PSConsoleReadLine]::AcceptLine()
14
-
15
- $inshellisense = "$env:USERPROFILE\AppData\Roaming\npm\node_modules\@microsoft\inshellisense\build\index.js"
16
- if ($command) {
17
- Start-Process -NoNewWindow -Wait "node" "$inshellisense -c $command -s powershell"
18
- }
19
- else {
20
- Start-Process -NoNewWindow -Wait "node" "$inshellisense -s powershell"
21
- }
22
-
23
- $executedCommand = node $inshellisense --history
24
- if ($executedCommand) {
25
- [Microsoft.PowerShell.PSConsoleReadLine]::AddToHistory($executedCommand)
26
- }
27
- }
@@ -1,27 +0,0 @@
1
- Set-PSReadLineKeyHandler -Chord 'Ctrl+a' -ScriptBlock {
2
- $command = $null
3
- [Microsoft.PowerShell.PSConsoleReadLine]::GetBufferState([ref]$command, [ref]$null)
4
-
5
- $oldPrompt = $function:prompt
6
- function prompt { "`r" }
7
- [Microsoft.PowerShell.PSConsoleReadLine]::InvokePrompt()
8
- $prompt = $oldPrompt
9
-
10
- [Microsoft.PowerShell.PSConsoleReadLine]::ClearKillRing()
11
- [Microsoft.PowerShell.PSConsoleReadLine]::BeginningOfLine()
12
- [Microsoft.PowerShell.PSConsoleReadLine]::KillLine()
13
-
14
- $inshellisense = "$env:USERPROFILE\AppData\Roaming\npm\node_modules\@microsoft\inshellisense\build\index.js"
15
- if ($command) {
16
- Start-Process -NoNewWindow -Wait "node" "$inshellisense -c $command -s pwsh"
17
- }
18
- else {
19
- Start-Process -NoNewWindow -Wait "node" "$inshellisense -s pwsh"
20
- }
21
-
22
- $executedCommand = node $inshellisense --history
23
- if ($executedCommand) {
24
- [Microsoft.PowerShell.PSConsoleReadLine]::AddToHistory($executedCommand)
25
- }
26
- [Microsoft.PowerShell.PSConsoleReadLine]::AcceptLine()
27
- }
@@ -1,7 +0,0 @@
1
- __inshellisense__() {
2
- inshellisense -c "$READLINE_LINE" -s bash
3
- history -s $(inshellisense --history)
4
- READLINE_LINE=
5
- }
6
-
7
- bind -x '"\C-a": __inshellisense__'
@@ -1,8 +0,0 @@
1
- function inshellisense-widget -d "Activate autocomplete"
2
- inshellisense -c (commandline -b) -s fish
3
- commandline -r ''
4
- commandline -f repaint
5
- # TODO: add support for history insertion
6
- end
7
-
8
- bind \ca inshellisense-widget
@@ -1,10 +0,0 @@
1
- __inshellisense__() {
2
- input=$LBUFFER
3
- LBUFFER=
4
- inshellisense -c "$input" -s zsh < $TTY
5
- print -s $(inshellisense --history)
6
- zle reset-prompt
7
- }
8
-
9
- zle -N __inshellisense __inshellisense__
10
- bindkey '^A' __inshellisense