Commits

ZyX_I committed 0b645d5

Added @/signs module

Comments (0)

Files changed (35)

         3.14. plugin/frawor/lua features          |frawor-f-frawor/lua|
         3.15. plugin/frawor/ruby features         |frawor-f-frawor/ruby|
         3.16. plugin/frawor/tcl features          |frawor-f-frawor/tcl|
+        3.17. plugin/frawor/signs features        |frawor-f-frawor/signs|
     4. Resources                                  |frawor-resources|
         4.1. map resource                         |frawor-r-map|
         4.2. os resource                          |frawor-r-os|
         4.3. py resource                          |frawor-r-py|
         4.4. printtable resource                  |frawor-r-printtable|
         4.5. base64 resource                      |frawor-r-base64|
+        4.6. sign resource                        |frawor-r-sign|
     5. Options                                    |frawor-options|
         5.1. Mapping options                      |frawor-mapoptions|
     6. Type definitions                           |frawor-types|
 
 delcommands : unloadpre + s:_commands                   *frawor-f-delcommands*
               register + s:_commands
-        Deletes autocmd groups listed in s:_commands. It is 
-        |frawor-fk-ignoredeps| feature, so you don't need specify 
-        plugin/frawor/commands in your dependencies.
+        Deletes commands listed in s:_commands. It is |frawor-fk-ignoredeps| 
+        feature, so you don't need specify plugin/frawor/commands in your 
+        dependencies.
         Usage: >
             command -nargs=? Foo echo "Bar"
             let s:_commands+=["Foo"]
         removes it when plugin is unloaded. It is |frawor-fk-ignoredeps| 
         feature, so you don't need to do anything to make it work.
 
+------------------------------------------------------------------------------
+3.17. plugin/frawor/signs features                     *frawor-f-frawor/signs*
+
+delsigns : unloadpre + s:_signs                            *frawor-f-delsigns*
+            register + s:_signs
+        Deletes signs listed in s:_signs. It is |frawor-fk-ignoredeps| 
+        feature, so you don't need specify plugin/frawor/signs in your 
+        dependencies.
+        Usage: >
+            sign define xxx text=EE texthl=Error
+            let s:_signs+=["xxx"]
+
+sign.new : function (sgid, sgopts)                         *frawor-f-sign.new*
+         + unload
+        Define a new sign with name {sgid} (0 if you don't care about 
+        human-readable names). Returns sign name ({sgid} if it is not 0). 
+        {sgopts} is a dictionary with the following keys (see |sign-define|):
+            Key     Description ~
+            text    One or two printable characters.
+            texthl  Highlight group for text.
+            linehl  Highlight group for line with sign.
+            icon    Sign icon. Ignored unless has("gui_running") return 1.
+        At least one of these keys must be present.
+
+sign.place : function (sgid, bufnr, line)                *frawor-f-sign.place*
+        Place sign defined using |frawor-f-sign.new|. Use 0 for {bufnr} if you 
+        want to place sign in current buffer.
+
+sign.delete : function ([ sgid ])                       *frawor-f-sign.delete*
+        Unplace and delete sign defined using |frawor-f-sign.new|. If no 
+        {sgid} given, delete all signs defined by this plugin.
+
 ==============================================================================
 4. Resources                                                *frawor-resources*
 
         returned by |readfile()| or |getline()| with two arguments (see 
         |NL-used-for-Nul|).
 
+------------------------------------------------------------------------------
+4.6. sign resource                                             *frawor-r-sign*
+
+Resource `sign' is defined in plugin/frawor/signs. It is used for signs 
+manipulation, see |:sign|.
+
+sign.exists :: sgid -> Bool                             *frawor-r-sign.exists*
+        Check whether sign with given name exists.
+sign.delete :: sgid -> _                                *frawor-r-sign.delete*
+        Unplace and delete sign with given id.
+sign.getbuf :: bufnr -> [(line, id, name)]              *frawor-r-sign.getbuf*
+        Get all signs placed in buffer with given number. Returns a list of 
+        3-tuples ({line}, {id}, {name}) where {line} is line number, {id} is 
+        placed id (see |:sign-place|) and {name} is sign id (see 
+        |:sign-define|).
+sign.getdef :: sgid -> sgopts                           *frawor-r-sign.getdef*
+        Get definition of sign named {sgid}. Returns a dictionary which may 
+        contain keys `text', `texthl', `linehl' and `icon', see 
+        |:sign-define|.
+
 ==============================================================================
 5. Options                                                    *frawor-options*
                                                              *g:fraworOptions*
                                   used by |frawor-f-delaugroups|.
 *s:_commands*      frawor/commands  List of strings containing command names. 
                                   Is used by |frawor-f-delcommands|.
