This generates an html formatted action list like this with a search box that takes a case-insensitive regex and matches against descriptions. Very hacky but fine for me. (The example action list is from Reaper 7.09).
#!/bin/bash
import re
import json
a = open("ActionList.txt").read().rstrip().splitlines()
b = [ x.split("\t") for x in a ]
j = json.dumps(b)
h = """<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
body {
font-family: monospace;
font-size: 12pt;
background-color: #ffd;
}
td {
border-left: 1px solid black;
}
table {
border: 2px solid black;
background-color: white;
border-collapse: collapse;
}
td {
height: 0.5em;
padding: 6px;
}
tr {
border-bottom: 1px solid #777;
}
tr:nth-child(even) {
background-color: #ccc;
}
td:nth-child(even) {
background-color: #ddf;
}
tr:nth-child(even) td:nth-child(even) {
background-color: #bbc;
}
input {
width: 90%;
margin: 6px;
font-family: monospace;
font-size: 16pt;
}
</style>
<script>
"""+f"const data = {j}"+"""
window.q = (x, y = document) => y.querySelector(x)
window.qq = (x, y = document) => Array.from(y.querySelectorAll(x))
window.addEventListener("load", _ => {
const ce = x => document.createElement(x)
const ctr = () => ce("tr")
const ctd = (cl = "") => { const a = ce("td"); a.setAttribute("class", cl); return a; }
const rows = data.map(row => {
const tr = ctr()
row.forEach((x, i) => {
const a = ctd(x);
a.innerText = x;
tr.append(a)
})
tr.setAttribute("key", row[2])
return tr;
})
const searchInput = q("#search")
const resultsDiv = q("#results")
let table = ce("table")
rows.forEach(tr => table.append(tr))
resultsDiv.append(table)
let lastQuery = searchInput.value
setInterval(_ => {
const newQuery = searchInput.value
if (newQuery !== lastQuery) {
lastQuery = newQuery
try_query(searchInput.value)
}
}, 500)
const try_query = x => {
const re = new RegExp(x, "i")
table.remove()
const newTable = ce("table")
rows.forEach(tr => {
const key = tr.getAttribute("key")
if (key.match(re)) {
newTable.append(tr)
}
})
table = newTable
resultsDiv.append(table)
}
searchInput.focus()
window.querystring = window.location.search ? window.location.search.substr(1).replace(/\+/g," ") : null
if( querystring ) {
searchInput.value = querystring
}
})
</script>
<title>Reaper Actions</title>
</head>
<body>
<h1>Reaper Actions</h1>
<input id="search" autofocus />
<div id="results"></div>
</body>
</html>
"""
print(h)