Dup Ver Goto 📝

ActionListFormatter

PT2/music/daw/reaper/misc reaper util does not exist
To
135 lines, 335 words, 3115 chars Page 'ActionListFormatter' does not exist.

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)