#!/usr/bin/awk -f
#
# A literate program in text/gemini document format to program converter.
# text/gemini specification can be found at:
#
#     gemini://gemini.circumlunar.space/docs/specification.html
#     https://gemini.circumlunar.space/docs/specification.html
#
# Call like:
#
#     gmitangle file.gmi > program
# 
# e.g. 
# 
#     gmitangle file.gmi > program
# 
# You can also call passing in the language identifier to tangle into the program, this will default
# to "AWK" if not passed in:
# 
#     gmitangle -v LANG={program type to tangle/weave} file.gmi > program
# 
# e.g.
# 
#     gmitangle -v LANG=SQL file.gmi > file.sql
#

BEGIN {
  true = "true"
  false = "false"
  preformat_toggle = false
  tangle = false
  macro = ""
  literate = false

  PROGRAM_COUNTER = 0
  MACRO_COUNTER = 0

  delete PROGRAM
  delete MACROS

  if (LANG == "") {
    LANG = "AWK"
  }
}

function trim(string) {
  sub(/^[ \t]+/,"",string)
  sub(/[ \t]+$/,"",string)

  return string
}

# Preformatting toggle line start
/^```/ && preformat_toggle == false {
  preformat_toggle = true

  # Check if this section should be output as code i.e. see if it has specified the 
  # language identifier the program is tangling
  # Check if this section should be captured as the program structure i.e. see if it
  # has the "litgmi" language identifier
  sub(/^```[ \t]*/, "")
  sub(/[ \t]+$/,"")
  split($0,identifier,":")

  language = trim(identifier[1])
  macro = trim(identifier[2])

  if (language == LANG) {
    tangle = true
  } else if (language == "litgmi") {
    literate = true
  }

  next
}

# Preformatting toggle line end
/^```/ && preformat_toggle == true {
  preformat_toggle = false
  literate = false

  # Record the number of lines that the macro contains so that it is easy to
  # print it out later
  if (tangle == true) { 
    MACROS[macro,"size"] = MACRO_COUNTER
  }

  macro = ""
  tangle = false
  MACRO_COUNTER = 0

  next
}

# Macro lines
preformat_toggle == true && tangle == true {
  MACROS[macro,++MACRO_COUNTER] = $0
}

# Literate lines
preformat_toggle == true && literate == true {
  PROGRAM[++PROGRAM_COUNTER] = trim($0)
}

END {
  for (i = 1; i <= PROGRAM_COUNTER; i++) {
    macro = PROGRAM[i]
    size = MACROS[macro,"size"]
    for (j = 1; j <= size; j++) {
      print MACROS[macro,j]
    }
    print ""
  }
}