squeezed gcd python part out as a file

This commit is contained in:
Ville Rantanen
2017-03-24 13:26:28 +02:00
parent 1b1e74b351
commit 632dcef70f
2 changed files with 224 additions and 185 deletions

80
files/gcd-findmatch.py Executable file
View File

@@ -0,0 +1,80 @@
#!/usr/bin/env python
import sys,os,re
Green="\033[32;1m"
Red="\033[31;1m"
Reset="\033[0m"
key_list="1234567890qwertyuiop"
class getch:
def get(self):
fd = sys.stdin.fileno()
old_settings = termios.tcgetattr(fd)
try:
tty.setraw(sys.stdin.fileno())
ch = sys.stdin.read(1)
finally:
termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
return ch
def printerr(s):
sys.stderr.write(s+"\n")
sys.stderr.flush()
# Print help
if len(sys.argv)==1 or sys.argv[-1]=="-h":
printerr("Guess cd: Find first match in folder, interactive if multiple matches\n Arguments: [dir/]pattern_to_match_folders")
if sys.argv[-1]=="-h":
sys.exit(0)
pattern=".".join(sys.argv[1:])
pat_base=os.path.basename(pattern)
pat_dir=os.path.dirname(pattern)
if pat_dir=="":
pat_dir="."
if not os.path.exists(pat_dir):
printerr("%s: %sNo such folder%s"%(pat_dir,Red,Reset))
sys.exit(1)
# list sub-folders in the folder
current_folders=[d for d in os.listdir(pat_dir) if os.path.isdir(d)]
current_folders=[d for d in current_folders if not d.startswith(".")]
current_folders.sort()
# find matches
match_case=re.compile(".*"+pat_base+".*")
repl_case=re.compile("("+pat_base+")")
matching_folders=[d for d in current_folders if match_case.match(d)]
matches=[repl_case.sub("%s\g<1>%s"%(Green,Reset),d) for d in matching_folders]
# no matches, try case insensitive
if len(matching_folders)==0:
match_nocase=re.compile(".*"+pat_base+".*",re.I)
repl_nocase=re.compile("("+pat_base+")",re.I)
matching_folders=[d for d in current_folders if match_nocase.match(d)]
matches=[repl_nocase.sub("%s\g<1>%s"%(Green,Reset),d) for d in matching_folders]
# One match, print and return
if len(matching_folders)==1:
printerr(matches[0])
print(os.path.join(pat_dir,matching_folders[0]))
sys.exit(0)
# No matches
if len(matching_folders)==0:
printerr("%sno matches%s"%(Red,Reset))
sys.exit(1)
# Many matches, ask the user for folder index
for i,m in enumerate(matches[0:len(key_list)]):
printerr(key_list[i]+": "+m)
if len(matches)>len(key_list):
printerr("Skipping the rest...")
import termios,tty
ch=getch()
key_in=ch.get()
try:
key_index=key_list.index(key_in)
key_match=matching_folders[key_index]
except (ValueError,IndexError) as err:
printerr("%s'%s' Not in the list%s"%(Red,key_in,Reset))
sys.exit(1)
print(os.path.join(pat_dir,key_match))

View File

