synvert 0.4.0 → 0.10.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
- SHA1:
3
- metadata.gz: 09ddea7b3540df0923b7051d97e4713050222da7
4
- data.tar.gz: be6e60c8d3e4eae741f4e5aade6300318a987b29
2
+ SHA256:
3
+ metadata.gz: 430688d602830d6cbccecf277a580969288b875e992dc1447eb108a7ebd0726c
4
+ data.tar.gz: 6ea78cce8187cea7470bbc043978b318a4f0bd608bf13124cb9ec5f75917fe37
5
5
  SHA512:
6
- metadata.gz: ea694f37dcb9db56b488d38bb6b8b347b6e962bc5d3b9431959db7d1f6d764f8e5a5206fc0a49a05e8837369e28420406dd0e088008f3b0d3f8ed5e8566c6003
7
- data.tar.gz: e82714766f3fb2111ebff51e0415a9a05a7c6c7b856dcabb564a96c83f70aebbdeac33dadfb2cf669acf6b649a8ea5723cb95b396851075bc438a0b8160dffcb
6
+ metadata.gz: dad3de4c88092bba08138b0b64d70e92fa33ca2d8d4d7acea22d7b5e468e48fb2b08b8531832c985b03f5a4b6c2e0fda5f5aa415aae204c414fc5d14d18646c1
7
+ data.tar.gz: e500c57544648cb230f43e52658d58c36bde8a13f052c5e66441fc3471c43e867c8693a0b4fde23a9a9c6c69eae28c0d174ef5ddedec499ff6594a676b0beece
data/.travis.yml CHANGED
@@ -1,5 +1,6 @@
1
1
  language: ruby
2
2
  rvm:
3
- - 1.9.3
4
- - 2.0.0
5
- - 2.1.1
3
+ - 2.1
4
+ - 2.2
5
+ - 2.3
6
+ - 2.4
data/CHANGELOG.md CHANGED
@@ -1,5 +1,26 @@
1
1
  # CHANGELOG
2
2
 
3
+ ## 0.10.0 (2021-02-07)
4
+
5
+ * Use new `Core::Confiruation`
6
+ * Use require instead of eval in order to preserve normal Ruby semantics
7
+
8
+ ## 0.9.0
9
+
10
+ * Add `-o` or `--open` option` to open a snippet
11
+
12
+ ## 0.5.3
13
+
14
+ * Show warning message if rewriter not found
15
+
16
+ ## 0.5.0
17
+
18
+ * Rewrite cli for rewriter group
19
+
20
+ ## 0.4.2
21
+
22
+ * Tell user to update synvert-core if necessary after syncing snippets.
23
+
3
24
  ## 0.4.0
4
25
 
5
26
  * Use synvert-core 0.4.0
data/README.md CHANGED
@@ -1,17 +1,18 @@
1
1
  # Synvert
2
2
 
3
- [![Build Status](https://secure.travis-ci.org/xinminlabs/synvert.png)](http://travis-ci.org/xinminlabs/synvert)
4
- [![Coverage Status](https://coveralls.io/repos/xinminlabs/synvert/badge.png?branch=master)](https://coveralls.io/r/xinminlabs/synvert)
5
- [![Gem Version](https://badge.fury.io/rb/synvert.png)](http://badge.fury.io/rb/synvert)
3
+ [![Build Status](https://secure.travis-ci.org/xinminlabs/synvert.svg)](http://travis-ci.org/xinminlabs/synvert)
4
+ [![Coverage Status](https://coveralls.io/repos/xinminlabs/synvert/badge.svg?branch=master)](https://coveralls.io/r/xinminlabs/synvert)
5
+ [![Gem Version](https://badge.fury.io/rb/synvert.svg)](http://badge.fury.io/rb/synvert)
6
6
 
7
7
  Synvert = syntax + convert, makes it easy to convert ruby code
8
8
  automatically.
9
9
 
10
- Synvert is tested against MRI 1.9.3, 2.0.0 and 2.1.1.
10
+ Synvert is tested against MRI 1.9.3, 2.0.0, 2.1.7 and 2.2.3.
11
11
 
12
12
  Synvert is composed by synvert-core and synvert-snippets.
13
13
 
14
14
  [synvert-core][1] provides a dsl to convert ruby code.
15
+
15
16
  [synvert-snippets][2] lists all snippets to convert ruby code based on
16
17
  synvert-core.
17
18
 
@@ -45,7 +46,7 @@ $ synvert --sync
45
46
  ```
46
47
 
