Language Server Protocol (LSP) Guide
What is LSP?
Language Server Protocol (LSP) is like having a smart assistant that understands your programming language. It provides IDE-like features such as:
- Error detection as you type
- Jump to definition of functions/variables
- Find all references to a symbol
- Auto-completion suggestions
- Rename symbols across your entire project
- Code formatting to keep style consistent
- Quick fixes for common errors
Instead of building these features separately for each language, LSP uses a standardized protocol. This means fac can support Python, JavaScript, Fortran, Rust, and 100+ other languages using the same system!
How Does It Work?
┌─────────────┐ LSP Protocol ┌──────────────────┐
│ │ ◄────────────────────────────► │ Language Server │
│ fac Editor │ (JSON messages over stdio) │ (e.g., pylsp) │
│ │ │ │
└─────────────┘ └──────────────────┘
│ │
│ You edit code │ Analyzes code
│ Send changes │ Finds errors
│ Request features │ Provides completions
When you open a file in fac:
facstarts the appropriate language server (e.g.,pylspfor Python)factells the server what file you're editing- As you type,
facsends your changes to the server - The server analyzes your code and sends back diagnostics (errors/warnings)
- When you press F12,
facasks the server "where is this defined?" - The server responds with the location, and
facjumps there
Quick Start
Step 1: Install a Language Server
Language servers are separate programs you install once. Here are the most common ones:
Python:
pip install python-lsp-server
JavaScript/TypeScript:
npm install -g typescript-language-server typescript
Rust:
rustup component add rust-analyzer
Fortran:
pip install fortls
Go:
go install golang.org/x/tools/gopls@latest
C/C++:
# On macOS with Homebrew
brew install llvm
# clangd comes with LLVM
# On Linux
sudo apt install clangd
See the Language Server Setup section below for detailed instructions.
Step 2: Open a File
Just open fac with a source code file:
fac my_script.py
That's it! If you have pylsp installed, fac will automatically:
- Start the language server
- Begin analyzing your code
- Show errors/warnings with red/yellow markers in the gutter
- Enable all LSP features
Step 3: Try It Out
- See errors: Look for
E(error) orW(warning) in the left gutter - View all diagnostics: Press
F8to open the diagnostics panel - Jump to definition: Put cursor on a function name and press
F12 - Find references: Press
Shift+F12to see everywhere a symbol is used - Rename: Press
F2to rename a variable across all files - Format code: Press
Shift+Alt+Fto auto-format
LSP Features Reference
1. Diagnostics (Errors & Warnings)
What it does: Shows syntax errors, type errors, and warnings as you code.
How to use:
- Errors appear with
Ein the gutter (red) - Warnings appear with
Win the gutter (yellow) - Put your cursor on a line with an error to see the message in the status bar
- Press
F8to open the Diagnostics Panel showing all issues
Example:
def greet(name):
print("Hello, " + nme) # Error: 'nme' is not defined
^^^^^^^^^^^^^^^^^^^^
E: Undefined name 'nme'
Keybinding:
F8orAlt+E- Open/close diagnostics panelj/kor↑/↓- Navigate issues in panelEnter- Jump to selected issueEsc- Close panel
2. Go to Definition (F12)
What it does: Jump to where a function, variable, or class is defined.
How to use:
- Put your cursor on a symbol (function name, variable, class, etc.)
- Press
F12 facjumps to the definition (opens file in new tab if needed)- Press
Alt+,to jump back to where you were
Example:
# In main.py
result = calculate_total(items)
^^^^^^^^^^^^^^^
Put cursor here, press F12
# Jumps to utils.py:
def calculate_total(items): # ← You land here
return sum(item.price for item in items)
Keybindings:
F12orCtrl+\orAlt+G- Go to definitionAlt+,- Jump back (navigate backward in jump history)
Cross-file navigation: If the definition is in another file, fac automatically opens it in a new tab!
3. Find References (Shift+F12)
What it does: Find all places where a symbol is used across your entire project.
How to use:
- Put cursor on a symbol
- Press
Shift+F12 - Browse references in the panel
- Press
Enterto jump to a reference
Example:
# You want to find everywhere `calculate_total` is called
def calculate_total(items):
...
# Press Shift+F12 shows:
References to 'calculate_total':
main.py:15:12 - result = calculate_total(items)
test.py:23:8 - assert calculate_total([]) == 0
utils.py:45:3 - total = calculate_total(cart.items)
Keybindings:
Shift+F12orAlt+R- Find all referencesj/kor↑/↓- Navigate referencesEnter- Jump to selected referenceEsc- Close panel
4. Code Actions & Quick Fixes (Alt+.)
What it does: Get quick fixes for errors and refactoring suggestions.
How to use:
- Put cursor on a line with a diagnostic (error/warning)
- Press
F10orAlt+. - Select an action from the menu
- Press
Enterto apply it
Example:
# Error: Missing import
result = json.loads(data)
^^^^
Error: 'json' is not defined
# Press Ctrl+. shows:
Code Actions:
→ Import 'json'
Ignore undefined name 'json'
# Select "Import 'json'" and fac adds:
import json # ← Automatically added!
Common actions:
- Add missing imports
- Fix spelling errors in variable names
- Extract method/function
- Organize imports
- Add type hints
Keybindings:
F10orAlt+.- Open code actions menuj/kor↑/↓- Navigate actions1-9- Quick select action by numberEnter- Apply selected actionEsc- Close menu
Note: Code actions are context-sensitive. On a line without diagnostics, you'll only see global actions like "Organize imports" and "Fix all". Position cursor on a line with an error/warning to see specific fixes.
5. Rename Symbol (F2)
What it does: Rename a variable, function, or class everywhere it's used.
How to use:
- Put cursor on a symbol
- Press
F2 - Type the new name
- Press
Enter - The symbol is renamed everywhere across all files!
Example:
# Before:
def calc(x, y):
return x + y
result = calc(5, 3)
total = calc(10, 20)
# Put cursor on 'calc', press F2, type 'calculate'
# After:
def calculate(x, y):
return x + y
result = calculate(5, 3)
total = calculate(10, 20)
Safe renaming: The language server understands your code's structure, so it won't accidentally rename:
- String contents:
"call calc function"stays unchanged - Comments:
# calc is faststays unchanged - Unrelated variables with the same name in different scopes
Keybinding:
F2- Rename symbol- Type new name, press
Enterto confirm - Press
Escto cancel
6. Document Symbols Outline (F4)
What it does: See an outline of all functions, classes, and variables in the current file.
How to use:
- Press
F4to open the symbols panel - Type to filter symbols (fuzzy search)
- Press
Enterto jump to a symbol
Example:
Document Symbols:
[Class] User
[Method] __init__
[Method] validate
[Property] full_name
[Function] create_user
[Function] delete_user
[Variable] DEFAULT_TIMEOUT
Keybindings:
F4orAlt+O- Open document symbols panel- Type to search (fuzzy matching)
j/kor↑/↓- Navigate symbolsEnter- Jump to selected symbolEsc- Close panel
7. Workspace Symbols (F6)
What it does: Search for any symbol across your entire project (all files).
How to use:
- Press
F6to open workspace symbols - Type part of a symbol name (fuzzy search)
- Navigate and press
Enterto jump to it
Example:
# Type "calc"
Workspace Symbols:
[Function] calculate_total in utils.py
[Function] calculator_init in calculator.py
[Class] Calculator in calculator.py
[Method] recalculate in models.py
[Variable] CALC_PRECISION in config.py
Fuzzy search: You don't need to type the exact name:
calcmatchescalculate_totalctmatchescalculate_total(first letters)calctotmatchescalculate_total(consecutive)
Keybindings:
F6orAlt+P- Open workspace symbols- Type to search across all files
j/kor↑/↓- Navigate resultsEnter- Jump to symbol (opens file if needed)Esc- Close panel
Pro tip: This is incredibly fast for navigating large codebases!
8. Signature Help
What it does: Shows function parameters and types as you're typing a function call.
How to use:
Just start typing a function call with (, and a tooltip appears:
Example:
# You type:
result = calculate_total(
^
Cursor here
# Tooltip shows:
calculate_total(items: list[Item], tax_rate: float = 0.0) -> float
^^^^^
Current parameter highlighted
Keybindings:
- Appears automatically when you type
( - Type
,to move to next parameter - Auto-dismisses when you type
)
Works with:
- Regular functions
- Class constructors
- Methods
- Overloaded functions (shows all signatures)
9. Document Formatting (Shift+Alt+F)
What it does: Automatically formats your code according to style guidelines.
How to use:
- Press
Shift+Alt+F - Your code is instantly formatted
Example:
# Before:
def greet( name,age ):
if age>18:
print( "Hello, "+name )
else:print("Hi, "+name)
# After (Shift+Alt+F):
def greet(name, age):
if age > 18:
print("Hello, " + name)
else:
print("Hi, " + name)
Respects:
.editorconfigsettings- Language-specific style guides (PEP 8 for Python, etc.)
- Project configuration files (
.pylintrc,pyproject.toml, etc.)
Keybinding:
Shift+Alt+F- Format entire document
Formatters by language:
- Python:
black,autopep8, oryapf(configured inpylsp) - JavaScript:
prettier - Rust:
rustfmt - Go:
gofmt
10. Command Palette (Ctrl+P)
What it does: Quick access to all LSP commands without remembering keybindings.
How to use:
- Press
Ctrl+P - Type to search commands (fuzzy search)
- Press
Enterto execute
Available commands:
Command Palette:
[LSP] Go to Definition
[LSP] Find References
[LSP] Rename Symbol
[LSP] Code Actions
[LSP] Document Symbols
[LSP] Workspace Symbols
[LSP] Format Document
[File] Save File
[Navigate] Jump Back
... and 40+ more!
Keybindings:
Ctrl+P- Open command palette- Type to search commands
Enter- Execute selected commandEsc- Close palette
Language Server Setup
Python (pylsp)
Install:
pip install python-lsp-server
# Optional plugins for more features:
pip install python-lsp-black # Black formatting
pip install pylsp-mypy # Type checking
pip install python-lsp-ruff # Fast linting
What you get:
- Error detection (syntax, undefined variables)
- Auto-completion
- Go to definition / Find references
- Rename symbol
- Code formatting (with black)
- Type checking (with mypy)
Configuration:
Create ~/.config/pylsp/config.json:
{
"plugins": {
"black": {"enabled": true},
"mypy": {"enabled": true}
}
}
JavaScript/TypeScript (typescript-language-server)
Install:
npm install -g typescript-language-server typescript
What you get:
- Error detection (TypeScript type errors)
- Auto-completion with type information
- Refactoring (extract function, rename, etc.)
- Import management
- JSDoc support
Works with:
- JavaScript (
.js) - TypeScript (
.ts,.tsx) - JSX/React files
Rust (rust-analyzer)
Install:
rustup component add rust-analyzer
What you get:
- Instant error detection
- Powerful type inference
- Macro expansion
- Cargo integration
- Inline type hints
Note: Works best with Cargo.toml in your project root.
Fortran (fortls)
Install:
pip install fortls
What you get:
- Syntax error detection
- Module/subroutine navigation
- Variable completion
- Signature help
- Hover documentation
Configuration:
Create .fortls in your project root:
{
"lowercase_intrinsics": true,
"hover_signature": true,
"use_signature_help": true
}
Go (gopls)
Install:
go install golang.org/x/tools/gopls@latest
What you get:
- Error detection
- Auto-imports
- Refactoring tools
- Test integration
- Fast navigation
C/C++ (clangd)
Install:
# macOS
brew install llvm
# Ubuntu/Debian
sudo apt install clangd
# Arch
sudo pacman -S clang
What you get:
- Real-time error checking
- Include path completion
- Cross-reference navigation
- Refactoring support
Configuration:
Create compile_commands.json in project root:
# With CMake:
cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=1 .
# With Make:
bear -- make
Troubleshooting
"No language server found"
Problem: fac can't find the language server executable.
Solution:
-
Make sure the language server is installed:
which pylsp # For Python which rust-analyzer # For Rust which gopls # For Go -
Make sure the executable is in your
PATH:echo $PATH -
Try running the language server manually:
pylsp --help
"LSP features not working"
Problem: File opens but no diagnostics/features appear.
Solution:
-
Check if the server started:
- Look in
fac's logs (if available) - The server might have crashed on startup
- Look in
-
Check file extension matches language:
.py→ Python.rs→ Rust.f90,.f95→ Fortran
-
Make sure the file is in a proper project structure:
- Python: Have a
setup.pyorpyproject.toml? - Rust: Have a
Cargo.toml? - Some servers need project metadata
- Python: Have a
"Diagnostics are slow/delayed"
Problem: Errors appear several seconds after typing.
Explanation: This is normal! Language servers analyze your code:
- Simple syntax errors: ~100ms
- Type checking: 500ms-2s
- Full project analysis: 2-10s
Tips:
facdebounces changes (waits 500ms after you stop typing)- Large projects take longer
- First-time analysis is slower (builds cache)
"Server keeps crashing"
Problem: LSP features work then suddenly stop.
Solution:
-
Check server version:
pylsp --version -
Update the language server:
pip install --upgrade python-lsp-server -
Check for conflicting plugins/extensions
-
Restart
fac
"Formatting changes my code unexpectedly"
Problem: Shift+Alt+F makes unwanted changes.
Solution:
-
Check your formatter configuration
-
Many formatters respect configuration files:
- Python:
pyproject.tomlor.pylintrc - JavaScript:
.prettierrc - Rust:
rustfmt.toml
- Python:
-
Configure line length, indentation, etc. in those files
Tips & Tricks
1. Use Jump Stack for Navigation
After using F12 to jump to a definition:
- Press
Alt+,to jump back - Works across multiple jumps (maintains history)
- Great for exploring unfamiliar codebases
2. Combine Search Features
Ctrl+F- Search text in current fileF4- Search symbols in current fileF6- Search symbols across projectShift+F12- Find all usages of current symbol
3. Fix Errors Faster
When you see an error:
- Press
F8to see all errors - Navigate to each error
- Press
Ctrl+.to see quick fixes - Apply fixes with
Enter
4. Rename Safely
Before renaming:
- Press
Shift+F12to see all references - Verify it's safe to rename
- Press
F2to rename everywhere at once
5. Format on Save
Many language servers support format-on-save:
- Press
Ctrl+Sto save - File is automatically formatted
- Keeps your code style consistent
LSP Keybindings Quick Reference
| Feature | Keybinding | What It Does |
|---|---|---|
| Diagnostics Panel | F8 or Alt+E |
Show all errors/warnings |
| Go to Definition | F12 or Ctrl+\ or Alt+G |
Jump to where symbol is defined |
| Find References | Shift+F12 or Alt+R |
Find all usages of symbol |
| Code Actions | F10 or Alt+. |
Quick fixes and refactorings |
| Rename Symbol | F2 |
Rename across entire project |
| Document Symbols | F4 or Alt+O |
Outline of current file |
| Workspace Symbols | F6 or Alt+P |
Search symbols across project |
| Format Document | Shift+Alt+F |
Auto-format code |
| Command Palette | Ctrl+P |
Access all commands |
| Jump Back | Alt+, |
Return to previous location |
Note: Alt+key combinations work better in terminals than Ctrl+Shift combinations.
Supported Languages
fac can work with any language that has an LSP server. Here are popular ones:
| Language | Server | Installation |
|---|---|---|
| Python | pylsp |
pip install python-lsp-server |
| JavaScript/TypeScript | typescript-language-server |
npm install -g typescript-language-server |
| Rust | rust-analyzer |
rustup component add rust-analyzer |
| Go | gopls |
go install golang.org/x/tools/gopls@latest |
| C/C++ | clangd |
brew install llvm or apt install clangd |
| Java | jdtls |
Download from Eclipse |
| Ruby | solargraph |
gem install solargraph |
| PHP | intelephense |
npm install -g intelephense |
| Bash | bash-language-server |
npm install -g bash-language-server |
| Fortran | fortls |
pip install fortls |
| Lua | lua-language-server |
Download from GitHub |
| HTML/CSS | vscode-html-languageserver |
npm install -g vscode-html-languageserver-bin |
For more language servers, visit: https://microsoft.github.io/language-server-protocol/implementors/servers/
What's Next?
Now that you understand LSP in fac:
- Install language servers for your languages
- Practice the keybindings - they'll become second nature
- Explore your codebase with
F6andF12 - Let LSP catch errors before you run your code
- Refactor confidently with
F2andCtrl+.
Welcome to IDE-level coding in the terminal! 🚀
View source
| 1 | # Language Server Protocol (LSP) Guide |
| 2 | |
| 3 | ## What is LSP? |
| 4 | |
| 5 | **Language Server Protocol (LSP)** is like having a smart assistant that understands your programming language. It provides IDE-like features such as: |
| 6 | |
| 7 | - **Error detection** as you type |
| 8 | - **Jump to definition** of functions/variables |
| 9 | - **Find all references** to a symbol |
| 10 | - **Auto-completion** suggestions |
| 11 | - **Rename** symbols across your entire project |
| 12 | - **Code formatting** to keep style consistent |
| 13 | - **Quick fixes** for common errors |
| 14 | |
| 15 | Instead of building these features separately for each language, LSP uses a standardized protocol. This means `fac` can support Python, JavaScript, Fortran, Rust, and 100+ other languages using the same system! |
| 16 | |
| 17 | ## How Does It Work? |
| 18 | |
| 19 | ``` |
| 20 | ┌─────────────┐ LSP Protocol ┌──────────────────┐ |
| 21 | │ │ ◄────────────────────────────► │ Language Server │ |
| 22 | │ fac Editor │ (JSON messages over stdio) │ (e.g., pylsp) │ |
| 23 | │ │ │ │ |
| 24 | └─────────────┘ └──────────────────┘ |
| 25 | │ │ |
| 26 | │ You edit code │ Analyzes code |
| 27 | │ Send changes │ Finds errors |
| 28 | │ Request features │ Provides completions |
| 29 | ``` |
| 30 | |
| 31 | When you open a file in `fac`: |
| 32 | 1. `fac` starts the appropriate language server (e.g., `pylsp` for Python) |
| 33 | 2. `fac` tells the server what file you're editing |
| 34 | 3. As you type, `fac` sends your changes to the server |
| 35 | 4. The server analyzes your code and sends back diagnostics (errors/warnings) |
| 36 | 5. When you press F12, `fac` asks the server "where is this defined?" |
| 37 | 6. The server responds with the location, and `fac` jumps there |
| 38 | |
| 39 | ## Quick Start |
| 40 | |
| 41 | ### Step 1: Install a Language Server |
| 42 | |
| 43 | Language servers are separate programs you install once. Here are the most common ones: |
| 44 | |
| 45 | **Python:** |
| 46 | ```bash |
| 47 | pip install python-lsp-server |
| 48 | ``` |
| 49 | |
| 50 | **JavaScript/TypeScript:** |
| 51 | ```bash |
| 52 | npm install -g typescript-language-server typescript |
| 53 | ``` |
| 54 | |
| 55 | **Rust:** |
| 56 | ```bash |
| 57 | rustup component add rust-analyzer |
| 58 | ``` |
| 59 | |
| 60 | **Fortran:** |
| 61 | ```bash |
| 62 | pip install fortls |
| 63 | ``` |
| 64 | |
| 65 | **Go:** |
| 66 | ```bash |
| 67 | go install golang.org/x/tools/gopls@latest |
| 68 | ``` |
| 69 | |
| 70 | **C/C++:** |
| 71 | ```bash |
| 72 | # On macOS with Homebrew |
| 73 | brew install llvm |
| 74 | # clangd comes with LLVM |
| 75 | |
| 76 | # On Linux |
| 77 | sudo apt install clangd |
| 78 | ``` |
| 79 | |
| 80 | See the **Language Server Setup** section below for detailed instructions. |
| 81 | |
| 82 | ### Step 2: Open a File |
| 83 | |
| 84 | Just open `fac` with a source code file: |
| 85 | |
| 86 | ```bash |
| 87 | fac my_script.py |
| 88 | ``` |
| 89 | |
| 90 | That's it! If you have `pylsp` installed, `fac` will automatically: |
| 91 | - Start the language server |
| 92 | - Begin analyzing your code |
| 93 | - Show errors/warnings with red/yellow markers in the gutter |
| 94 | - Enable all LSP features |
| 95 | |
| 96 | ### Step 3: Try It Out |
| 97 | |
| 98 | 1. **See errors**: Look for `E` (error) or `W` (warning) in the left gutter |
| 99 | 2. **View all diagnostics**: Press `F8` to open the diagnostics panel |
| 100 | 3. **Jump to definition**: Put cursor on a function name and press `F12` |
| 101 | 4. **Find references**: Press `Shift+F12` to see everywhere a symbol is used |
| 102 | 5. **Rename**: Press `F2` to rename a variable across all files |
| 103 | 6. **Format code**: Press `Shift+Alt+F` to auto-format |
| 104 | |
| 105 | --- |
| 106 | |
| 107 | ## LSP Features Reference |
| 108 | |
| 109 | ### 1. Diagnostics (Errors & Warnings) |
| 110 | |
| 111 | **What it does:** Shows syntax errors, type errors, and warnings as you code. |
| 112 | |
| 113 | **How to use:** |
| 114 | - Errors appear with `E` in the gutter (red) |
| 115 | - Warnings appear with `W` in the gutter (yellow) |
| 116 | - Put your cursor on a line with an error to see the message in the status bar |
| 117 | - Press `F8` to open the **Diagnostics Panel** showing all issues |
| 118 | |
| 119 | **Example:** |
| 120 | ```python |
| 121 | def greet(name): |
| 122 | print("Hello, " + nme) # Error: 'nme' is not defined |
| 123 | ^^^^^^^^^^^^^^^^^^^^ |
| 124 | E: Undefined name 'nme' |
| 125 | ``` |
| 126 | |
| 127 | **Keybinding:** |
| 128 | - `F8` or `Alt+E` - Open/close diagnostics panel |
| 129 | - `j`/`k` or `↑`/`↓` - Navigate issues in panel |
| 130 | - `Enter` - Jump to selected issue |
| 131 | - `Esc` - Close panel |
| 132 | |
| 133 | --- |
| 134 | |
| 135 | ### 2. Go to Definition (F12) |
| 136 | |
| 137 | **What it does:** Jump to where a function, variable, or class is defined. |
| 138 | |
| 139 | **How to use:** |
| 140 | 1. Put your cursor on a symbol (function name, variable, class, etc.) |
| 141 | 2. Press `F12` |
| 142 | 3. `fac` jumps to the definition (opens file in new tab if needed) |
| 143 | 4. Press `Alt+,` to jump back to where you were |
| 144 | |
| 145 | **Example:** |
| 146 | ```python |
| 147 | # In main.py |
| 148 | result = calculate_total(items) |
| 149 | ^^^^^^^^^^^^^^^ |
| 150 | Put cursor here, press F12 |
| 151 | |
| 152 | # Jumps to utils.py: |
| 153 | def calculate_total(items): # ← You land here |
| 154 | return sum(item.price for item in items) |
| 155 | ``` |
| 156 | |
| 157 | **Keybindings:** |
| 158 | - `F12` or `Ctrl+\` or `Alt+G` - Go to definition |
| 159 | - `Alt+,` - Jump back (navigate backward in jump history) |
| 160 | |
| 161 | **Cross-file navigation:** If the definition is in another file, `fac` automatically opens it in a new tab! |
| 162 | |
| 163 | --- |
| 164 | |
| 165 | ### 3. Find References (Shift+F12) |
| 166 | |
| 167 | **What it does:** Find all places where a symbol is used across your entire project. |
| 168 | |
| 169 | **How to use:** |
| 170 | 1. Put cursor on a symbol |
| 171 | 2. Press `Shift+F12` |
| 172 | 3. Browse references in the panel |
| 173 | 4. Press `Enter` to jump to a reference |
| 174 | |
| 175 | **Example:** |
| 176 | ```python |
| 177 | # You want to find everywhere `calculate_total` is called |
| 178 | def calculate_total(items): |
| 179 | ... |
| 180 | |
| 181 | # Press Shift+F12 shows: |
| 182 | References to 'calculate_total': |
| 183 | main.py:15:12 - result = calculate_total(items) |
| 184 | test.py:23:8 - assert calculate_total([]) == 0 |
| 185 | utils.py:45:3 - total = calculate_total(cart.items) |
| 186 | ``` |
| 187 | |
| 188 | **Keybindings:** |
| 189 | - `Shift+F12` or `Alt+R` - Find all references |
| 190 | - `j`/`k` or `↑`/`↓` - Navigate references |
| 191 | - `Enter` - Jump to selected reference |
| 192 | - `Esc` - Close panel |
| 193 | |
| 194 | --- |
| 195 | |
| 196 | ### 4. Code Actions & Quick Fixes (Alt+.) |
| 197 | |
| 198 | **What it does:** Get quick fixes for errors and refactoring suggestions. |
| 199 | |
| 200 | **How to use:** |
| 201 | 1. Put cursor on a line with a diagnostic (error/warning) |
| 202 | 2. Press `F10` or `Alt+.` |
| 203 | 3. Select an action from the menu |
| 204 | 4. Press `Enter` to apply it |
| 205 | |
| 206 | **Example:** |
| 207 | ```python |
| 208 | # Error: Missing import |
| 209 | result = json.loads(data) |
| 210 | ^^^^ |
| 211 | Error: 'json' is not defined |
| 212 | |
| 213 | # Press Ctrl+. shows: |
| 214 | Code Actions: |
| 215 | → Import 'json' |
| 216 | Ignore undefined name 'json' |
| 217 | |
| 218 | # Select "Import 'json'" and fac adds: |
| 219 | import json # ← Automatically added! |
| 220 | ``` |
| 221 | |
| 222 | **Common actions:** |
| 223 | - Add missing imports |
| 224 | - Fix spelling errors in variable names |
| 225 | - Extract method/function |
| 226 | - Organize imports |
| 227 | - Add type hints |
| 228 | |
| 229 | **Keybindings:** |
| 230 | - `F10` or `Alt+.` - Open code actions menu |
| 231 | - `j`/`k` or `↑`/`↓` - Navigate actions |
| 232 | - `1`-`9` - Quick select action by number |
| 233 | - `Enter` - Apply selected action |
| 234 | - `Esc` - Close menu |
| 235 | |
| 236 | **Note:** Code actions are context-sensitive. On a line without diagnostics, you'll only see global actions like "Organize imports" and "Fix all". Position cursor on a line with an error/warning to see specific fixes. |
| 237 | |
| 238 | --- |
| 239 | |
| 240 | ### 5. Rename Symbol (F2) |
| 241 | |
| 242 | **What it does:** Rename a variable, function, or class everywhere it's used. |
| 243 | |
| 244 | **How to use:** |
| 245 | 1. Put cursor on a symbol |
| 246 | 2. Press `F2` |
| 247 | 3. Type the new name |
| 248 | 4. Press `Enter` |
| 249 | 5. The symbol is renamed everywhere across all files! |
| 250 | |
| 251 | **Example:** |
| 252 | ```python |
| 253 | # Before: |
| 254 | def calc(x, y): |
| 255 | return x + y |
| 256 | |
| 257 | result = calc(5, 3) |
| 258 | total = calc(10, 20) |
| 259 | |
| 260 | # Put cursor on 'calc', press F2, type 'calculate' |
| 261 | # After: |
| 262 | def calculate(x, y): |
| 263 | return x + y |
| 264 | |
| 265 | result = calculate(5, 3) |
| 266 | total = calculate(10, 20) |
| 267 | ``` |
| 268 | |
| 269 | **Safe renaming:** The language server understands your code's structure, so it won't accidentally rename: |
| 270 | - String contents: `"call calc function"` stays unchanged |
| 271 | - Comments: `# calc is fast` stays unchanged |
| 272 | - Unrelated variables with the same name in different scopes |
| 273 | |
| 274 | **Keybinding:** |
| 275 | - `F2` - Rename symbol |
| 276 | - Type new name, press `Enter` to confirm |
| 277 | - Press `Esc` to cancel |
| 278 | |
| 279 | --- |
| 280 | |
| 281 | ### 6. Document Symbols Outline (F4) |
| 282 | |
| 283 | **What it does:** See an outline of all functions, classes, and variables in the current file. |
| 284 | |
| 285 | **How to use:** |
| 286 | 1. Press `F4` to open the symbols panel |
| 287 | 2. Type to filter symbols (fuzzy search) |
| 288 | 3. Press `Enter` to jump to a symbol |
| 289 | |
| 290 | **Example:** |
| 291 | ``` |
| 292 | Document Symbols: |
| 293 | [Class] User |
| 294 | [Method] __init__ |
| 295 | [Method] validate |
| 296 | [Property] full_name |
| 297 | [Function] create_user |
| 298 | [Function] delete_user |
| 299 | [Variable] DEFAULT_TIMEOUT |
| 300 | ``` |
| 301 | |
| 302 | **Keybindings:** |
| 303 | - `F4` or `Alt+O` - Open document symbols panel |
| 304 | - Type to search (fuzzy matching) |
| 305 | - `j`/`k` or `↑`/`↓` - Navigate symbols |
| 306 | - `Enter` - Jump to selected symbol |
| 307 | - `Esc` - Close panel |
| 308 | |
| 309 | --- |
| 310 | |
| 311 | ### 7. Workspace Symbols (F6) |
| 312 | |
| 313 | **What it does:** Search for any symbol across your **entire project** (all files). |
| 314 | |
| 315 | **How to use:** |
| 316 | 1. Press `F6` to open workspace symbols |
| 317 | 2. Type part of a symbol name (fuzzy search) |
| 318 | 3. Navigate and press `Enter` to jump to it |
| 319 | |
| 320 | **Example:** |
| 321 | ``` |
| 322 | # Type "calc" |
| 323 | Workspace Symbols: |
| 324 | [Function] calculate_total in utils.py |
| 325 | [Function] calculator_init in calculator.py |
| 326 | [Class] Calculator in calculator.py |
| 327 | [Method] recalculate in models.py |
| 328 | [Variable] CALC_PRECISION in config.py |
| 329 | ``` |
| 330 | |
| 331 | **Fuzzy search:** You don't need to type the exact name: |
| 332 | - `calc` matches `calculate_total` |
| 333 | - `ct` matches `calculate_total` (first letters) |
| 334 | - `calctot` matches `calculate_total` (consecutive) |
| 335 | |
| 336 | **Keybindings:** |
| 337 | - `F6` or `Alt+P` - Open workspace symbols |
| 338 | - Type to search across all files |
| 339 | - `j`/`k` or `↑`/`↓` - Navigate results |
| 340 | - `Enter` - Jump to symbol (opens file if needed) |
| 341 | - `Esc` - Close panel |
| 342 | |
| 343 | **Pro tip:** This is incredibly fast for navigating large codebases! |
| 344 | |
| 345 | --- |
| 346 | |
| 347 | ### 8. Signature Help |
| 348 | |
| 349 | **What it does:** Shows function parameters and types as you're typing a function call. |
| 350 | |
| 351 | **How to use:** |
| 352 | Just start typing a function call with `(`, and a tooltip appears: |
| 353 | |
| 354 | **Example:** |
| 355 | ```python |
| 356 | # You type: |
| 357 | result = calculate_total( |
| 358 | ^ |
| 359 | Cursor here |
| 360 | |
| 361 | # Tooltip shows: |
| 362 | calculate_total(items: list[Item], tax_rate: float = 0.0) -> float |
| 363 | ^^^^^ |
| 364 | Current parameter highlighted |
| 365 | ``` |
| 366 | |
| 367 | **Keybindings:** |
| 368 | - Appears automatically when you type `(` |
| 369 | - Type `,` to move to next parameter |
| 370 | - Auto-dismisses when you type `)` |
| 371 | |
| 372 | **Works with:** |
| 373 | - Regular functions |
| 374 | - Class constructors |
| 375 | - Methods |
| 376 | - Overloaded functions (shows all signatures) |
| 377 | |
| 378 | --- |
| 379 | |
| 380 | ### 9. Document Formatting (Shift+Alt+F) |
| 381 | |
| 382 | **What it does:** Automatically formats your code according to style guidelines. |
| 383 | |
| 384 | **How to use:** |
| 385 | 1. Press `Shift+Alt+F` |
| 386 | 2. Your code is instantly formatted |
| 387 | |
| 388 | **Example:** |
| 389 | ```python |
| 390 | # Before: |
| 391 | def greet( name,age ): |
| 392 | if age>18: |
| 393 | print( "Hello, "+name ) |
| 394 | else:print("Hi, "+name) |
| 395 | |
| 396 | # After (Shift+Alt+F): |
| 397 | def greet(name, age): |
| 398 | if age > 18: |
| 399 | print("Hello, " + name) |
| 400 | else: |
| 401 | print("Hi, " + name) |
| 402 | ``` |
| 403 | |
| 404 | **Respects:** |
| 405 | - `.editorconfig` settings |
| 406 | - Language-specific style guides (PEP 8 for Python, etc.) |
| 407 | - Project configuration files (`.pylintrc`, `pyproject.toml`, etc.) |
| 408 | |
| 409 | **Keybinding:** |
| 410 | - `Shift+Alt+F` - Format entire document |
| 411 | |
| 412 | **Formatters by language:** |
| 413 | - Python: `black`, `autopep8`, or `yapf` (configured in `pylsp`) |
| 414 | - JavaScript: `prettier` |
| 415 | - Rust: `rustfmt` |
| 416 | - Go: `gofmt` |
| 417 | |
| 418 | --- |
| 419 | |
| 420 | ### 10. Command Palette (Ctrl+P) |
| 421 | |
| 422 | **What it does:** Quick access to all LSP commands without remembering keybindings. |
| 423 | |
| 424 | **How to use:** |
| 425 | 1. Press `Ctrl+P` |
| 426 | 2. Type to search commands (fuzzy search) |
| 427 | 3. Press `Enter` to execute |
| 428 | |
| 429 | **Available commands:** |
| 430 | ``` |
| 431 | Command Palette: |
| 432 | [LSP] Go to Definition |
| 433 | [LSP] Find References |
| 434 | [LSP] Rename Symbol |
| 435 | [LSP] Code Actions |
| 436 | [LSP] Document Symbols |
| 437 | [LSP] Workspace Symbols |
| 438 | [LSP] Format Document |
| 439 | [File] Save File |
| 440 | [Navigate] Jump Back |
| 441 | ... and 40+ more! |
| 442 | ``` |
| 443 | |
| 444 | **Keybindings:** |
| 445 | - `Ctrl+P` - Open command palette |
| 446 | - Type to search commands |
| 447 | - `Enter` - Execute selected command |
| 448 | - `Esc` - Close palette |
| 449 | |
| 450 | --- |
| 451 | |
| 452 | ## Language Server Setup |
| 453 | |
| 454 | ### Python (pylsp) |
| 455 | |
| 456 | **Install:** |
| 457 | ```bash |
| 458 | pip install python-lsp-server |
| 459 | |
| 460 | # Optional plugins for more features: |
| 461 | pip install python-lsp-black # Black formatting |
| 462 | pip install pylsp-mypy # Type checking |
| 463 | pip install python-lsp-ruff # Fast linting |
| 464 | ``` |
| 465 | |
| 466 | **What you get:** |
| 467 | - Error detection (syntax, undefined variables) |
| 468 | - Auto-completion |
| 469 | - Go to definition / Find references |
| 470 | - Rename symbol |
| 471 | - Code formatting (with black) |
| 472 | - Type checking (with mypy) |
| 473 | |
| 474 | **Configuration:** |
| 475 | Create `~/.config/pylsp/config.json`: |
| 476 | ```json |
| 477 | { |
| 478 | "plugins": { |
| 479 | "black": {"enabled": true}, |
| 480 | "mypy": {"enabled": true} |
| 481 | } |
| 482 | } |
| 483 | ``` |
| 484 | |
| 485 | --- |
| 486 | |
| 487 | ### JavaScript/TypeScript (typescript-language-server) |
| 488 | |
| 489 | **Install:** |
| 490 | ```bash |
| 491 | npm install -g typescript-language-server typescript |
| 492 | ``` |
| 493 | |
| 494 | **What you get:** |
| 495 | - Error detection (TypeScript type errors) |
| 496 | - Auto-completion with type information |
| 497 | - Refactoring (extract function, rename, etc.) |
| 498 | - Import management |
| 499 | - JSDoc support |
| 500 | |
| 501 | **Works with:** |
| 502 | - JavaScript (`.js`) |
| 503 | - TypeScript (`.ts`, `.tsx`) |
| 504 | - JSX/React files |
| 505 | |
| 506 | --- |
| 507 | |
| 508 | ### Rust (rust-analyzer) |
| 509 | |
| 510 | **Install:** |
| 511 | ```bash |
| 512 | rustup component add rust-analyzer |
| 513 | ``` |
| 514 | |
| 515 | **What you get:** |
| 516 | - Instant error detection |
| 517 | - Powerful type inference |
| 518 | - Macro expansion |
| 519 | - Cargo integration |
| 520 | - Inline type hints |
| 521 | |
| 522 | **Note:** Works best with `Cargo.toml` in your project root. |
| 523 | |
| 524 | --- |
| 525 | |
| 526 | ### Fortran (fortls) |
| 527 | |
| 528 | **Install:** |
| 529 | ```bash |
| 530 | pip install fortls |
| 531 | ``` |
| 532 | |
| 533 | **What you get:** |
| 534 | - Syntax error detection |
| 535 | - Module/subroutine navigation |
| 536 | - Variable completion |
| 537 | - Signature help |
| 538 | - Hover documentation |
| 539 | |
| 540 | **Configuration:** |
| 541 | Create `.fortls` in your project root: |
| 542 | ```json |
| 543 | { |
| 544 | "lowercase_intrinsics": true, |
| 545 | "hover_signature": true, |
| 546 | "use_signature_help": true |
| 547 | } |
| 548 | ``` |
| 549 | |
| 550 | --- |
| 551 | |
| 552 | ### Go (gopls) |
| 553 | |
| 554 | **Install:** |
| 555 | ```bash |
| 556 | go install golang.org/x/tools/gopls@latest |
| 557 | ``` |
| 558 | |
| 559 | **What you get:** |
| 560 | - Error detection |
| 561 | - Auto-imports |
| 562 | - Refactoring tools |
| 563 | - Test integration |
| 564 | - Fast navigation |
| 565 | |
| 566 | --- |
| 567 | |
| 568 | ### C/C++ (clangd) |
| 569 | |
| 570 | **Install:** |
| 571 | ```bash |
| 572 | # macOS |
| 573 | brew install llvm |
| 574 | |
| 575 | # Ubuntu/Debian |
| 576 | sudo apt install clangd |
| 577 | |
| 578 | # Arch |
| 579 | sudo pacman -S clang |
| 580 | ``` |
| 581 | |
| 582 | **What you get:** |
| 583 | - Real-time error checking |
| 584 | - Include path completion |
| 585 | - Cross-reference navigation |
| 586 | - Refactoring support |
| 587 | |
| 588 | **Configuration:** |
| 589 | Create `compile_commands.json` in project root: |
| 590 | ```bash |
| 591 | # With CMake: |
| 592 | cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=1 . |
| 593 | |
| 594 | # With Make: |
| 595 | bear -- make |
| 596 | ``` |
| 597 | |
| 598 | --- |
| 599 | |
| 600 | ## Troubleshooting |
| 601 | |
| 602 | ### "No language server found" |
| 603 | |
| 604 | **Problem:** `fac` can't find the language server executable. |
| 605 | |
| 606 | **Solution:** |
| 607 | 1. Make sure the language server is installed: |
| 608 | ```bash |
| 609 | which pylsp # For Python |
| 610 | which rust-analyzer # For Rust |
| 611 | which gopls # For Go |
| 612 | ``` |
| 613 | |
| 614 | 2. Make sure the executable is in your `PATH`: |
| 615 | ```bash |
| 616 | echo $PATH |
| 617 | ``` |
| 618 | |
| 619 | 3. Try running the language server manually: |
| 620 | ```bash |
| 621 | pylsp --help |
| 622 | ``` |
| 623 | |
| 624 | --- |
| 625 | |
| 626 | ### "LSP features not working" |
| 627 | |
| 628 | **Problem:** File opens but no diagnostics/features appear. |
| 629 | |
| 630 | **Solution:** |
| 631 | 1. Check if the server started: |
| 632 | - Look in `fac`'s logs (if available) |
| 633 | - The server might have crashed on startup |
| 634 | |
| 635 | 2. Check file extension matches language: |
| 636 | - `.py` → Python |
| 637 | - `.rs` → Rust |
| 638 | - `.f90`, `.f95` → Fortran |
| 639 | |
| 640 | 3. Make sure the file is in a proper project structure: |
| 641 | - Python: Have a `setup.py` or `pyproject.toml`? |
| 642 | - Rust: Have a `Cargo.toml`? |
| 643 | - Some servers need project metadata |
| 644 | |
| 645 | --- |
| 646 | |
| 647 | ### "Diagnostics are slow/delayed" |
| 648 | |
| 649 | **Problem:** Errors appear several seconds after typing. |
| 650 | |
| 651 | **Explanation:** This is normal! Language servers analyze your code: |
| 652 | - Simple syntax errors: ~100ms |
| 653 | - Type checking: 500ms-2s |
| 654 | - Full project analysis: 2-10s |
| 655 | |
| 656 | **Tips:** |
| 657 | - `fac` debounces changes (waits 500ms after you stop typing) |
| 658 | - Large projects take longer |
| 659 | - First-time analysis is slower (builds cache) |
| 660 | |
| 661 | --- |
| 662 | |
| 663 | ### "Server keeps crashing" |
| 664 | |
| 665 | **Problem:** LSP features work then suddenly stop. |
| 666 | |
| 667 | **Solution:** |
| 668 | 1. Check server version: |
| 669 | ```bash |
| 670 | pylsp --version |
| 671 | ``` |
| 672 | |
| 673 | 2. Update the language server: |
| 674 | ```bash |
| 675 | pip install --upgrade python-lsp-server |
| 676 | ``` |
| 677 | |
| 678 | 3. Check for conflicting plugins/extensions |
| 679 | |
| 680 | 4. Restart `fac` |
| 681 | |
| 682 | --- |
| 683 | |
| 684 | ### "Formatting changes my code unexpectedly" |
| 685 | |
| 686 | **Problem:** `Shift+Alt+F` makes unwanted changes. |
| 687 | |
| 688 | **Solution:** |
| 689 | 1. Check your formatter configuration |
| 690 | 2. Many formatters respect configuration files: |
| 691 | - Python: `pyproject.toml` or `.pylintrc` |
| 692 | - JavaScript: `.prettierrc` |
| 693 | - Rust: `rustfmt.toml` |
| 694 | |
| 695 | 3. Configure line length, indentation, etc. in those files |
| 696 | |
| 697 | --- |
| 698 | |
| 699 | ## Tips & Tricks |
| 700 | |
| 701 | ### 1. Use Jump Stack for Navigation |
| 702 | |
| 703 | After using F12 to jump to a definition: |
| 704 | - Press `Alt+,` to jump back |
| 705 | - Works across multiple jumps (maintains history) |
| 706 | - Great for exploring unfamiliar codebases |
| 707 | |
| 708 | ### 2. Combine Search Features |
| 709 | |
| 710 | - `Ctrl+F` - Search text in current file |
| 711 | - `F4` - Search symbols in current file |
| 712 | - `F6` - Search symbols across project |
| 713 | - `Shift+F12` - Find all usages of current symbol |
| 714 | |
| 715 | ### 3. Fix Errors Faster |
| 716 | |
| 717 | When you see an error: |
| 718 | 1. Press `F8` to see all errors |
| 719 | 2. Navigate to each error |
| 720 | 3. Press `Ctrl+.` to see quick fixes |
| 721 | 4. Apply fixes with `Enter` |
| 722 | |
| 723 | ### 4. Rename Safely |
| 724 | |
| 725 | Before renaming: |
| 726 | - Press `Shift+F12` to see all references |
| 727 | - Verify it's safe to rename |
| 728 | - Press `F2` to rename everywhere at once |
| 729 | |
| 730 | ### 5. Format on Save |
| 731 | |
| 732 | Many language servers support format-on-save: |
| 733 | - Press `Ctrl+S` to save |
| 734 | - File is automatically formatted |
| 735 | - Keeps your code style consistent |
| 736 | |
| 737 | --- |
| 738 | |
| 739 | ## LSP Keybindings Quick Reference |
| 740 | |
| 741 | | Feature | Keybinding | What It Does | |
| 742 | |---------|-----------|--------------| |
| 743 | | **Diagnostics Panel** | `F8` or `Alt+E` | Show all errors/warnings | |
| 744 | | **Go to Definition** | `F12` or `Ctrl+\` or `Alt+G` | Jump to where symbol is defined | |
| 745 | | **Find References** | `Shift+F12` or `Alt+R` | Find all usages of symbol | |
| 746 | | **Code Actions** | `F10` or `Alt+.` | Quick fixes and refactorings | |
| 747 | | **Rename Symbol** | `F2` | Rename across entire project | |
| 748 | | **Document Symbols** | `F4` or `Alt+O` | Outline of current file | |
| 749 | | **Workspace Symbols** | `F6` or `Alt+P` | Search symbols across project | |
| 750 | | **Format Document** | `Shift+Alt+F` | Auto-format code | |
| 751 | | **Command Palette** | `Ctrl+P` | Access all commands | |
| 752 | | **Jump Back** | `Alt+,` | Return to previous location | |
| 753 | |
| 754 | **Note:** Alt+key combinations work better in terminals than Ctrl+Shift combinations. |
| 755 | |
| 756 | --- |
| 757 | |
| 758 | ## Supported Languages |
| 759 | |
| 760 | `fac` can work with **any** language that has an LSP server. Here are popular ones: |
| 761 | |
| 762 | | Language | Server | Installation | |
| 763 | |----------|--------|--------------| |
| 764 | | Python | `pylsp` | `pip install python-lsp-server` | |
| 765 | | JavaScript/TypeScript | `typescript-language-server` | `npm install -g typescript-language-server` | |
| 766 | | Rust | `rust-analyzer` | `rustup component add rust-analyzer` | |
| 767 | | Go | `gopls` | `go install golang.org/x/tools/gopls@latest` | |
| 768 | | C/C++ | `clangd` | `brew install llvm` or `apt install clangd` | |
| 769 | | Java | `jdtls` | Download from Eclipse | |
| 770 | | Ruby | `solargraph` | `gem install solargraph` | |
| 771 | | PHP | `intelephense` | `npm install -g intelephense` | |
| 772 | | Bash | `bash-language-server` | `npm install -g bash-language-server` | |
| 773 | | Fortran | `fortls` | `pip install fortls` | |
| 774 | | Lua | `lua-language-server` | Download from GitHub | |
| 775 | | HTML/CSS | `vscode-html-languageserver` | `npm install -g vscode-html-languageserver-bin` | |
| 776 | |
| 777 | For more language servers, visit: https://microsoft.github.io/language-server-protocol/implementors/servers/ |
| 778 | |
| 779 | --- |
| 780 | |
| 781 | ## What's Next? |
| 782 | |
| 783 | Now that you understand LSP in `fac`: |
| 784 | |
| 785 | 1. **Install language servers** for your languages |
| 786 | 2. **Practice the keybindings** - they'll become second nature |
| 787 | 3. **Explore your codebase** with `F6` and `F12` |
| 788 | 4. **Let LSP catch errors** before you run your code |
| 789 | 5. **Refactor confidently** with `F2` and `Ctrl+.` |
| 790 | |
| 791 | Welcome to IDE-level coding in the terminal! 🚀 |