v0.3
This commit is contained in:
parent
1eed56422a
commit
19860fe8db
85
README
85
README
@ -1,31 +1,23 @@
|
|||||||
********
|
|
||||||
G (GOTO)
|
|
||||||
********
|
|
||||||
|
|
||||||
A faster way to cd to commonly used directories. Inspired by commacd. Tested on
|
A faster way to cd to commonly used directories. Inspired by commacd. Tested on
|
||||||
Bash 5.1, but should work on most versions.
|
Bash and Dash.
|
||||||
|
|
||||||
Installation
|
Installation
|
||||||
************
|
============
|
||||||
|
|
||||||
On most operatin systems with Bash run::
|
On most operatin systems with Bash run:
|
||||||
|
|
||||||
$ curl -o ~/.goto.sh \
|
|
||||||
-sSL https://gitea.gch.icu/ge/goto/raw/branch/master/goto.sh
|
|
||||||
$ echo '[ -f ~/.goto.sh ] && . ~/.goto.sh' >> ~/.bashrc
|
|
||||||
|
|
||||||
Reread ~/.bashrc by command::
|
|
||||||
|
|
||||||
|
$ curl -o ~/.g.sh -sSL https://git.nxhs.cloud/ge/g/raw/branch/master/g.sh
|
||||||
|
$ echo '[ -f ~/.g.sh ] && . ~/.g.sh' >> ~/.bashrc
|
||||||
$ source ~/.bashrc
|
$ source ~/.bashrc
|
||||||
|
|
||||||
Usage
|
Usage
|
||||||
*****
|
=====
|
||||||
|
|
||||||
Available commands (actually is aliases to functions)::
|
Available commands (actually is aliases to functions):
|
||||||
|
|
||||||
g [<pattern>] goto directory. If you have single bookmark dir will be
|
g [<pattern>] goto directory. If you have single bookmark dir will be
|
||||||
changed without prompt. Type dir number in prompt to cd.
|
changed without prompt. Type dir number in prompt to cd.
|
||||||
g-save [<path>] bookmark $PWD or <path> (save into ~/.goto_saved).
|
g_save [<path>] bookmark $PWD or <path> (save into ~/.g).
|
||||||
|
|
||||||
Run `g` to show the entire list of bookmarks and select the one you need.
|
Run `g` to show the entire list of bookmarks and select the one you need.
|
||||||
|
|
||||||
@ -34,10 +26,10 @@ the bookmark number. The exception is when you have a two-digit number (or more)
|
|||||||
and you select a bookmark whose number is less than 10. Then you have to press
|
and you select a bookmark whose number is less than 10. Then you have to press
|
||||||
`Enter`.
|
`Enter`.
|
||||||
|
|
||||||
You can pass the Perl regular expression (processed by grep -Pi) as an for 'g'.
|
You can pass the Perl regular expression (processed by grep -Pi) as an for `g`.
|
||||||
At the same time, if only one bookmark is found, then the directory will be
|
At the same time, if only one bookmark is found, then the directory will be
|
||||||
changed directly to it. If there are several bookmarks, you will be prompted to
|
changed directly to it. If there are several bookmarks, you will be prompted to
|
||||||
choose the appropriate one. Also you can use autocompletion by pressing `Tab`.
|
choose the appropriate one. Also you can use autocompletion by pressing Tab.
|
||||||
It works in a similar way.
|
It works in a similar way.
|
||||||
|
|
||||||
Examples
|
Examples
|
||||||
@ -45,60 +37,65 @@ Examples
|
|||||||
|
|
||||||
Previously set up your commonly used dirs. Specify dir as argument::
|
Previously set up your commonly used dirs. Specify dir as argument::
|
||||||
|
|
||||||
$ g-save ~/Documents
|
$ g_save ~/Documents
|
||||||
$ g-save ~/Downloads
|
$ g_save ~/Downloads
|
||||||
|
|
||||||
or cd into dir and simply run::
|
or cd into dir and simply run::
|
||||||
|
|
||||||
$ g-save
|
$ g_save
|
||||||
|
|
||||||
Go to directory by number::
|
Go to directory by number:
|
||||||
|
|
||||||
$ g
|
$ g
|
||||||
0 ~/Documents/
|
0 ~/Documents/
|
||||||
1 ~/Downloads/
|
1 ~/Downloads/
|
||||||
: <type number here, e.g. 1>
|
: <type number here, e.g. 1>
|
||||||
=> cd /home/user/Downloads
|
=> cd /home/ge/Downloads
|
||||||
|
|
||||||
Goto '~/Downloads' directory by regex::
|
Goto '~/Downloads' directory by regex:
|
||||||
|
|
||||||
$ g w
|
$ g w
|
||||||
=> cd /home/user/Downloads
|
=> cd /home/ge/Downloads
|
||||||
|
|
||||||
Another way :)::
|
Another way:
|
||||||
|
|
||||||
$ g 'do[^c]'
|
$ g 'do[^c]'
|
||||||
=> cd /home/gd/Downloads
|
=> cd /home/ge/Downloads
|
||||||
|
|
||||||
and etc.
|
and etc.
|
||||||
|
|
||||||
Changelog
|
Changelog
|
||||||
*********
|
=========
|
||||||
|
|
||||||
06 Feb 2022
|
v0.3 (05 Oct 2022)
|
||||||
- `~/.gotosave` renamed to `~/.goto_saved`
|
|
||||||
- Alias `s` changed to `g-save`
|
|
||||||
|
|
||||||
07 Jan 2022
|
* Refactored, added POSIX-compatibility
|
||||||
Initial release.
|
* Script renamed to `g.sh`
|
||||||
|
* ~/.goto_saved renamed to ~/.g
|
||||||
|
* Alias `g-save` changed to `g_save`
|
||||||
|
* Functions renamed
|
||||||
|
|
||||||
|
v0.2 (06 Feb 2022)
|
||||||
|
|
||||||
|
* ~/.gotosave renamed to ~/.goto_saved
|
||||||
|
* Alias `s` changed to `g-save`
|
||||||
|
|
||||||
|
v0.1 (07 Jan 2022)
|
||||||
|
|
||||||
|
Initial release.
|
||||||
|
|
||||||
Tips
|
Tips
|
||||||
****
|
====
|
||||||
|
|
||||||
Combining `commacd`, `g` and Bash ``autocd`` option gives a great experience!
|
Combining `commacd`, `g` and Bash ``shopt -s autocd`` option gives a great
|
||||||
|
experience!
|
||||||
Add to you ~/.bashrc following line::
|
|
||||||
|
|
||||||
shopt -s autocd
|
|
||||||
|
|
||||||
Now you can type just directory name without 'cd' to change directory.
|
|
||||||
|
|
||||||
Get `commacd` here: https://github.com/shyiko/commacd
|
Get `commacd` here: https://github.com/shyiko/commacd
|
||||||
|
|
||||||
Alternatives?
|
Alternatives?
|
||||||
*************
|
=============
|
||||||
|
|
||||||
Some `g` alternatives:
|
Some `g` alternatives:
|
||||||
|
|
||||||
- aliases (yep, Bash builtin aliases)
|
* aliases (yep, Bash builtin aliases)
|
||||||
- https://github.com/huyng/bashmarks
|
* https://github.com/huyng/bashmarks
|
||||||
|
128
goto.sh → g.sh
128
goto.sh → g.sh
@ -1,5 +1,5 @@
|
|||||||
# * g (goto directory) - bookmark directories in Bash.
|
# * g (goto directory) - bookmark directories in shell.
|
||||||
# * versuion: 0.2
|
# * version: 0.3
|
||||||
|
|
||||||
# This is free and unencumbered software released into the public domain.
|
# This is free and unencumbered software released into the public domain.
|
||||||
#
|
#
|
||||||
@ -26,52 +26,63 @@
|
|||||||
#
|
#
|
||||||
# For more information, please refer to <http://unlicense.org/>
|
# For more information, please refer to <http://unlicense.org/>
|
||||||
|
|
||||||
_goto_cd() {
|
_g_file=~/.g
|
||||||
##### cd into directory #####
|
|
||||||
|
|
||||||
|
_read_char() {
|
||||||
|
# Read number of chars into variable
|
||||||
|
# Usage: _read_char VAR NUM
|
||||||
|
stty -icanon
|
||||||
|
eval "$1=\$(dd bs=1 count="$2" 2>/dev/null)"
|
||||||
|
stty icanon echo
|
||||||
|
}
|
||||||
|
|
||||||
|
_g_cd() {
|
||||||
|
# cd into directory
|
||||||
if [ ! -d "$1" ]; then
|
if [ ! -d "$1" ]; then
|
||||||
echo "goto: no such directory $1" >&2
|
printf 'g: no such directory %s\n' "$1" >&2
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if cd -- "$1" > /dev/null; then
|
if cd -- "$1" > /dev/null; then
|
||||||
echo "$1"
|
echo "$1"
|
||||||
else
|
else
|
||||||
echo -e "\bgoto: cannot cd into $1" >&2
|
printf '\bg: cannot cd into %s\n' "$1" >&2
|
||||||
fi
|
fi
|
||||||
return "$?"
|
return "$?"
|
||||||
}
|
}
|
||||||
|
|
||||||
_goto_prompt() {
|
_g_prompt() {
|
||||||
##### Prompt and cd #####
|
# Prompt and cd
|
||||||
|
|
||||||
# Exit if no dirs in ~/.goto_saved
|
# Exit if no dirs in $_g_file
|
||||||
if [ "${#dirs[@]}" -eq 0 ] || [[ "${dirs[@]}" == '' ]]; then
|
if [ "$#" -eq 0 ] || [ "$*" = '' ]; then
|
||||||
echo goto: nothing to do; return 1
|
echo goto: nothing to do; return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# cd into dir without prompt if you have single directory
|
# cd into dir without prompt if you have single directory
|
||||||
# in ~/.goto_saved
|
# in $_g_file
|
||||||
if [ "${#dirs[@]}" -eq 1 ]; then
|
if [ "$(echo "$*" | wc -l)" -eq 1 ]; then
|
||||||
_goto_cd "${dirs[@]}" && return 0
|
_g_cd "$*" && return 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Print directory list
|
# Print directory list
|
||||||
for i in "${!dirs[@]}"; do
|
i=0
|
||||||
echo -e "$i\t${dirs[$i]%%+(/)}/" | sed "s%${HOME}%~%"
|
echo "$*" | while read -r dir; do
|
||||||
|
dir="$(echo "$dir" | sed "s%$HOME%~%")"
|
||||||
|
printf '%s\t%s\n' "$i" "$dir"
|
||||||
|
i=$((i+1))
|
||||||
done
|
done
|
||||||
|
|
||||||
# Count digits in number of dirs for 'read'
|
# Input target dir number
|
||||||
local dirscount="$((${#dirs[@]}-1))"
|
dirs_num="$(echo "$*" | wc -l)"
|
||||||
local numlen="${#dirscount}"
|
num_len="${#dirs_num}"
|
||||||
|
printf '%s' ": "
|
||||||
# Read input to 'num' and set 'target' directory
|
_read_char _num "$num_len"
|
||||||
read -r -n "$numlen" -p ': ' num
|
if echo "$_num" | grep -E '[0-9]+' >/dev/null; then
|
||||||
if [[ "$num" =~ [0-9]+ ]]; then
|
_target_dir="$(echo "$*" |
|
||||||
target="${dirs[$num]}";
|
awk -v line="$((_num+1))" 'NR==line {print}')"
|
||||||
# Print new line to prevent line concatenation
|
# Print new line to prevent line concatenation
|
||||||
[ "${#num}" -eq "$numlen" ] && echo
|
[ "${#_num}" -eq "$num_len" ] && echo
|
||||||
elif [[ "$num" == '' ]]; then
|
elif [ "$_num" = '' ]; then
|
||||||
return 1 # Just exit if you press Enter.
|
return 1 # Just exit if you press Enter.
|
||||||
else
|
else
|
||||||
# Print new line and exit if printable chars passed.
|
# Print new line and exit if printable chars passed.
|
||||||
@ -80,63 +91,60 @@ _goto_prompt() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# cd into directory
|
# cd into directory
|
||||||
_goto_cd "$target"
|
_g_cd "$_target_dir"
|
||||||
}
|
}
|
||||||
|
|
||||||
_goto_search() {
|
_g_search() {
|
||||||
grep -iP "$1" ~/.goto_saved
|
grep -iP "$1" "$_g_file"
|
||||||
}
|
}
|
||||||
|
|
||||||
_goto() {
|
_g() {
|
||||||
##### Main function #####
|
# Main function
|
||||||
|
|
||||||
# Get directory list ('dirs' array)
|
# Get directory list ('dirs' array)
|
||||||
dirs=()
|
if [ -f "$_g_file" ]; then
|
||||||
if [ -f ~/.goto_saved ]; then
|
|
||||||
if [ "$1" ]; then
|
if [ "$1" ]; then
|
||||||
# Search dirs with Perl regex
|
# Search dirs with Perl regex
|
||||||
_source="$(_goto_search "$1")"
|
_dirs="$(_g_search "$1")"
|
||||||
else
|
else
|
||||||
# Load all directories
|
# Load all directories
|
||||||
_source="$(<~/.goto_saved)"
|
_dirs="$(cat "$_g_file")"
|
||||||
fi
|
fi
|
||||||
while read -r dir; do
|
|
||||||
dirs+=("$dir")
|
|
||||||
done <<< "$_source"
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
_goto_prompt # prompt and cd
|
_g_prompt "$_dirs" # prompt and cd
|
||||||
}
|
}
|
||||||
|
|
||||||
_goto_save() {
|
_g_save() {
|
||||||
##### Save PWD or 1 to ~/.goto_saved file #####
|
# Save dir in $_g_file
|
||||||
|
|
||||||
local dir
|
if [ -n "$1" ]; then
|
||||||
if [ "$1" ]; then
|
_dir="$1"
|
||||||
dir="$1"
|
|
||||||
else
|
else
|
||||||
dir="$PWD"
|
_dir="$PWD"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Exit if directory is already in ~/.goto_saved
|
# Exit if directory is already in $_g_file
|
||||||
if grep "^${dir%%+(/)}\$" ~/.goto_saved > /dev/null; then
|
if grep "^${_dir%%+(/)}\$" "$_g_file" >/dev/null 2>&1; then
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Save directory
|
# Save directory
|
||||||
if echo "${dir%%+(/)}" >> ~/.goto_saved; then
|
if echo "${_dir%%+(/)}" >> "$_g_file"; then
|
||||||
echo "$dir"
|
echo "$_dir"
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
_goto_complete() {
|
if type complete >/dev/null 2>&1; then
|
||||||
# Autocomplete directory by pattern
|
# Bash completion
|
||||||
local pattern=${COMP_WORDS[COMP_CWORD]}
|
_g_complete_bash() {
|
||||||
local IFS=$'\n'
|
_pattern=${COMP_WORDS[COMP_CWORD]}
|
||||||
COMPREPLY=($(compgen -W "$(printf "%s\n" "$(_goto_search "$pattern")")" -- ''))
|
COMPREPLY=($(compgen -W \
|
||||||
}
|
"$(printf "%s\n" "$(_g_search "$_pattern")")" -- ''))
|
||||||
|
}
|
||||||
|
complete -F _g_complete_bash g
|
||||||
|
else
|
||||||
|
:
|
||||||
|
fi
|
||||||
|
|
||||||
complete -F _goto_complete g
|
alias g='_g'
|
||||||
|
alias g_save='_g_save'
|
||||||
alias g='_goto'
|
|
||||||
alias g-save='_goto_save'
|
|
Loading…
Reference in New Issue
Block a user