140 lines
		
	
	
		
			4.7 KiB
		
	
	
	
		
			Bash
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			140 lines
		
	
	
		
			4.7 KiB
		
	
	
	
		
			Bash
		
	
	
		
			Executable File
		
	
	
	
	
#!/usr/bin/env bash
 | 
						||
# video demo at: http://www.youtube.com/watch?v=90xoathBYfk
 | 
						||
 | 
						||
# augmented by barbuk: https://github.com/BarbUk/dotfiles/blob/master/bin/snippy
 | 
						||
#  . restore current clipboard
 | 
						||
#  . {clipboard} placeholder to use current clipboard in snippet
 | 
						||
#  . {cursor} placeholder to place the cursor
 | 
						||
#  . ##noparse header in snippet to not parse
 | 
						||
#  . execute command begining by $
 | 
						||
#
 | 
						||
# augmented by "opennomad": https://gist.github.com/opennomad/15c4d624dce99066a82d
 | 
						||
# originally written by "mhwombat": https://bbs.archlinux.org/viewtopic.php?id=71938&p=2
 | 
						||
# Based on "snippy" by "sessy"
 | 
						||
# (https://bbs.archlinux.org/viewtopic.php?id=71938)
 | 
						||
#
 | 
						||
# You will also need "dmenu", "zenity", "xsel" and "xdotool". Get them from your linux
 | 
						||
# distro in the usual way.
 | 
						||
#
 | 
						||
# To use:
 | 
						||
# 1. Create the directory ~/.snippy
 | 
						||
#
 | 
						||
# 2. Create a file in that directory for each snippet that you want.
 | 
						||
#    The filename will be used as a menu item, so you might want to
 | 
						||
#    omit the file extension when you name the file.
 | 
						||
#
 | 
						||
#    TIP: If you have a lot of snippets, you can organise them into
 | 
						||
#    subdirectories under ~/.snippy.
 | 
						||
#
 | 
						||
#    TIP: The contents of the file will be pasted asis, so if you
 | 
						||
#    don't want a newline at the end when the text is pasted, don't
 | 
						||
#    put one in the file.
 | 
						||
#
 | 
						||
# 3. Bind a convenient key combination to this script.
 | 
						||
#
 | 
						||
#    TIP: If you're using XMonad, add something like this to xmonad.hs
 | 
						||
#      ((mod4Mask, xK_s), spawn "/path/to/snippy")
 | 
						||
#
 | 
						||
# 4. Set variables in ~/.snippy.conf. for example
 | 
						||
#    MENU_ENGINE="dmenu"
 | 
						||
#    DMENU_ARGS=' -p snippy -fn arial -sf green'
 | 
						||
#    ZENITY_ARGS='--list --hide-header --column=Snippet --text=snippy'
 | 
						||
#    GUIPASTE="xdotool key ctrl+v"
 | 
						||
#    CLIPASTE="xdotool key ctrl+shift+v"
 | 
						||
 | 
						||
DIR=${HOME}/.snippy
 | 
						||
MENU_ENGINE="rofi"
 | 
						||
DMENU_ARGS='-dmenu -i -sort'
 | 
						||
# if nothing happens, try "xdotool click 2", "xdotool key ctrl+v" or "xdotool key ctrl+shift+v"
 | 
						||
GUIPASTE="xdotool key ctrl+v"
 | 
						||
CLIPASTE="xdotool key ctrl+shift+v"
 | 
						||
 | 
						||
TMPFILE="/tmp/.snippy.tmp"; :>$TMPFILE
 | 
						||
 | 
						||
MENU_ARGS=${DMENU_ARGS}
 | 
						||
 | 
						||
# smarty like template engine which executes inline bash in (bashdown) strings (replaces variables with values e.g.)
 | 
						||
# @link http://github.com/coderofsalvation/bashdown
 | 
						||
# @dependancies: sed cat
 | 
						||
# @example: echo 'hi $NAME it is $(date)' | bashdown
 | 
						||
# fetches a document and interprets bashsyntax in string (bashdown) templates
 | 
						||
# @param string - string with bash(down) syntax (usually surrounded by ' quotes instead of ")
 | 
						||
