Project-aware file navigation for Zed (and other editors) via projections.json.
A Rust port of Tim Pope's vim-projectionist.
- Alternate file navigation: Switch between source and test files
- Related file discovery: Find all files related to the current file
- Template-based file creation: Create new files with predefined templates
- 14 transformations: Transform placeholders (camelCase, snake_case, plural, etc.)
# From source
cargo install --path .
# From crates.io (when published)
cargo install projectionist-
Create a
projections.jsonconfiguration file in your project root:.projections.json(vim-projectionist compatible).zed/projections.json(Zed-specific location)
Example:
{
"src/*.ts": {
"alternate": "test/{}.test.ts",
"type": "source"
},
"test/*.test.ts": {
"alternate": "src/{}.ts",
"type": "test"
}
}- Use the CLI:
# Find alternate file
projectionist alternate src/utils.ts
# Open alternate in Zed
projectionist alternate src/utils.ts --open
# Find related files
projectionist related src/components/Button.tsx
# Create file from template
projectionist create src/components/NewComponent.tsx
# Show projection info
projectionist info src/utils.ts[
{
"label": "Switch to Alternate File",
"command": "projectionist",
"args": ["alternate", "$ZED_FILE", "--open"],
"cwd": "$ZED_WORKTREE_ROOT",
"reveal": "never",
"hide": "always"
},
{
"label": "Show Projection Info",
"command": "projectionist",
"args": ["info", "$ZED_FILE"],
"cwd": "$ZED_WORKTREE_ROOT",
"reveal": "always"
}
]Important: You MUST include
"reevaluate_context": trueor Zed will cache the file path.
[
{
"context": "Editor && !menu",
"bindings": {
"ctrl-shift-a": [
"task::Spawn",
{ "task_name": "Switch to Alternate File", "reevaluate_context": true }
]
}
}
]The CLI searches for configuration files in the following order (first found wins):
| Location | Description |
|---|---|
.projections.json |
Root of project (vim-projectionist compatible) |
.zed/projections.json |
Inside .zed directory (Zed-specific) |
If both files exist, .projections.json takes priority for vim-projectionist compatibility.
The configuration file maps glob patterns to configurations:
{
"src/components/*.tsx": {
"alternate": "src/components/{}.test.tsx",
"related": ["src/components/{}.module.css", "src/components/{}.stories.tsx"],
"type": "component",
"template": [
"import React from 'react';",
"",
"export const {}: React.FC = () => {",
" return <div>{}</div>;",
"};"
],
"define": "export const {}"
}
}| Property | Type | Description |
|---|---|---|
alternate |
string |
Primary alternate file pattern |
related |
string[] |
Array of related file patterns |
type |
string |
File type identifier |
template |
string[] |
Template lines for new file creation |
define |
string |
Search pattern for auto-scroll |
| Syntax | Description |
|---|---|
{} |
The captured stem (everything matched by *) |
{name} |
Named placeholder |
{|transform} |
Stem with transformation |
{|t1|t2} |
Chained transformations |
Path separators:
dot- Replace/with.underscore- Replace/with_backslash- Replace/with\colons- Replace/with::
Case:
uppercase- Convert to UPPERCASElowercase- Convert to lowercasecamelcase- Convert to camelCasesnakecase- Convert to snake_casehyphenate- Replace_with-
Path components:
dirname- Directory portionbasename- File name onlyfile- Name without extensionext- Extension only
Inflection:
plural- Pluralize (user → users)singular- Singularize (users → user)
{
"src/components/*.tsx": {
"alternate": "src/components/{}.test.tsx",
"related": ["src/components/{}.module.css"],
"type": "component"
},
"src/components/*.test.tsx": {
"alternate": "src/components/{}.tsx",
"type": "test"
}
}{
"*.go": {
"alternate": "{}_test.go",
"type": "source"
},
"*_test.go": {
"alternate": "{}.go",
"type": "test"
}
}{
"app/models/*.rb": {
"alternate": "spec/models/{}_spec.rb",
"related": ["db/schema.rb"],
"define": "create_table \"{|plural}\"",
"type": "model"
},
"app/controllers/*_controller.rb": {
"alternate": "spec/controllers/{}_controller_spec.rb",
"type": "controller"
}
}projectionist <COMMAND>
Commands:
alternate Find alternate file(s) for the given file
related Find related files for the given file
create Create a new file from template
info Show projection info for a file
validate Validate .projections.json configuration
Options:
-h, --help Print help
-V, --version Print version
projectionist alternate <FILE> [OPTIONS]
Options:
-l, --line <LINE> Line number for cursor-aware features
-o, --open Open result in Zed editor
-j, --json Output as JSON
--create-if-missing Create the alternate file from template if missing
-v, --verbose Show verbose matching information
projectionist related <FILE> [OPTIONS]
Options:
-l, --line <LINE> Line number for cursor-aware features
-j, --json Output as JSON
--fzf Output one file per line for fzf/pipe usage
-v, --verbose Show verbose information
projectionist create <FILE> [OPTIONS]
Options:
-f, --force Overwrite if file already exists
-o, --open Open the created file in Zed
projectionist info <FILE> [OPTIONS]
Options:
-l, --line <LINE> Line number for cursor-aware features
-j, --json Output as JSON
-v, --verbose Show verbose information
MIT