Reputation: 23
I am forced to work with tcsh shell and I wanted to make myself a little more comfortable traversing around in commonly visited directories. So I looked for 'bookmarking' tool but I could not find one, so I went ahead and wrote a small tcsh scipt. My only complaint to how it works is that I can only print into single column in terminal. This is was not an issue with the first draft of the script as I wrote it in bash, but realized I cannot change directory from child process on running different shell...
This approached worked for bash, but it does not for tcsh:
for key in "${!map[@]}"; do
if [[ ${key} =~ $2 ]]; then
printf "%-8s\n" "${key}"
fi
done | sort | column
I could also force similar behavior through command line but it's suboptimal:
bookmark.sh -l | sort | column
Here is my full "Frankenstein" code:
#!/bin/tcsh
set BM = "${HOME}/.gtk-bookmarks"
set root = "file://"
set keys = ()
set values = ()
# Check if bookmarks file exists. If so parse it into hash
if ( -r $BM ) then
foreach line ( "`cat $BM |grep -v KEY`" )
set key = `echo $line | cut -d " " -f 2`
set value = `echo $line | cut -d " " -f 1 | sed 's/file:\/\///g'`
set keys = ( $keys "$key" )
set values = ( $values "$value" )
end
else
echo "[ERROR]: Bookmark file $BM does not exists."
exit 1
endif
if ( $# == 0 ) then
#############################
## D E F A U L T L I S T ##
#############################
set found = 0
foreach key ($keys)
set found = 1
printf "%-8s\n" "$key"
end
if ($found == 0) then
echo "[ERROR]: No bookmarks found."
exit 1
else
exit 0
endif
else
#############
## H E L P ##
#############
if ( "$argv[1]" == "-h" || "$argv[1]" == "--help" ) then
echo "Purpose: Work with bookmarks within terminal window."
echo "-a|--add Add a bookmark <name> <path>."
echo "-e|--edit Edit existing bookmark <name> <new_path>."
echo "-f|--find Find bookmark <string>,"
echo "-l|--list List available bookmarks."
echo "-v|--view View particular bookmark <name>."
echo "-cd|--change_directory Change directory to given bookmark <name>."
echo "-h|--help Prints help."
###########
## A D D ##
###########
else if ( "$argv[1]" == "-a" || "$argv[1]" == "--add" ) then
echo "Adding:"
if ($# != 3 ) then
echo "[ERROR]: bm -a|--add <bookmarkName> <validPath>."
exit 1
endif
set i = 1
set found = 0
while($i <= ${#keys})
if ( "$keys[$i]" == "$argv[2]" ) then
set found = 1
break
endif
@ i++
end
if ( $found == 0 ) then
if ( -d $argv[3] || -f $argv[3] ) then
set value = `realpath -s $argv[3]`
echo "$argv[2] $value"
echo "file://$value $argv[2]" >> $BM
exit 0
else
echo "[ERROR]: $argv[3] is neither a file or directory."
exit 1
endif
else
echo "[ERROR]: $argv[2] bookmark already exists."
exit 1
endif
#############
## E D I T ##
#############
else if ( "$argv[1]" == "-e" || "$argv[1]" == "--edit" ) then
echo "Editing:"
if ($# != 3 ) then
echo "[ERROR]: bm -e|--edit <bookmarkName> <validPath>."
exit 1
endif
set i = 1
set found = 0
while($i <= ${#keys})
if ( "$keys[$i]" == "$argv[2]" ) then
set found = 1
break
endif
@ i++
end
if ($found > 0) then
if ( -d $values[$i] || -f $values[$i] ) then
if ( -d $argv[3] || -f $argv[3] ) then
set value = `realpath -s $argv[3]`
# update file
set k = 1
while ($k <= ${#keys})
if ( $k == $i ) then
echo "[INFO]: Previous $keys[$k] : $values[$k]"
set line = "file://$value $keys[$k]"
echo "[INFO]: Updated $keys[$k] : $value"
else
set line = "file://$values[$k] $keys[$k]"
endif
if ( $k == 1 ) then
echo $line > $BM
else
echo $line >> $BM
endif
@ k++
end
exit 0
else
echo "[ERROR]: $argv[3] is neither a file or directory."
exit 1
endif
else
echo "[ERROR]: $values[$i] is neither a file or directory."
exit 1
endif
else
echo "[ERROR]: $argv[2] bookmark does not exist."
exit 1
endif
#############
## L I S T ##
#############
else if ("$argv[1]" == "-l" || "$argv[1]" == "--list") then
echo "List:"
if ($# > 1 ) then
echo "[ERROR]: bm -l|--list|<nothing>."
exit 1
endif
set found = 0
foreach key ($keys)
set found = 1
printf "%-8s\n" "$key"
end
if ($found == 0) then
echo "[ERROR]: No bookmarks found."
exit 1
else
exit 0
endif
#############
## F I N D ##
#############
else if ( "$argv[1]" == "-f" || "$argv[1]" == "--find" ) then
echo "Find:"
if ($# != 2 ) then
echo "[ERROR]: bm -f|--find <string>."
exit 1
endif
set found = 0
foreach key ($keys)
if ( $key =~ *$argv[2]* ) then
set found = 1
printf "%-8s\n" "$key"
endif
end
if ($found == 0) then
echo "[ERROR]: No bookmarks containing $argv[2] found."
exit 1
else
exit 0
endif
#########
## C D ##
#########
else if ( "$argv[1]" == "-cd" || "$argv[1]" == "--change_directory" ) then
echo "Changing directory & listing:"
if ($# != 2 ) then
echo "[ERROR]: bm -cd|--change_directory <bookmarkName>."
exit 1
endif
set i = 1
while($i <= ${#keys})
if ( "$keys[$i]" == "$argv[2]" ) then
cd "$values[$i]"
ls ./
exit 0
endif
@ i++
end
echo "[ERROR]: $argv[2] bookmark does not exists."
exit 1
#############
## V I E W ##
#############
else if ( "$argv[1]" == "-v" || "$argv[1]" == "--view" ) then
echo "View:"
if ($# != 2 ) then
echo "[ERROR]: bm -v|--view <bookmarkName>."
exit 1
endif
set i = 1
while($i <= ${#keys})
if ( "$keys[$i]" == "$argv[2]" ) then
echo "$keys[$i] : $values[$i]"
exit 0
endif
@ i++
end
echo "[ERROR]: $argv[2] bookmark does not exists."
exit 1
#####################
## Q U I C K C D ##
#####################
else
set i = 1
while($i <= ${#keys})
if ( "$keys[$i]" == "$argv[1]" ) then
echo "Changing directory & listing:"
cd "$values[$i]"
ls ./
exit 0
endif
@ i++
end
echo "[ERROR]: Unknown command option or bookmark $argv[1]. Use -h or --help to available command options."
exit 1
endif
endif
PS: I know my code is nowhere near efficient or pretty, but it does the job. I just want to utilize the entire available terminal width.
EDIT #1: I forgot to mention that in order to make my script effective in changing the directory when called, I have an alias that source it:
alias bm 'source /home/bookmark.sh'
Upvotes: 1
Views: 339
Reputation: 11
It looks a like job for $CDPATH
check out here.
Long story short -- that is $PATH
for directories; autocompletes cd ...
by making a lookup in subdirs under paths.
Works something like:
$ set cdpath = ($cdpath /path/to/dir1/ /path/to/dir2/ /path/to/dir3/)
$ ls /path/to/dir1/
ddir1
cd ddir1 # will jump into /path/to/dir1/ddir1
cd d<TAB> # SHOULD autocomplete,
# will update when proper settings is found
Maybe you also will benefit by setting some fancy inputrc settings.
Upvotes: 1