expandsync 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +4 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +52 -0
- data/HISTORY.md +3 -0
- data/LICENSE +21 -0
- data/LICENSE.txt +22 -0
- data/README.md +32 -0
- data/README.rdoc +19 -0
- data/Rakefile +61 -0
- data/bin/expandsync +56 -0
- data/expandsync.gemspec +33 -0
- data/features/1.ui.feature +18 -0
- data/features/2.run.feature +10 -0
- data/features/step_definitions/expandsync_steps.rb +20 -0
- data/features/support/env.rb +23 -0
- data/lib/expandsync/atext.rb +35 -0
- data/lib/expandsync/cli_message.rb +215 -0
- data/lib/expandsync/constants.rb +9 -0
- data/lib/expandsync/exceptions.rb +5 -0
- data/lib/expandsync/textexpander.rb +150 -0
- data/lib/expandsync.rb +9 -0
- data/test/tc_something.rb +7 -0
- data/tmp/Settings.textexpander +429 -0
- data/tmp/atext.csv +37 -0
- data/tmp/expected-new-atext.csv +30 -0
- data/tmp/expected-new-textexpander.xml +968 -0
- metadata +193 -0
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
data/Gemfile
ADDED
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
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
|
data/expandsync.gemspec
ADDED
@@ -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
|