relaunch 0.0.1 → 0.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/bin/rerun ADDED
@@ -0,0 +1,22 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+ libdir = "#{File.expand_path(File.dirname(File.dirname(__FILE__)))}/lib"
5
+ $LOAD_PATH.unshift libdir unless $LOAD_PATH.include?(libdir)
6
+
7
+ require 'rerun'
8
+ require 'optparse'
9
+
10
+ options = Rerun::Options.parse config_file: ".rerun"
11
+
12
+ if options and options[:verbose]
13
+ puts "\nrerun options:\n\t#{options}"
14
+ end
15
+
16
+ exit if options.nil? or options[:cmd].nil? or options[:cmd].empty?
17
+
18
+ begin
19
+ Rerun::Runner.keep_running(options[:cmd], options)
20
+ rescue Rerun::ExitException
21
+ exit 0
22
+ end
data/bin/rerun.bat ADDED
@@ -0,0 +1,3 @@
1
+ :: %~dp0 means "the directory of the current script file"
2
+ :: see https://stackoverflow.com/questions/17063947/get-current-batchfile-directory
3
+ ruby %~dp0\rerun %*
Binary file
Binary file
data/lib/relaunch.rb CHANGED
@@ -1 +1 @@
1
- puts "Coming soon."
1
+ require 'rerun'
data/lib/rerun/glob.rb ADDED
@@ -0,0 +1,85 @@
1
+ # based on http://cpan.uwinnipeg.ca/htdocs/Text-Glob/Text/Glob.pm.html#glob_to_regex_string-
2
+
3
+ # todo: release as separate gem
4
+ #
5
+ module Rerun
6
+ class Glob
7
+ NO_LEADING_DOT = '(?=[^\.])' # todo
8
+ START_OF_FILENAME = '(\A|\/)' # beginning of string or a slash
9
+ END_OF_STRING = '\z'
10
+
11
+ def initialize glob_string
12
+ @glob_string = glob_string
13
+ end
14
+
15
+ def to_regexp_string
16
+ chars = @glob_string.split('')
17
+
18
+ chars = smoosh(chars)
19
+
20
+ curlies = 0
21
+ escaping = false
22
+ string = chars.map do |char|
23
+ if escaping
24
+ escaping = false
25
+ char
26
+ else
27
+ case char
28
+ when '**'
29
+ "([^/]+/)*"
30
+ when '*'
31
+ ".*"
32
+ when "?"
33
+ "."
34
+ when "."
35
+ "\\."
36
+
37
+ when "{"
38
+ curlies += 1
39
+ "("
40
+ when "}"
41
+ if curlies > 0
42
+ curlies -= 1
43
+ ")"
44
+ else
45
+ char
46
+ end
47
+ when ","
48
+ if curlies > 0
49
+ "|"
50
+ else
51
+ char
52
+ end
53
+ when "\\"
54
+ escaping = true
55
+ "\\"
56
+
57
+ else
58
+ char
59
+
60
+ end
61
+ end
62
+ end.join
63
+ START_OF_FILENAME + string + END_OF_STRING
64
+ end
65
+
66
+ def to_regexp
67
+ Regexp.new(to_regexp_string)
68
+ end
69
+
70
+ def smoosh chars
71
+ out = []
72
+ until chars.empty?
73
+ char = chars.shift
74
+ if char == "*" and chars.first == "*"
75
+ chars.shift
76
+ chars.shift if chars.first == "/"
77
+ out.push("**")
78
+ else
79
+ out.push(char)
80
+ end
81
+ end
82
+ out
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,83 @@
1
+ # todo: unit tests
2
+
3
+ module Rerun
4
+ class Notification
5
+ include System
6
+
7
+ attr_reader :title, :body, :options
8
+
9
+ def initialize(title, body, options = Options::DEFAULTS.dup)
10
+ @title = title
11
+ @body = body
12
+ @options = options
13
+ end
14
+
15
+ def command
16
+ # todo: strategy or subclass
17
+
18
+ s = nil
19
+
20
+ if options[:notify] == true or options[:notify] == "growl"
21
+ if (cmd = command_named("growlnotify"))
22
+ # todo: check version of growlnotify and warn if it's too old
23
+ icon_str = ("--image \"#{icon}\"" if icon)
24
+ s = "#{cmd} -n \"#{app_name}\" -m \"#{body}\" \"#{app_name} #{title}\" #{icon_str}"
25
+ end
26
+ end
27
+
28
+ if s.nil? and options[:notify] == true or options[:notify] == "osx"
29
+ if (cmd = command_named("terminal-notifier"))
30
+ icon_str = ("-appIcon \"#{icon}\"" if icon)
31
+ s = "#{cmd} -title \"#{app_name}\" -message \"#{body}\" \"#{app_name} #{title}\" #{icon_str}"
32
+ end
33
+ end
34
+
35
+ if s.nil? and options[:notify] == true or options[:notify] == "notify-send"
36
+ if (cmd = command_named('notify-send'))
37
+ icon_str = "--icon #{icon}" if icon
38
+ s = "#{cmd} -t 500 --hint=int:transient:1 #{icon_str} \"#{app_name}: #{title}\" \"#{body}\""
39
+ end
40
+ end
41
+
42
+ s
43
+ end
44
+
45
+ def command_named(name)
46
+ which_command = windows? ? 'where.exe %{cmd}' : 'which %{cmd} 2> /dev/null'
47
+ # TODO: remove 'INFO' error message
48
+ path = `#{which_command % {cmd: name}}`.chomp
49
+ path.empty? ? nil : path
50
+ end
51
+
52
+ def send(background = true)
53
+ return unless command
54
+ with_clean_env do
55
+ `#{command}#{" &" if background}`
56
+ end
57
+ end
58
+
59
+ def app_name
60
+ options[:name]
61
+ end
62
+
63
+ def icon
64
+ "#{icon_dir}/rails_red_sml.png" if rails?
65
+ end
66
+
67
+ def icon_dir
68
+ here = File.expand_path(File.dirname(__FILE__))
69
+ File.expand_path("#{here}/../../icons")
70
+ end
71
+
72
+ def with_clean_env
73
+ return yield unless defined?(Bundler)
74
+
75
+ if Bundler.respond_to?(:with_unbundled_env)
76
+ Bundler.with_unbundled_env { yield }
77
+ else
78
+ # Deprecated on Bundler 2.1
79
+ Bundler.with_clean_env { yield }
80
+ end
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,148 @@
1
+ require 'optparse'
2
+ require 'pathname'
3
+ require 'rerun/watcher'
4
+ require 'rerun/system'
5
+
6
+ libdir = "#{File.expand_path(File.dirname(File.dirname(__FILE__)))}"
7
+
8
+ $spec = Gem::Specification.load(File.join(libdir, "..", "relaunch.gemspec"))
9
+
10
+ module Rerun
11
+ class Options
12
+
13
+ extend Rerun::System
14
+
15
+ # If you change the default pattern, please update the README.md file -- the list appears twice therein, which at the time of this comment are lines 17 and 119
16
+ DEFAULT_PATTERN = "**/*.{rb,js,coffee,css,scss,sass,erb,html,haml,ru,yml,slim,md,feature,c,h}"
17
+ DEFAULT_DIRS = ["."]
18
+
19
+ DEFAULTS = {
20
+ :background => false,
21
+ :dir => DEFAULT_DIRS,
22
+ :force_polling => false,
23
+ :ignore => [],
24
+ :ignore_dotfiles => true,
25
+ :name => Pathname.getwd.basename.to_s.capitalize,
26
+ :notify => true,
27
+ :pattern => DEFAULT_PATTERN,
28
+ :quiet => false,
29
+ :signal => (windows? ? "TERM,KILL" : "TERM,INT,KILL"),
30
+ :verbose => false,
31
+ :wait => 2,
32
+ }
33
+
34
+ def self.parse args: ARGV, config_file: nil
35
+
36
+ default_options = DEFAULTS.dup
37
+ options = {
38
+ ignore: []
39
+ }
40
+
41
+ if config_file && File.exist?(config_file)
42
+ require 'shellwords'
43
+ config_args = File.read(config_file).shellsplit
44
+ args = config_args + args
45
+ end
46
+
47
+ option_parser = OptionParser.new("", 24, ' ') do |o|
48
+ o.banner = "Usage: rerun [options] [--] cmd"
49
+
50
+ o.separator ""
51
+ o.separator "Launches an app, and restarts it when the filesystem changes."
52
+ o.separator "See http://github.com/alexch/rerun for more info."
53
+ o.separator "Version: #{$spec.version}"
54
+ o.separator ""
55
+ o.separator "Options:"
56
+
57
+ o.on("-d dir", "--dir dir", "directory to watch, default = \"#{DEFAULT_DIRS}\". Specify multiple paths with ',' or separate '-d dir' option pairs.") do |dir|
58
+ elements = dir.split(",")
59
+ options[:dir] = (options[:dir] || []) + elements
60
+ end
61
+
62
+ # todo: rename to "--watch"
63
+ o.on("-p pattern", "--pattern pattern", "file glob to watch, default = \"#{DEFAULTS[:pattern]}\"") do |pattern|
64
+ options[:pattern] = pattern
65
+ end
66
+
67
+ o.on("-i pattern", "--ignore pattern", "file glob(s) to ignore. Can be set many times. To ignore a directory, you must append '/*' e.g. --ignore 'coverage/*' . Globs do not match dotfiles by default.") do |pattern|
68
+ options[:ignore] += [pattern]
69
+ end
70
+
71
+ o.on("--[no-]ignore-dotfiles", "by default, file globs do not match files that begin with a dot. Setting --no-ignore-dotfiles allows you to monitor a relevant file like .env, but you may also have to explicitly --ignore more dotfiles and dotdirs.") do |value|
72
+ options[:ignore_dotfiles] = value
73
+ end
74
+
75
+ o.on("-s signal", "--signal signal", "terminate process using this signal. To try several signals in series, use a comma-delimited list. Default: \"#{DEFAULTS[:signal]}\"") do |signal|
76
+ options[:signal] = signal
77
+ end
78
+
79
+ o.on("-w sec", "--wait sec", "after asking the process to terminate, wait this long (in seconds) before either aborting, or trying the next signal in series. Default: #{DEFAULTS[:wait]} sec") do |value|
80
+ default_options[:wait] = value
81
+ end
82
+
83
+ o.on("-r", "--restart", "expect process to restart itself, so just send a signal and continue watching. Sends the HUP signal unless overridden using --signal") do |signal|
84
+ options[:restart] = true
85
+ default_options[:signal] = "HUP"
86
+ end
87
+
88
+ o.on("-x", "--exit", "expect the program to exit. With this option, rerun checks the return value; without it, rerun checks that the process is running.") do |value|
89
+ options[:exit] = value
90
+ end
91
+
92
+ o.on("-c", "--clear", "clear screen before each run") do |value|
93
+ options[:clear] = value
94
+ end
95
+
96
+ o.on("-b", "--background", "disable on-the-fly keypress commands, allowing the process to be backgrounded") do |value|
97
+ options[:background] = value
98
+ end
99
+
100
+ o.on("-n name", "--name name", "name of app used in logs and notifications, default = \"#{DEFAULTS[:name]}\"") do |name|
101
+ options[:name] = name
102
+ end
103
+
104
+ o.on("--[no-]force-polling", "use polling instead of a native filesystem scan (useful for Vagrant)") do |value|
105
+ options[:force_polling] = value
106
+ end
107
+
108
+ o.on("--no-growl", "don't use growl [OBSOLETE]") do
109
+ options[:growl] = false
110
+ $stderr.puts "--no-growl is obsolete; use --no-notify instead"
111
+ return
112
+ end
113
+
114
+ o.on("--[no-]notify [notifier]", "send messages through a desktop notification application. Supports growl (requires growlnotify), osx (requires terminal-notifier gem), and notify-send on GNU/Linux (notify-send must be installed)") do |notifier|
115
+ notifier = true if notifier.nil?
116
+ options[:notify] = notifier
117
+ end
118
+
119
+ o.on("-q", "--[no-]quiet", "don't output any logs") do |value|
120
+ options[:quiet] = value
121
+ end
122
+
123
+ o.on("--[no-]verbose", "log extra stuff like PIDs (unless you also specified `--quiet`") do |value|
124
+ options[:verbose] = value
125
+ end
126
+
127
+ o.on_tail("-h", "--help", "--usage", "show this message and immediately exit") do
128
+ puts o
129
+ return
130
+ end
131
+
132
+ o.on_tail("--version", "show version and immediately exit") do
133
+ puts $spec.version
134
+ return
135
+ end
136
+
137
+ end
138
+
139
+ puts option_parser if args.empty?
140
+ option_parser.parse! args
141
+ options = default_options.merge(options)
142
+ options[:cmd] = args.join(" ").strip # todo: better arg word handling
143
+
144
+ options
145
+ end
146
+ end
147
+
148
+ end