Class: Guard::Listener Abstract

Inherits:
Object
  • Object
show all
Defined in:
lib/guard/listener.rb

Overview

This class is abstract.

The Listener is the base class for all listener implementations.

Direct Known Subclasses

Darwin, Linux, Polling, Windows

Constant Summary collapse

DEFAULT_IGNORE_PATHS =

Default paths that gets ignored by the listener

%w[. .. .bundle .git log tmp vendor]

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(directory = Dir.pwd, options = {}) ⇒ Listener

Initialize the listener.

Parameters:

  • directory (String) (defaults to: Dir.pwd)

    the root directory to listen to

  • options (Hash) (defaults to: {})

    a customizable set of options

Options Hash (options):

  • relativize_paths (Boolean)

    use only relative paths

  • ignore_paths (Array<String>)

    the paths to ignore by the listener



54
55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/guard/listener.rb', line 54

def initialize(directory = Dir.pwd, options = {})
  @directory                = directory.to_s
  @sha1_checksums_hash      = {}
  @file_timestamp_hash      = {}
  @relativize_paths         = options.fetch(:relativize_paths, true)
  @changed_files            = []
  @paused                   = false
  @ignore_paths             = DEFAULT_IGNORE_PATHS
  @ignore_paths            |= options[:ignore_paths] if options[:ignore_paths]
  @watch_all_modifications  = options.fetch(:watch_all_modifications, false)

  update_last_event
  start_reactor
end

Instance Attribute Details

#changed_filesObject

Returns the value of attribute changed_files.



21
22
23
# File 'lib/guard/listener.rb', line 21

def changed_files
  @changed_files
end

#directoryObject (readonly)

Returns the value of attribute directory.



22
23
24
# File 'lib/guard/listener.rb', line 22

def directory
  @directory
end

#ignore_pathsObject (readonly)

Returns the value of attribute ignore_paths.



22
23
24
# File 'lib/guard/listener.rb', line 22

def ignore_paths
  @ignore_paths
end

Class Method Details

.select_and_init(watchdir = Dir.pwd, options = nil) ⇒ Guard::Listener

Select the appropriate listener implementation for the current OS and initializes it.

Parameters:

  • args (Array)

    the arguments for the listener

Returns:



34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/guard/listener.rb', line 34

def self.select_and_init(watchdir = Dir.pwd, options = nil)
  no_vendor = options && options.key?(:no_vendor) ? options[:no_vendor] : false
  if mac? && Darwin.usable?(no_vendor)
    Darwin.new(watchdir, options)
  elsif linux? && Linux.usable?(no_vendor)
    Linux.new(watchdir, options)
  elsif windows? && Windows.usable?(no_vendor)
    Windows.new(watchdir, options)
  else
    UI.info 'Using polling (Please help us to support your system better than that).'
    Polling.new(watchdir, options)
  end
end

Instance Method Details

#all_filesArray<String>

Get all files that are in the watched directory.

Returns:

  • (Array<String>)

    the list of files



176
177
178
# File 'lib/guard/listener.rb', line 176

def all_files
  potentially_modified_files([@directory], :all => true)
end

#clear_changed_filesObject

Clear the list of changed files.



113
114
115
# File 'lib/guard/listener.rb', line 113

def clear_changed_files
  @changed_files.clear
end

#exclude_ignored_paths(dirs, ignore_paths = self.ignore_paths) ⇒ Object

Removes the ignored paths from the directory list.

Parameters:

  • dirs (Array<String>)

    the directory to listen to

  • ignore_paths (Array<String>) (defaults to: self.ignore_paths)

    the paths to ignore

Returns:

  • children of the passed dirs that are not in the ignore_paths list



212
213
214
215
216
# File 'lib/guard/listener.rb', line 212

def exclude_ignored_paths(dirs, ignore_paths = self.ignore_paths)
  Dir.glob(dirs.map { |d| "#{d.sub(%r{/+$}, '')}/*" }, File::FNM_DOTMATCH).reject do |path|
    ignore_paths.include?(File.basename(path))
  end
end

