diff --git a/.gitignore b/.gitignore index 599be4e..4ae96a6 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,7 @@ *.ez /build erl_crash.dump +.DS_Store +*.swp +*.swo +luma_markdown diff --git a/README.md b/README.md index ccd0bdc..1502f6c 100644 --- a/README.md +++ b/README.md @@ -3,22 +3,78 @@ [![Package Version](https://img.shields.io/hexpm/v/luma_markdown)](https://hex.pm/packages/luma_markdown) [![Hex Docs](https://img.shields.io/badge/hex-docs-ffaff3)](https://hexdocs.pm/luma_markdown/) +`luma_markdown` converts Luma markup to Markdown. It can read a file or consume +all of its input from standard input. + +## Standalone executable + +Gleam can package the Erlang version of the program as an escript. An escript +is one executable file containing the compiled program and its dependencies +(it does require Erlang to be installed on the machine where it is run). + +From the project directory, run: + ```sh -gleam add luma_markdown@1 -``` -```gleam -import luma_markdown - -pub fn main() -> Nil { - // TODO: An example of the project in use -} +gleam export escript +chmod +x luma_markdown ``` -Further documentation can be found at . +This creates the single executable `./luma_markdown`. Re-run the export +command after changing the source. To use a different filename, rename the +generated file: + +```sh +mv luma_markdown luma-md +``` + +Pass a file path as the only argument: + +```sh +./luma_markdown input.luma +``` + +Or pipe content into it. The command receiving the pipe must come last: + +```sh +echo "#1 A heading" | ./luma_markdown +cat input.luma | ./luma_markdown +``` + +When using a shell with history expansion (such as interactive zsh), use +single quotes or `printf` for input beginning with `!`: + +```sh +printf '%s\n' '!4 emphasized text' | ./luma_markdown +``` + +With no arguments, the executable reads until standard input reaches EOF and +writes the resulting Markdown to standard output. + +## Neovim preview + +The working preview configuration is also included in +[`examples/neovim_luma_preview.lua`](examples/neovim_luma_preview.lua). Copy it +into your Neovim configuration or source it with: + +```lua +dofile(vim.fn.getcwd() .. "/examples/neovim_luma_preview.lua") +``` + +The snippet looks for `luma_markdown` on `PATH`. To use the executable in this +repository directly, set its path before starting Neovim: + +```sh +export LUMA_MARKDOWN_BIN="$PWD/luma_markdown" +``` + +It registers the `:LumaPreview` command and automatically refreshes the +preview for `*.luma` files. ## Development ```sh -gleam run # Run the project -gleam test # Run the tests +gleam run -- input.luma # Run from the Gleam toolchain +gleam test # Run the tests ``` + +Further documentation can be found at . diff --git a/examples/neovim_luma_preview.lua b/examples/neovim_luma_preview.lua new file mode 100644 index 0000000..7b90d0d --- /dev/null +++ b/examples/neovim_luma_preview.lua @@ -0,0 +1,52 @@ +-- Neovim preview for Luma files. +-- +-- Set LUMA_MARKDOWN_BIN to the path of the generated executable, or make +-- luma_markdown available on PATH: +-- export LUMA_MARKDOWN_BIN="$PWD/luma_markdown" + +local preview_buf = nil +local preview_win = nil + +local function update_luma_preview() + local src_buf = vim.api.nvim_get_current_buf() + local lines = vim.api.nvim_buf_get_lines(src_buf, 0, -1, false) + local cmd = vim.env.LUMA_MARKDOWN_BIN or "luma_markdown" + local output = vim.fn.systemlist(cmd, lines) + + if not preview_buf or not vim.api.nvim_buf_is_valid(preview_buf) then + preview_buf = vim.api.nvim_create_buf(false, true) + vim.api.nvim_buf_set_option(preview_buf, "buftype", "nofile") + vim.api.nvim_buf_set_option(preview_buf, "bufhidden", "hide") + vim.api.nvim_buf_set_option(preview_buf, "swapfile", false) + vim.api.nvim_buf_set_option(preview_buf, "filetype", "markdown") + end + + vim.api.nvim_buf_set_lines(preview_buf, 0, -1, false, output) + + if not preview_win or not vim.api.nvim_win_is_valid(preview_win) then + vim.cmd "rightbelow vsplit" + preview_win = vim.api.nvim_get_current_win() + vim.api.nvim_win_set_buf(preview_win, preview_buf) + + local src_win = vim.fn.bufwinid(src_buf) + if src_win ~= -1 then vim.api.nvim_set_current_win(src_win) end + end +end + +vim.api.nvim_create_autocmd("BufWritePost", { + pattern = "*.luma", + callback = update_luma_preview, +}) + +vim.api.nvim_create_user_command("LumaPreview", update_luma_preview, {}) + +local timer = nil +local function debounced_update() + if timer then timer:stop() end + timer = vim.defer_fn(update_luma_preview, 150) +end + +vim.api.nvim_create_autocmd({ "TextChanged", "TextChangedI" }, { + pattern = "*.luma", + callback = debounced_update, +}) diff --git a/src/helpers.gleam b/src/helpers.gleam index 3533af5..dd62650 100644 --- a/src/helpers.gleam +++ b/src/helpers.gleam @@ -18,8 +18,6 @@ pub fn gather(instructions: List(definition.Instruction)) -> Information { _ -> Error(Nil) } }) - echo pushes - let min_max = case pushes { [] -> Error(Nil) [first, ..rest] -> diff --git a/src/luma_markdown.gleam b/src/luma_markdown.gleam index 05a23e9..221518d 100644 --- a/src/luma_markdown.gleam +++ b/src/luma_markdown.gleam @@ -11,8 +11,6 @@ pub fn luma_markdown( information: helpers.Information, contents: String, ) -> String { - echo contents - echo information let lines = string.split(contents, "\n") let parsed = @@ -37,7 +35,7 @@ pub fn luma_markdown( definition.Truth(instruction) -> string.repeat("__", instruction) } - definition.Pop(instruction) -> "##" + definition.Pop(_) -> "##" } }), "", @@ -53,21 +51,37 @@ pub fn main() -> Nil { [filename] -> { case simplifile.read(filename) { Ok(contents) -> { - //programm goes here - let instructins = parser.handler(contents) - let information = case instructins { - // get informations - definition.TextInstructions(instruction) -> - helpers.gather(instruction) - } - echo information - let result = luma_markdown(information, contents) - io.println(result) + render(contents) + } + Error(_) -> { + io.println("Couldn't read file: " <> filename) Nil } - Error(_) -> io.println("Couldn't read file") } } - _ -> io.println("Usage: gleam run ") + [] -> render(read_stdin([])) + _ -> { + io.println("Usage: luma_markdown [file]") + Nil + } + } +} + +fn render(contents: String) -> Nil { + let information = case parser.handler(contents) { + definition.TextInstructions(instructions) -> helpers.gather(instructions) + } + let result = luma_markdown(information, contents) + io.println(result) +} + +@external(erlang, "luma_stdin", "read_line") +fn read_line() -> String + +fn read_stdin(lines: List(String)) -> String { + let line = read_line() + case line { + "" -> lines |> list.reverse |> string.join("") + _ -> read_stdin([line, ..lines]) } } diff --git a/src/luma_stdin.erl b/src/luma_stdin.erl new file mode 100644 index 0000000..41c3e6a --- /dev/null +++ b/src/luma_stdin.erl @@ -0,0 +1,9 @@ +-module(luma_stdin). + +-export([read_line/0]). + +read_line() -> + case io:get_line("") of + eof -> <<>>; + Line -> unicode:characters_to_binary(Line) + end.