expandsync 0.1.3 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6b47ba4f7292bf9155e7d8cfc7941f71101f7809
4
- data.tar.gz: 02614276a21b6f4b0cf961c99f8c67c78d544c9a
3
+ metadata.gz: f68be2f33e8ccba10bca1ccdbe3d22f209256b48
4
+ data.tar.gz: d93f58763fb2d3c44a66c9ec44402c707fc24bff
5
5
  SHA512:
6
- metadata.gz: c7f002d6cb68e442268786b8d0af895e81abce64dbb78f838695a33f2d99c08c0a262cc34edce36c894efba40c8f1fc6666373c2ff8341c705d7ba4aed088fcb
7
- data.tar.gz: 0f5cdc5aed4f59f8d5dda01ae4d484ff0995649ee002baf108c4077f86cf0a7bcd61c91a0002f4d69bc22a557c9cdd8e777be606c51b1f07ffededfa0e38bcbb
6
+ metadata.gz: 8704dd2a387a22cd156083dab719f77c6c1d2b2d523007b40e94ec42e4ad96e3fb58501080439e655de53349ecba8b23c8693e1cc8992b17d8fd22b52dbfd6c0
7
+ data.tar.gz: bbca23f9cd02b41f6189184e2e8fb346ddc1697c4d1e5b6dcf8dfd7fda1076434e4aaeb3e630756b334a6da7f8621a34290d178292827692fa1f2665b45abeda
data/.travis.yml CHANGED
@@ -2,5 +2,4 @@ language: ruby
2
2
  rvm:
3
3
  - 2.1.0
4
4
  - 2.0.0
5
- - 1.9.3
6
- - jruby-19mode
5
+ - 1.9.3
data/Gemfile.lock CHANGED
@@ -1,7 +1,8 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- expandsync (0.1.1)
4
+ expandsync (0.2.0)
5
+ cliutils
5
6
  methadone (~> 1.3, >= 1.3.1)
6
7
  nokogiri (~> 1.6, >= 1.6.1)
7
8
 
@@ -15,21 +16,22 @@ GEM
15
16
  builder (3.2.2)
16
17
  childprocess (0.5.1)
17
18
  ffi (~> 1.0, >= 1.0.11)
18
- cucumber (1.3.11)
19
+ cliutils (1.1.0)
20
+ cucumber (1.3.12)
19
21
  builder (>= 2.1.2)
20
22
  diff-lcs (>= 1.1.3)
21
23
  gherkin (~> 2.12)
22
24
  multi_json (>= 1.7.5, < 2.0)
23
- multi_test (>= 0.0.2)
25
+ multi_test (>= 0.1.1)
24
26
  diff-lcs (1.2.5)
25
27
  ffi (1.9.3)
26
28
  gherkin (2.12.2)
27
29
  multi_json (~> 1.3)
28
30
  methadone (1.3.2)
29
31
  bundler
30
- mini_portile (0.5.2)
32
+ mini_portile (0.5.3)
31
33
  multi_json (1.9.0)
32
- multi_test (0.0.3)
34
+ multi_test (0.1.1)
33
35
  nokogiri (1.6.1)
34
36
  mini_portile (~> 0.5.0)
35
37
  rake (0.9.6)
data/Rakefile CHANGED
@@ -1,39 +1,51 @@
1
1
  require 'rake/clean'
2
2
  require 'rubygems'
3
- require 'rubygems/package_task'
4
- require 'cucumber'
5
- require 'cucumber/rake/task'
3
+
4
+ def version
5
+ contents = File.read File.expand_path('../lib/expandsync/constants.rb', __FILE__)
6
+ contents[/\sVERSION = '([^']+)'/, 1]
7
+ end
8
+
6
9
  spec = eval(File.read('expandsync.gemspec'))
7
10
 
8
- Gem::PackageTask.new(spec) do |pkg|
11
+ require 'rake/testtask'
12
+ desc 'Run unit tests'
13
+ Rake::TestTask.new do |t|
14
+ t.libs << "test"
15
+ t.test_files = FileList['test/*_test.rb']
9
16
  end