47
48
  ```
48
- $ synvert -r factory_girl_short_syntax,upgrade_rails_3_2_to_4_0 ~/Sites/railsbp/rails-bestpractices.com
49
+ $ synvert -r factory_girl/use_short_syntax,rails/upgrade_3_2_to_4_0 ~/Sites/railsbp/rails-bestpractices.com
49
50
  ```
50
51
 
51
52
  ## Documentation
data/Rakefile CHANGED
@@ -1,4 +1,4 @@
1
- require "bundler/gem_tasks"
1
+ require 'bundler/gem_tasks'
2
2
  require 'rspec/core/rake_task'
3
3
 
4
4
  RSpec::Core::RakeTask.new(:spec)
data/lib/synvert.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # coding: utf-8
2
- require "synvert/version"
2
+ require 'synvert/version'
3
3
  require 'bundler'
4
4
  require 'synvert/core'
5
5
 
data/lib/synvert/cli.rb CHANGED
@@ -1,6 +1,5 @@
1
1
  # coding: utf-8
2
2
  require 'optparse'
3
- require 'open-uri'
4
3
 
5
4
  module Synvert
6
5
  # Synvert command line interface.
@@ -16,8 +15,6 @@ module Synvert
16
15
  # Initialize a CLI.
17
16
  def initialize
18
17
  @options = {command: 'run', custom_snippet_paths: [], snippet_names: []}
19
- Core::Configuration.instance.set :skip_files, []
20
- Core::Configuration.instance.set :default_snippets_path, File.join(ENV['HOME'], '.synvert')
21
18
  end
22
19
 
23
20
  # Run the CLI.
@@ -25,19 +22,29 @@ module Synvert
25
22
  # @return [Boolean] true if command runs successfully.
26
23
  def run(args)
27
24
  run_option_parser(args)
28
- load_rewriters
29
25
 
30
26
  case @options[:command]
31
- when 'list' then list_available_rewriters
32
- when 'query' then query_available_rewriters
33
- when 'show' then show_rewriter
34
- when 'sync' then sync_snippets
35
- else
27
+ when 'list'
28
+ load_rewriters
29
+ list_available_rewriters
30
+ when 'open'
31
+ open_rewriter
32
+ when 'query'
33
+ load_rewriters
34
+ query_available_rewriters
35
+ when 'show'
36
+ load_rewriters
37
+ show_rewriter
38
+ when 'sync'
39
+ sync_snippets
40
+ else # run
41
+ load_rewriters
36
42
  @options[:snippet_names].each do |snippet_name|
37
43
  puts "===== #{snippet_name} started ====="
38
- rewriter = Core::Rewriter.call snippet_name
44
+ group, name = snippet_name.split('/')
45
+ rewriter = Core::Rewriter.call group, name
39
46
  rewriter.warnings.each do |warning|
40
- puts "[Warn] " + warning.message
47
+ puts '[Warn] ' + warning.message
41
48
  end
42
49
  puts rewriter.todo if rewriter.todo
43
50
  puts "===== #{snippet_name} done ====="
@@ -51,24 +58,27 @@ module Synvert
51
58
  puts "file #{e.diagnostic.location.source_buffer.name}"
52
59
  puts "line #{e.diagnostic.location.line}"
53
60
  false
54
- rescue Exception => e
55
- print "Error: "
56
- p e
61
+ rescue Synvert::Core::RewriterNotFound => e
62
+ puts e.message
57
63
  false
58
64
  end
59
65
 
60
- private
66
+ private
61
67
 
62
68
  # Run OptionParser to parse arguments.
63
69
  def run_option_parser(args)
64
70
  optparse = OptionParser.new do |opts|
65
- opts.banner = "Usage: synvert [project_path]"
71
+ opts.banner = 'Usage: synvert [project_path]'
66
72
  opts.on '-d', '--load SNIPPET_PATHS', 'load custom snippets, snippet paths can be local file path or remote http url' do |snippet_paths|
67
73
  @options[:custom_snippet_paths] = snippet_paths.split(',').map(&:strip)
68
74
  end
69
75
  opts.on '-l', '--list', 'list all available snippets' do
70
76
  @options[:command] = 'list'
71
77
  end
78
+ opts.on '-o', '--open SNIPPET_NAME', 'Open a snippet' do |snippet_name|
79
+ @options[:command] = 'open'
80
+ @options[:snippet_name] = snippet_name
81
+ end
72
82
  opts.on '-q', '--query QUERY', 'query specified snippets' do |query|
73
83
  @options[:command] = 'query'
74
84
  @options[:query] = query
@@ -76,14 +86,14 @@ module Synvert
76
86
  opts.on '--skip FILE_PATTERNS', 'skip specified files or directories, separated by comma, e.g. app/models/post.rb,vendor/plugins/**/*.rb' do |file_patterns|
