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.
- 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.
- Two direct download links for .WLS files are as follows:
- https://raw.githubusercontent.com/maxitg/SetReplace/master/install.wls
- https://raw.githubusercontent.com/vguada/FindBounce/master/Build.wls
- 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.
Drag and drop a .WLS file here
- 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')
- 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");
// }
}
- 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');
- 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;
// }