From 546646b46f0536a5667b5232ab78a1e346f0e047 Mon Sep 17 00:00:00 2001 From: Abreu Date: Mon, 9 Aug 2021 23:23:19 -0300 Subject: [PATCH] Initial commit --- .editorconfig | 9 ++ .gitignore | 6 + LICENSE | 14 +++ README.md | 19 +++ dependency.fish | 261 +++++++++++++++++++++++++++++++++++++++++ functions/tsudope.fish | 57 +++++++++ hooks/install.fish | 3 + hooks/uninstall.fish | 1 + hooks/update.fish | 1 + key_bindings.fish | 13 ++ package | 2 + 11 files changed, 386 insertions(+) create mode 100644 .editorconfig create mode 100644 .gitignore create mode 100644 LICENSE create mode 100644 README.md create mode 100644 dependency.fish create mode 100644 functions/tsudope.fish create mode 100644 hooks/install.fish create mode 100644 hooks/uninstall.fish create mode 120000 hooks/update.fish create mode 100644 key_bindings.fish create mode 100644 package diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..4593073 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,9 @@ +# http://editorconfig.org +root = true + +[*] +end_of_line = lf +indent_size = 2 +indent_style = space +insert_final_newline = true +trim_trailing_whitespace = true diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..792edd5 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +* +!.gitignore +!README.md +!LICENSE +!*.fish +dependency.fish diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..047e06c --- /dev/null +++ b/LICENSE @@ -0,0 +1,14 @@ +Copyright (c) 2015-2017 Itzik Ephraim (oranja AT gmail DOT com) +Copyright (c) 2017 Chloe Kudryavtsev + +Permission to use, copy, modify, and distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..ca1bd76 --- /dev/null +++ b/README.md @@ -0,0 +1,19 @@ +[![GPL License](https://img.shields.io/badge/license-GPL-blue.svg?longCache=true&style=flat-square)](/LICENSE) +[![Fish Shell Version](https://img.shields.io/badge/fish-v3.0.1-blue.svg?style=flat-square)](https://fishshell.com) +[![Oh My Fish Framework](https://img.shields.io/badge/Oh%20My%20Fish-Framework-blue.svg?style=flat-square)](https://www.github.com/oh-my-fish/oh-my-fish) + +# tsudope + +> A plugin for [Oh My Fish](https://www.github.com/oh-my-fish/oh-my-fish) + +Prefix your command line with `tsudo ` using a keyboard shortcut. An adaptation of the fish plugin [sudope](github.com/oh-my-fish/plugin-sudope) for Termux's `tsudo`. + +### Usage + +Press `Alt`+`s` to activate it. It will add `tsudo ` to the beginning of the line if missing, remove it if it is present while preserving the cursor position. If the current line is empty, it will do the same thing to the most recent history item. + +### Install + +```fish +omf install tsudope +``` diff --git a/dependency.fish b/dependency.fish new file mode 100644 index 0000000..bdabeb6 --- /dev/null +++ b/dependency.fish @@ -0,0 +1,261 @@ +# Load dependency +function dep_plugin -d "Install or uninstall a fish plugin" + switch "$argv[1]" + case uninstall + omf remove (command basename $argv[2]) >/dev/null 2>&1 + case check + omf list | string match -qr "\b"(command basename $argv[2])"\b" + case '*' + type -t (command basename $argv) 2>/dev/null \ + | string match -q function + and return 0 + omf list | string match -qr "\b"(command basename $argv)"\b" + and return 0 + omf install $argv 2>&1 \ + | not string match -qr '^(Error$|Could not install)' + or return 1 + set -l install_script \ + $OMF_PATH/pkg/(command basename $argv)/hooks/install.fish + test -e "$install_script" + and fish "$install_script" + for function in \ + (command realpath -s $OMF_PATH/pkg/(command basename $argv)/functions/*) + source $function + end + end +end +dep_plugin https://gitlab.com/lusiadas/feedback + +# Parse arguments +if argparse -n dependency 'r/remove' 'n/name=' 'f/force=+' 'N/npm=+' 'p/pip=+' 'P/plugin=+' -- $argv 2>&1 | read err + err $err + exit 1 +end + +# Check for available permissions +set -l sudo +if command id -u | string match -qv 0 + if command groups | string match -qe sudo + type -qf sudo + and set sudo sudo + end +end + +# Check for a default package manager +test -n "$_flag_remove" +and dim -n "Checking available package managers..." +set -l verify +set -l install +set -l remove +if type -qf apt + set verify "dpkg -s" + set install 'apt install -y' + set remove "apt remove -y" +else if type -qf pacman + set verify 'pacman -Qi' + set install 'pacman -S --noconfirm' + set remove 'pacman -Rs --noconfirm' +else if type -qf zypper + set verify 'rpm -q' + set install 'zypper in -y' + set remove 'zypper rm -y' +else if type -qf yum + set verify 'rpm -q' + set install 'yum install -y' + set remove 'yum remove -y' +else if type -qf dnf + set verify 'rpm -q' + set install 'dnf install -y' + set remove 'dnf remove -y' +else if type -qf emerge + set verify 'emerge -p' + set install 'emerge' + set remove 'emerge -c' +else if test "$argv" + err "A package manager wasn't found to handle |"(string join '|, |' $argv)"|" + reg 'Ignoring... ' + set --erase argv +end + +# Search for an specific package manager +if test -n "$_flag_pip" -o -n "$_flag_npm" + set -l flags _flag_pip pip python _flag_npm npm nodejs + for i in 1 4 + set --query $flags[$i] + or continue + if not type -qf $flags[(math $i + 1)] + set -l failed + if test -z "$install" + set failed true + else if read -n 1 -p "wrn -n \"|"$flags[(math $i + 2)]"| isn't installed. Install it before proceding with installation? [y/n]: \"" | string match -viq y + set failed true + end + if test -z "$failed" + dim -on "Installing |"$flags[(math $i + 2)]"|... " + eval $install $flags[(math $i + 2)] >/dev/null 2>&1 + and reg -o "|"$flags[(math $i + 2)]"| installed" + or set failed true + end + if test "$failed" + string match -q $flags[$i] _flag_pip + and set -l packages $_flag_pip + or set -l packages $_flag_npm + err -o "|"$flags[(math $i + 2)]"| isn't installed. Cancelling the installation of |"(string join '|, |' $packages)"|" + set --erase $flags[$i] + end + end + end +end + +# Check if package is installed +set --query _flag_remove +and dim -on "Checking for dependencies... " +set -l dependencies (printf '%s\n' $argv $_flag_pip $_flag_npm $_flag_plugin $_flag_force | sort | uniq) +for dependency in $dependencies + if type -q (command basename $dependency) + set -a installed $dependency + continue + end + if contains $dependency $argv + if eval $verify $dependency >/dev/null 2>&1 + set -a installed $dependency + continue + end + end + if contains $dependency $_flag_plugin $argv + if dep_plugin check $dependency + set -a installed $dependency + continue + end + end + if contains $dependency $_flag_pip $argv + if type -qf pip + if pip show -q $dependency 2>/dev/null + set -a installed $dependency + continue + end + end + end + if contains $dependency $flag_npm $argv + if type -qf npm + if npm list -g | string match -qe $dependency + set -a installed $dependency + continue + end + end + end + set not_installed $not_installed $dependency +end + +# Remove dependencies +if test -n "$_flag_remove" -a -n "$installed" + + # Offer to uninstall dependencies + echo -en \r(tput el) + if test (count $installed) -eq 1 + read -n 1 -p "wrn \"Uninstall dependency |$installed|? [y/n]: \"" \ + | string match -qir y + else + read -n 1 -p "wrn 'Uninstall some dependencies as well? [y/n]: '" \ + | string match -qir y + end + or exit 0 + + # List available dependencies + if test (count $installed) -gt 1 + for i in (seq (count $installed)) + echo $i. $installed[$i] + end + reg -e (math (count $installed) + 1)'. |all|\n'(math (count $installed) + 2)'. |cancel|' + + # Select dependencies to be removed + read -n 1 -lP 'Which? [list one or more]: ' opt + string match -qr -- "[^1-"(math (count $installed) + 1)"]" $opt + and exit 0 + test $opt -le (count $installed) + and set installed $installed[$opt] + end + + # Find the appropriate package manager to uninstall + for dependency in $installed + dim -n "Uninstalling |$dependency|... " + if contains $dependency $argv + if eval "$sudo" $uninstall $dependency >/dev/null 2>&1 + reg -o "|$dependency| removed." + continue + end + end + if contains $dependency $_flag_pip $argv + if command pip list | string match -qr '^youtube-dl\b' + command pip uninstall -y $dependency >/dev/null 2>&1 + reg -o "|$dependency| removed." + continue + end + end + if contains $dependency $_flag_plugin + if dep_plugin uninstall $_flag_plugin + reg -o "|$dependency| removed." + continue + end + end + if contains $dependency $flag_npm + if command npm list -g | string match -qr "\b$dependency(?=@)" + command npm uninstall -g $dependency >/dev/null 2>&1 + reg -o "|$dependency| removed." + continue + end + end + if contains $dependency $_flag_force + if command rm $dependency >/dev/null 2>&1 + reg -o "|$dependency| removed." + continue + end + end + err -o "Failed to uninstall |$dependency|" + end + +# Install dependencies +else if test -z "$not_installed" + exit 0 + +else + # Ask for confirmation + if test -n "$_flag_name" -a -n "$not_installed" + test (count $not_installed) -eq 1 + and wrn -o "Plugin |$_flag_name| requires dependency |"(string match -ar '[^/]+$' $not_installed)"|. Install it? [y/n]: " + or wrn -o "Plugin |$_flag_name| requires dependencies |"(string match -ar '[^/]+$' $not_installed | string join '|, |')"|. Install them? [y/n]: " + read -n 1 | string match -qir y + or exit 1 + end + + # Find appropriate package manager to install + set -l failed + for dependency in $not_installed + dim -on "Installing |"(command basename $dependency)"|... " + if contains $dependency $argv + if eval "$sudo" $install $dependency >/dev/null 2>&1 + reg -o "|$dependency| was installed" + continue + end + else if contains $dependency $_flag_pip + if command pip install --user $dependency >/dev/null 2>&1 + reg -o "|$dependency| added." + continue + end + else if contains $dependency $_flag_plugin + if dep_plugin $dependency + reg -o "|$dependency| added." + continue + end + else if contains $dependency $_flag_npm + if command npm install -g $dependency >/dev/null 2>&1 + reg -o "|$dependency| added." + continue + end + end + err -o "Failed to install |$dependency|" + set failed true + end + functions -e (functions | string match -ar '^dep_.+') + test -z "$failed" +end diff --git a/functions/tsudope.fish b/functions/tsudope.fish new file mode 100644 index 0000000..bb8c8b8 --- /dev/null +++ b/functions/tsudope.fish @@ -0,0 +1,57 @@ +function tsudope -d "Quickly toggle tsudo prefix" + + source (status filename | command xargs dirname)/../dependency.fish -n tsu + or return 1 + + # Save the current command line and cursor position. + set -l command_buffer (commandline) + set -l cursor_position (commandline -C) + + # If the command line is empty, pull the last command from history. + if test -z "$command_buffer" + set command_buffer $history[1] + end + + # Parse the command line (first line only). + set -l command_parts (string match -ir '^(\s*)(tsudo(\s+|$))?(.*)' $command_buffer[1]) + + # Handle multiline commands with extra care. + set -l command_lines_count (count $command_buffer) + test $command_lines_count -gt 1 + and set -l command_rest $command_buffer[2..$command_lines_count] + + switch (count $command_parts) + case 3 + # No "tsudo". + + # Add "tsudo" to the beginning of the command, after any leading whitespace (if present). + commandline -r (string join \n (string join '' $command_parts[2] 'tsudo ' $command_parts[3]) $command_rest) + + # Push the cursor position ahead if necessary (+5 for 'tsudo '). + test $cursor_position -ge (string length -- "$command_parts[2]") + and set cursor_position (math $cursor_position+6) + + # Place the cursor where it was (or where it should be). + commandline -C $cursor_position + + case 5 + # "tsudo" is present in the beginning of the command. + + # Remove "tsudo", leave any leading whitespace (if present). + commandline -r (string join \n (string join '' $command_parts[2 5]) $command_rest) + + # Push the cursor position back if appropriate ('tsudo' and whitespace). + set -l lead_length (string length -- "$command_parts[2]") + set -l tsudo_length (string length -- "$command_parts[3]") + if test $cursor_position -ge (math $lead_length+$tsudo_length) + # The cursor was after "tsudo". + set cursor_position (math $cursor_position-$tsudo_length) + else if test $cursor_position -ge $lead_length + # The cursor was somewhere on "tsudo". + set cursor_position $lead_length + end + + # Place the cursor where it was (or where it should be). + commandline -C -- $cursor_position + end +end diff --git a/hooks/install.fish b/hooks/install.fish new file mode 100644 index 0000000..1d3d6b0 --- /dev/null +++ b/hooks/install.fish @@ -0,0 +1,3 @@ +command wget -qO $path/functions/dependency.fish \ +https://gitlab.com/argonautica/dependency/raw/master/dependency.fish +source $path/dependency.fish -n $package tsu diff --git a/hooks/uninstall.fish b/hooks/uninstall.fish new file mode 100644 index 0000000..d02c559 --- /dev/null +++ b/hooks/uninstall.fish @@ -0,0 +1 @@ +source $path/subfunctions/dependency.fish -r tsu \ No newline at end of file diff --git a/hooks/update.fish b/hooks/update.fish new file mode 120000 index 0000000..69c9327 --- /dev/null +++ b/hooks/update.fish @@ -0,0 +1 @@ +install.fish \ No newline at end of file diff --git a/key_bindings.fish b/key_bindings.fish new file mode 100644 index 0000000..afb342e --- /dev/null +++ b/key_bindings.fish @@ -0,0 +1,13 @@ +# default key sequence: Alt+s +set -q tsudope_sequence + or set -l tsudope_sequence \es + +# if tsudope is already bound to some sequence, leave it +if not bind | string match -rq '[[:space:]]tsudope$' + # not bound but sequence already taken? + if bind $tsudope_sequence >/dev/null 2>/dev/null + echo "tsudope: The requested sequence is already in use:" (bind $tsudope_sequence | cut -d' ' -f2-) + else + bind $tsudope_sequence tsudope + end +end diff --git a/package b/package new file mode 100644 index 0000000..e8cee96 --- /dev/null +++ b/package @@ -0,0 +1,2 @@ +name: sudope +type: plugin \ No newline at end of file