Files
q-tools/files/cclip

322 lines
6.8 KiB
Bash
Executable File

#!/bin/bash
set -e
_help() {
SELF=$( basename "$0" )
echo "Console Clipboard manager
Usage: $SELF [command] [name] [filename]
Short Command Description
p paste Display on screen / copies to file
c copy Save from stdin / from file
x cut Move file to clipboard
d delete Delete an entry
D Delete Clear the whole clibboard
e edit Edit contents, with \$EDITOR
l list [default] List names of clipboards
pmenu pastemenu Paste a file/folder using a simple menu (ex. for MC)
autocomplete Get Bash autocompletion script
Name: Any string for the clipboard name. default: 0
Filename:
When reading from clipboard:
File or folder to write the clipboard contents. If omitted: stdout
When writing to clipboard:
File or folder to read from. If omitted: stdin
Shorthand:
echo my data | $SELF 1 # writes data with name: 1
$SELF 1 | cat - # prints the contents of file: 1
Config:
CCLIP_HOME environment variable sets clipboard storage path,
defauls to ~/.cache/cclip
"
exit
}
_load_config() {
STORAGE=${CCLIP_HOME:-~/.cache/cclip}
[[ -d "$STORAGE" ]] || {
_msg "Creating $STORAGE folder, and inserting sample data"
mkdir -p "$STORAGE"
echo Sample data | _write_stdin 0
}
}
_list() {
cd "$STORAGE"
[[ $(ls -A) ]] || {
_msg "No clipboard entries"
return
}
printf " %30s %8s %-19s %s\n" Type Size Date Name
for n in *; do
size=$( du -k -h -s --apparent-size "$n" | awk '{ print $1 }' )
type=$( file -b "$n" )
date=$( date -r "$n" -Iseconds )
printf " %30s %8s %-19s %s\n" \
"${type:0:30}" \
"$size" \
"${date::-6}" \
"$n"
done
}
_simple_list() {
ls "$STORAGE"
}
_write() {
# no file mentioned, use stdin
[[ -z "$FILE" ]] && stream_in=1
# no file mentioned, use the name as file
[[ -z "$FILE" ]] && {
[[ -e "$NAME" ]] && {
# NAME is actually the file, reverse roles
FILE="$NAME"
NAME=$( basename "$NAME" )
}
}
[[ -e "$FILE" ]] && {
# Input file exists, dont use stream
stream_in=0
}
[[ $stream_in -ne 1 ]] && [[ -z "$FILE" ]] && {
_msg File to read needed, or use stdin
exit 1
}
# sure to write something, delete target first
rm -rf "$STORAGE/$NAME"
[[ "$stream_in" -eq 1 ]] && {
_write_stdin "$NAME"
} || {
_write_files "$NAME" "$FILE"
}
}
_write_files() { # name, file
if [[ $MOVE = true ]]; then
echo Cutting "$2" to "$1"
mv "$2" "$STORAGE/$1"
else
echo Copying "$2" to "$1"
cp -aT "$2" "$STORAGE/$1"
fi
touch "$STORAGE/$1"
}
_write_stdin() { # name
cat - > "$STORAGE/$1"
}
_read_menu() {
pushd "$STORAGE" &>/dev/null
echo "Select clipboard from menu"
ls
read -e NAME
popd &>/dev/null
if [[ -e "$STORAGE/$NAME" ]]; then
NAME=$( basename $NAME )
_read
fi
}
_read() {
[[ -e "$STORAGE/$NAME" ]] || {
_msg "No such clipboard: '$NAME'"
return
}
[[ "$FILE" = "-" ]] && stream_out=1
[ -t 1 ] || stream_out=1
[[ "$stream_out" -eq 1 ]] && {
_read_stdout "$NAME"
return
}
# no file mentioned, use the name as file
[[ -z "$FILE" ]] && {
[[ -n "$NAME" ]] && {
FILE=$( basename "$NAME" )
}
[[ -e "$FILE" ]] && {
echo "'$FILE' already exists, not overwriting"
exit 1
}
}
_read_files "$NAME" "$FILE"
}
_read_files() { # name, file
echo Pasting "$1" to "$2"
cp -aT "$STORAGE/$1" "$2"
}
_read_stdout() { # name
cat "$STORAGE/$1"
}
_delete() { # name
[[ -e "$STORAGE/$1" ]] || {
_msg No such clipboard
exit 1
}
[[ "$FORCE" -ne 1 ]] && {
read -p "Really delete $1 ? Break to cancel. " foo
}
echo Deleting "$1"
rm -rf "$STORAGE/$1"
}
_delete_all() {
[[ -e "$STORAGE" ]] || {
exit 0
}
[[ "$FORCE" -ne 1 ]] && {
read -p "Really delete $STORAGE ? Break to cancel. " foo
}
rm -vrf "$STORAGE/"
mkdir "$STORAGE"
}
_msg() {
echo "$@" >&2
}
_get_name() {
[[ "$ARG1" = "$CMD" ]] && {
NAME="$ARG2"
} || {
NAME="$ARG1"
}
[[ -z "$NAME" ]] && NAME=0
return 0
}
_get_file() {
[[ "$ARG1" = "$NAME" ]] && {
FILE="$ARG2"
}
[[ "$ARG2" = "$NAME" ]] && {
FILE="$ARG3"
}
return 0
}
_edit() {
EDITOR=${EDITOR:-vi}
[[ -d "$STORAGE/$NAME" ]] && {
_msg "$NAME is a directory, can not edit"
exit 1
}
$EDITOR "$STORAGE/$NAME"
}
_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 x cut p paste delete Delete pmenu" -- $curr_arg ) );
fi
if [[ $COMP_CWORD -eq 2 ]]; then
case ${COMP_WORDS[$(( $COMP_CWORD - 1 ))]} in
p|paste|d*)
local remotelist=$( eval CCLIP_EXEC simplelist )
COMPREPLY=( $(compgen -W "$remotelist" -- $curr_arg ) );
;;
x|c*)
COMPREPLY=( $(compgen -f -d -- $curr_arg ) );
;;
esac
fi
if [[ $COMP_CWORD -eq 3 ]]; then
COMPREPLY=( $(compgen -f -d -- $curr_arg ) );
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
ARG1="$1"
ARG2="$2"
ARG3="$3"
MOVE=false
CMD=help
if [[ -z "$1" ]]; then CMD=list; fi
[[ "$1" = "p" || "$1" = "paste" ]] && { CMD=read; ARG1=$CMD; }
[[ "$1" = "pmenu" || "$1" = "pastemenu" ]] && { CMD=read_menu; ARG1=$CMD; }
[[ "$1" = "c" || "$1" = "copy" ]] && { CMD=write; ARG1=$CMD; }
[[ "$1" = "x" || "$1" = "cut" ]] && { CMD=write; ARG1=$CMD; MOVE=true; }
[[ "$1" = "d" || "$1" = "delete" || "$1" = "del" ]] && { CMD=delete; ARG1=$CMD; }
[[ "$1" = "D" || "$1" = "Delete" || "$1" = "Del" ]] && { CMD=delete_all; ARG1=$CMD; }
[[ "$1" = "l" || "$1" = "list" ]] && { CMD=list; ARG1=$CMD; }
[[ "$1" = "e" || "$1" = "edit" ]] && { CMD=edit; ARG1=$CMD; }
[[ "$1" = "h" || "$1" = "help" ]] && _help
[[ "$1" = "autocomplete" ]] && { _get_completer; exit; }
[[ "$1" = "simplelist" ]] && { _simple_list; exit; }
[[ -n "$1" ]] && [[ -e "$STORAGE"/"$1" ]] && CMD=read
# if stdout redirected, default to read
[ -t 1 ] || CMD=read
# if stdin comes from stream, default to write
[ -t 0 ] || CMD=write
[[ "$CMD" = help ]] && {
_help
exit $?
}
[[ "$CMD" = list ]] && {
_list
exit $?
}
[[ "$CMD" = delete_all ]] && {
_delete_all
exit $?
}
_get_name
_get_file
[[ "$CMD" = read ]] && {
_read
exit $?
}
[[ "$CMD" = read_menu ]] && {
_read_menu
exit $?
}
[[ "$CMD" = delete ]] && {
_delete "$NAME"
exit $?
}
[[ "$CMD" = write ]] && {
_write
exit $?
}
[[ "$CMD" = edit ]] && {
_edit
exit $?
}
# TODO:
# folders written as TAR
# content encrypted with conf variable?