gm-notepad 0.0.10 → 0.0.11

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8a9f77aeaa803fe169c27b96242f16fcfe1ebaaf0db7c61aae75a2be0f9ba1c7
4
- data.tar.gz: 3a3728f49177fb88631f9e2c08df8ca9ca7148e7405b0df37986a861a80d950e
3
+ metadata.gz: 72cbb20c02dd2fa334bf57d7d88c40e7772d05ccf03bee599ddbf651e416c645
4
+ data.tar.gz: 1e474a0b888297ae5655e68710f5d40efcfbb59030aac36dab60e4fc765043de
5
5
  SHA512:
6
- metadata.gz: a89494760fa29c73d63381a6737e2b0e540fc88a82cb8abaf2c71c902af2ec2cc8c5d297b20824b50bd96d6cc42ca5c9fcf0432b35a16476a581ed775a2332bc
7
- data.tar.gz: a380d0f07547ff3c3e4f552033e97569e1539c6d82d441f913f4a906625c69e26e63a36479a78f7d6185745ccc68ae33af75c4d99b38f2d7b5777c2f0e94dcb2
6
+ metadata.gz: 49a06ad0a6f85eddaefa70f9f05dd358f39f163cc3c7555f0116d2c645436260910ef8f4ec4b955e26bbf8d332a0957a6dfa401c39b3a7664a44c6f787f6be60
7
+ data.tar.gz: a0f8bd008eb2220a4f8c68726aa96fcd68b110f50725b01091dc7ef5c57096e41d908674d4fa1bd46c0a552f61f01e68dddac3c508a499674d305361845363b4
data/README.md CHANGED
@@ -4,6 +4,10 @@ A command-line tool to help with your GM-ing.
4
4
 
5
5
  ## To install
6
6
 
