[arch-commits] Commit in vim-ansible/trunk (PKGBUILD generate.py)
David Runge
dvzrv at archlinux.org
Mon Jul 13 14:53:47 UTC 2020
Date: Monday, July 13, 2020 @ 14:53:46
Author: dvzrv
Revision: 663413
upgpkg: vim-ansible 2.2-1: Upgrading to 2.2.
Including custom (but offered to upstream) script to generate reproducible
snippets for vim-ultisnips.
Removing patch, that was solely based on the snippets file ending up in the wrong location...
Added:
vim-ansible/trunk/generate.py
Modified:
vim-ansible/trunk/PKGBUILD
-------------+
PKGBUILD | 22 ++--
generate.py | 276 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 287 insertions(+), 11 deletions(-)
Modified: PKGBUILD
===================================================================
--- PKGBUILD 2020-07-13 14:38:19 UTC (rev 663412)
+++ PKGBUILD 2020-07-13 14:53:46 UTC (rev 663413)
@@ -2,8 +2,8 @@
_name=ansible-vim
pkgname=vim-ansible
-pkgver=2.1
-pkgrel=2
+pkgver=2.2
+pkgrel=1
pkgdesc="A vim plugin for syntax highlighting Ansible's common filetypes "
arch=('any')
url="https://github.com/pearofducks/ansible-vim"
@@ -13,9 +13,11 @@
makedepends=('ansible' 'python')
optdepends=('vim-ultisnips: for ansible snippets')
source=("$pkgname-$pkgver.tar.gz::https://github.com/pearofducks/${_name}/archive/${pkgver}.tar.gz"
- "${pkgname}-2.1-fix_ultisnips_generator.patch::https://github.com/pearofducks/ansible-vim/pull/98/commits/82fdc7f56363663a9452cf729398aac04f1f919c.patch")
-sha512sums=('630276ee0587bddea1ece4639e7bb744533dd212d3756f3071a188597e5091d4946536a9c6a4af013b6a3c0391a32d24809a0d10ab3d0b4e2fbaa7f4d89ac232'
- '4e979c12514797af38621031d5a43c1ebbb2fb9e9c18684d75c45d85ca998d61f288c37f246c1b6abca66202c149c2c303ac15a19b110a1ea4ec13068b9c8f5b')
+ "generate.py")
+sha512sums=('73c9147c713b3eb2965f015c76c7c0495bf10518159ea69c16ee65cade2b670b59581b5a335f8e68bc91ff95e9238dd73228963aaa7a8f7d400904a973259f9c'
+ 'e24f8c4cebb0a5f1f9e9bc0b005af1a957d1a986be8746039ca8f73d8b7c4c93ae352822e709c96f71b7726d1a6ca91be14f5553ef0153db9ad23a01b7a285a8')
+b2sums=('98b673265ee4274c285d49ea11d17d4055bbac15d8a0726123c1b75f473e55dc112a5a0bac5a08725a2fc2a6811e33bd8d2cfb2bcea9cd8d1088ef7eba87b6dd'
+ '0938ca439158af536ca04544c2015214b2d33d73dc36c93c0e048704bf71d6b0abc11f91f2c487a828bffe12b9c293587a027ee8883b95a2e411422f33ca4f74')
prepare() {
mv -v "${_name}-$pkgver" "$pkgname-$pkgver"
@@ -24,15 +26,13 @@
# https://github.com/pearofducks/ansible-vim/issues/95
sed -e 's/jinja2/jinja/g' \
-i ftdetect/ansible.vim syntax/ansible.vim
- # fixing ultisnips generator:
- # https://github.com/pearofducks/ansible-vim/issue/96
- # https://github.com/pearofducks/ansible-vim/issue/97
- patch -Np1 -i "../${pkgname}-2.1-fix_ultisnips_generator.patch"
}
build() {
cd "$pkgname-$pkgver"
- python UltiSnips/generate.py --style 'dictionary' --sort
+ # generating a reproducible UltiSnips snippet file:
+ # https://github.com/pearofducks/ansible-vim/pull/105
+ python ../generate.py --style=dictionary
}
package() {
@@ -45,7 +45,7 @@
install -vDm 644 syntax/ansible*.vim \
-t "${pkgdir}/usr/share/vim/vimfiles/syntax/"
install -vDm 644 ansible.snippets \
- -t "${pkgdir}/usr/share/vim/vimfiles/snippets/"
+ -t "${pkgdir}/usr/share/vim/vimfiles/UltiSnips/"
install -vDm 644 README.md -t "${pkgdir}/usr/share/doc/${pkgname}"
install -vDm 644 LICENSE -t "${pkgdir}/usr/share/licenses/${pkgname}"
}
Added: generate.py
===================================================================
--- generate.py (rev 0)
+++ generate.py 2020-07-13 14:53:46 UTC (rev 663413)
@@ -0,0 +1,276 @@
+#!/usr/bin/env python3
+import argparse
+import os
+import os.path
+import ansible.modules
+from ansible.utils.plugin_docs import get_docstring
+from ansible.plugins.loader import fragment_loader
+from typing import Any, List
+
+
+OUTPUT_FILENAME = "ansible.snippets"
+OUTPUT_STYLE = ["multiline", "dictionary"]
+HEADER = [
+ "# NOTE: This file is auto-generated. Modifications may be overwritten.",
+ "priority -50",
+]
+MAX_DESCRIPTION_LENGTH = 512
+
+
+def get_files() -> List[str]:
+ """Return the sorted list of all module files that ansible provides
+
+ Returns
+ -------
+ List[str]
+ A list of strings representing the Python module files provided by
+ Ansible
+ """
+
+ file_names: List[str] = []
+ for root, dirs, files in os.walk(os.path.dirname(ansible.modules.__file__)):
+ file_names += [
+ f"{root}/{file_name}"
+ for file_name in files
+ if file_name.endswith(".py") and not file_name.startswith("__init__")
+ ]
+
+ return sorted(file_names)
+
+
+def get_docstrings(file_names: List[str]) -> List[Any]:
+ """Extract and return a list of docstring information from a list of files
+
+ Parameters
+ ----------
+ file_names: List[str]
+ A list of strings representing file names
+
+ Returns
+ -------
+ List[Any]
+ A list of AnsibleMapping objects, representing docstring information
+ (in dict form), excluding those that are marked as deprecated.
+
+ """
+
+ docstrings: List[Any] = []
+ docstrings += [
+ get_docstring(file_name, fragment_loader)[0] for file_name in file_names
+ ]
+ return [
+ docstring
+ for docstring in docstrings
+ if docstring and not docstring.get("deprecated")
+ ]
+
+
+def escape_strings(escapist: str) -> str:
+ """Escapes strings as required for ultisnips snippets
+
+ Escapes instances of \\, `, {, }, $
+
+ Parameters
+ ----------
+ escapist: str
+ A string to apply string replacement on
+
+ Returns
+ -------
+ str
+ The input string with all defined replacements applied
+ """
+
+ return (
+ escapist.replace("\\", "\\\\")
+ .replace("`", "\`")
+ .replace("{", "\{")
+ .replace("}", "\}")
+ .replace("$", "\$")
+ .replace("\"", "'")
+ )
+
+
+def option_data_to_snippet_completion(option_data: Any) -> str:
+ """Convert Ansible option info into a string used for ultisnip completion
+
+ Converts data about an Ansible module option (retrieved from an
+ AnsibleMapping object) into a formatted string that can be used within an
+ UltiSnip macro.
+
+ Parameters
+ ----------
+ option_data: Any
+ The option parameters
+
+ Returns
+ -------
+ str
+ A string representing one formatted option parameter
+ """
+
+ # join descriptions that are provided as lists and crop them
+ description = escape_strings(
+ "".join(option_data.get("description"))[0:MAX_DESCRIPTION_LENGTH]
+ )
+ default = option_data.get("default")
+ choices = option_data.get("choices")
+ option_type = option_data.get("type")
+
+ # if the option is of type "bool" return "yes" or "no"
+ if option_type and "bool" in option_type:
+ if default in [True, "True", "true", "yes"]:
+ return "true"
+ if default in [False, "False", "false", "no"]:
+ return "false"
+
+ # if there is no default and no choices, return the description
+ if not choices and default is None:
+ return f"# {description}"
+
+ # if there is a default but no choices return the default as string
+ if default is not None and not choices:
+ if len(str(default)) == 0:
+ return '""'
+ else:
+ if isinstance(default, str) and "\\" in default:
+ return f'"{escape_strings(str(default))}"'
+ elif isinstance(default, str):
+ return escape_strings(str(default))
+ else:
+ return default
+
+ # if there is a default and there are choices return the list of choices
+ # with the default prefixed with #
+ if default is not None and choices:
+ if isinstance(default, list):
+ # prefix default choice(s)
+ prefixed_choices = [
+ f"#{choice}" if choice in default else f"{choice}" for choice in choices
+ ]
+ return str(prefixed_choices)
+ else:
+ # prefix default choice
+ prefixed_choices = [
+ f"#{choice}" if str(choice) == str(default) else f"{choice}"
+ for choice in choices
+ ]
+ return "|".join(prefixed_choices)
+
+ # if there are choices but no default, return the choices as pipe separated
+ # list
+ if choices and default is None:
+ return "|".join([str(choice) for choice in choices])
+
+ # as fallback return empty string
+ return ""
+
+
+def module_options_to_snippet_options(module_options: Any) -> List[str]:
+ """Convert module options to UltiSnips snippet options
+
+ Parameters
+ ----------
+ module_options: Any
+ The "options" attribute of an AnsibleMapping object
+
+ Returns
+ -------
+ List[str]
+ A list of strings representing converted options
+ """
+
+ options: List[str] = []
+ delimiter = ": " if args.style == "dictionary" else "="
+
+ if not module_options:
+ return options
+
+ # order by option name
+ module_options = sorted(module_options.items(), key=lambda x: x[0])
+ # order by "required" attribute
+ module_options = sorted(
+ module_options, key=lambda x: x[1].get("required", False), reverse=True
+ )
+
+ # insert an empty option above the list of non-required options
+ for index, (_, option) in enumerate(module_options):
+ if not option.get("required"):
+ if index != 0:
+ module_options.insert(index, (None, None))
+ break
+
+ for index, (name, option_data) in enumerate(module_options, start=1):
+ # insert a line to seperate required/non-required options
+ if not name and not option_data:
+ options += [""]
+ else:
+ # the free_form option in some modules are special
+ if name == "free_form":
+ options += [
+ f"\t${{{index}:{name}{delimiter}{option_data_to_snippet_completion(option_data)}}}"
+ ]
+ else:
+ options += [
+ f"\t{name}{delimiter}${{{index}:{option_data_to_snippet_completion(option_data)}}}"
+ ]
+
+ return options
+
+
+def convert_docstring_to_snippet(docstring: Any) -> List[str]:
+ """Converts data about an Ansible module into an UltiSnips snippet string
+
+ Parameters
+ ----------
+ docstring: Any
+ An AnsibleMapping object representing the docstring for an Ansible
+ module
+
+ Returns
+ -------
+ str
+ A string representing an ultisnips compatible snippet of an Ansible
+ module
+ """
+
+ snippet: List[str] = []
+ snippet_options = "b"
+ module_name = docstring["module"]
+ module_short_description = docstring["short_description"]
+
+ snippet += [f'snippet {module_name} "{escape_strings(module_short_description)}" {snippet_options}']
+ if args.style == "dictionary":
+ snippet += [f"{module_name}:"]
+ else:
+ snippet += [f"{module_name}:{' >' if docstring.get('options') else ''}"]
+ module_options = module_options_to_snippet_options(docstring.get("options"))
+ snippet += module_options
+ snippet += ["endsnippet"]
+
+ return snippet
+
+
+if __name__ == "__main__":
+
+ parser = argparse.ArgumentParser()
+ parser.add_argument(
+ "--output",
+ help=f"Output filename (default: {OUTPUT_FILENAME})",
+ default=OUTPUT_FILENAME,
+ )
+ parser.add_argument(
+ "--style",
+ help=f"YAML format used for snippets (default: {OUTPUT_STYLE[0]})",
+ choices=OUTPUT_STYLE,
+ default=OUTPUT_STYLE[0],
+ )
+ args = parser.parse_args()
+
+ docstrings = get_docstrings(get_files())
+ with open(args.output, "w") as f:
+ f.writelines(f"{header}\n" for header in HEADER)
+ for docstring in docstrings:
+ f.writelines(
+ f"{line}\n" for line in convert_docstring_to_snippet(docstring)
+ )
Property changes on: vim-ansible/trunk/generate.py
___________________________________________________________________
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
More information about the arch-commits
mailing list