Skip to content

Conversation

@Hocnonsense
Copy link
Contributor

@Hocnonsense Hocnonsense commented Apr 20, 2025

This PR can improve snakemake coding in vscode

  1. allow eazily check shell zone with build-in highlights:
    image
  2. record the defination of rule, checkpoint, and module:
    image
  3. quick link of conda, script, include, configfile, and snakefile if plain text is provided (see above)

Summary by CodeRabbit

  • New Features

    • Introduced a Visual Studio Code extension for Snakemake with enhanced language support, including symbol navigation, clickable file links, and shell block hover previews.
    • Added a build script and related configuration for bundling the extension.
    • Added a new YAML syntax injection for Snakemake keywords within Python code contexts.
  • Improvements

    • Refined Snakemake syntax highlighting with unified string handling, improved function call recognition, and better pattern organization.
    • Expanded and clarified documentation for Snakemake keywords, rules, parameters, and global variables.
  • Chores

    • Upgraded development dependencies and GitHub Actions workflows, including Node.js version update to 18.
    • Added TypeScript configuration and improved build and packaging scripts.
    • Removed legacy syntax, snippet, and language configuration files to streamline extension.
    • Updated VS Code tasks and launch configurations for streamlined build processes.
    • Enhanced .vscodeignore to exclude GitHub workflow files.
  • Style

    • Minor whitespace adjustment in launch configuration.

@coderabbitai
Copy link

coderabbitai bot commented Apr 20, 2025

📝 Walkthrough

Walkthrough

This update introduces significant enhancements to the Snakemake Visual Studio Code extension. A new TypeScript-based extension implementation is added, featuring a SnakemakeManager class that parses Snakemake files for shell blocks, symbols, and document links, and integrates with VSCode's symbol, link, and hover providers. The build system is modernized with an esbuild-based script, new build tasks, and updated dependencies. The syntax highlighting definitions for Snakemake are refactored in YAML format to unify string and function call patterns and improve pattern granularity, while the previous JSON-based syntax definition and language configuration files are removed. Documentation in the README is expanded and restructured, and the release workflow is upgraded to use newer GitHub Actions and Node.js versions.

Changes

