emacs 渐进学习记录,利用yasnippet高效编写python __init__

动机

今天整理 yasnippet 脚本时, 发现一个脚本在写 __init__ 时可以自动按参数生成 docstring, 以下是我测试的例子:

我输入了doc, python, yas 这三个参数, 脚本自动为我准备好了对应的 docstring 中的参数文档

    def __init__(self, doc, a=b, c=d):
        """
        Keyword Arguments:
        doc --
        a   -- (default b)
        c   -- (default d)
        """

然后我就在想可不可以增加这个脚本,让它可以根据输入的参数,自动生成 self.x=x 的语句( 这样做肯定有多余的语句, 但是删除比自己写快多了)

相关资料整理

原 snippet 脚本, 可以看到调用了 python-args-to-docstring

# -*- mode: snippet -*-
# name: init_docstring
# key: init
# group : definitions
# --
def __init__(self$1):
    \"\"\"$2
    ${1:$(python-args-to-docstring)}
    \"\"\"
    $0
 

引用的 elisp 函数

(defun python-split-args (arg-string)
  "Split a python argument string into ((name, default)..) tuples"
  (mapcar (lambda (x)
             (split-string x "[[:blank:]]*=[[:blank:]]*" t))
          (split-string arg-string "[[:blank:]]*,[[:blank:]]*" t)))

(split-string STRING &optional SEPARATORS OMIT-NULLS TRIM)

根据 SEPARATORS(正则表达式) 的匹配位置来分割 STRING, (匹配 SEPARATORS 的部分会移除)分割后的 substring 放在 list 中返回.

这个函数首先会根据 「,」和附近的空格对输入的 string 进行分割得到 list, 之后再对每个元素进行「=」的分割, 得到变量名和对应的默认值(如果存在)

(defun python-args-to-docstring ()
  "return docstring format for the python arguments in yas-text"
  (let* ((indent (concat "\n" (make-string (current-column) 32)))
         (args (python-split-args yas-text))
         (max-len (if args (apply 'max (mapcar (lambda (x) (length (nth 0 x))) args)) 0))
         (formatted-args (mapconcat
                (lambda (x)
                   (concat (nth 0 x) (make-string (- max-len (length (nth 0 x))) ? ) " -- "
                           (if (nth 1 x) (concat "\(default " (nth 1 x) "\)"))))
                args
                indent)))
    (unless (string= formatted-args "")
      (mapconcat 'identity (list "Keyword Arguments:" formatted-args) indent))))

(indent (concat "\n" (make-string (current-column) 32))) 得到的是 \n+多个空格组成的字符串(这也意味着这个脚本比较适合用于空格缩进的python)

args 为处理后得到的 list

max-len 得到了最大变量名的长度, 用于保证 docstring 中的对齐

(formatted-args (mapconcat
                (lambda (x)
                   (concat (nth 0 x) (make-string (- max-len (length (nth 0 x))) ? ) " -- "
                           (if (nth 1 x) (concat "\(default " (nth 1 x) "\)"))))
                args
                indent))

这么长一段都是在生成每个变量对应的文档

在let* 的 body 中添加了docstring 的第一行

结果

yas脚本

# -*- mode: snippet -*-
# name: init_docstring
# key: init
# group : definitions
# --
def __init__(self$1):
    \"\"\"$2
    ${1:$(python-args-to-docstring)}
    \"\"\"
    ${1:$(my-python-args-to-assign)}
    $0

elisp函数

(defun my-python-args-to-assign()
  (let* ((indent (concat "\n" (make-string (current-column) 32)))
         (args (python-split-args yas-text)))
    (mapconcat
     (lambda (x)
       (concat "self." (nth 0 x)  " = " (nth 0 x)))
     args
     indent)))

效果

    def __init__(self, doc, a=b, c=d):
        """
        Keyword Arguments:
        doc --
        a   -- (default b)
        c   -- (default d)
        """
        self.doc = doc
        self.a = a
        self.c = c

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值