feat: issue #32 markdown editor for TUI
This commit is contained in:
@@ -25,8 +25,8 @@ defmodule BDS.TUI do
|
||||
`yyyy-mm-dd`; enter keeps the filter, esc clears it),
|
||||
`:` vi-style command prompt over the Blog-menu shell commands, `?`
|
||||
command help (commands whose report/apply UI is GUI-only are marked).
|
||||
Posts open in the rendered markdown preview (new empty posts open in
|
||||
the editor). Editor focus: `ctrl+e` toggles preview/editor, text keys
|
||||
Posts open in the syntax-highlighted, word-wrapping editor. Editor
|
||||
focus: `ctrl+e` toggles editor/rendered-markdown preview, text keys
|
||||
edit, `ctrl+s` save, `ctrl+p` publish, `ctrl+t` edit title, `ctrl+l`
|
||||
cycle language, `ctrl+g` AI suggestions, `esc` back to sidebar. `ctrl+q`
|
||||
quits, `esc` also closes a media preview. The UI locale is the
|
||||
@@ -42,6 +42,7 @@ defmodule BDS.TUI do
|
||||
alias BDS.Git
|
||||
alias BDS.Posts
|
||||
alias BDS.Projects
|
||||
alias BDS.UI.CodeEditor
|
||||
alias BDS.UI.PostEditor.{Draft, Metadata, Persistence}
|
||||
alias BDS.UI.SettingsForm
|
||||
alias BDS.UI.Sidebar
|
||||
@@ -49,7 +50,7 @@ defmodule BDS.TUI do
|
||||
alias ExRatatui.Layout
|
||||
alias ExRatatui.Layout.Rect
|
||||
alias ExRatatui.Style
|
||||
alias ExRatatui.Widgets.{Block, Clear, List, Markdown, Paragraph, Tabs, Textarea}
|
||||
alias ExRatatui.Widgets.{Block, Clear, List, Markdown, Paragraph, Tabs}
|
||||
|
||||
@views ~w(posts media templates scripts tags settings git)
|
||||
@git_diff_scroll_step 10
|
||||
@@ -230,8 +231,7 @@ defmodule BDS.TUI do
|
||||
when is_binary(project_id) do
|
||||
case Posts.create_post(%{project_id: project_id, title: "", content: ""}) do
|
||||
{:ok, post} ->
|
||||
# A fresh, empty post starts in the editor — there is nothing to
|
||||
# preview yet; existing posts open in the preview instead.
|
||||
# A fresh, empty post starts in the editor — like every post.
|
||||
{:noreply, state |> load_sidebar() |> open_post(post.id, false)}
|
||||
|
||||
{:error, reason} ->
|
||||
@@ -1448,10 +1448,9 @@ defmodule BDS.TUI do
|
||||
[title_widget, body_widget(state, editor, body_rect)]
|
||||
end
|
||||
|
||||
# The editing textarea cannot soft-wrap (upstream ratatui-textarea
|
||||
# limitation), so ctrl+e flips to a word-wrapped read-only Markdown
|
||||
# preview of the current draft. Wrap moves into the editor itself with
|
||||
# the planned MarkdownEditor custom widget.
|
||||
# ctrl+e flips to a word-wrapped read-only Markdown preview of the
|
||||
# current draft; the editor itself is a syntax-highlighted, wrapping
|
||||
# BDS.UI.CodeEditor over the same Rust-owned textarea.
|
||||
defp body_widget(_state, %{preview?: true} = editor, body_rect) do
|
||||
preview_title =
|
||||
"#{dgettext("ui", "Preview (ctrl+e to edit)")} [#{editor.language}]"
|
||||
@@ -1468,14 +1467,14 @@ defmodule BDS.TUI do
|
||||
"#{dgettext("ui", "Content")} [#{editor.language}]" <>
|
||||
if(editor.dirty, do: " •", else: "")
|
||||
|
||||
{%Textarea{
|
||||
state: editor.textarea,
|
||||
focused? = state.focus == :editor and not editor.editing_title?
|
||||
|
||||
{%CodeEditor{
|
||||
textarea: editor.textarea,
|
||||
language: :markdown_macros,
|
||||
block: %Block{title: body_title, borders: [:all]},
|
||||
cursor_style:
|
||||
if(state.focus == :editor and not editor.editing_title?,
|
||||
do: %Style{bg: :cyan},
|
||||
else: %Style{}
|
||||
)
|
||||
cursor_style: if(focused?, do: %Style{bg: :cyan}, else: %Style{}),
|
||||
line_highlight_style: if(focused?, do: %Style{bg: :dark_gray}, else: %Style{})
|
||||
}, body_rect}
|
||||
end
|
||||
|
||||
@@ -1945,9 +1944,9 @@ defmodule BDS.TUI do
|
||||
|
||||
# ── Post editor ──────────────────────────────────────────────────────────
|
||||
|
||||
# Posts open in the rendered markdown preview by default — the editor is
|
||||
# one ctrl+e away. New (empty) posts pass preview?: false.
|
||||
defp open_post(state, post_id, preview? \\ true) do
|
||||
# Posts open in the syntax-highlighted editor by default — the rendered
|
||||
# markdown preview is one ctrl+e away.
|
||||
defp open_post(state, post_id, preview? \\ false) do
|
||||
case Posts.get_post(post_id) do
|
||||
nil ->
|
||||
toast(state, dgettext("ui", "Posts"), dgettext("ui", "Post not found."))
|
||||
|
||||
Reference in New Issue
Block a user