#!/bin/sh

------------------------------------------------------------

rm -f tags touch tags find . -name '.retro' -print0 | xargs -0 -n 1 retro $0 >>tags find . -name '.forth' -print0 | xargs -0 -n 1 retro $0 >>tags cat tags | sort | uniq >tags2 mv tags2 tags exit


This will scan a source file and create output for a tags file in the minimal ctags format. In this, the tags file will contain one line per tag, with a tab separated structure:

tag-name<tab>tag-file<tab>tag-address

I am using the line number as the tag address.

To generate a tags file:

retro-tags

Tags for variables, constants, and data structures are not always identified correctly. Specifically:

'foo d:create ....             <- not identified #1 'foo const  #2 'bar const   <- only the last is identified 'foo var  'bar var             <- only the last is identified

For these, this assumes one name defined per line, with nothing following. Better detection and handling of this is left open for a future project.

To start, I bring in the retro-unu tool to locate the code blocks and call a combinator for each line in the code block. This one is extended to keep track of the tag address and file name as well.

~~~'TagAddress var 'TagFile var   {{   'Fenced var   :toggle-fence @Fenced not !Fenced ;   :fenced? (-f) @Fenced ;   :handle-line (s-)     fenced? [ over call ] [ drop ] choose ;   :prepare     #0 !TagAddress   over s:keep !TagFile ; ---reveal---   :unu (sq-)     prepare     swap [ &TagAddress v:inc            dup '~~~ s:eq?            [ drop toggle-fence ]            [ handle-line       ] choose          ] file:for-each-line drop ; }} ~~~

Next, identification of things to tag begins. This will use multiple passes of the source file.

First, colon definitions.

~~~:colon-definition?   dup ': s:begins-with? ;   :output-location   tab @TagFile #2 + s:put tab @TagAddress n:put nl ;   :output-name   ASCII:SPACE s:tokenize #0 a:fetch n:inc s:put ;   #0 script:get-argument [ s:trim colon-definition? &drop -if; output-name output-location ] unu ~~~

Then variables.

~~~:variable?   dup 'var s:ends-with? over 'var-n s:ends-with? or ;   :output-name   ASCII:SPACE s:tokenize dup a:length #2 - a:fetch n:inc s:put ;   #0 script:get-argument [ s:trim variable? &drop -if; output-name output-location ] unu ~~~

Constants.

~~~:constant?   dup 'const s:ends-with? ;   :output-name   ASCII:SPACE s:tokenize dup a:length #2 - a:fetch n:inc s:put ;   #0 script:get-argument [ s:trim constant? &drop -if; output-name output-location ] unu ~~~

And finally, words made with d:create:

~~~:created?   dup 'd:create s:ends-with? ;   :output-name   ASCII:SPACE s:tokenize dup a:length #2 - a:fetch n:inc s:put ;   #0 script:get-argument [ s:trim created? &drop -if; output-name output-location ] unu ~~~