#modified_files(dirs, options = {}) ⇒ Array<String>

Get the modified files.

If the ‘:watch_all_modifications` option is true, then moved and deleted files are also reported, but prefixed by an exclamation point.

Examples:

Deleted or moved file

!/home/user/dir/file.rb

Parameters:

  • dirs (Array<String>)

    the watched directories

  • options (Hash) (defaults to: {})

    the listener options

Options Hash (options):

  • all (Symbol)

    whether to files in sub directories

Returns:

  • (Array<String>)

    paths of files that have been modified



144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
# File 'lib/guard/listener.rb', line 144

def modified_files(dirs, options = {})
  last_event = @last_event
  files = []
  if @watch_all_modifications
    deleted_files = @file_timestamp_hash.collect do |path, ts|
      unless File.exists?(path)
        @sha1_checksums_hash.delete(path)
        @file_timestamp_hash.delete(path)
        "!#{path}"
      end
    end
    files.concat(deleted_files.compact)
  end
  update_last_event
  files.concat(potentially_modified_files(dirs, options).select { |path| file_modified?(path, last_event) })

  relativize_paths(files)
end

#on_change(&callback) ⇒ Object

Store a listener callback.

Parameters:

  • callback (Block)

    the callback to store



121
122
123
# File 'lib/guard/listener.rb', line 121

def on_change(&callback)
  @callback = callback
end

#pauseObject

Pause the listener to ignore change events.



101
102
103
# File 'lib/guard/listener.rb', line 101

def pause
  @paused = true
end

#paused?Boolean

Returns:

  • (Boolean)


24
25
26
# File 'lib/guard/listener.rb', line 24

def paused?
  @paused
end

#relativize_paths(paths) ⇒ Array<String>

Scopes all given paths to the current directory.

Parameters:

  • paths (Array<String>)

    the paths to change

Returns:

  • (Array<String>)

    all paths now relative to the current dir



185
186
187
188
189
190
# File 'lib/guard/listener.rb', line 185

def relativize_paths(paths)
  return paths unless relativize_paths?
  paths.map do |path|
  path.gsub(%r{^(!)?#{ @directory }/},'\1')
  end
end

#relativize_paths?Boolean

Use paths relative to the current directory.

Returns:

  • (Boolean)

    whether to use relative or absolute paths



196
197
198
# File 'lib/guard/listener.rb', line 196

def relativize_paths?
  !!@relativize_paths
end

#runObject

Unpause the listener to listen again to change events.



107
108
109
# File 'lib/guard/listener.rb', line 107

def run
  @paused = false
end

#startObject

Start watching the root directory.



89
90
91
92
# File 'lib/guard/listener.rb', line 89

def start
  watch(@directory)
  timestamp_files
end

#start_reactorObject

Start the listener thread.



71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# File 'lib/guard/listener.rb', line 71

def start_reactor
  return if ENV["GUARD_ENV"] == 'test'

  Thread.new do
    loop do
      if @changed_files != [] && !@paused
        changed_files = @changed_files.dup
        clear_changed_files
        ::Guard.run_on_change(changed_files)
      else
        sleep 0.1
      end
    end
  end
end

#stopObject

Stop listening for events.



96
97
# File 'lib/guard/listener.rb', line 96

def stop
end

#timestamp_filesObject

Populate initial timestamp file hash to watch for deleted or moved files.



202
203
204
# File 'lib/guard/listener.rb', line 202

def timestamp_files
  all_files.each {|path| set_file_timestamp_hash(path, file_timestamp(path)) } if @watch_all_modifications
end

#update_last_eventObject

Updates the timestamp of the last event.



127
128
129
# File 'lib/guard/listener.rb', line 127

def update_last_event
  @last_event = Time.now
end

#watch(directory) ⇒ Object

Register a directory to watch. Must be implemented by the subclasses.

Parameters:

  • directory (String)

    the directory to watch

Raises:

  • (NotImplementedError)


168
169
170
# File 'lib/guard/listener.rb', line 168

def watch(directory)
  raise NotImplementedError, "do whatever you want here, given the directory as only argument"
end