repla 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. checksums.yaml +7 -0
  2. data/lib/applescript/close_window.scpt +0 -0
  3. data/lib/applescript/create_window.scpt +0 -0
  4. data/lib/applescript/do_javascript.scpt +0 -0
  5. data/lib/applescript/exists.scpt +0 -0
  6. data/lib/applescript/hide_log.scpt +0 -0
  7. data/lib/applescript/load_html.scpt +0 -0
  8. data/lib/applescript/load_html_with_base_url.scpt +0 -0
  9. data/lib/applescript/load_plugin.scpt +0 -0
  10. data/lib/applescript/read_from_standard_input.scpt +0 -0
  11. data/lib/applescript/resource_path_for_plugin.scpt +0 -0
  12. data/lib/applescript/resource_url_for_plugin.scpt +0 -0
  13. data/lib/applescript/run_plugin.scpt +0 -0
  14. data/lib/applescript/run_plugin_in_split.scpt +0 -0
  15. data/lib/applescript/show_log.scpt +0 -0
  16. data/lib/applescript/split_id_in_window.scpt +0 -0
  17. data/lib/applescript/split_id_in_window_last.scpt +0 -0
  18. data/lib/applescript/toggle_log.scpt +0 -0
  19. data/lib/applescript/window_id_for_plugin.scpt +0 -0
  20. data/lib/repla/dependencies/css/style.css +15 -0
  21. data/lib/repla/dependencies/js/wcdependencies.js +10 -0
  22. data/lib/repla/dependencies/lib/controller.rb +34 -0
  23. data/lib/repla/dependencies/lib/model.rb +10 -0
  24. data/lib/repla/dependencies/lib/tester.rb +19 -0
  25. data/lib/repla/dependencies/lib/view.rb +19 -0
  26. data/lib/repla/dependencies/views/view.html.erb +25 -0
  27. data/lib/repla/dependencies.rb +34 -0
  28. data/lib/repla/extension_constants.rb +1 -0
  29. data/lib/repla/lib/constants.rb +11 -0
  30. data/lib/repla/lib/controller.rb +5 -0
  31. data/lib/repla/lib/module.rb +133 -0
  32. data/lib/repla/lib/view/erb.rb +17 -0
  33. data/lib/repla/lib/view/javascript.rb +45 -0
  34. data/lib/repla/lib/view/resources.rb +42 -0
  35. data/lib/repla/lib/view.rb +28 -0
  36. data/lib/repla/lib/window.rb +75 -0
  37. data/lib/repla/logger/test/Rakefile +20 -0
  38. data/lib/repla/logger/test/js/test_view_helper.js +3 -0
  39. data/lib/repla/logger/test/lib/test_constants.rb +8 -0
  40. data/lib/repla/logger/test/lib/test_view_helper.rb +27 -0
  41. data/lib/repla/logger/test/run_tests.sh +3 -0
  42. data/lib/repla/logger/test/tc_logger.rb +173 -0
  43. data/lib/repla/logger.rb +69 -0
  44. data/lib/repla/repl/css/style.css +20 -0
  45. data/lib/repla/repl/js/wcrepl.js +17 -0
  46. data/lib/repla/repl/lib/input_controller.rb +18 -0
  47. data/lib/repla/repl/lib/output_controller.rb +19 -0
  48. data/lib/repla/repl/lib/view.rb +68 -0
  49. data/lib/repla/repl/view/view.html.erb +12 -0
  50. data/lib/repla/repl.rb +49 -0
  51. data/lib/repla.rb +9 -0
  52. metadata +92 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 1b80e1592a3dc429896f001bda2bddff25b7e3d8
