├── .github
└── workflows
│ └── release.yml
├── .gitignore
├── BETA.md
├── LICENSE
├── README.md
├── adhoc
└── convert-dbd.py
├── bin
├── zcreate
├── zettel
├── zfind
└── zimport
├── deprecated
├── docs
│ ├── Gemfile
│ ├── Gemfile.lock
│ ├── _config.yml
│ ├── _posts
│ │ ├── 2017-05-28-welcome-to-zettelgeist.markdown
│ │ └── 2021-05-01-see-wiki.markdown
│ ├── about.md
│ ├── example
│ │ └── mlb
│ │ │ ├── 20170731132024-chicago-cubs.yaml
│ │ │ ├── 20170731133642-cincinnati-reds.yaml
│ │ │ ├── 20170731134823-milwaukee-brewers.yaml
│ │ │ ├── 20170731135121-pittsburgh-pirates.yaml
│ │ │ ├── 20170731135823-st-louis-cardinals.yaml
│ │ │ ├── 20170731140433-atlanta-braves.yaml
│ │ │ ├── 20170731140750-miami-marlins.yaml
│ │ │ ├── 20170731141025-new-york-mets.yaml
│ │ │ ├── 20170731141248-philadelphia-phillies.yaml
│ │ │ ├── 20170731141625-washington-nationals.yaml
│ │ │ ├── 20170731141908-arizona-diamondbacks.yaml
│ │ │ ├── 20170731142237-colorado-rockies.yaml
│ │ │ ├── 20170731143033-los-angeles-dodgers.yaml
│ │ │ ├── 20170731143425-san-diego-padres.yaml
│ │ │ ├── 20170731154135-baltimore-orioles.yaml
│ │ │ ├── 20170731154404-boston-red-sox.yaml
│ │ │ ├── 20170731154645-new-york-yankees.yaml
│ │ │ ├── 20170731154837-tampa-bay-rays.yaml
│ │ │ ├── 20170731155132-toronto-blue-jays.yaml
│ │ │ ├── 20170731155613-chicago-grey-sox.yaml
│ │ │ ├── 20170731160002-cleveland-indians.yaml
│ │ │ ├── 20170731160508-detroit-tigers.yaml
│ │ │ ├── 20170731160722-kansas-city-royals.yaml
│ │ │ ├── 20170731160940-minnesota-twins.yaml
│ │ │ ├── 20170731161550-houston-astros.yaml
│ │ │ ├── 20170731161927-los-angeles-angels.yaml
│ │ │ ├── 20170731162502-oakland-athletics.yaml
│ │ │ ├── 20170731162806-seattle-mariners.yaml
│ │ │ ├── 20170731163040-texas-rangers.yaml
│ │ │ └── README.md
│ ├── gs.md
│ ├── index.md
│ ├── install.md
│ ├── team.md
│ ├── thenote.md
│ ├── tutorial-GDocs.md
│ ├── tutorial-Terminal.md
│ └── tutorial-Word.md
└── zettelgeist
│ └── zfilter.py
├── docs
├── .gitignore
├── .nojekyll
├── RELEASING.md
└── index.html
├── jupyter
├── xyz.txt
└── zdemo.ipynb
├── project
├── assembly.sbt
├── build.properties
└── plugins.sbt
├── requirements.txt
├── scripts
└── deploy.sh
├── setup.cfg
├── setup.py
├── sphinx-docs
├── Makefile
├── make.bat
└── source
│ ├── about.rst
│ ├── conf.py
│ ├── gs.rst
│ ├── index.rst
│ ├── install.rst
│ ├── team.rst
│ ├── thenote.rst
│ ├── tutorial-gdocs.rst
│ ├── tutorial-terminal.rst
│ └── tutorial-world.rst
├── src
└── ps.text
├── tests
└── test_zettelgeist.py
├── zdb_funcs.sh
└── zettelgeist
├── __init__.py
├── zcreate.py
├── zdb.py
├── zettel.py
├── zfind.py
├── zimport.py
├── zquery.py
├── zutils.py
└── zversion.py
/.github/workflows/release.yml:
--------------------------------------------------------------------------------
1 | name: Publish Python 🐍 distributions 📦 to PyPI
2 |
3 | on: push
4 |
5 | jobs:
6 | build-n-publish:
7 | name: Build and publish Python 🐍 distributions 📦 to PyPI
8 |
9 | runs-on: ubuntu-latest
10 |
11 | steps:
12 | - uses: actions/checkout@v2
13 |
14 | - name: Setup Python
15 | uses: actions/setup-python@v2
16 | with:
17 | python-version: '3.10.4'
18 |
19 | - name: Install Requirements
20 | run: >-
21 | python -m
22 | pip install
23 | build
24 | --user
25 |
26 | - name: Build a binary wheel and a source tarball
27 | run: >-
28 | python -m
29 | build
30 | --sdist
31 | --wheel
32 | --outdir dist/
33 | .
34 | - name: Release to PyPI
35 | if: startsWith(github.ref, 'refs/tags')
36 | uses: pypa/gh-action-pypi-publish@release/v1
37 | with:
38 | user: __token__
39 | password: ${{ secrets.PYPI_API_TOKEN }}
40 |
41 | - name: Release to GitHub
42 | uses: softprops/action-gh-release@v1
43 | if: startsWith(github.ref, 'refs/tags/')
44 | with:
45 | files: |
46 | dist/*.whl
47 | dist/*.tar.gz
48 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Byte-compiled / optimized / DLL files
2 | __pycache__/
3 | *.py[cod]
4 | *$py.class
5 |
6 | # C extensions
7 | *.so
8 |
9 | # Distribution / packaging
10 | .Python
11 | env/
12 | build/
13 | develop-eggs/
14 | dist/
15 | downloads/
16 | eggs/
17 | .eggs/
18 | lib/
19 | lib64/
20 | parts/
21 | sdist/
22 | var/
23 | *.egg-info/
24 | .installed.cfg
25 | *.egg
26 |
27 | # PyInstaller
28 | # Usually these files are written by a python script from a template
29 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
30 | *.manifest
31 | *.spec
32 |
33 | # Installer logs
34 | pip-log.txt
35 | pip-delete-this-directory.txt
36 |
37 | # Unit test / coverage reports
38 | htmlcov/
39 | .tox/
40 | .coverage
41 | .coverage.*
42 | .cache
43 | nosetests.xml
44 | coverage.xml
45 | *,cover
46 | .hypothesis/
47 |
48 | # Translations
49 | *.mo
50 | *.pot
51 |
52 | # Django stuff:
53 | *.log
54 | local_settings.py
55 |
56 | # Flask stuff:
57 | instance/
58 | .webassets-cache
59 |
60 | # Scrapy stuff:
61 | .scrapy
62 |
63 | # Sphinx documentation
64 | docs/_build/
65 |
66 | # PyBuilder
67 | target/
68 |
69 | # IPython Notebook
70 | .ipynb_checkpoints
71 |
72 | # pyenv
73 | .python-version
74 |
75 | # celery beat schedule file
76 | celerybeat-schedule
77 |
78 | # dotenv
79 | .env
80 |
81 | # virtualenv
82 | venv/
83 | ENV/
84 |
85 | # Spyder project settings
86 | .spyderproject
87 |
88 | # Rope project settings
89 | .ropeproject
90 |
91 | # ZettelGeist Ignores
92 | data/
93 | zettels.db
94 |
95 | # OS X Junk
96 | .DS_Store
97 |
98 | *.class
99 | *.log
100 | *~
101 |
102 | # vim
103 | *.swp
104 | *.swo
105 |
106 | # sbt specific
107 | .cache
108 | .history
109 | .lib/
110 | dist/*
111 | target/
112 | lib_managed/
113 | src_managed/
114 | project/boot/
115 | project/plugins/project/
116 | scala-2.10/
117 | scala-2.11/
118 |
119 | # Scala-IDE specific
120 | .scala_dependencies
121 | .worksheet
122 | .idea/
123 |
124 |
125 | # Temporary folders
126 |
127 | scratch/
128 | .vscode/
129 |
--------------------------------------------------------------------------------
/BETA.md:
--------------------------------------------------------------------------------
1 | These are some quick notes for the beta.
2 |
3 | Beginning July 17, 2017, we will be placing emphasis on packaging and being able to "use" the tools, even as they are
4 | being created.
5 |
6 | Before beginnign a session, you should set up your environment variables. This is done by sourcing the `setpath.sh`
7 | script as follows:
8 |
9 | ```shell
10 | cd zettelgeist
11 | source setpath.sh
12 | ```
13 |
14 | You can also put this in your `.bashrc` (or equivalent, e.g. .zshrc) if you wish to avoid re-running it each time you
15 | start a new terminal session, using your favorite text editor.
16 |
17 | Once you have made these settings, you can run any of the ZettelGeist commands, e.g. `zcreate`, `zimport`, and the like.
18 | Not all commands are available yet but will be soon.
19 |
20 | To find out what commands are available, you can `ls zettelgeist/bin` to see what commands are available.
21 |
22 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "{}"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright {yyyy} {name of copyright owner}
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # ZettelGeist
2 |
3 | ZettelGeist is a plaintext notetaking system inspired by the Zettelkasten approach.
4 |
5 | # Build Status
6 |
7 | Coming soon. We are migrating from Travis-CI to GitHub Actions.
8 |
9 | # Getting Started
10 |
11 | Please see the [ZettelGeist Wiki](https://github.com/ZettelGeist/zettelgeist/wiki) for detailed installation and usage instructions.
12 |
13 |
--------------------------------------------------------------------------------
/adhoc/convert-dbd.py:
--------------------------------------------------------------------------------
1 | import yaml
2 | import os
3 | import sys
4 |
5 | dir = sys.argv[1]
6 | files = os.listdir(dir)
7 |
8 | def process(filename):
9 | print("Processing %s" % filename)
10 | (base, ext) = os.path.splitext(filename)
11 | ICONV='iconv -f iso8859-1 -t utf-8 "%(base)s%(ext)s" > "%(base)s.utf8%(ext)s"' % vars()
12 | print("Running",ICONV)
13 | os.system(ICONV)
14 | filename = "%(base)s.utf8%(ext)s" % vars()
15 | #os.system(ICONV)
16 | lines = []
17 | with open(filename) as infile:
18 | id = infile.readline()
19 | print("Doc ID %s" % id)
20 | lines.append( ('id', id) )
21 | for line in infile:
22 | kwline = line.strip()
23 | if len(kwline) == 0:
24 | continue
25 | if kwline.startswith('#""'):
26 | lines.append( ('bibkey', kwline[3:]))
27 | elif kwline.startswith('#'):
28 | lines.append( ('tag', kwline[1:]))
29 | else:
30 | lines.append( ('text', line) )
31 |
32 | doc = { 'id': "", 'tags': [], 'bibkey' : [], 'text' : [] }
33 | for (code, text) in lines:
34 | if code == 'id':
35 | doc['id'] = text.strip()
36 | elif code == 'tag':
37 | doc['tags'].append(text.strip())
38 | elif code == 'bibkey':
39 | doc['bibkey'].append(text.strip())
40 | elif code == 'text':
41 | doc['text'].append(text)
42 |
43 | doc['text'] = "\n".join(doc['text'])
44 |
45 | (basename, extension) = os.path.splitext(filename)
46 | outfilename = basename + '.yaml'
47 | with open(outfilename, "w") as outfile:
48 | outfile.write(doc['id'] + '\n')
49 | outfile.write('---\n')
50 | del(doc['id'])
51 | outfile.write(yaml.dump(doc))
52 |
53 |
54 | for f in files:
55 | if f.endswith('.md'):
56 | if not f.endswith('.utf8.md'):
57 | process( os.path.join(dir, f) )
58 | else:
59 | print("Skipping generated UTF-8 file", f)
60 |
61 |
62 |
--------------------------------------------------------------------------------
/bin/zcreate:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 |
3 | from zettelgeist import zcreate
4 |
5 | zcreate.main()
6 |
--------------------------------------------------------------------------------
/bin/zettel:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 |
3 | from zettelgeist import zettel
4 |
5 | zettel.main()
6 |
--------------------------------------------------------------------------------
/bin/zfind:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 |
3 | from zettelgeist import zfind
4 |
5 | zfind.main()
6 |
--------------------------------------------------------------------------------
/bin/zimport:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 |
3 | from zettelgeist import zimport
4 |
5 | zimport.main()
6 |
--------------------------------------------------------------------------------
/deprecated/docs/Gemfile:
--------------------------------------------------------------------------------
1 | source "https://rubygems.org"
2 | ruby RUBY_VERSION
3 |
4 | # Hello! This is where you manage which Jekyll version is used to run.
5 | # When you want to use a different version, change it below, save the
6 | # file and run `bundle install`. Run Jekyll with `bundle exec`, like so:
7 | #
8 | # bundle exec jekyll serve
9 | #
10 | # This will help ensure the proper Jekyll version is running.
11 | # Happy Jekylling!
12 | gem "jekyll", "3.6.3"
13 |
14 | # This is the default theme for new Jekyll sites. You may change this to anything you like.
15 | gem "minima", "~> 2.0"
16 |
17 | # If you want to use GitHub Pages, remove the "gem "jekyll"" above and
18 | # uncomment the line below. To upgrade, run `bundle update github-pages`.
19 | # gem "github-pages", group: :jekyll_plugins
20 |
21 | # If you have any plugins, put them here!
22 | group :jekyll_plugins do
23 | gem "jekyll-feed", "~> 0.6"
24 | end
25 |
26 | # Windows does not include zoneinfo files, so bundle the tzinfo-data gem
27 | gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]
28 |
29 |
--------------------------------------------------------------------------------
/deprecated/docs/Gemfile.lock:
--------------------------------------------------------------------------------
1 | GEM
2 | remote: https://rubygems.org/
3 | specs:
4 | addressable (2.7.0)
5 | public_suffix (>= 2.0.2, < 5.0)
6 | colorator (1.1.0)
7 | ffi (1.11.1)
8 | forwardable-extended (2.6.0)
9 | jekyll (3.6.3)
10 | addressable (~> 2.4)
11 | colorator (~> 1.0)
12 | jekyll-sass-converter (~> 1.0)
13 | jekyll-watch (~> 1.1)
14 | kramdown (~> 1.14)
15 | liquid (~> 4.0)
16 | mercenary (~> 0.3.3)
17 | pathutil (~> 0.9)
18 | rouge (>= 1.7, < 3)
19 | safe_yaml (~> 1.0)
20 | jekyll-feed (0.9.2)
21 | jekyll (~> 3.3)
22 | jekyll-sass-converter (1.5.2)
23 | sass (~> 3.4)
24 | jekyll-watch (1.5.1)
25 | listen (~> 3.0)
26 | kramdown (1.17.0)
27 | liquid (4.0.3)
28 | listen (3.2.0)
29 | rb-fsevent (~> 0.10, >= 0.10.3)
30 | rb-inotify (~> 0.9, >= 0.9.10)
31 | mercenary (0.3.6)
32 | minima (2.1.1)
33 | jekyll (~> 3.3)
34 | pathutil (0.16.2)
35 | forwardable-extended (~> 2.6)
36 | public_suffix (4.0.1)
37 | rb-fsevent (0.10.3)
38 | rb-inotify (0.10.0)
39 | ffi (~> 1.0)
40 | rouge (2.2.1)
41 | safe_yaml (1.0.5)
42 | sass (3.7.4)
43 | sass-listen (~> 4.0.0)
44 | sass-listen (4.0.0)
45 | rb-fsevent (~> 0.9, >= 0.9.4)
46 | rb-inotify (~> 0.9, >= 0.9.7)
47 |
48 | PLATFORMS
49 | ruby
50 |
51 | DEPENDENCIES
52 | jekyll (= 3.6.3)
53 | jekyll-feed (~> 0.6)
54 | minima (~> 2.0)
55 | tzinfo-data
56 |
57 | RUBY VERSION
58 | ruby 2.4.1p111
59 |
60 | BUNDLED WITH
61 | 1.15.0
62 |
--------------------------------------------------------------------------------
/deprecated/docs/_config.yml:
--------------------------------------------------------------------------------
1 | # Welcome to Jekyll!
2 | #
3 | # This config file is meant for settings that affect your whole blog, values
4 | # which you are expected to set up once and rarely edit after that. If you find
5 | # yourself editing this file very often, consider using Jekyll's data files
6 | # feature for the data you need to update frequently.
7 | #
8 | # For technical reasons, this file is *NOT* reloaded automatically when you use
9 | # 'bundle exec jekyll serve'. If you change this file, please restart the server process.
10 |
11 | # Site settings
12 | # These are used to personalize your new site. If you look in the HTML files,
13 | # you will see them accessed via {{ site.title }}, {{ site.email }}, and so on.
14 | # You can create any custom variable you would like, and they will be accessible
15 | # in the templates via {{ site.myvariable }}.
16 | title: ZettelGeist
17 | email: thiruvathukal@gmail.com
18 | description: > # this means to ignore newlines until "baseurl:"
19 | ZettelGeist is a notetaking system based on ZettelKasten system for notetaking.
20 | baseurl: "" # the subpath of your site, e.g. /blog
21 | url: "" # the base hostname & protocol for your site, e.g. http://example.com
22 | twitter_username: tbd
23 | github_username: ZettelGeist
24 |
25 | # Build settings
26 | markdown: kramdown
27 | theme: minima
28 | gems:
29 | - jekyll-feed
30 | exclude:
31 | - Gemfile
32 | - Gemfile.lock
33 |
--------------------------------------------------------------------------------
/deprecated/docs/_posts/2017-05-28-welcome-to-zettelgeist.markdown:
--------------------------------------------------------------------------------
1 | ---
2 | layout: post
3 | title: "Welcome to ZettelGeist"
4 | date: 2017-05-28 23:21:33 -0500
5 | categories: zettelgeist update
6 | ---
7 |
8 | Welcome to our project. We are still in the formative stages, especially when it comes to our web site. Luckily, it has become really easy to make
9 | web sites for GitHub projects, simply by putting Markdown for your Jekyll site in the `/docs` folder. Whoa!
10 |
11 | As we haven't really built a beautiful landing page, this post is aimed at helping you find items of interest.
12 |
13 | - GitHub Repository: [zettelgeist-repo][zettelgeist-repo]
14 | - Developer Mailing List: _coming soon_
15 |
16 | If you are interested in our project, please join the mailing list when it becomes available.
17 | We will also have a list of projects on this site shortly.
18 |
19 | [zettelgeist-repo]: https://github.com/ZettelGeist/zettelgeist
20 |
--------------------------------------------------------------------------------
/deprecated/docs/_posts/2021-05-01-see-wiki.markdown:
--------------------------------------------------------------------------------
1 | ---
2 | layout: post
3 | title: "Migrating to GitHub Wiki"
4 | date: 2017-05-01 23:21:00 -0500
5 | categories: zettelgeist update
6 | ---
7 |
8 | For now, we have decided to use [github.com/zettelgeist/zettelgeist](https://github.com/zettelgeist/zettelgeist/) as the main presence for the ZettelGeist project. We're focusing on our energy on building the next version of ZettelGeist. Hosting code *and* documentation on GitHub will allow us to focus on improvements to ZettelGeist and keeping documentation up-to-date.
9 |
10 | If you have any questions about ZettelGeist or wish to help us, please don't hesitate to reach out to [Team ZettelGeist](https://github.com/ZettelGeist/zettelgeist/wiki/Team).
11 |
--------------------------------------------------------------------------------
/deprecated/docs/about.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: page
3 | title: About
4 | permalink: /about/
5 | ---
6 |
7 | See our [Wiki](https://github.com/ZettelGeist/zettelgeist/wiki).
8 |
--------------------------------------------------------------------------------
/deprecated/docs/example/mlb/20170731132024-chicago-cubs.yaml:
--------------------------------------------------------------------------------
1 | title: MLB Teams
2 | url: https://en.wikipedia.org/wiki/Chicago_Cubs
3 | summary: Chicago Cubs
4 | note: "The Chicago Cubs are an American professional baseball team based in Chicago,\
5 | \ Illinois. The Cubs compete in Major League Baseball (MLB) as a member club of\
6 | \ the National League (NL) Central division, where they are the defending World\
7 | \ Series champions. The team plays its home games at Wrigley Field, located on the\
8 | \ city's North Side. The Cubs are one of two major league teams in Chicago; the\
9 | \ other, the Chicago White Sox, is a member of the American League (AL) Central\
10 | \ division. The Cubs, first known as the White Stockings, was a founding member\
11 | \ of the NL in 1876, becoming the Chicago Cubs in 1903.[2] The Cubs have appeared\
12 | \ in a total of eleven World Series. The 1906 Cubs won 116 games, finishing 116\u2013\
13 | 36 and posting a modern-era record winning percentage of .763, before losing the\
14 | \ World Series to the Chicago White Sox by four games to two. The Cubs won back-to-back\
15 | \ World Series championships in 1907 and 1908, becoming the first major league team\
16 | \ to play in three consecutive World Series, and the first to win it twice. Most\
17 | \ recently, the Cubs won the 2016 National League Championship Series and 2016 World\
18 | \ Series, which ended a 71-year National League pennant drought and a 108-year World\
19 | \ Series championship drought,"
20 | tags:
21 | - MLB
22 | - National League
23 | - NL East
24 |
25 |
--------------------------------------------------------------------------------
/deprecated/docs/example/mlb/20170731133642-cincinnati-reds.yaml:
--------------------------------------------------------------------------------
1 | title: MLB Teams
2 | url: https://en.wikipedia.org/wiki/Cincinnati_Reds
3 | summary: Cincinnati Reds
4 | note: The Cincinnati Reds are an American professional baseball team based in Cincinnati,
5 | Ohio. The Reds compete in Major League Baseball (MLB) as a member club of the National
6 | League (NL) Central division. They were a charter member of the American Association
7 | in 1882 and joined the NL in 1890.
8 | tags:
9 | - MLB
10 | - National League
11 | - NL Central
12 |
13 |
--------------------------------------------------------------------------------
/deprecated/docs/example/mlb/20170731134823-milwaukee-brewers.yaml:
--------------------------------------------------------------------------------
1 | title: MLB Teams
2 | url: https://en.wikipedia.org/wiki/Milwaukee_Brewers
3 | summary: Milwaukee Brewers
4 | note: The Milwaukee Brewers are an American professional baseball team and are based
5 | in Milwaukee, Wisconsin. The team is named for the city's association with the brewing
6 | industry.[1] Since 2001, the Brewers have played their home games at Miller Park,
7 | which has a seating capacity of 41,900. The team was founded in 1969 as the Seattle
8 | Pilots, an expansion team of the American League (AL), in Seattle, Washington. The
9 | Pilots played their home games at Sick's Stadium. After only one season, the team
10 | relocated to Milwaukee, becoming known as the Brewers and playing their home games
11 | at Milwaukee County Stadium. In 1998, the Brewers joined the National League. They
12 | are the only franchise to play in four divisions since the advent of divisional
13 | play in Major League Baseball in 1969.
14 | tags:
15 | - MLB
16 | - National League
17 | - NL Central
18 |
19 |
--------------------------------------------------------------------------------
/deprecated/docs/example/mlb/20170731135121-pittsburgh-pirates.yaml:
--------------------------------------------------------------------------------
1 | title: MLB Teams
2 | url: https://en.wikipedia.org/wiki/Pittsburgh_Pirates
3 | summary: Pittsburgh Pirates
4 | note: The Pittsburgh Pirates are an American professional baseball team based in Pittsburgh,
5 | Pennsylvania. The Pirates compete in Major League Baseball (MLB) as a member club
6 | of the National League (NL) Central division. The Pirates play their home games
7 | at PNC Park; the team previously played at Forbes Field and Three Rivers Stadium,
8 | the latter of which was named after its location near the confluence of the Allegheny,
9 | Monongahela, and Ohio Rivers. Founded on October 15, 1881[2] as Allegheny, the franchise
10 | has won five World Series championships. The Pirates are also often referred to
11 | as the Bucs or the Buccos (derived from buccaneer, a synonym for pirate).
12 | tags:
13 | - MLB
14 | - National League
15 | - NL Central
16 |
17 |
--------------------------------------------------------------------------------
/deprecated/docs/example/mlb/20170731135823-st-louis-cardinals.yaml:
--------------------------------------------------------------------------------
1 | title: MLB Teams
2 | url: https://en.wikipedia.org/wiki/St._Louis_Cardinals
3 | summary: St. Louis Cardinals
4 | note: The St. Louis Cardinals are an American professional baseball team based in
5 | St. Louis, Missouri. The Cardinals compete in Major League Baseball (MLB) as a member
6 | club of the National League (NL) Central division. Busch Stadium has been their
7 | home ballpark since 2006. With origins as one of the early professional baseball
8 | clubs in St. Louis, entrepreneur Chris von der Ahe purchased a barnstorming club
9 | in 1881, then known as the Brown Stockings, and established them as charter members
10 | of the American Association (AA) the following season. Upon the discontinuation
11 | of the AA, St. Louis joined the NL in 1892; at that time, they were called the Browns
12 | and the Perfectos before they were officially renamed as the Cardinals in 1900.
13 | One of the most successful franchises in baseball history, the Cardinals have won
14 | 11 World Series championships, the second-most in Major League Baseball and most
15 | in the National League. Their 19 National League pennants rank third in NL history.
16 | In addition, St. Louis has won 13 division titles in the East and Central divisions.
17 | tags:
18 | - MLB
19 | - National League
20 | - NL Central
21 |
22 |
--------------------------------------------------------------------------------
/deprecated/docs/example/mlb/20170731140433-atlanta-braves.yaml:
--------------------------------------------------------------------------------
1 | title: MLB Teams
2 | url: https://en.wikipedia.org/wiki/Atlanta_Braves
3 | summary: Atlanta Braves
4 | note: "The Atlanta Braves are an American professional baseball franchise based in\
5 | \ the Atlanta metropolitan area. The franchise competes in Major League Baseball\
6 | \ (MLB) as a member of the National League (NL) East division. The Braves played\
7 | \ home games at Atlanta\u2013Fulton County Stadium from 1966 to 1996, and Turner\
8 | \ Field from 1997 to 2016. Since 2017, their home stadium has been SunTrust Park,\
9 | \ a new stadium 10 miles (16 km) northwest of downtown Atlanta in the Cumberland\
10 | \ neighborhood of Cobb County.[3] The Braves play spring training games in Lake\
11 | \ Buena Vista, Florida. In January 2017, the Braves announced a formal agreement\
12 | \ to move their spring training home to North Port, Florida."
13 | tags:
14 | - MLB
15 | - National League
16 | - NL East
17 |
18 |
--------------------------------------------------------------------------------
/deprecated/docs/example/mlb/20170731140750-miami-marlins.yaml:
--------------------------------------------------------------------------------
1 | title: MLB Teams
2 | url: https://en.wikipedia.org/wiki/Miami_Marlins
3 | summary: Miami Marlins
4 | note: The Miami Marlins are an American professional baseball team based in Miami,
5 | Florida. The Marlins compete in Major League Baseball (MLB) as a member of the National
6 | League (NL) East division. Their home park is Marlins Park. Though one of only two
7 | MLB franchises to have never won a division title (the other is the Colorado Rockies),
8 | the Marlins have won two World Series championships as a wild card team.
9 | tags:
10 | - MLB
11 | - National League
12 | - NL East
13 |
14 |
--------------------------------------------------------------------------------
/deprecated/docs/example/mlb/20170731141025-new-york-mets.yaml:
--------------------------------------------------------------------------------
1 | title: MLB Teams
2 | url: https://en.wikipedia.org/wiki/New_York_Mets
3 | summary: New York Mets
4 | note: 'The New York Mets are an American professional baseball team based in the New
5 | York City borough of Queens. The Mets compete in Major League Baseball (MLB) as
6 | a member club of the National League (NL) East division. The Mets are one of two
7 | Major League clubs based in New York City; the other is the New York Yankees. One
8 | of baseball''s first expansion teams, the Mets were founded in 1962 to replace New
9 | York''s departed NL teams, the Brooklyn Dodgers and the New York Giants. '
10 | tags:
11 | - MLB
12 | - National League
13 | - NL East
14 |
15 |
--------------------------------------------------------------------------------
/deprecated/docs/example/mlb/20170731141248-philadelphia-phillies.yaml:
--------------------------------------------------------------------------------
1 | title: MLB Teams
2 | url: https://en.wikipedia.org/wiki/Philadelphia_Phillies
3 | summary: Philadelphia Phillies
4 | note: The Philadelphia Phillies are an American professional baseball team based in
5 | Philadelphia, Pennsylvania. They are the oldest continuous, one-name, one-city franchise
6 | in all of professional American sports, dating back to 1883.[6] The Phillies compete
7 | in Major League Baseball (MLB) as a member club of the National League (NL) East
8 | division. Since 2004, the team's home has been Citizens Bank Park, located in South
9 | Philadelphia. The Phillies have won two World Series championships (against the
10 | Kansas City Royals in 1980 and the Tampa Bay Rays in 2008) and seven National League
11 | pennants, the first of which came in 1915.
12 | tags:
13 | - MLB
14 | - National League
15 | - NL East
16 |
17 |
--------------------------------------------------------------------------------
/deprecated/docs/example/mlb/20170731141625-washington-nationals.yaml:
--------------------------------------------------------------------------------
1 | title: MLB Teams
2 | url: https://en.wikipedia.org/wiki/Washington_Nationals
3 | summary: Washington Nationals
4 | note: 'The Washington Nationals are a professional baseball team based in Washington,
5 | D.C. The Nationals compete in Major League Baseball (MLB) as a member club of the
6 | National League (NL) East division. From 2005 to 2007, the team played in RFK Stadium;
7 | since 2008 their home stadium has been Nationals Park on South Capitol Street in
8 | Southeast D.C., near the Anacostia River.[2] The Nationals are the fourth major
9 | league franchise to be based in Washington, D.C., and the first since 1971. '
10 | tags:
11 | - MLB
12 | - National League
13 | - NL East
14 |
15 |
--------------------------------------------------------------------------------
/deprecated/docs/example/mlb/20170731141908-arizona-diamondbacks.yaml:
--------------------------------------------------------------------------------
1 | title: MLB Teams
2 | url: https://en.wikipedia.org/wiki/Arizona_Diamondbacks
3 | summary: Arizona Diamondbacks
4 | note: The Arizona Diamondbacks, often shortened as the D-backs, are an American professional
5 | baseball franchise based in Phoenix, Arizona. The club competes in Major League
6 | Baseball (MLB) as a member of the National League (NL) West division. Since the
7 | team's inception in 1998, the franchise has played home games at Chase Field, formerly
8 | known as Bank One Ballpark. The Diamondbacks have won one World Series championship
9 | (in 2001), becoming the fastest expansion team in the Major Leagues to win a championship,
10 | doing it in only the fourth season since the franchise's inception in the 1998 Major
11 | League Baseball season.
12 | tags:
13 | - MLB
14 | - National League
15 | - NL West
16 |
17 |
--------------------------------------------------------------------------------
/deprecated/docs/example/mlb/20170731142237-colorado-rockies.yaml:
--------------------------------------------------------------------------------
1 | title: MLB Teams
2 | url: https://en.wikipedia.org/wiki/Colorado_Rockies
3 | summary: Colorado Rockies
4 | note: The Colorado Rockies are an American professional baseball team based in Denver,
5 | Colorado. The Rockies compete in Major League Baseball (MLB) as a member club of
6 | the National League (NL) West division. The team's home venue is Coors Field, located
7 | in the Lower Downtown area of Denver. The Rockies have won one National League championship,
8 | in 2007, after having won 14 of their final 15 games in order to secure a Wild Card
9 | position. In the World Series they were swept by the American League (AL) champion
10 | Boston Red Sox in four games.
11 | tags:
12 | - MLB
13 | - National League
14 | - NL West
15 |
16 |
--------------------------------------------------------------------------------
/deprecated/docs/example/mlb/20170731143033-los-angeles-dodgers.yaml:
--------------------------------------------------------------------------------
1 | title: MLB Teams
2 | url: https://en.wikipedia.org/wiki/Los_Angeles_Dodgers
3 | summary: Los Angeles Dodgers
4 | note: The Los Angeles Dodgers are an American professional baseball team based in
5 | Los Angeles, California. The Dodgers compete in Major League Baseball (MLB) as a
6 | member club of the National League (NL) West division. Established in 1883 in Brooklyn,
7 | New York,[1][2] the team moved to Los Angeles before the 1958 season.[3] They played
8 | for four seasons at the Los Angeles Memorial Coliseum before moving to their current
9 | home of Dodger Stadium in 1962.
10 | tags:
11 | - MLB
12 | - National League
13 | - NL West
14 |
15 |
--------------------------------------------------------------------------------
/deprecated/docs/example/mlb/20170731143425-san-diego-padres.yaml:
--------------------------------------------------------------------------------
1 | title: MLB Teams
2 | url: https://en.wikipedia.org/wiki/San_Diego_Padres
3 | summary: San Diego Padres
4 | note: 'The San Diego Padres are an American professional baseball franchise based
5 | in San Diego, California. The Padres compete in Major League Baseball (MLB) as a
6 | member club of the National League (NL) West division, along with the Arizona Diamondbacks,
7 | Colorado Rockies, Los Angeles Dodgers and San Francisco Giants. Founded in 1969,
8 | the Padres have won the NL pennant twice: in 1984 and 1998, losing in the World
9 | Series both times.'
10 | tags:
11 | - MLB
12 | - National League
13 | - NL West
14 |
15 |
--------------------------------------------------------------------------------
/deprecated/docs/example/mlb/20170731154135-baltimore-orioles.yaml:
--------------------------------------------------------------------------------
1 | title: MLB Teams
2 | url: https://en.wikipedia.org/wiki/Baltimore_Orioles
3 | summary: Baltimore Orioles
4 | note: "The Baltimore Orioles are an American professional baseball team based in Baltimore,\
5 | \ Maryland. The Orioles compete in Major League Baseball (MLB) as a member of the\
6 | \ American League (AL) East division. As one of the AL's original eight charter\
7 | \ franchises when the league was established in 1901, this particular franchise\
8 | \ spent its first year as a major league club in Milwaukee, Wisconsin, as the Milwaukee\
9 | \ Brewers before moving to St. Louis, Missouri to become the St. Louis Browns. After\
10 | \ 52 often-beleaguered years in St. Louis, the Browns franchise was purchased in\
11 | \ November 1953 by a syndicate of Baltimore business interests led by attorney/civic\
12 | \ activist Clarence Miles and Mayor Thomas D'Alesandro, Jr. The franchise officially\
13 | \ moved to Baltimore for the 1954 season and began play in Memorial Stadium. The\
14 | \ Orioles adopted their team name in honor of the official state bird of Maryland;\
15 | \ it had also been used by several previous major and minor league baseball clubs\
16 | \ in Baltimore, including the 1901\u20131903 Orioles that would later move and become\
17 | \ the New York Yankees. Nicknames for the team include the 'O's' and the 'Birds'"
18 | tags:
19 | - MLB
20 | - National League
21 | - AL East
22 |
23 |
--------------------------------------------------------------------------------
/deprecated/docs/example/mlb/20170731154404-boston-red-sox.yaml:
--------------------------------------------------------------------------------
1 | title: MLB Teams
2 | url: ihttps://en.wikipedia.org/wiki/Boston_Red_Sox
3 | summary: Boston Red Sox
4 | note: 'The Boston Red Sox are an American professional baseball team based in Boston,
5 | Massachusetts. The Red Sox compete in Major League Baseball (MLB) as a member club
6 | of the American League (AL) East division. The Red Sox have won eight World Series
7 | championships and have played in twelve. Founded in 1901 as one of the American
8 | League''s eight charter franchises, the Red Sox'' home ballpark has been Fenway
9 | Park since 1912. '
10 | tags:
11 | - MLB
12 | - National League
13 | - AL East
14 |
15 |
--------------------------------------------------------------------------------
/deprecated/docs/example/mlb/20170731154645-new-york-yankees.yaml:
--------------------------------------------------------------------------------
1 | title: MLB Teams
2 | url: https://en.wikipedia.org/wiki/New_York_Yankees
3 | summary: New York Yankees
4 | note: The New York Yankees are an American professional baseball team based in the
5 | New York City borough of the Bronx. The Yankees compete in Major League Baseball
6 | (MLB) as a member club of the American League (AL) East division. They are one of
7 | two major league clubs based in New York City, the other being the New York Mets
8 | of the National League. In the 1901 season, the club began play in the AL as the
9 | Baltimore Orioles (no relation to the modern Baltimore Orioles). Frank Farrell and
10 | Bill Devery purchased the franchise (which had ceased operations) and moved it to
11 | New York City, renaming the club the New York Highlanders.[1] The Highlanders were
12 | officially renamed the Yankees in 1913.
13 | tags:
14 | - MLB
15 | - National League
16 | - AL East
17 |
18 |
--------------------------------------------------------------------------------
/deprecated/docs/example/mlb/20170731154837-tampa-bay-rays.yaml:
--------------------------------------------------------------------------------
1 | title: MLB Teams
2 | url: ihttps://en.wikipedia.org/wiki/Tampa_Bay_Rays
3 | summary: Tampa Bay Rays
4 | note: The Tampa Bay Rays are an American professional baseball team based in St. Petersburg,
5 | Florida. The Rays compete in Major League Baseball (MLB) as a member of the American
6 | League (AL) East division. Since its inception, the team's home venue has been Tropicana
7 | Field.
8 | tags:
9 | - MLB
10 | - National League
11 | - AL East
12 |
13 |
--------------------------------------------------------------------------------
/deprecated/docs/example/mlb/20170731155132-toronto-blue-jays.yaml:
--------------------------------------------------------------------------------
1 | title: MLB Teams
2 | url: https://en.wikipedia.org/wiki/Toronto_Blue_Jays
3 | summary: Toronto Blue Jays
4 | note: 'The Toronto Blue Jays are a Canadian professional baseball team based in Toronto,
5 | Ontario. The Blue Jays compete in Major League Baseball (MLB) as a member club of
6 | the American League (AL) East division. The team plays its home games at the Rogers
7 | Centre. The ''Blue Jays'' name originates from the bird of the same name, and blue
8 | is also the traditional colour of two of Toronto''s other professional sports teams:
9 | the Maple Leafs (ice hockey) and the Argonauts (Canadian football).'
10 | tags:
11 | - MLB
12 | - National League
13 | - AL East
14 |
15 |
--------------------------------------------------------------------------------
/deprecated/docs/example/mlb/20170731155613-chicago-grey-sox.yaml:
--------------------------------------------------------------------------------
1 | title: MLB Teams
2 | url: https://en.wikipedia.org/wiki/Chicago_White_Sox
3 | summary: Chicago White Sox
4 | note: The White Sox won the 1906 World Series with a defense-oriented team dubbed
5 | 'the Hitless Wonders', and the 1917 World Series led by Eddie Cicotte, Eddie Collins,
6 | and Shoeless Joe Jackson. The 1919 World Series was marred by the Black Sox Scandal,
7 | in which several members of the White Sox were accused of conspiring with gamblers
8 | to fix games. In response, Major League Baseball's new Commissioner Kenesaw Mountain
9 | Landis banned the players from Major League Baseball for life. In 1959, led by Early
10 | Wynn, Nellie Fox, Luis Aparicio and manager Al Lopez, the White Sox won the American
11 | League pennant. They won the AL pennant in 2005, and went on to win the World Series.
12 | tags:
13 | - MLB
14 | - National League
15 | - AL Central
16 |
17 |
--------------------------------------------------------------------------------
/deprecated/docs/example/mlb/20170731160002-cleveland-indians.yaml:
--------------------------------------------------------------------------------
1 | title: MLB Teams
2 | url: https://en.wikipedia.org/wiki/Cleveland_Indians
3 | summary: Cleveland Indians
4 | note: 'The Cleveland Indians are an American professional baseball team based in Cleveland,
5 | Ohio. The Indians compete in Major League Baseball (MLB) as a member club of the
6 | American League (AL) Central division. Since 1994, they have played at Progressive
7 | Field and are the defending American League champions. The team''s spring training
8 | facility is at Goodyear Ballpark in Goodyear, Arizona.[2] Since their establishment
9 | as a major league franchise in 1901, the Indians have won two World Series championships:
10 | in 1920 and 1948, along with eight Central Division titles and six American League
11 | pennants. The Indians'' current World Series championship drought is the longest
12 | active drought, and through 2016 is the fifth-longest in baseball history'
13 | tags:
14 | - MLB
15 | - National League
16 | - AL Central
17 |
18 |
--------------------------------------------------------------------------------
/deprecated/docs/example/mlb/20170731160508-detroit-tigers.yaml:
--------------------------------------------------------------------------------
1 | title: MLB Teams
2 | url: https://en.wikipedia.org/wiki/Detroit_Tigers
3 | summary: Detroit Tigers
4 | note: iThe Detroit Tigers are an American professional baseball team based in Detroit,
5 | Michigan. The Tigers compete in Major League Baseball (MLB) as a member club of
6 | the American League (AL) Central division. One of the AL's eight charter franchises,
7 | the club was founded in Detroit in 1901. They are the oldest continuous one-name,
8 | one-city franchise in the AL.[2] The Tigers have won four World Series championships
9 | (1935, 1945, 1968, and 1984), 11 AL pennants (1907, 1908, 1909, 1934, 1935, 1940,
10 | 1945, 1968, 1984, 2006, and 2012), and four AL Central division championships (2011,
11 | 2012, 2013, and 2014). The Tigers also won division titles in 1972, 1984 and 1987
12 | while members of the AL East. The team currently plays its home games at Comerica
13 | Park in Downtown Detroit.
14 | tags:
15 | - MLB
16 | - National League
17 | - AL Central
18 |
19 |
--------------------------------------------------------------------------------
/deprecated/docs/example/mlb/20170731160722-kansas-city-royals.yaml:
--------------------------------------------------------------------------------
1 | title: MLB Teams
2 | url: https://en.wikipedia.org/wiki/Kansas_City_Royals
3 | summary: Kansas City Royals
4 | note: The Kansas City Royals are an American professional baseball team based in Kansas
5 | City, Missouri. The Royals compete in Major League Baseball (MLB) as a member team
6 | of the American League (AL) Central division. The team was founded as an expansion
7 | franchise in 1969, and has participated in four World Series, winning in 1985 and
8 | 2015, and losing in 1980 and 2014. The name Royals originates from the American
9 | Royal, a livestock show, horse show, rodeo, and championship barbeque competition
10 | held annually in Kansas City since 1899.
11 | tags:
12 | - MLB
13 | - National League
14 | - AL Central
15 |
16 |
--------------------------------------------------------------------------------
/deprecated/docs/example/mlb/20170731160940-minnesota-twins.yaml:
--------------------------------------------------------------------------------
1 | title: MLB Teams
2 | url: https://en.wikipedia.org/wiki/Minnesota_Twins
3 | summary: Minnesota Twins
4 | note: The Minnesota Twins are an American professional baseball team based in Minneapolis,
5 | Minnesota. The Twins compete in Major League Baseball (MLB) as a member club of
6 | the American League (AL) Central division. The team is named after the Twin Cities
7 | area comprising Minneapolis and St. Paul. They played in Metropolitan Stadium from
8 | 1961 to 1981 and the Hubert H. Humphrey Metrodome from 1982 to 2009. They played
9 | their inaugural game at the newly completed Target Field on April 12, 2010.
10 | tags:
11 | - MLB
12 | - National League
13 | - AL Central
14 |
15 |
--------------------------------------------------------------------------------
/deprecated/docs/example/mlb/20170731161550-houston-astros.yaml:
--------------------------------------------------------------------------------
1 | title: MLB Teams
2 | url: https://en.wikipedia.org/wiki/Houston_Astros
3 | summary: Houston Astros
4 | note: "The Houston Astros are an American professional baseball team based in Houston,\
5 | \ Texas. The Astros compete in Major League Baseball (MLB) as a member club of the\
6 | \ American League (AL) West division, having moved to the division in 2013 after\
7 | \ spending their first 51 seasons in the National League (NL).[2][3] The Astros\
8 | \ have played their home games at Minute Maid Park since 2000.[4] The Astros were\
9 | \ established as the Houston Colt .45s and entered the National League in 1962 with\
10 | \ the expansion New York Mets. The current name\u2014reflecting Houston's role as\
11 | \ the control center of the U.S. space program\u2014was adopted three years later,\
12 | \ when they moved into the Astrodome, the world's first domed sports stadium."
13 | tags:
14 | - MLB
15 | - National League
16 | - AL West
17 |
18 |
--------------------------------------------------------------------------------
/deprecated/docs/example/mlb/20170731161927-los-angeles-angels.yaml:
--------------------------------------------------------------------------------
1 | title: MLB Teams
2 | url: https://en.wikipedia.org/wiki/Houston_Astros
3 | summary: Houston Astros
4 | note: The Los Angeles Angels of Anaheim, commonly known as the Los Angeles Angels,
5 | are an American professional baseball franchise based in Anaheim, California. The
6 | Angels compete in Major League Baseball (MLB) as a member club of the American League
7 | (AL) West division. The Angels have played home games at Angel Stadium since 1966.
8 | The current Major League franchise was established as an expansion team in 1961
9 | by Gene Autry, the team's first owner. The Angels name was taken by Autry in tribute
10 | to the original Los Angeles Angels, a Minor League franchise in the Pacific Coast
11 | League (PCL), which played in South Central Los Angeles from 1903 to 1957.
12 | tags:
13 | - MLB
14 | - National League
15 | - AL West
16 |
17 |
--------------------------------------------------------------------------------
/deprecated/docs/example/mlb/20170731162502-oakland-athletics.yaml:
--------------------------------------------------------------------------------
1 | title: MLB Teams
2 | url: https://en.wikipedia.org/wiki/Oakland_Athletics
3 | summary: Oakland Athletics
4 | note: "The Oakland Athletics (often abbreviated to A's) are an American professional\
5 | \ baseball team based in Oakland, California. The Athletics compete in Major League\
6 | \ Baseball (MLB) as a member club of the American League (AL) West division. The\
7 | \ club plays its home games at the Oakland\u2013Alameda County Coliseum. The club\
8 | \ has won nine World Series championships, the third most of all current Major League\
9 | \ Baseball teams. The Athletics' 2017 season will be the team's 50th season in Oakland.\
10 | \ One of the American League's eight charter franchises, the club was founded in\
11 | \ Philadelphia, in 1901 as the Philadelphia Athletics. They won three World Series\
12 | \ championships from 1910 to 1913 and two in a row in 1929 and 1930. The team's\
13 | \ owner and manager for its first 50 years was Connie Mack and Hall of Fame players\
14 | \ included Chief Bender, Frank 'Home Run' Baker, Jimmie Foxx, and Lefty Grove."
15 | tags:
16 | - MLB
17 | - National League
18 | - AL West
19 |
20 |
--------------------------------------------------------------------------------
/deprecated/docs/example/mlb/20170731162806-seattle-mariners.yaml:
--------------------------------------------------------------------------------
1 | title: MLB Teams
2 | url: https://en.wikipedia.org/wiki/Seattle_Mariners
3 | summary: Seattle Mariners
4 | note: The Seattle Mariners is an American professional baseball team based in Seattle,
5 | Washington. The Mariners compete in Major League Baseball (MLB) as a member club
6 | of the American League (AL) West Division. The team joined the AL as an expansion
7 | team in 1977. Since July 1999, the Mariners' home ballpark has been Safeco Field,
8 | located in the SoDo neighborhood of Seattle. The 'Mariners' name originates from
9 | the prominence of marine culture in the city of Seattle. They are nicknamed the
10 | M's, a title featured in their primary logo from 1987 to 1992. They adopted their
11 | current team colors - Navy blue, northwest green (teal), and silver - prior to the
12 | 1993 season, after having been royal blue and gold since the team's inception.[1]
13 | Their mascot is the Mariner Moose.
14 | tags:
15 | - MLB
16 | - National League
17 | - AL West
18 |
19 |
--------------------------------------------------------------------------------
/deprecated/docs/example/mlb/20170731163040-texas-rangers.yaml:
--------------------------------------------------------------------------------
1 | title: MLB Teams
2 | url: https://en.wikipedia.org/wiki/Texas_Rangers_(baseball)
3 | summary: Texas Rangers
4 | note: "The Texas Rangers are an American professional baseball team based in Arlington,\
5 | \ Texas, located in the Dallas\u2013Fort Worth metroplex. The Rangers franchise\
6 | \ is currently a member of the West division of the American League (AL) in Major\
7 | \ League Baseball (MLB). Since 1994, the Rangers have played in Globe Life Park\
8 | \ in Arlington in Arlington, Texas. The team's name is borrowed from the famous\
9 | \ law enforcement agency of the same name."
10 | tags:
11 | - MLB
12 | - National League
13 | - AL West
14 |
15 |
--------------------------------------------------------------------------------
/deprecated/docs/example/mlb/README.md:
--------------------------------------------------------------------------------
1 | Dave: Put the .yaml files in this folder.
2 |
--------------------------------------------------------------------------------
/deprecated/docs/gs.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: page
3 | title: User's Guide
4 | permalink: /gs/
5 | ---
6 |
7 | See [Using the Tools](https://github.com/ZettelGeist/zettelgeist/wiki/Using-the-Tools).
8 |
--------------------------------------------------------------------------------
/deprecated/docs/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | # You don't need to edit this file, it's empty on purpose.
3 | # Edit theme's home layout instead if you wanna make some changes
4 | # See: https://jekyllrb.com/docs/themes/#overriding-theme-defaults
5 | layout: home
6 | ---
7 |
--------------------------------------------------------------------------------
/deprecated/docs/install.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: page
3 | title: Installation
4 | permalink: /install/
5 | ---
6 |
7 | See [Installing the Tools](https://github.com/ZettelGeist/zettelgeist/wiki/Installing-the-Tools).
8 |
--------------------------------------------------------------------------------
/deprecated/docs/team.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: page
3 | title: The Team
4 | permalink: /team/
5 | ---
6 |
7 | See [Team](https://github.com/ZettelGeist/zettelgeist/wiki/Team).
8 |
9 |
--------------------------------------------------------------------------------
/deprecated/docs/thenote.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: page
3 | title: Note Format
4 | permalink: /notes/
5 | ---
6 |
7 | See [The Zettel Format](https://github.com/ZettelGeist/zettelgeist/wiki/The-Zettel-format).
8 |
--------------------------------------------------------------------------------
/deprecated/docs/tutorial-GDocs.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: page
3 | title: Tutorial-GDocs
4 | permalink: /tutorial-gdocs/
5 | ---
6 |
7 | See [Writing with Google Docs](https://github.com/ZettelGeist/zettelgeist/wiki/Writing-with-Google-Docs).
8 |
--------------------------------------------------------------------------------
/deprecated/docs/tutorial-Terminal.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: page
3 | title: Tutorial-Terminal
4 | permalink: /tutorial-term/
5 | ---
6 |
7 | See [Tutorial](https://github.com/ZettelGeist/zettelgeist/wiki/Tutorial).
8 |
--------------------------------------------------------------------------------
/deprecated/docs/tutorial-Word.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: page
3 | title: Tutorial-Word
4 | permalink: /tutorial-word/
5 | ---
6 |
7 | See [Writing with Word](https://github.com/ZettelGeist/zettelgeist/wiki/Word-Musings).
8 |
--------------------------------------------------------------------------------
/deprecated/zettelgeist/zfilter.py:
--------------------------------------------------------------------------------
1 | import sys
2 | import argparse
3 | import re
4 | import os
5 | import os.path
6 | import yaml
7 | import json
8 | from time import strftime
9 |
10 | from . import zdb, zettel, zquery
11 |
12 |
13 | def get_argparse():
14 | parser = zdb.get_argparse()
15 |
16 | for field in zettel.ZettelFieldsOrdered:
17 | parser.add_argument('--show-%s' % field,
18 | action='store_const', const=True, default=False,
19 | help="include field <%s> in output" % field)
20 |
21 | parser.add_argument(
22 | '--metadata', action='store_const', const=True, default=False,
23 | help="write metadata")
24 |
25 | parser.add_argument(
26 | '--query-prompt', action='store_const', const=True, default=False,
27 | help="prompt for ZQL query (overrides --query, --query-file))")
28 |
29 | parser.add_argument(
30 | '--query-file', help="load ZQL query from file (overrides --query)", default=None)
31 |
32 | parser.add_argument(
33 | '--query-string',
34 | help="load ZQL from string", default=None)
35 |
36 | parser.add_argument(
37 | '--save-query',
38 | help="save source query to file", default=None)
39 |
40 | parser.add_argument(
41 | '--trace-sql',
42 | help="log all SQL statements used to file", default=None)
43 |
44 | parser.add_argument(
45 | '--save-sql',
46 | help="save compiled SQL to file (for developers only)", default=None)
47 |
48 | parser.add_argument(
49 | '--save',
50 | help="save to output folder", required=True)
51 |
52 | parser.add_argument(
53 | '--snip-size',
54 | help="snippet size", type=int, default=2500)
55 |
56 | return parser
57 |
58 |
59 | def write_data(filename, mode, comment, statement):
60 | if not filename:
61 | return
62 | with open(filename, mode) as outfile:
63 | outfile.write("\n".join([comment, statement]) + "\n\n")
64 |
65 |
66 | def counter():
67 | i = 0
68 | while True:
69 | yield i
70 | i = i + 1
71 |
72 |
73 | def offsets_gen(int_offsets, text):
74 | iterations = len(int_offsets) // 4
75 | grouped = [tuple(int_offsets[i * 4:i * 4 + 4]) for i in range(0, iterations)]
76 | grouped = sorted(grouped, key=lambda item: item[2])
77 |
78 | for group in grouped:
79 | (column, term, pos, size) = group
80 | yield {'column': column,
81 | 'term': term,
82 | 'pos': pos,
83 | 'size': size,
84 | 'substring': text[pos:pos + size]}
85 |
86 |
87 | def process_offsets(filename, text, offsets, context):
88 | int_offsets = [int(offset) for offset in offsets.split()]
89 | results = []
90 |
91 | previous = (len(text), 0)
92 | for info in offsets_gen(int_offsets, text):
93 | pos = info['pos']
94 | offset = info['size']
95 | low_pos = max(pos - offset - context, 0)
96 | high_pos = min(pos + offset + context, len(text))
97 | if pos >= previous[0] and pos + offset <= previous[1]:
98 | continue
99 | else:
100 | previous = (low_pos, high_pos)
101 | results.append(text[low_pos:high_pos])
102 | return results
103 |
104 |
105 | def write_to_file(filepath, text, **kwargs):
106 | mode = kwargs.get("mode", "a")
107 | newlines = kwargs.get("newlines", 1)
108 | with open(filepath, mode) as outfile:
109 | outfile.write(text)
110 | if newlines:
111 | outfile.write("\n" * int(newlines))
112 |
113 |
114 | def get_context(snip):
115 | text = snip.strip()
116 | ws_matches = list(re.finditer("\s+", text))
117 | if len(ws_matches) < 2:
118 | return text
119 |
120 | first = ws_matches[0].end()
121 | last = ws_matches[-1].start()
122 | return text[first:last]
123 |
124 |
125 | # TODO Create zutils.py module
126 |
127 | def dirname(path):
128 | return os.path.split(path)[0]
129 |
130 |
131 | def basename(path):
132 | return os.path.split(path)[1]
133 |
134 | def get_match_clause(query):
135 | try:
136 | match_pos = query.find("MATCH")
137 | query = query[match_pos+len("MATCH"):]
138 | and_pos = query.find("AND")
139 | query = query[:and_pos]
140 | except:
141 | pass
142 | return query
143 |
144 | def main():
145 | parser = get_argparse()
146 | args = parser.parse_args()
147 | argsd = vars(args)
148 |
149 | output_dir = args.save
150 | if os.path.exists(output_dir):
151 | print("Will not overwrite existing directory %s (exiting)." % output_dir)
152 | sys.exit(1)
153 |
154 | try:
155 | os.mkdir(output_dir)
156 | except:
157 | print("Could not create output folder %s (exiting)." % output_dir)
158 | sys.exit(1)
159 |
160 | if args.query_prompt:
161 | input_line = input("zfilter> ")
162 | elif args.query_file:
163 | with open(args.query_file) as infile:
164 | input_line = infile.read()
165 | elif args.query_string:
166 | input_line = args.query_string
167 | else:
168 | print("No query option (--query, --query-file, or --prompt) found (exiting).")
169 | sys.exit(1)
170 |
171 | print("zfilter writing results to folder %s" % output_dir)
172 |
173 | (ast2, semantics2) = zquery.compile2(input_line)
174 | db = zdb.get(args.database)
175 | gen = None
176 | for statement in [semantics2.sql_drop_matches_table(), semantics2.sql_create_matches_table(ast2)]:
177 | write_data(args.trace_sql, "a", "", statement)
178 | gen = db.fts_query(statement)
179 | for g in gen:
180 | pass
181 |
182 | select_sql = semantics2.sql_get_matches()
183 |
184 | write_data(args.trace_sql, "a", "# query match", select_sql)
185 | write_data(args.save_query, "w", "", input_line)
186 | write_data(args.save_sql, "w", "", ast2)
187 | write_data(args.trace_sql, "a", "# saved SQL query", ast2)
188 |
189 | search_counter = counter()
190 |
191 | search_count = next(search_counter)
192 | snippets_count = 0
193 |
194 | search_result_generator = db.fts_query(select_sql)
195 |
196 | all_results = list(search_result_generator)
197 | format_d_length = len(str(len(all_results)))
198 | match_filenames = []
199 | snips_written = set()
200 |
201 | for search_result in all_results:
202 | docid = search_result['docid']
203 | base_name = output_dir + ("-%%0%dd" % format_d_length) % search_count
204 | base_path = os.path.join(output_dir, base_name)
205 | yaml_path = base_path + '.yaml.in'
206 |
207 | print("... " + yaml_path)
208 |
209 | write_to_file(
210 | yaml_path, "# Note: This is a generated .yaml.in file intended for editing (editor or zettel command)", mode="w", newlines=0)
211 |
212 | bound_query = "SELECT *,docid from zettels where docid = %(docid)s" % vars(
213 | )
214 | write_data(args.trace_sql, "a",
215 | "# finding zettels by docid", bound_query)
216 |
217 | search_details_generator = db.fts_query(bound_query)
218 | try:
219 | row = next(search_details_generator)
220 | except:
221 | print("Unexpected end of iteration")
222 |
223 | current_filename = row['filename']
224 | match_filenames.append(current_filename)
225 |
226 | write_to_file(yaml_path, "# zfind search results",
227 | mode="a", newlines=1)
228 | write_to_file(yaml_path, "# filename = %s" %
229 | current_filename, mode="a", newlines=1)
230 | write_to_file(yaml_path, "# query = %s" %
231 | input_line.strip(), mode="a", newlines=2)
232 |
233 | try:
234 | loader = zettel.ZettelLoader(row['filename'])
235 | zettels = loader.getZettels()
236 | z = next(zettels)
237 | except:
238 | print("Warning: Cannot load source Zettel %s from filesystem (using database instead)" %
239 | row['filename'])
240 | z = None
241 |
242 | snip_size = max(args.snip_size, 250)
243 | for field in zettel.ZettelFields:
244 | show_field = "show_" + field
245 | if argsd.get(show_field, None):
246 | for query in semantics2.get_field_query_sql(field, snip_size, docid):
247 | field_query_generator = db.fts_query(query)
248 | write_data(args.trace_sql, "a", "", query)
249 | for result in field_query_generator:
250 | if query.find("offsets(") >= 0:
251 | #print("Processing offsets for %s" % field)
252 | snippets = process_offsets(current_filename,
253 | result[field + "_verbatim"], result[field + "_offsets"], snip_size)
254 | snippets_count = snippets_count + len(snippets)
255 |
256 | # Write text version
257 | snip_path = base_path + '-%s.txt' % field
258 |
259 | for snip in snippets:
260 | write_to_file(snip_path, "# filename = %s" %
261 | current_filename, mode="a", newlines=1)
262 | write_to_file(snip_path, "# field = %s" %
263 | field, mode="a", newlines=2)
264 | write_to_file(snip_path, "# query = %s" % get_match_clause(query), mode="a", newlines=2)
265 | write_to_file(snip_path, snip, mode="a", newlines=2)
266 |
267 | snip_id = (field, snip_path)
268 | if snip_id not in snips_written:
269 | write_to_file(yaml_path,
270 | "# %s -> See %s for snippets." % (field, snip_path), mode="a", newlines=2)
271 | snips_written.add(snip_id)
272 |
273 | elif result[field]:
274 | write_to_file(yaml_path, z.get_yaml(
275 | [field]), mode="a", newlines=1)
276 |
277 | search_count = next(search_counter)
278 |
279 | if False:
280 | drop_temp_matches_table = semantics2.sql_drop_matches_table()
281 | write_data(args.trace_sql, "a", "", drop_temp_matches_table)
282 | gen = db.fts_query(drop_temp_matches_table)
283 | for g in gen:
284 | pass
285 |
286 | if args.metadata:
287 | stats_path = os.path.join(output_dir, output_dir + '-stats.json')
288 | files_path = os.path.join(output_dir, output_dir + '-fileset.txt')
289 |
290 | doc = {'count': search_count,
291 | 'query': input_line.strip(),
292 | 'snips': list(snips_written)}
293 |
294 | write_to_file(stats_path,
295 | json.dumps(doc, indent=4, sort_keys=True), mode="w", newlines=1)
296 | write_to_file(files_path, "\n".join(
297 | match_filenames), mode="w", newlines=1)
298 |
299 |
300 | if __name__ == '__main__':
301 | main()
302 |
--------------------------------------------------------------------------------
/docs/.gitignore:
--------------------------------------------------------------------------------
1 | _site
2 | .sass-cache
3 | .jekyll-metadata
4 |
--------------------------------------------------------------------------------
/docs/.nojekyll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ZettelGeist/zettelgeist/477fa5427f089f9b9092c45f87f32a93af73e695/docs/.nojekyll
--------------------------------------------------------------------------------
/docs/RELEASING.md:
--------------------------------------------------------------------------------
1 | # Notes to Selves
2 |
3 | - Start by updating `zversion.py`
4 |
5 | - We only use major, minor, and point releases (x.y.z)
6 |
7 | - To bump the release, modify `zversion.py`. At some point, we may add a "version bumping" framework, e.g. bump2version, but I don't see an immediate need for this yet.
8 |
9 | - Commit the changes
10 |
11 | - Tag a release in GitHub. Note that releasing on PyPI and releasing on GitHub are two different things. You can avoid having to keep track by runnign `git tag $(python setup.py --version)`. This will give the version that is associated with the Python setup.py file and use it not only to make a release but to ensure this release triggers a release on PyPI.
12 |
13 | - Make sure not only to `git push` but to `git push --tags`.
14 |
--------------------------------------------------------------------------------
/docs/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
Redirecting to https://github.com/ZettelGeist/zettelgeist/wiki
4 |
5 |
6 |
--------------------------------------------------------------------------------
/jupyter/xyz.txt:
--------------------------------------------------------------------------------
1 | @misc{blahblahblah,
2 | title = {In Depth - In Depth: Ray Kurzweil - Book {TV}},
3 | url = {http://www.booktv.org/Program/7515/In+Depth+Ray+Kurzweil.aspx},
4 | urldate = {2011-02-11},
5 | keywords = {*{AddedToZettels}},
6 | file = {In Depth - In Depth\: Ray Kurzweil - Book TV:/Users/dbdennis/Library/Application Support/Zotero/Profiles/duztnovb.default/zotero/storage/TWWBX3QV/In+Depth+Ray+Kurzweil.html:text/html}
7 | }
8 |
--------------------------------------------------------------------------------
/project/assembly.sbt:
--------------------------------------------------------------------------------
1 | addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.14.1")
2 |
3 |
--------------------------------------------------------------------------------
/project/build.properties:
--------------------------------------------------------------------------------
1 | sbt.version=0.13.15
2 |
--------------------------------------------------------------------------------
/project/plugins.sbt:
--------------------------------------------------------------------------------
1 | addSbtPlugin("org.scalariform" % "sbt-scalariform" % "1.6.0")
2 | addSbtPlugin("com.timushev.sbt" % "sbt-updates" % "0.1.9")
3 | addSbtPlugin("org.scalastyle" %% "scalastyle-sbt-plugin" % "0.8.0")
4 |
5 |
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | python-frontmatter
2 | tatsu
3 |
--------------------------------------------------------------------------------
/scripts/deploy.sh:
--------------------------------------------------------------------------------
1 | #
2 | # Deploy to PyPI. Don't run this script.
3 | #
4 |
5 | rm -rf dist/*
6 | python setup.py sdist bdist_wheel
7 | twine upload --repository pypi dist/*
8 |
9 |
--------------------------------------------------------------------------------
/setup.cfg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ZettelGeist/zettelgeist/477fa5427f089f9b9092c45f87f32a93af73e695/setup.cfg
--------------------------------------------------------------------------------
/setup.py:
--------------------------------------------------------------------------------
1 | # setup.py - placeholder for eventual setup script
2 |
3 | from setuptools import setup
4 | from zettelgeist import zversion
5 |
6 | setup(
7 | name='zettelgeist',
8 | packages=['zettelgeist'],
9 | version=zversion.version(),
10 | description='ZettelGeist - a historiographically focused notetaking system',
11 | long_description='ZettelGeist - a historiographically focused notetaking system',
12 | author='ZettelGeist Laboratories',
13 | author_email='gkt@cs.luc.edu',
14 | license='Apache License 2.0',
15 | url='https://github.com/zettelgeist/zettelgeist',
16 | keywords=['notetaking', 'YAML', 'Markdown', 'sqlite3', 'GitHub'],
17 | classifiers=[
18 | 'Development Status :: 4 - Beta',
19 | 'Programming Language :: Python :: 3',
20 | "Programming Language :: Python :: 3.10",
21 | "Programming Language :: Python :: 3 :: Only",
22 | "Topic :: Software Development",
23 | 'License :: OSI Approved :: Apache Software License'
24 | ],
25 | python_requires='>=3.10',
26 | install_requires=[
27 | 'python-frontmatter',
28 | 'tatsu'
29 | ],
30 | entry_points = {
31 | 'console_scripts': [
32 | 'zcreate = zettelgeist.zcreate:main',
33 | 'zimport = zettelgeist.zimport:main',
34 | 'zfind = zettelgeist.zfind:main',
35 | 'zettel = zettelgeist.zettel:main'
36 | ]
37 | }
38 | )
39 |
--------------------------------------------------------------------------------
/sphinx-docs/Makefile:
--------------------------------------------------------------------------------
1 | # Minimal makefile for Sphinx documentation
2 | #
3 |
4 | # You can set these variables from the command line, and also
5 | # from the environment for the first two.
6 | SPHINXOPTS ?=
7 | SPHINXBUILD ?= sphinx-build
8 | SOURCEDIR = source
9 | BUILDDIR = build
10 |
11 | # Put it first so that "make" without argument is like "make help".
12 | help:
13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
14 |
15 | .PHONY: help Makefile
16 |
17 | # Catch-all target: route all unknown targets to Sphinx using the new
18 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
19 | %: Makefile
20 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
21 |
--------------------------------------------------------------------------------
/sphinx-docs/make.bat:
--------------------------------------------------------------------------------
1 | @ECHO OFF
2 |
3 | pushd %~dp0
4 |
5 | REM Command file for Sphinx documentation
6 |
7 | if "%SPHINXBUILD%" == "" (
8 | set SPHINXBUILD=sphinx-build
9 | )
10 | set SOURCEDIR=source
11 | set BUILDDIR=build
12 |
13 | if "%1" == "" goto help
14 |
15 | %SPHINXBUILD% >NUL 2>NUL
16 | if errorlevel 9009 (
17 | echo.
18 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
19 | echo.installed, then set the SPHINXBUILD environment variable to point
20 | echo.to the full path of the 'sphinx-build' executable. Alternatively you
21 | echo.may add the Sphinx directory to PATH.
22 | echo.
23 | echo.If you don't have Sphinx installed, grab it from
24 | echo.http://sphinx-doc.org/
25 | exit /b 1
26 | )
27 |
28 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
29 | goto end
30 |
31 | :help
32 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
33 |
34 | :end
35 | popd
36 |
--------------------------------------------------------------------------------
/sphinx-docs/source/about.rst:
--------------------------------------------------------------------------------
1 | About
2 | ======
3 |
4 | ZettelGeist is a plaintext note-taking system, inspired by the
5 | `ZettelKasten
6 | Method `__.
7 |
8 | The project founders have both been interested in taking notes long
9 | before discovering ZettelKasten. We really like the thought process
10 | behind ZettelKasten, however, and think it is ahead of its time by being
11 | “less is more” in its focus.
12 |
13 | A key, salient feature of our approach to implementing a ZettelKasten
14 | system is *not* to get distracted by GUI tools at an early stage of
15 | development. The default assumption of our system is that we work from
16 | plaintext files. We are particularly inspired by systems like Jekyll (a
17 | static-site generator for building web sites) that uses YAML to organize
18 | its front matter and Markdown as the body. We’re even starting more
19 | simply by just using YAML without Markdown, although we might introduce
20 | it at release time. The idea is to focus on true notetaking by not
21 | encouraging the writing of large, complex documents (which aren’t really
22 | notes, right??)
23 |
24 | So ZettelGeist is aimed at supporting the *spirit* of ZettelKasten,
25 | while ensuring that it will be useful in other domains. Our primary
26 | audience is the scholar who wants to write notes using a simple text
27 | editor and storing these notes in the cloud, e.g. in Dropbox, GitHub,
28 | etc. While we’d love to build something like the successor to Evernote
29 | or OneNote–even as a graphical client–our view is that no such tool
30 | should be developed without having the right core abstractions in place.
31 | Ultimately, the *note* is the central abstraction. Having support for
32 | metadata is crucial, especially for scholarly–or other serious–projects.
33 |
34 | Stay tuned!!
35 |
--------------------------------------------------------------------------------
/sphinx-docs/source/conf.py:
--------------------------------------------------------------------------------
1 | # Configuration file for the Sphinx documentation builder.
2 | #
3 | # This file only contains a selection of the most common options. For a full
4 | # list see the documentation:
5 | # https://www.sphinx-doc.org/en/master/usage/configuration.html
6 |
7 | # -- Path setup --------------------------------------------------------------
8 |
9 | # If extensions (or modules to document with autodoc) are in another directory,
10 | # add these directories to sys.path here. If the directory is relative to the
11 | # documentation root, use os.path.abspath to make it absolute, like shown here.
12 | #
13 | import os
14 | import sys
15 | # sys.path.insert(0, os.path.abspath('.'))
16 |
17 |
18 | # -- Project information -----------------------------------------------------
19 |
20 | project = 'ZettelGeist'
21 | copyright = '2020, George K. Thiruvathukal and David B. Dennis'
22 | author = 'George K. Thiruvathukal and David B. Dennis'
23 |
24 | # The full version, including alpha/beta/rc tags
25 | version = os.environ.get("BOOK_VERSION", "beta")
26 | release = version
27 |
28 |
29 | rst_epilog = """
30 |
31 | .. |site-version| replace:: **version %(version)s**
32 |
33 | """ % vars()
34 |
35 | # -- General configuration ---------------------------------------------------
36 |
37 | # Add any Sphinx extension module names here, as strings. They can be
38 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
39 | # ones.
40 | extensions = [
41 | 'sphinx.ext.todo',
42 | 'sphinx.ext.mathjax',
43 | ]
44 |
45 | # Add any paths that contain templates here, relative to this directory.
46 | templates_path = ['_templates']
47 | source_suffix = ['.rst', '.md']
48 |
49 | # List of patterns, relative to source directory, that match files and
50 | # directories to ignore when looking for source files.
51 | # This pattern also affects html_static_path and html_extra_path.
52 | exclude_patterns = []
53 |
54 |
55 | # -- Options for HTML output -------------------------------------------------
56 |
57 | # The theme to use for HTML and HTML Help pages. See the documentation for
58 | # a list of builtin themes.
59 | #
60 | html_theme = 'alabaster'
61 |
62 | html_theme_options = {
63 | 'logo': 'peace.png',
64 | 'github_user': 'zettelgeist',
65 | 'github_repo': 'zettelgeist',
66 | #'analytics_id' : 'UA-23507985-1',
67 | 'extra_nav_links' : {
68 | 'Site Index' : 'genindex.html',
69 | 'Software Systems Laboratory' : 'https://ssl.cs.luc.edu',
70 | }
71 | }
72 |
73 | # Add any paths that contain custom static files (such as style sheets) here,
74 | # relative to this directory. They are copied after the builtin static files,
75 | # so a file named "default.css" will overwrite the builtin "default.css".
76 | html_static_path = ['_static']
77 |
--------------------------------------------------------------------------------
/sphinx-docs/source/gs.rst:
--------------------------------------------------------------------------------
1 | Getting Started
2 | ===================
3 |
4 |
5 | Prerequisites
6 | -------------
7 |
8 | Please visit the `Installation `__ before starting the
9 | tutorial. This tutorial assumes you have installed ZettelGeist and have
10 | confirmed that the tools are available in a Python virtualenv.
11 |
12 | We assume that your virtualenv is named ``zenv`` here. Wherever you see
13 | ``zenv`` here, your setup can be different, as long as you completed the
14 | installation and verified that it is nominally functioning.
15 |
16 | This tutorial also depends on sample files, provided at
17 | https://github.com/ZettelGeist/zg-tutorial. You can visit this page to
18 | download the examples, or you can use ``git`` to fetch it:
19 |
20 | .. code:: shell
21 |
22 | $ git clone https://github.com/ZettelGeist/zg-tutorial.git
23 |
24 | This will create the folder ``zg-tutorial``, which we’ll reference in
25 | this tutorial.
26 |
27 | Creating Zettels
28 | ----------------
29 |
30 | The ``zettel`` command is used to create zettels. You can also create
31 | zettels using an ordinary text editor.
32 |
33 | Getting help
34 | ~~~~~~~~~~~~
35 |
36 | .. code:: shell
37 |
38 | zettel --help
39 |
40 | The help shows what at first glance appears to be a bewildering number
41 | of options. However, most of the options are *the same* and are just
42 | being used to do an operation (set, delete, append, etc.) on any given
43 | field.
44 |
45 | Create a simple zettel
46 | ~~~~~~~~~~~~~~~~~~~~~~
47 |
48 | .. code:: shell
49 |
50 | zettel --set-title "My First Zettel"
51 |
52 | This results in the following output:
53 |
54 | .. code:: yaml
55 |
56 | title: My First Zettel
57 |
58 | Create zettel with multiple fields
59 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
60 |
61 | A zettel can have as few fields as you wish, including zero. However, a
62 | zettel only becomes interesting as you add more information. Let’s add a
63 | *summary* and a *note*.
64 |
65 | .. code:: shell
66 |
67 | zettel --set-title "My First Zettel" --set-summary "A Zettel with a note" --set-note "Line 1\nLine 2\nLine 3"
68 |
69 | This results in
70 |
71 | .. code:: yaml
72 |
73 | title: My First Zettel
74 | summary: A Zettel with a note
75 | note: |-
76 | Line 1
77 | Line 2
78 | Line 3
79 |
80 | When setting a field to a string value as we have done for each of these
81 | fields, it is permitted to have *embedded newlines* anywhere you like.
82 | For the note we have written, we have three input lines, each of which
83 | appears on a separate line.
84 |
85 | YAML (the format in which Zettels are stored) provides excellent support
86 | for this concept and will take your text and indent it using a multiline
87 | string. As long as each line is indented consistently relative to the
88 | *note* key, it will be valid.
89 |
90 | Obviously, writing longer strings using the command line is sometimes
91 | impractical, so we created two ways of being able to do this easily:
92 | prompting for input (using the ``--prompt-`` options) or by
93 | loading the plaintext from a file (using ``--load-``). Each of
94 | these is easy to demonstrate.
95 |
96 | Let’s try loading some text by having ``zettel`` prompt for it. We’ll
97 | modify the above command as follows:
98 |
99 | .. code:: shell
100 |
101 | zettel --set-title "My First Zettel" --set-summary "A Zettel with a note" --prompt-note
102 |
103 | ::
104 |
105 | Enter text for note. ctrl-d to end.
106 | note> Line 1
107 | note> Line 2
108 | note> Line 3
109 | note>
110 | note> Even a blank line is allowed.
111 | note>
112 |
113 | Results
114 |
115 | .. code:: yaml
116 |
117 | title: My First Zettel
118 | summary: A Zettel with a note
119 | note: |-
120 | Line 1
121 | Line 2
122 | Line 3
123 |
124 | Even a blank line is allowed.
125 |
126 | Load field from another file
127 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
128 |
129 | TODO
130 |
131 | Indexing Zettels for Search
132 | ---------------------------
133 |
134 | For this section, we provide you with access to some sample zettels.
135 | These can be found in the ZettelGeist tutorial repository at
136 | https://github.com/ZettelGeist/zg-tutorial.git. (See Prerequisites
137 | above.)
138 |
139 | You can be in any folder while trying this, but we’ll assume you are in
140 | the ``zettelgeist\docs`` after performing an initial clone of our
141 | repository.
142 |
143 | .. code:: shell
144 |
145 | $ cd zg-tutorial
146 | $ zcreate --database mlb.db
147 | Creating new database mlb.db
148 |
149 |
150 | .. code:: shell
151 |
152 | $ ls zettels/baseball
153 |
154 | arizona-diamondbacks.yaml milwaukee-brewers.yaml
155 | atlanta-braves.yaml minnesota-twins.yaml
156 | baltimore-orioles.yaml new-york-mets.yaml
157 | boston-red-sox.yaml new-york-yankees.yaml
158 | chicago-cubs.yaml oakland-athletics.yaml
159 | chicago-grey-sox.yaml philadelphia-phillies.yaml
160 | cincinnati-reds.yaml pittsburgh-pirates.yaml
161 | cleveland-indians.yaml san-diego-padres.yaml
162 | colorado-rockies.yaml seattle-mariners.yaml
163 | detroit-tigers.yaml st-louis-cardinals.yaml
164 | houston-astros.yaml tampa-bay-rays.yaml
165 | kansas-city-royals.yaml texas-rangers.yaml
166 | los-angeles-angels.yaml toronto-blue-jays.yaml
167 | los-angeles-dodgers.yaml washington-nationals.yaml
168 | miami-marlins.yaml```
169 |
170 |
171 | .. code:: shell
172 |
173 | $ zimport --database mlb.db --dir $(pwd)
174 |
175 | Importing /Users/gkt/Work/zg-tutorial/zettels/baseball/baltimore-orioles.yaml
176 | Importing /Users/gkt/Work/zg-tutorial/zettels/baseball/kansas-city-royals.yaml
177 | Importing /Users/gkt/Work/zg-tutorial/zettels/baseball/los-angeles-angels.yaml
178 | Importing /Users/gkt/Work/zg-tutorial/zettels/baseball/miami-marlins.yaml
179 | Importing /Users/gkt/Work/zg-tutorial/zettels/baseball/milwaukee-brewers.yaml
180 | Importing /Users/gkt/Work/zg-tutorial/zettels/baseball/seattle-mariners.yaml
181 | Importing /Users/gkt/Work/zg-tutorial/zettels/baseball/arizona-diamondbacks.yaml
182 | Importing /Users/gkt/Work/zg-tutorial/zettels/baseball/st-louis-cardinals.yaml
183 | Importing /Users/gkt/Work/zg-tutorial/zettels/baseball/houston-astros.yaml
184 | Importing /Users/gkt/Work/zg-tutorial/zettels/baseball/oakland-athletics.yaml
185 | Importing /Users/gkt/Work/zg-tutorial/zettels/baseball/boston-red-sox.yaml
186 | Importing /Users/gkt/Work/zg-tutorial/zettels/baseball/new-york-yankees.yaml
187 | Importing /Users/gkt/Work/zg-tutorial/zettels/baseball/pittsburgh-pirates.yaml
188 | Importing /Users/gkt/Work/zg-tutorial/zettels/baseball/detroit-tigers.yaml
189 | Importing /Users/gkt/Work/zg-tutorial/zettels/baseball/cincinnati-reds.yaml
190 | [...]
191 |
192 | What you see will differ slightly. Where you see ``/Users/gkt/Work``,
193 | you are likely to see the path to your own checkout directory.
194 |
195 | Let’s look at one of these zettels.
196 |
197 | .. code:: yaml
198 |
199 | title: MLB Teams
200 | summary: Arizona Diamondbacks
201 | note: |
202 | The Arizona Diamondbacks, often shortened as the D-backs, are an American professional
203 | baseball franchise based in Phoenix, Arizona. The club competes in Major League
204 | Baseball (MLB) as a member of the National League (NL) West division. Since the
205 | team's inception in 1998, the franchise has played home games at Chase Field, formerly
206 | known as Bank One Ballpark. The Diamondbacks have won one World Series championship
207 | (in 2001), becoming the fastest expansion team in the Major Leagues to win a championship,
208 | doing it in only the fourth season since the franchise's inception in the 1998 Major
209 | League Baseball season.
210 | tags:
211 | - MLB
212 | - National League
213 | - NL West
214 | cite:
215 | bibkey: arizona-diamondbacks-wikipedia
216 | page: web page
217 |
218 | Each of these zettels contains some information one might typically
219 | place on a note card. In our view of the world, notes would include
220 | important basics. The note will often be one of the longer fields. It
221 | can be written using what is known as the YAML block style. This means
222 | that all lines of input are taken, provided they maintain the same
223 | indentation level and/or blank. Everything will be taken as input until
224 | the next field or end of file is found.
225 |
226 | Also shown here are how you can maintain a list of tags. The ``tags``
227 | field allows you to specify one or more tags. While we hope one day to
228 | build an auto-classifier (someday, someday…), we find that we actually
229 | need to assign labels, especially in our own book project that is
230 | actually making use of these tools.
231 |
232 | Search Examples
233 | ---------------
234 |
235 | Searching is done (at present) using the ``zfind`` tool. This tool can
236 | only perform AND-style queries, but it will soon offer every conceivable
237 | possibility. This limitation is similar to what you find in systems like
238 | Gmail’s search operators, but even Gmail allows for NOT terms.
239 |
240 | The ``zfind`` tool has options to search every field. Once a field
241 | matches, you can use the show options to project values from the Zettel.
242 | There is also a ``--count`` option to tell you how many Zettels matched
243 | a query.
244 |
245 | Find how many Zettels mention Chicago in the ``summary`` field:
246 |
247 | ::
248 |
249 | zfind --database mlb.db --find-summary Chicago --count
250 | 2 Zettels matched search
251 |
252 | …and print the ``summary and``\ filename\` of the zettels:
253 |
254 | ::
255 |
256 | zfind --database mlb.db --find-summary Chicago --count --show-filename
257 | filename:
258 | 20170731132024-chicago-cubs.yaml
259 |
260 | ----------------------------------------
261 |
262 | filename:
263 | 20170731155613-chicago-grey-sox.yaml
264 |
265 | ----------------------------------------
266 |
267 | 2 Zettels matched search
268 |
269 | …and show the ``summary`` about the teams:
270 |
271 | ::
272 |
273 | zfind --database mlb.db --find-summary Chicago --count --show-filename --show-summary
274 | summary:
275 | Chicago Cubs
276 |
277 | filename:
278 | 20170731132024-chicago-cubs.yaml
279 |
280 | ----------------------------------------
281 |
282 | summary:
283 | Chicago White Sox
284 |
285 | filename:
286 | 20170731155613-chicago-grey-sox.yaml
287 |
288 | ----------------------------------------
289 |
290 | Find the terms MLB and Central in the ``note`` field. Upon finding a
291 | match, show the ``filename`` and the ``summary`` fields.
292 |
293 | ::
294 |
295 | zfind --database mlb.db --find-note "MLB Central" --show-filename --show-summary
296 | summary:
297 | Chicago Cubs
298 |
299 | filename:
300 | 20170731132024-chicago-cubs.yaml
301 |
302 | ----------------------------------------
303 |
304 | summary:
305 | Cincinnati Reds
306 |
307 | filename:
308 | 20170731133642-cincinnati-reds.yaml
309 |
310 | ----------------------------------------
311 |
312 | summary:
313 | Pittsburgh Pirates
314 |
315 | filename:
316 | 20170731135121-pittsburgh-pirates.yaml
317 |
318 | ----------------------------------------
319 |
320 | summary:
321 | St. Louis Cardinals
322 |
323 | filename:
324 | 20170731135823-st-louis-cardinals.yaml
325 |
326 | ----------------------------------------
327 |
328 | Find all zettels with Cubs mentioned in the ``note`` field:
329 |
330 | ::
331 |
332 | zfind --database mlb.db --find-note Cubs --show-note
333 |
334 | note:
335 | The Chicago Cubs are an American professional baseball team based in Chicago, Illinois. The Cubs compete in Major League Baseball (MLB) as a member club of the National League (NL) Central division, where they are the defending World Series champions. The team plays its home games at Wrigley Field, located on the city's North Side. The Cubs are one of two major league teams in Chicago; the other, the Chicago White Sox, is a member of the American League (AL) Central division. The Cubs, first known as the White Stockings, was a founding member of the NL in 1876, becoming the Chicago Cubs in 1903.[2] The Cubs have appeared in a total of eleven World Series. The 1906 Cubs won 116 games, finishing 116–36 and posting a modern-era record winning percentage of .763, before losing the World Series to the Chicago White Sox by four games to two. The Cubs won back-to-back World Series championships in 1907 and 1908, becoming the first major league team to play in three consecutive World Series, and the first to win it twice. Most recently, the Cubs won the 2016 National League Championship Series and 2016 World Series, which ended a 71-year National League pennant drought and a 108-year World Series championship drought,
336 |
--------------------------------------------------------------------------------
/sphinx-docs/source/index.rst:
--------------------------------------------------------------------------------
1 | Welcome to ZettelGeist
2 | ======================
3 |
4 | ZettelGeist is research software for plaintext notettaking.
5 |
6 | .. toctree::
7 | :hidden:
8 | :caption: Contents:
9 |
10 | about
11 | gs
12 | install
13 | team
14 | thenote
15 | tutorial-gdocs
16 | tutorial-terminal
17 | tutorial-world
18 |
--------------------------------------------------------------------------------
/sphinx-docs/source/install.rst:
--------------------------------------------------------------------------------
1 | Prerequisites for All Installations
2 | -----------------------------------
3 |
4 | Python 3 is *required* to use ZettelGeist. We don’t have resources to
5 | support multiple versions of Python.
6 |
7 | We also recommend installing
8 | `bibutils `__ and
9 | `sqlite3 with full-text search `__.
10 | You may not need either of these, but should you run into issues, we may
11 | ask you to share some output from sqlite3 commands with us in your bug
12 | reports.
13 |
14 | We only support Unix/Linux, OS X using `Homebrew `__,
15 | and Windows using `Windows Subsystem for
16 | Linux `__.
17 |
18 | Please also note that ZettelGeist is not a web-based or GUI program
19 | (yet). This system is for people who *prefer* working with plaintext,
20 | text editors, and the command line. If this is not you, you will
21 | probably not like ZettelGeist and should proceed at your own peril.
22 |
23 | Installation for General Users
24 | ------------------------------
25 |
26 | - Create a virtual environment for running ZettelGeist:
27 |
28 | .. code:: shell
29 |
30 | python3 -m venv ~/zenv
31 |
32 | You can install your environment wherever you like, but we are going
33 | to assume ``~/zenv`` in the remaining discussion and in our tutorial
34 | to *avoid* having to talk about user-specific details.
35 |
36 | - Source the virtual environment
37 |
38 | .. code:: shell
39 |
40 | . ~/zenv/bin/activate
41 |
42 | - And *ensure* that you are picking up the right ``python`` and
43 | ``pip``.
44 |
45 | .. code:: shell
46 |
47 | ~ . ~/zenv/bin/activate
48 | (zenv) ~ which pip
49 | /Users/gkt/zenv/bin/pip
50 | (zenv) ~ which python
51 | /Users/gkt/zenv/bin/python
52 |
53 | Your username would likely appear above instead of *gkt*, unless you
54 | share my initials.
55 |
56 | - Now install ZettelGeist
57 |
58 | .. code:: shell
59 |
60 | (zenv) ~ pip install zettelgeist
61 | Collecting zettelgeist
62 | Downloading zettelgeist-0.12.2-py3-none-any.whl
63 | Collecting tatsu (from zettelgeist)
64 | Using cached TatSu-4.2.5-py2.py3-none-any.whl
65 | Collecting PyYAML (from zettelgeist)
66 | Installing collected packages: tatsu, PyYAML, zettelgeist
67 | Successfully installed PyYAML-3.12 tatsu-4.2.5 zettelgeist-0.12.2
68 |
69 | If you see ``zettelgeist-`` in the above output, you should
70 | have a successful install. Let’s verify:
71 |
72 | .. code:: shell
73 |
74 | (zenv) ~ which zcreate
75 | /Users/gkt/zenv2/bin/zcreate
76 | (zenv) ~ which zimport
77 | /Users/gkt/zenv2/bin/zimport
78 | (zenv) ~ which zquicksearch
79 | /Users/gkt/zenv2/bin/zquicksearch
80 | (zenv) ~ which zfilter
81 | /Users/gkt/zenv2/bin/zfilter
82 | (zenv) ~ which zettel
83 | /Users/gkt/zenv2/bin/zettel
84 |
85 | - And create your first zettel:
86 |
87 | .. code:: shell
88 |
89 | zettel --set-title "My First Zettel" --set-summary "I feel empowered." --append-tags "Tutorial" "ZettelGeist" "Install"
90 | title: My First Zettel
91 | summary: I feel empowered.
92 | tags:
93 | - Tutorial
94 | - ZettelGeist
95 | - Install
96 |
97 | - Then you should proceed to the `Getting Started `__ page.
98 |
99 | Developer Install
100 | -----------------
101 |
102 | Coming soon.
103 |
--------------------------------------------------------------------------------
/sphinx-docs/source/team.rst:
--------------------------------------------------------------------------------
1 | Team
2 | ==========
3 |
4 |
5 | - `George K. Thiruvathukal `__ -
6 | Professor of Computer Science at Loyola University Chicago
7 | - `David B. Dennis `__
8 | - Professor of History at Loyola University Chicago
9 |
--------------------------------------------------------------------------------
/sphinx-docs/source/thenote.rst:
--------------------------------------------------------------------------------
1 | The Note Format
2 | =================
3 |
4 | A note is nothing more than a YAML document. Please note that,
5 | hereafter, we may use the terms notes, cards, and zettels rather
6 | interchangeably. We’ve used other systems and sometimes find ourselves
7 | using the terminology rather freely.
8 |
9 | When we use the term *note*, please keep in mind that the term as we see
10 | it is interchangeable with *index cards*, *cards*, or *zettels*. So
11 | regardless of what terminlology you prefer, we welcome you!
12 |
13 | Anyway, the idea of notetaking is to keep it simple, so a note should
14 | make no assumptions about formatting whatsoever. In our view of the
15 | world, we should be able to introduce other fields but are hopeful that
16 | we have identified most of the important ones.
17 |
18 | In our current thinking, we have the following sections:
19 |
20 | - title: an optional title (string)
21 | - tags: one or more keywords (list of string)
22 | - mentions: one or more mentions (list of string)
23 | - dates: a year (string) and era (string) as a nested dictionary
24 | - bibtex, ris, or inline (string)
25 | - url (string)
26 | - bibkey (string)
27 | - cite: a bibkey (from same or another zettel) and a page number (or
28 | range of page numbers)
29 | - summary: (string) - concise summary of the note (by convention)
30 | - note (string) - details, usually the text you are wanting to cite
31 | - comment (string) - any comment you want to make about the zettel in
32 | general
33 |
34 | In most situations, freeform text is permitted. In some situations, you
35 | will need to put quotes around the text, especially if you are using
36 | reserved YAML characters.
37 |
38 | These all are intended to be string data, so there are no restrictions
39 | on what can be in any field; however, we will likely limit tags,
40 | mentions, dates in some way as we go forward. Fields such as bibtex,
41 | ris, or inline are also subject to validity checking.
42 |
43 | Here’s an example where of a zettel where most fields are being used.
44 |
45 | .. code:: yaml
46 |
47 | title: First BIB Note for Castells
48 | tags:
49 | - Castells
50 | - Network Society
51 | - Charles Babbage is Awesome
52 | - Charles Didn't do Everything
53 | mentions:
54 | - gkt
55 | - dbdennis
56 | dates:
57 | year: "2016"
58 | era: "AD"
59 | cite:
60 | bibkey: Castells Rise 2016
61 | page: ii-iv
62 | comment: This is my first zettel but my comments have nothing to do with the note itself.
63 | summary: Lorem ipsum rocks. This is a summary of what you see in the note field.
64 | note: |
65 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam eleifend est sed diam maximus rutrum. Quisque sit amet imperdiet odio, id tristique libero. Aliquam viverra convallis mauris vel tristique. Cras ac dolor non risus porttitor molestie vel at nisi. Donec vitae finibus quam. Phasellus vehicula urna sed nibh condimentum, ultrices interdum velit eleifend. Nam suscipit dolor eu rutrum fringilla. Sed pulvinar purus purus, sit amet venenatis enim convallis a. Duis fringilla nisl sit amet erat lobortis dictum. Nunc fringilla arcu nec ex blandit, a gravida purus commodo. Vivamus lacinia tellus dui, vel maximus lacus ornare id.
66 |
67 | Vivamus euismod justo sit amet luctus bibendum. Integer non mi ullamcorper enim fringilla vulputate sit amet in urna. Nullam eu sodales ipsum. Curabitur id convallis ex. Duis a condimentum lorem. Nulla et urna massa. Duis in nibh eu elit lobortis vehicula. Mauris congue mauris mollis metus lacinia, ut suscipit mi egestas. Donec luctus ante ante, eget viverra est mollis vitae.
68 |
69 | Vivamus in purus in erat dictum scelerisque. Aliquam dictum quis ligula ac euismod. Mauris elementum metus vel scelerisque feugiat. Vivamus bibendum massa eu pellentesque sodales. Nulla nec lacus dolor. Donec scelerisque, nibh sed placerat gravida, nunc turpis tristique nibh, ac feugiat enim massa ut eros. Nulla finibus, augue egestas hendrerit accumsan, tellus augue tempor eros, in sagittis dolor turpis nec mi. Nunc fringilla mi non malesuada aliquet.
70 | bibkey:
71 | Castells Rise 1996
72 | bibtex: |
73 | @book{castells_rise_1996,
74 | address = {Cambridge, Mass.},
75 | series = {Castells, {Manuel}, 1942- {Information} age . v},
76 | title = {The rise of the network society},
77 | isbn = {978-1-55786-616-5},
78 | language = {eng},
79 | publisher = {Blackwell Publishers},
80 | author = {Castells, Manuel},
81 | year = {1996},
82 | keywords = {Information networks., Information society., Information technology Economic aspects., Information technology Social aspects., Technology and civilization.}
83 | }
84 |
85 | Here is a simple example of a bookmark:
86 |
87 | .. code:: yaml
88 |
89 | title: Zettelgeist.com
90 | url: http://zettelgeist.com
91 | note: Zettelgeist is a plaintext notetaking system designed for scholarly/research purposes.
92 |
93 | It’s really that simple!
94 |
--------------------------------------------------------------------------------
/sphinx-docs/source/tutorial-gdocs.rst:
--------------------------------------------------------------------------------
1 | Gdocs
2 | ========
3 |
4 |
5 | **This page is under construction. Pardon the sketchiness for now.**
6 |
7 | What do you want to do?
8 | -----------------------
9 |
10 | - Take research notes for a paper in order to be able to search them
11 | for … anything.
12 |
13 | - Follow the traditional (and ever-valid) methods of writing a note
14 | with a title, some keywords (tags), a note (with comment or summary
15 | if desired), and some bibliographical information (book or article
16 | title and page number[s]).
17 |
18 | - Find particular notes on particular themes and issues.
19 |
20 | - Send those particular notes to a file that will be the basis for a
21 | portion of your outline or draft.
22 |
23 | All of these basic research, organization, and writing steps are steeped in traditional methods.
24 | ------------------------------------------------------------------------------------------------
25 |
26 | - As researchers and writers of papers, articles, books – from grade
27 | school, high school, college, graduate school, through our
28 | professional writings – as well as teachers and editors of countless
29 | efforts by others, we know the game. Indeed, we are the coaches and
30 | referees and main players of the game! And our own coaches taught us
31 | how to do it right!
32 |
33 | - On the basis of this experience, we made ZettelGeist to do the most
34 | important, fundamental steps of research and writing as clearly and
35 | directly as possible, based on the methods that our mentors used to
36 | write great books before personal computers came into being.
37 |
38 | - But because we are ourselves computerized (having come into
39 | professional life just as the pc revolution occurred and, therefore,
40 | having played *that game* ever since), we have here merged these
41 | techniques into the computer world more directly than any program has
42 | before. (Believe us: we know! We have tried and deployed every option
43 | out there, from 1980 until yesterday – as a matter of professional
44 | need.)
45 |
46 | - Since we know the frustration that many so-called “notetaking
47 | programs” cause, we have made a fundamental decision to ensure that
48 | the basis for all of this is already in the computer you own and the
49 | internet sites you have access to.
50 |
51 | - You don’t have to go and buy anything new. You already have
52 | *supercomputers* that earlier great writers could never have
53 | imagined. This system will just help you to take advantage of these
54 | machines in ways consistent with the key principles of research and
55 | organization that the great writers developed, but most computer
56 | programs have left out.
57 |
58 | - This is the Research-Writing-Computer Singularity we have been
59 | waiting for!
60 |
61 | The first thing to know is that with ZettelGeist you can do ALL of the above by starting (and finishing) your writing with ANY SOFTWARE YOU WANT TO USE!! The ZettelGeist program works with and *between* your preferred word processors.
62 | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
63 |
64 | - Many programs suggest they are “app-gnostic” (agnostic or indifferent
65 | about which app you use), but that usually just means you can save
66 | your work into another format (docx, pdf, txt, etc.).
67 |
68 | - ZettelGeist is truly app neutral in the sense that you can make notes
69 | (zettels) with any software, as long as you make them according to a
70 | certain pattern (indicating note section, title section, etc…) and
71 | save or download them in good old “.txt” format.
72 |
73 | - The “pattern” is exactly what you would use to write out a notecard
74 | in the traditional way (by hand, or typed on paper or computer), so
75 | it really isn’t that big a deal. Plus, once you make one card (or
76 | zettel), you can just edit the same card to make any necessary
77 | changes for the next card (change the note, change the page numbers,
78 | etc.) then save the new card with a new filename, eg. “note02.txt”
79 | and move on…
80 |
81 | - You can do this with ANY word processor you want to use: Google Docs,
82 | Microsoft Word, LibreOffice. In fact, you could just use one of the
83 | most basic editors that are already residing on your computer, or
84 | easily installed for free: Notepad, Wordpad (on Windows), TextEdit
85 | (Mac), Vim, Emacs, etc.
86 |
87 | - If that last sentence confuses you, don’t worry. Just use Google Docs
88 | or Word or whatever you are used to. (The surprise is that you don’t
89 | actually have to buy any word processor at all because the above
90 | basic text editors come with your system and ZettelGeist would allow
91 | you to use those for free to research, organize, and write any great
92 | work you need to produce – but let’s set that issue aside for the
93 | moment.)
94 |
95 | Let’s try it out with Google Docs since we all have access to that.
96 | -------------------------------------------------------------------
97 |
98 | - As you can see on the “Get Started” and “Note Format” page above, a
99 | note in ZettelGeist is just a set of information put together in
100 | sections marked with a colon, like title: or note: or tags:, etc.
101 |
102 | - There are a number of those built into the system (see Note Format
103 | page) because, as researchers, we know you might also want to
104 | “comment:” or write a “summary:” or add bibliographical information
105 | such as “bibkey:” and “pages:”, and so on.
106 |
107 | - BUT this is completely up to you. You can add any of these elements,
108 | or only one or two, in any order according to your needs. A
109 | completely valid note would just start with “note:” and then just
110 | consist of the text of your note in the following line surrounded by
111 | quotations, including all the information you want to produce or
112 | record right there. That would work just fine. You could then save it
113 | as “note-01.txt” and it could be processed in ZettelGeist without a
114 | problem (after a minor change to the filename so it can be searched
115 | and used in the system – more on that in a minute).
116 |
117 | - If you want the other elements, like title: summary: or comment:
118 | great, just add them too. As long as you name sections according to
119 | the list on the “Note Format” page, or listed in “zettel –help”, you
120 | can create notes however you prefer, with sections in whatever order
121 | you like. Basically, you are making up your own notetaking system
122 | (based on these universally valid “fields”) and can treat any “file”
123 | as a blank notecard, just as you do when you buy a pack of 3 x 5
124 | notecards at the pharmacy and make flash cards for a high school
125 | class. Fill them out as you like!
126 |
127 | So, with that flexibilty in mind, let’s make your first note.
128 | -------------------------------------------------------------
129 |
130 | For now, just go to Google Docs (or Word, or…your choice – but we will use Google Docs for this example since we all have access and some familiarity with this editor.)
131 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
132 |
133 | - Start a new Doc.
134 |
135 | - Then take one step that will help with this experiment.
136 |
137 | - Go to “Tools>Preferences” and **uncheck** most of the automatic
138 | styling elements.
139 |
140 | ``Uncheck "Automatically capitalize" "Use smart quotes" "Automatically detect lists" and the main "Automatic substitution."``
141 |
142 | - We want the simplest and plainest characters possible (most programs
143 | add fancier “unicode” characters with these features – but we don’t
144 | need them and they actually mess up searching and finding later).
145 |
146 | - You can always turn these back on later, but you probably wouldn’t
147 | miss most of these anyway.
148 |
149 | - Close preferences and then just look at your plain Doc page. But now
150 | you can think of it a little differently. This is now a *notecard*
151 | (right out of your 3 x 5 package)! Even though it is on a
152 | supercomputer in the “cloud” linked to the internet, it is just a
153 | “card” now. Let’s just fill it in as we would by hand.
154 |
155 | - Let’s say you want to give it a title (remember, it’s up to you
156 | whether you need a title, but this will remind you what this field
157 | and other subsequent ones in this research session are about).
158 |
159 | - So, type:
160 |
161 | ``title: Reading notes on The Great Gatsby``
162 |
163 | - Ok. That’s the top line of your note, just like on the “red” line of
164 | your good old notecard.
165 |
166 | - Now, let’s put in something about the book you are reading, for
167 | instance (you could be taking notes for anything including your own
168 | novel or writing poetry or writing a shopping list, but we are
169 | thinking research paper for now).
170 |
171 | - Make a new line and type:
172 |
173 | ``note: "This is a note about The Great Gatsby, a novel by F. Scott Fitzgerald. Written during The Jazz Age, it is a masterpiece of American Literature."``
174 |
175 | - Notice that I put the text part of this note: “inside quotation
176 | marks.” This is necessary when you write longer notes because it
177 | means you can put quotes and colons and multiple lines into your
178 | plain text card. Just a formality, but not a big deal. If you just
179 | write a single line without colons and other such things, you don’t
180 | need the quotes. But it works better with them if you are making
181 | notes this initial way with GDocs or another word processer.
182 |
183 | - For now, let’s just stop there and see what we can do with that very
184 | first note.
185 |
186 | - Let’s name the file, on Google Docs, by simply clicking in the file
187 | name box above (as usual – you know) and typing “Gatsby-Note”.
188 |
189 | - Now let’s download it to your computer so we can soon make it into a
190 | zettel for research processing.
191 |
192 | - Click “File>Download as” and select “Plain Text (.txt)”.
193 |
194 | - Immediately, it will save to your computer (into the directory set by
195 | your browser for downloads – usually Downloads).
196 |
197 | - If you want, you can click on the download tab at the bottom of your
198 | browser to open it, or go into the directory to see it there. It will
199 | look just like your original, but maybe a little simpler in a plain
200 | text editor (which is retro-cool).
201 |
202 | But let’s make a couple of more notes (zettels) before we do any more.
203 | ----------------------------------------------------------------------
204 |
205 | - All you need to do to make your next note(s) is edit your existing
206 | Google Doc! You don’t have to create a new one or anything. You
207 | already saved your first card, so it is safe. Now just edit your next
208 | one on the basis of this start, and save the new iteration as the
209 | next note.
210 |
211 | - We can leave title: the same… So no changes there.
212 |
213 | - Let’s change the note: (obviously). Just highlight from the first
214 | quotation mark to the last, delete the original note, and write
215 | another.
216 |
217 | ``note: "The novel opens with the lines 'In my younger and more vulnerable years my father gave me some advice that I’ve been turning over in my mind ever since. 'Whenever you feel like criticizing any one,' he told me, 'just remember that all the people in this world haven’t had the advantages that you’ve had.' (Gatsby, 1)"``
218 |
219 | - We just added a quote from the book. So you might want to write
220 | something about that citation (your own opinion of its importance,
221 | etc.) as well. (Teachers want to hear your voice, and you want to
222 | remember why you took the note.)
223 |
224 | - That’s simple: You could just add something to the “note:” section
225 | itself:
226 |
227 | ``"The novel opens with the lines 'In my younger and more vulnerable years my father gave me some advice that I’ve been turning over in my mind ever since. “Whenever you feel like criticizing any one,' he told me, 'just remember that all the people in this world haven’t had the advantages that you’ve had.' (Gatsby, 1) Comment: This is a famous first line and my teacher says that we should analyze it carefully."``
228 |
229 | - See the “Comment” at the end? That would do it. As a result, you have
230 | title, note, citation-page (Gatsby, 1), and a comment (inside that
231 | last quotation mark). All the elements of a traditional notecard are
232 | there, just within the “note:” field. So let’s save that as a second
233 | note.
234 |
235 | - Just click “File>Download>Plain Text (.txt) again. It will
236 | automatically download (and get a new name with”(1)" added by Google
237 | Docs) – so you don’t have to do anything to change the filename, etc.
238 | Just click.
239 |
240 | - Cool. Two notes are now in your research “card stack” for processing.
241 | If we did pull them into the system, they would be completely
242 | searchable and usable. Again: you could just take notes with “notes:”
243 | or “title:” and “note:” and that will do the job.
244 |
245 | - But, you can do a lot more if you want to. ZettelGeist allows you to
246 | break up these elements of research notes into each of the
247 | traditional elements listed on the “Note Format” page!
248 |
249 | So let’s go back to our GDocs page and adjust this note to make a third with a little more…zing!
250 | ------------------------------------------------------------------------------------------------
251 |
252 | - Highlight “Comment: This is a famous first line and my teacher says
253 | that we should analyze it carefully.” Then cut that (not delete).
254 |
255 | - Make a new line and paste it. Then make the capital “C” into a
256 | lowercase “c” and put your comment in quotations, resulting in:
257 |
258 | ``comment: This is a famous first line and my teacher says that we should analyze it carefully."``
259 |
260 | - You just set up a new “comment:” field that can be searched
261 | separately if you want. This is not necessary (as above) but it does
262 | allow you to separate, let’s say, the quotes you take from the source
263 | (in “note:”) and your ideas (in “comment:”). It’s up to you, but just
264 | in case you like it, it’s that easy to add more fields (per the “Note
265 | Format” page).
266 |
267 | - Now, let’s do something else that is key to research. Add “tags” to
268 | the note. This is another traditional part of any notecard system. It
269 | allows you to mark each note as being relevant to a theme or a
270 | keyword or a part of your paper (Intro, Body 1, Body 2, Conclusion,
271 | etc.). Adding tags is also really easy with the ZettelGeist method.
272 |
273 | - Continue with the existing GDoc.
274 |
275 | - (See? Making new “cards” just means editing and then re-saving
276 | your existing card in .txt format with a new name – done
277 | automatically in GDocs. But the process is essentially the same
278 | for Word or whatever editor you are using – just give each new
279 | “save as” a different number: Gatsby-Note-01.yaml,
280 | Gatsby-Note-02.yaml, Gatsby-Note-03.yaml, etc. The existing
281 | elements just get reused over and over as you save every new
282 | version to your “stack.”)
283 |
284 | - To add tags, start a new line under the “comment:” line.
285 |
286 | - Type this:
287 |
288 | ::
289 |
290 | tags:
291 | - My first tag
292 | - Gatsby note
293 | - First line of book
294 |
295 | - Could it be simpler? Ha! “tags:” is the new section, just as above.
296 | But each tag is separate, so you just start the line for each tag
297 | with a hyphen to indicate this is the case. That’s all!!! (BTW: This
298 | is why we turned off “automatic lists,” because that feature would
299 | make those hyphens into bullet points. We just want clean hyphens.)
300 |
301 | - Let’s save that fancier note, just as above: “File>Download>Plain
302 | Text.”
303 |
304 | Your research stack is growing! Let’s do one more, adding one more feature. Again, it isn’t necessary, but “It’s there!” So what the heck?
305 | ------------------------------------------------------------------------------------------------------------------------------------------
306 |
307 | - Edit the GDoc again.
308 |
309 | - Let’s find a new citation from the book and put it in the “note:”
310 | section (between quotes) and write a new “comment:” Just zap the old
311 | material and add the new, adjusting only what is necessary for the
312 | new note, resulting in something like:
313 |
314 | ::
315 |
316 | title: Reading notes on The Great Gatsby
317 | note: "Conduct may be founded on the hard rock or the wet marshes, but after a certain point I don’t care what it’s founded on. When I came back from the East last autumn I felt that I wanted the world to be in uniform and at a sort of moral attention forever; I wanted no more riotous excursions with privileged glimpses into the human heart."
318 | comment: "In second paragraph, Fitzgerald begins to suggest Gatsby's cynicism and hints at fact that he was a veteran of the First World War"
319 | tags:
320 | - Gatsby note
321 | - Cynicism
322 | - Impact of WWI
323 |
324 | - You can also change the tags for this next note, as I did here.
325 |
326 | - Obviously, you could save this to the “stack,” go on to the next, and
327 | be fine.
328 |
329 | - But notice that this time (for demonstration purposes) I didn’t add
330 | an bibliographical indicator like “(Gatsby, 2)”. Most of us would
331 | just put that MLA element in and be fine. In fact, for 99% of users,
332 | that’s enough. Just keep track of which books you are using and add
333 | the notes or footnotes when you pull things together later. No
334 | problem.
335 |
336 | - But if you are into “bibtex” and plan to build your paper with zotero
337 | and pandoc (for more advanced users) you could also use this system
338 | to keep track of your bibliography. That just involves adding the
339 | following at the bottom:
340 |
341 | ::
342 |
343 | cite:
344 | bibkey: fitzgerald_gatsby_1925
345 | page: p. 2
346 |
347 | - That’s all. If you don’t know what “bibkey” means right now, don’t
348 | worry about it. (Just use MLA as above.) But if you do, you can add
349 | it and link this to your .bib file and when you build with pandoc all
350 | will be well. Just notice the spaces before bibkey: and page: Don’t
351 | use tabs to indent – put in two spaces.
352 |
353 | - Now let’s save this new card, as above.
354 |
355 | - OK! Now we have a “Stack” of cards in our “Downloads” directory, each
356 | named “Gatsby-Note….txt” You could write a million more. Just change
357 | the elements that need to be changed and save the new version as a
358 | new card: copy or type out new quotes from your book; add comments;
359 | just write out notes; change tags; change page(s); change title if
360 | you want, etc.
361 |
362 | - *Quick tip*: copying and pasting from electronic sources can be a
363 | little tricky because you don’t know about the “fancy characters”
364 | that will end up in your note. It’s best to just type out a quote
365 | (and paraphrase more than quoting, as the masters say). But if you
366 | do this, then *highlight* the whole note and click the “Clear
367 | formatting” button to zap weird characters (as much as it will).
368 | Also make sure you are pasting things are inside those quotation
369 | marks). You might end up, after processing below, with some
370 | strange charcters like in your notecards.
371 | They can be deleted, but are a little bit of a pain (and why plain
372 | text writing emphasizes plain text).
373 |
374 | Let’s process our notes.
375 | ------------------------
376 |
377 | - Anyway, based on our start, let’s begin to process the notes we have
378 | made. (Just think about how you would start shuffling or organizing a
379 | stack of notecards you have written on paper.)
380 |
381 | - This is actually where the real power of this system starts.
382 |
383 | - Remember, the idea is to make a notecard for every idea for your
384 | project, then be able to find them, select the ones you need, then
385 | print them out for your paper or for each section of your paper,
386 | according to themes or keywords or…
387 |
388 | - This is waaaaaaay different from having all of your notes in a
389 | single document or having them on a few “Onenote” or “Evernote”
390 | pages, but then having difficulty selecting the particular cards
391 | or notes you need in particular. This is where the ZettelGeist
392 | system becomes an electronic version of “moving the cards around”
393 | when you start to outline or write the paper.
394 |
395 | - First, think about whether you want to keep working in the directory
396 | where your browser saved the cards, or somewhere else. It’s probably
397 | best to move them.
398 |
399 | - If you want to move them out of Downloads, make a new directory
400 | called Gatsby-Paper and move the notes there.
401 |
402 | - Now, we just need to rename these “.txt” files so they are understood
403 | as “.yaml” files by the system. That’s the “format” that the
404 | ZettelGeist system needs to work with.
405 |
406 | - This can be done a number of ways. Since we only have a few cards
407 | now, we can just do it with File Manager (or whatever)
408 | individually. You can also do them in bulk with some File Managers
409 | (on Mac) or with a command in the terminal. But for now, just
410 | change them by hand.
411 |
412 | - So, in your new Gatsby-Paper directory, change the names of each
413 | “.txt” file to “Gatsby-Note.yaml”. For GDocs users, you might also
414 | adjust the numbers automatically added, removing the parentheses
415 | but not the numbers. So, Gatsby-Note (1).txt becomes
416 | Gatsby-Note-1.yaml. It’s just neater that way.
417 |
418 | - When this is done, you are ready to rock. Now you can do everything
419 | that is demonstrated with the “test” materials on the “Getting
420 | Started” page, but with your own research notes written in GDocs or
421 | Word or…
422 |
423 | - Everything from this point on assumes you have installed ZettelGeist
424 | and have your zenv environment working as explained on the
425 | Installation page.
426 |
427 | - This can be done right in the same directory you are working in.
428 |
429 | - First create a database name.
430 |
431 | ``zcreate --database gatsby.db``
432 |
433 | - Then import all of the new yaml notecards (or zettels) into your
434 | database.
435 |
436 | ``zimport --database --dir $(pwd)``
437 |
438 | - The output will show each of your notes being pulled into the
439 | database.
440 |
441 | - Once that is done, you are ready to start searching and organizing
442 | your notes.
443 |
444 | - Of course, with only a few it isn’t super exciting. But if you have
445 | taken notes on every thought you had when reading The Great Gatsby,
446 | the game would really be on!!
447 |
448 | - Let’s search for something in our stack. To do this, you use “zfind.”
449 | To see all the elements of zfind, you could type “zfind –help”. But
450 | we will keep things simple now.
451 |
452 | - Let’s search for the card that had to do with the First World War.
453 |
454 | - To do that, at the command line, type:
455 |
456 | ``zfind --database Gatsby.db --query-string 'comment:"First World War"' --show-title --show-note --show-comment``
457 |
458 | - When you enter this, the output will be the card that included the
459 | “string” First World War in the “commment:” field. See?
460 |
461 | - There are a zillion things to be done now that you have this
462 | searching ability. Again, it really comes into play when you have a
463 | bunch of notes and want to search on them. But this is the start.
464 | Let’s do one more.
465 |
466 | ``zfind --database Gatsby.db --query-string 'tags:"First Line"' --show-title --show-note --show-comment``
467 |
468 | - Take a look at what each of those commands is doing. ``zfind`` is
469 | starting the search engine. It is looking in the
470 | ``--database Gatsby.db``. It is searching for particular strings of
471 | letters in particular fields
472 | ``--query-string 'comment:"First World War"' and --query-string 'tags:"First line"'``.
473 | Then, for each card that has those elements, it is showing the title,
474 | showing the note, and showing the comment. That is what is showing up
475 | on the output.
476 |
477 | - The real power of zfind (searching in ZettelGeist) comes from
478 | combining these things (in as many ways as you want to use for your
479 | purposes). Here is an example. Let’s search for *both* of these
480 | elements in your cards: those with tags with First Line and those
481 | with commments with First World War. To do that, you just use the
482 | “or” command (the vertical bar created by [shift-backslash] in the
483 | query string, as in:
484 |
485 | ``zfind --database Gatsby.db --query-string 'tags:"First Line" | comment:"First World War"' --show-title --show-note --show-comment``
486 |
487 | - Hit enter, and both of those cards will flash by (or the parts you
488 | specified: title, note, and comment – though you could have asked for
489 | tags and cite and… any elements you include).
490 |
491 | - You have just searched and found the two notes that met those
492 | requirements. Not such a big deal out of 4 notes, but out of 100?
493 | That’s cool.
494 |
495 | But, you want to use them for a portion of your paper on those themes, right?
496 | -----------------------------------------------------------------------------
497 |
498 | - To do that, just add one more basic element into your search command:
499 | “> search-results.txt” That’s all you need. The “>” sign (like an
500 | arrow) means “send that output into a file” – as in, your results
501 | file… Or your Gatsby-results.txt file… Or your
502 | “Gatsby-Body-Part-1.txt” file, depending on how you want to arrange
503 | your information.
504 |
505 | Let’s do the last one:
506 |
507 | ``zfind --database Gatsby.db --query-string 'tags:"First Line" | comment:"First World War"' --show-title --show-note --show-comment > Gatsby-Body-Part-1.txt``
508 |
509 | - Hit enter, and in an instant you will have a file with all the
510 | searched data under that name. Open Gatsby-Body-Part-1.txt with your
511 | editor. Or upload it to GDocs and open it there. It will have your
512 | notes on those issues all in one place for you to put into your paper
513 | document where you need it.
514 |
515 | - THAT’S how to use the *notecard* notetaking system to take notes,
516 | mark them for particular content, find them, collect them, and then
517 | pull them into your paper – all using the computer instead of paper
518 | notecards (not that there is anything wrong with paper notecards,
519 | they still rock, but we are digital writers now).
520 |
521 | - ZettelGeist has been made to make this great, traditional, powerful
522 | way to do research (on anything) or just write or just make lists or…
523 | as immediate as possible, but without trapping you in one word
524 | processing system OR trapping your notes (etc.) in a onenote system
525 | or an evernote system. (Nerd joke: EverNote keeps your notes,
526 | forever: like a black hole, once the information goes in, it never
527 | comes out.) ZettelGeist allows you to put your material in (according
528 | to some classic rules) and then GET IT OUT in the bits and pieces
529 | that you actually need.
530 |
531 | - The zfind feature can be modified in many ways to get more
532 | “fine-tuned” material from your electronic card stack(s). Also, you
533 | can break things up into the various fields we have discussed. BUT,
534 | again, you could also just take notes as “note:” and be fine,
535 | including whatever you need in that field alone (in quotations to be
536 | sure there aren’t processing issues) and then search for strings in
537 | all the “notes” sections. It can be that simple, or as complex or
538 | professional as you want. It is completely up to you.
539 |
540 | - It is as flexible as paper notecards were, but as powerful as any
541 | supercomputers are. That’s what we are talking about!!!!
542 |
543 | In conclusion, for GDocs users…
544 | -------------------------------
545 |
546 | **Your notetaking system is still there, ready and waiting for you to
547 | continue with your project! Just take a look back at the GDocs page you
548 | were working on – the master “card” is ever-ready for you to edit and
549 | save your next idea, and your next, and … (Fractals, baby!!)**
550 |
--------------------------------------------------------------------------------
/sphinx-docs/source/tutorial-world.rst:
--------------------------------------------------------------------------------
1 | World
2 | ========
3 |
4 |
5 | **This page is under construction. Pardon the sketchiness for now.**
6 |
7 | What do you want to do?
8 | -----------------------
9 |
10 | - Take research notes for a paper in order to be able to search them
11 | for … anything.
12 |
13 | - Follow the traditional (and ever-valid) methods of writing a note
14 | with a title, some keywords (tags), a note (with comment or summary
15 | if desired), and some bibliographical information (book or article
16 | title and page number[s]).
17 |
18 | - Find particular notes on particular themes and issues.
19 |
20 | - Send those particular notes to a file that will be the basis for a
21 | portion of your outline or draft.
22 |
23 | All of these basic research, organization, and writing steps are steeped in traditional methods.
24 | ------------------------------------------------------------------------------------------------
25 |
26 | - As researchers and writers of papers, articles, books – from grade
27 | school, high school, college, graduate school, through our
28 | professional writings – as well as teachers and editors of countless
29 | efforts by others, we know the game. Indeed, we are the coaches and
30 | referees and main players of the game! And our own coaches taught us
31 | how to do it right!
32 |
33 | - On the basis of this experience, we made ZettelGeist to do the most
34 | important, fundamental steps of research and writing as clearly and
35 | directly as possible, based on the methods that our mentors used to
36 | write great books before personal computers came into being.
37 |
38 | - But because we are ourselves computerized (having come into
39 | professional life just as the pc revolution occurred and, therefore,
40 | having played *that game* ever since), we have here merged these
41 | techniques into the computer world more directly than any program has
42 | before. (Believe us: we know! We have tried and deployed every option
43 | out there, from 1980 until yesterday – as a matter of professional
44 | need.)
45 |
46 | - Since we know the frustration that many so-called “notetaking
47 | programs” cause, we have made a fundamental decision to ensure that
48 | the basis for all of this is already in the computer you own and the
49 | internet sites you have access to.
50 |
51 | - You don’t have to go and buy anything new. You already have
52 | *supercomputers* that earlier great writers could never have
53 | imagined. This system will just help you to take advantage of these
54 | machines in ways consistent with the key principles of research and
55 | organization that the great writers developed, but most computer
56 | programs have left out.
57 |
58 | - This is the Research-Writing-Computer Singularity we have been
59 | waiting for!
60 |
61 | The first thing to know is that with ZettelGeist you can do ALL of the above by starting (and finishing) your writing with ANY SOFTWARE YOU WANT TO USE!! The ZettelGeist program works with and *between* your preferred word processors.
62 | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
63 |
64 | - Many programs suggest they are “app-gnostic” (agnostic or indifferent
65 | about which app you use), but that usually just means you can save
66 | your work into another format (docx, pdf, txt, etc.).
67 |
68 | - ZettelGeist is truly app neutral in the sense that you can make notes
69 | (zettels) with any software, as long as you make them according to a
70 | certain pattern (indicating note section, title section, etc…) and
71 | save or download them in good old “.txt” format.
72 |
73 | - The “pattern” is exactly what you would use to write out a notecard
74 | in the traditional way (by hand, or typed on paper or computer), so
75 | it really isn’t that big a deal. Plus, once you make one card (or
76 | zettel), you can just edit the same card to make any necessary
77 | changes for the next card (change the note, change the page numbers,
78 | etc.) then save the new card with a new filename, eg. “note02.txt”
79 | and move on…
80 |
81 | - You can do this with ANY word processor you want to use: Google Docs,
82 | Microsoft Word, LibreOffice. In fact, you could just use one of the
83 | most basic editors that are already residing on your computer, or
84 | easily installed for free: Notepad, Wordpad (on Windows), TextEdit
85 | (Mac), Vim, Emacs, etc.
86 |
87 | - If that last sentence confuses you, don’t worry. Just use Google Docs
88 | or Word or whatever you are used to. (The surprise is that you don’t
89 | actually have to buy any word processor at all because the above
90 | basic text editors come with your system and ZettelGeist would allow
91 | you to use those for free to research, organize, and write any great
92 | work you need to produce – but let’s set that issue aside for the
93 | moment.)
94 |
95 | Let’s try it out with Microsoft Word.
96 | -------------------------------------
97 |
98 | - As you can see on the “Get Started” and “Note Format” page above, a
99 | note in ZettelGeist is just a set of information put together in
100 | sections marked with a colon, like title: or note: or tags:, etc.
101 |
102 | - There are a number of those built into the system (see Note Format
103 | page) because, as researchers, we know you might also want to
104 | “comment:” or write a “summary:” or add bibliographical information
105 | such as “bibkey:” and “pages:”, and so on.
106 |
107 | - BUT this is completely up to you. You can add any of these elements,
108 | or only one or two, in any order according to your needs. A
109 | completely valid note would just start with “note:” and then just
110 | consist of the text of your note in the following line surrounded by
111 | quotations, including all the information you want to produce or
112 | record right there. That would work just fine. You could then save it
113 | as “note-01.txt” and it could be processed in ZettelGeist without a
114 | problem (after a minor change to the filename so it can be searched
115 | and used in the system – more on that in a minute).
116 |
117 | - If you want the other elements, like title: summary: or comment:
118 | great, just add them too. As long as you name sections according to
119 | the list on the “Note Format” page, or listed in “zettel –help”, you
120 | can create notes however you prefer, with sections in whatever order
121 | you like. Basically, you are making up your own notetaking system
122 | (based on these universally valid “fields”) and can treat any “file”
123 | as a blank notecard, just as you do when you buy a pack of 3 x 5
124 | notecards at the pharmacy and make flash cards for a high school
125 | class. Fill them out as you like!
126 |
127 | So, with that flexibilty in mind, let’s make your first note.
128 | -------------------------------------------------------------
129 |
130 | For now, just go to Word, or GDocs (on the other tab)…your choice.
131 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
132 |
133 | - Start a new document.
134 |
135 | - Then take one step that will help with this experiment.
136 |
137 | - Go to “Tools>Preferences>AutoCorrect” and **uncheck** most of the
138 | automatic styling elements. (This is based on the Mac version, but
139 | it should be about the same on the PC.)
140 |
141 | - Uncheck “Capitalize first letter of sentences”
142 |
143 | - Under “AutoFormat As You Type” uncheck “Automatic bulleted
144 | lists” and "“Straight quotes with smart quotes” and all the
145 | others.
146 |
147 | - We want the simplest and plainest characters possible (most
148 | programs add fancier “unicode” characters with these features –
149 | but we don’t need them and they actually mess up searching and
150 | finding later).
151 |
152 | - You can always turn these back on later, but you probably wouldn’t
153 | miss most of these anyway.
154 |
155 | - Close preferences and then just look at your plain document page. But
156 | now you can think of it a little differently. This is now a
157 | *notecard* (right out of your 3 x 5 package)! Even though it is on a
158 | supercomputer in the “cloud” linked to the internet, it is just a
159 | “card” now. Let’s just fill it in as we would by hand.
160 |
161 | - Let’s say you want to give it a title (remember, it’s up to you
162 | whether you need a title, but this will remind you what this field
163 | and other subsequent ones in this research session are about).
164 |
165 | - So, type:
166 |
167 | ``title: Reading notes on The Great Gatsby``
168 |
169 | - Ok. That’s the top line of your note, just like on the “red” line of
170 | your good old notecard.
171 |
172 | - Now, let’s put in something about the book you are reading, for
173 | instance (you could be taking notes for anything including your own
174 | novel or writing poetry or writing a shopping list, but we are
175 | thinking research paper for now).
176 |
177 | - Make a new line and type:
178 |
179 | ``note: "This is a note about The Great Gatsby, a novel by F. Scott Fitzgerald. Written during The Jazz Age, it is a masterpiece of American Literature."``
180 |
181 | - Notice that I put the text part of this note: “inside quotation
182 | marks.” This is necessary when you write longer notes because it
183 | means you can put quotes and colons and multiple lines into your
184 | plain text card. Just a formality, but not a big deal. If you just
185 | write a single line without colons and other such things, you don’t
186 | need the quotes. But it works better with them if you are making
187 | notes this initial way with Word or another word processer.
188 |
189 | - For now, let’s just stop there and see what we can do with that very
190 | first note.
191 |
192 | - Let’s name the file, on Google Docs, by simply clicking in the file
193 | name box above (as usual – you know) and typing “Gatsby-Note”.
194 |
195 | - Now let’s save it so we can soon make it into a zettel for research
196 | processing.
197 |
198 | - Click File> Save As, then, under file format “Plain Text.txt.”
199 |
200 | - Then name the file “Gatsby-Note-1.yaml” and save it to a directory
201 | called “Gatsby-Reading-Notes” (for this project): “.yaml” is the
202 | “format” that the ZettelGeist system needs to work with.
203 |
204 | - If it asks about “text encoding,” select "Western (ASCII)
205 |
206 | - Immediately, it will save to your computer (into the directory set by
207 | your browser for downloads – usually Downloads).
208 |
209 | But let’s make a couple of more notes (zettels) before we do any more.
210 | ----------------------------------------------------------------------
211 |
212 | - All you need to do to make your next note(s) is edit your existing
213 | document! You don’t have to create a new one or anything. You already
214 | saved your first card, so it is safe. Now just edit your next one on
215 | the basis of this start, and save the new iteration as the next note.
216 |
217 | - We can leave title: the same… So no changes there.
218 |
219 | - Let’s change the note: (obviously). Just highlight from the first
220 | quotation mark to the last, delete the original note, and write
221 | another.
222 |
223 | ``note: "The novel opens with the lines 'In my younger and more vulnerable years my father gave me some advice that I’ve been turning over in my mind ever since. 'Whenever you feel like criticizing any one,' he told me, 'just remember that all the people in this world haven’t had the advantages that you’ve had.' (Gatsby, 1)"``
224 |
225 | - We just added a quote from the book. So you might want to write
226 | something about that citation (your own opinion of its importance,
227 | etc.) as well. (Teachers want to hear your voice, and you want to
228 | remember why you took the note.)
229 |
230 | - That’s simple: You could just add something to the “note:” section
231 | itself:
232 |
233 | ``"The novel opens with the lines 'In my younger and more vulnerable years my father gave me some advice that I’ve been turning over in my mind ever since. “Whenever you feel like criticizing any one,' he told me, 'just remember that all the people in this world haven’t had the advantages that you’ve had.' (Gatsby, 1) Comment: This is a famous first line and my teacher says that we should analyze it carefully."``
234 |
235 | - See the “Comment” at the end? That would do it. As a result, you have
236 | title, note, citation-page (Gatsby, 1), and a comment (inside that
237 | last quotation mark). All the elements of a traditional notecard are
238 | there, just within the “note:” field. So let’s save that as a second
239 | note.
240 |
241 | - Just click “File>Save As” again. You don’t have to change settings
242 | again. Just change the name to “Gatsby-Note-2.yaml”.
243 |
244 | - Cool. Two notes are now in your research “card stack” for processing.
245 | If we did pull them into the system, they would be completely
246 | searchable and usable. Again: you could just take notes with “notes:”
247 | or “title:” and “note:” and that will do the job.
248 |
249 | - But, you can do a lot more if you want to. ZettelGeist allows you to
250 | break up these elements of research notes into each of the
251 | traditional elements listed on the “Note Format” page!
252 |
253 | So let’s go back to our document and adjust this note to make a third with a little more…zing!
254 | ----------------------------------------------------------------------------------------------
255 |
256 | - Highlight “Comment: This is a famous first line and my teacher says
257 | that we should analyze it carefully.” Then cut that (not delete).
258 |
259 | - Make a new line and paste it. Then make the capital “C” into a
260 | lowercase “c” and put your comment in quotations, resulting in:
261 |
262 | ``comment: This is a famous first line and my teacher says that we should analyze it carefully."``
263 |
264 | - You just set up a new “comment:” field that can be searched
265 | separately if you want. This is not necessary (as above) but it does
266 | allow you to separate, let’s say, the quotes you take from the source
267 | (in “note:”) and your ideas (in “comment:”). It’s up to you, but just
268 | in case you like it, it’s that easy to add more fields (per the “Note
269 | Format” page).
270 |
271 | - Now, let’s do something else that is key to research. Add “tags” to
272 | the note. This is another traditional part of any notecard system. It
273 | allows you to mark each note as being relevant to a theme or a
274 | keyword or a part of your paper (Intro, Body 1, Body 2, Conclusion,
275 | etc.). Adding tags is also really easy with the ZettelGeist method.
276 |
277 | - Continue with the existing document.
278 |
279 | - (See? Making new “cards” just means editing and then re-saving
280 | your existing card in .yaml format with a new numbered name. Just
281 | give each new “save as” a different number: Gatsby-Note-01.yaml,
282 | Gatsby-Note-02.yaml, Gatsby-Note-03.yaml, etc. The existing
283 | elements just get reused over and over as you save every new
284 | version to your “stack.”)
285 |
286 | - To add tags, start a new line under the “comment:” line.
287 |
288 | - Type this:
289 |
290 | ::
291 |
292 | tags:
293 | - My first tag
294 | - Gatsby note
295 | - First line of book
296 |
297 | - Could it be simpler? Ha! “tags:” is the new section, just as above.
298 | But each tag is separate, so you just start the line for each tag
299 | with a hyphen to indicate this is the case. That’s all!!! (BTW: This
300 | is why we turned off “automatic lists,” because that feature would
301 | make those hyphens into bullet points. We just want clean hyphens.)
302 |
303 | - Let’s save that fancier note, just as above: “File>Save
304 | as>Gatsby-Note-03.yaml,” and so on.)
305 |
306 | Your research stack is growing! Let’s do one more, adding one more feature. Again, it isn’t necessary, but “It’s there!” So what the heck?
307 | ------------------------------------------------------------------------------------------------------------------------------------------
308 |
309 | - Edit the document again.
310 |
311 | - Let’s find a new citation from the book and put it in the “note:”
312 | section (between quotes) and write a new “comment:” Just zap the old
313 | material and add the new, adjusting only what is necessary for the
314 | new note, resulting in something like:
315 |
316 | ::
317 |
318 | title: Reading notes on The Great Gatsby
319 | note: "Conduct may be founded on the hard rock or the wet marshes, but after a certain point I don’t care what it’s founded on. When I came back from the East last autumn I felt that I wanted the world to be in uniform and at a sort of moral attention forever; I wanted no more riotous excursions with privileged glimpses into the human heart."
320 | comment: "In second paragraph, Fitzgerald begins to suggest Gatsby's cynicism and hints at fact that he was a veteran of the First World War"
321 | tags:
322 | - Gatsby note
323 | - Cynicism
324 | - Impact of WWI
325 |
326 | - You can also change the tags for this next note, as I did here.
327 |
328 | - Obviously, you could save this to the “stack,” go on to the next, and
329 | be fine.
330 |
331 | - But notice that this time (for demonstration purposes) I didn’t add
332 | an bibliographical indicator like “(Gatsby, 2)”. Most of us would
333 | just put that MLA element in and be fine. In fact, for 99% of users,
334 | that’s enough. Just keep track of which books you are using and add
335 | the notes or footnotes when you pull things together later. No
336 | problem.
337 |
338 | - But if you are into “bibtex” and plan to build your paper with zotero
339 | and pandoc (for more advanced users) you could also use this system
340 | to keep track of your bibliography. That just involves adding the
341 | following at the bottom:
342 |
343 | ::
344 |
345 | cite:
346 | bibkey: fitzgerald_gatsby_1925
347 | page: p. 2
348 |
349 | - That’s all. If you don’t know what “bibkey” means right now, don’t
350 | worry about it. (Just use MLA as above.) But if you do, you can add
351 | it and link this to your .bib file and when you build with pandoc all
352 | will be well. Just notice the spaces before bibkey: and page: Don’t
353 | use tabs to indent – put in two spaces.
354 |
355 | - Now let’s save this new card, as above.
356 |
357 | - OK! Now we have a “Stack” of cards in our “Gatsby-Reading-Notes”
358 | directory, each named “Gatsby-Note….txt” You could write a million
359 | more. Just change the elements that need to be changed and save the
360 | new version as a new card: copy or type out new quotes from your
361 | book; add comments; just write out notes; change tags; change
362 | page(s); change title if you want, etc.
363 |
364 | - *Quick tip*: copying and pasting from electronic sources can be a
365 | little tricky because you don’t know about the “fancy characters”
366 | that will end up in your note. It’s best to just type out a quote
367 | (and paraphrase more than quoting, as the masters say). But if you
368 | do this, saving as plain text and Western (ASCII) should take care
369 | of it. Also make sure you are pasting things are inside those
370 | quotation marks). You might end up, after processing below, with
371 | some strange charcters like in your
372 | notecards. They can be deleted, but are a little bit of a pain
373 | (and why plain text writing emphasizes plain text).
374 |
375 | Let’s process our notes.
376 | ------------------------
377 |
378 | - Anyway, based on our start, let’s begin to process the notes we have
379 | made. (Just think about how you would start shuffling or organizing a
380 | stack of notecards you have written on paper.)
381 |
382 | - This is actually where the real power of this system starts.
383 |
384 | - Remember, the idea is to make a notecard for every idea for your
385 | project, then be able to find them, select the ones you need, then
386 | print them out for your paper or for each section of your paper,
387 | according to themes or keywords or…
388 |
389 | - This is waaaaaaay different from having all of your notes in a
390 | single document or having them on a few “Onenote” or “Evernote”
391 | pages, but then having difficulty selecting the particular cards
392 | or notes you need in particular. This is where the ZettelGeist
393 | system becomes an electronic version of “moving the cards around”
394 | when you start to outline or write the paper.
395 |
396 | - OK: you are ready to rock. Now you can do everything that is
397 | demonstrated with the “test” materials on the “Getting Started” page,
398 | but with your own research notes written in Word or GDocs or …
399 |
400 | - Everything from this point on assumes you have installed ZettelGeist
401 | and have your zenv environment working as explained on the
402 | Installation page.
403 |
404 | - This can be done right in the same directory you are working in.
405 |
406 | - First create a database name.
407 |
408 | ``zcreate --database gatsby.db``
409 |
410 | - Then import all of the new yaml notecards (or zettels) into your
411 | database.
412 |
413 | ``zimport --database --dir $(pwd)``
414 |
415 | - The output will show each of your notes being pulled into the
416 | database.
417 |
418 | - Once that is done, you are ready to start searching and organizing
419 | your notes.
420 |
421 | - Of course, with only a few it isn’t super exciting. But if you have
422 | taken notes on every thought you had when reading The Great Gatsby,
423 | the game would really be on!!
424 |
425 | - Let’s search for something in our stack. To do this, you use “zfind.”
426 | To see all the elements of zfind, you could type “zfind –help”. But
427 | we will keep things simple now.
428 |
429 | - Let’s search for the card that had to do with the First World War.
430 |
431 | - To do that, at the command line, type:
432 |
433 | ``zfind --database Gatsby.db --query-string 'comment:"First World War"' --show-title --show-note --show-comment``
434 |
435 | - When you enter this, the output will be the card that included the
436 | “string” First World War in the “commment:” field. See?
437 |
438 | - There are a zillion things to be done now that you have this
439 | searching ability. Again, it really comes into play when you have a
440 | bunch of notes and want to search on them. But this is the start.
441 | Let’s do one more.
442 |
443 | ``zfind --database Gatsby.db --query-string 'tags:"First Line"' --show-title --show-note --show-comment``
444 |
445 | - Take a look at what each of those commands is doing. ``zfind`` is
446 | starting the search engine. It is looking in the
447 | ``--database Gatsby.db``. It is searching for particular strings of
448 | letters in particular fields
449 | ``--query-string 'comment:"First World War"' and --query-string 'tags:"First line"'``.
450 | Then, for each card that has those elements, it is showing the title,
451 | showing the note, and showing the comment. That is what is showing up
452 | on the output.
453 |
454 | - The real power of zfind (searching in ZettelGeist) comes from
455 | combining these things (in as many ways as you want to use for your
456 | purposes). Here is an example. Let’s search for *both* of these
457 | elements in your cards: those with tags with First Line and those
458 | with commments with First World War. To do that, you just use the
459 | “or” command (the vertical bar created by [shift-backslash] in the
460 | query string, as in:
461 |
462 | ``zfind --database Gatsby.db --query-string 'tags:"First Line" | comment:"First World War"' --show-title --show-note --show-comment``
463 |
464 | - Hit enter, and both of those cards will flash by (or the parts you
465 | specified: title, note, and comment – though you could have asked for
466 | tags and cite and… any elements you include).
467 |
468 | - You have just searched and found the two notes that met those
469 | requirements. Not such a big deal out of 4 notes, but out of 100?
470 | That’s cool.
471 |
472 | But, you want to use them for a portion of your paper on those themes, right?
473 | -----------------------------------------------------------------------------
474 |
475 | - To do that, just add one more basic element into your search command:
476 | “> search-results.txt” That’s all you need. The “>” sign (like an
477 | arrow) means “send that output into a file” – as in, your results
478 | file… Or your Gatsby-results.txt file… Or your
479 | “Gatsby-Body-Part-1.txt” file, depending on how you want to arrange
480 | your information.
481 |
482 | Let’s do the last one:
483 |
484 | ``zfind --database Gatsby.db --query-string 'tags:"First Line" | comment:"First World War"' --show-title --show-note --show-comment > Gatsby-Body-Part-1.txt``
485 |
486 | - Hit enter, and in an instant you will have a file with all the
487 | searched data under that name. Open Gatsby-Body-Part-1.txt with Word
488 | or any editor. It will have your notes on those issues all in one
489 | place for you to put into your paper document where you need it.
490 |
491 | - THAT’S how to use the *notecard* notetaking system to take notes,
492 | mark them for particular content, find them, collect them, and then
493 | pull them into your paper – all using the computer instead of paper
494 | notecards (not that there is anything wrong with paper notecards,
495 | they still rock, but we are digital writers now).
496 |
497 | - ZettelGeist has been made to make this great, traditional, powerful
498 | way to do research (on anything) or just write or just make lists or…
499 | as immediate as possible, but without trapping you in one word
500 | processing system OR trapping your notes (etc.) in a onenote system
501 | or an evernote system. (Nerd joke: EverNote keeps your notes,
502 | forever: like a black hole, once the information goes in, it never
503 | comes out.) ZettelGeist allows you to put your material in (according
504 | to some classic rules) and then GET IT OUT in the bits and pieces
505 | that you actually need.
506 |
507 | - The zfind feature can be modified in many ways to get more
508 | “fine-tuned” material from your electronic card stack(s). Also, you
509 | can break things up into the various fields we have discussed. BUT,
510 | again, you could also just take notes as “note:” and be fine,
511 | including whatever you need in that field alone (in quotations to be
512 | sure there aren’t processing issues) and then search for strings in
513 | all the “notes” sections. It can be that simple, or as complex or
514 | professional as you want. It is completely up to you.
515 |
516 | - It is as flexible as paper notecards were, but as powerful as any
517 | supercomputers are. That’s what we are talking about!!!!
518 |
519 | In conclusion, for Word (etc.) users…
520 | -------------------------------------
521 |
522 | **Your notetaking system is still there, ready and waiting for you to
523 | continue with your project! Just take a look back at the Word document
524 | you were working on – the master “card” is ever-ready for you to edit
525 | and “save as” your next idea, and your next, and … (Fractals, baby!!)**
526 |
--------------------------------------------------------------------------------
/src/ps.text:
--------------------------------------------------------------------------------
1 | USER PID %CPU %MEM VSZ RSS TT STAT STARTED TIME COMMAND
2 | _windowserver 22462 5.3 0.6 3810764 52512 ?? Ss Tue11PM 97:34.94 /System/Library/PrivateFrameworks/SkyLight.framework/Resources/WindowServer -daemon
3 | gkt 41927 5.3 4.6 3569996 387396 ?? S 9:52PM 0:43.32 /Applications/Paltalk.app/Contents/MacOS/Paltalk
4 | _coreaudiod 170 4.9 0.1 2474348 5288 ?? Ss Sun11PM 112:38.13 /usr/sbin/coreaudiod
5 | gkt 22660 3.5 2.5 3677892 206684 ?? S Wed07AM 109:15.02 /Applications/Google Chrome.app/Contents/MacOS/Google Chrome
6 | gkt 26378 3.1 1.0 2940736 86936 ?? S Thu03PM 4:56.22 /Applications/iTerm.app/Contents/MacOS/iTerm2
7 | root 57 1.7 0.2 2509160 18132 ?? Ss Sun11PM 14:47.52 /usr/libexec/airportd
8 | _hidd 99 1.2 0.1 2473184 6372 ?? Ss Sun11PM 64:39.83 /usr/libexec/hidd
9 | root 77 0.9 0.2 2521356 16884 ?? Ss Sun11PM 1:24.75 /usr/libexec/opendirectoryd
10 |
--------------------------------------------------------------------------------
/tests/test_zettelgeist.py:
--------------------------------------------------------------------------------
1 | import sys
2 | import textwrap
3 | import yaml
4 |
5 | from zettelgeist import zettel
6 |
7 | # content of test_sysexit.py
8 | import pytest
9 |
10 |
11 | def f():
12 | raise SystemExit(1)
13 |
14 |
15 | def test_mytest():
16 | with pytest.raises(SystemExit):
17 | f()
18 |
19 |
20 | def test_parse_empty():
21 | doc = {}
22 | zettel.parse_zettel(doc)
23 |
24 |
25 | def test_parse_simple_valid():
26 | doc = {
27 | 'title': "Valid title"
28 | }
29 | zettel.parse_zettel(doc)
30 |
31 |
32 | def test_parse_simple_bad_value():
33 | doc = {
34 | 'title': 35
35 | }
36 | with pytest.raises(zettel.ParseError):
37 | zettel.parse_zettel(doc)
38 |
39 |
40 | def test_simple_zettel():
41 | zdoc = """
42 | title: My First Zettel
43 | mentions:
44 | - dbdennis
45 | - gkt
46 | tags:
47 | - Charles Babbage
48 | - Ada Lovelace
49 | cite:
50 | bibkey: Ifrah
51 | page: "22-36"
52 | dates:
53 | year: "1841"
54 | era: CE
55 | summary: An amazing Zettel
56 | note: Text of Zettel
57 | bibkey: BibKey
58 | bibtex: "@article{key, entries}"
59 | """
60 | zdoc = textwrap.dedent(zdoc)
61 | print(zdoc)
62 | zdict = yaml.load(zdoc)
63 | z = zettel.Zettel(zdict)
64 |
65 |
66 | def test_creator_and_load():
67 | z = zettel.Zettel({})
68 | z.set_field('title', 'My First Zettel')
69 | z.reset_list_field('mentions')
70 | z.append_list_field('mentions', 'dbdennis')
71 | z.append_list_field('mentions', 'gkt')
72 | z.reset_list_field('tags')
73 | z.append_list_field('tags', 'Charles Babbage')
74 | z.append_list_field('tags', 'Ada Lovelace')
75 | z.set_citation('Ifrah', '22-36')
76 | z.set_dates('1841', 'CE')
77 | z.set_field('summary', 'An amazing Zettel')
78 | z.set_field('note', 'Text of Zettel')
79 | z.set_field('bibkey', 'BibKey')
80 | z.set_field('bibtex', '@article{ley, entries}')
81 | text = z.get_yaml()
82 |
83 | ydoc = yaml.load(text)
84 | z2 = zettel.Zettel(ydoc)
85 | text2 = z2.get_yaml()
86 | assert text == text2
87 |
88 |
89 | def test_creator_and_load_optional_fields():
90 | z = zettel.Zettel({})
91 | z.set_field('title', 'My First Zettel')
92 | z.reset_list_field('mentions')
93 | z.append_list_field('mentions', 'dbdennis')
94 | z.append_list_field('mentions', 'gkt')
95 | z.reset_list_field('tags')
96 | z.append_list_field('tags', 'Charles Babbage')
97 | z.append_list_field('tags', 'Ada Lovelace')
98 | z.set_citation('Ifrah')
99 | z.set_dates('1841')
100 | z.set_field('summary', 'An amazing Zettel')
101 | z.set_field('note', 'Text of Zettel')
102 | z.set_field('bibkey', 'BibKey')
103 | z.set_field('bibtex', '@article{ley, entries}')
104 | text = z.get_yaml()
105 |
106 | ydoc = yaml.load(text)
107 | z2 = zettel.Zettel(ydoc)
108 | text2 = z2.get_yaml()
109 | assert text == text2
110 |
111 |
112 | def test_zettel_fts_strings():
113 | z = zettel.Zettel({})
114 | z.set_field("title", "title")
115 | z.set_field("summary", "a summary")
116 | expected = {'title': 'title', 'summary': 'a summary'}
117 | z.get_indexed_representation() == expected
118 |
119 |
120 | def test_zettel_fts_lists():
121 | z = zettel.Zettel({})
122 | z.reset_list_field("tags")
123 | z.append_list_field("tags", "Babbage")
124 | z.append_list_field("tags", "Lovelace")
125 | expected = {'tags': 'Babbage,Lovelace'}
126 | z.get_indexed_representation() == expected
127 |
128 |
129 | def test_zettel_fts_cite():
130 | z = zettel.Zettel({})
131 | z.set_citation("Castells 2006", "ii-iv")
132 | z.get_indexed_representation()
133 | expected = {'cite': 'bibkey:Castells 2006,page:ii-iv'}
134 | z.get_indexed_representation() == expected
135 |
136 | z.set_citation("Castells 2006") # omitting page numbers
137 | expected = {'cite': 'bibkey:Castells 2006'}
138 | z.get_indexed_representation() == expected
139 |
140 |
141 | def test_zettel_fts_dates():
142 | z = zettel.Zettel({})
143 | z.set_dates('2006', 'CE')
144 | expected = {'dates': 'year:2006,era:CE'}
145 | z.get_indexed_representation() == expected
146 |
147 | z.set_dates('2006') # omit era
148 | expected = {'dates': 'year:2006'}
149 | z.get_indexed_representation() == expected
150 |
151 |
152 | def test_invalid_zettel_fields():
153 | z = zettel.Zettel({})
154 | with pytest.raises(zettel.ParseError):
155 | z.set_field('blah', 'blah')
156 | z.delete_field('blah')
157 |
158 | # checks for injection of bad values in nested citation dictionary
159 | z.set_citation('Castells 2006', 'ii-iv')
160 | with pytest.raises(zettel.ParseError):
161 | z.zettel['cite']['blah'] = 'blah'
162 | z.get_yaml() # force checks
163 |
164 | del(z.zettel['cite']['blah'])
165 |
166 | # checks for injection of bad values in nested dates dictionary
167 | z.set_dates('2006', 'CE')
168 | with pytest.raises(zettel.ParseError):
169 | z.zettel['dates']['blah'] = 'blah'
170 | z.get_yaml()
171 | del(z.zettel['dates']['blah'])
172 |
--------------------------------------------------------------------------------
/zdb_funcs.sh:
--------------------------------------------------------------------------------
1 | # To use these in bash/zsh, you can source this file.
2 | # Usage:
3 | # db_keywords filename.db
4 | # db_mentions filename.db
5 | #
6 | # This is for keyword/mention discoery in a zdb until we can decide on
7 | # proper z-commands and how they would work.
8 |
9 | zdb_tags() {
10 | sqlite3 $1 'select distinct(lower(tag)) from tags' | sort -f | uniq -i
11 | }
12 |
13 | zdb_mentions() {
14 | sqlite3 $1 'select distinct(lower(mention)) from mentions' | sort -f | uniq -i
15 | }
16 |
17 |
18 |
--------------------------------------------------------------------------------
/zettelgeist/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ZettelGeist/zettelgeist/477fa5427f089f9b9092c45f87f32a93af73e695/zettelgeist/__init__.py
--------------------------------------------------------------------------------
/zettelgeist/zcreate.py:
--------------------------------------------------------------------------------
1 | # zcreate.py - create Zettel database
2 |
3 | import os.path
4 | import argparse
5 | from . import zdb
6 |
7 |
8 | def parse_options():
9 | parser = zdb.get_argparse()
10 | parser.add_argument('--delete', action='store_const', const=True,
11 | default=False, help="delete if it already exists")
12 | return parser.parse_args()
13 |
14 |
15 | def zcreate(args):
16 | if args.delete and os.path.exists(args.database):
17 | print("Deleting %s" % args.database)
18 | os.unlink(args.database)
19 |
20 | if not os.path.exists(args.database):
21 | print("Creating new database %s" % args.database)
22 | db = zdb.get(args.database)
23 | db.drop_table()
24 | db.create_table()
25 | db.done()
26 | else:
27 | print("Won't delete existing database %s" % args.database)
28 | print("- Rerun with --delete option to achieve this.")
29 |
30 |
31 | def main():
32 | args = parse_options()
33 | print("Warning: zcreate is deprecated - use zimport --create --database %s" % args.database)
34 | zcreate(args)
35 |
36 |
37 | if __name__ == '__main__':
38 | main()
39 |
--------------------------------------------------------------------------------
/zettelgeist/zdb.py:
--------------------------------------------------------------------------------
1 |
2 | # ZettelGeist uses a FTS system for organizing Zettels. The index is intended
3 | # to be emphemeral and can be regenerated at any time. The schema itself is
4 | # ephemeral and can be augmented with additional fields of interest.
5 | #
6 |
7 | import argparse
8 | import os
9 | import os.path
10 | import sqlite3
11 |
12 | from . import zettel
13 |
14 | # TODO: 'filename' and 'document' are special fields for stuff not really part of the YAML dictionary
15 | # but still needing to be indexable and searchable.
16 |
17 | ZettelSQLFields = zettel.ZettelFieldsOrdered
18 | # Default Zettel DB name
19 | ZDB = 'zettels.db'
20 |
21 |
22 | def get_argparse():
23 | parser = argparse.ArgumentParser()
24 | parser.add_argument(
25 | '--database', help="database name", required=True)
26 | return parser
27 |
28 |
29 | import pprint
30 | printer = pprint.PrettyPrinter(indent=2)
31 |
32 |
33 | def unquote(text):
34 | return text.replace('"', '').replace("'", "")
35 |
36 |
37 | class SQLiteFTS(object):
38 | def __init__(self, db_name, field_names):
39 | self.db_name = db_name
40 | self.conn = sqlite3.connect(db_name)
41 | self.conn.row_factory = sqlite3.Row
42 | self.cursor = self.conn.cursor()
43 |
44 | self.fts_field_names = field_names
45 | # for sqlite insert template generation
46 | self.fts_field_refs = ['?'] * len(self.fts_field_names)
47 | self.fts_field_init = [''] * len(self.fts_field_names)
48 | self.fts_fields = dict(zip(self.fts_field_names, self.fts_field_refs))
49 | self.fts_default_record = dict(
50 | zip(self.fts_field_names, self.fts_field_init))
51 | self.zettel = None
52 |
53 | def bind(self, zettel, filename, document=""):
54 | self.zettel = zettel
55 | doc = zettel.get_indexed_representation()
56 | doc.update({'filename': filename})
57 | doc.update({'document': document})
58 | self.record = self.fts_default_record.copy()
59 | for k in doc.keys():
60 | if k in self.record.keys():
61 | if doc[k] != None:
62 | self.record[k] = doc[k]
63 | else:
64 | print("Unknown fts field %s - deleting it" % k)
65 |
66 | # self.record.update(doc)
67 |
68 | def drop_table(self):
69 | self.cursor.execute("DROP TABLE IF EXISTS zettels")
70 | self.conn.commit()
71 |
72 | def create_table(self):
73 | sql_fields = ",".join(self.fts_default_record.keys())
74 | #print("CREATE VIRTUAL TABLE zettels USING fts4(%s)" % sql_fields)
75 | self.cursor.execute(
76 | "CREATE VIRTUAL TABLE zettels USING fts4(%s)" % sql_fields)
77 | self.conn.commit()
78 | self.create_index_table('tags', 'tag')
79 | self.create_index_table('mentions', 'mention')
80 |
81 | def create_index_table(self, table_name, field_name):
82 | self.cursor.execute("DROP TABLE IF EXISTS %(table_name)s" % vars())
83 | self.cursor.execute(
84 | "CREATE TABLE %(table_name)s (%(field_name)s text)" % vars())
85 | self.conn.commit()
86 |
87 | def update_index(self, table_name, field_name, items):
88 | if not items:
89 | return
90 | for item in items:
91 | self.cursor.execute(
92 | "INSERT INTO %(table_name)s (%(field_name)s) VALUES (?)" % vars(), (item,))
93 | # NB: (item,) means to pack this item into a tuple as required by sqlite3.
94 |
95 | def insert_into_table(self):
96 | sql_params = ",".join(self.fts_fields.values())
97 | sql_columns = ",".join(list(self.record.keys()))
98 | sql_insert_values = list(self.record.values())
99 | insert_sql = "INSERT INTO zettels (%s) VALUES (%s)" % (
100 | sql_columns, sql_params)
101 | self.cursor.execute(insert_sql, sql_insert_values)
102 | self.conn.commit()
103 | self.update_index('tags', 'tag', self.zettel.get_list_field('tags'))
104 | self.update_index('mentions', 'mention',
105 | self.zettel.get_list_field('mentions'))
106 |
107 | # A term_list is a list of 3-tuples (not-option, fieldname, word)
108 |
109 | def fts_search(self, term_list):
110 | safe_term_list = []
111 | for term in term_list:
112 | if type(term) == type(()) and len(term) == 3:
113 | (name, not_operator, words) = term
114 | words = unquote(words)
115 | if not_operator not in '-':
116 | not_operator = ''
117 | if name not in self.fts_field_names:
118 | continue
119 | for word in words.split():
120 | safe_term_list.append((name, ":", not_operator, word))
121 |
122 | # print(safe_term_list)
123 | fts_terms = " ".join(["".join(list(term)) for term in safe_term_list])
124 | Q = "SELECT * from zettels where zettels match '%s'" % fts_terms
125 | # print(Q)
126 | for row in self.cursor.execute(Q):
127 | yield(row)
128 |
129 | def fts_query(self, prepared_sql):
130 | return self.cursor.execute(prepared_sql)
131 |
132 | def get_tags_generator(self):
133 | Q = "select distinct(tag) from tags"
134 | for row in self.cursor.execute(Q):
135 | yield(row['tag'])
136 |
137 | def get_tags_list(self):
138 | gen = self.get_tags_generator()
139 | return list(gen)
140 |
141 | def get_mentions_generator(self):
142 | Q = "select distinct(mention) from mentions"
143 | for row in self.cursor.execute(Q):
144 | yield(row['mention'])
145 |
146 | def get_mentions_list(self):
147 | gen = self.get_mentions_generator()
148 | return list(gen)
149 |
150 | def done(self):
151 | self.conn.commit()
152 | self.conn.close()
153 |
154 |
155 | class FNF(Exception):
156 | def __init__(self, text):
157 | self.text = text
158 |
159 | def __str__(self):
160 | return "File not found: " + self.text
161 |
162 |
163 | def get(db_name):
164 | return SQLiteFTS(db_name, ZettelSQLFields)
165 |
166 | GRAMMAR = """@@grammar::ZQUERY
167 |
168 | start = expression $ ;
169 |
170 | expression
171 | =
172 | | or_expr
173 | | term
174 | ;
175 |
176 | or_expr
177 | =
178 | left:expression op:'|' right:term
179 | ;
180 |
181 | term
182 | =
183 | | and_expr
184 | | factor
185 | ;
186 |
187 | and_expr
188 | = left:term op:and_op right:factor
189 | ;
190 |
191 | and_op
192 | = op:'&'
193 | | op:'!'
194 | ;
195 |
196 | not_expr
197 | = left:term op:'!' right:factor
198 | ;
199 |
200 | factor
201 | =
202 | | '(' @:expression ')'
203 | | z_field
204 | ;
205 |
206 | z_field
207 | = field:literal ':' text:literal
208 | ;
209 |
210 | literal
211 | = word:/"(\s+|\w+)*"/
212 | | word:/\w+/
213 | ;
214 | """
215 |
--------------------------------------------------------------------------------
/zettelgeist/zettel.py:
--------------------------------------------------------------------------------
1 | #
2 | # zettel.py - A checker for Zettels
3 | #
4 |
5 | import sys
6 | import argparse
7 | import readline # for input()
8 |
9 | import frontmatter # to accommodate Markdown with YAML frontmatter
10 | import yaml
11 | try:
12 | from yaml import CLoader as Loader, CDumper as Dumper
13 | except ImportError:
14 | from yaml import Loader, Dumper
15 |
16 | import os
17 | import os.path
18 | import json
19 | import shutil
20 |
21 | from time import strftime
22 |
23 | # Recursive descent parsing of Zettel dictionary format.
24 |
25 | ZettelStringFields = ['title', 'bibkey', 'bibtex',
26 | 'ris', 'inline', 'url', 'summary', 'comment', 'note']
27 | ZettelListFields = ['tags', 'mentions']
28 | ZettelStructuredFields = ['cite', 'dates']
29 | ZettelExtraFields = ['filename', 'document']
30 | ZettelFieldsOrdered = ZettelStringFields + \
31 | ZettelListFields + ZettelStructuredFields + ZettelExtraFields
32 | ZettelFields = set(ZettelFieldsOrdered)
33 | CitationFields = set(['bibkey', 'page'])
34 | DatesFields = set(['year', 'era'])
35 |
36 | ZettelMarkdownExtensions = ['.text', '.txt', '.md', '.markdown']
37 |
38 |
39 | class ParseError(Exception):
40 | def __init__(self, message):
41 | self.message = message
42 |
43 | def __str__(self):
44 | return self.message
45 |
46 |
47 | def typename(value):
48 | return type(value).__name__
49 |
50 |
51 | def parse_zettel(doc):
52 | if not isinstance(doc, dict):
53 | raise ParseError(
54 | "Zettels require key/value mappings at top-level. Found %s" % typename(doc))
55 |
56 | parse_check_zettel_field_names(doc)
57 |
58 | # These fields are all optional but, if present, must be strings
59 | parse_string_field(doc, 'title')
60 | parse_string_field(doc, 'bibkey')
61 | parse_string_field(doc, 'bibtex')
62 | parse_string_field(doc, 'ris')
63 | parse_string_field(doc, 'inline')
64 | parse_string_field(doc, 'url')
65 | parse_string_field(doc, 'summary')
66 | parse_string_field(doc, 'comment')
67 | parse_string_field(doc, 'note')
68 | parse_string_field(doc, 'document')
69 |
70 | # These fields are all optional but, if present, must be list of strings
71 |
72 | parse_list_of_string_field(doc, 'tags')
73 | parse_list_of_string_field(doc, 'mentions')
74 |
75 | parse_citation(doc, 'cite')
76 | parse_dates(doc, 'dates')
77 |
78 | # TODO: Check for extraneous fields in all cases
79 |
80 |
81 | def parse_check_zettel_field_names(doc):
82 | check_field_names(doc, ZettelFields, "Zettel")
83 |
84 |
85 | def parse_check_citation_field_names(doc):
86 | check_field_names(doc, CitationFields, "Citation")
87 |
88 |
89 | def parse_check_dates_field_names(doc):
90 | check_field_names(doc, DatesFields, "Dates")
91 |
92 |
93 | def check_field_names(doc, name_set, label):
94 | for key in doc.keys():
95 | if key not in name_set:
96 | raise ParseError("Invalid field %s found in %s" % (key, label))
97 |
98 |
99 | def parse_string_field(doc, field, required=False):
100 | value = doc.get(field, None)
101 | if value == None:
102 | if required:
103 | raise ParseError("Field %s requires a string but found %s of type %s" % (
104 | field, value, typename(value)))
105 | # This extra check is needed to handle situation where a YAML field is
106 | # present but is null. We cannot allow it.
107 | if field in doc:
108 | raise ParseError("Field %s may not be (YAML) null" % field)
109 | return
110 | if not isinstance(value, str):
111 | raise ParseError("Field %s must be a string or not present at all - found value %s of type %s" %
112 | (field, value, typename(value)))
113 | #if len(value) == 0:
114 | # raise ParseError("Field %s is an empty string. Not permitted." % field)
115 |
116 |
117 | # TODO: There is a possible bug in list of string that allows a field to be defined as YAML none.
118 |
119 | def parse_list_of_string_field(doc, field, required=False):
120 | value = doc.get(field, None)
121 | if value == None:
122 | if required:
123 | raise ParseError("Field %s requires a list of strings" % field)
124 | # This extra check is needed to handle situation where a YAML field is
125 | # present but is null. We cannot allow it.
126 | if field in doc:
127 | raise ParseError("Field %s may not be (YAML) null" % field)
128 | return
129 | if not isinstance(value, (list, tuple)):
130 | raise ParseError("Field %s must be a list or not present at all - found value %s of type %s" %
131 | (field, value, typename(value)))
132 |
133 | # Make a dictionary of the list items for checking purposes only
134 | # That is, treat the list like a dictionary. Will simplify with comprehension magic later
135 | doc2 = {}
136 | pos = 0
137 | for item in value:
138 | doc2["%s(%d)" % (field, pos)] = item
139 | pos = pos + 1
140 | for key in doc2.keys():
141 | parse_string_field(doc2, key, True)
142 |
143 |
144 | def parse_citation(doc, field):
145 | value = doc.get(field, None)
146 | if value == None:
147 | return
148 | if not isinstance(value, dict):
149 | raise ParseError("%s must be a nested (citation) dictoinary" % field)
150 | parse_check_citation_field_names(value)
151 | parse_string_field(value, 'bibkey', True)
152 | parse_string_field(value, 'page')
153 |
154 |
155 | def parse_dates(doc, field):
156 | value = doc.get(field, None)
157 | if value == None:
158 | return
159 | if not isinstance(value, dict):
160 | raise ParseError("%s must be a nested (dates) dictionary" % field)
161 | parse_check_dates_field_names(value)
162 | parse_string_field(value, 'year', True)
163 | parse_string_field(value, 'era')
164 |
165 | # This is to support formatting of resulting YAML (after modification of the underlying dictionary)
166 |
167 |
168 | # Credit to StackOverflow for helping figure out how to format YAML
169 | # multiline strings properly (when emitting YAML representation of Zettel)
170 |
171 | from collections import OrderedDict
172 |
173 |
174 | class quoted(str):
175 | pass
176 |
177 |
178 | class literal(str):
179 | pass
180 |
181 |
182 | def quoted_presenter(dumper, data):
183 | return dumper.represent_scalar('tag:yaml.org,2002:str', data, style='"')
184 |
185 | # Note: Only use multiline syntax when there are actually multiple lines.
186 |
187 |
188 | def str_presenter(dumper, data):
189 | if len(data.splitlines()) > 1:
190 | return dumper.represent_scalar('tag:yaml.org,2002:str', data, style='|')
191 | return dumper.represent_scalar('tag:yaml.org,2002:str', data)
192 |
193 |
194 | def ordered_dict_presenter(dumper, data):
195 | return dumper.represent_dict(data.items())
196 |
197 |
198 | class ZettelBadKey(Exception):
199 | def __init__(self, name):
200 | self.name = name
201 |
202 |
203 | class ZettelStringRequired(Exception):
204 | def __init__(self, value):
205 | self.value = value
206 |
207 |
208 | def get_argparse():
209 | parser = argparse.ArgumentParser()
210 |
211 | # note is being deprecated in future releases to give users time to migrate away from it
212 |
213 | for field in ZettelFieldsOrdered:
214 | parser.add_argument('--delete-%s' % field, action="store_true",
215 | help="delete field %s" % field, default=False)
216 |
217 | for field in ZettelStringFields + ZettelExtraFields: # allow for filename, doc
218 | parser.add_argument('--set-%s' %
219 | field, help="set the value of field %s" % field)
220 | parser.add_argument('--load-%s' %
221 | field, help="load field %s from filename" % field)
222 |
223 | for field in ZettelListFields:
224 | parser.add_argument('--reset-%s' % field, action="store_true",
225 | help="reset list field %s" % field, default=False)
226 | parser.add_argument('--remove-entries-in-%s' % field, nargs=2, metavar=('FASS ENTRY', 'LIST ENTRY'), type=str,
227 | help="delete comma-separated LIST ENTRY positions from FASS ENTRY")
228 | parser.add_argument('--append-%s' %
229 | field, nargs="+", help="add value to list field %s" % field)
230 |
231 | parser.add_argument('--set-cite', nargs='+', type=str, metavar=('BIBKEY', 'PAGES'),
232 | help="set citation BIBKEY [ PAGE* ] - leave blank to override existing BIBKEY")
233 |
234 | parser.add_argument('--set-dates', nargs='+', type=str, metavar=('YEAR', 'ERA'),
235 | help="set dates; YEAR required - ERA is optional (extra arguments beyond the 2nd are ignored but allowed")
236 |
237 | for field in ZettelFieldsOrdered:
238 | parser.add_argument('--prompt-%s' % field, action="store_true",
239 | help="prompt for input of %s" % field,
240 | default=False)
241 |
242 | parser.add_argument(
243 | '--file', help='Zettel file (.yaml) to process (or check syntax)')
244 |
245 | parser.add_argument('--save', help='Write output to specified file.')
246 |
247 | parser.add_argument('--in-place', action="store_true", default=False,
248 | help="overwrite original file specified by --file")
249 |
250 | parser.add_argument(
251 | '--backup-id', help='backup suffix for original filename', default="orig")
252 |
253 | parser.add_argument('--name', nargs='+', help="order of components, e.g. id, or timestamp")
254 | parser.add_argument('--name-dir', type=str, help="folder where to write file generated by --name (will NOT be created, if it does not exist)", default=".")
255 | parser.add_argument('--id', help="human-understandable id to include in filename")
256 | parser.add_argument('--digits', type=int, help="digits in counter (default=4)", default=4)
257 |
258 | parser.add_argument('--separator', type=str, help="separate components with delimiter (default is '-')", default="-")
259 | parser.add_argument('--counter', type=str, help="counter name (defaults to --id if present) ")
260 | parser.add_argument('--counter-path', type=str, help="counter filename/path to filename", default=".counter.dat")
261 |
262 | parser.add_argument('--restrict-output-fields',
263 | nargs="+", help="restrict output fields (list of Zettel field names)",
264 | default=ZettelFieldsOrdered)
265 |
266 | # deprecated
267 | parser.add_argument('--omit-markdown-header', action="store_true", default=False,
268 | help="add markdown header when writing Markdown for each YAML field")
269 |
270 | return parser
271 |
272 |
273 | def flatten(item):
274 | if item == None:
275 | return [""]
276 | elif isinstance(item, dict):
277 | return flatten([":".join([k, item[k]]) for k in item])
278 | elif not isinstance(item, (tuple, list)):
279 | return [str(item)]
280 |
281 | if len(item) == 0:
282 | return item
283 | else:
284 | return flatten(item[0]) + flatten(item[1:])
285 |
286 |
287 | def prompt(field):
288 | print("Enter text for %s. ctrl-d to end." % field)
289 | lines = []
290 | while True:
291 | try:
292 | line = input("%s> " % field)
293 | lines.append(line)
294 | except EOFError:
295 | print()
296 | break
297 | return lines
298 |
299 |
300 | class Zettel(object):
301 |
302 | def __init__(self, data={}):
303 | self.zettel = data
304 | parse_zettel(self.zettel)
305 |
306 | def set_field(self, name, value):
307 | self.zettel[name] = value
308 | parse_zettel(self.zettel)
309 |
310 | def delete_field(self, name):
311 | try:
312 | del(self.zettel[name])
313 | except:
314 | pass
315 | parse_zettel(self.zettel)
316 |
317 | def reset_list_field(self, name):
318 | self.zettel[name] = []
319 | parse_zettel(self.zettel)
320 |
321 | def delete_list_field_entries(self, name, positions):
322 | if name not in self.zettel:
323 | return
324 | positions.sort(reverse=True)
325 | for position in positions:
326 | del(self.zettel[name][position])
327 | if len(self.zettel[name]) == 0:
328 | del(self.zettel[name])
329 |
330 | def append_list_field(self, name, value):
331 | self.zettel[name] = self.zettel.get(name, [])
332 | tag_set = set(self.zettel[name])
333 | if not value in tag_set:
334 | self.zettel[name].append(value)
335 | parse_zettel(self.zettel)
336 |
337 | def get_list_field(self, name):
338 | return self.zettel.get(name, [])
339 |
340 | def set_citation(self, bibkey, page=None):
341 | citation = {'bibkey': bibkey}
342 | if page != None:
343 | citation['page'] = page
344 | self.zettel['cite'] = citation
345 | parse_zettel(self.zettel)
346 |
347 | def has_citation(self):
348 | return 'cite' in self.zettel
349 |
350 | def set_cite_bibkey(self, bibkey):
351 | if len(bibkey) == 0:
352 | return
353 | if self.has_citation():
354 | self.zettel['cite']['bibkey'] = bibkey
355 | parse_zettel(self.zettel)
356 |
357 | def set_cite_page(self, page):
358 | if len(page) == 0:
359 | return
360 | if self.has_citation():
361 | self.zettel['cite']['page'] = page
362 | parse_zettel(self.zettel)
363 |
364 | def has_dates(self):
365 | return 'dates' in self.zettel
366 |
367 | def set_dates_year(self, year):
368 | if len(year) == 0:
369 | return
370 | if self.has_dates():
371 | self.zettel['dates']['year'] = year
372 | parse_zettel(self.zettel)
373 |
374 | def set_dates_era(self, era):
375 | if len(era) == 0:
376 | return
377 | if self.has_dates():
378 | self.zettel['dates']['era'] = era
379 | parse_zettel(self.zettel)
380 |
381 | def set_dates(self, year, era=None):
382 | dates = {'year': year}
383 | if era != None:
384 | dates['era'] = era
385 | self.zettel['dates'] = dates
386 | parse_zettel(self.zettel)
387 |
388 | def load_field(self, name, filename):
389 | text = []
390 | with open(filename, 'r') as infile:
391 | text = infile.readlines()
392 | text = ''.join(text)
393 | text = text.strip()
394 | self.set_field(name, text)
395 | parse_zettel(self.zettel)
396 |
397 | def get_yaml(self, restrict_to_fields=ZettelFieldsOrdered):
398 | yaml.add_representer(quoted, quoted_presenter)
399 | yaml.add_representer(literal, str_presenter)
400 | yaml.add_representer(OrderedDict, ordered_dict_presenter)
401 | parse_zettel(self.zettel)
402 | yaml_zettel = OrderedDict()
403 | for key in ZettelFieldsOrdered:
404 | if key not in self.zettel:
405 | continue
406 | if key not in restrict_to_fields:
407 | continue
408 | if key in ZettelStringFields:
409 | yaml_zettel[key] = literal(self.zettel[key])
410 | elif key != 'document': # Only field not allowed is Markdown document
411 | try:
412 | yaml_zettel[key] = self.zettel[key].copy()
413 | except:
414 | print("Warning: Cannot copy %s" % key)
415 | if len(yaml_zettel) > 0:
416 | return yaml.dump(yaml_zettel, default_flow_style=False)
417 | else:
418 | return ""
419 |
420 | def get_document(self):
421 | return self.zettel.get('document','')
422 |
423 | def get_filename(self):
424 | return self.zettel.get('filename','')
425 |
426 | # Unlikely we need this code anymore.
427 | # def get_text(self, omit_markdown_header, restrict_to_fields=ZettelFieldsOrdered):
428 | # text = []
429 | # parse_zettel(self.zettel)
430 | # for key in ZettelFieldsOrdered:
431 | # if key not in self.zettel:
432 | # continue
433 | # if key not in restrict_to_fields:
434 | # continue
435 | # if not omit_markdown_header:
436 | # text.append(markdown_h1(key))
437 | # if key in ZettelStringFields:
438 | # text.append(self.zettel[key].strip())
439 | # elif key in ZettelListFields:
440 | # for item in self.zettel[key]:
441 | # text.append(markdown_listitem(item))
442 | # else:
443 | # text.append(self.get_yaml([key]))
444 | # text.append("\n")
445 | # return "\n".join(text)
446 |
447 | def get_yaml_subset(self, fields=[]):
448 | z = Zettel({})
449 | for field in fields:
450 | z.zettel[field] = self.zettel[field].copy()
451 |
452 | def get_indexed_representation(self):
453 | parse_zettel(self.zettel)
454 | return {key: ",".join(flatten(self.zettel[key])) for key in self.zettel}
455 |
456 |
457 | # deprecated
458 | # def markdown_h1(text):
459 | # return "\n".join([text, len(text) * "="]) + "\n"
460 | # deprecated
461 | #def markdown_listitem(text):
462 | # return "- %s" % text.strip().replace("\n", "").replace("\r", "")
463 |
464 |
465 | class ZettelLoaderError(Exception):
466 | def __init__(self, message):
467 | self.message = message
468 |
469 |
470 | def load_pure_yaml(filepath):
471 | # TODO: Consider using the frontmatter to load the YAML and do all error reporting.
472 | #print("Importing YAML: %s" % filepath)
473 | ydoc = {}
474 | document = ""
475 | with open(filepath) as infile:
476 | try:
477 | text = infile.read()
478 | except:
479 | print("- Warning: I/O error on %s; is doc UTF-8" % filepath)
480 | return (ydoc, document)
481 | try:
482 | ydocs = yaml.load_all(text, Loader=Loader)
483 | except:
484 | print("- Warning: Cannot load YAML from %s; consider running YAML linter" % filepath)
485 | return (ydoc, document)
486 |
487 | try:
488 | ydoc = next(ydocs)
489 | except:
490 | print("- Warning: Cannot load first YAML document from %s" % filepath)
491 | return (ydoc, document)
492 | return (ydoc, document)
493 |
494 | def load_markdown_with_frontmatter(filepath):
495 | #print("Importing Markdown with Frontmatter: %s" % filepath)
496 | post = frontmatter.load(filepath)
497 | return (post.metadata, post.content)
498 |
499 |
500 | class ZettelLoader(object):
501 | def __init__(self, infile):
502 | # developer note: When we developed this code, we were thinking about a "fass" of zettels.
503 | # Now we just have individual zettels.
504 | if infile.endswith('.yaml'):
505 | self.ydocs = [load_pure_yaml(infile)]
506 | elif infile.endswith('.md'):
507 | self.ydocs = [load_markdown_with_frontmatter(infile)]
508 | else:
509 | self.ydocs = []
510 |
511 | def getZettels(self):
512 | for yaml_document in self.ydocs:
513 | (ydoc, document) = yaml_document
514 | ydoc['document'] = document
515 | if isinstance(ydoc, dict):
516 | yield Zettel(ydoc)
517 | else:
518 | yield Zettel({})
519 |
520 |
521 | def main():
522 | parser = get_argparse()
523 | args = parser.parse_args()
524 | argsd = vars(args)
525 | argsd['timestamp'] = True
526 | z_generator = gen_new_zettels(args)
527 |
528 | try:
529 | first_zettel = next(z_generator)
530 | except ParseError as error:
531 | print(error)
532 |
533 | filename = None
534 | if args.in_place:
535 | if not args.file:
536 | print("--in-place requires --file")
537 | sys.exit(1)
538 | filename = args.file
539 | filename_parts = os.path.splitext(filename)
540 | if filename_parts[1] not in ['.yaml', '.md']:
541 | print("Input file not .yaml/.md: %s" % filename)
542 | sys.exit(1)
543 | backup_filename = ".".join([filename, args.backup_id])
544 | shutil.copyfile(filename, backup_filename)
545 | outfile = open(args.file, "w")
546 | elif args.save:
547 | filename = args.save
548 | if args.file == args.save:
549 | print("Use --in-place instead of --save if you want to replace input file (specified with --file)")
550 | sys.exit(1)
551 | if os.path.exists(filename):
552 | backup_filename = ".".join([filename, args.backup_id])
553 | shutil.copyfile(filename, backup_filename)
554 | outfile = open(args.save, "w")
555 | elif args.name:
556 | name_components = {}
557 | name_dir = args.name_dir
558 | if not os.path.exists(name_dir):
559 | print("Destination directory specified (--name-dir %s) does not exist. Will not write file.")
560 | sys.exit(1)
561 | for arg in args.name:
562 | if arg not in ['id','timestamp', 'counter']:
563 | print("--name may only use id, counter, and timestamp (%s found)" % arg)
564 | sys.exit(1)
565 | if not argsd.get(arg, None) != None:
566 | print("--name %s requires --%s" % (args.name, arg))
567 | print(argsd)
568 | sys.exit(1)
569 | if args.id != None:
570 | name_components['id'] = args.id
571 | digits = args.digits
572 |
573 | # --counter and --id can be specified separately
574 | # If omitted, --counter takes on --id
575 | # If both are omitted, then we are not using counters in the generated names.
576 | counter_name = args.counter
577 | if not args.counter:
578 | counter_name = args.id
579 |
580 | if counter_name != None:
581 | seq = get_count(args.counter_path, counter_name)
582 | seq_text = str(seq)
583 | digits = max(len(seq_text), digits)
584 | pad_text = "0" * (digits - len(seq_text))
585 | name_components['counter'] = pad_text + seq_text
586 |
587 | name_components['timestamp'] = strftime("%Y%m%d%H%M%S")
588 |
589 | name_template = args.separator.join(["%%(%s)s" % name for name in args.name]) + ".md"
590 | name_template = "/".join([name_dir, name_template])
591 | filename = name_template % name_components
592 | if os.path.exists(filename):
593 | backup_filename = ".".join([filename, args.backup_id])
594 | shutil.copyfile(filename, backup_filename)
595 | outfile = open(filename, "w")
596 | else:
597 | outfile = sys.stdout
598 |
599 | if filename:
600 | (basename, extension) = os.path.splitext(filename)
601 | else:
602 | extension = '.yaml'
603 |
604 | try:
605 | yaml_repr_stripped = first_zettel.get_yaml(args.restrict_output_fields).rstrip()
606 | document = first_zettel.get_document()
607 | if len(yaml_repr_stripped) > 0:
608 | outfile.write('\n'.join(['---', yaml_repr_stripped, '---', document.rstrip()])+'\n')
609 | else:
610 | doc_stripped = document.rstrip()
611 | if len(doc_stripped) > 0:
612 | outfile.write(doc_stripped + '\n')
613 | except ParseError as error:
614 | print(error)
615 |
616 | def gen_id():
617 | id = 0
618 | while True:
619 | yield id
620 | id = id + 1
621 |
622 |
623 | def gen_new_zettels(args):
624 | vargs = vars(args)
625 | id_gen = gen_id()
626 | if args.file:
627 | loader = ZettelLoader(args.file)
628 | last_z = None
629 | for z in loader.getZettels():
630 | last_z = process_zettel_command_line_options(
631 | z, vargs, next(id_gen))
632 | yield last_z
633 | if not last_z:
634 | yield process_zettel_command_line_options(Zettel(), vargs, next(id_gen))
635 | else:
636 | yield process_zettel_command_line_options(Zettel(), vargs, next(id_gen))
637 |
638 |
639 | def process_zettel_command_line_options(z, vargs, id):
640 | # --reset-*, --delete-*, and --remove_entries_in-* are evaluated first
641 | for arg in vargs:
642 | if not vargs[arg]:
643 | continue
644 |
645 | if arg.startswith("reset_"):
646 | reset_what = arg[len("reset_"):]
647 | z.reset_list_field(reset_what)
648 |
649 | if arg.startswith("delete_"):
650 | delete_what = arg[len("delete_"):]
651 | z.delete_field(delete_what)
652 |
653 | if arg.startswith("remove_entries_in_"):
654 | delete_what = arg[len("remove_entries_in_"):]
655 | try:
656 | (zettel_id, list_entries) = vargs[arg][:2]
657 | zettel_id = int(zettel_id)
658 | list_entries = [int(pos) for pos in list_entries.split(",")]
659 | except:
660 | print(
661 | "Non-integer zettel ID or list position found in %s. Aborting." % arg)
662 | sys.exit(1)
663 | if id == zettel_id:
664 | z.delete_list_field_entries(delete_what, list_entries)
665 |
666 | for arg in vargs:
667 | if not vargs[arg]:
668 | continue
669 | if arg == "set_cite":
670 | cite_info = vargs[arg]
671 | bibkey = cite_info[0]
672 | pages = ",".join(cite_info[1:])
673 |
674 | if z.has_citation():
675 | z.set_cite_bibkey(bibkey)
676 | z.set_cite_page(pages)
677 | else:
678 | z.set_citation(bibkey, pages)
679 |
680 | elif arg == "set_dates":
681 | date_info = vargs[arg]
682 | year = date_info[0]
683 | era = ','.join(date_info[1:])
684 | if z.has_dates():
685 | z.set_dates_year(year)
686 | z.set_dates_era(era)
687 | else:
688 | z.set_dates(year, era)
689 |
690 | elif arg.startswith("set_"):
691 | set_what = arg[len("set_"):]
692 | value = vargs[arg].replace(r"\n", "\n")
693 | z.set_field(set_what, value)
694 |
695 | elif arg.startswith("prompt_"):
696 | prompt_field = arg[len("prompt_"):]
697 | lines = prompt(prompt_field)
698 | if prompt_field in ZettelStringFields:
699 | z.set_field(prompt_field, "\n".join(lines))
700 | elif prompt_field in ZettelExtraFields:
701 | z.set_field(prompt_field, "\n".join(lines))
702 | elif prompt_field in ZettelListFields:
703 | for line in lines:
704 | z.append_list_field(prompt_field, line)
705 | elif prompt_field == "dates":
706 | if len(lines) > 0:
707 | try:
708 | z.set_dates(lines[0], lines[1])
709 | except:
710 | z.set_dates(lines[0])
711 | elif prompt_field == "cite":
712 | if len(lines) > 0:
713 | try:
714 | z.set_citation(lines[0], lines[1])
715 | except:
716 | z.set_citation(lines[0])
717 |
718 | if arg.startswith("append_"):
719 | append_what = arg[len("append_"):]
720 | for text in vargs[arg]:
721 | z.append_list_field(append_what, text)
722 |
723 | if arg.startswith("load_"):
724 | load_what = arg[len("load_"):]
725 | z.load_field(load_what, vargs[arg])
726 | return z
727 |
728 |
729 | def get_count(counter_path, counter_name):
730 | # Create counter db if not present.
731 | if not os.path.exists(counter_path):
732 | with open(counter_path, 'w') as dbfile:
733 | json.dump({}, dbfile)
734 |
735 | # Read count from counter. If non-existent, start at 0.
736 | with open(counter_path, 'r') as dbfile:
737 | db = json.load(dbfile)
738 | count = db.get(counter_name, -1) + 1
739 |
740 | # save count for next invocation
741 | with open(counter_path, 'w') as dbfile:
742 | db[counter_name] = count
743 | json.dump(db, dbfile)
744 | return count
745 |
746 | def dict_as_yaml(data):
747 | yaml.add_representer(quoted, quoted_presenter)
748 | yaml.add_representer(literal, str_presenter)
749 | yaml.add_representer(OrderedDict, ordered_dict_presenter)
750 | presented_data = OrderedDict()
751 | for key in data:
752 | if key in ZettelStringFields:
753 | presented_data[key] = literal(data[key])
754 | else:
755 | presented_data[key] = data[key]
756 | return yaml.dump(presented_data, default_flow_style=False, Dumper=Dumper)
757 |
758 |
759 | if __name__ == '__main__':
760 | main()
761 |
--------------------------------------------------------------------------------
/zettelgeist/zfind.py:
--------------------------------------------------------------------------------
1 | import argparse
2 | import sys
3 | from time import strftime
4 | import yaml
5 | from . import zdb, zettel, zquery
6 | from .zutils import *
7 |
8 | YAML_HEADER = '---'
9 |
10 | def get_argparse():
11 | parser = zdb.get_argparse()
12 |
13 | for field in zdb.ZettelSQLFields:
14 | parser.add_argument('--show-%s' % field,
15 | action='store_const', const=True, default=False,
16 | help="include field <%s> in output" % field)
17 |
18 | parser.add_argument('--show-all',
19 | action='store_const', const=True, default=False,
20 | help="include all fields in output")
21 |
22 | parser.add_argument('--publish', help="use template to publish zfind output (suppresses all --show-FIELD)", default=None)
23 |
24 | parser.add_argument('--publish-conf', help="use publish configuration file to format special fields", default=None)
25 |
26 | parser.add_argument('--count', action='store_const', const=True,
27 | default=False, help="Show number of Zettels matching this search")
28 |
29 | parser.add_argument(
30 | '--query-prompt', action='store_const', const=True, default=False,
31 | help="prompt for ZQL query (overrides --query-string, --query-file))")
32 |
33 | parser.add_argument(
34 | '--query-file', help="load ZQL query from file (overrides --query)", default=None)
35 |
36 | parser.add_argument(
37 | '--query-string',
38 | help="load ZQL from string", default=None)
39 |
40 | parser.add_argument(
41 | '--fileset', help="write fileset to filename", default=None)
42 |
43 | parser.add_argument(
44 | '--stats', help="write statistics and parameters to filename", default=None)
45 |
46 | parser.add_argument(
47 | '--get-all-tags', help="show all tags in this database (disables all other options)", action="store_true", default=False)
48 |
49 | parser.add_argument(
50 | '--get-all-mentions', help="show all mentions in this database (disables all other options)", action="store_true", default=False)
51 |
52 |
53 | return parser
54 |
55 |
56 | def main():
57 | parser = get_argparse()
58 | args = parser.parse_args()
59 | argsd = vars(args)
60 |
61 | db = zdb.get(args.database)
62 |
63 | # The --get-all-tags and --get-all-mentions stop processing of all other tags
64 | # TODO: Make each group of functions a function to make this more comprehensible.
65 |
66 | if args.get_all_tags:
67 | print('\n'.join(db.get_tags_list()))
68 | exit(0)
69 |
70 | if args.get_all_mentions:
71 | print('\n'.join(db.get_mentions_list()))
72 | exit(0)
73 |
74 | # The --query-{prompt,file,string} options are for ZQL processing.
75 |
76 | if args.query_prompt:
77 | input_line = input("zfind> ")
78 | elif args.query_file:
79 | with open(args.query_file) as infile:
80 | input_line = infile.read()
81 | elif args.query_string:
82 | input_line = args.query_string
83 | else:
84 | print("No query option (--query-string, --query-file, or --query-prompt) found")
85 | return
86 |
87 | if input_line:
88 | ast = zquery.compile(input_line)
89 | gen = db.fts_query(ast[0])
90 | else:
91 | print("Warning: Query could not be loaded via --query, --query-file, or --query-prompt")
92 | sys.exit(1)
93 |
94 | # This is the actual logic to find and process results.
95 |
96 | search_count = 0
97 | match_filenames = []
98 |
99 | # This is for the --publish option. Publish suppresses all other output.
100 |
101 | if args.publish:
102 | template_file = args.publish
103 | publish_conf = args.publish_conf
104 | for row in gen:
105 | loader = zettel.ZettelLoader(row['filename'])
106 | zettels = loader.getZettels()
107 | z = next(zettels)
108 | publish(row, z, template_file, publish_conf)
109 | return
110 |
111 | # This is for the --show options
112 | for row in gen:
113 | search_count = search_count + 1
114 | printed_something = False
115 | match_filenames.append(row['filename'])
116 | loader = zettel.ZettelLoader(row['filename'])
117 | zettels = loader.getZettels()
118 | z = next(zettels)
119 |
120 | # Handle output of YAML here
121 | this_result_output = []
122 | for field in row.keys():
123 | show_field = 'show_' + field
124 | if argsd.get(show_field, None) or argsd.get('show_all'):
125 | if field == 'filename':
126 | filename_yaml = yaml.dump({ 'filename' : row['filename']})
127 | this_result_output.append(filename_yaml.rstrip())
128 | elif field == 'document':
129 | continue
130 | elif row[field]:
131 | if z:
132 | this_result_output.append(z.get_yaml([field]).rstrip())
133 | else:
134 | this_result_output.append("%s:" % field)
135 | this_result_output.append(row[field])
136 |
137 | # No output if just --- and ---
138 | if len(this_result_output) > 0:
139 | print('\n'.join([YAML_HEADER] + this_result_output + [YAML_HEADER]))
140 |
141 | if argsd.get("show_document"):
142 | document = row['document']
143 | if len(document) > 0:
144 | print(row['document'])
145 | print()
146 |
147 | # --count here / Should this be added to the YAML payload? I think the answer is yes.
148 |
149 | if args.count:
150 | print("%d Zettels matched search" % search_count)
151 |
152 | # --fileset handled here / Should --fileset actually suppress the --show options?
153 | # It's primary purpose is to *avoid* showing output for subsequent processing, say, in a shell loop
154 |
155 | if args.fileset:
156 | if not os.path.exists(args.fileset):
157 | write_to_file(args.fileset, "\n".join(match_filenames), mode="w", newlines=1)
158 | else:
159 | print("Filename %s exists; will not overwrite." % args.fileset)
160 |
161 | # --stats seems to duplicate the work of --count. yes, it goes to a file, but that would
162 | # allow for subsequent querying, say, with yq or equivalent.
163 |
164 | if args.stats:
165 | if not os.path.exists(args.stats):
166 | doc = {'count': search_count, 'query': input_line.strip()}
167 | write_to_file(args.stats, zettel.dict_as_yaml(doc), mode="w", newlines=1)
168 | else:
169 | print("Filename %s exists; will not overwrite." % args.stats)
170 |
171 | def publish(row, z, template_file, publish_conf):
172 | import json
173 |
174 | formatting = {}
175 | if publish_conf:
176 | with open(publish_conf) as jsonf:
177 | formatting = json.load(jsonf)
178 |
179 | all_vars = { k:'' for k in zettel.ZettelFields }
180 | all_vars.update(z.zettel)
181 | all_vars['filename'] = row['filename']
182 |
183 |
184 |
185 | tags = reformat_tags(all_vars, formatting)
186 | mentions = reformat_mentions(all_vars, formatting)
187 | cite = reformat_cite(all_vars, formatting)
188 |
189 | reformatted_data = { 'tags' : tags, 'mentions' : mentions, 'cite' : cite }
190 |
191 | all_vars.update(reformatted_data)
192 |
193 | with open(template_file) as tf:
194 | text = tf.read()
195 | print(text % all_vars)
196 |
197 | def reformat_tags(all_vars, formatting):
198 | tags_format = formatting.get('tags', {})
199 | tags = all_vars.get('tags', [])
200 | if len(tags) == 0:
201 | return ''
202 | default_tag_format = '%(tag)s'
203 | formatted_tags = \
204 | [ tags_format.get('tag', default_tag_format) % { 'tag' : tag } for tag in tags ]
205 | return tags_format.get('before','') + ''.join(formatted_tags) + tags_format.get('after','')
206 |
207 | def reformat_mentions(all_vars, formatting):
208 | mentions_format = formatting.get('mentions', {})
209 | mentions = all_vars.get('mentions', [])
210 | if len(mentions) == 0:
211 | return ''
212 | default_mention_format = '%(mention)s'
213 | formatted_mentions = \
214 | [ mentions_format.get('mention', default_mention_format) % { 'mention' : mention } for mention in mentions ]
215 | return mentions_format.get('before','') + ''.join(formatted_mentions) + mentions_format.get('after','')
216 |
217 | def reformat_cite(all_vars, formatting):
218 | cite_format = formatting.get('cite', {})
219 | cite = all_vars.get("cite", {})
220 | if len(cite) == 0:
221 | return ''
222 | if len(cite) > 0 and type(cite_format) == type({}):
223 | cite_template = cite_format.get('before')
224 | cite_template += cite_format.get('bibkey', '%(bibkey)s')
225 | cite_template += cite_format.get('page', '%(page)s')
226 | cite_template += cite_format.get('after')
227 | new_cite = cite_template % cite
228 | return new_cite
229 | else:
230 | return ''
231 |
232 | if __name__ == '__main__':
233 | main()
234 |
--------------------------------------------------------------------------------
/zettelgeist/zimport.py:
--------------------------------------------------------------------------------
1 | # zimport.py - Import Zettels into an exising database
2 |
3 | import os
4 | import os.path
5 | import sys
6 | import frontmatter # to accommodate Markdown with YAML frontmatter
7 |
8 | from . import zdb, zettel
9 |
10 | import yaml
11 | try:
12 | from yaml import CLoader as Loader, CDumper as Dumper
13 | except ImportError:
14 | from yaml import Loader, Dumper
15 |
16 |
17 | def get_zettels(dir):
18 | for (dirpath, dirnames, filenames) in os.walk(dir):
19 | for filename in filenames:
20 | if filename.endswith('.yaml') or filename.endswith('.md'):
21 | yield os.path.join(dirpath, filename)
22 |
23 |
24 | def main():
25 | parser = zdb.get_argparse()
26 | parser.add_argument(
27 | '--dir', help="location of Zettels (path to folder)", required=True)
28 |
29 | parser.add_argument('--fullpath', action="store_true",
30 | help="store full path to file in index", default=False)
31 |
32 | parser.add_argument('--validate', action="store_true",
33 | help="check Zettels only (don't import)", default=False)
34 |
35 | parser.add_argument('--create', action="store_true",
36 | help="create database and delete existing if present", default=False)
37 |
38 | args = parser.parse_args()
39 |
40 | if args.create or not os.path.exists(args.database):
41 | zcreate(args)
42 |
43 | db = zdb.get(args.database)
44 | zettel_dir = args.dir
45 |
46 | for entry in get_zettels(zettel_dir):
47 | if args.fullpath:
48 | filepath = os.path.abspath(entry)
49 | else:
50 | filepath = entry
51 | print("Processing %s" % filepath)
52 | if filepath.endswith('.yaml'):
53 | yaml_info = zettel.load_pure_yaml(filepath)
54 | elif filepath.endswith('.md'):
55 | yaml_info = zettel.load_markdown_with_frontmatter(filepath)
56 | else:
57 | print("Warning: %s is not .yaml or .md (ignoring)")
58 |
59 | (ydoc, document) = yaml_info
60 | if len(ydoc) > 0:
61 | try:
62 | z = zettel.Zettel(ydoc)
63 | except zettel.ParseError as error:
64 | error_text = str(error)
65 | print("%s:\n%s" % (filepath, error_text))
66 | continue
67 |
68 | if not args.validate:
69 | db.bind(z, filepath, document)
70 | db.insert_into_table()
71 |
72 | db.done()
73 |
74 |
75 | def zcreate(args):
76 | if os.path.exists(args.database):
77 | print("Deleting existing database %s" % args.database)
78 | os.unlink(args.database)
79 | print("Creating new database %s" % args.database)
80 | db = zdb.get(args.database)
81 | db.drop_table()
82 | db.create_table()
83 | db.done()
84 |
85 | if __name__ == '__main__':
86 | main()
87 |
--------------------------------------------------------------------------------
/zettelgeist/zquery.py:
--------------------------------------------------------------------------------
1 | import sys
2 | import readline
3 | import pprint
4 | import json
5 | import tatsu
6 | import argparse
7 | import os.path
8 | import tempfile
9 | import pprint
10 |
11 | from . import zdb, zettel
12 |
13 |
14 | def unquote(text):
15 | return text.replace('"', '').replace("'", "")
16 |
17 |
18 | class ZG(object):
19 | def literal(self, ast):
20 | return ast.word
21 |
22 | def _get_match_clause(self, ast, negate):
23 | text = unquote(ast.text)
24 | words = text.split()
25 | return " NEAR/1 ".join(["%s%s:%s" % (negate, ast.field, word) for word in words])
26 |
27 | def z_field(self, ast):
28 | match_clause = self._get_match_clause(ast, '')
29 | return "SELECT * FROM zettels WHERE zettels MATCH '%s'" % match_clause
30 |
31 | def and_expr(self, ast):
32 | if ast.op == '&':
33 | return "SELECT * from (%s INTERSECT %s)" % (ast.left, ast.right)
34 | elif ast.op == '!':
35 | return "SELECT * from (%s EXCEPT %s)" % (ast.left, ast.right)
36 | # else: parser should have caught any non-op
37 |
38 | def and_op(self, ast):
39 | return ast.op
40 |
41 | def or_expr(self, ast):
42 | return "SELECT * from (%s UNION %s)" % (ast.left, ast.right)
43 |
44 |
45 | def get_temp_table_name():
46 | return os.path.split(tempfile.mktemp())[1]
47 |
48 |
49 | class ZG2(object):
50 | def __init__(self, select_fields=["docid"]):
51 | self.queries = {}
52 | self.select_fields = ",".join(select_fields)
53 | self.temp_table_name = get_temp_table_name()
54 | self.create_temp_table_clause = "CREATE TABLE %s AS %%s" % self.temp_table_name
55 | self.drop_table_statement = "DROP TABLE IF EXISTS %s" % self.temp_table_name
56 | self.select_all = "SELECT docid from %s" % self.temp_table_name
57 |
58 | def sql_drop_matches_table(self):
59 | return self.drop_table_statement
60 |
61 | def sql_create_matches_table(self, compiled_query):
62 | return self.create_temp_table_clause % compiled_query
63 |
64 | def sql_get_matches(self):
65 | return self.select_all
66 |
67 | def get_field_query_sql(self, field, field_context, docid):
68 | default = """SELECT docid, %(field)s FROM zettels WHERE docid = %(docid)s""" % vars(
69 | )
70 | field_queries = self.queries.get(field, [default]).copy()
71 | for i in range(0, len(field_queries)):
72 | field_queries[i] = field_queries[i] % vars()
73 | #print(">>> field_queries", field_queries)
74 | return field_queries
75 |
76 | def literal(self, ast):
77 | return ast.word
78 |
79 | def _get_match_clause(self, ast, negate):
80 | text = unquote(ast.text)
81 | words = text.split()
82 | return " NEAR/1 ".join(["%s%s:%s" % (negate, ast.field, word) for word in words])
83 |
84 | def z_field(self, ast):
85 | match_clause = self._get_match_clause(ast, '')
86 | query_list = self.queries.get(ast.field, [])
87 | field_query = "SELECT docid FROM zettels WHERE zettels MATCH '%s'" % match_clause
88 | context_query = """SELECT docid, snippet(zettels, '[', ']', '...', -1, -%%(field_context)s) as %s, %s as %s_verbatim, offsets(zettels) as %s_offsets FROM zettels WHERE zettels MATCH '%s' AND docid = %%(docid)s""" % (
89 | ast.field, ast.field, ast.field, ast.field, match_clause)
90 | query_list.append(context_query)
91 | self.queries[ast.field] = query_list
92 | return field_query
93 |
94 | def and_expr(self, ast):
95 | if ast.op == '&':
96 | return "SELECT %s from (%s INTERSECT %s)" % (self.select_fields, ast.left, ast.right)
97 | elif ast.op == '!':
98 | return "SELECT %s from (%s EXCEPT %s)" % (self.select_fields, ast.left, ast.right)
99 | # else: parser should have caught any non-op
100 |
101 | def and_op(self, ast):
102 | return ast.op
103 |
104 | def or_expr(self, ast):
105 | return "SELECT %s from (%s UNION %s)" % (self.select_fields, ast.left, ast.right)
106 |
107 |
108 | def compile(input_line):
109 | parser = tatsu.compile(zdb.GRAMMAR)
110 | zg_semantics = ZG()
111 | ast = parser.parse(input_line, semantics=zg_semantics)
112 | return (ast, zg_semantics)
113 |
114 |
115 | def compile2(input_line):
116 | parser = tatsu.compile(zdb.GRAMMAR)
117 | zg_semantics = ZG2()
118 | ast = parser.parse(input_line, semantics=zg_semantics)
119 | return (ast, zg_semantics)
120 |
--------------------------------------------------------------------------------
/zettelgeist/zutils.py:
--------------------------------------------------------------------------------
1 | import argparse
2 | import os
3 | import os.path
4 | import sqlite3
5 |
6 | from . import zettel
7 |
8 | # Compute MD5 for large files
9 | #
10 | # Credit to:
11 | # stackoverflow.com/questions/1131220/get-md5-hash-of-big-files-in-python
12 |
13 |
14 | def md5_for_file(f, block_size=2**20):
15 | md5 = hashlib.md5()
16 | while True:
17 | data = f.read(block_size)
18 | if not data:
19 | break
20 | md5.update(data)
21 | return md5.digest()
22 |
23 |
24 | def write_to_file(filepath, text, **kwargs):
25 | mode = kwargs.get("mode", "a")
26 | newlines = kwargs.get("newlines", 1)
27 | with open(filepath, mode) as outfile:
28 | outfile.write(text)
29 | if newlines:
30 | outfile.write("\n" * int(newlines))
31 |
32 |
33 | def write_data(filename, mode, comment, statement):
34 | if not filename:
35 | return
36 | with open(filename, mode) as outfile:
37 | outfile.write("\n".join([comment, statement]) + "\n\n")
38 |
39 |
40 | def dirname(path):
41 | return os.path.split(path)[0]
42 |
43 |
44 | def basename(path):
45 | return os.path.split(path)[1]
46 |
--------------------------------------------------------------------------------
/zettelgeist/zversion.py:
--------------------------------------------------------------------------------
1 | #
2 | # ZettelGeist Version for Python
3 | #
4 |
5 | __version__ = "1.1.5"
6 |
7 | def version():
8 | return __version__
9 |
--------------------------------------------------------------------------------