gm-notepad 0.0.1
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 +7 -0
- data/.gitignore +12 -0
- data/.rspec +2 -0
- data/.travis.yml +5 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +6 -0
- data/README.md +118 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/exe/gm-notepad +83 -0
- data/gm-notepad.gemspec +29 -0
- data/lib/gm/notepad/exceptions.rb +9 -0
- data/lib/gm/notepad/input_handler_registry.rb +32 -0
- data/lib/gm/notepad/input_handlers/default_handler.rb +43 -0
- data/lib/gm/notepad/input_handlers/help_handler.rb +36 -0
- data/lib/gm/notepad/input_handlers/query_table_handler.rb +64 -0
- data/lib/gm/notepad/input_handlers/query_table_names_handler.rb +41 -0
- data/lib/gm/notepad/input_handlers/write_line_handler.rb +32 -0
- data/lib/gm/notepad/input_handlers/write_to_table_handler.rb +56 -0
- data/lib/gm/notepad/input_processor.rb +46 -0
- data/lib/gm/notepad/line_evaluator.rb +26 -0
- data/lib/gm/notepad/line_renderer.rb +69 -0
- data/lib/gm/notepad/pad.rb +73 -0
- data/lib/gm/notepad/table.rb +65 -0
- data/lib/gm/notepad/table_entry.rb +40 -0
- data/lib/gm/notepad/table_registry.rb +82 -0
- data/lib/gm/notepad/version.rb +5 -0
- data/lib/gm/notepad.rb +9 -0
- metadata +155 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 4666e0ae345ed21a19074c884d3d5052287d70f79d61c005598c0176b5305a4c
|
4
|
+
data.tar.gz: fbe40603b8d2c7ac16176e04c8dd4c314728891a07cf291fc84522071faca9ef
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 29cc37dc451ebb46573cf70c39353d6c73f65962c2956f18ddbd0abedaaa3f9a921c3ce828c10c22f2afda7268fe51099a3255fae938ca0171bfa8ab0ccfde6f
|
7
|
+
data.tar.gz: d1d5a709afe55264d2bd694463837b14afaaec529c84f238ca6c6374b706c3dbaea41971d70badd6229a506aed7cdab2dcf4c660c798d22d6d91dae583be594e
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.travis.yml
ADDED
data/CODE_OF_CONDUCT.md
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
# Contributor Covenant Code of Conduct
|
2
|
+
|
3
|
+
## Our Pledge
|
4
|
+
|
5
|
+
In the interest of fostering an open and welcoming environment, we as
|
6
|
+
contributors and maintainers pledge to making participation in our project and
|
7
|
+
our community a harassment-free experience for everyone, regardless of age, body
|
8
|
+
size, disability, ethnicity, gender identity and expression, level of experience,
|
9
|
+
nationality, personal appearance, race, religion, or sexual identity and
|
10
|
+
orientation.
|
11
|
+
|
12
|
+
## Our Standards
|
13
|
+
|
14
|
+
Examples of behavior that contributes to creating a positive environment
|
15
|
+
include:
|
16
|
+
|
17
|
+
* Using welcoming and inclusive language
|
18
|
+
* Being respectful of differing viewpoints and experiences
|
19
|
+
* Gracefully accepting constructive criticism
|
20
|
+
* Focusing on what is best for the community
|
21
|
+
* Showing empathy towards other community members
|
22
|
+
|
23
|
+
Examples of unacceptable behavior by participants include:
|
24
|
+
|
25
|
+
* The use of sexualized language or imagery and unwelcome sexual attention or
|
26
|
+
advances
|
27
|
+
* Trolling, insulting/derogatory comments, and personal or political attacks
|
28
|
+
* Public or private harassment
|
29
|
+
* Publishing others' private information, such as a physical or electronic
|
30
|
+
address, without explicit permission
|
31
|
+
* Other conduct which could reasonably be considered inappropriate in a
|
32
|
+
professional setting
|
33
|
+
|
34
|
+
## Our Responsibilities
|
35
|
+
|
36
|
+
Project maintainers are responsible for clarifying the standards of acceptable
|
37
|
+
behavior and are expected to take appropriate and fair corrective action in
|
38
|
+
response to any instances of unacceptable behavior.
|
39
|
+
|
40
|
+
Project maintainers have the right and responsibility to remove, edit, or
|
41
|
+
reject comments, commits, code, wiki edits, issues, and other contributions
|
42
|
+
that are not aligned to this Code of Conduct, or to ban temporarily or
|
43
|
+
permanently any contributor for other behaviors that they deem inappropriate,
|
44
|
+
threatening, offensive, or harmful.
|
45
|
+
|
46
|
+
## Scope
|
47
|
+
|
48
|
+
This Code of Conduct applies both within project spaces and in public spaces
|
49
|
+
when an individual is representing the project or its community. Examples of
|
50
|
+
representing a project or community include using an official project e-mail
|
51
|
+
address, posting via an official social media account, or acting as an appointed
|
52
|
+
representative at an online or offline event. Representation of a project may be
|
53
|
+
further defined and clarified by project maintainers.
|
54
|
+
|
55
|
+
## Enforcement
|
56
|
+
|
57
|
+
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
58
|
+
reported by contacting the project team at jeremy.n.friesen@gmail.com. All
|
59
|
+
complaints will be reviewed and investigated and will result in a response that
|
60
|
+
is deemed necessary and appropriate to the circumstances. The project team is
|
61
|
+
obligated to maintain confidentiality with regard to the reporter of an incident.
|
62
|
+
Further details of specific enforcement policies may be posted separately.
|
63
|
+
|
64
|
+
Project maintainers who do not follow or enforce the Code of Conduct in good
|
65
|
+
faith may face temporary or permanent repercussions as determined by other
|
66
|
+
members of the project's leadership.
|
67
|
+
|
68
|
+
## Attribution
|
69
|
+
|
70
|
+
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
|
71
|
+
available at [http://contributor-covenant.org/version/1/4][version]
|
72
|
+
|
73
|
+
[homepage]: http://contributor-covenant.org
|
74
|
+
[version]: http://contributor-covenant.org/version/1/4/
|
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,118 @@
|
|
1
|
+
# GM::Notepad
|
2
|
+
|
3
|
+
A command-line tool to help with your GM-ing.
|
4
|
+
|
5
|
+
## Todo
|
6
|
+
|
7
|
+
- [ ] Colorize puts to `interactive` buffer
|
8
|
+
- [ ] Normalize `WriteToTableHandler` to use a renderer
|
9
|
+
- [ ] Normalize `WriteToTableHandler` to deliver on `grep` and `index` behavior
|
10
|
+
- [ ] Gracefully handle requesting an entry from a table with an index that does not exist (e.g. with test data try `+name[23]`)
|
11
|
+
- [ ] Gracefully handle `+name[]`, where "name" is a registered table
|
12
|
+
|
13
|
+
## To install
|
14
|
+
|
15
|
+
`$ gem install gm-notepad`
|
16
|
+
|
17
|
+
## Introduction
|
18
|
+
|
19
|
+
By default `gm-notepad` interacts with `$stdout` and `$stderr`. There are
|
20
|
+
three conceptual buffers:
|
21
|
+
|
22
|
+
* interactive (defaults to `$stderr`)
|
23
|
+
* output (defaults to `$stderr`)
|
24
|
+
* filesystem (defaults to your file system)
|
25
|
+
|
26
|
+
When you type a line, and hit \<enter\>, `gm-notepad` will evaluate the
|
27
|
+
line and render it to one or more of the buffers.
|
28
|
+
|
29
|
+
## Examples
|
30
|
+
|
31
|
+
### Simple Help
|
32
|
+
|
33
|
+
First, take a look at the help: `$ gm-notepad -h`
|
34
|
+
|
35
|
+
```console
|
36
|
+
Usage: gm-notepad [options] [files]
|
37
|
+
Note taking tool with random table expansion.
|
38
|
+
|
39
|
+
Examples:
|
40
|
+
$ gm-notepad
|
41
|
+
$ gm-notepad rolls.txt
|
42
|
+
$ echo '{name}' | gm-notepad
|
43
|
+
|
44
|
+
Specific options:
|
45
|
+
--timestamp Append a timestamp to the note (Default: false)
|
46
|
+
-c, --config_reporting Dump the configuration data (Default: false)
|
47
|
+
-d, --defer_output Defer output until system close (Default: true)
|
48
|
+
-p, --path=PATH Path for {table_name}.<config.table_extension> files (Default: ["."])
|
49
|
+
-tTABLE_EXTENSION, Path for {table_name}.<config.table_extension> files (Default: ".txt")
|
50
|
+
--table_extension
|
51
|
+
-l, --list_tables List tables loaded (Default: nil)
|
52
|
+
-h, --help You're looking at it!
|
53
|
+
```
|
54
|
+
|
55
|
+
At it's core, `gm-shell` interacts with named tables. A named table is a file
|
56
|
+
found amongst the specified `paths` and has the specified `table_extension`.
|
57
|
+
Let's take a look at the defaults. In a new shell, type: `$ gm-notepad -c`
|
58
|
+
|
59
|
+
Which writes the following to the `interactive` buffer (eg. `$stderr`)::
|
60
|
+
|
61
|
+
```console
|
62
|
+
=> # Configuration Parameters:
|
63
|
+
=> # config[:config_reporting] = true
|
64
|
+
=> # config[:defer_output] = true
|
65
|
+
=> # config[:interactive_buffer] = #<IO:<STDERR>>
|
66
|
+
=> # config[:output_buffer] = #<IO:<STDOUT>>
|
67
|
+
=> # config[:paths] = ["."]
|
68
|
+
=> # config[:table_extension] = ".txt"
|
69
|
+
=> # config[:with_timestamp] = false
|
70
|
+
```
|
71
|
+
|
72
|
+
You'll need to exit out (CTRL+D).
|
73
|
+
|
74
|
+
By default `gm-notepad` will load as tables all files matching the following
|
75
|
+
glob: `./**/*.txt`.
|
76
|
+
|
77
|
+
Included in the gem's test suite are three files:
|
78
|
+
|
79
|
+
* `./spec/fixtures/name.txt`
|
80
|
+
* `./spec/fixtures/first-name.txt`
|
81
|
+
* `./spec/fixtures/last-name.txt`
|
82
|
+
|
83
|
+
When I run `gm-notepad -l`, `gm-notepad` does the following:
|
84
|
+
|
85
|
+
* load all found tables
|
86
|
+
* puts the config (see above) to the `interactive` buffer
|
87
|
+
* puts the table_names to the `interactive` buffer
|
88
|
+
* exits
|
89
|
+
|
90
|
+
Below are the table names when you run the `gm-notepad` against the
|
91
|
+
repository:
|
92
|
+
|
93
|
+
```console
|
94
|
+
=> first-name
|
95
|
+
=> last-name
|
96
|
+
=> name
|
97
|
+
```
|
98
|
+
|
99
|
+
Now let's load `gm-notepad` for interaction. In the terminal, type:
|
100
|
+
`$ gm-notepad`
|
101
|
+
|
102
|
+
You now have an interactive shell for `gm-notepad`. Type `?` and hit
|
103
|
+
\<enter\>.
|
104
|
+
|
105
|
+
`gm-notepad` will write the following to `interactive` buffer (eg. `$stderr`):
|
106
|
+
|
107
|
+
```console
|
108
|
+
=> Prefixes:
|
109
|
+
=> ? - Help (this command)
|
110
|
+
=> + - Query table names and contents
|
111
|
+
=> <table_name> - Write the results to the given table
|
112
|
+
=>
|
113
|
+
=> Tokens:
|
114
|
+
=> ! - Skip expansion
|
115
|
+
=> /search/ - Grep for the given 'search' within the prefix
|
116
|
+
=> [index] - Target a specific 'index'
|
117
|
+
=> {table_name} - expand_line the given 'table_name'
|
118
|
+
```
|
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "gm/notepad"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
data/exe/gm-notepad
ADDED
@@ -0,0 +1,83 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'gm/notepad'
|
3
|
+
|
4
|
+
require 'optparse'
|
5
|
+
config = {
|
6
|
+
config_reporting: false,
|
7
|
+
defer_output: true,
|
8
|
+
interactive_buffer: $stderr,
|
9
|
+
output_buffer: $stdout,
|
10
|
+
paths: ['.'],
|
11
|
+
table_extension: '.txt',
|
12
|
+
with_timestamp: false
|
13
|
+
}
|
14
|
+
|
15
|
+
command_name = File.basename(__FILE__)
|
16
|
+
|
17
|
+
OptionParser.new do |options|
|
18
|
+
# This banner is the first line of your help documentation.
|
19
|
+
options.set_banner "Usage: #{command_name} [options] [files]\n" \
|
20
|
+
"Note taking tool with random table expansion.\n\n" \
|
21
|
+
"Examples:\n" \
|
22
|
+
"\t$ #{command_name}\n" \
|
23
|
+
"\t$ #{command_name} rolls.txt\n" \
|
24
|
+
"\t$ echo '{name}' | #{command_name}"
|
25
|
+
|
26
|
+
# Separator just adds a new line with the specified text.
|
27
|
+
options.separator ""
|
28
|
+
options.separator "Specific options:"
|
29
|
+
|
30
|
+
options.on("-t", "--timestamp", "Append a timestamp to the note (Default: #{config[:with_timestamp].inspect})") do |timestamp|
|
31
|
+
config[:with_timestamp] = timestamp
|
32
|
+
end
|
33
|
+
|
34
|
+
options.on("-c", "--config_reporting", "Dump the configuration data (Default: #{config[:config_reporting].inspect})") do |config_reporting|
|
35
|
+
config[:config_reporting] = config_reporting
|
36
|
+
end
|
37
|
+
|
38
|
+
options.on("-d", "--defer_output", "Defer output until system close (Default: #{config[:defer_output].inspect})") do |defer_output|
|
39
|
+
config[:defer_output] = defer_output
|
40
|
+
end
|
41
|
+
|
42
|
+
options.on("-pPATH", "--path=PATH", String, "Path for {table_name}.<config.table_extension> files (Default: #{config[:paths].inspect})") do |path|
|
43
|
+
config[:paths] << path
|
44
|
+
end
|
45
|
+
|
46
|
+
options.on("-tTABLE_EXTENSION", "--table_extension=TABLE_EXTENSION", String, "Path for {table_name}.<config.table_extension> files (Default: #{config[:table_extension].inspect})") do |table_extension|
|
47
|
+
config[:table_extension] = table_extension
|
48
|
+
end
|
49
|
+
|
50
|
+
options.on("-l", "--list_tables", "List tables loaded (Default: #{config[:list_tables].inspect})") do |list_tables|
|
51
|
+
config[:list_tables] = list_tables
|
52
|
+
end
|
53
|
+
|
54
|
+
options.on_tail("-h", "--help", "You're looking at it!") do
|
55
|
+
$stderr.puts options
|
56
|
+
exit 1
|
57
|
+
end
|
58
|
+
end.parse!
|
59
|
+
|
60
|
+
if config[:list_tables]
|
61
|
+
notepad = Gm::Notepad.new(config.merge(config_reporting: true))
|
62
|
+
notepad.process(input: "+")
|
63
|
+
exit(1)
|
64
|
+
end
|
65
|
+
|
66
|
+
begin
|
67
|
+
@notepad = Gm::Notepad.new(**config)
|
68
|
+
# Keep reading lines of input as long as they're coming.
|
69
|
+
while input = ARGF.gets
|
70
|
+
input.each_line do |input|
|
71
|
+
begin
|
72
|
+
@notepad.process(input: input)
|
73
|
+
rescue Errno::EPIPE
|
74
|
+
# sysexits(3) specifies that exit code 74 represent an IO error,
|
75
|
+
# which is the likely situation
|
76
|
+
@notepad.close!
|
77
|
+
exit(74)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
ensure
|
82
|
+
@notepad.close!
|
83
|
+
end
|
data/gm-notepad.gemspec
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path("../lib", __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require "gm/notepad/version"
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "gm-notepad"
|
8
|
+
spec.version = Gm::Notepad::VERSION
|
9
|
+
spec.authors = ["Jeremy Friesen"]
|
10
|
+
spec.email = ["jeremy.n.friesen@gmail.com"]
|
11
|
+
|
12
|
+
spec.summary = %q{A command line tool for GM-ing}
|
13
|
+
spec.description = %q{A command line tool for GM-ing}
|
14
|
+
spec.homepage = "https://github.com/jeremyf/gm-notepad"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
17
|
+
f.match(%r{^(test|spec|features)/})
|
18
|
+
end
|
19
|
+
spec.bindir = "exe"
|
20
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
21
|
+
spec.require_paths = ["lib"]
|
22
|
+
|
23
|
+
spec.add_dependency "dice_parser"
|
24
|
+
spec.add_development_dependency "bundler"
|
25
|
+
spec.add_development_dependency "rake"
|
26
|
+
spec.add_development_dependency "rspec"
|
27
|
+
spec.add_development_dependency "pry-byebug"
|
28
|
+
spec.add_development_dependency "rspec-its"
|
29
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require_relative 'input_handlers/default_handler'
|
2
|
+
module Gm
|
3
|
+
module Notepad
|
4
|
+
# Responsible for registering the various input handlers
|
5
|
+
class InputHandlerRegistry
|
6
|
+
def initialize
|
7
|
+
@registry = []
|
8
|
+
yield(self) if block_given?
|
9
|
+
end
|
10
|
+
|
11
|
+
def handler_for(input:, skip_default: false)
|
12
|
+
handler = nil
|
13
|
+
@registry.each do |handler_builder|
|
14
|
+
if handler = handler_builder.build_if_handled(input: input)
|
15
|
+
break
|
16
|
+
end
|
17
|
+
end
|
18
|
+
return handler if handler
|
19
|
+
return nil if skip_default
|
20
|
+
default_handler_builder.build_if_handled(input: input)
|
21
|
+
end
|
22
|
+
|
23
|
+
def register(handler:)
|
24
|
+
@registry << handler
|
25
|
+
end
|
26
|
+
|
27
|
+
def default_handler_builder
|
28
|
+
InputHandlers::DefaultHandler
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module Gm
|
2
|
+
module Notepad
|
3
|
+
module InputHandlers
|
4
|
+
class DefaultHandler
|
5
|
+
def self.build_if_handled(input:)
|
6
|
+
return false unless handles?(input: input)
|
7
|
+
new(input: input)
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.handles?(input:)
|
11
|
+
true
|
12
|
+
end
|
13
|
+
|
14
|
+
def initialize(input:, table_registry: nil)
|
15
|
+
self.to_interactive = false
|
16
|
+
self.to_output = false
|
17
|
+
self.to_filesystem = false
|
18
|
+
self.expand_line = false
|
19
|
+
self.input = input
|
20
|
+
self.table_registry = table_registry
|
21
|
+
after_initialize!
|
22
|
+
end
|
23
|
+
attr_accessor :table_registry, :to_interactive, :to_output, :expand_line, :input, :to_filesystem
|
24
|
+
|
25
|
+
def after_initialize!
|
26
|
+
end
|
27
|
+
|
28
|
+
def lines
|
29
|
+
[]
|
30
|
+
end
|
31
|
+
|
32
|
+
alias expand_line? expand_line
|
33
|
+
|
34
|
+
def each_line_with_parameters
|
35
|
+
lines.each do |line|
|
36
|
+
line = table_registry.evaluate(line: line.to_s.strip) if expand_line?
|
37
|
+
yield(line, to_output: to_output, to_interactive: to_interactive)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require_relative "default_handler"
|
2
|
+
module Gm
|
3
|
+
module Notepad
|
4
|
+
module InputHandlers
|
5
|
+
class HelpHandler < DefaultHandler
|
6
|
+
HELP_PREFIX = '?'.freeze
|
7
|
+
|
8
|
+
def self.handles?(input:)
|
9
|
+
return false unless input[0] == HELP_PREFIX
|
10
|
+
true
|
11
|
+
end
|
12
|
+
|
13
|
+
def after_initialize!
|
14
|
+
self.to_interactive = true
|
15
|
+
self.to_output = false
|
16
|
+
self.expand_line = false
|
17
|
+
end
|
18
|
+
|
19
|
+
def lines
|
20
|
+
[
|
21
|
+
"Prefixes:",
|
22
|
+
"\t? - Help (this command)",
|
23
|
+
"\t+ - Query table names and contents",
|
24
|
+
"\t<table_name> - Write the results to the given table",
|
25
|
+
"",
|
26
|
+
"Tokens:",
|
27
|
+
"\t! - Skip expansion",
|
28
|
+
"\t/search/ - Grep for the given 'search' within the prefix",
|
29
|
+
"\t[index] - Target a specific 'index'",
|
30
|
+
"\t{table_name} - expand_line the given 'table_name'"
|
31
|
+
]
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require_relative "default_handler"
|
2
|
+
module Gm
|
3
|
+
module Notepad
|
4
|
+
module InputHandlers
|
5
|
+
class QueryTableHandler < DefaultHandler
|
6
|
+
QUERY_TABLE_NAMES_PREFIX = '+'.freeze
|
7
|
+
def self.handles?(input:)
|
8
|
+
# Does not have the table prefix
|
9
|
+
return false unless input[0] == QUERY_TABLE_NAMES_PREFIX
|
10
|
+
# It is only the table prefix
|
11
|
+
return false if input == QUERY_TABLE_NAMES_PREFIX
|
12
|
+
# It is querying all tables by way of grep
|
13
|
+
return false if input[0..1] == "#{QUERY_TABLE_NAMES_PREFIX}/"
|
14
|
+
true
|
15
|
+
end
|
16
|
+
|
17
|
+
WITH_GREP_REGEXP = %r{(?<declaration>\/(?<grep>[^\/]+)/)}
|
18
|
+
WITH_INDEX_REGEXP = %r{(?<declaration>\[(?<index>[^\]]+)\])}
|
19
|
+
NON_EXPANDING_CHARATER = '!'.freeze
|
20
|
+
def after_initialize!
|
21
|
+
self.expand_line = false
|
22
|
+
self.to_output = false
|
23
|
+
self.to_interactive = true
|
24
|
+
|
25
|
+
line = input[1..-1].to_s
|
26
|
+
self.expand_line = false
|
27
|
+
if match = WITH_INDEX_REGEXP.match(line)
|
28
|
+
line = line.sub(match[:declaration], '')
|
29
|
+
index = match[:index]
|
30
|
+
self.index = index
|
31
|
+
elsif match = WITH_GREP_REGEXP.match(line)
|
32
|
+
line = line.sub(match[:declaration], '')
|
33
|
+
grep = match[:grep]
|
34
|
+
self.grep = grep
|
35
|
+
end
|
36
|
+
if line[-1] == NON_EXPANDING_CHARATER
|
37
|
+
line = line[0..-2]
|
38
|
+
end
|
39
|
+
self.table_name = line.downcase
|
40
|
+
end
|
41
|
+
|
42
|
+
attr_accessor :index, :grep, :table_name
|
43
|
+
|
44
|
+
def lines
|
45
|
+
begin
|
46
|
+
table = table_registry.fetch_table(name: table_name)
|
47
|
+
rescue KeyError
|
48
|
+
message = "Unknown table #{table_name.inspect}. Did you mean: "
|
49
|
+
message += table_registry.table_names.grep(/\A#{table_name}/).map(&:inspect).join(", ")
|
50
|
+
return [message]
|
51
|
+
end
|
52
|
+
if index
|
53
|
+
[table.lookup(index: index)]
|
54
|
+
elsif grep
|
55
|
+
regexp = %r{#{grep}}i
|
56
|
+
table.grep(regexp)
|
57
|
+
else
|
58
|
+
table.all
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require_relative "default_handler"
|
2
|
+
|
3
|
+
module Gm
|
4
|
+
module Notepad
|
5
|
+
module InputHandlers
|
6
|
+
class QueryTableNamesHandler < DefaultHandler
|
7
|
+
QUERY_TABLE_NAMES_PREFIX = '+'.freeze
|
8
|
+
def self.handles?(input:)
|
9
|
+
# Does not have the table prefix
|
10
|
+
return false unless input[0] == QUERY_TABLE_NAMES_PREFIX
|
11
|
+
# It is only the table prefix
|
12
|
+
return true if input == QUERY_TABLE_NAMES_PREFIX
|
13
|
+
# It is querying all tables by way of grep
|
14
|
+
return true if input[0..1] == "#{QUERY_TABLE_NAMES_PREFIX}/"
|
15
|
+
false
|
16
|
+
end
|
17
|
+
|
18
|
+
WITH_GREP_REGEXP = %r{(?<declaration>\/(?<grep>[^\/]+)/)}
|
19
|
+
def after_initialize!
|
20
|
+
self.expand_line = false
|
21
|
+
self.to_output = false
|
22
|
+
self.to_interactive = true
|
23
|
+
|
24
|
+
line = input[1..-1]
|
25
|
+
if match = WITH_GREP_REGEXP.match(line)
|
26
|
+
line = line.sub(match[:declaration], '')
|
27
|
+
self.grep = match[:grep]
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
attr_accessor :grep
|
32
|
+
|
33
|
+
def lines
|
34
|
+
table_names = table_registry.table_names
|
35
|
+
return table_names unless grep
|
36
|
+
table_names.grep(%r{#{grep}})
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require_relative "default_handler"
|
2
|
+
|
3
|
+
module Gm
|
4
|
+
module Notepad
|
5
|
+
module InputHandlers
|
6
|
+
class WriteLineHandler < DefaultHandler
|
7
|
+
NON_EXPANDING_CHARATER = '!'.freeze
|
8
|
+
def self.handles?(input:)
|
9
|
+
true
|
10
|
+
end
|
11
|
+
|
12
|
+
attr_accessor :line
|
13
|
+
def after_initialize!
|
14
|
+
self.expand_line = false
|
15
|
+
self.to_output = true
|
16
|
+
self.to_interactive = true
|
17
|
+
if input[0] == NON_EXPANDING_CHARATER
|
18
|
+
self.line = input[1..-1].strip
|
19
|
+
self.expand_line = false
|
20
|
+
else
|
21
|
+
self.line = input.strip
|
22
|
+
self.expand_line = true
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def lines
|
27
|
+
[line]
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require_relative "default_handler"
|
2
|
+
|
3
|
+
module Gm
|
4
|
+
module Notepad
|
5
|
+
module InputHandlers
|
6
|
+
class WriteToTableHandler < DefaultHandler
|
7
|
+
def self.handles?(input:)
|
8
|
+
return true if input[0] == "<"
|
9
|
+
end
|
10
|
+
|
11
|
+
attr_accessor :index, :grep, :table_name, :line
|
12
|
+
NON_EXPANDING_CHARATER = '!'.freeze
|
13
|
+
WITH_INDEX_REGEXP = %r{(?<declaration>\[(?<index>[^\]]+)\])}
|
14
|
+
WITH_GREP_REGEXP = %r{(?<declaration>\/(?<grep>[^\/]+)/)}
|
15
|
+
WITH_WRITE_TARGET_REGEXP = %r{\A<(?<table_name>[^>]+)>(?<line>.*)}
|
16
|
+
def after_initialize!
|
17
|
+
self.to_filesystem = true
|
18
|
+
self.to_interactive = true
|
19
|
+
|
20
|
+
if match = WITH_WRITE_TARGET_REGEXP.match(input)
|
21
|
+
line = match[:line].strip
|
22
|
+
table_name = match[:table_name]
|
23
|
+
if index_match = WITH_INDEX_REGEXP.match(table_name)
|
24
|
+
table_name = table_name.sub(index_match[:declaration], '')
|
25
|
+
self.index = index_match[:index]
|
26
|
+
elsif grep_match = WITH_GREP_REGEXP.match(table_name)
|
27
|
+
table_name = table_name.sub(grep_match[:declaration], '')
|
28
|
+
self.grep = grep_match[:grep]
|
29
|
+
end
|
30
|
+
self.table_name = table_name.downcase
|
31
|
+
else
|
32
|
+
raise "I don't know what to do"
|
33
|
+
end
|
34
|
+
if line[0] == NON_EXPANDING_CHARATER
|
35
|
+
self.expand_line = false
|
36
|
+
self.line = line[1..-1]
|
37
|
+
else
|
38
|
+
self.expand_line = true
|
39
|
+
end
|
40
|
+
self.line = line.strip
|
41
|
+
end
|
42
|
+
|
43
|
+
def lines
|
44
|
+
if index
|
45
|
+
elsif grep
|
46
|
+
end
|
47
|
+
if expand_line
|
48
|
+
else
|
49
|
+
end
|
50
|
+
table_registry.append(table_name: table_name, line: line, write: true)
|
51
|
+
[]
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module Gm
|
2
|
+
module Notepad
|
3
|
+
# Responsible for processing the given input into a renderable state
|
4
|
+
class InputProcessor
|
5
|
+
def initialize(table_registry:, **config)
|
6
|
+
self.table_registry = table_registry
|
7
|
+
self.input_handler_registry = config.fetch(:input_handler_registry) { default_input_handler_registry }
|
8
|
+
end
|
9
|
+
|
10
|
+
def process(input:)
|
11
|
+
processor = build_for(input: input)
|
12
|
+
processor.each_line_with_parameters do |*args|
|
13
|
+
yield(*args)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
attr_accessor :table_registry, :input_handler_registry
|
18
|
+
private :table_registry=, :input_handler_registry
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def build_for(input:)
|
23
|
+
input = input.to_s.strip
|
24
|
+
handler = input_handler_registry.handler_for(input: input)
|
25
|
+
handler.table_registry = table_registry
|
26
|
+
handler
|
27
|
+
end
|
28
|
+
|
29
|
+
def default_input_handler_registry
|
30
|
+
require_relative "input_handler_registry"
|
31
|
+
require_relative "input_handlers/help_handler"
|
32
|
+
require_relative "input_handlers/query_table_handler"
|
33
|
+
require_relative "input_handlers/query_table_names_handler"
|
34
|
+
require_relative "input_handlers/write_to_table_handler"
|
35
|
+
require_relative "input_handlers/write_line_handler"
|
36
|
+
InputHandlerRegistry.new do |registry|
|
37
|
+
registry.register(handler: InputHandlers::HelpHandler)
|
38
|
+
registry.register(handler: InputHandlers::QueryTableHandler)
|
39
|
+
registry.register(handler: InputHandlers::QueryTableNamesHandler)
|
40
|
+
registry.register(handler: InputHandlers::WriteToTableHandler)
|
41
|
+
registry.register(handler: InputHandlers::WriteLineHandler)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'dice'
|
2
|
+
module Gm
|
3
|
+
module Notepad
|
4
|
+
# Responsible for recording entries and then dumping them accordingly.
|
5
|
+
class LineEvaluator
|
6
|
+
TABLE_NAME_REGEXP = %r{(?<table_name_container>\{(?<table_name>[^\}]+)\})}
|
7
|
+
DICE_REGEXP = %r{(?<dice_container>\[(?<dice>[^\]]+)\])}
|
8
|
+
def call(line:, table_lookup_function:, expand_line: true)
|
9
|
+
return line unless expand_line
|
10
|
+
while match = line.match(TABLE_NAME_REGEXP)
|
11
|
+
evaluated_table_name = table_lookup_function.call(table_name: match[:table_name].strip)
|
12
|
+
line = line.sub(match[:table_name_container], evaluated_table_name)
|
13
|
+
end
|
14
|
+
while match = line.match(DICE_REGEXP)
|
15
|
+
if parsed_dice = Dice.parse(match[:dice])
|
16
|
+
evaluated_dice = "#{parsed_dice.evaluate} (#{match[:dice]})"
|
17
|
+
else
|
18
|
+
evaluated_dice = "(#{match[:dice]})"
|
19
|
+
end
|
20
|
+
line = line.sub(match[:dice_container], evaluated_dice)
|
21
|
+
end
|
22
|
+
line
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require 'time'
|
2
|
+
module Gm
|
3
|
+
module Notepad
|
4
|
+
# Responsible for rendering lines to the corresponding buffers
|
5
|
+
class LineRenderer
|
6
|
+
def initialize(with_timestamp: false, defer_output:, output_buffer: default_output_buffer, interactive_buffer: default_interactive_buffer)
|
7
|
+
@output_buffer = output_buffer
|
8
|
+
@interactive_buffer = interactive_buffer
|
9
|
+
@with_timestamp = with_timestamp
|
10
|
+
@defer_output = defer_output
|
11
|
+
@lines = []
|
12
|
+
yield(self) if block_given?
|
13
|
+
end
|
14
|
+
|
15
|
+
def call(line, to_output: false, to_interactive: true, as_of: Time.now)
|
16
|
+
render_output(line, defer_output: defer_output, as_of: as_of) if to_output
|
17
|
+
render_interactive(line) if to_interactive
|
18
|
+
end
|
19
|
+
|
20
|
+
def close!
|
21
|
+
if defer_output
|
22
|
+
@lines.each do |line|
|
23
|
+
output_buffer.puts(line)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
# When true, we defer_output writing until we close the notepad
|
31
|
+
# When false, we write immediately to the output buffer
|
32
|
+
attr_reader :defer_output
|
33
|
+
|
34
|
+
# The receiver of interactive messages
|
35
|
+
attr_reader :interactive_buffer
|
36
|
+
|
37
|
+
# The receiver of output
|
38
|
+
attr_reader :output_buffer
|
39
|
+
|
40
|
+
# When writing to output_buffer, should we prefix with a timestamp?
|
41
|
+
def with_timestamp?
|
42
|
+
@with_timestamp
|
43
|
+
end
|
44
|
+
|
45
|
+
def render_output(line, defer_output:, as_of:)
|
46
|
+
if with_timestamp?
|
47
|
+
line = "#{as_of}\t#{line}"
|
48
|
+
end
|
49
|
+
if defer_output
|
50
|
+
@lines << line
|
51
|
+
else
|
52
|
+
output_buffer.puts(line)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def render_interactive(line)
|
57
|
+
interactive_buffer.puts("=>\t#{line}")
|
58
|
+
end
|
59
|
+
|
60
|
+
def default_output_buffer
|
61
|
+
$stdout
|
62
|
+
end
|
63
|
+
|
64
|
+
def default_interactive_buffer
|
65
|
+
$stderr
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
module Gm
|
2
|
+
module Notepad
|
3
|
+
# Responsible for recording entries and then dumping them accordingly.
|
4
|
+
class Pad
|
5
|
+
attr_reader :config
|
6
|
+
def initialize(**config)
|
7
|
+
self.config = config
|
8
|
+
self.table_registry = config.fetch(:table_registry) { default_table_registry }
|
9
|
+
self.renderer = config.fetch(:renderer) { default_renderer }
|
10
|
+
self.input_processor = config.fetch(:input_processor) { default_input_processor }
|
11
|
+
open!
|
12
|
+
end
|
13
|
+
|
14
|
+
def process(input:)
|
15
|
+
input_processor.process(input: input) do |*args|
|
16
|
+
renderer.call(*args)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def close!
|
21
|
+
@renderer.close!
|
22
|
+
end
|
23
|
+
|
24
|
+
attr_reader :table_registry
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
attr_reader :renderer
|
29
|
+
def open!
|
30
|
+
return unless config[:config_reporting]
|
31
|
+
renderer.call("# Configuration Parameters:", to_interactive: true, to_output: true)
|
32
|
+
config.each do |key, value|
|
33
|
+
line = "# config[#{key.inspect}] = #{value.inspect}"
|
34
|
+
renderer.call(line, to_interactive: true, to_output: true)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
attr_accessor :renderer, :input_processor
|
39
|
+
attr_writer :config, :table_registry
|
40
|
+
|
41
|
+
def default_input_processor
|
42
|
+
require_relative "input_processor"
|
43
|
+
InputProcessor.new(table_registry: table_registry)
|
44
|
+
end
|
45
|
+
|
46
|
+
def default_table_registry
|
47
|
+
require_relative "table_registry"
|
48
|
+
TableRegistry.load_for(
|
49
|
+
paths: config.fetch(:paths, []),
|
50
|
+
table_extension: config.fetch(:table_extension, ".txt")
|
51
|
+
)
|
52
|
+
end
|
53
|
+
|
54
|
+
def default_renderer
|
55
|
+
require_relative 'line_renderer'
|
56
|
+
LineRenderer.new(
|
57
|
+
with_timestamp: config.fetch(:with_timestamp, false),
|
58
|
+
defer_output: config.fetch(:defer_output, false),
|
59
|
+
output_buffer: config.fetch(:output_buffer, default_output_buffer),
|
60
|
+
interactive_buffer: config.fetch(:interactive_buffer, default_interactive_buffer)
|
61
|
+
)
|
62
|
+
end
|
63
|
+
|
64
|
+
def default_output_buffer
|
65
|
+
$stdout
|
66
|
+
end
|
67
|
+
|
68
|
+
def default_interactive_buffer
|
69
|
+
$stderr
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
require_relative "exceptions"
|
2
|
+
require_relative "table_entry"
|
3
|
+
|
4
|
+
module Gm
|
5
|
+
module Notepad
|
6
|
+
class Table
|
7
|
+
def initialize(table_name:, lines:, filename: nil)
|
8
|
+
self.table_name = table_name
|
9
|
+
self.filename = filename
|
10
|
+
process(lines: lines)
|
11
|
+
end
|
12
|
+
|
13
|
+
def lookup(index: false)
|
14
|
+
if index
|
15
|
+
@table.fetch(index)
|
16
|
+
else
|
17
|
+
@table.values[random_index]
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def all
|
22
|
+
@table.values
|
23
|
+
end
|
24
|
+
|
25
|
+
def grep(expression)
|
26
|
+
returning_value = []
|
27
|
+
@table.each_value do |entry|
|
28
|
+
if expression.match(entry.entry_column)
|
29
|
+
returning_value << entry
|
30
|
+
end
|
31
|
+
end
|
32
|
+
returning_value
|
33
|
+
end
|
34
|
+
|
35
|
+
def append(line:, write: false)
|
36
|
+
process(lines: [line])
|
37
|
+
return unless filename
|
38
|
+
return unless write
|
39
|
+
File.open(filename, "a") do |file|
|
40
|
+
file.puts(line)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
attr_accessor :table_name, :filename
|
47
|
+
|
48
|
+
def random_index
|
49
|
+
rand(@table.size)
|
50
|
+
end
|
51
|
+
|
52
|
+
def process(lines:)
|
53
|
+
@table = {}
|
54
|
+
lines.each do |line|
|
55
|
+
entry = TableEntry.new(line: line)
|
56
|
+
entry.lookup_range.each do |i|
|
57
|
+
key = i.to_s
|
58
|
+
raise DuplicateKeyError.new(key: table_name, object: self) if @table.key?(key)
|
59
|
+
@table[key] = entry
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module Gm
|
2
|
+
module Notepad
|
3
|
+
TABLE_ENTRY_SEPARATOR = "|".freeze
|
4
|
+
TABLE_ENTRY_RANGE_MARKER = "-".freeze
|
5
|
+
class TableEntry
|
6
|
+
def initialize(line:)
|
7
|
+
self.lookup_column, self.entry_column = line.split(TABLE_ENTRY_SEPARATOR)
|
8
|
+
end
|
9
|
+
|
10
|
+
include Comparable
|
11
|
+
def <=>(other)
|
12
|
+
to_str <=> String(other)
|
13
|
+
end
|
14
|
+
|
15
|
+
NUMBER_RANGE_REGEXP = %r{(?<left>\d+) *- *(?<right>\d+)}
|
16
|
+
def lookup_range
|
17
|
+
if match = NUMBER_RANGE_REGEXP.match(lookup_column)
|
18
|
+
(match[:left].to_i..match[:right].to_i).map(&:to_s)
|
19
|
+
else
|
20
|
+
[lookup_column]
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
attr_reader :lookup_column, :entry_column
|
25
|
+
|
26
|
+
alias to_s entry_column
|
27
|
+
alias to_str entry_column
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def lookup_column=(input)
|
32
|
+
@lookup_column = input.strip.freeze
|
33
|
+
end
|
34
|
+
|
35
|
+
def entry_column=(input)
|
36
|
+
@entry_column = input.strip.freeze
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
require_relative "table"
|
2
|
+
require_relative "exceptions"
|
3
|
+
|
4
|
+
module Gm
|
5
|
+
module Notepad
|
6
|
+
# Responsible for loading and registering all of the named tables
|
7
|
+
class TableRegistry
|
8
|
+
def self.load_for(paths:, table_extension: ".txt")
|
9
|
+
table_registry = new(paths: paths, table_extension: table_extension)
|
10
|
+
paths.each do |path|
|
11
|
+
Dir.glob(File.join(path, "**/*#{table_extension}")).each do |filename|
|
12
|
+
table_name = File.basename(filename, table_extension)
|
13
|
+
table_registry.register_by_filename(table_name: table_name, filename: filename)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
table_registry
|
17
|
+
end
|
18
|
+
|
19
|
+
def initialize(line_evaluator: default_line_evaluator, paths: [], table_extension: ".txt")
|
20
|
+
self.line_evaluator = line_evaluator
|
21
|
+
self.table_extension = table_extension
|
22
|
+
self.paths = paths
|
23
|
+
@registry = {}
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
attr_accessor :line_evaluator, :paths, :table_extension
|
28
|
+
public
|
29
|
+
|
30
|
+
def table_names
|
31
|
+
@registry.keys.sort
|
32
|
+
end
|
33
|
+
|
34
|
+
def fetch_table(name:)
|
35
|
+
@registry.fetch(name)
|
36
|
+
end
|
37
|
+
|
38
|
+
def append(table_name:, line:, write:)
|
39
|
+
table = nil
|
40
|
+
begin
|
41
|
+
table = fetch_table(name: table_name)
|
42
|
+
rescue KeyError => e
|
43
|
+
filename = File.join(paths.first || ".", "#{table_name}#{table_extension}")
|
44
|
+
table = register(table_name: table_name, lines: [], filename: filename)
|
45
|
+
end
|
46
|
+
table.append(line: line, write: write)
|
47
|
+
end
|
48
|
+
|
49
|
+
def register_by_filename(table_name:, filename:)
|
50
|
+
content = File.read(filename)
|
51
|
+
register(table_name: table_name, lines: content.split("\n"), filename: filename)
|
52
|
+
end
|
53
|
+
|
54
|
+
def register_by_string(table_name:, string:)
|
55
|
+
register(table_name: table_name, lines: string.split("\n"))
|
56
|
+
end
|
57
|
+
|
58
|
+
def lookup(table_name:, **kwargs)
|
59
|
+
table = @registry.fetch(table_name)
|
60
|
+
table.lookup(**kwargs)
|
61
|
+
rescue KeyError
|
62
|
+
"(undefined #{table_name})"
|
63
|
+
end
|
64
|
+
|
65
|
+
def evaluate(line:)
|
66
|
+
line_evaluator.call(line: line, table_lookup_function: method(:lookup))
|
67
|
+
end
|
68
|
+
|
69
|
+
private
|
70
|
+
|
71
|
+
def register(table_name:, lines:, filename: nil)
|
72
|
+
raise DuplicateKeyError.new(key: table_name, object: self) if @registry.key?(table_name)
|
73
|
+
@registry[table_name] = Table.new(table_name: table_name, lines: lines, filename: filename)
|
74
|
+
end
|
75
|
+
|
76
|
+
def default_line_evaluator
|
77
|
+
require_relative 'line_evaluator'
|
78
|
+
LineEvaluator.new
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
data/lib/gm/notepad.rb
ADDED
metadata
ADDED
@@ -0,0 +1,155 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: gm-notepad
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Jeremy Friesen
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2019-07-26 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: dice_parser
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: bundler
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rspec
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: pry-byebug
|
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'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rspec-its
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
description: A command line tool for GM-ing
|
98
|
+
email:
|
99
|
+
- jeremy.n.friesen@gmail.com
|
100
|
+
executables:
|
101
|
+
- gm-notepad
|
102
|
+
extensions: []
|
103
|
+
extra_rdoc_files: []
|
104
|
+
files:
|
105
|
+
- ".gitignore"
|
106
|
+
- ".rspec"
|
107
|
+
- ".travis.yml"
|
108
|
+
- CODE_OF_CONDUCT.md
|
109
|
+
- Gemfile
|
110
|
+
- README.md
|
111
|
+
- Rakefile
|
112
|
+
- bin/console
|
113
|
+
- bin/setup
|
114
|
+
- exe/gm-notepad
|
115
|
+
- gm-notepad.gemspec
|
116
|
+
- lib/gm/notepad.rb
|
117
|
+
- lib/gm/notepad/exceptions.rb
|
118
|
+
- lib/gm/notepad/input_handler_registry.rb
|
119
|
+
- lib/gm/notepad/input_handlers/default_handler.rb
|
120
|
+
- lib/gm/notepad/input_handlers/help_handler.rb
|
121
|
+
- lib/gm/notepad/input_handlers/query_table_handler.rb
|
122
|
+
- lib/gm/notepad/input_handlers/query_table_names_handler.rb
|
123
|
+
- lib/gm/notepad/input_handlers/write_line_handler.rb
|
124
|
+
- lib/gm/notepad/input_handlers/write_to_table_handler.rb
|
125
|
+
- lib/gm/notepad/input_processor.rb
|
126
|
+
- lib/gm/notepad/line_evaluator.rb
|
127
|
+
- lib/gm/notepad/line_renderer.rb
|
128
|
+
- lib/gm/notepad/pad.rb
|
129
|
+
- lib/gm/notepad/table.rb
|
130
|
+
- lib/gm/notepad/table_entry.rb
|
131
|
+
- lib/gm/notepad/table_registry.rb
|
132
|
+
- lib/gm/notepad/version.rb
|
133
|
+
homepage: https://github.com/jeremyf/gm-notepad
|
134
|
+
licenses: []
|
135
|
+
metadata: {}
|
136
|
+
post_install_message:
|
137
|
+
rdoc_options: []
|
138
|
+
require_paths:
|
139
|
+
- lib
|
140
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
141
|
+
requirements:
|
142
|
+
- - ">="
|
143
|
+
- !ruby/object:Gem::Version
|
144
|
+
version: '0'
|
145
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
146
|
+
requirements:
|
147
|
+
- - ">="
|
148
|
+
- !ruby/object:Gem::Version
|
149
|
+
version: '0'
|
150
|
+
requirements: []
|
151
|
+
rubygems_version: 3.0.1
|
152
|
+
signing_key:
|
153
|
+
specification_version: 4
|
154
|
+
summary: A command line tool for GM-ing
|
155
|
+
test_files: []
|