-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Jacob Clarke
committed
May 14, 2022
1 parent
0dcc97d
commit 0dc0192
Showing
19 changed files
with
443 additions
and
14 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
**_DEBUG.* | ||
**_INJECTED.* | ||
TouchOSC_ScriptInjector | ||
TouchOSC_ScriptInjector* |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
{ | ||
"semi": false, | ||
"singleQuote": true, | ||
"printWidth": 120 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,42 @@ | ||
### VSCode plugins: | ||
[redhat.vscode-xml](https://marketplace.visualstudio.com/items?itemName=redhat.vscode-xml) | ||
[denoland.vscode-deno](https://marketplace.visualstudio.com/items?itemName=denoland.vscode-deno) | ||
# TouchOSC Script Injector | ||
|
||
A neat little CLI tool that allows you to write TouchOSC LUA scripts externally by injecting them into the TouchOSC project file directly, with some bonus smarts. | ||
|
||
## Project setup | ||
|
||
In the same folder as your `.tosc` project file make a folder called `scripts`, in there you can make as many `.lua` files as you want. | ||
|
||
`_globals.lua` is a special file that is always injected into the top of all other scripts. | ||
|
||
`_root.lua` will get applied to your document's root script. | ||
|
||
All other `.lua` files will map directly to any controls of the same name. By pre-pending a file name with `tag_` the mapping will be done by tag instead of name. | ||
|
||
This name/tag script copying process will find controls nested in however many groups. | ||
|
||
## Using this thing | ||
|
||
Head to [releases](https://github.com/jacobclarke92/TouchOSC-Script-Injector/releases) and download the version best suited for your OS. | ||
Windows, Mac and Linux options available but I've only tested Mac so far. | ||
|
||
Simply run the program and follow the prompts! | ||
You will be prompted for your project file, drag your `.tosc` file into the window and press enter and you'll be away. | ||
|
||
The program will run in its entirety after initially receiving a project file. It will creating a new `_INJECTED.tosc` file next to your original. | ||
|
||
After this point the program will monitor your `scripts` folder and watch for any changes to `.lua` files, patching your project file as necessary. | ||
|
||
--- | ||
|
||
## Dev stuff | ||
|
||
Built with DENO just because I like typescript and the compile functionality seemed pretty convenient for distribution. | ||
|
||
`.tosc` files by default are compressed with zlib, if decompressed end up just being an xml file. | ||
|
||
Check the scripts inside `package.json` for quick access but otherwise this should be all you need to get started: | ||
``` | ||
deno run --allow-read --allow-write src/index.ts | ||
``` | ||
There is a `--debug` argument that adds extra logs and outputs a debug `.json` file, and you can also pass a `.tosc` file path (relative or absolute) as an argument to skip the prompting step. | ||
|
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
NAME_COLOR = '00ff00' | ||
TAG_COLOR = '0000ff' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
print('Hello from root') |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
self.color = Color.fromHexString(NAME_COLOR) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
self.color = Color.fromHexString(TAG_COLOR) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
const banner = ` | ||
_____ _ _____ _____ _____ | ||
|_ _|___ _ _ ___| |_| | __| | | ||
| | | . | | | _| | | |__ | --| | ||
|_| |___|___|___|_|_|_____|_____|_____| | ||
_____ _ __ ____ _ __ | ||
/ ___/__________(_)___ / /_ / _/___ (_)__ _____/ /_____ _____ | ||
\\__ \\/ ___/ ___/ / __ \\/ __/ / // __ \\ / / _ \\/ ___/ __/ __ \\/ ___/ | ||
___/ / /__/ / / / /_/ / /_ _/ // / / / / / __/ /__/ /_/ /_/ / / | ||
/____/\\___/_/ /_/ .___/\\__/ /___/_/ /_/_/ /\\___/\\___/\\__/\\____/_/ | ||
/_/ /___/ | ||
by Jacob Clarke | ||
https://github.com/jacobclarke92/TouchOSC-Script-Injector | ||
` | ||
export const printBanner = (clearFirst = false) => { | ||
if (clearFirst) console.clear() | ||
console.log(banner) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
import { ToscDoc, ToscNode, ToscGroupNode, ToscProperty } from './types.ts' | ||
import { stopwatchTick } from './main.ts' | ||
import { parse as parseXml, stringify as encodeXml } from 'https://deno.land/x/[email protected]/mod.ts' | ||
import { XmlEntities } from 'https://deno.land/x/[email protected]/mod.js' | ||
import { inflate } from 'https://deno.land/x/[email protected]/zlib/inflate.ts' | ||
|
||
export async function getToscFileContent(filePath: string) { | ||
const content = await Deno.readTextFile(filePath) | ||
if (content.match(/^<\?xml/)) { | ||
console.log(`✅ Project file is XML-based`) | ||
return content | ||
} | ||
|
||
console.log(`Project file is not XML based, attempting to convert...`) | ||
stopwatchTick() | ||
const decodedFile = await decodeToscFile(filePath) | ||
console.log(`✅ Decoded file in ${stopwatchTick()}ms`) | ||
return decodedFile | ||
} | ||
|
||
export async function decodeToscFile(filePath: string) { | ||
try { | ||
const rawContent = await Deno.readFile(filePath) | ||
const inflatedContent = inflate(rawContent) | ||
return new TextDecoder('utf-8').decode(inflatedContent) | ||
} catch (err) { | ||
throw '❌ Failed to decode file' | ||
} | ||
} | ||
|
||
export function parseToscXML(xmlString: string): ToscDoc { | ||
stopwatchTick() | ||
try { | ||
const json = parseXml(xmlString) as unknown as ToscDoc | ||
console.log(`✅ XML successfully parsed (took ${stopwatchTick()} ms)`) | ||
return json | ||
} catch (e) { | ||
throw '❌ Could not parse XML file' | ||
} | ||
} | ||
|
||
export async function writeDebugFiles(fileDir: string, fileName: string, parsedProject: ToscDoc) { | ||
stopwatchTick() | ||
await Deno.writeTextFile(fileDir + fileName + '_DEBUG.json', JSON.stringify(parsedProject, null, 2)) | ||
console.log(`✅ Wrote to JSON file for debugging (took ${stopwatchTick()} ms)`) | ||
|
||
stopwatchTick() | ||
await Deno.writeTextFile( | ||
fileDir + fileName + '_DEBUG.tosc', | ||
encodeXml(parsedProject as any, { replacer: cDataRestorer }) | ||
) | ||
console.log(`✅ Wrote to XML file for debugging (took ${stopwatchTick()} ms)`) | ||
} | ||
|
||
type StringifierOptions = Exclude<Parameters<typeof encodeXml>[1], undefined> | ||
const cDataRestorer: StringifierOptions['replacer'] = ({ key, value, tag }) => | ||
['key', 'value'].includes(tag) && key === '#text' && typeof value === 'string' && !!value | ||
? `<![CDATA[${XmlEntities.decode(value)}]]>` | ||
: value | ||
|
||
export async function writeProjectFile(parsedProject: ToscDoc, fileDir: string, fileName: string) { | ||
console.log('📝 Re-encoding to XML and saving file...') | ||
stopwatchTick() | ||
const xmlString = encodeXml(parsedProject as any, { indentSize: 0, replacer: cDataRestorer }) | ||
const newFileName = fileDir + fileName + '_INJECTED.tosc' | ||
await Deno.writeTextFile(newFileName, xmlString) | ||
console.log(`✅ Project file written (took ${stopwatchTick()} ms)`) | ||
console.log(newFileName) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
import { printBanner } from './banner.ts' | ||
import { processToscFile, startWatcher } from './main.ts' | ||
import Ask from 'https://deno.land/x/[email protected]/mod.ts' | ||
|
||
const debugMode = !!(Deno.args || []).find((arg) => arg === '--debug') | ||
const filePathArg = (Deno.args || []).find((str) => str.match(/\.tosc$/)) | ||
const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms)) | ||
|
||
export const fileNameAndExtRegex = /[^\\/:"*?<>|]+\.\w+$/ | ||
export const fileNameRegex = /([^\\/:"*?<>|]+)(?:\.\w+$)/ | ||
const runtimePath = new URL('', import.meta.url).pathname | ||
const runtimeDir = runtimePath.replace(fileNameAndExtRegex, '') | ||
|
||
const ask = new Ask() | ||
const askForFilePath = async () => | ||
( | ||
await ask.input({ name: 'filePath', message: `Drag a .tosc file into this window, then press enter\n` }) | ||
)?.filePath?.trim() | ||
|
||
const ensureFilePath = async () => { | ||
let answer = await askForFilePath() | ||
while (!answer) answer = await askForFilePath() | ||
const isAbsolutePath = answer.match(/^\//) | ||
if (!isAbsolutePath) answer = runtimeDir + answer | ||
return answer | ||
} | ||
|
||
if (!debugMode) printBanner(true) | ||
|
||
let filePath: string = filePathArg ? filePathArg.replace(/^\.\//, '') : await ensureFilePath() | ||
let scriptsDir: string = filePath.replace(fileNameAndExtRegex, '') + 'scripts/' | ||
|
||
async function letsGo() { | ||
const parsedProject = await (async () => { | ||
try { | ||
return await processToscFile(filePath, scriptsDir, debugMode) | ||
} catch (e) { | ||
console.log(e) | ||
return false | ||
} | ||
})() | ||
|
||
if (!parsedProject) { | ||
console.log('❌ An issue occurred, will restart shortly...') | ||
await sleep(2500) | ||
if (!debugMode) printBanner(true) | ||
filePath = await ensureFilePath() | ||
scriptsDir = filePath.replace(fileNameAndExtRegex, '') + 'scripts/' | ||
await letsGo() | ||
return | ||
} | ||
|
||
console.log('\n🎉🎉🎉🎉🎉\n') | ||
|
||
await startWatcher(parsedProject, filePath, scriptsDir) | ||
} | ||
|
||
letsGo() |
Oops, something went wrong.