" Filter_cnf.vim
" @Author:      Tom Link (mailto:micathom AT gmail com?subject=[vim])
" @Website:     http://www.vim.org/account/profile.php?user_id=4037
" @License:     GPL (see http://www.gnu.org/licenses/gpl.txt)
" @Created:     2008-11-25.
" @Last Change: 2014-11-18.
" @Revision:    0.0.114

let s:prototype = tlib#Object#New({'_class': ['Filter_cnf'], 'name': 'cnf'}) "{{{2
let s:prototype.highlight = g:tlib#input#higroup

" The search pattern for |tlib#input#List()| is in conjunctive normal 
" form: (P1 OR P2 ...) AND (P3 OR P4 ...) ...
" The pattern is a '/\V' very no-'/magic' regexp pattern.
"
" Pressing <space> joins two patterns with AND.
" Pressing | joins two patterns with OR.
" I.e. In order to get "lala AND (foo OR bar)", you type 
" "lala foo|bar".
"
" This is also the base class for other filters.
function! tlib#Filter_cnf#New(...) "{{{3
    let object = s:prototype.New(a:0 >= 1 ? a:1 : {})
    return object
endf


" :nodoc:
function! s:prototype.Init(world) dict "{{{3
endf


" :nodoc:
function! s:prototype.Help(world) dict "{{{3
    call a:world.PushHelp(
                \ printf('"%s", "%s", "%sWORD"', g:tlib#input#and, g:tlib#input#or, g:tlib#input#not),
                \ 'AND, OR, NOT')
endf


" :nodoc:
function! s:prototype.AssessName(world, name) dict "{{{3
    let xa  = 0
    let prefix = self.FilterRxPrefix()
    for flt in a:world.filter_pos
        " let flt = prefix . a:world.GetRx(fltl)
        " if flt =~# '\u' && a:name =~# flt
        "     let xa += 5
        " endif

        if a:name =~ '\^'. flt
            let xa += 4
        elseif a:name =~ '\<'. flt
            let xa += 3
        " elseif a:name =~ '[[:punct:][:space:][:digit:]]'. flt
        "     let xa += 2
        elseif a:name =~ '\A'. flt .'\|'. flt .'\A'
            let xa += 1
        endif
    endfor
    " TLogVAR a:name, xa
    return xa
endf


" :nodoc:
function! s:prototype.Match(world, text) dict "{{{3
    " TLogVAR a:text
    " let sc = &smartcase
    " let ic = &ignorecase
    " if &ignorecase
    "     set smartcase
    " endif
    " try
    if !empty(a:world.filter_neg)
        for rx in a:world.filter_neg
            " TLogVAR rx
            if a:text =~ rx
                return 0
            endif
        endfor
    endif
    if !empty(a:world.filter_pos)
        for rx in a:world.filter_pos
            " TLogVAR rx
            if a:text !~ rx
                return 0
            endif
        endfor
    endif
    " finally
    "     let &smartcase = sc
    "     let &ignorecase = ic
    " endtry
    return 1
endf


" :nodoc:
function! s:prototype.DisplayFilter(filter) dict "{{{3
    let filter1 = deepcopy(a:filter)
    call map(filter1, '"(". join(reverse(self.Pretty(v:val)), " OR ") .")"')
    return join(reverse(filter1), ' AND ')
endf


function! s:prototype.Pretty(filter) dict "{{{3
    " call map(a:filter, 'substitute(v:val, ''\\\.\\{-}'', ''=>'', ''g'')')
    call map(a:filter, 'self.CleanFilter(v:val)')
    return a:filter
endf


" :nodoc:
function! s:prototype.SetFrontFilter(world, pattern) dict "{{{3
    let a:world.filter[0] = reverse(split(a:pattern, '\s*|\s*')) + a:world.filter[0][1 : -1]
endf


" :nodoc:
function! s:prototype.PushFrontFilter(world, char) dict "{{{3
    let a:world.filter[0][0] .= nr2char(a:char)
endf


" :nodoc:
function! s:prototype.ReduceFrontFilter(world) dict "{{{3
    let filter = a:world.filter[0][0]
    " TLogVAR filter
    let str = matchstr(filter, '\(\\\(\.\\{-}\|[.?*+$^]\)\|\)$')
    if empty(str)
        let filter = filter[0 : -2]
    else
        let filter = strpart(filter, 0, len(filter) - len(str))
    endif
    " TLogVAR str, filter
    let a:world.filter[0][0] = filter
endf


" :nodoc:
function! s:prototype.FilterRxPrefix() dict "{{{3
    return '\V'
endf


" :nodoc:
function! s:prototype.CleanFilter(filter) dict "{{{3
    return a:filter
endf