10
17
 
18
+ require 'cucumber'
19
+ require 'cucumber/rake/task'
11
20
  CUKE_RESULTS = 'results.html'
12
21
  CLEAN << CUKE_RESULTS
13
-
14
- desc 'Run features'
22
+ desc 'Run Cucumber features'
15
23
  Cucumber::Rake::Task.new(:features) do |t|
16
- opts = "features --format html -o #{CUKE_RESULTS} --format pretty -x"
24
+ opts = "features --format html -o #{CUKE_RESULTS} --format progress -x"
17
25
  opts += " --tags #{ENV['TAGS']}" if ENV['TAGS']
18
26
  t.cucumber_opts = opts
19
27
  t.fork = false
20
28
  end
21
29
 
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
30
+ desc "Release ExpandSync version #{ version }"
31
+ task :release => :build do
32
+ unless `git branch` =~ /^\* master$/
33
+ puts "You must be on the master branch to release!"
34
+ exit!
35
+ end
36
+
37
+ sh "git commit --allow-empty -a -m 'Release #{ version }'"
38
+ sh "git tag v#{ version }"
39
+ sh "git push origin master"
40
+ sh "git push origin v#{ version }"
41
+ sh "gem push pkg/expandsync-#{ version }.gem"
28
42
  end
29
43
 
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']
44
+ desc "Build the gem"
45
+ task :build do
46
+ FileUtils.mkdir_p "pkg"
47
+ sh "gem build expandsync.gemspec"
48
+ FileUtils.mv("./expandsync-#{ version }.gem", "pkg")
37
49
  end
38
50
 
39
- task :default => [:test,:features]
51
+ task :default => [:test, :features]
data/bin/expandsync CHANGED
@@ -1,20 +1,48 @@
1
1
  #!/usr/bin/env ruby
2
-
3
- require 'csv'
2
+ # Encoding: utf-8
3
+ #--------------------------------------------------------------------
4
+ # ExpandSync
5
+ #
6
+ # Synchronizes text expansion snippets between aText and
7
+ # TextExpander Touch
8
+ #
9
+ # Copyright (c) 2014
10
+ # Aaron Bach <bachya1208@gmail.com>
11
+ #
12
+ # Permission is hereby granted, free of charge, to any person
13
+ # obtaining a copy of this software and associated documentation
14
+ # files (the "Software"), to deal in the Software without
15
+ # restriction, including without limitation the rights to use,
16
+ # copy, modify, merge, publish, distribute, sublicense, and/or sell
17
+ # copies of the Software, and to permit persons to whom the
18
+ # Software is furnished to do so, subject to the following
19
+ # conditions:
20
+ #
21
+ # The above copyright notice and this permission notice shall be
22
+ # included in all copies or substantial portions of the Software.
23
+ #
24
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
26
+ # OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
28
+ # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
29
+ # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
30
+ # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
31
+ # OTHER DEALINGS IN THE SOFTWARE.
32
+ #--------------------------------------------------------------------
33
+ require 'cliutils'
4
34
  require 'expandsync'
5
- require 'fileutils'
6
35
  require 'methadone'
7
- require 'nokogiri'
8
36
  require 'optparse'
9
37
 
10
38
  class App
39
+ include CLIUtils::Messenging
11
40
  include Methadone::Main
12
- include Methadone::CLILogging
13
41
 
14
42
  main do |atext_filepath|
15
43
  begin
16
- atext = AText.new(atext_filepath, options[:a])
17
- textexpander = TextExpander.new
44
+ atext = ExpandSync::AText.new(atext_filepath, options[:a])
45
+ textexpander = ExpandSync::TextExpander.new
18
46
 
19
47
  # Create file content (CSV for aText, XML for TextExpander)
20
48
  # that contains the correct data:
@@ -36,7 +64,7 @@ class App
36
64
  # This has to be here so that my Cucumber Aruba tests work. Don't ask why.
37
65
  leak_exceptions(true)
38
66
  rescue StandardError => e