bashdown(){
 | 
						||
    while IFS= read -r line; do
 | 
						||
        line="$(eval "printf -- \"$( printf "%s" "$line" | sed 's/"/\\"/g')\"")";
 | 
						||
        echo -e "$line"
 | 
						||
    done
 | 
						||
}
 | 
						||
 | 
						||
is_gui(){
 | 
						||
    name="$(xprop -id "$(xdotool getwindowfocus)" WM_CLASS | cut -d'"' -f2 | tr '[:upper:]' '[:lower:]')"
 | 
						||
    [[ "$name" =~ term|tilda|kitty|alacritty ]] && return 1
 | 
						||
    return 0
 | 
						||
}
 | 
						||
 | 
						||
run(){
 | 
						||
    cd "${DIR}" || exit
 | 
						||
    # Use the filenames in the snippy directory as menu entries.
 | 
						||
    # Get the menu selection from the user.
 | 
						||
    # shellcheck disable=SC2086
 | 
						||
    FILE=$(find -L .  -type f | grep -v '^\.$' | sed 's!\.\/!!' | grep -vE '\.git/|\.gitconfig|\.gitkeep' | ${MENU_ENGINE} ${MENU_ARGS} -p '❯ ')
 | 
						||
    # just return if nothing was selected
 | 
						||
    [[ -z "${FILE}" ]] && return 1
 | 
						||
 | 
						||
    if [ -f "${DIR}/${FILE}" ]; then
 | 
						||
        # Put the contents of the selected file into the paste buffer.
 | 
						||
        # don't parse file with the ##noparse header
 | 
						||
        if grep -qE "^##noparse" "${FILE}"; then
 | 
						||
            content="$(tail -n +2 "${DIR}/${FILE}")"
 | 
						||
        else
 | 
						||
            content="$(bashdown < "${DIR}/${FILE}")"
 | 
						||
        fi
 | 
						||
        printf "%s" "$content" > $TMPFILE
 | 
						||
    else [[ ${FILE} =~ ^$ ]]
 | 
						||
        ${FILE##*$} 2>/dev/null > $TMPFILE # execute as bashcommand
 | 
						||
    fi
 | 
						||
 | 
						||
    local current_clip cursor
 | 
						||
    current_clip=$(xsel -b)
 | 
						||
    # define cursor at 0, we don't need to go up if there is no {cursor}
 | 
						||
    cursor=0
 | 
						||
 | 
						||
    # replace {clipboard} by the cliboard comtent
 | 
						||
    sed -i -e "s~{clipboard}~${current_clip}~g" "$TMPFILE"
 | 
						||
 | 
						||
    # Check if there is a {cursor} placeholder
 | 
						||
    if grep -qF '{cursor}' "$TMPFILE";then
 | 
						||
        local file_lines
 | 
						||
        # retrieve the line
 | 
						||
        cursor=$(grep -n '{cursor}' "$TMPFILE" | cut -d: -f1)
 | 
						||
        # calculate snippet total lines
 | 
						||
        file_lines=$(wc -l < "$TMPFILE")
 | 
						||
        # determine the number of line to go
 | 
						||
        cursor=$((file_lines - cursor))
 | 
						||
        # remove the placeholder
 | 
						||
        sed -i -e "s/{cursor}//g" "$TMPFILE"
 | 
						||
    fi
 | 
						||
 | 
						||
    xsel -b --input < "$TMPFILE"
 | 
						||
    # Paste into the current application.
 | 
						||
    if is_gui; then
 | 
						||
        ${GUIPASTE}
 | 
						||
 | 
						||
        if [[ $cursor -gt 0 ]]; then
 | 
						||
            local keyup
 | 
						||
            until [  $cursor -eq 0 ]; do
 | 
						||
                keyup+="Up "
 | 
						||
            ((cursor-=1))
 | 
						||
            # shellcheck disable=SC2086
 | 
						||
            xdotool key --delay -0.1 $keyup
 | 
						||
        done
 | 
						||
        fi
 | 
						||
    else
 | 
						||
        ${CLIPASTE}
 | 
						||
    fi
 | 
						||
 | 
						||
    echo -ne "$current_clip" | xsel -b --input
 | 
						||
}
 | 
						||
 | 
						||
run
 |