Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

List and prompt #3

Merged
merged 17 commits into from
Jul 15, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 13 additions & 4 deletions .ok
Original file line number Diff line number Diff line change
@@ -1,4 +1,13 @@
# Manipulate customizations (colors)
unset _OK_C_HEADING;unset _OK_C_NUMBER;unset _OK_C_COMMENT;unset _OK_C_COMMAND;unset _OK_C_PROMPT #Reset colors to defaults
_OK_C_HEADING="[h]";_OK_C_NUMBER="[n]";_OK_C_COMMENT="[--]";_OK_C_COMMAND="[C]";_OK_C_PROMPT="[p]" #Change colors to text markers for debugging
_OK_C_HEADING=$'\033[1;30;45m';_OK_C_NUMBER=$'\033[1;33;44m';_OK_C_COMMENT=$'\033[1;34;46m';_OK_C_COMMAND=$'\033[1;37;44m' #Custom color scheme
# Manipulate customizations (colors)
unset _OK_C_HEADING;unset _OK_C_NUMBER;unset _OK_C_COMMENT;unset _OK_C_COMMAND;unset _OK_C_PROMPT #Reset colors to defaults
_OK_C_HEADING="[h]";_OK_C_NUMBER="[n]";_OK_C_COMMENT="[--]";_OK_C_COMMAND="[C]";_OK_C_PROMPT="[p]" #Change colors to text markers for debugging
_OK_C_HEADING=$'\033[1;30;45m';_OK_C_NUMBER=$'\033[1;33;44m ';_OK_C_COMMENT=$'\033[1;34;46m';_OK_C_COMMAND=$'\033[1;37;44m' #Custom color scheme
# Other customizations
unset _OK_PROMPT; unset _OK_VERBOSE # Reset to defaults
_OK_PROMPT="-=> "; _OK_VERBOSE=2 # Show a "nice" prompt, and give all the feedback ok can provide for
_OK_PROMPT="% "; _OK_VERBOSE=0 # Show ancient prompt, and only say the most necessary (don't even show executed command)

# Tests arguments passing (you can pass arguments after <number>, both at the bash-prompt and the ok-prompt)
echo "Passed arguments: 1:[$1], 2:[$2], 3:[$3], 4+:[${@:4}] (nr args: $#)" # Comment-color starts too early; clearly a bug (so better
echo "All passed arguments: [$@]" # not to use a number sign in a command for now)...
ok help --verbose # Show help page of 🆗, including environment variables
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
## "ok" gives you .ok folder profiles for bash


💡 Tip: "." (i.e. source) the "ok" script from your profile (.bashrc), e.g:
💡 Tip: "." (i.e. source) the "ok.sh" script from your profile (.bashrc), e.g:

. ~/ok
. ~/ok.sh

See <http://secretgeek.net/ok> for description of how to use "ok"

Expand Down
42 changes: 0 additions & 42 deletions ok

This file was deleted.

155 changes: 155 additions & 0 deletions ok.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
#!/usr/bin/env bash

# tip: "." (i.e. source) this file from your profile (.bashrc), e.g. ". ~/path/to/ok-bash/ok.sh"

