From nobody Sat Nov 15 14:49:52 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1750108618; cv=none; d=zohomail.com; s=zohoarc; b=hf8Z60eimIDR4WrPipR+rZgk2pgtdO9OweV5u7llDDAGhDiOcgPb14m/4ew0k4AAeQTlYjXhQjsUPXqSM+bKNGzcCKi+E4VY/+P/MnLCzTCwk56Bl8+2eo0Xq9eKEQHl/lBWTN5zk0H4Y/YOxu4jDp5jC2jT6Pi2CWwsxJTVIjo= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1750108618; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=tcd4dbglLSCOiuJ/nJX96YmhKJtOYx7qlmVMX+T1vX8=; b=W2asiKdw/U5ABFtafeluUKkgYZj7Wy/ufV3/fVxREj4FdHFBaT28ZBH064ggu3xfYGbFTd71KDYad3DKVkLYev0xbYOGUmnZ5C6UJK02c1dcjxWYwe/Xe/zWcDdu6f5mEVmQre4aQRTWVDFvBphkIks3s1MCD7amp73vfejWrFA= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1750108618788475.1635312498179; Mon, 16 Jun 2025 14:16:58 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1uRHBi-0001n2-8x; Mon, 16 Jun 2025 17:16:18 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1uRHBf-0001lQ-TZ for qemu-devel@nongnu.org; Mon, 16 Jun 2025 17:16:15 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1uRHBc-00051E-U5 for qemu-devel@nongnu.org; Mon, 16 Jun 2025 17:16:15 -0400 Received: from mx-prod-mc-04.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-590-C5CTIwZgNNmGsA_S_hDqzQ-1; Mon, 16 Jun 2025 17:16:08 -0400 Received: from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.111]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-04.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id EBE1119560BB for ; Mon, 16 Jun 2025 21:16:07 +0000 (UTC) Received: from jsnow-thinkpadp16vgen1.westford.csb (unknown [10.22.80.82]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 85E3B180035E; Mon, 16 Jun 2025 21:16:05 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1750108570; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding; bh=tcd4dbglLSCOiuJ/nJX96YmhKJtOYx7qlmVMX+T1vX8=; b=Pb4fZ7rCkc2nAdSwF+72dXJOaG/tm6NVwjtPfDVDpc0wSvWRq2aC495Ynpo4uR/QKIgSE/ fkyxW9Oz7dstRORSLJ5/XOJ9TUQvfmK/VBkLyXF2iu2CAJb9tfc6P1mXezKXC61L3fjNRI twMdbgRsgngLHWIeHQXJD1sMZJ04ZYY= X-MC-Unique: C5CTIwZgNNmGsA_S_hDqzQ-1 X-Mimecast-MFC-AGG-ID: C5CTIwZgNNmGsA_S_hDqzQ_1750108568 From: John Snow To: qemu-devel@nongnu.org, armbru@redhat.com, eblake@redhat.com Cc: John Snow Subject: [PATCH] docs/contrib: add insert_crossrefs script Date: Mon, 16 Jun 2025 17:16:04 -0400 Message-ID: <20250616211604.1399219-1-jsnow@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.111 Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=170.10.133.124; envelope-from=jsnow@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -39 X-Spam_score: -4.0 X-Spam_bar: ---- X-Spam_report: (-4.0 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-1.892, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1750108621534116600 Content-Type: text/plain; charset="utf-8" This isn't really meant for inclusion as it's a bit of a hackjob, but I figured it would be best to share it in some form or another to serve as a basis for a kind of meta-review of the crossreferenceification series. This script is designed to convert 'name', "name", name, and @name instances in qapi/*.json files to `name` for the purposes of cross-referencing commands, events, and data types in the generated HTML documentation. It is specifically tuned for our QAPI files and is not suitable for running on generic rST source files. It can likely be made to operate on QEMU guest agent or other qapi JSON files with some edits to which files its opening. Navigate to your qemu/qapi/ directory and run this script with "python insert_crossrefs.py" and it'll handle the rest. Definitely don't run it in a non-git-controlled folder, it edits your source files. (Yes, in polishing this script, I found a few instances of cross-references I missed in my v1 series. I figure I'll let us discuss the conversion a bit before I send out a v2 patchbomb.) Signed-off-by: John Snow --- contrib/autoxref/insert_crossrefs.py | 69 ++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 contrib/autoxref/insert_crossrefs.py diff --git a/contrib/autoxref/insert_crossrefs.py b/contrib/autoxref/insert= _crossrefs.py new file mode 100644 index 00000000000..399dd7524c2 --- /dev/null +++ b/contrib/autoxref/insert_crossrefs.py @@ -0,0 +1,69 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +import os +import re +import sys + +if not os.path.exists("qapi-schema.json"): + raise Exception( + "This script was meant to be run from the qemu.git/qapi directory." + ) +sys.path.append("../scripts/") + +from qapi.schema import QAPISchema, QAPISchemaDefinition + +# Adjust this global to exclude certain tokens from being xreffed. +SKIP_TOKENS =3D ('String', 'stop', 'transaction', 'eject', 'migrate', 'qui= t') + +print("Compiling schema to build list of reference-able entities ...", end= =3D'') +tokens =3D [] +schema =3D QAPISchema("qapi-schema.json") +for ent in schema._entity_list: + if isinstance(ent, QAPISchemaDefinition) and not ent.is_implicit(): + if ent.name not in SKIP_TOKENS: + tokens.append(ent.name) +print("OK") + +patt_names =3D r'(' + '|'.join(tokens) + r')' + +# catch 'token' and "token" specifically +patt =3D re.compile(r'([\'"]|``)' + patt_names + r'\1') +# catch naked instances of token, excluding those where prefixed or +# suffixed by a quote, dash, or word character. Exclude "@" references +# specifically to handle them elsewhere. Exclude matches, as +# these are explicit cross-reference targets. +patt2 =3D r"(?])" +# catch @references. prohibit when followed by ":" to exclude members +# whose names happen to match xreffable entities. +patt3 =3D r"@" + patt_names + r"(?![-\w:])" + + + + +for file in os.scandir(): + outlines =3D [] + if not file.name.endswith(".json"): + continue + print(f"Scanning {file.name} ...") + with open(file.name) as searchfile: + block_start =3D False + for line in searchfile: + # Don't mess with the start of doc blocks. + # We don't want to convert "# @name:" to a reference! + if block_start and line.startswith('# @'): + outlines.append(line) + continue + block_start =3D bool(line.startswith('##')) + + # Don't mess with anything outside of comment blocks, + # and don't mess with example blocks. We use five spaces + # as a heuristic for detecting example blocks. It's not perfec= t, + # but it seemingly does the job well. + if line.startswith('# ') and not line.startswith('# '): + line =3D re.sub(patt, r'`\2`', line) + line =3D re.sub(patt2, r'`\1`', line) + line =3D re.sub(patt3, r'`\1`', line) + outlines.append(line) + with open(file.name, "w") as outfile: + for line in outlines: + outfile.write(line) --=20 2.48.1