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.

fv 2.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. #!/usr/bin/env bash
  2. declare -r esc=$'\033'
  3. declare -r c_reset="${esc}[0m"
  4. declare -r c_red="${esc}[31m"
  5. err() {
  6. printf "${c_red}%s${c_reset}\n" "$*" >&2
  7. }
  8. die() {
  9. [[ -n "$1" ]] && err "$1"
  10. exit 1
  11. }
  12. has() {
  13. local verbose=0
  14. if [[ $1 == '-v' ]]; then
  15. verbose=1
  16. shift
  17. fi
  18. for c; do c="${c%% *}"
  19. if ! command -v "$c" &> /dev/null; then
  20. (( verbose > 0 )) && err "$c not found"
  21. return 1
  22. fi
  23. done
  24. }
  25. usage() {
  26. more <<'HELP'
  27. fv [OPTIONS] [SEARCH]
  28. fuzzy file filtering and command executing
  29. -c command to execute [defaults to vim]
  30. -a search all dirs and hidden files (still quirky)
  31. -d detach from terminal via nohup
  32. HELP
  33. }
  34. set_cmd() {
  35. if has "$1"; then
  36. cmd="$1"
  37. else
  38. die "$1 is not a valid command"
  39. fi
  40. }
  41. declare cmd='vim'
  42. declare cmdopts=()
  43. declare search_str=''
  44. declare search_cmd=''
  45. declare search_opts=()
  46. declare allfiles=0
  47. while getopts "hadlc:" opt; do
  48. case "$opt" in
  49. h) usage; exit 0 ;;
  50. a) allfiles=1 ;;
  51. c) set_cmd "$OPTARG" ;;
  52. d) unset detach ;;
  53. l) search_opts+=( '-l' ) ;;
  54. esac
  55. done
  56. shift "$((OPTIND-1))"
  57. has -v 'fzf' || die
  58. for c in 'ag' 'ack' 'grep'; do
  59. if has "$c"; then
  60. search_cmd="$c"
  61. break
  62. fi
  63. done
  64. if [[ "$search_cmd" == 'grep' ]]; then
  65. err 'grep is slow, you should strongly consider installing ag or ack'
  66. sleep .5
  67. fi
  68. if [[ -n "$1" ]]; then
  69. if [[ -d "$1" ]]; then
  70. search_opts+=( "$1" )
  71. else
  72. search_str="$1"
  73. fi
  74. shift
  75. fi
  76. case "$search_cmd" in
  77. 'ag')
  78. search_opts+=( '--color' )
  79. if [[ "$allfiles" == 1 ]]; then
  80. search_opts+=( '-u' '--hidden' )
  81. fi
  82. if [[ "$search_str" == '' ]]; then
  83. search_opts+=( '-l' )
  84. fi
  85. ;;
  86. 'ack')
  87. if [[ "$search_str" == '' ]]; then
  88. if [[ "$allfiles" == 0 ]]; then
  89. search_opts+=( '-g' '^[^\.]' )
  90. else
  91. search_opts+=( '-f' )
  92. fi
  93. else
  94. search_opts+=( '-l' )
  95. # search_opts+=( '--match' )
  96. fi
  97. ;;
  98. 'grep')
  99. search_opts+=( '-r' '-I' )
  100. if [[ "$allfiles" == 0 ]]; then
  101. search_opts+=( '--exclude-dir=bower_components' )
  102. search_opts+=( '--exclude-dir=node_modules' )
  103. search_opts+=( '--exclude-dir=jspm_packages' )
  104. search_opts+=( '--exclude-dir=.cvs' )
  105. search_opts+=( '--exclude-dir=.git' )
  106. search_opts+=( '--exclude-dir=.hg' )
  107. search_opts+=( '--exclude-dir=.svn' )
  108. fi
  109. if [[ "$search_str" == '' ]]; then
  110. search_opts+=( '' )
  111. fi
  112. ;;
  113. esac
  114. if [[ "$search_str" != '' ]]; then
  115. search_opts+=( "$search_str" )
  116. fi
  117. choices=$($search_cmd "${search_opts[@]}" 2> /dev/null |
  118. fzf --ansi --cycle --multi) || exit 1
  119. if [[ "$search_str" != '' ]]; then
  120. if [[ $search_cmd == 'ag' ]]; then
  121. choices=$(cut -d: -f1 <<< "$choices")
  122. fi
  123. fi
  124. mapfile -t choices <<< "$choices"
  125. $cmd ${cmdopts[*]} "${choices[@]}"