call textobj#user#plugin('number', {
\   'default': {
\     'pattern': '\a\+',
\     'select': 'nd',
\   },
\   'cursor': {
\     'pattern': '\a\+',
\     'select': 'nc',
\     'scan': 'cursor',
\   },
\   'forward': {
\     'pattern': '\a\+',
\     'select': 'nf',
\     'scan': 'forward',
\   },
\   'line': {
\     'pattern': '\a\+',
\     'select': 'nl',
\     'scan': 'line',
\   },
\   'nearest': {
\     'pattern': '\a\+',
\     'select': 'nn',
\     'scan': 'nearest',
\   },
\ })

function! Select(lnum, col, object)
  call cursor(a:lnum, a:col)
  execute 'normal' 'v'.a:object."\<Esc>"
  return [visualmode(), getpos("'<")[1:2], getpos("'>")[1:2]]
endfunction

function! Test(object, cases)
  for c in a:cases
    execute printf('Expect Select(%d, %d, %s) ==# ["v", %s, %s]',
    \              c[0][0], c[0][1],
    \              string(a:object),
    \              string(c[1]),
    \              string(c[2]))
  endfor
endfunction

describe '"pattern"-based text object'
  before
    new
    0 put =[
    \   '___AAA___',
    \   'BBB___CCC',
    \   '_________',
    \   '___DDD___',
    \   '_________',
    \ ]
  end

  after
    close!
  end

  context 'without "scan"'
    it 'is targeted if it is under or following to the cursor'
      call Test('nd', [
      \   [[1, 1], [1, 4], [1, 6]],
      \   [[1, 2], [1, 4], [1, 6]],
      \   [[1, 3], [1, 4], [1, 6]],
      \   [[1, 4], [1, 4], [1, 6]],
      \   [[1, 5], [1, 4], [1, 6]],
      \   [[1, 6], [1, 4], [1, 6]],
      \   [[1, 7], [2, 1], [2, 3]],
      \   [[1, 8], [2, 1], [2, 3]],
      \   [[1, 9], [2, 1], [2, 3]],
      \
      \   [[2, 1], [2, 1], [2, 3]],
      \   [[2, 2], [2, 1], [2, 3]],
      \   [[2, 3], [2, 1], [2, 3]],
      \   [[2, 4], [2, 7], [2, 9]],
      \   [[2, 5], [2, 7], [2, 9]],
      \   [[2, 6], [2, 7], [2, 9]],
      \   [[2, 7], [2, 7], [2, 9]],
      \   [[2, 8], [2, 7], [2, 9]],
      \   [[2, 9], [2, 7], [2, 9]],
      \
      \   [[3, 1], [4, 4], [4, 6]],
      \   [[3, 2], [4, 4], [4, 6]],
      \   [[3, 3], [4, 4], [4, 6]],
      \   [[3, 4], [4, 4], [4, 6]],
      \   [[3, 5], [4, 4], [4, 6]],
      \   [[3, 6], [4, 4], [4, 6]],
      \   [[3, 7], [4, 4], [4, 6]],
      \   [[3, 8], [4, 4], [4, 6]],
      \   [[3, 9], [4, 4], [4, 6]],
      \
      \   [[4, 1], [4, 4], [4, 6]],
      \   [[4, 2], [4, 4], [4, 6]],
      \   [[4, 3], [4, 4], [4, 6]],
      \   [[4, 4], [4, 4], [4, 6]],
      \   [[4, 5], [4, 4], [4, 6]],
      \   [[4, 6], [4, 4], [4, 6]],
      \   [[4, 7], [4, 7], [4, 7]],
      \   [[4, 8], [4, 8], [4, 8]],
      \   [[4, 9], [4, 9], [4, 9]],
      \
      \   [[5, 1], [5, 1], [5, 1]],
      \   [[5, 2], [5, 2], [5, 2]],
      \   [[5, 3], [5, 3], [5, 3]],
      \   [[5, 4], [5, 4], [5, 4]],
      \   [[5, 5], [5, 5], [5, 5]],
      \   [[5, 6], [5, 6], [5, 6]],
      \   [[5, 7], [5, 7], [5, 7]],
      \   [[5, 8], [5, 8], [5, 8]],
      \   [[5, 9], [5, 9], [5, 9]],
      \ ])
    end
  end

  context 'with "scan" = "cursor"'
    it 'is targeted if it is under the cursor'
      call Test('nc', [
      \   [[1, 1], [1, 1], [1, 1]],
      \   [[1, 2], [1, 2], [1, 2]],
      \   [[1, 3], [1, 3], [1, 3]],
      \   [[1, 4], [1, 4], [1, 6]],
      \   [[1, 5], [1, 4], [1, 6]],
      \   [[1, 6], [1, 4], [1, 6]],
      \   [[1, 7], [1, 7], [1, 7]],
      \   [[1, 8], [1, 8], [1, 8]],
      \   [[1, 9], [1, 9], [1, 9]],
      \
      \   [[2, 1], [2, 1], [2, 3]],
      \   [[2, 2], [2, 1], [2, 3]],
      \   [[2, 3], [2, 1], [2, 3]],
      \   [[2, 4], [2, 4], [2, 4]],
      \   [[2, 5], [2, 5], [2, 5]],
      \   [[2, 6], [2, 6], [2, 6]],
      \   [[2, 7], [2, 7], [2, 9]],
      \   [[2, 8], [2, 7], [2, 9]],
      \   [[2, 9], [2, 7], [2, 9]],
      \
      \   [[3, 1], [3, 1], [3, 1]],
      \   [[3, 2], [3, 2], [3, 2]],
      \   [[3, 3], [3, 3], [3, 3]],
      \   [[3, 4], [3, 4], [3, 4]],
      \   [[3, 5], [3, 5], [3, 5]],
      \   [[3, 6], [3, 6], [3, 6]],
      \   [[3, 7], [3, 7], [3, 7]],
      \   [[3, 8], [3, 8], [3, 8]],
      \   [[3, 9], [3, 9], [3, 9]],
      \
      \   [[4, 1], [4, 1], [4, 1]],
      \   [[4, 2], [4, 2], [4, 2]],
      \   [[4, 3], [4, 3], [4, 3]],
      \   [[4, 4], [4, 4], [4, 6]],
      \   [[4, 5], [4, 4], [4, 6]],
      \   [[4, 6], [4, 4], [4, 6]],
      \   [[4, 7], [4, 7], [4, 7]],
      \   [[4, 8], [4, 8], [4, 8]],
      \   [[4, 9], [4, 9], [4, 9]],
      \
      \   [[5, 1], [5, 1], [5, 1]],
      \   [[5, 2], [5, 2], [5, 2]],
      \   [[5, 3], [5, 3], [5, 3]],
      \   [[5, 4], [5, 4], [5, 4]],
      \   [[5, 5], [5, 5], [5, 5]],
      \   [[5, 6], [5, 6], [5, 6]],
      \   [[5, 7], [5, 7], [5, 7]],
      \   [[5, 8], [5, 8], [5, 8]],
      \   [[5, 9], [5, 9], [5, 9]],
      \ ])
    end
  end

  context 'with "scan" = "forward"'
    it 'is targeted if it is under or following to the cursor'
      call Test('nf', [
      \   [[1, 1], [1, 4], [1, 6]],
      \   [[1, 2], [1, 4], [1, 6]],
      \   [[1, 3], [1, 4], [1, 6]],
      \   [[1, 4], [1, 4], [1, 6]],
      \   [[1, 5], [1, 4], [1, 6]],
      \   [[1, 6], [1, 4], [1, 6]],
      \   [[1, 7], [2, 1], [2, 3]],
      \   [[1, 8], [2, 1], [2, 3]],
      \   [[1, 9], [2, 1], [2, 3]],
      \
      \   [[2, 1], [2, 1], [2, 3]],
      \   [[2, 2], [2, 1], [2, 3]],
      \   [[2, 3], [2, 1], [2, 3]],
      \   [[2, 4], [2, 7], [2, 9]],
      \   [[2, 5], [2, 7], [2, 9]],
      \   [[2, 6], [2, 7], [2, 9]],
      \   [[2, 7], [2, 7], [2, 9]],
      \   [[2, 8], [2, 7], [2, 9]],
      \   [[2, 9], [2, 7], [2, 9]],
      \
      \   [[3, 1], [4, 4], [4, 6]],
      \   [[3, 2], [4, 4], [4, 6]],
      \   [[3, 3], [4, 4], [4, 6]],
      \   [[3, 4], [4, 4], [4, 6]],
      \   [[3, 5], [4, 4], [4, 6]],
      \   [[3, 6], [4, 4], [4, 6]],
      \   [[3, 7], [4, 4], [4, 6]],
      \   [[3, 8], [4, 4], [4, 6]],
      \   [[3, 9], [4, 4], [4, 6]],
      \
      \   [[4, 1], [4, 4], [4, 6]],
      \   [[4, 2], [4, 4], [4, 6]],
      \   [[4, 3], [4, 4], [4, 6]],
      \   [[4, 4], [4, 4], [4, 6]],
      \   [[4, 5], [4, 4], [4, 6]],
      \   [[4, 6], [4, 4], [4, 6]],
      \   [[4, 7], [4, 7], [4, 7]],
      \   [[4, 8], [4, 8], [4, 8]],
      \   [[4, 9], [4, 9], [4, 9]],
      \
      \   [[5, 1], [5, 1], [5, 1]],
      \   [[5, 2], [5, 2], [5, 2]],
      \   [[5, 3], [5, 3], [5, 3]],
      \   [[5, 4], [5, 4], [5, 4]],
      \   [[5, 5], [5, 5], [5, 5]],
      \   [[5, 6], [5, 6], [5, 6]],
      \   [[5, 7], [5, 7], [5, 7]],
      \   [[5, 8], [5, 8], [5, 8]],
      \   [[5, 9], [5, 9], [5, 9]],
      \ ])
    end
  end

  context 'with "scan" = "line"'
    it 'is targeted if it is in the current line'
      call Test('nl', [
      \   [[1, 1], [1, 4], [1, 6]],
      \   [[1, 2], [1, 4], [1, 6]],
      \   [[1, 3], [1, 4], [1, 6]],
      \   [[1, 4], [1, 4], [1, 6]],
      \   [[1, 5], [1, 4], [1, 6]],
      \   [[1, 6], [1, 4], [1, 6]],
      \   [[1, 7], [1, 4], [1, 6]],
      \   [[1, 8], [1, 4], [1, 6]],
      \   [[1, 9], [1, 4], [1, 6]],
      \
      \   [[2, 1], [2, 1], [2, 3]],
      \   [[2, 2], [2, 1], [2, 3]],
      \   [[2, 3], [2, 1], [2, 3]],
      \   [[2, 4], [2, 7], [2, 9]],
      \   [[2, 5], [2, 7], [2, 9]],
      \   [[2, 6], [2, 7], [2, 9]],
      \   [[2, 7], [2, 7], [2, 9]],
      \   [[2, 8], [2, 7], [2, 9]],
      \   [[2, 9], [2, 7], [2, 9]],
      \
      \   [[3, 1], [3, 1], [3, 1]],
      \   [[3, 2], [3, 2], [3, 2]],
      \   [[3, 3], [3, 3], [3, 3]],
      \   [[3, 4], [3, 4], [3, 4]],
      \   [[3, 5], [3, 5], [3, 5]],
      \   [[3, 6], [3, 6], [3, 6]],
      \   [[3, 7], [3, 7], [3, 7]],
      \   [[3, 8], [3, 8], [3, 8]],
      \   [[3, 9], [3, 9], [3, 9]],
      \
      \   [[4, 1], [4, 4], [4, 6]],
      \   [[4, 2], [4, 4], [4, 6]],
      \   [[4, 3], [4, 4], [4, 6]],
      \   [[4, 4], [4, 4], [4, 6]],
      \   [[4, 5], [4, 4], [4, 6]],
      \   [[4, 6], [4, 4], [4, 6]],
      \   [[4, 7], [4, 4], [4, 6]],
      \   [[4, 8], [4, 4], [4, 6]],
      \   [[4, 9], [4, 4], [4, 6]],
      \
      \   [[5, 1], [5, 1], [5, 1]],
      \   [[5, 2], [5, 2], [5, 2]],
      \   [[5, 3], [5, 3], [5, 3]],
      \   [[5, 4], [5, 4], [5, 4]],
      \   [[5, 5], [5, 5], [5, 5]],
      \   [[5, 6], [5, 6], [5, 6]],
      \   [[5, 7], [5, 7], [5, 7]],
      \   [[5, 8], [5, 8], [5, 8]],
      \   [[5, 9], [5, 9], [5, 9]],
      \ ])
    end
  end

  context 'with "scan" = "nearest"'
    it 'is targeted if it is nearest from the cursor'
      call Test('nn', [
      \   [[1, 1], [1, 4], [1, 6]],
      \   [[1, 2], [1, 4], [1, 6]],
      \   [[1, 3], [1, 4], [1, 6]],
      \   [[1, 4], [1, 4], [1, 6]],
      \   [[1, 5], [1, 4], [1, 6]],
      \   [[1, 6], [1, 4], [1, 6]],
      \   [[1, 7], [1, 4], [1, 6]],
      \   [[1, 8], [1, 4], [1, 6]],
      \   [[1, 9], [1, 4], [1, 6]],
      \
      \   [[2, 1], [2, 1], [2, 3]],
      \   [[2, 2], [2, 1], [2, 3]],
      \   [[2, 3], [2, 1], [2, 3]],
      \   [[2, 4], [2, 7], [2, 9]],
      \   [[2, 5], [2, 7], [2, 9]],
      \   [[2, 6], [2, 7], [2, 9]],
      \   [[2, 7], [2, 7], [2, 9]],
      \   [[2, 8], [2, 7], [2, 9]],
      \   [[2, 9], [2, 7], [2, 9]],
      \
      \   [[3, 1], [4, 4], [4, 6]],
      \   [[3, 2], [4, 4], [4, 6]],
      \   [[3, 3], [4, 4], [4, 6]],
      \   [[3, 4], [4, 4], [4, 6]],
      \   [[3, 5], [4, 4], [4, 6]],
      \   [[3, 6], [4, 4], [4, 6]],
      \   [[3, 7], [4, 4], [4, 6]],
      \   [[3, 8], [4, 4], [4, 6]],
      \   [[3, 9], [4, 4], [4, 6]],
      \
      \   [[4, 1], [4, 4], [4, 6]],
      \   [[4, 2], [4, 4], [4, 6]],
      \   [[4, 3], [4, 4], [4, 6]],
      \   [[4, 4], [4, 4], [4, 6]],
      \   [[4, 5], [4, 4], [4, 6]],
      \   [[4, 6], [4, 4], [4, 6]],
      \   [[4, 7], [4, 4], [4, 6]],
      \   [[4, 8], [4, 4], [4, 6]],
      \   [[4, 9], [4, 4], [4, 6]],
      \
      \   [[5, 1], [4, 4], [4, 6]],
      \   [[5, 2], [4, 4], [4, 6]],
      \   [[5, 3], [4, 4], [4, 6]],
      \   [[5, 4], [4, 4], [4, 6]],
      \   [[5, 5], [4, 4], [4, 6]],
      \   [[5, 6], [4, 4], [4, 6]],
      \   [[5, 7], [4, 4], [4, 6]],
      \   [[5, 8], [4, 4], [4, 6]],
      \   [[5, 9], [4, 4], [4, 6]],
      \ ])
    end
  end
end