39
- ExpandSync::CLIMessage.error(e, false)
67
+ messenger.error(e.to_s)
40
68
  exit!(1)
41
69
  end
42
70
  end
@@ -45,7 +73,7 @@ class App
45
73
  version ExpandSync::VERSION
46
74
 
47
75
  # Flags & Switches
48
- on('-a FILEPATH', "Output location for aText rules (defaults to ~/#{ AText::OUTPUT_FILENAME })")
76
+ on('-a FILEPATH', "Output location for aText rules (defaults to ~/#{ ExpandSync::AText::OUTPUT_FILENAME })")
49
77
  on('-n', 'Disable backing up of Settings.textexpander (RUN AT YOUR OWN RISK!)')
50
78
  on('-v', '--verbose', 'Turn on verbose output')
51
79
 
data/expandsync.gemspec CHANGED
@@ -1,7 +1,7 @@
1
1
  # coding: utf-8
2
2
  lib = File.expand_path('../lib', __FILE__)
3
3
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
- require 'expandsync/version'
4
+ require 'expandsync/constants'
5
5
 
6
6
  Gem::Specification.new do |spec|
7
7
  spec.name = 'expandsync'
@@ -25,6 +25,7 @@ Gem::Specification.new do |spec|
25
25
 
26
26
  spec.add_development_dependency('rake', '~> 0')
27
27
  spec.add_development_dependency('aruba', '~> 0')
28
+ spec.add_dependency('cliutils', '~> 0')
28
29
  spec.add_dependency('methadone', '~> 1.3', '>= 1.3.1')
29
30
  spec.add_dependency('nokogiri', '~> 1.6', '>= 1.6.1')
30
31
  end
@@ -7,9 +7,9 @@ Then(/^"(.*?)" should exist$/) do |file|
7
7
  end
8
8
 
9
9
  Then(/^Settings\.textexpander should be backed up$/) do
10
- expect(File).to exist("/tmp/expandsync/Dropbox/TextExpander/Settings.textexpander_#{ Time.now.utc.iso8601 }")
10
+ expect(Dir['/tmp/expandsync/Dropbox/TextExpander/*'].count).to eq(2)
11
11
  end
12
12
 
13
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 }")
14
+ expect(Dir['/tmp/expandsync/Dropbox/TextExpander/*'].count).to eq(1)
15
15
  end
@@ -1,69 +1,64 @@
1
- # ======================================================
2
- # AText Class
3
- # ======================================================
4
- class AText
5
- # ====================================================
6
- # Constants
7
- # ====================================================
8
- OUTPUT_FILENAME = 'aText-snippets.csv'
9
- OUTPUT_PATH = ENV['HOME']
1
+ require 'csv'
10
2
 
11
- # ====================================================
12
- # Attributes
13
- # ====================================================
14
- attr_accessor :output_file, :snippet_csv, :snippets
3
+ module ExpandSync
4
+ # AText Class
5
+ class AText
6
+ # The output filename
7
+ OUTPUT_FILENAME = 'aText-snippets.csv'
15
8
 
16
- # ====================================================
17
- # Methods
18
- # ====================================================
19
- # ----------------------------------------------------
20
- # initialize method
21
- #
22
- # @param csv_filepath The filepath to the aText CSV
23
- # @return Void
24
- # ----------------------------------------------------
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
9
+ # The output filepath
10
+ OUTPUT_PATH = ENV['HOME']
11
+
12
+ # Stores the output filepath.
13
+ # @return [String]
14
+ attr_accessor :output_file
15
+
16
+ # Stores a CSV string of the snippets.
17
+ # @return [String]
18
+ attr_accessor :snippet_csv
19
+
20
+ # Stores an array of snippets.
21
+ # @return [Array]
22
+ attr_accessor :snippets
23
+
24
+ # Initialize by loading snippets from an aText CSV.
25
+ # @param [String] csv_filepath The filepath to the aText CSV
26
+ # @return [void]
27
+ def initialize(csv_filepath, custom_output_path)
28
+ if custom_output_path.nil?
29
+ @output_file = File.join(OUTPUT_PATH, OUTPUT_FILENAME)
31
30
  else
