The fish-lsp aims to create an experience that aligns with the fish language goals.
In a quick overview, the project hopes to create a development environment that is as friendly as possible.
Thanks for the interest in contributing to the project 🙏
There are many ways to contribute to the project:
- Submit bugs, and help work on fixes
- Refactor out unnecessary source code
- Implement features, outlined in the roadmap.
- Implement new client configurations, outlined in this repo
- Add tests to verify expected behavior.
- Update documentation, across any of the project's repositories
-
Begin by forking the project, then build your local fork 🗃️.
-
Once you have installed the local fork of the project (i.e., you have a successfully compiled
fish-lsp
executable, and have a working client configuration), you can then begin testing locally 📝. -
Upon completing a change, submit a PR 🎉.
- Roadmap - future ideas to support
- Issues and discussions - get ideas from others
- Sources - helpful insight about potential features you want to adapt
Note
Browsing both wiki/sources#vscode-extensions-examples and ROADMAP are the easiest method for understanding how to create future fish-lsp feature's
Since stdin/stdout are reserved for the protocol to communicate, a generally successful method to achieve quick results, is through TDD (Test Driven Development). Many tree-sitter helper functions (tree-sitter.ts, and node-types.ts) have already been written, to aid in providing useful functionality for generic support of any possible combination need for future types.
Having said that, if you a need for a new definition in tree-sitter.ts or node-types.ts comes up,
adding it to the proper file is fine (tree-sitter.ts
generally deals with movement or interacting with
a SyntaxNode[] | Tree
, where as node-types.ts
generally deals with filter
functions that can determine what type of SyntaxNode
is passed into it).
The only requirement is that you will for new additions to these files, is that
you include proper tests in their corresponding test-data/{node-types,tree-sitter}.test.ts)
Test directly in the client of your choosing. This is a more difficult to setup, but could be helpful if you are testing specific behaviors like the interacting with fish-lsp's environment variables, configuration options, handler testing or other more specific tasks.
-
Pull up some Documentation 🔬
- lsif - The official Language Server Protocol specification
- wiki/sources - Sources that are similar to this project
- roadmap - Ideas/Documentation for future plans
-
Create a
file
in the test-data/ directory 👷- START WITH VERY BASIC EXAMPLES!!! Pure functions are your friend
- Checkout ./test-data/helpers.ts,
setLogger()
which is provided forlogging
tests - Test your
FILE.test.ts
with command:yarn test FILE --watchAll
- Feel free to overwrite any existing test-file that is not in the
package.json key
test-hook
- Use
import { initializeParser } from '../src/parser
for buildingSyntaxNode[]
composite object arrays (aka trees).
-
Iteratively continue improving your feature ♾️
-
Once you have a feature's hard coded input & outputs working as expected, you can begin trying to impalement it as an actual
server.handler
-
You can try adding logging to your feature's specific
handlerParams
, to get an exact example of it's shape. (This is the premise outlined via: integration testing workflow)# display the logs tail -f $(fish-lsp info --logs-file)
-
Alternatively, you can mock the data-type from the
vscode-languageserver
or refer to the same documentation on lsif
-
-
Add your feature to a server.ts
handler
🤝- Document your handler, if necessary.
- Feel free to submit your server handler in separate working release stages,
instead of trying to build entire feature's independently. (i.e., if your
CodeAction's
only support a singularCodeActionType
) - Submit your PR 🍾
Currying is a useful design pattern, that makes iterating through the Abstract Syntax Trees (ASTs) significantly less error prone.
Note
While it is still not entirely perfect, errors that appear to be caused by inconsistencies in our node-types.ts functors are more likely to be caused by the earlier language server protocol versions requirement for our Nodes in our tree items, to be stored as a flat list.
Due to this reason, the project has undergone a significant rewrite of previously working features (diagnostics, etc...). Working on reintroducing the disabled features would be a great place to start, as many of server providers were implemented using range based location calculation's to abide to their prior protocol use.
Relevant examples for each of the feature's mentioned above are included @ wiki/sources
Child process execution via sub-shells. Sub-shell environment's are extensively relied on throughout the code base.
Markdown formatting syntax, and nested language support via triple backticks.
Asynchronous processes and race conditions. Especially during src/server.ts startup.
Prefetching relevant information and caching it for global use.
-
tree-sitter - used for data structures/algorithms, prevalent to the shell language.
yarn sh:build-wasm
- should handle building the wasm file@esdmr/tree-sitter-fish@3.5.1
- handles installing the actual tree-sitter-fish.wasm packageweb-tree-sitter
- is the API forSyntaxNode[]
,Parser
,Range
, etc...
-
eslint - used for linting and formatting
yarn lint
- lint and fix the current project (husky pre-push
hook)yarn lint:verbose
- lint, and display output
-
knip - used for tree-shaking and checking unused dependencies
yarn refactacor
- package.json script to run knip- You can refactor major sections of unused code of out the project easily with this command
-
commander.js - used for src/cli.ts and other tooling to start the server
- Handles parsing the ./bin/fish-lsp
stdin
, in a structured manor
- Handles parsing the ./bin/fish-lsp
-
zod - parses the
env
into a typesafe object- handles parsing the
fish_lsp*
variables in our nodeprocess.env
object - builds the result object in the global variable
config
- handles parsing the
-
vscode-languageserver - the SPEC for defining our LSP.
Objects
&Interfaces
specific tofish-lsp
typically extend this base specificationType Definitions
useful for handler's are defined throughout this package
-
husky - the git-hooks for interacting with project's source code
- lints the project
on-push
- removes dependencies before commit
pre-commit
- initializes yarn
post-merge
- lints the project
-
jest - testing the project
- relevant locations: test-data/*.test.ts, jest.config.js && tsconfig.test.json
yarn test-hook
is a future supported feature, for specifying individual test files to opt into successful reporting for master branch (viagit action
).yarn test someFile.test.ts --watchAll
is the designated method for watching a test's changes
Becoming familiar with using the src/utils/{tree-sitter,node-types}.ts
code, is significantly easier while
using the previously mentioned TDD Workflow.
Using an equivalent tree-sitter visualization command to neovim's command, :InspectEdit
is also
highly recommended. If you are unsure what this command does, it essentially allows you to visualize
the AST that tree-sitter parsed from fish input. Using this while writing test
files, significantly improves the overall testing experience.
Also don't forget to make use of the fish-lsp --flags! There is plenty of use cases the binary supports,
like: fish-lsp env --create
, fish-lsp complete
,
fish-lsp info --logs-file
,
fish-lsp info --time
, fish-lsp url --sources
, fish-lsp logger --show
, + more...
Generally, all that is required is using the fish-lsp start
command, and
specifying fish for attaching the server to a filetype. Any other fluff in this
settings, as seen in the JSON example, is only for ease of use.
Adding new client configurations, to the fish-lsp-client's repo, is greatly appreciated!
If you're trying to add a new github action to the project, please take a close look at the scripts/* directory, along with package.json.
A github action that uses that compiles the project, requires fish
to be
installed and setup, before yarn
in the action.
The current workflow actions, are the best place to see how this is achieved.
Show & tell is a helpful place to document your useful configurations for working on the fish-lsp.
Displaying demos, features and other cool discoveries are also welcome :)