From 9a978d8984fb2ef5b977562fb305cc2483c71132 Mon Sep 17 00:00:00 2001 From: Robert Bendun Date: Wed, 21 Sep 2022 19:32:31 +0200 Subject: [PATCH] [cheatsheet] Splitted into sections, added navigation --- doc/musique-vs-languages-cheatsheet.template | 77 +++++++++++---- scripts/code-size.sh | 3 + scripts/language-cmp-cheatsheet.py | 98 +++++++++++++------- 3 files changed, 125 insertions(+), 53 deletions(-) create mode 100755 scripts/code-size.sh diff --git a/doc/musique-vs-languages-cheatsheet.template b/doc/musique-vs-languages-cheatsheet.template index e24590d..3ee6d7d 100644 --- a/doc/musique-vs-languages-cheatsheet.template +++ b/doc/musique-vs-languages-cheatsheet.template @@ -21,6 +21,8 @@ END INTRO BEGIN TABLE +SECTION Podstawy + n Kategoria m Musique p Python @@ -63,6 +65,36 @@ r return x + y r end c Musique nie rozróżnia funkcji anonimowych i zadeklarowanych +n Instrukcja warunkowa +m if (n == 42) +m [ say 1 ] +m [ say 2 ] +p if n == 42: +p print(1) +p else: +p print(2) +r if n == 42 +r puts 1 +r else +r puts 2 +r end +c Musique nie posiada instrukcji warunkowej, a funkcję if, +c która przyjmuje wartość logiczną i dwa bloki (funkcje anonimowe) +c - jeden z nich zostanie wykonany jeśli warunek jest prawdziwy, +c a drugi jeśli jest fałszywy. +n Wyrażenie warunkowe +m x := if (n == 42) [1] [2] +p x = 1 if n == 42 else 2 +r x = n == 42 ? 1 : 2 + +SECTION Tablice + +n Kategoria +m Musique +p Python +r Ruby (SonicPi) +c Komentarz + n Tablice m x = [1; 2; 3; 4] p x = [1, 2, 3, 4] @@ -104,25 +136,30 @@ r [*1..5].inject(:*) c Musique pozwala zmienić dowolny operator w funkcję c poprzez zapis 'operator jak '* w przykładzie -n Instrukcja warunkowa -m if (n == 42) -m [ say 1 ] -m [ say 2 ] -p if n == 42: -p print(1) -p else: -p print(2) -r if n == 42 -r puts 1 -r else -r puts 2 +n Iteracja po elementach tablicy +m for (up 5) [ i | say i ] +p for i in range(5): +p print(i) +r (0..4).each do |i| +r puts i r end -c Musique nie posiada instrukcji warunkowej, a funkcję if, -c która przyjmuje wartość logiczną i dwa bloki (funkcje anonimowe) -c - jeden z nich zostanie wykonany jeśli warunek jest prawdziwy, -c a drugi jeśli jest fałszywy. -n Wyrażenie warunkowe -m x := if (n == 42) [1] [2] -p x = 1 if n == 42 else 2 -r x = n == 42 ? 1 : 2 +c Podobnie jak w przypadku instrukcji warunkowej, Musique używa funkcji. + +n Sortowanie tablicy +m xs := sort [1; 5; 3; 3; 2] +p xs = sorted([1, 5, 3, 3, 2]) +r xs = [1, 5, 3, 3, 2].sort + + +n Sortowanie wielu tablic w jedną +m xs := sort [1; 5; 3; 3; 2] +m [3; 4; 5] 1 2 3 +p xs = sorted(itertools.chain( +p [1, 5, 3, 3, 2], [3, 4, 5], +p [1], [2], [3] +p )) +c Wiele operacji na tablicach może być wykonywane na dowolnej kombinacji +c tablic i pojedyńczych wartości. Tworzy to jedną tablicę wykoniową. + + END TABLE diff --git a/scripts/code-size.sh b/scripts/code-size.sh new file mode 100755 index 0000000..70fd47a --- /dev/null +++ b/scripts/code-size.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env bash + +cloc src/*.cc include/*.hh lib/midi/include lib/midi/src diff --git a/scripts/language-cmp-cheatsheet.py b/scripts/language-cmp-cheatsheet.py index d53ceec..b06b016 100644 --- a/scripts/language-cmp-cheatsheet.py +++ b/scripts/language-cmp-cheatsheet.py @@ -1,9 +1,20 @@ import argparse import os import string -import collections +import dataclasses -Directive = collections.namedtuple("Directive", "line_number type content") +@dataclasses.dataclass +class Section: + name: str + rows: list = dataclasses.field(default_factory=lambda: [{}]) + order: list = dataclasses.field(default_factory=list) + ref: str = "" + +@dataclasses.dataclass +class Directive: + line_number: int + type: str + content: str HTML_TEMPLATE = string.Template(""" @@ -14,15 +25,16 @@ HTML_TEMPLATE = string.Template("""

$intro

- $table
+ +
$body
""") -def parse_table(lines: list): +def parse_table(lines: list[str]) -> list[Section]: previus_column_type = None - rows, order = [{}], [] - current_row = rows[0] + sections = [] + current_section = None # Each nonblank matches this regular expression /(\S*)\s(.*)/ # where first capture is type of column (essentialy column id) and @@ -35,27 +47,34 @@ def parse_table(lines: list): sep = line.find(' ') column_type, cell_content = line[:sep].strip(), line[sep:] - if column_type not in order: - order.append(column_type) + if column_type == "SECTION": + sections.append(Section(name=cell_content)) + current_section = sections[-1] + continue - if previus_column_type != column_type and column_type in current_row: - rows.append({}) - current_row = rows[-1] + assert current_section is not None, "Define SECTION before table entries" - cell = current_row.get(column_type, []) + if column_type not in current_section.order: + current_section.order.append(column_type) + + if previus_column_type != column_type and column_type in current_section.rows[-1]: + current_section.rows.append({}) + + cell = current_section.rows[-1].get(column_type, []) cell.append(cell_content) - current_row[column_type] = cell + current_section.rows[-1][column_type] = cell previus_column_type = column_type # Eliminate common whitespace prefix in given column type (not all whitespace # prefix since examples in Python may have significant whitespace) - for row in rows: - for cell in row.values(): - prefix_whitespace = min(len(s) - len(s.lstrip()) for s in cell) - for i, s in enumerate(cell): - cell[i] = s[prefix_whitespace:] + for section in sections: + for row in section.rows: + for cell in row.values(): + prefix_whitespace = min(len(s) - len(s.lstrip()) for s in cell) + for i, s in enumerate(cell): + cell[i] = s[prefix_whitespace:] - return rows, order + return sections def compile_template(*, template_path: str, target_path: str): # Read template file and separate it into lines @@ -98,27 +117,40 @@ def compile_template(*, template_path: str, target_path: str): assert intro_source is not None assert title is not None - rows, columns_order = parse_table(lines=table_source) + sections = parse_table(lines=table_source) - table = "" + for section in sections: + section.ref = section.name.replace(" ", "_") - for i, row in enumerate(rows): - if i == 0: - line = ["" + ' '.join(row[k]) + "" for k in columns_order] - else: - line = [] - for column in columns_order: - val = row.get(column, []) - line.append('
' + '
'.join(val) + '
') + nav = "" + for section in sections: + nav += f"
  • {section.name}
  • " - table += "\n" + '\n'.join(line) + "\n\n" + body = "" + for section in sections: + table = f"

    {section.name}

    \n" + + for i, row in enumerate(section.rows): + if i == 0: + line = ["" for k in section.order] + else: + line = [] + for column in section.order: + val = row.get(column, []) + line.append('') + + table += "\n" + '\n'.join(line) + "\n\n" + + table += "\n
    " + ' '.join(row[k]) + "
    ' + '
    '.join(val) + '

    \n" + body += table final = HTML_TEMPLATE.substitute({ - "title": title, + "body": body, "css": "\n".join(css_source), - "table": table, - "intro": "\n".join(intro_source) + "intro": "\n".join(intro_source), + "nav": nav, + "title": title, }) with open(target_path, "w") as f: