trecs 0.1.11 → 0.1.12
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 +13 -5
- data/Gemfile.lock +3 -1
- data/bin/trecs +27 -47
- data/bin/trecs_record +23 -27
- data/lib/trecs/frame.rb +37 -0
- data/lib/trecs/player.rb +1 -1
- data/lib/trecs/readers/json_reader.rb +18 -11
- data/lib/trecs/recorder.rb +23 -15
- data/lib/trecs/recording_strategies/config_strategy.rb +31 -0
- data/lib/trecs/recording_strategies/file_frames_strategy.rb +30 -0
- data/lib/trecs/recording_strategies/hash_strategy.rb +4 -0
- data/lib/trecs/recording_strategies/ttyrec_strategy.rb +1 -37
- data/lib/trecs/sources/tgz_source.rb +106 -0
- data/lib/trecs/version.rb +1 -1
- data/lib/trecs/writers/json_writer.rb +28 -9
- data/spec/trecs/frame_spec.rb +68 -0
- data/spec/trecs/player_spec.rb +1 -1
- data/spec/trecs/readers/json_reader_spec.rb +1 -1
- data/spec/trecs/readers/yaml_store_reader_spec.rb +1 -1
- data/spec/trecs/recorder_spec.rb +48 -29
- data/spec/trecs/recording_strategies/config_strategy_spec.rb +129 -0
- data/spec/trecs/recording_strategies/file_frames_strategy_spec.rb +10 -0
- data/spec/trecs/recording_strategies/shell_command_strategy_spec.rb +1 -1
- data/spec/trecs/sources/tgz_source_spec.rb +8 -0
- data/spec/trecs/writers/json_writer_spec.rb +8 -0
- data/trecs.gemspec +1 -0
- metadata +48 -25
- data/old_specs/player_spec.rb +0 -198
- data/old_specs/recorders/zip_file_recorder_spec.rb +0 -64
- data/old_specs/timestamps_spec.rb +0 -44
- data/old_specs/trecs_message_spec.rb +0 -125
- data/old_specs/trecs_spec.rb +0 -115
checksums.yaml
CHANGED
@@ -1,7 +1,15 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
MGY1NWJjMWVhZmIyZjkzMjIwMmNmZjU0N2JlMmU5ZWYwODY3YjFhNw==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
MDMyNTg1YTYyOGIxYjRiYTVlOGM3ZWEzNzA0ZTQyYzlmZjZlZGNkNg==
|
5
7
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
YTMzNzQ4ZGFkZDYzNGI4MTRlNTdhYjhmNTFjOGZlZDhhNmU4NWUxNjVmN2Q5
|
10
|
+
NTc4ZmNiY2YwZTkzODM1NTBhMTZlYjMyOGE0MjQzZDYxM2FlMWIwMTAxNGM2
|
11
|
+
MzhjNDllNDhjYWNkYTk2YWE1MjNmMjA3OTFkMzI2Zjg2ZWIyYzM=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
MDdhYTMwODk1NWMwNzQ1MThkMDEzODQzZjlhMjdkM2U5NGYyYzQ2NDNjNTdk
|
14
|
+
YjJmYzZiNmZmZjkzYmRkNjlkZmEyYjA2NGQ5MTRjMGMxY2FkYmNkNDdmZDg5
|
15
|
+
YWQ4YzdkNGM2OGVhZTg2Y2JjZTFjYWZiNDBhYmRiOWQzM2JlOWM=
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
trecs (0.1.
|
4
|
+
trecs (0.1.12)
|
5
|
+
minitar (~> 0.5.4)
|
5
6
|
trollop (~> 2.0)
|
6
7
|
|
7
8
|
GEM
|
@@ -10,6 +11,7 @@ GEM
|
|
10
11
|
diff-lcs (1.2.5)
|
11
12
|
given_core (3.5.4)
|
12
13
|
sorcerer (>= 0.3.7)
|
14
|
+
minitar (0.5.4)
|
13
15
|
rake (10.3.2)
|
14
16
|
rspec (2.99.0)
|
15
17
|
rspec-core (~> 2.99.0)
|
data/bin/trecs
CHANGED
@@ -3,75 +3,55 @@
|
|
3
3
|
$:.unshift(File.expand_path("../../lib", __FILE__))
|
4
4
|
require "trecs"
|
5
5
|
require "player"
|
6
|
+
require "sources/tgz_source"
|
7
|
+
|
6
8
|
require "trollop"
|
7
9
|
|
10
|
+
def finish(opts)
|
11
|
+
puts "Finished"
|
12
|
+
puts "Replay with:"
|
13
|
+
puts "trecs #{opts[:trecs_file]}"
|
14
|
+
end
|
15
|
+
|
16
|
+
trap "SIGINT" do
|
17
|
+
finish(opts)
|
18
|
+
exit rescue nil
|
19
|
+
end
|
8
20
|
|
9
21
|
opts = Trollop::options do
|
10
22
|
version TRecs::VERSION
|
11
23
|
|
12
|
-
opt :step,
|
13
|
-
opt :
|
14
|
-
opt :ticker, "Ticker", type: String, default: "clock"
|
24
|
+
opt :step, "Time in ms between frames", short: 's', default: 100
|
25
|
+
opt :ticker, "Ticker", type: String, default: "clock"
|
15
26
|
|
16
|
-
opt :from,
|
17
|
-
opt :to,
|
18
|
-
opt :speed,
|
27
|
+
opt :from, "Play from", type: Integer, default: 0
|
28
|
+
opt :to, "Play to", type: Integer, default: 0
|
29
|
+
opt :speed, "Playing speed", type: Float, default: 1.0
|
19
30
|
|
20
|
-
opt :ticker_file, "File to watch",
|
21
|
-
|
22
|
-
opt :audio, "Play with audio", type: String
|
31
|
+
opt :ticker_file, "File to watch", type: String, default: "/tmp/ticker"
|
23
32
|
end
|
24
33
|
opts[:trecs_file] = ARGV[0]
|
25
34
|
|
26
|
-
|
27
|
-
|
28
|
-
reader_class = Kernel.const_get([
|
29
|
-
"TRecs::",
|
30
|
-
opts[:format].split(/[-_\s]/).map(&:capitalize),
|
31
|
-
"Reader"
|
32
|
-
].join
|
33
|
-
)
|
34
|
-
|
35
|
+
source = TRecs::TgzSource.new(trecs_file: opts.fetch(:trecs_file))
|
36
|
+
reader = source.reader(opts)
|
35
37
|
|
36
|
-
|
37
|
-
ticker_file = "tickers/#{opts[:ticker]}#{ticker_separator}ticker"
|
38
|
+
ticker_file = "tickers/#{opts[:ticker]}_ticker"
|
38
39
|
require ticker_file
|
39
|
-
|
40
|
+
ticker_class_name = [
|
40
41
|
"TRecs::",
|
41
42
|
opts[:ticker].split(/[-_\s]/).map(&:capitalize),
|
42
43
|
"Ticker"
|
43
44
|
].join
|
44
|
-
|
45
|
-
|
46
|
-
########## AUDIO ##########
|
47
|
-
def start_sound_player(file_name='sound.ogg')
|
48
|
-
return unless File.exist?(file_name)
|
49
|
-
# at_exit { system('stty echo') }
|
50
|
-
STDOUT.puts "=> Starting sound player..."
|
51
|
-
@sox_pid = fork do
|
52
|
-
`play #{file_name} 2>&1`
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
def stop_sound_player
|
57
|
-
return unless File.exist?(file_name)
|
58
|
-
STDOUT.puts "=> Stopping sound player..."
|
59
|
-
Process.waitpid(@sox_pid)
|
60
|
-
end
|
61
|
-
######## END AUDIO ########
|
62
|
-
|
45
|
+
ticker_class = ticker_class_name.split("::").reduce(Object) { |a, e| a.const_get e }
|
46
|
+
ticker = ticker_class.new(opts)
|
63
47
|
|
64
48
|
player_options = {
|
65
|
-
reader:
|
66
|
-
ticker:
|
49
|
+
reader: reader,
|
50
|
+
ticker: ticker,
|
67
51
|
step: opts[:step],
|
68
52
|
}
|
69
53
|
|
70
54
|
player = TRecs::Player.new(player_options)
|
71
|
-
|
72
|
-
opts[:audio] && start_sound_player(opts[:audio])
|
73
55
|
player.play
|
74
56
|
|
75
|
-
|
76
|
-
puts "Replay with:"
|
77
|
-
puts "trecs #{opts[:trecs_file]}"
|
57
|
+
finish(opts)
|
data/bin/trecs_record
CHANGED
@@ -9,40 +9,31 @@ require "trollop"
|
|
9
9
|
opts = Trollop::options do
|
10
10
|
version TRecs::VERSION
|
11
11
|
|
12
|
-
opt :step,
|
13
|
-
opt :
|
14
|
-
opt :strategy, "Strategy", type: String, default: "incremental"
|
12
|
+
opt :step, "Time in ms between frames", short: 's', default: 100
|
13
|
+
opt :strategy, "Strategy", type: String, default: "incremental"
|
15
14
|
|
16
|
-
opt :message,
|
17
|
-
opt :width,
|
18
|
-
opt :command,
|
19
|
-
opt :input_file, "File to record",
|
20
|
-
opt :terminal,
|
21
|
-
opt :color,
|
22
|
-
|
23
|
-
opt :audio, "Record audio", type: String
|
15
|
+
opt :message, "Message to record", type: String, default: "TRecs!"
|
16
|
+
opt :width, "Width", type: Integer, default: 10
|
17
|
+
opt :command, "Command" , short: "c", type: String
|
18
|
+
opt :input_file, "File to record", type: String, default: ""
|
19
|
+
opt :terminal, "Launch terminal", default: true
|
20
|
+
opt :color, "Record colors", default: true
|
24
21
|
|
22
|
+
opt :audio, "Record audio", type: String
|
25
23
|
end
|
26
24
|
opts[:trecs_file] = ARGV[0]
|
27
25
|
|
28
|
-
|
29
|
-
|
30
|
-
writer_class = Kernel.const_get([
|
31
|
-
"TRecs::",
|
32
|
-
opts[:format].split(/[-_\s]/).map(&:capitalize),
|
33
|
-
"Writer"
|
34
|
-
].join
|
35
|
-
)
|
36
|
-
|
26
|
+
require "writers/json_writer"
|
27
|
+
writer_class = TRecs::JsonWriter
|
37
28
|
|
38
29
|
strategy_file = "recording_strategies/#{opts[:strategy]}_strategy"
|
39
30
|
require strategy_file
|
40
|
-
|
31
|
+
strategy_class_name = [
|
41
32
|
"TRecs::",
|
42
33
|
opts[:strategy].split(/[-_\s]/).map(&:capitalize),
|
43
34
|
"Strategy"
|
44
35
|
].join
|
45
|
-
|
36
|
+
strategy_class = strategy_class_name.split("::").reduce(Object) { |a, e| a.const_get e }
|
46
37
|
|
47
38
|
########## AUDIO ##########
|
48
39
|
def start_sound_recording(file_name='sound.ogg')
|
@@ -66,32 +57,37 @@ end
|
|
66
57
|
|
67
58
|
######## END AUDIO ########
|
68
59
|
|
60
|
+
if strategy_class.to_s == "TRecs::TmuxSessionStrategy" && !ENV['TMUX']
|
61
|
+
puts "You need to be inside a tmux session to use the Tmux Session Strategy"
|
62
|
+
exit(0)
|
63
|
+
end
|
69
64
|
|
70
65
|
puts "Recording ..."
|
71
66
|
|
72
|
-
|
73
|
-
if strategy_class.to_s == "TRecs::TtyrecStrategy"
|
67
|
+
if strategy_class.to_s == "TRecs::TtyrecStrategy" || strategy_class.to_s == "TRecs::TmuxSessionStrategy"
|
74
68
|
opts[:height], opts[:width] = `stty size`.split(" ").map(&:to_i)
|
75
69
|
opts[:audio] && start_sound_recording(opts[:audio])
|
70
|
+
|
76
71
|
system "ttyrec #{opts[:input_file]}" if opts[:terminal]
|
77
72
|
end
|
78
73
|
|
74
|
+
opts[:audio_files] = [opts[:audio]] if opts[:audio]
|
75
|
+
|
79
76
|
recorder_options = {
|
80
77
|
writer: writer_class.new(opts),
|
81
78
|
strategy: strategy_class.new(opts),
|
82
79
|
step: opts[:step],
|
83
80
|
}
|
84
81
|
|
85
|
-
opts[:audio] && stop_sound_recording
|
86
82
|
RECORDER = TRecs::Recorder.new(recorder_options)
|
87
83
|
|
88
84
|
trap "SIGINT" do
|
85
|
+
opts[:audio] && stop_sound_recording
|
89
86
|
RECORDER.stop
|
90
87
|
end
|
91
88
|
|
92
|
-
|
93
89
|
RECORDER.record
|
94
90
|
|
95
91
|
puts "Recording finished"
|
96
92
|
puts "Play with:"
|
97
|
-
puts "
|
93
|
+
puts "trecs #{opts[:trecs_file]}"
|
data/lib/trecs/frame.rb
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
module TRecs
|
2
|
+
class Frame
|
3
|
+
include Enumerable
|
4
|
+
attr_accessor :content
|
5
|
+
def initialize(content="")
|
6
|
+
@content = content
|
7
|
+
end
|
8
|
+
|
9
|
+
def width
|
10
|
+
content.each_line.map { |line|
|
11
|
+
line.chomp.size
|
12
|
+
}.max
|
13
|
+
end
|
14
|
+
|
15
|
+
def height
|
16
|
+
content.lines.count
|
17
|
+
end
|
18
|
+
|
19
|
+
def each
|
20
|
+
content.each_line
|
21
|
+
end
|
22
|
+
|
23
|
+
def to_s
|
24
|
+
content
|
25
|
+
end
|
26
|
+
alias :to_str :to_s
|
27
|
+
end
|
28
|
+
|
29
|
+
def Frame(value)
|
30
|
+
case value
|
31
|
+
when Frame then value
|
32
|
+
else
|
33
|
+
Frame.new(value.to_str)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
module_function :Frame
|
37
|
+
end
|
data/lib/trecs/player.rb
CHANGED
@@ -1,25 +1,31 @@
|
|
1
|
-
require
|
2
|
-
require "pathname"
|
1
|
+
require "sources/tgz_source"
|
3
2
|
|
4
3
|
module TRecs
|
5
4
|
class JsonReader
|
6
5
|
attr_accessor :player
|
7
6
|
attr_reader :frames
|
8
|
-
attr_reader :file
|
9
7
|
attr_reader :timestamps
|
8
|
+
attr_reader :source
|
10
9
|
|
11
10
|
def initialize(options={})
|
12
|
-
|
13
|
-
|
14
|
-
@frames =
|
15
|
-
parsed_json = JSON.parse(json_string)
|
16
|
-
parsed_json.each do |time, content|
|
17
|
-
@frames[Integer(time)] = content
|
18
|
-
end
|
19
|
-
|
11
|
+
trecs_file = options.fetch(:trecs_file)
|
12
|
+
@source = options.fetch(:source)
|
13
|
+
@frames = get_frames
|
20
14
|
@timestamps = @frames.keys
|
21
15
|
end
|
22
16
|
|
17
|
+
def get_frames
|
18
|
+
frames = {}
|
19
|
+
source.read do
|
20
|
+
json_string = source.read_file("frames.json")
|
21
|
+
parsed_json = JSON.parse(json_string)
|
22
|
+
parsed_json.each do |time, content|
|
23
|
+
frames[Integer(time)] = content
|
24
|
+
end
|
25
|
+
end
|
26
|
+
frames
|
27
|
+
end
|
28
|
+
|
23
29
|
def setup
|
24
30
|
true
|
25
31
|
end
|
@@ -32,5 +38,6 @@ module TRecs
|
|
32
38
|
"<#{self.class}>"
|
33
39
|
end
|
34
40
|
alias :inspect :to_s
|
41
|
+
|
35
42
|
end
|
36
43
|
end
|
data/lib/trecs/recorder.rb
CHANGED
@@ -3,42 +3,43 @@ module TRecs
|
|
3
3
|
attr_reader :writer
|
4
4
|
attr_reader :strategy
|
5
5
|
attr_reader :step
|
6
|
-
attr_reader :offset
|
7
6
|
attr_reader :recording
|
8
7
|
attr_reader :current_time
|
9
8
|
attr_reader :current_content
|
10
9
|
|
10
|
+
attr_accessor :offset
|
11
11
|
|
12
12
|
def initialize(options={})
|
13
|
-
@writer
|
14
|
-
@writer.recorder
|
13
|
+
@writer = options.fetch(:writer)
|
14
|
+
@writer.recorder = self
|
15
15
|
|
16
|
-
@strategy
|
16
|
+
@strategy = options.fetch(:strategy)
|
17
17
|
@strategy.recorder = self
|
18
18
|
|
19
|
-
@step
|
19
|
+
@step = options.fetch(:step) { 100 }
|
20
20
|
@offset = options.fetch(:offset) { 0 }
|
21
|
-
|
21
|
+
|
22
|
+
@recording = false
|
22
23
|
@current_time = nil
|
23
24
|
end
|
24
25
|
|
25
26
|
def record
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
self.recording = false
|
27
|
+
do_record do
|
28
|
+
writer.setup
|
29
|
+
strategy.perform
|
30
|
+
writer.render
|
31
|
+
end
|
32
32
|
end
|
33
33
|
|
34
34
|
def current_frame(options={})
|
35
|
-
time
|
35
|
+
time = options.fetch(:time) { next_timestamp }
|
36
36
|
content = options.fetch(:content)
|
37
|
-
|
37
|
+
|
38
|
+
@current_time = time
|
38
39
|
@current_content = content
|
39
40
|
|
40
41
|
if @previous_content != content
|
41
|
-
new_current_time
|
42
|
+
new_current_time = current_time + offset
|
42
43
|
writer.create_frame(time: new_current_time, content: current_content)
|
43
44
|
@previous_content = content
|
44
45
|
end
|
@@ -58,5 +59,12 @@ module TRecs
|
|
58
59
|
attr_writer :current_time
|
59
60
|
attr_writer :current_content
|
60
61
|
|
62
|
+
def do_record
|
63
|
+
self.current_time = nil
|
64
|
+
self.recording = true
|
65
|
+
yield
|
66
|
+
self.recording = false
|
67
|
+
end
|
68
|
+
|
61
69
|
end
|
62
70
|
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require "recording_strategies/strategy"
|
2
|
+
|
3
|
+
module TRecs
|
4
|
+
class ConfigStrategy
|
5
|
+
include Strategy
|
6
|
+
attr_reader :step
|
7
|
+
attr_reader :format
|
8
|
+
attr_reader :strategies
|
9
|
+
|
10
|
+
def initialize(options={})
|
11
|
+
@step = options.fetch(:step) { 100 }
|
12
|
+
@format = options.fetch(:format) { "json" }
|
13
|
+
@strategies = options.fetch(:strategies) { [] }
|
14
|
+
end
|
15
|
+
|
16
|
+
def <<(strategies)
|
17
|
+
Array(strategies).each do |strategy|
|
18
|
+
@strategies << strategy
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def perform
|
23
|
+
strategies.each do |strategy|
|
24
|
+
strategy.recorder = recorder
|
25
|
+
strategy.perform
|
26
|
+
recorder.offset = recorder.next_timestamp
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require "recording_strategies/strategy"
|
2
|
+
module TRecs
|
3
|
+
class FileFramesStrategy
|
4
|
+
include Strategy
|
5
|
+
attr_accessor :frames
|
6
|
+
|
7
|
+
def initialize(dirname)
|
8
|
+
@frames = Dir.entries(dirname)
|
9
|
+
.select { |d| d =~ /\d+/}
|
10
|
+
.each_with_object(Hash.new) do |filename, h|
|
11
|
+
h[filename.to_i] = File.read(dirname + "/" + filename)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def perform
|
16
|
+
@frames.each do |time, content|
|
17
|
+
current_time(time)
|
18
|
+
current_content(content)
|
19
|
+
save_frame
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def stop
|
24
|
+
end
|
25
|
+
|
26
|
+
def inspect
|
27
|
+
"<#{self.class}: frames: #{frames}>"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|