Am 30.06.2010 11:59, schrieb Andrei Popescu:
On Mi, 30 iun 10, 11:12:03, Christian Brabandt wrote:
On Wed, June 30, 2010 10:52 am, Andrei Popescu wrote:
I'm trying to add new features to vim's handling of .po files. How could
I highlight the differences between the current msgid and the previous
one?

I don't understand your question. Can you elaborate, on what the file
looks like and where the previous message id comes from? Please show a
sample file, with which we can see your problem.

What I posted was an excerpt of a .po file. Here is a full "string" with
comments:

[blank line]
#. Type: select
#. Description
#. :sl5:
#: ../s390-dasd.templates:1002
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ other stuff, not interesting in this case
#, fuzzy
^^^^^^^^ fuzzy flag, indicates the original (usually English) msgid
          (string) has changed
#| msgid ""
#| "The following disk access storage devices (DASD) are available. Please "
#| "select each device you want to use one at a time."
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ old English msgid
msgid ""
"The following direct access storage devices (DASD) are available. Please"
"select each device you want to use one at a time."
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ new English msgid
msgstr ""
"Următoarele Dispozitive de stocare cu acces la disc (DASD) sunt disponibile."
"Vă rugăm să alegeți pe rând fiecare dispozitiv pe care doriți să-l folosiți."
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ translation
[blank line]

"strings" are always separated by (at least) one blank line and a .po
file usually contains a lot of them (hundreds or more), which is why I
won't post a complete file. A translator must not, ever, touch the
"other stuff" and the current msgid.

After editing the translation the fuzzy flag must be removed to indicate
the translation is ok (handled by po.vim) and the previous msgid becomes
useless and is removed as well (I have a patch for po.vim).

It would be of great help to the translator to have the differences
between the previous and current msgid highlighted, especially in long
strings with only small changes.

Regards,
Andrei

Attached script defines a  :DiffMsgId  command, which attempts to
overlay diff highlighting to the current section using matchadd().
E.g. it works on the following section:

#| msgid ""
#| "The following disk access storage devices (DASD) are available. Please "
#| "select each device you want to use one at a time."

msgid ""
"The following direct access storage devices (DASD) are available. Please"
"select each device you want to use one at a time."

msgstr ""
"Urmatoarele Dispozitive de stocare cu acces la disc (DASD) sunt disponibile."
"Va rugam sa alege?i pe rând fiecare dispozitiv pe care dori?i sa-l folosi?i."


Not yet tested with UTF-8

--
Andy

--
You received this message from the "vim_use" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php
" File:         diffmsgid.vim
" Created:      2010 Aug 19
" Last Change:  2010 Aug 20
" Rev Days:     1
" Author:       Andy Wokula <anw...@yahoo.de>

" :DiffMsgId
"
"   look back, find /^#| msgid/ (old English), find /^msgid ""/ (new
"   English)
"
" - get the lines
" - strip off and remember prefixes, suffixes for each line (only the column
"   offsets are interesting)
" - join the two blocks of lines each into one line
" - diff the two joined lines
" - go through the diff spec: attach diff attributes to each of the original
"   lines (may involve splitting of "a" or "c" or "d")
" - for each line, turn diff spec into highlighting

" TODO
" - check with UTF-8 !

com! -bar DiffMsgId  call s:DiffMsgId()

func! s:DiffMsgId() "{{{

    call DiffMsgIdClearMatches()

    if !executable('diff')
        echoerr 'DiffTwoLines: no diff program found'
        return
    endif

    let sav_cursor = getpos(".")

    " ---------------
    let oldmsgidlnum = search('^#| msgid ""', 'bW')
    if oldmsgidlnum == 0
        return
    endif
    let oldlines = getline(oldmsgidlnum+1, line("'}")-1)
    if empty(oldlines)
        return
    endif
    let oldleftcolumn = 1 + matchend(oldlines[0], '"')
    call map(oldlines, 'substitute(v:val, ''^#| "\|"$'', "", "g")')
    let old = s:NewBlock(oldmsgidlnum+1, oldleftcolumn, oldlines)

    let newmsgidlnum = search('^msgid ""', "W")
    if newmsgidlnum == 0
        return
    endif
    let newlines = getline(newmsgidlnum+1, line("'}")-1)
    if empty(newlines)
        return
    endif
    let newleftcolumn = 1 + matchend(newlines[0], '"')
    call map(newlines, 'substitute(v:val, ''^"\|"$'', "", "g")')
    let new = s:NewBlock(newmsgidlnum+1, newleftcolumn, newlines)

    let line1 = join(oldlines, '')
    let line2 = join(newlines, '')
    " ---------------

    let spL1 = split(line1, '\m')
    let spL2 = split(line2, '\m')

    let tmpfn1 = tempname()
    let tmpfn2 = tempname()

    call writefile(spL1, tmpfn1)
    call writefile(spL2, tmpfn2)

    sil let diff_data = system('diff '.shellescape(tmpfn1).' '. 
shellescape(tmpfn2))
    " Decho v:shell_error

    call delete(tmpfn1)
    call delete(tmpfn2)

    let diff_list = split(diff_data, "\n")

    let dcmdpat = '^[[:digit:],dca]\+$'
    call filter(diff_list, 'v:val =~ dcmdpat')

    for dcmd in diff_list
        if dcmd =~ 'd'
            let range = substitute(dcmd, 'd.*', '', '')
            call old.RangeAdd("DiffDelete", range)

        elseif dcmd =~ 'a'
            let range = substitute(dcmd, '.*a', '', '')
            call new.RangeAdd("DiffAdd", range)

        elseif dcmd =~ 'c'
            let [range1, range2] = split(dcmd, "c")
            call old.RangeAdd("DiffChange", range1)
            call new.RangeAdd("DiffChange", range2)

        endif
    endfor

    call setpos(".", sav_cursor)
