You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

fzrepl 2.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. #!/usr/bin/env bash
  2. usage() {
  3. less -FEXR <<'HELP'
  4. fzrepl
  5. interactively edit stdin using stream filters like awk, sed, jq
  6. -c, --cmd command used to filter input
  7. -q, --query default command string to use
  8. command history can be saved to a file by setting the environment variable
  9. FZREPL_FILE
  10. examples:
  11. echo 'foo bar' | fzrepl -c 'awk {q}' -q '{print}'
  12. echo 'hello world' | fzrepl -q p 'sed -n {q}'
  13. FZREPL_FILE=jqhistory fzrepl jq package.json
  14. HELP
  15. }
  16. # TODO: better "wrapping", this is painful:
  17. # fzrepl 'node -e {q}' -q "done = data => data;\nlet A='';process.stdin.on('data',x=>A=A.concat(x.toString())).on('end',()=>{let d = done(A);process.stdout.write(`${String.prototype.trim.call(typeof d==='string'?d:JSON.stringify(d,null,2))}\n`)})"
  18. declare tmpfile=/tmp/fzreplinput
  19. declare cmd
  20. declare default_query
  21. declare output
  22. declare -A colors
  23. colors[red]=$(tput setaf 1)
  24. colors[green]=$(tput setaf 2)
  25. colors[reset]=$(tput sgr0)
  26. cleanup() {
  27. [[ -e "$tmpfile" ]] && rm "$tmpfile"
  28. }
  29. trap cleanup SIGHUP SIGINT SIGTERM
  30. color() {
  31. local color
  32. color="$1"; shift
  33. printf '%s' "${colors[$color]}" "$*" "${colors[reset]}"
  34. }
  35. err() {
  36. color red "$@" >&2
  37. return 1
  38. }
  39. die() {
  40. (( $# > 0 )) && err "$@"
  41. exit 1
  42. }
  43. for arg; do
  44. case $arg in
  45. -q|--query)
  46. [[ -z $2 || $2 = -* ]] && die "missing argument to $1"
  47. default_query="$2"
  48. shift 2 ;;
  49. -c|--cmd)
  50. [[ -z $2 || $2 = -* ]] && die "missing argument to $1"
  51. cmd="$2"
  52. shift 2 ;;
  53. -h|--help) usage; exit ;;
  54. *) break 2;
  55. esac
  56. done
  57. if [[ -z $cmd && -n $1 && ! -f $1 ]]; then
  58. cmd="$1"
  59. shift
  60. fi
  61. if [[ $cmd != *'{q}'* ]]; then
  62. cmd+=' {q}'
  63. fi
  64. if [[ -n $1 && -f $1 ]]; then
  65. file=$1
  66. shift
  67. fi
  68. if [[ -z $file ]]; then
  69. file=/dev/stdin
  70. fi
  71. mapfile -t REPLY < <(
  72. tee "$tmpfile" < "$file" | fzf \
  73. --height=100% \
  74. --phony \
  75. --print-query \
  76. --query="$default_query" \
  77. ${FZREPL_FILE:+--history=$FZREPL_FILE} \
  78. --preview="$cmd < '$tmpfile'"
  79. )
  80. q="${REPLY[0]}"
  81. q=${q@Q}
  82. echo "${cmd//'{q}'/$q}"