32
- fail "Invalid output directory for aText: #{ custom_output_path }"
31
+ if Dir.exists?(File.dirname(custom_output_path))
32
+ @output_file = custom_output_path
33
+ else
34
+ fail "Invalid output directory for aText: #{ custom_output_path }"
35
+ end
33
36
  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 }"
37
+
38
+ if File.exists?(csv_filepath) && File.extname(csv_filepath) == '.csv'
39
+ begin
40
+ @snippets = CSV.read(csv_filepath)
41
+ rescue
42
+ fail "Could not load CSV from file: #{ csv_filepath }"
43
+ end
44
+
45
+ @snippets.each { |s| s[2] = 'aText' }
46
+ else
47
+ fail "Invalid CSV file: #{ csv_filepath }"
41
48
  end
42
-
43
- @snippets.each { |s| s[2] = 'aText' }
44
- else
45
- fail "Invalid CSV file: #{ csv_filepath }"
46
49
  end
47
- end
48
-
49
- # ----------------------------------------------------
50
- # construct_data method
51
- #
52
- # Outputs a CSV listing of the supplied snippets
53
- # @param new_snippets The snippet array to use
54
- # @return String
55
- # ----------------------------------------------------
56
- def construct_data(new_snippets)
57
- @snippet_csv = CSV.generate { |csv| new_snippets.each { |s| csv << [s[0], s[1]] } }
58
- end
59
50
 
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) }
51
+ # Outputs a CSV listing of the supplied snippets
52
+ # @param [Array] new_snippets The snippet array to use
53
+ # @return [String]
54
+ def construct_data(new_snippets)
55
+ @snippet_csv = CSV.generate { |csv| new_snippets.each { |s| csv << [s[0], s[1]] } }
56
+ end
57
+
58
+ # Saves the current snippets to Settings.textexpander.
59
+ # @return [void]
60
+ def save
61
+ File.open(@output_file, 'w') {|f| f.write(@snippet_csv) }
62
+ end
68
63
  end
69
64
  end
@@ -1,5 +1,10 @@
1
1
  module ExpandSync
2
+ # The Gem's description
2
3
  DESCRIPTION = 'A command line app that synchronizes text expansion snippets between aText for OS X and TextExpander for iOS'
4
+
5
+ # The Gem's summary
3
6
  SUMMARY = 'An engine for synchronizing snippets from aText on OS X and TextExpander Touch'
4
- VERSION = '0.1.3'
7
+
8
+ # The Gem's version
9
+ VERSION = '0.2.0'
5
10
  end
@@ -1,179 +1,164 @@
1
+ require 'nokogiri'
1
2
  require 'securerandom'
2
3
  require 'time'
3
4
 
4
- # ======================================================
5
- # TextExpander Class
6
- # ======================================================
7
- class TextExpander
8
- # ====================================================
9
- # Constants
10
- # ====================================================
11
- OUTPUT_FILENAME = 'Settings.textexpander'
12
- OUTPUT_PATH = File.join(ENV['HOME'], 'Dropbox', 'TextExpander')
5
+ module ExpandSync
6
+ # TextExpander Class
7
+ class TextExpander
8
+ # The output filename
9
+ OUTPUT_FILENAME = 'Settings.textexpander'
10
+
11
+ # The output filepath
12
+ OUTPUT_PATH = File.join(ENV['HOME'], 'Dropbox', 'TextExpander')
13
13
 
14
- # ====================================================
15
- # Attributes
16
- # ====================================================
17
- attr_accessor :base_xml, :output_file, :snippet_xml, :snippets
14
+ # Stores the initial XML as pulled from Settings.textexpander.
15
+ # @return [Nokogiri::XML::Document]
16
+ attr_accessor :base_xml
18
17
 