77
87
  @options[:skip_file_patterns] = file_patterns.split(',')
78
88
  end
79
- opts.on '-s', '--show SNIPPET_NAME', 'show specified snippet description' do |snippet_name|
89
+ opts.on '-s', '--show SNIPPET_NAME', 'show specified snippet description, SNIPPET_NAME is combined by group and name, e.g. ruby/new_hash_syntax' do |snippet_name|
80
90
  @options[:command] = 'show'
81
91
  @options[:snippet_name] = snippet_name
82
92
  end
83
93
  opts.on '--sync', 'sync snippets' do
84
94
  @options[:command] = 'sync'
85
95
  end
86
- opts.on '-r', '--run SNIPPET_NAMES', 'run specified snippets' do |snippet_names|
96
+ opts.on '-r', '--run SNIPPET_NAMES', 'run specified snippets, each SNIPPET_NAME is combined by group and name, e.g. ruby/new_hash_syntax,ruby/new_lambda_syntax' do |snippet_names|
87
97
  @options[:snippet_names] = snippet_names.split(',').map(&:strip)
88
98
  end
89
99
  opts.on '-v', '--version', 'show this version' do
@@ -92,48 +102,74 @@ module Synvert
92
102
  end
93
103
  end
94
104
  paths = optparse.parse(args)
95
- Core::Configuration.instance.set :path, paths.first || Dir.pwd
105
+ Core::Configuration.path = paths.first || Dir.pwd
96
106
  if @options[:skip_file_patterns] && !@options[:skip_file_patterns].empty?
97
- skip_files = @options[:skip_file_patterns].map { |file_pattern|
98
- full_file_pattern = File.join(Core::Configuration.instance.get(:path), file_pattern)
107
+ skip_files = @options[:skip_file_patterns].map do |file_pattern|
108
+ full_file_pattern = File.join(Core::Configuration.path, file_pattern)
99
109
  Dir.glob(full_file_pattern)
100
- }.flatten
101
- Core::Configuration.instance.set :skip_files, skip_files
110
+ end.flatten
111
+ Core::Configuration.skip_files = skip_files
102
112
  end
103
113
  end
104
114
 
105
115
  # Load all rewriters.
106
116
  def load_rewriters
107
- default_snippets_path = Core::Configuration.instance.get :default_snippets_path
108
- Dir.glob(File.join(default_snippets_path, 'lib/**/*.rb')).each { |file| eval(File.read(file)) }
117
+ Dir.glob(File.join(default_snippets_path, 'lib/**/*.rb')).each { |file| require file }
109
118
 
110
119
  @options[:custom_snippet_paths].each do |snippet_path|
111
120
  if snippet_path =~ /^http/
112
121
  uri = URI.parse snippet_path
113
122
  eval(uri.read)
114
123
  else
115
- eval(File.read(snippet_path))
124
+ require snippet_path
116
125
  end
117
126
  end
127
+ rescue
128
+ FileUtils.rm_rf default_snippets_path
129
+ retry
118
130
  end
119
131
 
120
132
  # List and print all available rewriters.
121
133
  def list_available_rewriters
122
134
  if Core::Rewriter.availables.empty?
123
- puts "There is no snippet under ~/.synvert, please run `synvert --sync` to fetch snippets."
135
+ puts 'There is no snippet under ~/.synvert, please run `synvert --sync` to fetch snippets.'
124
136
  else
125
- Core::Rewriter.availables.each do |rewriter|
126
- print rewriter.name.to_s + " "
137
+ Core::Rewriter.availables.each do |group, rewriters|
138
+ puts group
139
+ rewriters.each do |name, rewriter|
140
+ puts ' ' + name
141
+ end
127
142
  end
128
143
  puts
129
144
  end
130
145
  end
131
146
 
147
+ # Open one rewriter.
148
+ def open_rewriter
149
+ editor = [ENV['SYNVERT_EDITOR'], ENV['EDITOR']].find { |e| !e.nil? && !e.empty? }
150
+ return puts 'To open a synvert snippet, set $EDITOR or $SYNVERT_EDITOR' unless editor
151
+
152
+ path = File.expand_path(File.join(default_snippets_path, "lib/#{@options[:snippet_name]}.rb"))
153
+ if File.exist? path
154
+ system editor, path
155
+ else
156
+ puts "Can't run #{editor} #{path}"
157
+ end
158
+ end
159
+
132
160
  # Query and print available rewriters.
133
161
  def query_available_rewriters
