upd
This commit is contained in:
@@ -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
|
||||
Reference in New Issue
Block a user