prremote 0.1.4 → 0.1.6
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.
- checksums.yaml +4 -4
- data/README.md +18 -10
- data/VERSION +1 -1
- data/lib/prremote/cli.rb +24 -10
- data/lib/prremote/commands/deploy.rb +22 -18
- data/lib/prremote/commands/ls.rb +61 -0
- data/lib/prremote/commands/run.rb +16 -13
- data/lib/prremote/commands/serial_helpers.rb +27 -0
- data/lib/prremote/commands/watch.rb +13 -12
- metadata +3 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 45e633df22e18c19d4c78f58c93580d3f8bfee065806067415004220b50957d2
|
|
4
|
+
data.tar.gz: 291cfe851b01f38dad3d6bb10a827713d247b5ff0b8942043cbb2d2a57f40038
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 1f1af87f2ae1c9b72ad86dbf14d7a8cc05a94078c9913cafa294bea45c71844baf3bfad804cbb3a9c5cc3bf726866695b8d4685eb658906e35ebaba9181e46e0
|
|
7
|
+
data.tar.gz: 4cf41d9ea379ba497d70c648100c907c7a51cdd452034a7fead5ba0a2d3021e60d5817f9fcaaa84b7254cd49cf7b4634a030af56f9228a9312b54c9284f33822
|
data/README.md
CHANGED
|
@@ -69,27 +69,34 @@ Put the device into BOOTSEL mode (hold BOOTSEL, connect USB, release) when promp
|
|
|
69
69
|
|
|
70
70
|
---
|
|
71
71
|
|
|
72
|
-
### `run FILE`
|
|
72
|
+
### `run FILE [FILE ...]`
|
|
73
73
|
|
|
74
|
-
Compile
|
|
74
|
+
Compile one or more local `.rb` files to mruby bytecode and run them on the device immediately (one-shot).
|
|
75
75
|
|
|
76
76
|
```bash
|
|
77
77
|
prremote run app.rb
|
|
78
78
|
prremote run blink.rb --port /dev/tty.usbmodem101
|
|
79
79
|
```
|
|
80
80
|
|
|
81
|
+
Multiple files are compiled in order into a single `.mrb`. Classes and methods defined in earlier files are available to later ones — this is the recommended alternative to `require`, which is not available in mruby/c.
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
prremote run lib.rb main.rb
|
|
85
|
+
```
|
|
86
|
+
|
|
81
87
|
The device responds with `RUNNING`, streams any output, then `DONE`.
|
|
82
88
|
|
|
83
89
|
You can find some examples in [test/samples](test/samples/).
|
|
84
90
|
|
|
85
91
|
---
|
|
86
92
|
|
|
87
|
-
### `deploy FILE`
|
|
93
|
+
### `deploy FILE [FILE ...]`
|
|
88
94
|
|
|
89
|
-
Compile
|
|
95
|
+
Compile one or more local `.rb` files and save them to the device's flash. The script runs automatically on every boot.
|
|
90
96
|
|
|
91
97
|
```bash
|
|
92
98
|
prremote deploy app.rb
|
|
99
|
+
prremote deploy lib.rb main.rb
|
|
93
100
|
```
|
|
94
101
|
|
|
95
102
|
The device responds with `DEPLOYED` when the write is complete.
|
|
@@ -127,15 +134,16 @@ prremote reset
|
|
|
127
134
|
|
|
128
135
|
---
|
|
129
136
|
|
|
130
|
-
### `watch FILE`
|
|
137
|
+
### `watch FILE [FILE ...]`
|
|
131
138
|
|
|
132
|
-
Watch
|
|
139
|
+
Watch one or more local files for changes and automatically re-run them on the device on every save.
|
|
133
140
|
|
|
134
141
|
```bash
|
|
135
142
|
prremote watch app.rb
|
|
143
|
+
prremote watch lib.rb main.rb
|
|
136
144
|
```
|
|
137
145
|
|
|
138
|
-
Useful during development — save
|
|
146
|
+
Useful during development — save any watched file and the device immediately runs the updated code.
|
|
139
147
|
|
|
140
148
|
---
|
|
141
149
|
|
|
@@ -155,9 +163,9 @@ Show the gem version, mrbc version, and the connected device's runtime version.
|
|
|
155
163
|
|
|
156
164
|
```bash
|
|
157
165
|
prremote version
|
|
158
|
-
# prremote: 0.1.
|
|
159
|
-
#
|
|
160
|
-
#
|
|
166
|
+
# prremote: 0.1.6
|
|
167
|
+
# runtime: 0.1.6 (/dev/tty.usbmodem101)
|
|
168
|
+
# mrbc: mruby 4.0.0 (2026-04-20) (/opt/homebrew/bin/mrbc)
|
|
161
169
|
```
|
|
162
170
|
|
|
163
171
|
---
|
data/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
0.1.
|
|
1
|
+
0.1.6
|
data/lib/prremote/cli.rb
CHANGED
|
@@ -7,6 +7,7 @@ require_relative 'runtime_manager'
|
|
|
7
7
|
require_relative 'commands/install'
|
|
8
8
|
require_relative 'commands/deploy'
|
|
9
9
|
require_relative 'commands/undeploy'
|
|
10
|
+
require_relative 'commands/ls'
|
|
10
11
|
require_relative 'commands/run'
|
|
11
12
|
require_relative 'commands/eval_cmd'
|
|
12
13
|
require_relative 'commands/watch'
|
|
@@ -37,19 +38,31 @@ module Prremote
|
|
|
37
38
|
raise Thor::Error, e.message
|
|
38
39
|
end
|
|
39
40
|
|
|
40
|
-
desc 'run FILE', 'Compile and run
|
|
41
|
-
def run_script(
|
|
41
|
+
desc 'run FILE [FILE ...]', 'Compile and run Ruby scripts on the device (one-shot)'
|
|
42
|
+
def run_script(*files)
|
|
43
|
+
raise Thor::Error, 'At least one file is required.' if files.empty?
|
|
44
|
+
|
|
42
45
|
port = resolve_port
|
|
43
|
-
Commands::Run.new(port: port, baud: options[:baud]).call(
|
|
46
|
+
Commands::Run.new(port: port, baud: options[:baud]).call(*files)
|
|
44
47
|
rescue StandardError => e
|
|
45
48
|
raise Thor::Error, e.message
|
|
46
49
|
end
|
|
47
50
|
map 'run' => :run_script
|
|
48
51
|
|
|
49
|
-
desc 'deploy FILE', 'Compile and save
|
|
50
|
-
def deploy(
|
|
52
|
+
desc 'deploy FILE [FILE ...]', 'Compile and save Ruby scripts to flash (auto-runs on boot)'
|
|
53
|
+
def deploy(*files)
|
|
54
|
+
raise Thor::Error, 'At least one file is required.' if files.empty?
|
|
55
|
+
|
|
51
56
|
port = resolve_port
|
|
52
|
-
Commands::Deploy.new(port: port, baud: options[:baud]).call(
|
|
57
|
+
Commands::Deploy.new(port: port, baud: options[:baud]).call(*files)
|
|
58
|
+
rescue StandardError => e
|
|
59
|
+
raise Thor::Error, e.message
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
desc 'ls', 'Show the script deployed to flash (use `reset` first if a script is running)'
|
|
63
|
+
def ls
|
|
64
|
+
port = resolve_port
|
|
65
|
+
Commands::Ls.new(port: port, baud: options[:baud]).call
|
|
53
66
|
rescue StandardError => e
|
|
54
67
|
raise Thor::Error, e.message
|
|
55
68
|
end
|
|
@@ -70,10 +83,12 @@ module Prremote
|
|
|
70
83
|
raise Thor::Error, e.message
|
|
71
84
|
end
|
|
72
85
|
|
|
73
|
-
desc 'watch FILE', 'Watch
|
|
74
|
-
def watch(
|
|
86
|
+
desc 'watch FILE [FILE ...]', 'Watch Ruby files for changes and re-run on the device automatically'
|
|
87
|
+
def watch(*files)
|
|
88
|
+
raise Thor::Error, 'At least one file is required.' if files.empty?
|
|
89
|
+
|
|
75
90
|
port = resolve_port
|
|
76
|
-
Commands::Watch.new(port: port, baud: options[:baud]).call(
|
|
91
|
+
Commands::Watch.new(port: port, baud: options[:baud]).call(*files)
|
|
77
92
|
rescue StandardError => e
|
|
78
93
|
raise Thor::Error, e.message
|
|
79
94
|
end
|
|
@@ -116,7 +131,6 @@ module Prremote
|
|
|
116
131
|
rescue StandardError => e
|
|
117
132
|
puts "mrbc: (#{e.message})"
|
|
118
133
|
end
|
|
119
|
-
|
|
120
134
|
end
|
|
121
135
|
|
|
122
136
|
private
|
|
@@ -1,34 +1,38 @@
|
|
|
1
1
|
require 'open3'
|
|
2
2
|
require 'tempfile'
|
|
3
3
|
require_relative '../mrbc'
|
|
4
|
+
require_relative 'serial_helpers'
|
|
4
5
|
|
|
5
6
|
module Prremote
|
|
6
7
|
module Commands
|
|
7
8
|
class Deploy
|
|
9
|
+
include SerialHelpers
|
|
10
|
+
|
|
8
11
|
DEPLOY_MAGIC = 'DPLY'.freeze
|
|
12
|
+
META_MAGIC = 'META'.freeze
|
|
9
13
|
|
|
10
14
|
def initialize(port:, baud:)
|
|
11
15
|
@port = port
|
|
12
16
|
@baud = baud
|
|
13
17
|
end
|
|
14
18
|
|
|
15
|
-
def call(
|
|
16
|
-
raise "File not found: #{
|
|
19
|
+
def call(*rb_paths)
|
|
20
|
+
rb_paths.each { |f| raise "File not found: #{f}" unless File.exist?(f) }
|
|
17
21
|
|
|
18
|
-
warn "Compiling #{
|
|
19
|
-
mrb_data = compile(
|
|
22
|
+
warn "Compiling #{rb_paths.map { |f| File.basename(f) }.join(', ')}..."
|
|
23
|
+
mrb_data = compile(*rb_paths)
|
|
20
24
|
|
|
21
25
|
warn 'Deploying to flash...'
|
|
22
|
-
deploy_to_device(mrb_data)
|
|
26
|
+
deploy_to_device(mrb_data, rb_paths)
|
|
23
27
|
warn 'Deployed. Script will run automatically on next boot.'
|
|
24
28
|
end
|
|
25
29
|
|
|
26
30
|
private
|
|
27
31
|
|
|
28
|
-
def compile(
|
|
32
|
+
def compile(*rb_paths)
|
|
29
33
|
Mrbc.check_version!
|
|
30
34
|
tmp = Tempfile.new(['prremote', '.mrb'])
|
|
31
|
-
out, status = Open3.capture2e(Mrbc.bin, '-o', tmp.path,
|
|
35
|
+
out, status = Open3.capture2e(Mrbc.bin, '-o', tmp.path, *rb_paths)
|
|
32
36
|
raise "mrbc failed:\n#{out.chomp}" unless status.success?
|
|
33
37
|
|
|
34
38
|
File.binread(tmp.path)
|
|
@@ -36,19 +40,23 @@ module Prremote
|
|
|
36
40
|
tmp&.close!
|
|
37
41
|
end
|
|
38
42
|
|
|
39
|
-
def deploy_to_device(mrb_data)
|
|
43
|
+
def deploy_to_device(mrb_data, rb_paths)
|
|
40
44
|
serial = Serial.new(@port, @baud)
|
|
41
|
-
|
|
42
|
-
serial.
|
|
43
|
-
|
|
44
|
-
serial.write(DEPLOY_MAGIC + mrb_data)
|
|
45
|
-
debug "sent DPLY + #{mrb_data.bytesize} bytes"
|
|
46
|
-
|
|
45
|
+
wait_for_ready(serial)
|
|
46
|
+
serial.write(DEPLOY_MAGIC + build_meta_packet(rb_paths) + mrb_data)
|
|
47
47
|
wait_for_deployed(serial)
|
|
48
48
|
ensure
|
|
49
49
|
serial&.close
|
|
50
50
|
end
|
|
51
51
|
|
|
52
|
+
def build_meta_packet(rb_paths)
|
|
53
|
+
names_bytes = rb_paths.map { |f| File.basename(f) }.join(' ').encode('UTF-8').b
|
|
54
|
+
name_len = [names_bytes.bytesize, 240].min
|
|
55
|
+
ts = Time.now.to_i
|
|
56
|
+
debug "meta: #{name_len} bytes, ts=#{ts}"
|
|
57
|
+
META_MAGIC + [name_len].pack('C') + names_bytes[0, name_len] + [ts].pack('N')
|
|
58
|
+
end
|
|
59
|
+
|
|
52
60
|
def wait_for_deployed(serial)
|
|
53
61
|
buf = +''
|
|
54
62
|
deadline = Time.now + 30
|
|
@@ -64,10 +72,6 @@ module Prremote
|
|
|
64
72
|
end
|
|
65
73
|
end
|
|
66
74
|
|
|
67
|
-
def normalize(str)
|
|
68
|
-
str.gsub("\r\n", "\n").gsub("\r", '')
|
|
69
|
-
end
|
|
70
|
-
|
|
71
75
|
def debug(msg)
|
|
72
76
|
warn "[debug] #{msg}" if ENV['PRREMOTE_DEBUG']
|
|
73
77
|
end
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
require_relative 'serial_helpers'
|
|
2
|
+
|
|
3
|
+
module Prremote
|
|
4
|
+
module Commands
|
|
5
|
+
class Ls
|
|
6
|
+
include SerialHelpers
|
|
7
|
+
|
|
8
|
+
QUERY_MAGIC = 'QURY'.freeze
|
|
9
|
+
|
|
10
|
+
def initialize(port:, baud:)
|
|
11
|
+
@port = port
|
|
12
|
+
@baud = baud
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def call
|
|
16
|
+
result = query_device
|
|
17
|
+
if result
|
|
18
|
+
ts_str = if result[:timestamp].positive?
|
|
19
|
+
Time.at(result[:timestamp]).strftime('%Y-%m-%d %H:%M:%S')
|
|
20
|
+
else
|
|
21
|
+
'(unknown)'
|
|
22
|
+
end
|
|
23
|
+
puts 'Deployed script:'
|
|
24
|
+
puts " Files: #{result[:names]}"
|
|
25
|
+
puts " Deployed: #{ts_str}"
|
|
26
|
+
else
|
|
27
|
+
puts 'No script deployed.'
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
private
|
|
32
|
+
|
|
33
|
+
def query_device
|
|
34
|
+
serial = Serial.new(@port, @baud)
|
|
35
|
+
wait_for_ready(serial)
|
|
36
|
+
serial.write(QUERY_MAGIC)
|
|
37
|
+
|
|
38
|
+
buf = +''
|
|
39
|
+
deadline = Time.now + 5
|
|
40
|
+
loop do
|
|
41
|
+
chunk = normalize(serial.read(256) || '')
|
|
42
|
+
buf << chunk
|
|
43
|
+
|
|
44
|
+
if (m = buf.match(/^DEPLOYED (\d+) (.+)\n/))
|
|
45
|
+
return { timestamp: m[1].to_i, names: m[2].strip }
|
|
46
|
+
end
|
|
47
|
+
return nil if buf.include?("NONE\n")
|
|
48
|
+
|
|
49
|
+
if Time.now > deadline
|
|
50
|
+
raise 'Timeout waiting for device response. ' \
|
|
51
|
+
'If a script is running, use `prremote reset` first.'
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
sleep 0.05
|
|
55
|
+
end
|
|
56
|
+
ensure
|
|
57
|
+
serial&.close
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
@@ -1,31 +1,36 @@
|
|
|
1
1
|
require 'open3'
|
|
2
2
|
require 'tempfile'
|
|
3
3
|
require_relative '../mrbc'
|
|
4
|
+
require_relative 'serial_helpers'
|
|
4
5
|
|
|
5
6
|
module Prremote
|
|
6
7
|
module Commands
|
|
7
8
|
class Run
|
|
9
|
+
include SerialHelpers
|
|
10
|
+
|
|
8
11
|
def initialize(port:, baud:)
|
|
9
12
|
@port = port
|
|
10
13
|
@baud = baud
|
|
11
14
|
end
|
|
12
15
|
|
|
13
|
-
def call(
|
|
14
|
-
raise "File not found: #{
|
|
16
|
+
def call(*rb_paths)
|
|
17
|
+
rb_paths.each { |f| raise "File not found: #{f}" unless File.exist?(f) }
|
|
15
18
|
|
|
16
|
-
warn "Compiling #{
|
|
17
|
-
mrb_data = compile(
|
|
19
|
+
warn "Compiling #{rb_paths.map { |f| File.basename(f) }.join(', ')}..."
|
|
20
|
+
mrb_data = compile(*rb_paths)
|
|
18
21
|
|
|
19
22
|
warn 'Running...'
|
|
20
23
|
run_on_device(mrb_data)
|
|
24
|
+
rescue Interrupt
|
|
25
|
+
warn ''
|
|
21
26
|
end
|
|
22
27
|
|
|
23
28
|
private
|
|
24
29
|
|
|
25
|
-
def compile(
|
|
30
|
+
def compile(*rb_paths)
|
|
26
31
|
Mrbc.check_version!
|
|
27
32
|
tmp = Tempfile.new(['prremote', '.mrb'])
|
|
28
|
-
out, status = Open3.capture2e(Mrbc.bin, '-o', tmp.path,
|
|
33
|
+
out, status = Open3.capture2e(Mrbc.bin, '-o', tmp.path, *rb_paths)
|
|
29
34
|
raise "mrbc failed:\n#{out.chomp}" unless status.success?
|
|
30
35
|
|
|
31
36
|
File.binread(tmp.path)
|
|
@@ -35,15 +40,17 @@ module Prremote
|
|
|
35
40
|
|
|
36
41
|
def run_on_device(mrb_data)
|
|
37
42
|
serial = Serial.new(@port, @baud)
|
|
38
|
-
|
|
39
|
-
drained = serial.read(4096) || ''
|
|
40
|
-
debug "drained #{drained.bytesize} bytes: #{drained.inspect}"
|
|
43
|
+
wait_for_ready(serial)
|
|
41
44
|
|
|
42
45
|
serial.write(mrb_data)
|
|
43
46
|
debug "sent #{mrb_data.bytesize} bytes (first 4: #{mrb_data[0, 4].inspect})"
|
|
44
47
|
|
|
45
48
|
post_running = wait_for_running(serial)
|
|
46
49
|
stream_until_done(serial, post_running)
|
|
50
|
+
rescue Interrupt
|
|
51
|
+
serial&.write("\x03")
|
|
52
|
+
sleep 0.1
|
|
53
|
+
raise
|
|
47
54
|
ensure
|
|
48
55
|
serial&.close
|
|
49
56
|
end
|
|
@@ -91,10 +98,6 @@ module Prremote
|
|
|
91
98
|
end
|
|
92
99
|
end
|
|
93
100
|
|
|
94
|
-
def normalize(str)
|
|
95
|
-
str.gsub("\r\n", "\n").gsub("\r", '')
|
|
96
|
-
end
|
|
97
|
-
|
|
98
101
|
def debug(msg)
|
|
99
102
|
warn "[debug] #{msg}" if ENV['PRREMOTE_DEBUG']
|
|
100
103
|
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
module Prremote
|
|
2
|
+
module Commands
|
|
3
|
+
module SerialHelpers
|
|
4
|
+
def wait_for_ready(serial)
|
|
5
|
+
# On macOS, USB CDC TX buffers can be dropped when the host reopens the port,
|
|
6
|
+
# leaving the device stuck in getchar() without re-sending READY.
|
|
7
|
+
# Sending Ctrl+C forces the device to restart its READY loop.
|
|
8
|
+
sleep 0.1
|
|
9
|
+
serial.write("\x03") rescue nil
|
|
10
|
+
|
|
11
|
+
buf = +''
|
|
12
|
+
deadline = Time.now + 10
|
|
13
|
+
loop do
|
|
14
|
+
buf << normalize(serial.read(256) || '')
|
|
15
|
+
return if buf.include?('READY ')
|
|
16
|
+
raise 'Timeout waiting for device. Run `prremote reset` if a script is running.' if Time.now > deadline
|
|
17
|
+
|
|
18
|
+
sleep 0.05
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def normalize(str)
|
|
23
|
+
str.gsub("\r\n", "\n").gsub("\r", '')
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -10,21 +10,22 @@ module Prremote
|
|
|
10
10
|
@baud = baud
|
|
11
11
|
end
|
|
12
12
|
|
|
13
|
-
def call(
|
|
14
|
-
raise "File not found: #{
|
|
13
|
+
def call(*rb_paths)
|
|
14
|
+
rb_paths.each { |f| raise "File not found: #{f}" unless File.exist?(f) }
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
label = rb_paths.map { |f| File.basename(f) }.join(', ')
|
|
17
|
+
warn "Watching #{label} (Ctrl+C to stop)..."
|
|
18
|
+
mtimes = rb_paths.map { |f| File.mtime(f) }
|
|
19
|
+
run(*rb_paths)
|
|
19
20
|
|
|
20
21
|
loop do
|
|
21
22
|
sleep POLL_INTERVAL
|
|
22
|
-
|
|
23
|
-
next if
|
|
23
|
+
new_mtimes = rb_paths.map { |f| File.mtime(f) }
|
|
24
|
+
next if new_mtimes == mtimes
|
|
24
25
|
|
|
25
|
-
|
|
26
|
-
warn "\n--- #{
|
|
27
|
-
run(
|
|
26
|
+
mtimes = new_mtimes
|
|
27
|
+
warn "\n--- #{label} changed, re-running ---"
|
|
28
|
+
run(*rb_paths)
|
|
28
29
|
end
|
|
29
30
|
rescue Interrupt
|
|
30
31
|
warn "\nStopped watching."
|
|
@@ -32,8 +33,8 @@ module Prremote
|
|
|
32
33
|
|
|
33
34
|
private
|
|
34
35
|
|
|
35
|
-
def run(
|
|
36
|
-
Run.new(port: @port, baud: @baud).call(
|
|
36
|
+
def run(*rb_paths)
|
|
37
|
+
Run.new(port: @port, baud: @baud).call(*rb_paths)
|
|
37
38
|
rescue StandardError => e
|
|
38
39
|
warn "Error: #{e.message}"
|
|
39
40
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: prremote
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.6
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- ITO Yosei
|
|
@@ -110,7 +110,9 @@ files:
|
|
|
110
110
|
- lib/prremote/commands/deploy.rb
|
|
111
111
|
- lib/prremote/commands/eval_cmd.rb
|
|
112
112
|
- lib/prremote/commands/install.rb
|
|
113
|
+
- lib/prremote/commands/ls.rb
|
|
113
114
|
- lib/prremote/commands/run.rb
|
|
115
|
+
- lib/prremote/commands/serial_helpers.rb
|
|
114
116
|
- lib/prremote/commands/undeploy.rb
|
|
115
117
|
- lib/prremote/commands/watch.rb
|
|
116
118
|
- lib/prremote/detector.rb
|