134
- Core::Rewriter.availables.each do |rewriter|
135
- if rewriter.name.include? @options[:query]
136
- print rewriter.name + " "
162
+ Core::Rewriter.availables.each do |group, rewriters|
163
+ if group.include? @options[:query]
164
+ puts group
165
+ rewriters.each do |name, rewriter|
166
+ puts ' ' + name
167
+ end
168
+ elsif rewriters.keys.any? { |name| name.include? @options[:query] }
169
+ puts group
170
+ rewriters.each do |name, rewriter|
171
+ puts ' ' + name if name.include?(@options[:query])
172
+ end
137
173
  end
138
174
  end
139
175
  puts
@@ -141,15 +177,16 @@ module Synvert
141
177
 
142
178
  # Show and print one rewriter.
143
179
  def show_rewriter
144
- rewriter = Core::Rewriter.fetch(@options[:snippet_name])
180
+ group, name = @options[:snippet_name].split('/')
181
+ rewriter = Core::Rewriter.fetch(group, name)
145
182
  if rewriter
146
183
  rewriter.process_with_sandbox
147
184
  puts rewriter.description
148
185
  rewriter.sub_snippets.each do |sub_rewriter|
149
186
  puts
150
- puts "=" * 80
187
+ puts '=' * 80
151
188
  puts "snippet: #{sub_rewriter.name}"
152
- puts "=" * 80
189
+ puts '=' * 80
153
190
  puts sub_rewriter.description
154
191
  end
155
192
  else
@@ -159,8 +196,16 @@ module Synvert
159
196
 
160
197
  # sync snippets
161
198
  def sync_snippets
162
- Snippet.sync
163
- puts "synvert snippets are synced"
199
+ Snippet.new(default_snippets_path).sync
200
+ puts 'synvert snippets are synced'
201
+ core_version = Snippet.fetch_core_version
202
+ if Gem::Version.new(core_version) > Gem::Version.new(Synvert::Core::VERSION)
203
+ puts "synvert-core is updated, please install synvert-core #{core_version}"
204
+ end
205
+ end
206
+
207
+ def default_snippets_path
208
+ File.join(ENV['HOME'], '.synvert')
164
209
  end
165
210
  end
166
211
  end
@@ -1,17 +1,27 @@
1
1
  # coding: utf-8
2
+ require 'open-uri'
3
+ require 'json'
2
4
 
3
5
  module Synvert
4
6
  # Manage synvert snippets.
5
7
  class Snippet
8
+ def initialize(snippets_path)
9
+ @snippets_path = snippets_path
10
+ end
11
+
6
12
  # synchronize snippets from github.
7
- def self.sync
8
- snippets_path = Core::Configuration.instance.get :default_snippets_path
9
- if File.exist?(snippets_path)
10
- FileUtils.cd snippets_path
11
- `git pull --rebase --quiet`
13
+ def sync
14
+ if File.exist?(@snippets_path)
15
+ FileUtils.cd @snippets_path
16
+ Kernel.system('git pull --rebase')
12
17
  else
13
- `git clone https://github.com/xinminlabs/synvert-snippets.git #{snippets_path} --quiet`
18
+ Kernel.system("git clone https://github.com/xinminlabs/synvert-snippets.git #{@snippets_path}")
14
19
  end
15
20
  end
21
+
22
+ def fetch_core_version
23
+ content = URI.open('https://rubygems.org/api/v1/versions/synvert-core.json').read
24
+ JSON.parse(content).first['number']
25
+ end
16
26
  end
17
27
  end
@@ -1,5 +1,5 @@
1
1
  # coding: utf-8
2
2
 
3
3
  module Synvert
4
- VERSION = "0.4.0"
4
+ VERSION = '0.10.0'
5
5
  end
data/spec/spec_helper.rb CHANGED
@@ -1,6 +1,7 @@
1
- $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), "..", "lib"))
1
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
2
 
3
3
  require 'synvert'
4
+ require 'webmock/rspec'
4
5
 
5
6
  require 'coveralls'
6
7
  Coveralls.wear!
@@ -2,19 +2,30 @@ require 'spec_helper'
2
2
 
3
3
  module Synvert
4
4
  describe Snippet do
5
- let(:default_snippets_path) { File.join(File.dirname(__FILE__), '.synvert') }
6
- before { Core::Configuration.instance.set :default_snippets_path, default_snippets_path }
7
- after { FileUtils.rm_rf default_snippets_path }
5
+ let(:snippets_path) { File.join(File.dirname(__FILE__), '.synvert') }
6
+ let(:snippet) { Snippet.new(snippets_path) }
7
+ after { FileUtils.rmdir(snippets_path) if File.exist?(snippets_path) }
8
8
 
