#*

ABOUT 

 Show bash functions in a file and the descriptive comments 
 above them.

 I often write comments above bash functions to explain what they do.
 These can be multiple lines and may even have blank lines in them
 of before the function name. The following script uses a line-by-line
 parsing technique with the nom nom://until command to concatenate the 
 comments and associate them with the bash function name which follows
 them. This is the sort of example that becomes tricky with [sed] 
 because there is multiline recognition taking place.

 Adding the line* parse token below (which is any not 'function' bash
 statement) complicates the grammar but is necessary because other 
 wise every comment above a function name will be regarded as pertaining
 to that function.

NOTES

  This [nom] script obviously doesn't completely parse bash syntax. 
  Just # comments and function names in a pretty 'maybe-just-good-enough'
  sort of way.

HISTORY 

  1 march 2025
    created this script in nomlang.org/doc/scripts/nom.linebyline.txt
    as an example. It seems to work ok.

*#

 # print bash function names and comments above them 
 # just ignore empty lines
 until "\n"; 
 [:space:] { clear; }
 !"" { 
   put; 
   # remove upto 5 leading/trailing spaces, a bit primitive, 
   # or parse with whilenot [\n] etc
   B"  " { clop; clop; } B"  " { clop; clop; } B" " { clip; }
   E"  " { clip; clip; } E"  " { clip; clip; } E" " { clip; }
   B"#" { 
     replace "#" " "; put;
     clear; add "comment*"; push; .reparse
   }
   B"function", E"()  {", E"() {", E"(){" { 
     replace "function " ""; replace "{" ""; replace "()" ""; put; 
     clear; add "function*"; push; .reparse
   }
   # comments above none function lines should be ignored
   !"" { clear; add "line*"; push; .reparse }
 }
parse>
 # for debugging
 # unstack; print; stack; add "\n"; print; clear;
 pop;pop; 

 # ignore comments before non-function bash statement 
 "comment*line*","line*line*" { clear; }

 # concatenate comment lines
 "comment*comment*" { 
   clear; get; ++; get; --; put; 
   clear; add "comment*"; push; .reparse
 }

 # print and delete function token 
 "*function*comment*" { 
   clear; get; print; 
   # transfer comment text
   clear; ++; get; --; put; 
   clear; add "comment*"; push; .reparse
 }

 # just print, no need to reduce
 "function*function*" { 
   clear; get; ++; get; --; print; 
   clear;
 }

 "function*line*" { clear; get; print; clear; }
 "line*function*" { clear; ++; get; --; print; clear; }

 # just print, no need to reduce? but print in order 
 # function name with comment as description after (indented)
 "comment*function*" { 
   clear; 
   # a swap trick to indent the (mulitline) comment and then
   # prepend the function name.
   #add "  "; get; replace "\n" "\n  ";
   #++; swap; get; --; print; 
   add "\n"; ++; get; --; get; print; 
   clear;
 }

 push;push;
 (eof) { quit; }