MartyPlugin

Trait MartyPlugin 

Source
pub trait MartyPlugin {
    // Required methods
    fn name(&self) -> &str;
    fn key(&self) -> &str;
    fn workspace_provider(&self) -> &dyn WorkspaceProvider;

    // Provided method
    fn configuration_options(&self) -> Option<Value> { ... }
}
Expand description

The main plugin interface that defines plugin metadata and behavior.

This trait provides Marty with essential information about your plugin and connects it to the workspace scanning logic via WorkspaceProvider.

§Implementation Requirements

Your plugin struct must also implement:

  • Default or provide a new() constructor for the export_plugin! macro
  • Be Send + Sync for thread safety (automatically satisfied for most structs)

§Example

use marty_plugin_protocol::{MartyPlugin, WorkspaceProvider};
use serde_json::{json, Value};

pub struct MyPlugin;

impl MyPlugin {
    pub const fn new() -> Self { Self }
}

impl Default for MyPlugin {
    fn default() -> Self { Self::new() }  
}

impl MartyPlugin for MyPlugin {
    fn name(&self) -> &str {
        "My Awesome Framework Plugin"  // User-friendly display name
    }
     
    fn key(&self) -> &str {
        "my-framework"  // Unique identifier (no spaces!)
    }
     
    fn workspace_provider(&self) -> &dyn WorkspaceProvider {
        &MyWorkspaceProvider  // Your detection logic
    }
     
    fn configuration_options(&self) -> Option<Value> {
        Some(json!({
            "type": "object",
            "properties": {
                "version": {
                    "type": "string",
                    "description": "Target framework version",
                    "default": "latest"
                }
            },
            "additionalProperties": false
        }))
    }
}

Required Methods§

Source

fn name(&self) -> &str

Return the human-readable name of this plugin.

Purpose: Displayed to users in logs, error messages, and plugin listings. Should be descriptive and professional.

Guidelines:

  • Use proper capitalization and spacing
  • Include the technology/framework name
  • Keep it concise but descriptive
  • Avoid technical jargon that users might not understand
§Examples
fn name(&self) -> &str {
    "Cargo Workspace Plugin"      // ✅ Clear, professional
     
    // Other good examples:
    // "TypeScript Project Plugin"   - Technology-specific
    // "Python Requirements Plugin"  - Describes functionality
     
    // ❌ Avoid these patterns:
    // "cargo-plugin"               - Too technical
    // "My Super Awesome Plugin!!!" - Unprofessional
    // "Plugin"                     - Too generic
}
Source

fn key(&self) -> &str

Return the unique identifier for this plugin.

Purpose: Used internally by Marty for:

  • Plugin registration and loading
  • Configuration file sections ([plugins.your-key])
  • Dependency resolution and caching
  • The discovered_by field in InferredProject

Requirements:

  • Must be unique across all plugins
  • No whitespace characters (spaces, tabs, newlines)
  • Use kebab-case for consistency
  • Should be stable across plugin versions

Naming Convention:

  • Use the primary technology name: "cargo", "typescript", "python"
  • For sub-technologies, use hyphens: "next-js", "create-react-app"
  • Avoid version numbers or vendor names in the key
§Examples
fn key(&self) -> &str {
    "cargo"           // ✅ Rust Cargo projects
     
    // Other good examples:
    // "typescript"      - TypeScript projects  
    // "python"          - Python projects
    // "next-js"         - Next.js frameworks
    // "docker-compose"  - Docker Compose files
     
    // ❌ Avoid these patterns:
    // "cargo plugin"    - Contains space
    // "typescript-v2"   - Version in key
    // "my company-ts"   - Vendor name + space
}
Source

fn workspace_provider(&self) -> &dyn WorkspaceProvider

Return the workspace provider implementation for this plugin.

Purpose: Connects your plugin to the workspace scanning and project detection logic. This is where the actual work happens.

Implementation Pattern: Most plugins create a separate struct for the workspace provider and return a reference to a static instance.

§Example
fn workspace_provider(&self) -> &dyn WorkspaceProvider {
    // Pattern 1: Static instance (most common)
    &MyWorkspaceProvider
     
    // Pattern 2: If you need state, use a field
    // &self.workspace_provider
}

Provided Methods§

Source

fn configuration_options(&self) -> Option<Value>

Return JSON Schema configuration options for this plugin.

Purpose: Allow users to customize plugin behavior through configuration files. The schema is used for validation and IDE autocomplete in Marty config files.

When to Provide Configuration:

  • Plugin has configurable behavior (build commands, versions, paths)
  • Users need to specify framework-specific options
  • Different projects might need different settings

Schema Requirements:

  • Must be valid JSON Schema (draft 7 recommended)
  • Should have a root "type": "object"
  • Include "description" for all properties
  • Provide sensible "default" values
  • Use "additionalProperties": false for strict validation
§Example: Comprehensive Configuration Schema
fn configuration_options(&self) -> Option<Value> {
    Some(json!({
        "type": "object",
        "description": "Configuration for My Framework Plugin",
        "properties": {
            // String configurations
            "build_command": {
                "type": "string",
                "description": "Command to build projects",
                "default": "build",
                "examples": ["build", "compile", "make"]
            },
            "target_version": {
                "type": "string",
                "description": "Framework version to target",
                "default": "latest",
                "enum": ["1.0", "2.0", "latest"]
            },
             
            // Boolean flags
            "enable_optimization": {
                "type": "boolean",
                "description": "Enable build optimizations",
                "default": true
            },
            "strict_mode": {
                "type": "boolean",
                "description": "Enable strict validation rules",
                "default": false
            },
             
            // Array configurations
            "additional_includes": {
                "type": "array",
                "description": "Extra glob patterns to include",
                "items": { "type": "string" },
                "default": [],
                "examples": [["**/*.config.js", "**/*.env"]]
            },
             
            // Nested object configurations
            "build_settings": {
                "type": "object",
                "description": "Advanced build configuration",
                "properties": {
                    "output_dir": {
                        "type": "string",
                        "description": "Build output directory",
                        "default": "dist"
                    },
                    "minify": {
                        "type": "boolean",
                        "description": "Minify output files",
                        "default": true
                    }
                },
                "additionalProperties": false
            }
        },
        "additionalProperties": false,
        "required": []  // Specify required fields if any
    }))
}

For Simple Plugins: Return None if your plugin doesn’t need configuration.

fn configuration_options(&self) -> Option<Value> {
    None  // No configuration needed for this plugin
}

Implementors§