irongit

A Neovim plugin enabling you to solve LeetCode problems.

feat(question): option to disable translated contents for cn

kawreauthored
parent 551e4bbcommit 7ccfaa35e9c10301c62fa276a2dd1e990bb08d2aBrowse files

14 files changed, +99 -121

+4-28lua/leetcode-plugins/cn/queries.lua
@@ -13,32 +13,6 @@ queries.auth = [[
1313 }
1414 ]]
1515
16-queries.problemset = [[
17- query problemsetQuestionList($limit: Int) {
18- problemsetQuestionList(
19- categorySlug: ""
20- limit: $limit
21- filters: { }
22- ) {
23- questions {
24- frontend_id: frontendQuestionId
25- title
26- title_slug: titleSlug
27- title_cn: titleCn
28- status
29- paid_only: paidOnly
30- ac_rate: acRate
31- difficulty
32- topic_tags: topicTags {
33- name
34- slug
35- id
36- }
37- }
38- }
39- }
40- ]]
41-
4216 queries.qot = [[
4317 query questionOfToday {
4418 todayRecord {
@@ -54,14 +28,16 @@ queries.question = [[
5428 question(titleSlug: $titleSlug) {
5529 id: questionId
5630 frontend_id: questionFrontendId
57- title: translatedTitle
5831 title_slug: titleSlug
5932 is_paid_only: isPaidOnly
6033 difficulty
6134 likes
6235 dislikes
6336 category_title: categoryTitle
64- content: translatedContent
37+ content
38+ translated_content: translatedContent
39+ title
40+ translated_title: translatedTitle
6541 mysql_schemas: mysqlSchemas
6642 data_schemas: dataSchemas
6743 code_snippets: codeSnippets {
+1-0lua/leetcode/api/auth.lua
@@ -18,6 +18,7 @@ function Auth.user(cb)
1818 end
1919 end
2020
21+---@private
2122 ---@return lc.UserStatus|nil, lc.err|nil
2223 function Auth.handle(res, err)
2324 if err then return res, err end
+2-2lua/leetcode/api/problems.lua
@@ -18,7 +18,7 @@ function M.all(cb)
1818
1919 local problems = utils.normalize_problems(res.stat_status_pairs)
2020
21- if config.is_cn and config.user.cn.translate then
21+ if config.is_cn then
2222 M.translated_titles(function(titles)
2323 problems = utils.translate_titles(problems, titles)
2424 cb(problems)
@@ -31,7 +31,7 @@ function M.all(cb)
3131 local res, err = utils.get(endpoint)
3232 local problems = utils.normalize_problems(res.stat_status_pairs)
3333
34- if config.is_cn and config.user.cn.translate then
34+ if config.is_cn then
3535 local titles = M.translated_titles()
3636 return utils.translate_titles(problems, titles)
3737 else
+0-25lua/leetcode/api/queries.lua
@@ -13,31 +13,6 @@ queries.auth = [[
1313 }
1414 ]]
1515
16-queries.problemset = [[
17- query problemsetQuestionList($limit: Int) {
18- problemsetQuestionList: questionList(
19- categorySlug: ""
20- limit: $limit
21- filters: { }
22- ) {
23- questions: data {
24- frontend_id: questionFrontendId
25- title
26- title_slug: titleSlug
27- status
28- paid_only: isPaidOnly
29- ac_rate: acRate
30- difficulty
31- topic_tags: topicTags {
32- name
33- slug
34- id
35- }
36- }
37- }
38- }
39- ]]
40-
4116 queries.qot = [[
4217 query questionOfToday {
4318 todayRecord: activeDailyCodingChallengeQuestion {
+2-0lua/leetcode/api/types.lua
@@ -255,6 +255,7 @@
255255 ---@field id integer
256256 ---@field frontend_id integer
257257 ---@field title string
258+---@field translated_title string
258259 ---@field title_slug string
259260 ---@field is_paid_only boolean
260261 ---@field difficulty string
@@ -262,6 +263,7 @@
262263 ---@field dislikes integer
263264 ---@field category_title string
264265 ---@field content string
266+---@field translated_content string
265267 ---@field mysql_schemas string[]
266268 ---@field data_schemas string[]
267269 ---@field code_snippets code_snippet[]
+2-5lua/leetcode/api/utils.lua
@@ -165,7 +165,7 @@ function utils.normalize_problems(problems)
165165 id = p.stat.question_id,
166166 frontend_id = p.stat.frontend_question_id,
167167 title = p.stat.question__title,
168- sec_title = "",
168+ title_cn = "",
169169 title_slug = p.stat.question__title_slug,
170170 link = ("%s/problems/%s/"):format(config.domain, p.stat.question__title_slug),
171171 paid_only = p.paid_only,
@@ -189,10 +189,7 @@ function utils.translate_titles(problems, titles)
189189
190190 return vim.tbl_map(function(p)
191191 local title = map[tostring(p.id)]
192- if title then
193- p.sec_title = p.title
194- p.title = title
195- end
192+ if title then p.title_cn = title end
196193 return p
197194 end, problems)
198195 end
+2-6lua/leetcode/cache/init.lua
@@ -1,12 +1,8 @@
1-local cookie = require("leetcode.cache.cookie")
2-local problems = require("leetcode.cache.problemlist")
1+local Problemlist = require("leetcode.cache.problemlist")
32
43 ---@class lc.Cache
54 local cache = {}
65
7-function cache.update()
8- problems.update(true)
9- -- cookie.update()
10-end
6+function cache.update() Problemlist.update() end
117
128 return cache
+48-46lua/leetcode/cache/problemlist.lua
@@ -2,8 +2,11 @@ local path = require("plenary.path")
22 local log = require("leetcode.logger")
33
44 local config = require("leetcode.config")
5+---@type Path
56 local file = config.home:joinpath((".problemlist%s"):format(config.is_cn and "_cn" or ""))
67
8+local hist = {}
9+
710 local problems_api = require("leetcode.api.problems")
811
912 ---@class lc.Cache.Question.topicTags
@@ -15,7 +18,6 @@ local problems_api = require("leetcode.api.problems")
1518 ---@field frontend_id string
1619 ---@field link string
1720 ---@field title string
18----@field sec_title string
1921 ---@field title_cn string
2022 ---@field title_slug string
2123 ---@field status string
@@ -24,25 +26,25 @@ local problems_api = require("leetcode.api.problems")
2426 ---@field difficulty "Easy" | "Medium" | "Hard"
2527 ---@field topic_tags lc.Cache.Question.topicTags[]
2628
27-local problemlist = {}
29+---@class lc.cache.Problemlist
30+local Problemlist = {}
2831
29-local function populate()
32+function Problemlist.populate()
3033 local spinner = require("leetcode.logger.spinner")
3134
32- local noti = spinner:init("Fetching Problem List", "points")
35+ local noti = spinner:init("fetching problem list", "points")
3336 local data = problems_api.all()
34- problemlist.write(data)
35- noti:stop("Problems Cache Updated!")
37+ noti:stop("problems cache updated")
38+ Problemlist.write(data)
39+ return data
3640 end
3741
3842 ---@param data string|table
39-function problemlist.write(data)
43+function Problemlist.write(data)
4044 local str
4145
4246 if type(data) == "table" then
43- local ok, dec = pcall(vim.json.encode, data)
44- assert(ok, dec)
45- str = dec
47+ str = vim.json.encode(data)
4648 else
4749 str = data
4850 end
@@ -51,65 +53,65 @@ function problemlist.write(data)
5153 end
5254
5355 ---@return lc.Cache.Question[]
54-function problemlist.get()
55- problemlist.update()
56+function Problemlist.get()
57+ if not file:exists() then return Problemlist.populate() end
5658
57- local r_ok, contents = pcall(path.read, file)
58- assert(r_ok)
59+ local fstats = file:_stat()
60+ local ftime = fstats.mtime.sec
61+ local curr_time = os.time()
5962
60- local ok, problems = pcall(problemlist.parse, contents)
61- assert(ok)
63+ if (curr_time - ftime) > config.user.cache.update_interval then Problemlist.update() end
6264
63- return problems
64-end
65+ local hproblem = hist[ftime]
66+ if hproblem then return hproblem end
6567
66----@param force? boolean
67-function problemlist.update(force)
68- local stats = file:_stat()
69- if vim.tbl_isempty(stats) then return populate() end
68+ local contents = file:read()
69+ if not contents or type(contents) ~= "string" then return Problemlist.populate() end
7070
71- local mod_time = stats.mtime.sec
72- local curr_time = os.time()
71+ local problems = Problemlist.parse(contents)
72+ if not problems then return Problemlist.populate() end
7373
74- if force or (curr_time - mod_time) > 60 * 60 * 24 * 7 then
75- local spinner = require("leetcode.logger.spinner")
76- local noti = spinner:init("Fetching Problem List", "points")
74+ hist[ftime] = problems
75+ return problems
76+end
7777
78- problems_api.all(function(data)
79- problemlist.write(data)
80- noti:stop("Problems Cache Updated!")
81- end)
82- end
78+function Problemlist.update()
79+ local spinner = require("leetcode.logger.spinner")
80+ local noti = spinner:init("fetching problemlist", "points")
81+
82+ problems_api.all(function(data)
83+ Problemlist.write(data)
84+ noti:stop("problems cache updated!")
85+ end)
8386 end
8487
8588 ---@return lc.Cache.Question
86-function problemlist.get_by_title_slug(title_slug)
87- local problems = problemlist.get()
89+function Problemlist.get_by_title_slug(title_slug)
90+ local problems = Problemlist.get()
8891 return vim.tbl_filter(function(e) return e.title_slug == title_slug end, problems)[1] or {}
8992 end
9093
91----@param problems_str string
94+---@param str string
9295 ---
9396 ---@return lc.Cache.Question[]
94-function problemlist.parse(problems_str)
95- ---@type boolean, lc.Cache.Question[]
96- local ok, problems = pcall(vim.json.decode, problems_str)
97- assert(ok, "Failed to parse problems")
98-
99- return problems
97+function Problemlist.parse(str)
98+ return vim.json.decode(str) ---@diagnostic disable-line
10099 end
101100
102101 ---@param title_slug string
103102 ---@param status "ac" | "notac"
104-function problemlist.change_status(title_slug, status)
105- local problist = problemlist.get()
103+function Problemlist.change_status(title_slug, status)
104+ local problist = Problemlist.get()
106105
107- problemlist.write(vim.tbl_map(function(p)
106+ Problemlist.write(vim.tbl_map(function(p)
108107 if p.title_slug == title_slug then p.status = status end
109108 return p
110109 end, problist))
111110 end
112111
113-function problemlist.delete() file:rm() end
112+function Problemlist.delete()
113+ if not file:exists() then return false end
114+ return pcall(path.rm, file)
115+end
114116
115-return problemlist
117+return Problemlist
+13-2lua/leetcode/config/template.lua
@@ -87,9 +87,20 @@ local M = {
8787 ---@type boolean
8888 image_support = false, -- setting this to `true` will disable question description wrap
8989
90- cn = {
91- translate = true, ---@type boolean
90+ cache = {
91+ ---@type integer
92+ update_interval = 60 * 60 * 24 * 7, -- 7 days
9293 },
94+
95+ plugins = {
96+ cn = {
97+ enabled = true,
98+ translate_problems = true, ---@type boolean
99+ },
100+ },
101+ -- cn = {
102+ -- translate = true, ---@type boolean
103+ -- },
93104 }
94105
95106 return M
+2-1lua/leetcode/pickers/language.lua
@@ -1,6 +1,7 @@
11 local log = require("leetcode.logger")
22 local Question = require("leetcode.ui.question")
33 local utils = require("leetcode.utils")
4+local t = require("leetcode.translator")
45
56 local pickers = require("telescope.pickers")
67 local finders = require("telescope.finders")
@@ -69,7 +70,7 @@ local opts = require("telescope.themes").get_dropdown()
6970 M.pick_lang = function(question, callback)
7071 pickers
7172 .new(opts, {
72- prompt_title = "Available Languages",
73+ prompt_title = t("Available Languages"),
7374 finder = finders.new_table({
7475 results = question.q.code_snippets,
7576 entry_maker = entry_maker,
+4-2lua/leetcode/pickers/question.lua
@@ -1,5 +1,6 @@
11 local log = require("leetcode.logger")
22 local t = require("leetcode.translator")
3+local utils = require("leetcode.utils")
34
45 local Question = require("leetcode.ui.question")
56
@@ -19,7 +20,7 @@ local function question_formatter(question)
1920 return ("%s. %s %s %s"):format(
2021 tostring(question.frontend_id),
2122 question.title,
22- question.sec_title,
23+ question.title_cn,
2324 question.title_slug
2425 )
2526 end
@@ -55,7 +56,8 @@ end
5556 local function display_question(question)
5657 local ac_rate = { ("%.1f%%"):format(question.ac_rate), "leetcode_ref" }
5758 local index = { question.frontend_id .. ".", "leetcode_normal" }
58- local title = { question.title }
59+
60+ local title = { utils.translate(question.title, question.title_cn) }
5961
6062 return unpack({ index, title, ac_rate })
6163 end
+1-0lua/leetcode/translator/init.lua
@@ -36,6 +36,7 @@ local translate = {
3636 ["no hints available"] = "没有提示可用",
3737 ["drawn question is for premium users only. please try again"] = "抽选的问题仅供高级用户使用。请再试一次。",
3838 ["please verify your email address in order to use your account"] = "请验证您的电子邮件地址以便使用您的账户",
39+ ["available languages"] = "可用语言",
3940 ["languages"] = "语言",
4041 ["skills"] = "技能",
4142 ["runtime"] = "时间",
+4-4lua/leetcode/ui/description.lua
@@ -1,5 +1,6 @@
11 local config = require("leetcode.config")
22 local log = require("leetcode.logger")
3+local utils = require("leetcode.utils")
34
45 local img_ok, image_api = pcall(require, "image")
56 local img_sup = img_ok and config.user.image_support
@@ -17,8 +18,6 @@ local Split = require("nui.split")
1718 ---@class lc.Description
1819 ---@field split NuiSplit
1920 ---@field parent lc.Question
20----@field content any
21----@field title any
2221 ---@field layout lc-ui.Layout
2322 ---@field visible boolean
2423 ---@field images table<string, Image>
@@ -125,7 +124,8 @@ function description:populate()
125124
126125 local titleline = NuiLine()
127126 titleline:append(q.frontend_id .. ". ", "leetcode_normal")
128- titleline:append(q.title)
127+
128+ titleline:append(utils.translate(q.title, q.translated_title))
129129
130130 local statsline = NuiLine()
131131 statsline:append(
@@ -155,7 +155,7 @@ function description:populate()
155155 local statscomp = Text:init({ statsline }, { position = "center" })
156156 local linkcomp = Text:init({ linkline }, { position = "center" })
157157
158- local contents = parser:parse(q.content)
158+ local contents = parser:parse(utils.translate(q.content, q.translated_content))
159159
160160 self.layout = Layout:init({
161161 linkcomp,
+14-0lua/leetcode/utils.lua
@@ -141,4 +141,18 @@ function utils.log_err(err)
141141 end
142142 end
143143
144+---@param content string
145+---@param translated_content string
146+function utils.translate(content, translated_content)
147+ if config.is_cn then
148+ if config.user.plugins.cn.translate_problems then
149+ return translated_content or content
150+ else
151+ return content or translated_content
152+ end
153+ else
154+ return content
155+ end
156+end
157+
144158 return utils