diff --git a/commands.c b/commands.c
index a46a774..6d9ff38 100644
--- a/commands.c
+++ b/commands.c
@@ -46,6 +46,8 @@ extern win_t win;
 extern fileinfo_t *files;
 extern int filecnt, fileidx;
 
+extern int prefix;
+
 bool it_quit(arg_t a) {
 	cleanup();
 	exit(EXIT_SUCCESS);
@@ -143,12 +145,14 @@ bool it_first(arg_t a) {
 	}
 }
 
-bool it_last(arg_t a) {
-	if (mode == MODE_IMAGE && fileidx != filecnt - 1) {
-		load_image(filecnt - 1);
+bool it_n_or_last(arg_t a) {
+	int n = prefix != 0 && prefix - 1 < filecnt ? prefix - 1 : filecnt - 1;
+
+	if (mode == MODE_IMAGE && fileidx != n) {
+		load_image(n);
 		return true;
-	} else if (mode == MODE_THUMB && tns.sel != tns.cnt - 1) {
-		tns.sel = tns.cnt - 1;
+	} else if (mode == MODE_THUMB && tns.sel != n) {
+		tns.sel = n;
 		tns.dirty = true;
 		return true;
 	} else {
diff --git a/commands.h b/commands.h
index 94a08fd..8785822 100644
--- a/commands.h
+++ b/commands.h
@@ -48,7 +48,7 @@ bool it_reload_image(arg_t);
 bool it_remove_image(arg_t);
 bool i_navigate(arg_t);
 bool it_first(arg_t);
-bool it_last(arg_t);
+bool it_n_or_last(arg_t);
 bool i_navigate_frame(arg_t);
 bool i_toggle_animation(arg_t);
 bool it_move(arg_t);
diff --git a/config.def.h b/config.def.h
index 6041e61..8454a82 100644
--- a/config.def.h
+++ b/config.def.h
@@ -79,7 +79,7 @@ static const keymap_t keys[] = {
 	{ false,  XK_bracketright,  i_navigate,           (arg_t) +10 },
 	{ false,  XK_bracketleft,   i_navigate,           (arg_t) -10 },
 	{ false,  XK_g,             it_first,             (arg_t) None },
-	{ false,  XK_G,             it_last,              (arg_t) None },
+	{ false,  XK_G,             it_n_or_last,         (arg_t) None },
 
 	{ true,   XK_n,             i_navigate_frame,     (arg_t) +1 },
 	{ true,   XK_p,             i_navigate_frame,     (arg_t) -1 },
@@ -109,12 +109,10 @@ static const keymap_t keys[] = {
 	{ false,  XK_L,             i_pan_edge,           (arg_t) DIR_RIGHT },
 
 	{ false,  XK_plus,          i_zoom,               (arg_t) +1 },
-	{ false,  XK_equal,         i_zoom,               (arg_t) +1 },
 	{ false,  XK_KP_Add,        i_zoom,               (arg_t) +1 },
 	{ false,  XK_minus,         i_zoom,               (arg_t) -1 },
 	{ false,  XK_KP_Subtract,   i_zoom,               (arg_t) -1 },
-	{ false,  XK_0,             i_zoom,               (arg_t) None },
-	{ false,  XK_KP_0,          i_zoom,               (arg_t) None },
+	{ false,  XK_equal,         i_zoom,               (arg_t) None },
 	{ false,  XK_w,             i_fit_to_win,         (arg_t) None },
 	{ false,  XK_W,             i_fit_to_img,         (arg_t) None },
 
diff --git a/main.c b/main.c
index 719a61c..1d73283 100644
--- a/main.c
+++ b/main.c
@@ -63,6 +63,8 @@ fileinfo_t *files;
 int filecnt, fileidx;
 size_t filesize;
 
+int prefix;
+
 char win_title[TITLE_LEN];
 
 timeout_t timeouts[] = {
@@ -335,10 +337,17 @@ void on_keypress(XKeyEvent *kev) {
 
 	XLookupString(kev, &key, 1, &ksym, NULL);
 
+	if (key >= '0' && key <= '9' && (kev->state & ControlMask) == 0) {
+		/* number prefix for commands */
+		prefix = prefix * 10 + (int) (key - '0');
+		return;
+	}
+
 	for (i = 0; i < ARRLEN(keys); i++) {
 		if (keys[i].ksym == ksym && keymask(&keys[i], kev->state)) {
 			if (keys[i].cmd != NULL && keys[i].cmd(keys[i].arg))
 				redraw();
+			prefix = 0;
 			return;
 		}
 	}