4
+ data.tar.gz: fdc62f4bd40eee40bd310317e0a69c94aed98c57
5
+ SHA512:
6
+ metadata.gz: cc65843d273f506f347478d436fbc9ccc12e07f49621be18dba68f2f3428907c349c140e83b2c20c5d6ad70bdb0e3d2e46b727a48ee5b7ebe3130a1e2027144e
7
+ data.tar.gz: 29484bdba1f0240d71ff699a530a938756f2911473472d9d5efe102da1657d46e3f128b6a77573ced49fce80949932eb18fa1b09b71c2beb5942e4ef440ac7ec
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
@@ -0,0 +1,15 @@
1
+ body, h5 {
2
+ font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
3
+ font-size: 13px;
4
+ }
5
+ h5 {
6
+ font-weight: normal;
7
+ color: red;
8
+ }
9
+ blockquote {
10
+ margin-left: 2em;
11
+ }
12
+ code {
13
+ background-color: #DBE2EC;
14
+ font-family: "Menlo", monospace;
15
+ }
@@ -0,0 +1,10 @@
1
+ function addMissingDependency(name, type, installationInstructions) {
2
+ var source = $("#dependency-template").html();
3
+ var template = Handlebars.compile(source);
4
+ var data = {
5
+ name: name,
6
+ type: type,
7
+ installationInstructions: installationInstructions
8
+ };
9
+ $(template(data)).appendTo("body");
10
+ }
@@ -0,0 +1,34 @@
1
+ require_relative 'tester'
2
+ require_relative 'model'
3
+ require_relative 'view'
4
+
5
+ module Repla::Dependencies
6
+
7
+ class Controller < Repla::Controller
8
+
9
+ def initialize
10
+ @view = View.new
11
+ end
12
+
13
+ def missing_dependency(dependency)
14
+ name = dependency.name
15
+ type = self.class.string_for_type(dependency.type)
16
+ options = dependency.options
17
+ if options.has_key?(:installation_instructions)
18
+ installation_instructions = options[:installation_instructions]
19
+ end
20
+ @view.add_missing_dependency(name, type, installation_instructions)
21
+ end
22
+
23
+ private
24
+
25
+ def self.string_for_type(type)
26
+ case type
27
+ when :shell_command
28
+ return "shell command"
29
+ end
30
+ nil
31
+ end
32
+
33
+ end
34
+ end
@@ -0,0 +1,10 @@
1
+ module Repla::Dependencies
2
+ class Dependency
3
+ attr_reader :name, :type, :options
4
+ def initialize(name, type, options = {})
5
+ @name = name
6
+ @type = type
7
+ @options = options
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,19 @@
1
+ module Repla::Dependencies
2
+ module Tester
3
+ def self.check(name, type)
4
+ case type
5
+ when :shell_command
6
+ return check_shell_command(name)
7
+ end
8
+ end
9
+
10
+ private
11
+
12
+ require 'shellwords'
13
+ def self.check_shell_command(name)
14
+ command = "type -a #{Shellwords.escape(name)} > /dev/null 2>&1"
15
+ system(command)
16
+ end
17
+
18
+ end
19
+ end
@@ -0,0 +1,19 @@
1
+ module Repla::Dependencies
2
+
3
+ class View < Repla::View
4
+ BASE_DIRECTORY = File.join(File.dirname(__FILE__), '..')
5
+ VIEWS_DIRECTORY = File.join(BASE_DIRECTORY, "views")
6
+ VIEW_TEMPLATE = File.join(VIEWS_DIRECTORY, 'view.html.erb')
7
+
8
+ def initialize
9
+ super
10
+ self.base_url_path = File.expand_path(BASE_DIRECTORY)
11
+ load_erb_from_path(VIEW_TEMPLATE)
12
+ end
13
+
14
+ ADD_MISSING_DEPENDENCY_FUNCTION = "addMissingDependency"
15
+ def add_missing_dependency(name, type, installation_instructions = nil)
16
+ do_javascript_function(ADD_MISSING_DEPENDENCY_FUNCTION, [name, type, installation_instructions])
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,25 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <title><%= title %></title>
6
+ <%= shared_stylesheet_link_tag "raster" %>
7
+ <link rel="stylesheet" href="css/style.css" />
8
+ <script id="dependency-template" type="text/x-handlebars-template">
9
+ <section>
10
+ <header>
11
+ <h5>Dependency <span class="type">{{type}}</span> <code class="name">{{name}}</code> not found.</h5>
12
+ </header>
13
+ {{#if installationInstructions}}
14
+ <p><blockquote class="installation">To install <code>{{name}}</code>: {{{installationInstructions}}}</blockquote></p>
15
+ {{/if}}
16
+ </section>
17
+ </script>
18
+ <%= shared_javascript_include_tag "handlebars" %>
19
+ <%= shared_javascript_include_tag "zepto" %>
20
+ <script type="text/javascript" src="js/wcdependencies.js"></script>
21
+ </head>
22
+ <body>
23
+
24
+ </body>
25
+ </html>
@@ -0,0 +1,34 @@
1
+ require_relative 'extension_constants'
2
+ require REPLA_FILE
3
+
4
+ module Repla::Dependencies
5
+ class Checker
6
+ require_relative 'dependencies/lib/model'
7
+ require_relative 'dependencies/lib/controller'
8
+
9
+ def check_dependencies(dependencies)
10
+ passed = true
11
+ dependencies.each { |dependency|
12
+ dependency_passed = check(dependency)
13
+ passed = false unless dependency_passed
14
+ }
15
+ passed
16
+ end
17
+
18
+ def check(dependency)
19
+ name = dependency.name
20
+ type = dependency.type
21
+ passed = Tester::check(name, type)
22
+ controller.missing_dependency(dependency) unless passed
23
+ passed
24
+ end
25
+
26
+ private
27
+
28
+ def controller
29
+ @controller ||= Controller.new
30
+ end
31
+
32
+ end
33
+
34
+ end
@@ -0,0 +1 @@
1
+ REPLA_FILE = File.join(File.dirname(__FILE__), "../repla")
@@ -0,0 +1,11 @@
1
+ module Repla
2
+ # Keys
3
+ PLUGIN_NAME_KEY = 'WC_PLUGIN_NAME'
4
+ SPLIT_ID_KEY = 'WC_SPLIT_ID'
5
+ WINDOW_ID_KEY = 'WC_WINDOW_ID'
6
+ SHARED_RESOURCES_PATH_KEY = 'WC_SHARED_RESOURCES_PATH'
7
+ SHARED_RESOURCES_URL_KEY = 'WC_SHARED_RESOURCES_URL'
8
+
9
+ # Directories
10
+ APPLESCRIPT_DIRECTORY = File.join(File.dirname(__FILE__), "..", "..", "applescript")
11
+ end
@@ -0,0 +1,5 @@
1
+ module Repla
2
+ class Controller
3
+ attr_reader :view
4
+ end
5
+ end
@@ -0,0 +1,133 @@
1
+ require 'Shellwords'
2
+ module Repla
3
+ LOAD_PLUGIN_SCRIPT = File.join(APPLESCRIPT_DIRECTORY, "load_plugin.scpt")
4
+ def self.load_plugin(path)
5
+ self.run_applescript(LOAD_PLUGIN_SCRIPT, [path])
6
+ end
7
+
8
+ EXISTS_SCRIPT = File.join(APPLESCRIPT_DIRECTORY, "exists.scpt")
9
+ def self.application_exists
10
+ result = self.run_applescript(EXISTS_SCRIPT)
11
+ result == "true" ? true : false
12
+ end
13
+
14
+ RUN_PLUGIN_SCRIPT = File.join(APPLESCRIPT_DIRECTORY, "run_plugin.scpt")
15
+ def self.run_plugin(name, directory = nil, arguments = nil)
16
+ parameters = [name]
17
+ parameters.push(directory) unless directory.nil?
18
+ parameters += arguments unless arguments.nil?
19
+ self.run_applescript(RUN_PLUGIN_SCRIPT, parameters)
20
+ end
21
+
22
+ RUN_PLUGIN_IN_SPLIT_SCRIPT = File.join(APPLESCRIPT_DIRECTORY, "run_plugin_in_split.scpt")
23
+ def self.run_plugin_in_split(name, window_id, split_id)
24
+ parameters = [name, window_id, split_id]
25
+ self.run_applescript(RUN_PLUGIN_IN_SPLIT_SCRIPT, parameters)
26
+ end
27
+
28
+ WINDOW_ID_FOR_PLUGIN_SCRIPT = File.join(APPLESCRIPT_DIRECTORY, "window_id_for_plugin.scpt")
29
+ def self.window_id_for_plugin(name)
30
+ self.run_applescript(WINDOW_ID_FOR_PLUGIN_SCRIPT, [name])
31
+ end
32
+
33
+ SPLIT_ID_IN_WINDOW_SCRIPT = File.join(APPLESCRIPT_DIRECTORY, "split_id_in_window.scpt")
34
+ def self.split_id_in_window(window_id, pluginName = nil)
35
+ arguments = [window_id]
36
+ arguments.push(pluginName) unless pluginName.nil?
37
+ self.run_applescript(SPLIT_ID_IN_WINDOW_SCRIPT, arguments)
38
+ end
39
+
40
+ SPLIT_ID_IN_WINDOW_LAST_SCRIPT = File.join(APPLESCRIPT_DIRECTORY, "split_id_in_window_last.scpt")
41
+ def self.split_id_in_window_last(window_id)
42
+ arguments = [window_id]
43
+ self.run_applescript(SPLIT_ID_IN_WINDOW_LAST_SCRIPT, arguments)
44
+ end
45
+
46
+ CREATE_WINDOW_SCRIPT = File.join(APPLESCRIPT_DIRECTORY, "create_window.scpt")
47
+ def self.create_window
48
+ self.run_applescript(CREATE_WINDOW_SCRIPT)
49
+ end
50
+
51
+ # Shared Resources
52
+
53
+ RESOURCE_PATH_FOR_PLUGIN_SCRIPT = File.join(APPLESCRIPT_DIRECTORY, "resource_path_for_plugin.scpt")
54
+ def self.resource_path_for_plugin(name)
55
+ self.run_applescript(RESOURCE_PATH_FOR_PLUGIN_SCRIPT, [name])
56
+ end
57
+
58
+ # Shared Resource Path
59
+
60
+ SHARED_RESOURCES_PLUGIN_NAME = "Shared Resources"
61
+ SHARED_TEST_RESOURCES_PLUGIN_NAME = "Shared Test Resources"
62
+ def self.shared_resources_path
63
+ resource_path_for_plugin(SHARED_RESOURCES_PLUGIN_NAME)
64
+ end
65
+ def self.shared_test_resources_path
66
+ resource_path_for_plugin(SHARED_TEST_RESOURCES_PLUGIN_NAME)
67
+ end
68
+
69
+ def self.shared_resource(resource)
70
+ File.join(self.shared_resources_path, resource)
71
+ end
72
+ def self.shared_test_resource(resource)
73
+ File.join(self.shared_test_resources_path, resource)
74
+ end
75
+
76
+ # Shared Resource URL
77
+
78
+ RESOURCE_URL_FOR_PLUGIN_SCRIPT = File.join(APPLESCRIPT_DIRECTORY, "resource_url_for_plugin.scpt")
79
+ def self.resource_url_for_plugin(name)
80
+ self.run_applescript(RESOURCE_URL_FOR_PLUGIN_SCRIPT, [name])
81
+ end
82
+ def self.shared_resources_url
83
+ resource_url_for_plugin(SHARED_RESOURCES_PLUGIN_NAME)
84
+ end
85
+
86
+ private
87
+
88
+ def self.run_applescript(script, arguments = nil)
89
+ command = "osascript #{script.shell_escape}"
90
+
91
+ if arguments
92
+ command += " " + arguments.compact.map(&:to_s).map(&:shell_escape).join(' ')
93
+ end
94
+
95
+ result = `#{command}`
96
+
97
+ result.chomp!
98
+
99
+ return nil if result.empty?
100
+ return result.to_i if result.is_integer?
101
+ return result.to_f if result.is_float?
102
+
103
+ result
104
+ end
105
+
106
+ class ::String
107
+ def is_float?
108
+ true if Float(self) rescue false
109
+ end
110
+
111
+ def is_integer?
112
+ self.to_i.to_s == self
113
+ end
114
+
115
+ def shell_escape
116
+ Shellwords.escape(self)
117
+ end
118
+
119
+ def shell_escape!
120
+ replace(shell_escape)
121
+ end
122
+
123
+ end
124
+
125
+ class ::Float
126
+ alias_method :javascript_argument, :to_s
127
+ end
128
+
129
+ class ::Integer
130
+ alias_method :javascript_argument, :to_s
131
+ end
132
+
133
+ end
@@ -0,0 +1,17 @@
1
+ module Repla
2
+ class View < Window
3
+
4
+ require 'erb'
5
+
6
+ def load_erb_from_path(path)
7
+ erb = File.new(path).read
8
+ load_erb(erb)
9
+ end
10
+
11
+ def load_erb(erb)
12
+ template = ERB.new(erb, nil, '-')
13
+ html = template.result(binding)
14
+ load_html(html)
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,45 @@
1
+ module Repla
2
+ class View < Window
3
+
4
+ def do_javascript_function(function, arguments = nil)
5
+ javascript = self.class.javascript_function(function, arguments)
6
+ do_javascript(javascript)
7
+ end
8
+
9
+ def self.javascript_function(function, arguments = nil)
10
+ function = function.dup
11
+ function << '('
12
+
13
+ if arguments
14
+ arguments.each { |argument|
15
+ if argument
16
+ function << argument.javascript_argument
17
+ else
18
+ function << "null"
19
+ end
20
+ function << ', '
21
+ }
22
+ function = function[0...-2]
23
+ end
24
+
25
+ function << ');'
26
+ end
27
+
28
+ private
29
+
30
+ class ::String
31
+ def javascript_argument
32
+ "'#{self.javascript_escape}'"
33
+ end
34
+
35
+ def javascript_escape
36
+ self.gsub('\\', "\\\\\\\\").gsub("\n", "\\\\n").gsub("'", "\\\\'")
37
+ end
38
+
39
+ def javascript_escape!
40
+ replace(self.javascript_escape)
41
+ end
42
+ end
43
+
44
+ end
45
+ end
@@ -0,0 +1,42 @@
1
+ module Repla
2
+ class View < Window
3
+ require 'open-uri'
4
+
5
+ require_relative "../constants"
6
+ require_relative "../module"
7
+
8
+ attr_accessor :title
9
+
10
+ CSS_EXTENSION = ".css"
11
+ CSS_PATH_COMPONENT = "css/"
12
+ def shared_stylesheet_link_tag(resource)
13
+ uri = URI.join(shared_resources_url, CSS_PATH_COMPONENT, resource + CSS_EXTENSION)
14
+ stylesheet_link_tag(uri.to_s)
15
+ end
16
+
17
+ def stylesheet_link_tag(url)
18
+ "<link rel=\"stylesheet\" href=\"#{url}\" />"
19
+ end
20
+
21
+ JS_EXTENSION = ".js"
22
+ JS_PATH_COMPONENT = "js/"
23
+ def shared_javascript_include_tag(resource)
24
+ uri = URI.join(shared_resources_url, JS_PATH_COMPONENT, resource + JS_EXTENSION)
25
+ javascript_include_tag(uri.to_s)
26
+ end
27
+
28
+ def javascript_include_tag(url)
29
+ "<script type=\"text/javascript\" src=\"#{url}\"></script>"
30
+ end
31
+
32
+ def title
33
+ @title ||= ENV.has_key?(PLUGIN_NAME_KEY) ? ENV[PLUGIN_NAME_KEY] : nil
34
+ end
35
+
36
+ private
37
+
38
+ def shared_resources_url
39
+ @shared_resources_url || ENV.has_key?(SHARED_RESOURCES_URL_KEY) ? ENV[SHARED_RESOURCES_URL_KEY] : Repla::shared_resources_url
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,28 @@
1
+ require_relative "window"
2
+ require_relative "view/javascript"
3
+ require_relative "view/erb"
4
+ require_relative "view/resources"
5
+
6
+ module Repla
7
+ class View < Window
8
+
9
+ # Properties
10
+ def initialize(window_id = nil, view_id = nil)
11
+ super(window_id)
12
+ @view_id = view_id
13
+ end
14
+
15
+ def view_id
16
+ @view_id ||= ENV.has_key?(SPLIT_ID_KEY) ? ENV[SPLIT_ID_KEY] : split_id
17
+ end
18
+
19
+ private
20
+
21
+ # Web
22
+
23
+ def arguments_with_target(arguments)
24
+ super(arguments).push(view_id)
25
+ end
26
+
27
+ end
28
+ end
@@ -0,0 +1,75 @@
1
+ module Repla
2
+ class Window
3
+ require_relative "constants"
4
+
5
+ attr_writer :base_url
6
+
7
+ def initialize(window_id = nil)
8
+ @window_id = window_id
9
+ end
10
+
11
+ # Properties
12
+
13
+ def base_url_path=(value)
14
+ @base_url = "file://" + value
15
+ end
16
+
17
+ def window_id
18
+ @window_id ||= ENV.has_key?(WINDOW_ID_KEY) ? ENV[WINDOW_ID_KEY] : Repla::create_window
19
+ end
20
+
21
+ # Web
22
+
23
+ LOADHTML_SCRIPT = File.join(APPLESCRIPT_DIRECTORY, "load_html.scpt")
24
+ LOADHTMLWITHBASEURL_SCRIPT = File.join(APPLESCRIPT_DIRECTORY, "load_html_with_base_url.scpt")
25
+ def load_html(html)
26
+ arguments = [html]
27
+
28
+ script = LOADHTML_SCRIPT
29
+
30
+ if @base_url
31
+ script = LOADHTMLWITHBASEURL_SCRIPT
32
+ arguments.push(@base_url)
33
+ end
34
+
35
+ run_script(script, arguments)
36
+ end
37
+
38
+ DOJAVASCRIPT_SCRIPT = File.join(APPLESCRIPT_DIRECTORY, "do_javascript.scpt")
39
+ def do_javascript(javascript)
40
+ run_script(DOJAVASCRIPT_SCRIPT, [javascript])
41
+ end
42
+
43
+ READ_FROM_STANDARD_INPUT_SCRIPT = File.join(APPLESCRIPT_DIRECTORY, "read_from_standard_input.scpt")
44
+ def read_from_standard_input(text)
45
+ run_script(READ_FROM_STANDARD_INPUT_SCRIPT, [text])
46
+ end
47
+
48
+ # Window
49
+
50
+ CLOSEWINDOW_SCRIPT = File.join(APPLESCRIPT_DIRECTORY, "close_window.scpt")
51
+ def close
52
+ Repla::run_applescript(CLOSEWINDOW_SCRIPT, [window_id])
53
+ end
54
+
55
+ def split_id
56
+ Repla::split_id_in_window(window_id)
57
+ end
58
+
59
+ def split_id_last
60
+ Repla::split_id_in_window_last(window_id)
61
+ end
62
+
63
+ private
64
+
65
+ def run_script(script, arguments = [])
66
+ arguments = arguments_with_target(arguments)
67
+ Repla::run_applescript(script, arguments)
68
+ end
69
+
70
+ def arguments_with_target(arguments)
71
+ arguments.push(window_id)
72
+ end
73
+
74
+ end
75
+ end
@@ -0,0 +1,20 @@
1
+ require 'shellwords'
2
+ require 'repla'
3
+ require Repla::shared_test_resource("ruby/test_constants")
4
+ require Repla::Tests::TEST_HELPER_FILE
5
+
6
+ task :default => ['logger:tests']
7
+
8
+ namespace :logger do
9
+
10
+ task :tests => [:clean_up]
11
+
12
+ task :test_logger do
13
+ logger_tests_file = File.join(File.dirname(__FILE__), "tc_logger.rb")
14
+ ruby Shellwords.escape(logger_tests_file)
15
+ end
16
+
17
+ task :clean_up => [:test_logger] do
18
+ Repla::Tests::Helper::quit
19
+ end
20
+ end
@@ -0,0 +1,3 @@
1
+ function innerTextOfBodyChildAtIndex(index) {
2
+ return document.body.children[index].innerText;
3
+ }
@@ -0,0 +1,8 @@
1
+ require_relative "../../../extension_constants"
2
+
3
+ TEST_CLASS_JAVASCRIPT = "document.body.lastChild.classList[0]"
4
+ TEST_MESSAGE_JAVASCRIPT = "document.body.lastChild.innerText"
5
+ TEST_MESSAGE_COUNT_JAVASCRIPT = "document.body.children.length"
6
+
7
+ TEST_JAVASCRIPT_DIRECTORY = File.join(File.dirname(__FILE__), "..", "js")
8
+ TEST_JAVASCRIPT_FILE = File.join(TEST_JAVASCRIPT_DIRECTORY, "test_view_helper.js")
@@ -0,0 +1,27 @@
1
+ require_relative 'test_constants'
2
+
3
+ class TestViewHelper
4
+
5
+ def initialize(window_id, view_id)
6
+ @view = Repla::View.new(window_id, view_id)
7
+ javascript = File.read(TEST_JAVASCRIPT_FILE)
8
+ @view.do_javascript(javascript)
9
+ end
10
+
11
+ def log_message_at_index(index)
12
+ @view.do_javascript_function('innerTextOfBodyChildAtIndex', [index])
13
+ end
14
+
15
+ def number_of_log_messages
16
+ @view.do_javascript(TEST_MESSAGE_COUNT_JAVASCRIPT)
17
+ end
18
+
19
+ def last_log_message
20
+ @view.do_javascript(TEST_MESSAGE_JAVASCRIPT)
21
+ end
22
+
23
+ def last_log_class
24
+ @view.do_javascript(TEST_CLASS_JAVASCRIPT)
25
+ end
26
+
27
+ end
@@ -0,0 +1,3 @@
1
+ #!/bin/sh
2
+
3
+ rake
@@ -0,0 +1,173 @@
1
+ #!/System/Library/Frameworks/Ruby.framework/Versions/2.3/usr/bin/ruby
2
+
3
+ require "test/unit"
4
+
5
+ require_relative "lib/test_constants"
6
+ require REPLA_FILE
7
+ require Repla::shared_test_resource("ruby/test_constants")
8
+ require Repla::Tests::TEST_HELPER_FILE
9
+
10
+ require_relative "lib/test_view_helper"
11
+ require_relative "../../logger"
12
+
13
+
14
+ class TestConstants < Test::Unit::TestCase
15
+
16
+ def test_constants
17
+ message_prefix = Repla::Logger::MESSAGE_PREFIX
18
+ assert_not_nil(message_prefix, "The message prefix should not be nil.")
19
+ error_prefix = Repla::Logger::ERROR_PREFIX
20
+ assert_not_nil(message_prefix, "The error prefix should not be nil.")
21
+ end
22
+
23
+ end
24
+
25
+
26
+ class TestUnintializedLogger < Test::Unit::TestCase
27
+
28
+ def teardown
29
+ Repla::Tests::Helper::quit
30
+ assert(!Repla::Tests::Helper::is_running, "The application should not be running.")
31
+ end
32
+
33
+ def test_uninitialized_logger
34
+ logger = Repla::Logger.new
35
+
36
+ # Test Message
37
+ message = "Testing log message"
38
+ logger.info(message)
39
+ sleep Repla::Tests::TEST_PAUSE_TIME # Pause for output to be processed
40
+
41
+ # Make sure the log messages before accessing the logger's `view_id` and `window_id` because those run the logger.
42
+ # This test should test logging a message and running the logger itself simultaneously.
43
+ # This is why the `TestViewHelper` is intialized after logging the message.
44
+ test_view_helper = TestViewHelper.new(logger.window_id, logger.view_id)
45
+
46
+ test_message = test_view_helper.last_log_message
47
+ assert_equal(message, test_message, "The messages should match")
48
+ test_class = test_view_helper.last_log_class
49
+ assert_equal("message", test_class, "The classes should match")
50
+
51
+ end
52
+
53
+ end
54
+
55
+
56
+ class TestLogger < Test::Unit::TestCase
57
+
58
+ def setup
59
+ @logger = Repla::Logger.new
60
+ @logger.show
61
+ @test_view_helper = TestViewHelper.new(@logger.window_id, @logger.view_id)
62
+ end
63
+
64
+ def teardown
65
+ Repla::Tests::Helper::quit
66
+ assert(!Repla::Tests::Helper::is_running, "The application should not be running.")
67
+ end
68
+
69
+ def test_logger
70
+ test_count = 0
71
+
72
+ # Test Error
73
+ message = "Testing log error"
74
+ @logger.error(message)
75
+ sleep Repla::Tests::TEST_PAUSE_TIME # Pause for output to be processed
76
+ test_message = @test_view_helper.last_log_message
77
+ assert_equal(message, test_message, "The messages should match")
78
+ test_class = @test_view_helper.last_log_class
79
+ assert_equal("error", test_class, "The classes should match")
80
+ result_count = @test_view_helper.number_of_log_messages
81
+ test_count += 1
82
+ assert_equal(test_count, result_count, "The number of log messages should match")
83
+
84
+ # Test Message
85
+ message = "Testing log message"
86
+ @logger.info(message)
87
+ sleep Repla::Tests::TEST_PAUSE_TIME # Pause for output to be processed
88
+ test_message = @test_view_helper.last_log_message
89
+ assert_equal(message, test_message, "The messages should match")
90
+ test_class = @test_view_helper.last_log_class
91
+ assert_equal("message", test_class, "The classes should match")
92
+ result_count = @test_view_helper.number_of_log_messages
93
+ test_count += 1
94
+ assert_equal(test_count, result_count, "The number of log messages should match")
95
+
96
+ # Test Only Error Prefix
97
+ message = Repla::Logger::ERROR_PREFIX.rstrip # Note the trailing whitespace is trimmed
98
+ @logger.info(message)
99
+ sleep Repla::Tests::TEST_PAUSE_TIME # Pause for output to be processed
100
+ test_message = @test_view_helper.last_log_message
101
+ assert_equal(message, test_message, "The messages should match")
102
+ test_class = @test_view_helper.last_log_class
103
+ assert_equal("message", test_class, "The classes should match")
104
+ result_count = @test_view_helper.number_of_log_messages
105
+ test_count += 1
106
+ assert_equal(test_count, result_count, "The number of log messages should match")
107
+
108
+ # Test Only Message Prefix
109
+ message = Repla::Logger::MESSAGE_PREFIX.rstrip # Note the trailing whitespace is trimmed
110
+ @logger.info(message)
111
+ sleep Repla::Tests::TEST_PAUSE_TIME # Pause for output to be processed
112
+ test_message = @test_view_helper.last_log_message
113
+ assert_equal(message, test_message, "The messages should match")
114
+ test_class = @test_view_helper.last_log_class
115
+ assert_equal("message", test_class, "The classes should match")
116
+ result_count = @test_view_helper.number_of_log_messages
117
+ test_count += 1
118
+ assert_equal(test_count, result_count, "The number of log messages should match")
119
+
120
+ # Test Blank Spaces
121
+ @logger.info(" \t")
122
+ sleep Repla::Tests::TEST_PAUSE_TIME # Pause for output to be processed
123
+ test_message = @test_view_helper.last_log_message()
124
+ assert_equal(message, test_message, "The messages should match")
125
+ test_class = @test_view_helper.last_log_class()
126
+ assert_equal("message", test_class, "The classes should match")
127
+
128
+ # Test Empty String
129
+ @logger.info("")
130
+ sleep Repla::Tests::TEST_PAUSE_TIME # Pause for output to be processed
131
+ test_message = @test_view_helper.last_log_message()
132
+ assert_equal(message, test_message, "The messages should match")
133
+ test_class = @test_view_helper.last_log_class()
134
+ assert_equal("message", test_class, "The classes should match")
135
+
136
+ # TODO: Also add the following tests the `Log.wcplugin`
137
+
138
+ # Test Whitespace
139
+ # White space to the left should be preserved, whitespace to the right should be removed
140
+ # This test fails because retrieving the `innerText` doesn't preserve whitepace.
141
+
142
+ # message = "\t Testing log message"
143
+ # @logger.info(message + "\t ")
144
+ # sleep Repla::Tests::TEST_PAUSE_TIME # Pause for output to be processed
145
+ # test_message = @test_view_helper.last_log_message
146
+ # assert_equal(message, test_message, "The messages should match")
147
+ # test_class = @test_view_helper.last_log_class
148
+ # assert_equal("message", test_class, "The classes should match")
149
+ # result_count = @test_view_helper.number_of_log_messages
150
+ # test_count += 1
151
+ # assert_equal(test_count, result_count, "The number of log messages should match")
152
+ end
153
+
154
+ def test_long_input
155
+ message = %q(
156
+ Line 1
157
+
158
+ Line 2
159
+ Line 3
160
+ )
161
+ @logger.info(message)
162
+ sleep Repla::Tests::TEST_PAUSE_TIME * 2 # Pause for output to be processed
163
+ result_count = @test_view_helper.number_of_log_messages
164
+ assert_equal(result_count, 3, "The number of log messages should match")
165
+
166
+ (1..3).each { |i|
167
+ result = @test_view_helper.log_message_at_index(i - 1)
168
+ test_result = "Line #{i}"
169
+ assert_equal(result, test_result, "The number of log messages should match")
170
+ }
171
+ end
172
+
173
+ end
@@ -0,0 +1,69 @@
1
+ require_relative 'extension_constants'
2
+ require REPLA_FILE
3
+
4
+ module Repla
5
+
6
+ class Logger
7
+ MESSAGE_PREFIX = 'MESSAGE '
8
+ ERROR_PREFIX = 'ERROR '
9
+ LOG_PLUGIN_NAME = 'Log'
10
+
11
+ # Toggle
12
+
13
+ SHOW_LOG_SCRIPT = File.join(APPLESCRIPT_DIRECTORY, "show_log.scpt")
14
+ def show
15
+ Repla::run_applescript(SHOW_LOG_SCRIPT, [window_id])
16
+ end
17
+
18
+ HIDE_LOG_SCRIPT = File.join(APPLESCRIPT_DIRECTORY, "hide_log.scpt")
19
+ def hide
20
+ Repla::run_applescript(HIDE_LOG_SCRIPT, [window_id])
21
+ end
22
+
23
+ TOGGLE_LOG_SCRIPT = File.join(APPLESCRIPT_DIRECTORY, "toggle_log.scpt")
24
+ def toggle
25
+ Repla::run_applescript(TOGGLE_LOG_SCRIPT, [window_id])
26
+ end
27
+
28
+ # Messages
29
+
30
+ def info(message)
31
+ message = message.dup
32
+ message.gsub!(%r{^}, MESSAGE_PREFIX) # Prefix all lines
33
+ # Strip trailing white space
34
+ # Add a line break
35
+ log_message(message)
36
+ end
37
+
38
+ def error(message)
39
+ message = message.dup
40
+ message.gsub!(%r{^}, ERROR_PREFIX)
41
+ log_message(message)
42
+ end
43
+
44
+ # Properties
45
+
46
+ def window_id
47
+ @window_id ||= ENV.has_key?(WINDOW_ID_KEY) ? ENV[WINDOW_ID_KEY] : Repla::create_window
48
+ end
49
+
50
+ def view_id
51
+ @view_id ||= Repla::split_id_in_window(window_id, LOG_PLUGIN_NAME)
52
+ return @view_id unless @view_id.nil?
53
+
54
+ @view_id = Repla::split_id_in_window_last(window_id)
55
+ Repla::run_plugin_in_split(LOG_PLUGIN_NAME, window_id, @view_id)
56
+ @view_id
57
+ end
58
+
59
+ private
60
+
61
+ READ_FROM_STANDARD_INPUT_SCRIPT = File.join(APPLESCRIPT_DIRECTORY, "read_from_standard_input.scpt")
62
+ def log_message(message)
63
+ message.rstrip!
64
+ message += "\n"
65
+ Repla::run_applescript(READ_FROM_STANDARD_INPUT_SCRIPT, [message, window_id, view_id])
66
+ end
67
+
68
+ end
69
+ end
@@ -0,0 +1,20 @@
1
+ body {
2
+ font-family: "Menlo", monospace;
3
+ font-size: 13px;
4
+ }
5
+ li {
6
+ list-style: none;
7
+ white-space: pre-wrap;
8
+ }
9
+ pre {
10
+ position: relative;
11
+ padding-left: 18px;
12
+ }
13
+ pre.output code:before
14
+ {
15
+ content: '>';
16
+ font-weight: bold;
17
+ left: 7px;
18
+ position: absolute;
19
+ opacity: 0.5;
20
+ }
@@ -0,0 +1,17 @@
1
+ var WcREPL = {
2
+ addCode: function(code, source) {
3
+ var template = Handlebars.compile(source);
4
+ var data = {
5
+ code: code
6
+ };
7
+ return $(template(data)).appendTo("body");
8
+ },
9
+ addInput: function(code) {
10
+ var source = $("#input-template").html();
11
+ this.addCode(code, source);
12
+ },
13
+ addOutput: function(code) {
14
+ var source = $("#output-template").html();
15
+ this.addCode(code, source);
16
+ }
17
+ }
@@ -0,0 +1,18 @@
1
+ module Repla::REPL
2
+ class InputController < Repla::Controller
3
+
4
+ attr_accessor :view
5
+ def initialize(view)
6
+ @view = view
7
+ end
8
+
9
+ def parse_input(input)
10
+ input = input.dup
11
+ input.chomp!
12
+ if !input.strip.empty? # Ignore empty lines
13
+ @view.add_input(input)
14
+ end
15
+ end
16
+
17
+ end
18
+ end
@@ -0,0 +1,19 @@
1
+ module Repla::REPL
2
+ class OutputController < Repla::Controller
3
+
4
+ attr_accessor :view
5
+ def initialize(view)
6
+ @view = view
7
+ end
8
+
9
+ def parse_output(output)
10
+ output = output.dup
11
+ output.gsub!(/\x1b[^m]*m/, "") # Remove escape sequences
12
+ output.chomp!
13
+ if !output.strip.empty? # Ignore empty lines
14
+ @view.add_output(output)
15
+ end
16
+ end
17
+
18
+ end
19
+ end
@@ -0,0 +1,68 @@
1
+ module Repla::REPL
2
+ class View < Repla::View
3
+
4
+ BASE_DIRECTORY = File.join(File.dirname(__FILE__), "..")
5
+ VIEWS_DIRECTORY = File.join(BASE_DIRECTORY, "view")
6
+ VIEW_TEMPLATE = File.join(VIEWS_DIRECTORY, 'view.html.erb')
7
+ def initialize
8
+ super
9
+ self.base_url_path = File.expand_path(BASE_DIRECTORY)
10
+ load_erb_from_path(VIEW_TEMPLATE)
11
+ end
12
+
13
+ ADD_INPUT_JAVASCRIPT_FUNCTION = "WcREPL.addInput"
14
+ def add_input(input)
15
+ do_javascript_function(ADD_INPUT_JAVASCRIPT_FUNCTION, [input])
16
+ end
17
+
18
+ ADD_OUTPUT_JAVASCRIPT_FUNCTION = "WcREPL.addOutput"
19
+ def add_output(output)
20
+ do_javascript_function(ADD_OUTPUT_JAVASCRIPT_FUNCTION, [output])
21
+ end
22
+
23
+ # Helpers to allow easy loading of REPL resource even from another base URL
24
+
25
+ def repl_header_tags
26
+ %Q[
27
+ #{repl_stylesheet_link_tag}
28
+ #{repl_handlebars_template_tags}
29
+ #{shared_javascript_include_tag("handlebars")}
30
+ #{shared_javascript_include_tag("zepto")}
31
+ #{repl_javascript_include_tag}
32
+ ]
33
+ end
34
+
35
+ def repl_handlebars_template_tags
36
+ %Q[
37
+ <script id="output-template" type="text/x-handlebars-template">
38
+ <pre class="output"><code>{{code}}</code></pre>
39
+ </script>
40
+ <script id="input-template" type="text/x-handlebars-template">
41
+ <pre><code>{{code}}</code></pre>
42
+ </script>]
43
+ end
44
+
45
+ def repl_stylesheet_link_tag
46
+ path = File.join(repl_base_resource_path, "css/style.css")
47
+ url = repl_url_for_path(path)
48
+ stylesheet_link_tag(url)
49
+ end
50
+
51
+ def repl_javascript_include_tag
52
+ path = File.join(repl_base_resource_path, "js/wcrepl.js")
53
+ url = repl_url_for_path(path)
54
+ javascript_include_tag(url)
55
+ end
56
+
57
+ require 'open-uri'
58
+ def repl_url_for_path(path)
59
+ uri = URI::encode(path)
60
+ "file://" + uri
61
+ end
62
+
63
+ def repl_base_resource_path
64
+ File.expand_path(File.join(File.dirname(__FILE__), "../"))
65
+ end
66
+
67
+ end
68
+ end
@@ -0,0 +1,12 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <title><%= title %></title>
6
+ <%= shared_stylesheet_link_tag "raster" %>
7
+ <%= repl_header_tags %>
8
+ </head>
9
+ <body>
10
+
11
+ </body>
12
+ </html>
data/lib/repla/repl.rb ADDED
@@ -0,0 +1,49 @@
1
+ require_relative 'extension_constants'
2
+ require REPLA_FILE
3
+
4
+ module Repla::REPL
5
+ require_relative "repl/lib/input_controller"
6
+ require_relative "repl/lib/output_controller"
7
+ require_relative "repl/lib/view"
8
+
9
+ class Wrapper
10
+ require 'pty'
11
+
12
+ def initialize(command)
13
+
14
+ PTY.spawn(command) do |output, input, pid|
15
+ Thread.new do
16
+ output.each { |line|
17
+ output_controller.parse_output(line)
18
+ }
19
+ end
20
+ @input = input
21
+ end
22
+
23
+ end
24
+
25
+ def parse_input(input)
26
+ input_controller.parse_input(input)
27
+ write_input(input)
28
+ end
29
+
30
+ def write_input(input)
31
+ @input.write(input)
32
+ end
33
+
34
+ private
35
+
36
+ def input_controller
37
+ @input_controller ||= InputController.new(view)
38
+ end
39
+
40
+ def output_controller
41
+ @output_controller ||= OutputController.new(view)
42
+ end
43
+
44
+ def view
45
+ @view ||= View.new
46
+ end
47
+
48
+ end
49
+ end
data/lib/repla.rb ADDED
@@ -0,0 +1,9 @@
1
+ module Repla
2
+ require_relative "repla/lib/constants"
3
+ require_relative "repla/lib/window"
4
+ require_relative "repla/lib/controller"
5
+ require_relative "repla/lib/view"
6
+ require_relative "repla/lib/module"
7
+ end
8
+
9
+ Repla::application_exists || abort("The Web Console application is not installed.")
metadata ADDED
@@ -0,0 +1,92 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: repla
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.3.0
5
+ platform: ruby
6
+ authors:
7
+ - Roben Kleene
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-07-04 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: Bridge from Ruby to AppleScript to control Repla.
14
+ email: contact@robenkleene.com
15
+ executables: []
16
+ extensions: []
17
+ extra_rdoc_files: []
18
+ files:
19
+ - lib/applescript/close_window.scpt
20
+ - lib/applescript/create_window.scpt
21
+ - lib/applescript/do_javascript.scpt
22
+ - lib/applescript/exists.scpt
23
+ - lib/applescript/hide_log.scpt
24
+ - lib/applescript/load_html.scpt
25
+ - lib/applescript/load_html_with_base_url.scpt
26
+ - lib/applescript/load_plugin.scpt
27
+ - lib/applescript/read_from_standard_input.scpt
28
+ - lib/applescript/resource_path_for_plugin.scpt
29
+ - lib/applescript/resource_url_for_plugin.scpt
30
+ - lib/applescript/run_plugin.scpt
31
+ - lib/applescript/run_plugin_in_split.scpt
32
+ - lib/applescript/show_log.scpt
33
+ - lib/applescript/split_id_in_window.scpt
34
+ - lib/applescript/split_id_in_window_last.scpt
35
+ - lib/applescript/toggle_log.scpt
36
+ - lib/applescript/window_id_for_plugin.scpt
37
+ - lib/repla.rb
38
+ - lib/repla/dependencies.rb
39
+ - lib/repla/dependencies/css/style.css
40
+ - lib/repla/dependencies/js/wcdependencies.js
41
+ - lib/repla/dependencies/lib/controller.rb
42
+ - lib/repla/dependencies/lib/model.rb
43
+ - lib/repla/dependencies/lib/tester.rb
44
+ - lib/repla/dependencies/lib/view.rb
45
+ - lib/repla/dependencies/views/view.html.erb
46
+ - lib/repla/extension_constants.rb
47
+ - lib/repla/lib/constants.rb
48
+ - lib/repla/lib/controller.rb
49
+ - lib/repla/lib/module.rb
50
+ - lib/repla/lib/view.rb
51
+ - lib/repla/lib/view/erb.rb
52
+ - lib/repla/lib/view/javascript.rb
53
+ - lib/repla/lib/view/resources.rb
54
+ - lib/repla/lib/window.rb
55
+ - lib/repla/logger.rb
56
+ - lib/repla/logger/test/Rakefile
57
+ - lib/repla/logger/test/js/test_view_helper.js
58
+ - lib/repla/logger/test/lib/test_constants.rb
59
+ - lib/repla/logger/test/lib/test_view_helper.rb
60
+ - lib/repla/logger/test/run_tests.sh
61
+ - lib/repla/logger/test/tc_logger.rb
62
+ - lib/repla/repl.rb
63
+ - lib/repla/repl/css/style.css
64
+ - lib/repla/repl/js/wcrepl.js
65
+ - lib/repla/repl/lib/input_controller.rb
66
+ - lib/repla/repl/lib/output_controller.rb
67
+ - lib/repla/repl/lib/view.rb
68
+ - lib/repla/repl/view/view.html.erb
69
+ homepage:
70
+ licenses: []
71
+ metadata: {}
72
+ post_install_message:
73
+ rdoc_options: []
74
+ require_paths:
75
+ - lib
76
+ required_ruby_version: !ruby/object:Gem::Requirement
77
+ requirements:
78
+ - - "~>"
79
+ - !ruby/object:Gem::Version
80
+ version: '2.0'
81
+ required_rubygems_version: !ruby/object:Gem::Requirement
82
+ requirements:
83
+ - - ">="
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ requirements: []
87
+ rubyforge_project:
88
+ rubygems_version: 2.5.2.3
89
+ signing_key:
90
+ specification_version: 4
91
+ summary: Repla helper gem
92
+ test_files: []