expandsync 0.1.3 → 0.2.0

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 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