19
- # ====================================================
20
- # Methods
21
- # ====================================================
22
- # ----------------------------------------------------
23
- # initialize method
24
- #
25
- # @return Void
26
- # ----------------------------------------------------
27
- def initialize
28
- begin
29
- xpath = "/*/*/array[preceding-sibling::key[1] = 'snippetsTE2']/*"
30
- @output_file = File.join(OUTPUT_PATH, OUTPUT_FILENAME)
31
- @base_xml = Nokogiri::XML(File.open(@output_file))
32
- @snippet_xml = @base_xml
18
+ # Stores the full output path for the produced XML.
19
+ # @return [String]
20
+ attr_accessor :output_file
33
21
 
34
- arr = []
35
- @base_xml.xpath(xpath).each do |snippet|
36
- abbreviation = snippet.xpath("string[preceding-sibling::key[1] = 'abbreviation']").text
37
- value = snippet.xpath("string[preceding-sibling::key[1] = 'plainText']").text
38
- arr << [abbreviation, value, 'TextExpander']
22
+ # Stores the final XML to save.
23
+ # @return [Nokogiri::XML::Document]
24
+ attr_accessor :snippet_xml
25
+
26
+ # Stores an array of snippets.
27
+ # @return [Array]
28
+ attr_accessor :snippets
29
+
30
+ # Initialize by loading snippets from TextExpander.
31
+ # @return [void]
32
+ def initialize
33
+ begin
34
+ xpath = "/*/*/array[preceding-sibling::key[1] = 'snippetsTE2']/*"
35
+ @output_file = File.join(OUTPUT_PATH, OUTPUT_FILENAME)
36
+ @base_xml = Nokogiri::XML(File.open(@output_file))
37
+ @snippet_xml = @base_xml
38
+
39
+ arr = []
40
+ @base_xml.xpath(xpath).each do |snippet|
41
+ abbreviation = snippet.xpath("string[preceding-sibling::key[1] = 'abbreviation']").text
42
+ value = snippet.xpath("string[preceding-sibling::key[1] = 'plainText']").text
43
+ arr << [abbreviation, value, 'TextExpander']
44
+ end
45
+ @snippets = arr
46
+ rescue
47
+ fail "Invalid TextExpander XML file: #{ @output_file }"
39
48
  end
40
- @snippets = arr
41
- rescue
42
- fail "Invalid TextExpander XML file: #{ @output_file }"
43
49
  end
44
- end
45
50
 
46
- # ----------------------------------------------------
47
- # add_groups_to_base_xml method
48
- #
49
- # Creates correct group information for the provided
50
- # snippets.
51
- # @param snippets An array of snippets to add
52
- # @return Void
53
- # ----------------------------------------------------
54
- def add_group_to_base_xml(snippet_uuids)
55
- groups_xpath = "/*/*/array[preceding-sibling::key[1] = 'groupsTE2']"
56
- at_group_xpath = groups_xpath + "/*[string[preceding-sibling::key[1] = 'name'] = 'aText']"
57
-
58
- if @snippet_xml.xpath(at_group_xpath).empty?
59
- xml_builder = Nokogiri::XML::Builder.new do |xml|
60
- xml.dict {
61
- xml.key 'expandAfterMode'
62
- xml.integer '0'
63
- xml.key 'expanderExceptionsMode'
64
- xml.integer '4'
65
- xml.key 'name'
66
- xml.string 'aText'
67
- xml.key 'snippetUUIDs'
68
- xml.array {
69
- snippet_uuids.each do |u|
70
- xml.string u
71
- end
72
- }
73
- xml.key 'suggestAbbreviations'
74
- xml.integer '1'
75
- xml.key 'updateFrequency'
76
- xml.integer '0'
77
- xml.key 'uuidString'
78
- xml.string SecureRandom.uuid.upcase
79
- xml.key 'writable'
80
- xml.integer '1'
81
- }
82
- end
83
- @snippet_xml.xpath(groups_xpath)[0].add_child(xml_builder.doc.root.to_xml)
84
- else
85
- xml_builder = Nokogiri::XML::Builder.new do |xml|
86
- xml.array {
87
- snippet_uuids.each do |uuid|
88
- xml.string uuid
89
- end
90
- }
91
- end
92
-
93
- @snippet_xml.xpath(at_group_xpath + "/array[preceding-sibling::key[1] = 'snippetUUIDs']")[0].add_child(xml_builder.doc.root.children.to_xml)
51
+ # Backs up the current TextExpander settings to a
52
+ # timestamped file in the same directory.
53
+ # @return [String]
54
+ def backup
55
+ FileUtils.cp(@output_file, @output_file + "_#{ Time.now.utc.iso8601 }")
94
56
  end
