Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 46 additions & 36 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -150,42 +150,52 @@ And for inline code block you just have to change the class property

## Languages supported 🌐

| Name | Class name | Support | Language detection |
| ---------- | ------------------- | --------------------------------------------------- | ------------------ |
| asm | shj-lang-asm | | ✅ |
| bash | shj-lang-bash | | ✅ |
| brainfuck | shj-lang-bf | increment, operator, print, comment | ❌ |
| c | shj-lang-c | | ✅ |
| css | shj-lang-css | comment, str, selector, units, function, ... | ✅ |
| csv | shj-lang-csv | punctuation, ... | ❌ |
| diff | shj-lang-diff | | ✅ |
| docker | shj-lang-docker | | ✅ |
| git | shj-lang-git | comment, insert, deleted, string, ... | ❌ |
| go | shj-lang-go | | ✅ |
| html | shj-lang-html | | ✅ |
| http | shj-lang-http | keywork, string, punctuation, variable, version | ✅ |
| ini | shj-lang-ini | | ❌ |
| java | shj-lang-java | | ✅ |
| javascipt | shj-lang-js | basic syntax, regex, jsdoc, json, template literals | ✅ |
| jsdoc | shj-lang-jsdoc | | ❌ |
| json | shj-lang-json | string, number, bool, ... | ❌ |
| leanpub-md | shj-lang-leanpub-md | | ❌ |
| log | shj-lang-log | number, string, comment, errors | ❌ |
| lua | shj-lang-lua | | ✅ |
| makefile | shj-lang-make | | ✅ |
| markdown | shj-lang-md | | ✅ |
| perl | shj-lang-pl | | ✅ |
| plain | shj-lang-plain | | ❌ |
| python | shj-lang-py | | ✅ |
| regex | shj-lang-regex | count, set, ... | ❌ |
| rust | shj-lang-rs | | ✅ |
| sql | shj-lang-sql | number, string, function, ... | ✅ |
| todo | shj-lang-todo | | ❌ |
| toml | shj-lang-toml | comment, table, string, bool, variable | ❌ |
| typescript | shj-lang-ts | js syntax, ts keyword, types | ✅ |
| uri | shj-lang-uri | | ✅ |
| xml | shj-lang-xml | | ✅ |
| yaml | shj-lang-yaml | comment, numbers, variable, string, bool | ❌ |
| Name | Class name | Support | Language detection |
| ----------- | ------------------- | --------------------------------------------------- | ------------------ |
| asm | shj-lang-asm | | ✅ |
| bash | shj-lang-bash | | ✅ |
| brainfuck | shj-lang-bf | increment, operator, print, comment | ❌ |
| c | shj-lang-c | | ✅ |
| c# | shj-lang-cs | | ✅ |
| c++ | shj-lang-cpp | | ✅ |
| cobol | shj-lang-cobol | | ✅ |
| css | shj-lang-css | comment, str, selector, units, function, ... | ✅ |
| csv | shj-lang-csv | punctuation, ... | ❌ |
| diff | shj-lang-diff | | ✅ |
| docker | shj-lang-docker | | ✅ |
| gdscript | shj-lang-gd | | ❌ |
| git | shj-lang-git | comment, insert, deleted, string, ... | ❌ |
| go | shj-lang-go | | ✅ |
| html | shj-lang-html | | ✅ |
| http | shj-lang-http | keywork, string, punctuation, variable, version | ✅ |
| ini | shj-lang-ini | | ❌ |
| java | shj-lang-java | | ✅ |
| javascipt | shj-lang-js | basic syntax, regex, jsdoc, json, template literals | ✅ |
| jsdoc | shj-lang-jsdoc | | ❌ |
| json | shj-lang-json | string, number, bool, ... | ❌ |
| leanpub-md | shj-lang-leanpub-md | | ❌ |
| log | shj-lang-log | number, string, comment, errors | ❌ |
| lua | shj-lang-lua | | ✅ |
| makefile | shj-lang-make | | ✅ |
| markdown | shj-lang-md | | ✅ |
| mongodb | shj-lang-mongodb | | ❌ |
| perl | shj-lang-pl | | ✅ |
| php | shj-lang-php | | ✅ |
| plain | shj-lang-plain | | ❌ |
| powershell | shj-lang-ps1 | | ❌ |
| python | shj-lang-py | | ✅ |
| regex | shj-lang-regex | count, set, ... | ❌ |
| ruby | shj-lang-rb | | ✅ |
| rust | shj-lang-rs | | ✅ |
| sql | shj-lang-sql | number, string, function, ... | ✅ |
| todo | shj-lang-todo | | ❌ |
| toml | shj-lang-toml | comment, table, string, bool, variable | ❌ |
| typescript | shj-lang-ts | js syntax, ts keyword, types | ✅ |
| uri | shj-lang-uri | | ✅ |
| vimscript | shj-lang-vim | | ✅ |
| webassembly | shj-lang-wat | | ❌ |
| xml | shj-lang-xml | | ✅ |
| yaml | shj-lang-yaml | comment, numbers, variable, string, bool | ❌ |

