srt-shell 0.0.1

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 451374bce528e8072d296659b7b80776094761da
4
+ data.tar.gz: 05bc3f85cce7d283c7a04204f6ffb3e4db81054f
5
+ SHA512:
6
+ metadata.gz: 0508c7547e778cee210482dfd5e9d88afb0cebd7edff39fa77649e7710db1fde4ec32fef18bb5697987f5d14a90a03b18206e266d7f09b4f3f51f9e249d3a1d1
7
+ data.tar.gz: 4122c0f3beaa7f290f98692ac87c5acdd6656011c5ced75dacb94da6cd5f4168b78cf5dc364be8c388f20ab312ea44b0518a7270ac1d7a763a7baee7042eb970
data/.gitignore ADDED
@@ -0,0 +1,14 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in srt-shell.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 skliew
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,69 @@
1
+ # SRT::Shell
2
+
3
+ An interactive shell to retime SRT files.
4
+
5
+ ## Installation
6
+
7
+ For now you can only install this by cloning the repo, and then run the following commands:
8
+
9
+ ```shell
10
+ bundle install
11
+ rake install
12
+ ```
13
+ ## Usage
14
+
15
+ Start the shell with the command:
16
+
17
+ ```shell
18
+ srt-shell
19
+ ```
20
+
21
+ You could also optionally pass in an SRT file's path as an argument:
22
+ ```shell
23
+ srt-shell file.srt
24
+ ```
25
+
26
+ ## Commands
27
+
28
+ In the shell, the commands available will be shown with the 'help' command:
29
+ ```shell
30
+ help
31
+ ```
32
+
33
+ #### load '[filename]'
34
+ Load an SRT file.
35
+
36
+ ### exit
37
+ Exit the shell
38
+
39
+ ###### The following commands can only be used when we already have an SRT file loaded.
40
+ ###### Do note that all indexes start from 1, not 0.
41
+
42
+ #### interval [time in ms]
43
+ This would scan the SRT file for time gaps larger than the given time in ms. This is useful to search for indexes to be used with the time-shifting commands.
44
+
45
+ #### upshift|u [index] [time in ms]
46
+ Rewind the given time in ms for lines from index onwards.
47
+
48
+ #### forward|f [index] [time in ms]
49
+ Forward the given time in ms for lines from index onwards.
50
+
51
+ #### remove [index]
52
+ Remove line with the given index
53
+
54
+ #### save
55
+ Save (overwrite) the SRT file. You can place an executable file in $HOME/.srt_shell_hook to be executed when 'save' is used.
56
+
57
+ #### search [word]
58
+ Search for the given word in the SRT file and print out the entries that contain the word.
59
+
60
+ ## Platform
61
+ I've only tested this on Linux because it's the only machine I have.
62
+
63
+ ## Contributing
64
+
65
+ 1. Fork it ( https://github.com/skliew/srt-shell/fork )
66
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
67
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
68
+ 4. Push to the branch (`git push origin my-new-feature`)
69
+ 5. Create a new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,7 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ desc 'Run tests'
4
+ task :test do |t|
5
+ sh 'rspec -Ilib -I. test/spec_*.rb'
6
+ end
7
+
data/bin/srt-shell ADDED
@@ -0,0 +1,33 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'srt/shell'
4
+ require 'readline'
5
+
6
+ WORDS = %w( load interval upshift u forward f remove save show s search help h exit )
7
+ DEFAULT_WORD_BREAK_CHARS = " \t\n\"\\'`@$><=;|&{("
8
+ FILENAME_WORD_BREAK_CHARS = "\t\n\"\\'`@$><=;|&{"
9
+
10
+ Readline.completion_proc = lambda do |word|
11
+ Readline.completer_word_break_characters = DEFAULT_WORD_BREAK_CHARS
12
+ buffer = Readline.line_buffer.chomp
13
+
14
+ if buffer.match(/^\s*load\s+/)
15
+ Readline.completer_word_break_characters = FILENAME_WORD_BREAK_CHARS
16
+ return Readline::FILENAME_COMPLETION_PROC.call(word)
17
+ end
18
+
19
+ return [] if WORDS.find { |w| buffer.match(/^\s*#{w}\s+/) }
20
+ WORDS.grep(/^#{Regexp.escape(word)}/)
21
+ end
22
+
23
+ Signal.trap('INT') do
24
+ puts "Caught SIGINT, exiting..."
25
+ exit 0
26
+ end
27
+ shell = SRT::Shell.new(ARGV[0])
28
+
29
+ loop do
30
+ line = Readline.readline('> ', true)
31
+ shell.eval_command(line.chomp)
32
+ end
33
+
@@ -0,0 +1,7 @@
1
+ module SRT
2
+ class Line
3
+ def to_s(time_str_function=:time_str)
4
+ [sequence, (display_coordinates ? send(time_str_function) + display_coordinates : send(time_str_function)), text, ''].flatten.join("\n")
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,5 @@
1
+ module SRT
2
+ class Shell
3
+ VERSION = "0.0.1"
4
+ end
5
+ end
data/lib/srt/shell.rb ADDED
@@ -0,0 +1,181 @@
1
+ # encoding: utf-8
2
+ require 'srt/shell/version'
3
+ require 'srt'
4
+ require 'srt/patches'
5
+
6
+ module SRT
7
+ class Shell
8
+ SAVE_HOOK_FILE = ::File.expand_path('~/.srt_shell_hook')
9
+ BOM_STRING = "\xEF\xBB\xBF"
10
+ BOM_REGEX = /#{BOM_STRING}/
11
+ USAGE_MSG = <<USAGE
12
+ Usage: #{$0} [SRT_FILENAME]
13
+ Commands:
14
+ EX: load 'SRT_FILENAME'
15
+ EX: interval 90
16
+ EX: upshift|u 50 5000
17
+ EX: forward|f 50 5000
18
+ EX: remove 50
19
+ EX: save
20
+ EX: show|s 50
21
+ EX: search TERM
22
+ EX: help|h
23
+ EX: exit
24
+ USAGE
25
+
26
+ def initialize(path = nil, save_hook=SAVE_HOOK_FILE)
27
+ @file, @path = nil, nil
28
+ @bom = false
29
+ load_path(path) if path
30
+ @save_hook = ::File.exists?(save_hook) ? save_hook : nil
31
+ end
32
+
33
+ def load_path(path)
34
+ path = ::File.expand_path(path)
35
+ @path = path
36
+
37
+ # Test if file contains BOM
38
+ ::File.open(path) do |file|
39
+ lines = file.read.split("\n")
40
+ unless lines.empty?
41
+ if lines[0].match(BOM_REGEX)
42
+ lines[0].sub!(BOM_REGEX, '')
43
+ @bom = true
44
+ end
45
+ @file = SRT::File.parse(lines.join("\n"))
46
+ else
47
+ raise ArgumentError, 'Invalid SRT file'
48
+ end
49
+ end
50
+ self
51
+ end
52
+
53
+ def show(index)
54
+ check_index(index)
55
+ puts @file.lines[index - 1].to_s + "\n"
56
+ rescue IndexError => error
57
+ puts error.message
58
+ end
59
+
60
+ def timeshift(index, timecode)
61
+ check_index(index)
62
+ if time = Parser.timespan(timecode)
63
+ @file.lines[index-1..-1].each do |line|
64
+ line.start_time += time
65
+ line.end_time += time
66
+ end
67
+ else
68
+ puts "Invalid timeshift input (#{index}, #{timecode})"
69
+ end
70
+ rescue IndexError => error
71
+ puts error.message
72
+ end
73
+
74
+ def rewind(index, time)
75
+ timeshift(index, "-#{time}ms")
76
+ end
77
+
78
+ def forward(index, time)
79
+ timeshift(index, "+#{time}ms")
80
+ end
81
+
82
+ def scan_interval(input_time)
83
+ unless time = Parser.timespan("#{input_time}ms")
84
+ puts "Invalid time used #{input_time}"
85
+ return
86
+ end
87
+ end_time = 0
88
+ result = []
89
+ @file.lines.each do |line|
90
+ interval = line.start_time - end_time
91
+ if interval >= time
92
+ result << "index: #{line.sequence} time: #{line.time_str} gap: #{interval}"
93
+ end
94
+ end_time = line.end_time
95
+ end
96
+ puts result.join("\n")
97
+ end
98
+
99
+ def remove(index)
100
+ check_index(index)
101
+ index -= 1
102
+ @file.lines.delete_at(index)
103
+ @file.lines[index..-1].each do |line|
104
+ line.sequence -= 1
105
+ end
106
+ rescue IndexError => error
107
+ puts error.message
108
+ end
109
+
110
+ def search(term)
111
+ result = []
112
+ @file.lines.each do |line|
113
+ if line.text.find { |text| text[term] }
114
+ result << line.to_s
115
+ end
116
+ end
117
+ puts result.join("\n") + "\n"
118
+ end
119
+
120
+ def show_all
121
+ puts @file
122
+ end
123
+
124
+ def save(path=@path)
125
+ ::File.open(path, 'w') do |file|
126
+ file.print BOM_STRING if @bom
127
+ file.print @file.to_s.split("\n").join("\r\n"), "\r\n\r\n"
128
+ end
129
+ if @save_hook
130
+ output = `sh #{@save_hook}`
131
+ puts output unless output.empty?
132
+ end
133
+ end
134
+
135
+ def eval_command(cmd)
136
+ case cmd
137
+ when /^\s*(?:help|h)\s*$/
138
+ puts USAGE_MSG
139
+ return
140
+ when /^\s*exit\s*$/
141
+ exit 0
142
+ when /^\s*load\s+\'?([^']+)\'?\s*$/
143
+ load_path($1)
144
+ return
145
+ end
146
+
147
+ if @file
148
+ case cmd
149
+ when /^\s*(?:show|s)\s+(\d+)\s*$/
150
+ show($1.to_i)
151
+ when /^\s*(?:showall)\s*$/
152
+ show_all
153
+ when /^\s*interval\s+(\d+)\s*$/
154
+ scan_interval($1.to_i)
155
+ when /^\s*(?:u|rewind)\s+(\d+)\s+(\d+)\s*$/
156
+ rewind($1.to_i, $2.to_i)
157
+ when /^\s*(?:f|forward)\s+(\d+)\s+(\d+)\s*$/
158
+ forward($1.to_i, $2.to_i)
159
+ when /^\s*(?:remove)\s+(\d+)\s*$/
160
+ remove($1.to_i)
161
+ when /^\s*save\s*$/
162
+ save
163
+ when /^\s*search\s*(.*)$/
164
+ search($1)
165
+ else
166
+ puts "Invalid command"
167
+ end
168
+ else
169
+ puts "File is not loaded. Load a file using the 'load' command"
170
+ end
171
+ end
172
+
173
+ private
174
+
175
+ def check_index(index)
176
+ if index < 1
177
+ raise IndexError, "Invalid index given, index must be more than 0"
178
+ end
179
+ end
180
+ end
181
+ end
data/srt-shell.gemspec ADDED
@@ -0,0 +1,27 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'srt/shell/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "srt-shell"
8
+ spec.version = SRT::Shell::VERSION
9
+ spec.authors = ["skliew"]
10
+ spec.email = ["skliew@gmail.com"]
11
+ spec.summary = %q{An interactive shell to retime SRT files.}
12
+ spec.description = %q{}
13
+ spec.homepage = ""
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.6"
22
+ spec.add_development_dependency "rake", "~> 10.0"
23
+ spec.add_development_dependency "rspec", "~> 3.0"
24
+ spec.add_development_dependency "simplecov", "~> 0.9"
25
+
26
+ spec.add_runtime_dependency "srt", "~> 0.1"
27
+ end
@@ -0,0 +1,21 @@
1
+ 1
2
+ 00:03:55,339 --> 00:03:57,236
3
+ I had the craziest dream last night.
4
+
5
+ 2
6
+ 00:03:59,679 --> 00:04:01,586
7
+ I was dancing the White Swan.
8
+
9
+ 3
10
+ 00:04:03,346 --> 00:04:06,552
11
+ It was different choreography, though.
12
+ It was more like the Bolshoi's.
13
+
14
+ 4
15
+ 00:04:10,566 --> 00:04:12,193
16
+ It was the prologue,
17
+
18
+ 5
19
+ 00:04:12,228 --> 00:04:15,015
20
+ when Rothbart casts his spell.
21
+
@@ -0,0 +1 @@
1
+ echo "Saved"
data/test/helper.rb ADDED
@@ -0,0 +1,4 @@
1
+ require 'simplecov'
2
+ SimpleCov.start
3
+
4
+ require 'srt/shell'
@@ -0,0 +1,91 @@
1
+ require File.join(File.dirname(__FILE__), 'helper')
2
+
3
+ describe SRT::Shell do
4
+ before do
5
+ @app = SRT::Shell.new(
6
+ File.dirname(__FILE__) + '/fixtures/sample.srt',
7
+ File.dirname(__FILE__) + '/fixtures/save_hook'
8
+ )
9
+ end
10
+
11
+ it "should return a SRT::Shell" do
12
+ expect(@app.class).to eq(SRT::Shell)
13
+ end
14
+
15
+ it "should load a file" do
16
+ expect{ @app.load_path(File.dirname(__FILE__) + '/fixtures/sample.srt') }.to_not raise_error(Exception)
17
+
18
+ end
19
+
20
+ it 'should print out its USAGE' do
21
+ expect(STDOUT).to receive(:puts).with(SRT::Shell::USAGE_MSG)
22
+ @app.eval_command('help')
23
+ end
24
+
25
+ describe "With a loaded SRT file" do
26
+ it "should show a line" do
27
+ expect(STDOUT).to receive(:puts).with(
28
+ "1\n00:03:55,339 --> 00:03:57,236\nI had the craziest dream last night.\n\n"
29
+ )
30
+ @app.eval_command('show 1')
31
+ end
32
+
33
+ it "should forward SRT file's time" do
34
+ @app.eval_command('forward 1 1')
35
+ expect(STDOUT).to receive(:puts).with(
36
+ "1\n00:03:55,340 --> 00:03:57,237\nI had the craziest dream last night.\n\n"
37
+ )
38
+ @app.eval_command('show 1')
39
+ end
40
+
41
+ it "should rewind SRT file's time" do
42
+ @app.eval_command('rewind 1 1')
43
+ expect(STDOUT).to receive(:puts).with(
44
+ "1\n00:03:55,338 --> 00:03:57,235\nI had the craziest dream last night.\n\n"
45
+ )
46
+ @app.eval_command('show 1')
47
+ end
48
+
49
+ it "should show a message when an invalid index is used for rewind/forward" do
50
+ expect(STDOUT).to receive(:puts).with(/Invalid/)
51
+ @app.eval_command('rewind 0 1')
52
+ end
53
+
54
+ it "should scan for lines' interval" do
55
+ expect(STDOUT).to receive(:puts).with(
56
+ "index: 1 time: 00:03:55,339 --> 00:03:57,236 gap: 235.339\nindex: 4 time: 00:04:10,566 --> 00:04:12,193 gap: 4.01400000000001"
57
+ )
58
+ @app.eval_command('interval 3000')
59
+ end
60
+
61
+ it "should remove a line from SRT::File" do
62
+ @app.eval_command('remove 1')
63
+ expect(STDOUT).to receive(:puts).with(
64
+ <<OUT
65
+ 1
66
+ 00:03:59,679 --> 00:04:01,586
67
+ I was dancing the White Swan.
68
+
69
+ OUT
70
+ )
71
+ @app.eval_command('show 1')
72
+ end
73
+
74
+ it "should return the lines containing the searched term" do
75
+ expect(STDOUT).to receive(:puts).with(
76
+ <<OUT
77
+ 2
78
+ 00:03:59,679 --> 00:04:01,586
79
+ I was dancing the White Swan.
80
+
81
+ OUT
82
+ )
83
+ @app.eval_command('search dancing')
84
+ end
85
+
86
+ it "should save and trigger its hook" do
87
+ expect(STDOUT).to receive(:puts).with("Saved\n")
88
+ @app.save
89
+ end
90
+ end
91
+ end
metadata ADDED
@@ -0,0 +1,133 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: srt-shell
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - skliew
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-09-30 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.6'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.6'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '3.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: simplecov
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '0.9'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '0.9'
69
+ - !ruby/object:Gem::Dependency
70
+ name: srt
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '0.1'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '0.1'
83
+ description: ''
84
+ email:
85
+ - skliew@gmail.com
86
+ executables:
87
+ - srt-shell
88
+ extensions: []
89
+ extra_rdoc_files: []
90
+ files:
91
+ - ".gitignore"
92
+ - Gemfile
93
+ - LICENSE.txt
94
+ - README.md
95
+ - Rakefile
96
+ - bin/srt-shell
97
+ - lib/srt/patches.rb
98
+ - lib/srt/shell.rb
99
+ - lib/srt/shell/version.rb
100
+ - srt-shell.gemspec
101
+ - test/fixtures/sample.srt
102
+ - test/fixtures/save_hook
103
+ - test/helper.rb
104
+ - test/spec_shell.rb
105
+ homepage: ''
106
+ licenses:
107
+ - MIT
108
+ metadata: {}
109
+ post_install_message:
110
+ rdoc_options: []
111
+ require_paths:
112
+ - lib
113
+ required_ruby_version: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ required_rubygems_version: !ruby/object:Gem::Requirement
119
+ requirements:
120
+ - - ">="
121
+ - !ruby/object:Gem::Version
122
+ version: '0'
123
+ requirements: []
124
+ rubyforge_project:
125
+ rubygems_version: 2.4.5.1
126
+ signing_key:
127
+ specification_version: 4
128
+ summary: An interactive shell to retime SRT files.
129
+ test_files:
130
+ - test/fixtures/sample.srt
131
+ - test/fixtures/save_hook
132
+ - test/helper.rb
133
+ - test/spec_shell.rb