From f4a1319352d466308cd85eb1263aef9fd2c54293 Mon Sep 17 00:00:00 2001 From: iurii plugatarov Date: Sat, 3 Aug 2024 00:01:35 +0300 Subject: init --- README.md | 58 ++++++++++++++++++++++++++++++++++ config.lua | 88 +++++++++++++++++++++++++++++++++++++++++++++++++++ create_note.lua | 20 ++++++++++++ git_sync.lua | 36 +++++++++++++++++++++ init.lua | 15 +++++++++ quick_note.lua | 91 +++++++++++++++++++++++++++++++++++++++++++++++++++++ search_notes.lua | 10 ++++++ select_template.lua | 71 +++++++++++++++++++++++++++++++++++++++++ update_index.lua | 22 +++++++++++++ 9 files changed, 411 insertions(+) create mode 100644 README.md create mode 100644 config.lua create mode 100644 create_note.lua create mode 100644 git_sync.lua create mode 100644 init.lua create mode 100644 quick_note.lua create mode 100644 search_notes.lua create mode 100644 select_template.lua create mode 100644 update_index.lua diff --git a/README.md b/README.md new file mode 100644 index 0000000..f67702d --- /dev/null +++ b/README.md @@ -0,0 +1,58 @@ +# sketchbook.nvim - simple notetaking + +Motivationg behind this thing, that I tried lots of notetaking tools but nothing really clicked. +I didn't want to leave nvim and it's not really convenient to manage ~/notes directory. + + +## Warn + +This was quick and dirty implementation, so not everything will perfectly because currently its in "works on my machine" state. + + +## Features + +- **Quick Note Creation**: Quickly create and manage notes. +- **Template Selection**: Choose from predefined templates for your notes. +- **Note Searching**: Search through your notes easily. +- **Git Integration**: Commit and push your notes to a Git repository. +- **Floating Windows**: Use floating windows for quick notes. + +## Installation + +You can install Sketchbook using [lazy.nvim](https://github.com/folke/lazy.nvim). + +### Using [lazy.nvim](https://github.com/folke/lazy.nvim) + +Add the following to your `lazy.nvim` configuration: + +```lua +require('lazy').setup({ + { + 'makefunstuff/sketchbook.nvim', + config = function() + require('sketchbook').setup({ + notes_directory = "~/my_notes/", + templates_directory = "~/my_notes/templates/", + keymaps = { + create_note = "nc", + update_index = "ni", + search_notes = "ns", + select_template = "nt", + create_quick_note = "nq", + toggle_quick_note = "qc", -- Keymap for toggling quick note window + open_entire_quick_note = "nqe", + commit_notes = "ngc", -- Keymap for committing notes + push_notes = "ngp", -- Keymap for pushing notes + } + }) + end + } +}) + +``` + +## TODO: + +- [ ] improve git Integration +- [ ] fix telescope issues with indexing +- [ ] add auto indexing diff --git a/config.lua b/config.lua new file mode 100644 index 0000000..999245d --- /dev/null +++ b/config.lua @@ -0,0 +1,88 @@ +local M = {} + +-- Default configuration +M.defaults = { + notes_directory = "~/notes", + templates_directory = "~/notes/templates/", + keymaps = { + create_note = "tnn", + update_index = "tui", + search_notes = "tns", + select_template = "ttn", + toggle_quick_note = "qc", + create_quick_note = "nq", + open_entire_quick_note = "qo", + commit_notes = "tgc", + push_notes = "tgp", -- New keymap for pushing notes + }, +} + +M.config = {} + +function M.setup(user_config) + M.config = vim.tbl_deep_extend("force", {}, M.defaults, user_config or {}) + vim.g.notes_directory = M.config.notes_directory + vim.g.notes_templates_dir = M.config.templates_directory + M.set_keymaps() +end + +function M.set_keymaps() + local keymaps = M.config.keymaps + + vim.api.nvim_set_keymap( + "n", + keymaps.create_note, + ':lua require("sketchbook.create_note").create_new_note()', + { noremap = true, silent = true, desc = "Create a new note" } + ) + vim.api.nvim_set_keymap( + "n", + keymaps.update_index, + ':lua require("sketchbook.update_index").update_index()', + { noremap = true, silent = true, desc = "Update notes index" } + ) + vim.api.nvim_set_keymap( + "n", + keymaps.search_notes, + ':lua require("sketchbook.search_notes").search_notes()', + { noremap = true, silent = true, desc = "Search notes" } + ) + vim.api.nvim_set_keymap( + "n", + keymaps.select_template, + ':lua require("sketchbook.select_template").select_template()', + { noremap = true, silent = true, desc = "Select a note template" } + ) + vim.api.nvim_set_keymap( + "n", + keymaps.create_quick_note, + ':lua require("sketchbook.quick_note").create_quick_note_window()', + { noremap = true, silent = true, desc = "Create a quick note buffer" } + ) + vim.api.nvim_set_keymap( + "n", + keymaps.toggle_quick_note, + ':lua require("sketchbook.quick_note").toggle_quick_note_window()', + { noremap = true, silent = true, desc = "Toggle quick note window" } + ) + vim.api.nvim_set_keymap( + "n", + keymaps.open_entire_quick_note, + ':lua require("sketchbook.quick_note").open_entire_quick_note()', + { noremap = true, silent = true, desc = "Open entire quick note" } + ) + vim.api.nvim_set_keymap( + "n", + keymaps.commit_notes, + ':lua require("sketchbook.git_sync").commit_notes()', + { noremap = true, silent = true, desc = "Commit notes to Git" } + ) + vim.api.nvim_set_keymap( + "n", + keymaps.push_notes, + ':lua require("sketchbook.git_sync").push_notes()', + { noremap = true, silent = true, desc = "Push notes to remote Git repository" } + ) +end + +return M diff --git a/create_note.lua b/create_note.lua new file mode 100644 index 0000000..d85e267 --- /dev/null +++ b/create_note.lua @@ -0,0 +1,20 @@ +local M = {} + +function M.create_new_note() + local notes_dir = vim.g.notes_directory or "~/notes/" + local filename = os.date "%Y-%m-%d_%H-%M-%S" .. ".md" + local filepath = vim.fn.expand(notes_dir) .. filename + local title = "Title " .. os.date "%Y-%m-%d %H:%M:%S" + local template = { + "# " .. title, + "", + } + local file = io.open(filepath, "w") + for _, line in ipairs(template) do + file:write(line .. "\n") + end + file:close() + vim.cmd("edit " .. filepath) +end + +return M diff --git a/git_sync.lua b/git_sync.lua new file mode 100644 index 0000000..d19f024 --- /dev/null +++ b/git_sync.lua @@ -0,0 +1,36 @@ +local M = {} + +function M.is_git_repo(path) + local git_dir = vim.fn.systemlist("git -C " .. path .. " rev-parse --is-inside-work-tree")[1] + return git_dir == "true" +end + +function M.commit_notes() + local notes_dir = vim.g.notes_directory or "~/notes/" + notes_dir = vim.fn.expand(notes_dir) + + if not M.is_git_repo(notes_dir) then + vim.notify("Note folder is not a Git repository.", vim.log.levels.WARN) + return + end + + local commit_message = "Update notes: " .. os.date "%Y-%m-%d %H:%M:%S" + vim.fn.system("git -C " .. notes_dir .. " add .") + vim.fn.system("git -C " .. notes_dir .. " commit -m '" .. commit_message .. "'") + vim.notify("Notes committed to Git repository.", vim.log.levels.INFO) +end + +function M.push_notes() + local notes_dir = vim.g.notes_directory or "~/notes/" + notes_dir = vim.fn.expand(notes_dir) + + if not M.is_git_repo(notes_dir) then + vim.notify("Note folder is not a Git repository.", vim.log.levels.WARN) + return + end + + vim.fn.system("git -C " .. notes_dir .. " push") + vim.notify("Notes pushed to remote repository.", vim.log.levels.INFO) +end + +return M diff --git a/init.lua b/init.lua new file mode 100644 index 0000000..0afcfe4 --- /dev/null +++ b/init.lua @@ -0,0 +1,15 @@ +local config = require "sketchbook.config" +local create_note = require "sketchbook.create_note" +local update_index = require "sketchbook.update_index" +local search_notes = require "sketchbook.search_notes" +local select_template = require "sketchbook.select_template" +local quick_note = require "sketchbook.quick_note" +local git_support = require "sketchbook.git_sync" + +local M = {} + +function M.setup(user_config) + config.setup(user_config) +end + +return M diff --git a/quick_note.lua b/quick_note.lua new file mode 100644 index 0000000..1196faf --- /dev/null +++ b/quick_note.lua @@ -0,0 +1,91 @@ +local M = {} +local floating_win = nil + +local function get_win_config() + local width = math.floor(vim.o.columns * 0.8) + local height = math.floor(vim.o.lines * 0.8) + local row = math.floor((vim.o.lines - height) / 2) + local col = math.floor((vim.o.columns - width) / 2) + return { + relative = "editor", + width = width, + height = height, + row = row, + col = col, + style = "minimal", + border = "rounded", + } +end + +function M.create_quick_note_window() + if floating_win and vim.api.nvim_win_is_valid(floating_win) then + vim.api.nvim_set_current_win(floating_win) + return + end + + local buf = vim.api.nvim_create_buf(false, true) + floating_win = vim.api.nvim_open_win(buf, true, get_win_config()) + + vim.api.nvim_buf_set_option(buf, "buftype", "acwrite") + vim.api.nvim_buf_set_name(buf, "QuickNote") +end + +function M.toggle_quick_note_window() + if floating_win and vim.api.nvim_win_is_valid(floating_win) then + M.close_quick_note_window() + else + M.create_quick_note_window() + end +end + +function M.close_quick_note_window() + if floating_win and vim.api.nvim_win_is_valid(floating_win) then + local buf = vim.api.nvim_win_get_buf(floating_win) + M.prepend_to_quick_note() + vim.api.nvim_win_close(floating_win, true) + vim.api.nvim_buf_delete(buf, { force = true }) + end +end + +function M.prepend_to_quick_note() + local notes_dir = vim.g.notes_directory or "~/notes/" + local filepath = vim.fn.expand(notes_dir) .. "/quick_note.md" + local buf = vim.api.nvim_win_get_buf(floating_win) + local content = vim.api.nvim_buf_get_lines(buf, 0, -1, false) + + -- Add a separator and timestamp before the new content + local separator = "------------------------" + local timestamp = os.date "%Y-%m-%d %H:%M:%S" + table.insert(content, 1, "") + table.insert(content, 1, separator) + table.insert(content, 1, timestamp) + table.insert(content, 1, separator) + table.insert(content, 1, "") + + -- Check if quick_note.md exists, create it if it doesn't + if vim.fn.filereadable(filepath) == 0 then + vim.fn.writefile({}, filepath) + end + + local file_content = vim.fn.readfile(filepath) + for i = #file_content, 1, -1 do + table.insert(content, 1, file_content[i]) + end + + vim.fn.writefile(content, filepath) + print "Prepended content to quick_note.md" +end + +function M.open_entire_quick_note() + local notes_dir = vim.g.notes_directory or "~/notes/" + local filepath = vim.fn.expand(notes_dir) .. "/quick_note.md" + + if vim.fn.filereadable(filepath) == 0 then + print "No quick_note.md file found." + return + end + + vim.cmd("edit " .. filepath) +end + +return M diff --git a/search_notes.lua b/search_notes.lua new file mode 100644 index 0000000..152355e --- /dev/null +++ b/search_notes.lua @@ -0,0 +1,10 @@ +local M = {} + +function M.search_notes() + local notes_dir = vim.g.notes_directory or "~/notes/" + require("telescope.builtin").live_grep { + search_dirs = { vim.fn.expand(notes_dir) }, + } +end + +return M diff --git a/select_template.lua b/select_template.lua new file mode 100644 index 0000000..e0c9f7e --- /dev/null +++ b/select_template.lua @@ -0,0 +1,71 @@ +local M = {} + +local templates_dir = vim.g.notes_templates_dir or "~/notes/templates/" + +function M.select_template() + templates_dir = vim.fn.expand(templates_dir) + local templates = vim.fn.readdir(templates_dir, function(name) + return name:match "%.md$" + end) + + if vim.tbl_isempty(templates) then + M.create_note_from_template(nil) + else + local template_files = {} + for _, template in ipairs(templates) do + table.insert(template_files, templates_dir .. template) + end + + require("telescope.pickers") + .new({}, { + prompt_title = "Select Template", + finder = require("telescope.finders").new_table { + results = template_files, + entry_maker = function(entry) + return { + value = entry, + display = vim.fn.fnamemodify(entry, ":t"), + ordinal = entry, + } + end, + }, + sorter = require("telescope.config").values.generic_sorter {}, + attach_mappings = function(prompt_bufnr, map) + local actions = require "telescope.actions" + local action_state = require "telescope.actions.state" + + actions.select_default:replace(function() + actions.close(prompt_bufnr) + local selection = action_state.get_selected_entry() + M.create_note_from_template(selection.value) + end) + + return true + end, + }) + :find() + end +end + +function M.create_note_from_template(template_path) + local notes_dir = vim.g.notes_directory or "~/notes/" + local filename = os.date "%Y-%m-%d_%H-%M-%S" .. ".md" + local filepath = vim.fn.expand(notes_dir) .. filename + vim.cmd("edit " .. filepath) + if template_path then + vim.cmd("0r " .. template_path) + else + local title = "Title " .. os.date "%Y-%m-%d %H:%M:%S" + local template = { + "# " .. title, + "", + } + local file = io.open(filepath, "w") + for _, line in ipairs(template) do + file:write(line .. "\n") + end + file:close() + end +end + +return M diff --git a/update_index.lua b/update_index.lua new file mode 100644 index 0000000..1a6044e --- /dev/null +++ b/update_index.lua @@ -0,0 +1,22 @@ +local M = {} + +function M.update_index() + local notes_dir = vim.g.notes_directory or "~/notes/" + notes_dir = vim.fn.expand(notes_dir) + local index_file = notes_dir .. "index.md" + local notes = vim.fn.globpath(notes_dir, "*.md", false, true) + local content = { "# Index", "" } + for _, note in ipairs(notes) do + if vim.fn.fnamemodify(note, ":t") ~= "index.md" then + table.insert(content, "- [" .. vim.fn.fnamemodify(note, ":t:r") .. "](" .. note .. ")") + end + end + local file = io.open(index_file, "w") + for _, line in ipairs(content) do + file:write(line .. "\n") + end + file:close() + print "Index updated" +end + +return M -- cgit 1.4.1-2-gfad0