Bibliothèque pour insérer automatiquement la docstring python dans le style Google


9

Je cherche un paquet elisp qui insère automatiquement la docstring Python pour une méthode. J'ai trouvé un colis, ce qui est très proche de mon objectif. Mais c'est en texte restructuré, pas en style Google.

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

Décrire les arguments dans docstrings (guide de style Google python) https://www.chromium.org/chromium-os/python-style-guidelines#TOC-Describing-arguments-in-docstrings

Mon attente est lorsque j'appelle M-x sphinx-doc-googledans la fonction suivante,

def some_function(a, b, c):

J'ai besoin d'un résultat comme celui-ci.

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

Je sais que ce n'est pas difficile à mettre en œuvre par moi-même. Je veux juste poser cette question pour éviter la réinvention.


Je ne pense pas qu'il y en ait. Ce style n'est pas exactement populaire dans la plus grande communauté Python pour autant que je sache.
lunaryorn

Merci. Je pensais que c'était populaire car le paramètre par défaut de la règle d'insertion automatique de docstring de PyCharm est le style Google. J'avais utilisé du texte restructuré pendant un certain temps, mais ce n'est pas très lisible par l'homme. :(
sy2

Réponses:


9

J'utilise le package appelé yasnippet pour quelque chose de similaire à cela. Après quelques modifications mineures, je l'ai adapté pour utiliser le style de docstring Google à la place:

Yasnippet en Python de style Google

Notez cependant qu'il nécessite une configuration:

L'extrait lui-même doit exécuter du code elisp utilitaire pour générer le texte. Cela est généralement résolu en créant un fichier appelé .yas-setup.elavec le code dans le python-moderépertoire d'extraits de code . Il est cependant également possible de placer le code quelque part à l'intérieur de votre .emacs.

Le code de l'extrait est:

# -*- 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)))}

Le code pour le .yas-setup.elest:

(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"))))

Notez que cela python-split-argsest fourni par les extraits standard . C'est-à-dire: https://github.com/AndreaCrotti/yasnippet-snippets/tree/master Vous les obtenez cependant par défaut lorsque vous installez le package package.el.

Avec tout configuré correctement, vous devriez pouvoir écrire "defg" suivi Tabde développer l'extrait de code (voir l'image pour un exemple).

Il y a toujours un problème avec l'utilisation de cette indentation imbriquée, par exemple, dans des classes ou en tant que fonctions imbriquées. Dans ces cas, la docstring est indentée par erreur un temps supplémentaire pour une raison quelconque. Je mettrai à jour ce message si je parviens à résoudre ce problème.

L'extrait devrait maintenant fonctionner dans d'autres étendues en interdisant l' yasnippetauto-indentation de la deuxième extension.


1
Question stupide, mais comment faire pour que cela fonctionne sur une fonction existante? Je tape defget cela me donne une nouvelle fonction nommée namesans arguments, et je ne vois aucun moyen d'automatiser la mise à jour de la docstring lorsque je change cette fonction. Quand je regarde mon tampon Messages, je vois yas--update-mirrors: Wrong type argument: stringp, (python-args-to-google-docstring).
Autumnsault

1
J'ai également rencontré cela aujourd'hui dans un autre de mes extraits, je pense que cela peut être un bug yasnippet. Je devrai cependant créer un exemple minimal pour le signaler correctement. Il se peut également que le chaînage d' extraits de cette manière ne soit plus pris en charge, mais j'espère que ce n'est pas le cas.
Xaldew

Est-ce toujours un problème? Je ne suis plus en mesure de reproduire l'erreur ci-dessus en utilisant le dernier Emacs / yasnippet.
Xaldew

Ouais, c'est toujours problématique. J'utilise emacs 24.5.1 (la dernière version d'Ubuntu) et la dernière version de yasnippet.
Autumnsault

1
@AstroFloyd C'est exact, le code de .yas-setup.eldevrait se retrouver dans le même répertoire que le répertoire d'extraits pour le mode actuellement actif. Ce qui est ~/.emacs.d/snippets/python-mode/.yas-setup.elpour le mode python comme vous l'avez souligné.
Xaldew

3

Comme l'a mentionné lunaryorn, ce style n'est pas populaire et il n'y a pas de packages.

Cependant, il existe un package appelé sphinx-doc qui générera une chaîne de doc au format sphinx ( démo ).

Vous pouvez modifier ce package pour générer des chaînes selon vos besoins.


-1

Vous pouvez utiliser ce code.

Déplacez le curseur sur le nom de votre fonction puis sur 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)
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.