diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..eebb821 --- /dev/null +++ b/flake.nix @@ -0,0 +1,36 @@ +{ + description = "Nix q.sh dev environment"; + + # Flake inputs + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs"; + }; + + # Flake outputs + outputs = { self, nixpkgs }: + let + # Systems supported + allSystems = [ + "x86_64-linux" # 64-bit Intel/AMD Linux + "aarch64-linux" # 64-bit ARM Linux + "x86_64-darwin" # 64-bit Intel macOS + "aarch64-darwin" # 64-bit ARM macOS + ]; + + # Helper to provide system-specific attributes + forAllSystems = f: nixpkgs.lib.genAttrs allSystems (system: f { + pkgs = import nixpkgs { inherit system; }; + }); + in + { + # Development environment output + devShells = forAllSystems ({ pkgs }: { + default = pkgs.mkShell { + # The Nix packages provided in the environment + packages = with pkgs; [ + fzf + ]; + }; + }); + }; +} diff --git a/q b/q index b97b6d8..95f87f2 100755 --- a/q +++ b/q @@ -1,4 +1,4 @@ -#!/bin/bash +#!/bin/sh # # Distributed under the terms of the BSD License # @@ -29,181 +29,181 @@ set -e if [[ -z "$Q_SCRIPT_DIR" ]]; then - Q_SCRIPT_DIR=~/.config/q.sh + Q_SCRIPT_DIR=~/.config/q.sh fi -SELF="$0" +SELF=$(cd -P -- "$(dirname -- "$0")" && printf '%s\n' "$(pwd -P)/$(basename -- "$0")") INDEX_FILE=~/.q.index HINT_FILE=~/.q.hints new_scripts_exist() { - if [[ ! -d "$Q_SCRIPT_DIR" ]]; then - return 0 - fi + if [[ ! -d "$Q_SCRIPT_DIR" ]]; then + return 0 + fi - if [[ ! -s "$INDEX_FILE" ]]; then - return 0 - fi + if [[ ! -s "$INDEX_FILE" ]]; then + return 0 + fi - NEWER_FILES="$(find "$Q_SCRIPT_DIR" -name "q-*" -newer "$INDEX_FILE")" + NEWER_FILES="$(find "$Q_SCRIPT_DIR" -name "q-*" -newer "$INDEX_FILE")" - if [[ -z "$NEWER_FILES" ]]; then - return 1 - fi + if [[ -z "$NEWER_FILES" ]]; then + return 1 + fi - return 0 + return 0 } rebuild_index() { - if [[ ! -d "$Q_SCRIPT_DIR" ]]; then - return - fi + if [[ ! -d "$Q_SCRIPT_DIR" ]]; then + return + fi - pushd "$Q_SCRIPT_DIR" >/dev/null - find . -type f -name 'q-*' | while read -r FN - do - FILENAME="$(echo "$FN" | sed 's/^\.\///g')" + pushd "$Q_SCRIPT_DIR" >/dev/null + find . -type f -name 'q-*' | while read -r FN + do + FILENAME="$(echo "$FN" | sed 's/^\.\///g')" - "$Q_SCRIPT_DIR/$FILENAME" | while read -r line - do - echo "/$line/ {print \"$FILENAME\"}" - done - done - popd > /dev/null + "$Q_SCRIPT_DIR/$FILENAME" | while read -r line + do + echo "/$line/ {print \"$FILENAME\"}" + done + done + popd > /dev/null } rebuild_hints() { - if [[ ! -d "$Q_SCRIPT_DIR" ]]; then - return - fi + if [[ ! -d "$Q_SCRIPT_DIR" ]]; then + return + fi - pushd "$Q_SCRIPT_DIR" >/dev/null - find . -type f -name 'q-*' | while read -r FN - do - FILENAME="$(echo "$FN" | sed 's/^\.\///g')" + pushd "$Q_SCRIPT_DIR" >/dev/null + find . -type f -name 'q-*' | while read -r FN + do + FILENAME="$(echo "$FN" | sed 's/^\.\///g')" - "$Q_SCRIPT_DIR/$FILENAME" --hint - done - popd > /dev/null + "$Q_SCRIPT_DIR/$FILENAME" --hint + done + popd > /dev/null } get_scripts_for_cmd() { - if [[ ! -f "$INDEX_FILE" ]]; then - return - fi + if [[ ! -f "$INDEX_FILE" ]]; then + return + fi - echo "$1" | awk -f "$INDEX_FILE" | while read -r line - do - echo "$line" - done + echo "$1" | awk -f "$INDEX_FILE" | while read -r line + do + echo "$line" + done } complete_command() { - COMMAND="$@" - SCRIPTS="$(get_scripts_for_cmd "$COMMAND")" - if [ -z "$SCRIPTS" ] || \ - [ "$(echo "$SCRIPTS" | wc -w)" -gt "1" ]; then - cat "$HINT_FILE" - exit 0 - fi - "$Q_SCRIPT_DIR/$SCRIPTS" --complete "$@" + COMMAND="$@" + SCRIPTS="$(get_scripts_for_cmd "$COMMAND")" + if [ -z "$SCRIPTS" ] || \ + [ "$(echo "$SCRIPTS" | wc -w)" -gt "1" ]; then + cat "$HINT_FILE" + exit 0 + fi + "$Q_SCRIPT_DIR/$SCRIPTS" --complete "$@" } run_command() { - COMMAND="$@" - FIRST=${COMMAND%%" "*} - REST=${COMMAND#*" "} - SCRIPTS="$(get_scripts_for_cmd "$REST")" - if [ -z "$SCRIPTS" ] || \ - [ "$(echo "$SCRIPTS" | wc -w)" -gt "1" ]; then - echo "Scripts matched: $SCRIPTS" - exit 0 - fi - "$Q_SCRIPT_DIR/$SCRIPTS" --run "$FIRST" "$REST" + COMMAND="$@" + FIRST=${COMMAND%%" "*} + REST=${COMMAND#*" "} + SCRIPTS="$(get_scripts_for_cmd "$REST")" + if [ -z "$SCRIPTS" ] || \ + [ "$(echo "$SCRIPTS" | wc -w)" -gt "1" ]; then + echo "Scripts matched: $SCRIPTS" + exit 0 + fi + "$Q_SCRIPT_DIR/$SCRIPTS" --run "$FIRST" "$REST" } run_command_cli() { - COMMAND="$@" - SCRIPTS="$(get_scripts_for_cmd "$COMMAND")" - if [ -z "$SCRIPTS" ] || \ - [ "$(echo "$SCRIPTS" | wc -w)" -gt "1" ]; then - echo "Scripts matched: $SCRIPTS" - exit 0 - fi - "$Q_SCRIPT_DIR/$SCRIPTS" --cli "$COMMAND" + COMMAND="$@" + SCRIPTS="$(get_scripts_for_cmd "$COMMAND")" + if [ -z "$SCRIPTS" ] || \ + [ "$(echo "$SCRIPTS" | wc -w)" -gt "1" ]; then + echo "Scripts matched: $SCRIPTS" + exit 0 + fi + "$Q_SCRIPT_DIR/$SCRIPTS" --cli "$COMMAND" } preview_command() { - COMMAND="$@" - FIRST=${COMMAND%%" "*} - REST=${COMMAND#*" "} - SCRIPTS="$(get_scripts_for_cmd "$REST")" - if [ -z "$SCRIPTS" ] || \ - [ "$(echo "$SCRIPTS" | wc -w)" -gt "1" ]; then - echo "Scripts matched: $SCRIPTS" - exit 0 - fi - "$Q_SCRIPT_DIR/$SCRIPTS" --preview "$FIRST" "$REST" + COMMAND="$@" + FIRST=${COMMAND%%" "*} + REST=${COMMAND#*" "} + SCRIPTS="$(get_scripts_for_cmd "$REST")" + if [ -z "$SCRIPTS" ] || \ + [ "$(echo "$SCRIPTS" | wc -w)" -gt "1" ]; then + echo "Scripts matched: $SCRIPTS" + exit 0 + fi + "$Q_SCRIPT_DIR/$SCRIPTS" --preview "$FIRST" "$REST" } if [[ ! -f "$INDEX_FILE" ]] || new_scripts_exist; then - rebuild_index > "$INDEX_FILE" - rebuild_hints > "$HINT_FILE" + rebuild_index > "$INDEX_FILE" + rebuild_hints > "$HINT_FILE" fi while (( "$#" )); do - case "$1" in - -c|--complete) - shift - complete_command "$@" - exit 0 - ;; - -r|--run) - shift - if [[ -z "$@" ]]; then - exit 0 - fi - run_command "$@" - exit 0 - ;; - -p|--preview) - shift - if [[ -z "$@" ]]; then - exit 0 - fi - preview_command "$@" - exit 0 - ;; - -u|--update) - shift - rebuild_index > "$INDEX_FILE" - rebuild_hints > "$HINT_FILE" - exit 0 - ;; - *) - break - ;; - esac + case "$1" in + -c|--complete) + shift + complete_command "$@" + exit 0 + ;; + -r|--run) + shift + if [[ -z "$@" ]]; then + exit 0 + fi + run_command "$@" + exit 0 + ;; + -p|--preview) + shift + if [[ -z "$@" ]]; then + exit 0 + fi + preview_command "$@" + exit 0 + ;; + -u|--update) + shift + rebuild_index > "$INDEX_FILE" + rebuild_hints > "$HINT_FILE" + exit 0 + ;; + *) + break + ;; + esac done COMMAND="$@" if [[ -z "$COMMAND" ]] && [[ ! -t 0 ]]; then - COMMAND="$(cat)" + COMMAND="$(cat)" fi if [[ -z "$COMMAND" ]]; then - PREF="$SELF -c" - INITIAL="" - FZF_DEFAULT_COMMAND="$PREF '$INITIAL'" fzf \ - --bind "change:reload:$PREF {q} || true" \ - --ansi --query "$INITIAL" \ - --preview "$SELF -p {}" \ - --with-nth="2..-1" \ - --preview-window wrap \ - --tiebreak=index | xargs -o "$SELF" -r + PREF="$SELF -c" + INITIAL="" + FZF_DEFAULT_COMMAND="$PREF '$INITIAL'" fzf \ + --bind "change:reload-sync:$PREF {q} || true" \ + --ansi --query "$INITIAL" \ + --preview "$SELF -p {}" \ + --with-nth="2..-1" \ + --preview-window wrap \ + --tiebreak=index | xargs -o "$SELF" -r else - run_command_cli "$COMMAND" + run_command_cli "$COMMAND" fi diff --git a/q-bookmarks b/q-bookmarks index c5e3245..f68965f 100755 --- a/q-bookmarks +++ b/q-bookmarks @@ -1,24 +1,24 @@ -#!/bin/bash +#!/bin/sh if [[ -z "$@" ]]; then - echo "^b .*$" + echo "^b .*$" elif [[ "$1" == "--hint" ]]; then - shift - if [[ -f ~/.bookmarks.txt ]]; then - cat ~/.bookmarks.txt | awk '{print $1 " b " $2}' - fi + shift + if [[ -f ~/.bookmarks.txt ]]; then + cat ~/.bookmarks.txt | awk '{print $1 " b " $2}' + fi elif [[ "$1" == "--complete" ]]; then - shift - if [[ -f ~/.bookmarks.txt ]]; then - cat ~/.bookmarks.txt | awk '{print $1 " b " $2}' - fi + shift + if [[ -f ~/.bookmarks.txt ]]; then + cat ~/.bookmarks.txt | awk '{print $1 " b " $2}' + fi elif [[ "$1" == "--preview" ]]; then - shift - echo "$1" + shift + echo "$1" elif [[ "$1" == "--run" ]]; then - shift - xdg-open "$1" + shift + xdg-open "$1" else - echo "Unexpected arguments: $@" + echo "Unexpected arguments: $@" fi diff --git a/q-browse b/q-browse new file mode 100755 index 0000000..2562253 --- /dev/null +++ b/q-browse @@ -0,0 +1,19 @@ +#!/bin/sh + +if [[ -z "$@" ]]; then + echo "^f .*$" +elif [[ "$1" == "--hint" ]]; then + shift +elif [[ "$1" == "--complete" ]]; then + shift + echo "0 $@" +elif [[ "$1" == "--preview" ]]; then + shift + URL="$(echo "$@" | cut -d ' ' -f3-)" + echo "Will open '$URL' in firefox" +elif [[ "$1" == "--run" ]]; then + shift + URL="$(echo "$@" | cut -d ' ' -f3-)" + (nohup xdg-open "$URL" 2>/dev/null &) + sleep 0.01 +fi diff --git a/q-calc b/q-calc index 596a72f..36f3b60 100755 --- a/q-calc +++ b/q-calc @@ -1,33 +1,33 @@ -#!/bin/bash +#!/bin/sh calc() { - res="$(echo "$1" | bc 2>/dev/null)" - if [ "$res" == "" ]; then - res="-" - fi - echo "$res" + res="$(echo "$1" | bc 2>/dev/null)" + if [ "$res" == "" ]; then + res="-" + fi + echo "$res" } if [[ -z "$@" ]]; then - echo "^= .*$" + echo "^= .*$" elif [[ "$1" == "--hint" ]]; then - shift - echo "- = " + shift + echo "- = " elif [[ "$1" == "--complete" ]]; then - shift - EXPR="$(echo "$@" | cut -d ' ' -f2-)" - RES="$(calc "$EXPR")" - echo "$RES = $EXPR -> $(calc "$EXPR")" + shift + EXPR="$(echo "$@" | cut -d ' ' -f2-)" + RES="$(calc "$EXPR")" + echo "$RES = $EXPR -> $(calc "$EXPR")" elif [[ "$1" == "--preview" ]]; then - shift - echo "$1" + shift + echo "$1" elif [[ "$1" == "--run" ]]; then - shift - echo "$1" - echo "$1" | (nohup wl-copy -n 2>/dev/null &) + shift + echo "$1" + echo "$1" | (nohup wl-copy -n 2>/dev/null &) elif [[ "$1" == "--cli" ]]; then - shift - calc "$(echo "$@" | cut -d ' ' -f2-)" + shift + calc "$(echo "$@" | cut -d ' ' -f2-)" else - echo "Unexpected arguments: $@" + echo "Unexpected arguments: $@" fi diff --git a/q-clipboard b/q-clipboard index fb10a29..1dcb76b 100755 --- a/q-clipboard +++ b/q-clipboard @@ -1,26 +1,26 @@ -#!/bin/bash +#!/bin/sh if [[ -z "$@" ]]; then - echo "^c .*$" + echo "^c .*$" elif [[ "$1" == "--hint" ]]; then - shift - if [[ -f ~/.clipboard.txt ]]; then - cat ~/.clipboard.txt | tac - fi + shift + if [[ -f ~/.clipboard.txt ]]; then + cat ~/.clipboard.txt | tac + fi elif [[ "$1" == "--complete" ]]; then - shift - if [[ -f ~/.clipboard.txt ]]; then - cat ~/.clipboard.txt | tac - fi + shift + if [[ -f ~/.clipboard.txt ]]; then + cat ~/.clipboard.txt | tac + fi elif [[ "$1" == "--preview" ]]; then - shift - echo "$1" | base64 -d + shift + echo "$1" | base64 -d elif [[ "$1" == "--run" ]]; then - shift - TEXT="$(echo "$1" | base64 -d)" - echo "$TEXT" - echo -n "$TEXT" | (nohup wl-copy -n 2>/dev/null &) + shift + TEXT="$(echo "$1" | base64 -d)" + echo "$TEXT" + echo -n "$TEXT" | (nohup wl-copy -n 2>/dev/null &) else - echo "Unexpected arguments: $@" + echo "Unexpected arguments: $@" fi diff --git a/q-pass b/q-pass index 118c78f..dbf9da6 100755 --- a/q-pass +++ b/q-pass @@ -1,34 +1,34 @@ -#!/bin/bash +#!/bin/sh if [[ -z "$@" ]]; then - # Return a regular expression that should trigger - # this subcommand. q.sh will then pass control to - # this script whenever the input line matches. - echo "^p .*$" + # Return a regular expression that should trigger + # this subcommand. q.sh will then pass control to + # this script whenever the input line matches. + echo "^p .*$" elif [[ "$1" == "--hint" ]]; then - # This subcommand has no hints - shift + # This subcommand has no hints + shift elif [[ "$1" == "--complete" ]]; then - shift - # Return a list of all accounts for which we store - # passwords. This will be used to provide a list of - # completions. - cd ~/.password-store - find . -name "*.gpg" | sed -E 's/\.\/(.*)\.gpg/\1 p \1/' + shift + # Return a list of all accounts for which we store + # passwords. This will be used to provide a list of + # completions. + cd ~/.password-store + find . -name "*.gpg" | sed -E 's/\.\/(.*)\.gpg/\1 p \1/' elif [[ "$1" == "--preview" ]]; then - shift - # This information will be displayed in the preview - # pane on the right. - echo "Will get password for $1" + shift + # This information will be displayed in the preview + # pane on the right. + echo "Will get password for $1" elif [[ "$1" == "--run" ]]; then - shift - # This will be triggered when enter is pressed on - # one of the options. We now decrypt the password - # and place it to the clipboard. - NAME="$1" - pass "$NAME" | (nohup wl-copy -n 2>/dev/null &) + shift + # This will be triggered when enter is pressed on + # one of the options. We now decrypt the password + # and place it to the clipboard. + NAME="$1" + pass "$NAME" | (nohup wl-copy -n 2>/dev/null &) - # A short sleep is needed to wait for child process - # to spawn before exiting. - sleep 0.01 + # A short sleep is needed to wait for child process + # to spawn before exiting. + sleep 0.01 fi diff --git a/q-run b/q-run new file mode 100755 index 0000000..cf74fe5 --- /dev/null +++ b/q-run @@ -0,0 +1,26 @@ +#!/bin/sh + +export PATH=~/.prefix/bin:~/.local/bin:$PATH + +find_all_executables() { + { + IFS=:; for d in $PATH; do for f in $d/*; do [ -f $f ] && [ -x $f ] && echo ${f##*/}; done; done; + } | sort + #flatpak --columns=application --app list | tail -n +1 | awk '{print "flatpak run " $0}'; +} + +if [[ -z "$@" ]]; then + echo "^run [a-zA-Z0-9_-]*$" +elif [[ "$1" == "--hint" ]]; then + find_all_executables | awk '{print $1 " run " $1}' +elif [[ "$1" == "--complete" ]]; then + shift + find_all_executables | awk '{print $1 " run " $1}' +elif [[ "$1" == "--preview" ]]; then + shift + echo "Will run $1" +elif [[ "$1" == "--run" ]]; then + shift + (nohup "$1" 2>/dev/null &) + sleep 0.01 +fi