ok() {
function _ok_cmd_usage {
unset -f _ok_cmd_usage #emulate a "local" function
echo -e "Usage: ok [options] <number> [script-arguments..]
ok command [options]

command (use one):
<number> Run the <number>th command from the '.ok' file.
l, list Show the list from the '.ok' file.
L, list-once Same as list, but only show when pwd is different from when the list was last shown.
p, list-prompt Show the list and wait for input at the ok-prompt (like --list and <number> in one command). Default command.
h, help Show this usage page.
options:
-v, --verbose Show more output, most of the time to stderr.
-q, --quiet Only show really necessary output.
script-arguments:
... These are passed through, when a line is executed (you can enter these too at the ok-prompt)\n"

if [[ $verbose -ge 2 ]]; then
if [ -z ${_OK_PROMPT+x} ]; then local p="unset"; else local p="'$_OK_PROMPT'"; fi
if [ -z ${_OK_VERBOSE+x} ]; then local v="unset"; else local v="'$_OK_VERBOSE'"; fi
echo -e "environment variables (used for colored output; current colors are shown):
_OK_C_HEADING ${_OK_C_HEADING}Color-code${C_NC} for lines starting with a comment (heading). Defaults to red.
_OK_C_NUMBER ${_OK_C_NUMBER}Color-code${C_NC} for numbering. Defaults to cyan.
_OK_C_COMMENT ${_OK_C_COMMENT}Color-code${C_NC} for comments after commands. Defaults to blue.
_OK_C_COMMAND ${_OK_C_COMMAND}Color-code${C_NC} for commands. Defaults to color-reset.
_OK_C_PROMPT ${_OK_C_PROMPT}Color-code${C_NC} for prompt (both input as command confirmation). Defaults to color for numbering.
environment variables (other):
_OK_PROMPT String ($p) used as prompt (both input as command confirmation). Defaults to '$ '.
_OK_VERBOSE Level ($v) of feedback ok provides. 0=quiet, 1=normal, 2=verbose. Defaults to 1. Can be overriden with --verbose or --quiet.\n"
fi
if [[ -n $1 ]]; then
echo -e "$1\n"
return 1
fi
}

function _ok_cmd_run {
unset -f _ok_cmd_run
# save and remove argument. Remaining arguments are passwed to eval automatically
local LINE_NR=$1 #LINE_NR is guaranteed to be 1 or more
shift
# get the line to be executed
local LINE_TEXT=$( cat .ok | grep -vE "^(#|$)" | sed ${LINE_NR}'!d' )
if [[ -n $LINE_TEXT ]]; then
if [[ $verbose -ge 1 ]]; then
# output the command first
echo -e "${C_PROMPT}${PROMPT}${C_COMMAND}${LINE_TEXT}${C_NC}" | sed -E "s/(#.*)\$/${C_COMMENT}\1/1"
fi
# finally execute the line
eval $LINE_TEXT
else
if [[ $verbose -ge 2 ]]; then
>&2 echo "ERROR: entered line number '$LINE_NR' does not exist"
fi
return 1
fi
}

function _ok_cmd_list {
unset -f _ok_cmd_list
# list the content of the file, with a number (1-based) before each line,
# except lines starting with a "#", those are printed red without a number) as headers
cat .ok | awk -v h="$C_HEADING" -v n="$C_NUMBER" -v c="$C_COMMENT" -v m="$C_COMMAND" -v x="$C_NC" $'
$0 ~ /^(#|$)/ {
#print the (sub-)headings and/or empty lines
print x h $0 x;
}
$0 ~ /^[^#]/ {
#print the commands
sub(/#/,c "#");
print x n "" ++i "." m " " $0 x;
}'
}

# used for colored output (see: https://stackoverflow.com/a/20983251/56)
local C_NC=$(tput sgr 0)
if [ -z ${_OK_C_HEADING+x} ]; then local C_HEADING=$(tput setaf 1); else local C_HEADING=$_OK_C_HEADING; fi #HEADING defaults to RED
if [ -z ${_OK_C_NUMBER+x} ]; then local C_NUMBER=$(tput setaf 6); else local C_NUMBER=$_OK_C_NUMBER; fi #NUMBER defaults to CYAN
if [ -z ${_OK_C_COMMENT+x} ]; then local C_COMMENT=$(tput setaf 4); else local C_COMMENT=$_OK_C_COMMENT; fi #COMMENT defaults to BLUE
if [ -z ${_OK_C_COMMAND+x} ]; then local C_COMMAND=$C_NC; else local C_COMMAND=$_OK_C_COMMAND; fi #COMMAND defaults to NO COLOR
if [ -z ${_OK_C_PROMPT+x} ]; then local C_PROMPT=$C_NUMBER; else local C_PROMPT=$_OK_C_PROMPT; fi #PROMPT defaults to same color as NUMBER
# other customizations (some environment variables can be overridden by arguments)
if [ -z ${_OK_PROMPT+x} ]; then local PROMPT="$ "; else local PROMPT=$_OK_PROMPT; fi
if [ -z ${_OK_VERBOSE+x} ]; then local verbose=1; else local verbose=$_OK_VERBOSE; fi

# handle command line arguments first
local re_is_num='^[1-9][0-9]*$' #numbers starting with "0" would be octal, and nobody knows those (also: sed on Linux complains about line "0")...
local cmd=list
local line_nr=0
local once_check=0
local show_prompt=1
local usage_error=
local loop_args=1 #the Pascal-way to break loops
while (( $# > 0 && $loop_args == 1 )) ; do
# if the user provided a parameter, $1, which contains a number...
if [[ $1 =~ $re_is_num ]]; then
cmd=run
line_nr=$1
loop_args=0
else
case $1 in
#commands
l | list) cmd=list; show_prompt=0; once_check=0;;
L | list-once) cmd=list; show_prompt=0; once_check=1;;
p | list-prompt) cmd=list; show_prompt=1; once_check=0;;
h | help) cmd=usage;;
#options
-\? | -h | --help) cmd=usage;;
-v | --verbose) verbose=2;;
-q | --quiet) verbose=0;;
*) cmd=usage; usage_error="Unknown command/option '$1'";;
esac
fi
shift
done

# if there is a file called .ok...
if [ -f .ok ]; then
if [[ $cmd == run ]]; then
_ok_cmd_run $line_nr "$@" || return $?
elif [[ $cmd == list ]]; then
if [[ $once_check == 0 || ($once_check == 1 && $_OK_LAST_PWD != $(pwd)) ]]; then
_ok_cmd_list || return $?
if [[ $show_prompt == 1 ]]; then
local prompt_input
local re_num_begin='^[1-9][0-9]*($| )' # You can enter arguments at the ok-prompt too, hence different regex
read -p "${C_PROMPT}${PROMPT}${C_NC}" prompt_input
if [[ $prompt_input =~ $re_num_begin ]]; then
eval _ok_cmd_run $prompt_input || return $?
else
if [[ $verbose -ge 2 ]]; then
>&2 echo "ERROR: input '$prompt_input' does not start with a number"
fi
return 1
fi
fi
fi
if [[ $verbose -ge 2 && $once_check == 1 && $_OK_LAST_PWD == $(pwd) ]]; then
echo "The listing for this folder has already been shown"
fi
export _OK_LAST_PWD=$(pwd)
elif [[ $cmd == usage ]]; then
_ok_cmd_usage "$usage_error" || return $?
fi
else
if [[ $verbose -ge 2 ]]; then
echo "Nothing to do: this folder doesn't have an '.ok' file"
fi
fi
}