rufio 0.32.0 → 0.33.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +23 -0
- data/README.md +63 -7
- data/README_EN.md +25 -0
- data/docs/CHANGELOG_v0.33.0.md +444 -0
- data/docs/file-preview-optimization-analysis.md +759 -0
- data/docs/file-preview-performance-issue-FIXED.md +547 -0
- data/lib/rufio/application.rb +9 -1
- data/lib/rufio/background_command_executor.rb +98 -0
- data/lib/rufio/command_logger.rb +118 -0
- data/lib/rufio/command_mode.rb +17 -2
- data/lib/rufio/directory_listing.rb +60 -12
- data/lib/rufio/keybind_handler.rb +73 -2
- data/lib/rufio/native/rufio_native.bundle +0 -0
- data/lib/rufio/native/rufio_zig.bundle +0 -0
- data/lib/rufio/native_scanner.rb +306 -0
- data/lib/rufio/native_scanner_magnus.rb +194 -0
- data/lib/rufio/native_scanner_zig.rb +221 -0
- data/lib/rufio/terminal_ui.rb +66 -16
- data/lib/rufio/version.rb +1 -1
- data/lib/rufio.rb +5 -0
- data/lib_rust/rufio_native/.cargo/config.toml +2 -0
- data/lib_rust/rufio_native/Cargo.lock +346 -0
- data/lib_rust/rufio_native/Cargo.toml +18 -0
- data/lib_rust/rufio_native/build.rs +46 -0
- data/lib_rust/rufio_native/src/lib.rs +197 -0
- data/lib_zig/rufio_native/Makefile +33 -0
- data/lib_zig/rufio_native/build.zig +45 -0
- data/lib_zig/rufio_native/src/main.zig +167 -0
- metadata +20 -2
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
const std = @import("std");
|
|
2
|
+
const c = @cImport({
|
|
3
|
+
@cInclude("ruby.h");
|
|
4
|
+
@cInclude("dirent.h");
|
|
5
|
+
@cInclude("sys/stat.h");
|
|
6
|
+
@cInclude("string.h");
|
|
7
|
+
@cInclude("time.h");
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
/// ディレクトリエントリ情報
|
|
11
|
+
const DirEntry = struct {
|
|
12
|
+
name: []const u8,
|
|
13
|
+
is_dir: bool,
|
|
14
|
+
size: u64,
|
|
15
|
+
mtime: i64,
|
|
16
|
+
executable: bool,
|
|
17
|
+
hidden: bool,
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
/// ディレクトリをスキャンしてRuby配列を返す
|
|
21
|
+
fn scanDirectory(self: c.VALUE, path_value: c.VALUE) callconv(.c) c.VALUE {
|
|
22
|
+
_ = self;
|
|
23
|
+
|
|
24
|
+
// パス文字列を取得
|
|
25
|
+
var mutable_path = path_value;
|
|
26
|
+
const path_str = c.rb_string_value_cstr(@ptrCast(&mutable_path));
|
|
27
|
+
const path_len = c.strlen(path_str);
|
|
28
|
+
const path = path_str[0..path_len];
|
|
29
|
+
|
|
30
|
+
// ディレクトリを開く
|
|
31
|
+
const dir = c.opendir(path_str) orelse {
|
|
32
|
+
c.rb_raise(c.rb_eRuntimeError, "Failed to open directory");
|
|
33
|
+
return c.Qnil;
|
|
34
|
+
};
|
|
35
|
+
defer _ = c.closedir(dir);
|
|
36
|
+
|
|
37
|
+
// Ruby配列を作成
|
|
38
|
+
const ary = c.rb_ary_new();
|
|
39
|
+
|
|
40
|
+
// ディレクトリエントリを読み取り
|
|
41
|
+
while (c.readdir(dir)) |entry| {
|
|
42
|
+
const name_ptr = @as([*:0]const u8, @ptrCast(&entry.*.d_name));
|
|
43
|
+
const name_len = c.strlen(name_ptr);
|
|
44
|
+
const name = name_ptr[0..name_len];
|
|
45
|
+
|
|
46
|
+
// "." と ".." をスキップ
|
|
47
|
+
if (std.mem.eql(u8, name, ".") or std.mem.eql(u8, name, "..")) {
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// フルパスを構築
|
|
52
|
+
var path_buf: [std.fs.max_path_bytes]u8 = undefined;
|
|
53
|
+
const full_path = std.fmt.bufPrintZ(&path_buf, "{s}/{s}", .{ path, name }) catch {
|
|
54
|
+
continue;
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
// ファイル情報を取得
|
|
58
|
+
var stat_buf: c.struct_stat = undefined;
|
|
59
|
+
if (c.lstat(full_path.ptr, &stat_buf) != 0) {
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// ディレクトリかどうか
|
|
64
|
+
const is_dir = (stat_buf.st_mode & c.S_IFMT) == c.S_IFDIR;
|
|
65
|
+
|
|
66
|
+
// 実行可能かどうか
|
|
67
|
+
const executable = (stat_buf.st_mode & c.S_IXUSR) != 0;
|
|
68
|
+
|
|
69
|
+
// 隠しファイルかどうか
|
|
70
|
+
const hidden = name[0] == '.';
|
|
71
|
+
|
|
72
|
+
// Rubyハッシュを作成
|
|
73
|
+
const hash = c.rb_hash_new();
|
|
74
|
+
|
|
75
|
+
// ハッシュにキーと値を設定
|
|
76
|
+
_ = c.rb_hash_aset(hash, c.ID2SYM(c.rb_intern("name")), c.rb_str_new(name.ptr, @intCast(name.len)));
|
|
77
|
+
_ = c.rb_hash_aset(hash, c.ID2SYM(c.rb_intern("is_dir")), if (is_dir) c.Qtrue else c.Qfalse);
|
|
78
|
+
_ = c.rb_hash_aset(hash, c.ID2SYM(c.rb_intern("size")), c.ULL2NUM(@as(c_ulonglong, @intCast(stat_buf.st_size))));
|
|
79
|
+
_ = c.rb_hash_aset(hash, c.ID2SYM(c.rb_intern("mtime")), c.LL2NUM(@as(c_longlong, @intCast(stat_buf.st_mtimespec.tv_sec))));
|
|
80
|
+
_ = c.rb_hash_aset(hash, c.ID2SYM(c.rb_intern("executable")), if (executable) c.Qtrue else c.Qfalse);
|
|
81
|
+
_ = c.rb_hash_aset(hash, c.ID2SYM(c.rb_intern("hidden")), if (hidden) c.Qtrue else c.Qfalse);
|
|
82
|
+
|
|
83
|
+
// 配列に追加
|
|
84
|
+
_ = c.rb_ary_push(ary, hash);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
return ary;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/// 高速スキャン(エントリ数制限付き)
|
|
91
|
+
fn scanDirectoryFast(self: c.VALUE, path_value: c.VALUE, max_entries_value: c.VALUE) callconv(.c) c.VALUE {
|
|
92
|
+
_ = self;
|
|
93
|
+
|
|
94
|
+
const max_entries = @as(usize, @intCast(c.NUM2INT(max_entries_value)));
|
|
95
|
+
var mutable_path = path_value;
|
|
96
|
+
const path_str = c.rb_string_value_cstr(@ptrCast(&mutable_path));
|
|
97
|
+
const path_len = c.strlen(path_str);
|
|
98
|
+
const path = path_str[0..path_len];
|
|
99
|
+
|
|
100
|
+
const dir = c.opendir(path_str) orelse {
|
|
101
|
+
c.rb_raise(c.rb_eRuntimeError, "Failed to open directory");
|
|
102
|
+
return c.Qnil;
|
|
103
|
+
};
|
|
104
|
+
defer _ = c.closedir(dir);
|
|
105
|
+
|
|
106
|
+
const ary = c.rb_ary_new();
|
|
107
|
+
var count: usize = 0;
|
|
108
|
+
|
|
109
|
+
while (c.readdir(dir)) |entry| {
|
|
110
|
+
if (count >= max_entries) break;
|
|
111
|
+
|
|
112
|
+
const name_ptr = @as([*:0]const u8, @ptrCast(&entry.*.d_name));
|
|
113
|
+
const name_len = c.strlen(name_ptr);
|
|
114
|
+
const name = name_ptr[0..name_len];
|
|
115
|
+
|
|
116
|
+
if (std.mem.eql(u8, name, ".") or std.mem.eql(u8, name, "..")) {
|
|
117
|
+
continue;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
var path_buf: [std.fs.max_path_bytes]u8 = undefined;
|
|
121
|
+
const full_path = std.fmt.bufPrintZ(&path_buf, "{s}/{s}", .{ path, name }) catch {
|
|
122
|
+
continue;
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
var stat_buf: c.struct_stat = undefined;
|
|
126
|
+
if (c.lstat(full_path.ptr, &stat_buf) != 0) {
|
|
127
|
+
continue;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
const is_dir = (stat_buf.st_mode & c.S_IFMT) == c.S_IFDIR;
|
|
131
|
+
const executable = (stat_buf.st_mode & c.S_IXUSR) != 0;
|
|
132
|
+
const hidden = name[0] == '.';
|
|
133
|
+
|
|
134
|
+
const hash = c.rb_hash_new();
|
|
135
|
+
_ = c.rb_hash_aset(hash, c.ID2SYM(c.rb_intern("name")), c.rb_str_new(name.ptr, @intCast(name.len)));
|
|
136
|
+
_ = c.rb_hash_aset(hash, c.ID2SYM(c.rb_intern("is_dir")), if (is_dir) c.Qtrue else c.Qfalse);
|
|
137
|
+
_ = c.rb_hash_aset(hash, c.ID2SYM(c.rb_intern("size")), c.ULL2NUM(@as(c_ulonglong, @intCast(stat_buf.st_size))));
|
|
138
|
+
_ = c.rb_hash_aset(hash, c.ID2SYM(c.rb_intern("mtime")), c.LL2NUM(@as(c_longlong, @intCast(stat_buf.st_mtimespec.tv_sec))));
|
|
139
|
+
_ = c.rb_hash_aset(hash, c.ID2SYM(c.rb_intern("executable")), if (executable) c.Qtrue else c.Qfalse);
|
|
140
|
+
_ = c.rb_hash_aset(hash, c.ID2SYM(c.rb_intern("hidden")), if (hidden) c.Qtrue else c.Qfalse);
|
|
141
|
+
|
|
142
|
+
_ = c.rb_ary_push(ary, hash);
|
|
143
|
+
count += 1;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
return ary;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/// バージョン情報
|
|
150
|
+
fn getVersion(_: c.VALUE) callconv(.c) c.VALUE {
|
|
151
|
+
const version = "1.0.0-zig";
|
|
152
|
+
return c.rb_str_new(version.ptr, @intCast(version.len));
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/// Ruby拡張の初期化
|
|
156
|
+
export fn Init_rufio_zig() void {
|
|
157
|
+
// Rufioモジュールを取得または作成
|
|
158
|
+
const rufio_module = c.rb_define_module("Rufio");
|
|
159
|
+
|
|
160
|
+
// NativeScannerZigクラスを定義
|
|
161
|
+
const scanner_class = c.rb_define_class_under(rufio_module, "NativeScannerZig", c.rb_cObject);
|
|
162
|
+
|
|
163
|
+
// クラスメソッドを定義
|
|
164
|
+
c.rb_define_singleton_method(scanner_class, "scan_directory", @ptrCast(&scanDirectory), 1);
|
|
165
|
+
c.rb_define_singleton_method(scanner_class, "scan_directory_fast", @ptrCast(&scanDirectoryFast), 2);
|
|
166
|
+
c.rb_define_singleton_method(scanner_class, "version", @ptrCast(&getVersion), 0);
|
|
167
|
+
}
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: rufio
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.33.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- masisz
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-01-
|
|
11
|
+
date: 2026-01-03 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: io-console
|
|
@@ -129,22 +129,27 @@ files:
|
|
|
129
129
|
- docs/CHANGELOG_v0.30.0.md
|
|
130
130
|
- docs/CHANGELOG_v0.31.0.md
|
|
131
131
|
- docs/CHANGELOG_v0.32.0.md
|
|
132
|
+
- docs/CHANGELOG_v0.33.0.md
|
|
132
133
|
- docs/CHANGELOG_v0.4.0.md
|
|
133
134
|
- docs/CHANGELOG_v0.5.0.md
|
|
134
135
|
- docs/CHANGELOG_v0.6.0.md
|
|
135
136
|
- docs/CHANGELOG_v0.7.0.md
|
|
136
137
|
- docs/CHANGELOG_v0.8.0.md
|
|
137
138
|
- docs/CHANGELOG_v0.9.0.md
|
|
139
|
+
- docs/file-preview-optimization-analysis.md
|
|
140
|
+
- docs/file-preview-performance-issue-FIXED.md
|
|
138
141
|
- info/help.md
|
|
139
142
|
- info/keybindings.md
|
|
140
143
|
- info/welcome.md
|
|
141
144
|
- lib/rufio.rb
|
|
142
145
|
- lib/rufio/application.rb
|
|
146
|
+
- lib/rufio/background_command_executor.rb
|
|
143
147
|
- lib/rufio/bookmark.rb
|
|
144
148
|
- lib/rufio/bookmark_manager.rb
|
|
145
149
|
- lib/rufio/color_helper.rb
|
|
146
150
|
- lib/rufio/command_completion.rb
|
|
147
151
|
- lib/rufio/command_history.rb
|
|
152
|
+
- lib/rufio/command_logger.rb
|
|
148
153
|
- lib/rufio/command_mode.rb
|
|
149
154
|
- lib/rufio/command_mode_ui.rb
|
|
150
155
|
- lib/rufio/config.rb
|
|
@@ -159,6 +164,11 @@ files:
|
|
|
159
164
|
- lib/rufio/info_notice.rb
|
|
160
165
|
- lib/rufio/keybind_handler.rb
|
|
161
166
|
- lib/rufio/logger.rb
|
|
167
|
+
- lib/rufio/native/rufio_native.bundle
|
|
168
|
+
- lib/rufio/native/rufio_zig.bundle
|
|
169
|
+
- lib/rufio/native_scanner.rb
|
|
170
|
+
- lib/rufio/native_scanner_magnus.rb
|
|
171
|
+
- lib/rufio/native_scanner_zig.rb
|
|
162
172
|
- lib/rufio/plugin.rb
|
|
163
173
|
- lib/rufio/plugin_config.rb
|
|
164
174
|
- lib/rufio/plugin_manager.rb
|
|
@@ -173,6 +183,14 @@ files:
|
|
|
173
183
|
- lib/rufio/text_utils.rb
|
|
174
184
|
- lib/rufio/version.rb
|
|
175
185
|
- lib/rufio/zoxide_integration.rb
|
|
186
|
+
- lib_rust/rufio_native/.cargo/config.toml
|
|
187
|
+
- lib_rust/rufio_native/Cargo.lock
|
|
188
|
+
- lib_rust/rufio_native/Cargo.toml
|
|
189
|
+
- lib_rust/rufio_native/build.rs
|
|
190
|
+
- lib_rust/rufio_native/src/lib.rs
|
|
191
|
+
- lib_zig/rufio_native/Makefile
|
|
192
|
+
- lib_zig/rufio_native/build.zig
|
|
193
|
+
- lib_zig/rufio_native/src/main.zig
|
|
176
194
|
- publish_gem.zsh
|
|
177
195
|
- retag.sh
|
|
178
196
|
- test_delete/test1.txt
|