Skip to content

jeremyf/gm-notepad

Repository files navigation

GM::Notepad

A command-line tool to help with your GM-ing.

To install

First, you will need a working copy of Ruby. I recommend following the instructions over at rbenv's Github page.

Next, you'll want to install the gm-notepad gem.

$ gem install gm-notepad

Datasets

Background

On a commute home from work, while listening to Judd Karlman's "Daydreaming about Dragons" podcast he wondered about ways to organize notes for NPCs. And I started thinking. How might I organize my content for access while gaming? And what kind of content? More importantly, what kind of tasks do I need to complete as a GM.

  • Remember a character name
  • Lookup their passive perception
  • Lookup a random table
  • Roll on a random table
  • Create a random character name. Maybe based on a culture.
  • Record quick notes about an NPC

I thought about swnt, and command line tool for Stars without Numbers. See the github project for more information.

And I thought about Alex Schroeder's tools.

I have kicked this around for awhile. I made an attempt in Rollio. But I built that to roll on tables. I needed something more general. I will, however, begin converting the data.

Introduction

By default gm-notepad interacts with $stdout and $stderr. There are three conceptual buffers:

  • interactive (defaults to $stderr)
  • output (defaults to $stderr)
  • filesystem (defaults to your file system)

When you type a line, and hit <enter>, gm-notepad will evaluate the line and render it to one or more of the buffers.

Examples

First, take a look at the help: $ gm-notepad -h

Usage: gm-notepad [options] [files]
Note taking tool with random table expansion.

Examples:
	$ gm-notepad
	$ gm-notepad filename
	$ echo '{name}' | gm-notepad

Options:
    -l, --list_tables                List tables loaded and exit (Default: false)
    -r, --report_config              Dump the configuration data (Default: false)
    -p, --path=PATH                  Path(s) for {table_name}.<config.table_extension> files (Default: ["."])
    -f, --filesystem_directory=DIR   Path to dump tables (Default: ".")
    -x, --table_extension=EXT        Extension to use for selecting tables (Default: ".txt")
        --time_to_live=TTL           Per line of input, how many times to allow text expansion (Default: 100)
    -d, --delimiter=DELIM            Default column delimiter for tables (Default: "|")

Output options:
    -t, --timestamp                  Append a timestamp to the note (Default: false)

Color options:
    -i, --skip-interactive-color     Disable color rendering for interactive buffer (Default: false)
    -o, --with-output-color          Enable color rendering for output buffer (Default: true)

    -h, --help                       You're looking at it!

At it's core, gm-shell interacts with named tables. A named table is a file found amongst the specified paths and has the specified table_extension. Let's take a look at the defaults. In a new shell, type: $ gm-notepad -r

Which writes the following to the interactive buffer (eg. $stderr)::

# Configuration Parameters:
#   config[:column_delimiter] = "|"
#   config[:filesystem_directory] = "."
#   config[:include_original_command_as_comment] = true
#   config[:index_entry_prefix] = "index"
#   config[:interactive_buffer] = #<IO:<STDERR>>
#   config[:interactive_color] = :faint
#   config[:list_tables] = false
#   config[:output_buffer] = #<IO:<STDOUT>>
#   config[:output_color] = false
#   config[:paths] = ["."]
#   config[:report_config] = true
#   config[:skip_readlines] = false
#   config[:table_extension] = ".txt"
#   config[:time_to_live] = 100
#   config[:with_timestamp] = false

You'll need to exit out (CTRL+D).

By default gm-notepad will load as tables all files matching the following glob: ./**/*.txt.

Included in the gem's test suite are four files:

  • ./spec/fixtures/name.txt
  • ./spec/fixtures/first-name.txt
  • ./spec/fixtures/last-name.txt
  • ./spec/fixtures/location.csv

When I run gm-notepad -l, gm-notepad does the following:

  • load all found tables
  • puts the config (see above) to the interactive buffer
  • puts the table_names to the interactive buffer
  • exits

