Skip to content

Instantly share code, notes, and snippets.

@ttscoff
Last active October 2, 2018 09:24
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ttscoff/2632ab3df4193d3dafc94631f5e77542 to your computer and use it in GitHub Desktop.
Save ttscoff/2632ab3df4193d3dafc94631f5e77542 to your computer and use it in GitHub Desktop.
Script to convert [RegExRX](https://itunes.apple.com/us/app/regexrx/id498370702&at=10l4tL&ct=blog) files to Markdown.
#!/usr/bin/env ruby
require 'fileutils'
require 'nokogiri'
require 'optparse'
require 'erb'
def class_exists?(class_name)
klass = Module.const_get(class_name)
return klass.is_a?(Class)
rescue NameError
return false
end
if class_exists? 'Encoding'
Encoding.default_external = Encoding::UTF_8 if Encoding.respond_to?('default_external')
Encoding.default_internal = Encoding::UTF_8 if Encoding.respond_to?('default_internal')
end
class String
def unpack
[self].pack('H*')
end
def indent
out = ''
self.split("\n").each {|line|
out += " #{line}\n"
}
out
end
def to_js
self.gsub(/(?mi)(?<!\\)\//,'\/')
end
end
class RegexRX
attr_reader :title, :search, :flags, :replace, :source
def initialize(file)
doc = File.open(file) { |f| Nokogiri::XML(f) }
@content = doc.xpath('RegExRX_Document')
@title = doc.xpath("//Window").first["Title"].strip
@search = grabString('fldSearch')
@flags = ''
@flags += 's' if grabOpt('Dot Matches Newline')
@flags += 'i' unless grabOpt('Case Sensitive')
@flags += 'm' if grabOpt('Treat Target As One Line')
if @flags.length == 0
@flags = false
end
# @regex = '/' + @search + '/' + @flags
if grabPref('Do Replace')
@replace = grabString('fldReplace')
else
@replace = false
end
@source = false
source = grabString('fldSource')
if source.length > 0
@source = source
end
end
def to_markdown(template)
out = ERB.new(template).result(binding)
out.force_encoding('utf-8')
end
def grabString(name)
out = @content.xpath("//Control[@name=\"#{name}\"]").first
.content
.strip
.force_encoding('utf-8')
out.unpack
end
def grabPref(name)
@content.xpath("//Preference[@name=\"#{name}\"]").first["value"] == "true"
end
def grabOpt(name)
@content.xpath("//OptionMenu[@text=\"#{name}\"]").first["checked"] == "true"
end
end
options = {}
optparse = OptionParser.new do|opts|
opts.banner = "Usage: #{__FILE__} [OPTIONS]"
options[:prefix] = ''
options[:output] = 'markdown output'
opts.on( '-o', '--output-dir=DIRECTORY', 'Output folder, defaults to "markdown output"') do |output|
options[:output] = output
end
opts.on( '-p','--prefix=PREFIX', 'Prefix added before output filenames' ) do |prefix|
options[:prefix] = prefix.strip + ' '
end
options[:template] = nil
opts.on( '-t','--template=TEMPLATE', 'Use alternate ERB template' ) do |template|
options[:template] = template
end
opts.on( '-h', '--help', 'Display this screen' ) do
puts opts
exit
end
end
optparse.parse!
default_template = <<-ENDOFTEMPLATE
# <%= @title %>
<% if @flags %>
**Flags:** _<%= @flags %>_
<% end %>
**Search:**
<%= @search.indent %>
<% if @replace %>
**Replace:**
<%= @replace.indent %>
<% end %>
<% if @source %>
---
## Test string:
```text
<%= @source %>
```
<% end %>
ENDOFTEMPLATE
# If ERB template is specified, use that instead of the default
if options[:template]
if File.exists?(File.expand_path(options[:template])) && File.basename(options[:template]) =~ /\.erb$/
template = IO.read(File.expand_path(options[:template]))
else
$stderr.puts %Q{Specified template "#{options[:template]}" is not a valid template}
Process.exit 1
end
else
template = default_template
end
FileUtils.mkdir_p(options[:output]) unless File.exists?(options[:output])
Dir.glob('*.regexrx').each {|file|
# $stderr.puts "Reading #{file}"
rx = RegexRX.new(file)
filename = File.join(options[:output], options[:prefix] + rx.title + '.md')
File.open(filename, 'w') {|f|
f.print(rx.to_markdown(template))
}
$stderr.puts "Regex written to #{filename}"
}
<% if @flags %>**Flags:** _<%= @flags %>_
<% end %>#### Search
<%= @search.indent %>
<% if @replace %>
#### Replace
<%= @replace.indent %><% end %>
<% if @source %>---
#### Test string
```text
<%= @source %>
```
<% end %>
<% if @flags %>
<% end %>
### Search
```javascript
/<%= @search.to_js %>/<%= @flags %>
```
<% if @replace %>
### Replace
```javascript
'<%= @replace %>'
```
<% end %>
<% if @source %>
### Test string
```text
<%= @source %>
```
<% end %>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment