expandsync 0.1.0 → 0.1.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 +4 -4
- data/.gitignore +3 -2
- data/Gemfile.lock +5 -11
- data/README.md +29 -1
- data/Rakefile +24 -46
- data/bin/expandsync +16 -16
- data/expandsync.gemspec +5 -7
- data/features/1.ui.feature +1 -2
- data/features/2.run.feature +20 -5
- data/features/3.failures.feature +14 -0
- data/features/step_definitions/expandsync_steps.rb +8 -13
- data/features/support/env.rb +8 -1
- data/lib/expandsync/atext.rb +42 -8
- data/lib/expandsync/constants.rb +3 -7
- data/lib/expandsync/textexpander.rb +46 -17
- data/{tmp → res}/Settings.textexpander +0 -0
- data/{tmp → res}/atext.csv +0 -0
- data/{tmp → res}/expected-new-atext.csv +0 -0
- data/{tmp → res}/expected-new-textexpander.xml +0 -0
- data/res/pretty-print.xsl +10 -0
- data/res/random-text-file.txt +1 -0
- metadata +11 -37
- data/LICENSE.txt +0 -22
- data/README.rdoc +0 -19
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 39e3fc74b7b97e14036f6b3328faef9930813f5f
|
4
|
+
data.tar.gz: e0dbeeece56ba82f1f3daa38a85ff2b370f285c2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8bc18828f6874276b291fcfd72e8eb2d115e8d2bd92d20321ceab20db3522613b1541ee2ef1f4b3e5b0c21aab71f8a09a0d6a5323bf386b88890353e1f464678
|
7
|
+
data.tar.gz: 5589cfdbbecba36bea6680c5889c391426711d8f04b5be8de2cfb035dcb13462e3fb7b83ebd8d572d597bc56d81b56955b499051858e084080a94c1873e7ac0d
|
data/.gitignore
CHANGED
data/Gemfile.lock
CHANGED
@@ -2,8 +2,8 @@ PATH
|
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
4
|
expandsync (0.1.0)
|
5
|
-
methadone (~> 1.3.1)
|
6
|
-
nokogiri (~> 1.6.1)
|
5
|
+
methadone (~> 1.3, >= 1.3.1)
|
6
|
+
nokogiri (~> 1.6, >= 1.6.1)
|
7
7
|
|
8
8
|
GEM
|
9
9
|
remote: https://rubygems.org/
|
@@ -25,7 +25,6 @@ GEM
|
|
25
25
|
ffi (1.9.3)
|
26
26
|
gherkin (2.12.2)
|
27
27
|
multi_json (~> 1.3)
|
28
|
-
json (1.8.1)
|
29
28
|
methadone (1.3.2)
|
30
29
|
bundler
|
31
30
|
mini_portile (0.5.2)
|
@@ -33,10 +32,7 @@ GEM
|
|
33
32
|
multi_test (0.0.3)
|
34
33
|
nokogiri (1.6.1)
|
35
34
|
mini_portile (~> 0.5.0)
|
36
|
-
nori (2.3.0)
|
37
35
|
rake (0.9.6)
|
38
|
-
rdoc (4.1.1)
|
39
|
-
json (~> 1.4)
|
40
36
|
rspec-expectations (2.14.5)
|
41
37
|
diff-lcs (>= 1.1.3, < 2.0)
|
42
38
|
|
@@ -44,9 +40,7 @@ PLATFORMS
|
|
44
40
|
ruby
|
45
41
|
|
46
42
|
DEPENDENCIES
|
47
|
-
aruba
|
48
|
-
bundler
|
43
|
+
aruba (~> 0)
|
44
|
+
bundler
|
49
45
|
expandsync!
|
50
|
-
|
51
|
-
rake (~> 0.9.2)
|
52
|
-
rdoc
|
46
|
+
rake
|
data/README.md
CHANGED
@@ -7,9 +7,37 @@ A simple engine to sync aText and TextExpander iOS.
|
|
7
7
|
|
8
8
|
$ gem install expandsync
|
9
9
|
|
10
|
+
# Warning
|
11
|
+
|
12
|
+
ExpandSync is still *heavily* in development; as such, expect this repository to change daily. **USE AT YOUR OWN DISCRETION.**
|
13
|
+
|
10
14
|
# Usage
|
11
15
|
|
12
|
-
TODO: Write usage instructions
|
16
|
+
TODO: Write better usage instructions
|
17
|
+
|
18
|
+
Syntax and usage can be accessed by running `expandsync --help`:
|
19
|
+
|
20
|
+
```
|
21
|
+
$ expandsync --help
|
22
|
+
Usage: expandsync [options] atext_filepath
|
23
|
+
|
24
|
+
An engine for synchronizing snippets from aText on OS X and TextExpander iOS
|
25
|
+
|
26
|
+
v0.1.0
|
27
|
+
|
28
|
+
Options:
|
29
|
+
-h, --help Show command line help
|
30
|
+
--version Show help/version info
|
31
|
+
-a FILEPATH Specify an output location for aText rules (default to /Users/abach/aText-snippets.csv})
|
32
|
+
-n Disable backing up of Settings.textexpander (RUN AT YOUR OWN RISK!)
|
33
|
+
-t FILEPATH Specify a location for the TextExpander iOS XML file
|
34
|
+
-v, --verbose Turn on verbose output
|
35
|
+
|
36
|
+
Arguments:
|
37
|
+
|
38
|
+
atext_filepath
|
39
|
+
The filepath to a CSV file exported from aText
|
40
|
+
```
|
13
41
|
|
14
42
|
# Contributing
|
15
43
|
|
data/Rakefile
CHANGED
@@ -1,61 +1,39 @@
|
|
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
1
|
require 'rake/clean'
|
28
|
-
|
29
|
-
require '
|
30
|
-
|
2
|
+
require 'rubygems'
|
3
|
+
require 'rubygems/package_task'
|
31
4
|
require 'cucumber'
|
32
5
|
require 'cucumber/rake/task'
|
33
|
-
|
34
|
-
require 'rdoc/task'
|
6
|
+
spec = eval(File.read('expandsync.gemspec'))
|
35
7
|
|
36
|
-
|
37
|
-
|
38
|
-
Bundler::GemHelper.install_tasks
|
39
|
-
|
40
|
-
|
41
|
-
Rake::TestTask.new do |t|
|
42
|
-
t.pattern = 'test/tc_*.rb'
|
8
|
+
Gem::PackageTask.new(spec) do |pkg|
|
43
9
|
end
|
44
10
|
|
45
|
-
|
46
11
|
CUKE_RESULTS = 'results.html'
|
47
12
|
CLEAN << CUKE_RESULTS
|
13
|
+
|
14
|
+
desc 'Run features'
|
48
15
|
Cucumber::Rake::Task.new(:features) do |t|
|
49
|
-
|
16
|
+
opts = "features --format html -o #{CUKE_RESULTS} --format pretty -x"
|
17
|
+
opts += " --tags #{ENV['TAGS']}" if ENV['TAGS']
|
18
|
+
t.cucumber_opts = opts
|
50
19
|
t.fork = false
|
51
20
|
end
|
52
21
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
22
|
+
desc 'Run features tagged as work-in-progress (@wip)'
|
23
|
+
Cucumber::Rake::Task.new('features:wip') do |t|
|
24
|
+
tag_opts = ' --tags ~@pending'
|
25
|
+
tag_opts = ' --tags @wip'
|
26
|
+
t.cucumber_opts = "features --format html -o #{CUKE_RESULTS} --format pretty -x -s#{tag_opts}"
|
27
|
+
t.fork = false
|
58
28
|
end
|
59
29
|
|
60
|
-
task :
|
30
|
+
task :cucumber => :features
|
31
|
+
task 'cucumber:wip' => 'features:wip'
|
32
|
+
task :wip => 'features:wip'
|
33
|
+
require 'rake/testtask'
|
34
|
+
Rake::TestTask.new do |t|
|
35
|
+
t.libs << "test"
|
36
|
+
t.test_files = FileList['test/*_test.rb']
|
37
|
+
end
|
61
38
|
|
39
|
+
task :default => [:test,:features]
|
data/bin/expandsync
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
require 'csv'
|
4
4
|
require 'expandsync'
|
5
|
+
require 'fileutils'
|
5
6
|
require 'methadone'
|
6
7
|
require 'nokogiri'
|
7
8
|
require 'optparse'
|
@@ -12,31 +13,31 @@ class App
|
|
12
13
|
|
13
14
|
main do |atext_filepath|
|
14
15
|
begin
|
15
|
-
|
16
|
-
|
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] }
|
16
|
+
atext = AText.new(atext_filepath, options[:a])
|
17
|
+
textexpander = TextExpander.new
|
20
18
|
|
21
|
-
#
|
19
|
+
# Create file content (CSV for aText, XML for TextExpander)
|
22
20
|
# that contains the correct data:
|
23
21
|
# 1. aText CSV should contain any new TextExpander snippets.
|
24
22
|
# 2. TextExpander XML should contain original snippets *and*
|
25
23
|
# any new aText snippets.
|
26
|
-
|
27
|
-
|
24
|
+
combined_snippets = (atext.snippets + textexpander.snippets).uniq { |s| s[0] }
|
25
|
+
atext.construct_data(combined_snippets - atext.snippets)
|
26
|
+
textexpander.construct_data(combined_snippets - textexpander.snippets)
|
28
27
|
|
29
|
-
# Save new aText snippets
|
30
|
-
|
28
|
+
# Save new aText snippets .
|
29
|
+
atext.save
|
31
30
|
|
32
|
-
# Backup the original TextExpander file
|
33
|
-
|
34
|
-
|
31
|
+
# Backup the original TextExpander file (unless the user has specified
|
32
|
+
# that they don't want a backup) and save the new one.
|
33
|
+
textexpander.backup unless options[:n]
|
34
|
+
textexpander.save
|
35
35
|
|
36
36
|
# This has to be here so that my Cucumber Aruba tests work. Don't ask why.
|
37
37
|
leak_exceptions(true)
|
38
38
|
rescue StandardError => e
|
39
39
|
ExpandSync::CLIMessage.error(e, false)
|
40
|
+
exit!(1)
|
40
41
|
end
|
41
42
|
end
|
42
43
|
|
@@ -44,9 +45,8 @@ class App
|
|
44
45
|
version ExpandSync::VERSION
|
45
46
|
|
46
47
|
# Flags & Switches
|
47
|
-
on('-a FILEPATH', "
|
48
|
-
on('-n', )
|
49
|
-
on('-t FILEPATH', 'Specify a location for the TextExpander iOS XML file')
|
48
|
+
on('-a FILEPATH', "Output location for aText rules (defaults to ~/#{ AText::OUTPUT_FILENAME })")
|
49
|
+
on('-n', 'Disable backing up of Settings.textexpander (RUN AT YOUR OWN RISK!)')
|
50
50
|
on('-v', '--verbose', 'Turn on verbose output')
|
51
51
|
|
52
52
|
# Arguments
|
data/expandsync.gemspec
CHANGED
@@ -8,26 +8,24 @@ Gem::Specification.new do |spec|
|
|
8
8
|
spec.version = ExpandSync::VERSION
|
9
9
|
spec.authors = ['Aaron Bach']
|
10
10
|
spec.email = ['bachya1208@googlemail.com']
|
11
|
-
spec.summary = ExpandSync::
|
12
|
-
spec.description =
|
11
|
+
spec.summary = ExpandSync::SUMMARY
|
12
|
+
spec.description = ExpandSync::DESCRIPTION
|
13
13
|
spec.homepage = 'https://github.com/bachya/ExpandSync'
|
14
14
|
spec.license = 'MIT'
|
15
15
|
spec.platform = Gem::Platform::RUBY
|
16
|
-
|
16
|
+
|
17
|
+
spec.require_paths = ["lib"]
|
17
18
|
spec.files = `git ls-files -z`.split("\x0")
|
18
19
|
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
19
20
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
20
|
-
spec.require_paths = ["lib"]
|
21
21
|
|
22
22
|
spec.license = 'MIT'
|
23
23
|
spec.rdoc_options = ['--charset=UTF-8']
|
24
|
-
spec.extra_rdoc_files = %w[README.md HISTORY.md LICENSE
|
24
|
+
spec.extra_rdoc_files = %w[README.md HISTORY.md LICENSE]
|
25
25
|
|
26
26
|
spec.add_development_dependency('bundler', '~> 0')
|
27
27
|
spec.add_development_dependency('rake', '~> 0')
|
28
|
-
spec.add_development_dependency('rdoc', '~> 0')
|
29
28
|
spec.add_development_dependency('aruba', '~> 0')
|
30
|
-
spec.add_development_dependency('nori', '~> 0')
|
31
29
|
spec.add_dependency('methadone', '~> 1.3', '>= 1.3.1')
|
32
30
|
spec.add_dependency('nokogiri', '~> 1.6', '>= 1.6.1')
|
33
31
|
end
|
data/features/1.ui.feature
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
Feature: UI
|
2
|
-
|
2
|
+
As a user, when I ask for help, I should be presented
|
3
3
|
with instructions on how to run the app.
|
4
4
|
|
5
5
|
Scenario: Display help instructions
|
@@ -13,6 +13,5 @@ Feature: UI
|
|
13
13
|
And the following options should be documented:
|
14
14
|
| -a |
|
15
15
|
| -n |
|
16
|
-
| -t |
|
17
16
|
| -v |
|
18
17
|
| --verbose |
|
data/features/2.run.feature
CHANGED
@@ -1,10 +1,25 @@
|
|
1
1
|
Feature: Run
|
2
|
-
|
3
|
-
the correct
|
2
|
+
As a user, when I run the app (w/ or w/o flags), I
|
3
|
+
should have the correct content be placed in the correct
|
4
|
+
files.
|
4
5
|
|
5
6
|
Scenario: Run with no flags
|
6
|
-
Given
|
7
|
-
When I successfully run `expandsync /tmp/atext.csv`
|
7
|
+
Given a file located at "/tmp/expandsync/input/atext.csv"
|
8
|
+
When I successfully run `expandsync /tmp/expandsync/input/atext.csv`
|
8
9
|
Then "~/aText-snippets.csv" should exist
|
9
10
|
And "~/Dropbox/TextExpander/Settings.textexpander" should exist
|
10
|
-
And
|
11
|
+
And Settings.textexpander should be backed up
|
12
|
+
|
13
|
+
Scenario: Run with -a flag
|
14
|
+
Given a file located at "/tmp/expandsync/input/atext.csv"
|
15
|
+
When I run `expandsync -a /tmp/expandsync/output/aText-output.csv /tmp/expandsync/input/atext.csv`
|
16
|
+
Then "/tmp/expandsync/output/aText-output.csv" should exist
|
17
|
+
And "~/Dropbox/TextExpander/Settings.textexpander" should exist
|
18
|
+
And Settings.textexpander should be backed up
|
19
|
+
|
20
|
+
Scenario: Run with -n flags
|
21
|
+
Given a file located at "/tmp/expandsync/input/atext.csv"
|
22
|
+
When I successfully run `expandsync -n /tmp/expandsync/input/atext.csv`
|
23
|
+
Then "~/aText-snippets.csv" should exist
|
24
|
+
And "~/Dropbox/TextExpander/Settings.textexpander" should exist
|
25
|
+
And Settings.textexpander should not be backed up
|
@@ -0,0 +1,14 @@
|
|
1
|
+
Feature: Failures
|
2
|
+
As a user, when something goes wrong (either via my
|
3
|
+
own doing, or because of something unexpected), I
|
4
|
+
should be notified
|
5
|
+
|
6
|
+
Scenario: Run with bad aText Input
|
7
|
+
Given a file located at "/tmp/expandsync/input/random-text-file.txt"
|
8
|
+
When I run `expandsync /tmp/expandsync/input/random-text-file.txt`
|
9
|
+
Then the exit status should be 1
|
10
|
+
|
11
|
+
Scenario: Run with bad -a flag
|
12
|
+
Given a file located at "/tmp/expandsync/input/atext.csv"
|
13
|
+
When I run `expandsync -a /asdgsaduatsidtigasd/out.csv /tmp/expandsync/input/atext.csv`
|
14
|
+
Then the exit status should be 1
|
@@ -1,20 +1,15 @@
|
|
1
|
-
|
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
|
1
|
+
Given(/^a file located at "(.*?)"$/) do |filepath|
|
2
|
+
expect(File).to exist(File.expand_path(filepath))
|
9
3
|
end
|
10
4
|
|
11
5
|
Then(/^"(.*?)" should exist$/) do |file|
|
12
6
|
expect(File).to exist(File.expand_path(file))
|
13
7
|
end
|
14
8
|
|
15
|
-
Then(/^
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
9
|
+
Then(/^Settings\.textexpander should be backed up$/) do
|
10
|
+
expect(File).to exist("/tmp/expandsync/Dropbox/TextExpander/Settings.textexpander_#{ Time.now.utc.iso8601 }")
|
11
|
+
end
|
12
|
+
|
13
|
+
Then(/^Settings\.textexpander should not be backed up$/) do
|
14
|
+
expect(File).to_not exist("/tmp/expandsync/Dropbox/TextExpander/Settings.textexpander_#{ Time.now.utc.iso8601 }")
|
20
15
|
end
|
data/features/support/env.rb
CHANGED
@@ -3,7 +3,7 @@ require 'methadone/cucumber'
|
|
3
3
|
|
4
4
|
ENV['PATH'] = "#{File.expand_path(File.dirname(__FILE__) + '/../../bin')}#{File::PATH_SEPARATOR}#{ENV['PATH']}"
|
5
5
|
LIB_DIR = File.join(File.expand_path(File.dirname(__FILE__)),'..','..','lib')
|
6
|
-
|
6
|
+
RES_DIR = File.join(File.expand_path(File.dirname(__FILE__)),'..','..','res')
|
7
7
|
|
8
8
|
Before do
|
9
9
|
# Using "announce" causes massive warnings on 1.9.2
|
@@ -12,9 +12,16 @@ Before do
|
|
12
12
|
ENV['RUBYLIB'] = LIB_DIR + File::PATH_SEPARATOR + ENV['RUBYLIB'].to_s
|
13
13
|
@original_home = ENV['HOME']
|
14
14
|
ENV['HOME'] = "/tmp/expandsync"
|
15
|
+
|
15
16
|
FileUtils.rm_rf "/tmp/expandsync"
|
16
17
|
FileUtils.mkdir "/tmp/expandsync"
|
18
|
+
FileUtils.mkdir "/tmp/expandsync/input"
|
19
|
+
FileUtils.mkdir "/tmp/expandsync/output"
|
17
20
|
FileUtils.mkdir_p "/tmp/expandsync/Dropbox/TextExpander"
|
21
|
+
|
22
|
+
FileUtils.cp(File.join(RES_DIR, 'atext.csv'), '/tmp/expandsync/input/atext.csv')
|
23
|
+
FileUtils.cp(File.join(RES_DIR, 'random-text-file.txt'), '/tmp/expandsync/input/random-text-file.txt')
|
24
|
+
FileUtils.cp(File.join(RES_DIR, 'Settings.textexpander'), '/tmp/expandsync/Dropbox/TextExpander')
|
18
25
|
end
|
19
26
|
|
20
27
|
After do
|
data/lib/expandsync/atext.rb
CHANGED
@@ -2,7 +2,16 @@
|
|
2
2
|
# AText Class
|
3
3
|
# ======================================================
|
4
4
|
class AText
|
5
|
-
|
5
|
+
# ====================================================
|
6
|
+
# Constants
|
7
|
+
# ====================================================
|
8
|
+
OUTPUT_FILENAME = 'aText-snippets.csv'
|
9
|
+
OUTPUT_PATH = ENV['HOME']
|
10
|
+
|
11
|
+
# ====================================================
|
12
|
+
# Attributes
|
13
|
+
# ====================================================
|
14
|
+
attr_accessor :output_file, :snippet_csv, :snippets
|
6
15
|
|
7
16
|
# ====================================================
|
8
17
|
# Methods
|
@@ -13,12 +22,27 @@ class AText
|
|
13
22
|
# @param csv_filepath The filepath to the aText CSV
|
14
23
|
# @return Void
|
15
24
|
# ----------------------------------------------------
|
16
|
-
def initialize(csv_filepath)
|
17
|
-
|
18
|
-
@
|
19
|
-
|
20
|
-
|
21
|
-
|
25
|
+
def initialize(csv_filepath, custom_output_path)
|
26
|
+
if custom_output_path.nil?
|
27
|
+
@output_file = File.join(OUTPUT_PATH, OUTPUT_FILENAME)
|
28
|
+
else
|
29
|
+
if Dir.exists?(File.dirname(custom_output_path))
|
30
|
+
@output_file = custom_output_path
|
31
|
+
else
|
32
|
+
fail "Invalid output directory for aText: #{ custom_output_path }"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
if File.exists?(csv_filepath) && File.extname(csv_filepath) == '.csv'
|
37
|
+
begin
|
38
|
+
@snippets = CSV.read(csv_filepath)
|
39
|
+
rescue
|
40
|
+
fail "Could not load CSV from file: #{ csv_filepath }"
|
41
|
+
end
|
42
|
+
|
43
|
+
@snippets.each { |s| s[2] = 'aText' }
|
44
|
+
else
|
45
|
+
fail "Invalid CSV file: #{ csv_filepath }"
|
22
46
|
end
|
23
47
|
end
|
24
48
|
|
@@ -30,6 +54,16 @@ class AText
|
|
30
54
|
# @return String
|
31
55
|
# ----------------------------------------------------
|
32
56
|
def construct_data(new_snippets)
|
33
|
-
CSV.generate { |csv| new_snippets.each { |s| csv << [s[0], s[1]] } }
|
57
|
+
@snippet_csv = CSV.generate { |csv| new_snippets.each { |s| csv << [s[0], s[1]] } }
|
58
|
+
end
|
59
|
+
|
60
|
+
# ----------------------------------------------------
|
61
|
+
# save method
|
62
|
+
#
|
63
|
+
# Saves the current snippets to Settings.textexpander.
|
64
|
+
# @return Void
|
65
|
+
# ----------------------------------------------------
|
66
|
+
def save
|
67
|
+
File.open(@output_file, 'w') {|f| f.write(@snippet_csv) }
|
34
68
|
end
|
35
69
|
end
|
data/lib/expandsync/constants.rb
CHANGED
@@ -1,9 +1,5 @@
|
|
1
1
|
module ExpandSync
|
2
|
-
|
3
|
-
|
4
|
-
VERSION = '0.1.
|
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')
|
2
|
+
DESCRIPTION = 'A command line app that synchronizes text expansion snippets between aText for OS X and TextExpander for iOS'
|
3
|
+
SUMMARY = 'An engine for synchronizing snippets from aText on OS X and TextExpander iOS'
|
4
|
+
VERSION = '0.1.1'
|
9
5
|
end
|
@@ -5,7 +5,16 @@ require 'time'
|
|
5
5
|
# TextExpander Class
|
6
6
|
# ======================================================
|
7
7
|
class TextExpander
|
8
|
-
|
8
|
+
# ====================================================
|
9
|
+
# Constants
|
10
|
+
# ====================================================
|
11
|
+
OUTPUT_FILENAME = 'Settings.textexpander'
|
12
|
+
OUTPUT_PATH = File.join(ENV['HOME'], 'Dropbox', 'TextExpander')
|
13
|
+
|
14
|
+
# ====================================================
|
15
|
+
# Attributes
|
16
|
+
# ====================================================
|
17
|
+
attr_accessor :base_xml, :output_file, :snippet_xml, :snippets
|
9
18
|
|
10
19
|
# ====================================================
|
11
20
|
# Methods
|
@@ -13,24 +22,24 @@ class TextExpander
|
|
13
22
|
# ----------------------------------------------------
|
14
23
|
# initialize method
|
15
24
|
#
|
16
|
-
# @param csv_filepath The filepath to the aText CSV
|
17
25
|
# @return Void
|
18
26
|
# ----------------------------------------------------
|
19
|
-
def initialize
|
27
|
+
def initialize
|
20
28
|
begin
|
21
29
|
xpath = "/*/*/array[preceding-sibling::key[1] = 'snippetsTE2']/*"
|
22
|
-
@
|
23
|
-
@base_xml = Nokogiri::XML(File.open(
|
30
|
+
@output_file = File.join(OUTPUT_PATH, OUTPUT_FILENAME)
|
31
|
+
@base_xml = Nokogiri::XML(File.open(@output_file))
|
32
|
+
@snippet_xml = @base_xml
|
24
33
|
|
25
34
|
arr = []
|
26
35
|
@base_xml.xpath(xpath).each do |snippet|
|
27
36
|
abbreviation = snippet.xpath("string[preceding-sibling::key[1] = 'abbreviation']").text
|
28
37
|
value = snippet.xpath("string[preceding-sibling::key[1] = 'plainText']").text
|
29
|
-
arr << [abbreviation, value]
|
38
|
+
arr << [abbreviation, value, 'TextExpander']
|
30
39
|
end
|
31
40
|
@snippets = arr
|
32
41
|
rescue
|
33
|
-
fail "Invalid TextExpander XML file: #{
|
42
|
+
fail "Invalid TextExpander XML file: #{ @output_file }"
|
34
43
|
end
|
35
44
|
end
|
36
45
|
|
@@ -46,7 +55,7 @@ class TextExpander
|
|
46
55
|
groups_xpath = "/*/*/array[preceding-sibling::key[1] = 'groupsTE2']"
|
47
56
|
at_group_xpath = groups_xpath + "/*[string[preceding-sibling::key[1] = 'name'] = 'aText']"
|
48
57
|
|
49
|
-
if @
|
58
|
+
if @snippet_xml.xpath(at_group_xpath).empty?
|
50
59
|
xml_builder = Nokogiri::XML::Builder.new do |xml|
|
51
60
|
xml.dict {
|
52
61
|
xml.key 'expandAfterMode'
|
@@ -71,18 +80,17 @@ class TextExpander
|
|
71
80
|
xml.integer '1'
|
72
81
|
}
|
73
82
|
end
|
74
|
-
@
|
75
|
-
# File.open(File.join(ENV['HOME'], 'Downloads/test.xml'), 'w') { |f| @base_xml.write_xml_to f }
|
83
|
+
@snippet_xml.xpath(groups_xpath)[0].add_child(xml_builder.doc.root.to_xml)
|
76
84
|
else
|
77
85
|
xml_builder = Nokogiri::XML::Builder.new do |xml|
|
78
86
|
xml.array {
|
79
|
-
snippet_uuids.each do |
|
80
|
-
xml.string
|
87
|
+
snippet_uuids.each do |uuid|
|
88
|
+
xml.string uuid
|
81
89
|
end
|
82
90
|
}
|
83
91
|
end
|
84
92
|
|
85
|
-
@
|
93
|
+
@snippet_xml.xpath(at_group_xpath + "/array[preceding-sibling::key[1] = 'snippetUUIDs']")[0].add_child(xml_builder.doc.root.children.to_xml)
|
86
94
|
end
|
87
95
|
end
|
88
96
|
|
@@ -129,21 +137,42 @@ class TextExpander
|
|
129
137
|
}
|
130
138
|
end
|
131
139
|
|
132
|
-
@
|
140
|
+
@snippet_xml.xpath("/*/*/array[preceding-sibling::key[1] = 'snippetsTE2']")[0].add_child(xml_builder.doc.root.children.to_xml)
|
133
141
|
uuids
|
134
142
|
end
|
135
143
|
|
144
|
+
# ----------------------------------------------------
|
145
|
+
# backup method
|
146
|
+
#
|
147
|
+
# Backs up the current TextExpander settings to a
|
148
|
+
# timestamped file in the same directory.
|
149
|
+
# @return String
|
150
|
+
# ----------------------------------------------------
|
151
|
+
def backup
|
152
|
+
FileUtils.cp(@output_file, @output_file + "_#{ Time.now.utc.iso8601 }")
|
153
|
+
end
|
154
|
+
|
136
155
|
# ----------------------------------------------------
|
137
156
|
# construct_data method
|
138
157
|
#
|
139
|
-
#
|
158
|
+
# Modifies the currently held XML data with new snippet
|
159
|
+
# information.
|
140
160
|
# @param new_snippets The snippet array to use
|
141
|
-
# @return
|
161
|
+
# @return Void
|
142
162
|
# ----------------------------------------------------
|
143
163
|
def construct_data(new_snippets)
|
144
164
|
snippet_uuids = add_snippets_to_base_xml(new_snippets)
|
145
165
|
add_group_to_base_xml(snippet_uuids)
|
146
|
-
|
166
|
+
end
|
167
|
+
|
168
|
+
# ----------------------------------------------------
|
169
|
+
# save method
|
170
|
+
#
|
171
|
+
# Saves the current snippets to Settings.textexpander.
|
172
|
+
# @return Void
|
173
|
+
# ----------------------------------------------------
|
174
|
+
def save
|
175
|
+
File.open(@output_file, 'w') {|f| f.write(@snippet_xml) }
|
147
176
|
end
|
148
177
|
|
149
178
|
private :add_group_to_base_xml, :add_snippets_to_base_xml
|
File without changes
|
data/{tmp → res}/atext.csv
RENAMED
File without changes
|
File without changes
|
File without changes
|
@@ -0,0 +1,10 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
|
3
|
+
<xsl:output omit-xml-declaration="no" indent="yes"/>
|
4
|
+
<xsl:strip-space elements="*"/>
|
5
|
+
<xsl:template match="@*|node()">
|
6
|
+
<xsl:copy>
|
7
|
+
<xsl:apply-templates select="@*|node()"/>
|
8
|
+
</xsl:copy>
|
9
|
+
</xsl:template>
|
10
|
+
</xsl:stylesheet>
|
@@ -0,0 +1 @@
|
|
1
|
+
Test
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: expandsync
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Aaron Bach
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-03-
|
11
|
+
date: 2014-03-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -38,20 +38,6 @@ dependencies:
|
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '0'
|
41
|
-
- !ruby/object:Gem::Dependency
|
42
|
-
name: rdoc
|
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
41
|
- !ruby/object:Gem::Dependency
|
56
42
|
name: aruba
|
57
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -66,20 +52,6 @@ dependencies:
|
|
66
52
|
- - "~>"
|
67
53
|
- !ruby/object:Gem::Version
|
68
54
|
version: '0'
|
69
|
-
- !ruby/object:Gem::Dependency
|
70
|
-
name: nori
|
71
|
-
requirement: !ruby/object:Gem::Requirement
|
72
|
-
requirements:
|
73
|
-
- - "~>"
|
74
|
-
- !ruby/object:Gem::Version
|
75
|
-
version: '0'
|
76
|
-
type: :development
|
77
|
-
prerelease: false
|
78
|
-
version_requirements: !ruby/object:Gem::Requirement
|
79
|
-
requirements:
|
80
|
-
- - "~>"
|
81
|
-
- !ruby/object:Gem::Version
|
82
|
-
version: '0'
|
83
55
|
- !ruby/object:Gem::Dependency
|
84
56
|
name: methadone
|
85
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -130,21 +102,20 @@ extensions: []
|
|
130
102
|
extra_rdoc_files:
|
131
103
|
- README.md
|
132
104
|
- HISTORY.md
|
133
|
-
- LICENSE
|
105
|
+
- LICENSE
|
134
106
|
files:
|
135
107
|
- ".gitignore"
|
136
108
|
- Gemfile
|
137
109
|
- Gemfile.lock
|
138
110
|
- HISTORY.md
|
139
111
|
- LICENSE
|
140
|
-
- LICENSE.txt
|
141
112
|
- README.md
|
142
|
-
- README.rdoc
|
143
113
|
- Rakefile
|
144
114
|
- bin/expandsync
|
145
115
|
- expandsync.gemspec
|
146
116
|
- features/1.ui.feature
|
147
117
|
- features/2.run.feature
|
118
|
+
- features/3.failures.feature
|
148
119
|
- features/step_definitions/expandsync_steps.rb
|
149
120
|
- features/support/env.rb
|
150
121
|
- lib/expandsync.rb
|
@@ -153,11 +124,13 @@ files:
|
|
153
124
|
- lib/expandsync/constants.rb
|
154
125
|
- lib/expandsync/exceptions.rb
|
155
126
|
- lib/expandsync/textexpander.rb
|
127
|
+
- res/Settings.textexpander
|
128
|
+
- res/atext.csv
|
129
|
+
- res/expected-new-atext.csv
|
130
|
+
- res/expected-new-textexpander.xml
|
131
|
+
- res/pretty-print.xsl
|
132
|
+
- res/random-text-file.txt
|
156
133
|
- test/tc_something.rb
|
157
|
-
- tmp/Settings.textexpander
|
158
|
-
- tmp/atext.csv
|
159
|
-
- tmp/expected-new-atext.csv
|
160
|
-
- tmp/expected-new-textexpander.xml
|
161
134
|
homepage: https://github.com/bachya/ExpandSync
|
162
135
|
licenses:
|
163
136
|
- MIT
|
@@ -187,6 +160,7 @@ summary: An engine for synchronizing snippets from aText on OS X and TextExpande
|
|
187
160
|
test_files:
|
188
161
|
- features/1.ui.feature
|
189
162
|
- features/2.run.feature
|
163
|
+
- features/3.failures.feature
|
190
164
|
- features/step_definitions/expandsync_steps.rb
|
191
165
|
- features/support/env.rb
|
192
166
|
- test/tc_something.rb
|
data/LICENSE.txt
DELETED
@@ -1,22 +0,0 @@
|
|
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.rdoc
DELETED
@@ -1,19 +0,0 @@
|
|
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
|
-
|