rufio 1.1.0 → 1.3.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 +34 -0
- data/README.md +74 -3
- data/README_ja.md +71 -2
- data/Rakefile +14 -1
- data/bin/rufio +31 -2
- data/docs/fast_zip_design_ja.md +167 -0
- data/info/help.md +2 -0
- data/info/keybindings.md +3 -1
- data/info/welcome.md +1 -1
- data/lib/rufio/application.rb +12 -1
- data/lib/rufio/archive_controller.rb +211 -0
- data/lib/rufio/background_command_executor.rb +9 -0
- data/lib/rufio/background_status.rb +49 -0
- data/lib/rufio/bookmark_controller.rb +38 -121
- data/lib/rufio/bookmark_manager.rb +77 -331
- data/lib/rufio/command_completion.rb +6 -1
- data/lib/rufio/command_history.rb +5 -2
- data/lib/rufio/command_mode.rb +40 -134
- data/lib/rufio/command_mode_ui.rb +4 -42
- data/lib/rufio/config.rb +88 -136
- data/lib/rufio/config_loader.rb +3 -11
- data/lib/rufio/dialog_renderer.rb +64 -152
- data/lib/rufio/dialog_support.rb +69 -0
- data/lib/rufio/document_text_extractor.rb +167 -0
- data/lib/rufio/file_operation_controller.rb +49 -222
- data/lib/rufio/file_preview.rb +46 -2
- data/lib/rufio/global_search.rb +121 -9
- data/lib/rufio/help_menu.rb +8 -2
- data/lib/rufio/interpreter_resolver.rb +6 -11
- data/lib/rufio/job_manager.rb +2 -5
- data/lib/rufio/key_input.rb +77 -0
- data/lib/rufio/keybind_handler.rb +81 -115
- data/lib/rufio/local_script_scanner.rb +6 -18
- data/lib/rufio/native/aarch64-linux-gnu/librufio_zig.so +0 -0
- data/lib/rufio/native/aarch64-linux-musl/librufio_zig.so +0 -0
- data/lib/rufio/native/aarch64-macos/librufio_zig.dylib +0 -0
- data/lib/rufio/native/aarch64-windows/rufio_zig.dll +0 -0
- data/lib/rufio/native/x86_64-linux-gnu/librufio_zig.so +0 -0
- data/lib/rufio/native/x86_64-linux-musl/librufio_zig.so +0 -0
- data/lib/rufio/native/x86_64-macos/librufio_zig.dylib +0 -0
- data/lib/rufio/native/x86_64-windows/rufio_zig.dll +0 -0
- data/lib/rufio/native_content_search.rb +153 -0
- data/lib/rufio/native_scanner.rb +13 -68
- data/lib/rufio/native_scanner_zig.rb +106 -56
- data/lib/rufio/native_zip.rb +121 -0
- data/lib/rufio/navigation_controller.rb +18 -20
- data/lib/rufio/screen.rb +2 -12
- data/lib/rufio/script_executor.rb +6 -73
- data/lib/rufio/script_file.rb +44 -0
- data/lib/rufio/script_path_manager.rb +9 -43
- data/lib/rufio/script_runner.rb +13 -50
- data/lib/rufio/search_controller.rb +1 -1
- data/lib/rufio/shell_command_completion.rb +1 -5
- data/lib/rufio/shell_init.rb +90 -0
- data/lib/rufio/task_status.rb +5 -1
- data/lib/rufio/terminal_ui.rb +55 -294
- data/lib/rufio/text_utils.rb +26 -3
- data/lib/rufio/ui_renderer.rb +63 -40
- data/lib/rufio/version.rb +1 -1
- data/lib/rufio/zip_archive.rb +314 -0
- data/lib/rufio/zip_extractor.rb +346 -0
- data/lib/rufio/zip_writer.rb +268 -0
- data/lib/rufio/zoxide_integration.rb +5 -43
- data/lib/rufio.rb +5 -0
- data/lib_zig/rufio_native/Makefile +54 -17
- data/lib_zig/rufio_native/bench.sh +36 -0
- data/lib_zig/rufio_native/build.zig +32 -35
- data/lib_zig/rufio_native/src/cli.zig +99 -0
- data/lib_zig/rufio_native/src/main.zig +187 -83
- data/lib_zig/rufio_native/src/os.zig +889 -0
- data/lib_zig/rufio_native/src/search.zig +919 -0
- data/lib_zig/rufio_native/src/search_test.zig +88 -0
- data/lib_zig/rufio_native/src/zip.zig +482 -0
- metadata +125 -3
- data/lib/rufio/native/rufio_zig.bundle +0 -0
data/lib/rufio.rb
CHANGED
|
@@ -4,6 +4,8 @@ require_relative 'rufio/version'
|
|
|
4
4
|
require_relative 'rufio/config'
|
|
5
5
|
require_relative 'rufio/config_loader'
|
|
6
6
|
require_relative 'rufio/color_helper'
|
|
7
|
+
require_relative 'rufio/key_input'
|
|
8
|
+
require_relative 'rufio/shell_init'
|
|
7
9
|
require_relative 'rufio/directory_listing'
|
|
8
10
|
require_relative 'rufio/filter_manager'
|
|
9
11
|
require_relative 'rufio/selection_manager'
|
|
@@ -22,6 +24,9 @@ require_relative 'rufio/search_controller'
|
|
|
22
24
|
require_relative 'rufio/keybind_handler'
|
|
23
25
|
require_relative 'rufio/ansi_line_parser'
|
|
24
26
|
require_relative 'rufio/syntax_highlighter'
|
|
27
|
+
require_relative 'rufio/zip_archive'
|
|
28
|
+
require_relative 'rufio/zip_extractor'
|
|
29
|
+
require_relative 'rufio/zip_writer'
|
|
25
30
|
require_relative 'rufio/file_preview'
|
|
26
31
|
require_relative 'rufio/terminal_ui'
|
|
27
32
|
require_relative 'rufio/application'
|
|
@@ -1,34 +1,71 @@
|
|
|
1
|
-
# Makefile for Zig Ruby
|
|
1
|
+
# Makefile for Zig native library (Ruby ABI 非依存・Fiddle 経由でロード)
|
|
2
|
+
#
|
|
3
|
+
# make 現在の環境向けにビルド
|
|
4
|
+
# make install 現在の環境向けだけを Gem 同梱と同じ設定でビルドして lib/rufio/native/<platform>/ に配置
|
|
5
|
+
# make dist Gem 同梱用に全プラットフォームをクロスコンパイル
|
|
6
|
+
# make test 検索エンジンの単体テスト
|
|
2
7
|
|
|
3
|
-
RUBY := ruby
|
|
4
8
|
ZIG := zig
|
|
5
|
-
|
|
6
|
-
# Rubyの設定を取得
|
|
7
|
-
RUBY_INCLUDE := $(shell $(RUBY) -e "puts RbConfig::CONFIG['rubyhdrdir']")
|
|
8
|
-
RUBY_ARCH_INCLUDE := $(shell $(RUBY) -e "puts RbConfig::CONFIG['rubyarchhdrdir']")
|
|
9
|
-
RUBY_LIB_DIR := $(shell $(RUBY) -e "puts RbConfig::CONFIG['libdir']")
|
|
10
|
-
RUBY_VERSION := $(shell $(RUBY) -e "puts RbConfig::CONFIG['MAJOR'] + '.' + RbConfig::CONFIG['MINOR']")
|
|
9
|
+
RUBY := ruby
|
|
11
10
|
|
|
12
11
|
# コンパイルフラグ
|
|
13
12
|
ZIG_FLAGS := -O ReleaseFast -dynamic -lc
|
|
14
|
-
ZIG_FLAGS += -I$(RUBY_INCLUDE)
|
|
15
|
-
ZIG_FLAGS += -I$(RUBY_ARCH_INCLUDE)
|
|
16
|
-
ZIG_FLAGS += -L$(RUBY_LIB_DIR)
|
|
17
|
-
ZIG_FLAGS += -lruby.$(RUBY_VERSION)
|
|
18
13
|
|
|
19
14
|
# ターゲット
|
|
20
15
|
TARGET := librufio_zig.dylib
|
|
16
|
+
BENCH := rufio_search
|
|
21
17
|
SRC := src/main.zig
|
|
18
|
+
SOURCES := src/main.zig src/search.zig src/os.zig src/zip.zig
|
|
19
|
+
NATIVE_DIR := ../../lib/rufio/native
|
|
20
|
+
BUILD_DIR := zig-out/dist
|
|
21
|
+
|
|
22
|
+
# Gem 同梱プラットフォーム(ディレクトリ名:Zig ターゲット:ファイル名)
|
|
23
|
+
# Linux は glibc 2.17(CentOS 7 世代)以降で動くようにリンクする
|
|
24
|
+
PLATFORMS := \
|
|
25
|
+
aarch64-macos:aarch64-macos.11.0:librufio_zig.dylib \
|
|
26
|
+
x86_64-macos:x86_64-macos.10.15:librufio_zig.dylib \
|
|
27
|
+
x86_64-linux-gnu:x86_64-linux-gnu.2.17:librufio_zig.so \
|
|
28
|
+
aarch64-linux-gnu:aarch64-linux-gnu.2.17:librufio_zig.so \
|
|
29
|
+
x86_64-linux-musl:x86_64-linux-musl:librufio_zig.so \
|
|
30
|
+
aarch64-linux-musl:aarch64-linux-musl:librufio_zig.so \
|
|
31
|
+
x86_64-windows:x86_64-windows-gnu:rufio_zig.dll \
|
|
32
|
+
aarch64-windows:aarch64-windows-gnu:rufio_zig.dll
|
|
22
33
|
|
|
23
34
|
all: $(TARGET)
|
|
24
35
|
|
|
25
|
-
$(TARGET): $(
|
|
36
|
+
$(TARGET): $(SOURCES)
|
|
26
37
|
$(ZIG) build-lib $(SRC) $(ZIG_FLAGS) -femit-bin=$@
|
|
27
38
|
|
|
39
|
+
# ripgrep との比較用 CLI
|
|
40
|
+
$(BENCH): src/cli.zig src/search.zig src/os.zig
|
|
41
|
+
$(ZIG) build-exe src/cli.zig -O ReleaseFast -lc -femit-bin=$@
|
|
42
|
+
|
|
43
|
+
test:
|
|
44
|
+
$(ZIG) test src/search_test.zig
|
|
45
|
+
|
|
46
|
+
bench: $(BENCH)
|
|
47
|
+
./bench.sh
|
|
48
|
+
|
|
49
|
+
# ONLY=<platform> で 1 つだけビルドする
|
|
50
|
+
dist: $(SOURCES)
|
|
51
|
+
@for entry in $(PLATFORMS); do \
|
|
52
|
+
dir=$${entry%%:*}; rest=$${entry#*:}; triple=$${rest%%:*}; file=$${rest#*:}; \
|
|
53
|
+
if [ -n "$(ONLY)" ] && [ "$(ONLY)" != "$$dir" ]; then continue; fi; \
|
|
54
|
+
echo "==> $$dir ($$triple)"; \
|
|
55
|
+
mkdir -p $(BUILD_DIR)/$$dir $(NATIVE_DIR)/$$dir || exit 1; \
|
|
56
|
+
$(ZIG) build-lib $(SRC) -target $$triple $(ZIG_FLAGS) -fstrip \
|
|
57
|
+
-femit-bin=$(BUILD_DIR)/$$dir/$$file || exit 1; \
|
|
58
|
+
cp $(BUILD_DIR)/$$dir/$$file $(NATIVE_DIR)/$$dir/$$file || exit 1; \
|
|
59
|
+
done
|
|
60
|
+
|
|
28
61
|
clean:
|
|
29
|
-
rm -
|
|
62
|
+
rm -rf $(TARGET) $(BENCH) *.o $(BUILD_DIR)
|
|
30
63
|
|
|
31
|
-
|
|
32
|
-
|
|
64
|
+
# 現在の環境のプラットフォーム名は Ruby 側の判定(NativeScannerZigFFI.platform_dir)に合わせ、
|
|
65
|
+
# Gem 同梱と同じ設定でビルドする
|
|
66
|
+
install:
|
|
67
|
+
@platform=$$($(RUBY) -I../../lib -rrufio/native_scanner -rrufio/native_scanner_zig -e 'print Rufio::NativeScannerZigFFI.platform_dir.to_s' 2>/dev/null); \
|
|
68
|
+
if [ -z "$$platform" ]; then echo "unsupported platform"; exit 1; fi; \
|
|
69
|
+
$(MAKE) --no-print-directory dist ONLY=$$platform
|
|
33
70
|
|
|
34
|
-
.PHONY: all clean install
|
|
71
|
+
.PHONY: all clean install test bench dist
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# rufio_search と ripgrep の速度比較(ウォームキャッシュ、各 10 回の中央値)
|
|
3
|
+
# 使い方: ./bench.sh [DIR] [QUERY...]
|
|
4
|
+
set -euo pipefail
|
|
5
|
+
cd "$(dirname "$0")"
|
|
6
|
+
|
|
7
|
+
DIR=${1:-$(cd ../.. && pwd)}
|
|
8
|
+
shift || true
|
|
9
|
+
QUERIES=("$@")
|
|
10
|
+
[ ${#QUERIES[@]} -eq 0 ] && QUERIES=(rb_define_method zzqxj_not_found "the" "日本語")
|
|
11
|
+
RUNS=${RUNS:-10}
|
|
12
|
+
|
|
13
|
+
[ -x ./rufio_search ] || make rufio_search >/dev/null
|
|
14
|
+
|
|
15
|
+
measure() {
|
|
16
|
+
python3 - "$RUNS" "$@" <<'EOF'
|
|
17
|
+
import subprocess, sys, time, statistics
|
|
18
|
+
runs = int(sys.argv[1]); cmd = sys.argv[2:]
|
|
19
|
+
for _ in range(2):
|
|
20
|
+
subprocess.run(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
|
21
|
+
times = []
|
|
22
|
+
for _ in range(runs):
|
|
23
|
+
t = time.perf_counter()
|
|
24
|
+
subprocess.run(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
|
25
|
+
times.append((time.perf_counter() - t) * 1000)
|
|
26
|
+
print(f"median {statistics.median(times):8.1f} ms min {min(times):8.1f} ms")
|
|
27
|
+
EOF
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
echo "corpus: $DIR ($(find "$DIR" -type f | wc -l | tr -d ' ') files, $(du -sh "$DIR" | cut -f1))"
|
|
31
|
+
for q in "${QUERIES[@]}"; do
|
|
32
|
+
hits=$(./rufio_search "$q" "$DIR" | wc -l | tr -d ' ')
|
|
33
|
+
echo "== query: $q ($hits lines)"
|
|
34
|
+
printf ' rufio_search : '; measure ./rufio_search "$q" "$DIR"
|
|
35
|
+
printf ' rg -uu -i -F : '; measure rg -uu -i -F -n "$q" "$DIR"
|
|
36
|
+
done
|
|
@@ -4,42 +4,39 @@ pub fn build(b: *std.Build) void {
|
|
|
4
4
|
const target = b.standardTargetOptions(.{});
|
|
5
5
|
const optimize = b.standardOptimizeOption(.{});
|
|
6
6
|
|
|
7
|
-
//
|
|
8
|
-
const lib = b.
|
|
7
|
+
// 動的ライブラリ(Ruby ABI 非依存・Fiddle 経由でロード)
|
|
8
|
+
const lib = b.addLibrary(.{
|
|
9
9
|
.name = "rufio_zig",
|
|
10
|
-
.
|
|
11
|
-
.
|
|
12
|
-
|
|
10
|
+
.linkage = .dynamic,
|
|
11
|
+
.root_module = b.createModule(.{
|
|
12
|
+
.root_source_file = b.path("src/main.zig"),
|
|
13
|
+
.target = target,
|
|
14
|
+
.optimize = optimize,
|
|
15
|
+
.link_libc = true,
|
|
16
|
+
}),
|
|
13
17
|
});
|
|
14
|
-
|
|
15
|
-
// 共有ライブラリとしてリンク
|
|
16
|
-
lib.linkage = .dynamic;
|
|
17
|
-
lib.linkLibC();
|
|
18
|
-
|
|
19
|
-
// RubyのヘッダーとライブラリへのパスをRubyから取得
|
|
20
|
-
var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
|
|
21
|
-
defer arena.deinit();
|
|
22
|
-
const allocator = arena.allocator();
|
|
23
|
-
|
|
24
|
-
// Rubyのインクルードパスを取得
|
|
25
|
-
const ruby_include_result = b.run(&.{ "ruby", "-e", "puts RbConfig::CONFIG['rubyhdrdir']" });
|
|
26
|
-
const ruby_include = std.mem.trim(u8, ruby_include_result, " \n\r\t");
|
|
27
|
-
|
|
28
|
-
const ruby_arch_include_result = b.run(&.{ "ruby", "-e", "puts RbConfig::CONFIG['rubyarchhdrdir']" });
|
|
29
|
-
const ruby_arch_include = std.mem.trim(u8, ruby_arch_include_result, " \n\r\t");
|
|
30
|
-
|
|
31
|
-
const ruby_lib_dir_result = b.run(&.{ "ruby", "-e", "puts RbConfig::CONFIG['libdir']" });
|
|
32
|
-
const ruby_lib_dir = std.mem.trim(u8, ruby_lib_dir_result, " \n\r\t");
|
|
33
|
-
|
|
34
|
-
// インクルードパスを追加
|
|
35
|
-
lib.addIncludePath(.{ .cwd_relative = ruby_include });
|
|
36
|
-
lib.addIncludePath(.{ .cwd_relative = ruby_arch_include });
|
|
37
|
-
|
|
38
|
-
// ライブラリパスを追加
|
|
39
|
-
lib.addLibraryPath(.{ .cwd_relative = ruby_lib_dir });
|
|
40
|
-
|
|
41
|
-
// Rubyライブラリとリンク
|
|
42
|
-
lib.linkSystemLibrary("ruby.3.4");
|
|
43
|
-
|
|
44
18
|
b.installArtifact(lib);
|
|
19
|
+
|
|
20
|
+
// ripgrep との比較用 CLI
|
|
21
|
+
const cli = b.addExecutable(.{
|
|
22
|
+
.name = "rufio_search",
|
|
23
|
+
.root_module = b.createModule(.{
|
|
24
|
+
.root_source_file = b.path("src/cli.zig"),
|
|
25
|
+
.target = target,
|
|
26
|
+
.optimize = optimize,
|
|
27
|
+
.link_libc = true,
|
|
28
|
+
}),
|
|
29
|
+
});
|
|
30
|
+
b.installArtifact(cli);
|
|
31
|
+
|
|
32
|
+
const tests = b.addTest(.{
|
|
33
|
+
.root_module = b.createModule(.{
|
|
34
|
+
.root_source_file = b.path("src/search_test.zig"),
|
|
35
|
+
.target = target,
|
|
36
|
+
.optimize = optimize,
|
|
37
|
+
.link_libc = true,
|
|
38
|
+
}),
|
|
39
|
+
});
|
|
40
|
+
const test_step = b.step("test", "検索エンジンの単体テストを実行");
|
|
41
|
+
test_step.dependOn(&b.addRunArtifact(tests).step);
|
|
45
42
|
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
//! ripgrep と同条件で比較するためのベンチマーク用 CLI。
|
|
2
|
+
//! 使い方: rufio_search [-j N] [-r N] QUERY DIR...
|
|
3
|
+
//! -r N: キャッシュを使って同じ検索を N 回繰り返し、各回の所要時間を標準エラーに出す(G mode の再検索を再現)
|
|
4
|
+
//! 出力は rg -n と同じ `path:line:text` 形式(text はマッチ周辺の最大 1KB)。
|
|
5
|
+
const std = @import("std");
|
|
6
|
+
const c = std.c;
|
|
7
|
+
const search = @import("search.zig");
|
|
8
|
+
const os = @import("os.zig");
|
|
9
|
+
|
|
10
|
+
fn writeAll(bytes: []const u8) void {
|
|
11
|
+
os.writeAll(1, bytes);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
pub fn main(init: std.process.Init.Minimal) !void {
|
|
15
|
+
var args = try init.args.iterateAllocator(std.heap.c_allocator);
|
|
16
|
+
defer args.deinit();
|
|
17
|
+
_ = args.skip();
|
|
18
|
+
var threads: usize = 0;
|
|
19
|
+
var repeat: usize = 0;
|
|
20
|
+
var query: ?[]const u8 = null;
|
|
21
|
+
var roots: std.ArrayList(u8) = .empty;
|
|
22
|
+
const alloc = std.heap.c_allocator;
|
|
23
|
+
defer roots.deinit(alloc);
|
|
24
|
+
|
|
25
|
+
while (args.next()) |arg| {
|
|
26
|
+
if (std.mem.eql(u8, arg, "-j")) {
|
|
27
|
+
threads = try std.fmt.parseInt(usize, args.next() orelse return error.MissingValue, 10);
|
|
28
|
+
} else if (std.mem.eql(u8, arg, "-r")) {
|
|
29
|
+
repeat = try std.fmt.parseInt(usize, args.next() orelse return error.MissingValue, 10);
|
|
30
|
+
} else if (query == null) {
|
|
31
|
+
query = arg;
|
|
32
|
+
} else {
|
|
33
|
+
if (roots.items.len > 0) try roots.append(alloc, 0);
|
|
34
|
+
try roots.appendSlice(alloc, std.mem.trimEnd(u8, arg, "/"));
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
const q = query orelse {
|
|
38
|
+
writeAll("usage: rufio_search [-j N] [-r N] QUERY DIR...\n");
|
|
39
|
+
return;
|
|
40
|
+
};
|
|
41
|
+
if (roots.items.len == 0) try roots.append(alloc, '.');
|
|
42
|
+
|
|
43
|
+
if (repeat > 0) {
|
|
44
|
+
const cache = try search.Cache.create(256 * 1024 * 1024);
|
|
45
|
+
defer cache.destroy();
|
|
46
|
+
var i: usize = 0;
|
|
47
|
+
while (i < repeat) : (i += 1) {
|
|
48
|
+
const t0 = os.nowNs();
|
|
49
|
+
const lines = try runSearch(roots.items, q, threads, cache, i + 1 == repeat);
|
|
50
|
+
const ms = @as(f64, @floatFromInt(os.nowNs() - t0)) / 1e6;
|
|
51
|
+
var msg: [128]u8 = undefined;
|
|
52
|
+
os.writeAll(2, try std.fmt.bufPrint(&msg, "run {d}: {d:.1} ms, {d} lines, cache {d} MB\n", .{ i + 1, ms, lines, cache.cachedBytes() >> 20 }));
|
|
53
|
+
}
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
_ = try runSearch(roots.items, q, threads, null, true);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
fn runSearch(roots: []const u8, q: []const u8, threads: usize, cache: ?*search.Cache, print: bool) !usize {
|
|
60
|
+
const alloc = std.heap.c_allocator;
|
|
61
|
+
const s = try search.Search.create(roots, q, "", "", threads, cache);
|
|
62
|
+
defer s.destroy();
|
|
63
|
+
|
|
64
|
+
var lines: usize = 0;
|
|
65
|
+
var out: std.ArrayList(u8) = .empty;
|
|
66
|
+
defer out.deinit(alloc);
|
|
67
|
+
var line_buf: [24]u8 = undefined;
|
|
68
|
+
while (true) {
|
|
69
|
+
const state = s.getState();
|
|
70
|
+
const data = s.drain();
|
|
71
|
+
var pos: usize = 0;
|
|
72
|
+
while (pos + search.RECORD_HEADER <= data.len) {
|
|
73
|
+
const kind = data[pos];
|
|
74
|
+
const line = std.mem.readInt(u64, data[pos + 5 ..][0..8], .little);
|
|
75
|
+
const a_len = std.mem.readInt(u32, data[pos + 17 ..][0..4], .little);
|
|
76
|
+
const b_len = std.mem.readInt(u32, data[pos + 21 ..][0..4], .little);
|
|
77
|
+
const a = data[pos + search.RECORD_HEADER ..][0..a_len];
|
|
78
|
+
const b = data[pos + search.RECORD_HEADER + a_len ..][0..b_len];
|
|
79
|
+
pos += search.RECORD_HEADER + a_len + b_len;
|
|
80
|
+
if (kind != @intFromEnum(search.Kind.match)) continue;
|
|
81
|
+
lines += 1;
|
|
82
|
+
if (!print) continue;
|
|
83
|
+
try out.appendSlice(alloc, a);
|
|
84
|
+
try out.appendSlice(alloc, try std.fmt.bufPrint(&line_buf, ":{d}:", .{line}));
|
|
85
|
+
try out.appendSlice(alloc, std.mem.trimEnd(u8, b, "\r\n"));
|
|
86
|
+
try out.append(alloc, '\n');
|
|
87
|
+
}
|
|
88
|
+
if (out.items.len >= 1 << 16) {
|
|
89
|
+
writeAll(out.items);
|
|
90
|
+
out.clearRetainingCapacity();
|
|
91
|
+
}
|
|
92
|
+
if (data.len == 0) {
|
|
93
|
+
if (state != .scanning) break;
|
|
94
|
+
os.sleepMicros(50);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
writeAll(out.items);
|
|
98
|
+
return lines;
|
|
99
|
+
}
|