Re: Web applications and pattern match

2019-11-17 Thread Vindaar
Good to hear! I couldn't find the source for the new version of the live demo 
though. In the markdown document it's still the old code as far as I can tell.

Yes, please just ask!


Re: Web applications and pattern match

2019-11-17 Thread edu500ac
Hi, Vindaar. I will use the solution you pointed out in the tutorial. By the 
way, if you visit the demo page, you will see that I already replaced the 
inicial version of the program with another one, which is based on the scanf. I 
also used the decode.Url procedure in order to test the utf-8 encoding.

I still have a few questions, where I will need your help again. 


Re: Web applications and pattern match

2019-11-17 Thread Vindaar
So originally I wanted to write a up a nice example to do the replacements via 
the scanf macro:

[https://nim-lang.github.io/Nim/strscans.html](https://nim-lang.github.io/Nim/strscans.html)

by defining tuples of strings to match against and their replacements, but I 
hit a dead end, because an element of a const tuple doesn't count as a static 
string for the pattern.

Also scanf turned out to be more problematic than I thought, because the $* 
term does not like to match any string until the end.

But since your book is (at least partly) about Nim macros and writing macros is 
fun, I built the following even longer version of your code, haha. It also 
includes a custom matcher that matches anything until the end of the string.


# File: web.nim
import strutils, os, strscans, macros
let input = open("rage.md")

let form = """
 
   


  """

echo "Content-type: text/html\n\n"
echo """
  

  
"""
echo ""

proc rest(input: string; match: var string, start: int): int =
  ## matches until the end of the string
  match = input[start .. input.high]
  # result is either 1 (string is empty) or the number of found chars
  result = max(1, input.len - start)

macro match(args, line: typed): untyped =
  ## match the `args` via `scanf` in `line`. `args` must be a `[]` of
  ## `(scanf string matcher, replacement string)` tuples, where the latter
  ## has to include a single `$#` to indicate the position of the 
replacement.
  ## The order of the `args` is important, since an if statement is built.
  let argImpl = args.getImpl
  expectKind argImpl, nnkBracket
  result = newStmtList()
  let matched = genSym(nskVar, "matched")
  result.add quote do:
var `matched`: string
  var ifStmt = nnkIfStmt.newTree()
  for el in argImpl:
expectKind el, nnkTupleConstr
let toMatch = el[0]
let toReplace = el[1]
let ifBody = nnkStmtList.newTree(nnkCall.newTree(ident"echo",
 
nnkCall.newTree(ident"%",
 
toReplace,
 
matched)),
 nnkAsgn.newTree(matched, newLit("")))
let ifCond = nnkCall.newTree(ident"scanf", line, toMatch, matched)
ifStmt.add nnkElifBranch.newTree(ifCond, ifBody)
  result.add ifStmt
  echo result.repr

const h1title = ("# ${rest}", "$#")
const h2title = ("## ${rest}", "$#")
const elseLine = ("${rest}", "$#")
const replacements = [h1title, h2title, elseLine]
for line in input.lines:
  match(replacements, line)
  # produces:
  # var matched: string
  # if scanf("# ${rest}", line, matched):
  #   echo h1title[1] % matched
  # if scanf("## ${rest}", line, matched):
  #   echo h2title[1] % matched
  # if scanf("${rest}", line, matched):
  #   echo elseLine[1] % matched
echo form

let qs = getEnv("QUERY_STRING", "none").split({'+'}).join(" ")
if qs != "none" and qs.len > 0:
  let output = open("visitors.txt", fmAppend)
  write(output, qs&"\n")
  output.close

let inputVisitors= open("visitors.txt")
for line in inputVisitors.lines:
  match(replacements, line)
inputVisitors.close
echo ""
input.close


Run

This is totally not practicle I'd say and one's better off writing something by 
hand or using the excellent 
[https://github.com/zevv/npeg](https://github.com/zevv/npeg) by @zevv.

Still fun though. And if someone wants to improve on this...

Finally, to just remove a prefix of a string, you may just use removePrefix 
from strutils:

[https://nim-lang.github.io/Nim/strutils.html#removePrefix%2Cstring%2Cstring](https://nim-lang.github.io/Nim/strutils.html#removePrefix%2Cstring%2Cstring)

Note that it only works inplace on string. You could use the new outplace 
though:

[https://github.com/nim-lang/Nim/pull/12599](https://github.com/nim-lang/Nim/pull/12599)