+*s:_signs*         frawor/signs     List of strings containing sign names. Is 
+                                  used by |frawor-f-delsigns|.
 *s:_functions*     frawor/functions List containing references to global and 
                                   script-local functions or their names. Is 
                                   used by |frawor-f-delfunctions| and set by 

plugin/frawor/signs.vim

+"▶1 Header
+scriptencoding utf-8
+execute frawor#Setup('0.0', {'@/os': '0.0',
+            \         '@/resources': '0.0',}, 1)
+let s:F.sign={}
+let s:signs={}
+let s:lastsgid=0
+"▶1 Define messages
+if v:lang=~?'ru'
+    let s:_messages={
+                \  'sgidnstr': 'Ошибка создания знака для дополнения %s: '.
+                \              'имя команды не является строкой',
+                \   'invsgid': 'Ошибка создания знака для дополнения %s: '.
+                \              'строка «%s» не может являться именем знака',
+                \ 'dsgidnstr': 'Ошибка удаления знака для дополнения %s: '.
+                \              'имя команды не является строкой',
+                \  'dinvsgid': 'Ошибка удаления знака для дополнения %s: '.
+                \              'строка «%s» не может являться именем знака',
+                \  'nthisdef': 'Ошибка удаления знака %s для дополнения %s: '.
+                \              'знак не был определён данным дополнением',
+                \ 'psgidnstr': 'Ошибка показа знака для дополнения %s: '.
+                \              'имя команды не является строкой',
+                \  'pinvsgid': 'Ошибка показа знака для дополнения %s: '.
+                \              'строка «%s» не может являться именем знака',
+            \}
+    call extend(s:_messages, map({
+                \   'sgiddef': 'знак уже определён дополнением %s',
+                \'sgoptsndct': 'второй аргумент не является словарём',
+                \  'sgoempty': 'второй аргумент не содержит информации, '.
+                \              'достаточной для определения знака',
+                \'sgokeynstr': 'значение ключа %s не является строкой',
+                \    'hlndef': 'неизвестная группа подсветки: %s',
+                \  'iconread': 'файл с иконкой (%s) нечитаем',
+                \   'invtext': '«%s» не может использовать в качестве '.
+                \              'текста знака',
+            \}, '"Ошибка создания знака %s для дополнения %s: ".v:val'))
+    call extend(s:_messages, map({
+                \ 'sgidundef': 'знак не определён',
+                \     'bnnum': 'второй аргумент не является числом',
+                \      'bnex': 'буфер с номером %i не существует',
+                \     'lnnum': 'третий аргумент не является числом',
+                \   'linvnum': 'номер строки должен быть положительным',
+                \    'sgndep': 'знак определён не данным дополнением и '.
+                \              'не одной из его зависимостей',
+            \}, '"Ошибка показа знака %s для дополнения %s: ".v:val'))
+else
+    let s:_messages={
+                \  'sgidnstr': 'Error while creating sign for plugin %s: '.
+                \              'command name is not a String',
+                \   'invsgid': 'Error while creating sign for plugin %s: '.
+                \              '`%s'' is not a valid sign name',
+                \ 'dsgidnstr': 'Error while deleting sign for plugin %s: '.
+                \              'command name is not a String',
+                \  'dinvsgid': 'Error while deleting sign for plugin %s: '.
+                \              '`%s'' is not a valid sign name',
+                \  'nthisdef': 'Error while deleting sign %s for plugin %s: '.
+                \              'sign was not defined by this plugin',
+                \ 'psgidnstr': 'Error while placing sign for plugin %s: '.
+                \              'command name is not a String',
+                \  'pinvsgid': 'Error while placing sign for plugin %s: '.
+                \              '`%s'' is not a valid sign name',
+            \}
+    call extend(s:_messages, map({
+                \   'sgiddef': 'sign was already defined by plugin %s',
+                \'sgoptsndct': 'second argument is not a Dictionary',
+                \  'sgoempty': 'second argument is missing information '.
+                \              'required to define a sign',
+                \'sgokeynstr': 'value of %s key is not a String',
+                \    'hlndef': 'unknown higlight group: %s',
+                \  'iconread': 'icon file (%s) is not readable',
+                \   'invtext': '`%s'' is not a valid sign text',
+            \}, '"Error while creating sign %s for plugin %s: ".v:val'))
+    call extend(s:_messages, map({
+                \ 'sgidundef': 'undefined sign',
+                \     'bnnum': 'second argument is not a Number',
+                \      'bnex': 'there is no buffer #%i',
+                \     'lnnum': 'third argument is not a Number',
+                \   'linvnum': 'line number must be positive',
+                \    'sgndep': 'sign was defined neither by this plugin '.
+                \              'nor by one of its dependencies',
+            \}, '"Error while placing sign %s for plugin %s: ".v:val'))
+endif
+"▶1 signexists  :: sgid + :sign → Bool
+function s:F.signexists(sgid)
+    try
+        silent execute 'sign list '.a:sgid
+        return 1
+    catch /Vim(sign):E155:/
+        return 0
+    endtry
+endfunction
+"▶1 getsigns    :: buf + :sign → [(line, id, name)]
+function s:F.getsigns(buf)
+    redir => placedstr
+        silent execute 'sign place buffer='.a:buf
+    redir END
+    return map(map(filter(split(placedstr, "\n"),
+                \         'v:val[:3] is# "    "'),
+                \  'map(split(v:val[4:]), "v:val[stridx(v:val, ''='')+1:]")'),
+                \'[+v:val[1], +v:val[0], v:val[2]]')
+endfunction
+"▶1 delsign     :: sgid → + :sign
+function s:F.delsign(sgid)
+    for buf in filter(range(1, bufnr('$')), 'bufexists(v:val)')
+        for psign in filter(s:F.getsigns(buf), 'v:val[2] is# a:sgid')
+            execute 'sign unplace '.psign[0].' buffer='.buf
+        endfor
+    endfor
+    execute 'sign undefine '.a:sgid
+endfunction
+"▶1 getsigndef  :: sgid + :sign → sgopts
+function s:F.getsigndef(sgid)
+    redir => defstr
+        silent execute 'sign list' a:sgid
+    redir END
+    let defstr=defstr[(6+len(a:sgid)):]
+    let r={}
+    " TODO check icons with spaces
+    for prop in split(defstr)
+        let eqidx=stridx(prop, '=')
+        let r[prop[:(eqidx-1)]]=prop[(eqidx+1):]
+    endfor
+    return r
+endfunction
+"▶1 Post resource
+call s:_f.postresource('sign', {'exists': s:F.signexists,
+            \                   'delete': s:F.delsign,
+            \                   'getbuf': s:F.getsigns,
+            \                   'getdef': s:F.getsigndef,})
+"▶1 add_signs   :: {f} → + p:_signs
+function s:F.add_signs(plugdict, fdict)
+    if !has_key(a:plugdict.g, '_signs') || type(a:plugdict.g._signs)!=type([])
+        let a:plugdict.g._signs=[]
+    endif
+endfunction
+"▶1 delsigns    :: {f} + p:_signs → + :delcommand, p:_signs
+function s:F.delsigns(plugdict, fdict)
+    if !has_key(a:plugdict.g, '_signs') || type(a:plugdict.g._signs)!=type([])
+        return
+    endif
+    call map(filter(a:plugdict.g._signs,
+                \   'type(v:val)=='.type('').' && v:val=~#''\v%(\d+|\h\w*)$'' '.
+                \   '&& s:F.signexists(v:val)'),
+                \'s:F.delsign(v:val)')
+endfunction
+call s:_f.newfeature('delsigns', {'unloadpre': s:F.delsigns,
+            \                      'register': s:F.add_signs,
+            \                    'ignoredeps': 1})
+"▶1 sign.delete :: {f}[, sgid] → + :sign, s:signs
+function s:F.sign.delete(plugdict, fdict, ...)
+    if a:0
+        "▶2 Check argument
+        if type(a:1)!=type('')
+            call s:_f.throw('dsgidnstr', a:plugdict.id)
+        elseif a:1!~#'\v^%(\d+|\h\w*)$'
+            call s:_f.throw('dinvsgid', a:plugdict.id, a:1)
+        elseif !has_key(a:fdict, a:1)
+            call s:_f.throw('nthisdef', a:1, a:plugdict.id)
+        endif
+        "▲2
+        call s:F.delsign(a:1)
+        unlet s:signs[a:1]
+        unlet a:fdict[a:1]
+    else
+        for sgid in keys(a:fdict)
+            call s:F.delsign(sgid)
+            unlet s:signs[sgid]
+            unlet a:fdict[sgid]
+        endfor
+    endif
+endfunction
+"▶1 sign.new    :: {f}, sgid, sgopts → + :sign, s:signs
+let s:sgokeys=['linehl', 'text', 'texthl']
+if has('gui_running')
+    call add(s:sgokeys, 'icon')
+endif
+function s:F.sign.new(plugdict, fdict, sgid, sgopts)
+    "▶2 Check first argument
+    if a:sgid isnot 0
+        if type(a:sgid)!=type('')
+            call s:_f.throw('sgidnstr', a:plugdict.id)
+        elseif a:sgid!~#'\v^%(\d+|\h\w*)$'
+            call s:_f.throw('invsgid', a:plugdict.id, a:sgid)
+        elseif has_key(s:signs, a:sgid)
+            call s:_f.throw('sgiddef', a:sgid, a:plugdict.id,
+                        \              s:signs[a:sgid].plid)
+        endif
+    endif
+    "▶2 Get sign id
+    if a:sgid is 0
+        let sgid=printf('frawor%x', s:lastsgid)
+        let s:lastsgid+=1
+        while s:F.signexists(sgid)
+            let sgid=printf('frawor%x', s:lastsgid)
+            let s:lastsgid+=1
+        endwhile
+    else
+        let sgid=a:sgid
+    endif
+    "▶2 Check second argument
+    if type(a:sgopts)!=type({})
+        call s:_f.throw('sgoptsndct', sgid, a:plugdict.id)
+    endif
+    "▲2
+    let sgokeys=filter(copy(s:sgokeys), 'has_key(a:sgopts, v:val)')
+    "▶2 Check sgokeys
+    if empty(sgokeys)
+        call s:_f.throw('sgoempty', sgid, a:plugdict.id)
+    endif
+    "▲2
+    let sign={'id': sgid, 'places': [], 'plid': a:plugdict.id}
+    "▶2 Process options
+    let d={}
+    for key in sgokeys
+        let d.value=a:sgopts[key]
+        if type(d.value)!=type('')
+            call s:_f.throw('sgokeynstr', sgid, a:plugdict.id, key)
+        endif
+        if key[-2:] is# 'hl'
+            if !hlexists(d.value)
+                call s:_f.throw('hlndef', sgid, a:plugdict.id, d.value)
+            endif
+        elseif key is# 'icon'
+            if !filereadable(d.value)
+                call s:_f.throw('iconread', sgid, a:plugdict.id, d.value)
+            endif
+            let sign.ifile=s:_r.os.path.abspath(s:_r.os.path.normpath(d.value))
+            let d.value=fnameescape(sign.ifile)
+        elseif key is# 'text'
+            if d.value!~#'\v^\p?\p$'
+                call s:_f.throw('invtext', sgid, a:plugdict.id, d.value)
+            endif
+        endif
+        let sign[key]=d.value
+    endfor
+    "▲2
+    let sign.cmd='sign define '.sign.id.' '.
+                \join(map(copy(sgokeys), 'v:val."=".sign[v:val]'))
+    execute sign.cmd
+    let a:fdict[sign.id]=sign
+    let s:signs[sign.id]=sign
+    return sign.id
+endfunction
+"▶1 sign.place  :: {f}, sgid, buf, line → + :sign, s:signs
+function s:F.sign.place(plugdict, fdict, sgid, buf, line)
+    "▶2 Check arguments
+    if type(a:sgid)!=type('')
+        call s:_f.throw('psgidnstr', a:plugdict.id)
+    elseif a:sgid!~#'\v^%(\d+|\h\w*)$'
+        call s:_f.throw('pinvsgid', a:plugdict.id, a:sgid)
+    elseif !s:F.signexists(a:sgid)
+        call s:_f.throw('sgidundef', a:sgid, a:plugdict.id)
+    elseif type(a:buf)!=type(0)
+        call s:_f.throw('bnnum', a:sgid, a:plugdict.id)
+    elseif a:buf isnot 0 && !bufexists(a:buf)
+        call s:_f.throw('bnex', a:sgid, a:plugdict.id, a:buf)
+    elseif type(a:line)!=type(0)
+        call s:_f.throw('lnnum', a:sgid, a:plugdict.id)
+    elseif a:line<=0
+        call s:_f.throw('linvnum', a:sgid, a:plugdict.id)
+    endif
+    "▶2 Sign was defined by this module
+    if has_key(s:signs, a:sgid)
+        let sign=s:signs[a:sgid]
+        if !(has_key(a:fdict, a:sgid) ||
+                    \has_key(a:plugdict.dependencies, sign.plid))
+            call s:_f.throw('sgndep', a:sgid, a:plugdict.id)
+        endif
+    endif
+    "▶2 Define buf
+    let buf=a:buf
+    if buf is 0
+        let buf=bufnr('%')
+    endif
+    "▲2
+    let id=max(map(s:F.getsigns(buf), 'v:val[0]'))+1
+    execute 'sign place '.id.' line='.a:line.' name='.a:sgid.' buffer='.buf
+    "▶2 Add tuple to sign.places
+    if exists('sign')
+        call add(sign.places, [id, buf, a:line])
+    endif
+    "▲2
+    return id
+endfunction
+"▶1 Register feature
+call s:_f.newfeature('sign', {'cons': s:F.sign,
+            \               'unload': s:F.sign.delete,})
+"▶1
+call frawor#Lockvar(s:, 'signs,lastsgid')
+" vim: fmr=▶,▲ sw=4 ts=4 sts=4 et tw=80

