'use babel'
// TODO: docstrings

import { forLines } from './scopes'

function getLine (ed, l) {
  return {
    scope: ed.scopeDescriptorForBufferPosition([l, 0]).scopes,
    line: ed.getTextInBufferRange([[l, 0], [l, Infinity]])
  }
}

function isBlank ({line, scope}) {
  for (let s of scope) {
    if (/\bcomment\b/.test(s) || /\bstring\b/.test(s)) {
      return true
    }
  }
  return line.match(/^\s*(#.*)?$/)
}
function isEnd ({line, scope}) {
  return line.match(/^(end\b|\)|\]|\})/)
}
function isCont ({line, scope}) {
  return line.match(/^(else|elseif|catch|finally)\b/)
}
function isStart (lineInfo) {
  return !(lineInfo.line.match(/^\s/) || isBlank(lineInfo) || isEnd(lineInfo) || isCont(lineInfo))
}

function walkBack(ed, row) {
  while ((row > 0) && !isStart(getLine(ed, row))) {
    row--
  }
  return row
}

function walkForward (ed, start) {
  let end
  let mark = (end = start)
  while (mark < ed.getLastBufferRow()) {
    mark++
    const lineInfo = getLine(ed, mark)

    if (isStart(lineInfo)) {
      break
    }
    if (isEnd(lineInfo)) {
      if (!(forLines(ed, start, mark-1).length === 0)) {
        end = mark
      }
    } else if (!(isBlank(lineInfo) || isStart(lineInfo))) {
      end = mark
    }
  }
  return end
}

function getRange (ed, row) {
  const start = walkBack(ed, row)
  const end = walkForward(ed, start)
  if (start <= row && row <= end) {
    return [[start, 0], [end, Infinity]]
  }
}

function getSelection (ed, sel) {
  const {start, end} = sel.getBufferRange()
  const range = [[start.row, start.column], [end.row, end.column]]
  while (isBlank(getLine(ed, range[0][0])) && (range[0][0] <= range[1][0])) {
    range[0][0]++
    range[0][1] = 0
  }
  while (isBlank(getLine(ed, range[1][0])) && (range[1][0] >= range[0][0])) {
    range[1][0]--
    range[1][1] = Infinity
  }
  return range
}

export function moveNext (ed, sel, range) {
  // Ensure enough room at the end of the buffer
  let row = range[1][0]
  let last
  while ((last = ed.getLastBufferRow()) < (row+2)) {
    if ((last !== row) && !isBlank(getLine(ed, last))) {
      break
    }
    sel.setBufferRange([[last, Infinity], [last, Infinity]])
    sel.insertText('\n')
  }
  // Move the cursor
  let to = row + 1
  while ((to < ed.getLastBufferRow()) && isBlank(getLine(ed, to))) {
    to++
  }
  to = walkForward(ed, to)
  return sel.setBufferRange([[to, Infinity], [to, Infinity]])
}

function getRanges (ed) {
  const ranges = ed.getSelections().map((sel) => ({
    selection: sel,
    range: sel.isEmpty() ? getRange(ed, sel.getHeadBufferPosition().row) :
                           getSelection(ed, sel)
  }));
  return ranges.filter(({range}) => (range != null) && ed.getTextInBufferRange(range).trim())
}

export function get (ed) {
  const result = []
  for (let {range, selection} of getRanges(ed)) {
    result.push({
      range,
      selection,
      line: range[0][0],
      text: ed.getTextInBufferRange(range)
    })
  }
  return result
}

export function select (ed = atom.workspace.getActiveTextEditor()) {
  if (!ed) return
  return ed.mutateSelectedText(selection => {
    let range = getRange(ed, selection.getHeadBufferPosition().row)
    if (range) {
      selection.setBufferRange(range)
    }
  })
}

@@ -257,24 +257,49 @@
 line, scope%7D
+, allowDocstrings = false
 ) %7B%0A  for (l
@@ -348,19 +348,43 @@
 t(s) %7C%7C 
-/%5Cb
+(!allowDocstrings && /%5Cbdoc
 string%5Cb
@@ -393,16 +393,17 @@
 test(s))
+)
  %7B%0A     
@@ -654,24 +654,119 @@
 lineInfo) %7B%0A
+  for (let s of lineInfo.scope) %7B%0A    if (/%5Cbstring%5Cb/.test(s)) %7B%0A      return false%0A    %7D%0A  %7D%0A
   return !(l
@@ -1010,16 +1010,24 @@
  let end
+ = start
 %0A  let m
@@ -1035,22 +1035,14 @@
 rk =
- (end =
  start
-)
 %0A  w
@@ -1129,17 +1129,16 @@
 , mark)%0A
-%0A
     if (
@@ -1757,24 +1757,30 @@
 range%5B0%5D%5B0%5D)
+, true
 ) && (range%5B
@@ -1887,16 +1887,22 @@
 e%5B1%5D%5B0%5D)
+, true
 ) && (ra

fix string block finding