|
@@ -0,0 +1,387 @@
|
|
|
|
|
+using Spry;
|
|
|
|
|
+using Inversion;
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * ComponentsMkcomponentPage - Documentation for the spry-mkcomponent tool
|
|
|
|
|
+ *
|
|
|
|
|
+ * This page explains how to use spry-mkcomponent to inject HTML markup
|
|
|
|
|
+ * into Vala component files.
|
|
|
|
|
+ */
|
|
|
|
|
+public class ComponentsMkcomponentPage : PageComponent {
|
|
|
|
|
+
|
|
|
|
|
+ public const string ROUTE = "/components/spry-mkcomponent";
|
|
|
|
|
+
|
|
|
|
|
+ private ComponentFactory factory = inject<ComponentFactory>();
|
|
|
|
|
+
|
|
|
|
|
+ public override string markup { get {
|
|
|
|
|
+ return """
|
|
|
|
|
+ <div sid="page" class="doc-content">
|
|
|
|
|
+ <h1>spry-mkcomponent Tool</h1>
|
|
|
|
|
+
|
|
|
|
|
+ <section class="doc-section">
|
|
|
|
|
+ <h2>What is spry-mkcomponent?</h2>
|
|
|
|
|
+ <p>
|
|
|
|
|
+ <code>spry-mkcomponent</code> is a command-line tool that processes Vala component
|
|
|
|
|
+ files by injecting HTML markup into the <code>markup</code> property getter. This
|
|
|
|
|
+ allows you to maintain your HTML templates in separate files while keeping your
|
|
|
|
|
+ Vala code clean and focused on logic.
|
|
|
|
|
+ </p>
|
|
|
|
|
+ <p>
|
|
|
|
|
+ The tool enables a cleaner separation of concerns:
|
|
|
|
|
+ </p>
|
|
|
|
|
+ <ul>
|
|
|
|
|
+ <li><strong>Component logic</strong> - Vala code handling actions, state, and behavior</li>
|
|
|
|
|
+ <li><strong>HTML templates</strong> - Separate .html files with your markup</li>
|
|
|
|
|
+ </ul>
|
|
|
|
|
+ </section>
|
|
|
|
|
+
|
|
|
|
|
+ <section class="doc-section">
|
|
|
|
|
+ <h2>Command-Line Usage</h2>
|
|
|
|
|
+
|
|
|
|
|
+ <spry-component name="CodeBlockComponent" sid="usage-code"/>
|
|
|
|
|
+
|
|
|
|
|
+ <h3>Options</h3>
|
|
|
|
|
+ <table class="doc-table">
|
|
|
|
|
+ <thead>
|
|
|
|
|
+ <tr>
|
|
|
|
|
+ <th>Option</th>
|
|
|
|
|
+ <th>Description</th>
|
|
|
|
|
+ </tr>
|
|
|
|
|
+ </thead>
|
|
|
|
|
+ <tbody>
|
|
|
|
|
+ <tr>
|
|
|
|
|
+ <td><code>-o, --output FILE</code></td>
|
|
|
|
|
+ <td>Output file path (default: input filename in build directory)</td>
|
|
|
|
|
+ </tr>
|
|
|
|
|
+ <tr>
|
|
|
|
|
+ <td><code>-h, --html FILE</code></td>
|
|
|
|
|
+ <td>HTML template file (default: <input_vala>.html)</td>
|
|
|
|
|
+ </tr>
|
|
|
|
|
+ <tr>
|
|
|
|
|
+ <td><code>-v, --version</code></td>
|
|
|
|
|
+ <td>Show version information</td>
|
|
|
|
|
+ </tr>
|
|
|
|
|
+ <tr>
|
|
|
|
|
+ <td><code>--help</code></td>
|
|
|
|
|
+ <td>Show help message</td>
|
|
|
|
|
+ </tr>
|
|
|
|
|
+ </tbody>
|
|
|
|
|
+ </table>
|
|
|
|
|
+ </section>
|
|
|
|
|
+
|
|
|
|
|
+ <section class="doc-section">
|
|
|
|
|
+ <h2>How It Works</h2>
|
|
|
|
|
+ <p>
|
|
|
|
|
+ The tool takes two input files and produces a single output file with the
|
|
|
|
|
+ HTML template embedded in the markup property:
|
|
|
|
|
+ </p>
|
|
|
|
|
+
|
|
|
|
|
+ <spry-component name="CodeBlockComponent" sid="workflow-diagram"/>
|
|
|
|
|
+
|
|
|
|
|
+ <div class="info-box">
|
|
|
|
|
+ <p>
|
|
|
|
|
+ <strong>💡 Key Concept:</strong> The tool looks for an empty <code>markup</code>
|
|
|
|
|
+ property getter and injects the HTML content. If the getter already has content,
|
|
|
|
|
+ the file is passed through unchanged.
|
|
|
|
|
+ </p>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </section>
|
|
|
|
|
+
|
|
|
|
|
+ <section class="doc-section">
|
|
|
|
|
+ <h2>Example Transformation</h2>
|
|
|
|
|
+ <p>
|
|
|
|
|
+ Here's a complete example showing how the tool transforms your component files:
|
|
|
|
|
+ </p>
|
|
|
|
|
+
|
|
|
|
|
+ <h3>Input Vala File (<code>UserContentComponent.vala</code>)</h3>
|
|
|
|
|
+ <spry-component name="CodeBlockComponent" sid="input-vala"/>
|
|
|
|
|
+
|
|
|
|
|
+ <h3>Input HTML File (<code>UserContentComponent.vala.html</code>)</h3>
|
|
|
|
|
+ <spry-component name="CodeBlockComponent" sid="input-html"/>
|
|
|
|
|
+
|
|
|
|
|
+ <h3>Output Vala File (<code>UserContentComponent.vala</code>)</h3>
|
|
|
|
|
+ <spry-component name="CodeBlockComponent" sid="output-vala"/>
|
|
|
|
|
+
|
|
|
|
|
+ <p>
|
|
|
|
|
+ Notice how the empty <code>markup</code> getter now returns the HTML content
|
|
|
|
|
+ as a verbatim string literal. The <code>sid</code> attributes in your HTML
|
|
|
|
|
+ are preserved, allowing you to access elements via <code>this["sid"]</code>
|
|
|
|
|
+ in your Vala code.
|
|
|
|
|
+ </p>
|
|
|
|
|
+ </section>
|
|
|
|
|
+
|
|
|
|
|
+ <section class="doc-section">
|
|
|
|
|
+ <h2>Integrating with Meson</h2>
|
|
|
|
|
+ <p>
|
|
|
|
|
+ The recommended way to use spry-mkcomponent is with meson's build system.
|
|
|
|
|
+ You can use either <code>generator()</code> for processing multiple files
|
|
|
|
|
+ or <code>custom_target()</code> for single files with custom options.
|
|
|
|
|
+ </p>
|
|
|
|
|
+
|
|
|
|
|
+ <h3>Using generator() for Multiple Files</h3>
|
|
|
|
|
+ <spry-component name="CodeBlockComponent" sid="meson-generator"/>
|
|
|
|
|
+
|
|
|
|
|
+ <p>
|
|
|
|
|
+ The <code>generator()</code> function is ideal when you have multiple component
|
|
|
|
|
+ files that all follow the same pattern (HTML file named
|
|
|
|
|
+ <code><component>.vala.html</code>).
|
|
|
|
|
+ </p>
|
|
|
|
|
+
|
|
|
|
|
+ <h3>Using custom_target() for Single Files</h3>
|
|
|
|
|
+ <spry-component name="CodeBlockComponent" sid="meson-custom-target"/>
|
|
|
|
|
+
|
|
|
|
|
+ <p>
|
|
|
|
|
+ Use <code>custom_target()</code> when you need more control over file paths
|
|
|
|
|
+ or want to specify a custom HTML template location.
|
|
|
|
|
+ </p>
|
|
|
|
|
+
|
|
|
|
|
+ <h3>Complete meson.build Example</h3>
|
|
|
|
|
+ <spry-component name="CodeBlockComponent" sid="meson-complete"/>
|
|
|
|
|
+
|
|
|
|
|
+ <div class="info-box">
|
|
|
|
|
+ <p>
|
|
|
|
|
+ <strong>💡 Tip:</strong> The <code>@INPUT@</code> and <code>@OUTPUT@</code>
|
|
|
|
|
+ placeholders are automatically replaced by meson with the actual file paths.
|
|
|
|
|
+ The <code>@BASENAME@</code> placeholder is replaced with the input filename
|
|
|
|
|
+ without extension.
|
|
|
|
|
+ </p>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </section>
|
|
|
|
|
+
|
|
|
|
|
+ <section class="doc-section">
|
|
|
|
|
+ <h2>HTML Template Guidelines</h2>
|
|
|
|
|
+ <p>
|
|
|
|
|
+ When creating HTML templates for use with spry-mkcomponent, follow these guidelines:
|
|
|
|
|
+ </p>
|
|
|
|
|
+
|
|
|
|
|
+ <ul>
|
|
|
|
|
+ <li>
|
|
|
|
|
+ <strong>Use <code>sid</code> attributes</strong> - Add <code>sid="name"</code>
|
|
|
|
|
+ to elements you need to access from Vala code via <code>this["name"]</code>
|
|
|
|
|
+ </li>
|
|
|
|
|
+ <li>
|
|
|
|
|
+ <strong>Keep templates alongside Vala files</strong> - Name them
|
|
|
|
|
+ <code>ComponentName.vala.html</code> for automatic discovery
|
|
|
|
|
+ </li>
|
|
|
|
|
+ <li>
|
|
|
|
|
+ <strong>Use HTMX attributes</strong> - Add <code>hx-*</code> attributes for
|
|
|
|
|
+ interactivity without writing JavaScript
|
|
|
|
|
+ </li>
|
|
|
|
|
+ <li>
|
|
|
|
|
+ <strong>Avoid complex logic</strong> - Keep templates focused on structure;
|
|
|
|
|
+ use Vala for conditional rendering
|
|
|
|
|
+ </li>
|
|
|
|
|
+ </ul>
|
|
|
|
|
+
|
|
|
|
|
+ <spry-component name="CodeBlockComponent" sid="html-guidelines"/>
|
|
|
|
|
+ </section>
|
|
|
|
|
+
|
|
|
|
|
+ <section class="doc-section">
|
|
|
|
|
+ <h2>Workflow Integration</h2>
|
|
|
|
|
+ <p>
|
|
|
|
|
+ A typical development workflow with spry-mkcomponent looks like this:
|
|
|
|
|
+ </p>
|
|
|
|
|
+
|
|
|
|
|
+ <ol>
|
|
|
|
|
+ <li><strong>Create</strong> your Vala component with an empty <code>markup</code> getter</li>
|
|
|
|
|
+ <li><strong>Create</strong> an HTML template file with the same base name</li>
|
|
|
|
|
+ <li><strong>Build</strong> your project - meson runs spry-mkcomponent automatically</li>
|
|
|
|
|
+ <li><strong>Iterate</strong> - Edit either file; changes are picked up on rebuild</li>
|
|
|
|
|
+ </ol>
|
|
|
|
|
+
|
|
|
|
|
+ <p>
|
|
|
|
|
+ During development, you can run the tool manually to preview the generated output:
|
|
|
|
|
+ </p>
|
|
|
|
|
+
|
|
|
|
|
+ <spry-component name="CodeBlockComponent" sid="manual-run"/>
|
|
|
|
|
+ </section>
|
|
|
|
|
+
|
|
|
|
|
+ <section class="doc-section">
|
|
|
|
|
+ <h2>When to Use spry-mkcomponent</h2>
|
|
|
|
|
+
|
|
|
|
|
+ <h3>✅ Good Use Cases</h3>
|
|
|
|
|
+ <ul>
|
|
|
|
|
+ <li>Components with substantial HTML markup</li>
|
|
|
|
|
+ <li>Teams where designers work on HTML separately from developers</li>
|
|
|
|
|
+ <li>Reusing HTML templates across multiple components</li>
|
|
|
|
|
+ <li>Keeping Vala files focused on logic</li>
|
|
|
|
|
+ </ul>
|
|
|
|
|
+
|
|
|
|
|
+ <h3>❌ When to Skip It</h3>
|
|
|
|
|
+ <ul>
|
|
|
|
|
+ <li>Simple components with minimal markup</li>
|
|
|
|
|
+ <li>Quick prototypes where separation isn't beneficial</li>
|
|
|
|
|
+ <li>Components with dynamically generated markup</li>
|
|
|
|
|
+ </ul>
|
|
|
|
|
+
|
|
|
|
|
+ <div class="info-box">
|
|
|
|
|
+ <p>
|
|
|
|
|
+ <strong>💡 Remember:</strong> You can always inline markup directly in your
|
|
|
|
|
+ Vala files. spry-mkcomponent is opt-in - use it when the separation provides
|
|
|
|
|
+ value for your project.
|
|
|
|
|
+ </p>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </section>
|
|
|
|
|
+
|
|
|
|
|
+ <section class="doc-section">
|
|
|
|
|
+ <h2>Next Steps</h2>
|
|
|
|
|
+ <div class="nav-cards">
|
|
|
|
|
+ <a href="/components/template-syntax" class="nav-card">
|
|
|
|
|
+ <h3>← Template Syntax</h3>
|
|
|
|
|
+ <p>Learn about component template syntax</p>
|
|
|
|
|
+ </a>
|
|
|
|
|
+ <a href="/components/actions" class="nav-card">
|
|
|
|
|
+ <h3>Actions →</h3>
|
|
|
|
|
+ <p>Handle user interactions in components</p>
|
|
|
|
|
+ </a>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </section>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ """;
|
|
|
|
|
+ }}
|
|
|
|
|
+
|
|
|
|
|
+ public override async void prepare() throws Error {
|
|
|
|
|
+ var usage_code = get_component_child<CodeBlockComponent>("usage-code");
|
|
|
|
|
+ usage_code.language = "Bash";
|
|
|
|
|
+ usage_code.code = "spry-mkcomponent [OPTIONS] <INPUT_VALA_FILE>\n\n" +
|
|
|
|
|
+ "# Examples:\n" +
|
|
|
|
|
+ "spry-mkcomponent Components/UserComponent.vala\n" +
|
|
|
|
|
+ "spry-mkcomponent -o build/UserComponent.vala Components/UserComponent.vala\n" +
|
|
|
|
|
+ "spry-mkcomponent --html Templates/User.html Components/UserComponent.vala";
|
|
|
|
|
+
|
|
|
|
|
+ var workflow_diagram = get_component_child<CodeBlockComponent>("workflow-diagram");
|
|
|
|
|
+ workflow_diagram.language = "Text";
|
|
|
|
|
+ workflow_diagram.code = "┌─────────────────────────────┐ ┌─────────────────────────────┐\n" +
|
|
|
|
|
+ "│ Component.vala │ │ Component.vala.html │\n" +
|
|
|
|
|
+ "│ (empty markup getter) │ │ (HTML template) │\n" +
|
|
|
|
|
+ "└─────────────┬───────────────┘ └─────────────┬───────────────┘\n" +
|
|
|
|
|
+ " │ │\n" +
|
|
|
|
|
+ " └───────────────┬───────────────────┘\n" +
|
|
|
|
|
+ " │\n" +
|
|
|
|
|
+ " ▼\n" +
|
|
|
|
|
+ " ┌─────────────────┐\n" +
|
|
|
|
|
+ " │ spry-mkcomponent │\n" +
|
|
|
|
|
+ " └────────┬────────┘\n" +
|
|
|
|
|
+ " │\n" +
|
|
|
|
|
+ " ▼\n" +
|
|
|
|
|
+ " ┌─────────────────────────────┐\n" +
|
|
|
|
|
+ " │ Component.vala │\n" +
|
|
|
|
|
+ " │ (with generated getter) │\n" +
|
|
|
|
|
+ " └─────────────────────────────┘";
|
|
|
|
|
+
|
|
|
|
|
+ var input_vala = get_component_child<CodeBlockComponent>("input-vala");
|
|
|
|
|
+ input_vala.language = "Vala";
|
|
|
|
|
+ input_vala.code = "class UserContentComponent : Component {\n" +
|
|
|
|
|
+ " public override string markup { get; }\n\n" +
|
|
|
|
|
+ " public async override void handle_action(string action) throws Error {\n" +
|
|
|
|
|
+ " this[\"message\"].text_content = \"Hello, World!\";\n" +
|
|
|
|
|
+ " }\n" +
|
|
|
|
|
+ "}";
|
|
|
|
|
+
|
|
|
|
|
+ var input_html = get_component_child<CodeBlockComponent>("input-html");
|
|
|
|
|
+ input_html.language = "HTML";
|
|
|
|
|
+ input_html.code = "<p>You said: <strong sid=\"message\"></strong></p>";
|
|
|
|
|
+
|
|
|
|
|
+ var output_vala = get_component_child<CodeBlockComponent>("output-vala");
|
|
|
|
|
+ output_vala.language = "Vala";
|
|
|
|
|
+ output_vala.code = "class UserContentComponent : Component {\n" +
|
|
|
|
|
+ " public override string markup { get {\n" +
|
|
|
|
|
+ " return \"\"\"<p>You said: <strong sid=\"message\"></strong></p>\"\"\";\n" +
|
|
|
|
|
+ " }}\n\n" +
|
|
|
|
|
+ " public async override void handle_action(string action) throws Error {\n" +
|
|
|
|
|
+ " this[\"message\"].text_content = \"Hello, World!\";\n" +
|
|
|
|
|
+ " }\n" +
|
|
|
|
|
+ "}";
|
|
|
|
|
+
|
|
|
|
|
+ var meson_generator = get_component_child<CodeBlockComponent>("meson-generator");
|
|
|
|
|
+ meson_generator.language = "Meson";
|
|
|
|
|
+ meson_generator.code = "# Find the tool\n" +
|
|
|
|
|
+ "spry_mkcomponent = find_program('spry-mkcomponent')\n\n" +
|
|
|
|
|
+ "# Define the generator once\n" +
|
|
|
|
|
+ "spry_mkcomponent_gen = generator(spry_mkcomponent,\n" +
|
|
|
|
|
+ " output: '@BASENAME@.vala',\n" +
|
|
|
|
|
+ " arguments: ['@INPUT@', '@OUTPUT@']\n" +
|
|
|
|
|
+ ")\n\n" +
|
|
|
|
|
+ "# Process multiple component files\n" +
|
|
|
|
|
+ "generated_components = spry_mkcomponent_gen.process(files(\n" +
|
|
|
|
|
+ " 'Components/UserContentComponent.vala',\n" +
|
|
|
|
|
+ " 'Components/LoginFormComponent.vala',\n" +
|
|
|
|
|
+ " 'Components/NavSidebarComponent.vala',\n" +
|
|
|
|
|
+ "))\n\n" +
|
|
|
|
|
+ "# Use in executable\n" +
|
|
|
|
|
+ "executable('myapp',\n" +
|
|
|
|
|
+ " sources: [other_sources, generated_components],\n" +
|
|
|
|
|
+ " dependencies: [spry_dep]\n" +
|
|
|
|
|
+ ")";
|
|
|
|
|
+
|
|
|
|
|
+ var meson_custom_target = get_component_child<CodeBlockComponent>("meson-custom-target");
|
|
|
|
|
+ meson_custom_target.language = "Meson";
|
|
|
|
|
+ meson_custom_target.code = "# Simple case - HTML file is ComponentName.vala.html\n" +
|
|
|
|
|
+ "user_content_component = custom_target('user-content-component',\n" +
|
|
|
|
|
+ " input: 'Components/UserContentComponent.vala',\n" +
|
|
|
|
|
+ " output: 'UserContentComponent.vala',\n" +
|
|
|
|
|
+ " command: [spry_mkcomponent, '@INPUT@', '@OUTPUT@']\n" +
|
|
|
|
|
+ ")\n\n" +
|
|
|
|
|
+ "# With explicit HTML file path\n" +
|
|
|
|
|
+ "login_form_component = custom_target('login-form-component',\n" +
|
|
|
|
|
+ " input: 'Components/LoginFormComponent.vala',\n" +
|
|
|
|
|
+ " output: 'LoginFormComponent.vala',\n" +
|
|
|
|
|
+ " command: [spry_mkcomponent, '@INPUT@', '@OUTPUT@',\n" +
|
|
|
|
|
+ " '--html', 'Templates/LoginForm.html']\n" +
|
|
|
|
|
+ ")";
|
|
|
|
|
+
|
|
|
|
|
+ var meson_complete = get_component_child<CodeBlockComponent>("meson-complete");
|
|
|
|
|
+ meson_complete.language = "Meson";
|
|
|
|
|
+ meson_complete.code = "# Find the spry-mkcomponent tool\n" +
|
|
|
|
|
+ "spry_mkcomponent = find_program('spry-mkcomponent')\n\n" +
|
|
|
|
|
+ "# Define generator for components\n" +
|
|
|
|
|
+ "component_gen = generator(spry_mkcomponent,\n" +
|
|
|
|
|
+ " output: '@BASENAME@.vala',\n" +
|
|
|
|
|
+ " arguments: ['@INPUT@', '@OUTPUT@']\n" +
|
|
|
|
|
+ ")\n\n" +
|
|
|
|
|
+ "# Process all component files with HTML templates\n" +
|
|
|
|
|
+ "generated_components = component_gen.process(files(\n" +
|
|
|
|
|
+ " 'Components/HeaderComponent.vala',\n" +
|
|
|
|
|
+ " 'Components/FooterComponent.vala',\n" +
|
|
|
|
|
+ " 'Components/SidebarComponent.vala',\n" +
|
|
|
|
|
+ "))\n\n" +
|
|
|
|
|
+ "# Other source files (no HTML templates)\n" +
|
|
|
|
|
+ "other_sources = files(\n" +
|
|
|
|
|
+ " 'Main.vala',\n" +
|
|
|
|
|
+ " 'Components/SimpleComponent.vala', # Inline markup\n" +
|
|
|
|
|
+ ")\n\n" +
|
|
|
|
|
+ "# Build executable with generated components\n" +
|
|
|
|
|
+ "executable('myapp',\n" +
|
|
|
|
|
+ " sources: [other_sources, generated_components],\n" +
|
|
|
|
|
+ " dependencies: [spry_dep],\n" +
|
|
|
|
|
+ " vala_args: ['--vapidir', spry_vapi_dir]\n" +
|
|
|
|
|
+ ")";
|
|
|
|
|
+
|
|
|
|
|
+ var html_guidelines = get_component_child<CodeBlockComponent>("html-guidelines");
|
|
|
|
|
+ html_guidelines.language = "HTML";
|
|
|
|
|
+ html_guidelines.code = "<!-- Good: Use sid attributes for elements you need to access -->\n" +
|
|
|
|
|
+ "<div class=\"user-card\">\n" +
|
|
|
|
|
+ " <h2 sid=\"username\"></h2>\n" +
|
|
|
|
|
+ " <p sid=\"email\"></p>\n" +
|
|
|
|
|
+ " <button sid=\"delete-btn\" hx-post=\"/delete\" hx-target=\"closest .user-card\">\n" +
|
|
|
|
|
+ " Delete\n" +
|
|
|
|
|
+ " </button>\n" +
|
|
|
|
|
+ "</div>\n\n" +
|
|
|
|
|
+ "<!-- Good: Keep it simple and focused on structure -->\n" +
|
|
|
|
|
+ "<form sid=\"login-form\" hx-post=\"/login\">\n" +
|
|
|
|
|
+ " <input type=\"text\" name=\"username\" sid=\"username-input\"/>\n" +
|
|
|
|
|
+ " <input type=\"password\" name=\"password\" sid=\"password-input\"/>\n" +
|
|
|
|
|
+ " <button type=\"submit\">Login</button>\n" +
|
|
|
|
|
+ "</form>";
|
|
|
|
|
+
|
|
|
|
|
+ var manual_run = get_component_child<CodeBlockComponent>("manual-run");
|
|
|
|
|
+ manual_run.language = "Bash";
|
|
|
|
|
+ manual_run.code = "# Run manually to see generated output\n" +
|
|
|
|
|
+ "spry-mkcomponent Components/MyComponent.vala -o /tmp/output.vala\n\n" +
|
|
|
|
|
+ "# View the result\n" +
|
|
|
|
|
+ "cat /tmp/output.vala\n\n" +
|
|
|
|
|
+ "# Check if the tool would modify a file (compare with diff)\n" +
|
|
|
|
|
+ "spry-mkcomponent Components/MyComponent.vala -o /tmp/test.vala && \\\n" +
|
|
|
|
|
+ " diff Components/MyComponent.vala /tmp/test.vala";
|
|
|
|
|
+ }
|
|
|
|
|
+}
|