generated from nvdaaddons/AddonTemplate
-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 8eb49d4
Showing
10 changed files
with
748 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
# Set default behaviour, in case users don't have core.autocrlf set. | ||
* text=auto | ||
|
||
# Try to ensure that po files in the repo does not include | ||
# source code line numbers. | ||
# Every person expected to commit po files should change their personal config file as described here: | ||
# https://mail.gnome.org/archives/kupfer-list/2010-June/msg00002.html | ||
*.po filter=cleanpo |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
addon/doc/*.css | ||
addon/doc/en/ | ||
*_docHandler.py | ||
*.html | ||
*.ini | ||
*.mo | ||
*.pot | ||
*.py[co] | ||
*.nvda-addon | ||
.sconsign.dblite |
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
# -*- coding: UTF-8 -*- | ||
|
||
# Build customizations | ||
# Change this file instead of sconstruct or manifest files, whenever possible. | ||
|
||
# Full getext (please don't change) | ||
_ = lambda x : x | ||
|
||
# Add-on information variables | ||
addon_info = { | ||
# for previously unpublished addons, please follow the community guidelines at: | ||
# https://bitbucket.org/nvdaaddonteam/todo/raw/master/guidelines.txt | ||
# add-on Name, internal for nvda | ||
"addon_name" : "addonTemplate", | ||
# Add-on summary, usually the user visible name of the addon. | ||
# Translators: Summary for this add-on to be shown on installation and add-on information. | ||
"addon_summary" : _("Add-on user visible name"), | ||
# Add-on description | ||
# Translators: Long description to be shown for this add-on on add-on information from add-ons manager | ||
"addon_description" : _("""Description for the add-on. | ||
It can span multiple lines."""), | ||
# version | ||
"addon_version" : "x.y", | ||
# Author(s) | ||
"addon_author" : u"name <[email protected]>", | ||
# URL for the add-on documentation support | ||
"addon_url" : None, | ||
# Documentation file name | ||
"addon_docFileName" : "readme.html", | ||
# Minimum NVDA version supported (e.g. "2018.3.0", minor version is optional) | ||
"addon_minimumNVDAVersion" : None, | ||
# Last NVDA version supported/tested (e.g. "2018.4.0", ideally more recent than minimum version) | ||
"addon_lastTestedNVDAVersion" : None, | ||
# Add-on update channel (default is None, denoting stable releases, and for development releases, use "dev"; do not change unless you know what you are doing) | ||
"addon_updateChannel" : None, | ||
} | ||
|
||
|
||
import os.path | ||
|
||
# Define the python files that are the sources of your add-on. | ||
# You can use glob expressions here, they will be expanded. | ||
pythonSources = [] | ||
|
||
# Files that contain strings for translation. Usually your python sources | ||
i18nSources = pythonSources + ["buildVars.py"] | ||
|
||
# Files that will be ignored when building the nvda-addon file | ||
# Paths are relative to the addon directory, not to the root directory of your addon sources. | ||
excludedFiles = [] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
summary = "{addon_summary}" | ||
description = """{addon_description}""" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
name = {addon_name} | ||
summary = "{addon_summary}" | ||
description = """{addon_description}""" | ||
author = "{addon_author}" | ||
url = {addon_url} | ||
version = {addon_version} | ||
docFileName = {addon_docFileName} | ||
minimumNVDAVersion = {addon_minimumNVDAVersion} | ||
lastTestedNVDAVersion = {addon_lastTestedNVDAVersion} | ||
updateChannel = {addon_updateChannel} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
# NVDA Add-on Scons Template # | ||
|
||
This package contains a basic template structure for NVDA add-on development, building, distribution and localization. | ||
For details about NVDA add-on development please see the [NVDA Developer Guide](http://www.nvda-project.org/documentation/developerGuide.html). | ||
The NVDA addon development/discussion list [is here](https://nvda-addons.groups.io/g/nvda-addons) | ||
|
||
Copyright (C) 2012-2019 nvda addon team contributors. | ||
|
||
This package is distributed under the terms of the GNU General Public License, version 2 or later. Please see the file COPYING.txt for further details. | ||
|
||
## Features | ||
|
||
This template provides the following features you can use to help NVDA add-on development: | ||
|
||
* Automatic add-on package creation, with naming and version loaded from a centralized build variables file (buildVars.py). | ||
* Manifest file creation using a template (manifest.ini.tpl). Build variables are replaced on this template. | ||
* Compilation of gettext mo files before distribution, when needed. | ||
* To generate a gettext pot file, please run scons pot. A **addon-name.pot** file will be created with all gettext messages for your add-on. You need to check the buildVars.i18nSources variable to comply with your requirements. | ||
* Automatic generation of manifest localization files directly from gettext po files. Please make sure buildVars.py is included in i18nFiles. | ||
* Automatic generation of HTML documents from markdown (.md) files, to manage documentation in different languages. | ||
|
||
## Requirements | ||
|
||
You need the following software to use this code for your NVDA add-ons development: | ||
|
||
* a Python distribution (2.7 or greater is recommended). Check the [Python Website](http://www.python.org) for Windows Installers. | ||
* Scons - [Website](http://www.scons.org/) - version 2.1.0 or greater. Install it using **easy_install** or grab an windows installer from the website. | ||
* GNU Gettext tools, if you want to have localization support for your add-on - Recommended. Any Linux distro or cygwin have those installed. You can find windows builds [here](http://gnuwin32.sourceforge.net/downlinks/gettext.php). | ||
* Markdown-2.0.1 or greater, if you want to convert documentation files to HTML documents. You can [Download Markdown-2.0.1 installer for Windows](https://pypi.python.org/pypi/Markdown/2.0.1) or get it using `easy_install markdown`. | ||
|
||
## Usage | ||
|
||
### To create a new NVDA add-on, taking advantage of this template: | ||
|
||
1. Create an empty folder to hold the files for your add-on. | ||
2. Copy the **site_scons** folder, and the following files, into your new empty folder: **buildVars.py**, **manifest.ini.tpl**, **manifest-translated.ini.tpl**, **sconstruct**, **.gitignore**, and **.gitattributes** | ||
3. Create an **addon** folder inside your new folder. Inside the **addon* folder, create needed folders for the add-on modules (e.g. appModules, synthDrivers, etc.). An add-on may have one or more module folders. | ||
4. In the **buildVars.py** file, change variable **addon_info** with your add-on's information (name, summary, description, version, author and url). | ||
5. Put your code in the usual folders for NVDA extension, under the **addon** folder. For instance: globalPlugins, synthDrivers, etc. | ||
6. Gettext translations must be placed into addon\locale\<lang>/LC_MESSAGES\nvda.po. | ||
|
||
### To manage documentation files for your addon: | ||
|
||
1. Copy the **readme.md** file for your add-on to the first created folder, where you copied **buildVars.py**. You can also copy **style.css** to improve the presentation of HTML documents. | ||
2. Documentation files (named **readme.md**) must be placed into addon\doc\<lang>/. | ||
|
||
+### To package the add-on for distribution: | ||
|
||
1. Open a command line, change to the folder that has the **sconstruct** file (usually the root of your add-on development folder) and run the **scons** command. The created add-on, if there were no errors, is placed in the current directory. | ||
2. You can further customize variables in the **buildVars.py** file. | ||
|
||
Note that this template only provides a basic add-on structure and build infrastructure. You may need to adapt it for your specific needs. | ||
|
||
If you have any issues please use the NVDA addon list mentioned above. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,195 @@ | ||
# NVDA add-on template SCONSTRUCT file | ||
#Copyright (C) 2012, 2014 Rui Batista <[email protected]> | ||
#This file is covered by the GNU General Public License. | ||
#See the file COPYING.txt for more details. | ||
|
||
import codecs | ||
import gettext | ||
import os | ||
import os.path | ||
import zipfile | ||
import sys | ||
sys.dont_write_bytecode = True | ||
|
||
import buildVars | ||
|
||
def md2html(source, dest): | ||
import markdown | ||
lang = os.path.basename(os.path.dirname(source)).replace('_', '-') | ||
title="{addonSummary} {addonVersion}".format(addonSummary=buildVars.addon_info["addon_summary"], addonVersion=buildVars.addon_info["addon_version"]) | ||
headerDic = { | ||
"[[!meta title=\"": "# ", | ||
"\"]]": " #", | ||
} | ||
with codecs.open(source, "r", "utf-8") as f: | ||
mdText = f.read() | ||
for k, v in headerDic.items(): | ||
mdText = mdText.replace(k, v, 1) | ||
htmlText = markdown.markdown(mdText) | ||
with codecs.open(dest, "w", "utf-8") as f: | ||
f.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + | ||
"<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\"\n" + | ||
" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n" + | ||
"<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"%s\" lang=\"%s\">\n" % (lang, lang) + | ||
"<head>\n" + | ||
"<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\"/>\n" + | ||
"<link rel=\"stylesheet\" type=\"text/css\" href=\"../style.css\" media=\"screen\"/>\n" + | ||
"<title>%s</title>\n" % title + | ||
"</head>\n<body>\n" | ||
) | ||
f.write(htmlText) | ||
f.write("\n</body>\n</html>") | ||
|
||
def mdTool(env): | ||
mdAction=env.Action( | ||
lambda target,source,env: md2html(source[0].path, target[0].path), | ||
lambda target,source,env: 'Generating %s'%target[0], | ||
) | ||
mdBuilder=env.Builder( | ||
action=mdAction, | ||
suffix='.html', | ||
src_suffix='.md', | ||
) | ||
env['BUILDERS']['markdown']=mdBuilder | ||
|
||
vars = Variables() | ||
vars.Add("version", "The version of this build", buildVars.addon_info["addon_version"]) | ||
vars.Add(BoolVariable("dev", "Whether this is a daily development version", False)) | ||
vars.Add("channel", "Update channel for this build", buildVars.addon_info["addon_updateChannel"]) | ||
|
||
env = Environment(variables=vars, ENV=os.environ, tools=['gettexttool', mdTool]) | ||
env.Append(**buildVars.addon_info) | ||
|
||
if env["dev"]: | ||
import datetime | ||
buildDate = datetime.datetime.now() | ||
year, month, day = str(buildDate.year), str(buildDate.month), str(buildDate.day) | ||
env["addon_version"] = "".join([year, month.zfill(2), day.zfill(2), "-dev"]) | ||
env["channel"] = "dev" | ||
elif env["version"] is not None: | ||
env["addon_version"] = env["version"] | ||
if "channel" in env and env["channel"] is not None: | ||
env["addon_updateChannel"] = env["channel"] | ||
|
||
addonFile = env.File("${addon_name}-${addon_version}.nvda-addon") | ||
|
||
def addonGenerator(target, source, env, for_signature): | ||
action = env.Action(lambda target, source, env : createAddonBundleFromPath(source[0].abspath, target[0].abspath) and None, | ||
lambda target, source, env : "Generating Addon %s" % target[0]) | ||
return action | ||
|
||
def manifestGenerator(target, source, env, for_signature): | ||
action = env.Action(lambda target, source, env : generateManifest(source[0].abspath, target[0].abspath) and None, | ||
lambda target, source, env : "Generating manifest %s" % target[0]) | ||
return action | ||
|
||
def translatedManifestGenerator(target, source, env, for_signature): | ||
dir = os.path.abspath(os.path.join(os.path.dirname(str(source[0])), "..")) | ||
lang = os.path.basename(dir) | ||
action = env.Action(lambda target, source, env : generateTranslatedManifest(source[1].abspath, lang, target[0].abspath) and None, | ||
lambda target, source, env : "Generating translated manifest %s" % target[0]) | ||
return action | ||
|
||
env['BUILDERS']['NVDAAddon'] = Builder(generator=addonGenerator) | ||
env['BUILDERS']['NVDAManifest'] = Builder(generator=manifestGenerator) | ||
env['BUILDERS']['NVDATranslatedManifest'] = Builder(generator=translatedManifestGenerator) | ||
|
||
def createAddonHelp(dir): | ||
docsDir = os.path.join(dir, "doc") | ||
if os.path.isfile("style.css"): | ||
cssPath = os.path.join(docsDir, "style.css") | ||
cssTarget = env.Command(cssPath, "style.css", Copy("$TARGET", "$SOURCE")) | ||
env.Depends(addon, cssTarget) | ||
if os.path.isfile("readme.md"): | ||
readmePath = os.path.join(docsDir, "en", "readme.md") | ||
readmeTarget = env.Command(readmePath, "readme.md", Copy("$TARGET", "$SOURCE")) | ||
env.Depends(addon, readmeTarget) | ||
|
||
def createAddonBundleFromPath(path, dest): | ||
""" Creates a bundle from a directory that contains an addon manifest file.""" | ||
basedir = os.path.abspath(path) | ||
with zipfile.ZipFile(dest, 'w', zipfile.ZIP_DEFLATED) as z: | ||
# FIXME: the include/exclude feature may or may not be useful. Also python files can be pre-compiled. | ||
for dir, dirnames, filenames in os.walk(basedir): | ||
relativePath = os.path.relpath(dir, basedir) | ||
for filename in filenames: | ||
pathInBundle = os.path.join(relativePath, filename) | ||
absPath = os.path.join(dir, filename) | ||
if pathInBundle not in buildVars.excludedFiles: z.write(absPath, pathInBundle) | ||
return dest | ||
|
||
def generateManifest(source, dest): | ||
addon_info = buildVars.addon_info | ||
addon_info["addon_version"] = env["addon_version"] | ||
addon_info["addon_updateChannel"] = env["addon_updateChannel"] | ||
with codecs.open(source, "r", "utf-8") as f: | ||
manifest_template = f.read() | ||
manifest = manifest_template.format(**addon_info) | ||
with codecs.open(dest, "w", "utf-8") as f: | ||
f.write(manifest) | ||
|
||
def generateTranslatedManifest(source, language, out): | ||
# No ugettext in Python 3. | ||
if sys.version_info.major == 2: | ||
_ = gettext.translation("nvda", localedir=os.path.join("addon", "locale"), languages=[language]).ugettext | ||
else: | ||
_ = gettext.translation("nvda", localedir=os.path.join("addon", "locale"), languages=[language]).gettext | ||
vars = {} | ||
for var in ("addon_summary", "addon_description"): | ||
vars[var] = _(buildVars.addon_info[var]) | ||
with codecs.open(source, "r", "utf-8") as f: | ||
manifest_template = f.read() | ||
result = manifest_template.format(**vars) | ||
with codecs.open(out, "w", "utf-8") as f: | ||
f.write(result) | ||
|
||
def expandGlobs(files): | ||
return [f for pattern in files for f in env.Glob(pattern)] | ||
|
||
addon = env.NVDAAddon(addonFile, env.Dir('addon')) | ||
|
||
langDirs = [f for f in env.Glob(os.path.join("addon", "locale", "*"))] | ||
|
||
#Allow all NVDA's gettext po files to be compiled in source/locale, and manifest files to be generated | ||
for dir in langDirs: | ||
poFile = dir.File(os.path.join("LC_MESSAGES", "nvda.po")) | ||
moFile=env.gettextMoFile(poFile) | ||
env.Depends(moFile, poFile) | ||
translatedManifest = env.NVDATranslatedManifest(dir.File("manifest.ini"), [moFile, os.path.join("manifest-translated.ini.tpl")]) | ||
env.Depends(translatedManifest, ["buildVars.py"]) | ||
env.Depends(addon, [translatedManifest, moFile]) | ||
|
||
pythonFiles = expandGlobs(buildVars.pythonSources) | ||
for file in pythonFiles: | ||
env.Depends(addon, file) | ||
|
||
#Convert markdown files to html | ||
createAddonHelp("addon") # We need at least doc in English and should enable the Help button for the add-on in Add-ons Manager | ||
for mdFile in env.Glob(os.path.join('addon', 'doc', '*', '*.md')): | ||
htmlFile = env.markdown(mdFile) | ||
env.Depends(htmlFile, mdFile) | ||
env.Depends(addon, htmlFile) | ||
|
||
# Pot target | ||
i18nFiles = expandGlobs(buildVars.i18nSources) | ||
gettextvars={ | ||
'gettext_package_bugs_address' : '[email protected]', | ||
'gettext_package_name' : buildVars.addon_info['addon_name'], | ||
'gettext_package_version' : buildVars.addon_info['addon_version'] | ||
} | ||
|
||
pot = env.gettextPotFile("${addon_name}.pot", i18nFiles, **gettextvars) | ||
env.Alias('pot', pot) | ||
env.Depends(pot, i18nFiles) | ||
mergePot = env.gettextMergePotFile("${addon_name}-merge.pot", i18nFiles, **gettextvars) | ||
env.Alias('mergePot', mergePot) | ||
env.Depends(mergePot, i18nFiles) | ||
|
||
# Generate Manifest path | ||
manifest = env.NVDAManifest(os.path.join("addon", "manifest.ini"), os.path.join("manifest.ini.tpl")) | ||
# Ensure manifest is rebuilt if buildVars is updated. | ||
env.Depends(manifest, "buildVars.py") | ||
|
||
env.Depends(addon, manifest) | ||
env.Default(addon) | ||
env.Clean (addon, ['.sconsign.dblite', 'addon/doc/en/']) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
""" This tool allows generation of gettext .mo compiled files, pot files from source code files | ||
and pot files for merging. | ||
Three new builders are added into the constructed environment: | ||
- gettextMoFile: generates .mo file from .pot file using msgfmt. | ||
- gettextPotFile: Generates .pot file from source code files. | ||
- gettextMergePotFile: Creates a .pot file appropriate for merging into existing .po files. | ||
To properly configure get text, define the following variables: | ||
- gettext_package_bugs_address | ||
- gettext_package_name | ||
- gettext_package_version | ||
""" | ||
from SCons.Action import Action | ||
|
||
def exists(env): | ||
return True | ||
|
||
XGETTEXT_COMMON_ARGS = ( | ||
"--msgid-bugs-address='$gettext_package_bugs_address' " | ||
"--package-name='$gettext_package_name' " | ||
"--package-version='$gettext_package_version' " | ||
"-c -o $TARGET $SOURCES" | ||
) | ||
|
||
def generate(env): | ||
env.SetDefault(gettext_package_bugs_address="[email protected]") | ||
env.SetDefault(gettext_package_name="") | ||
env.SetDefault(gettext_package_version="") | ||
|
||
env['BUILDERS']['gettextMoFile']=env.Builder( | ||
action=Action("msgfmt -o $TARGET $SOURCE", "Compiling translation $SOURCE"), | ||
suffix=".mo", | ||
src_suffix=".po" | ||
) | ||
|
||
env['BUILDERS']['gettextPotFile']=env.Builder( | ||
action=Action("xgettext " + XGETTEXT_COMMON_ARGS, "Generating pot file $TARGET"), | ||
suffix=".pot") | ||
|
||
env['BUILDERS']['gettextMergePotFile']=env.Builder( | ||
action=Action("xgettext " + "--omit-header --no-location " + XGETTEXT_COMMON_ARGS, | ||
"Generating pot file $TARGET"), | ||
suffix=".pot") | ||
|
Oops, something went wrong.