/obsidian-execute-code

Obsidian Plugin to execute code in a note.

Primary LanguageTypeScriptMIT LicenseMIT

Obsidian Execute Code Plugin

This plugin allows you to execute code snippets in code blocks in your notes. The plugin adds a 'run' button for code blocks in supported languages. Clicking them results in the code of the block being executed. After the execution the result of the execution is showed.

The result is shown only after the execution is finished. It is not possible to enter text on the command line into the executed programm now.

Video that shows how the plugin works.

The following languages are supported: CPP, Golang, Groovy, Kotlin, Java, JavaScript, Prolog, Rust, Python, R, Shell & Powershell.

Python and Rust support embedded plots. All languages support "magic" commands that help you to access paths in obsidian or show images in your notes.

Supported programming languages

  • JavaScript

    • Requirements: Node.js is installed and the correct path is set in the settings.
    function hello(name){
        console.log(`Hello ${name}!`);
    }
    
    hello("Bob")
  • Python

    • Requirements: Python is installed and the correct path is set in the settings.
    def hello(name):
        print("Hello", name)
    
    if __name__ == "__main__":
        hello("Eve")
    • Plots with matplotlib/seaborn are embedded in the note by default. You can turn this off in the settings.
    import seaborn as sns
    import matplotlib.pyplot as plt
    sns.set_style("darkgrid")
    iris = sns.load_dataset('iris')
    sns.FacetGrid(iris, hue ="species",
        height = 5).map(plt.scatter,
        'sepal_length',
        'petal_length').add_legend()
    
    plt.show()

    Example of an embedded plot.

  • R

    • Requirements: R is installed and the correct path is set in the settings.
    hello <- function(name){
        print(paste("Hello", name, sep = " "))
    }
    
    hello("Bob")
    • Plots can be embedded in the note by default. You can turn this off in the settings.
    y = c(12, 15, 28, 17, 18)
    x = 1:length(y)
    plot(x, y, type="l")
  • Java

    • Requirements: Java 11 or higher is installed and the correct path is set in the settings.
    public class HelloWorld {
        public static void main(String[] args) {
      	  System.out.println("Hello World!");
        }
    }
  • CPP

    • Requirements: NO requirements, works with JSCPP.
    • Problems: No error handling implemented yet and JSCPP doesn't support all language features.
    #include <iostream>
    using namespace std;
    
    void hello(char name[]) {
        cout << "Hello " << name << "!\n";
    }
    
    int main() {
        hello("Alice");
        return 0;
    }
  • Shell

    • Requirements: Set the path to your preferred shell in the settings. Default is Bash
    echo "Hello World!"
    ls -la
  • Powershell

    echo "Hello World!"
  • Prolog

    • Requirements: NO requirements, works with Tau-Prolog.
    • Important: Add your queries after a line "% query" in the code block like in the following
    likes(john, pizza).
    likes(john, cheese).
    likes(jane, beer).
    
    % query
    likes(john, X).
  • Groovy

    • Requirements: Groovy is installed and the correct path is set in the settings.
      	def hello(name){  
      		 println "Hello ${name}!" 
      	}  
      	  
      	def helloClosure = {  
      	   println "Hello ${it}!" 
      	}  
      	  
      	hello("Bob")
      	  
      	helloClosure "Bob"
  • Golang

    • Requirements: Golang is installed and correct path is set in the settings(go binary is available).
    • Every code block must contain package declaration and a main function.
        package main
    
        import "fmt"
    
        func main() {
      	  fmt.Println("Hello World")
        }
  • Rust

    • Requirements: Cargo is installed and correct path is set in the settings(cargo binary is available).
    • cargo-eval is installed. Install using cargo install cargo-eval.
    • Import statements and external crates is supported by cargo-eval. Read their documentation.
    • Every code block must a main function.
        fn main() {
      	  println!("Hello World");
        }
  • Kotlin

    • Requirements: Kotlin is installed and correct path is set in the settings.
    hello(name: String) {
        println("Hello $name!")
    }
    
    hello("Bob")
  • Squiggle: For Squiggle support look at the Obsidian Squiggle plugin by @jqhoogland.

Support for the following is planned:

  • Matlab
  • Julia Lang

Open for suggestions.

Magic Commands

Magic commands are some meta commands that can be used in the code block. They are processed by the plugin before the source code is executed.

The following magic commands are supported:

  • @vault: Inserts the vault path as string.
  • @note: Inserts the note path as string.
  • @title: Inserts the note title as string.
  • @show(ImagePath): Displays an image at the given path in the note.
  • @show(ImagePath, Width, Height): Displays an image at the given path in the note.
  • @show(ImagePath, Width, Height, Alignment[center|left|right]): Displays an image at the given path in the note.

(@show(...) is only supported for JavaScript and Python yet.)

Example how to use the magic commands.

Running in Preview

Adding run- before the language name in the code blocks (as in the example below) renders the code block in the preview already. This allows you to execute the code in the preview.

```run-python
def hello(name):
print("Hello", name)

    if __name__ == "__main__":
        hello("Eve")

Installation

In your vault go to Settings > Community plugins > Browse and search for "Execute Code". Select the plugin, install it and activate it.

or

Follow this link and click "Open in Obsidian".

Warning

Do not execute code from sources you don't know or code you don't understand. Executing code can cause irrepairable damage.

Known Problems

  • Missing when run button after switching the theme: Try to close and reopen your notes and wait for a few minutes. It seems like obsidian doesn't call the postprocessors after the theme switch.

Future Work

  • Find better way to show that the program is running (for example a loading sign).
  • Notebook Mode similar to Jupyter
  • Global Declarations that make method and variable definitions available to subsequent code blocks
  • Key combination to execute all code blocks in a file
  • Error warning when the execution fails (e.g. when python isn't installed)
  • Test if this plugin works in combination with dataview.

Contribution

All contributions are welcome. Just create a merge request or email me: tim.wibiral(at)uni-ulm.de

The bullet points in Future Work are a good starting point if you want to help.

Contributers

List of contributers to this project.

Made with contrib.rocks.