95
- end
96
57
 
97
- # ----------------------------------------------------
98
- # add_snippets_to_base_xml method
99
- #
100
- # Inserts XML for the provided snippets to the base XML
101
- # @param snippets An array of snippets to add and returns
102
- # an array of snippet UUIDs
103
- # @return Void
104
- # ----------------------------------------------------
105
- def add_snippets_to_base_xml(snippets)
106
- uuids = []
58
+ # Modifies the currently held XML data with new snippet
59
+ # information.
60
+ # @param [Array] new_snippets The snippet array to use
61
+ # @return [void]
62
+ def construct_data(new_snippets)
63
+ snippet_uuids = _add_snippets_to_base_xml(new_snippets)
64
+ _add_group_to_base_xml(snippet_uuids)
65
+ end
107
66
 
108
- xml_builder = Nokogiri::XML::Builder.new do |xml|
109
- xml.snippets {
110
- snippets.each do |s|
111
- uuid = SecureRandom.uuid.upcase
112
- uuids << uuid
113
-
67
+ # Saves the current snippets to Settings.textexpander.
68
+ # @return [void]
69
+ def save
70
+ File.open(@output_file, 'w') {|f| f.write(@snippet_xml) }
71
+ end
72
+
73
+ private
74
+
75
+ # Creates correct group information for the provided
76
+ # snippets.
77
+ # @param [Array] snippets An array of snippet UUIDs
78
+ # @return [void]
79
+ def _add_group_to_base_xml(snippet_uuids)
80
+ groups_xpath = "/*/*/array[preceding-sibling::key[1] = 'groupsTE2']"
81
+ at_group_xpath = groups_xpath + "/*[string[preceding-sibling::key[1] = 'name'] = 'aText']"
82
+
83
+ if @snippet_xml.xpath(at_group_xpath).empty?
84
+ xml_builder = Nokogiri::XML::Builder.new do |xml|
114
85
  xml.dict {
115
- xml.key 'abbreviation'
116
- xml.string s[0]
117
- xml.key 'abbreviationMode'
86
+ xml.key 'expandAfterMode'
118
87
  xml.integer '0'
119
- xml.key 'creationDate'
120
- xml.date Time.now.utc.iso8601
121
- xml.key 'flags'
122
- xml.integer '0'
123
- xml.key 'label'
124
- xml.string
125
- xml.key 'modificationDate'
126
- xml.date Time.now.utc.iso8601
127
- xml.key 'plainText'
128
- xml.string s[1]
129
- xml.key 'snippetType'
130
- xml.integer '0'
131
- xml.key 'useCount'
88
+ xml.key 'expanderExceptionsMode'
89
+ xml.integer '4'
90
+ xml.key 'name'
91
+ xml.string 'aText'
92
+ xml.key 'snippetUUIDs'
93
+ xml.array {
94
+ snippet_uuids.each do |u|
95
+ xml.string u
96
+ end
97
+ }
98
+ xml.key 'suggestAbbreviations'
99
+ xml.integer '1'
100
+ xml.key 'updateFrequency'
132
101
  xml.integer '0'
133
102
  xml.key 'uuidString'
134
- xml.string uuid
103
+ xml.string SecureRandom.uuid.upcase
104
+ xml.key 'writable'
105
+ xml.integer '1'
106
+ }
107
+ end
108
+ @snippet_xml.xpath(groups_xpath)[0].add_child(xml_builder.doc.root.to_xml)
109
+ else
110
+ xml_builder = Nokogiri::XML::Builder.new do |xml|
111
+ xml.array {
112
+ snippet_uuids.each do |uuid|
113
+ xml.string uuid
114
+ end
135
115
  }
136
116
  end
137
- }
117
+
118
+ @snippet_xml.xpath(at_group_xpath + "/array[preceding-sibling::key[1] = 'snippetUUIDs']")[0].add_child(xml_builder.doc.root.children.to_xml)
119
+ end
138
120
  end
