3. sda chapter new is Faulty

The help of sda chapter --help states:

COMMAND CHAPTER
  chapter [SUB-COMMAND] [COMMON-OPTIONS] [ARGS]

COMMON-OPTIONS
  | option              | args | description                                |
  | -p, --preserve-case |      | do not lowercase title for filename suffix |
  | -h, --help          |      | show help                                  |

  chapter new CHAPTER-FILENAME-OR-TOPIC
    * Convert CHAPTER-TOPIC to a canonical name CANONICAL-CHAPTER-TOPIC
      which is suitable as filename README-CANONICAL-CHAPTER-TOPIC.txt

    * Generate README-CANONICAL-CHAPTER-TOPIC.txt, if it does not exist.

However, this is not how the command actually works.

With an existing file README-Check-Chapter-New.txt, the command

sda chapter new README-Check-Chapter-New.txt

takes no action. No canonicalization whatsoever is performed.

3.1. From Gibberish to Brilliant Clarity

It is obvious, that the phrasing of the help text is less than clear and should be more precise to produce a meaningful command description.

3.1.1. BNF Is a Tool That Needs To Be Mastered As Such

It always helps to construct a BNF syntax declaration or at least have it in mind to clearly identify the parts of a syntactic entity.

A BNF syntax is constructed top-down. It starts with top-level syntax elements, which are then further defined until only terminal definitions or transformations are used.

The production of a BNF syntax is extremely simple:

  • define top-level element with terminal and non-terminal elements
  • for each undefined element, append a definition placeholder to the end of the syntax description
  • define the next placeholder element

Starting with the input CHAPTER-FILENAME-or-TOPIC, the BNF syntax is as follows.

// input

CHAPTER-FILENAME-or-TOPIC:
    CHAPTER-FILENAME | TOPIC

CHAPTER-FILENAME:
   PREFIX TOPIC-SUFFIX EXTENSION

TOPIC:
   "Mixed Case Topic with Spaces"

PREFIX:
   "README"

TOPIC-SUFFIX:
   "-" FN-TOPIC | /* empty */

EXTENSION:
   ".txt"

FN-TOPIC:
   subst("[^-0-9A-Za-z], "-", TOPIC)

The output of the operation requires a CANONICAL-CHAPTER-FILENAME, which is constructed from some fixed string elements and a transformed canonical-topic derived from a TOPIC which is one possible input. The other possible input is a CHAPTER-FILENAME, which contains a TOPIC and must therefore be deconstructed.

// output

CANONICAL-CHAPTER-FILENAME:
   PREFIX CANONICAL-TOPIC-SUFFIX EXTENSION

CANONICAL-TOPIC-SUFFIX:
   "-" FN-CANONICAL-TOPIC | /* empty */

FN-CANONICAL-TOPIC:
   subst("[^-0-9A-Za-z], "-", canonical-topic)

canonical-topic:
   lowercase(TOPIC)

It is more appropiate to describe the simpler transformation of a generic TOPIC into a canonical-topic and a CANONICAL-TOPIC-SUFFIX before describing the deconstruction of a CHAPTER-FILENAME and then again describing the transformation of the generic TOPIC into a CANONICAL-TOPIC-SUFFIX.

The requirement of a CHAPTER-FILENAME as input is too strict, it is better to accept the name of any existing file, construct a proper chapter filename and rename the input file (FILE-NAME).

With option –preserve-case the chapter filename output is not canonical.

All of this should be reflected in the underlying BNF syntax tree:

// input

TOPIC-or-FILENAME:
    TOPIC | FILENAME

TOPIC:
   "Mixed Case Topic with Spaces"

FILENAME:
   FILEBASE EXTENSION | FILEBASE

FILEBASE:
   PREFIX TOPIC-SUFFIX | TOPIC

EXTENSION:
   ".txt"

PREFIX:
   "README"

TOPIC-SUFFIX:
   "-" TOPIC | /* empty */

// output

CHAPTER-FILENAME:
   PREFIX TOPIC-SUFFIX EXTENSION

TOPIC-SUFFIX:
   "-" FN-TOPIC | /* empty */

FN-TOPIC:
   subst([^-0-9A-Za-z], "-", CHAPTER-TOPIC)

CHAPTER-TOPIC:
    ifelse(--preserve-case, TOPIC, canonical-topic)

canonical-topic:
   lowercase(TOPIC)

The description should then speak of

  • TOPIC-or-FILENAME, deconstructed into TOPIC and FILENAME
  • canonical-topic (to emphasize the all lowercase requirement of a canonical topic suffix)
  • CANONICAL-CHAPTER-FILENAME
chapter new TOPIC-or-FILENAME
  1. If TOPIC-or-FILENAME is the name of an existing file
     - extract TOPIC from FILENAME
  2. If --preserve-case is given,
     - use TOPIC as CHAPTER-TOPIC, otherwise
     - use TOPIC converted to lowercase as CHAPTER-TOPIC.
  3. Construct FN-TOPIC by replacing all non-alpha characters
     in CHAPTER-TOPIC with dashes "-" and squeezing multiple
     dashes into a single dash.
  4. Construct CHAPTER-FILENAME from FN-TOPIC as:
       "README" "-" FN-TOPIC ".txt"
  5. If CHAPTER-FILENAME exists
     - if FILENAME exists
       - if FILENAME is different from CHAPTER-FILENAME
         - warn about existing CHAPTER-FILENAME for FILENAME
       - warn about existing CHAPTER-FILENAME for TOPIC
     - if FILENAME exists
       - if FILENAME is different from CHAPTER-FILENAME
         - rename FILENAME as CHAPTER-FILENAME
       - Create new CHAPTER-FILENAME with title TOPIC.
"README-" canonical-chapter-topic ".txt"