现在 在改一个模块的功能,实现如下,从 gerrit服务器上拉去 评审数据,数据是json的格式
"currentPatchSet": {
"number": 1,
"revision": "994361fe09fc8dd2c57ff1a7807777d31baf6cbb",
"parents": [
"b16533668dd56cfb8749bbd7ab51c55da5443e56"
],
"ref": "refs/changes/49/305649/1",
"createdOn": 1681976338,
"kind": "REWORK",
"approvals": [
{
"type": "Verified",
"description": "Verified",
"value": "1",
"grantedOn": 1681976600,
},
{
"type": "Code-Review",
"description": "Code-Review",
"value": "1",
"grantedOn": 1681979445,
},
{
"type": "Code-Review",
"description": "Code-Review",
"value": "2",
"grantedOn": 1681979508,
}
],
"sizeInsertions": 16,
"sizeDeletions": 3
},
现在想要做的功能,就是解析里面的type对应的 value,整合成一行显示。
显示规则如下:
如果相同type中 value 值存在负数(-1 -2)则不管是否有+1 +2 都显示 x ,
如果相同type中最大 value = +1 则显示 +1,如果最大value 是+2 则显示 √
如果对应的type,最大值是 0 或没有 则显示空,,
然后把所有的type类型现实在一个行内。期望实现的效果如gerrit 首页显示的样子
现在显示的 样子 是这样,想把 这个review 信息 加在尾巴上,
本人 elisp 实在太菜,有人帮忙指点下吗?
项目地址 https://github.com/darcylee/magit-gerrit/tree/newfeature
解析json 用 (json-read-from-string STRING)
返回的是一个alist.
解析json 倒不是最大的问题,原始项目有解析的方法,主要是 不知道怎么合并和计算 json arry里面取到的值
zsxh
4
简单写了个,不保证边界判断以及性能
{
"approvals": [
{
"type": "acr",
"value": "-1"
},
{
"type": "pc",
"value": "0"
},
{
"type": "Verified",
"value": "1"
},
{
"type": "Code-Review",
"value": "1"
},
{
"type": "Code-Review",
"value": "2"
}
]
}
(defun trans (value-list)
(if (and value-list (length> value-list 0))
(let ((min-v (apply 'min value-list))
(max-v (apply 'max value-list)))
(cond
((< min-v 0) "x")
((= max-v 2) "√")
((= max-v 1) "+1")
(t " ")))
" "))
(defun test ()
(let* ((json (with-temp-buffer
(insert-file-contents "/tmp/test.json")
(json-parse-buffer :object-type 'plist :false-object :json-false :array-type 'list)))
(approvals (plist-get json :approvals))
type-values)
(dolist (elt approvals type-values)
(let* ((type (intern (concat ":" (plist-get elt :type))))
(value (string-to-number (plist-get elt :value)))
(values (or (plist-get type-values type) '())))
(push value values)
(setq type-values (plist-put type-values type values))))
(format "acr:%s cr:%s pc:%s v:%s"
(trans (plist-get type-values :acr))
(trans (plist-get type-values :Code-Review))
(trans (plist-get type-values :pc))
(trans (plist-get type-values :Verified)))))
(test) ;; => "acr:x cr:√ pc: v:+1"
(or (plist-get type-values type) '())
(or X nil)
等同于 X
,可以直接替换为(plist-get type-values type)
。
感谢 ,初步以json 文件读取 解析,可以达到效果了
但是原来代码运行到这里的时候,已经被解析成lisp对象了,如下这种
[
((type . "pc") (description . "PCheck") (value . "-1") (grantedOn . 1679646873) (by (name . "cf") (email . "[email protected]") (username . "cmf")))
((type . "Verified") (description . "Verified") (value . "1") (grantedOn . 1679647276) (by (name . "sv") (email . "[email protected]") (username . "svmm")))
((type . "Verified") (description . "Verified") (value . "1") (grantedOn . 1680272580) (by (name . "name1") (email . "[email protected]") (username . "name1")))
((type . "Code-Review") (description . "Code-Review") (value . "1") (grantedOn . 1679888276) (by (name . "yangx") (email . "[email protected]") (username . "yangx")))
需要怎么替换这个解析过程呢?
(defun trans (type value-list)
(if (and value-list (length> value-list 0))
(let ((min-v (apply 'min value-list))
(max-v (apply 'max value-list))
(t-max-v 1) (t-min-v -1))
(if (string= "Code-Review" type)
(progn (setq t-max-v 2) (setq t-min-v -2)))
(cond
((<= min-v t-min-v) "x")
(t (cond
((>= max-v t-max-v) "√")
((> min-v 0) (format "+%d" min-v))
(t (format "%d" min-v))))
))
" "))
trans 函数 按照gerrit 显示规则改了下
如果value-list
是list的话不需要length>
这部分,非nil就够了。
里面的progn setq
没必要,一个setq可以带多个赋值,另外这可以直接放在底下的cond里。
另外底下的两层cond也可以简化一下。
我看原始工程用的assoc函数,配合 mapc 去遍历这个list,应该是可以 但是不知道要怎么写 ,实在太菜了
用dolist
, 不一定用mapc, 基本的循环语句emacs lisp 都支持。
尴尬 搞半天搞不定
(defun magit-gerrit-wash-approvals-online (approvals)
(let* (type-values)
;; (dolist (labeltuple magit-gerrit-review-labels)
(dolist (approval approvals type-values)
(let* ((type (cdr-safe (assoc 'type approval)))
(value (cdr-safe (assoc 'value approval)))
(values (plist-get type-values type)))
;; (push (and (string= type (car-safe labeltuple)) value) values)
(push value values)
(setq type-values (plist-put type-values type values))))
(format "CR:%-2s PC:%-2s Vr:%-2s"
(magit-gerrit-trans-score "Code-Review" (plist-get type-values :Code-Review))
(magit-gerrit-trans-score "PSTL-Check" (plist-get type-values :PSTL-Check))
(magit-gerrit-trans-score "Verified" (plist-get type-values :Verified))))
;; )
)
(defun magit-gerrit-wash-review ()
(let* ((beg (point))
(jobj (json-read))
(end (point))
(num (cdr-safe (assoc 'number jobj)))
(subj (cdr-safe (assoc 'subject jobj)))
(br (cdr-safe (assoc 'branch jobj)))
(owner (cdr-safe (assoc 'owner jobj)))
(owner-name (cdr-safe (assoc 'name owner)))
;; (owner-email (cdr-safe (assoc 'email owner)))
(patchsets (cdr-safe (assoc 'currentPatchSet jobj)))
(patchset-num (cdr-safe (assoc 'number patchsets)))
(last-update (cdr-safe (assoc 'lastUpdated jobj)))
(size-insert (cdr-safe (assoc 'sizeInsertions patchsets)))
(size-delete (cdr-safe (assoc 'sizeDeletions patchsets)))
;; compare w/t since when false the value is => :json-false
(isdraft (eq (cdr-safe (assoc 'isDraft patchsets)) t))
(approvs (cdr-safe (if (listp patchsets)
(assoc 'approvals patchsets)
(assoc 'approvals (aref patchsets 0)))))
(scoreinfo (magit-gerrit-wash-approvals-online (ensure-list approvs)))
)
(if (and beg end)
(delete-region beg end))
(when (and num subj owner-name)
(magit-insert-section (section subj)
(insert (propertize
(magit-gerrit-pretty-print-review num
patchset-num
subj
owner-name
br
size-insert
size-delete
last-update
;; "CR:√ PC:x Vr:√ "
scoreinfo
isdraft)
'magit-gerrit-jobj
jobj))
(add-text-properties beg (point) (list 'magit-gerrit-jobj jobj)))
t)))
出现错误
Debugger entered--Lisp error: (wrong-type-argument listp [((type . "PSTL-Check") (description . "PSTL-Check") (value . "-1") (grantedOn . 1679646873) (by (name . "gcf") (email . "[email protected]") (username . "gcf"))) ((type . "Verified") (description . "Verified") (value . "1") (grantedOn . 1679647276) (by (name . "ssr") (email . "[email protected]") (username . "ssr"))) ((type . "Verified") (description . "Verified") (value . "1") (grantedOn . 1680272580) (by (name . "smy") (email . "[email protected]") (username . "sunmingyang"))) ((type . "Code-Review") (description . "Code-Review") (value . "1") (grantedOn . 1679888276) (by (name . "yxy") (email . "[email protected]") (username . "yxy")))])
assoc(type [((type . "PSTL-Check") (description . "PSTL-Check") (value . "-1") (grantedOn . 1679646873) (by (name . "gcf") (email . "[email protected]") (username . "gcf"))) ((type . "Verified") (description . "Verified") (value . "1") (grantedOn . 1679647276) (by (name . "ssr") (email . "[email protected]") (username . "ssr"))) ((type . "Verified") (description . "Verified") (value . "1") (grantedOn . 1680272580) (by (name . "smy") (email . "[email protected]") (username . "sunmingyang"))) ((type . "Code-Review") (description . "Code-Review") (value . "1") (grantedOn . 1679888276) (by (name . "yxy") (email . "[email protected]") (username . "yxy")))])
(cdr-safe (assoc 'type approval))
(let* ((type (cdr-safe (assoc 'type approval))) (value (cdr-safe (assoc 'value approval))) (values (plist-get type-values type))) (setq values (cons value values)) (setq type-values (plist-put type-values type values)))
(let ((approval (car --dolist-tail--))) (let* ((type (cdr-safe (assoc 'type approval))) (value (cdr-safe (assoc 'value approval))) (values (plist-get type-values type))) (setq values (cons value values)) (setq type-values (plist-put type-values type values))) (setq --dolist-tail-- (cdr --dolist-tail--)))
(while --dolist-tail-- (let ((approval (car --dolist-tail--))) (let* ((type (cdr-safe (assoc 'type approval))) (value (cdr-safe (assoc 'value approval))) (values (plist-get type-values type))) (setq values (cons value values)) (setq type-values (plist-put type-values type values))) (setq --dolist-tail-- (cdr --dolist-tail--))))
(let ((--dolist-tail-- approvals)) (while --dolist-tail-- (let ((approval (car --dolist-tail--))) (let* ((type (cdr-safe (assoc ... approval))) (value (cdr-safe (assoc ... approval))) (values (plist-get type-values type))) (setq values (cons value values)) (setq type-values (plist-put type-values type values))) (setq --dolist-tail-- (cdr --dolist-tail--)))) type-values)
(let* (type-values) (let ((--dolist-tail-- approvals)) (while --dolist-tail-- (let ((approval (car --dolist-tail--))) (let* ((type (cdr-safe ...)) (value (cdr-safe ...)) (values (plist-get type-values type))) (setq values (cons value values)) (setq type-values (plist-put type-values type values))) (setq --dolist-tail-- (cdr --dolist-tail--)))) type-values) (format "CR:%-2s PC:%-2s Vr:%-2s" (magit-gerrit-trans-score "Code-Review" (plist-get type-values :Code-Review)) (magit-gerrit-trans-score "PSTL-Check" (plist-get type-values :PSTL-Check)) (magit-gerrit-trans-score "Verified" (plist-get type-values :Verified))))
magit-gerrit-wash-approvals-online(([((type . "PSTL-Check") (description . "PSTL-Check") (value . "-1") (grantedOn . 1679646873) (by (name . "gcf") (email . "[email protected]") (username . "gcf"))) ((type . "Verified") (description . "Verified") (value . "1") (grantedOn . 1679647276) (by (name . "ssr") (email . "[email protected]") (username . "ssr"))) ((type . "Verified") (description . "Verified") (value . "1") (grantedOn . 1680272580) (by (name . "smy") (email . "[email protected]") (username . "sunmingyang"))) ((type . "Code-Review") (description . "Code-Review") (value . "1") (grantedOn . 1679888276) (by (name . "yxy") (email . "[email protected]") (username . "yxy")))]))
看报错里说approval
是一个vector啊?看最外面的方括号
cireu
15
[]
是 vector, ()
才是 list, dolist 显然只能操作 list
1 个赞
misaki
16
dolist
的确不能传array,虽然你传的也不是array,在magit-gerrit-wash-review
里,approvs
是array,(ensure-list approvs)
是list of array。不需要用ensure-list
,直接传approvs
。
那么在magit-gerrit-wash-approvals-online
里,approvals
就是一个array,按照你的描述,是一个array of alist。所以dolist
不能用,相对应的,你可以用seq-doseq
或者mapc
。
按照上面给出的trans
,value-list
是list of number,所以value
要用string-to-number
。
由于type
是string,而plist-get
用eq
做comparison,所以(plist-get type-values type)
可能会是nil
。这里可以用type-values
可以用alist,而不是plist。然后用assoc
,或者alist-get
指定testfn。另,push
是destructive的,之后不用再setq
。
所以:
(defun magit-gerrit-wash-approvals-online (approvals)
(let* (type-values)
(seq-doseq (approval approvals)
(let ((type (cdr (assq 'type approval)))
(value (string-to-number (cdr (assq 'value approval)))))
(push value (alist-get type type-values nil nil #'string-equal))))
(format "CR:%-2s PC:%-2s Vr:%-2s"
(magit-gerrit-trans-score "Code-Review"
(cdr (assoc "Code-Review" type-values)))
(magit-gerrit-trans-score "PSTL-Check"
(cdr (assoc "PSTL-Check" type-values)))
(magit-gerrit-trans-score "Verified"
(cdr (assoc "Verified" type-values))))))
1 个赞
底下format那一块有点重复代码,感觉可以用apply + mapcar
改写一下。
厉害了。。学习消化下,现在用了这个代码显示结果是ok了,非常感谢!
后续得再继续优化下
- √、x、-1、+1 这些标志赋上颜色属性,这个可以参考现有的改改。
- “Code-Review”,“PSTL-Check”,“Verified” 这些type,实际来自custom变量magit-gerrit-review-labels里面指定的,相当于可配置用户关心的type,这部分后续还得优化下。
magit-gerrit-review-labels is a variable defined in ‘magit-gerrit.el’.
Its value is
(("Code-Review" "CR")
("Verified" "Ve")
("PSTL-Check" "PC"))
恩,这块是要再改下,具体type也是来自custom变量magit-gerrit-review-labels,不是写死的。
既然是这样的结构,那就是用mapconcat之类的函数,里面用个format写每一个部分的内容