M README.md => README.md +0 -1
@@ 18,7 18,6 @@ to be used as a file selector for other programs.
## TODO:
-* Maybe rename "selection" to "cursor" to not conflict with the "select prompt"?
* refresh dirmap when directory content change
- inotify?
* command/search history
M doc/nfm.1 => doc/nfm.1 +37 -38
@@ 33,17 33,15 @@ operations via the command mode.
Only opening files and changing directories is implemented directly for
convenience.
.P
-nfm operates using two concepts, \fBselection\fR and \fBmarks\fR.
+In nfm you can use two methods of selecting files, via \fBcursor\fR and via
+\fBmarks\fR.
+The cursor is the highlighted line you can move with keybinds and allows you to
+select a single file in the current directory.
+If you want to operate on multiple files at once, perhaps even across
+multiple directories, you can use marks.
.P
-Selection simply is the file or directory currently selected by the cursor.
-As such there can only ever be one selected file.
-.P
-Marks are for operations on multiple files.
-You can mark multiple files in different directories and apply operations to
-them collectively.
-.P
-Selection and marks do not conflict.
-You can operate on the selection even if marked files exist.
+The cursor and marks do not conflict.
+You can operate on the file selected by the cursor even if marked files exist.
.
.
.SH OPTIONS
@@ 79,13 77,13 @@ The following keybinds are available when navigating the filesystem.
.P
\fBj\fR, \fBdown\fR
.RS
-Move the selection down.
+Move the cursor down.
.RE
.
.P
\fBk\fR, \fBup\fR
.RS
-Move the selection up.
+Move the cursor up.
.RE
.
.P
@@ 97,32 95,32 @@ Go to the parent directory.
.P
\fBl\fR, \fBright\fR
.RS
-If selection is a directory, enter it.
-If selection is a file, try to open it.
+If the cursor selects a directory, enter it.
+If it selects a file, try to open it.
.RE
.
.P
\fBg\fR, \fBK\fR, \fBhome\fR
.RS
-Move the selection to the top of the list.
+Move the cursor to the top of the list.
.RE
.
.P
\fBG\fR, \fBJ\fR, \fBend\fR
.RS
-Move the selection to the bottom of the list.
+Move the cursor to the bottom of the list.
.RE
.
.P
\fBpage-down\fR
.RS
-Move the selection down by 80% of the terminal height.
+Move the cursor down by 80% of the terminal height.
.RE
.
.P
\fBpage-up\fR
.RS
-Move the selection up by 80% of the terminal height.
+Move the cursor up by 80% of the terminal height.
.RE
.
.P
@@ 135,22 133,22 @@ If there are none, same behaviour as for \fBl\fR.
.P
\fBm\fR
.RS
-Toggle the mark of the selection.
+Toggle the mark of the file selected by the cursor.
.RE
.
.P
\fB/\fR
.RS
Open the search prompt, where a regular expression can be entered.
-When enter is pressed, the next file in the current directory matching the
-search pattern is selected.
+When enter is pressed, the cursor will jump next file in the current directory
+matching the search pattern.
The search pattern remains active until a new one is entered.
.RE
.
.P
\fBn\fR
.RS
-Move selection to the next file matching the search pattern.
+Move cursor to the next file matching the search pattern.
.RE
.
.P
@@ 164,13 162,13 @@ pattern are marked.
.P
\fBN\fR
.RS
-Move selection to the next marked file.
+Move cursor to the next marked file.
.RE
.
.P
\fBi\fR
.RS
-Invert marks for all entries of the current directory.
+Invert marks for all files in the current directory.
.RE
.
.P
@@ 208,8 206,8 @@ Open command prompt.
.P
\fBo\fR
.RS
-Open command prompt, prefilled with the name of the selected file and the cursor
-at the start.
+Open command prompt, prefilled with the name of the file selected by the cursor
+with the prompt cursor at the start.
This allows to quickly open files with specific programs, like alternative
editors or viewers.
.RE
@@ 218,7 216,7 @@ editors or viewers.
\fBx\fR
.RS
Open command prompt, prefilled with the 'rm' command and the name of the
-selected file.
+file selected by the cursor.
This allows to quickly delete the selected file.
.RE
.
@@ 226,7 224,7 @@ This allows to quickly delete the selected file.
\fBc\fR
.RS
Open command prompt, prefilled with the 'mv' command and the name of the
-selected file.
+file selected by the cursor.
This allows to quickly move or rename the selected file.
.RE
.
@@ 239,8 237,8 @@ exceptions.
.P
\fBl\fR
.RS
-If selection is a directory, enter it.
-If selection is a file, print its full path to stdout and exit.
+If the cursor selects a directory, enter it.
+If it selects a file, print its full path to stdout and exit.
.RE
.
.P
@@ 248,7 246,8 @@ If selection is a file, print its full path to stdout and exit.
.RS
If there are marked files or directories, write their full paths to stdout and
exit.
-Otherwise write the full path of the selection to stdout and exit.
+Otherwise write the full path of the file selected by the cursor to stdout and
+exit.
.RE
.
.
@@ 268,19 267,19 @@ Commit operation.
.P
\fBCtrl-a\fR
.RS
-Move the cursor to the beginning of the line.
+Move the prompt cursor to the beginning of the line.
.RE
.
.P
\fBCtrl-e\fR
.RS
-Move the cursor to the end of the line.
+Move the prompt cursor to the end of the line.
.RE
.
.P
\fBCtrl-s\fR
.RS
-Insert the name of the selected file.
+Insert the name of the file selected by the cursor.
.RE
.
.P
@@ 292,25 291,25 @@ Insert the paths of all marked files.
.P
\fBCtrl-w\fR
.RS
-Delete all characters from the cursor to the start of the previous word.
+Delete all characters from the prompt cursor to the start of the previous word.
.RE
.
.P
\fBCtrl-k\fR
.RS
-Delete all characters from the cursor to the end of the line.
+Delete all characters from the prompt cursor to the end of the line.
.RE
.
.P
\fBAlt-f\fR
.RS
-Move cursor to the start of the previous word.
+Move prompt cursor to the start of the previous word.
.RE
.
.P
\fBAlt-f\fR
.RS
-Move cursor to the start of the next word.
+Move prompt cursor to the start of the next word.
.RE
.
.
M src/DirMap.zig => src/DirMap.zig +2 -2
@@ 105,14 105,14 @@ pub const Dir = struct {
name: []const u8,
files: std.ArrayList(File),
- selection: usize,
+ cursor: usize,
scroll_offset: usize,
dirty: bool, // if true file list needs to be refreshed
pub fn init(self: *Dir, alloc: mem.Allocator, dir: fs.Dir, name: []const u8) !void {
self.files = std.ArrayList(File).init(alloc);
self.name = name;
- self.selection = 0;
+ self.cursor = 0;
self.scroll_offset = 0;
self.dirty = false;
M src/UserInterface.zig => src/UserInterface.zig +15 -15
@@ 625,26 625,26 @@ fn drawList(self: *Self, writer: anytype) !void {
try setAttr(writer, .{ .fg = .red, .bold = true });
try writer.writeAll(msg);
} else {
- // Move selection
- if (context.selection_delta > 0) {
- if (context.cwd.selection +| @intCast(usize, context.selection_delta) >= context.cwd.files.items.len - 1) {
- context.cwd.selection = context.cwd.files.items.len - 1;
+ // Move cursor.
+ if (context.cursor_delta > 0) {
+ if (context.cwd.cursor +| @intCast(usize, context.cursor_delta) >= context.cwd.files.items.len - 1) {
+ context.cwd.cursor = context.cwd.files.items.len - 1;
} else {
- context.cwd.selection +|= @intCast(usize, context.selection_delta);
+ context.cwd.cursor +|= @intCast(usize, context.cursor_delta);
}
- } else if (context.selection_delta < 0) {
- context.cwd.selection -|= @intCast(usize, try math.absInt(context.selection_delta));
+ } else if (context.cursor_delta < 0) {
+ context.cwd.cursor -|= @intCast(usize, try math.absInt(context.cursor_delta));
}
- // Move scroll offset
- if (context.cwd.selection < context.cwd.scroll_offset) {
- context.cwd.scroll_offset = context.cwd.selection;
- } else if (context.cwd.selection > context.cwd.scroll_offset +| self.height - 2) {
- context.cwd.scroll_offset +|= context.cwd.selection - ((self.height - 2) +| context.cwd.scroll_offset);
+ // Move scroll offset.
+ if (context.cwd.cursor < context.cwd.scroll_offset) {
+ context.cwd.scroll_offset = context.cwd.cursor;
+ } else if (context.cwd.cursor > context.cwd.scroll_offset +| self.height - 2) {
+ context.cwd.scroll_offset +|= context.cwd.cursor - ((self.height - 2) +| context.cwd.scroll_offset);
}
// TODO In most cases, only two list entries need to be drawn, the
- // previous selection and the next selection. The full list only
+ // previous cursor and the next cursor. The full list only
// needs to be draws when either the scroll_offset changes or when
// the cwd has changed.
var i: usize = 0;
@@ 653,12 653,12 @@ fn drawList(self: *Self, writer: anytype) !void {
writer,
i + 1,
context.cwd.files.items[i + context.cwd.scroll_offset],
- i + context.cwd.scroll_offset == context.cwd.selection,
+ i + context.cwd.scroll_offset == context.cwd.cursor,
self.width,
);
}
}
- context.selection_delta = 0;
+ context.cursor_delta = 0;
}
fn drawFileName(writer: anytype, y: usize, file: DirMap.Dir.File, selected: bool, _width: usize) !void {
M src/nfm.zig => src/nfm.zig +27 -28
@@ 58,9 58,9 @@ pub const Context = struct {
initial_cwd_path: []const u8 = undefined,
search: ?Regex = null,
- /// A change in the selection index, likely caused by keybind. It will be
+ /// A change in the cursor index, likely caused by keybind. It will be
/// applied whenever ui.render() is called.
- selection_delta: isize = 0,
+ cursor_delta: isize = 0,
loop: bool = true,
@@ 204,7 204,7 @@ fn handleEventUserInput(ev: UserInterface.Event) !void {
'a' => buffer.cursor = 0,
'e' => buffer.cursor = buffer.buffer.items.len,
's' => {
- const file = &context.cwd.files.items[context.cwd.selection];
+ const file = &context.cwd.files.items[context.cwd.cursor];
try buffer.insertSlice(file.name, .single_word);
try buffer.insertChar(' ');
},
@@ 340,11 340,11 @@ fn handleEventNav(ev: UserInterface.Event) !void {
.escape => try handleEscapeNav(),
.page_up => {
// Scroll 80% of the terminal height.
- context.selection_delta -|= 4 * @intCast(isize, @divFloor(context.ui.height, 5));
+ context.cursor_delta -|= 4 * @intCast(isize, @divFloor(context.ui.height, 5));
try context.ui.render(true, false);
},
.page_down => {
- context.selection_delta +|= 4 * @intCast(isize, @divFloor(context.ui.height, 5));
+ context.cursor_delta +|= 4 * @intCast(isize, @divFloor(context.ui.height, 5));
try context.ui.render(true, false);
},
.ctrl => |ch| {
@@ 407,25 407,25 @@ fn handleAsciiKeyNav(key: u8) !void {
switch (key) {
'j' => {
if (context.cwd.files.items.len != 0) {
- context.selection_delta += 1;
+ context.cursor_delta += 1;
try context.ui.render(true, title_dirty);
}
},
'k' => {
if (context.cwd.files.items.len != 0) {
- context.selection_delta -= 1;
+ context.cursor_delta -= 1;
try context.ui.render(true, title_dirty);
}
},
'h' => try setCwd(".."),
'l' => try enterOrOpen(),
'g', 'K' => {
- context.cwd.selection = 0;
+ context.cwd.cursor = 0;
context.cwd.scroll_offset = 0;
try context.ui.render(true, title_dirty);
},
'G', 'J' => {
- context.cwd.selection = context.cwd.files.items.len - 1;
+ context.cwd.cursor = context.cwd.files.items.len - 1;
try context.ui.render(true, title_dirty);
},
// TODO find out why enter is suddenly carriage return instead of newline.
@@ 436,7 436,7 @@ fn handleAsciiKeyNav(key: u8) !void {
},
'm' => {
if (context.cwd.files.items.len == 0) return;
- const file = &context.cwd.files.items[context.cwd.selection];
+ const file = &context.cwd.files.items[context.cwd.cursor];
file.mark = !file.mark;
try context.ui.render(true, title_dirty);
},
@@ 457,7 457,7 @@ fn handleAsciiKeyNav(key: u8) !void {
// own command prompt commands, with some sort of special
// format syntax to insert file names and set the cursor
// position.
- const file = &context.cwd.files.items[context.cwd.selection];
+ const file = &context.cwd.files.items[context.cwd.cursor];
try context.mode.setUserInput(.command);
try context.mode.user_input.buffer.insertChar(' ');
try context.mode.user_input.buffer.insertSlice(file.name, .single_word);
@@ 465,7 465,7 @@ fn handleAsciiKeyNav(key: u8) !void {
try context.ui.render(false, true);
},
'x' => {
- const file = &context.cwd.files.items[context.cwd.selection];
+ const file = &context.cwd.files.items[context.cwd.cursor];
try context.mode.setUserInput(.command);
try context.mode.user_input.buffer.insertSlice("rm ", .pure);
try context.mode.user_input.buffer.insertSlice(file.name, .single_word);
@@ 477,7 477,7 @@ fn handleAsciiKeyNav(key: u8) !void {
try context.ui.render(false, true);
},
'c' => {
- const file = &context.cwd.files.items[context.cwd.selection];
+ const file = &context.cwd.files.items[context.cwd.cursor];
try context.mode.setUserInput(.command);
try context.mode.user_input.buffer.insertSlice("mv ", .pure);
try context.mode.user_input.buffer.insertSlice(file.name, .single_word);
@@ 504,19 504,19 @@ fn handleAsciiKeyNav(key: u8) !void {
return;
};
- var i = context.cwd.selection;
- for (context.cwd.files.items[context.cwd.selection + 1 ..]) |file| {
+ var i = context.cwd.cursor;
+ for (context.cwd.files.items[context.cwd.cursor + 1 ..]) |file| {
i +|= 1;
if (try search.partialMatch(file.name)) {
- context.cwd.selection = i;
+ context.cwd.cursor = i;
try context.ui.render(true, title_dirty);
return;
}
}
i = 0;
- for (context.cwd.files.items[0 .. context.cwd.selection + 1]) |file| {
+ for (context.cwd.files.items[0 .. context.cwd.cursor + 1]) |file| {
if (try search.partialMatch(file.name)) {
- context.cwd.selection = i;
+ context.cwd.cursor = i;
try context.ui.render(true, title_dirty);
return;
}
@@ 527,19 527,19 @@ fn handleAsciiKeyNav(key: u8) !void {
try context.ui.render(false, true);
},
'N' => {
- var i = context.cwd.selection;
- for (context.cwd.files.items[context.cwd.selection + 1 ..]) |file| {
+ var i = context.cwd.cursor;
+ for (context.cwd.files.items[context.cwd.cursor + 1 ..]) |file| {
i +|= 1;
if (file.mark) {
- context.cwd.selection = i;
+ context.cwd.cursor = i;
try context.ui.render(true, false);
return;
}
}
i = 0;
- for (context.cwd.files.items[0 .. context.cwd.selection + 1]) |file| {
+ for (context.cwd.files.items[0 .. context.cwd.cursor + 1]) |file| {
if (file.mark) {
- context.cwd.selection = i;
+ context.cwd.cursor = i;
try context.ui.render(true, false);
return;
}
@@ 616,7 616,7 @@ fn handleReturnNav() !void {
fn enterOrOpen() !void {
if (context.cwd.files.items.len == 0) return;
- const file = &context.cwd.files.items[context.cwd.selection];
+ const file = &context.cwd.files.items[context.cwd.cursor];
if (file.kind == .Directory) {
try setCwd(file.name);
} else if (file.kind == .File) {
@@ 685,13 685,12 @@ fn setCwd(dirname: []const u8) !void {
}
};
- // If we go up one directory, ensure that the selection is on the previous
- // cwd.
+ // If we go up one directory, ensure that the cursor is on the previous cwd.
if (dirname[0] == '.' and dirname[1] == '.') {
var i: usize = 0;
for (context.cwd.files.items) |*dir| {
if (mem.eql(u8, prev_basename, dir.name)) {
- context.cwd.selection = i;
+ context.cwd.cursor = i;
break;
}
i += 1;
@@ 713,7 712,7 @@ fn dumpSelection() !void {
// If there were no marked files, try to output the selected file.
if (!mark) {
if (context.cwd.files.items.len == 0) return;
- const file = context.cwd.files.items[context.cwd.selection];
+ const file = context.cwd.files.items[context.cwd.cursor];
try file.dumpPath(writer);
}
}