From 0aed1528e29fea8fee30cb79e3716e0da37d99e8 Mon Sep 17 00:00:00 2001 From: Wong Ding Feng Date: Fri, 5 Jun 2026 22:18:39 +0800 Subject: [PATCH] upd --- org/study_deck_02/lc-org.el | 157 ++++++++++++++++++++++++++++++++++++ 1 file changed, 157 insertions(+) create mode 100644 org/study_deck_02/lc-org.el diff --git a/org/study_deck_02/lc-org.el b/org/study_deck_02/lc-org.el new file mode 100644 index 0000000..1fa760a --- /dev/null +++ b/org/study_deck_02/lc-org.el @@ -0,0 +1,157 @@ +;;; lc-org.el --- LeetCode CLI integration for org source blocks -*- lexical-binding: t; -*- + +;; Usage: +;; In an org source block: +;; #+BEGIN_SRC python :lc-problem two-sum +;; class Solution: +;; def twoSum(self, nums, target): +;; ... +;; #+END_SRC +;; +;; M-x lc-org-submit — submit the block's code +;; M-x lc-org-run — run with test input +;; M-x lc-org-status — check last submission +;; +;; Header args: +;; :lc-problem SLUG — problem number or slug (required) +;; :lc-lang LANG — language (default: python3) +;; :lc-input INPUT — test input for `lc run` + +(defvar lc-org-bin "lc" + "Path to the `lc` CLI binary. +Set this if `lc` is not on PATH, e.g. \"uv run lc\" or \"/home/you/.local/bin/lc\".") + +(defvar lc-org-default-lang "python3" + "Default language when :lc-lang is not specified in the source block.") + +(defun lc-org--block-params () + "Extract lc parameters and code from the current org source block. +Returns a plist (:problem :lang :input :code) or signals an error." + (let* ((info (org-babel-get-src-block-info t)) + (lang (nth 0 info)) + (body (nth 1 info)) + (params (nth 2 info)) + (problem (cdr (assq :lc-problem params))) + (lc-lang (or (cdr (assq :lc-lang params)) + (cond + ((string= lang "python") "python3") + ((string= lang "python3") "python3") + ((string= lang "cpp") "cpp") + ((string= lang "c++") "cpp") + ((string= lang "c") "c") + ((string= lang "java") "java") + ((string= lang "javascript") "javascript") + ((string= lang "typescript") "typescript") + ((string= lang "rust") "rust") + ((string= lang "go") "golang") + ((string= lang "golang") "golang") + (t lc-org-default-lang)))) + (input (cdr (assq :lc-input params)))) + (unless problem + (user-error "No :lc-problem header arg on this source block")) + (list :problem (format "%s" problem) :lang lc-lang :input input :code body))) + +(defun lc-org--lc-command (&rest args) + "Build shell command string from lc-org-bin and ARGS." + (mapconcat #'shell-quote-argument (cons lc-org-bin (list-to-vector args)) " ")) + +(defun lc-org--run-command (cmd) + "Run CMD in a compilation buffer named *lc*." + (let ((buf (get-buffer-create "*lc*"))) + (with-current-buffer buf + (read-only-mode -1) + (erase-buffer) + (insert "$ " cmd "\n\n")) + (make-process + :name "lc" + :buffer buf + :command (list shell-file-name shell-command-switch cmd) + :sentinel (lambda (proc _event) + (when (memq (process-status proc) '(exit signal)) + (with-current-buffer (process-buffer proc) + (goto-char (point-max)) + (insert "\n--- finished (exit " (number-to-string (process-exit-code proc)) ") ---\n") + (read-only-mode 1)) + (display-buffer (process-buffer proc))))) + (display-buffer buf))) + +;;;###autoload +(defun lc-org-submit () + "Submit the current org source block to LeetCode." + (interactive) + (let* ((params (lc-org--block-params)) + (problem (plist-get params :problem)) + (lang (plist-get params :lang)) + (code (plist-get params :code)) + (tmpfile (make-temp-file "lc-org-" nil + (concat "." (cond ((string= lang "python3") "py") + ((string= lang "cpp") "cpp") + ((string= lang "c") "c") + ((string= lang "java") "java") + ((string= lang "javascript") "js") + ((string= lang "typescript") "ts") + ((string= lang "rust") "rs") + ((string= lang "golang") "go") + (t "txt")))))) + (with-temp-file tmpfile (insert code)) + (lc-org--run-command (format "%s submit %s --lang %s --file %s" + lc-org-bin + (shell-quote-argument problem) + (shell-quote-argument lang) + (shell-quote-argument tmpfile))))) + +;;;###autoload +(defun lc-org-run () + "Run the current org source block against test input. +Input is taken from :lc-input header arg, or prompted interactively." + (interactive) + (let* ((params (lc-org--block-params)) + (problem (plist-get params :problem)) + (lang (plist-get params :lang)) + (code (plist-get params :code)) + (input (or (plist-get params :input) + (read-string "Test input: "))) + (tmpfile (make-temp-file "lc-org-" nil + (concat "." (cond ((string= lang "python3") "py") + ((string= lang "cpp") "cpp") + ((string= lang "c") "c") + ((string= lang "java") "java") + ((string= lang "javascript") "js") + ((string= lang "typescript") "ts") + ((string= lang "rust") "rs") + ((string= lang "golang") "go") + (t "txt")))))) + (with-temp-file tmpfile (insert code)) + (lc-org--run-command (format "%s run %s --lang %s --file %s --input %s" + lc-org-bin + (shell-quote-argument problem) + (shell-quote-argument lang) + (shell-quote-argument tmpfile) + (shell-quote-argument input))))) + +;;;###autoload +(defun lc-org-status (submission-id) + "Check the status of a LeetCode submission by SUBMISSION-ID." + (interactive "sSubmission ID: ") + (lc-org--run-command (format "%s status %s" + lc-org-bin + (shell-quote-argument submission-id)))) + +;;;###autoload +(defun lc-org-show-problem () + "Show the problem description for the :lc-problem on the current block." + (interactive) + (let* ((params (lc-org--block-params)) + (problem (plist-get params :problem))) + (lc-org--run-command (format "%s problems show %s" + lc-org-bin + (shell-quote-argument problem))))) + +;;;###autoload +(defun lc-org-daily () + "Show today's daily challenge." + (interactive) + (lc-org--run-command (format "%s problems daily" lc-org-bin))) + +(provide 'lc-org) +;;; lc-org.el ends here