expandsync 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: ee8ddf4aacd31807cb6112c1f1b21107236acdfa
4
+ data.tar.gz: 91ea767a37797fe7b06a376350cc5c16b2974a1f
5
+ SHA512:
6
+ metadata.gz: 95fb60d96619e13024f7d3c3213b9e4a9df03185ffdbc0972bdebf1cd6acb368e1ea593d389d9cae1d3fdf2939ab6fd9ffa9fbcc07efe9a61be50fd6474fe602
7
+ data.tar.gz: 68ac78ebf1423078dd62e0489fdc952bd36b9163e51e48a54076b268ccbaf7ff9980dc4ac412c47550774f921b9a0bf3e9189fad37a429c5d7b6ad5b0c016339
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ .DS_Store
2
+ results.html
3
+ pkg
4
+ html
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in expandsync.gemspec
4
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,52 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ expandsync (0.1.0)
5
+ methadone (~> 1.3.1)
6
+ nokogiri (~> 1.6.1)
7
+
8
+ GEM
9
+ remote: https://rubygems.org/
10
+ specs:
11
+ aruba (0.5.4)
12
+ childprocess (>= 0.3.6)
13
+ cucumber (>= 1.1.1)
14
+ rspec-expectations (>= 2.7.0)
15
+ builder (3.2.2)
16
+ childprocess (0.5.1)
17
+ ffi (~> 1.0, >= 1.0.11)
18
+ cucumber (1.3.11)
19
+ builder (>= 2.1.2)
20
+ diff-lcs (>= 1.1.3)
21
+ gherkin (~> 2.12)
22
+ multi_json (>= 1.7.5, < 2.0)
23
+ multi_test (>= 0.0.2)
24
+ diff-lcs (1.2.5)
25
+ ffi (1.9.3)
26
+ gherkin (2.12.2)
27
+ multi_json (~> 1.3)
28
+ json (1.8.1)
29
+ methadone (1.3.2)
30
+ bundler
31
+ mini_portile (0.5.2)
32
+ multi_json (1.9.0)
33
+ multi_test (0.0.3)
34
+ nokogiri (1.6.1)
35
+ mini_portile (~> 0.5.0)
36
+ nori (2.3.0)
37
+ rake (0.9.6)
38
+ rdoc (4.1.1)
39
+ json (~> 1.4)
40
+ rspec-expectations (2.14.5)
41
+ diff-lcs (>= 1.1.3, < 2.0)
42
+
43
+ PLATFORMS
44
+ ruby
45
+
46
+ DEPENDENCIES
47
+ aruba
48
+ bundler (~> 1.5)
49
+ expandsync!
50
+ nori
51
+ rake (~> 0.9.2)
52
+ rdoc
data/HISTORY.md ADDED
@@ -0,0 +1,3 @@
1
+ # 0.1.0 (2014-03-12)
2
+
3
+ * Initial release of ExpandSync
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2014 Aaron Bach
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Aaron Bach
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,32 @@
1
+ ExpandSync
2
+ ==========
3
+
4
+ A simple engine to sync aText and TextExpander iOS.
5
+
6
+ # Installation
7
+
8
+ $ gem install expandsync
9
+
10
+ # Usage
11
+
12
+ TODO: Write usage instructions here
13
+
14
+ # Contributing
15
+
16
+ 1. Fork it ( http://github.com/bachya/expandsync/fork )
17
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
18
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
19
+ 4. Push to the branch (`git push origin my-new-feature`)
20
+ 5. Create new Pull Request
21
+
22
+ # License
23
+
24
+ (The MIT License)
25
+
26
+ Copyright © 2014 Aaron Bach bachya1208@gmail.com
27
+
28
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
29
+
30
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
31
+
32
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,19 @@
1
+ = expandsync - DESCRIBE YOUR GEM
2
+
3
+ Author:: YOUR NAME (YOUR EMAIL)
4
+ Copyright:: Copyright (c) 2014 YOUR NAME
5
+
6
+
7
+ DESCRIBE YOUR GEM HERE
8
+
9
+ == Links
10
+
11
+ * {Source on Github}[LINK TO GITHUB]
12
+ * RDoc[LINK TO RDOC.INFO]
13
+
14
+ == Install
15
+
16
+ == Examples
17
+
18
+ == Contributing
19
+
data/Rakefile ADDED
@@ -0,0 +1,61 @@
1
+ def dump_load_path
2
+ puts $LOAD_PATH.join("\n")
3
+ found = nil
4
+ $LOAD_PATH.each do |path|
5
+ if File.exists?(File.join(path,"rspec"))
6
+ puts "Found rspec in #{path}"
7
+ if File.exists?(File.join(path,"rspec","core"))
8
+ puts "Found core"
9
+ if File.exists?(File.join(path,"rspec","core","rake_task"))
10
+ puts "Found rake_task"
11
+ found = path
12
+ else
13
+ puts "!! no rake_task"
14
+ end
15
+ else
16
+ puts "!!! no core"
17
+ end
18
+ end
19
+ end
20
+ if found.nil?
21
+ puts "Didn't find rspec/core/rake_task anywhere"
22
+ else
23
+ puts "Found in #{path}"
24
+ end
25
+ end
26
+ require 'bundler'
27
+ require 'rake/clean'
28
+
29
+ require 'rake/testtask'
30
+
31
+ require 'cucumber'
32
+ require 'cucumber/rake/task'
33
+ gem 'rdoc' # we need the installed RDoc gem, not the system one
34
+ require 'rdoc/task'
35
+
36
+ include Rake::DSL
37
+
38
+ Bundler::GemHelper.install_tasks
39
+
40
+
41
+ Rake::TestTask.new do |t|
42
+ t.pattern = 'test/tc_*.rb'
43
+ end
44
+
45
+
46
+ CUKE_RESULTS = 'results.html'
47
+ CLEAN << CUKE_RESULTS
48
+ Cucumber::Rake::Task.new(:features) do |t|
49
+ t.cucumber_opts = "features --format html -o #{CUKE_RESULTS} --format pretty --no-source -x"
50
+ t.fork = false
51
+ end
52
+
53
+ Rake::RDocTask.new do |rd|
54
+
55
+ rd.main = "README.rdoc"
56
+
57
+ rd.rdoc_files.include("README.rdoc","lib/**/*.rb","bin/**/*")
58
+ end
59
+
60
+ task :default => [:test,:features]
61
+
data/bin/expandsync ADDED
@@ -0,0 +1,56 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'csv'
4
+ require 'expandsync'
5
+ require 'methadone'
6
+ require 'nokogiri'
7
+ require 'optparse'
8
+
9
+ class App
10
+ include Methadone::Main
11
+ include Methadone::CLILogging
12
+
13
+ main do |atext_filepath|
14
+ begin
15
+ # Collect snippets from both aText and TextExpander and create an
16
+ # array with the unique entries of both.
17
+ atext = AText.new(atext_filepath)
18
+ textexpander = TextExpander.new(options[:t] || ExpandSync::DEFAULT_TE_SNIPPET_PATH)
19
+ combined_snippets = (atext.snippets + textexpander.snippets).uniq { |s| s[0] }
20
+
21
+ # Next, create file content (CSV for aText, XML for TextExpander)
22
+ # that contains the correct data:
23
+ # 1. aText CSV should contain any new TextExpander snippets.
24
+ # 2. TextExpander XML should contain original snippets *and*
25
+ # any new aText snippets.
26
+ new_at_csv = atext.construct_data(combined_snippets - atext.snippets)
27
+ new_te_xml = textexpander.construct_data(combined_snippets - textexpander.snippets)
28
+
29
+ # Save new aText snippets
30
+ File.open(options[:a] || ExpandSync::DEFAULT_AT_OUTPUT_PATH, 'w') {|f| f.write(new_at_csv) }
31
+
32
+ # Backup the original TextExpander file and output the new one.
33
+ FileUtils.cp(ExpandSync::DEFAULT_TE_SNIPPET_PATH, ExpandSync::DEFAULT_TE_SNIPPET_PATH + '.bak')
34
+ File.open(ExpandSync::DEFAULT_TE_SNIPPET_PATH, 'w') {|f| f.write(new_te_xml) }
35
+
36
+ # This has to be here so that my Cucumber Aruba tests work. Don't ask why.
37
+ leak_exceptions(true)
38
+ rescue StandardError => e
39
+ ExpandSync::CLIMessage.error(e, false)
40
+ end
41
+ end
42
+
43
+ description ExpandSync::DESCRIPTION
44
+ version ExpandSync::VERSION
45
+
46
+ # Flags & Switches
47
+ on('-a FILEPATH', "Specify an output location for aText rules (default to...})")
48
+ on('-n', )
49
+ on('-t FILEPATH', 'Specify a location for the TextExpander iOS XML file')
50
+ on('-v', '--verbose', 'Turn on verbose output')
51
+
52
+ # Arguments
53
+ arg :atext_filepath, 'The filepath to a CSV file exported from aText'
54
+
55
+ go!
56
+ end
@@ -0,0 +1,33 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'expandsync/constants'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'expandsync'
8
+ spec.version = ExpandSync::VERSION
9
+ spec.authors = ['Aaron Bach']
10
+ spec.email = ['bachya1208@googlemail.com']
11
+ spec.summary = ExpandSync::DESCRIPTION
12
+ spec.description = 'A command line app that synchronizes text expansion snippets between aText for OS X and TextExpander for iOS'
13
+ spec.homepage = 'https://github.com/bachya/ExpandSync'
14
+ spec.license = 'MIT'
15
+ spec.platform = Gem::Platform::RUBY
16
+
17
+ spec.files = `git ls-files -z`.split("\x0")
18
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
19
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
20
+ spec.require_paths = ["lib"]
21
+
22
+ spec.license = 'MIT'
23
+ spec.rdoc_options = ['--charset=UTF-8']
24
+ spec.extra_rdoc_files = %w[README.md HISTORY.md LICENSE.txt]
25
+
26
+ spec.add_development_dependency('bundler', '~> 0')
27
+ spec.add_development_dependency('rake', '~> 0')
28
+ spec.add_development_dependency('rdoc', '~> 0')
29
+ spec.add_development_dependency('aruba', '~> 0')
30
+ spec.add_development_dependency('nori', '~> 0')
31
+ spec.add_dependency('methadone', '~> 1.3', '>= 1.3.1')
32
+ spec.add_dependency('nokogiri', '~> 1.6', '>= 1.6.1')
33
+ end
@@ -0,0 +1,18 @@
1
+ Feature: UI
2
+ When the user asks for help, he should be presented
3
+ with instructions on how to run the app.
4
+
5
+ Scenario: Display help instructions
6
+ When I get help for "expandsync"
7
+ Then the exit status should be 0
8
+ And the banner should be present
9
+ And the banner should include the version
10
+ And the banner should document that this app takes options
11
+ And the banner should document that this app's arguments are:
12
+ | atext_file | which is required |
13
+ And the following options should be documented:
14
+ | -a |
15
+ | -n |
16
+ | -t |
17
+ | -v |
18
+ | --verbose |
@@ -0,0 +1,10 @@
1
+ Feature: Run
2
+ The user runs the app and it outputs
3
+ the correct files in the correct locations
4
+
5
+ Scenario: Run with no flags
6
+ Given an aText CSV file at "/tmp/atext.csv"
7
+ When I successfully run `expandsync /tmp/atext.csv`
8
+ Then "~/aText-snippets.csv" should exist
9
+ And "~/Dropbox/TextExpander/Settings.textexpander" should exist
10
+ And "~/Dropbox/TextExpander/Settings.textexpander.bak" should exist
@@ -0,0 +1,20 @@
1
+ require 'nori'
2
+
3
+ Given(/^an aText CSV file at "(.*?)"$/) do |atext_input|
4
+ Dir.chdir(File.dirname(atext_input)) do
5
+ FileUtils.cp(File.join(TMP_DIR, 'atext.csv'), 'atext.csv')
6
+ FileUtils.cp(File.join(TMP_DIR, 'expected-new-textexpander.xml'), 'expected-new-textexpander.xml')
7
+ FileUtils.cp(File.join(TMP_DIR, 'Settings.textexpander'), '/tmp/expandsync/Dropbox/TextExpander/Settings.textexpander')
8
+ end
9
+ end
10
+
11
+ Then(/^"(.*?)" should exist$/) do |file|
12
+ expect(File).to exist(File.expand_path(file))
13
+ end
14
+
15
+ Then(/^"(.*?)" should be the same as "(.*?)"$/) do |file1, file2|
16
+ parser = Nori.new
17
+ file1_xml = parser.parse(File.read(File.expand_path(file1)))
18
+ file2_xml = parser.parse(File.read(File.expand_path(file2)))
19
+ expect(file1_xml).to eq(file2_xml)
20
+ end
@@ -0,0 +1,23 @@
1
+ require 'aruba/cucumber'
2
+ require 'methadone/cucumber'
3
+
4
+ ENV['PATH'] = "#{File.expand_path(File.dirname(__FILE__) + '/../../bin')}#{File::PATH_SEPARATOR}#{ENV['PATH']}"
5
+ LIB_DIR = File.join(File.expand_path(File.dirname(__FILE__)),'..','..','lib')
6
+ TMP_DIR = File.join(File.expand_path(File.dirname(__FILE__)),'..','..','tmp')
7
+
8
+ Before do
9
+ # Using "announce" causes massive warnings on 1.9.2
10
+ @puts = true
11
+ @original_rubylib = ENV['RUBYLIB']
12
+ ENV['RUBYLIB'] = LIB_DIR + File::PATH_SEPARATOR + ENV['RUBYLIB'].to_s
13
+ @original_home = ENV['HOME']
14
+ ENV['HOME'] = "/tmp/expandsync"
15
+ FileUtils.rm_rf "/tmp/expandsync"
16
+ FileUtils.mkdir "/tmp/expandsync"
17
+ FileUtils.mkdir_p "/tmp/expandsync/Dropbox/TextExpander"
18
+ end
19
+
20
+ After do
21
+ ENV['RUBYLIB'] = @original_rubylib
22
+ ENV['HOME'] = @original_home
23
+ end
@@ -0,0 +1,35 @@
1
+ # ======================================================
2
+ # AText Class
3
+ # ======================================================
4
+ class AText
5
+ attr_accessor :filepath, :snippets
6
+
7
+ # ====================================================
8
+ # Methods
9
+ # ====================================================
10
+ # ----------------------------------------------------
11
+ # initialize method
12
+ #
13
+ # @param csv_filepath The filepath to the aText CSV
14
+ # @return Void
15
+ # ----------------------------------------------------
16
+ def initialize(csv_filepath)
17
+ begin
18
+ @filepath = csv_filepath
19
+ @snippets = CSV.read(csv_filepath)
20
+ rescue
21
+ fail "Invalid aText CSV file: #{ csv_filepath }"
22
+ end
23
+ end
24
+
25
+ # ----------------------------------------------------
26
+ # construct_data method
27
+ #
28
+ # Outputs a CSV listing of the supplied snippets
29
+ # @param new_snippets The snippet array to use
30
+ # @return String
31
+ # ----------------------------------------------------
32
+ def construct_data(new_snippets)
33
+ CSV.generate { |csv| new_snippets.each { |s| csv << [s[0], s[1]] } }
34
+ end
35
+ end
@@ -0,0 +1,215 @@
1
+ module ExpandSync
2
+ # ======================================================
3
+ # CliManager Module
4
+ # Singleton to manage common CLI interfacing
5
+ # ======================================================
6
+ module CLIMessage
7
+ # ====================================================
8
+ # Methods
9
+ # ====================================================
10
+ # ----------------------------------------------------
11
+ # error method
12
+ #
13
+ # Outputs a formatted-red error message.
14
+ # @param m The message to output
15
+ # @return Void
16
+ # ----------------------------------------------------
17
+ def self.error(m, log = true)
18
+ Methadone::CLILogging.error(m) if log
19
+ puts "---> ERROR: #{ m }".red
20
+ end
21
+
22
+ # ----------------------------------------------------
23
+ # info method
24
+ #
25
+ # Outputs a formatted-blue informational message.
26
+ # @param m The message to output
27
+ # @return Void
28
+ # ----------------------------------------------------
29
+ def self.info(m, log = true)
30
+ Methadone::CLILogging.info(m) if log
31
+ puts "---> INFO: #{ m }".blue
32
+ end
33
+
34
+ # ----------------------------------------------------
35
+ # info_block method
36
+ #
37
+ # Wraps a block in an opening and closing info message.
38
+ # @param m1 The opening message to output
39
+ # @param m2 The closing message to output
40
+ # @param multiline Whether the message should be multiline
41
+ # @return Void
42
+ # ----------------------------------------------------
43
+ def self.info_block(m1, m2 = 'Done.', multiline = false, log = true)
44
+ if block_given?
45
+ if multiline
46
+ info(m1, log)
47
+ else
48
+ print "---> INFO: #{ m1 }".blue
49
+ end
50
+
51
+ yield
52
+
53
+ if multiline
54
+ info(m2, log)
55
+ else
56
+ puts m2.blue
57
+ end
58
+ else
59
+ error = 'Did not specify a valid block'
60
+ Methadone::CLILogging.error(error) if log
61
+ fail ArgumentError, error
62
+ end
63
+ end
64
+
65
+ # ----------------------------------------------------
66
+ # prompt method
67
+ #
68
+ # Outputs a prompt, collects the user's response, and
69
+ # returns it.
70
+ # @param prompt The prompt to output
71
+ # @param default The default option
72
+ # @return String
73
+ # ----------------------------------------------------
74
+ def self.prompt(prompt, default = nil, log = true)
75
+ print "#{ prompt } #{ default.nil? ? '' : "[default: #{ default }]:" } ".blue
76
+ choice = $stdin.gets.chomp
77
+ if choice.empty?
78
+ r = default
79
+ else
80
+ r = choice
81
+ end
82
+
83
+ Methadone::CLILogging.info("Answer to '#{ prompt }': #{r}") if log
84
+ r
85
+ end
86
+
87
+ # ----------------------------------------------------
88
+ # section method
89
+ #
90
+ # Outputs a formatted-orange section message.
91
+ # @param m The message to output
92
+ # @return Void
93
+ # ----------------------------------------------------
94
+ def self.section(m, log = true)
95
+ Methadone::CLILogging.info(m) if log
96
+ puts "#### #{ m }".purple
97
+ end
98
+
99
+ # ----------------------------------------------------
100
+ # section_block method
101
+ #
102
+ # Wraps a block in an opening and closing section
103
+ # message.
104
+ # @param m1 The opening message to output
105
+ # @param m2 The closing message to output
106
+ # @param multiline A multiline message or not
107
+ # @return Void
108
+ # ----------------------------------------------------
109
+ def self.section_block(m, multiline = true, log = true)
110
+ if block_given?
111
+ if multiline
112
+ section(m, log)
113
+ else
114
+ print "#### #{ m }".purple
115
+ end
116
+
117
+ yield
118
+ else
119
+ error = 'Did not specify a valid block'
120
+ Methadone::CLILogging.error(error) if log
121
+ fail ArgumentError, error
122
+ end
123
+ end
124
+
125
+ # ----------------------------------------------------
126
+ # success method
127
+ #
128
+ # Outputs a formatted-green success message.
129
+ # @param m The message to output
130
+ # @return Void
131
+ # ----------------------------------------------------
132
+ def self.success(m, log = true)
133
+ Methadone::CLILogging.info(m) if log
134
+ puts "---> SUCCESS: #{ m }".green
135
+ end
136
+
137
+ # ----------------------------------------------------
138
+ # warning method
139
+ #
140
+ # Outputs a formatted-yellow warning message.
141
+ # @param m The message to output
142
+ # @return Void
143
+ # ----------------------------------------------------
144
+ def self.warning(m, log = true)
145
+ Methadone::CLILogging.warn(m) if log
146
+ puts "---> WARNING: #{ m }".yellow
147
+ end
148
+ end
149
+ end
150
+
151
+ # ======================================================
152
+ # String Class
153
+ # ======================================================
154
+ class String
155
+ # ----------------------------------------------------
156
+ # colorize method
157
+ #
158
+ # Outputs a string in a formatted color.
159
+ # @param color_code The code to use
160
+ # @return Void
161
+ # ----------------------------------------------------
162
+ def colorize(color_code)
163
+ "\e[#{ color_code }m#{ self }\e[0m"
164
+ end
165
+
166
+ # ----------------------------------------------------
167
+ # blue method
168
+ #
169
+ # Convenience method to output a blue string
170
+ # @return Void
171
+ # ----------------------------------------------------
172
+ def blue
173
+ colorize(34)
174
+ end
175
+
176
+ # ----------------------------------------------------
177
+ # green method
178
+ #
179
+ # Convenience method to output a green string
180
+ # @return Void
181
+ # ----------------------------------------------------
182
+ def green
183
+ colorize(32)
184
+ end
185
+
186
+ # ----------------------------------------------------
187
+ # purple method
188
+ #
189
+ # Convenience method to output a purple string
190
+ # @return Void
191
+ # ----------------------------------------------------
192
+ def purple
193
+ colorize(35)
194
+ end
195
+
196
+ # ----------------------------------------------------
197
+ # red method
198
+ #
199
+ # Convenience method to output a red string
200
+ # @return Void
201
+ # ----------------------------------------------------
202
+ def red
203
+ colorize(31)
204
+ end
205
+
206
+ # ----------------------------------------------------
207
+ # yellow method
208
+ #
209
+ # Convenience method to output a yellow string
210
+ # @return Void
211
+ # ----------------------------------------------------
212
+ def yellow
213
+ colorize(33)
214
+ end
215
+ end
@@ -0,0 +1,9 @@
1
+ module ExpandSync
2
+ # App Info
3
+ DESCRIPTION = 'An engine for synchronizing snippets from aText on OS X and TextExpander iOS'
4
+ VERSION = '0.1.0'
5
+
6
+ # Filepaths
7
+ DEFAULT_AT_OUTPUT_PATH = File.join(ENV['HOME'], 'aText-snippets.csv')
8
+ DEFAULT_TE_SNIPPET_PATH = File.join(ENV['HOME'], 'Dropbox', 'TextExpander', 'Settings.textexpander')
9
+ end
@@ -0,0 +1,5 @@
1
+ module Exceptions
2
+ class InvalidFileError < StandardError; end
3
+ class InvalidCSVError < InvalidFileError; end
4
+ class InvalidXMLError < InvalidFileError; end
5
+ end