mirror of
https://github.com/rizonesoft/Notepad3.git
synced 2026-06-23 21:01:01 +08:00
Merge pull request #5885 from RaiKoHoff/dev_master
feat: open file/folder from selection + bare-path hyperlink hotspots
This commit is contained in:
commit
2b546fca90
@ -162,6 +162,12 @@ User-facing description of every entry in Notepad3's menus and context menus, st
|
||||
|
||||
📋 **Menu reference:** [readme/MenuEntriesAndCmds.md](readme/MenuEntriesAndCmds.md)
|
||||
|
||||
## File-Path Handling
|
||||
|
||||
How Notepad3 turns clickable links, selected text, and path-shaped tokens into real files — including bare paths with line specs (`file.c:42`, `file.c(42)`), `file:///` URLs, relative-path anchor rules (current document's directory → working directory), environment-variable expansion, and the two new selection commands **Open Containing Folder of Selection** / **Open File from Selection**.
|
||||
|
||||
🗂️ **File-path reference:** [readme/paths/FilePathHandling.md](readme/paths/FilePathHandling.md)
|
||||
|
||||
## Keyboard Shortcuts
|
||||
|
||||
Every key combination Notepad3 understands — file, editing, view, search, customization — grouped by menu, with Notepad2 → Notepad3 reassignments flagged.
|
||||
|
||||
@ -1,226 +0,0 @@
|
||||
# Plan — Follow-up enhancements: file/path reference handling
|
||||
|
||||
Companion to the now-shipped change that added `IDM_EDIT_OPEN_CONTAINING_FOLDER_SEL` / `IDM_EDIT_OPEN_FILE_FROM_SEL` and fixed the `Paths.ModuleDirectory` anchor bug in the hyperlink-click handler.
|
||||
|
||||
These items were intentionally deferred from that change to keep the scope tight. They are independent of each other; pick any subset.
|
||||
|
||||
## Status (2026-05-16)
|
||||
|
||||
Already shipped on `dev_master`:
|
||||
- New selection-based commands `IDM_EDIT_OPEN_CONTAINING_FOLDER_SEL` (40395) and `IDM_EDIT_OPEN_FILE_FROM_SEL` (40396), wired to Edit > Miscellaneous and the editor right-click popup. No accelerator — users can bind one via custom keybindings if desired.
|
||||
- Shared helpers in `src\Helpers.c`: `ExtractSelectionOrTokenAtCaret`, `SplitFilePathLineColNum`, `ResolveSelectionToPath`.
|
||||
- Bug fix at `src\Notepad3.c:8891` (or thereabouts after later edits) — relative `file:///` URLs now anchor to the current document's directory, fallback `Paths.WorkingDirectory`, never `Paths.ModuleDirectory`.
|
||||
- English placeholder strings replicated across all 25 sibling locale `menu_*.rc` files. Translators still need to translate them.
|
||||
|
||||
Function bodies for the two new commands live in `src\Notepad3.c` (not Edit.c) because `<shlobj.h>` defines `SORT_ASCENDING` / `SORT_DESCENDING` enum values that conflict with Edit.c's `SortOrderMask` enum.
|
||||
|
||||
## Item 1 — Bare-path hotspotting (`HYPLNK_REGEX_FULL` extension)
|
||||
|
||||
**Goal**: make `C:\Users\me\foo.txt`, `\\server\share\file`, `.\rel\path.c`, `../include/foo.h`, and similar bare paths clickable hotspots in the editor, just like `https://...` URLs already are.
|
||||
|
||||
### Why this is deferred and load-bearing
|
||||
|
||||
The existing hyperlink hotspot system (`src\Edit.c:111-116`) uses one big PCRE2 regex that requires an explicit scheme prefix:
|
||||
```c
|
||||
#define HYPLNK_REGEX_FULL "\\b(?:(?:https?|ftp)://|file:///|file://|mailto:|www\\.|ftp\\.)" ...
|
||||
```
|
||||
Adding bare-path matching is high-risk because:
|
||||
1. **False positives** — `C:` could match in non-path text (e.g. a code snippet, a colon-time `12:34:56`).
|
||||
2. **Indicator-marking pass cost** — the URL hotspotter runs on every restyle (`MarkAllOccurrences` flow). A broader regex adds CPU per keystroke in large documents.
|
||||
3. **Lexer interference** — many lexers already style strings/paths in domain-specific ways. Adding `INDIC_NP3_HYPERLINK` on top of an existing lexer style can cause visual conflicts (double-underlining, color clash).
|
||||
4. **`SCN_INDICATORRELEASE` activation** — currently `HandleHotSpotURLClicked` at `src\Notepad3.c:8824` is dispatched on indicator-release. It calls `UrlIsFileUrl(szTextW)` to decide between OPEN_IN_NOTEPAD3 and OPEN_WITH_BROWSER. Bare paths aren't file:// URLs, so the routing logic needs a new branch: "if it looks like a Windows path, treat it as OPEN_IN_NOTEPAD3 directly."
|
||||
|
||||
### Implementation sketch
|
||||
|
||||
Two viable approaches:
|
||||
|
||||
**A. Single bigger regex.** Add an alternation arm for paths. E.g.:
|
||||
```
|
||||
\\b(?:[A-Za-z]:[\\\\/]|\\\\\\\\[^\\s]+\\\\|\\.{1,2}[\\\\/])[^\\s'`"<>|*,;]+
|
||||
```
|
||||
- Drive-letter: `C:\...`, `c:/...`
|
||||
- UNC: `\\server\share\...`
|
||||
- Relative: `.\foo`, `..\foo`, `./foo`, `../foo`
|
||||
|
||||
Pros: minimal code change. Cons: regex becomes harder to maintain; false-positive risk is concentrated.
|
||||
|
||||
**B. Second-pass detection.** Keep `HYPLNK_REGEX_FULL` for scheme URLs. Add a separate, more restrictive pass for bare paths only when the line context suggests "this is a path" — e.g. preceded by `at`, `file:`, `> `, in compiler-error format `file.c:42:`, etc. More conservative; harder to author.
|
||||
|
||||
**Recommendation**: try (A) but gate behind a `Settings2.HyperlinkBarePaths` opt-in toggle defaulting to `false`. Document the toggle in `Build\Notepad3.ini` `[Settings2]` and `readme/config/Configuration.md` (CLAUDE.md invariant).
|
||||
|
||||
### Required touchpoints
|
||||
|
||||
| File | Change |
|
||||
|---|---|
|
||||
| `src\Edit.c:111-116` | Extend `HYPLNK_REGEX_FULL` (or add `HYPLNK_REGEX_BAREPATH` and run both) |
|
||||
| `src\Notepad3.c:8824` (`HandleHotSpotURLClicked`) | New branch when `!UrlIsFileUrl(szTextW)` AND text looks like a Windows path → call same OPEN_IN_NOTEPAD3 logic but skip `PathCreateFromUrlW` (use the text as-is, then `ResolveSelectionToPath`-style anchoring) |
|
||||
| `src\TypeDefs.h` (`Settings2`) | Add `HyperlinkBarePaths` bool with default `false` |
|
||||
| `src\Config\Config.cpp` | Persist `HyperlinkBarePaths` |
|
||||
| `Build\Notepad3.ini`, `readme\config\Configuration.md` | Document new INI key |
|
||||
|
||||
### Verification
|
||||
|
||||
- Open a fresh `.txt` buffer with toggle ON. Paste:
|
||||
```
|
||||
C:\Windows\notepad.exe
|
||||
..\src\Helpers.c
|
||||
\\?\C:\Windows
|
||||
src/Edit.c:111
|
||||
See line C: this should NOT highlight
|
||||
Time 12:34:56 must NOT highlight
|
||||
```
|
||||
Expect: lines 1-4 hotspotted, lines 5-6 not.
|
||||
- With toggle OFF: no change vs. current behavior.
|
||||
- Test in C/C++ buffer (SCLEX_CPP) to confirm no lexer-style clash on strings containing paths.
|
||||
|
||||
## Item 2 — Markdown `[label](url)` extraction in `ExtractSelectionOrTokenAtCaret`
|
||||
|
||||
**Goal**: when the caret is inside the URL portion of a Markdown link `[label](url)`, the selection extractor should grab `url` rather than expanding outward through the closing `)` and stopping at the next whitespace.
|
||||
|
||||
### Why this is deferred
|
||||
|
||||
The current `ExtractSelectionOrTokenAtCaret` in `src\Helpers.c` uses a flat boundary set `[\s'`"<>|*,;]` and never considers paired-delimiter context. Notepad4's `EditGetStringAroundCaret` (`notepad4\src\Edit.cpp:7015-7093`) has a dedicated subroutine to recognize `(...)` after a Markdown link target and clamp the extraction.
|
||||
|
||||
It's deferred because: (a) Notepad3 already hotspots Markdown URLs via the lexer-driven indicator path, so most Markdown click flows already work; (b) the extractor is used by the new selection commands, where the user can always select the URL by hand if the auto-expand is wrong.
|
||||
|
||||
### Sketch
|
||||
|
||||
Inside `ExtractSelectionOrTokenAtCaret` in `src\Helpers.c`, when the selection is empty, BEFORE the regular boundary scan:
|
||||
|
||||
```c
|
||||
// Markdown link target: if caret sits inside `(...)` and the char before '(' is ']',
|
||||
// clamp the extraction to the contents of the parens.
|
||||
DocPos const posCur = SciCall_GetCurrentPos();
|
||||
// Walk back to find an unmatched '(' on the same line.
|
||||
// If found AND the char immediately before is ']', use [openParen+1, matching ')') as the span.
|
||||
```
|
||||
|
||||
Use Scintilla's bracket-matching (`SciCall_BraceMatch`) — but only on `(`; Scintilla supports `()` `[]` `{}` `<>`. Caveat: caret-on-`(` semantics vary; you may need to do a manual scan.
|
||||
|
||||
### Touchpoints
|
||||
|
||||
- `src\Helpers.c` — `ExtractSelectionOrTokenAtCaret` (introduced in the prior change).
|
||||
|
||||
### Verification
|
||||
|
||||
```markdown
|
||||
See [the doc](D:\projects\foo\readme.md) for details.
|
||||
^ caret here
|
||||
```
|
||||
Invoke "Open File from Selection" → opens `D:\projects\foo\readme.md`. Currently expands to `D:\projects\foo\readme.md)` and the trailing `)` may or may not be tolerated by `ResolveSelectionToPath`.
|
||||
|
||||
## Item 3 — Enable/disable gating in `MsgInitMenu` for the new commands
|
||||
|
||||
**Goal**: grey out `IDM_EDIT_OPEN_CONTAINING_FOLDER_SEL` / `IDM_EDIT_OPEN_FILE_FROM_SEL` when there's no selection AND no token at the caret position.
|
||||
|
||||
### Current behavior
|
||||
|
||||
The commands are always enabled. Invoking them with an empty selection on whitespace-only content silently produces a `MessageBeep(MB_ICONHAND)`. This matches Notepad4's UX and is acceptable, but a power user might prefer a greyed-out menu.
|
||||
|
||||
### Sketch
|
||||
|
||||
`MsgInitMenu()` in `src\Notepad3.c` should add (near the existing `IDM_EDIT_INSERT_GUID` enable check around line 4963):
|
||||
```c
|
||||
bool const bHasToken = !SciCall_IsSelectionEmpty();
|
||||
// optionally also check word boundaries at SciCall_GetCurrentPos()
|
||||
EnableCmd(hmenu, IDM_EDIT_OPEN_CONTAINING_FOLDER_SEL, bHasToken /* OR token-at-caret */);
|
||||
EnableCmd(hmenu, IDM_EDIT_OPEN_FILE_FROM_SEL, bHasToken);
|
||||
```
|
||||
|
||||
Right-click context menu builder at `src\Notepad3.c:4549` (`imenu == MNU_EDIT` branch) already has a similar pattern for the case-conversion commands using `s_iCtxMenuClickPos`. Add the same predicate there.
|
||||
|
||||
### Verification
|
||||
|
||||
- Empty selection, caret on whitespace → menu items greyed.
|
||||
- Empty selection, caret in a word → enabled.
|
||||
- Any non-empty selection → enabled.
|
||||
|
||||
## Item 4 — `\\?\` long-path prefix handling in `ResolveSelectionToPath`
|
||||
|
||||
**Goal**: gracefully handle paths with the Windows long-path prefix when passed to `SHParseDisplayName`.
|
||||
|
||||
### Why
|
||||
|
||||
`SHParseDisplayName` does not always accept `\\?\C:\...`. For shell-API consumption the prefix should be stripped. PathLib wrappers already handle this internally for filesystem ops, but `EditOpenContainingFolderFromSelection` calls `SHParseDisplayName` directly with `Path_Get(hpth)` which may include the prefix.
|
||||
|
||||
### Sketch
|
||||
|
||||
Inside `EditOpenContainingFolderFromSelection` in `src\Notepad3.c`, before `SHParseDisplayName`:
|
||||
```c
|
||||
LPCWSTR pth = Path_Get(hpth);
|
||||
if (StrCmpNW(pth, L"\\\\?\\", 4) == 0) {
|
||||
// Skip the prefix for shell-API use. If \\?\UNC\..., strip differently.
|
||||
if (StrCmpNW(pth + 4, L"UNC\\", 4) == 0) {
|
||||
// \\?\UNC\server\share → \\server\share
|
||||
WCHAR shellPath[MAX_PATH_EXPLICIT];
|
||||
StringCchPrintf(shellPath, COUNTOF(shellPath), L"\\\\%s", pth + 8);
|
||||
SHParseDisplayName(shellPath, ...);
|
||||
} else {
|
||||
SHParseDisplayName(pth + 4, ...);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Verification
|
||||
|
||||
- `\\?\C:\Windows` → opens `C:\Windows` in Explorer.
|
||||
- `\\?\UNC\server\share\file.txt` → opens `\\server\share\` with `file.txt` selected.
|
||||
|
||||
## Item 5 — `#fragment` parsing for `file://` URLs
|
||||
|
||||
**Goal**: a `file:///D:/docs/readme.md#section-2` URL clicked in Notepad3 should at minimum open the file (currently works) and ideally jump to the line with `#section-2` as a heading anchor.
|
||||
|
||||
### Why deferred
|
||||
|
||||
Markdown anchor resolution is out of scope for a text editor — the heading-anchor mapping is a Markdown-specific convention. The minimum useful behavior is to strip `#...` before resolving the path. Currently `PathCreateFromUrlW` may or may not strip it depending on Windows version.
|
||||
|
||||
### Sketch
|
||||
|
||||
In `HandleHotSpotURLClicked` at `src\Notepad3.c:8824`, after `PathCreateFromUrlW`:
|
||||
```c
|
||||
LPWSTR const hash = StrChr(szUnEscW, L'#');
|
||||
if (hash) {
|
||||
*hash = L'\0'; // discard fragment
|
||||
}
|
||||
```
|
||||
A future Markdown-aware extension could parse `#anchor-name`, scan the buffer for `## Anchor Name` (case-insensitive, dashes→spaces), and `SCI_GOTOLINE` there. Probably not worth the complexity.
|
||||
|
||||
### Verification
|
||||
|
||||
Click `file:///D:/test/foo.md#whatever` — opens `foo.md`. Don't error or attempt to interpret `#whatever`.
|
||||
|
||||
## Item 6 — Localize the new menu strings (translator task, not Claude's)
|
||||
|
||||
The 25 sibling locales currently have **English placeholder** strings for the two new menu items. Translators need to update:
|
||||
|
||||
- `language\np3_*\menu_*.rc` — replace `"Open &Containing Folder of Selection\tCtrl+Shift+,"` and `"Open &File from Selection"` (both in Edit > Miscellaneous AND in `IDR_MUI_POPUPMENU`).
|
||||
|
||||
This is normal translator workflow — not blocked, just pending.
|
||||
|
||||
### What Claude can do
|
||||
|
||||
Nothing without authoritative translations. If asked to "translate", refuse and ask the user to source translations from the locale maintainers listed in `language\np3_*\strings_*.rc` (`IDS_MUI_TRANSL_AUTHOR`).
|
||||
|
||||
## Item 7 — Tinyexpr behavior in `SplitFilePathLineColNum` `:N` fallback
|
||||
|
||||
`SplitFilePathLineColNum` falls back to `SplitFilePathLineNum` (which uses `te_interp`) for the single-colon case `foo.c:42`. This means `foo.c:42+1` would parse as line 43 — a side effect of using tinyexpr. Two existing callers depend on this:
|
||||
|
||||
- `src\Notepad3.c:8666` — `SplitFilePathLineNum(wchUrl, NULL)` — only cuts the suffix, discards the number.
|
||||
- `src\Notepad3.c:8879` — `SplitFilePathLineNum(szTextW, &lineNum)` — uses the parsed number.
|
||||
|
||||
If we ever want to drop the tinyexpr quirk: replace the wrapper with a plain `_wtoi` parse. Verify the two existing callers don't pass arithmetic.
|
||||
|
||||
## Touch-stones for any future session
|
||||
|
||||
- **CLAUDE.md** in repo root has all the build/encoding/localization invariants. Read it before touching `.rc` files.
|
||||
- **`.venv\Scripts\python.exe`** is required for bulk locale edits. Do NOT use sed/perl.
|
||||
- **`.rc` files** are UTF-8 *without* BOM, CRLF. Use `Build\rc_to_utf8.cmd` if a BOM sneaks in.
|
||||
- **Locale es_la** has an empty directory — script-based bulk edits should skip it gracefully.
|
||||
- **Reference impl**: Notepad4 at `D:\DEV\GitHub\notepad4\` — inspect `src\Edit.cpp` (`EditOpenSelection`, `EditGetStringAroundCaret`) and `src\Helpers.cpp` (`OpenContainingFolder`).
|
||||
- **Build**: `Build\Build_x64.cmd Release` for quick verification. The Build.ps1 wrapper has quoting quirks under some PowerShell versions — invoke MSBuild directly if it fails: `& "C:\Program Files\Microsoft Visual Studio\18\Community\MSBuild\Current\Bin\MSBuild.exe" "D:\DEV\GitHub\Notepad3\Notepad3.sln" /m /p:Configuration=Release /p:Platform=x64 /v:minimal`.
|
||||
|
||||
## Out of scope for these follow-ups
|
||||
|
||||
- IDS_MUI_* / Notepad3DLL string resources — none of the deferred items add user-facing strings beyond menu labels (which are inline in `.rc`).
|
||||
- ARM64-specific concerns — none of these touch rendering or CET paths.
|
||||
- grepWin integration — orthogonal.
|
||||
@ -8,6 +8,7 @@ A user-facing reference for every command exposed by Notepad3's menus and contex
|
||||
> - **`Notepad3.ini` reference** (every `[Settings2]` key referenced below): [`config/Configuration.md`](config/Configuration.md).
|
||||
> - **Focused View** in depth: [`focusedview/FocusedView.md`](focusedview/FocusedView.md).
|
||||
> - **Encryption** in depth: [`encryption/Encryption.md`](encryption/Encryption.md).
|
||||
> - **File-path handling** — hyperlinks, selection commands, line/column suffixes, anchor rules: [`paths/FilePathHandling.md`](paths/FilePathHandling.md).
|
||||
> - **MiniPath** (the bundled file browser launched with `Ctrl+M`): [`minipath/`](minipath/).
|
||||
> - **FAQ**, including the Notepad2 migration table: [`faq/FAQ.md`](faq/FAQ.md).
|
||||
|
||||
@ -321,6 +322,8 @@ Less-frequently-used utilities and selection commands.
|
||||
| **Select To Previous** | `Ctrl+Alt+Shift+F2` | Extend the selection backward to the previous match. |
|
||||
| **Select Word or Lines** | `Ctrl+Spc` | Select the word at the caret; press again to extend to the whole line. |
|
||||
| **Multi-Select All Matches** | `Ctrl+Shift+Spc` | Place multi-carets at every occurrence of the word at the caret (true multi-selection, edits affect all). |
|
||||
| **Open Containing Folder of Selection** | — | Resolve the selection (or token at the caret) to a path and reveal it in Windows Explorer. For relative paths the anchor is the current document's directory, falling back to the working directory. Greyed out when there is no selection and no word at the caret. See [`paths/FilePathHandling.md`](paths/FilePathHandling.md). |
|
||||
| **Open File from Selection** | — | Same resolution as above; loads the file into Notepad3 (jumping to a parsed `:line` if present) or opens the file-open dialog rooted at the resolved directory. See [`paths/FilePathHandling.md`](paths/FilePathHandling.md). |
|
||||
| **Split Undo Transaction at Line-Breaks** | — | Toggle: when on, every newline boundary becomes an undo checkpoint, so `Ctrl+Z` rolls back line-by-line instead of by typing run. |
|
||||
|
||||
### Bookmarks
|
||||
|
||||
@ -2,6 +2,8 @@
|
||||
|
||||
Notepad3 stores its settings in a portable INI file (`Notepad3.ini`). Press **Ctrl+F7** to open it directly in the editor. Most `[Settings2]` changes require restarting Notepad3.
|
||||
|
||||
> Path-handling behaviour controlled by keys below (`AtomicFileSave`, `ResolveUNCPaths`, `DefaultDirectory`, `OpenWithDir`, `FavoritesDir`, `HyperlinkShellExURLWithApp`, `HyperlinkFileProtocolVerb`, `ShowHypLnkToolTip`, …) is summarised in [`../paths/FilePathHandling.md`](../paths/FilePathHandling.md).
|
||||
|
||||
---
|
||||
|
||||
## `[Notepad3]`
|
||||
|
||||
326
readme/paths/FilePathHandling.md
Normal file
326
readme/paths/FilePathHandling.md
Normal file
@ -0,0 +1,326 @@
|
||||
# File-path handling in Notepad3
|
||||
|
||||
Everywhere Notepad3 turns a piece of text into a *file* — a clickable link in
|
||||
the editor, a path you typed into a dialog, a reference you selected from a
|
||||
build log — it goes through the same few rules. This page collects them in
|
||||
one place.
|
||||
|
||||
> Related references
|
||||
> - **Menu entries** for the commands below: [`../MenuEntriesAndCmds.md`](../MenuEntriesAndCmds.md).
|
||||
> - **INI keys** that influence path handling: [`../config/Configuration.md`](../config/Configuration.md).
|
||||
> - **Command-line switches** for opening files: [`../cmdln/CmdLnOptions.md`](../cmdln/CmdLnOptions.md).
|
||||
> - **MiniPath** (the bundled file browser): [`../minipath/`](../minipath/).
|
||||
|
||||
## Quick reference
|
||||
|
||||
| Want to … | Do this |
|
||||
|---|---|
|
||||
| Open a `http://…` or `https://…` URL from the document | Ctrl+Click the highlighted link → opens in your default browser. |
|
||||
| Open a `file:///…` URL in Notepad3 | Alt+Click the highlighted link → loads the target into the editor. |
|
||||
| Open a bare path like `C:\foo\bar.c:42` in Notepad3 | Alt+Click — bare paths are highlighted only when they end in `:42`, `:42:7`, or `(42)`. |
|
||||
| Reveal the file under the caret in Explorer | Place the caret on the path and choose **Edit → Miscellaneous → Open Containing Folder of Selection**, or right-click → same. |
|
||||
| Open a file referenced by selection / token at caret | **Edit → Miscellaneous → Open File from Selection** (right-click also). |
|
||||
| Reveal the *current* document in Explorer | **File → Open File Explorer**. |
|
||||
| Copy the current path | **File → Path to Clipboard → Copy Filename / Directory / Full-Path**. |
|
||||
|
||||
---
|
||||
|
||||
## 1. Clickable hyperlinks in your document
|
||||
|
||||
When **View → Hyperlink Hotspots** is enabled (default), Notepad3 detects
|
||||
links and paths in your text and marks them with an underline. Click
|
||||
modifiers control what happens:
|
||||
|
||||
| Gesture | Action |
|
||||
|---|---|
|
||||
| **Ctrl+Click** | Open in the associated external app (browser for URLs, default opener for files). |
|
||||
| **Ctrl+Shift+Click** | Open in the associated app *in the background* (Notepad3 stays in front). |
|
||||
| **Alt+Click** | Open in Notepad3 itself — works for `file:///…` URLs and bare file paths. |
|
||||
| **Alt+Shift+Click** | Open in a *new* Notepad3 instance. |
|
||||
| **Middle-mouse click** | Same as Ctrl+Click. |
|
||||
| **Right-click on a hotspot** | Context menu with explicit "Open Hyperlink" / "Copy Hyperlink URL" entries. |
|
||||
| **Hover** (with `ShowHypLnkToolTip`) | Tooltip showing the link target. |
|
||||
|
||||
### URL forms Notepad3 recognises
|
||||
|
||||
Detected as a clickable URL with a scheme:
|
||||
|
||||
| Form | Example |
|
||||
|---|---|
|
||||
| HTTP(S) | `https://example.com/foo` |
|
||||
| FTP | `ftp://example.com/foo` |
|
||||
| `www.…` (no scheme) | `www.example.com` |
|
||||
| `ftp.…` (no scheme) | `ftp.example.com` |
|
||||
| `mailto:` | `mailto:nobody@example.com` |
|
||||
| `file://` | `file://server/share/file.txt` |
|
||||
| `file:///` | `file:///D:/projects/foo/readme.md` |
|
||||
|
||||
The matcher is a single PCRE2 regular expression — it stops at common
|
||||
sentence punctuation (`. , ! ? :`) so a URL followed by punctuation in prose
|
||||
doesn't absorb the period.
|
||||
|
||||
### File URLs (`file://` and `file:///`)
|
||||
|
||||
After the scheme is stripped, the rest is treated as a filesystem path.
|
||||
**Relative `file:///` URLs** are resolved against:
|
||||
|
||||
1. The directory of the *current document*, if it has been saved.
|
||||
2. Otherwise, the working directory (the directory Notepad3 was launched
|
||||
from, or set via `/y` on the command line).
|
||||
|
||||
It is *never* resolved against Notepad3's install directory — that was a bug
|
||||
in older versions and is now fixed.
|
||||
|
||||
A trailing `#fragment` (e.g. `file:///foo.md#section-2`) is **stripped before
|
||||
the file is opened**. Notepad3 doesn't resolve Markdown anchor names; the
|
||||
file is opened cleanly without trying to interpret `#section-2`.
|
||||
|
||||
### Bare file paths (with mandatory line spec)
|
||||
|
||||
Plain filesystem paths are clickable **when they're followed by a line-number
|
||||
indicator** — that's a strong signal the text is a build-error reference,
|
||||
log entry, or stack-trace line rather than prose. Three prefix shapes are
|
||||
recognised:
|
||||
|
||||
| Form | Example |
|
||||
|---|---|
|
||||
| Drive letter + separator | `C:\foo\bar.c:42` · `c:/foo/bar.c(42)` |
|
||||
| UNC | `\\server\share\foo\bar.c:42` |
|
||||
| Relative | `.\src\Helpers.c:42` · `../include/foo.h:42:7` |
|
||||
|
||||
A bare path without a line spec — for example `C:\Windows` typed in prose —
|
||||
is **not** highlighted. That's intentional, to keep false positives down.
|
||||
If you need to act on such a path, select it and use **Open Containing
|
||||
Folder of Selection** or **Open File from Selection** (see §2).
|
||||
|
||||
### Line / column suffix patterns
|
||||
|
||||
Notepad3 recognises four trailing patterns and jumps to the parsed line
|
||||
when opening:
|
||||
|
||||
| Pattern | Example | Meaning |
|
||||
|---|---|---|
|
||||
| `:N` | `Helpers.c:42` | Line 42 |
|
||||
| `:N:M` | `Helpers.c:42:7` | Line 42, column 7 (column currently ignored) |
|
||||
| `(N)` | `Helpers.c(42)` | Line 42 |
|
||||
| `,N` | `Helpers.c,42` | Line 42 |
|
||||
|
||||
The parser is digit-only — `Helpers.c:42+1` is **not** interpreted as
|
||||
"line 43"; it's treated as a non-match and the path is opened without a
|
||||
jump.
|
||||
|
||||
A colon that follows a drive letter (`C:`) is never treated as a line
|
||||
separator.
|
||||
|
||||
---
|
||||
|
||||
## 2. Selection-based commands
|
||||
|
||||
For paths that *aren't* highlighted as hotspots — or when you just want to
|
||||
act on the path under the caret without targeting an indicator precisely —
|
||||
use the two **Edit → Miscellaneous** entries (also in the editor right-click
|
||||
menu when there's a selection or a token at the click point):
|
||||
|
||||
### Open Containing Folder of Selection
|
||||
|
||||
Resolves the selected text (or token at caret) to a filesystem path and
|
||||
opens Windows Explorer with that file highlighted. If the target is a
|
||||
folder, opens the folder itself.
|
||||
|
||||
### Open File from Selection
|
||||
|
||||
Resolves the same way, then loads the file into Notepad3 (jumps to the
|
||||
parsed line if a line spec was present). If the target is a folder, opens
|
||||
the file-open dialog rooted in it.
|
||||
|
||||
### How the token is extracted
|
||||
|
||||
If there's a non-empty selection:
|
||||
- Use the selected text.
|
||||
- Truncate at the first newline or tab character.
|
||||
|
||||
If the selection is empty:
|
||||
- Expand from the caret outward on the same line.
|
||||
- Stop at any of: whitespace, single quote, backtick, double quote, `<`,
|
||||
`>`, `|`, `*`, `,`, `;`.
|
||||
- **Markdown link special-case**: if the caret sits inside `(…)` parens
|
||||
immediately preceded by `]`, the inner contents of the parens are used
|
||||
instead — so caret inside the URL of `[label](D:\projects\foo\readme.md)`
|
||||
picks up `D:\projects\foo\readme.md`, not the surrounding text.
|
||||
|
||||
Surrounding whitespace, `"`, `'`, `` ` ``, `<`, `>` are stripped from the
|
||||
result.
|
||||
|
||||
Any trailing line/column suffix (`:N`, `:N:M`, `(N)`, `,N`) is split off
|
||||
before path resolution. For *Open File from Selection*, the parsed line
|
||||
number controls the caret jump after the file loads.
|
||||
|
||||
### Menu state
|
||||
|
||||
Both commands are greyed out when there's no selection *and* no word at the
|
||||
caret / click position. They have no default keyboard shortcut; users can
|
||||
bind one via custom keybindings if desired.
|
||||
|
||||
---
|
||||
|
||||
## 3. Path resolution rules
|
||||
|
||||
The same rules apply to file-URL clicks, bare-path clicks, and both
|
||||
selection-based commands.
|
||||
|
||||
### Anchor priority for relative paths
|
||||
|
||||
A *relative* path (one without a drive letter, UNC `\\`, or leading slash)
|
||||
is resolved against:
|
||||
|
||||
1. The directory of the **current document** (`Paths.CurrentFile`), if it
|
||||
has been saved.
|
||||
2. Otherwise, the **working directory** (`Paths.WorkingDirectory`).
|
||||
|
||||
Notepad3's *install directory* (`Paths.ModuleDirectory`) is **never** used
|
||||
as an anchor for in-document references.
|
||||
|
||||
### Environment-variable expansion
|
||||
|
||||
Tokens containing `%VAR%` are expanded against the current process
|
||||
environment before resolution. So `%WINDIR%\notepad.exe` and
|
||||
`%USERPROFILE%\Documents\foo.txt` resolve correctly.
|
||||
|
||||
### `file://` → Windows path conversion
|
||||
|
||||
`file://`-prefixed URLs go through the Windows shell's `PathCreateFromUrlW`
|
||||
to convert URL-encoded characters (`%20` → space, etc.) into a real
|
||||
filesystem path. If `PathCreateFromUrlW` fails on a malformed URL, the
|
||||
prefix is stripped manually and the resolver tries the rest as a best
|
||||
effort.
|
||||
|
||||
### Long paths (`\\?\` prefix)
|
||||
|
||||
When **Open Containing Folder of Selection** hands a path to the Windows
|
||||
shell, the long-path prefix `\\?\` is stripped first so Explorer can accept
|
||||
the path:
|
||||
|
||||
- `\\?\C:\Windows` → `C:\Windows`
|
||||
- `\\?\UNC\server\share\file.txt` → `\\server\share\file.txt`
|
||||
|
||||
Internally Notepad3 uses long-path-aware Win32 wrappers throughout. If
|
||||
Windows' long-path support (`LongPathsEnabled` group policy) is off and a
|
||||
path is ≥ 260 characters, Notepad3 applies the `\\?\` prefix transparently
|
||||
where necessary.
|
||||
|
||||
---
|
||||
|
||||
## 4. Path-related menu commands
|
||||
|
||||
### File menu
|
||||
|
||||
| Command | What it does |
|
||||
|---|---|
|
||||
| **Open…** (Ctrl+O) | Standard file-open dialog. |
|
||||
| **Open with…** (Alt+L) | Hand the current file to an external editor — choose via `OpenWithDir` setting. |
|
||||
| **Recent Files** (sub-menu) | Most-recently-used list. Paths are stored relative to Notepad3.exe by default — flip via the `Notepad3.ini` redirect mechanism. |
|
||||
| **Save** / **Save As…** / **Save Copy…** | Standard write paths; respects `AtomicFileSave` (see §5). |
|
||||
| **Open File Explorer** | Reveal the **current document** in Windows Explorer (or, if untitled, the working directory). Distinct from **Open Containing Folder of Selection**, which operates on text *inside* the document. |
|
||||
| **Path to Clipboard → Copy Filename only / Copy Directory-Path only / Copy Full-Path** | Self-explanatory; for filling into other tools. |
|
||||
| **Add to Favorites** / **Favorites…** | Pin a path to a quick-pick list, stored under `FavoritesDir`. |
|
||||
| **Launch Default Application** (Ctrl+L) | ShellExecute the current document with its registered "open" verb. |
|
||||
| **Run…** | ShellExecute an arbitrary command line, prefilled with the document's full path. |
|
||||
|
||||
### Edit menu
|
||||
|
||||
| Command | What it does |
|
||||
|---|---|
|
||||
| **Edit → Miscellaneous → Open Containing Folder of Selection** | See §2. |
|
||||
| **Edit → Miscellaneous → Open File from Selection** | See §2. |
|
||||
| **Edit → Insert → Filename / Directory / Path** | Insert the current document's name / parent dir / full path into the buffer at the caret. |
|
||||
|
||||
---
|
||||
|
||||
## 5. Background behavior
|
||||
|
||||
These mechanisms aren't user-triggered but are worth knowing about because
|
||||
they affect what you'll see on disk.
|
||||
|
||||
### File watching
|
||||
|
||||
Notepad3 asks Windows to notify it of changes in the **parent directory**
|
||||
of the open file. When the current file changes externally, the **File
|
||||
Change Notification** dialog offers to reload (or you can configure silent
|
||||
reload). The watch is released before *Save* and re-armed afterwards so
|
||||
Notepad3 doesn't observe its own writes.
|
||||
|
||||
### Atomic save
|
||||
|
||||
With `AtomicFileSave=true` (the default), *Save* writes to a temporary file
|
||||
alongside the target and then atomically replaces the original via
|
||||
`ReplaceFileW`. ACLs, alternate data streams, and attributes are preserved
|
||||
on failure — nothing is lost if the write is interrupted. See
|
||||
[`../config/Configuration.md#atomicfilesave-true`](../config/Configuration.md#atomicfilesavetrue)
|
||||
to disable on very large files where in-place writing is faster.
|
||||
|
||||
### MRU (Most-Recently-Used) list
|
||||
|
||||
The Recent Files list in the File menu is persisted in `Notepad3.ini` under
|
||||
`[Recent Files]`. Disable persistence with the `NoSaveRecent` setting.
|
||||
Entries can be removed individually from the MRU dialog.
|
||||
|
||||
### Portable & redirected INI
|
||||
|
||||
By default `Notepad3.ini` lives next to `Notepad3.exe` (portable mode). The
|
||||
file `Notepad3.ini` itself can specify a `Notepad3.ini=<path>` redirect
|
||||
under `[Notepad3]` (up to two levels) that points at a per-user location —
|
||||
useful for shared installs. The redirected file is auto-created on first
|
||||
write.
|
||||
|
||||
---
|
||||
|
||||
## 6. Configuration keys that affect path handling
|
||||
|
||||
All in `Notepad3.ini` under `[Settings2]` unless noted — see
|
||||
[`../config/Configuration.md`](../config/Configuration.md) for full
|
||||
descriptions.
|
||||
|
||||
| Key | Effect |
|
||||
|---|---|
|
||||
| `AtomicFileSave` | Two-phase Save (temp file + ReplaceFileW). |
|
||||
| `ResolveUNCPaths` | When opening a UNC path that's actually a mapped drive's share, prefer the drive-letter form for display. |
|
||||
| `DefaultDirectory` | Initial directory of the **Open…** dialog. |
|
||||
| `OpenWithDir` | Directory used by **Open with…**. |
|
||||
| `FavoritesDir` | Where the Favorites list lives. |
|
||||
| `GrepWinPath` | Override the grepWin executable lookup. |
|
||||
| `HyperlinkShellExURLWithApp` | Open URLs with a specific external app instead of the OS default. |
|
||||
| `HyperlinkShellExURLCmdLnArgs` | Argument template for the above. |
|
||||
| `HyperlinkFileProtocolVerb` | Override the verb used to ShellExecute `file:` URLs. |
|
||||
| `ShowHypLnkToolTip` | Hover tooltip showing the link target. |
|
||||
| `MonitoringLog` | `FileWatching.MonitoringLog`; tails the file by default. |
|
||||
|
||||
---
|
||||
|
||||
## 7. Troubleshooting
|
||||
|
||||
**Q. My path has spaces and the resolver only picked up part of it.**
|
||||
Wrap it in double quotes or single quotes in the source text, or select the
|
||||
full path manually before invoking the command.
|
||||
|
||||
**Q. `..\..\foo.c:42` opened the wrong file.**
|
||||
Save your document first — relative paths anchor to the document's
|
||||
directory only after it has been saved. Until then, they anchor to the
|
||||
working directory.
|
||||
|
||||
**Q. A path is highlighted but Alt+Click does nothing.**
|
||||
Notepad3 silently does nothing when the resolved path doesn't exist on
|
||||
disk. Check the path with **Open Containing Folder of Selection** — it will
|
||||
beep if the resolution fails.
|
||||
|
||||
**Q. `C:\Windows` isn't highlighted as a hotspot.**
|
||||
By design — bare paths are only hotspotted when they end in a line spec
|
||||
(`:42`, `:42:7`, or `(42)`). For paths without a line number, use the
|
||||
selection-based commands instead.
|
||||
|
||||
**Q. The line jump for `foo.c:42:7` ignores `7`.**
|
||||
The column is parsed and accepted but not currently acted on — only the
|
||||
line is set. Tracked for a future enhancement.
|
||||
|
||||
**Q. `file:///D:/docs/readme.md#section-2` doesn't jump to the anchor.**
|
||||
Heading-anchor resolution is a Markdown-specific convention and isn't
|
||||
implemented — the fragment is stripped and the file opens at the top.
|
||||
58
src/Edit.c
58
src/Edit.c
@ -112,8 +112,24 @@ static LPCWSTR const s_pUnicodeRegEx = L"(\\\\[uU|xX]([0-9a-fA-F]){4}|\\\\[xX]([
|
||||
"(?:\\([-" HYPLNK_REGEX_VALID_CDPT "?!:,.]*+\\)|[-" HYPLNK_REGEX_VALID_CDPT "?!:,.])*"\
|
||||
"(?:\\([-" HYPLNK_REGEX_VALID_CDPT "?!:,.]*+\\)|[-" HYPLNK_REGEX_VALID_CDPT "])"
|
||||
|
||||
// Bare-path-with-line-spec detection. Conservative (Approach B): only paths
|
||||
// followed by a digit suffix `:N`, `:N:M`, or `(N)` are detected — that's a
|
||||
// strong signal the token is a file reference (compiler error, log entry,
|
||||
// build output) rather than a noun in prose. Avoids the false-positive
|
||||
// risk of hotspotting any drive-letter substring.
|
||||
//
|
||||
// Prefix arms: drive letter, UNC `\\host\share\`, or relative `.\`/`..\`.
|
||||
// Leading lookbehind prevents accidental matches inside identifiers (e.g. a
|
||||
// stray `xC:\foo:42` wouldn't start at the `C`). Body chars exclude the
|
||||
// token-boundary set [\s'`"<>|*,;].
|
||||
#define HYPLNK_REGEX_FILEREF "(?<![A-Za-z0-9_])"\
|
||||
"(?:[A-Za-z]:[\\\\/]|\\\\\\\\[^\\s\\\\/]+\\\\[^\\s\\\\/]+\\\\|\\.{1,2}[\\\\/])"\
|
||||
"[^\\s'`\"<>|*,;]+"\
|
||||
"(?::\\d+(?::\\d+)?|\\(\\d+\\))"
|
||||
|
||||
static LPCSTR const s_pUrlRegExA = HYPLNK_REGEX_FULL;
|
||||
static LPCWSTR const s_pUrlRegEx = _W(HYPLNK_REGEX_FULL);
|
||||
static LPCWSTR const s_pFileRefRegEx = _W(HYPLNK_REGEX_FILEREF);
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
@ -8829,8 +8845,15 @@ static void _ClearIndicatorInRange(const int indicator, const int indicator2nd,
|
||||
}
|
||||
}
|
||||
|
||||
// Scan [startPos, endPos) for regex matches and stamp the indicator(s) onto
|
||||
// each match. When bClearGaps is true, the regions BETWEEN matches (and the
|
||||
// trailing region after the last match) are cleared first — used for the
|
||||
// authoritative URL pass. When false, the function is purely additive —
|
||||
// used to LAYER a second regex onto the same indicator without undoing the
|
||||
// first pass's matches.
|
||||
static void _UpdateIndicators(const int indicator, const int indicator2nd,
|
||||
LPCWSTR regExpr, DocPos startPos, DocPos endPos)
|
||||
LPCWSTR regExpr, DocPos startPos, DocPos endPos,
|
||||
bool bClearGaps)
|
||||
{
|
||||
if (endPos < 0) {
|
||||
endPos = Sci_GetDocEndPosition();
|
||||
@ -8845,26 +8868,25 @@ static void _UpdateIndicators(const int indicator, const int indicator2nd,
|
||||
return;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
DocPos start = startPos;
|
||||
DocPos end = endPos;
|
||||
do {
|
||||
|
||||
DocPos const start_m = start;
|
||||
DocPos const end_m = end;
|
||||
DocPos const iPos = _FindInTarget(regExpr, SCFIND_REGEXP, &start, &end, true, FRMOD_IGNORE);
|
||||
|
||||
if (iPos < 0) {
|
||||
// not found
|
||||
_ClearIndicatorInRange(indicator, indicator2nd, start_m, end_m);
|
||||
if (bClearGaps) {
|
||||
_ClearIndicatorInRange(indicator, indicator2nd, start_m, end_m);
|
||||
}
|
||||
break;
|
||||
}
|
||||
DocPos const mlen = end - start;
|
||||
if ((mlen <= 0) || (end > endPos)) {
|
||||
// wrong match
|
||||
_ClearIndicatorInRange(indicator, indicator2nd, start_m, end_m);
|
||||
break; // wrong match
|
||||
if (bClearGaps) {
|
||||
_ClearIndicatorInRange(indicator, indicator2nd, start_m, end_m);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// URL-specific: if match ends with single-quote and is preceded by one, strip trailing quote
|
||||
@ -8875,7 +8897,9 @@ static void _UpdateIndicators(const int indicator, const int indicator2nd,
|
||||
}
|
||||
}
|
||||
|
||||
_ClearIndicatorInRange(indicator, indicator2nd, start_m, end);
|
||||
if (bClearGaps) {
|
||||
_ClearIndicatorInRange(indicator, indicator2nd, start_m, end);
|
||||
}
|
||||
|
||||
SciCall_SetIndicatorCurrent(indicator);
|
||||
SciCall_IndicatorFillRange(start, mlen_adj);
|
||||
@ -8884,12 +8908,9 @@ static void _UpdateIndicators(const int indicator, const int indicator2nd,
|
||||
SciCall_IndicatorFillRange(start, mlen_adj);
|
||||
}
|
||||
|
||||
// next occurrence
|
||||
start = end;
|
||||
end = endPos;
|
||||
|
||||
} while (start < end);
|
||||
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
@ -8907,23 +8928,26 @@ void EditUpdateIndicators(DocPos startPos, DocPos endPos, bool bClearOnly)
|
||||
return;
|
||||
}
|
||||
if (Settings.HyperlinkHotspot) {
|
||||
_UpdateIndicators(INDIC_NP3_HYPERLINK, INDIC_NP3_HYPERLINK_U, s_pUrlRegEx, startPos, endPos);
|
||||
_UpdateIndicators(INDIC_NP3_HYPERLINK, INDIC_NP3_HYPERLINK_U, s_pUrlRegEx, startPos, endPos, true);
|
||||
// Layer bare-path-with-line-spec matches onto the same indicator —
|
||||
// additive (bClearGaps=false) so the URL matches above survive.
|
||||
_UpdateIndicators(INDIC_NP3_HYPERLINK, INDIC_NP3_HYPERLINK_U, s_pFileRefRegEx, startPos, endPos, false);
|
||||
} else {
|
||||
_ClearIndicatorInRange(INDIC_NP3_HYPERLINK, INDIC_NP3_HYPERLINK_U, startPos, endPos);
|
||||
}
|
||||
|
||||
if (IsColorDefHotspotEnabled()) {
|
||||
if (Settings.ColorDefHotspot < 3) {
|
||||
_UpdateIndicators(INDIC_NP3_COLOR_DEF, -1, s_pColorRegEx, startPos, endPos);
|
||||
_UpdateIndicators(INDIC_NP3_COLOR_DEF, -1, s_pColorRegEx, startPos, endPos, true);
|
||||
} else {
|
||||
_UpdateIndicators(INDIC_NP3_COLOR_DEF, -1, s_pColorRegEx_Tr, startPos, endPos);
|
||||
_UpdateIndicators(INDIC_NP3_COLOR_DEF, -1, s_pColorRegEx_Tr, startPos, endPos, true);
|
||||
}
|
||||
} else {
|
||||
_ClearIndicatorInRange(INDIC_NP3_COLOR_DEF, INDIC_NP3_COLOR_DEF_T, startPos, endPos);
|
||||
}
|
||||
|
||||
if (Settings.HighlightUnicodePoints) {
|
||||
_UpdateIndicators(INDIC_NP3_UNICODE_POINT, -1, s_pUnicodeRegEx, startPos, endPos);
|
||||
_UpdateIndicators(INDIC_NP3_UNICODE_POINT, -1, s_pUnicodeRegEx, startPos, endPos, true);
|
||||
} else {
|
||||
_ClearIndicatorInRange(INDIC_NP3_UNICODE_POINT, -1, startPos, endPos);
|
||||
}
|
||||
|
||||
127
src/Helpers.c
127
src/Helpers.c
@ -34,11 +34,6 @@
|
||||
#include "DarkMode/DarkMode.h"
|
||||
#include "Version.h"
|
||||
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4201) // union/struct w/o name
|
||||
#include "tinyexprcpp/tinyexpr_cif.h"
|
||||
#pragma warning(pop)
|
||||
|
||||
#include "Scintilla.h"
|
||||
|
||||
|
||||
@ -1136,34 +1131,6 @@ void PathFixBackslashes(LPWSTR lpsz)
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// SplitFilePathLineNum()
|
||||
//
|
||||
bool SplitFilePathLineNum(LPWSTR lpszPath, int* lineNum)
|
||||
{
|
||||
|
||||
LPWSTR const lpszSplit = StrRChr(lpszPath, NULL, L':');
|
||||
|
||||
bool res = false;
|
||||
if (lpszSplit) {
|
||||
char chLnNumber[128];
|
||||
char const defchar = (char)0x24;
|
||||
WideCharToMultiByte(CP_ACP, (WC_COMPOSITECHECK | WC_DISCARDNS), &lpszSplit[1], -1, chLnNumber, COUNTOF(chLnNumber), &defchar, NULL);
|
||||
te_int_t iExprError = true;
|
||||
int const ln = (int)te_interp(chLnNumber, &iExprError);
|
||||
if (!iExprError) {
|
||||
res = true;
|
||||
lpszSplit[0] = L'\0'; // split
|
||||
if (lineNum) {
|
||||
*lineNum = ln;
|
||||
}
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// _IsAllDigitsW() - non-empty wide string consisting solely of ASCII digits
|
||||
@ -1199,6 +1166,29 @@ static inline void _StripCommonQuoting(HSTRINGW hstr)
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// SplitFilePathLineNum()
|
||||
//
|
||||
// Strips a trailing ":N" digit-only line-number suffix from lpszPath in
|
||||
// place and writes N into *lineNum (if non-NULL). Returns true on a strip.
|
||||
// No expression evaluation — `foo:42` works; `foo:42+1` does NOT.
|
||||
//
|
||||
bool SplitFilePathLineNum(LPWSTR lpszPath, int* lineNum)
|
||||
{
|
||||
LPWSTR const lpszSplit = StrRChr(lpszPath, NULL, L':');
|
||||
if (!lpszSplit || !_IsAllDigitsW(lpszSplit + 1)) {
|
||||
return false;
|
||||
}
|
||||
int const ln = _wtoi(lpszSplit + 1);
|
||||
lpszSplit[0] = L'\0'; // split in place
|
||||
if (lineNum) {
|
||||
*lineNum = ln;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// SplitFilePathLineColNum()
|
||||
@ -1208,7 +1198,7 @@ static inline void _StripCommonQuoting(HSTRINGW hstr)
|
||||
// foo.c(42) -> line 42
|
||||
// foo.c,42 -> line 42
|
||||
// foo.c:42:7 -> line 42, column 7
|
||||
// foo.c:<expr> -> falls through to SplitFilePathLineNum (te_interp)
|
||||
// foo.c:42 -> falls through to SplitFilePathLineNum (single colon)
|
||||
//
|
||||
// Drive-letter colons ("C:\...") are never treated as line separators.
|
||||
// Returns true if a suffix was stripped.
|
||||
@ -1292,7 +1282,7 @@ bool SplitFilePathLineColNum(LPWSTR lpszPath, int* lineNum, int* colNum)
|
||||
*lastColon = saved;
|
||||
}
|
||||
|
||||
// Single-colon fallback (preserves te_interp expression support)
|
||||
// Single-colon fallback: digit-only :N parse.
|
||||
return SplitFilePathLineNum(lpszPath, lineNum);
|
||||
}
|
||||
|
||||
@ -1316,6 +1306,54 @@ static inline bool _IsTokenBoundary(char c)
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// _TryMarkdownLinkSpan() - if caret sits inside `(...)` preceded by `]` on
|
||||
// the same line, return the inner (url) span.
|
||||
// Handles nested parens via depth counting.
|
||||
//
|
||||
static bool _TryMarkdownLinkSpan(DocPos pos, DocPos lineStart, DocPos lineEnd,
|
||||
DocPos* outStart, DocPos* outEnd)
|
||||
{
|
||||
DocPos openP = -1;
|
||||
int depth = 0;
|
||||
for (DocPos p = pos; p > lineStart; --p) {
|
||||
char const c = SciCall_GetCharAt(p - 1);
|
||||
if (c == ')') {
|
||||
++depth;
|
||||
}
|
||||
else if (c == '(') {
|
||||
if (depth == 0) {
|
||||
if (p - 1 > lineStart && SciCall_GetCharAt(p - 2) == ']') {
|
||||
openP = p - 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
--depth;
|
||||
}
|
||||
}
|
||||
if (openP < 0) {
|
||||
return false;
|
||||
}
|
||||
int d2 = 0;
|
||||
for (DocPos p = pos; p < lineEnd; ++p) {
|
||||
char const c = SciCall_GetCharAt(p);
|
||||
if (c == '(') {
|
||||
++d2;
|
||||
}
|
||||
else if (c == ')') {
|
||||
if (d2 == 0) {
|
||||
*outStart = openP + 1;
|
||||
*outEnd = p;
|
||||
return true;
|
||||
}
|
||||
--d2;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// ExtractSelectionOrTokenAtCaret()
|
||||
@ -1324,6 +1362,8 @@ static inline bool _IsTokenBoundary(char c)
|
||||
// the current selection, or - if the selection is empty - the span around
|
||||
// the caret bounded by [\s'`"<>|*,;]. Newline-truncates selections.
|
||||
// Strips surrounding whitespace and quote-like characters.
|
||||
// Special-cases Markdown link targets: caret inside `[label](url)` parens
|
||||
// grabs `url` rather than expanding outward.
|
||||
//
|
||||
HSTRINGW ExtractSelectionOrTokenAtCaret(void)
|
||||
{
|
||||
@ -1349,13 +1389,16 @@ HSTRINGW ExtractSelectionOrTokenAtCaret(void)
|
||||
DocLn const ln = SciCall_LineFromPosition(pos);
|
||||
DocPos const lineStart = SciCall_PositionFromLine(ln);
|
||||
DocPos const lineEnd = SciCall_GetLineEndPosition(ln);
|
||||
byteStart = pos;
|
||||
while (byteStart > lineStart && !_IsTokenBoundary(SciCall_GetCharAt(byteStart - 1))) {
|
||||
--byteStart;
|
||||
}
|
||||
byteEnd = pos;
|
||||
while (byteEnd < lineEnd && !_IsTokenBoundary(SciCall_GetCharAt(byteEnd))) {
|
||||
++byteEnd;
|
||||
|
||||
if (!_TryMarkdownLinkSpan(pos, lineStart, lineEnd, &byteStart, &byteEnd)) {
|
||||
byteStart = pos;
|
||||
while (byteStart > lineStart && !_IsTokenBoundary(SciCall_GetCharAt(byteStart - 1))) {
|
||||
--byteStart;
|
||||
}
|
||||
byteEnd = pos;
|
||||
while (byteEnd < lineEnd && !_IsTokenBoundary(SciCall_GetCharAt(byteEnd))) {
|
||||
++byteEnd;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
118
src/Notepad3.c
118
src/Notepad3.c
@ -4488,6 +4488,22 @@ LRESULT MsgCopyData(HWND hwnd, WPARAM wParam, LPARAM lParam)
|
||||
//
|
||||
static DocPos s_iCtxMenuClickPos = -1;
|
||||
|
||||
// Returns true if there is something to act on at this position — either a
|
||||
// non-empty selection (then pos is ignored), or a non-empty word span at
|
||||
// pos. Pass pos = -1 to test selection-only.
|
||||
static bool _HasSelectionOrWordAt(DocPos pos)
|
||||
{
|
||||
if (!SciCall_IsSelectionEmpty()) {
|
||||
return true;
|
||||
}
|
||||
if (pos < 0) {
|
||||
return false;
|
||||
}
|
||||
DocPos const ws = SciCall_WordStartPosition(pos, true);
|
||||
DocPos const we = SciCall_WordEndPosition(pos, true);
|
||||
return (ws != we);
|
||||
}
|
||||
|
||||
LRESULT MsgContextMenu(HWND hwnd, UINT umsg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
bool const bMargin = (SCN_MARGINRIGHTCLICK == umsg);
|
||||
@ -4556,21 +4572,18 @@ LRESULT MsgContextMenu(HWND hwnd, UINT umsg, WPARAM wParam, LPARAM lParam)
|
||||
ModifyMenu(hStdCtxMenu, CMD_WEBACTION2, MF_BYCOMMAND | MF_STRING, CMD_WEBACTION2, Settings2.WebTmpl2MenuName);
|
||||
}
|
||||
|
||||
// case conversion submenu: enable based on selection or word at click position
|
||||
// Enable selection-acting commands based on selection-or-word-at-click-position.
|
||||
s_iCtxMenuClickPos = SciCall_CharPositionFromPointClose(pt.x, pt.y);
|
||||
bool const ro = SciCall_GetReadOnly();
|
||||
bool const se = SciCall_IsSelectionEmpty();
|
||||
bool bHasTarget = !se;
|
||||
if (se && (s_iCtxMenuClickPos >= 0)) {
|
||||
DocPos const ws = SciCall_WordStartPosition(s_iCtxMenuClickPos, true);
|
||||
DocPos const we = SciCall_WordEndPosition(s_iCtxMenuClickPos, true);
|
||||
bHasTarget = (ws != we);
|
||||
}
|
||||
bool const bHasTarget = _HasSelectionOrWordAt(s_iCtxMenuClickPos);
|
||||
EnableCmd(hStdCtxMenu, CMD_CTX_UPPERCASE, bHasTarget && !ro);
|
||||
EnableCmd(hStdCtxMenu, CMD_CTX_LOWERCASE, bHasTarget && !ro);
|
||||
EnableCmd(hStdCtxMenu, CMD_CTX_INVERTCASE, bHasTarget && !ro);
|
||||
EnableCmd(hStdCtxMenu, CMD_CTX_TITLECASE, bHasTarget && !ro);
|
||||
EnableCmd(hStdCtxMenu, CMD_CTX_SENTENCECASE, bHasTarget && !ro);
|
||||
|
||||
EnableCmd(hStdCtxMenu, IDM_EDIT_OPEN_CONTAINING_FOLDER_SEL, bHasTarget);
|
||||
EnableCmd(hStdCtxMenu, IDM_EDIT_OPEN_FILE_FROM_SEL, bHasTarget);
|
||||
}
|
||||
|
||||
// back to screen coordinates for menu display
|
||||
@ -4962,6 +4975,14 @@ LRESULT MsgInitMenu(HWND hwnd, WPARAM wParam, LPARAM lParam)
|
||||
|
||||
EnableCmd(hmenu, IDM_EDIT_INSERT_GUID, !ro);
|
||||
|
||||
// The selection-based "Open …" commands need either a non-empty selection
|
||||
// or a token at the caret. Read-only is irrelevant — neither modifies.
|
||||
{
|
||||
bool const bHasTarget = _HasSelectionOrWordAt(SciCall_GetCurrentPos());
|
||||
EnableCmd(hmenu, IDM_EDIT_OPEN_CONTAINING_FOLDER_SEL, bHasTarget);
|
||||
EnableCmd(hmenu, IDM_EDIT_OPEN_FILE_FROM_SEL, bHasTarget);
|
||||
}
|
||||
|
||||
EnableCmd(hmenu, IDM_EDIT_FIND, !te);
|
||||
EnableCmd(hmenu, IDM_EDIT_SAVEFIND, !te);
|
||||
EnableCmd(hmenu, IDM_EDIT_FINDNEXT, !te);
|
||||
@ -6071,8 +6092,21 @@ void EditOpenContainingFolderFromSelection(void)
|
||||
return;
|
||||
}
|
||||
|
||||
// SHParseDisplayName doesn't reliably accept the \\?\ long-path prefix.
|
||||
// Strip it for shell-API use: \\?\C:\… -> C:\…, \\?\UNC\server\share -> \\server\share.
|
||||
LPCWSTR pszForShell = Path_Get(hpth);
|
||||
WCHAR shellPath[PATHLONG_MAX_CCH];
|
||||
if (pszForShell && StrCmpNW(pszForShell, L"\\\\?\\", 4) == 0) {
|
||||
if (StrCmpNIW(pszForShell + 4, L"UNC\\", 4) == 0) {
|
||||
StringCchPrintf(shellPath, COUNTOF(shellPath), L"\\\\%s", pszForShell + 8);
|
||||
} else {
|
||||
StringCchCopy(shellPath, COUNTOF(shellPath), pszForShell + 4);
|
||||
}
|
||||
pszForShell = shellPath;
|
||||
}
|
||||
|
||||
PIDLIST_ABSOLUTE pidl = NULL;
|
||||
SHParseDisplayName(Path_Get(hpth), NULL, &pidl, SFGAO_BROWSABLE | SFGAO_FILESYSTEM, NULL);
|
||||
SHParseDisplayName(pszForShell, NULL, &pidl, SFGAO_BROWSABLE | SFGAO_FILESYSTEM, NULL);
|
||||
if (pidl) {
|
||||
SHOpenFolderAndSelectItems(pidl, 0, NULL, 0);
|
||||
ILFree(pidl);
|
||||
@ -8951,6 +8985,40 @@ void HandleDWellStartEnd(const DocPos position, const UINT uid)
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// _IsLikelyBarePath()
|
||||
//
|
||||
// Pure prefix-shape check mirroring HYPLNK_REGEX_FILEREF's three arms:
|
||||
// drive letter, UNC `\\…`, or relative `.\` / `..\` (forward slashes too).
|
||||
// Does NOT verify the path exists or follows the full token grammar — used
|
||||
// only to decide hyperlink-click routing.
|
||||
//
|
||||
static bool _IsLikelyBarePath(LPCWSTR s)
|
||||
{
|
||||
if (!s) {
|
||||
return false;
|
||||
}
|
||||
// Drive-letter: <letter>:[\/]
|
||||
if (((s[0] >= L'A' && s[0] <= L'Z') || (s[0] >= L'a' && s[0] <= L'z'))
|
||||
&& s[1] == L':' && (s[2] == L'\\' || s[2] == L'/')) {
|
||||
return true;
|
||||
}
|
||||
// UNC: \\<host>
|
||||
if (s[0] == L'\\' && s[1] == L'\\') {
|
||||
return true;
|
||||
}
|
||||
// Relative: .\, ./, ..\, ../
|
||||
if (s[0] == L'.' && (s[1] == L'\\' || s[1] == L'/')) {
|
||||
return true;
|
||||
}
|
||||
if (s[0] == L'.' && s[1] == L'.' && (s[2] == L'\\' || s[2] == L'/')) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// HandleHotSpotURLClicked()
|
||||
@ -9011,16 +9079,38 @@ bool HandleHotSpotURLClicked(const DocPos position, const HYPERLINK_OPS operatio
|
||||
DWORD dCch = COUNTOF(szUnEscW);
|
||||
|
||||
int lineNum = -1;
|
||||
SplitFilePathLineNum(szTextW, &lineNum);
|
||||
// Use Col-aware splitter so (N), :N:M, ,N suffixes are all stripped
|
||||
// — bare-path indicators include these forms.
|
||||
SplitFilePathLineColNum(szTextW, &lineNum, NULL);
|
||||
lineNum = clampi(lineNum, 0, INT_MAX);
|
||||
|
||||
if (((operation & OPEN_IN_NOTEPAD3) || (operation & OPEN_NEW_NOTEPAD3)) && UrlIsFileUrl(szTextW)) {
|
||||
// A bare Windows path that didn't go through PathCreateFromUrlW.
|
||||
// Detected by the file-ref indicator regex (HYPLNK_REGEX_FILEREF).
|
||||
bool const isFileScheme = UrlIsFileUrl(szTextW);
|
||||
bool const isBarePath = !isFileScheme && _IsLikelyBarePath(szTextW);
|
||||
|
||||
if (((operation & OPEN_IN_NOTEPAD3) || (operation & OPEN_NEW_NOTEPAD3)) && (isFileScheme || isBarePath)) {
|
||||
|
||||
bool const bReuseWindow = Flags.bReuseWindow && !(operation & OPEN_NEW_NOTEPAD3);
|
||||
|
||||
PathCreateFromUrlW(szTextW, szUnEscW, &dCch, 0);
|
||||
szUnEscW[INTERNET_MAX_URL_LENGTH] = L'\0'; // limit length
|
||||
StrTrim(szUnEscW, L"/");
|
||||
if (isFileScheme) {
|
||||
PathCreateFromUrlW(szTextW, szUnEscW, &dCch, 0);
|
||||
szUnEscW[INTERNET_MAX_URL_LENGTH] = L'\0'; // limit length
|
||||
StrTrim(szUnEscW, L"/");
|
||||
|
||||
// Discard any trailing #fragment — anchor names are a
|
||||
// markup concept the editor doesn't resolve, but the file
|
||||
// half of the URL should still open cleanly.
|
||||
LPWSTR const hash = StrChrW(szUnEscW, L'#');
|
||||
if (hash) {
|
||||
*hash = L'\0';
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Bare path: szTextW is already the filesystem path text
|
||||
// (line suffix already stripped above).
|
||||
StringCchCopy(szUnEscW, COUNTOF(szUnEscW), szTextW);
|
||||
}
|
||||
|
||||
HPATHL hfile_pth = Path_Allocate(szUnEscW);
|
||||
// Anchor relative file:// URLs to the directory of the current
|
||||
|
||||
422
test/test_files/StyleLexers/AllFiles.txt
Normal file
422
test/test_files/StyleLexers/AllFiles.txt
Normal file
@ -0,0 +1,422 @@
|
||||
; Notepad3 lexer test fixtures - 'Open File from Selection' targets.
|
||||
;
|
||||
; Each entry appears twice: (1) file:// URL with absolute path,
|
||||
; (2) the same target as a relative path resolved via the
|
||||
; document-anchor (this file's directory).
|
||||
;
|
||||
; Usage: place the caret on a line (or select the line text) and
|
||||
; invoke Edit > Open File from Selection. Files whose names
|
||||
; contain spaces must be selected explicitly - whitespace is a
|
||||
; token boundary when no selection is active.
|
||||
|
||||
; --- styleLexABAQUS ---
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexABAQUS/example.inp
|
||||
styleLexABAQUS/example.inp
|
||||
|
||||
; --- styleLexAHK2 ---
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexAHK2/lexer_ahk_v2_smoke.ahk2
|
||||
styleLexAHK2/lexer_ahk_v2_smoke.ahk2
|
||||
|
||||
; --- styleLexAHKL ---
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexAHKL/AHKL_Test.ahk
|
||||
styleLexAHKL/AHKL_Test.ahk
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexAHKL/lexer_ahk_v1_smoke.ahk
|
||||
styleLexAHKL/lexer_ahk_v1_smoke.ahk
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexAHKL/NP3_Test.ahk
|
||||
styleLexAHKL/NP3_Test.ahk
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexAHKL/NP3_Test_Gui.ahk
|
||||
styleLexAHKL/NP3_Test_Gui.ahk
|
||||
|
||||
; --- styleLexANSI ---
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexANSI/acme.nfo
|
||||
styleLexANSI/acme.nfo
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexANSI/DEADLINE.nfo
|
||||
styleLexANSI/DEADLINE.nfo
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexANSI/file01_id.diz
|
||||
styleLexANSI/file01_id.diz
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexANSI/file02_id.diz
|
||||
styleLexANSI/file02_id.diz
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexANSI/file03_id.diz
|
||||
styleLexANSI/file03_id.diz
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexANSI/FILE_ID.DIZ
|
||||
styleLexANSI/FILE_ID.DIZ
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexANSI/jerry.nfo
|
||||
styleLexANSI/jerry.nfo
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexANSI/NFO_01%20-%20BOX.nfo
|
||||
styleLexANSI/NFO_01 - BOX.nfo
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexANSI/NFO_02%20-%20PENTIUM.nfo
|
||||
styleLexANSI/NFO_02 - PENTIUM.nfo
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexANSI/wwc94.nfo
|
||||
styleLexANSI/wwc94.nfo
|
||||
|
||||
; --- styleLexASM ---
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexASM/lowhelpr.asm
|
||||
styleLexASM/lowhelpr.asm
|
||||
|
||||
; --- styleLexAU3 ---
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexAU3/clipboard_logger.au3
|
||||
styleLexAU3/clipboard_logger.au3
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexAU3/Configure_NP3%20%28Craigo-%29.au3
|
||||
styleLexAU3/Configure_NP3 (Craigo-).au3
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexAU3/environment.au3
|
||||
styleLexAU3/environment.au3
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexAU3/evernote_details.au3
|
||||
styleLexAU3/evernote_details.au3
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexAU3/free_diskspace.au3
|
||||
styleLexAU3/free_diskspace.au3
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexAU3/get_putty_sessions.au3
|
||||
styleLexAU3/get_putty_sessions.au3
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexAU3/logoff.au3
|
||||
styleLexAU3/logoff.au3
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexAU3/security_eventlog.au3
|
||||
styleLexAU3/security_eventlog.au3
|
||||
|
||||
; --- styleLexAVS ---
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexAVS/Sample_AVS.avs
|
||||
styleLexAVS/Sample_AVS.avs
|
||||
|
||||
; --- styleLexAwk ---
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexAwk/mve.awk
|
||||
styleLexAwk/mve.awk
|
||||
|
||||
; --- styleLexBASH ---
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexBASH/autogen.sh
|
||||
styleLexBASH/autogen.sh
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexBASH/backup.sh
|
||||
styleLexBASH/backup.sh
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexBASH/gawk.csh
|
||||
styleLexBASH/gawk.csh
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexBASH/gettext.sh
|
||||
styleLexBASH/gettext.sh
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexBASH/perlbin.csh
|
||||
styleLexBASH/perlbin.csh
|
||||
|
||||
; --- styleLexBAT ---
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexBAT/BAT_01.bat
|
||||
styleLexBAT/BAT_01.bat
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexBAT/CMD_01.cmd
|
||||
styleLexBAT/CMD_01.cmd
|
||||
|
||||
; --- styleLexCmake ---
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexCmake/minizip-exports.cmake
|
||||
styleLexCmake/minizip-exports.cmake
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexCmake/symbols.cmake
|
||||
styleLexCmake/symbols.cmake
|
||||
|
||||
; --- styleLexCOFFEESCRIPT ---
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexCOFFEESCRIPT/coffeelint.coffee
|
||||
styleLexCOFFEESCRIPT/coffeelint.coffee
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexCOFFEESCRIPT/commandline.coffee
|
||||
styleLexCOFFEESCRIPT/commandline.coffee
|
||||
|
||||
; --- styleLexCONF ---
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexCONF/Example1%20of%20httpd.conf
|
||||
styleLexCONF/Example1 of httpd.conf
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexCONF/Example2%20of%20httpd.conf
|
||||
styleLexCONF/Example2 of httpd.conf
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexCONF/fonts.conf
|
||||
styleLexCONF/fonts.conf
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexCONF/httpd%20%28issue%20%231662%29.conf
|
||||
styleLexCONF/httpd (issue #1662).conf
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexCONF/jsl.node.conf
|
||||
styleLexCONF/jsl.node.conf
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexCONF/mscormmc.cfg
|
||||
styleLexCONF/mscormmc.cfg
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexCONF/WildCard.0809.cfg
|
||||
styleLexCONF/WildCard.0809.cfg
|
||||
|
||||
; --- styleLexCPP ---
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexCPP/Config.cpp
|
||||
styleLexCPP/Config.cpp
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexCPP/DBCS.cxx
|
||||
styleLexCPP/DBCS.cxx
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexCPP/DefaultLexer.cxx
|
||||
styleLexCPP/DefaultLexer.cxx
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexCPP/Empty.cpp
|
||||
styleLexCPP/Empty.cpp
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexCPP/Notepad3.c
|
||||
styleLexCPP/Notepad3.c
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexCPP/Test_Replace%20%28issue%20%231901%29.cxx
|
||||
styleLexCPP/Test_Replace (issue #1901).cxx
|
||||
|
||||
; --- styleLexCS ---
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexCS/SecurityPage.cs
|
||||
styleLexCS/SecurityPage.cs
|
||||
|
||||
; --- styleLexCSS ---
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexCSS/markdown.css
|
||||
styleLexCSS/markdown.css
|
||||
|
||||
; --- styleLexCSV ---
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexCSV/Sample3.csv
|
||||
styleLexCSV/Sample3.csv
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexCSV/SampleCSVFile_1kb.csv
|
||||
styleLexCSV/SampleCSVFile_1kb.csv
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexCSV/SampleCSVFile_2kb.csv
|
||||
styleLexCSV/SampleCSVFile_2kb.csv
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexCSV/SampleCSVFile_4kb.csv
|
||||
styleLexCSV/SampleCSVFile_4kb.csv
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexCSV/SampleCSVFile_inconsistent.csv
|
||||
styleLexCSV/SampleCSVFile_inconsistent.csv
|
||||
|
||||
; --- styleLexD ---
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexD/Sample_D.d
|
||||
styleLexD/Sample_D.d
|
||||
|
||||
; --- styleLexDart ---
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexDart/ExampleCode.dart
|
||||
styleLexDart/ExampleCode.dart
|
||||
|
||||
; --- styleLexDIFF ---
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexDIFF/Fix%20broken%20Style%20Scheme%20Export%20%28%231409%29.diff
|
||||
styleLexDIFF/Fix broken Style Scheme Export (#1409).diff
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexDIFF/Fix%20broken%20Style%20Scheme%20Export%20%28%231409%29.patch
|
||||
styleLexDIFF/Fix broken Style Scheme Export (#1409).patch
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexDIFF/float.patch
|
||||
styleLexDIFF/float.patch
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexDIFF/No%20pre-defined%20font%20for%20Text%20Files%20%28%231445%29.diff
|
||||
styleLexDIFF/No pre-defined font for Text Files (#1445).diff
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexDIFF/No%20pre-defined%20font%20for%20Text%20Files%20%28%231445%29.patch
|
||||
styleLexDIFF/No pre-defined font for Text Files (#1445).patch
|
||||
|
||||
; --- styleLexFortran ---
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexFortran/cylinder.f90
|
||||
styleLexFortran/cylinder.f90
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexFortran/Fortran_Control.f90
|
||||
styleLexFortran/Fortran_Control.f90
|
||||
|
||||
; --- styleLexGo ---
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexGo/Go_goroutine_channel.go
|
||||
styleLexGo/Go_goroutine_channel.go
|
||||
|
||||
; --- styleLexHTML ---
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexHTML/Design.html
|
||||
styleLexHTML/Design.html
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexHTML/MultiLang.html
|
||||
styleLexHTML/MultiLang.html
|
||||
|
||||
; --- styleLexINNO ---
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexINNO/AllPagesExample.iss
|
||||
styleLexINNO/AllPagesExample.iss
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexINNO/Example3.iss
|
||||
styleLexINNO/Example3.iss
|
||||
|
||||
; --- styleLexJAVA ---
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexJAVA/DecryptNotepad3.java
|
||||
styleLexJAVA/DecryptNotepad3.java
|
||||
|
||||
; --- styleLexJS ---
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexJS/codepen.js
|
||||
styleLexJS/codepen.js
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexJS/environment.js
|
||||
styleLexJS/environment.js
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexJS/pythonMain.js
|
||||
styleLexJS/pythonMain.js
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexJS/test_script.js
|
||||
styleLexJS/test_script.js
|
||||
|
||||
; --- styleLexJSON ---
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexJSON/Sample_JSON%20%28issue%20%233070%29.json
|
||||
styleLexJSON/Sample_JSON (issue #3070).json
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexJSON/Sample_JSON5_extended.json
|
||||
styleLexJSON/Sample_JSON5_extended.json
|
||||
|
||||
; --- styleLexJulia ---
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexJulia/x.jl
|
||||
styleLexJulia/x.jl
|
||||
|
||||
; --- styleLexKiX ---
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexKiX/demo.kix
|
||||
styleLexKiX/demo.kix
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexKiX/kick.kix
|
||||
styleLexKiX/kick.kix
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexKiX/kixtart.kix
|
||||
styleLexKiX/kixtart.kix
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexKiX/plt.kix
|
||||
styleLexKiX/plt.kix
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexKiX/test.kix
|
||||
styleLexKiX/test.kix
|
||||
|
||||
; --- styleLexKotlin ---
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexKotlin/CommandLine%20%28issue%20%233343%29.kt
|
||||
styleLexKotlin/CommandLine (issue #3343).kt
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexKotlin/ExampleCode.kt
|
||||
styleLexKotlin/ExampleCode.kt
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexKotlin/NetworkConnectionMonitor.kts
|
||||
styleLexKotlin/NetworkConnectionMonitor.kts
|
||||
|
||||
; --- styleLexLATEX ---
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexLATEX/Sample_LATEX.tex
|
||||
styleLexLATEX/Sample_LATEX.tex
|
||||
|
||||
; --- styleLexLUA ---
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexLUA/Sample_LUA.lua
|
||||
styleLexLUA/Sample_LUA.lua
|
||||
|
||||
; --- styleLexMAK ---
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexMAK/scintilla.mak
|
||||
styleLexMAK/scintilla.mak
|
||||
|
||||
; --- styleLexMARKDOWN ---
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexMARKDOWN/README.md
|
||||
styleLexMARKDOWN/README.md
|
||||
|
||||
; --- styleLexMATLAB ---
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexMATLAB/bresenham.m
|
||||
styleLexMATLAB/bresenham.m
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexMATLAB/evidence.m
|
||||
styleLexMATLAB/evidence.m
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexMATLAB/example.m
|
||||
styleLexMATLAB/example.m
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexMATLAB/ThinICAnew.m
|
||||
styleLexMATLAB/ThinICAnew.m
|
||||
|
||||
; --- styleLexNim ---
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexNim/aliases.nim
|
||||
styleLexNim/aliases.nim
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexNim/sugar.nim
|
||||
styleLexNim/sugar.nim
|
||||
|
||||
; --- styleLexNSIS ---
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexNSIS/GeneratorWizard.nsi
|
||||
styleLexNSIS/GeneratorWizard.nsi
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexNSIS/PortableApps.comLauncher.nsi
|
||||
styleLexNSIS/PortableApps.comLauncher.nsi
|
||||
|
||||
; --- styleLexPAS ---
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexPAS/nsis.pas
|
||||
styleLexPAS/nsis.pas
|
||||
|
||||
; --- styleLexPL ---
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexPL/CA.pl
|
||||
styleLexPL/CA.pl
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexPL/svn.pl
|
||||
styleLexPL/svn.pl
|
||||
|
||||
; --- styleLexPROPS ---
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexPROPS/html.properties
|
||||
styleLexPROPS/html.properties
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexPROPS/INI_Notepad3_01.ini
|
||||
styleLexPROPS/INI_Notepad3_01.ini
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexPROPS/INI_Old_Reg_01.ini
|
||||
styleLexPROPS/INI_Old_Reg_01.ini
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexPROPS/usbxhci.inf
|
||||
styleLexPROPS/usbxhci.inf
|
||||
|
||||
; --- styleLexPS ---
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexPS/PS1_Version_NP3.ps1
|
||||
styleLexPS/PS1_Version_NP3.ps1
|
||||
|
||||
; --- styleLexPY ---
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexPY/hello_world.py
|
||||
styleLexPY/hello_world.py
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexPY/python.py
|
||||
styleLexPY/python.py
|
||||
|
||||
; --- styleLexR ---
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexR/Sample_R.r
|
||||
styleLexR/Sample_R.r
|
||||
|
||||
; --- styleLexRC ---
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexRC/np3_en_us.rc
|
||||
styleLexRC/np3_en_us.rc
|
||||
|
||||
; --- styleLexRegistry ---
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexRegistry/REG_01.reg
|
||||
styleLexRegistry/REG_01.reg
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexRegistry/REG_02.reg
|
||||
styleLexRegistry/REG_02.reg
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexRegistry/Registry.reg
|
||||
styleLexRegistry/Registry.reg
|
||||
|
||||
; --- styleLexRUBY ---
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexRUBY/test.rb
|
||||
styleLexRUBY/test.rb
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexRUBY/test_erb.rb
|
||||
styleLexRUBY/test_erb.rb
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexRUBY/test_logger.rb
|
||||
styleLexRUBY/test_logger.rb
|
||||
|
||||
; --- styleLexRust ---
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexRust/Rust.rs
|
||||
styleLexRust/Rust.rs
|
||||
|
||||
; --- styleLexSQL ---
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexSQL/SQL-File-10-Rows.sql
|
||||
styleLexSQL/SQL-File-10-Rows.sql
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexSQL/SQL-TestData.sql
|
||||
styleLexSQL/SQL-TestData.sql
|
||||
|
||||
; --- styleLexTCL ---
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexTCL/branch_create.tcl
|
||||
styleLexTCL/branch_create.tcl
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexTCL/commit.tcl
|
||||
styleLexTCL/commit.tcl
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexTCL/option.tcl
|
||||
styleLexTCL/option.tcl
|
||||
|
||||
; --- styleLexTEXT ---
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexTEXT/Find.since.certain_current.line.not.1st.line%20%28issue%20%233107%29.txt
|
||||
styleLexTEXT/Find.since.certain_current.line.not.1st.line (issue #3107).txt
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexTEXT/License.txt
|
||||
styleLexTEXT/License.txt
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexTEXT/Malayan_Problem.txt
|
||||
styleLexTEXT/Malayan_Problem.txt
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexTEXT/regex_find.txt
|
||||
styleLexTEXT/regex_find.txt
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexTEXT/strange_chacter_visual_artefacts.txt
|
||||
styleLexTEXT/strange_chacter_visual_artefacts.txt
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexTEXT/TXT_Readme_01.txt
|
||||
styleLexTEXT/TXT_Readme_01.txt
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexTEXT/TXT_Test_20_Long_Lines.txt
|
||||
styleLexTEXT/TXT_Test_20_Long_Lines.txt
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexTEXT/TXT_The_quick_brown_fox.txt
|
||||
styleLexTEXT/TXT_The_quick_brown_fox.txt
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexTEXT/TXT_vertical-selection-bug.txt
|
||||
styleLexTEXT/TXT_vertical-selection-bug.txt
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexTEXT/TXT_Word-Wrapped_1_Lines.txt
|
||||
styleLexTEXT/TXT_Word-Wrapped_1_Lines.txt
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexTEXT/TXT_Word-Wrapped_many_Lines.txt
|
||||
styleLexTEXT/TXT_Word-Wrapped_many_Lines.txt
|
||||
|
||||
; --- styleLexTOML ---
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexTOML/TOML.toml
|
||||
styleLexTOML/TOML.toml
|
||||
|
||||
; --- styleLexVB ---
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexVB/Sample_VB.vb
|
||||
styleLexVB/Sample_VB.vb
|
||||
|
||||
; --- styleLexVBS ---
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexVBS/base.vbs
|
||||
styleLexVBS/base.vbs
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexVBS/VBS_01.vbs
|
||||
styleLexVBS/VBS_01.vbs
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexVBS/VBS_02.vbs
|
||||
styleLexVBS/VBS_02.vbs
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexVBS/wisubstg.vbs
|
||||
styleLexVBS/wisubstg.vbs
|
||||
|
||||
; --- styleLexVerilog ---
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexVerilog/SystemVerilog_example.sv
|
||||
styleLexVerilog/SystemVerilog_example.sv
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexVerilog/Verilog_example.v
|
||||
styleLexVerilog/Verilog_example.v
|
||||
|
||||
; --- styleLexVHDL ---
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexVHDL/Sample_VHDL.vhdl
|
||||
styleLexVHDL/Sample_VHDL.vhdl
|
||||
|
||||
; --- styleLexXML ---
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexXML/MiniPath.exe.manifest
|
||||
styleLexXML/MiniPath.exe.manifest
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexXML/Sample%20of%20FFS_GUI.ffs_gui
|
||||
styleLexXML/Sample of FFS_GUI.ffs_gui
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexXML/Sample%20of%20NZB.nzb
|
||||
styleLexXML/Sample of NZB.nzb
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexXML/XML_01.xml
|
||||
styleLexXML/XML_01.xml
|
||||
|
||||
; --- styleLexYAML ---
|
||||
file:///D:/DEV/GitHub/Notepad3/test/test_files/StyleLexers/styleLexYAML/appveyor.yml
|
||||
styleLexYAML/appveyor.yml
|
||||
Loading…
Reference in New Issue
Block a user