@@ -389,7 +389,7 @@ static struct motion motion_table[] = {
389389 {'W' , next_WORD_start , EXCLUSIVE },
390390 {'e' , next_word_end , INCLUSIVE },
391391 {'E' , next_WORD_end , INCLUSIVE },
392- {'G' , down , LINEWISE }, // See motion_apply...
392+ {'G' , NULL , LINEWISE }, // See motion_apply...
393393 {'t' , till_forward_exclusive , INCLUSIVE },
394394 {'f' , till_forward_inclusive , INCLUSIVE },
395395 {'T' , till_backward_exclusive , INCLUSIVE },
@@ -431,18 +431,21 @@ struct motion *motion_get(struct editor *editor, struct tb_event *ev) {
431431}
432432
433433size_t motion_apply (struct motion * motion , struct editor * editor ) {
434- unsigned int n = editor -> count ? editor -> count : 1 ;
435-
436434 size_t cursor = window_cursor (editor -> window );
437435 struct motion_context ctx = {cursor , editor -> window , editor };
438436
439- size_t nlines = gb_nlines (editor -> window -> buffer -> text );
440- // TODO(isbadawi): This is a hack to make G work correctly.
437+ // For G, don't repeatedly apply a motion; jump directly to the target line.
441438 if (motion -> name == 'G' ) {
442- n = (editor -> count ? editor -> count : (unsigned int ) nlines ) - 1 ;
443- ctx .pos = buffer_top (ctx );
439+ struct gapbuf * gb = editor -> window -> buffer -> text ;
440+ int line = gb_nlines (gb ) - 1 ;
441+ if (editor -> count ) {
442+ line = min ((int )editor -> count - 1 , line );
443+ }
444+ editor -> count = 0 ;
445+ return gb_linecol_to_pos (gb , line , 0 );
444446 }
445447
448+ unsigned int n = editor -> count ? editor -> count : 1 ;
446449 for (unsigned int i = 0 ; i < n ; ++ i ) {
447450 ctx .pos = motion -> op (ctx );
448451 }
0 commit comments