Below are the table names when you run the gm-notepad -l against the repository (note when you run this command you'll get a preamble of the config):

character
first-name
last-name
name

Now let's load gm-notepad for interaction. In the terminal, type: $ gm-notepad

You now have an interactive shell for gm-notepad. Type ? and hit <enter>.

gm-notepad will write the following to interactive buffer (eg. $stderr):

Prefixes:
	?  - Help (this command)
	+  - Query table names and contents
	<table_name: - Write the results to the given table
	`  - Shell out command and write to interactive buffer
	`> - Shell out command and write to interactive AND output buffer
Tokens:
	! - Skip expansion
	/search/ - Grep for the given 'search' within the prefix
	[index] - Target a specific 'index'
	[][column] - Pick a random index
	{table_name} - expand_line the given 'table_name'
	{table_name[d6]} - roll a d6 and lookup that row on the given 'table_name'
	{table_name[d6][name]} - pick a random row (between 1 and 6) and select the 'name' column from the given table_name

Now, let's take look at a table. Again in an active gm-notepad session type the following: +first-name

gm-notepad will write the following to interactive buffer (eg. $stderr):

[1]	Frodo
[2]	Merry
[3]	Pippin
[4]	Sam
[5-6]	{first-name}Wise

These are the five table entries in the first-name table. "Frodo" is at index 1. "Merry", "Pippin", and "Sam" are at indices 2,3,4 respectively. For the fifth line there are two things happening. First the index spans a range. Second, notice the entry: {first-name}Wise. The {first-name} references a table named "first-name" (the same on you are looking at). Now type the following in your gm-notepad session: Hello {first-name}

gm-notepad will read the line and recursively expand the {first-name} and write the result to the interactive buffer and output buffer. The expander randomly picks a name from all entries, with ranges increasing the chance of being picked. In the above table "Frodo", "Merry", "Pippin", and "Sam" each have a 1 in 6 chance of being picked. And "{first-name}Wise" has a 2 in 6 chance.

In the session you might have something like the below:

=>	Hello SamWise
Hello SamWise

The line with starting with => is the interactive buffer. The other line is written to the output buffer.

You can also roll within a table. In the gm-notepad type the following: {first-name[1d4]}. The system will output "Frodo", "Merry", "Pippin", or "Sam". You won't get a "SamWise" or "FrodoWise" (or "FrodoWiseWise").

To wrap up our first session, let's try one more thing. In your gm-notepad session type the following: {first-name} owes {2d6}gp to {first-name}:

Frodo owes 3gp to SamWise

Let's take a look at the +character table. Your table indices need not be numbers. And you can mix numbers and text. This example introduces the idea of columns. I am still working on retrieving by column names as well as rendering column names.

[grell]	Grell	15	12D12
[jehat]	Jehat	19	14D6

You can write a new table, without exiting gm-notepad, by doing the following:

<junk:1|2\n3|4

This will write to the junk.txt file the following:

1|2
3|4

You can then immediately access the junk table, by typing the following: +junk

[1]	2
[3]	4

Testing Locally

  • Clone the repository
  • Bundle the dependencies ($ bundle install)
  • Run the specs ($ bundle exec rspec)
  • Run the command from the repository ($ bundle exec exe/gm-notepad)

Todo

  • When printing tables, also print column names/indices
  • Write expected interface document
  • Raise load error if table index is a "dice" expression
  • Gracefully handle loading a malformed data file (maybe?)
  • Add concept of "journal entry"; its not a table (perhaps) but something that you could capture notes.
  • Add ability to pass a configuration file that includes parameters
  • Colorize puts to interactive buffer
  • Disable colors as a configuration option
  • Handle {critical[5]}
  • Allow {critical[{2d6+1}]} to roll the dice then lookup the value in the critical table
  • Handle {critical[{2d6}]} for {2d6} damage
  • For {critical[{2d6+1}]}, how to handle out of bounds
  • Skip table lines that begin with #
  • Skip processing input lines that begin with #
  • Allow configuration to specify table delimiter
  • Allow configuration for where to dump data
  • Normalize WriteToTableHandler to use a renderer
  • Gracefully handle requesting an entry from a table with an index that does not exist (e.g. with test data try +name[23])
  • Gracefully handle +name[], where "name" is a registered table
  • Add time to live for line expansion (to prevent infinite loops); I suspect 100 to be reasonable
  • Enable "up" and "down" to scroll through history
  • Add index name when rendering table entries
  • Add concept of history
  • When expanding tables account for line expansion (via \n and \t)
  • Separate the InputHandler into pre-amble (e.g. allow overrides to where we are writing, determine what command we are writing)
  • Create a configuration object that captures the initial input (reduce passing around parameters and persisting copies of the config)
  • Add column handling {table[][]}
  • Gracefully handle cell lookup when named cell for entry is not found
  • 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
  • Ensure index names are lower-case
  • Hit 100% spec coverage
  • 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.
  • Remove "defer" printing concept
  • Add ability to shell out; I would love to leverage the swnt command line tool
  • Refine row/column grep behavior, as it is pre-dates the idea of a table having columns

Stretch TODO

  • Handle a .gm-notepadrc to inject default configurations
  • Extract exe/gm-notepad logic into a Runner, to provide better file configuration
  • Allow configuration to specify colors
  • Aspiration: Enable \{\{monster}[ac]} to pick a random monster and then fetch that monster's AC
  • Allow option to add a table to memory (instead of writing the table)
  • Add auto table expansion for "{}"
  • Add auto table expansion for "+"
  • Add auto index expansion for "["
  • Determine feasibility of adding dice to the {} expansion syntax (instead of the [] syntax)
  • Add force write results to output
  • Add option to dump all tables to the given directory
  • Add config that expands dice results while including the requested roll
  • Normalize WriteToTableHandler to deliver on grep and index behavior

About

A command-line tool to help with your GM-ing.

Resources

License

Code of conduct

Stars

Watchers

Forks

Packages

No packages published