232 lines
5.3 KiB
Bash
Executable File
232 lines
5.3 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
# For any command require a file path, this function
|
|
# helps to select the correct file with key words
|
|
# Usage:
|
|
# Add the command to desired list
|
|
|
|
# fzf match everything
|
|
fzf_command_list_all=(\
|
|
)
|
|
|
|
# fzf match files
|
|
fzf_command_list_file=(\
|
|
cat \
|
|
#vim \
|
|
#nvim \
|
|
set_wallpaper \
|
|
)
|
|
|
|
# fzf only match folders
|
|
fzf_command_list_dir=(\
|
|
cd \
|
|
)
|
|
|
|
# in case above functions are broken
|
|
function no_fzf(){
|
|
for c in "${fzf_command_list_all[@]}"; do
|
|
unalias $c
|
|
done
|
|
for c in "${fzf_command_list_file[@]}"; do
|
|
unalias $c
|
|
done
|
|
for c in "${fzf_command_list_dir[@]}"; do
|
|
unalias $c
|
|
done
|
|
}
|
|
|
|
function dp(){
|
|
local debug=0
|
|
[ "$debug" = "1" ] && echo $1
|
|
}
|
|
|
|
# SHELL specific setting
|
|
if [ ! -z "$ZSH_NAME" ]; then
|
|
SHELL_NAME=zsh
|
|
dp "[bash_tools]: In ZSH shell"
|
|
# disable error output when
|
|
# wildcard found 0 match
|
|
setopt +o nomatch
|
|
|
|
#setopt extended_glob
|
|
|
|
# show hidden file when using wildcard
|
|
# use in fzf_selector
|
|
# only for zsh
|
|
setopt dotglob
|
|
setopt glob_dots
|
|
else
|
|
# temporary
|
|
SHELL_NAME=bash
|
|
dp "[bash_tools]: In non-ZSH shell"
|
|
# only for bash
|
|
shopt -s dotglob
|
|
|
|
# allow reverse wildcard exp. !(b*)
|
|
# shopt -s extglob
|
|
|
|
# allows filename patterns which match no
|
|
# files to expand to a null string, rather
|
|
# than themselves
|
|
shopt -s nullglob
|
|
fi
|
|
|
|
ret=''
|
|
|
|
# $1 keyword
|
|
# $2
|
|
# 0: show all
|
|
# 1: only show directories
|
|
# 2: only show files
|
|
function fzf_selector() {
|
|
ret=$1
|
|
if [ "$1" = "." ] || [ "$1" = ".." ] || \
|
|
[[ "$1" == -* ]] || [[ "$1" == */* ]]; then
|
|
dp "fzf return directly"
|
|
return 1
|
|
fi
|
|
|
|
if [ $2 = 0 ]; then
|
|
all_items=(*)
|
|
elif [ $2 = 1 ]; then
|
|
dp "try to find dirs"
|
|
all_items=(*/)
|
|
elif [ $2 = 2 ]; then
|
|
dp "try to find files"
|
|
if [ "$SHELL_NAME" = "zsh" ]; then
|
|
eval "all_items=(*(^/))"
|
|
elif [ "$SHELL_NAME" = "bash" ]; then
|
|
# no easy way to list just regular files
|
|
# in bash???
|
|
all=(*)
|
|
all_items=()
|
|
for item in "${all[@]}"; do
|
|
[ -f "$item" ] && all_items+=("$item")
|
|
done
|
|
fi
|
|
fi
|
|
|
|
|
|
dp "fzf-keyword: $1"
|
|
files=()
|
|
# match
|
|
# 1. try match file/dir equals to keyword completely
|
|
# 2. try match file/dir which keyword is substring of
|
|
# 3. try match file/dir equals to keyword completely after ignoring cases
|
|
# 4. try match file/dir which keyword is substring of after ignoring cases
|
|
|
|
for item in "${all_items[@]}"; do
|
|
dp "item: $item"
|
|
# 1.
|
|
if [ "$item" = "$1" ] || [ "$item" = "$1/" ]; then
|
|
return 0
|
|
fi
|
|
|
|
# 2.
|
|
# this line ignore cases
|
|
# [[ $1 =~ [A-Z] ]] && \
|
|
grep $1 <<< $item > /dev/null 2>&1 && \
|
|
files+=("$item")
|
|
done
|
|
|
|
dp "len contains upper cases ${#files[@]}"
|
|
|
|
if [ "${#files[@]}" = "0" ]; then
|
|
for item in "${all_items[@]}"; do
|
|
# 3.
|
|
if ([ "$SHELL_NAME" = "bash" ] && ( [ "${item,,}" = "${1,,}" ] || [ "${item,,}" = "${1,,}/" ] )) || \
|
|
([ "$SHELL_NAME" = "zsh" ] && ( [ "${item:l}" = "${1:l}" ] || [ "${item:l}" = "${1:l}/" ] )) ; then
|
|
ret=$item
|
|
return 0
|
|
fi
|
|
# 4.
|
|
grep -i $1 <<< $item > /dev/null 2>&1 && files+=("$item")
|
|
done
|
|
fi
|
|
|
|
if [ "${#files[@]}" = "0" ]; then
|
|
# if grep find zero file
|
|
ret=$1
|
|
elif [ "${#files[@]}" = "1" ]; then
|
|
ret=$files
|
|
else
|
|
select file in "${files[@]}"; do
|
|
ret=$file
|
|
break
|
|
done
|
|
fi
|
|
}
|
|
|
|
# $1 command for fzf substuting(like ls)
|
|
# $2 original args pass to function
|
|
# $3 command require file type (file: 0 |directory: 1)
|
|
function fzf_command_execute() {
|
|
local args=($@)
|
|
local len=${#args[@]}
|
|
|
|
dp "args: $args"
|
|
dp "lens: $len"
|
|
|
|
# zsh shell's array starts with 1 rather than 0
|
|
if [ ! -z "$ZSH_NAME" ]; then
|
|
dp "zsh"
|
|
flag="${args[2]}"
|
|
unset 'args[2]'
|
|
command_prefix="${args[1]}"
|
|
else
|
|
dp "not zsh"
|
|
flag="${args[1]}"
|
|
unset 'args[1]'
|
|
command_prefix="${args[0]}"
|
|
fi
|
|
|
|
dp "flag: $flag"
|
|
|
|
if [ "$len" = "2" ]; then
|
|
# flag will take 1 length
|
|
# so if len == 2 means no argument is given
|
|
${args[@]}
|
|
return 0
|
|
fi
|
|
# probably work for bash
|
|
#keyword="${args: -1}"
|
|
|
|
keyword=""
|
|
slice_flag=1
|
|
for arg in "${args[@]:2}"; do
|
|
dp "argg $arg"
|
|
if [ "$slice_flag" = "1" ]; then
|
|
if [ "$keyword" = "" ]; then
|
|
keyword="$arg"
|
|
else
|
|
keyword="$keyword $arg"
|
|
fi
|
|
elif [[ "$arg" == "-"* ]]; then
|
|
command_prefix="$command_prefix $arg"
|
|
else
|
|
slice_flag=1
|
|
fi
|
|
done
|
|
dp "command_prefix: $command_prefix"
|
|
dp "keyword: $keyword"
|
|
|
|
# Delete last argument
|
|
# Here we assume it is a file path
|
|
|
|
fzf_selector "$keyword" $flag
|
|
dp "ret: $ret"
|
|
|
|
$command_prefix "$ret"
|
|
}
|
|
|
|
for c in "${fzf_command_list_all[@]}"; do
|
|
alias $c="fzf_command_execute $c 0"
|
|
done
|
|
for c in "${fzf_command_list_file[@]}"; do
|
|
alias $c="fzf_command_execute $c 2"
|
|
done
|
|
for c in "${fzf_command_list_dir[@]}"; do
|
|
alias $c="fzf_command_execute $c 1"
|
|
done
|
|
|