Initial commit: LWP (Line Wrapping Program) with deno compile and formatting

Added support for deno compilation and formatting to .deno.json file.
Implemented basic line wrapping functionality in src/lwrap.ts, using Wrapper
class to wrap lines at 80 characters.
This commit is contained in:
Matthieu Jolimaitre 2025-06-26 14:07:21 +02:00
commit 06e062b0a5
5 changed files with 107 additions and 0 deletions

75
src/lwrap.ts Executable file
View file

@ -0,0 +1,75 @@
#!/usr/bin/env -S deno run
async function main() {
const input = readable_text(Deno.stdin.readable)
const output = writable_text(Deno.stdout.writable).getWriter()
const wrapper = new Wrapper(80)
for await (const chunk of input) {
const wrapped = wrapper.wrap(chunk)
for (const chunk of wrapped) await output.write(chunk)
}
}
function readable_text(readable: ReadableStream<Uint8Array<ArrayBuffer>>): ReadableStream<string> {
const decoder = new TextDecoderStream()
readable.pipeTo(decoder.writable)
return decoder.readable
}
function writable_text(writable: WritableStream<Uint8Array<ArrayBufferLike>>): WritableStream<string> {
const decoder = new TextEncoderStream()
decoder.readable.pipeTo(writable)
return decoder.writable
}
class Wrapper {
current_length = 0
prev_sep = ""
public constructor(
private max_width: number,
) {}
*wrap(chunk: string) {
let is_first = true
for (const line of chunk.split("\n")) {
this.current_length = 0
if (is_first) is_first = false
else yield "\n"
for (const word of this.split(line)) {
const length_after = this.current_length + word.word.length + this.prev_sep.length
if (length_after > 80) {
yield "\n"
yield word.word
this.prev_sep = word.sep
this.current_length = word.word.length
} else {
yield this.prev_sep
yield word.word
this.prev_sep = word.sep
this.current_length = length_after
}
}
}
}
*split(chunk: string) {
const separators = [" "]
let word_start = 0
let index = 0
for (const char of chunk) {
if (separators.includes(char)) {
const word = chunk.substring(word_start, index)
const sep = char
yield { word, sep }
word_start = index + 1
}
index += 1
}
const word = chunk.substring(word_start, index)
const sep = ""
if (word_start != index) yield { word, sep }
}
}
if (import.meta.main) await main()