139
-
140
- @snippet_xml.xpath("/*/*/array[preceding-sibling::key[1] = 'snippetsTE2']")[0].add_child(xml_builder.doc.root.children.to_xml)
141
- uuids
142
- end
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
-
155
- # ----------------------------------------------------
156
- # construct_data method
157
- #
158
- # Modifies the currently held XML data with new snippet
159
- # information.
160
- # @param new_snippets The snippet array to use
161
- # @return Void
162
- # ----------------------------------------------------
163
- def construct_data(new_snippets)
164
- snippet_uuids = add_snippets_to_base_xml(new_snippets)
165
- add_group_to_base_xml(snippet_uuids)
166
- end
121
+
122
+ # Inserts XML for the provided snippets to the base XML
123
+ # @param [Array] snippets An array of snippets to add and returns an array of snippet UUIDs
124
+ # @return [void]
125
+ def _add_snippets_to_base_xml(snippets)
126
+ uuids = []
167
127
 
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) }
128
+ xml_builder = Nokogiri::XML::Builder.new do |xml|
129
+ xml.snippets {
130
+ snippets.each do |s|
131
+ uuid = SecureRandom.uuid.upcase
132
+ uuids << uuid
133
+
134
+ xml.dict {
135
+ xml.key 'abbreviation'
136
+ xml.string s[0]
137
+ xml.key 'abbreviationMode'
138
+ xml.integer '0'
139
+ xml.key 'creationDate'
140
+ xml.date Time.now.utc.iso8601
141
+ xml.key 'flags'
142
+ xml.integer '0'
143
+ xml.key 'label'
144
+ xml.string
145
+ xml.key 'modificationDate'
146
+ xml.date Time.now.utc.iso8601
147
+ xml.key 'plainText'
148
+ xml.string s[1]
149
+ xml.key 'snippetType'
150
+ xml.integer '0'
151
+ xml.key 'useCount'
152
+ xml.integer '0'
153
+ xml.key 'uuidString'
154
+ xml.string uuid
155
+ }
156
+ end
157
+ }
158
+ end
159
+
160
+ @snippet_xml.xpath("/*/*/array[preceding-sibling::key[1] = 'snippetsTE2']")[0].add_child(xml_builder.doc.root.children.to_xml)
161
+ uuids
162
+ end
176
163
  end
177
-
178
- private :add_group_to_base_xml, :add_snippets_to_base_xml
179
164
  end
data/lib/expandsync.rb CHANGED
@@ -1,8 +1,9 @@
1
1
  require "expandsync/atext"
2
- require "expandsync/cli_message"
2
+ require "expandsync/constants"
3
3
  require "expandsync/textexpander"
4
- require "expandsync/version"
5
4
 
5
+ # The ExpandSync module, which wraps everything
6
+ # in this gem.
6
7
  module ExpandSync
7
8
 
8
9
  end
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.3
4
+ version: 0.2.0
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-18 00:00:00.000000000 Z
11
+ date: 2014-04-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -38,6 +38,20 @@ dependencies:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: cliutils
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
41
55
  - !ruby/object:Gem::Dependency
42
56
  name: methadone
43
57
  requirement: !ruby/object:Gem::Requirement
@@ -107,9 +121,8 @@ files:
107
121
  - features/support/env.rb
108
122
  - lib/expandsync.rb
109
123
  - lib/expandsync/atext.rb
110
- - lib/expandsync/cli_message.rb
124
+ - lib/expandsync/constants.rb
111
125
  - lib/expandsync/textexpander.rb
112
- - lib/expandsync/version.rb
113
126
  - res/Settings.textexpander
114
127
  - res/atext.csv
115
128
  - res/expected-new-atext.csv
@@ -1,215 +0,0 @@
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