gm-notepad 0.0.6 → 0.0.8
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +9 -3
- data/examples/basic_example_file +21 -3
- data/exe/gm-notepad +1 -1
- data/lib/gm/notepad/configuration.rb +1 -2
- data/lib/gm/notepad/evaluators/dice_evaluator.rb +16 -0
- data/lib/gm/notepad/exceptions.rb +3 -0
- data/lib/gm/notepad/line_evaluator.rb +4 -14
- data/lib/gm/notepad/pad.rb +1 -0
- data/lib/gm/notepad/parameters/table_lookup.rb +42 -12
- data/lib/gm/notepad/readline.rb +1 -1
- data/lib/gm/notepad/table.rb +21 -9
- data/lib/gm/notepad/table_entry.rb +22 -10
- data/lib/gm/notepad/table_registry.rb +4 -9
- data/lib/gm/notepad/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: da3bbc8cbf352187a313f8815110edef14d41c7c37e4f2dd1f3bb49e43200bcf
|
4
|
+
data.tar.gz: 12ffebdda56b6d2e3a4c43da401c884b8c1a659767ea618081792346530ca15c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fa277d748161cb37f2b1105d02d17cc551769f171953746bfd8aed13cd009c48fbb155a96c08a980f1c34ab66e6c6afa07cf42b804eac77cf5a5a79016533f4e
|
7
|
+
data.tar.gz: a0539f38a29bcce258255da060388f29cbeab6cd59505fbcb2af2f757f8094637d8b821f63e339f8002169ffe720b9346d5b10c5fd6a03ead9ad6ba759308116
|
data/README.md
CHANGED
@@ -177,6 +177,10 @@ Hello SamWise
|
|
177
177
|
The line with starting with `=>` is the `interactive` buffer. The other line
|
178
178
|
is written to the `output` buffer.
|
179
179
|
|
180
|
+
You can also roll within a table. In the `gm-notepad` type the following:
|
181
|
+
`{first-name[1d4]}`. The system will output "Frodo", "Merry", "Pippin", or "Sam".
|
182
|
+
You won't get a "SamWise" or "FrodoWise" (or "FrodoWiseWise").
|
183
|
+
|
180
184
|
To wrap up our first session, let's try one more thing. In your `gm-notepad`
|
181
185
|
session type the following: `{first-name} owes [2d6]gp to {first-name}`:
|
182
186
|
|
@@ -213,7 +217,7 @@ entry has a 1 in 3 chance of being randomly chosen.
|
|
213
217
|
- [X] Skip table lines that begin with `#`
|
214
218
|
- [X] Skip processing input lines that begin with `#`
|
215
219
|
- [X] Allow configuration to specify table delimiter
|
216
|
-
- [ ]
|
220
|
+
- [ ] Raise load error if table index is a "dice" expression
|
217
221
|
- [X] Allow configuration for where to dump data
|
218
222
|
- [ ] Normalize `WriteToTableHandler` to use a renderer
|
219
223
|
- [ ] Normalize `WriteToTableHandler` to deliver on `grep` and `index` behavior
|
@@ -221,7 +225,6 @@ entry has a 1 in 3 chance of being randomly chosen.
|
|
221
225
|
- [X] Gracefully handle `+name[]`, where "name" is a registered table
|
222
226
|
- [ ] Add time to live for line expansion (to prevent infinite loops); I suspect 100 to be reasonable
|
223
227
|
- [X] Enable "up" and "down" to scroll through history
|
224
|
-
- [ ] Add config that expands dice results while including the requested roll
|
225
228
|
- [X] Add index name when rendering table entries
|
226
229
|
- [ ] Gracefully handle loading a malformed data file (maybe?)
|
227
230
|
- [X] Add concept of history
|
@@ -229,7 +232,8 @@ entry has a 1 in 3 chance of being randomly chosen.
|
|
229
232
|
- [ ] Separate the InputHandler into pre-amble (e.g. allow overrides to where we are writing, determine what command we are writing)
|
230
233
|
- [X] Create a configuration object that captures the initial input (reduce passing around parameters and persisting copies of the config)
|
231
234
|
- [ ] Add concept of "journal entry"; its not a table (perhaps) but something that you could capture notes.
|
232
|
-
- [
|
235
|
+
- [X] Add column handling `{table[][]}`
|
236
|
+
- [ ] Gracefully handle cell lookup when named cell for entry is not found
|
233
237
|
- [X] Support `\{\{table}-name}` You should be able to do `\{\{culture}-name}` and first evaluate to `{arabic-name}` and then get a value from the `arabic-name` table
|
234
238
|
- [X] Ensure index names are lower-case
|
235
239
|
- [ ] Hit 100% spec coverage
|
@@ -245,3 +249,5 @@ entry has a 1 in 3 chance of being randomly chosen.
|
|
245
249
|
- [ ] Add auto index expansion for "["
|
246
250
|
- [ ] Determine feasibility of adding dice to the `{}` expansion syntax (instead of the `[]` syntax)
|
247
251
|
- [ ] Add force write results to `output`
|
252
|
+
- [ ] Add option to dump all tables to the given directory
|
253
|
+
- [ ] Add config that expands dice results while including the requested roll
|
data/examples/basic_example_file
CHANGED
@@ -1,14 +1,32 @@
|
|
1
1
|
# Write entry `1|entry one` to in memory table `basic_example`
|
2
|
-
|
2
|
+
<basic_example:1|entry one
|
3
|
+
|
3
4
|
# Should render to interactive the internal help
|
4
5
|
?
|
6
|
+
|
7
|
+
# Should roll the dice
|
8
|
+
[2d6] goblins attack
|
9
|
+
|
5
10
|
# Should render to interactive the given tables
|
6
11
|
+
|
12
|
+
|
7
13
|
# Should render to interactive the table `basic_example`
|
8
14
|
+basic_example
|
15
|
+
|
9
16
|
# Should render `entry one`
|
10
17
|
{basic_example}
|
18
|
+
|
11
19
|
# Should append entry `2|entry two` into memory table `basic_example`
|
12
20
|
<basic_example:2|entry two
|
13
|
-
|
14
|
-
|
21
|
+
|
22
|
+
# Should show that there are two entries in `basic example`
|
23
|
+
+basic_example
|
24
|
+
|
25
|
+
# Should lookup entry 1 and 2
|
26
|
+
{basic_example[1]} and {basic_example[2]}
|
27
|
+
|
28
|
+
# Should lookup entry 1 and 2
|
29
|
+
{basic_example[1d1]}
|
30
|
+
|
31
|
+
# Should lookup entry 1 and 2
|
32
|
+
{2d6} {basic_example[1d1]}
|
data/exe/gm-notepad
CHANGED
@@ -80,7 +80,7 @@ end
|
|
80
80
|
begin
|
81
81
|
@notepad = Gm::Notepad.new(**config)
|
82
82
|
if config.fetch(:skip_readlines)
|
83
|
-
input_getter =
|
83
|
+
input_getter = ARGF.method(:gets)
|
84
84
|
else
|
85
85
|
require 'gm/notepad/readline'
|
86
86
|
input_getter = Gm::Notepad::Readline.input_getter(**config)
|
@@ -14,11 +14,10 @@ module Gm
|
|
14
14
|
output_buffer: $stdout,
|
15
15
|
paths: ['.'],
|
16
16
|
column_delimiter: Gm::Notepad::DEFAULT_COLUMN_DELIMITER,
|
17
|
-
shell_prompt: Gm::Notepad::DEFAULT_SHELL_PROMPT,
|
18
17
|
skip_readlines: false,
|
19
18
|
table_extension: '.txt',
|
20
19
|
with_timestamp: false
|
21
|
-
}
|
20
|
+
}
|
22
21
|
|
23
22
|
# NOTE: ORDER MATTERS! I have a temporal dependency in these
|
24
23
|
# defaults
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'dice'
|
2
|
+
module Gm
|
3
|
+
module Notepad
|
4
|
+
module Evaluators
|
5
|
+
module DiceEvaluator
|
6
|
+
def self.call(text:, fallback: text)
|
7
|
+
if parsed_text = Dice.parse(text)
|
8
|
+
parsed_text.evaluate.to_s
|
9
|
+
else
|
10
|
+
fallback.to_s
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -9,13 +9,16 @@ module Gm
|
|
9
9
|
end
|
10
10
|
class MissingTableError < RuntimeError
|
11
11
|
def initialize(name:)
|
12
|
+
@name = name
|
12
13
|
super(%(Missing table "#{name}"))
|
13
14
|
end
|
15
|
+
alias to_buffer_message to_s
|
14
16
|
end
|
15
17
|
class MissingTableEntryError < RuntimeError
|
16
18
|
def initialize(table_name:, index:)
|
17
19
|
super(%(Missing index "#{index}" for table "#{table_name}"))
|
18
20
|
end
|
21
|
+
alias to_buffer_message to_s
|
19
22
|
end
|
20
23
|
end
|
21
24
|
end
|
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'dice'
|
2
2
|
require 'gm/notepad/parameters/table_lookup'
|
3
|
+
require 'gm/notepad/evaluators/dice_evaluator'
|
3
4
|
module Gm
|
4
5
|
module Notepad
|
5
6
|
# Responsible for recording entries and then dumping them accordingly.
|
@@ -20,15 +21,8 @@ module Gm
|
|
20
21
|
|
21
22
|
def parse_table(text:)
|
22
23
|
while match = text.match(TABLE_NAME_REGEXP)
|
23
|
-
table_lookup = Parameters::TableLookup.new(text: match[:table_name].strip)
|
24
|
-
|
25
|
-
if index = Dice.parse(table_lookup.index)
|
26
|
-
table_lookup.index = index.evaluate
|
27
|
-
end
|
28
|
-
entry = table_registry.lookup(index: table_lookup.index, table_name: table_lookup.table_name)
|
29
|
-
else
|
30
|
-
entry = table_registry.lookup(table_name: table_lookup.table_name)
|
31
|
-
end
|
24
|
+
table_lookup = Parameters::TableLookup.new(text: match[:table_name].strip, roll_dice: true)
|
25
|
+
entry = table_registry.lookup(**table_lookup.parameters)
|
32
26
|
text = text.sub(match[:table_name_container], entry)
|
33
27
|
end
|
34
28
|
text
|
@@ -36,11 +30,7 @@ module Gm
|
|
36
30
|
DICE_REGEXP = %r{(?<dice_container>\[(?<dice>[^\]]+)\])}
|
37
31
|
def parse_dice(text:)
|
38
32
|
while match = text.match(DICE_REGEXP)
|
39
|
-
|
40
|
-
evaluated_dice = "#{parsed_dice.evaluate}"
|
41
|
-
else
|
42
|
-
evaluated_dice = "(#{match[:dice]})"
|
43
|
-
end
|
33
|
+
evaluated_dice = Evaluators::DiceEvaluator.call(text: match[:dice], fallback: "(#{match[:dice]})")
|
44
34
|
text = text.sub(match[:dice_container], evaluated_dice)
|
45
35
|
end
|
46
36
|
text
|
data/lib/gm/notepad/pad.rb
CHANGED
@@ -1,43 +1,73 @@
|
|
1
|
+
require 'gm/notepad/evaluators/dice_evaluator'
|
1
2
|
module Gm
|
2
3
|
module Notepad
|
3
4
|
module Parameters
|
4
5
|
# Responsible for teasing apart the table logic
|
5
6
|
class TableLookup
|
6
|
-
|
7
|
-
WITH_INDEX_REGEXP = %r{(?<declaration>\[(?<index>[^\]]+)\])}
|
8
|
-
WITH_EMPTY_INDEX_REGEX = %r{(?<declaration>\[\])}
|
9
|
-
WITH_EMPTY_GREP_REGEX = %r{(?<declaration>\/\/)}
|
10
|
-
|
11
|
-
def initialize(text:)
|
7
|
+
def initialize(text:, roll_dice: false)
|
12
8
|
@text = text
|
9
|
+
@role_dice = false
|
10
|
+
@parameters = {}
|
13
11
|
extract_parameters!
|
12
|
+
roll_them_bones! if roll_dice
|
14
13
|
end
|
15
14
|
|
16
|
-
|
15
|
+
attr_reader :cell, :index, :grep, :table_name
|
17
16
|
|
18
17
|
def parameters
|
19
18
|
parameters = { table_name: table_name }
|
20
19
|
parameters[:grep] = grep if grep
|
21
20
|
parameters[:index] = index if index
|
21
|
+
parameters[:cell] = cell if cell
|
22
22
|
parameters
|
23
23
|
end
|
24
24
|
|
25
25
|
private
|
26
|
+
|
27
|
+
attr_writer :cell, :index, :grep, :table_name
|
28
|
+
|
29
|
+
def roll_them_bones!
|
30
|
+
if index
|
31
|
+
self.index = Evaluators::DiceEvaluator.call(text: index)
|
32
|
+
end
|
33
|
+
if cell
|
34
|
+
self.cell = Evaluators::DiceEvaluator.call(text: cell)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
WITH_GREP_REGEXP = %r{(?<declaration>\/(?<found>[^\/]+)/)}
|
39
|
+
WITH_INDEX_REGEXP = %r{(?<declaration>\[(?<found>[^\]]+)\])}
|
40
|
+
CELL_WITHOUT_INDEX_REGEXP = %r{(?<declaration>\[\]\[(?<found>[^\]]+)\])}
|
41
|
+
EMPTY_INDEX_EMPTY_CELL_REGEXP = %r{(?<declaration>\[\]\[\])}
|
42
|
+
WITH_EMPTY_INDEX_REGEX = %r{(?<declaration>\[\])}
|
43
|
+
WITH_EMPTY_GREP_REGEX = %r{(?<declaration>\/\/)}
|
44
|
+
|
26
45
|
def extract_parameters!
|
27
|
-
@parameters = {}
|
28
46
|
text = @text
|
29
|
-
if match =
|
47
|
+
if match = EMPTY_INDEX_EMPTY_CELL_REGEXP.match(text)
|
48
|
+
text = text.sub(match[:declaration], '')
|
49
|
+
elsif match = CELL_WITHOUT_INDEX_REGEXP.match(text)
|
50
|
+
text = text.sub(match[:declaration], '')
|
51
|
+
self.cell = match[:found]
|
52
|
+
elsif match = WITH_EMPTY_INDEX_REGEX.match(text)
|
30
53
|
text = text.sub(match[:declaration], '')
|
31
54
|
elsif match = WITH_INDEX_REGEXP.match(text)
|
32
55
|
text = text.sub(match[:declaration], '')
|
33
|
-
|
56
|
+
self.index = match[:found]
|
57
|
+
# Moving on to the cell
|
58
|
+
if match = WITH_EMPTY_INDEX_REGEX.match(text)
|
59
|
+
text = text.sub(match[:declaration], '')
|
60
|
+
elsif match = WITH_INDEX_REGEXP.match(text)
|
61
|
+
text = text.sub(match[:declaration], '')
|
62
|
+
self.cell = match[:found]
|
63
|
+
end
|
34
64
|
elsif match = WITH_EMPTY_GREP_REGEX.match(text)
|
35
65
|
text = text.sub(match[:declaration], '')
|
36
66
|
elsif match = WITH_GREP_REGEXP.match(text)
|
37
67
|
text = text.sub(match[:declaration], '')
|
38
|
-
|
68
|
+
self.grep = match[:found]
|
39
69
|
end
|
40
|
-
|
70
|
+
self.table_name = text.downcase
|
41
71
|
end
|
42
72
|
end
|
43
73
|
end
|
data/lib/gm/notepad/readline.rb
CHANGED
data/lib/gm/notepad/table.rb
CHANGED
@@ -8,15 +8,15 @@ module Gm
|
|
8
8
|
process(lines: lines)
|
9
9
|
end
|
10
10
|
|
11
|
-
def lookup(index: false)
|
12
|
-
if index
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
11
|
+
def lookup(index: false, cell: false)
|
12
|
+
if index && cell
|
13
|
+
lookup_entry_by(index: index).lookup(cell: cell)
|
14
|
+
elsif index
|
15
|
+
lookup_entry_by(index: index)
|
16
|
+
elsif cell
|
17
|
+
lookup_random_entry.lookup(cell: cell)
|
18
18
|
else
|
19
|
-
|
19
|
+
lookup_random_entry
|
20
20
|
end
|
21
21
|
end
|
22
22
|
|
@@ -45,6 +45,18 @@ module Gm
|
|
45
45
|
|
46
46
|
private
|
47
47
|
|
48
|
+
def lookup_entry_by(index:)
|
49
|
+
begin
|
50
|
+
@table.fetch(index.to_s)
|
51
|
+
rescue KeyError
|
52
|
+
raise MissingTableEntryError.new(table_name: table_name, index: index.to_s)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def lookup_random_entry
|
57
|
+
@table.values[random_index]
|
58
|
+
end
|
59
|
+
|
48
60
|
attr_accessor :filename, :config
|
49
61
|
attr_reader :table_name
|
50
62
|
|
@@ -60,7 +72,7 @@ module Gm
|
|
60
72
|
@table = {}
|
61
73
|
lines.each do |line|
|
62
74
|
next if line[0] == '#'
|
63
|
-
entry = TableEntry.new(line: line,
|
75
|
+
entry = TableEntry.new(line: line, config: config)
|
64
76
|
entry.lookup_range.each do |i|
|
65
77
|
key = i.to_s
|
66
78
|
raise DuplicateKeyError.new(key: table_name, object: self) if @table.key?(key)
|
@@ -4,7 +4,9 @@ module Gm
|
|
4
4
|
TABLE_ENTRY_RANGE_MARKER = "-".freeze
|
5
5
|
class TableEntry
|
6
6
|
Configuration.init!(target: self, from_config: [:column_delimiter], additional_params: [:line]) do
|
7
|
-
|
7
|
+
row = line.split(column_delimiter)
|
8
|
+
self.index = row.shift
|
9
|
+
self.cells = row
|
8
10
|
end
|
9
11
|
|
10
12
|
include Comparable
|
@@ -12,30 +14,40 @@ module Gm
|
|
12
14
|
to_str <=> String(other)
|
13
15
|
end
|
14
16
|
|
17
|
+
def lookup(cell:)
|
18
|
+
# TODO: Need to deal with named columns
|
19
|
+
cells[cell.to_i]
|
20
|
+
end
|
21
|
+
|
15
22
|
NUMBER_RANGE_REGEXP = %r{(?<left>\d+) *- *(?<right>\d+)}
|
16
23
|
def lookup_range
|
17
|
-
if match = NUMBER_RANGE_REGEXP.match(
|
24
|
+
if match = NUMBER_RANGE_REGEXP.match(index)
|
18
25
|
(match[:left].to_i..match[:right].to_i).map(&:to_s)
|
19
26
|
else
|
20
|
-
[
|
27
|
+
[index]
|
21
28
|
end
|
22
29
|
end
|
23
30
|
|
24
|
-
attr_reader :
|
31
|
+
attr_reader :index, :cells
|
32
|
+
|
33
|
+
def entry
|
34
|
+
cells.join("\t")
|
35
|
+
end
|
36
|
+
alias entry_column entry
|
25
37
|
|
26
38
|
def to_s
|
27
|
-
"[#{
|
39
|
+
"[#{index}]\t#{entry}"
|
28
40
|
end
|
29
|
-
alias to_str
|
41
|
+
alias to_str entry
|
30
42
|
|
31
43
|
private
|
32
44
|
|
33
|
-
def
|
34
|
-
@
|
45
|
+
def index=(input)
|
46
|
+
@index = input.strip.downcase.freeze
|
35
47
|
end
|
36
48
|
|
37
|
-
def
|
38
|
-
@
|
49
|
+
def cells=(input)
|
50
|
+
@cells = Array(input).map { |i| i.strip.freeze }.freeze
|
39
51
|
end
|
40
52
|
end
|
41
53
|
end
|
@@ -59,15 +59,10 @@ module Gm
|
|
59
59
|
end
|
60
60
|
|
61
61
|
def lookup(table_name:, **kwargs)
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
rescue MissingTableError
|
67
|
-
"(undefined table_name: #{table_name.inspect})"
|
68
|
-
rescue KeyError
|
69
|
-
"(missing entry for #{kwargs.inspect})"
|
70
|
-
end
|
62
|
+
table = fetch_table(name: table_name)
|
63
|
+
table.lookup(**kwargs)
|
64
|
+
rescue MissingTableError, MissingTableEntryError => e
|
65
|
+
e.to_buffer_message
|
71
66
|
end
|
72
67
|
|
73
68
|
def evaluate(line:)
|
data/lib/gm/notepad/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gm-notepad
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.8
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jeremy Friesen
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-07-
|
11
|
+
date: 2019-07-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: dice_parser
|
@@ -146,6 +146,7 @@ files:
|
|
146
146
|
- lib/gm/notepad.rb
|
147
147
|
- lib/gm/notepad/configuration.rb
|
148
148
|
- lib/gm/notepad/defaults.rb
|
149
|
+
- lib/gm/notepad/evaluators/dice_evaluator.rb
|
149
150
|
- lib/gm/notepad/exceptions.rb
|
150
151
|
- lib/gm/notepad/input_handler_registry.rb
|
151
152
|
- lib/gm/notepad/input_handlers/comment_handler.rb
|