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:
commit
06e062b0a5
5 changed files with 107 additions and 0 deletions
75
src/lwrap.ts
Executable file
75
src/lwrap.ts
Executable 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()
|
Loading…
Add table
Add a link
Reference in a new issue