@@ -9,6 +9,8 @@ const cacheKey = "denops_std/buffer/decoration/vimDecorate/rs@1";
99
1010const PREFIX = "denops_std:buffer:decoration:decorate" ;
1111
12+ const DEFAULT_DECORATION_PRIORITY = 0 ;
13+
1214export type DecorateOptions = {
1315 /**
1416 * Decoration namespace
@@ -33,6 +35,11 @@ export interface Decoration {
3335 * Highlight name
3436 */
3537 highlight : string ;
38+ /**
39+ * Priority for the decoration (higher numbers are displayed on top)
40+ * Defaults to 0 if not specified
41+ */
42+ priority ?: number ;
3643}
3744
3845/**
@@ -53,6 +60,7 @@ export interface Decoration {
5360 * column: 1,
5461 * length: 10,
5562 * highlight: "Special",
63+ * priority: 10,
5664 * },
5765 * {
5866 * line: 2,
@@ -157,41 +165,50 @@ export function listDecorations(
157165 }
158166}
159167
160- function uniq < T > ( array : readonly T [ ] ) : T [ ] {
161- return [ ...new Set ( array ) ] ;
162- }
163-
164168async function vimDecorate (
165169 denops : Denops ,
166170 bufnr : number ,
167171 decorations : readonly Decoration [ ] ,
168172 options : Readonly < DecorateOptions > = { } ,
169173) : Promise < void > {
170174 const prefix = options . namespace ?? `${ PREFIX } :${ denops . name } ` ;
171- const toPropType = ( n : string ) => `${ prefix } :${ n } ` ;
175+ const toPropTypeName = ( n : string , p : number | undefined ) =>
176+ `${ prefix } :${ p ?? DEFAULT_DECORATION_PRIORITY } :${ n } ` ;
172177 const rs = ( denops . context [ cacheKey ] ?? new Set ( ) ) as Set < string > ;
173178 denops . context [ cacheKey ] = rs ;
174- const hs = uniq ( decorations . map ( ( v ) => v . highlight ) ) . filter ( ( v ) =>
175- ! rs . has ( v )
176- ) ;
177- const decoMap = new Map < string , Set < [ number , number , number , number ] > > ( ) ;
179+ const decosToUpdate = Array . from (
180+ new Map (
181+ decorations
182+ . map ( ( { highlight, priority } ) => ( { highlight, priority } ) )
183+ . map ( ( p ) => [ toPropTypeName ( p . highlight , p . priority ) , p ] as const ) ,
184+ ) . values ( ) ,
185+ ) . filter ( ( p ) => ! rs . has ( toPropTypeName ( p . highlight , p . priority ) ) ) ;
186+
187+ const propsByType = new Map < string , Set < [ number , number , number , number ] > > ( ) ;
178188 for ( const deco of decorations ) {
179- const propType = toPropType ( deco . highlight ) ;
180- const props = decoMap . get ( propType ) ?? new Set ( ) ;
189+ const propTypeName = toPropTypeName ( deco . highlight , deco . priority ) ;
190+ const props = propsByType . get ( propTypeName ) ?? new Set ( ) ;
181191 props . add ( [ deco . line , deco . column , deco . line , deco . column + deco . length ] ) ;
182- decoMap . set ( propType , props ) ;
192+ propsByType . set ( propTypeName , props ) ;
183193 }
194+
184195 await batch ( denops , async ( denops ) => {
185- for ( const highlight of hs ) {
186- const propType = toPropType ( highlight ) ;
187- await vimFn . prop_type_add ( denops , propType , {
196+ for ( const { highlight, priority } of decosToUpdate ) {
197+ const propTypeName = toPropTypeName ( highlight , priority ) ;
198+ const propOptions : Record < string , unknown > = {
188199 highlight,
189200 combine : false ,
190- } ) ;
191- rs . add ( highlight ) ;
201+ priority : priority ?? DEFAULT_DECORATION_PRIORITY ,
202+ } ;
203+
204+ if ( ! rs . has ( propTypeName ) ) {
205+ await vimFn . prop_type_add ( denops , propTypeName , propOptions ) ;
206+ }
207+ rs . add ( propTypeName ) ;
192208 }
209+
193210 let id = 1 ;
194- for ( const [ type , props ] of decoMap . entries ( ) ) {
211+ for ( const [ type , props ] of propsByType . entries ( ) ) {
195212 await vimFn . prop_add_list ( denops , { bufnr, type, id : id ++ } , [ ...props ] ) ;
196213 }
197214 } ) ;
@@ -240,14 +257,22 @@ async function vimListDecorations(
240257 type : string ;
241258 type_bufnr : number ;
242259 } [ ] ;
243- return props
244- . filter ( ( prop ) => prop . type . startsWith ( `${ prefix } :` ) )
245- . map ( ( prop ) => ( {
246- line : prop . lnum ,
247- column : prop . col ,
248- length : prop . length ,
249- highlight : prop . type . split ( ":" ) . pop ( ) as string ,
250- } ) ) ;
260+ return Promise . all (
261+ props
262+ . filter ( ( prop ) => prop . type . startsWith ( `${ prefix } :` ) )
263+ . map ( async ( prop ) => {
264+ const propType = await vimFn . prop_type_get ( denops , prop . type ) as {
265+ priority : number ;
266+ } ;
267+ return ( {
268+ line : prop . lnum ,
269+ column : prop . col ,
270+ length : prop . length ,
271+ highlight : prop . type . split ( ":" ) . pop ( ) as string ,
272+ priority : propType . priority ,
273+ } ) ;
274+ } ) ,
275+ ) ;
251276}
252277
253278async function nvimDecorate (
@@ -270,6 +295,7 @@ async function nvimDecorate(
270295 {
271296 end_col : deco . column - 1 + deco . length ,
272297 hl_group : deco . highlight ,
298+ priority : deco . priority ?? DEFAULT_DECORATION_PRIORITY ,
273299 } ,
274300 ) ;
275301 }
@@ -323,5 +349,6 @@ async function nvimListDecorations(
323349 column : extmark [ 2 ] + 1 ,
324350 length : extmark [ 3 ] . end_col - extmark [ 2 ] ,
325351 highlight : extmark [ 3 ] . hl_group ,
352+ priority : extmark [ 3 ] . priority ?? DEFAULT_DECORATION_PRIORITY ,
326353 } ) ) ;
327354}
0 commit comments