dutchman 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 +7 -0
- data/.gitignore +17 -0
- data/.rspec +2 -0
- data/Gemfile +7 -0
- data/Guardfile +6 -0
- data/LICENSE.txt +22 -0
- data/README.md +103 -0
- data/Rakefile +11 -0
- data/dutchman.gemspec +27 -0
- data/lib/dutchman/application.rb +21 -0
- data/lib/dutchman/ghost_writer/apple_script/apple_script.rb +29 -0
- data/lib/dutchman/ghost_writer/apple_script/application.rb +91 -0
- data/lib/dutchman/ghost_writer/apple_script/command.rb +42 -0
- data/lib/dutchman/ghost_writer/apple_script/command_line.erb +3 -0
- data/lib/dutchman/ghost_writer/apple_script/tell_application.erb +10 -0
- data/lib/dutchman/ghost_writer/ghost_writer.rb +27 -0
- data/lib/dutchman/ghost_writer/typing_speed.rb +51 -0
- data/lib/dutchman/version.rb +3 -0
- data/lib/dutchman.rb +23 -0
- data/spec/lib/dutchman/application_spec.rb +24 -0
- data/spec/lib/dutchman/ghost_writer/apple_script/apple_script_spec.rb +10 -0
- data/spec/lib/dutchman/ghost_writer/apple_script/application_spec.rb +83 -0
- data/spec/lib/dutchman/ghost_writer/apple_script/command_spec.rb +29 -0
- data/spec/lib/dutchman/ghost_writer/ghost_writer_spec.rb +0 -0
- data/spec/lib/dutchman/ghost_writer/typing_speed_spec.rb +44 -0
- data/spec/lib/dutchman_spec.rb +38 -0
- data/spec/spec_helper.rb +19 -0
- metadata +125 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: b13e16f9e84f0e1eff1f99e8a100a6616ac79062
|
4
|
+
data.tar.gz: e558954bc3a31f33adafab4bf7b605c3be059db1
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: dc0873e17ea8344be6e4afc6f062943e4e108a851d38d7d9bc3428991e0d119e3c55870ef965475269537147646238a85e4c0b9cd278474e0887d14672fa828a
|
7
|
+
data.tar.gz: 271161c177277cfa05d641c0d657d0c0a29a6df73f60d106213e54761731ac85f0ced5a6b0bf2dc5d544e570f61c000f177f0fcfc7c2e84b2f6539b9c730d3b4
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/Gemfile
ADDED
data/Guardfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 Franklin Webber
|
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,103 @@
|
|
1
|
+
# Dutchman
|
2
|
+
|
3
|
+
(Flying) Dutchman is a tool is a wrapper for AppleScript with the purpose of
|
4
|
+
providing an easier interface for inserting text into applications at various
|
5
|
+
speeds as though they were typed by a person. SPOOOOKY!
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
Add this line to your application's Gemfile:
|
10
|
+
|
11
|
+
gem 'dutchman'
|
12
|
+
|
13
|
+
And then execute:
|
14
|
+
|
15
|
+
$ bundle
|
16
|
+
|
17
|
+
Or install it yourself as:
|
18
|
+
|
19
|
+
$ gem install dutchman
|
20
|
+
|
21
|
+
## Usage
|
22
|
+
|
23
|
+
Imagine you are writing a screencast and wanted to save yourself the
|
24
|
+
embarassment of all those typos, the viewers the discomfort of watching you
|
25
|
+
fumble, or all the hours you are going to spend mind-numblingly slicing and
|
26
|
+
splicing the recording.
|
27
|
+
|
28
|
+
So we have a screencast we are recording and we want to have Dutchman type
|
29
|
+
out a block of code within our favorite editor Sublime Text.
|
30
|
+
|
31
|
+
First, we would need to configure the editor to not help us with auto
|
32
|
+
identation. By setting `"auto_indent": false`
|
33
|
+
|
34
|
+
```
|
35
|
+
require 'dutchman'
|
36
|
+
|
37
|
+
Dutchman.write(to: "Sublime Text",
|
38
|
+
text: """
|
39
|
+
class Ball < Toy
|
40
|
+
def bounce
|
41
|
+
|
42
|
+
end
|
43
|
+
end
|
44
|
+
""")
|
45
|
+
```
|
46
|
+
|
47
|
+
The text is typed at the default typing speed "moderate". There are three
|
48
|
+
available speeds.
|
49
|
+
|
50
|
+
| Speed | Words Per Minute (wpm) | Parameter |
|
51
|
+
| slow | ~ 23 | :slow |
|
52
|
+
| moderate (default) | ~ 35 | :moderate |
|
53
|
+
| fast | ~ 50 | :fast |
|
54
|
+
|
55
|
+
|
56
|
+
Here we write our original slowly, to allow the viewers to savor the flavor of
|
57
|
+
the code we are presenting. In the follow up code we choose to type it out fast
|
58
|
+
because the viewer is obviously understood the original code we typed.
|
59
|
+
|
60
|
+
```
|
61
|
+
require 'dutchman'
|
62
|
+
|
63
|
+
Dutchman.write(to: "Sublime Text", speed: :slow, text: """
|
64
|
+
class Ball < Toy
|
65
|
+
def bounce
|
66
|
+
|
67
|
+
end
|
68
|
+
end
|
69
|
+
""")
|
70
|
+
|
71
|
+
# This content would appear after the Ball class.
|
72
|
+
|
73
|
+
Dutchman.write(to: "Sublime Text", speed: :fast, text: """
|
74
|
+
class Blocks < Toy
|
75
|
+
def stack
|
76
|
+
|
77
|
+
end
|
78
|
+
end
|
79
|
+
""")
|
80
|
+
```
|
81
|
+
|
82
|
+
The text is typed out in a uniform manner, to add a little variation to the
|
83
|
+
speed, you can specify an additional parameter to `humanize` the typing.
|
84
|
+
|
85
|
+
```
|
86
|
+
require 'dutchman'
|
87
|
+
|
88
|
+
Dutchman.write(to: "Sublime Text", speed: :slow, humanize: true, text: """
|
89
|
+
class Ball < Toy
|
90
|
+
def bounce
|
91
|
+
|
92
|
+
end
|
93
|
+
end
|
94
|
+
""")
|
95
|
+
```
|
96
|
+
|
97
|
+
## Contributing
|
98
|
+
|
99
|
+
1. Fork it ( http://github.com/burtlo/dutchman/fork )
|
100
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
101
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
102
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
103
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
data/dutchman.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 'dutchman/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "dutchman"
|
8
|
+
spec.version = Dutchman::VERSION
|
9
|
+
spec.authors = ["Franklin Webber"]
|
10
|
+
spec.email = ["franklin.webber@gmail.com"]
|
11
|
+
spec.summary = %q{A an interface to have your computer do the automated type (OSX only).}
|
12
|
+
spec.description = %q{Imagine you are writing a screencast and wanted to save yourself the
|
13
|
+
embarassment of all those typos, the viewers the discomfort of watching you
|
14
|
+
fumble, or all the hours you are going to spend mind-numblingly slicing and
|
15
|
+
splicing the recording.}
|
16
|
+
spec.homepage = ""
|
17
|
+
spec.license = "MIT"
|
18
|
+
|
19
|
+
spec.files = `git ls-files -z`.split("\x0")
|
20
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
21
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
22
|
+
spec.require_paths = ["lib"]
|
23
|
+
|
24
|
+
spec.add_development_dependency "bundler", "~> 1.5"
|
25
|
+
spec.add_development_dependency "rake"
|
26
|
+
spec.add_development_dependency "rspec"
|
27
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require "dutchman/ghost_writer/ghost_writer"
|
2
|
+
|
3
|
+
module Dutchman
|
4
|
+
class Application
|
5
|
+
def initialize(params)
|
6
|
+
@name = params.delete(:name)
|
7
|
+
end
|
8
|
+
|
9
|
+
attr_reader :name
|
10
|
+
|
11
|
+
def write(text)
|
12
|
+
_write(name,text,:moderate)
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def _write(name,text,speed)
|
18
|
+
GhostWriter.write(application: name, text: text,speed: speed)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require "ERB"
|
2
|
+
require_relative "command"
|
3
|
+
require_relative "application"
|
4
|
+
|
5
|
+
module Dutchman
|
6
|
+
module GhostWriter
|
7
|
+
|
8
|
+
#
|
9
|
+
# The current rb_appscript gem said to beware and not to use in new
|
10
|
+
# applications. Instead of digging into that application I thought that it
|
11
|
+
# be better to simply create a wrapper class that executes the osascript
|
12
|
+
# command on the command line.
|
13
|
+
#
|
14
|
+
class AppleScript
|
15
|
+
def app(name)
|
16
|
+
Application.new(self,name)
|
17
|
+
end
|
18
|
+
|
19
|
+
def execute(applescript)
|
20
|
+
`#{command(applescript)}`
|
21
|
+
end
|
22
|
+
|
23
|
+
def command(applescript)
|
24
|
+
Command.new(self,applescript)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
module Dutchman
|
2
|
+
module GhostWriter
|
3
|
+
class AppleScript
|
4
|
+
|
5
|
+
class Application
|
6
|
+
def initialize(container,name)
|
7
|
+
@container = container
|
8
|
+
@name = name
|
9
|
+
end
|
10
|
+
|
11
|
+
attr_reader :name, :command
|
12
|
+
|
13
|
+
attr_reader :container
|
14
|
+
|
15
|
+
def command(new_command = nil)
|
16
|
+
if new_command
|
17
|
+
@command = new_command
|
18
|
+
else
|
19
|
+
@command
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def keystroke(key_name)
|
24
|
+
command [ apl_keystroke(key_name) ]
|
25
|
+
end
|
26
|
+
|
27
|
+
def typed_phrase(phrase,typing_speed)
|
28
|
+
command(phrase.chars.map do |letter|
|
29
|
+
[ apl_keystroke(letter), apl_delay(typing_speed.delay_between_characters) ]
|
30
|
+
end.flatten)
|
31
|
+
end
|
32
|
+
|
33
|
+
def applescript
|
34
|
+
tell_application_command
|
35
|
+
end
|
36
|
+
|
37
|
+
def execute
|
38
|
+
container.execute(applescript)
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def tell_application_command
|
44
|
+
ERB.new(tell_application_command_template,nil,erb_trim_mode).result(binding)
|
45
|
+
end
|
46
|
+
|
47
|
+
def erb_trim_mode
|
48
|
+
"-"
|
49
|
+
end
|
50
|
+
|
51
|
+
def tell_application_command_template
|
52
|
+
template_with_name "tell_application"
|
53
|
+
end
|
54
|
+
|
55
|
+
def template_with_name(name)
|
56
|
+
File.read(File.join(File.dirname(__FILE__),"#{name}.erb"))
|
57
|
+
end
|
58
|
+
|
59
|
+
# AppleScript Commands
|
60
|
+
|
61
|
+
def apl_keystroke(name)
|
62
|
+
"keystroke #{translate_to_keystroke(name)}"
|
63
|
+
end
|
64
|
+
|
65
|
+
def translate_to_keystroke(name)
|
66
|
+
keystroke_translations[name]
|
67
|
+
end
|
68
|
+
|
69
|
+
#
|
70
|
+
# Translate text characters to their counterpart in the world of
|
71
|
+
# AppleScript.
|
72
|
+
#
|
73
|
+
def keystroke_translations
|
74
|
+
@keystroke_translations ||= begin
|
75
|
+
hash = { "\n" => "return",
|
76
|
+
"\\" => "\\\\",
|
77
|
+
"\"" => "\\\"" }
|
78
|
+
hash.default_proc = proc { |hash,key| hash[key] = "\"#{key}\"" }
|
79
|
+
hash
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def apl_delay(amount)
|
84
|
+
"delay #{amount}"
|
85
|
+
end
|
86
|
+
|
87
|
+
end
|
88
|
+
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module Dutchman
|
2
|
+
module GhostWriter
|
3
|
+
class AppleScript
|
4
|
+
|
5
|
+
#
|
6
|
+
# The Command class executes the provided AppleScript.
|
7
|
+
#
|
8
|
+
class Command
|
9
|
+
def initialize(container,applescript)
|
10
|
+
@container = container
|
11
|
+
@applescript = applescript
|
12
|
+
end
|
13
|
+
|
14
|
+
attr_reader :container
|
15
|
+
|
16
|
+
attr_reader :applescript
|
17
|
+
|
18
|
+
def to_s
|
19
|
+
command_line
|
20
|
+
end
|
21
|
+
|
22
|
+
def execute
|
23
|
+
container.execute(self)
|
24
|
+
end
|
25
|
+
|
26
|
+
def command_line
|
27
|
+
ERB.new(command_line_template).result(binding)
|
28
|
+
end
|
29
|
+
|
30
|
+
def command_line_template
|
31
|
+
template_with_name "command_line"
|
32
|
+
end
|
33
|
+
|
34
|
+
def template_with_name(name)
|
35
|
+
File.read(File.join(File.dirname(__FILE__),"#{name}.erb"))
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# TODO: Figure out platform and load the correct one
|
2
|
+
require_relative "apple_script/apple_script"
|
3
|
+
require_relative "typing_speed"
|
4
|
+
|
5
|
+
module Dutchman
|
6
|
+
module GhostWriter
|
7
|
+
|
8
|
+
#
|
9
|
+
# @params params [Hash] the parameters :application, :text, :speed
|
10
|
+
#
|
11
|
+
def self.write(params)
|
12
|
+
params[:speed] = speed(params[:speed],params[:humanize])
|
13
|
+
# TODO: Platform Switching Here
|
14
|
+
apple_script(params)
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.apple_script(params)
|
18
|
+
app = AppleScript.new.app(params[:application])
|
19
|
+
app.typed_phrase(params[:text],params[:speed])
|
20
|
+
app.execute
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.speed(value,humanize)
|
24
|
+
TypingSpeed.new(value,humanize)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module Dutchman
|
2
|
+
module GhostWriter
|
3
|
+
|
4
|
+
class TypingSpeed
|
5
|
+
|
6
|
+
def initialize(name,humanize)
|
7
|
+
@name = name
|
8
|
+
@humanize = humanize
|
9
|
+
end
|
10
|
+
|
11
|
+
attr_reader :name
|
12
|
+
|
13
|
+
attr_reader :humanize
|
14
|
+
|
15
|
+
#
|
16
|
+
# The value in milliseconds to wait between characters
|
17
|
+
#
|
18
|
+
def delay_between_characters
|
19
|
+
standard_delay = (1.0 / available_speeds[name]).round(2)
|
20
|
+
current_delay = standard_delay + variance(standard_delay)
|
21
|
+
current_delay.round(2)
|
22
|
+
end
|
23
|
+
|
24
|
+
def variance(delay)
|
25
|
+
humanize ? random_number_between_pos_and_neg(delay) : 0.0
|
26
|
+
end
|
27
|
+
|
28
|
+
def random_number_between_pos_and_neg(number)
|
29
|
+
rand(number * 100).to_f / 100 * (rand(2).odd? ? -1 : 1)
|
30
|
+
end
|
31
|
+
|
32
|
+
def available_speeds
|
33
|
+
@avaliable_speeds ||= begin
|
34
|
+
hash = { slow: wpm_to_cps(23.0),
|
35
|
+
moderate: wpm_to_cps(35.0),
|
36
|
+
fast: wpm_to_cps(50.0) }
|
37
|
+
hash.default = hash[:moderate]
|
38
|
+
hash
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
#
|
43
|
+
# The assumption is that each word is 8 characters in length.
|
44
|
+
#
|
45
|
+
def wpm_to_cps(wpm)
|
46
|
+
wpm.to_f * 10.0 / 60.0
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
end
|
data/lib/dutchman.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
require "dutchman/version"
|
2
|
+
require "dutchman/application"
|
3
|
+
|
4
|
+
module Dutchman
|
5
|
+
|
6
|
+
def self.write(params)
|
7
|
+
to = params.delete(:to)
|
8
|
+
text = params.delete(:text)
|
9
|
+
speed = params.fetch(:speed,default_speed)
|
10
|
+
humanize = params.fetch(:humanize,false)
|
11
|
+
|
12
|
+
_write(application: to, text: text, speed: speed, humanize: humanize)
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.default_speed
|
16
|
+
:moderate
|
17
|
+
end
|
18
|
+
|
19
|
+
def self._write(params)
|
20
|
+
GhostWriter.write params
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Dutchman::Application do
|
4
|
+
|
5
|
+
subject { described_class.new(name: "Chrome") }
|
6
|
+
|
7
|
+
it "has a name" do
|
8
|
+
expect(subject.name).to eq("Chrome")
|
9
|
+
end
|
10
|
+
|
11
|
+
describe "#write" do
|
12
|
+
context "when given a body of text" do
|
13
|
+
it "writes the text to the application" do
|
14
|
+
expect(subject).to receive(:_write).with("Chrome","All your roommates know my voice!",:moderate)
|
15
|
+
subject.write("All your roommates know my voice!")
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
context "when no text is provided" do
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Dutchman::GhostWriter::AppleScript::Application do
|
4
|
+
|
5
|
+
let(:subject) { described_class.new(container,application) }
|
6
|
+
|
7
|
+
let(:container) { mock("Applescript") }
|
8
|
+
let(:application) { "Sublime Text" }
|
9
|
+
|
10
|
+
describe "#keystroke" do
|
11
|
+
|
12
|
+
it "sends a keystroke to an application" do
|
13
|
+
subject.keystroke("Hello")
|
14
|
+
expect(subject.name).to eq application
|
15
|
+
expect(subject.applescript).to eq expected_applescript_command
|
16
|
+
end
|
17
|
+
|
18
|
+
let(:expected_applescript_command) do
|
19
|
+
"""tell application \"#{application}\"
|
20
|
+
activate
|
21
|
+
|
22
|
+
tell application \"System Events\"
|
23
|
+
keystroke \"Hello\"
|
24
|
+
end
|
25
|
+
|
26
|
+
end tell"""
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
describe "#typed_phrase" do
|
32
|
+
|
33
|
+
let(:typing_speed) { double("Speed",delay_between_characters: 0.1)}
|
34
|
+
|
35
|
+
it "sends keystrokes over time to an application" do
|
36
|
+
subject.typed_phrase("Hello",typing_speed)
|
37
|
+
expect(subject.applescript).to eq expected_applescript_command
|
38
|
+
end
|
39
|
+
|
40
|
+
let(:expected_applescript_command) do
|
41
|
+
%{tell application "#{application}"
|
42
|
+
activate
|
43
|
+
|
44
|
+
tell application "System Events"
|
45
|
+
keystroke "H"
|
46
|
+
delay 0.1
|
47
|
+
keystroke "e"
|
48
|
+
delay 0.1
|
49
|
+
keystroke "l"
|
50
|
+
delay 0.1
|
51
|
+
keystroke "l"
|
52
|
+
delay 0.1
|
53
|
+
keystroke "o"
|
54
|
+
delay 0.1
|
55
|
+
end
|
56
|
+
|
57
|
+
end tell}
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
|
62
|
+
describe "All Characters" do
|
63
|
+
|
64
|
+
it "sends a keystroke to an application" do
|
65
|
+
subject.keystroke("abcdefghijklmnopqrstuvwxyz0123456789~`!@#$%^&*()-=_+{}[]\\|:'\",.<>/?")
|
66
|
+
expect(subject.name).to eq application
|
67
|
+
expect(subject.applescript).to eq expected_applescript_command
|
68
|
+
end
|
69
|
+
|
70
|
+
let(:expected_applescript_command) do
|
71
|
+
"""tell application \"#{application}\"
|
72
|
+
activate
|
73
|
+
|
74
|
+
tell application \"System Events\"
|
75
|
+
keystroke \"abcdefghijklmnopqrstuvwxyz0123456789~`!@#$%^&*()-=_+{}[]\\|:'\",.<>/?\"
|
76
|
+
end
|
77
|
+
|
78
|
+
end tell"""
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Dutchman::GhostWriter::AppleScript::Command do
|
4
|
+
|
5
|
+
let(:subject) { described_class.new(container,given_applescript) }
|
6
|
+
|
7
|
+
let(:container) { mock("Applescript") }
|
8
|
+
|
9
|
+
it "allows you to execute a command" do
|
10
|
+
expect(subject.to_s).to eq expected_command
|
11
|
+
end
|
12
|
+
|
13
|
+
let(:given_applescript) do
|
14
|
+
"""tell application \"Safari\"
|
15
|
+
activate
|
16
|
+
|
17
|
+
tell application \"System Events\"
|
18
|
+
keystroke \"Hello\"
|
19
|
+
end
|
20
|
+
end tell"""
|
21
|
+
end
|
22
|
+
|
23
|
+
let(:expected_command) do
|
24
|
+
"""osascript <<END
|
25
|
+
#{given_applescript}
|
26
|
+
END"""
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
File without changes
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Dutchman::GhostWriter::TypingSpeed do
|
4
|
+
|
5
|
+
context "when slow" do
|
6
|
+
|
7
|
+
subject { described_class.new(:slow,false) }
|
8
|
+
|
9
|
+
it "has the correct delay between characters" do
|
10
|
+
expect(subject.delay_between_characters).to eq(0.26)
|
11
|
+
end
|
12
|
+
|
13
|
+
end
|
14
|
+
|
15
|
+
context "when moderate" do
|
16
|
+
|
17
|
+
subject { described_class.new(:moderate,false) }
|
18
|
+
|
19
|
+
it "has the correct delay between characters" do
|
20
|
+
expect(subject.delay_between_characters).to eq(0.17)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
context "when fast" do
|
25
|
+
|
26
|
+
subject { described_class.new(:fast,false) }
|
27
|
+
|
28
|
+
it "has the correct delay between characters" do
|
29
|
+
expect(subject.delay_between_characters).to eq(0.12)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
context "when humanized" do
|
34
|
+
|
35
|
+
subject { described_class.new(:fast,true) }
|
36
|
+
|
37
|
+
it "has the correct delay between characters" do
|
38
|
+
subject.stub(:random_number_between_pos_and_neg) { 0.01 }
|
39
|
+
expect(subject.delay_between_characters).to eq(0.13)
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Dutchman do
|
4
|
+
|
5
|
+
describe ".write" do
|
6
|
+
|
7
|
+
subject { described_class }
|
8
|
+
|
9
|
+
context "when an application and text are specified" do
|
10
|
+
it "writes the text to the specified application at the default speed" do
|
11
|
+
expect(subject).to receive(:_write).with(application: "Sublime Text",
|
12
|
+
text: "I want fruit roll ups!",
|
13
|
+
speed: :moderate,
|
14
|
+
humanize: false)
|
15
|
+
subject.write(to: "Sublime Text", text: "I want fruit roll ups!")
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
context "when the speed is provided" do
|
20
|
+
it "writes all the text out to the application at the specified speed" do
|
21
|
+
expect(subject).to receive(:_write).with(application: "Sublime Text",
|
22
|
+
text: "Put your groceries in my cart tonight",
|
23
|
+
speed: :slow,
|
24
|
+
humanize: false)
|
25
|
+
subject.write(to: "Sublime Text", text: "Put your groceries in my cart tonight", speed: :slow)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
context "when an application is not specified" do
|
30
|
+
it "tells the user an error has occurred"
|
31
|
+
end
|
32
|
+
|
33
|
+
context "when text is not specified" do
|
34
|
+
it "tells the user that no text was specified"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
# This file was generated by the `rspec --init` command. Conventionally, all
|
2
|
+
# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
|
3
|
+
# Require this file using `require "spec_helper"` to ensure that it is only
|
4
|
+
# loaded once.
|
5
|
+
#
|
6
|
+
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
7
|
+
RSpec.configure do |config|
|
8
|
+
config.treat_symbols_as_metadata_keys_with_true_values = true
|
9
|
+
config.run_all_when_everything_filtered = true
|
10
|
+
config.filter_run :focus
|
11
|
+
|
12
|
+
# Run specs in random order to surface order dependencies. If you find an
|
13
|
+
# order dependency and want to debug it, you can fix the order by providing
|
14
|
+
# the seed, which is printed after each run.
|
15
|
+
# --seed 1234
|
16
|
+
config.order = 'random'
|
17
|
+
end
|
18
|
+
|
19
|
+
require 'dutchman'
|
metadata
ADDED
@@ -0,0 +1,125 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: dutchman
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Franklin Webber
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-03-27 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.5'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.5'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '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: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
description: |-
|
56
|
+
Imagine you are writing a screencast and wanted to save yourself the
|
57
|
+
embarassment of all those typos, the viewers the discomfort of watching you
|
58
|
+
fumble, or all the hours you are going to spend mind-numblingly slicing and
|
59
|
+
splicing the recording.
|
60
|
+
email:
|
61
|
+
- franklin.webber@gmail.com
|
62
|
+
executables: []
|
63
|
+
extensions: []
|
64
|
+
extra_rdoc_files: []
|
65
|
+
files:
|
66
|
+
- .gitignore
|
67
|
+
- .rspec
|
68
|
+
- Gemfile
|
69
|
+
- Guardfile
|
70
|
+
- LICENSE.txt
|
71
|
+
- README.md
|
72
|
+
- Rakefile
|
73
|
+
- dutchman.gemspec
|
74
|
+
- lib/dutchman.rb
|
75
|
+
- lib/dutchman/application.rb
|
76
|
+
- lib/dutchman/ghost_writer/apple_script/apple_script.rb
|
77
|
+
- lib/dutchman/ghost_writer/apple_script/application.rb
|
78
|
+
- lib/dutchman/ghost_writer/apple_script/command.rb
|
79
|
+
- lib/dutchman/ghost_writer/apple_script/command_line.erb
|
80
|
+
- lib/dutchman/ghost_writer/apple_script/tell_application.erb
|
81
|
+
- lib/dutchman/ghost_writer/ghost_writer.rb
|
82
|
+
- lib/dutchman/ghost_writer/typing_speed.rb
|
83
|
+
- lib/dutchman/version.rb
|
84
|
+
- spec/lib/dutchman/application_spec.rb
|
85
|
+
- spec/lib/dutchman/ghost_writer/apple_script/apple_script_spec.rb
|
86
|
+
- spec/lib/dutchman/ghost_writer/apple_script/application_spec.rb
|
87
|
+
- spec/lib/dutchman/ghost_writer/apple_script/command_spec.rb
|
88
|
+
- spec/lib/dutchman/ghost_writer/ghost_writer_spec.rb
|
89
|
+
- spec/lib/dutchman/ghost_writer/typing_speed_spec.rb
|
90
|
+
- spec/lib/dutchman_spec.rb
|
91
|
+
- spec/spec_helper.rb
|
92
|
+
homepage: ''
|
93
|
+
licenses:
|
94
|
+
- MIT
|
95
|
+
metadata: {}
|
96
|
+
post_install_message:
|
97
|
+
rdoc_options: []
|
98
|
+
require_paths:
|
99
|
+
- lib
|
100
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
101
|
+
requirements:
|
102
|
+
- - '>='
|
103
|
+
- !ruby/object:Gem::Version
|
104
|
+
version: '0'
|
105
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
106
|
+
requirements:
|
107
|
+
- - '>='
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0'
|
110
|
+
requirements: []
|
111
|
+
rubyforge_project:
|
112
|
+
rubygems_version: 2.1.9
|
113
|
+
signing_key:
|
114
|
+
specification_version: 4
|
115
|
+
summary: A an interface to have your computer do the automated type (OSX only).
|
116
|
+
test_files:
|
117
|
+
- spec/lib/dutchman/application_spec.rb
|
118
|
+
- spec/lib/dutchman/ghost_writer/apple_script/apple_script_spec.rb
|
119
|
+
- spec/lib/dutchman/ghost_writer/apple_script/application_spec.rb
|
120
|
+
- spec/lib/dutchman/ghost_writer/apple_script/command_spec.rb
|
121
|
+
- spec/lib/dutchman/ghost_writer/ghost_writer_spec.rb
|
122
|
+
- spec/lib/dutchman/ghost_writer/typing_speed_spec.rb
|
123
|
+
- spec/lib/dutchman_spec.rb
|
124
|
+
- spec/spec_helper.rb
|
125
|
+
has_rdoc:
|