## Themes 🌈

Expand Down
10 changes: 10 additions & 0 deletions examples/data.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,16 @@ export const themesBrowser = [
/** @type {import('../src/terminal.js').ShjTerminalTheme[]} */
export const themesTerminal = [
'default',
'cobol',
'cpp',
'cs',
'gd',
'mongodb',
'php',
'ps1',
'rb',
'vim',
'wat',
'atom-dark'
]

Expand Down
60 changes: 60 additions & 0 deletions examples/languages/test.cobol
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
*****************************************************************
* PAYROLL EXTRACT - MONTHLY NET PAY LISTING
* TODO MOVE THE TAX RATE INTO A COPYBOOK, DON'T PERFORM IT HERE
IDENTIFICATION DIVISION.
PROGRAM-ID. PAYRUN.
AUTHOR. M-DUPONT.
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT EMP-FILE ASSIGN TO "EMPLOYEE.DAT"
ORGANIZATION IS SEQUENTIAL
FILE STATUS IS WS-FILE-STATUS.
/
DATA DIVISION.
FILE SECTION.
FD EMP-FILE.
01 EMP-RECORD.
05 EMP-ID PIC 9(6).
05 EMP-NAME PICTURE X(30).
05 EMP-GROSS PIC S9(7)V99 COMP-3.
WORKING-STORAGE SECTION.
01 WS-FLAGS.
05 WS-FILE-STATUS PIC XX VALUE "00".
05 WS-EOF-FLAG PIC X VALUE 'N'.
88 WS-END-OF-FILE VALUE 'Y'.
01 WS-WORK-AREAS.
05 WS-READ-COUNT PIC 9(5) VALUE ZERO.
05 WS-NET-PAY PIC S9(7)V99 VALUE +0.00.
05 WS-TAX-RATE PIC V9(4) VALUE 0.1750.
05 WS-EDIT-NAME PIC X(20) VALUE SPACES.
05 WS-EDIT-PAY PIC ZZ,ZZ9.99-.
PROCEDURE DIVISION.
0000-MAIN-CONTROL.
PERFORM 1000-INITIALIZE
PERFORM UNTIL WS-END-OF-FILE
PERFORM 2000-PROCESS-EMPLOYEE
END-PERFORM
CLOSE EMP-FILE
DISPLAY "RECORDS READ: " WS-READ-COUNT
STOP RUN.
*
1000-INITIALIZE.
OPEN INPUT EMP-FILE
IF WS-FILE-STATUS NOT = "00"
DISPLAY "OPEN FAILED, STATUS *> " WS-FILE-STATUS
MOVE 16 TO RETURN-CODE
GOBACK
END-IF.
2000-PROCESS-EMPLOYEE.
READ EMP-FILE
AT END
SET WS-END-OF-FILE TO TRUE
NOT AT END
ADD 1 TO WS-READ-COUNT
COMPUTE WS-NET-PAY ROUNDED =
EMP-GROSS * (1 - WS-TAX-RATE)
MOVE EMP-NAME(1:20) TO WS-EDIT-NAME
MOVE WS-NET-PAY TO WS-EDIT-PAY
DISPLAY WS-EDIT-NAME WS-EDIT-PAY *> FIXME ALIGN
END-READ.
60 changes: 60 additions & 0 deletions examples/languages/test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
#include <cmath>
#include <iostream>
#include <memory>
#include <string>
#include <vector>
#include "logger.hpp"

#define LOG_PREFIX "[mixer] "

namespace dsp::audio {

constexpr std::size_t kMaxFrames = 0x4000;

// TODO: drop the copy in push() once the template deduction is fixed
template <typename T>
class RingBuffer {
public:
explicit RingBuffer(std::size_t capacity) : data_(capacity), head_(0) {}
RingBuffer& operator=(const RingBuffer&) = delete;

bool push(const T& value) {
if (head_ + 1 >= data_.size())
return false;
data_[head_++] = value;
return true;
}
std::size_t size() const noexcept { return head_; }
private:
std::vector<T> data_;
std::size_t head_;
};

/*
* The curve is a plain exponential, see docs/dsp.md for the derivation.
* FIXME: clamp to -60 dB instead of returning the floor value
*/
constexpr float gainToDb(float gain) {
return gain > 1e-6f ? 20.0f * std::log10(gain) : -120.0f;
}

} // namespace dsp::audio

int main(int argc, char** argv) {
using namespace dsp::audio;
auto buffer = std::make_unique<RingBuffer<float>>(kMaxFrames);
const char* usage = R"(usage: mix [--gain 0.5] // slashes are literal here)";
std::string path = argc > 1 ? argv[1] : "//tmp/render.wav";
auto total = 0.0f;
std::vector<float> frames{0.25f, 0.5f, 1.0f};
auto scale = [&total](float f) { total += f * 0.5f; };
for (float f : frames)
scale(f);

if (argc < 2 || argv == nullptr) {
std::cerr << usage << '\n';
return 1;
}
std::cout << LOG_PREFIX << path << " gain = " << gainToDb(total) << " dB\n";
return buffer->size() > 0 && total < 1.0f ? 0 : 2;
}
79 changes: 79 additions & 0 deletions examples/languages/test.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.Json.Serialization;
using System.Threading.Tasks;

#nullable enable

namespace Warehouse.Orders;

[Serializable]
public record OrderLine(string Sku, int Quantity, double UnitPrice)
{
public double Total => Quantity * UnitPrice;
}

public class OrderRepository
{
private const string Endpoint = "https://api.example.com/v1/orders";
private static readonly char Separator = '\t';
private readonly Dictionary<string, OrderLine> _cache = new();
private bool _dirty = false;
private const string Fallback = "unknown-sku";
private const decimal VatRate = 0.20m;
private static readonly decimal FreeShippingFrom = 1500.50m;

public const string SchemaHint = """
{ "kind": "order", "version": 2 }
""";

[JsonPropertyName("shipped_at")]
public DateTime? ShippedAt { get; set; }

public bool IsEmpty => _cache.Count == 0;

public OrderLine Default() => _cache[Fallback];

public decimal WithVat(decimal amount) => amount * (1m + VatRate);

// TODO: switch to a streaming reader once the gateway supports it
public async Task<int> SyncAsync(IEnumerable<OrderLine> lines, int? limit = null)
{
var taken = 0;
foreach (var line in lines)
{
if (limit is int max && taken>=max)
break;

_cache[line.Sku] = line;
taken+=1;
}

_dirty = true;
await Task.Delay(TimeSpan.FromMilliseconds(250));
return taken;
}

/* The verbatim path below is Windows only. We keep the old share
around while the migration to the object store is not finished. */
public string DumpPath => @"C:\exports\orders\daily.csv";

public string Describe(OrderLine line)
{
var label = line.Quantity > 1 ? "units" : "unit";
return $"{line.Sku} - {line.Quantity} {label} at {line.UnitPrice:0.00}";
}

public IReadOnlyList<string> Expensive(double threshold = 0.08)
{
var query = from entry in _cache.Values
where entry.Total > threshold
orderby entry.Total descending
select entry.Sku;

return query.ToList();
}

public static string Quote(string who) => $@"He answered ""{who}"" and left";
}
64 changes: 64 additions & 0 deletions examples/languages/test.gd
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
class_name Player
extends CharacterBody2D

## Side scroller player: walk, jump, take damage.
# TODO: double jump is not wired yet, extends and signal stay as is

signal health_changed(amount: int)

const MAX_HEALTH := 100
const GRAVITY := 980.0
const HURT_SOUND = preload("res://sfx/hurt.ogg")
const HELP_TEXT := """
Arrows to move, space to jump.
If not on the floor you can still jump for a moment.
Build #42 - report bugs to the studio.
"""

@export var speed: float = 220.0
@export_range(0.0, 1.0) var friction := 0.15
@export var invincible: bool = false

@onready var sprite: AnimatedSprite2D = $Visuals/AnimatedSprite2D
@onready var label := %HealthLabel

enum State { IDLE, RUN, JUMP }
var state: State = State.IDLE
var health := MAX_HEALTH
var _coyote := 0.0


func _ready() -> void:
$HurtBox.body_entered.connect(_on_hit)
label.text = "HP %d/%d" % [health, MAX_HEALTH]
print("loaded # not a comment, still a string")


func _physics_process(delta: float) -> void:
if not is_on_floor():
velocity.y += GRAVITY*delta
_coyote = maxf(_coyote-delta, 0.0)
else:
_coyote = 0.12

var dir := Input.get_axis('move_left', 'move_right')
velocity.x = lerpf(velocity.x, dir*speed, friction)
if Input.is_action_just_pressed("jump") and _coyote > 0.0:
velocity.y = -420.0

match state:
State.RUN when is_zero_approx(dir):
state = State.IDLE
_:
sprite.play(&"idle")
move_and_slide()


func _on_hit(body: Node2D) -> void:
if invincible or not (body is Enemy):
return
health = clampi(health-body.damage, 0, MAX_HEALTH)
health_changed.emit(health)
if health == 0:
await get_tree().create_timer(0.5).timeout
queue_free()
Loading