if edge.suffix and rfind(frag, edge.suffix, nil, --[[plain]] true) == #frag - #edge.suffix + 1 then
      Current_state = edge.target
      break
    end
  end
end
function trim(s)
  return s:gsub('^%s+', ''):gsub('%s+$', '')
end
function ltrim(s)
  return s:gsub('^%s+', '')
end
function rtrim(s)
  return s:gsub('%s+$', '')
end
  dstring=String_color,
  block_string=String_color,
  block_comment=Comment_color,
}
Current_state = 'normal'
function initialize_color()
--?   print('new line')
  Current_state = 'normal'
end
function select_color(frag)
--?   print('before', '^'..frag..'$', Current_state)
  switch_color_based_on_prefix(frag)
--?   print('using color', Current_state, Colors[Current_state])
  App.color(Colors[Current_state])
  switch_color_based_on_suffix(frag)
--?   print('state after suffix', Current_state)
end
function switch_color_based_on_prefix(frag)
  if Next_state[Current_state] == nil then
    return
  end
  frag = rtrim(frag)
  for _,edge in pairs(Next_state[Current_state]) do
    if edge.prefix and find(frag, edge.prefix, nil, --[[plain]] true) == 1 then
      Current_state = edge.target
      break
    end
  end
end
function switch_color_based_on_suffix(frag)
  if Next_state[Current_state] == nil then
    return
  end
  frag = rtrim(frag)
  for _,edge in pairs(Next_state[Current_state]) do
  comment=Comment_color,
  sstring=String_color,
Comment_color = {r=0, g=0, b=1}
String_color = {r=0, g=0.5, b=0.5}
Divider_color = {r=0.7, g=0.7, b=0.7}
Colors = {
  normal=Text_color,
  block_string={
    {suffix=']]', target='normal'},
  },
  block_comment={
    {suffix=']]', target='normal'},
  },
  -- comments are a sink
}
    {prefix='[[', target='block_string'},  -- only single line for now
  },
  dstring={
    {suffix='"', target='normal'},
  },
  sstring={
    {suffix="'", target='normal'},
  },
    {prefix='--[[', target='block_comment'},  -- only single-line for now
    {prefix='--', target='comment'},
    {prefix='"', target='dstring'},
    {prefix="'", target='sstring'},