@@ -234,12 +234,12 @@ void goto_commands(Context& context, NormalParams params)
234234 else
235235 {
236236 on_next_key_with_autoinfo (context, " goto" , KeymapMode::Goto,
237- [ ](Key key, Context& context) {
237+ [params ](Key key, Context& context) {
238238 auto cp = key.codepoint ();
239239 if (not cp or key == Key::Escape)
240240 return ;
241241 auto & buffer = context.buffer ();
242- switch (to_lower (*cp))
242+ switch (auto lower_cp = to_lower (*cp); lower_cp )
243243 {
244244 case ' g' :
245245 case ' k' :
@@ -297,6 +297,30 @@ void goto_commands(Context& context, NormalParams params)
297297 context.change_buffer (*target);
298298 break ;
299299 }
300+ case ' d' :
301+ case ' u' :
302+ {
303+ auto offset = (lower_cp == ' d' ? 1_line : -1_line) * std::max (params.count , 1 );
304+ select (context, mode, [&](Context& context, Selection& sel) -> Optional<Selection> {
305+ if (context.has_window ())
306+ {
307+ auto & cursor = sel.cursor ();
308+ auto & window = context.window ();
309+ if (auto display_coord = window.display_coord (cursor))
310+ {
311+ if (cursor.display_target == -1 )
312+ cursor.display_target = display_coord->column ;
313+ display_coord->column = cursor.display_target ;
314+ if (auto buffer_coord = window.buffer_coord (*display_coord + offset))
315+ return Selection{BufferCoordAndTarget{*buffer_coord, -1 , cursor.display_target }};
316+ }
317+ }
318+ const ColumnCount tabstop = context.options ()[" tabstop" ].get <int >();
319+ return Selection{context.buffer ().offset_coord (sel.cursor (), offset, tabstop)};
320+ });
321+ break ;
322+ }
323+
300324 case ' f' :
301325 {
302326 static constexpr char forbidden[] = { ' \' ' , ' \\ ' , ' \0 ' };
0 commit comments