test/global-functions-reload.ok

 1      echo 1
    endfunction
 
-   function <SNR>28_testFunction()
+   function <SNR>29_testFunction()
 1      echo 2
    endfunction
 
 1      echo 1
    endfunction
 
-   function <SNR>28_testFunction()
+   function <SNR>29_testFunction()
 1      echo 2
    endfunction

test/ignoredeps-feature.ok

 load: plugin/frawor/fwc/parser
 register: plugin/frawor
 load: plugin/frawor
+register: plugin/frawor/signs
+load: plugin/frawor/signs
 register: plugin/frawor/decorators
 load: plugin/frawor/decorators
 register: plugin/frawor/mappings

test/invalid-signs.in

+:let &rtp.=",".escape($TESTDIR, ',\').'/rtp'
+:let i=1
+:while filereadable("rtp/plugin/".g:curtest.".".i.".vim") | let g:testfile="plugin/".g:curtest.".".i.".vim" | source test-nomessages.vim | let i+=1 | endwhile
+:source test-writemessages.vim

test/invalid-signs.ok

+.1: plugin/frawor/signs:sgidnstr
+.2: plugin/frawor/signs:sgidnstr
+.3: plugin/frawor/signs:sgoptsndct
+.4: plugin/frawor/signs:sgoempty
+.5: plugin/frawor/signs:invtext
+.6: plugin/frawor/signs:invtext
+.7: plugin/frawor/signs:hlndef
+.8: plugin/frawor/signs:hlndef
+.9: plugin/frawor/signs:sgokeynstr
+.10: plugin/frawor/signs:sgokeynstr
+.11: plugin/frawor/signs:sgokeynstr
+.12: plugin/frawor/signs:psgidnstr
+.13: plugin/frawor/signs:bnex
+.14: plugin/frawor/signs:linvnum
+.15: plugin/frawor/signs:lnnum
+.16: plugin/frawor/signs:bnnum
+.17: plugin/frawor/signs:dsgidnstr
+.18: plugin/frawor/signs:dinvsgid
+.19: plugin/frawor/signs:nthisdef

test/reload-frawor.ok

 load: plugin/frawor/fwc/parser
 register: plugin/frawor
 load: plugin/frawor
+register: plugin/frawor/signs
+load: plugin/frawor/signs
 register: plugin/frawor/decorators
 load: plugin/frawor/decorators
 register: plugin/frawor/mappings
 unloadpre: plugin/frawor/perl
 unloadpre: plugin/frawor/python
 unloadpre: plugin/frawor/ruby
+unloadpre: plugin/frawor/signs
 unloadpre: plugin/frawor/table
 unloadpre: plugin/frawor/tcl
 unloadpre: plugin/ignoredeps-feature
 unload: plugin/frawor/perl
 unload: plugin/frawor/python
 unload: plugin/frawor/ruby
+unload: plugin/frawor/signs
 unload: plugin/frawor/table
 unload: plugin/frawor/tcl
 unload: plugin/ignoredeps-feature
 register: plugin/frawor/tcl
 load: plugin/frawor/tcl
 register: plugin/frawor/table
+register: plugin/frawor/signs
+load: plugin/frawor/signs
 register: plugin/frawor/ruby
 load: plugin/frawor/ruby
 register: plugin/frawor/python

test/reload-ignoredeps.ok

 load: plugin/frawor/fwc/parser
 register: plugin/frawor
 load: plugin/frawor
+register: plugin/frawor/signs
+load: plugin/frawor/signs
 register: plugin/frawor/decorators
 load: plugin/frawor/decorators
 register: plugin/frawor/mappings
 load: plugin/frawor/fwc/parser
 register: plugin/frawor
 load: plugin/frawor
+register: plugin/frawor/signs
+load: plugin/frawor/signs
 register: plugin/frawor/decorators
 load: plugin/frawor/decorators
 register: plugin/frawor/mappings

test/reload-writefile.ok

 load: plugin/frawor/fwc/parser
 register: plugin/frawor
 load: plugin/frawor
+register: plugin/frawor/signs
+load: plugin/frawor/signs
 register: plugin/frawor/decorators
 load: plugin/frawor/decorators
 register: plugin/frawor/mappings
 load: plugin/frawor/fwc/parser
 register: plugin/frawor
 load: plugin/frawor
+register: plugin/frawor/signs
+load: plugin/frawor/signs
 register: plugin/frawor/decorators
 load: plugin/frawor/decorators
 register: plugin/frawor/mappings

test/rtp/plugin/invalid-signs.1.vim

+execute frawor#Setup('0.0', {'@/signs': '0.0'})
+call s:_f.sign.new(1, {'text': '<>'})

test/rtp/plugin/invalid-signs.10.vim

+execute frawor#Setup('0.0', {'@/signs': '0.0'})
+call s:_f.sign.new('abc', {'texthl': 0})

test/rtp/plugin/invalid-signs.11.vim

+execute frawor#Setup('0.0', {'@/signs': '0.0'})
+call s:_f.sign.new('abc', {'text': 0})

test/rtp/plugin/invalid-signs.12.vim

+execute frawor#Setup('0.0', {'@/signs': '0.0'})
+call s:_f.sign.new('abc', {'text': '<>'})
+try
+    call s:_f.sign.place(0, 0, 1)
+finally
+    call s:_f.sign.delete('abc')
+endtry

test/rtp/plugin/invalid-signs.13.vim

+execute frawor#Setup('0.0', {'@/signs': '0.0'})
+call s:_f.sign.new('abc', {'text': '<>'})
+try
+    call s:_f.sign.place('abc', 10, 1)
+finally
+    call s:_f.sign.delete('abc')
+endtry

test/rtp/plugin/invalid-signs.14.vim

+execute frawor#Setup('0.0', {'@/signs': '0.0'})
+call s:_f.sign.new('abc', {'text': '<>'})
+try
+    call s:_f.sign.place('abc', 1, -1)
+finally
+    call s:_f.sign.delete('abc')
+endtry

test/rtp/plugin/invalid-signs.15.vim

+execute frawor#Setup('0.0', {'@/signs': '0.0'})
+call s:_f.sign.new('abc', {'text': '<>'})
+try
+    call s:_f.sign.place('abc', 1, [])
+finally
+    call s:_f.sign.delete('abc')
+endtry

test/rtp/plugin/invalid-signs.16.vim

+execute frawor#Setup('0.0', {'@/signs': '0.0'})
+call s:_f.sign.new('abc', {'text': '<>'})
+try
+    call s:_f.sign.place('abc', [], 1)
+finally
+    call s:_f.sign.delete('abc')
+endtry

test/rtp/plugin/invalid-signs.17.vim

+execute frawor#Setup('0.0', {'@/signs': '0.0'})
+call s:_f.sign.new('abc', {'text': '<>'})
+try
+    call s:_f.sign.delete(0)
+finally
+    call s:_f.sign.delete('abc')
+endtry

test/rtp/plugin/invalid-signs.18.vim

+execute frawor#Setup('0.0', {'@/signs': '0.0'})
+call s:_f.sign.new('abc', {'text': '<>'})
+try
+    call s:_f.sign.delete('<>')
+finally
+    call s:_f.sign.delete('abc')
+endtry

test/rtp/plugin/invalid-signs.19.vim

+execute frawor#Setup('0.0', {'@/signs': '0.0'})
+call s:_f.sign.new('abc', {'text': '<>'})
+try
+    call s:_f.sign.delete('def')
+finally
+    call s:_f.sign.delete('abc')
+endtry

test/rtp/plugin/invalid-signs.2.vim

+execute frawor#Setup('0.0', {'@/signs': '0.0'})
+call s:_f.sign.new([], {'text': '<>'})

test/rtp/plugin/invalid-signs.3.vim

+execute frawor#Setup('0.0', {'@/signs': '0.0'})
+call s:_f.sign.new('abc', [])

test/rtp/plugin/invalid-signs.4.vim

+execute frawor#Setup('0.0', {'@/signs': '0.0'})
+call s:_f.sign.new('abc', {})

test/rtp/plugin/invalid-signs.5.vim

+execute frawor#Setup('0.0', {'@/signs': '0.0'})
+call s:_f.sign.new('abc', {'text': "\x80"})

test/rtp/plugin/invalid-signs.6.vim

+execute frawor#Setup('0.0', {'@/signs': '0.0'})
+call s:_f.sign.new('abc', {'text': '>>>'})

test/rtp/plugin/invalid-signs.7.vim

+execute frawor#Setup('0.0', {'@/signs': '0.0'})
+call s:_f.sign.new('abc', {'texthl': 'XXXUnknownHL'})

test/rtp/plugin/invalid-signs.8.vim

+execute frawor#Setup('0.0', {'@/signs': '0.0'})
+call s:_f.sign.new('abc', {'linehl': 'XXXUnknownHL'})

test/rtp/plugin/invalid-signs.9.vim

+execute frawor#Setup('0.0', {'@/signs': '0.0'})
+call s:_f.sign.new('abc', {'linehl': 0})

test/rtp/plugin/signs.vim

+execute frawor#Setup('0.0', {'@/signs': '0.0'})
+let s:sgopts1={'text': '<>'}
+let s:sgopts2={'text': '><'}
+
+let s:sign1=s:_f.sign.new(   0,   s:sgopts1)
+let s:sign2=s:_f.sign.new('test', s:sgopts2)
+
+call WriteFile('name of sign2: '.s:sign2)
+
+call WriteFile('sign1: '.string(items(s:_r.sign.getdef(s:sign1))),
+            \  'sign2: '.string(items(s:_r.sign.getdef(s:sign2))))
+
+vnew
+
+call WriteFile('buf1signs: '.string(s:_r.sign.getbuf(1)),
+            \  'buf2signs: '.string(s:_r.sign.getbuf(2)))
+
+call s:_f.sign.place(s:sign1, 0, 1)
+call s:_f.sign.place(s:sign2, 1, 1)
+
+call WriteFile('buf1signs: '.string(s:_r.sign.getbuf(1)),
+            \  'buf2signs: '.string(s:_r.sign.getbuf(2)))
+call WriteFile('exists: '.s:_r.sign.exists(s:sign1).' '.s:_r.sign.exists(s:sign2))
+
+call s:_f.sign.delete(s:sign1)
+
+call WriteFile('buf1signs: '.string(s:_r.sign.getbuf(1)),
+            \  'buf2signs: '.string(s:_r.sign.getbuf(2)))
+call WriteFile('exists: '.s:_r.sign.exists(s:sign1).' '.s:_r.sign.exists(s:sign2))
+
+call s:_f.sign.delete(s:sign2)
+
+call WriteFile('buf1signs: '.string(s:_r.sign.getbuf(1)),
+            \  'buf2signs: '.string(s:_r.sign.getbuf(2)))
+call WriteFile('exists: '.s:_r.sign.exists(s:sign1).' '.s:_r.sign.exists(s:sign2))
+
+sign define test2 text=--
+sign place  1     line=1 name=test2 buffer=1
+sign place  2     line=1 name=test2 buffer=2
+call WriteFile('buf1signs: '.string(s:_r.sign.getbuf(1)),
+            \  'buf2signs: '.string(s:_r.sign.getbuf(2)))
+
+call s:_r.sign.delete('test2')
+call WriteFile('buf1signs: '.string(s:_r.sign.getbuf(1)),
+            \  'buf2signs: '.string(s:_r.sign.getbuf(2)))
+:let &rtp.=",".escape($TESTDIR, ',\').'/rtp'
+:let g:testfile="plugin/".g:curtest.".vim"
+:source test-redir.vim
+name of sign2: test
+sign1: [['text', '<>']]
+sign2: [['text', '><']]
+buf1signs: []
+buf2signs: []
+buf1signs: [[1, 1, 'test']]
+buf2signs: [[1, 1, 'frawor0']]
+exists: 1 1
+buf1signs: [[1, 1, 'test']]
+buf2signs: []
+exists: 0 1
+buf1signs: []
+buf2signs: []
+exists: 0 0
+buf1signs: [[1, 1, 'test2']]
+buf2signs: [[2, 1, 'test2']]
+buf1signs: []
+buf2signs: []

test/template-single-redir.in.

+:let &rtp.=",".escape($TESTDIR, ',\').'/rtp'
+:let g:testfile="plugin/".g:curtest.".vim"
+:source test-redir.vim

test/test-nomessages.vim

+if !exists('g:testcmd')
+    let s:testcmd='call FraworLoad(g:testfile[:-5])'
+else
+    let s:testcmd=g:testcmd.' '.fnameescape(g:testfile)
+endif
+let s:testprefix=substitute(g:testfile,
+            \'^\Vplugin/'.escape(g:curtest,'\'), '', '')[:-5]
+if !empty(s:testprefix)
+    let s:testprefix.=': '
+endif
+let s:exception=""
+try
+    execute s:testcmd
+catch /^Frawor:/
+    let s:exception=v:exception
+    call WriteFile(s:testprefix.PurgeFrawor(v:exception))
+endtry

test/test-writemessages.vim

+redir => s:var
+messages
+redir END
+let s:messages=split(s:var, "\n")[1:]
+if !empty(s:messages) && s:messages!=#[s:exception]
+    call map(s:messages, 'PurgeFrawor(v:val)')
+    call WriteFile(['>>> '.s:testprefix.'messages']+s:messages+['<<< messages'])
+endif
+unlet s:messages s:var s:exception s:testprefix

test/unload-self.ok

 register: plugin/frawor
 load: plugin/frawor
 register: plugin/unload-self
+register: plugin/frawor/signs
+load: plugin/frawor/signs
 register: plugin/frawor/decorators
 load: plugin/frawor/decorators
 register: plugin/frawor/mappings
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.