Perpustakaan untuk memasukkan python docstring secara otomatis dalam gaya Google

9

Saya mencari paket elisp yang secara otomatis memasukkan metode Python docstring. Saya menemukan paket, yang sangat dekat dengan tujuan saya. Tapi itu dalam teks terstruktur, bukan dalam gaya Google.

sphinx-doc.el https://github.com/naiquevin/sphinx-doc.el

Menjelaskan argumen dalam dokumen (panduan gaya python Google) https://www.chromium.org/chromium-os/python-style-guidelines#TOC-Deskripsi-argument-in-docstrings

Harapan saya adalah ketika saya memanggil M-x sphinx-doc-googledalam fungsi berikut,

def some_function(a, b, c):

Saya butuh hasil seperti ini.

def some_function(a, b, c):
    """
    Args:
        a:
        b:
        c:
    Returns:
    """

Saya tahu ini tidak sulit untuk diterapkan sendiri. Saya hanya ingin menanyakan pertanyaan ini untuk menghindari reinvention.

sy2
sumber
Saya kira tidak ada. Gaya ini tidak persis populer di komunitas Python yang lebih besar sejauh yang saya tahu.
lunaryorn
Terima kasih. Saya pikir ini populer karena pengaturan default aturan penyisipan docstring otomatis PyCharm adalah gaya Google. Saya telah menggunakan teks terstruktur untuk sementara waktu, tetapi itu tidak bisa dibaca oleh manusia. :(
sy2

Jawaban:

9

Saya menggunakan paket yang disebut yasnippet untuk sesuatu yang mirip dengan ini. Setelah beberapa perubahan kecil saya mengadaptasinya untuk menggunakan gaya Google docstring sebagai gantinya:

Google bergaya Python yasnippet

Namun perlu dicatat bahwa ini memerlukan beberapa pengaturan:

Cuplikan itu sendiri perlu menjalankan beberapa kode elisp utilitas untuk menghasilkan teks. Ini biasanya diselesaikan dengan membuat file yang disebut .yas-setup.eldengan kode di dalam python-modedirektori snippet. Namun dimungkinkan juga untuk menempatkan kode di suatu tempat di dalam Anda .emacssebagai gantinya.

Kode untuk cuplikan adalah:

# -*- mode: snippet -*-
# Insert Google style docstring and function definition.
# name: Python Google style Docstring
# key: defg
# type: snippet
# contributor: Xaldew
# --
def ${1:name}($2):
    \"\"\"$3
    ${2:$(python-args-to-google-docstring yas-text t)}
    ${5:Returns:
        $6
}
    \"\"\"
    ${0:$$(let ((beg yas-snippet-beg)
                (end yas-snippet-end))
        (yas-expand-snippet
          (buffer-substring-no-properties beg end) beg end
              (quote ((yas-indent-line nil) (yas-wrap-around-region nil))))
            (delete-trailing-whitespace beg (- end 1)))}

Kode untuk .yas-setup.elis:

(defun python-args-to-google-docstring (text &optional make-fields)
  "Return a reST docstring format for the python arguments in yas-text."
  (let* ((indent (concat "\n" (make-string (current-column) 32)))
         (args (python-split-args text))
     (nr 0)
         (formatted-args
      (mapconcat
       (lambda (x)
         (concat "   " (nth 0 x)
             (if make-fields (format " ${%d:arg%d}" (cl-incf nr) nr))
             (if (nth 1 x) (concat " \(default " (nth 1 x) "\)"))))
       args
       indent)))
    (unless (string= formatted-args "")
      (concat
       (mapconcat 'identity
          (list "" "Args:" formatted-args)
          indent)
       "\n"))))

Catatan yang python-split-argsdisediakan oleh cuplikan standar . Yaitu: https://github.com/AndreaCrotti/yasnippet-snippets/tree/master Namun Anda mendapatkannya secara default saat Anda menginstal paket melalui package.el.

Dengan pengaturan semuanya dengan benar, Anda harus dapat menulis "defg" diikuti oleh Tabuntuk memperluas cuplikan (Lihat gambar sebagai contoh).

Masih ada masalah dengan menggunakan indentasi bersarang di dalam ini, misalnya, di dalam kelas atau sebagai fungsi bersarang. Dalam kasus-kasus itu, docstring secara keliru diberi indentasi waktu tambahan untuk beberapa alasan. Saya akan memperbarui posting ini jika saya berhasil memperbaikinya.

Cuplikan sekarang harus bekerja di dalam lingkup lain dengan melarang yasnippetdari indentasi ekspansi kedua.

Xaldew
sumber
1
Pertanyaan bodoh, tetapi bagaimana saya benar-benar membuat ini berfungsi pada fungsi yang ada? Saya mengetik defgdan itu memberi saya fungsi baru bernama nametanpa argumen, dan saya tidak bisa melihat cara untuk mengotomatiskannya memperbarui docstring ketika saya mengubah fungsi itu. Ketika saya melihat buffer Pesan saya, saya melihat yas--update-mirrors: Wrong type argument: stringp, (python-args-to-google-docstring).
Autumnsault
1
Saya sebenarnya menemukan ini hari ini juga di cuplikan saya, saya pikir itu mungkin bug di yasnippet. Saya harus membuat contoh minimal untuk melaporkannya dengan benar. Mungkin juga potongan rantai dalam mode ini tidak didukung lagi, tapi saya harap bukan itu.
Xaldew
Apakah ini masih menjadi masalah? Saya tidak lagi dapat meniru kesalahan di atas menggunakan Emacs / yasnippet terbaru.
Xaldew
Ya, masih bermasalah. Saya menggunakan emacs 24.5.1 (versi Ubuntu terbaru) dan versi terbaru dari yasnippet.
Autumnsault
1
@AstroFloyd Benar, kode untuk .yas-setup.elharus berakhir di direktori yang sama dengan direktori snippet untuk mode yang sedang aktif. Yang ~/.emacs.d/snippets/python-mode/.yas-setup.eluntuk mode python seperti yang Anda tunjukkan.
Xaldew
3

Seperti yang disebutkan lunaryorn bahwa gaya tidak populer dan tidak ada paket.

Namun ada paket yang disebut sphinx-doc yang akan menghasilkan string doc dalam format sphinx ( demo ).

Anda dapat memodifikasi paket itu untuk menghasilkan string sesuai kebutuhan Anda.

ChillarAnand
sumber
-1

Anda dapat menggunakan kode ini.

Pindahkan kursor pada nama fungsi Anda dan kemudian F9.

 (defun chomp (str)
        "Chomp leading and tailing whitespace from STR."
        (let ((s (if (symbolp str) (symbol-name str) str)))
          (replace-regexp-in-string
           "\\(^[[:space:]\n]*\\|[[:space:]\n]*$\\)" "" s)))
 (defun get-function-definition(sentence)
    (if (string-match "def.*(.*):" sentence)
        (match-string 0 sentence)))
 (defun get-parameters(sentence)
    (setq y (get-function-definition sentence))
    (if y
        (if (string-match "(.*)" y)
            (match-string 0 y))))
 (autoload 'thing-at-point "thingatpt" nil t) ;; build-in librairie
 (defun python-insert-docstring()
        (interactive)
        (setq p (get-parameters (thing-at-point 'sentence)))
        (forward-line 1)
        (insert "    \"\"\"\n")
        (insert "\tArgs:\n")
        (setq params (split-string p "[?\,?\(?\)?\ ]"))
        (while params
          (if (/= (length (chomp (car params))) 0)
              (progn
                (insert "        ")
                (insert (chomp (car params)))
                (insert ": \n")))
          (setq params (cdr params)))
        (insert "    Returns:\n    \"\"\"\n"))
      (global-set-key (kbd "<f9>") 'python-insert-docstring)
Djangoliv
sumber