Skip to content

Commit ffc5d6b

Browse files
authored
Add bash support (#30)
* Add bash keybindings file * Update install script to install bash keybinds * Update readme
1 parent cb342f5 commit ffc5d6b

File tree

3 files changed

+75
-36
lines changed

3 files changed

+75
-36
lines changed

README.md

+5-6
Original file line numberDiff line numberDiff line change
@@ -56,11 +56,11 @@ Key features of ShellOracle include:
5656
Installing ShellOracle is easy!
5757

5858
1. First, pip install the `shelloracle` package
59-
```zsh
59+
```shell
6060
python3 -m pip install shelloracle
6161
```
6262
2. Next, run `shelloracle --init` and follow the prompts
63-
```zsh
63+
```shell
6464
python3 -m shelloracle --init
6565
```
6666

@@ -69,7 +69,7 @@ Installing ShellOracle is easy!
6969

7070
## Usage
7171

72-
ShellOracle is designed to be used as a ZSH Line Editor widget activated by the CTRL+F keyboard shortcut.
72+
ShellOracle is designed to be used as a BASH/ZSH widget activated by the CTRL+F keyboard shortcut.
7373

7474
1. Press CTRL+F
7575
2. Describe your command or goal
@@ -82,7 +82,7 @@ The generated command will be inserted into your shell prompt after a brief proc
8282
Before using ShellOracle with Ollama, pull the model you want to use. The default model is `codellama:13b`. To pull the
8383
default model, run:
8484

85-
```zsh
85+
```shell
8686
ollama pull codellama:13b
8787
```
8888

@@ -152,8 +152,7 @@ system_prompt = "..."
152152

153153
### Software
154154

155-
ShellOracle supports ZSH on macOS and Linux. Bash support is planned; however, it is not currently
156-
supported.
155+
ShellOracle supports BASH and ZSH on macOS and Linux.
157156

158157
### Hardware
159158

src/shelloracle/bootstrap.py

+50-30
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import os
1+
import subprocess
22
from pathlib import Path
33

44
from prompt_toolkit import print_formatted_text
@@ -20,50 +20,70 @@ def replace_home_with_tilde(path: Path) -> Path:
2020
return Path("~") / relative_path
2121

2222

23-
def ensure_zsh() -> None:
24-
shell = os.environ.get("SHELL")
25-
if shell is None:
26-
print_error("Unable to determine shell environment. If you are confident "
27-
"that you are running in zsh, run again with `SHELL=zsh python3 -m shelloracle --init`")
28-
exit(1)
29-
if "zsh" not in shell:
30-
print_error(f"'{shell}' is currently unsupported. "
31-
f"Please open an issue https://github.com/djcopley/ShellOracle/issues.")
32-
exit(1)
23+
supported_shells = ["zsh", "bash"]
3324

3425

35-
zshrc_path = Path.home() / ".zshrc"
36-
shelloracle_zsh_dest = Path.home() / ".shelloracle.zsh"
26+
def get_installed_shells() -> list[str]:
27+
shells = []
28+
for shell in supported_shells:
29+
if subprocess.run(["command", "-v", shell], stdout=subprocess.DEVNULL):
30+
shells.append(shell)
31+
return shells
3732

3833

39-
def write_shelloracle_zsh() -> None:
40-
zsh_path = Path(__file__).parent.absolute() / "shelloracle.zsh"
41-
shelloracle_zsh = zsh_path.read_bytes()
42-
shelloracle_zsh_dest.write_bytes(shelloracle_zsh)
43-
print_info(f"Successfully wrote key bindings to {replace_home_with_tilde(shelloracle_zsh_dest)}")
34+
def get_bundled_script_path(shell: str) -> Path:
35+
parent = Path(__file__).parent
36+
if shell == "zsh":
37+
return parent / "shelloracle.zsh"
38+
elif shell == "bash":
39+
return parent / "shelloracle.bash"
4440

4541

46-
def update_zshrc() -> None:
47-
zshrc_path.touch(exist_ok=True)
48-
with zshrc_path.open("r") as file:
42+
def get_script_path(shell: str) -> Path:
43+
if shell == "zsh":
44+
return Path.home() / ".shelloracle.zsh"
45+
elif shell == "bash":
46+
return Path.home() / ".shelloracle.bash"
47+
48+
49+
def get_rc_path(shell: str) -> Path:
50+
if shell == "zsh":
51+
return Path.home() / ".zshrc"
52+
elif shell == "bash":
53+
return Path.home() / ".bashrc"
54+
55+
56+
def write_script_home(shell: str) -> None:
57+
shelloracle = get_bundled_script_path(shell).read_bytes()
58+
destination = get_script_path(shell)
59+
destination.write_bytes(shelloracle)
60+
print_info(f"Successfully wrote key bindings to {replace_home_with_tilde(destination)}")
61+
62+
63+
def update_rc(shell: str) -> None:
64+
rc_path = get_rc_path(shell)
65+
rc_path.touch(exist_ok=True)
66+
with rc_path.open("r") as file:
4967
zshrc = file.read()
50-
line = f"[ -f {shelloracle_zsh_dest} ] && source {shelloracle_zsh_dest}"
68+
shelloracle_script = get_script_path(shell)
69+
line = f"[ -f {shelloracle_script} ] && source {shelloracle_script}"
5170
if line not in zshrc:
52-
with zshrc_path.open("a") as file:
71+
with rc_path.open("a") as file:
5372
file.write("\n")
5473
file.write(line)
55-
print_info(f"Successfully updated {replace_home_with_tilde(zshrc_path)}")
74+
print_info(f"Successfully updated {replace_home_with_tilde(rc_path)}")
5675

5776

5877
def bootstrap() -> None:
5978
with create_app_session_from_tty():
60-
ensure_zsh()
61-
62-
if confirm("Enable terminal keybindings?", suffix=" ([y]/n) ") is False:
79+
if not (shells := get_installed_shells()):
80+
print_error(f"No compatible shells found. Supported shells: {', '.join(supported_shells)}")
6381
return
64-
65-
write_shelloracle_zsh()
66-
update_zshrc()
82+
if confirm("Enable terminal keybindings and update rc ?", suffix=" ([y]/n) ") is False:
83+
return
84+
for shell in shells:
85+
write_script_home(shell)
86+
update_rc(shell)
6787

6888

6989
if __name__ == '__main__':

src/shelloracle/shelloracle.bash

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
__shelloracle__() {
2+
local output
3+
output=$(python3 -m shelloracle) || return
4+
READLINE_LINE=${output#*$'\t'}
5+
if [[ -z "$READLINE_POINT" ]]; then
6+
echo "$READLINE_LINE"
7+
else
8+
READLINE_POINT=0x7fffffff
9+
fi
10+
}
11+
12+
if (( BASH_VERSINFO[0] < 4 )); then
13+
bind -m emacs-standard '"\C-f": "\C-e \C-u\C-y\ey\C-u"$(__shelloracle__)"\e\C-e\er"'
14+
bind -m vi-command '"\C-f": "\C-z\C-r\C-z"'
15+
bind -m vi-insert '"\C-f": "\C-z\C-r\C-z"'
16+
else
17+
bind -m emacs-standard -x '"\C-f": __shelloracle__'
18+
bind -m vi-command -x '"\C-f": __shelloracle__'
19+
bind -m vi-insert -x '"\C-f": __shelloracle__'
20+
fi

0 commit comments

Comments
 (0)