find_file_scanner.rb 3.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. # Copyright 2014 Wincent Colaiuta. All rights reserved.
  2. #
  3. # Redistribution and use in source and binary forms, with or without
  4. # modification, are permitted provided that the following conditions are met:
  5. #
  6. # 1. Redistributions of source code must retain the above copyright notice,
  7. # this list of conditions and the following disclaimer.
  8. # 2. Redistributions in binary form must reproduce the above copyright notice,
  9. # this list of conditions and the following disclaimer in the documentation
  10. # and/or other materials provided with the distribution.
  11. #
  12. # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  13. # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  14. # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  15. # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
  16. # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  17. # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  18. # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  19. # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  20. # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  21. # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  22. # POSSIBILITY OF SUCH DAMAGE.
  23. require 'open3'
  24. require 'command-t/vim'
  25. require 'command-t/vim/path_utilities'
  26. require 'command-t/scanner/file_scanner'
  27. module CommandT
  28. class FileScanner
  29. # A FileScanner which shells out to the `find` executable in order to scan.
  30. class FindFileScanner < FileScanner
  31. include VIM::PathUtilities
  32. def paths
  33. super || begin
  34. set_wild_ignore(@wild_ignore)
  35. # temporarily set field separator to NUL byte; this setting is
  36. # respected by both `readlines` and `chomp!` below, and makes it easier
  37. # to parse the output of `find -print0`
  38. separator = $/
  39. $/ = "\x00"
  40. unless @scan_dot_directories
  41. dot_directory_filter = [
  42. '-not', '-path', "#{@path}/.*/*", # top-level dot dir
  43. '-and', '-not', '-path', "#{@path}/*/.*/*" # lower-level dot dir
  44. ]
  45. end
  46. Open3.popen3(*([
  47. 'find', '-L', # follow symlinks
  48. @path, # anchor search here
  49. '-maxdepth', @max_depth.to_s, # limit depth of DFS
  50. '-type', 'f', # only show regular files (not dirs etc)
  51. dot_directory_filter, # possibly skip out dot directories
  52. '-print0' # NUL-terminate results
  53. ].flatten.compact)) do |stdin, stdout, stderr|
  54. counter = 1
  55. paths = []
  56. stdout.readlines.each do |line|
  57. next if path_excluded?(line.chomp!)
  58. paths << line[@prefix_len + 1..-1]
  59. break if (counter += 1) > @max_files
  60. end
  61. @paths[@path] = paths
  62. end
  63. ensure
  64. $/ = separator
  65. set_wild_ignore(@base_wild_ignore)
  66. end
  67. @paths[@path]
  68. end
  69. end # class FindFileScanner
  70. end # class FileScanner
  71. end # module CommandT