diff --git a/lua/typstar/anki.lua b/lua/typstar/anki.lua new file mode 100644 index 0000000..01c2a43 --- /dev/null +++ b/lua/typstar/anki.lua @@ -0,0 +1,32 @@ +local M = {} +local config = require('typstar.config') +local utils = require('typstar.utils') + +local cfg = config.config.anki + + +local function run_typstar_anki(args) + local cwd = vim.fn.getcwd() + local anki_key = '' + if cfg.ankiKey ~= nil then + anki_key = ' --anki-key ' .. cfg.ankiKey + end + local cmd = string.format( + '%s --root-dir %s --typst-cmd %s --anki-url %s %s %s', + cfg.typstarAnkiCmd, cwd, cfg.typstCmd, cfg.ankiUrl, anki_key, args) + utils.run_shell_command(cmd, true) +end + +function M.scan() + run_typstar_anki('') +end + +function M.scan_force() + run_typstar_anki('--force-scan ' .. vim.fn.getcwd()) +end + +function M.scan_force_current() + run_typstar_anki('--force-scan ' .. vim.fn.expand('%:p')) +end + +return M diff --git a/lua/typstar/config.lua b/lua/typstar/config.lua index 3890c5d..c8530b2 100644 --- a/lua/typstar/config.lua +++ b/lua/typstar/config.lua @@ -2,6 +2,12 @@ local M = {} local default_config = { typstarRoot = '~/typstar', + anki = { + typstarAnkiCmd = 'typstar-anki', + typstCmd = 'typst', + ankiUrl = 'http://127.0.0.1:8765', + ankiKey = nil, + }, excalidraw = { assetsDir = 'assets', filename = 'drawing-%Y-%m-%d-%H-%M-%S', diff --git a/lua/typstar/excalidraw.lua b/lua/typstar/excalidraw.lua index fe0c7cd..f714d9d 100644 --- a/lua/typstar/excalidraw.lua +++ b/lua/typstar/excalidraw.lua @@ -11,7 +11,9 @@ local affix = [[ local function launch_obsidian(path) print(string.format('Opening %s in Excalidraw', path)) - utils.run_shell_command(string.format('%s "obsidian://open?path=%s"', cfg.uriOpenCommand, utils.urlencode(path))) + utils.run_shell_command( + string.format('%s "obsidian://open?path=%s"', cfg.uriOpenCommand, utils.urlencode(path)), false + ) end function M.insert_drawing() @@ -27,7 +29,7 @@ function M.insert_drawing() for pattern, template_path in pairs(cfg.templatePath) do if string.match(path, pattern) then found_match = true - utils.run_shell_command(string.format('cat %s > %s', template_path, path)) -- don't copy file metadata + utils.run_shell_command(string.format('cat %s > %s', template_path, path), false) -- don't copy file metadata break end end diff --git a/lua/typstar/init.lua b/lua/typstar/init.lua index 2b38178..6089e82 100644 --- a/lua/typstar/init.lua +++ b/lua/typstar/init.lua @@ -4,11 +4,19 @@ local config = require('typstar.config') M.setup = function(args) config.merge_config(args) - local excalidraw = require('typstar.excalidraw') local autosnippets = require('typstar.autosnippets') + local excalidraw = require('typstar.excalidraw') + local anki = require('typstar.anki') + + vim.api.nvim_create_user_command('TypstarToggleSnippets', autosnippets.toggle_autosnippets, {}) + vim.api.nvim_create_user_command('TypstarInsertExcalidraw', excalidraw.insert_drawing, {}) vim.api.nvim_create_user_command('TypstarOpenExcalidraw', excalidraw.open_drawing, {}) - vim.api.nvim_create_user_command('TypstarToggleSnippets', autosnippets.toggle_autosnippets, {}) + + vim.api.nvim_create_user_command('TypstarAnkiScan', anki.scan, {}) + vim.api.nvim_create_user_command('TypstarAnkiForce', anki.scan_force, {}) + vim.api.nvim_create_user_command('TypstarAnkiForceCurrent', anki.scan_force_current, {}) + autosnippets.setup() end diff --git a/lua/typstar/utils.lua b/lua/typstar/utils.lua index 3343e98..6093ca3 100644 --- a/lua/typstar/utils.lua +++ b/lua/typstar/utils.lua @@ -26,8 +26,31 @@ function M.insert_text_block(snip) vim.api.nvim_buf_set_lines(vim.api.nvim_get_current_buf(), line_num, line_num, false, lines) end -function M.run_shell_command(cmd) - vim.fn.jobstart(cmd) +function M.run_shell_command(cmd, show_output) + local handle_output = function(data, err) + local msg = table.concat(data, '\n') + if not string.match(msg, '^%s*$') then + local level = err and vim.log.levels.ERROR or vim.log.levels.INFO + vim.notify(msg, level) + end + end + if show_output then + vim.fn.jobstart( + cmd, + { + on_stdout = function(_, data, _) + handle_output(data, false) + end, + on_stderr = function(_, data, _) + handle_output(data, true) + end, + stdout_buffered = false, + stderr_buffered = true, + } + ) + else + vim.fn.jobstart(cmd) + end end function M.char_to_hex(c) diff --git a/src/anki/anki_api.py b/src/anki/anki_api.py index 9857697..5fd2ee4 100644 --- a/src/anki/anki_api.py +++ b/src/anki/anki_api.py @@ -42,7 +42,7 @@ class AnkiConnectApi: update[card.deck].append(card) n_update += 1 - print(f"Pushing {n_add} new flashcards and {n_update} updated flashcards to Anki...") + print(f"Pushing {n_add} new flashcards and {n_update} updated flashcards to Anki...", flush=True) await self._create_required_decks({*add.keys(), *update.keys()}) await self._add_new_cards(add) await _gather_exceptions( diff --git a/src/anki/main.py b/src/anki/main.py index 7a5f5e2..327fb86 100644 --- a/src/anki/main.py +++ b/src/anki/main.py @@ -32,7 +32,7 @@ async def export_flashcards(root_dir, force_scan, clear_cache, typst_cmd, anki_u # write id updates to files parser.update_ids_in_source() parser.save_file_hashes() - print("Done") + print("Done", flush=True) @cli.command() diff --git a/src/anki/parser.py b/src/anki/parser.py index d7b8178..5347d35 100644 --- a/src/anki/parser.py +++ b/src/anki/parser.py @@ -108,7 +108,7 @@ class FlashcardParser: else: scan_dir = force_scan - print(f"Parsing flashcards in {scan_dir if single_file is None else single_file} ...") + print(f"Parsing flashcards in {scan_dir if single_file is None else single_file} ...", flush=True) preambles = {} flashcards = [] @@ -158,7 +158,7 @@ class FlashcardParser: self.save_file_hashes() def update_ids_in_source(self): - print("Updating ids in source...") + print("Updating ids in source...", flush=True) for fh, cards in self.file_handlers: file_updated = False for c in cards: diff --git a/src/anki/typst_compiler.py b/src/anki/typst_compiler.py index 6b89bd4..784552a 100644 --- a/src/anki/typst_compiler.py +++ b/src/anki/typst_compiler.py @@ -55,7 +55,7 @@ class TypstCompiler: card.set_svgs(front, back) async def compile_flashcards(self, cards: List[Flashcard]): - print(f"Compiling {len(cards)} flashcards...") + print(f"Compiling {len(cards)} flashcards...", flush=True) semaphore = asyncio.Semaphore(self.max_processes) async def compile_coro(card):