9
- it 'git clones snippets' do
10
- Snippet.sync
11
- expect(File.exist?(default_snippets_path)).to be_truthy
9
+ describe 'sync' do
10
+ it 'git clones snippets' do
11
+ expect(Kernel).to receive(:system).with("git clone https://github.com/xinminlabs/synvert-snippets.git #{snippets_path}")
12
+ snippet.sync
13
+ end
14
+
15
+ it 'git pull snippets' do
16
+ FileUtils.mkdir snippets_path
17
+ expect(Kernel).to receive(:system).with('git pull --rebase')
18
+ snippet.sync
19
+ FileUtils.cd File.dirname(__FILE__)
20
+ end
12
21
  end
13
22
 
14
- it 'git pull snippets' do
15
- Snippet.sync
16
- Snippet.sync
17
- expect(File.exist?(default_snippets_path)).to be_truthy
23
+ describe 'fetch_core_version' do
24
+ it 'gets remote version' do
25
+ stub_request(:get, 'https://rubygems.org/api/v1/versions/synvert-core.json').
26
+ to_return(:body => '[{"number":"0.4.2"}]')
27
+ expect(snippet.fetch_core_version).to eq '0.4.2'
28
+ end
18
29
  end
19
30
  end
20
31
  end
data/synvert.gemspec CHANGED
@@ -4,23 +4,24 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
4
  require 'synvert/version'
5
5
 
6
6
  Gem::Specification.new do |spec|
7
- spec.name = "synvert"
7
+ spec.name = 'synvert'
8
8
  spec.version = Synvert::VERSION
9
- spec.authors = ["Richard Huang"]
10
- spec.email = ["flyerhzm@gmail.com"]
11
- spec.description = %q{synvert is used to convert ruby code to better syntax.}
12
- spec.summary = %q{synvert = syntax + convert.}
13
- spec.homepage = "https://github.com/xinminlabs/synvert"
14
- spec.license = "MIT"
9
+ spec.authors = ['Richard Huang']
10
+ spec.email = ['flyerhzm@gmail.com']
11
+ spec.description = 'synvert is used to convert ruby code to better syntax.'
12
+ spec.summary = 'synvert = syntax + convert.'
13
+ spec.homepage = 'https://github.com/xinminlabs/synvert'
14
+ spec.license = 'MIT'
15
15
 
16
16
  spec.files = `git ls-files`.split($/)
17
17
  spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
18
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
- spec.require_paths = ["lib"]
19
+ spec.require_paths = ['lib']
20
20
 
21
- spec.add_runtime_dependency "synvert-core", "~> 0.2.0"
21
+ spec.add_runtime_dependency 'synvert-core', '>= 0.19.0'
22
22
 
23
- spec.add_development_dependency "bundler", "~> 1.3"
24
- spec.add_development_dependency "rake"
25
- spec.add_development_dependency "rspec"
23
+ spec.add_development_dependency 'bundler'
24
+ spec.add_development_dependency 'rake'
25
+ spec.add_development_dependency 'rspec'
26
+ spec.add_development_dependency 'webmock'
26
27
  end
metadata CHANGED
@@ -1,43 +1,43 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: synvert
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.10.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Richard Huang
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-07-26 00:00:00.000000000 Z
11
+ date: 2021-02-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: synvert-core
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - "~>"
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: 0.2.0
19
+ version: 0.19.0
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - "~>"
24
+ - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: 0.2.0
26
+ version: 0.19.0
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: bundler
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - "~>"
31
+ - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: '1.3'
33
+ version: '0'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - "~>"
38
+ - - ">="
39
39
  - !ruby/object:Gem::Version
40
- version: '1.3'
40
+ version: '0'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rake
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -66,6 +66,20 @@ dependencies:
66
66
  - - ">="
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: webmock
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'
69
83
  description: synvert is used to convert ruby code to better syntax.
70
84
  email:
71
85
  - flyerhzm@gmail.com
@@ -94,7 +108,7 @@ homepage: https://github.com/xinminlabs/synvert
94
108
  licenses:
95
109
  - MIT
96
110
  metadata: {}
97
- post_install_message:
111
+ post_install_message:
98
112
  rdoc_options: []
99
113
  require_paths:
100
114
  - lib
@@ -109,9 +123,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
109
123
  - !ruby/object:Gem::Version
110
124
  version: '0'
111
125
  requirements: []
112
- rubyforge_project:
113
- rubygems_version: 2.2.2
114
- signing_key:
126
+ rubygems_version: 3.1.4
127
+ signing_key:
115
128
  specification_version: 4
116
129
  summary: synvert = syntax + convert.
117
130
  test_files: