Add the synconcealed() function and use it for :TOhtml. (Benjamin Fritz)

This commit is contained in:
Bram Moolenaar
2010-07-25 12:46:44 +02:00
parent e6dc573b6e
commit 7510fe7433
8 changed files with 190 additions and 49 deletions

View File

@ -1,6 +1,6 @@
" Vim autoload file for the tohtml plugin.
" Maintainer: Ben Fritz <fritzophrenic@gmail.com>
" Last Change: 2010 July 16
" Last Change: 2010 July 24
"
" Additional contributors:
"
@ -64,6 +64,7 @@ func! tohtml#Diff2HTML(win_list, buf_list)
call add(html, '<head>')
call add(html, '<title>diff</title>')
call add(html, '<meta name="Generator" content="Vim/'.v:version/100.'.'.v:version%100.'">')
call add(html, '<meta name="plugin-version" content="'.g:loaded_2html_plugin.'">')
" TODO: copy or move encoding logic from 2html.vim so generated markup can
" validate without warnings about encoding

View File

@ -1,4 +1,4 @@
*eval.txt* For Vim version 7.3b. Last change: 2010 May 14
*eval.txt* For Vim version 7.3b. Last change: 2010 Jul 25
VIM REFERENCE MANUAL by Bram Moolenaar
@ -5550,6 +5550,21 @@ synID({lnum}, {col}, {trans}) *synID()*
Example (echoes the name of the syntax item under the cursor): >
:echo synIDattr(synID(line("."), col("."), 1), "name")
<
synconcealed({lnum}, {col}) *synconcealed()*
The result is a List. The first item in the list is 0 if the
character at the position {lnum} and {col} is not part of a
concealable region, 1 if it is. The second item in the list is
a string. If the first item is 1, the second item contains the
text which will be displayed in place of the concealed text,
depending on the current setting of 'conceallevel'. The third
and final item in the list is a unique number representing the
specific syntax region matched. This allows detection of the
beginning of a new concealable region if there are two
consecutive regions with the same replacement character.
For an example use see $VIMRUNTIME/syntax/2html.vim .
synIDattr({synID}, {what} [, {mode}]) *synIDattr()*
The result is a String, which is the {what} attribute of
syntax ID {synID}. This can be used to obtain information

View File

@ -428,8 +428,14 @@ cascading style sheets (CSS1) for the attributes (resulting in considerably
shorter and valid HTML 4 file), use: >
:let g:html_use_css = 1
Closed folds are put in the HTML as they are displayed. If you don't want
this, use the |zR| command before invoking 2html, or use: >
Concealed text is removed from the HTML and replaced with the appropriate
character from |syn-cchar| or 'listchars' depending on the current value of
'conceallevel'. If you always want to display all text in your document,
either set 'conceallevel' to before invoking 2html, or use: >
:let g:html_ignore_conceal = 1
Similarly, closed folds are put in the HTML as they are displayed. If you
don't want this, use the |zR| command before invoking 2html, or use: >
:let g:html_ignore_folding = 1
You may want to generate HTML that includes all the data within the folds, and

View File

@ -1,4 +1,4 @@
*todo.txt* For Vim version 7.3b. Last change: 2010 Jul 24
*todo.txt* For Vim version 7.3b. Last change: 2010 Jul 25
VIM REFERENCE MANUAL by Bram Moolenaar
@ -30,6 +30,8 @@ be worked on, but only if you sponsor Vim development. See |sponsor|.
*known-bugs*
-------------------- Known bugs and current work -----------------------
concealends does not appear to work.
if_python3.c is missing some changes that were applied to if_python.c.
Find the old version of if_python.c from when the copy was made.

View File

@ -1,10 +1,15 @@
" Vim plugin for converting a syntax highlighted file to HTML.
" Maintainer: Ben Fritz <fritzophrenic@gmail.com>
" Last Change: 2010 Jul 16
" Last Change: 2010 July 24
"
" The core of the code is in $VIMRUNTIME/autoload/tohtml.vim and
" $VIMRUNTIME/syntax/2html.vim
if exists('g:loaded_2html_plugin')
finish
endif
let g:loaded_2html_plugin = 'vim7.3_v1'
" Define the :TOhtml command when:
" - 'compatible' is not set
" - this plugin was not already loaded

View File

@ -1,19 +1,19 @@
" Vim syntax support file
" Maintainer: Ben Fritz <fritzophrenic@gmail.com>
" Last Change: 2010 July 16
" Last Change: 2010 July 24
"
" Additional contributors:
"
" Original by Bram Moolenaar <Bram@vim.org>
" Modified by David Ne\v{c}as (Yeti) <yeti@physics.muni.cz>
" XHTML support by Panagiotis Issaris <takis@lumumba.luc.ac.be>
" Made w3 compliant by Edd Barrett <vext01@gmail.com>
" Added html_font. Edd Barrett <vext01@gmail.com>
" Progress bar based off code from "progressbar widget" plugin by
" Andreas Politz, heavily modified:
" http://www.vim.org/scripts/script.php?script_id=2006
" Original by Bram Moolenaar <Bram@vim.org>
" Modified by David Ne\v{c}as (Yeti) <yeti@physics.muni.cz>
" XHTML support by Panagiotis Issaris <takis@lumumba.luc.ac.be>
" Made w3 compliant by Edd Barrett <vext01@gmail.com>
" Added html_font. Edd Barrett <vext01@gmail.com>
" Progress bar based off code from "progressbar widget" plugin by
" Andreas Politz, heavily modified:
" http://www.vim.org/scripts/script.php?script_id=2006
"
" See Mercurial change logs for more!
" See Mercurial change logs for more!
" Transform a file into HTML, using the current syntax highlighting.
@ -241,6 +241,18 @@ setlocal et
set nomore
set report=1000000
if exists(':ownsyntax') && exists('w:current_syntax')
let s:current_syntax = w:current_syntax
elseif exists('b:current_syntax')
let s:current_syntax = b:current_syntax
else
let s:current_syntax = 'none'
endif
if s:current_syntax == ''
let s:current_syntax = 'none'
endif
" Split window to create a buffer with the HTML file.
let s:orgbufnr = winbufnr(0)
let s:origwin_stl = &l:stl
@ -315,10 +327,12 @@ call extend(s:lines, [
\"<head>",
\("<title>".expand("%:p:~")."</title>"),
\("<meta name=\"Generator\" content=\"Vim/".v:version/100.".".v:version%100.'"'.s:tag_close),
\("<meta name=\"plugin-version\" content=\"".g:loaded_2html_plugin.'"'.s:tag_close),
\])
if s:html_encoding != ""
call add(s:lines, "<meta http-equiv=\"content-type\" content=\"text/html; charset=" . s:html_encoding . '"' . s:tag_close)
endif
call add(s:lines, '<meta name="syntax" content="'.s:current_syntax.'"'.s:tag_close)
if exists("g:html_use_css")
if exists("g:html_dynamic_folds")
@ -810,8 +824,11 @@ while s:lnum <= s:end
" html_no_pre to make it easier
if !exists("g:html_no_foldcolumn")
if empty(s:foldstack)
" add the empty foldcolumn for unfolded lines
let s:new = s:new . s:HtmlFormat(repeat(' ', s:foldcolumn), "FoldColumn")
" add the empty foldcolumn for unfolded lines if there is a fold
" column at all
if s:foldcolumn > 0
let s:new = s:new . s:HtmlFormat(repeat(' ', s:foldcolumn), "FoldColumn")
endif
else
" add the fold column for folds not on the opening line
if get(s:foldstack, 0).firstline < s:lnum
@ -831,11 +848,24 @@ while s:lnum <= s:end
" Get the diff attribute, if any.
let s:diffattr = diff_hlID(s:lnum, 1)
" initialize conceal info to act like not concealed, just in case
let s:concealinfo = [0, '']
" Loop over each character in the line
let s:col = 1
while s:col <= s:len || (s:col == 1 && s:diffattr)
let s:startcol = s:col " The start column for processing text
if s:diffattr
if !exists('g:html_ignore_conceal') && has('conceal')
let s:concealinfo = synconcealed(s:lnum, s:col)
endif
if !exists('g:html_ignore_conceal') && s:concealinfo[0]
let s:col = s:col + 1
" Speed loop (it's small - that's the trick)
" Go along till we find a change in the match sequence number (ending
" the specific concealed region) or until there are no more concealed
" characters.
while s:col <= s:len && s:concealinfo == synconcealed(s:lnum, s:col) | let s:col = s:col + 1 | endwhile
elseif s:diffattr
let s:id = diff_hlID(s:lnum, s:col)
let s:col = s:col + 1
" Speed loop (it's small - that's the trick)
@ -854,39 +884,50 @@ while s:lnum <= s:end
while s:col <= s:len && s:id == synID(s:lnum, s:col, 1) | let s:col = s:col + 1 | endwhile
endif
" Expand tabs
let s:expandedtab = strpart(s:line, s:startcol - 1, s:col - s:startcol)
let s:offset = 0
let s:idx = stridx(s:expandedtab, "\t")
while s:idx >= 0
if has("multi_byte_encoding")
if s:startcol + s:idx == 1
let s:i = &ts
else
if s:idx == 0
let s:prevc = matchstr(s:line, '.\%' . (s:startcol + s:idx + s:offset) . 'c')
else
let s:prevc = matchstr(s:expandedtab, '.\%' . (s:idx + 1) . 'c')
endif
let s:vcol = virtcol([s:lnum, s:startcol + s:idx + s:offset - len(s:prevc)])
let s:i = &ts - (s:vcol % &ts)
endif
let s:offset -= s:i - 1
else
let s:i = &ts - ((s:idx + s:startcol - 1) % &ts)
endif
let s:expandedtab = substitute(s:expandedtab, '\t', repeat(' ', s:i), '')
if exists('g:html_ignore_conceal') || !s:concealinfo[0]
" Expand tabs
let s:expandedtab = strpart(s:line, s:startcol - 1, s:col - s:startcol)
let s:offset = 0
let s:idx = stridx(s:expandedtab, "\t")
endwhile
while s:idx >= 0
if has("multi_byte_encoding")
if s:startcol + s:idx == 1
let s:i = &ts
else
if s:idx == 0
let s:prevc = matchstr(s:line, '.\%' . (s:startcol + s:idx + s:offset) . 'c')
else
let s:prevc = matchstr(s:expandedtab, '.\%' . (s:idx + 1) . 'c')
endif
let s:vcol = virtcol([s:lnum, s:startcol + s:idx + s:offset - len(s:prevc)])
let s:i = &ts - (s:vcol % &ts)
endif
let s:offset -= s:i - 1
else
let s:i = &ts - ((s:idx + s:startcol - 1) % &ts)
endif
let s:expandedtab = substitute(s:expandedtab, '\t', repeat(' ', s:i), '')
let s:idx = stridx(s:expandedtab, "\t")
endwhile
" Output the text with the same synID, with class set to {s:id_name}
let s:id = synIDtrans(s:id)
let s:id_name = synIDattr(s:id, "name", s:whatterm)
let s:new = s:new . s:HtmlFormat(s:expandedtab, s:id_name)
" get the highlight group name to use
let s:id = synIDtrans(s:id)
let s:id_name = synIDattr(s:id, "name", s:whatterm)
else
" use Conceal highlighting for concealed text
let s:id_name = 'Conceal'
let s:expandedtab = s:concealinfo[1]
endif
" Output the text with the same synID, with class set to {s:id_name},
" unless it has been concealed completely. Always output empty lines.
if strlen(s:expandedtab) > 0
let s:new = s:new . s:HtmlFormat(s:expandedtab, s:id_name)
endif
endwhile
endif
call extend(s:lines, split(s:new.s:HtmlEndline, '\n'))
call extend(s:lines, split(s:new.s:HtmlEndline, '\n', 1))
if !s:html_no_progress && s:pgb.needs_redraw
redrawstatus
let s:pgb.needs_redraw = 0
@ -1054,8 +1095,8 @@ let &ls=s:ls
unlet s:htmlfont
unlet s:old_et s:old_paste s:old_icon s:old_report s:old_title s:old_search s:old_magic s:old_more s:old_fdm s:old_winheight s:old_winfixheight
unlet s:whatterm s:idlist s:lnum s:end s:margin s:fgc s:bgc
unlet! s:col s:id s:attr s:len s:line s:new s:expandedtab s:numblines
unlet! s:orgwin s:newwin s:orgbufnr s:idx s:i s:offset s:ls s:origwin_stl s:newwin_stl
unlet! s:col s:id s:attr s:len s:line s:new s:expandedtab s:numblines s:concealinfo
unlet! s:orgwin s:newwin s:orgbufnr s:idx s:i s:offset s:ls s:origwin_stl s:newwin_stl s:current_syntax
if !v:profiling
delfunc s:HtmlColor
delfunc s:HtmlFormat

View File

@ -718,6 +718,7 @@ static void f_synID __ARGS((typval_T *argvars, typval_T *rettv));
static void f_synIDattr __ARGS((typval_T *argvars, typval_T *rettv));
static void f_synIDtrans __ARGS((typval_T *argvars, typval_T *rettv));
static void f_synstack __ARGS((typval_T *argvars, typval_T *rettv));
static void f_synconcealed __ARGS((typval_T *argvars, typval_T *rettv));
static void f_system __ARGS((typval_T *argvars, typval_T *rettv));
static void f_tabpagebuflist __ARGS((typval_T *argvars, typval_T *rettv));
static void f_tabpagenr __ARGS((typval_T *argvars, typval_T *rettv));
@ -7876,6 +7877,7 @@ static struct fst
{"synID", 3, 3, f_synID},
{"synIDattr", 2, 3, f_synIDattr},
{"synIDtrans", 1, 1, f_synIDtrans},
{"synconcealed", 2, 2, f_synconcealed},
{"synstack", 2, 2, f_synstack},
{"system", 1, 2, f_system},
{"tabpagebuflist", 0, 1, f_tabpagebuflist},
@ -17131,6 +17133,68 @@ f_synIDtrans(argvars, rettv)
rettv->vval.v_number = id;
}
/*
* "synconcealed(lnum, col)" function
*/
static void
f_synconcealed(argvars, rettv)
typval_T *argvars UNUSED;
typval_T *rettv;
{
#if defined(FEAT_SYN_HL) && defined(FEAT_CONCEAL)
long lnum;
long col;
int syntax_flags = 0;
int cchar;
int matchid = 0;
char_u str[NUMBUFLEN];
#endif
rettv->v_type = VAR_LIST;
rettv->vval.v_list = NULL;
#if defined(FEAT_SYN_HL) && defined(FEAT_CONCEAL)
lnum = get_tv_lnum(argvars); /* -1 on type error */
col = get_tv_number(&argvars[1]) - 1; /* -1 on type error */
vim_memset(str, NUL, sizeof(str));
if (rettv_list_alloc(rettv) != FAIL)
{
if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count
&& col >= 0 && col <= (long)STRLEN(ml_get(lnum))
&& curwin->w_p_cole > 0)
{
(void)syn_get_id(curwin, lnum, col, FALSE, NULL, FALSE);
syntax_flags = get_syntax_info(&matchid);
/* get the conceal character */
if ((syntax_flags & HL_CONCEAL) && curwin->w_p_cole < 3)
{
cchar = syn_get_sub_char();
if (cchar == NUL && curwin->w_p_cole == 1 && lcs_conceal != NUL)
cchar = lcs_conceal;
if (cchar != NUL)
{
# ifdef FEAT_MBYTE
if (has_mbyte)
(*mb_char2bytes)(cchar, str);
else
# endif
str[0] = cchar;
}
}
}
list_append_number(rettv->vval.v_list,
(syntax_flags & HL_CONCEAL) != 0);
/* -1 to auto-determine strlen */
list_append_string(rettv->vval.v_list, str, -1);
list_append_number(rettv->vval.v_list, matchid);
}
#endif
}
/*
* "synstack(lnum, col)" function
*/

View File

@ -474,6 +474,10 @@ syntax_start(wp, lnum)
int dist;
static int changedtick = 0; /* remember the last change ID */
#ifdef FEAT_CONCEAL
current_sub_char = NUL;
#endif
/*
* After switching buffers, invalidate current_state.
* Also do this when a change was made, the current state may be invalid
@ -1786,6 +1790,9 @@ get_syntax_attr(col, can_spell, keep_state)
#ifdef FEAT_EVAL
current_id = 0;
current_trans_id = 0;
#endif
#ifdef FEAT_CONCEAL
current_flags = 0;
#endif
return 0;
}