Commit 833f753e authored by ChangZhuo Chen's avatar ChangZhuo Chen

Imported Upstream version 0.1.1

parent 5838a268
image: jkozera/qt5-mingw32 # Dockerfile available at
- wine regedit /root/qttemp.reg # doesn't work for some reason in Dockerfile's
- cd zeal
- date +%Y%m%d > VERSION
# a bit ugly version updating:
- grep -v ZEAL_VERSION >
- mv
- echo 'DEFINES += ZEAL_VERSION=\\\"'`cat VERSION`'\\\"' >>
- wine qmake
- wine mingw32-make
- mkdir zeal-$(cat VERSION)
- cp release/zeal.exe zeal-$(cat VERSION)
- cp -r icons zeal-$(cat VERSION)
- wget -O zeal-$(cat VERSION)/bsdtar.exe
- wget -O zeal-$(cat VERSION)/bzip2.dll
- wget -O zeal-$(cat VERSION)/zlib1.dll
- mkdir zeal-$(cat VERSION)/imageformats
- mkdir zeal-$(cat VERSION)/platforms
- mkdir zeal-$(cat VERSION)/sqldrivers
- cp /root/Tools/mingw482_32/opt/bin/ssleay32.dll zeal-$(cat VERSION)
- cp /root/Tools/mingw482_32/opt/bin/libeay32.dll zeal-$(cat VERSION)
- cp /root/5.3/mingw482_32/plugins/imageformats/qico.dll zeal-$(cat VERSION)/imageformats
- cp /root/5.3/mingw482_32/plugins/platforms/qwindows.dll zeal-$(cat VERSION)/platforms
- cp /root/5.3/mingw482_32/plugins/sqldrivers/qsqlite.dll zeal-$(cat VERSION)/sqldrivers
- cp /root/5.3/mingw482_32/bin/libstdc++-6.dll zeal-$(cat VERSION)
- cp /root/5.3/mingw482_32/bin/libgcc_s_dw2-1.dll zeal-$(cat VERSION)
- cp /root/5.3/mingw482_32/bin/libwinpthread-1.dll zeal-$(cat VERSION)
- cp /root/5.3/mingw482_32/bin/icu*.dll zeal-$(cat VERSION)
- for l in Core Gui Multimedia MultimediaWidgets Network OpenGL Qml Quick Sql WebKit WebKitWidgets Widgets Xml Positioning PrintSupport Sensors; do cp /root/5.3/mingw482_32/bin/Qt5$l.dll zeal-$(cat VERSION); done
- zip -r zeal-$(cat VERSION).zip zeal-$(cat VERSION)
- mkdir win32_release
- mv zeal-$(cat VERSION).zip win32_release
branch: master
- win32_release/
tag: $(cat VERSION)
token: $$github_token
user: jkozera
repo: zeal
# C++ objects and libs
# Qt-es
# QtCreator
#QtCtreator Qml
build_image: shippableimages/ubuntu1404_base
cache: true
- dpkg --add-architecture i386
- shippable_retry sudo apt-get -y -q update
- export QT_DIR=$HOME/qt/5.4/mingw491_32
- shippable_retry sudo apt-get -y -q install --no-install-recommends wine p7zip-full ca-certificates curl
# Install Qt
- bash -c '[ -d $HOME/qt/Tools ] || mkdir -p $HOME/qt/OUT'
- bash -c '[ -d $HOME/qt/Tools ] || curl -Lso $HOME/qt/qt.exe'
- bash -c '[ -d $HOME/qt/Tools ] || wine $HOME/qt/qt.exe --dump-binary-data -o $HOME/qt/OUT'
- bash -c '[ -d $HOME/qt/Tools ] || 7z x $HOME/qt/OUT/qt.54.win32_mingw491/5.4.0-1i686-4.9.1-release-posix-dwarf-rt_v3-rev2-runtime.7z -o$HOME/qt'
- bash -c '[ -d $HOME/qt/Tools ] || 7z x $HOME/qt/OUT/qt.54.win32_mingw491/5.4.0-1icu_53_1_mingw_builds_4_9_1_posix_dwarf_32.7z -o$HOME/qt'
- bash -c '[ -d $HOME/qt/Tools ] || 7z x $HOME/qt/OUT/qt.54.win32_mingw491/5.4.0-1qt5_addons.7z -o$HOME/qt'
- bash -c '[ -d $HOME/qt/Tools ] || 7z x $HOME/qt/OUT/qt.54.win32_mingw491/5.4.0-1qt5_essentials.7z -o$HOME/qt'
- bash -c '[ -d $HOME/qt/Tools ] || 7z x $HOME/qt/OUT/ -o$HOME/qt'
- rm -rf $HOME/qt/OUT
- rm -f $HOME/qt/qt.exe
# Install libarchive headers and library
- bash -c '[ -f $HOME/qt/Tools/mingw491_32/i686-w64-mingw32/include/archive.h ] || curl -LOs'
- bash -c '[ -f $HOME/qt/Tools/mingw491_32/i686-w64-mingw32/include/archive.h ] || 7z x libarchive-3.1.2-win32-mingw491.7z -o$HOME/qt/Tools/mingw491_32/i686-w64-mingw32'
- rm -f libarchive-3.1.2-win32-mingw491.7z
# Setup environment
- echo '[Paths]' > $QT_DIR/bin/qt.conf
- echo 'Prefix=..' >> $QT_DIR/bin/qt.conf
- echo '[HKEY_CURRENT_USER\Environment]' > $HOME/qt/temp.reg
- echo '"QMAKESPEC"="BASEDIR\\5.4\\mingw491_32\\mkspecs\\win32-g++"' >> $HOME/qt/temp.reg
- echo '"QTDIR"="BASEDIR\\5.4\\mingw491_32"' >> $HOME/qt/temp.reg
- echo '"PATH"="BASEDIR\\Tools\\mingw491_32\\libexec\\gcc\\i686-w64-mingw32;BASEDIR\\Tools\\mingw491_32\\bin;BASEDIR\\5.4\\mingw491_32\\bin"' >> $HOME/qt/temp.reg
- sed -i "s.BASEDIR.Z:$HOME/qt.g" $HOME/qt/temp.reg
- sed -i 's./.\\\\.g' $HOME/qt/temp.reg
- wine regedit $HOME/qt/temp.reg
- export ZEAL_VERSION=`date +%Y%m%d`
- export ZEAL_DIR=zeal-$ZEAL_VERSION
- wine qmake
- wine mingw32-make
# Prepare ZIP package
- mkdir $ZEAL_DIR
- cp bin/zeal.exe $ZEAL_DIR
- for dir in imageformats platforms sqldrivers; do mkdir $ZEAL_DIR/$dir; done
- cp $HOME/qt/Tools/mingw491_32/opt/bin/ssleay32.dll $ZEAL_DIR
- cp $HOME/qt/Tools/mingw491_32/opt/bin/libeay32.dll $ZEAL_DIR
- for l in gif ico jpeg tiff; do cp $QT_DIR/plugins/imageformats/q$l.dll $ZEAL_DIR/imageformats; done
- cp $QT_DIR/plugins/platforms/qwindows.dll $ZEAL_DIR/platforms
- cp $QT_DIR/plugins/sqldrivers/qsqlite.dll $ZEAL_DIR/sqldrivers
- cp $QT_DIR/bin/libstdc++-6.dll $ZEAL_DIR
- cp $QT_DIR/bin/libgcc_s_dw2-1.dll $ZEAL_DIR
- cp $QT_DIR/bin/libwinpthread-1.dll $ZEAL_DIR
- cp $QT_DIR/bin/icu*.dll $ZEAL_DIR
- for l in Core Gui Multimedia MultimediaWidgets Network OpenGL Qml Quick Sql WebKit WebKitWidgets WebChannel Widgets Positioning PrintSupport Sensors; do cp $QT_DIR/bin/Qt5$l.dll $ZEAL_DIR; done
# Pack everything into ZIP
- 7z a -mx=9 $ $ZEAL_DIR
# Upload to BitBucket
- bash -c 'curl -H "Content-Type:application/octet-stream" -H "Auth-Token:$AUTH_TOKEN" --data-binary @$ || true'
# Cleanup
- rm -rf $ZEAL_DIR*
- secure: LRSLJQbkpc6kkWDVbmvCARm20edC+1RCCgSdEzK0GfG66V+dyGYi6ubFBv1M+kV9YEVY1FkkZctiKlneJLpi/YS3pSJF7bEhYggtxNxRD+9bAVk4GZwVxT7TUw1ZPtLUkWc7L7PqgIO+OOiI8THwsONBNcn5q4fLsByhlt2XOyGPOrQYmfmqjWpgErgI0K4aYoJfoJGTgV2v5sZ+owSkMniyJY5WU9iZkRLO63ddmk72d9eq8ECwgQqxDyhR9/WtHkMPCrwVh06RFd9jG4DfCNDDZRdQLdGxCPXTNwP7QHqG9mKFRQeM91gs/tKlhFFlfPHMckWiBK4hAo+WLC+Ekg==
# Zeal
[![Build Status](](
[![Coverity Scan](](
1. a feeling of strong eagerness (usually in favor of a person or cause)
2. excessive fervor to do something or accomplish some end
3. prompt willingness
> **zeal** *noun*
> 1. a feeling of strong eagerness (usually in favor of a person or cause)
> 2. excessive fervor to do something or accomplish some end
> 3. prompt willingness
> (from WordNet 3.0)
(from WordNet 3.0)
Zeal is a simple documentation browser inspired by [Dash](
Zeal is a simple offline documentation browser inspired by [Dash](
[More screenshots (imgur)](
[More screenshots](
## Download
For details about binary packages (currently available for Windows and Ubuntu) see [downloads page](
For details about binary packages (currently available for Windows and Ubuntu) see [downloads page]( Also, the latest unstable builds are available [here](
## How to use
After installing/compiling it you need to download docsets. It can be done automatically by clicking 'Edit', 'Options', 'Docsets', 'Download...'.
After installing Zeal, you need to download docsets. Go to *File->Options->Docsets*, select the ones you want, and click the *Download* button.
## How to compile
If you prefer to compile Zeal manually.
### Requirements
* Qt 5.0
* X C Binding – keysyms (Ubuntu `libxcb-keysyms1-dev`)
* `bsdtar` is required for the built-in docset extracting to work
* `libappindicator` and `libappindicator-devel` for notifications
* you may need to install `libqt5webkit5-dev` and `qtbase5-private-dev`
* [Qt]( (version 5.2.0 or above is required)
* [libarchive](
* Optionally [libappindicator]( for Unity users
To compile it, run `qmake` and `make` in the `zeal` directory. On Linux, a final `make install` is required to install icons.
To compile it, run `qmake` and `make`.
## Query & Filter docsets
......@@ -48,28 +50,10 @@ You can also search multiple docsets separating them with a comma:
## Command line
If you prefer, you can start with Zeal queries from command line, for this, use the option `--query`:
`zeal --query python:bomb`
If you prefer, you can start Zeal with a query from command line:
* [Issues](
* Search enhancements - some ideas:
* Allow selecting subset of docsets to search in (enable/disable docsets, docset groups)
* Grouping of similar results (like overloaded functions)
* Code cleanup
* Refactoring to reuse common code between `ZealDocsetsRegistry` and `ZealListModel`
* ...
`zeal python:bomb`
## Creating your own docsets
You can use [Dash's instructions for generating docsets](
## Contributions / Project Status
Any feedback, feature requests, or pull requests are welcome. However the project is not under active development at the moment, so unless someone is interested in contributing code, no new features are expected.
I'm going to continue updating docsets that are part of Dash/Zeal exchange programme, and try to fix critical stability/compatibility issues if any arise, to keep the project somewhat alive, but will not implement new features in foreseeable future. Anyway, I should be able to review pull requests.
Please keep in mind I'm not an experienced C++ programmer, so the code quality might be not great.
AppceleratorTitanium 201309192030
Django 201303282044
ExtJS-4.2.1 201305242113
jQuery 201305312107
python-2.7.3-docs-html 201303062116
Qt5 201303062116
Ruby 201303170016
Ruby2 201303170016
SenchaTouch-2.2.1 201305242113
This diff was suppressed by a .gitattributes entry.
This diff was suppressed by a .gitattributes entry.
#!/usr/bin/env python
"""ExtJS docsets parser - needs to be run in the ExtJS reference documentation
directory as a working directory. It can be downloaded from"""
from cStringIO import StringIO
import errno
import os
import re
from json import loads
from lxml.html import parse, tostring, fromstring
from shutil import copytree, rmtree, copy
import sqlite3
OUTPUT_DIR = os.path.join(INPUT_DIR, 'output')
icon = 'icon.png'
indexpath = 'html/Ext.html'
if os.path.exists(os.path.join(INPUT_DIR, 'extjs-build')):
builddir = 'extjs-build'
OUT_DIR = 'ExtJS-4.2.2.docset'
docsetname = 'ExtJS'
docsetshortname = 'extjs'
elif os.path.exists(os.path.join(INPUT_DIR, 'touch-build')):
builddir = 'touch-build'
OUT_DIR = 'SenchaTouch-2.3.0.docset'
docsetname = 'Sencha Touch'
docsetshortname = 'sencha'
# assuming Appcelerator Titanium
builddir = None
OUT_DIR = 'AppceleratorTitanium.docset'
docsetname = 'Appcelerator Titanium'
docsetshortname = 'titanium'
icon = 'appcelerator.png'
indexpath = 'html/Titanium.html'
DOCUMENTS_DIR = os.path.join(OUT_DIR, 'Contents', 'Resources', 'Documents')
HTML_DIR = os.path.join(DOCUMENTS_DIR, 'html')
rmtree(OUT_DIR, ignore_errors=True)
# index.html doesn't work with Dash
rmtree(os.path.join(DOCUMENTS_DIR, 'output'))
if builddir:
rmtree(os.path.join(DOCUMENTS_DIR, builddir))
rmtree(os.path.join(DOCUMENTS_DIR, 'guides'), ignore_errors=True)
if docsetname == 'Appcelerator Titanium':
# CSS fix for fluid width
for dirpath, dirnames, filenames in os.walk(DOCUMENTS_DIR):
for fname in filenames:
if not fname.endswith('.css'): continue
with open(os.path.join(dirpath, fname), 'a') as f:
body {min-width:0px !important}
.class-overview p.private {border:0px; background-color:inherit; padding:0px; text-align:left;}""")
print os.path.join(dirpath, fname), 'CSS fixed'
os.unlink(os.path.join(DOCUMENTS_DIR, 'index.html'))
copy(os.path.join(os.path.dirname(__file__), icon), os.path.join(OUT_DIR, 'icon.png'))
with open(os.path.join(OUT_DIR, 'Contents', 'Info.plist'), 'w') as plist:
plist.write("""<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "">
<plist version="1.0">
</plist>""" % (docsetshortname, docsetname, docsetshortname, indexpath))
conn = sqlite3.connect(os.path.join(OUT_DIR, 'Contents', 'Resources', 'docSet.dsidx'))
c = conn.cursor()
c.execute('CREATE TABLE searchIndex (id integer primary key, name text, type text, path text)')
c.execute('CREATE UNIQUE INDEX anchor ON searchIndex (name, type, path);')
ids = {}
trees = {}
h3_bug_re = re.compile(r"<h4 class='members-subtitle'>([^<>]+)</h3>")
for fname in os.listdir(OUTPUT_DIR):
data = loads(open(os.path.join(OUTPUT_DIR, fname), 'r').read().split('(', 1)[1].rsplit(')', 1)[0])
html = h3_bug_re.sub(r'<h4 class="members-subtitle">\1</h4>', data['html'].encode('utf-8'))
name = fname.rsplit('.', 1)[0]+'.html'
if not fname.rsplit('.', 1)[0].strip():
# ignore invalid files with empty names
trees[name] = tree = parse(StringIO(html))
for div in tree.findall('//div'):
if 'id' in div.attrib:
ids[name[:-len('.html')]+'-'+div.attrib['id']] = (name, div.attrib['id'])
untypes = set()
for fname, tree in trees.iteritems():
with open(os.path.join(HTML_DIR, fname), 'w') as htmlfile:
htmlfile.write("""<!doctype html>
<link rel="stylesheet" href="../resources/css/app-4689d2a5522dcd3c9e9923ca59c33f27.css" type="text/css" />
<!-- titanium hack -->
<link rel="stylesheet" href="../resources/css/my.css" type="text/css" />
<link rel="stylesheet" href="../resources/css/viewport.css" type="text/css" />
<link rel="stylesheet" href="../resources/css/docs-ext.css" type="text/css" />
body {
margin: 2em;
.members .member .short {
display: none;
.members .member .long {
display: block;
<span style="font-size:2em; font-weight:bold">%s</span>
<!-- center-container is for titanium -->
<div id="center-container" class="class-overview"><div class="x-panel-body">"""%fname[:-len('.html')])
for a in tree.findall('//a'):
if 'href' not in a.attrib: continue
if a.attrib['href'].startswith('source/'):
a.attrib['href'] = '../' + a.attrib['href']
if not a.attrib['href'].startswith('#'): continue
ignore = ['/guide/', '/example/', '/guides/', '/video/']
if any(i in a.attrib['href'] for i in ignore): continue
fragment = a.attrib['href'].replace('#!/api/', '')
def cfg():
return fragment.replace('property-', 'cfg-')
if fragment in ids:
a.attrib['href'] = ids[fragment][0] + '#' + ids[fragment][1]
elif cfg() in ids:
a.attrib['href'] = ids[cfg()][0] + '#' + ids[cfg()][1]
elif fragment == '#':
# remove JS elements
if os.path.isfile(os.path.join(OUTPUT_DIR, fragment+'.js')):
a.attrib['href'] = fragment+'.html'
print fragment, 'missing.'
for pre in tree.findall('//pre'):
if not pre.attrib.get('class'):
# enables CSS
pre.attrib['class'] = 'notpretty'
for section in tree.getroot().find_class('members-section'):
stype = section.find('h3').text
idxtype = {'Methods': 'clm',
'Properties': 'Property',
'Config options': 'Option',
'Events': 'event',
'CSS Mixins': 'Mixin',
'CSS Variables': 'var'}[stype]
except KeyError:
idxtype = 'unknown'
for member in section.find_class('member'):
membername = member.xpath('div[@class="title"]/a/text()')
if not len(membername): continue
membername = membername[0]
member.insert(0, fromstring("<a name='//apple_ref/cpp/%s/%s' class='dashAnchor' />" % (idxtype, membername)))
if member.find_class('defined-in')[0].text and \
member.find_class('defined-in')[0].text != fname[:-len('.html')]:
assert member.find_class('defined-in')[0].text + '.html' in trees, member.find_class('defined-in')[0].text
c.execute('INSERT INTO searchIndex(type, name, path) values(?, ?, ?)',
(idxtype, fname[:-len('html')]+membername,
os.path.join('html', fname)+'#'+member.attrib['id']))
c.execute('INSERT INTO searchIndex(type, name, path) values("cl", ?, ?)',
(fname[:-len('.html')], os.path.join('html', fname)))
if untypes:
print 'Unknown types:', untypes
import sqlite3
import os
from lxml.html import parse
conn = sqlite3.connect('index.sqlite')
c = conn.cursor()
c.execute('CREATE TABLE things (id integer primary key, type text, name text, path text, parent integer)')
tree = parse('py-modindex.html')
modules = {}
classes = {}
for tbl in tree.xpath('//table[@class="indextable modindextable"]'):
for tr in tbl.findall('tr'):
a = tr.findall('td')[1].find('a')
if a is None: continue
modname = a.find('tt').text
c.execute('INSERT INTO things(type, name, path) values("module", ?, ?)', (modname, a.attrib['href']))
modules[modname] = (c.lastrowid, a.attrib['href'].split('#')[0])
parsed_files = set()
for modname, (modid, fname) in modules.items():
if '.' in modname: modname = modname.split('.')[0] # modules aren't well-structured