stardance has been extended another month! the new deadline is october 31 :)

You are browsing as a guest. Sign up (or log in) to start making projects!

hacha-mouse

@hacha-mouse

Joined May 31st, 2026

  • 45Devlogs
  • 4Projects
  • 3Ships
  • 48Votes
16yo Japanese Kosen student fascinated with Rust.
Open comments for this post

25m 50s logged

Rewritten the README

My previous project was rejected multiple times due to suspected AI usage, though I didn’t use AI to generate my README. So this time, I recorded the entire process when writing the README and made a timelapse of it.

0
1
50
Open comments for this post

1h 38m 43s logged

Added an Example Ruleset

I’ve added an example ruleset for reviewers and raters (I don’t know what they are named) to test my linting language quickly without writing one themselves.
The program on the screenshot is a rule that flags headings that are not continuous from the previous headings (like jumping from H1 to H3).

Honestly, this language is way more expressive than I first thought. I thought it would be impossible to detect skipping levels, but it could.

0
0
9
Open comments for this post

21m 22s logged

Wrote README

I created README.md and added some information to it.
I also added a sample linter program:

for sentence in sentences(doc) (
    length = char_count(doc, sentence)
    words = word_count(doc, sentence)
    has_hedging = or(
        contains(doc, sentence, "I think"),
        contains(doc, sentence, "I believe"),
        contains(doc, sentence, "perhaps"),
        contains(doc, sentence, "probably")
    )

    if and(
        gt(length, 100),
        gt(words, 15),
        has_hedging
    ) (
        sentence
    )
)
0
0
32
Open comments for this post

1h 46m 51s logged

Implemented Result Formatting

I’ve implemented the print logic of the lint result. I used owo-colors to colorize the output.

0
0
20
Open comments for this post

1h 48m 53s logged

Linting With Custom DSL

I’ve completed implementing my custom language for linting documents, and I added a few more functions to it.
Sample program:

for match in sentences(doc) (
    if gt(char_count(doc, match), 100) (
        match
    )
)

In this language, for and if are statements. This means that they can return values.
for collects non-null values and returns the list of values. if returns the value if it exists, and null if the value is not returned in it or the condition is false.

My plint CLI shows the errors on the position of the returned matches.

0
0
8
Open comments for this post

6h 38m 59s logged

Implemented Linting Language

I’ve implement the parser and the interpreter for my custom linting language.
I have some experience making custom language and this is not my first time doing that so it was quite easy and it took no longer than 10 hours to implement this.

0
0
4
Open comments for this post

1h 57m 35s logged

Added Commands

I implemented a few more commands:

ruleset check: Check if the ruleset is valid
ruleset create: Create a new ruleset
ruleset edit: Open the ruleset YAML file in the default editor
ruleset list: List all rulesets

group create: Create a new group
group edit: Open the group YAML file in the default editor
group add-set: Add the ruleset to the group
group remove-set: Remove the ruleset from the group
group list: List all groups

0
0
2
Open comments for this post

22m 44s logged

Added check command

I added ruleset check command to check if the ruleset is valid.
The error message is not yet implemented so it just shows the error using Debug, but I’ll change it later.

0
0
14
Open comments for this post

11h 24m 28s logged

Removed Interactive Editing

You may wonder why I removed it after more than 5 hours of coding. Here’s why.

I wanted to achieve something like this:

Ruleset
> Name: rule-foo-bar
  Authors: Alice
  Description: This is a placeholder description.
  Version: 1
  Edit Rules
  ← Back

I tried inquire and Ratatui to implement this. However, both of them was not suitable for this after all.

inquire

inquire is a very simple crate to ask users some question on CLI.
The main problem was that I could not add multiple fields and let user edit multiple fields in the same screen (like above), which means that the implementation had to be like this:

Select what to edit
> Name
  Authors
  Description
  Version
  Back

and I wanted to avoid this.

Ratatui

Ratatui is a crate to build a “TUI” application in Rust.
It is very powerful, but I found it a bit over-engineered for my use case. Also, it is mainly designed for full-screen terminal application and was not suitable for inline CLI application like mine.

Making a CLI Library Myself

I also tried to make a CLI library myself, but I decided not to do so. (You can find my library repository here.)
I used crossterm and I had to calculate the position of the cursor, characters and I also had to count unicode characters and calculate the widths for them. I thought that this was not worth it, especially because I didn’t have so much time before the summer break ends.

For now, I decided to make edit command just open the default editor and implement other things, and make the CLI after adding all other essential features.

0
0
14
Open comments for this post

3h 25m 58s logged

Use inquire for interactive ruleset creation

I added inquire to the dependency and used it to ask the name, the authors, the description and the version of the new ruleset when creating a ruleset.

0
0
30
Open comments for this post

1h 39m 39s logged

Conditional linting

I’ve added conditions so that the linter can use the returned value from the checker to determine whether to show an error.
Currently, condition includes eq, neq, gt, gte, lt, lte, and, or, and not.

0
0
14
Open comments for this post

2h 11m 1s logged

Implemented Linting & Testing

I added the basic linting logic and I tested if it works.
As you can see in the video, linting works nicely and it successfully returns the matches.

Here’s the example rule set I used in the video:

name: basic-ruleset
description: This is a basic ruleset.
version: 1

rules:
  - id: no-hello
    message: '"hello" is not allowed.'
    severity: error
    checker: std.regex
    args:
        pattern: hello

  - id: invalid-hello
    message: '"helloooo" is not allowed.'
    severity: error
    checker: std.regex
    args:
        pattern: helloooo
0
0
6
Open comments for this post

57m 49s logged

