Skip to content

Commit

Permalink
Merge pull request #36 from secretGeek/zsh-support
Browse files Browse the repository at this point in the history
Works with zsh
  • Loading branch information
doekman authored Aug 16, 2022
2 parents eeab518 + fa735d7 commit 2032fed
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 19 deletions.
1 change: 1 addition & 0 deletions .ok
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ _OK_PROMPT="% "; _OK_VERBOSE=0; _OK_PROMPT_DEFAULT=0; _OK_COMMENT_ALIGN=0 # Show
args: echo "Passed arguments: 1:[$1], 2:[$2], 3:[$3], 4+:[${*:4}] (nr args: $#)" # Comment-color starts too early; clearly a bug (so better
args-all: echo "All passed arguments (no comment on this line): [$*]"
cd test
test: shellcheck -x ok.sh

env-reset: for x in $(set|grep "^_OK_[^_]"|awk -F = '{print $1}');do unset "$x";done # for when updating README help part
ok --verbose help # Show help page of 🆗, including environment variables
Expand Down
26 changes: 20 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
See <http://secretgeek.net/ok> for the blog post launching (and describing) "ok".


## "ok" gives you .ok folder profiles for bash
## "ok" gives you .ok folder profiles for shell scripts

(There is also a [PowerShell version](https://github.com/secretGeek/ok-ps/))
`ok-bash` Works with `bash` and `zsh` shells (There is also a [PowerShell version](https://github.com/secretGeek/ok-ps/)). See also [shell support](#shell-support).

`ok` makes you smarter and more efficient.

Expand Down Expand Up @@ -57,7 +57,7 @@ And you can pass simple arguments to the commands. For example:

Clone the git-repository (`git clone https://github.com/secretGeek/ok-bash.git`), so you can easily update it with a `git pull`.

Install it by "." (i.e. dot-sourcing) the "ok.sh" script from your `~/.bashrc` (or your favorite [initialization script][bashrc]), e.g:
Install it by "." (i.e. dot-sourcing) the "ok.sh" script from your `~/.bashrc` (or your favorite [initialization][bashrc] [script][zshrc]), e.g:

. ~/path/to/ok-bash/ok.sh

Expand Down Expand Up @@ -108,7 +108,7 @@ When you now run `ok` you will see this:

To run the second (now named) line, you can type `ok deploy`, but running `ok 2` still works. You don't even need to type the whole command: only the part from the left that's unique within the ok-file is enough. In this case that would be `ok d`, because no other command starts with the letter "d". The unique part of the name will be printed slightly brighter, if your terminal supports it.

You can't use every text as a command name. The first character has to be a letter or underscore (`_`). After this, you also can use numbers, a dash (`-`) or a period (`.`). The command has to be ASCII and is interpreted case-sensitive. You can put whitespace around it, but that will be stripped because _ok-bash_ does some formatting so it looks nice.
You can't use every text as a command name. The first character has to be a letter or underscore (`_`). After this, you also can use numbers, a dash (`-`) or a period (`.`). The command has to be ASCII and is interpreted case-sensitive. You can put whitespace around it, but that will be stripped because _ok-sh_ does some formatting so it looks nice.


## Auto completion
Expand Down Expand Up @@ -299,7 +299,7 @@ On Linux machines with multiple users, it makes sense to have a shared installat

Why install in `/opt`? I guess this would be [the best location](https://en.wikipedia.org/wiki/Filesystem_Hierarchy_Standard). After all: `ok-bash` only works with _scripts_, not _binaries_.

If you want all users to automatically have _ok-bash_ initialized:
If you want all users to automatically have _ok-sh_ initialized:

echo ". /opt/ok-bash/ok.sh" | sudo tee "/etc/profile.d/ok-bash.sh"

Expand All @@ -310,9 +310,23 @@ For per-user use, add something like this to the `~/.bashrc`¹:
. /opt/ok-bash/ok.sh


¹) or your favorite [initialization script][bashrc]
¹) or your favorite [initialization][bashrc] [script][zshrc].

[bashrc]: https://www.gnu.org/software/bash/manual/html_node/Bash-Startup-Files.html "Bash Startup Files"
[zshrc]: https://zsh.sourceforge.io/Doc/Release/Files.html#Files "Zsh Startup/Shutdown Files"


## Shell support

Bash is supported, starting with version 3.2, which is installed on macOS, and up (most Linux installations).

Zsh is also supported, but some notes:

* autocomplete is not supported at the moment
* and you have to consider a bit of different behaviour you get with bash:
- when sourcing ok.sh in the current folder, a path is needed (`. ok.sh` fails, but `. ./ok.sh` works)
- when running `./ok.sh` as a script, zsh needs bash to execute the script, because of the `env`-construct.


## Development

Expand Down
53 changes: 40 additions & 13 deletions ok.sh
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
#!/usr/bin/env bash

called=$_

#basically, get the absolute path of this script (handy for loads of things)
pushd "$(dirname "${BASH_SOURCE[0]}")" > /dev/null || (>&2 echo "ok-bash: pushd failed")
pushd "$(dirname "${BASH_SOURCE[0]:-$0}")" > /dev/null || (>&2 echo "ok-sh: pushd failed")
_OK__PATH_TO_ME=$(pwd)
popd > /dev/null || (>&2 echo "ok-bash: popd failed")
popd > /dev/null || (>&2 echo "ok-sh: popd failed")

# Don't let ok-show.py's shebang control the python version; prefer python3 above python regular (2)
_OK__PATH_TO_PYTHON=$(command -v python3 || command -v python)
Expand Down Expand Up @@ -114,7 +112,7 @@ environment variables (for internal use):
eval "$line_text"
}

local -r version="0.8.4dev"
local -r version="0.9.0dev"
# used for colored output (see: https://stackoverflow.com/a/20983251/56)
# notice: this is partly a duplication from code in ok-show.py
local -r c_nc=$'\033''[0m'
Expand Down Expand Up @@ -186,11 +184,11 @@ environment variables (for internal use):
elif [[ $cmd == usage ]]; then
_ok_cmd_usage "$usage_error" || return $?
elif [[ $cmd == version ]]; then
echo "ok-bash $version"
echo "ok-sh $version"
elif [[ - == "$ok_file" || -r "$ok_file" ]]; then
if [[ $cmd == run ]]; then
_ok_cmd_run "$external_command" "$@" || return $?
elif [[ $cmd =~ \..+ ]]; then
elif [[ $cmd =~ [.].+ ]]; then
if [[ $verbose -ge 2 ]]; then
echo "Running system command '$cmd'"
fi
Expand All @@ -204,11 +202,19 @@ environment variables (for internal use):
elif [[ $show_prompt == 1 && $list_result == 0 ]]; then #only show prompt, if there where commands printed
local prompt_input
local re_num_begin="${re_begins_with_cmd}($| )" # You can enter arguments at the ok-prompt too, hence different regex
# Show a prompt (read -p "XXX" fails in zsh)
echo -n "${c_prompt}${prompt}${c_nc}"
# The following read doesn't work in a sub-shell, so list-prompt fails when using it in a script
read -rp "${c_prompt}${prompt}${c_nc}" prompt_input
read -r prompt_input
if [[ $prompt_input =~ $re_num_begin ]]; then
#save command to history first
history -s "$args $prompt_input"
if [ -n "${ZSH_VERSION+x}" ]; then
# The Zsh way to do it
builtin print -s "$args $prompt_input"
else
# The Bash way to do it
builtin history -s "$args $prompt_input"
fi
#execute command
eval _ok_cmd_run "$prompt_input" || return $?
else
Expand All @@ -225,6 +231,10 @@ environment variables (for internal use):
fi
_OK__LAST_PWD=$(pwd)
export _OK__LAST_PWD
else
if [[ $verbose -ge 2 ]]; then
echo "Unknown command/state: '$cmd'"
fi
fi
else
if [[ $cmd == list ]]; then
Expand All @@ -237,7 +247,18 @@ environment variables (for internal use):
fi
}

if [[ "$called" == "$0" ]]; then
is_sourced=""
if [ "${ZSH_ARGZERO:+IS_SET}" = "IS_SET" ]; then
if [ "$ZSH_ARGZERO" = "zsh" ]; then
is_sourced="yes_indeed"
fi
else
if [ "$0" = "-bash" ]; then
is_sourced="yes_indeed"
fi
fi

if [ -z "$is_sourced" ]; then
if [[ -z "$_OK__PATH_TO_PYTHON" ]]; then
>&2 echo "ERROR: python is required to run 'ok', but can't be found"
exit 1
Expand All @@ -246,7 +267,7 @@ if [[ "$called" == "$0" ]]; then
shift
ok "$@"
else
# tip: "." (i.e. source) this file from your profile (.bashrc), e.g. ". ~/path/to/ok-bash/ok.sh"
# tip: "." (i.e. source) this file from your profile (.bashrc), e.g. ". ~/path/to/ok-sh/ok.sh"
echo -e "tip: \".\" (i.e. source) this file from your ~/.profile, e.g. \". ${_OK__PATH_TO_ME/$HOME/~}/ok.sh <arguments>\"
arguments, if you need to customize (these can also be set via arguments/environment):
Expand Down Expand Up @@ -275,7 +296,14 @@ else
comment_align) if [[ $# -ge 2 ]]; then export _OK_COMMENT_ALIGN=$2; shift; else >&2 echo "the comment_align argument needs a number (0..3) as 2nd argument"; fi;;
verbose) export _OK_VERBOSE=2;;
quiet) export _OK_VERBOSE=0;;
auto_show) if [[ ! $PROMPT_COMMAND =~ $re_list_once ]]; then export PROMPT_COMMAND="${PROMPT_COMMAND}"$'\n'"${re_list_once}"; fi;;
auto_show) if [ -n "${ZSH_VERSION+x}" ]; then
function _zsh_list_once {
ok list-once
}
precmd_functions+=( _zsh_list_once )
else
if [[ ! $PROMPT_COMMAND =~ $re_list_once ]]; then export PROMPT_COMMAND="${PROMPT_COMMAND}"$'\n'"${re_list_once}"; fi
fi;;
*) >&2 echo "Ignoring unknown argument '$1'";;
esac
shift
Expand All @@ -291,4 +319,3 @@ else
. "${_OK__PATH_TO_ME}/ok-complete.bash"
fi
fi
unset called

0 comments on commit 2032fed

Please sign in to comment.