Add post title
This commit is contained in:
@@ -1,9 +1,7 @@
|
|||||||
-- Load persistent configuration from .workspace.lua
|
require("lua/lemon")
|
||||||
local ws_file = "./.nvim.workspace.lua"
|
|
||||||
local loaded, workspace = pcall(dofile, ws_file)
|
local def_workspace = { args = {}, build_type = "debug", binary = "blog-server" }
|
||||||
if not loaded then
|
local workspace = InitWorkspace(def_workspace)
|
||||||
workspace = { args = {}, build_type = "debug", binary = "blog-server" }
|
|
||||||
end
|
|
||||||
|
|
||||||
local build_folder
|
local build_folder
|
||||||
local bin_target
|
local bin_target
|
||||||
@@ -47,35 +45,6 @@ vim.api.nvim_create_autocmd("FileType", {
|
|||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
|
|
||||||
local function writeWorkspace()
|
|
||||||
-- A very minimal serializer for workspace configuration
|
|
||||||
local s = { l = "", ls = {}, i = "" }
|
|
||||||
local function w(v) s.l = s.l .. v end
|
|
||||||
local function nl()
|
|
||||||
s.ls[#s.ls + 1] = s.l; s.l = s.i;
|
|
||||||
end
|
|
||||||
local function wv(v)
|
|
||||||
local t = type(v)
|
|
||||||
if t == 'table' then
|
|
||||||
w('{'); local pi = s.i; s.i = s.i .. " "
|
|
||||||
for k1, v1 in pairs(v) do
|
|
||||||
nl(); w('['); wv(k1); w('] = '); wv(v1); w(',')
|
|
||||||
end
|
|
||||||
s.i = pi; nl(); w('}');
|
|
||||||
elseif t == 'number' then
|
|
||||||
w(tostring(v))
|
|
||||||
elseif t == 'string' then
|
|
||||||
w('"' .. v .. '"')
|
|
||||||
else
|
|
||||||
w(tostring(v))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Write the workspace file
|
|
||||||
w("return "); wv(workspace); nl()
|
|
||||||
vim.fn.writefile(s.ls, ws_file)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- nvim-dap configuration
|
-- nvim-dap configuration
|
||||||
local dap_ok, dap = pcall(require, "dap")
|
local dap_ok, dap = pcall(require, "dap")
|
||||||
local dap_def_cfg
|
local dap_def_cfg
|
||||||
@@ -85,22 +54,7 @@ local dap_configs
|
|||||||
local function updateArgs(args)
|
local function updateArgs(args)
|
||||||
workspace.args = args
|
workspace.args = args
|
||||||
if dap_configs ~= nil then dap_configs[1].args = args end
|
if dap_configs ~= nil then dap_configs[1].args = args end
|
||||||
writeWorkspace()
|
WriteWorkspace()
|
||||||
end
|
|
||||||
|
|
||||||
-- Find terminal tab or create new one, then run command
|
|
||||||
local function TermRun(cmd)
|
|
||||||
local found = false
|
|
||||||
for i = 1, vim.fn.tabpagenr('$') do
|
|
||||||
vim.cmd('tabnext ' .. i)
|
|
||||||
if vim.bo.buftype == 'terminal' then
|
|
||||||
found = true
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if not found then vim.cmd('tabnew | terminal') end
|
|
||||||
vim.fn.chansend(vim.b.terminal_job_id, '' .. cmd .. '\n')
|
|
||||||
vim.fn.feedkeys("G", "n")
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- The Configure command
|
-- The Configure command
|
||||||
@@ -110,7 +64,7 @@ vim.api.nvim_create_user_command("Configure", function(a)
|
|||||||
if #a.args > 0 then bt = a.args end
|
if #a.args > 0 then bt = a.args end
|
||||||
workspace.build_type = bt
|
workspace.build_type = bt
|
||||||
updateBuildEnv()
|
updateBuildEnv()
|
||||||
writeWorkspace()
|
WriteWorkspace()
|
||||||
end, { nargs = '?', desc = "Update run/debug arguments" })
|
end, { nargs = '?', desc = "Update run/debug arguments" })
|
||||||
|
|
||||||
vim.api.nvim_create_user_command("Args", function(a) updateArgs(a.fargs) end,
|
vim.api.nvim_create_user_command("Args", function(a) updateArgs(a.fargs) end,
|
||||||
@@ -125,7 +79,7 @@ if dap_ok then
|
|||||||
}
|
}
|
||||||
dap_configs = {
|
dap_configs = {
|
||||||
{
|
{
|
||||||
name = 'test all',
|
name = 'default',
|
||||||
type = 'codelldb',
|
type = 'codelldb',
|
||||||
request = 'launch',
|
request = 'launch',
|
||||||
program = bin_name,
|
program = bin_name,
|
||||||
@@ -147,7 +101,6 @@ if dap_ok then
|
|||||||
end, { nargs = '*', desc = "Starts debugging with specified arguments" })
|
end, { nargs = '*', desc = "Starts debugging with specified arguments" })
|
||||||
end
|
end
|
||||||
|
|
||||||
if MakeAnd then
|
|
||||||
local r = function()
|
local r = function()
|
||||||
MakeAnd(function()
|
MakeAnd(function()
|
||||||
TermRun(bin_name .. " " .. table.concat(workspace.args, " "))
|
TermRun(bin_name .. " " .. table.concat(workspace.args, " "))
|
||||||
@@ -161,6 +114,17 @@ if MakeAnd then
|
|||||||
|
|
||||||
-- F6 to run the application
|
-- F6 to run the application
|
||||||
vim.keymap.set('n', '<F6>', r)
|
vim.keymap.set('n', '<F6>', r)
|
||||||
|
vim.keymap.set('n', '<F18>', function()
|
||||||
|
local info = GetTermInfo()
|
||||||
|
if info then
|
||||||
|
-- Send interrupt to terminal without switching
|
||||||
|
vim.fn.chansend(info.job_id, '\003')
|
||||||
|
-- Close window if it's open
|
||||||
|
vim.print("Stopped program")
|
||||||
|
else
|
||||||
|
vim.print("No terminal buffer found")
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
if dap_ok then
|
if dap_ok then
|
||||||
-- Shift-F5 to launch default config
|
-- Shift-F5 to launch default config
|
||||||
@@ -170,4 +134,3 @@ if MakeAnd then
|
|||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use chrono::{DateTime, Utc};
|
use chrono::{DateTime, Utc};
|
||||||
use pulldown_cmark::{html, Options, Parser};
|
use pulldown_cmark::{html, Event, HeadingLevel, Options, Parser, Tag};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
@@ -8,6 +8,7 @@ use std::process::Command;
|
|||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Post {
|
pub struct Post {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
|
pub title: String,
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub filename: String,
|
pub filename: String,
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
@@ -143,9 +144,10 @@ impl PostManager {
|
|||||||
}
|
}
|
||||||
let markdown_content = fs::read_to_string(&entry.file_path)
|
let markdown_content = fs::read_to_string(&entry.file_path)
|
||||||
.map_err(|e| format!("Failed to read post file: {}", e))?;
|
.map_err(|e| format!("Failed to read post file: {}", e))?;
|
||||||
let html_content = markdown_to_html(&markdown_content);
|
let (html_content, title) = markdown_to_html(&markdown_content);
|
||||||
let post = Post {
|
let post = Post {
|
||||||
name: name.clone(),
|
name: name.clone(),
|
||||||
|
title: title,
|
||||||
filename: entry.file_path,
|
filename: entry.file_path,
|
||||||
markdown_content,
|
markdown_content,
|
||||||
html_content,
|
html_content,
|
||||||
@@ -189,7 +191,28 @@ impl PostManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn markdown_to_html(markdown: &str) -> String {
|
fn markdown_title(markdown: &str) -> Option<String> {
|
||||||
|
let parser = Parser::new(markdown);
|
||||||
|
for event in parser {
|
||||||
|
if let Event::Start(tag) = event {
|
||||||
|
if let Tag::Heading {
|
||||||
|
level,
|
||||||
|
id,
|
||||||
|
..
|
||||||
|
} = tag
|
||||||
|
{
|
||||||
|
if level == HeadingLevel::H1 {
|
||||||
|
if let Some(str) = id {
|
||||||
|
return Some(str.to_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn markdown_to_html(markdown: &str) -> (String, String) {
|
||||||
let mut options = Options::empty();
|
let mut options = Options::empty();
|
||||||
options.insert(Options::ENABLE_STRIKETHROUGH);
|
options.insert(Options::ENABLE_STRIKETHROUGH);
|
||||||
options.insert(Options::ENABLE_TABLES);
|
options.insert(Options::ENABLE_TABLES);
|
||||||
@@ -197,8 +220,10 @@ fn markdown_to_html(markdown: &str) -> String {
|
|||||||
options.insert(Options::ENABLE_TASKLISTS);
|
options.insert(Options::ENABLE_TASKLISTS);
|
||||||
options.insert(Options::ENABLE_SMART_PUNCTUATION);
|
options.insert(Options::ENABLE_SMART_PUNCTUATION);
|
||||||
|
|
||||||
|
let title = markdown_title(markdown).unwrap_or("unknown".to_string());
|
||||||
|
|
||||||
let parser = Parser::new_ext(markdown, options);
|
let parser = Parser::new_ext(markdown, options);
|
||||||
let mut html_output = String::new();
|
let mut html_output = String::new();
|
||||||
html::push_html(&mut html_output, parser);
|
html::push_html(&mut html_output, parser);
|
||||||
html_output
|
(html_output, title)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -171,6 +171,17 @@ fn process_tag(
|
|||||||
Ok(post.html_content.clone())
|
Ok(post.html_content.clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
"title" => {
|
||||||
|
let post_name = current_post
|
||||||
|
.ok_or_else(|| "title tag used outside of post context".to_string())?;
|
||||||
|
|
||||||
|
let post = post_manager
|
||||||
|
.get_post(post_name)
|
||||||
|
.ok_or_else(|| format!("Post '{}' not found", post_name))?;
|
||||||
|
|
||||||
|
Ok(post.title.to_string())
|
||||||
|
}
|
||||||
|
|
||||||
"updated" => {
|
"updated" => {
|
||||||
// Insert the last updated time of the current post (or most recent post)
|
// Insert the last updated time of the current post (or most recent post)
|
||||||
let post_ts = if let Some(p) = current_post {
|
let post_ts = if let Some(p) = current_post {
|
||||||
|
|||||||
Reference in New Issue
Block a user