<commit_before>let s:suite = themis#suite('default_behaviors')
let s:assert = themis#helper('assert')

map /  <Plug>(incsearch-forward)
map ?  <Plug>(incsearch-backward)
map g/ <Plug>(incsearch-stay)

" Helper:
function! AddLine(str)
    put! =a:str
endfunction
function! AddLines(lines)
    for line in reverse(a:lines)
        put! =line
    endfor
endfunction

function! s:assert.eq_with_default(command, default_command, pattern)
    let [x, y] = s:get_pos_with_default(a:command, a:default_command, a:pattern)
    call s:assert.equals(x,y)
endfunction

function! s:assert.not_eq_with_default(command, default_command, pattern)
    let [x, y] = s:get_pos_with_default(a:command, a:default_command, a:pattern)
    call s:assert.not_equals(x,y)
endfunction

function! s:get_pos_with_default(command, default_command, pattern)
    let w = winsaveview()
    silent! exec 'normal! ' . a:default_command . a:pattern . "\<CR>"
    let x = getcurpos()
    call winrestview(w)
    silent! exec 'normal ' . a:command . a:pattern . "\<CR>"
    let y = getcurpos()
    return [x, y]
endfunction

function! s:is_pos_less_equal(x, y) " x <= y
    return (a:x[0] == a:y[0]) ? a:x[1] <= a:y[1] : a:x[0] < a:y[0]
endfunction

function! s:get_pos_char()
    return getline('.')[col('.')-1]
endfunction

" Main:

function! s:suite.forward()
    call AddLines(['pattern1 pattern2 pattern3',
                \  'pattern4 pattern5 pattern6'])
    set nowrapscan
    call s:assert.eq_with_default('/','/','pat')
    call s:assert.eq_with_default('/','/','pattern\d')
    normal! gg0
    call s:assert.eq_with_default('/','/','pattern1')
    call s:assert.eq_with_default('/','/','pattern2')
    call s:assert.eq_with_default('/','/','pattern3')
    set wrapscan
    normal! gg0
    call s:assert.eq_with_default('/','/','pattern2')
    call s:assert.eq_with_default('/','/','pattern1')

    " Handle empty input
    normal! gg0
    call s:assert.eq_with_default('/','/','pat')
    let x = getpos('.')
    call s:assert.eq_with_default('/','/','')
    let y = getpos('.')
    call s:assert.not_equals(x, y)
    call s:assert.true(s:is_pos_less_equal(x, y))
endfunction

function! s:suite.backward()
    call AddLines(['pattern1 pattern2 pattern3',
                \  'pattern4 pattern5 pattern6'])
    set nowrapscan
    normal! G$
    call s:assert.eq_with_default('?','?','pattern3')
    call s:assert.eq_with_default('?','?','pattern2')
    call s:assert.eq_with_default('?','?','pattern1')
    normal! G$
    call s:assert.not_eq_with_default('?','/','pattern3')
    call s:assert.not_eq_with_default('?','/','pattern2')
    call s:assert.not_eq_with_default('?','/','pattern1')
    set wrapscan
    normal! gg0
    call s:assert.eq_with_default('?','?','pattern5')
    call s:assert.eq_with_default('?','/','pattern5')

    " Handle empty input
    normal! G$
    call s:assert.eq_with_default('?','?','pat')
    let x = getpos('.')[1:2]
    call s:assert.eq_with_default('?','?','')
    let y = getpos('.')[1:2]
    call s:assert.not_equals(x, y)
    call s:assert.true(s:is_pos_less_equal(y, x))
endfunction

function! s:suite.stay()
    call AddLines(['pattern1 pattern2 pattern3',
                \  'pattern4 pattern5 pattern6'])
    set nowrapscan
    normal! gg0
    let c = getcurpos()
    call s:assert.not_eq_with_default('g/','/','pat')
    call s:assert.equals(getcurpos(), c)
    set wrapscan
    call s:assert.not_eq_with_default('g/','/','pat')
    call s:assert.equals(getcurpos(), c)

    " History
    exec "normal g/hoge\<CR>"
    call s:assert.equals('hoge', @/)
    call s:assert.equals('hoge', histget('/', -1))

    " Handle empty input
    normal! gg0
    call s:assert.not_eq_with_default('g/','/','pat')
    let x = getpos('.')
    call s:assert.not_eq_with_default('g/','/','')
    let y = getpos('.')
    call s:assert.equals(x, y)
    call s:assert.not_equals('', @/)
    call s:assert.not_equals('', histget('/', -1))
    call s:assert.equals('pat', @/)
    call s:assert.equals('pat', histget('/', -1))
endfunction

function! s:suite.offset()
    call AddLines(['pattern1 pattern2 pattern3',
                \  'pattern4 pattern5 pattern6'])
    normal! gg0
    call s:assert.eq_with_default('/','/','pattern1/e')
    call s:assert.equals(s:get_pos_char(), '1')
    call s:assert.eq_with_default('?','?','pat?e5+1')
    call s:assert.equals(s:get_pos_char(), '6')
    exec "normal g/pattern\\d/e\<CR>"
    call s:assert.equals('pattern\d', @/)
    call s:assert.equals('pattern\d/e', histget('/', -1))
endfunction
<commit_msg>Use winsaveview() instead of getcurpos()<commit_after>let s:suite = themis#suite('default_behaviors')
let s:assert = themis#helper('assert')

map /  <Plug>(incsearch-forward)
map ?  <Plug>(incsearch-backward)
map g/ <Plug>(incsearch-stay)

