diff --git a/README.md b/README.md
index bc7301a..456dbce 100644
--- a/README.md
+++ b/README.md
@@ -20,27 +20,29 @@ An R language server, linter, and code formatter, written in Rust.
Roughly aims to support the following language server features (some are experimental or in progress):
-- **Code Navigation**
- - Goto definition (🧪 experimental)
- - Search current document (Ctrl + Shift + O *in VS Code*)
- - Search global workspace (Ctrl + T *in VS Code*)
- - Indexing of global symbols, S4 classes/generics/methods and R6 classes/methods
+- **Navigation**
+ - Indexing of global variables, S4 and R6 classes/methods
+ - Search current document - Ctrl + Shift + O *in VS Code*
+ - Search global workspace - Ctrl + T *in VS Code*
+ - Go to definition *(🧪 experimental)*
+ - Find all references *(🧪 experimental)*
- **Diagnostics**
- Syntax errors (including missing or trailing commas)
- - Basic linting rules (e.g. `<-` assignment and variable naming)
- - Unused variables (🧪 experimental)
+ - Basic linting rules (e.g. using `<-` for assignment or consistent `snake_case` / `camelCase`)
+ - Warn about unused variables *(🧪 experimental)*
+
+- **Editing**
+ - Autocomplete locals and global variables
+ - Autocomplete variables from other packages *(⚠️ missing)*
+ - Rename local variables *(🧪 experimental)*
+ - Rename global variables *(⚠️ missing)*
+ - Signature help *(🔨 work in progress)*
- **Formatting**
- - Entire documents
- - Selected ranges (🧪 experimental)
-
-- **Code Completion**
- - Local symbols
- - Global symbols
- - Package symbols (⚠️ missing)
- - Signature help (⚠️ missing)
-
+ - Format entire documents
+ - Format selected code ranges *(🧪 experimental)*
+
## Roughly CLI
You can install the Roughly CLI by downloading a pre-built binary or by building from source.
@@ -87,13 +89,9 @@ Roughly can also be used as a VS Code extension.
### From Marketplace (Recommended)
-Install directly from VS Code:
-- Open VS Code
-- Press Ctrl+Shift+X to open Extensions
-- Search for "roughly"
-- Click "Install" on the extension by `felix-andreas`
+[](https://marketplace.visualstudio.com/items?itemName=felix-andreas.roughly)
-Or, install using the [VS Code Marketplace website](https://marketplace.visualstudio.com/items?itemName=felix-andreas.roughly).
+Install the extension from the [VS Code Marketplace](https://marketplace.visualstudio.com/items?itemName=felix-andreas.roughly).
> [!NOTE]
> The VS Code extension from the marketplace includes a bundled version of the Roughly CLI **only for Windows and Linux x64**. If you are using macOS or a different architecture, you will need to install the Roughly CLI manually.
@@ -121,8 +119,8 @@ You can customize the Roughly extension in VS Code through the following setting
{
// Use a custom binary instead of the bundled one
"roughly.path": "/path/to/roughly",
- // Pass extra arguments to the language server
- "roughly.args": ["server", "--extra", "arg"],
+ // Pass custom arguments; defaults to ["server"]
+ "roughly.args": ["server", "--verbose"],
// Enable experimental features
"roughly.experimentalFeatures": ["goto_definition", "range_formatting"],
}
@@ -135,8 +133,10 @@ You can customize the Roughly extension in VS Code through the following setting
You can access Roughly-specific commands in VS Code via the Command Palette (Ctrl+Shift+P):
-- **Roughly: Start/Stop/Restart Server**
- **Roughly: Open logs**
+- **Roughly: Start/Stop/Restart Server**
+- **Roughly: Format workspace** (⚠️ missing)
+- **Roughly: Show syntax tree** (⚠️ missing)
## RStudio Integration
@@ -163,14 +163,14 @@ naming-style = "snake_case" # or "camelCase", omit to disable this lint entirely
Roughly includes several experimental features that can be enabled in the VS Code extension settings or via the CLI:
-| Name | Description |
-| ------------------ | --------------------------------- |
-| `all` | Enables all experimental features |
-| `goto_definition` | Jump to symbol definitions |
-| `goto_references` | Find all references to a symbol |
-| `range_formatting` | Format selected code ranges |
-| `rename` | Rename symbols |
-| `unused` | Detect unused variables |
+| Name | Description |
+| ------------------ | -------------------------------- |
+| `all` | Enable all experimental features |
+| `goto_definition` | Jump to symbol definitions |
+| `goto_references` | Find all references to a symbol |
+| `range_formatting` | Format selected code ranges |
+| `rename` | Rename symbols |
+| `unused` | Warn about unused variables |
## Development
diff --git a/editors/code/README.md b/editors/code/README.md
index 1a9ea4a..f30784d 100644
--- a/editors/code/README.md
+++ b/editors/code/README.md
@@ -7,10 +7,30 @@ This extension provides support for the [R programming language](https://www.r-p
## Features
-* Autocomplete
-* Code Formatting
-* Syntax Diagnostics
-* Workspace Symbol Search
+Roughly aims to support the following language server features (some are experimental or in progress):
+
+- **Navigation**
+ - Indexing of global variables, S4 and R6 classes/methods
+ - Search current document - Ctrl + Shift + O *in VS Code*
+ - Search global workspace - Ctrl + T *in VS Code*
+ - Go to definition *(🧪 experimental)*
+ - Find all references *(🧪 experimental)*
+
+- **Diagnostics**
+ - Syntax errors (including missing or trailing commas)
+ - Basic linting rules (e.g. using `<-` for assignment or consistent `snake_case` / `camelCase`)
+ - Warn about unused variables *(🧪 experimental)*
+
+- **Editing**
+ - Autocomplete locals and global variables
+ - Autocomplete variables from other packages *(⚠️ missing)*
+ - Rename local variables *(🧪 experimental)*
+ - Rename global variables *(⚠️ missing)*
+ - Signature help *(🔨 work in progress)*
+
+- **Formatting**
+ - Format entire documents
+ - Format selected code ranges *(🧪 experimental)*
## Usage
@@ -24,8 +44,8 @@ You can customize the Roughly extension in VS Code through the following setting
{
// Use a custom binary instead of the bundled one
"roughly.path": "/path/to/roughly",
- // Pass extra arguments to the language server
- "roughly.args": ["server", "--extra", "arg"],
+ // Pass custom arguments; defaults to ["server"]
+ "roughly.args": ["server", "--verbose"],
// Enable experimental features
"roughly.experimentalFeatures": ["goto_definition", "range_formatting"],
}
diff --git a/scripts/create_large_codebase.rs b/scripts/create_large_codebase.rs
new file mode 100644
index 0000000..9df6344
--- /dev/null
+++ b/scripts/create_large_codebase.rs
@@ -0,0 +1,114 @@
+use std::{fs, io::Write, path::Path};
+
+const CONSTANT: &str = " <- 12345";
+
+const FUNCTION: &str = r#"
+ <- function(n) {
+ if (n <= 0) {
+ return(NULL)
+ } else if (n == 1) {
+ return(0)
+ } else if (n == 2) {
+ return(1)
+ } else {
+ return((n - 1) + (n - 2))
+ }
+}
+"#;
+
+const S4_CLASS: &str = r#"
+setClass("",
+ slots = c(
+ name = "character",
+ age = "numeric"
+ ),
+ prototype = list(
+ name = NA_character_,
+ age = NA_real_
+ )
+)
+"#;
+
+const S4_METHODS: &str = r#"
+setGeneric("", function(x) standardGeneric(""))
+setGeneric("<-", function(x, value) standardGeneric("<-"))
+
+setMethod("", "", function(x) x@)
+setMethod("<-", "", function(x, value) {
+ x@name <- value
+ x
+})
+"#;
+
+const R6_CLASS: &str = r#"
+ <- R6Class("",
+ public = list(
+ initialize = function(...) {
+ for (item in list(...)) {
+ self$add(item)
+ }
+ },
+ add = function(x) {
+ private$queue <- c(private$queue, list(x))
+ invisible(self)
+ },
+ remove = function() {
+ if (private$length() == 0) return(NULL)
+ # Can use private$queue for explicit access
+ head <- private$queue[[1]]
+ private$queue <- private$queue[-1]
+ head
+ }
+ ),
+ private = list(
+ queue = list(),
+ length = function() base::length(private$queue)
+ )
+)
+"#;
+fn main() {
+ use std::{fs, path::Path};
+
+ let base_dir = Path::new(env!("CARGO_MANIFEST_DIR")).join("../R-large-codebase");
+ let r_dir = base_dir.join("R");
+
+ if r_dir.exists() {
+ fs::remove_dir_all(&r_dir).unwrap();
+ }
+
+ fs::create_dir_all(&r_dir).unwrap();
+
+ for file in (b'a'..=b'z').flat_map(|c| (0..4).map(move |n| format!("{}{}", c, n))) {
+ let code = [
+ // Constants
+ ["ALPHA", "BETA", "GAMA"]
+ .map(|name| CONSTANT.replace("", &format!("{}.{}", file, name))),
+ // Functions
+ ["alpha", "beta", "gama"]
+ .map(|name| FUNCTION.replace("", &format!("{}.{}", file, name))),
+ // S4 Classes and Methods
+ ["Alpha", "Beta", "Gamma"].map(|name| {
+ let class_code = S4_CLASS.replace("", &format!("{}.{}", file, name));
+ let methods_code = (0..3)
+ .map(|i| {
+ S4_METHODS
+ .replace("", &format!("{}.{}.method{}", file, name, i))
+ .replace("", &format!("{}.{}", file, name))
+ })
+ .collect::>()
+ .join("\n");
+ format!("{}\n{}", class_code, methods_code)
+ }),
+ // R6 Classes
+ ["AlphaR6", "BetaR6", "GammaR6"]
+ .map(|name| R6_CLASS.replace("", &format!("{}.{}", file, name))),
+ ]
+ .into_iter()
+ .flat_map(|group| group)
+ .collect::>()
+ .join("\n");
+
+ let file_path = r_dir.join(format!("{}.R", file));
+ fs::write(file_path, code).expect("Failed to write file");
+ }
+}