endfunc "}}}

let s:block = {}

func! s:NewBlock(firstlnum, leftcolumn, lines) "{{{
    let block = copy(s:block)

    let block.firstlnum = a:firstlnum
    let block.leftcolumn = a:leftcolumn
    let block.lineidx = 0

    let pos = 0
    let offsets = [pos]
    for line in a:lines
        let pos += s:StrLen(line)
        call add(offsets, pos)
    endfor
    let block.offsets = offsets

    return block
endfunc "}}}

func! s:block.RangeAdd(hlgroup, range) "{{{
    if a:range =~ ","
        let [diffpos1, diffpos2] = split(a:range, ",")
    else
        let [diffpos1, diffpos2] = [a:range, a:range]
    endif
    let diffpos1 -= 1
    let diffpos2 -= 1
    while diffpos1 >= self.offsets[self.lineidx + 1]
        let self.lineidx += 1
    endwhile
    if diffpos2 < self.offsets[self.lineidx + 1]
        call self.AddMatch(a:hlgroup, self.lineidx,
            \ diffpos1 - self.offsets[self.lineidx],
            \ diffpos2 - self.offsets[self.lineidx])
    else
        call self.AddMatch(a:hlgroup, self.lineidx,
            \ diffpos1 - self.offsets[self.lineidx],
            \ self.offsets[self.lineidx + 1] - self.offsets[self.lineidx] - 1)
        let self.lineidx += 1
        while diffpos2 >= self.offsets[self.lineidx + 1]
            call self.AddMatch(a:hlgroup, self.lineidx,
                \ 0,
                \ self.offsets[self.lineidx + 1] - self.offsets[self.lineidx] - 
1)
            let self.lineidx += 1
        endwhile
        call self.AddMatch(a:hlgroup, self.lineidx,
            \ 0,
            \ diffpos2 - self.offsets[self.lineidx])
    endif
endfunc "}}}

func! s:block.AddMatch(hlgroup, lineidx, dcoloff1, dcoloff2) "{{{
    let lnum = self.firstlnum + a:lineidx
    let col1 = self.leftcolumn + a:dcoloff1
    if a:dcoloff1 == a:dcoloff2
        let mapat = '\%'.lnum.'l\%'.col1.'c.'
    else
        let col2 = self.leftcolumn + a:dcoloff2
        let mapat = '\%'.lnum.'l\%'.col1.'c.\{-}\%'.col2.'c.'
    endif
    call s:IdAdd(matchadd(a:hlgroup, mapat))
endfunc "}}}

func! s:IdAdd(id) "{{{
    if !exists("w:match_ids")
        let w:match_ids = []
    endif
    call add(w:match_ids, a:id)
endfunc "}}}

func! DiffMsgIdClearMatches() "{{{
    if !exists("w:match_ids")
        return
    endif
    for id in w:match_ids
        sil! call matchdelete(id)
        " sil! might be necessary after clearmatches()
    endfor
    let w:match_ids = []
endfunc "}}}

func! s:StrLen(str) "{{{
    return strlen(substitute(a:str, '.', 'x', 'g'))
endfunc "}}}

finish

#| msgid ""
#| "The following disk access storage devices (DASD) are available. Please "
#| "select each device you want to use one at a time."
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ old English msgid
msgid ""
"The following direct access storage devices (DASD) are available. Please "
"select each device you want to use one at a time."
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ new English msgid
msgstr ""
"Urmatoarele Dispozitive de stocare cu acces la disc (DASD) sunt disponibile. "
"Va rugam sa alege?i pe rând fiecare dispozitiv pe care dori?i sa-l folosi?i."
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ translation

#| msgid ""
#| "The following disk access storage devices (DASD) are available. Please "
#| "bla"
#| "select each device you to use one at a time."

msgid ""
"The following disk access storage devices (DASD) are available. Please"
" each device you want to use one at a time."

msgstr ""
"Urmatoarele Dispozitive de stocare cu acces la disc (DASD) sunt disponibile. "
"Va rugam sa alege?i pe rând fiecare dispozitiv pe care dori?i sa-l folosi?i."
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ translation

Reply via email to