Skip to content

Commit bc40ae1

Browse files
committed
Merge remote-tracking branch 'upstream/master' into filter-sort
2 parents 57c33e0 + f61ad97 commit bc40ae1

1 file changed

Lines changed: 82 additions & 20 deletions

File tree

leetcode.el

Lines changed: 82 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
;; Author: Wang Kai <kaiwkx@gmail.com>
66
;; Keywords: extensions, tools
77
;; URL: https://github.com/kaiwk/leetcode.el
8-
;; Package-Requires: ((emacs "26.1") (s "1.13.0") (aio "1.0") (log4e "0.3.3"))
8+
;; Package-Requires: ((emacs "28.1") (s "1.13.0") (aio "1.0") (log4e "0.3.3"))
99
;; Version: 0.1.27
1010

1111
;; This program is free software; you can redistribute it and/or modify
@@ -71,14 +71,26 @@
7171

7272
(defun leetcode--install-my-cookie ()
7373
"Install leetcode dependencies."
74-
(let ((async-shell-command-display-buffer t))
74+
(let ((async-shell-command-display-buffer t)
75+
(pipx (executable-find "pipx"))
76+
(python3 (executable-find "python3"))
77+
(python (executable-find "python")))
7578
(async-shell-command
76-
"pip3 install my_cookies"
79+
(if pipx
80+
(format "%s install my_cookies" pipx)
81+
(format "%s -m venv --clear %s && %s/bin/pip3 install my_cookies"
82+
(or python3 python "python") ; require python environment
83+
leetcode-python-environment leetcode-python-environment))
7784
(get-buffer-create "*leetcode-install*"))))
7885

86+
(defun leetcode--my-cookies-path ()
87+
"Find the path to the my_cookies executable."
88+
(or (executable-find (format "%s/bin/my_cookies" leetcode-python-environment))
89+
(executable-find "my_cookies")))
90+
7991
(defun leetcode--check-deps ()
8092
"Check if all dependencies installed."
81-
(if (executable-find "my_cookies")
93+
(if (leetcode--my-cookies-path)
8294
t
8395
(leetcode--install-my-cookie)
8496
nil))
@@ -121,6 +133,11 @@ mysql, mssql, oraclesql."
121133
:group 'leetcode
122134
:type 'boolean)
123135

136+
(defcustom leetcode-python-environment (file-name-concat user-emacs-directory "leetcode-env")
137+
"The path to the isolated python virtual-environment to use."
138+
:group 'leetcode
139+
:type 'directory)
140+
124141
(cl-defstruct leetcode-user
125142
"A LeetCode User.
126143
The object with following attributes:
@@ -216,6 +233,11 @@ Default is programming language.")
216233
c, cpp, csharp, golang, java, javascript, typescript, kotlin, php, python,
217234
python3, ruby, rust, scala, swift, mysql, mssql, oraclesql.")
218235

236+
(defconst leetcode--code-start "// code_start"
237+
"Code start mark in LeetCode description.")
238+
(defconst leetcode--code-end "// code_end"
239+
"Code end mark in LeetCode description.")
240+
219241
(defvar leetcode--filter-status nil "Filter rows by status.")
220242
(defvar leetcode--filter-regex nil "Filter rows by regex.")
221243
(defvar leetcode--filter-tag nil "Filter rows by tag.")
@@ -377,15 +399,27 @@ query consolePanelConfig($titleSlug: String!) {
377399

378400
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Utils ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
379401

402+
(defun leetcode--insert-code-start-marker ()
403+
"Insert code start marker."
404+
(when (or (string= leetcode--lang "c")
405+
(string= leetcode--lang "cpp"))
406+
(insert (format "\n\n%s\n\n" leetcode--code-start))))
407+
408+
(defun leetcode--insert-code-end-marker ()
409+
"Insert code end marker."
410+
(when (or (string= leetcode--lang "c")
411+
(string= leetcode--lang "cpp"))
412+
(insert (format "\n\n%s\n\n" leetcode--code-end))))
413+
380414
(defun leetcode--referer (value)
381415
"It will return an alist as the HTTP Referer Header.
382416
VALUE should be the referer."
383417
(cons "Referer" value))
384418

385419
(defun leetcode--cookie-get-all ()
386420
"Get leetcode session with `my_cookies'. You can install it with pip."
387-
(let* ((my-cookies (executable-find "my_cookies"))
388-
(my-cookies-output (shell-command-to-string "my_cookies"))
421+
(let* ((my-cookies (leetcode--my-cookies-path))
422+
(my-cookies-output (shell-command-to-string (leetcode--my-cookies-path)))
389423
(cookies-list (seq-filter (lambda (s) (not (string-empty-p s)))
390424
(s-split "\n" my-cookies-output 'OMIT-NULLS)))
391425
(cookies-pairs (seq-map (lambda (s) (s-split-up-to " " s 1 'OMIT-NULLS)) cookies-list)))
@@ -425,7 +459,7 @@ VALUE should be the referer."
425459
"Make TITLE a slug title.
426460
Such as 'Two Sum' will be converted to 'two-sum'. 'Pow(x, n)' will be 'powx-n'"
427461
(let* ((str1 (replace-regexp-in-string "[\s-]+" "-" (downcase title)))
428-
(res (replace-regexp-in-string "[(),]" "" str1)))
462+
(res (replace-regexp-in-string "[(),']" "" str1)))
429463
res))
430464

431465
(defun leetcode--replace-in-buffer (regex to)
@@ -492,7 +526,11 @@ Such as 'Two Sum' will be converted to 'two-sum'. 'Pow(x, n)' will be 'powx-n'"
492526

493527
(defun leetcode--code-buffer-data ()
494528
"Get code buffer content, that is, the `current-buffer'."
495-
(leetcode--buffer-content (current-buffer)))
529+
(let ((code (leetcode--buffer-content (current-buffer)))
530+
(pattern (concat leetcode--code-start "\\([\0-\377]*?\\)" leetcode--code-end)))
531+
(if (string-match pattern code)
532+
(match-string 1 code)
533+
code)))
496534

497535
(defun leetcode--get-slug-title (code-buf)
498536
"Get slug title before try or submit with CODE-BUF.
@@ -560,7 +598,7 @@ of QUERY-NAME."
560598
:acceptance (format "%.1f%%" .acRate)
561599
:frequency (format "%.1f%%" .freqBar)
562600
:difficulty .difficulty
563-
:paid-only (eq .paidOnly :json-true)
601+
:paid-only (eq .paidOnly t)
564602
:tags (seq-reduce (lambda (tags tag)
565603
(let-alist tag
566604
(push .slug tags)))
@@ -734,7 +772,7 @@ Return a list of rows, each row is a vector:
734772
(p-title (concat
735773
(leetcode-problem-title p)
736774
" "
737-
(if (eq (leetcode-problem-paid-only p) t)
775+
(if (leetcode-problem-paid-only p)
738776
(leetcode--add-font-lock leetcode--paid 'leetcode-paid-face)
739777
" ")))
740778
(p-acceptance (leetcode-problem-acceptance p))
@@ -940,11 +978,12 @@ row."
940978
(goto-char url-http-end-of-headers)
941979
(let-alist (json-read)
942980
(let ((qid .data.activeDailyCodingChallengeQuestion.question.qid))
943-
(leetcode-show-problem (string-to-number qid)))))))
981+
(leetcode-show-problem qid))))))
944982

945983
(aio-defun leetcode-try ()
946984
"Asynchronously test the code using customized testcase."
947985
(interactive)
986+
(leetcode-restore-layout)
948987
(aio-await (leetcode--ensure-login t))
949988
(let* ((title-slug (leetcode--get-slug-title (current-buffer)))
950989
(problem (leetcode--get-problem title-slug))
@@ -955,9 +994,10 @@ row."
955994
(aio-defun leetcode-submit ()
956995
"Asynchronously submit the code and show result."
957996
(interactive)
997+
(leetcode-restore-layout)
958998
(aio-await (leetcode--ensure-login t))
959999
(let* ((code-buf (current-buffer))
960-
(code (leetcode--buffer-content code-buf))
1000+
(code (leetcode--code-buffer-data))
9611001
(slug-title (leetcode--get-slug-title code-buf))
9621002
(problem (leetcode--get-problem slug-title))
9631003
(problem-id (leetcode-problem-id problem))
@@ -1045,6 +1085,10 @@ alist specified in `display-buffer-alist'."
10451085
(goto-char (point-max))
10461086
(cond
10471087
((eq .status_code 10)
1088+
(if (equal .code_answer .expected_code_answer)
1089+
(insert (leetcode--add-font-lock "PASS: " 'leetcode-accepted-face))
1090+
(insert (leetcode--add-font-lock "FAIL: " 'leetcode-error-face)))
1091+
(insert "\n\n")
10481092
;; Code Answer
10491093
(insert "Code Answer:\n")
10501094
(dotimes (i (length .code_answer))
@@ -1061,8 +1105,15 @@ alist specified in `display-buffer-alist'."
10611105
(dotimes (i (length .std_output_list))
10621106
(when (aref .std_output_list i)
10631107
(insert (aref .std_output_list i))))))
1064-
((eq .status_code 14)
1065-
(insert .status_msg))
1108+
((or (eq .status_code 12) (eq .status_code 14))
1109+
(insert (format "Status: %s\n\n"
1110+
(leetcode--add-font-lock
1111+
(format "%s (%s/%s)" .status_msg .total_correct .total_testcases)
1112+
'leetcode-error-face)))
1113+
(insert (format "Test Case: \n%s\n\n" .last_testcase))
1114+
(insert (format "Expected Answer: %s\n\n" .expected_output))
1115+
(unless (string-empty-p .std_output)
1116+
(insert (format "Stdout: \n%s\n" .std_output))))
10661117
((eq .status_code 15)
10671118
(insert (leetcode--add-font-lock .status_msg 'leetcode-error-face))
10681119
(insert "\n\n")
@@ -1114,9 +1165,12 @@ STATUS_CODE has following possible value:
11141165
(insert (format "Last Test Case: %s\n" .last_testcase)))
11151166
((eq .status_code 14)
11161167
(insert (format "Status: %s" (leetcode--add-font-lock .status_msg 'leetcode-error-face)))
1117-
(insert "\n"))
1168+
(insert (format "\n\n%s / %s testcases passed\n" .total_correct .total_testcases))
1169+
(insert (format "Last Test Case: %s\n" .last_testcase)))
11181170
((eq .status_code 15)
11191171
(insert (format "Status: %s" (leetcode--add-font-lock .status_msg 'leetcode-error-face)))
1172+
(insert (format "\n\n%s / %s testcases passed\n" .total_correct .total_testcases))
1173+
(insert (format "Last Test Case: %s\n" .last_testcase))
11201174
(insert "\n\n")
11211175
(insert (format .full_runtime_error)))
11221176
((eq .status_code 20)
@@ -1184,7 +1238,8 @@ Get problem by id and use `shr-render-buffer' to render problem
11841238
detail. This action will show the detail in other window and jump
11851239
to it."
11861240
(interactive (list (read-string "Show problem by problem id: "
1187-
(leetcode--get-current-problem-id))))
1241+
(when (derived-mode-p 'leetcode--problems-mode)
1242+
(leetcode--get-current-problem-id)))))
11881243
(let* ((problem (leetcode--get-problem-by-id problem-id))
11891244
(title-slug (leetcode-problem-title-slug problem))
11901245
(problem-with-title (aio-await (leetcode--ensure-question-title problem)))
@@ -1267,8 +1322,9 @@ Call `leetcode-solve-problem' on the current problem id."
12671322

12681323
(defun leetcode--kill-buff-and-delete-window (buf)
12691324
"Kill BUF and delete its window."
1270-
(delete-windows-on buf t)
1271-
(kill-buffer buf))
1325+
(when buf
1326+
(delete-windows-on buf t)
1327+
(kill-buffer buf)))
12721328

12731329
(defun leetcode-quit ()
12741330
"Close and delete leetcode related buffers and windows."
@@ -1283,7 +1339,8 @@ Call `leetcode-solve-problem' on the current problem id."
12831339
(leetcode--kill-buff-and-delete-window (get-buffer (leetcode--detail-buffer-name problem-id)))
12841340
(leetcode--kill-buff-and-delete-window (get-buffer (leetcode--result-buffer-name problem-id)))
12851341
(leetcode--kill-buff-and-delete-window (get-buffer (leetcode--testcase-buffer-name problem-id)))))
1286-
leetcode--problem-titles))
1342+
leetcode--problem-titles)
1343+
(setq leetcode--problem-titles '()))
12871344

12881345
(defun leetcode--set-lang (snippets)
12891346
"Set `leetcode--lang' based on langSlug in SNIPPETS."
@@ -1369,7 +1426,9 @@ major mode by `leetcode-prefer-language'and `auto-mode-alist'."
13691426
(equal (leetcode-snippet-lang-slug s) leetcode--lang))
13701427
snippets))
13711428
(template-code (leetcode-snippet-code snippet)))
1429+
(leetcode--insert-code-start-marker)
13721430
(insert template-code)
1431+
(leetcode--insert-code-end-marker)
13731432
(leetcode--replace-in-buffer "" "")))
13741433
(funcall (assoc-default suffix auto-mode-alist #'string-match-p))
13751434
(leetcode-solution-mode t))
@@ -1392,7 +1451,7 @@ major mode by `leetcode-prefer-language'and `auto-mode-alist'."
13921451
"This command should be run in LeetCode code buffer.
13931452
It will restore the layout based on current buffer's name."
13941453
(interactive)
1395-
(let* ((slug-title (file-name-sans-extension (buffer-name)))
1454+
(let* ((slug-title (leetcode--get-slug-title (current-buffer)))
13961455
(problem (leetcode--get-problem slug-title))
13971456
(problem-id (leetcode-problem-id problem))
13981457
(desc-buf (get-buffer (leetcode--detail-buffer-name problem-id)))
@@ -1401,6 +1460,9 @@ It will restore the layout based on current buffer's name."
14011460
(leetcode--solving-window-layout)
14021461
(unless desc-buf
14031462
(aio-await (leetcode-show-problem problem-id)))
1463+
(with-current-buffer result-buf
1464+
(erase-buffer)
1465+
(insert "Waiting for result..."))
14041466
(display-buffer desc-buf
14051467
'((display-buffer-reuse-window
14061468
leetcode--display-detail)

0 commit comments

Comments
 (0)