repper 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: '0889e10cd309dbdd42315e1049c2f7e10a9ab46b949b08c390614965aa2c1483'
4
+ data.tar.gz: 8ef2f61c38c6e23abcd933c1e3e462602c19d153824c7632114673b57b291ad5
5
+ SHA512:
6
+ metadata.gz: a78030f011bb7d74c0263b2e6353114bdd94c9bdd5ee05f36ec7712dd5ad719f23050cea5627fb51cfc8ebe8bdf8b7813ec2094ea163c0253c58996e1fa5997c
7
+ data.tar.gz: 28b9f8a9243497e1be1ae2243c81817e2dc566532b314b03b9aa3410a947a9eb50f16b79b9b33a8e76e189c63efbc98b173acf160f814ca9bff2e91deb1d839f
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
data/CHANGELOG.md ADDED
@@ -0,0 +1,5 @@
1
+ ## [Unreleased]
2
+
3
+ ## [1.0.0] - 2022-04-30
4
+
5
+ - Initial release
data/Gemfile ADDED
@@ -0,0 +1,10 @@
1
+ source "https://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in repper.gemspec
4
+ gemspec
5
+
6
+ # gem 'regexp_parser', path: '../regexp_parser'
7
+
8
+ gem "rake", "~> 13.0"
9
+
10
+ gem "rspec", "~> 3.0"
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2022 Janosch Müller
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,94 @@
1
+ <h1>
2
+ Repper
3
+ <img alt='Rapper necklace with dollar pendant' src='https://user-images.githubusercontent.com/10758879/167485870-5c49284d-a783-453e-8be0-a3597c2ef97c.png' height='46' align='right' />
4
+ </h1>
5
+
6
+ Repper is a regular expression pretty printer for Ruby.
7
+
8
+ ## Installation
9
+
10
+ `gem install repper`, or add it to your `Gemfile`.
11
+
12
+ ## Usage
13
+
14
+ `repper` can be integrated into the REPL (e.g. IRB) through core extensions or used manually.
15
+
16
+ There are also a few customization options.
17
+
18
+ ### Full REPL integration (recommended)
19
+
20
+ `require 'repper/core_ext/regexp'` in your `~/.irbrc` or `~/.pryrc` to override `Regexp#inspect` and automatically use `repper` to display Regexps:
21
+
22
+ <img width="313" alt="screenshot1" src="https://user-images.githubusercontent.com/10758879/167497359-e5bb94db-1382-465b-903a-3e114721b7a6.png">
23
+
24
+ ### Extending Kernel#pp
25
+
26
+ Alternatively, `require 'repper/core_ext/kernel'` to make the `pp` command give nicer output for Regexps (which will look like above by default).
27
+
28
+ ### Using Repper manually
29
+
30
+ ```ruby
31
+ Repper.call(/foo/) # pretty prints the given Regexp and returns nil
32
+ Repper.render(/foo/) # returns the pretty print String
33
+ ```
34
+
35
+ ### Customization
36
+
37
+ #### Customizing the format
38
+
39
+ The default format is the annotated, indented format shown above.
40
+
41
+ If you want to see the indented structure without annotations, use the `:structured` format.
42
+
43
+ If you only want colorization you can use the `:inline` format.
44
+
45
+ You can change the format globally:
46
+
47
+ ```ruby
48
+ Repper.format = :structured
49
+ ```
50
+
51
+ Or pick a format on a case-by-case basis:
52
+
53
+ <img width="445" alt="screenshot2" src="https://user-images.githubusercontent.com/10758879/167497599-105f39c7-91e0-4954-bce3-d04ad7266695.png">
54
+
55
+ Or create your own format:
56
+
57
+ ```ruby
58
+ require 'csv'
59
+
60
+ csv_format = ->(elements, _theme) { elements.map(&:text).to_csv }
61
+ Repper.render(/re[\p{pe}\r]$/, format: csv_format)
62
+ => "/,re,[,\\p{pe},\\r,],$,/\n"
63
+ ```
64
+
65
+ #### Customizing the colors
66
+
67
+ The color theme can also be set globally or passed on call:
68
+
69
+ ```ruby
70
+ Repper.theme = :monokai # a nicer theme, if the terminal supports it
71
+ ```
72
+ <img width="316" alt="screenshot3" src="https://user-images.githubusercontent.com/10758879/167497895-0cdc017f-5c77-4b15-afaa-207f7eb887cc.png">
73
+
74
+ ```ruby
75
+ Repper.call(/foo/, theme: nil) # render without colors
76
+ ```
77
+
78
+ Or create your own theme - you can use all colors supported by the [`rainbow` gem](https://github.com/sickill/rainbow).
79
+
80
+ ```ruby
81
+ Repper.theme = {
82
+ group: :green,
83
+ set: :red,
84
+ default: :white,
85
+ }
86
+ ```
87
+
88
+ ## Contributing
89
+
90
+ Bug reports and pull requests are welcome on GitHub at https://github.com/jaynetics/repper.
91
+
92
+ ## License
93
+
94
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task default: %i[spec]
@@ -0,0 +1,4 @@
1
+ require 'repper'
2
+ require_relative 'kernel_ext'
3
+
4
+ ::Kernel.prepend(Repper::KernelExt)
@@ -0,0 +1,14 @@
1
+ # This extension does not include itself automatically,
2
+ # require 'repper/core_ext/kernel' to do so.
3
+ module Repper
4
+ module KernelExt
5
+ def pp(*args)
6
+ if args[0].is_a?(Regexp) && (args.size == 1 || args.size == 2 && args[1].is_a?(Hash))
7
+ Repper.call(args[0], **args[1].to_h)
8
+ args[0]
9
+ else
10
+ super
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,4 @@
1
+ require 'repper'
2
+ require_relative 'regexp_ext'
3
+
4
+ ::Regexp.prepend(Repper::RegexpExt)
@@ -0,0 +1,44 @@
1
+ # This extension does not include itself automatically,
2
+ # require 'repper/core_ext/regexp' to do so.
3
+ module Repper
4
+ ALREADY_COLORED_MARK = :@__already_colored__
5
+
6
+ module RegexpExt
7
+ def inspect
8
+ Repper.prevent_color_override_by_repl
9
+ str = Repper.render(self)
10
+ str.instance_variable_set(Repper::ALREADY_COLORED_MARK, true)
11
+ str
12
+ rescue => e
13
+ warn "Error in Repper:\n#{e.message}\n#{e.class} @ #{e.backtrace[0]}"
14
+ super
15
+ end
16
+ end
17
+
18
+ def self.prevent_color_override_by_repl
19
+ # Must be applied lazily because REPLs may be loaded after dependencies.
20
+ return if @prevented_color_override
21
+
22
+ if defined?(::IRB::Color)
23
+ ::IRB::Color.singleton_class.prepend(IRBExt)
24
+ end
25
+
26
+ if defined?(::Pry::SyntaxHighlighter)
27
+ ::Pry::SyntaxHighlighter.singleton_class.prepend(PryExt)
28
+ end
29
+
30
+ @prevented_color_override = true
31
+ end
32
+
33
+ module IRBExt
34
+ def colorize_code(v, *args, **kwars, &blk)
35
+ v&.instance_variable_get(ALREADY_COLORED_MARK) ? v : super
36
+ end
37
+ end
38
+
39
+ module PryExt
40
+ def highlight(v, *args, **kwars, &blk)
41
+ v&.instance_variable_get(ALREADY_COLORED_MARK) ? "\n#{v}" : super
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,31 @@
1
+ module Repper
2
+ Element = Struct.new(:type, :subtype, :level, :text, :id, keyword_init: true) do
3
+ def indented_text
4
+ inlined_text = text.gsub(/[\n\r\t\v]/) { |ws| ws.inspect.delete(?") }
5
+ "#{' ' * level}#{inlined_text}"
6
+ end
7
+
8
+ def whitespace?
9
+ subtype == :whitespace
10
+ end
11
+
12
+ def annotation
13
+ case [type, subtype]
14
+ in [_, :root]
15
+ nil
16
+ in [_, :alternation | :comment | :condition | :intersection | :range => subtype]
17
+ subtype
18
+ in [:conditional | :free_space => type, _]
19
+ type
20
+ in [:group, :capture | :named]
21
+ "capture group #{id}"
22
+ in [:meta, :dot]
23
+ 'match-all'
24
+ in [:keep, :mark]
25
+ 'keep-mark lookbehind'
26
+ in [type, subtype]
27
+ [subtype, type].uniq.join(' ')
28
+ end.to_s.tr('_', ' ')
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,7 @@
1
+ module Repper
2
+ module Error; end
3
+
4
+ class ArgumentError < ::ArgumentError
5
+ include Repper::Error
6
+ end
7
+ end
@@ -0,0 +1,16 @@
1
+ module Repper
2
+ module Format
3
+ Annotated = ->(elements, theme) do
4
+ table = Tabulo::Table.new(elements.reject(&:whitespace?), **TABULO_STYLE)
5
+ table.add_column(
6
+ :indented_text,
7
+ styler: ->(_, string, cell) { theme.colorize(string, cell.source.type) }
8
+ )
9
+ table.add_column(
10
+ :annotation,
11
+ styler: ->(_, string, cell) { theme.colorize(string, :annotation) }
12
+ )
13
+ table.pack.to_s
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,7 @@
1
+ module Repper
2
+ module Format
3
+ Inline = ->(elements, theme) do
4
+ elements.map { |el| theme.colorize(el.text, el.type) }.join
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ module Repper
2
+ module Format
3
+ Plain = ->(elements, *) do
4
+ elements.map(&:text).join
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,12 @@
1
+ module Repper
2
+ module Format
3
+ Structured = ->(elements, theme) do
4
+ table = Tabulo::Table.new(elements.reject(&:whitespace?), **TABULO_STYLE)
5
+ table.add_column(
6
+ :indented_text,
7
+ styler: ->(_, string, cell) { theme.colorize(string, cell.source.type) }
8
+ )
9
+ table.pack.to_s
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ require 'tabulo'
2
+
3
+ module Repper
4
+ module Format
5
+ TABULO_STYLE = {
6
+ border: :blank,
7
+ header_frequency: nil,
8
+ truncation_indicator: '…',
9
+ wrap_body_cells_to: 1,
10
+ }
11
+ end
12
+ end
@@ -0,0 +1,13 @@
1
+ module Repper
2
+ module Format
3
+ def self.cast(arg)
4
+ case arg
5
+ when ::Proc then arg
6
+ when ::Symbol, ::String then Format.const_get(arg.capitalize) rescue nil
7
+ when false, nil then Format::Plain
8
+ end || raise(Repper::ArgumentError, "unknown format #{arg.inspect}")
9
+ end
10
+ end
11
+ end
12
+
13
+ ::Dir["#{__dir__}/format/*.rb"].each { |file| require file }
@@ -0,0 +1,49 @@
1
+ require 'regexp_parser'
2
+
3
+ module Repper
4
+ module Parser
5
+ module_function
6
+
7
+ def call(regexp)
8
+ tree = ::Regexp::Parser.parse(regexp)
9
+ flatten(tree)
10
+ rescue ::Regexp::Parser::Error => e
11
+ raise e.extend(Repper::Error)
12
+ end
13
+
14
+ # Turn Regexp::Parser AST back into a flat Array of visual elements
15
+ # that match the Regexp notation.
16
+ def flatten(exp, acc = [])
17
+ # Add opening entry.
18
+ exp.is?(:root) && acc << make_element(exp, '/')
19
+
20
+ # Ignore nesting of invisible intermediate branches for better visuals.
21
+ exp.is?(:sequence) && exp.nesting_level -= 1
22
+
23
+ exp.parts.each do |part|
24
+ if part.instance_of?(::String)
25
+ acc << make_element(exp, part)
26
+ else # part.is_a?(Regexp::Expression::Base)
27
+ flatten(part, acc)
28
+ end
29
+ end
30
+
31
+ exp.quantified? && flatten(exp.quantifier, acc)
32
+
33
+ # Add closing entry.
34
+ exp.is?(:root) && acc << make_element(exp, "/#{exp.options.keys.join}")
35
+
36
+ acc
37
+ end
38
+
39
+ def make_element(exp, text)
40
+ Element.new(
41
+ type: exp.type,
42
+ subtype: exp.token,
43
+ level: exp.nesting_level,
44
+ text: text,
45
+ id: exp.respond_to?(:identifier) && exp.identifier,
46
+ )
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,25 @@
1
+ module Repper
2
+ class Theme
3
+ Default = new(
4
+ anchor: :yellow,
5
+ annotation: nil, # only for annotated formats
6
+ assertion: :green,
7
+ backref: :blue,
8
+ conditional: :green,
9
+ escape: :red,
10
+ expression: :red, # root
11
+ free_space: nil,
12
+ group: :blue,
13
+ keep: :yellow,
14
+ literal: :red,
15
+ meta: :magenta,
16
+ nonposixclass: :cyan,
17
+ nonproperty: :cyan,
18
+ posixclass: :cyan,
19
+ property: :cyan,
20
+ quantifier: :white,
21
+ set: :cyan,
22
+ type: :cyan,
23
+ )
24
+ end
25
+ end
@@ -0,0 +1,25 @@
1
+ module Repper
2
+ class Theme
3
+ Monokai = new(
4
+ anchor: '#FD971F',
5
+ annotation: '#75715E', # only for annotated formats
6
+ assertion: '#A6E22E',
7
+ backref: '#66D9EF',
8
+ conditional: '#A6E22E',
9
+ escape: '#F92672',
10
+ expression: '#F92672', # root
11
+ free_space: '#75715E',
12
+ group: '#66D9EF',
13
+ keep: '#FD971F',
14
+ literal: '#F92672',
15
+ meta: '#E69F66',
16
+ nonposixclass: '#AE81FF',
17
+ nonproperty: '#AE81FF',
18
+ posixclass: '#AE81FF',
19
+ property: '#AE81FF',
20
+ quantifier: '#F8F8F2',
21
+ set: '#AE81FF',
22
+ type: '#AE81FF',
23
+ )
24
+ end
25
+ end
@@ -0,0 +1,5 @@
1
+ module Repper
2
+ class Theme
3
+ Plain = new
4
+ end
5
+ end
@@ -0,0 +1,25 @@
1
+ require 'rainbow'
2
+
3
+ module Repper
4
+ class Theme
5
+ def self.cast(arg)
6
+ case arg
7
+ when Theme then arg
8
+ when ::Hash then Theme.new(**arg)
9
+ when ::Symbol, ::String then Theme.const_get(arg.capitalize) rescue nil
10
+ when false, nil then Theme::Plain
11
+ end || raise(Repper::ArgumentError, "unknown theme #{arg.inspect}")
12
+ end
13
+
14
+ def initialize(**colors)
15
+ @colors = colors
16
+ end
17
+
18
+ def colorize(str, type)
19
+ color = @colors[type] || @colors[:default]
20
+ color ? Rainbow(str).color(color).bold : str
21
+ end
22
+ end
23
+ end
24
+
25
+ ::Dir["#{__dir__}/theme/*.rb"].each { |file| require file }
@@ -0,0 +1,3 @@
1
+ module Repper
2
+ VERSION = "1.0.0"
3
+ end
data/lib/repper.rb ADDED
@@ -0,0 +1,34 @@
1
+ require_relative "repper/element"
2
+ require_relative "repper/errors"
3
+ require_relative "repper/format"
4
+ require_relative "repper/parser"
5
+ require_relative "repper/theme"
6
+ require_relative "repper/version"
7
+
8
+ module Repper
9
+ class << self
10
+ attr_reader :format, :theme
11
+
12
+ def call(regexp, format: self.format, theme: self.theme)
13
+ puts render(regexp, format: format, theme: theme)
14
+ end
15
+
16
+ def render(regexp, format: self.format, theme: self.theme)
17
+ elements = Parser.call(regexp)
18
+ format = Format.cast(format)
19
+ theme = Theme.cast(theme)
20
+ format.call(elements, theme)
21
+ end
22
+
23
+ def theme=(theme)
24
+ @theme = Theme.cast(theme)
25
+ end
26
+
27
+ def format=(format)
28
+ @format = Format.cast(format)
29
+ end
30
+ end
31
+
32
+ self.format = Format::Annotated
33
+ self.theme = Theme::Default
34
+ end
data/repper.gemspec ADDED
@@ -0,0 +1,30 @@
1
+ require_relative "lib/repper/version"
2
+
3
+ Gem::Specification.new do |spec|
4
+ spec.name = "repper"
5
+ spec.version = Repper::VERSION
6
+ spec.authors = ["Janosch Müller"]
7
+ spec.email = ["janosch84@gmail.com"]
8
+
9
+ spec.summary = "Regexp pretty printer for Ruby"
10
+ spec.homepage = "https://github.com/jaynetics/repper"
11
+ spec.license = "MIT"
12
+ spec.required_ruby_version = ">= 2.7.0"
13
+
14
+ spec.metadata["homepage_uri"] = spec.homepage
15
+ spec.metadata["source_code_uri"] = "https://github.com/jaynetics/repper"
16
+ spec.metadata["changelog_uri"] = "https://github.com/jaynetics/repper/tree/main/CHANGELOG.md"
17
+
18
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
19
+ `git ls-files -z`.split("\x0").reject do |f|
20
+ (f == __FILE__) || f.match(%r{\A(?:(?:bin|test|spec|features)/|\.(?:git|travis|circleci)|appveyor)})
21
+ end
22
+ end
23
+ spec.bindir = "exe"
24
+ spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
25
+ spec.require_paths = ["lib"]
26
+
27
+ spec.add_dependency "rainbow", "~> 3.1"
28
+ spec.add_dependency "regexp_parser", "~> 2.4"
29
+ spec.add_dependency "tabulo", "~> 2.8"
30
+ end
data/repper.svg ADDED
@@ -0,0 +1,447 @@
1
+ <?xml version="1.0" encoding="UTF-8" standalone="no"?>
2
+ <!-- Created with Inkscape (http://www.inkscape.org/) -->
3
+
4
+ <svg
5
+ width="210mm"
6
+ height="297mm"
7
+ viewBox="0 0 210 297"
8
+ version="1.1"
9
+ id="svg5"
10
+ inkscape:version="1.1.2 (b8e25be8, 2022-02-05)"
11
+ sodipodi:docname="repper.svg"
12
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
13
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
14
+ xmlns="http://www.w3.org/2000/svg"
15
+ xmlns:svg="http://www.w3.org/2000/svg">
16
+ <sodipodi:namedview
17
+ id="namedview7"
18
+ pagecolor="#ffffff"
19
+ bordercolor="#666666"
20
+ borderopacity="1.0"
21
+ inkscape:pageshadow="2"
22
+ inkscape:pageopacity="0.0"
23
+ inkscape:pagecheckerboard="0"
24
+ inkscape:document-units="mm"
25
+ showgrid="false"
26
+ inkscape:zoom="0.3"
27
+ inkscape:cx="395"
28
+ inkscape:cy="400"
29
+ inkscape:window-width="1383"
30
+ inkscape:window-height="916"
31
+ inkscape:window-x="0"
32
+ inkscape:window-y="38"
33
+ inkscape:window-maximized="0"
34
+ inkscape:current-layer="layer1" />
35
+ <defs
36
+ id="defs2">
37
+ <inkscape:path-effect
38
+ effect="skeletal"
39
+ id="path-effect43053"
40
+ is_visible="true"
41
+ lpeversion="1"
42
+ pattern="m 191.43677,45.145623 c -0.62159,-1.995117 -4.55335,-2.733918 -8.77626,-1.649108 -4.2229,1.084808 -7.1457,3.584459 -6.5241,5.579576 0.62159,1.995118 4.55336,2.733917 8.77626,1.649108 4.2229,-1.084809 7.14569,-3.58446 6.5241,-5.579576 z"
43
+ copytype="single_stretched"
44
+ prop_scale="1"
45
+ scale_y_rel="false"
46
+ spacing="0"
47
+ normal_offset="0"
48
+ tang_offset="0"
49
+ prop_units="false"
50
+ vertical_pattern="false"
51
+ hide_knot="false"
52
+ fuse_tolerance="0" />
53
+ <inkscape:path-effect
54
+ effect="simplify"
55
+ id="path-effect43049"
56
+ is_visible="true"
57
+ lpeversion="1"
58
+ steps="1"
59
+ threshold="0.00221557"
60
+ smooth_angles="360"
61
+ helper_size="0"
62
+ simplify_individual_paths="false"
63
+ simplify_just_coalesce="false" />
64
+ <inkscape:path-effect
65
+ effect="skeletal"
66
+ id="path-effect29550"
67
+ is_visible="true"
68
+ lpeversion="1"
69
+ pattern="m 199.24476,54.875255 c -0.48117,-2.232133 -4.35348,-3.293167 -8.64355,-2.368379 -4.29007,0.924786 -7.38135,3.486925 -6.90018,5.719057 0.48117,2.232134 4.35348,3.293167 8.64355,2.368379 4.29007,-0.924786 7.38135,-3.486925 6.90018,-5.719057 z"
70
+ copytype="single_stretched"
71
+ prop_scale="1"
72
+ scale_y_rel="false"
73
+ spacing="0"
74
+ normal_offset="0"
75
+ tang_offset="0"
76
+ prop_units="false"
77
+ vertical_pattern="false"
78
+ hide_knot="false"
79
+ fuse_tolerance="0" />
80
+ <inkscape:path-effect
81
+ effect="simplify"
82
+ id="path-effect29546"
83
+ is_visible="true"
84
+ lpeversion="1"
85
+ steps="1"
86
+ threshold="0.00221557"
87
+ smooth_angles="360"
88
+ helper_size="0"
89
+ simplify_individual_paths="false"
90
+ simplify_just_coalesce="false" />
91
+ <inkscape:path-effect
92
+ effect="skeletal"
93
+ id="path-effect29146"
94
+ is_visible="true"
95
+ lpeversion="1"
96
+ pattern="m 73.732994,76.354002 c -0.275483,-2.266725 3.036692,-4.536102 7.39325,-5.065572 4.356559,-0.529469 8.115897,0.880478 8.39138,3.147205 0.275485,2.266725 -3.03669,4.536102 -7.393249,5.065572 -4.356558,0.52947 -8.115896,-0.880478 -8.391381,-3.147205 z"
97
+ copytype="single_stretched"
98
+ prop_scale="1"
99
+ scale_y_rel="false"
100
+ spacing="0"
101
+ normal_offset="0"
102
+ tang_offset="0"
103
+ prop_units="false"
104
+ vertical_pattern="false"
105
+ hide_knot="false"
106
+ fuse_tolerance="0" />
107
+ <inkscape:path-effect
108
+ effect="simplify"
109
+ id="path-effect29142"
110
+ is_visible="true"
111
+ lpeversion="1"
112
+ steps="1"
113
+ threshold="0.00221557"
114
+ smooth_angles="360"
115
+ helper_size="0"
116
+ simplify_individual_paths="false"
117
+ simplify_just_coalesce="false" />
118
+ <inkscape:path-effect
119
+ effect="skeletal"
120
+ id="path-effect29029"
121
+ is_visible="true"
122
+ lpeversion="1"
123
+ pattern="m 20.669672,46.003934 c 0.621589,-1.918412 4.553331,-2.628809 8.77621,-1.585706 4.222877,1.043101 7.145659,3.446649 6.524067,5.365061 -0.62159,1.918412 -4.553331,2.628807 -8.776209,1.585705 -4.222877,-1.043101 -7.14566,-3.446649 -6.524068,-5.36506 z"
124
+ copytype="single_stretched"
125
+ prop_scale="1"
126
+ scale_y_rel="false"
127
+ spacing="0"
128
+ normal_offset="0"
129
+ tang_offset="0"
130
+ prop_units="false"
131
+ vertical_pattern="false"
132
+ hide_knot="false"
133
+ fuse_tolerance="0" />
134
+ <inkscape:path-effect
135
+ effect="simplify"
136
+ id="path-effect29027"
137
+ is_visible="true"
138
+ lpeversion="1"
139
+ steps="1"
140
+ threshold="0.00221557"
141
+ smooth_angles="360"
142
+ helper_size="0"
143
+ simplify_individual_paths="false"
144
+ simplify_just_coalesce="false" />
145
+ <inkscape:path-effect
146
+ effect="simplify"
147
+ id="path-effect29023"
148
+ is_visible="true"
149
+ lpeversion="1"
150
+ steps="1"
151
+ threshold="0.00221557"
152
+ smooth_angles="360"
153
+ helper_size="0"
154
+ simplify_individual_paths="false"
155
+ simplify_just_coalesce="false" />
156
+ <inkscape:path-effect
157
+ effect="simplify"
158
+ id="path-effect17842"
159
+ is_visible="true"
160
+ lpeversion="1"
161
+ steps="1"
162
+ threshold="0.00221557"
163
+ smooth_angles="360"
164
+ helper_size="0"
165
+ simplify_individual_paths="false"
166
+ simplify_just_coalesce="false" />
167
+ <inkscape:path-effect
168
+ effect="skeletal"
169
+ id="path-effect17838"
170
+ is_visible="true"
171
+ lpeversion="1"
172
+ pattern="M 0,4.9921382 C 0,2.2364779 2.2364779,0 4.9921382,0 c 2.7556604,0 4.9921383,2.2364779 4.9921383,4.9921382 0,2.7556604 -2.2364779,4.9921383 -4.9921383,4.9921383 C 2.2364779,9.9842765 0,7.7477986 0,4.9921382 Z"
173
+ copytype="single_stretched"
174
+ prop_scale="1"
175
+ scale_y_rel="false"
176
+ spacing="0"
177
+ normal_offset="0"
178
+ tang_offset="0"
179
+ prop_units="false"
180
+ vertical_pattern="false"
181
+ hide_knot="false"
182
+ fuse_tolerance="0" />
183
+ <inkscape:path-effect
184
+ effect="simplify"
185
+ id="path-effect17836"
186
+ is_visible="true"
187
+ lpeversion="1"
188
+ steps="1"
189
+ threshold="0.00221557"
190
+ smooth_angles="360"
191
+ helper_size="0"
192
+ simplify_individual_paths="false"
193
+ simplify_just_coalesce="false" />
194
+ <inkscape:path-effect
195
+ effect="skeletal"
196
+ id="path-effect17832"
197
+ is_visible="true"
198
+ lpeversion="1"
199
+ pattern="M 0,4.9921382 C 0,2.2364779 2.2364779,0 4.9921382,0 c 2.7556604,0 4.9921383,2.2364779 4.9921383,4.9921382 0,2.7556604 -2.2364779,4.9921383 -4.9921383,4.9921383 C 2.2364779,9.9842765 0,7.7477986 0,4.9921382 Z"
200
+ copytype="single_stretched"
201
+ prop_scale="1"
202
+ scale_y_rel="false"
203
+ spacing="0"
204
+ normal_offset="0"
205
+ tang_offset="0"
206
+ prop_units="false"
207
+ vertical_pattern="false"
208
+ hide_knot="false"
209
+ fuse_tolerance="0" />
210
+ <inkscape:path-effect
211
+ effect="skeletal"
212
+ id="path-effect17828"
213
+ is_visible="true"
214
+ lpeversion="1"
215
+ pattern="M 0,4.9921382 C 0,2.2364779 2.2364779,0 4.9921382,0 c 2.7556604,0 4.9921383,2.2364779 4.9921383,4.9921382 0,2.7556604 -2.2364779,4.9921383 -4.9921383,4.9921383 C 2.2364779,9.9842765 0,7.7477986 0,4.9921382 Z"
216
+ copytype="single_stretched"
217
+ prop_scale="1"
218
+ scale_y_rel="false"
219
+ spacing="0"
220
+ normal_offset="0"
221
+ tang_offset="0"
222
+ prop_units="false"
223
+ vertical_pattern="false"
224
+ hide_knot="false"
225
+ fuse_tolerance="0" />
226
+ <inkscape:path-effect
227
+ effect="simplify"
228
+ id="path-effect29027-3"
229
+ is_visible="true"
230
+ lpeversion="1"
231
+ steps="1"
232
+ threshold="0.00221557"
233
+ smooth_angles="360"
234
+ helper_size="0"
235
+ simplify_individual_paths="false"
236
+ simplify_just_coalesce="false" />
237
+ <inkscape:path-effect
238
+ effect="skeletal"
239
+ id="path-effect29029-7"
240
+ is_visible="true"
241
+ lpeversion="1"
242
+ pattern="m 13.472962,69.233088 c 0,-2.283405 3.561774,-4.136604 7.950388,-4.136604 4.388615,0 7.950388,1.853199 7.950388,4.136604 0,2.283405 -3.561773,4.136604 -7.950388,4.136604 -4.388614,0 -7.950388,-1.853199 -7.950388,-4.136604 z"
243
+ copytype="single_stretched"
244
+ prop_scale="1"
245
+ scale_y_rel="false"
246
+ spacing="0"
247
+ normal_offset="0"
248
+ tang_offset="0"
249
+ prop_units="false"
250
+ vertical_pattern="false"
251
+ hide_knot="false"
252
+ fuse_tolerance="0" />
253
+ <inkscape:path-effect
254
+ effect="simplify"
255
+ id="path-effect29027-1"
256
+ is_visible="true"
257
+ lpeversion="1"
258
+ steps="1"
259
+ threshold="0.00221557"
260
+ smooth_angles="360"
261
+ helper_size="0"
262
+ simplify_individual_paths="false"
263
+ simplify_just_coalesce="false" />
264
+ <inkscape:path-effect
265
+ effect="skeletal"
266
+ id="path-effect29029-3"
267
+ is_visible="true"
268
+ lpeversion="1"
269
+ pattern="m 18.456187,53.513287 c 0.481167,-2.232133 4.353477,-3.293167 8.643549,-2.368379 4.29007,0.924786 7.381351,3.486925 6.900182,5.719057 -0.481168,2.232134 -4.353477,3.293167 -8.643548,2.368379 -4.290071,-0.924786 -7.381353,-3.486925 -6.900183,-5.719057 z"
270
+ copytype="single_stretched"
271
+ prop_scale="1"
272
+ scale_y_rel="false"
273
+ spacing="0"
274
+ normal_offset="0"
275
+ tang_offset="0"
276
+ prop_units="false"
277
+ vertical_pattern="false"
278
+ hide_knot="false"
279
+ fuse_tolerance="0" />
280
+ <inkscape:path-effect
281
+ effect="simplify"
282
+ id="path-effect29027-33"
283
+ is_visible="true"
284
+ lpeversion="1"
285
+ steps="1"
286
+ threshold="0.00221557"
287
+ smooth_angles="360"
288
+ helper_size="0"
289
+ simplify_individual_paths="false"
290
+ simplify_just_coalesce="false" />
291
+ <inkscape:path-effect
292
+ effect="skeletal"
293
+ id="path-effect29029-70"
294
+ is_visible="true"
295
+ lpeversion="1"
296
+ pattern="m 20.669672,49.309136 c 0.621589,-2.197172 4.553331,-3.010795 8.77621,-1.816121 4.222877,1.194672 7.145659,3.947474 6.524067,6.144646 -0.62159,2.197173 -4.553331,3.010794 -8.776209,1.816121 -4.222877,-1.194672 -7.14566,-3.947475 -6.524068,-6.144646 z"
297
+ copytype="single_stretched"
298
+ prop_scale="1"
299
+ scale_y_rel="false"
300
+ spacing="0"
301
+ normal_offset="0"
302
+ tang_offset="0"
303
+ prop_units="false"
304
+ vertical_pattern="false"
305
+ hide_knot="false"
306
+ fuse_tolerance="0" />
307
+ </defs>
308
+ <g
309
+ inkscape:label="Ebene 1"
310
+ inkscape:groupmode="layer"
311
+ id="layer1">
312
+ <text
313
+ xml:space="preserve"
314
+ style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:50.8px;line-height:1;font-family:Thonburi;-inkscape-font-specification:'Thonburi Bold';stroke-width:0.264583"
315
+ x="88.609558"
316
+ y="142.00261"
317
+ id="text473"><tspan
318
+ sodipodi:role="line"
319
+ id="tspan471"
320
+ style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:50.8px;font-family:Thonburi;-inkscape-font-specification:'Thonburi Bold';stroke-width:0.264583"
321
+ x="88.609558"
322
+ y="142.00261">$</tspan></text>
323
+ <text
324
+ xml:space="preserve"
325
+ style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:50.8px;line-height:1;font-family:Thonburi;-inkscape-font-specification:'Thonburi Bold';stroke-width:0.264583"
326
+ x="26.48514"
327
+ y="147.63461"
328
+ id="text473-4"
329
+ inkscape:transform-center-x="2.9956772"
330
+ inkscape:transform-center-y="-2.5677233"><tspan
331
+ id="tspan471-3"
332
+ style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:50.8px;font-family:Thonburi;-inkscape-font-specification:'Thonburi Bold';stroke-width:0.264583"
333
+ x="26.48514"
334
+ y="147.63461"
335
+ sodipodi:role="line" /></text>
336
+ <text
337
+ xml:space="preserve"
338
+ style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:42.7622px;line-height:1;font-family:Thonburi;-inkscape-font-specification:'Thonburi Bold';stroke-width:0.222719"
339
+ x="84.480263"
340
+ y="-73.830437"
341
+ id="text473-1"
342
+ transform="matrix(-0.01039371,0.84174345,-1.1879195,-0.00736484,0,0)"><tspan
343
+ sodipodi:role="line"
344
+ id="tspan471-8"
345
+ style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:42.7622px;font-family:Thonburi;-inkscape-font-specification:'Thonburi Bold';stroke-width:0.222719"
346
+ x="84.480263"
347
+ y="-73.830437">0</tspan></text>
348
+ <text
349
+ xml:space="preserve"
350
+ style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:44.4055px;line-height:1;font-family:Thonburi;-inkscape-font-specification:'Thonburi Bold';white-space:pre;inline-size:40.7295;stroke-width:0.231278"
351
+ x="18.91221"
352
+ y="-47.323662"
353
+ id="text473-1-5"
354
+ transform="matrix(-0.45969555,0.66650243,-0.97588205,-0.53512053,4.2333335,10.289189)"><tspan
355
+ x="18.91221"
356
+ y="-47.323662"
357
+ id="tspan84688">0</tspan></text>
358
+ <text
359
+ xml:space="preserve"
360
+ style="font-size:10.5833px;line-height:1.25;font-family:'System Font';-inkscape-font-specification:'System Font';stroke-width:0.264583"
361
+ x="47.930836"
362
+ y="84.734871"
363
+ id="text18132"><tspan
364
+ sodipodi:role="line"
365
+ id="tspan18130"
366
+ style="stroke-width:0.264583"
367
+ x="47.930836"
368
+ y="84.734871" /></text>
369
+ <text
370
+ xml:space="preserve"
371
+ style="font-size:10.5833px;line-height:1.25;font-family:'System Font';-inkscape-font-specification:'System Font';stroke-width:0.264583"
372
+ x="35.948128"
373
+ y="33.380402"
374
+ id="text23204"><tspan
375
+ sodipodi:role="line"
376
+ id="tspan23202"
377
+ style="stroke-width:0.264583"
378
+ x="35.948128"
379
+ y="33.380402" /></text>
380
+ <path
381
+ style="fill:#000000;stroke:none;stroke-width:0.284007px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
382
+ d="m 59.099047,70.776083 c 2.120975,-1.078377 10.77195,1.950654 20.22924,5.094731 -0.147517,-0.0492 1.418427,0.473496 1.27091,0.424299 9.989745,3.340154 17.614113,6.281378 15.582927,8.125798 -1.600508,1.453348 -9.549486,1.32287 -18.585399,-1.349413 0,0 -1e-6,0 -1e-6,0 C 76.147903,82.64138 74.690387,82.144385 73.237982,81.580972 62.456459,77.398636 57.08906,71.798024 59.099047,70.776083 Z"
383
+ id="path29025"
384
+ inkscape:path-effect="#path-effect29027;#path-effect29029"
385
+ inkscape:original-d="m 58.148912,72.423541 c 13.62864,5.908708 23.245218,8.103634 38.499876,10.153486"
386
+ sodipodi:nodetypes="cc" />
387
+ <text
388
+ xml:space="preserve"
389
+ style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:42.0429px;line-height:1;font-family:Thonburi;-inkscape-font-specification:'Thonburi Bold';stroke-width:0.218973"
390
+ x="146.16597"
391
+ y="96.452888"
392
+ id="text473-1-5-0"
393
+ transform="matrix(0.4855282,0.70395662,1.0307219,-0.5651917,0,0)"><tspan
394
+ sodipodi:role="line"
395
+ id="tspan471-8-6-1"
396
+ style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:42.0429px;font-family:Thonburi;-inkscape-font-specification:'Thonburi Bold';stroke-width:0.218973"
397
+ x="146.16597"
398
+ y="96.452888">0</tspan></text>
399
+ <path
400
+ style="fill:#000000;stroke:none;stroke-width:0.28963px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
401
+ d="m 115.94486,85.097149 c 1.62878,1.516174 9.67995,1.368939 18.78066,-1.453697 0,0 0,-10e-7 0,-10e-7 1.41436,-0.440526 2.83487,-0.946725 4.24854,-1.517955 10.78635,-4.358484 16.03105,-10.152634 13.97777,-11.206085 -2.16623,-1.111417 -10.64635,1.973884 -20.10584,5.251398 0.20166,-0.07012 -1.57428,0.547897 -1.37261,0.477773 -9.95865,3.471655 -17.58664,6.532745 -15.52852,8.448567 z"
402
+ id="path29025-0"
403
+ sodipodi:nodetypes="cc"
404
+ inkscape:original-d="m 153.95732,72.621585 c -13.62872,6.144952 -23.24535,8.427629 -38.50001,10.55943"
405
+ inkscape:path-effect="#path-effect43049;#path-effect43053" />
406
+ <text
407
+ xml:space="preserve"
408
+ style="font-size:10.5833px;line-height:1.25;font-family:'System Font';-inkscape-font-specification:'System Font';stroke-width:0.264583"
409
+ x="67.616714"
410
+ y="123.67867"
411
+ id="text30077"><tspan
412
+ sodipodi:role="line"
413
+ id="tspan30075"
414
+ style="stroke-width:0.264583"
415
+ x="67.616714"
416
+ y="123.67867" /></text>
417
+ <rect
418
+ id="rect66881"
419
+ width="6.5312495"
420
+ height="16.90856"
421
+ x="102.88905"
422
+ y="91.982559"
423
+ style="stroke-width:0.274066" />
424
+ <text
425
+ xml:space="preserve"
426
+ style="font-size:31.75px;line-height:1.25;font-family:Arial;-inkscape-font-specification:Arial;stroke-width:0.264583;font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal"
427
+ x="72.62812"
428
+ y="153.12755"
429
+ id="text75927"><tspan
430
+ sodipodi:role="line"
431
+ id="tspan75925"
432
+ style="font-size:31.75px;stroke-width:0.264583;-inkscape-font-specification:Arial;font-family:Arial;font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal"
433
+ x="72.62812"
434
+ y="153.12755">*</tspan></text>
435
+ <text
436
+ xml:space="preserve"
437
+ style="font-size:31.75px;line-height:1.25;font-family:Arial;-inkscape-font-specification:Arial;stroke-width:0.264583;font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal"
438
+ x="124.74483"
439
+ y="125.85077"
440
+ id="text75927-8"><tspan
441
+ sodipodi:role="line"
442
+ id="tspan75925-9"
443
+ style="font-size:31.75px;stroke-width:0.264583;-inkscape-font-specification:Arial;font-family:Arial;font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal"
444
+ x="124.74483"
445
+ y="125.85077">*</tspan></text>
446
+ </g>
447
+ </svg>
data/sig/repper.rbs ADDED
@@ -0,0 +1,4 @@
1
+ module Repper
2
+ VERSION: String
3
+ # See the writing guide of rbs: https://github.com/ruby/rbs#guides
4
+ end
metadata ADDED
@@ -0,0 +1,116 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: repper
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Janosch Müller
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2022-05-09 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rainbow
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '3.1'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '3.1'
27
+ - !ruby/object:Gem::Dependency
28
+ name: regexp_parser
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '2.4'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '2.4'
41
+ - !ruby/object:Gem::Dependency
42
+ name: tabulo
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '2.8'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '2.8'
55
+ description:
56
+ email:
57
+ - janosch84@gmail.com
58
+ executables: []
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - ".rspec"
63
+ - CHANGELOG.md
64
+ - Gemfile
65
+ - LICENSE.txt
66
+ - README.md
67
+ - Rakefile
68
+ - lib/repper.rb
69
+ - lib/repper/core_ext/kernel.rb
70
+ - lib/repper/core_ext/kernel_ext.rb
71
+ - lib/repper/core_ext/regexp.rb
72
+ - lib/repper/core_ext/regexp_ext.rb
73
+ - lib/repper/element.rb
74
+ - lib/repper/errors.rb
75
+ - lib/repper/format.rb
76
+ - lib/repper/format/annotated.rb
77
+ - lib/repper/format/inline.rb
78
+ - lib/repper/format/plain.rb
79
+ - lib/repper/format/structured.rb
80
+ - lib/repper/format/tabulo_style.rb
81
+ - lib/repper/parser.rb
82
+ - lib/repper/theme.rb
83
+ - lib/repper/theme/default.rb
84
+ - lib/repper/theme/monokai.rb
85
+ - lib/repper/theme/plain.rb
86
+ - lib/repper/version.rb
87
+ - repper.gemspec
88
+ - repper.svg
89
+ - sig/repper.rbs
90
+ homepage: https://github.com/jaynetics/repper
91
+ licenses:
92
+ - MIT
93
+ metadata:
94
+ homepage_uri: https://github.com/jaynetics/repper
95
+ source_code_uri: https://github.com/jaynetics/repper
96
+ changelog_uri: https://github.com/jaynetics/repper/tree/main/CHANGELOG.md
97
+ post_install_message:
98
+ rdoc_options: []
99
+ require_paths:
100
+ - lib
101
+ required_ruby_version: !ruby/object:Gem::Requirement
102
+ requirements:
103
+ - - ">="
104
+ - !ruby/object:Gem::Version
105
+ version: 2.7.0
106
+ required_rubygems_version: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ requirements: []
112
+ rubygems_version: 3.4.0.dev
113
+ signing_key:
114
+ specification_version: 4
115
+ summary: Regexp pretty printer for Ruby
116
+ test_files: []