File(s) Change Summary
.github/workflows/release-please.yml Updated workflow to use new versions of actions (release-please v4, checkout v4, setup-node v4), increased Node.js version to 18, added a build step running npm run build conditioned on release creation, and updated publishing steps to use HaaLeo/publish-vscode-extension v1.
.github/workflows/main.yml Modified CI workflow test step to run npm install followed by npm ci instead of just npm ci. Upgraded Node.js setup action to v3 and Node.js version to 18.x.
.vscode/launch.json Adjusted whitespace/indentation for the "version" field; no functional or configuration changes.
.vscode/tasks.json Removed individual shell tasks (regex_build, syntax_build, language_build, snippets_build). Updated the build task from a shell task with dependencies to an npm task running the build script, assigned it to the build group and marked as default.
.vscodeignore Added .github/** directory pattern to the ignore list.
README.md Expanded and restructured documentation on Snakemake keywords, rules, parameters, modules, global variables, job parameters, and functions with detailed explanations, examples, and links. Added new TODO items related to file recognition after keywords and bash-color in docstrings.
build.mjs Added new build script using esbuild to synchronously bundle and minify src/extension.ts targeting Node.js platform, outputting CommonJS format to dist/extension.js, excluding vscode and node modules.
package.json Added devDependencies: @types/node (^14, ^16, or ^18), @types/vscode (1.53.0), and esbuild (0.25.2). Set "main" to "dist/extension.js". Added "activationEvents" for "onLanguage:snakemake". Added "node": ">=18" to engines. Introduced "scripts" for clean, build, watch, package, prepublish, and publish commands. Updated VS Code engine version to ^1.75.0.
src/extension.ts New file implementing the Snakemake VSCode extension: defines SnakemakeManager class that parses documents for shell blocks, document symbols (rules, checkpoints, modules, subworkflows), and document links (file paths). Registers document symbol, link, and hover providers. Maintains internal state keyed by document URI and updates on document changes. Provides shell block hover with syntax-highlighted shell content. Includes utility functions for trimming shell block content and resolving file paths. Exports activate function to register providers and listeners.
src/js/build_regex.js Replaced deprecated yaml.safeLoad call with yaml.load for YAML parsing; no other logic changes.
src/yaml/snakemake.syntax.yaml Refactored Snakemake syntax highlighting definitions to unify string quote patterns into #snakestrings, added new patterns for function-call with nested function-arguments, quoteall, snakemakenames, and rulesrefernce. Adjusted scopes and capture names for rule arguments and objects. Removed old shell_block pattern. Improved nesting and granularity of patterns for better syntax recognition and highlighting consistency.
syntaxes/snakemake.tmLanguage.json Entire file removed, removing the previous comprehensive Snakemake syntax highlighting definition including all patterns and repository entries.
tsconfig.json Added new TypeScript configuration file specifying CommonJS modules, ES2020 target, strict type checking, source root as src, no emit output, ES module interop, Node module resolution, and excluding node_modules and dist.
languages/snakemake.json Deleted file removing Snakemake language configuration for comments, brackets, auto-closing pairs, surrounding pairs, and on-enter indentation rules.
snippets/snakemake.json Deleted file removing Snakemake code snippets for rule and script rule templates.
src/js/keywords-regex.json Deleted file removing centralized keyword category definitions used for syntax highlighting or parsing.
src/yaml/snakemake-inject.syntax.yaml Added new YAML syntax injection file for Snakemake keywords in Python source code with scope source.python.snakemake.keywords injecting into Python function calls and member access contexts.
src/keywords.yaml Renamed keyword group ruleargs to jobparams without changing the keyword list. Added new keyword group legal-name with regex pattern for valid identifiers.

Sequence Diagram(s)

sequenceDiagram
    participant VSCode
    participant SnakemakeManager
    participant FileSystem

    VSCode->>SnakemakeManager: On document open/change
    SnakemakeManager->>FileSystem: Read document content
    SnakemakeManager->>SnakemakeManager: Parse for rules, modules, shell blocks, links
    SnakemakeManager->>VSCode: Provide symbols and document links

    VSCode->>SnakemakeManager: On hover over shell block
    SnakemakeManager->>VSCode: Return shell block content as hover tooltip
Loading
sequenceDiagram
    participant Developer
    participant VSCode Tasks
    participant build.mjs
    participant esbuild

    Developer->>VSCode Tasks: Run "build" task
    VSCode Tasks->>build.mjs: Execute build script
    build.mjs->>esbuild: Bundle and minify src/extension.ts
    esbuild-->>build.mjs: Output dist/extension.js
    build.mjs-->>VSCode Tasks: Build complete
Loading

Possibly related PRs

  • feat: update more keywords and highlighting #42: Updates and expands the existing Snakemake syntax highlighting rules within the now-removed syntaxes/snakemake.tmLanguage.json and related files; this PR is related as it supersedes and replaces those syntax files with a new approach.

Suggested reviewers

  • johanneskoester

Tip

⚡️ Faster reviews with caching
  • CodeRabbit now supports caching for code and dependencies, helping speed up reviews. This means quicker feedback, reduced wait times, and a smoother review experience overall. Cached data is encrypted and stored securely. This feature will be automatically enabled for all accounts on May 16th. To opt out, configure Review - Disable Cache at either the organization or repository level. If you prefer to disable all data retention across your organization, simply turn off the Data Retention setting under your Organization Settings.

Enjoy the performance boost—your workflow just got faster.


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ed01912 and 0732a55.

📒 Files selected for processing (1)
  • src/extension.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/extension.ts
✨ Finishing Touches
  • 📝 Generate Docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

🔭 Outside diff range comments (1)
syntaxes/snakemake.tmLanguage.json (1)

257-278: 🛠️ Refactor suggestion

Simplify optional with: handling in userulesfromas
Embedding a free‑spacing comment inside the JSON regex can lead to escaping pitfalls. Instead of the inline comment, capture the optional with: clause directly:

- "match": "(?x)\n  \\b(use\\s+rule)\\s+(\\w+|\\w+\\*|\\*)\\s+(from)\\s+(\\w+)\\s+(as)\\s+(\\w+|\\w+\\*)\n  # may end with a \"with:\"\", but that can be caught by other rules\n",
+ "match": "(?x)\n  \\b(use\\s+rule)\\s+(\\w+|\\w+\\*|\\*)\\s+(from)\\s+(\\w+)\\s+(as)\\s+(\\w+|\\w+\\*)\n  (?:\\s+with:)?\n",

This explicit optional group is easier to maintain and avoids JSON‑escaping complexity.

🧹 Nitpick comments (12)
src/js/build_regex.js (1)

10-10: Ensure safe YAML parsing with explicit schema
Switching from the deprecated safeLoad to load is correct, but by default yaml.load may allow unsafe types. To preserve the original safe behavior, explicitly pass a safe schema, for example:

const config = yaml.load(fs.readFileSync(keywords, 'utf8'), { schema: yaml.JSON_SCHEMA });
build.mjs (1)

1-12: Consider adding inline source maps for debugging
To improve debugging of the bundled extension, you could enable inline source maps:

 esbuild.buildSync({
   entryPoints: ['src/extension.ts'],
   bundle: true,
   platform: 'node',
   outfile: 'dist/extension.js',
   external: ['vscode', 'node'],
   format: 'cjs',
   minify: true,
+  sourcemap: 'inline',
 });

This will help trace runtime errors back to the original TypeScript sources.

.vscode/tasks.json (1)

25-29: Simplify js_build command
Using npx node build.mjs works, but invoking Node directly is sufficient. You can simplify the task to:

"command": "node build.mjs"

avoiding the extra npx layer.

.github/workflows/release-please.yml (1)

26-33: Add an actions/setup-node cache for faster releases

Every release run currently installs all npm packages from scratch.
Caching $HOME/.npm (or ~/.cache/npm) with cache: "npm" in setup-node@v4 cuts the release time noticeably, especially with the newly‑added build step.

Example:

- uses: actions/setup-node@v4
  if: ${{ steps.release.outputs.release_created }}
  with:
    node-version: 18
    cache: 'npm'
README.md (2)

49-56: Minor wording / formatting glitch

The sentence starts with “You can re- used rule …”, which looks like an unfinished edit.
Consider re‑phrasing to:

-  - You can re- `used rule <rulename> as <newrulename> ... with`
+  - You can reuse a rule via  
+    ```snakemake
+    use rule <rulename> as <newrulename> ...
+    ```

104-105: Convert TODOs into tracked GitHub issues

The README TODO list is easy to forget. Creating GitHub issues (labelled e.g. enhancement) provides visibility and lets the community pick them up.

src/extension.ts (2)

205-213: Avoid synchronous filesystem checks inside the hot parsing loop

fs.existsSync is called for every candidate path on every document change, blocking the extension host thread.
Either:

  1. Cache already‑tested paths in a WeakMap, or
  2. Switch to vscode.workspace.fs.stat (async) and throttle look‑ups.

This will keep typing latency low for large Snakefiles.


59-67: Full document re‑parse on each keystroke can hurt performance

update() walks the entire file on onDidChangeTextDocument, even for single‑character edits. Consider debouncing and/or incremental parsing to avoid quadratic behaviour in large files.

syntaxes/snakemake.tmLanguage.json (2)

53-62: Capture function name and paren for highlighting
The function-call block correctly matches name(args) but lacks a beginCaptures to scope the function name (group 1) and the opening parenthesis. Adding these will improve syntax highlighting consistency:

"function-call": {
  "begin": "(?x)\n  \\b(?=\n    ([[:alpha:]_]\\w*) \\s* (\\()\n  )\n",
+ "beginCaptures": {
+   "1": { "name": "entity.name.function.snakemake.call" },
+   "2": { "name": "punctuation.definition.arguments.begin.python" }
+ },
  "end": "(\\))",
  "endCaptures": { ... },
  "patterns": [ ... ]
}

350-362: Typo in rulesrefernce identifier
The key and references use rulesrefernce (missing the second e in “reference”). While this is internally consistent, renaming to rulesreference would improve readability and avoid confusion.

src/yaml/snakemake.syntax.yaml (2)

23-40: Function-call lacks beginCaptures for function name
The function-call entry correctly matches calls but does not capture the function name (group 1) or opening parenthesis. Adding:

    beginCaptures:
      "1": { name: entity.name.function.snakemake.call }
      "2": { name: punctuation.definition.arguments.begin.python }

will enable proper token scoping.


198-204: Typo in rulesrefernce key
The pattern is named rulesrefernce but should likely be rulesreference. Renaming will enhance readability and align with standard spelling.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between dd8d7ed and 71906f0.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (11)
  • .github/workflows/release-please.yml (1 hunks)
  • .vscode/launch.json (1 hunks)
  • .vscode/tasks.json (1 hunks)
  • README.md (1 hunks)
  • build.mjs (1 hunks)
  • package.json (1 hunks)
  • src/extension.ts (1 hunks)
  • src/js/build_regex.js (1 hunks)
  • src/yaml/snakemake.syntax.yaml (4 hunks)
  • syntaxes/snakemake.tmLanguage.json (10 hunks)
  • tsconfig.json (1 hunks)
🧰 Additional context used
🪛 Biome (1.9.4)
src/extension.ts

[error] 155-155: Unnecessary continue statement

Unsafe fix: Delete the unnecessary continue statement

(lint/correctness/noUnnecessaryContinue)

🔇 Additional comments (23)
.vscode/launch.json (1)

6-6: Styling-only change
This whitespace adjustment is purely cosmetic and doesn’t affect functionality.

tsconfig.json (1)

1-21: TypeScript configuration is well-defined
The tsconfig.json settings align with the new TypeScript build process, enabling strict checks, proper module resolution, and excluding build artifacts.

.vscode/tasks.json (1)

31-37: Integrate js_build into the composite build task
The addition of js_build to the build task dependencies ensures the TypeScript bundle step is run alongside the existing build tasks, aligning VSCode’s task configuration with your updated CI/build pipeline.

.github/workflows/release-please.yml (1)

18-21: Branch still hard‑coded to master

If the repository has transitioned to main, or plans to, this trigger will silently stop firing.
Double‑check that master is indeed the default branch.

src/extension.ts (1)

149-156: Remove superfluous continue

The continue at line 155 is flagged by Biome and is indeed redundant—the loop proceeds to the next iteration naturally after the block.
Deleting it cleans up the control flow.

-                this.pushAnyBlocks(blocks, state, i, line, state.blockStart.character);
-                continue;
+                this.pushAnyBlocks(blocks, state, i, line, state.blockStart.character);
🧰 Tools
🪛 Biome (1.9.4)

[error] 155-155: Unnecessary continue statement

Unsafe fix: Delete the unnecessary continue statement

(lint/correctness/noUnnecessaryContinue)

syntaxes/snakemake.tmLanguage.json (9)

10-11: New repository pattern includes correctly integrated
The #snakestrings, #function-call, #quoteall, and #snakemakenames patterns have been added to the top‑level patterns array in the correct order, ensuring that strings, function calls, nested quotes, and semantic name groups are tokenized before falling back to source.python.

Also applies to: 40-41, 43-44, 46-47


81-148: Function-arguments patterns are comprehensive
The function-arguments repository entry cleanly handles argument separators, unpacking (***), named parameters, nested expressions, and reinserts #snakemakenames and string patterns as needed. The lookahead anchors and content naming align with best practices.


149-161: Consolidated quoting patterns correctly defined
The quoteall pattern aggregates quotessmall, quotesmid, and quotesbig to support nested structures, simplifying the overall grammar.


162-175: Parenthesis-based string content patterns validated
The quotessmall block recursively includes nested quotes and Snakemake name patterns, ensuring balanced parenthesis segments inside strings are highlighted.


177-190: Bracket-based string content patterns validated
The quotesmid pattern mirrors quotessmall for square brackets, correctly reusing the quoting and name sub-patterns.


192-205: Brace-based string content patterns validated
The quotesbig pattern completes the quoting triad with curly braces, maintaining consistency across nested quotes support.


280-296: Simple rule import pattern is clear
The userulesfrom regex accurately captures use rule <X> from <Y> without ambiguity, matching both starred and unstarred rule names.


321-342: Name aggregation for Snakemake entities
The snakemakenames repository entry effectively groups classes, rule references, objects, rule args, and functions, improving semantic tokenization across different contexts.


400-428: Unified string quoting pattern
The snakestrings block correctly matches single, double, and triple‑quoted strings, integrating Python formatting and nested quoting patterns. This consolidation replaces the old shell_block pattern effectively.

src/yaml/snakemake.syntax.yaml (9)

7-7: Top-level pattern includes updated
The YAML syntax now mirrors the JSON version by adding #snakestrings, #function-call, #quoteall, and #snakemakenames to the patterns list, ensuring consistent highlighting across formats.

Also applies to: 17-20


41-67: Function arguments pattern is comprehensive
The function-arguments block handles commas, unpacking (***), named parameters, and nested expressions, leveraging free‑spacing mode and embedded Python patterns effectively.


72-76: Consolidated quoting patterns correctly defined
The quoteall aggregator cleanly includes quotessmall, quotesmid, and quotesbig, aligning with the JSON definition.


77-84: Parenthesis-based quoting validated
The quotessmall pattern correctly recurses into nested quoting and name patterns within parentheses.


85-91: Bracket-based quoting validated
The quotesmid pattern accurately mirrors the parenthesis logic for square brackets.


92-97: Brace-based quoting validated
The quotesbig pattern completes the nested quoting setup for curly braces.


153-160: Simple rule import pattern is clear
The userulesfrom regex cleanly captures use rule X from Y with minimal complexity.


186-194: Name aggregation for Snakemake entities
The snakemakenames entry consolidates classes, rule references, objects, args, and functions, streamlining name matching across the grammar.


224-232: Unified string quoting pattern
The snakestrings block in YAML consistently matches the JSON variant, handling single/double/triple quotes and nested patterns.

Comment on lines 183 to 186
if (newStartMatch) {
state.shellBlock = { delimiter: newStartMatch[0], content: [] };
state.blockStart = new vscode.Position(i, newStart + state.shellBlock.delimiter.length + newStartMatch.length);
} else {
Copy link

@coderabbitai coderabbitai bot Apr 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Incorrect column calculation for nested shell‑blocks

newStartMatch.length is the number of capture groups, not the matched text length, causing mis‑aligned ranges and broken hovers for consecutive """ blocks.

-                state.blockStart = new vscode.Position(i, newStart + state.shellBlock.delimiter.length + newStartMatch.length);
+                const newDelimiterPos = line.indexOf(newStartMatch[0], newStart);
+                state.blockStart = new vscode.Position(
+                    i,
+                    newDelimiterPos + newStartMatch[0].length
+                );

✅ Addressed in commits aa9c726 to 987a08c

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (1)
src/extension.ts (1)

187-188: Column calculation for nested shell-blocks is fixed correctly

Great job fixing the column calculation for nested shell blocks by properly determining the delimiter position and length.

🧹 Nitpick comments (5)
src/extension.ts (5)

10-12: Consider optimizing document updates

The current implementation updates the manager for every text change in Snakemake documents, which could be inefficient for large files or frequent edits.

-        vscode.workspace.onDidChangeTextDocument(e => {
-            if (e.document.languageId.toLowerCase() === 'snakemake') snakemakeManager.update(e.document);
+        vscode.workspace.onDidChangeTextDocument(e => {
+            if (e.document.languageId.toLowerCase() === 'snakemake') {
+                // Only update if necessary (e.g., check if the change affects shell blocks or symbols)
+                snakemakeManager.update(e.document);
+            }
         }),

56-60: Consider resource management for closed documents

The current implementation maintains maps for all processed documents but doesn't clean them up when documents are closed.

export function activate(context: vscode.ExtensionContext) {
    const snakemakeManager = new SnakemakeManager();

    context.subscriptions.push(
        vscode.workspace.onDidChangeTextDocument(e => {
            if (e.document.languageId.toLowerCase() === 'snakemake') snakemakeManager.update(e.document);
        }),
+       vscode.workspace.onDidCloseTextDocument(document => {
+           if (document.languageId.toLowerCase() === 'snakemake') snakemakeManager.removeDocument(document);
+       }),
        registerShellHoverProvider(snakemakeManager)
    );

    // rest of the code...
}

class SnakemakeManager {
    private blockMap = new Map<string, ShellBlock[]>();
    private symbolMap = new Map<string, vscode.DocumentSymbol[]>();
    private linkMap = new Map<string, vscode.DocumentLink[]>();
    
+   removeDocument(document: vscode.TextDocument): void {
+       const uri = document.uri.toString();
+       this.blockMap.delete(uri);
+       this.symbolMap.delete(uri);
+       this.linkMap.delete(uri);
+   }
    
    // rest of the class...
}

122-131: Remove commented-out code

There appears to be commented-out code that's no longer needed. Clean it up to improve code readability.

                } else if (
                    snakemakeRegex.path.global.exec(line)
                ) {
                    state.current.blockType = 'global:path'
-                    // } else if (
-                    //     snakemakeRegex.shell.test(line) ||
-                    //     snakemakeRegex.path.rule.test(line) ||
-                    //     snakemakeRegex.path.module.test(line)
-                    // ) {
-                    //     error
                }

195-217: Enhance link detection mechanism

The current implementation has a few limitations:

  1. It only captures the first quoted string in a line
  2. It uses synchronous file existence checking which could impact performance
  3. It doesn't handle paths with environment variables or substitutions

Consider enhancing the link detection:

  1. Add support for multiple links per line
  2. Implement asynchronous file existence checking
  3. Support environment variables and path substitutions common in Snakemake

157-157: Remove unnecessary continue statement

This continue statement is unnecessary as it's at the end of a code block and the loop would continue to the next iteration anyway.

                }
                this.pushAnyBlocks(blocks, state, i, line, state.blockStart.character);
-                continue;
            }
🧰 Tools
🪛 Biome (1.9.4)

[error] 157-157: Unnecessary continue statement

Unsafe fix: Delete the unnecessary continue statement

(lint/correctness/noUnnecessaryContinue)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 71906f0 and 987a08c.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (2)
  • package.json (2 hunks)
  • src/extension.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • package.json
🧰 Additional context used
🪛 Biome (1.9.4)
src/extension.ts

[error] 157-157: Unnecessary continue statement

Unsafe fix: Delete the unnecessary continue statement

(lint/correctness/noUnnecessaryContinue)

🔇 Additional comments (3)
src/extension.ts (3)

16-25: Disposable registration issue fixed correctly

Great job fixing the disposable leak by properly pushing the symbol provider into context.subscriptions. This ensures proper cleanup when the extension is deactivated.


143-150: Ensure proper state transitions in path handling

Line 149 resets the block type inside a condition that checks if a link was found, but it will always be executed if a link is found. Make sure this is the intended behavior.

            if (regexMatch = /(.+):path$/.exec(state.current.blockType)) {
                const link = this.checkLinks(line, i, document.uri.fsPath)
                if (link) {
                    links.push(link)
                    // check the file path just after the keyword
-                    state.current.blockType = regexMatch[1]
+                    // Reset the block type to the base type
+                    state.current.blockType = regexMatch[1]
                }
            }

This logic implies that you're resetting the block type to its base form (without :path suffix) only when a link is found. Is this the intended behavior? What happens when no link is found? Should the state remain in the :path mode for subsequent lines, or should it reset regardless?


219-227: 🛠️ Refactor suggestion

Improve checkDocument method clarity and return type safety

The current implementation is counterintuitive - it returns false when the document was already processed and could theoretically return undefined in some edge cases.

    checkDocument(document: vscode.TextDocument): boolean {
        const blocks = this.blockMap.get(document.uri.toString());
        if (!blocks) {
            this.update(document);
-           return !!this.blockMap.get(document.uri.toString());
+           return true; // Document was processed during this call
        }
-       return false;
+       return true; // Document was already processed
    }

Likely an incorrect or invalid review comment.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9c28ed2 and 3cf26d5.

📒 Files selected for processing (1)
  • .github/workflows/main.yml (1 hunks)

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

♻️ Duplicate comments (1)
.github/workflows/main.yml (1)

21-24: Optimize dependency installation in CI
Running both npm install and npm ci adds unnecessary time and undermines reproducibility. Consider leveraging a cache for ~/.npm and use only npm ci for installs, as recommended in CI environments.

🧹 Nitpick comments (2)
package.json (2)

56-58: Align @types/vscode version with declared VS Code engine
The extension targets VS Code ^1.75.0, but @types/vscode is pinned to ^1.53.0. To match the API surface, consider bumping the type definitions:

- "@types/vscode": "^1.53.0",
+ "@types/vscode": "^1.75.0",

64-75: Consider adding a prepare script for automatic builds
Adding a prepare script ensures npm install triggers a build, keeping CI and local workflows in sync:

 "scripts": {
+  "prepare": "npm run build",
   "clean": "rm -rf dist syntaxes languages snippets out",
   ...
 }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3cf26d5 and fedfa5f.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (7)
  • .github/workflows/main.yml (2 hunks)
  • .vscode/tasks.json (1 hunks)
  • .vscodeignore (1 hunks)
  • languages/snakemake.json (0 hunks)
  • package.json (2 hunks)
  • snippets/snakemake.json (0 hunks)
  • syntaxes/snakemake.tmLanguage.json (0 hunks)
💤 Files with no reviewable changes (3)
  • languages/snakemake.json
  • syntaxes/snakemake.tmLanguage.json
  • snippets/snakemake.json
✅ Files skipped from review due to trivial changes (1)
  • .vscodeignore
🚧 Files skipped from review as they are similar to previous changes (1)
  • .vscode/tasks.json
🧰 Additional context used
🧠 Learnings (1)
package.json (2)
Learnt from: Hocnonsense
PR: snakemake/snakemake-lang-vscode-plugin#45
File: package.json:62-73
Timestamp: 2025-04-20T16:05:33.444Z
Learning: VSCE (VS Code Extension packaging tool) does not support using both a `.vscodeignore` file and a "files" property in package.json simultaneously. Only one of these strategies should be used for determining which files are included in the packaged extension.
Learnt from: Hocnonsense
PR: snakemake/snakemake-lang-vscode-plugin#45
File: package.json:62-73
Timestamp: 2025-04-20T16:05:33.444Z
Learning: VSCE (VS Code Extension packaging tool) does not support using both a `.vscodeignore` file and a "files" property in package.json simultaneously. Only one of these strategies should be used for determining which files are included in the packaged extension.
🪛 actionlint (1.7.4)
.github/workflows/main.yml

8-8: "branches-ignore" section should not be empty

(syntax-check)

🔇 Additional comments (2)
package.json (2)

17-19: Confirm necessity of the node engine field
The engines.node constraint (>=18) is only enforced by npm and not by VSCE. VS Code extensions rely on engines.vscode for compatibility. Please verify if the node field is required or if it can be removed to avoid confusion.


62-63: Ensure inclusion of compiled extension entry point
The "main": "dist/extension.js" field correctly points to your bundled output. Ensure your .vscodeignore does not exclude dist/ so that this file is packaged.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (2)
.github/workflows/main.yml (2)

8-8: Remove empty branches-ignore entry
An empty branches-ignore: [] is a no-op and triggers an actionlint warning. Remove this line or specify the actual branch patterns you intend to ignore.

🧰 Tools
🪛 actionlint (1.7.4)

8-8: "branches-ignore" section should not be empty

(syntax-check)


22-24: Eliminate redundant npm install step
Combining npm install && npm ci is redundant because npm ci already performs a clean install from package-lock.json. Remove npm install and consider adding caching (e.g., actions/cache@v3) for ~/.npm to speed up subsequent CI runs.

-      - run:
-          npm install && npm ci
+      - run: npm ci
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e8bb4dd and ec45ce3.

📒 Files selected for processing (2)
  • .github/workflows/main.yml (2 hunks)
  • .github/workflows/release-please.yml (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • .github/workflows/release-please.yml
🧰 Additional context used
🪛 actionlint (1.7.4)
.github/workflows/main.yml

8-8: "branches-ignore" section should not be empty

(syntax-check)


18-18: the runner of "actions/setup-node@v3" action is too old to run on GitHub Actions. update the action's version to fix this issue

(action)

Comment on lines 18 to 21
- uses: actions/setup-node@v3
with:
node-version: 12

- run: npm ci
node-version: 18.*

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Use latest actions/setup-node version and lock node-version
Upgrade to actions/setup-node@v4 and use a stable version specifier (e.g., '18.x') to ensure compatibility with the GitHub Actions runner and avoid potential deprecation issues.

-      - uses: actions/setup-node@v3
-        with:
-          node-version: 18.*
+      - uses: actions/setup-node@v4
+        with:
+          node-version: '18.x'
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- uses: actions/setup-node@v3
with:
node-version: 12
- run: npm ci
\ No newline at end of file
node-version: 18.*
- uses: actions/setup-node@v4
with:
node-version: '18.x'
🧰 Tools
🪛 actionlint (1.7.4)

18-18: the runner of "actions/setup-node@v3" action is too old to run on GitHub Actions. update the action's version to fix this issue

(action)

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

♻️ Duplicate comments (1)
package.json (1)

63-65: @types/node version aligned with runtime.

You’ve correctly reverted to

"@types/node": "^14 || ^16 || ^18"

which matches VS Code’s embedded Node versions and avoids Node 22-only typings.

🧹 Nitpick comments (1)
package.json (1)

63-64: Align @types/vscode with your engine requirement.

Currently you pin

"@types/vscode": "^1.53.0"

but your engines.vscode is ^1.75.0. Consider bumping the types package to ^1.75.0 (or the closest matching SDK) to cover all used APIs.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6243c09 and 3cbac6e.

📒 Files selected for processing (3)
  • package.json (3 hunks)
  • src/yaml/snakemake-inject.syntax.yaml (1 hunks)
  • src/yaml/snakemake.syntax.yaml (4 hunks)
✅ Files skipped from review due to trivial changes (1)
  • src/yaml/snakemake-inject.syntax.yaml
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/yaml/snakemake.syntax.yaml
🧰 Additional context used
🧠 Learnings (1)
package.json (2)
Learnt from: Hocnonsense
PR: snakemake/snakemake-lang-vscode-plugin#45
File: package.json:62-73
Timestamp: 2025-04-20T16:05:33.456Z
Learning: VSCE (VS Code Extension packaging tool) does not support using both a `.vscodeignore` file and a "files" property in package.json simultaneously. Only one of these strategies should be used for determining which files are included in the packaged extension.
Learnt from: Hocnonsense
PR: snakemake/snakemake-lang-vscode-plugin#45
File: package.json:62-73
Timestamp: 2025-04-20T16:05:33.456Z
Learning: VSCE (VS Code Extension packaging tool) does not support using both a `.vscodeignore` file and a "files" property in package.json simultaneously. Only one of these strategies should be used for determining which files are included in the packaged extension.
🔇 Additional comments (2)
package.json (2)

17-18: Confirm VS Code engine and Node.js compatibility.

You’ve bumped the minimum VS Code engine to ^1.75.0 and Node.js to >=18. Please verify that the new symbol, link, and hover provider APIs you’re using indeed require VS Code 1.75.0+ and that your build scripts (ES modules, top‑level awaits, etc.) run successfully on Node 18+.


69-69: Verify packaging of compiled entry point.

You set

"main": "dist/extension.js"

Ensure your .vscodeignore does not exclude the dist/ directory so that the compiled bundle is included when you vsce package.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🔭 Outside diff range comments (1)
src/yaml/snakemake.syntax.yaml (1)

51-73: 🛠️ Refactor suggestion

⚠️ Potential issue

Comments embedded inside the match: > block will break the regex
Line 66’s comment (# may end with a "with:"", but that can be caught by other rules) is actually included in the multi‑line regex, rendering the pattern invalid. Move or remove this comment and explicitly handle the optional with: clause in the regex.

Proposed diff:

  userulefromas:
    match: >
      (?x)
        \b(use\s+rule)\s+(\w+|\w+\*|\*)\s+(from)\s+(\w+)\s+(as)\s+(\w+|\w+\*)
-       # may end with a "with:"", but that can be caught by other rules
+       (?:\s+with:)?
    captures:
      "1": { name: keyword.control.snakemake }
      "2": { name: entity.name.function.snakemake.rule }
      "3": { name: keyword.control.snakemake }
      "4": { name: entity.name.type.snakemake.rule }
      "5": { name: keyword.control.snakemake }
      "6": { name: entity.name.function.snakemake.rule }
🧹 Nitpick comments (2)
src/yaml/snakemake.syntax.yaml (1)

107-119: Optional: Enhance f‑string support in snakestrings
Current snakestrings includes standard Python string patterns, but may not cover f‑string interpolation braces. Consider adding "source.python#string-interpolations" or "source.python#f-string-expression" under patterns: to fully support f‑strings in shell blocks.

src/yaml/snakemake-inject.syntax.yaml (1)

56-61: Refine the objects scope name
The objects pattern is currently scoped as meta.c, which is too generic. A more descriptive scope like meta.object.snakemake would improve readability and maintain consistency with other Snakemake scopes.

-  objects:
-    name: meta.c
+  objects:
+    name: meta.object.snakemake
     match: \b({{objects}})\b(?!\s*=)
     captures:
       "1": { name: entity.name.type.class.snakemake }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3cbac6e and 02977c5.

📒 Files selected for processing (4)
  • README.md (1 hunks)
  • package.json (3 hunks)
  • src/yaml/snakemake-inject.syntax.yaml (1 hunks)
  • src/yaml/snakemake.syntax.yaml (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • README.md
  • package.json
🔇 Additional comments (6)
src/yaml/snakemake.syntax.yaml (2)

7-17: Top-level patterns list is clear and correct
The new patterns array cleanly includes all Snakemake constructs (#snakestrings, #configs, #rules, etc.) and falls back to source.python for general Python syntax.


20-50: Repository patterns for configs, rules, and modules look solid
Each pattern uses free‑spacing ((?x)) for readability, captures the correct keyword tokens, and assigns accurate scopes for Snakemake constructs.

src/yaml/snakemake-inject.syntax.yaml (4)

6-9: Core injection patterns are correctly included
The patterns section properly pulls in the root #quoteall and #snakemakenames for keyword injection into Python contexts.


11-36: Nested delimiter patterns are well‑structured
The quotessmall, quotesmid, and quotesbig definitions recursively include each other alongside #snakemakenames and base Python, enabling deep nesting support.


38-46: Grouping of Snakemake names is comprehensive
The snakemakenames pattern aggregates classes, rule references, objects, arguments, and functions—covering all key Snakemake identifiers.


61-75: Rule‑argument and function patterns are well‑defined
The ruleargargs, ruleargs, and functions entries correctly capture Snakemake parameters and built‑in functions with appropriate scopes.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (1)
src/extension.ts (1)

14-23: ⚠️ Potential issue

Ensure DocumentSymbolProvider disposal.

The DocumentSymbolProvider is registered correctly, but its Disposable should be pushed to the context.subscriptions array, as you've done with the other providers.

-    context.subscriptions.push(
-        vscode.languages.registerDocumentSymbolProvider(
+    context.subscriptions.push(vscode.languages.registerDocumentSymbolProvider(
             { language: 'snakemake' },
             {
                 provideDocumentSymbols(document: vscode.TextDocument) {
                     return snakemakeManager.getSymbols(document);
                 }
             }
-        )
+        ))
🧹 Nitpick comments (1)
src/extension.ts (1)

168-168: Remove unnecessary continue statement.

The continue statement at line 168 is unnecessary as it's the last statement in the loop body.

-                continue;
🧰 Tools
🪛 Biome (1.9.4)

[error] 168-168: Unnecessary continue statement

Unsafe fix: Delete the unnecessary continue statement

(lint/correctness/noUnnecessaryContinue)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 49e0c50 and ed01912.

📒 Files selected for processing (4)
  • src/extension.ts (1 hunks)
  • src/keywords.yaml (2 hunks)
  • src/yaml/snakemake-inject.syntax.yaml (1 hunks)
  • src/yaml/snakemake.syntax.yaml (5 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/keywords.yaml
🧰 Additional context used
🪛 Biome (1.9.4)
src/extension.ts

[error] 168-168: Unnecessary continue statement

Unsafe fix: Delete the unnecessary continue statement

(lint/correctness/noUnnecessaryContinue)

🔇 Additional comments (17)
src/yaml/snakemake-inject.syntax.yaml (6)

1-4: Looks good! The injection selector is well-defined.

The file appropriately defines a scopeName for Snakemake keywords and correctly specifies the file types. The injection selector properly targets Python contexts while excluding comments and strings, which is exactly what we want for syntax highlighting.


6-13: Well-structured pattern includes.

The patterns are logically organized and include all the important Snakemake constructs for highlighting: classes, rules and checkpoints references, objects, job parameters, and functions.


17-19: Good boundary handling in the regex pattern.

The regex pattern includes proper word boundary handling with (?<![\w.]) and (?!\s*=) which prevents false positives from partial word matches and assignments.


20-25: Proper rule reference implementation.

The pattern correctly captures rules references with optional dot-notation access to rule names, and assigns appropriate semantic token types for good syntax highlighting.


26-32: Well-designed checkpoints reference pattern.

This pattern thoughtfully captures three components: the checkpoints keyword, an optional rule name, and the optional .get method, with appropriate semantic tokens for each part.


38-43: Good variable handling in job parameters pattern.

The pattern correctly identifies and differentiates between job parameter names and their dot-accessed properties, applying proper semantic token types to each component.

src/extension.ts (7)

9-12: Good use of subscriptions for proper disposal.

The code correctly pushes event listeners and providers into the context subscriptions array, ensuring proper cleanup when the extension is deactivated.


38-41: Good shell block interface design.

The ShellBlock interface is well-designed, capturing both the range in the document and the extracted content, which is exactly what's needed for hover providers.


43-52: Well-structured regex definitions.

Organizing the regex patterns in a namespace makes the code more maintainable. The patterns are also well-structured to capture the various Snakemake constructs.


60-70: Excellent debounce implementation.

The debounce mechanism efficiently prevents excessive updates during rapid document changes, improving performance. The code also properly cleans up timeouts to prevent memory leaks.


197-200: Good fix for nested shell block handling.

The code correctly calculates the position of the new delimiter using newDelimiterPos, avoiding potential issues with nested shell blocks. This is a robust implementation.


259-271: Well-implemented hover provider.

The hover provider is well-implemented, showing syntax-highlighted shell blocks and using proper markdown rendering. The trimEmptyLines function ensures a clean hover display.


206-228:

Details

✅ Verification successful

Verify file paths across operating systems.

The link resolution looks good for local files, but may need additional handling for cross-platform path formats or network paths. Consider testing with both Unix and Windows paths.


🏁 Script executed:

#!/bin/bash
# Test path resolution across different formats

# Check if the code can handle both Unix and Windows paths
cat << EOF > test_path_formats.js
const path = require('path');
const isWin = process.platform === 'win32';

console.log("Testing path resolution:");
console.log("1. Current platform:", process.platform);

// Test path joining
const baseDir = "/some/base/dir";
const baseDirWin = "C:\\some\\base\\dir";
const testPaths = [
  "relative/path.txt",
  "./relative/path.txt",
  "../parent/path.txt",
  "/absolute/path.txt",
  "C:\\absolute\\windows\\path.txt"
];

console.log("\n2. Path resolution results:");
testPaths.forEach(p => {
  const base = isWin ? baseDirWin : baseDir;
  try {
    const resolved = path.resolve(base, p);
    console.log(`${p}${resolved} ${p.startsWith('/') || /^[A-Z]:[\\\/]/.test(p) ? "(absolute)" : "(relative)"}`);
  } catch (e) {
    console.log(`${p} → ERROR: ${e.message}`);
  }
});

EOF

node test_path_formats.js

Length of output: 387


No cross-platform path issues detected

We’ve verified that Node’s built-in path.resolve uses POSIX semantics on Unix/macOS and Win32 semantics on Windows, correctly handling:

  • Relative paths (e.g. foo/bar.txt)
  • Absolute POSIX paths (/usr/local/bin)
  • Drive-letter paths (C:\dir\file.txt)
  • UNC network paths (\\server\share\file.txt)

Since the extension calls require('path').resolve, it will automatically use the correct resolution logic for the host OS. No further changes are needed.

src/yaml/snakemake.syntax.yaml (4)

7-7: Good consolidation of string patterns.

Replacing multiple quote patterns with a single consolidated #snakestrings pattern simplifies the grammar and makes it easier to maintain.


33-33: Improved rule and module name pattern matching.

Using {{legal-name}} instead of generic \w+ pattern provides more precise matching for rule and module names, aligning with Snakemake's naming conventions.

Also applies to: 44-44


64-81: Enhanced rule reference pattern with good comments.

The expanded userulefromas pattern now properly handles optional "as" clauses and "exclude" lists with multiple legal names. The comment about "with:" is helpful for maintenance.


117-128: Strong unified string pattern implementation.

The new snakestrings pattern correctly captures single, double, and triple-quoted strings with proper begin/end delimiters. Using Python string sub-patterns for formatting and unicode is a good approach that ensures consistency with Python string highlighting.

src/extension.ts Outdated
Comment on lines 230 to 238
checkDocument(document: vscode.TextDocument): boolean {
const blocks = this.blockMap.get(document.uri.toString());
if (!blocks) {
this.update(document);
return !!this.blockMap.get(document.uri.toString());
}
return false;

}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Returns incorrect value in checkDocument.

The checkDocument method incorrectly returns false when blocks exist, but it should return the presence of blocks to indicate whether document checking was successful.

-        if (!blocks) {
+        const documentNeedsUpdate = !blocks;
+        if (documentNeedsUpdate) {
             this.update(document);
-            return !!this.blockMap.get(document.uri.toString());
+            return true;
         }
-        return false;
+        return true;

Committable suggestion skipped: line range outside the PR's diff.

@johanneskoester
Copy link
Contributor

I like this, but I am not a vscode plugin expert. If we could get a second review by anybody with vscode plugin development expertise, that would be great.

Copy link

@LSTM-Kirigaya LSTM-Kirigaya left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice PR! The language support LSP provider and highlight textmate are written quite systematic. Thanks for your contribution !

@johanneskoester johanneskoester merged commit 2b1d256 into master Jun 11, 2025
3 checks passed
@johanneskoester johanneskoester deleted the feat/extension.ts branch June 11, 2025 12:44
@github-project-automation github-project-automation bot moved this from In review to Done in Snakemake Hackathon March 2025 Jun 11, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Development

Successfully merging this pull request may close these issues.

4 participants