From 3e2250414f008215639ed2c399df4db566159b33 Mon Sep 17 00:00:00 2001 From: Ville Rantanen Date: Sat, 17 Jul 2021 13:41:56 +0300 Subject: [PATCH] multiple file support for cclip --- files/cclip | 281 ++++++++++++++++++++++++++++++++++------------------ 1 file changed, 187 insertions(+), 94 deletions(-) diff --git a/files/cclip b/files/cclip index 16fc6e6..bdaf61a 100755 --- a/files/cclip +++ b/files/cclip @@ -9,26 +9,29 @@ _help() { can not be copied anymore. List clipboard names: - $SELF l/list + $SELF l/list [clipboard] Make a link to clipboard: - $SELF c/copy filename[s] + $SELF c/copy filename[s] [clipboard] Paste files using clipboard: - $SELF p/paste [switches] clipboardname[s] + $SELF p/paste [switches] [clipboardname[s]] [folder/] + Default folder: . Switches: + -s Use soft link instead of file copying -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: + Delete source files using clipboard links (WARNING): $SELF rm/remove clipboardname[s] + Edit links manually: + $SELF e/edit clipboardname[s] Clear clipboard links: $SELF d/del clipboardname[s] Clear all clipboard links: - $SELF D/Del clipboardname[s] + $SELF D/Del Get autocomplete: $SELF autocomplete @@ -50,13 +53,18 @@ _load_config() { } _list() { - cd "$STORAGE" - [[ $(ls -A) ]] || { + if [[ ! $( ls -A "${STORAGE}" ) ]]; then _msg "No clipboard entries" return - } + fi + if [[ $# -gt 1 ]]; then + list_only="${2}" + fi + # TODO: single clipboard only + longest=4 - for n in *; do + for f in ${STORAGE}/*; do + n=$( basename "$f" ) if [[ $longest -lt ${#n} ]]; then longest=${#n} fi @@ -65,16 +73,15 @@ _list() { 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" + printf "%s%-${longest}s %-10s %s%s\n" "$he" Name Added/Size 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" ) + while read name; do + if [[ -n "$list_only" ]]; then + if [[ ! "$list_only" = "$name" ]]; then + continue + fi + fi + date=$( stat --printf "%y" "${STORAGE}/$name" ) if [[ "$date" = "$now"* ]]; then date=${date#* } date="${date:0:8}" @@ -82,90 +89,151 @@ _list() { date=${date%% *} date="${date:2:8}" fi + printf "%-${longest}s %-10s\n" \ + "$name" \ + "${date}" + while read f; do + if [[ ! -e "$f" ]]; then + size=MISS"!" + else + size=$( du -k -h -s --apparent-size "$f" | awk '{ print $1 }' ) + fi - printf "%-${longest}s %-4s %-8s %s%s%s\n" \ - "${n}" \ - "$size" \ - "${date}" \ - "$hl" "${f}" \ - "$no" - done < <( ls -t ) + printf "%-${longest}s %5s %s%s%s\n" \ + " " \ + "$size" \ + "$hl" "${f}" \ + "$no" + done < "${STORAGE}/$name" + done < <( ls "${STORAGE}" -t ) } _simple_list() { ls -1 "$STORAGE" } -_get_item() { - # TODO: Items could be just symbolic links - cat "$STORAGE/$1" -} - _copy() { + numargs=$# if [[ $# -lt 2 ]]; then _help fi - for (( i=2; i<=$#; i++ )); do - name=$( basename "${!i}" | tr -c '[:alnum:],_.\n\r' "-" ) + for i in $@; do :; done + if [[ ! -e "$i" ]]; then + CLIPBOARD=$( echo "$i" | tr -d './' | tr -cd '[[:print:]]' ) + if [[ -z "$CLIPBOARD" ]]; then + _msg "Invalid clipboard name: '$i'" + exit 1 + fi + numargs=$(( numargs - 1 )) + fi + for (( i=2; i<=$numargs; i++ )); do + #~ name=$( basename "${!i}" | tr -c '[:alnum:],_.\n\r' "-" ) + name=$( basename "${!i}" ) 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}" + printf "%s\n" "$path" >> "$STORAGE/${CLIPBOARD}" done + sort -u -o "$STORAGE/${CLIPBOARD}" "$STORAGE/${CLIPBOARD}" + _list l "$CLIPBOARD" +} + + +_edit() { + numargs=$# + if [[ $# -lt 2 ]]; then + _help + fi + for (( i=2; i<=$numargs; i++ )); do + CLIPBOARD=$( echo "${!i}" | tr -d './' | tr -cd '[[:print:]]' ) + if [[ ! -f "$STORAGE/${!i}" ]]; then + echo "No such clipboard: ${!i}" + continue + fi + ${VISUAL:-vim} "$STORAGE/${CLIPBOARD}" + _list l "$CLIPBOARD" + done + } _paste() { - if [[ $# -lt 2 ]]; then - _help - fi + numargs=$# + keeplink=1 for (( i=2; i<=$#; i++ )); do case ${!i} in - -a) copy_all=1; ;; + -s) softlink=1; ;; -l) hardlink=1; ;; - -k) keeplink=1; ;; + -d) keeplink=0; ;; -m) movelink=1; ;; + *) + if [[ ! -f "$STORAGE/${!i}" ]]; then + # no such clipboard + if [[ $i -gt 2 ]]; then + if [[ $i -eq $numargs ]]; then + # but argument is last (but not only) + OUTPUT=${!i} + numargs=$(( numargs - 1 )) + continue + fi + fi + echo No such clipboard: ${!i} + return + fi + ;; 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 + echo "Pasting to folder: $OUTPUT" + mkdir -p "$OUTPUT" + for (( i=2; i<=$numargs; i++ )); do if [[ "${!i}" =~ ^-.$ ]]; then continue fi - _paste_single "${!i}" + single_copied=1 + _paste_clipboard "${!i}" done + if [[ ! "$single_copied" = 1 ]]; then + _paste_clipboard "$CLIPBOARD" + fi + } -_paste_single() { - if [[ ! -e "$STORAGE/$1" ]];then +_paste_clipboard() { + if [[ ! -f "$STORAGE/$1" ]];then _msg "No such clipboard: '$1'" return fi - path=$( _get_item "$1" ) - if [[ ! -e "$path" ]]; then - _msg "No such path: $1 -> '$path'" + while read f; do + _paste_single "$f" + done < "${STORAGE}/$1" + + if [[ "$movelink" = 1 ]]; then + keeplink=0 + fi + if [[ "$softlink" = 1 ]]; then + keeplink=1 + fi + if [[ ! "$keeplink" = 1 ]]; then + echo "Removing link: $1" + rm "$STORAGE/$1" + fi + +} + + +_paste_single() { + if [[ ! -e "$1" ]]; then + _msg "No such path: $1" return fi - target=$( basename "$path" ) - if [[ -d "$path" ]]; then + target=$( basename "$1" ) + if [[ -d "$1" ]]; then extension="" basetarget="${target}" else @@ -180,55 +248,76 @@ _paste_single() { origbase="$basetarget" post=0 - while [[ -e "${basetarget}${extension}" ]]; do + while [[ -e "${OUTPUT}/${basetarget}${extension}" ]]; do post=$(( post + 1 )) basetarget="${origbase}-${post}" done target="${basetarget}${extension}" + # -L dereference symlinks, -P no-deref (keep as symlink) + # -H follow symlinks 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 + echo Moving "${1} -> $target" + mv "$1" "$target" + return $? fi - if [[ ! "$keeplink" = 1 ]]; then - echo "Removing link: $1" - rm "$STORAGE/$1" + + if [[ "$softlink$hardlink" = "11" ]]; then + _msg "Can not do both soft and hard link" + exit 1 fi + + if [[ "$softlink" = 1 ]]; then + echo Symbolic link "${1} -> ${OUTPUT}/$target" + ln -s "${1}" "${OUTPUT}/$target" + return $? + fi + + if [[ "$hardlink" = 1 ]]; then + echo Hard link "${1} -> ${OUTPUT}/$target" + cp -aTl "${1}" "${OUTPUT}/$target" + return $? + fi + + echo Copying "${1} -> ${OUTPUT}/$target" + cp -aT "${1}" "${OUTPUT}/$target" || return + } _remove() { + # Remove files based on clipboard 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 + CLIPBOARD=$( echo "${!i}" | tr -d './' | tr -cd '[[:print:]]' ) - echo "Removing data: ${path}" - rm -ir "$path" - echo "Removing link: ${!i}" - rm "$STORAGE/${!i}" + if [[ ! -e "$STORAGE/${CLIPBOARD}" ]];then + _msg "No such clipboard: '${CLIPBOARD}'" + continue + fi + _list l "$CLIPBOARD" + echo "Sure to delete? [Enter]" + read foo + while read f; do + if [[ ! -e "$f" ]]; then + _msg "No such path: '$f'" + continue + fi + echo "Removing SOURCE data: ${f}" + rm -r "$f" || exit 1 + done < "${STORAGE}/$CLIPBOARD" + + echo "Removing clipboard: ${CLIPBOARD}" + rm "$STORAGE/${CLIPBOARD}" done } _delete() { # name - + if [[ $# -lt 2 ]]; then + _help + fi for (( i=2; i<=$#; i++ )); do name=$( basename "${!i}" ) if [[ ! -e "$STORAGE/$name" ]]; then @@ -236,7 +325,8 @@ _delete() { # name EC=1 continue fi - printf "Removing %s: %s\n" "$name" $( _get_item "$name" ) + printf "Clearing %s:\n" "$name" + cat "$STORAGE/$name" rm "$STORAGE/$name" done } @@ -247,7 +337,7 @@ _delete_all() { } _simple_list [[ "$FORCE" -ne 1 ]] && { - read -p "Really delete the whole clipboard? ($STORAGE) Break to cancel. " foo + read -p "Really clear the whole clipboard? ($STORAGE) Break to cancel. " foo } rm -vrf "$STORAGE/" mkdir "$STORAGE" @@ -268,7 +358,7 @@ if [[ $COMP_CWORD -eq 1 ]]; then fi if [[ $COMP_CWORD -eq 2 ]]; then case ${COMP_WORDS[$(( $COMP_CWORD - 1 ))]} in - p|paste|d*|rm|remove) + p|paste|d*|e|edit|rm|remove) local IFS=$'"'"'\n'"'"' local remotelist=( $( eval CCLIP_EXEC simplelist ) ) COMPREPLY=( $(compgen -W "${remotelist[*]}" -- $curr_arg ) ); @@ -294,11 +384,14 @@ done _load_config source qolop &>/dev/null || true CMD="${1:-list}" -[[ "$CMD" = help || "$CMD" = "-h" || "$CMD" = "--help" ]] && { _help; } -[[ "$CMD" = "l" || "$CMD" = "list" ]] && { _list; } +CLIPBOARD=0 +OUTPUT=. +[[ "$CMD" = help || "$CMD" = h || "$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" = "e" || "$CMD" = "edit" ]] && { _edit "$@"; } [[ "$CMD" = "p" || "$CMD" = "paste" ]] && { _paste "$@"; } [[ "$CMD" = "rm" || "$CMD" = "remove" ]] && { _remove "$@"; }