" Helper:
function! AddLine(str)
    put! =a:str
endfunction
function! AddLines(lines)
    for line in reverse(a:lines)
        put! =line
    endfor
endfunction

function! s:assert.eq_with_default(command, default_command, pattern)
    let [x, y] = s:get_pos_with_default(a:command, a:default_command, a:pattern)
    call s:assert.equals(x,y)
endfunction

function! s:assert.not_eq_with_default(command, default_command, pattern)
    let [x, y] = s:get_pos_with_default(a:command, a:default_command, a:pattern)
    call s:assert.not_equals(x,y)
endfunction

function! s:get_pos_with_default(command, default_command, pattern)
    let w = winsaveview()
    silent! exec 'normal! ' . a:default_command . a:pattern . "\<CR>"
    " let x = getcurpos()
    let x = winsaveview()
    call winrestview(w)
    silent! exec 'normal ' . a:command . a:pattern . "\<CR>"
    " let y = getcurpos()
    let y = winsaveview()
    return [x, y]
endfunction

function! s:is_pos_less_equal(x, y) " x <= y
    return (a:x[0] == a:y[0]) ? a:x[1] <= a:y[1] : a:x[0] < a:y[0]
endfunction

function! s:get_pos_char()
    return getline('.')[col('.')-1]
endfunction

" Main:

function! s:suite.forward()
    call AddLines(['pattern1 pattern2 pattern3',
                \  'pattern4 pattern5 pattern6'])
    set nowrapscan
    call s:assert.eq_with_default('/','/','pat')
    call s:assert.eq_with_default('/','/','pattern\d')
    normal! gg0
    call s:assert.eq_with_default('/','/','pattern1')
    call s:assert.eq_with_default('/','/','pattern2')
    call s:assert.eq_with_default('/','/','pattern3')
    set wrapscan
    normal! gg0
    call s:assert.eq_with_default('/','/','pattern2')
    call s:assert.eq_with_default('/','/','pattern1')

    " Handle empty input
    normal! gg0
    call s:assert.eq_with_default('/','/','pat')
    let x = getpos('.')
    call s:assert.eq_with_default('/','/','')
    let y = getpos('.')
    call s:assert.not_equals(x, y)
    call s:assert.true(s:is_pos_less_equal(x, y))
endfunction

function! s:suite.backward()
    call AddLines(['pattern1 pattern2 pattern3',
                \  'pattern4 pattern5 pattern6'])
    set nowrapscan
    normal! G$
    call s:assert.eq_with_default('?','?','pattern3')
    call s:assert.eq_with_default('?','?','pattern2')
    call s:assert.eq_with_default('?','?','pattern1')
    normal! G$
    call s:assert.not_eq_with_default('?','/','pattern3')
    call s:assert.not_eq_with_default('?','/','pattern2')
    call s:assert.not_eq_with_default('?','/','pattern1')
    set wrapscan
    normal! gg0
    call s:assert.eq_with_default('?','?','pattern5')
    call s:assert.eq_with_default('?','/','pattern5')

    " Handle empty input
    normal! G$
    call s:assert.eq_with_default('?','?','pat')
    let x = getpos('.')[1:2]
    call s:assert.eq_with_default('?','?','')
    let y = getpos('.')[1:2]
    call s:assert.not_equals(x, y)
    call s:assert.true(s:is_pos_less_equal(y, x))
endfunction

function! s:suite.stay()
    call AddLines(['pattern1 pattern2 pattern3',
                \  'pattern4 pattern5 pattern6'])
    set nowrapscan
    normal! gg0
    " let c = getcurpos()
    let c = winsaveview()
    call s:assert.not_eq_with_default('g/','/','pat')
    " call s:assert.equals(getcurpos(), c)
    call s:assert.equals(winsaveview(), c)
    set wrapscan
    call s:assert.not_eq_with_default('g/','/','pat')
    " call s:assert.equals(getcurpos(), c)
    call s:assert.equals(winsaveview(), c)

    " History
    exec "normal g/hoge\<CR>"
    call s:assert.equals('hoge', @/)
    call s:assert.equals('hoge', histget('/', -1))

    " Handle empty input
    normal! gg0
    call s:assert.not_eq_with_default('g/','/','pat')
    let x = getpos('.')
    call s:assert.not_eq_with_default('g/','/','')
    let y = getpos('.')
    call s:assert.equals(x, y)
    call s:assert.not_equals('', @/)
    call s:assert.not_equals('', histget('/', -1))
    call s:assert.equals('pat', @/)
    call s:assert.equals('pat', histget('/', -1))
endfunction

function! s:suite.offset()
    call AddLines(['pattern1 pattern2 pattern3',
                \  'pattern4 pattern5 pattern6'])
    normal! gg0
    call s:assert.eq_with_default('/','/','pattern1/e')
    call s:assert.equals(s:get_pos_char(), '1')
    call s:assert.eq_with_default('?','?','pat?e5+1')
    call s:assert.equals(s:get_pos_char(), '6')
    exec "normal g/pattern\\d/e\<CR>"
    call s:assert.equals('pattern\d', @/)
    call s:assert.equals('pattern\d/e', histget('/', -1))
endfunction

{'fraction_non_alphanumeric': 0.18675282714054928, 'fraction_numerical': 0.013785675821217017, 'mean_word_length': 3.762051282051282, 'pattern_counts': {'":': 0, '<': 23, '<?xml version=': 0, '>': 17, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7430852', 'n_tokens_mistral': 3441, 'n_tokens_neox': 3424, 'n_words': 649}