Files
q-tools/files/cclip
2021-07-11 21:58:42 +03:00

309 lines
6.6 KiB
Bash
Executable File

#!/bin/bash
set -e
_help() {
SELF=$( basename "$0" )
echo "Console Clipboard manager
Note: Copying happens only to a list. If source file is deleted, it
can not be copied anymore.
List clipboard names:
$SELF l/list
Make a link to clipboard:
$SELF c/copy filename[s]
Paste files using clipboard:
$SELF p/paste [switches] clipboardname[s]
Switches:
-l Use hardlink instead of file copying
-k Keep clipboard link
-m Move instead of copy (can not be used with -h, can not -k)
-a Paste all files from clipboard
Delete files using clipboard links:
$SELF rm/remove clipboardname[s]
Clear clipboard links:
$SELF d/del clipboardname[s]
Clear all clipboard links:
$SELF D/Del clipboardname[s]
Get autocomplete:
$SELF autocomplete
Config:
CCLIP_HOME environment variable sets clipboard storage folder,
defauls to ~/.cache/cclip
"
exit
}
_load_config() {
STORAGE=${CCLIP_HOME:-~/.cache/cclip}
[[ -d "$STORAGE" ]] || {
_msg "Creating $STORAGE folder"
mkdir -p "$STORAGE"
}
}
_list() {
cd "$STORAGE"
[[ $(ls -A) ]] || {
_msg "No clipboard entries"
return
}
longest=4
for n in *; do
if [[ $longest -lt ${#n} ]]; then
longest=${#n}
fi
done
hl=$( _qCol W 2>/dev/null || true )
he=$( _qCol y U 2>/dev/null || true )
no=$( _qCol z 2>/dev/null || true )
now=$( date -Idate )
printf "%s%-${longest}s %-4s %-8s %s%s\n" "$he" Name Size Added Path "$no"
IFS=$'\n'
while read n; do
f=$( _get_item "$n" )
size=$( du -k -h -s --apparent-size "$f" | awk '{ print $1 }' )
#type=$( stat --printf "%A" "$f" )
#type=${type:0:1}
#if [[ "$type" = "-" ]]; then type=f; fi
date=$( stat --printf "%y" "$n" )
if [[ "$date" = "$now"* ]]; then
date=${date#* }
date="${date:0:8}"
else
date=${date%% *}
date="${date:2:8}"
fi
printf "%-${longest}s %-4s %-8s %s%s%s\n" \
"${n}" \
"$size" \
"${date}" \
"$hl" "${f}" \
"$no"
done < <( ls -t )
}
_simple_list() {
ls -1 "$STORAGE"
}
_get_item() {
# TODO: Items could be just symbolic links
cat "$STORAGE/$1"
}
_copy() {
if [[ $# -lt 2 ]]; then
_help
fi
for (( i=2; i<=$#; i++ )); do
name=$( basename "${!i}" | tr -c '[:alnum:],_.\n\r' "-" )
origname="$name"
path=$( readlink -f "${!i}" )
if [[ -d "$path" ]]; then
path="$path/"
fi
post=0
while [[ -e "$STORAGE/${name}" ]]; do
post=$(( post + 1 ))
name="${origname}-${post}"
done
printf "%s %s\n" "$name" "$path"
printf "%s" "$path" > "$STORAGE/${name}"
done
}
_paste() {
if [[ $# -lt 2 ]]; then
_help
fi
for (( i=2; i<=$#; i++ )); do
case ${!i} in
-a) copy_all=1; ;;
-l) hardlink=1; ;;
-k) keeplink=1; ;;
-m) movelink=1; ;;
esac
done
if [[ "$copy_all" = 1 ]]; then
for n in "$STORAGE"/*; do
_paste_single "$( basename "$n" )"
done
return
fi
for (( i=2; i<=$#; i++ )); do
if [[ "${!i}" =~ ^-.$ ]]; then
continue
fi
_paste_single "${!i}"
done
}
_paste_single() {
if [[ ! -e "$STORAGE/$1" ]];then
_msg "No such clipboard: '$1'"
return
fi
path=$( _get_item "$1" )
if [[ ! -e "$path" ]]; then
_msg "No such path: $1 -> '$path'"
return
fi
target=$( basename "$path" )
if [[ -d "$path" ]]; then
extension=""
basetarget="${target}"
else
if [[ "$target" = *.* ]]; then
basetarget="${target%.*}"
extension=."${target##*.}"
else
extension=""
basetarget="${target}"
fi
fi
origbase="$basetarget"
post=0
while [[ -e "${basetarget}${extension}" ]]; do
post=$(( post + 1 ))
basetarget="${origbase}-${post}"
done
target="${basetarget}${extension}"
if [[ "$movelink" = 1 ]]; then
keeplink=0
echo Moving "${path} -> $target"
mv "$path" "$target" || return
else
hardlinkswitch=""
if [[ "$hardlink" = 1 ]]; then
hardlinkswitch="-l"
fi
echo Copying "${path} -> $target"
cp -aT $hardlinkswitch "${path}" "$target" || return
fi
if [[ ! "$keeplink" = 1 ]]; then
echo "Removing link: $1"
rm "$STORAGE/$1"
fi
}
_remove() {
if [[ $# -lt 2 ]]; then
_help
fi
for (( i=2; i<=$#; i++ )); do
if [[ ! -e "$STORAGE/${!i}" ]];then
_msg "No such clipboard: '${!i}'"
continue
fi
path=$( _get_item "${!i}" )
if [[ ! -e "$path" ]]; then
_msg "No such path: $1 -> '$path'"
continue
fi
echo "Removing data: ${path}"
rm -ir "$path"
echo "Removing link: ${!i}"
rm "$STORAGE/${!i}"
done
}
_delete() { # name
for (( i=2; i<=$#; i++ )); do
name=$( basename "${!i}" )
if [[ ! -e "$STORAGE/$name" ]]; then
_msg "No such clipboard '$name'"
EC=1
continue
fi
printf "Removing %s: %s\n" "$name" $( _get_item "$name" )
rm "$STORAGE/$name"
done
}
_delete_all() {
[[ -e "$STORAGE" ]] || {
exit 0
}
_simple_list
[[ "$FORCE" -ne 1 ]] && {
read -p "Really delete the whole clipboard? ($STORAGE) Break to cancel. " foo
}
rm -vrf "$STORAGE/"
mkdir "$STORAGE"
}
_msg() {
echo "$@"
}
_get_completer() {
self=$( basename $( readlink -f "$0" ) )
echo '_CCLIP_EXEC_complete() {
local curr_arg
curr_arg=${COMP_WORDS[COMP_CWORD]}
if [[ $COMP_CWORD -eq 1 ]]; then
COMPREPLY=( $(compgen -W "help autocomplete l list c copy p paste delete Delete" -- $curr_arg ) );
fi
if [[ $COMP_CWORD -eq 2 ]]; then
case ${COMP_WORDS[$(( $COMP_CWORD - 1 ))]} in
p|paste|d*|rm|remove)
local IFS=$'"'"'\n'"'"'
local remotelist=( $( eval CCLIP_EXEC simplelist ) )
COMPREPLY=( $(compgen -W "${remotelist[*]}" -- $curr_arg ) );
;;
c*)
COMPREPLY=( $(compgen -f -d -X '' -- $curr_arg ) );
;;
esac
fi
}
complete -F _CCLIP_EXEC_complete CCLIP_EXEC
# Run me as: source <( CCLIP_EXEC autocomplete )
' | sed "s,CCLIP_EXEC,$self,g"
exit 0
}
for (( i=1; i<=$#; i++ )); do
[[ "${!i}" = "-h" ]] && _help
[[ "${!i}" = "--help" ]] && _help
done
_load_config
source qolop &>/dev/null || true
CMD="${1:-list}"
[[ "$CMD" = help || "$CMD" = "-h" || "$CMD" = "--help" ]] && { _help; }
[[ "$CMD" = "l" || "$CMD" = "list" ]] && { _list; }
[[ "$CMD" = "c" || "$CMD" = "copy" ]] && { _copy "$@"; }
[[ "$CMD" = "d" || "$CMD" = "delete" || "$CMD" = "del" ]] && { _delete "$@"; }
[[ "$CMD" = "D" || "$CMD" = "Delete" || "$CMD" = "Del" ]] && { _delete_all; }
[[ "$CMD" = "p" || "$CMD" = "paste" ]] && { _paste "$@"; }
[[ "$CMD" = "rm" || "$CMD" = "remove" ]] && { _remove "$@"; }
[[ "$1" = "autocomplete" ]] && { _get_completer; exit; }
[[ "$1" = "simplelist" ]] && { _simple_list; exit; }
exit $EC