7
+ First, you will need a working copy of Ruby. I recommend following the [instructions over at rbenv's Github page](https://github.com/rbenv/rbenv#installation).
8
+
9
+ Next, you'll want to install the `gm-notepad` gem.
10
+
7
11
  `$ gem install gm-notepad`
8
12
 
9
13
  ## Background
@@ -61,7 +65,6 @@ Options:
61
65
  -f, --filesystem_directory=DIR Path to dump tables (Default: ".")
62
66
  -x, --table_extension=EXT Extension to use for selecting tables (Default: ".txt")
63
67
  -t, --timestamp Append a timestamp to the note (Default: false)
64
- -d, --defer_output Defer output until system close (Default: false)
65
68
 
66
69
  Color options:
67
70
  -i, --skip-interactive-color Disable color rendering for interactive buffer (Default: false)
@@ -79,7 +82,6 @@ Which writes the following to the `interactive` buffer (eg. `$stderr`)::
79
82
  ```console
80
83
  # Configuration Parameters:
81
84
  # config[:report_config] = true
82
- # config[:defer_output] = false
83
85
  # config[:filesystem_directory] = "."
84
86
  # config[:interactive_buffer] = #<IO:<STDERR>>
85
87
  # config[:interactive_color] = true
@@ -227,15 +229,17 @@ columns. _I am still working on retrieving by column names as well as rendering
227
229
  - [ ] Gracefully handle loading a malformed data file (maybe?)
228
230
  - [X] Add concept of history
229
231
  - [X] When expanding tables account for line expansion (via \n and \t)
230
- - [ ] Separate the InputHandler into pre-amble (e.g. allow overrides to where we are writing, determine what command we are writing)
232
+ - [X] Separate the InputHandler into pre-amble (e.g. allow overrides to where we are writing, determine what command we are writing)
231
233
  - [X] Create a configuration object that captures the initial input (reduce passing around parameters and persisting copies of the config)
232
234
  - [ ] Add concept of "journal entry"; its not a table (perhaps) but something that you could capture notes.
233
235
  - [X] Add column handling `{table[][]}`
234
- - [ ] Gracefully handle cell lookup when named cell for entry is not found
236
+ - [X] Gracefully handle cell lookup when named cell for entry is not found
235
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
236
238
  - [X] Ensure index names are lower-case
237
239
  - [ ] Hit 100% spec coverage
238
240
  - [ ] Create a "To Render Object"; When you parse the input, you push relevant lines to that "To Render Object". When you look at a table, you want to know what the column names are.
241
+ - [X] Remove "defer" printing concept
242
+ - [ ] Add ability to shell out; I would love to leverage the [swnt](https://github.com/nboughton/swnt) command line tool
239
243
 
240
244
  ### Stretch TODO
241
245
 
data/Rakefile CHANGED
@@ -17,7 +17,7 @@ namespace :commitment do
17
17
  lastrun_filename = File.expand_path('../coverage/.last_run.json', __FILE__)
18
18
  if File.exist?(lastrun_filename)
19
19
  coverage_percentage = JSON.parse(File.read(lastrun_filename)).fetch('result').fetch('covered_percent').to_i
20
- EXPECTED_COVERAGE_GOAL = 98
20
+ EXPECTED_COVERAGE_GOAL = 97
21
21
  if coverage_percentage < EXPECTED_COVERAGE_GOAL
22
22
  abort("ERROR: Code Coverage Goal Not Met:\n\t#{coverage_percentage}%\tExpected\n\t#{EXPECTED_COVERAGE_GOAL}%\tActual")
23
23
  else
data/exe/gm-notepad CHANGED
@@ -2,7 +2,8 @@
2
2
  require 'gm/notepad'
3
3
 
4
4
  require 'optparse'
5
- config = Gm::Notepad::Configuration::CLI_CONFIG_DEFAULTS.clone
5
+ defaults = Gm::Notepad::Config
6
+ config = {}
6
7
 
7
8
  command_name = File.basename(__FILE__)
8
9
 
@@ -16,50 +17,47 @@ OptionParser.new do |options|
16
17
  "\t$ echo '{name}' | #{command_name}\n\n" \
17
18
  "Options:\n"
18
19
 
19
- options.on_head("-l", "--list_tables", "List tables loaded and exit (Default: #{config[:list_tables].inspect})") do |list_tables|
20
+ options.on_head("-l", "--list_tables", "List tables loaded and exit (Default: #{defaults.list_tables.inspect})") do |list_tables|
20
21
  config[:list_tables] = list_tables
21
22
  end
22
23
 
23
- options.on("-r", "--report_config", "Dump the configuration data (Default: #{config[:report_config].inspect})") do |report_config|
24
+ options.on("-r", "--report_config", "Dump the configuration data (Default: #{defaults.report_config.inspect})") do |report_config|
24
25
  config[:report_config] = report_config
25
26
  end
26
27
 
27
- options.on("-pPATH", "--path=PATH", String, "Path(s) for {table_name}.<config.table_extension> files (Default: [\".\"])") do |path|
28
+ options.on("-pPATH", "--path=PATH", String, "Path(s) for {table_name}.<config.table_extension> files (Default: #{defaults.paths.inspect})") do |path|
29
+ config[:paths] ||= []
28
30
  config[:paths] << path
29
31
  end
30
32
 
31
- options.on("-fDIR", "--filesystem_directory=DIR", String, "Path to dump tables (Default: #{config[:filesystem_directory].inspect})") do |filesystem_directory|
33
+ options.on("-fDIR", "--filesystem_directory=DIR", String, "Path to dump tables (Default: #{defaults.filesystem_directory.inspect})") do |filesystem_directory|
32
34
  # Should we guard that this exists?
33
35
  config[:filesystem_directory] = filesystem_directory
34
36
  end
35
37
 
36
- options.on("-xEXT", "--table_extension=EXT", String, "Extension to use for selecting tables (Default: #{config[:table_extension].inspect})") do |table_extension|
38
+ options.on("-xEXT", "--table_extension=EXT", String, "Extension to use for selecting tables (Default: #{defaults.table_extension.inspect})") do |table_extension|
37
39
  config[:table_extension] = table_extension
38
40
  end
39
41
 
40
- options.on("-dDELIM", "--delimiter=DELIM", String, "Default column delimiter for tables (Default: #{config[:column_delimiter].inspect})") do |column_delimiter|
42
+ options.on("-dDELIM", "--delimiter=DELIM", String, "Default column delimiter for tables (Default: #{defaults.column_delimiter.inspect})") do |column_delimiter|
41
43
  map = { "t" => "\t" }
42
44
  config[:column_delimiter] = map.fetch(column_delimiter) { column_delimiter }
43
45
  end
44
46
 
45
47
  options.separator("")
46
48
  options.separator("Output options:")
47
- options.on("-t", "--timestamp", "Append a timestamp to the note (Default: #{config[:with_timestamp].inspect})") do |timestamp|
49
+ options.on("-t", "--timestamp", "Append a timestamp to the note (Default: #{defaults.with_timestamp.inspect})") do |timestamp|
48
50
  config[:with_timestamp] = timestamp
49
51
  end
50
52
 
51
- options.on("--defer_output", "Defer output until system close (Default: #{config[:defer_output].inspect})") do |defer_output|
52
- config[:defer_output] = defer_output
53
- end
54
-
55
53
  options.separator("")
56
54
  options.separator("Color options:")
57
55
 
58
- options.on("-i", "--skip-interactive-color", "Disable color rendering for interactive buffer (Default: #{!config[:interactive_color].inspect})") do |interactive_color|
56
+ options.on("-i", "--skip-interactive-color", "Disable color rendering for interactive buffer (Default: #{(!defaults.interactive_color).inspect})") do |interactive_color|
59
57
  config[:interactive_color] = !interactive_color
60
58
  end
61
59
 
62
- options.on("-o", "--with-output-color", "Enable color rendering for output buffer (Default: #{!config[:output_color].inspect})") do |output_color|
60
+ options.on("-o", "--with-output-color", "Enable color rendering for output buffer (Default: #{(!defaults.output_color).inspect})") do |output_color|
63
61
  config[:output_color] = output_color
64
62
  end
65
63
 
@@ -72,14 +70,14 @@ OptionParser.new do |options|
72
70
  end.parse!
73
71
 
74
72
  if config[:list_tables]
75
- notepad = Gm::Notepad.new(config.merge(report_config: true))
76
- notepad.process(input: "+")
73
+ notepad = Gm::Notepad.new(finalize: true, **config.merge(report_config: true))
74
+ notepad.process(text: "+")
77
75
  exit(1)
78
76
  end
79
77
 
80
78
  begin
81
- @notepad = Gm::Notepad.new(**config)
82
- if config.fetch(:skip_readlines)
79
+ @notepad = Gm::Notepad.new(finalize: true, **config)
80
+ if Gm::Notepad::Config.skip_readlines
83
81
  input_getter = ARGF.method(:gets)
84
82
  else
85
83
  require 'gm/notepad/readline'
@@ -87,9 +85,9 @@ begin
87
85
  end
88
86
  while input = input_getter.call
89
87
  # # Keep reading lines of input as long as they're coming.
90
- input.each_line do |input|
88
+ input.each_line do |text|
91
89
  begin
92
- @notepad.process(input: input)
90
+ @notepad.process(text: text)
93
91
  rescue Errno::EPIPE
94
92
  @notepad.close!
95
93
 
data/gm-notepad.gemspec CHANGED
@@ -22,6 +22,9 @@ Gem::Specification.new do |spec|
22
22
  spec.require_paths = ["lib"]
23
23
 
24
24
  spec.add_dependency "dice_parser"
25
+ spec.add_dependency "dry-configurable"
26
+ spec.add_dependency "dry-container"
27
+ spec.add_dependency "dry-initializer"
25
28
  spec.add_dependency "term-ansicolor"
26
29
  spec.add_development_dependency "bundler"
27
30
  spec.add_development_dependency "rake"
data/lib/gm/notepad.rb CHANGED
@@ -1,12 +1,14 @@
1
1
  require "gm/notepad/version"
2
- require "gm/notepad/defaults"
3
- require "gm/notepad/pad"
4
- require "gm/notepad/configuration"
2
+ require 'gm/notepad/config'
3
+ require "gm/notepad/app"
5
4
  module Gm
6
5
  module Notepad
7
- def self.new(*args)
8
- config = Configuration.new(*args)
9
- Pad.new(config: config)
6
+ def self.new(finalize: false, **config_parameters)
7
+ config_parameters.each_pair do |key, value|
8
+ Config.config.public_send("#{key}=", value)
9
+ end
10
+ Config.finalize! if finalize
11
+ App.new
10
12
  end
11
13
  end
12
14
  end
@@ -0,0 +1,45 @@
1
+ require 'dry-initializer'
2
+ require 'gm/notepad/container'
3
+ require 'gm/notepad/throughput_text'
4
+
5
+ module Gm
6
+ module Notepad
7
+ # Responsible for recording entries and then dumping them accordingly.
8
+ class App
9
+ extend Dry::Initializer
10
+ option :renderer, default: -> { Container.resolve(:renderer) }
11
+ option :input_processor, default: -> { Container.resolve(:input_processor) }
12
+ option :report_config, default: -> { Container.resolve(:config).report_config }, reader: :private
13
+ option :list_tables, default: -> { Container.resolve(:config).list_tables }, reader: :private
14
+
15
+ def initialize(*args)
16
+ super
17
+ open!
18
+ end
19
+
20
+ def process(text:)
21
+ output = input_processor.convert_to_output(input: text)
22
+ renderer.render(output: output)
23
+ end
24
+
25
+ def close!
26
+ renderer.close!
27
+ end
28
+
29
+ private
30
+
31
+ def open!
32
+ renderer.call("Welcome to gm-notepad. type \"?\" for help.", to_interactive: true, to_output: false)
33
+ return unless report_config
34
+ lines = ["# Configuration Parameters:"]
35
+ Config.settings.each do |setting|
36
+ lines << "# config[#{setting.inspect}] = #{Config.public_send(setting).inspect}"
37
+ end
38
+ # When running :list_tables by default I don't want to report
39
+ # that to the output buffer.
40
+ to_output = !list_tables
41
+ renderer.call(lines, to_interactive: true, to_output: to_output)
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,47 @@
1
+ require 'dry-initializer'
2
+ require 'term/ansicolor'
3
+ require 'gm/notepad/container'
4
+
5
+ module Gm
6
+ module Notepad
7
+ # To provide a means for colorizing the output and defering output
8
+ class BufferWrapper
9
+ def self.for_interactive(buffer:)
10
+ new(buffer: buffer, color: Container[:config].interactive_color, append_new_line_on_close: true)
11
+ end
12
+
13
+ def self.for_output(buffer:)
14
+ new(buffer: buffer, color: Container[:config].output_color, append_new_line_on_close: false)
15
+ end
16
+ private_class_method :new
17
+
18
+ extend Dry::Initializer
19
+ option :buffer
20
+ option :color, default: -> { false }
21
+ option :append_new_line_on_close, default: -> { false }
22
+ option :lines, default: -> { [] }
23
+
24
+ def initialize(*args)
25
+ super
26
+ if color
27
+ buffer.extend(Term::ANSIColor)
28
+ end
29
+ end
30
+
31
+ def puts(text)
32
+ if color
33
+ buffer.puts("#{buffer.public_send(color)}#{text}#{buffer.reset}")
34
+ else
35
+ buffer.puts("#{text}")
36
+ end
37
+ end
38
+
39
+ def close!
40
+ self.lines.each do |line|
41
+ puts(line)
42
+ end
43
+ buffer.print("\n") if append_new_line_on_close
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,31 @@
1
+ require 'dry-container'
2
+ module Gm
3
+ module Notepad
4
+ class Config
5
+ extend Dry::Configurable
6
+
7
+ setting :report_config, false, reader: true
8
+ setting :filesystem_directory, '.', reader: true
9
+ setting :index_entry_prefix, "index", reader: true
10
+ setting :interactive_buffer, $stderr, reader: true
11
+ setting :interactive_color, :faint, reader: true
12
+ setting :output_color, false, reader: true
13
+ setting :list_tables, false, reader: true
14
+ setting :output_buffer, $stdout, reader: true
15
+ setting :paths, ['.'], reader: true
16
+ setting :column_delimiter, "|", reader: true
17
+ setting :skip_readlines, false, reader: true
18
+ setting :include_original_command_as_comment, true, reader: true
19
+ setting :table_extension, '.txt', reader: true
20
+ setting :with_timestamp, false, reader: true
21
+
22
+ def self.index_entry_prefix_regexp
23
+ %r{^#{Regexp.escape(index_entry_prefix)} *#{Regexp.escape(column_delimiter)}}i
24
+ end
25
+
26
+ def index_entry_prefix_regexp
27
+ %r{^#{Regexp.escape(index_entry_prefix)} *#{Regexp.escape(column_delimiter)}}i
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,50 @@
1
+ require 'dry-container'
2
+
3
+ module Gm
4
+ module Notepad
5
+ # A container for dependency injection
6
+ class Container
7
+ extend Dry::Container::Mixin
8
+
9
+ register "input_processor" do
10
+ require 'gm/notepad/input_processor'
11
+ InputProcessor.new
12
+ end
13
+
14
+ register "config" do
15
+ require 'gm/notepad/config'
16
+ Config
17
+ end
18
+
19
+ register "table_registry" do
20
+ require 'gm/notepad/table_registry'
21
+ TableRegistry.build_and_load
22
+ end
23
+
24
+ register "renderer" do
25
+ require 'gm/notepad/line_renderer'
26
+ LineRenderer.new
27
+ end
28
+
29
+ register "input_handler_registry" do
30
+ # Order matters. The first registered will be the first to
31
+ # answer "Can you handle the input?"
32
+ require "gm/notepad/input_handler_registry"
33
+ require "gm/notepad/input_handlers/help_handler"
34
+ require "gm/notepad/input_handlers/comment_handler"
35
+ require "gm/notepad/input_handlers/query_table_handler"
36
+ require "gm/notepad/input_handlers/query_table_names_handler"
37
+ require "gm/notepad/input_handlers/write_to_table_handler"
38
+ require "gm/notepad/input_handlers/write_line_handler"
39
+ InputHandlerRegistry.new do |registry|
40
+ registry.register(handler: InputHandlers::HelpHandler)
41
+ registry.register(handler: InputHandlers::CommentHandler)
42
+ registry.register(handler: InputHandlers::QueryTableHandler)
43
+ registry.register(handler: InputHandlers::QueryTableNamesHandler)
44
+ registry.register(handler: InputHandlers::WriteToTableHandler)
45
+ registry.register(handler: InputHandlers::WriteLineHandler)
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -10,7 +10,7 @@ module Gm
10
10
  class MissingTableError < RuntimeError
11
11
  def initialize(name:)
12
12
  @name = name
13
- super(%(Missing table "#{name}"))
13
+ super(%((Missing table "#{name}")))
14
14
  end
15
15
  alias to_buffer_message to_s
16
16
  end
@@ -8,16 +8,16 @@ module Gm
8
8
  yield(self) if block_given?
9
9
  end
10
10
 
11
- def handler_for(input:, skip_default: false)
11
+ def handler_for(input:, skip_default: false, table_registry: Container.resolve(:table_registry))
12
12
  handler = nil
13
13
  @registry.each do |handler_builder|
14
- if handler = handler_builder.build_if_handled(input: input)
14
+ if handler = handler_builder.build_if_handled(input: input, table_registry: table_registry)
15
15
  break
16
16
  end
17
17
  end
18
18
  return handler if handler
19
19
  return nil if skip_default
20
- default_handler_builder.build_if_handled(input: input)
20
+ default_handler_builder.build_if_handled(input: input, table_registry: table_registry)
21
21
  end
22
22
 
23
23
  def register(handler:)
@@ -6,18 +6,16 @@ module Gm
6
6
  COMMENT_PREFIX = '#'.freeze
7
7
 
8
8
  def self.handles?(input:)
9
- return false unless input[0] == COMMENT_PREFIX
9
+ return false unless input.match(/^#/)
10
10
  true
11
11
  end
12
12
 
13
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
- [input]
14
+ input.render_current_text(
15
+ to_interactive: true,
16
+ to_output: false,
17
+ expand_line: false
18
+ )
21
19
  end
22
20
  end
23
21
  end
@@ -1,41 +1,33 @@
1
+ require 'gm/notepad/throughput_text'
2
+ require 'dry-initializer'
1
3
  module Gm
2
4
  module Notepad
3
5
  module InputHandlers
4
6
  class DefaultHandler
5
- def self.build_if_handled(input:)
7
+ def self.build_if_handled(input:, table_registry: Container.resolve(:table_registry))
6
8
  return false unless handles?(input: input)
7
- new(input: input)
9
+ new(input: input, table_registry: table_registry)
8
10
  end
9
11
 
10
12
  def self.handles?(input:)
11
13
  true
12
14
  end
13
15
 
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
16
+ extend Dry::Initializer
17
+ option :input
18
+ option :table_registry, default: -> { Container.resolve(:table_registry) }
19
+ def initialize(*args)
20
+ super
21
21
  after_initialize!
22
22
  end
23
- attr_accessor :table_registry, :to_interactive, :to_output, :expand_line, :input, :to_filesystem
24
-
25
- def after_initialize!
26
- end
27
23
 
28
24
  def lines
29
- []
25
+ input.lines
30
26
  end
31
27
 
32
- alias expand_line? expand_line
28
+ private
33
29
 
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
30
+ def after_initialize!
39
31
  end
40
32
  end
41
33
  end