Finished Condition enum

I’ve implemented Condition enum used to evaluate the result of the checkers and decide whether to show an error in the ruleset.
Next I’m going to add the YAML loading feature

0
0
28
Open comments for this post

1h 25m 35s logged

Checker trait

I initialized the project structure and added basic types & traits. I also added RegexChecker that returns the matches of the given regular expression.

0
0
20
Ship Pending review

Kadent

Kadent is a cross-platform DAW featuring KASL, a domain-specific audio language, and node-graph processing system.

Features

  • Create music with familiar track-based UI
  • Two track types: Note Track & Audio Track
  • Node graph for every track
  • KASL language with syntax similar to Swift
    The node graph allows you to combine multiple KASL programs to perform much more complex processing.

What Is a Node Graph?

Kadent uses node graph for track processing.

A Node is a processing unit that calculates the output. In node graph, an output of one node can be connected to an input of another node. This allows you to connect multiple inputs and outputs freely to other nodes to create sound.

Then, why did I adopt node graph? KASL programs can have multiple inputs and outputs, and their types may also vary. So placing them in order does not work because the DAW cannot know which output is connected to the specific input. That’s why Kadent uses node graph.

Characteristics of KASL

  • Utilizes Cranelift as a backend for quicker JIT compilation
  • Specialized type of variables such as input, output and state
  • Supports fixed-length arrays and structs
  • Fixed-count loop syntax for predictable execution time
  • Module system influenced by Python
  • Custom infix/prefix/postfix operators (even normal arithmetic operators are defined and provided by std)

KASL Sample Program

audio module is built-in module provided by Kadent. Note that these programs below won’t work outside the DAW.

Gain Node

import audio
import std

input in = audio.zero_sample()
input gain = 0.0
output out = audio.zero_sample()

func main() {
    out = in * [gain; audio.max_channels]
}

Mix Node

import std
import std/math/float as f
import audio

input input_1 = audio.zero_sample()
input input_2 = audio.zero_sample()
input factor = 0.0
output out = audio.zero_sample()

func main() {
    let clamped_factor = f.clamp(factor, 0.0, 1.0)
    let multiplied_input_1: audio.Sample = input_1 * [clamped_factor; audio.max_channels]
    let multiplied_input_2: audio.Sample = input_2 * [1.0 - clamped_factor; audio.max_channels]
    out = multiplied_input_1 + multiplied_input_2
}

Sawtooth Wave Synthesizer

import audio as a
import std
import std/math/float as f

input notes = a.EventSlot()
input pitch = 1.0
output out = a.zero_sample()
state allocator = a.Allocator()

let base_freq = 440.0
let volume = 0.1

func main() {
    allocator.update(notes)

    var i = 0
    loop a.max_voices {
        let voice = allocator.voices[i]
        let freq = pitch * base_freq * f.pow(2.0, (voice.pitch - 69.0) / 12.0)

        if voice.is_active {
            let t = voice.age

            let sample = saw(freq: freq, time: t)
            out = out + [sample * volume; a.max_channels]
        }
        i = i + 1
    }
}

func saw(freq f = 440.0, time t: Float) -> Float {
    return 2.0 * (t * f) % 1.0 - 1.0
}

Installation

Go to the Releases page of my GitHub repository to download the latest precompiled binary, or compile the binary yourself. Detailed installation steps are described in README.

  • 23 devlogs
  • 229h
Try project → See source code →
Open comments for this post

17h 10m 49s logged

Added License Browser

It’s been a while since my last devlog!
During this time I’ve added an Acknowledgements view where you can look at license text and other informations of the Fonts and Crates that I’ve used.
It was a bit difficult to implement because there are so many crates, but I’m satisfied with the result.

0
0
37
Open comments for this post

41h 27m 13s logged

Improved code editor

I’ve implemented error highlighting in the code editor. I also added a list of errors at the bottom of the code editor, and I can jump to the position of the error by clicking the error.

TextEdit in egui does not support highlighting character by character and instead it only highlighting by each sections, so red underlined part may be bigger than the actual error range, but I guess it still looks nice.

0
0
6
Open comments for this post

10h 56m 7s logged

sode

I’ve created a simple binary serialization crate called “sode” for Kadent. This guarantees that the output binary won’t change even if the struct is modified so I thought it would be better than serde or that sort of serialization library.

impl Encode for Note {
    fn encode(&self, e: &mut Encoder) -> Result<(), EncodeError> {
        e.field(0, &self.start)?;
        e.field(1, &self.duration)?;
        e.field(2, &self.pitch)?;
        e.field(3, &self.velocity)?;
        Ok(())
    }
}

impl Decode for Note {
    fn decode(d: &mut ValueDecoder) -> Result<Self, DecodeError> {
        let d = d.to_field_decoder()?;
        Ok(Note::new(
            d.field(0)?.ok_or(DecodeError::InvalidData)?,
            d.field(1)?.ok_or(DecodeError::InvalidData)?,
            d.field(2)?.ok_or(DecodeError::InvalidData)?,
            d.field(3)?.ok_or(DecodeError::InvalidData)?,
        ))
    }
}
0
0
9
Open comments for this post

4h 21m 24s logged

Curve type selection

I’ve implemented a selection dropdown for three curve types: linear, step, and smooth. Next thing to do is to add a text field to adjust the curve tension

0
0
5
Open comments for this post

8h 42m 10s logged

Automation

Automation is here.
I’ve implemented an automation node, which is associated with an automation track that you can add keyframes to value that changes over time.
You can even connect automation nodes to KASL Node to use the value for calculation!

0
0
7
Loading more…

Followers

Loading…