@@ -1,3 +1,33 @@
## improved CD commands:
function gcd() {
# guess cd, find first match in folder, or ask if multiple hits
local cdto QCDPATH
QCDPATH=$( dirname ${BASH_SOURCE[0]} )
cdto=$( python "$QCDPATH"/files/gcd-findmatch.py "$@" )
[[ -z "$cdto" ]] && return
\cd "$cdto"
} # gcd ends
function hcd() {
[[ "$1" = "-h" ]] && {
echo History cd. Run without arguments to see list of entries, number as arg. to change directory.
return
}
local d
if [ -z "$1" ]
then tail -n 20 "$HOME/.bash_cdhistory" | head -n 19 | cut -d: -f2 | tac | cat -n | sed 's,^ \+,,' | tac
return
fi
d=$( tail -n 20 "$HOME/.bash_cdhistory" | head -n 19 | cut -d: -f2 | tac | cat -n | sed 's,^ \+,,' | grep -h "^$1 " )
d=${d/* /}
if [ ! -z "$d" ]
then \cd "$d"
fi
}
function cd_history () { function cd_history () {
# Function that replaces "cd". It stores visited folder in ~/.bash_cdhistory # Function that replaces "cd". It stores visited folder in ~/.bash_cdhistory
local old local old
@@ -17,21 +47,6 @@ function cd_history () {
} }
alias cd=cd_history alias cd=cd_history
function hcd() {
# History cd. Run without arguments to see list of entries, give number to change cwd.
local d
if [ -z "$1" ]
then tail -n 20 "$HOME/.bash_cdhistory" | head -n 19 | cut -d: -f2 | tac | cat -n | sed 's,^ \+,,' | tac
return
fi
d=$( tail -n 20 "$HOME/.bash_cdhistory" | head -n 19 | cut -d: -f2 | tac | cat -n | sed 's,^ \+,,' | grep -h "^$1 " )
d=${d/* /}
if [ ! -z "$d" ]
then \cd "$d"
fi
}
function qcd() { function qcd() {
# cd command, that jumps to folders visited in the near history, or user bookmarked folders # cd command, that jumps to folders visited in the near history, or user bookmarked folders
local OPTIND local OPTIND
@@ -120,7 +135,7 @@ complete -F _qcd qcd
;; ;;
h) h)
echo 'qcd [-hiLm]|[-al] [name] echo 'qcd [-hiLm]|[-al] [name]
Version: 2015-10-13 Version: 2017-03-24
Change current working path based on the list ~/.qcd Change current working path based on the list ~/.qcd
Keeps a history of folders visited in ~/.bash_cdhistory Keeps a history of folders visited in ~/.bash_cdhistory
@@ -156,6 +171,112 @@ Keeps a history of folders visited in ~/.bash_cdhistory
then \cd "$d" then \cd "$d"
fi fi
} # qcd ends
function ncd() {
[[ "$1" = "-h" ]] && {
echo Next sibling cd: change directory to [../next_folder]. ncd - to go to previous.
return
}
local _current_pwd _iter_d _iter_prev _current_found
_current_pwd=$( basename $( pwd ) )
\cd ..
for _iter_d in *; do
if [ ! -d "$_iter_d" ]; then continue; fi
if [ -n "$_current_found" ]; then
\cd "$_iter_d"
return
fi
if [ "$_iter_d" = "$_current_pwd" ]; then
_current_found=true
if [ "$1" = "-" ]; then
if [ -z "$_iter_prev" ]; then
echo $_current_pwd was the first folder.
else
\cd "$_iter_prev";
return
fi
fi
fi
_iter_prev="$_iter_d"
done
if [ -n "$_current_found" ]; then
echo "$_current_pwd" was the last folder.
else
echo "$_current_pwd" was not found in ../
fi
}
## File processing functions
function foldermenu_prompt {
# Function to add in PS prompt variable, enabling foldermenu support
[ -f .foldermenu ] && {
foldermenu -lf 10 $@ || echo -n "*"
} || {
true
}
}
function igrep () {
[[ "$1" = "-h" ]] && [[ "$#" -eq 1 ]] && {
echo Interactive grep, read grep arguments
return
}
local args
args="-i -e "
while true
do read -e -i "$args" args
echo $@
grep --color=auto $args "$@"
if [ "$?" -ne 0 ]
then echo _no_matches_ | grep --color=auto ".*"
fi
done
}
function ised () {
[[ "$1" = "-h" ]] && [[ "$#" -eq 1 ]] && {
echo Interactive sed, read sed arguments
return
}
local args
if [ ! -f "$1" ]; then echo must give atleast one file; return 1;fi;
args="-e s/string//g"
while true
do read -e -i "$args" args
echo input files: "$@"
eval sed $args "$@"
if [ "$?" -ne 0 ]
then echo Error output | grep --color=auto ".*"
fi
done
}
function rmv () {
[[ "$1" = "-h" ]] && {
echo 'mv files/folders with rsync (shows speed and progress)'
echo 'Usage: rmv source [source2] [source3] target'
return
}
local sources
sources=()
# remove / from ends, if target is an existing folder
for (( i=1; i<=$(($#-1)); i++ ))
do if [ -d "${@: -1}" ]
then sources+=("${!i%/}")
else sources+=("${!i}")
fi
done
rsync -vaP --remove-source-files "${sources[@]}" "${@: -1}"
# remove empty folders from sources (not last argument)
for (( i=1; i<=$(($#-1)); i++ ))
do if [ -d "${!i}" ]
then find "${!i}" -depth -type d -exec rmdir \{\} \;
fi
done
} }
function whenfilechanges() { function whenfilechanges() {
@@ -205,184 +326,22 @@ function whenfilechanges() {
} }
function gcd() { # Shell enhancement
# guess cd, find first match in folder, or ask if multiple hits
local cdto
{ cdto=$( python -c '
import sys,os,re
if len(sys.argv)==1 or sys.argv[-1]=="-h":
print("Arguments: [dir/]pattern_to_match_folders")
if sys.argv[-1]=="-h":
sys.exit(0)
def G():
return "\033[32;1m"
def R():
return "\033[31;1m"
def Z():
return "\033[0m"
def CS():
return "1234567890qwertyuiop"
class getch:
def get(self):
fd = sys.stdin.fileno()
old_settings = termios.tcgetattr(fd)
try:
tty.setraw(sys.stdin.fileno())
ch = sys.stdin.read(1)
finally:
termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
return ch
pattern=".".join(sys.argv[1:])
pat_dir=os.path.dirname(pattern)
if pat_dir=="":
pat_dir="."
pat_base=os.path.basename(pattern)
if not os.path.exists(pat_dir):
print(pat_dir+": "+R()+"No such folder"+Z())
sys.exit(1)
current_folders=[d for d in os.listdir(pat_dir) if os.path.isdir(d)]
current_folders=[d for d in current_folders if not d.startswith(".")]
current_folders.sort()
match_case=re.compile(".*"+pat_base+".*")
repl_case=re.compile("("+pat_base+")")
matching_folders=[d for d in current_folders if match_case.match(d)]
matches=[repl_case.sub(G()+"\g<1>"+Z(),d) for d in matching_folders]
if len(matching_folders)==0:
match_nocase=re.compile(".*"+pat_base+".*",re.I)
repl_nocase=re.compile("("+pat_base+")",re.I)
matching_folders=[d for d in current_folders if match_nocase.match(d)]
matches=[repl_nocase.sub(G()+"\g<1>"+Z(),d) for d in matching_folders]
if len(matching_folders)==1:
print(matches[0])
sys.stderr.write(os.path.join(pat_dir,matching_folders[0]))
sys.exit(0)
if len(matching_folders)==0:
print(R()+"no matches"+Z())
sys.exit(1)
for i,m in enumerate(matches[0:20]):
print(CS()[i]+": "+m)
if len(matches)>20:
print("Skipping rest...")
import termios,tty
ch=getch()
key_in=ch.get()
try:
key_index=CS().index(key_in)
key_match=matching_folders[key_index]
except ValueError,IndexError:
sys.exit(1)
sys.stderr.write(os.path.join(pat_dir,key_match))
' "$@" 2>&1 1>&$out); } {out}>&1 ; \cd "$cdto"
}
function ncd() {
# Next cd: cd to ../[next_folder]. ncd - to go to previous
local _current_pwd _iter_d _iter_prev _current_found
_current_pwd=$( basename $( pwd ) )
\cd ..
for _iter_d in *; do
if [ ! -d "$_iter_d" ]; then continue; fi
if [ -n "$_current_found" ]; then
\cd "$_iter_d"
return
fi
if [ "$_iter_d" = "$_current_pwd" ]; then
_current_found=true
if [ "$1" = "-" ]; then
if [ -z "$_iter_prev" ]; then
echo $_current_pwd was the first folder.
else
\cd "$_iter_prev";
return
fi
fi
fi
_iter_prev="$_iter_d"
done
if [ -n "$_current_found" ]; then
echo "$_current_pwd" was the last folder.
else
echo "$_current_pwd" was not found in ../
fi
}
function rmv () {
# mv files/folders with rsync (shows speed and progress)
local sources
sources=()
# remove / from ends, if target is an existing folder
for (( i=1; i<=$(($#-1)); i++ ))
do if [ -d "${@: -1}" ]
then sources+=("${!i%/}")
else sources+=("${!i}")
fi
done
rsync -vaP --remove-source-files "${sources[@]}" "${@: -1}"
# remove empty folders from sources (not last argument)
for (( i=1; i<=$(($#-1)); i++ ))
do if [ -d "${!i}" ]
then find "${!i}" -depth -type d -exec rmdir \{\} \;
fi
done
}
function igrep () {
# Interactive grep
local args
args="-i -e "
while true
do read -e -i "$args" args
echo $@
grep --color=auto $args "$@"
if [ "$?" -ne 0 ]
then echo _no_matches_ | grep --color=auto ".*"
fi
done
}
function ised () {
# Interactive sed
local args
if [ ! -f "$1" ]; then echo must give atleast one file; return 1;fi;
args="-e s/string//g"
while true
do read -e -i "$args" args
echo input files: "$@"
eval sed $args "$@"
if [ "$?" -ne 0 ]
then echo Error output | grep --color=auto ".*"
fi
done
}
function foldermenu_prompt {
# Function to add in PS prompt variable, enabling foldermenu support
[ -f .foldermenu ] && {
foldermenu -lf 10 $@ || echo -n "*"
} || {
true
}
}
function qbg { function qbg {
# Run a program quiet, and backgrounded [[ "$1" = "-h" ]] && {
echo 'Run a command quiet, and backgrounded ( typically X11 executable )'
return
}
"$@" &> /dev/null & "$@" &> /dev/null &
} }
function set_term_title { function set_term_title {
# set term in byobu/screen xterm etc.. # set term in byobu/screen xterm etc..
[ -z "$1" ] && { [ -z "$1" ] && {
echo -e '\033k'$HOSTNAME'\033\\' echo -ne '\033k'$HOSTNAME'\033\\\r'
} || { } || {
echo -e '\033k'$1'\033\\' echo -ne '\033k'$1'\033\\\r'
} }
} }