Skip to content
Back to skills

line-locator

ASecurity

Định vị dòng trước khi đọc file hoặc tìm file trong cây thư mục — tránh đọc mù, tiết kiệm token. Dùng khi cần tìm hàm, class, symbol, hoặc bất kỳ pattern nào trong source code trước khi gọi view_range. Hai công cụ: findtree.py (tìm file nào có chứa pattern) và findtool.py (tìm dòng nào trong một file).

  • 7 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added May 26, 2026
ai-agentspythonrustgojavarubyc++c#shellbashsql

Works with

  • api

Security analysis

A100/100

Pro scans all 6 files and shows the line behind each finding

Scanned May 27, 2026

npx -y skills add unkluco/line-locator --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of line-locator?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for line-locator
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/unkluco-line-locator/badge)](https://www.skillsdirectory.com/skills/unkluco-line-locator)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: line-locator
description: >
  Định vị dòng trước khi đọc file hoặc tìm file trong cây thư mục — tránh đọc mù, tiết kiệm token. Dùng khi cần tìm hàm, class, symbol, hoặc bất kỳ pattern nào trong source code trước khi gọi view_range. Hai công cụ: findtree.py (tìm file nào có chứa pattern) và findtool.py (tìm dòng nào trong một file).
author: Kluco
github: unkluco
email: huylet334@gmail.com
version: 1.1.1
---

# Line-Locator

Hai script phối hợp để định vị chính xác trước khi đọc:

| Script | Phạm vi | Câu hỏi trả lời |
|---|---|---|
| `findtree.py` | Cả cây thư mục | *File nào* chứa pattern này? |
| `findtool.py` | Một file duy nhất | *Dòng nào* trong file này? |

**Workflow:**
```
findtree.py (shortlist files) → findtool.py (locate lines) → view_range (read)
```

Script nằm tại: `skills/line-locator/scripts/`

---

## Output contract

**Tất cả pattern dùng Python regex.**

**findtool — success (stdout):**
```json
{"matches": {"processOrder": [247, 312]}}
{"line": 248}
{"matched": true}
```

**findtree — success (stdout):**
```json
{"matched_files": ["src/order.js", "tests/order.test.js"]}
```

**Failure — cả hai tool (stderr, exit 1):**
```json
{"ok": false, "error": "No line matching pattern 'foo' was found after line 0."}
```

**Parse nhanh:**
```python
import json, subprocess
out = subprocess.check_output([...])
data = json.loads(out)

# findtool
lines   = data["matches"]["pat"]   # -mr  → list[int]
line    = data["line"]             # -n / -b / -c / -o → int
matched = data["matched"]          # -e   → bool

# findtree
files   = data["matched_files"]    # list[str] relative paths
```

---

## findtree — tìm file

```bash
python findtree.py --root ROOT --pattern PAT [options]
```

| Option | Mặc định | Mô tả |
|---|---|---|
| `--root` | *(required)* | Thư mục gốc |
| `--pattern` | *(required)* | Regex pattern |
| `--include GLOB...` | *(tất cả)* | Chỉ tìm file khớp glob |
| `--exclude GLOB...` | *(không)* | Bỏ qua file/thư mục khớp glob |
| `--ignore-case` | off | Case-insensitive |
| `--max-results N` | *(không giới hạn)* | Dừng sau N file |
| `--show` | `matched` | `matched` / `errors` / `both` / `summary` / `all` |
| `--max-file-size` | *(không)* | Bỏ qua file lớn hơn (VD: `64K`, `10M`) |
| `--no-default-dir-excludes` | off | Tắt auto-skip `.git`, `node_modules`, v.v. |
| `--text` | off | Output text thay vì JSON |

**Auto-excluded dirs:** `.git`, `.hg`, `node_modules`, `venv`, `.venv`, `__pycache__`, `dist`, `build`, `target`, `.mypy_cache`, `.pytest_cache`, `.tox`, `coverage`

```bash
python findtree.py --root ./src --pattern "processOrder"
python findtree.py --root ./src --pattern "class\s+\w+Service"
python findtree.py --root . --pattern "TODO" --include "*.ts" "*.js" --exclude "dist/**"
python findtree.py --root . --pattern "deprecated_api" --max-results 1
```

---

## findtool — tìm dòng

```bash
python findtool.py --file FILE [--ignore-case] [-s] FLAG... [--text]
```

| Flag | Args | Mô tả | `result` key |
|---|---|---|---|
| `-mr` | `PAT [PAT ...]` | Tất cả dòng khớp một hoặc nhiều pattern | `{"matches": {"pat": [1,5]}}` |
| `-n` | `PAT LINE` | Dòng đầu tiên khớp **sau** LINE (0 = từ đầu file) | `{"line": 45}` |
| `-b` | `PAT LINE` | Dòng cuối cùng khớp **trước** LINE (999999 = cuối file) | `{"line": 12}` |
| `-e` | `PAT` | File có chứa pattern không? | `{"matched": true}` |
| `-c` | `OPEN CLOSE LINE N` | Dòng đóng khớp với OPEN thứ N trên LINE (scan xuôi) | `{"line": 89}` |
| `-o` | `OPEN CLOSE LINE N` | Dòng mở khớp với CLOSE thứ N trên LINE (scan ngược) | `{"line": 34}` |

Flag `-s` (chỉ dùng với `-c`/`-o`): bỏ qua nội dung string và comment khi đếm depth.

```bash
python findtool.py --file app.js -mr "processOrder"
python findtool.py --file app.js -mr "processOrder" "cancelOrder" "getUser"
python findtool.py --file app.js -n "function\s+\w+" 0
python findtool.py --file app.js -b "^import\s" 999999
python findtool.py --file app.js -e "TODO"
python findtool.py --file app.js -c "\{" "\}" 248 1
python findtool.py --file app.js -c "\{" "\}" 248 1 -s
python findtool.py --file app.js -o "\{" "\}" 298 1
```

---

## Pair matching (-c / -o)

Cả hai flag đều nhận `OPEN CLOSE LINE N` theo cùng thứ tự:

```
-c  OPEN  CLOSE  LINE  N  →  anchor tại OPEN thứ N trên LINE, scan xuôi  → trả về dòng CLOSE
-o  OPEN  CLOSE  LINE  N  →  anchor tại CLOSE thứ N trên LINE, scan ngược → trả về dòng OPEN
```

**Algorithm:** depth-tracking. Mỗi dòng tiếp theo: `depth += count(OPEN) - count(CLOSE)`. Khi `depth == 0` → trả về dòng đó.

**Flag `-s`:** trước khi đếm, mask toàn bộ string literals và comments (`//`, `#`, `/* */`, `'...'`, `"..."`, backtick, triple-quote). Dùng khi file có nhiều delimiter trong string/comment.

### Pairs phổ biến theo ngôn ngữ

| Ngôn ngữ | Block mở | Block đóng | Ghi chú |
|---|---|---|---|
| JS/TS/Java/Go/Rust/C/C++/C# | `\{` | `\}` | Dùng `-s` nếu file có `{` trong string |
| Bất kỳ — argument list | `\(` | `\)` | Áp dụng mọi ngôn ngữ |
| Bất kỳ — array/list | `\[` | `\]` | Áp dụng mọi ngôn ngữ |
| HTML/XML | `<div\b[^>]*>` | `</div>` | Thay `div` bằng tên tag |
| Ruby | `\bdo\b` | `\bend\b` | Hoặc `\bdef\b` / `\bend\b` |
| Lua / Pascal-like | `\bdo\b` | `\bend\b` | |
| Shell (bash) | `\bthen\b\|\bdo\b` | `\bfi\b\|\bdone\b` | Phức tạp hơn |
| Python | *(không có bracket)* | *(xem note bên dưới)* | Dùng `-n` tìm def tiếp theo |

> **Python note:** Python dùng indentation thay vì `{}`. Để tìm cuối hàm, dùng `-n "^(def\|class)\s" FUNC_LINE` tìm `def`/`class` tiếp theo cùng cấp, hoặc đọc từ `FUNC_LINE` đến dòng trước đó. Với argument list nhiều dòng: `-c "\(" "\)" FUNC_LINE 1` vẫn hoạt động.

```bash
# JS/TS function
python findtool.py --file service.ts -c "\{" "\}" 248 1 -s
# → {"line": 298}

# HTML div
python findtool.py --file index.html -c "<div\b[^>]*>" "</div>" 10 1
# → {"line": 25}

# Ruby method
python findtool.py --file user.rb -c "\bdef\b" "\bend\b" 42 1
# → {"line": 67}

# Argument list dài nhiều dòng (mọi ngôn ngữ)
python findtool.py --file builder.java -c "\(" "\)" 120 1
# → {"line": 128}

# -o: đang ở dòng }, tìm dòng {
python findtool.py --file app.go -o "\{" "\}" 298 1
# → {"line": 248}
```

---

## Workflows

### 1. Đọc một hàm đã biết tên

```bash
# Bước 1: Tìm dòng định nghĩa
python findtool.py --file app.js -mr "processOrder"
# → {"matches": {"processOrder": [247, 312]}}  → 247 là định nghĩa

# Bước 2: Tìm dòng OPEN thực sự (KHÔNG đoán cùng dòng hay dòng dưới)
python findtool.py --file app.js -n "\{" 247
# → {"line": 248}

# Bước 3: Tìm dòng đóng
python findtool.py --file app.js -c "\{" "\}" 248 1
# → {"line": 298}

# Bước 4: Đọc
view_range [247, 298]
```

### 2. Từ repository lạ → đọc hàm

```bash
python findtree.py --root ./src --pattern "processOrder"
# → {"matched_files": ["services/order.js"]}

python findtool.py --file services/order.js -mr "processOrder"
# → tiếp tục Workflow 1
```

### 3. Scan cấu trúc tổng thể file

```bash
# JS/TS/Java/Go/C#
python findtool.py --file service.ts -mr "class\s+\w+" "function\s+\w+" "\bexport\b"

# Python
python findtool.py --file service.py -mr "^class\s+\w+" "^def\s+\w+" "^    def\s+\w+"

# Ruby
python findtool.py --file user.rb -mr "^\s*def\s+\w+" "^\s*class\s+\w+"

# Java/C#
python findtool.py --file Service.java -mr "public\s+\w" "private\s+\w" "protected\s+\w"
```

### 4. Tìm nhiều symbol cùng lúc

```bash
python findtool.py --file app.js -mr "processOrder" "cancelOrder" "getUser"
# → {"matches": {"processOrder": [247], "cancelOrder": [312], "getUser": [89]}}
# Lên kế hoạch đọc toàn bộ từ một lần call
```

### 5. Đọc tất cả imports

```bash
# JS/TS
python findtool.py --file app.ts -mr "^import\s"
# → {"matches": {"^import\\s": [1,2,3,14,15]}} → view_range [1, 15]

# Python
python findtool.py --file app.py -mr "^import\s" "^from\s"

# Java/C#
python findtool.py --file App.java -mr "^import\s" "^using\s"

# Go
python findtool.py --file main.go -mr "^\s*\"" 
# (lines inside import block — hoặc tìm block import trước)
```

### 6. Xác định dòng đang thuộc scope nào (ngôn ngữ có `{}`)

```bash
python findtool.py --file dao.js -b "\{" X    # → OPEN_LINE
python findtool.py --file dao.js -c "\{" "\}" OPEN_LINE 1  # verify X trong scope này
view_range [OPEN_LINE - 1, OPEN_LINE]         # đọc tên scope
```

### 7. Leo scope chain

```bash
python findtool.py --file app.js -b "\{" 245  →  198
python findtool.py --file app.js -b "\{" 198  →  134
python findtool.py --file app.js -b "\{" 134  →  12
python findtool.py --file app.js -b "\{" 12   →  error → top-level
```

### 8. Tìm decorator / annotation

```bash
# Python decorator
python findtool.py --file routes.py -b "@\w+" FUNC_LINE
# → nếu kết quả >= FUNC_LINE - 3 → có decorator trực tiếp

# Java/C# annotation
python findtool.py --file Controller.java -b "@\w+" FUNC_LINE

# JS/TS decorator
python findtool.py --file service.ts -b "@\w+" FUNC_LINE
```

### 9. Tìm else / catch / finally

```bash
python findtool.py --file handler.js -c "\{" "\}" IF_LINE 1  # → close of if-block
python findtool.py --file handler.js -n "else|catch|finally" CLOSE_LINE
# → nếu ngay sau CLOSE_LINE → đây là else/catch của block đó
```

---

## ⚠️ Sai lầm phổ biến

### 1. Gọi `-c` trên dòng function name thay vì dòng `{`

```bash
# ❌ SAI — dòng 247 có tên hàm nhưng chưa chắc có {
python findtool.py --file app.js -c "\{" "\}" 247 1
# → error: "Line 247 contains only 0 occurrence(s) of open pattern '\{'"

# ✅ ĐÚNG — tìm dòng { trước, rồi mới -c
python findtool.py --file app.js -n "\{" 247   # → {"line": 248}
python findtool.py --file app.js -c "\{" "\}" 248 1
```

Lý do: Trong nhiều ngôn ngữ, `{` có thể ở dòng tiếp theo sau tên hàm (Allman style). **Không bao giờ đoán.**

---

### 2. Nhầm lẫn kết quả đầu tiên của `-mr` là định nghĩa

```bash
python findtool.py --file app.js -mr "processOrder"
# → {"matches": {"processOrder": [89, 247, 312]}}
#   89  = call site hoặc comment
#   247 = định nghĩa hàm (def/function)
#   312 = call site khác
```

Số nhỏ nhất chưa chắc là định nghĩa. Đọc thêm vài dòng context để xác nhận, hoặc dùng pattern cụ thể hơn:

```bash
python findtool.py --file app.js -mr "function processOrder" "processOrder\s*\("
# → pattern cụ thể hơn → ít kết quả giả hơn
```

---

### 3. Pattern có ký tự đặc biệt không escape

```bash
# ❌ SAI — regex error vì ( không được escape
python findtool.py --file app.py -mr "foo(bar)"
# → {"ok": false, "error": "Invalid regex pattern 'foo(bar)': missing ), ..."}

# ✅ ĐÚNG
python findtool.py --file app.py -mr "foo\(bar\)"
# hoặc dùng word boundary thay vì match toàn bộ call:
python findtool.py --file app.py -mr "foo"
```

Ký tự cần escape trong regex: `. ^ $ * + ? { } [ ] \ | ( )`

---

### 4. Dùng Python `{}` để match scope hàm

Python không dùng `{}` cho function/class body. Dùng `-c "\{" "\}"` sẽ chỉ match dict/set literals.

```bash
# ❌ Không có tác dụng cho Python function body
python findtool.py --file service.py -c "\{" "\}" 42 1

# ✅ Python: tìm def/class tiếp theo cùng level
python findtool.py --file service.py -n "^def \|^class " 42
# → dòng tiếp theo ở cùng indent level = kết thúc hàm hiện tại

# ✅ Python method trong class:
python findtool.py --file service.py -n "^    def " 42
```

---

### 5. Quên rằng `-n` là **sau** LINE, không phải **tại** LINE

```bash
python findtool.py --file app.js -n "def " 247
# → Tìm match STRICTLY AFTER dòng 247, không phải tại 247
# Nếu def ở dòng 247 → sẽ không được trả về

# Để bao gồm chính dòng đó:
python findtool.py --file app.js -n "def " 246  # tìm sau dòng 246
```

---

### 6. Bỏ qua `-s` khi file có nhiều `{` trong string/comment

```bash
# File có: const tmpl = `SELECT * FROM t WHERE col = '{value}'`
# ❌ Không -s: depth tracking đếm sai vì { trong template string
python findtool.py --file query.ts -c "\{" "\}" 50 1
# → kết quả sai

# ✅ Dùng -s để bỏ qua string/comment
python findtool.py --file query.ts -c "\{" "\}" 50 1 -s
```

Nên dùng `-s` khi: file là template (`.html`, `.ejs`, `.hbs`), SQL inline, hoặc bất kỳ file nào có nhiều `{` không phải code.

---

### 7. Dùng findtool trực tiếp mà không biết file ở đâu

```bash
# ❌ Tốn thời gian — không biết file nào
python findtool.py --file src/auth/service.js -mr "validateToken"
# → File not found

# ✅ findtree trước
python findtree.py --root ./src --pattern "validateToken"
# → {"matched_files": ["src/auth/service.js"]}
```

---

### 8. Không biết ngôn ngữ dùng `{` hay không → kiểm tra trước

Trước khi dùng `-c "\{" "\}"`, xác nhận file có `{` không:
```bash
python findtool.py --file service.py -e "\{"
# → {"matched": false} → Python file, không có {-based scope
# → {"matched": true}  → file có {, tiến hành bình thường
```

### 9. Dùng `\|` thay vì `|` cho alternation trong Python regex

```bash
# ❌ SAI — \| trong Python regex là ký tự pipe literal, không phải alternation
python findtool.py --file app.java -mr "focusLost\|hidePopup\|showPopup"
# → {"matches": {"focusLost\\|hidePopup\\|showPopup": []}}  ← tìm chuỗi literal   "focusLost|hidePopup|showPopup"

# ✅ ĐÚNG — | không cần escape trong Python regex
python findtool.py --file app.java -mr "focusLost|hidePopup|showPopup"
# → {"matches": {"focusLost|hidePopup|showPopup": [192, 723, 701]}}

Lý do nhầm: grep basic mode (BRE) dùng \| cho alternation. Python dùng ERE-style — | đã là   alternation, \| là literal pipe.

Khi nào \| hợp lệ: không bao giờ trong Python regex nếu mục đích là alternation.
```

---

## Bảng quyết định nhanh

| Tình huống | Dùng gì |
|---|---|
| Chưa biết file nào | `findtree --root ... --pattern ...` |
| Biết tên hàm, muốn đọc body (ngôn ngữ có `{}`) | `-mr "name"` → `-n "\{" LINE` → `-c "\{" "\}" OPEN 1` |
| Ngôn ngữ không có `{}` (Python...) | `-mr "name"` → `-n "^def\|^class" LINE` |
| Nhiều hàm cùng lúc | `-mr "fn1" "fn2" "fn3"` |
| Pattern có ký tự đặc biệt | escape: `\(`, `\)`, `\{`, `\.`, v.v. |
| File có nhiều `{` trong string | thêm `-s` vào `-c`/`-o` |
| Duyệt từng hàm không biết tên | `-mr "\{"` → `-c "\{" "\}"` → `-n "\{"` → lặp |
| Ở dòng X, muốn biết thuộc hàm nào | `-b "\{" X` → `-c "\{" "\}" OPEN 1` verify |
| Đọc hết imports | `-mr "^import\s"` → min/max → `view_range` |
| Argument list nhiều dòng | `-c "\(" "\)" LINE 1` |
| Tìm else/catch/finally | `-c "\{" "\}" IF_LINE 1` → `-n "else\|catch\|finally"` |
| Có decorator/annotation không? | `-b "@\w+" FUNC_LINE` → check khoảng cách |
| HTML tag pair | `-c "<tag\b[^>]*>" "</tag>" LINE 1` |
| Ruby/Lua method body | `-c "\bdef\b" "\bend\b" LINE 1` |
| Scope ngoài cùng | `-b "\{"` lặp đến error |
| File có chứa pattern không? | `-e "pattern"` |
| Chỉ tìm trong file .ts .js | findtree `--include "*.ts" "*.js"` |
| Dừng sớm khi tìm đủ | findtree `--max-results 1` |

---

## Xử lý lỗi

| Lỗi | Nguyên nhân | Cách xử lý |
|---|---|---|
| `"For -n, LINE must be >= 0"` | Truyền số âm vào `-n` | Dùng 0 để tìm từ đầu file |
| `"For -b, LINE must be >= 1"` | Truyền 0 vào `-b` | Dùng 999999 để tìm từ cuối file |
| `"Line X contains only 0 occurrence(s) of open pattern"` | `{` không ở dòng đó | Dùng `-n "\{" FUNC_LINE` để tìm dòng `{` thực tế |
| `"No closing match for open pattern"` | Không tìm thấy CLOSE trong file | File chưa đóng bracket, hoặc dùng thêm `-s` |
| `"No line matching pattern ... was found"` | Pattern không khớp trong phạm vi | Kiểm tra lại regex; với `-b` có thể tăng LINE |
| `"Invalid regex pattern"` | Regex sai cú pháp | Escape: `\(`, `\)`, `\{`, `\.` |
| `"Root directory not found"` | `--root` không tồn tại | Kiểm tra lại đường dẫn |
| `"N must be >= 1"` | N = 0 trong `-c`/`-o` | N bắt đầu từ 1 |

---

## Ví dụ end-to-end

**Bài toán:** Đọc hàm `validateToken` trong codebase 50 file, không biết nó nằm ở đâu.

```bash
# 1. Tìm file
python findtree.py --root ./src --pattern "validateToken"
# → {"matched_files": ["auth/service.ts"]}

# 2. Tìm dòng định nghĩa
python findtool.py --file auth/service.ts -mr "validateToken"
# → {"matches": {"validateToken": [312, 467]}}  → 312 là định nghĩa

# 3. Kiểm tra decorator
python findtool.py --file auth/service.ts -b "@\w+" 312
# → {"line": 310}  → có decorator ở dòng 310

# 4. Tìm dòng {
python findtool.py --file auth/service.ts -n "\{" 312
# → {"line": 313}

# 5. Tìm dòng đóng (dùng -s vì file TS hay có template string)
python findtool.py --file auth/service.ts -c "\{" "\}" 313 1 -s
# → {"line": 389}

# 6. Đọc
view_range [310, 389]
```

**Token tiêu thụ:** ~80 dòng thay vì hàng nghìn. Tiết kiệm >90%.

Files in this skill

  • SKILL.md17.4 KB
  • assets/banner.png67.6 KB
  • assets/benchmark_chart.svg22.8 KB
  • assets/workflow.png66.2 KB
  • scripts/findtool.py16.4 KB
  • scripts/findtree.py15.8 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.