@@ -5,9 +5,10 @@ local str = require('render-markdown.core.str')
5
5
6
6
--- @class render.md.table.Column
7
7
--- @field row integer
8
- --- @field col integer
8
+ --- @field start_col integer
9
+ --- @field end_col integer
9
10
--- @field width integer
10
- --- @field free integer
11
+ --- @field space { left : integer , right : integer }
11
12
12
13
--- @class render.md.table.Row
13
14
--- @field info render.md.NodeInfo
@@ -80,9 +81,13 @@ function Render:setup()
80
81
end
81
82
-- Store the max width information in the delimiter
82
83
for _ , row in ipairs (rows ) do
83
- for i , r_column in ipairs (row .columns ) do
84
- local d_column = delim .columns [i ]
85
- d_column .width = math.max (d_column .width , r_column .width )
84
+ for i , column in ipairs (row .columns ) do
85
+ local delim_column , width = delim .columns [i ], column .width
86
+ if self .table .cell == ' trimmed' then
87
+ local space_available = column .space .left + column .space .right - (2 * self .table .padding )
88
+ width = width - math.max (space_available , 0 )
89
+ end
90
+ delim_column .width = math.max (delim_column .width , width )
86
91
end
87
92
end
88
93
@@ -143,19 +148,26 @@ function Render:parse_row(row, num_columns)
143
148
end
144
149
local columns = {}
145
150
for i , cell in ipairs (cells ) do
146
- local width = pipes [i + 1 ].start_col - pipes [i ].end_col
147
- -- Account for double width glyphs by replacing cell spacing with width
151
+ local start_col , end_col = pipes [i ].end_col , pipes [i + 1 ].start_col
152
+ -- Account for double width glyphs by replacing cell range with width
153
+ local width = end_col - start_col
148
154
width = width - (cell .end_col - cell .start_col ) + self .context :width (cell )
149
- local free = 0
150
- if self . table . cell == ' trimmed ' then
151
- -- Remove trailing spaces from width calculation except for 1
152
- free = math.max ( str . spaces ( ' end ' , cell . text ) - 1 , 0 )
153
- width = width - free
154
- end
155
+ local space = {
156
+ -- Left space comes from the gap between the node start and the pipe start
157
+ left = math.max ( cell . start_col - start_col , 0 ),
158
+ -- Right space is attached to the node itself
159
+ right = math.max ( str . spaces ( ' end ' , cell . text ), 0 ),
160
+ }
155
161
if width < 0 then
156
162
return nil
157
163
end
158
- table.insert (columns , { row = cell .start_row , col = cell .end_col , width = width , free = free })
164
+ table.insert (columns , {
165
+ row = cell .start_row ,
166
+ start_col = cell .start_col ,
167
+ end_col = cell .end_col ,
168
+ width = width ,
169
+ space = space ,
170
+ })
159
171
end
160
172
return { info = row , pipes = pipes , columns = columns }
161
173
end
@@ -198,22 +210,19 @@ function Render:delimiter()
198
210
local delim , border = self .data .delim , self .table .border
199
211
200
212
local sections = Iter .list .map (delim .columns , function (column )
201
- local indicator = self .table .alignment_indicator
213
+ local indicator , box = self .table .alignment_indicator , border [ 11 ]
202
214
-- If column is small there's no good place to put the alignment indicator
203
215
-- Alignment indicator must be exactly one character wide
204
216
-- Do not put an indicator for default alignment
205
- if column .width < 4 or str .width (indicator ) ~= 1 or column .alignment == ' default' then
206
- return border [ 11 ] :rep (column .width )
217
+ if column .width < 3 or str .width (indicator ) ~= 1 or column .alignment == ' default' then
218
+ return box :rep (column .width )
207
219
end
208
- -- Handle the various alignmnet possibilities
209
- local left = border [11 ]:rep (math.floor (column .width / 2 ))
210
- local right = border [11 ]:rep (math.ceil (column .width / 2 ) - 1 )
211
220
if column .alignment == ' left' then
212
- return indicator .. left .. right
221
+ return indicator .. box : rep ( column . width - 1 )
213
222
elseif column .alignment == ' right' then
214
- return left .. right .. indicator
223
+ return box : rep ( column . width - 1 ) .. indicator
215
224
else
216
- return left .. indicator .. right
225
+ return indicator .. box : rep ( column . width - 2 ) .. indicator
217
226
end
218
227
end )
219
228
@@ -246,22 +255,22 @@ function Render:row(row)
246
255
end
247
256
end
248
257
249
- -- Use low priority to include pipe marks
250
258
if vim .tbl_contains ({ ' trimmed' , ' padded' }, self .table .cell ) then
251
259
for i , column in ipairs (row .columns ) do
252
- local offset = delim .columns [i ].width - column .width - column .free
253
- if offset > 0 then
254
- self .marks :add (true , column .row , column .col , {
255
- priority = 0 ,
256
- virt_text = { { str .pad (offset ), self .table .filler } },
257
- virt_text_pos = ' inline' ,
258
- })
259
- elseif offset < 0 then
260
- self .marks :add (true , column .row , column .col + offset , {
261
- priority = 0 ,
262
- end_col = column .col ,
263
- conceal = ' ' ,
264
- })
260
+ local delim_column = delim .columns [i ]
261
+ local filler = delim_column .width - column .width
262
+ if delim_column .alignment == ' center' then
263
+ local shift = math.floor ((filler + column .space .right - column .space .left ) / 2 )
264
+ self :shift (column , ' left' , shift )
265
+ self :shift (column , ' right' , filler - shift )
266
+ elseif delim_column .alignment == ' right' then
267
+ local shift = column .space .right - self .table .padding
268
+ self :shift (column , ' left' , filler + shift )
269
+ self :shift (column , ' right' , - shift )
270
+ else
271
+ local shift = column .space .left - self .table .padding
272
+ self :shift (column , ' left' , - shift )
273
+ self :shift (column , ' right' , filler + shift )
265
274
end
266
275
end
267
276
end
@@ -276,6 +285,28 @@ function Render:row(row)
276
285
end
277
286
end
278
287
288
+ --- Use low priority to include pipe marks
289
+ --- @private
290
+ --- @param column render.md.table.Column
291
+ --- @param side ' left' | ' right'
292
+ --- @param amount integer
293
+ function Render :shift (column , side , amount )
294
+ local col = side == ' left' and column .start_col or column .end_col
295
+ if amount > 0 then
296
+ self .marks :add (true , column .row , col , {
297
+ priority = 0 ,
298
+ virt_text = { { str .pad (amount ), self .table .filler } },
299
+ virt_text_pos = ' inline' ,
300
+ })
301
+ elseif amount < 0 then
302
+ self .marks :add (true , column .row , col + amount , {
303
+ priority = 0 ,
304
+ end_col = col ,
305
+ conceal = ' ' ,
306
+ })
307
+ end
308
+ end
309
+
279
310
--- @private
280
311
function Render :full ()
281
312
local delim , rows , border = self .data .delim , self .data .rows , self .table .border
0 commit comments