-find_next_cursor_position = (n, i) ->
- if n.type is TYPE_TEXT
- if n.text.length > i
- return [n, i + 1]
- return null
- if n.type is TYPE_TAG
- if n.children.length
- for c in n.children
- ret = find_next_cursor_position c, -1
- return ret if ret?
- return null
- else
- # FIXME create an empty text node if needed depending on tag name
+traverse_tree = (tree, state, cb) ->
+ for c in tree
+ cb c, state
+ break if state.done?
+ if c.children.length
+ traverse_tree c.children, state, cb
+ break if state.done?
+ return state
+# find the next element in top (and decendants) that is after n and can contain text
+# TODO make it so cursor can go places that don't have text but could
+find_next_cursor_position = (top, n, i) ->
+ if n? and n.type is TYPE_TEXT and n.text.length > i
+ return [n, i + 1]
+ found = traverse_tree top, before: n?, (node, state) ->
+ if node.type is TYPE_TEXT and state.before is false
+ state.node = node
+ state.done = true
+ if node is n
+ state.before = false
+ if found.node?
+ return [found.node, 0]
+ return null
+
+# TODO make it so cursor can go places that don't have text but could
+find_prev_cursor_position = (top, n, i) ->
+ if n? and n.type is TYPE_TEXT and i > 0
+ return [n, i - 1]
+ found = traverse_tree top, before: n?, (node, state) ->
+ if node.type is TYPE_TEXT
+ unless n?
+ state.node = node
+ state.done = true
+ if node is n
+ if state.prev?
+ state.node = state.prev
+ state.done = true
+ if node
+ state.prev = node
+ if found.node?
+ return [found.node, found.node.text.length]