Task 813: .WLS File Format

Task 813: ,WLS File Format

The .WLS file format refers to the Wolfram Language Script file, utilized for executing Wolfram Language code via command-line interfaces such as WolframScript. This format consists of UTF-8 encoded text, optionally commencing with a shebang line to specify execution parameters, followed by Wolfram Language expressions. The structure may incorporate special comments to delineate sections, facilitating organization and documentation within the script.

  1. The properties of this file format intrinsic to its structure include the following elements, which define its organized content:
  • Shebang line: An optional initial line specifying the interpreter and options (e.g., #!/usr/bin/env wolframscript).
  • Package marker: Denotes the start of a package context (e.g., (* ::Package:: *)).
  • Title: Provides the script's title (e.g., (* ::Title:: *)).
  • Author: Indicates authorship details (e.g., (* ::Author:: *)).
  • Section: Defines major divisions (e.g., (* ::Section:: *)).
  • Subsection: Defines secondary divisions (e.g., (* ::Subsection:: *)).
  • Subsubsection: Defines tertiary divisions (e.g., (* ::Subsubsection:: *)).
  • Text: Contains descriptive text (e.g., (* ::Text:: *)).
  • Input: Specifies input expressions (e.g., (* ::Input:: *)).
  • Output: Specifies output expressions (e.g., (* ::Output:: *)).
  • Code: Contains executable code blocks (e.g., (* ::Code:: *)).
  • Usage: Provides usage documentation for functions (e.g., (* ::Usage:: *)).

These properties are extracted by parsing special comment patterns, with content following each marker until the next marker or end of file.

  1. Two direct download links for .WLS files are as follows:
  1. The following is an embedded HTML and JavaScript code snippet suitable for integration into a blog post (such as on the Ghost platform). It enables users to drag and drop a .WLS file, parses the content to extract the listed properties, and displays them on the screen.
WLS File Parser
Drag and drop a .WLS file here
  1. The following Python class handles opening, decoding (parsing), reading, writing, and printing the properties of a .WLS file to the console.
import re

class WLSHandler:
    def __init__(self, filepath):
        self.filepath = filepath
        self.properties = {}

    def read_and_decode(self):
        with open(self.filepath, 'r', encoding='utf-8') as file:
            content = file.read()
        lines = content.split('\n')
        current_prop = None
        shebang = lines[0] if lines and lines[0].startswith('#!') else None
        if shebang:
            self.properties['Shebang line'] = shebang

        marker_regex = re.compile(r'\(\* ::(\w+):: \*\)')
        for line in lines:
            match = marker_regex.match(line.strip())
            if match:
                current_prop = match.group(1)
                if current_prop not in self.properties:
                    self.properties[current_prop] = []
            elif current_prop:
                self.properties[current_prop].append(line.strip())

    def print_properties(self):
        for key, value in self.properties.items():
            print(f"{key}:")
            if isinstance(value, list):
                print('\n'.join(value))
            else:
                print(value)
            print()

    def write(self, new_filepath=None):
        filepath = new_filepath or self.filepath
        with open(filepath, 'w', encoding='utf-8') as file:
            if 'Shebang line' in self.properties:
                file.write(self.properties['Shebang line'] + '\n')
            for key, value in self.properties.items():
                if key != 'Shebang line':
                    file.write(f"(* ::{key}:: *)\n")
                    if isinstance(value, list):
                        file.write('\n'.join(value) + '\n')
                    else:
                        file.write(value + '\n')

# Example usage:
# handler = WLSHandler('example.wls')
# handler.read_and_decode()
# handler.print_properties()
# handler.write('output.wls')
  1. The following Java class handles opening, decoding (parsing), reading, writing, and printing the properties of a .WLS file to the console.
import java.io.*;
import java.util.*;
import java.util.regex.*;

public class WLSHandler {
    private String filepath;
    private Map<String, List<String>> properties = new LinkedHashMap<>();

    public WLSHandler(String filepath) {
        this.filepath = filepath;
    }

    public void readAndDecode() throws IOException {
        List<String> lines = new ArrayList<>();
        try (BufferedReader reader = new BufferedReader(new FileReader(filepath))) {
            String line;
            while ((line = reader.readLine()) != null) {
                lines.add(line);
            }
        }
        String currentProp = null;
        String shebang = !lines.isEmpty() && lines.get(0).startsWith("#!") ? lines.get(0) : null;
        if (shebang != null) {
            properties.put("Shebang line", List.of(shebang));
        }

        Pattern markerPattern = Pattern.compile("\\(\\* ::(\\w+):: \\*\\)");
        for (String line : lines) {
            Matcher match = markerPattern.matcher(line.trim());
            if (match.matches()) {
                currentProp = match.group(1);
                properties.computeIfAbsent(currentProp, k -> new ArrayList<>());
            } else if (currentProp != null) {
                properties.get(currentProp).add(line.trim());
            }
        }
    }

    public void printProperties() {
        for (Map.Entry<String, List<String>> entry : properties.entrySet()) {
            System.out.println(entry.getKey() + ":");
            entry.getValue().forEach(System.out::println);
            System.out.println();
        }
    }

    public void write(String newFilepath) throws IOException {
        String writePath = (newFilepath != null) ? newFilepath : filepath;
        try (BufferedWriter writer = new BufferedWriter(new FileWriter(writePath))) {
            if (properties.containsKey("Shebang line")) {
                writer.write(properties.get("Shebang line").get(0) + "\n");
            }
            for (Map.Entry<String, List<String>> entry : properties.entrySet()) {
                if (!entry.getKey().equals("Shebang line")) {
                    writer.write("(* ::" + entry.getKey() + ":: *)\n");
                    for (String val : entry.getValue()) {
                        writer.write(val + "\n");
                    }
                }
            }
        }
    }

    // Example usage:
    // public static void main(String[] args) throws IOException {
    //     WLSHandler handler = new WLSHandler("example.wls");
    //     handler.readAndDecode();
    //     handler.printProperties();
    //     handler.write("output.wls");
    // }
}
  1. The following JavaScript class handles opening, decoding (parsing), reading, writing, and printing the properties of a .WLS file to the console. Note that file operations require a Node.js environment with the 'fs' module.
const fs = require('fs');

class WLSHandler {
    constructor(filepath) {
        this.filepath = filepath;
        this.properties = {};
    }

    readAndDecode() {
        const content = fs.readFileSync(this.filepath, 'utf-8');
        const lines = content.split('\n');
        let currentProp = null;
        const shebang = lines[0].startsWith('#!') ? lines[0] : null;
        if (shebang) this.properties['Shebang line'] = shebang;

        const markerRegex = /\(\* ::(\w+):: \*\)/;
        lines.forEach(line => {
            const match = line.match(markerRegex);
            if (match) {
                currentProp = match[1];
                if (!this.properties[currentProp]) this.properties[currentProp] = [];
            } else if (currentProp) {
                this.properties[currentProp].push(line.trim());
            }
        });
    }

    printProperties() {
        for (const [key, value] of Object.entries(this.properties)) {
            console.log(`${key}:`);
            if (Array.isArray(value)) {
                value.forEach(v => console.log(v));
            } else {
                console.log(value);
            }
            console.log('');
        }
    }

    write(newFilepath = null) {
        const filepath = newFilepath || this.filepath;
        let output = '';
        if (this.properties['Shebang line']) {
            output += this.properties['Shebang line'] + '\n';
        }
        for (const [key, value] of Object.entries(this.properties)) {
            if (key !== 'Shebang line') {
                output += `(* ::${key}:: *)\n`;
                if (Array.isArray(value)) {
                    output += value.join('\n') + '\n';
                } else {
                    output += value + '\n';
                }
            }
        }
        fs.writeFileSync(filepath, output, 'utf-8');
    }
}

// Example usage:
// const handler = new WLSHandler('example.wls');
// handler.readAndDecode();
// handler.printProperties();
// handler.write('output.wls');
  1. The following C++ class handles opening, decoding (parsing), reading, writing, and printing the properties of a .WLS file to the console.
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <map>
#include <regex>

class WLSHandler {
private:
    std::string filepath;
    std::map<std::string, std::vector<std::string>> properties;

public:
    WLSHandler(const std::string& fp) : filepath(fp) {}

    void readAndDecode() {
        std::ifstream file(filepath);
        if (!file.is_open()) {
            std::cerr << "Failed to open file." << std::endl;
            return;
        }
        std::vector<std::string> lines;
        std::string line;
        while (std::getline(file, line)) {
            lines.push_back(line);
        }
        file.close();

        std::string currentProp;
        std::string shebang = (!lines.empty() && lines[0].rfind("#!", 0) == 0) ? lines[0] : "";
        if (!shebang.empty()) {
            properties["Shebang line"] = {shebang};
        }

        std::regex markerRegex(R"(\(\* ::(\w+):: \*\))");
        std::smatch match;
        for (const auto& ln : lines) {
            std::string trimmed = ln;
            trimmed.erase(0, trimmed.find_first_not_of(" \t"));
            trimmed.erase(trimmed.find_last_not_of(" \t") + 1);
            if (std::regex_match(trimmed, match, markerRegex)) {
                currentProp = match[1].str();
                if (properties.find(currentProp) == properties.end()) {
                    properties[currentProp] = {};
                }
            } else if (!currentProp.empty()) {
                properties[currentProp].push_back(trimmed);
            }
        }
    }

    void printProperties() const {
        for (const auto& [key, value] : properties) {
            std::cout << key << ":" << std::endl;
            for (const auto& v : value) {
                std::cout << v << std::endl;
            }
            std::cout << std::endl;
        }
    }

    void write(const std::string& newFilepath = "") const {
        std::string writePath = newFilepath.empty() ? filepath : newFilepath;
        std::ofstream file(writePath);
        if (!file.is_open()) {
            std::cerr << "Failed to write file." << std::endl;
            return;
        }
        auto it = properties.find("Shebang line");
        if (it != properties.end()) {
            file << it->second[0] << "\n";
        }
        for (const auto& [key, value] : properties) {
            if (key != "Shebang line") {
                file << "(* ::" << key << ":: *)" << "\n";
                for (const auto& v : value) {
                    file << v << "\n";
                }
            }
        }
        file.close();
    }
};

// Example usage:
// int main() {
//     WLSHandler handler("example.wls");
//     handler.readAndDecode();
//     handler.printProperties();
//     handler.write("output.wls");
//     return 0;
// }