├── .gitignore
├── INSTALL.md
├── LICENSE
├── README.md
├── bin
├── format_lean
└── format_project
├── docs
├── example
│ ├── colorful.css
│ ├── jquery.min.js
│ ├── lean.js
│ ├── lecture.css
│ ├── lecture.css.map
│ ├── sandwich.html
│ └── source.html
├── index.html
└── style.css
├── docs_src
├── build.sh
├── index.md
├── pandocfilter-pygments
└── template.html
├── examples
├── leanpkg.toml
└── src
│ └── sandwich.lean
├── requirements.txt
├── sass
├── _big_tactic_state_layout.scss
├── _definitions.scss
├── _examples.scss
├── _lean_elements.scss
├── _lemmas.scss
├── _proofs.scss
├── _reset.scss
├── _theorems.scss
├── _tikzcd.scss
├── _typography.scss
├── lecture.scss
├── teach_lean.scss
└── with_tufte.scss
├── setup.py
└── src
└── format_lean
├── __init__.py
├── colorful.css
├── jquery.min.js
├── lean.js
├── lecture.css
├── lecture.css.map
├── lexer.py
├── line_reader.py
├── objects.py
├── renderer.py
├── server.py
├── teach_lean.css
├── teach_lean.css.map
├── templates
├── definition
├── example
├── lemma
├── page
├── section
├── subsection
├── text
├── theorem
├── tikzcd
└── trad
├── tikzcd.py
├── with_tufte.css
└── with_tufte.css.map
/.gitignore:
--------------------------------------------------------------------------------
1 | **/__pycache__
2 | node_modules/
3 | package-lock.json
4 | **/Lean_formatter.egg-info
5 |
--------------------------------------------------------------------------------
/INSTALL.md:
--------------------------------------------------------------------------------
1 | # Lean formatter full install guide
2 |
3 | This guide assumes you use a Debian-based Linux (e.g. Ubuntu), although
4 | it may hopefully be somewhat relevant to more exotic operating systems.
5 | It will install this software in an isolated environment. Of course this
6 | means wasting some space, but it guarantees no unwanted side effects.
7 |
8 | ## Python 3.7
9 |
10 | You need a recent python, at least python 3.7, because we use
11 | the [dataclass decorator](https://docs.python.org/3.7/library/dataclasses.html#module-dataclasses). An easy way to arrange that is to use [PyEnv](https://github.com/pyenv/pyenv).
12 | ```bash
13 | git clone https://github.com/pyenv/pyenv.git ~/.pyenv
14 | ```
15 | You need to make sure your shell will find pyenv, for instance typing:
16 | ```bash
17 | echo 'export PATH="$HOME/.pyenv/bin:$PATH"' >> ~/.bashrc
18 | ```
19 |
20 | You are now ready to download python 3.7. It will be installed in your
21 | home directory, but you still need some system-wide library support. A
22 | good way to make sure everything is there is to run:
23 | ```bash
24 | sudo apt install -y make build-essential libssl-dev zlib1g-dev libbz2-dev libreadline-dev libsqlite3-dev wget curl llvm libncurses5-dev libncursesw5-dev xz-utils tk-dev libffi-dev liblzma-dev python-openssl
25 | ```
26 | or the equivalent command for non-Debian distributions.
27 |
28 | Then restart a shell in order to get your new PATH variable (or use
29 | `source ~/.bashrc`) and install the python version you need.
30 | ```bash
31 | pyenv install 3.7.2
32 | ```
33 | You should now have a working copy of python 3.7.2 hidden in
34 | `$HOME/.pyenv/versions/3.7.2` (pyenv does not do anything outside of
35 | this `.pyenv` folder, so you can very easily get rid of it by deleting
36 | this folder, and unsetting the PATH variable addition).
37 |
38 | We will now prepare for a virtual environment dedicated to
39 | `format_lean`. The most convenient way is to use a system-wide
40 | `virtualenvwrapper`, setting three shell environment variables to
41 | configure it:
42 | ```bash
43 | sudo apt install virtualenv python3-pip
44 | sudo -H pip3 install virtualenvwrapper
45 | echo -e 'export WORKON_HOME=$HOME/.virtualenvs\nexport VIRTUALENVWRAPPER_PYTHON=/usr/bin/python3\nsource /usr/local/bin/virtualenvwrapper.sh' >> ~/.bashrc
46 | ```
47 | And then create a virtual environment for `format_lean` (after
48 | restarting you shell, or at least sourcing bashrc in order to get those
49 | variables set) typing in your home:
50 | ```bash
51 | mkvirtualenv --python=$HOME/.pyenv/versions/3.7.2/bin/python format_lean
52 | ```
53 |
54 | ## Install a custom pygment library
55 |
56 | You will probably also want to get Lean syntax highlighthing. The most
57 | up to date version of [pygment](http://pygments.org/) for Lean can be found in
58 | [Gabriel's Ebner fork](https://bitbucket.org/gebner/pygments-main/downloads/)
59 |
60 | Activate your python virtualenv by typing `workon format_lean` in case
61 | you left it after creating it. Then download pygment using the above
62 | link, uncompress it, go to the created folder and type `pip install .`.
63 | You can then get rid of this folder.
64 |
65 | ## Install `format_lean`
66 |
67 | Sill inside the virtual environment, type
68 | ```bash
69 | git clone https://github.com/leanprover-community/format_lean.git
70 | cd format_lean
71 | pip install .
72 | ```
73 |
74 | You now have the format Lean library inside you virtual environment. You
75 | probably also want to `pip install ipython` for a nicer interactive
76 | experience.
77 |
--------------------------------------------------------------------------------
/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 | # Lean formatter
2 |
3 | This prototype is a python library which renders convert Lean files to
4 | other files, for instance another Lean file of a html file.
5 |
6 | ## Installation
7 |
8 | You need Python 3.7 or later, and Lean. Make sure the python package
9 | manager `pip` is installed. Clone this repository, go to its root directory
10 | and run `pip install .` (using `sudo -H` if needed). It's also recommended to
11 | install `ipython` for interactive use. Alternatively, if you don't want to mess
12 | up with your global python environment, you can use a dedicated virtual
13 | environment. This is explained in the more complete
14 | [installation guide](https://github.com/leanprover-community/format_lean/blob/master/INSTALL.md).
15 |
16 | ## Usage
17 |
18 | If you only want to play with my example formatter you can simply run
19 | `format_lean` (which should be in your path if `pip install .` did its
20 | job). The basic usage is:
21 | ```bash
22 | format_lean --inpath limits.lean --outdir build --lib-path /usr/lib/lean-mathlib/src
23 | ```
24 | if you are in a folder containing `limits.lean`, have mathlib in `/usr/lib/lean-mathlib`, and
25 | want to render into directory `build`. See `format_lean -- --help` for
26 | more option.
27 |
28 | Of course you need to point to your local copy of `mathlib` (unless you
29 | don't need mathlib?!). You can use `--toolchain` if your default `elan`
30 | toolchain isn't appropriate (you do use [elan](https://github.com/Kha/elan), right?). Optional
31 | arguments also include `outpath` if replacing `.lean` by `.html` is not
32 | good enough, and `templates` if you want to point to an alternate
33 | template directory.
34 |
35 | The script source in the `bin` folder of this repository is a good entry
36 | point to understand how to customize more.
37 |
38 | If you get addicted to it, and want to render a full Lean project, you
39 | can go to the root of the project (the folder containing `leanpkg.toml`)
40 | and run `format_project`. Optional arguments `--outdir my_dir` and
41 | `--template` as above. There is no need to point out a toolchain or
42 | dependencies since those are indicated in your `leanpkg.toml`.
43 | If you want to exclude files `src/hide_me.lean` and `src/secret.lean`
44 | from the rendering process, you can create a file `format.toml` next to
45 | your `leanpkg.toml` containing `exclude = ['hide_me.lean', 'secret.lean']`.
46 | On the other extreme, if you want to render only `public.lean`, you can
47 | use `only = ['public.lean']`.
48 | In this file you can also put `template = "path"` where path is the
49 | relative path to a folder containing jinja templates to be used instead
50 | of the default ones.
51 |
52 | When using `format_project`, you can put a file `format_lang.toml` containing some translations, say:
53 | ```
54 | Example = "Exemple"
55 | Lemma = "Lemme"
56 | Theorem = "Théorème"
57 | Proof = "Démonstration"
58 | ```
59 |
--------------------------------------------------------------------------------
/bin/format_lean:
--------------------------------------------------------------------------------
1 | #! /usr/bin/env python3
2 |
3 | from pathlib import Path
4 | import os, shutil, distutils.spawn
5 |
6 | from fire import Fire
7 | import toml
8 |
9 | import format_lean
10 | from format_lean.line_reader import FileReader
11 | from format_lean.renderer import Renderer
12 | from format_lean.objects import (HeaderBegin, HeaderEnd, SectionBegin,
13 | SectionEnd, SubSectionBegin, SubSectionEnd, TextBegin, TextEnd,
14 | DefinitionBegin, DefinitionEnd,
15 | ExampleBegin, ExampleEnd,
16 | LemmaBegin, LemmaEnd,
17 | TheoremBegin, TheoremEnd,
18 | ProofBegin, ProofEnd,
19 | ProofComment)
20 |
21 | module_path = Path(format_lean.__file__).parent
22 |
23 | def render_lean_file(inpath, outpath=None, outdir=None,
24 | toolchain=None, lib_path=None, templates=None, css='lecture.css',
25 | debug=False):
26 | if toolchain:
27 | lean_exec_path = Path.home() / '.elan/toolchains' / toolchain / 'bin/lean'
28 | core_path = lean_exec_path.parent / '../lib/lean/library'
29 | else:
30 | lean_exec_path = Path(distutils.spawn.find_executable('lean'))
31 | if '.elan' in str(lean_exec_path):
32 | s = toml.load(str(lean_exec_path.parent / '../settings.toml'))
33 | toolchain = s['default_toolchain']
34 | core_path = lean_exec_path.parent / '../toolchains' / toolchain / 'lib/lean/library'
35 | else:
36 | core_path = lean_exec_path.parent / '../lib/lean/library'
37 |
38 | lean_path = f'{core_path}:{lib_path}' if lib_path else core_path
39 | templates = templates or str(module_path / 'templates/')
40 | if debug:
41 | print(f"Lean executable path: {lean_exec_path}")
42 | print(f"LEAN_PATH: {lean_path}")
43 | print(f"Templates folder: {templates}")
44 |
45 | outpath = outpath or inpath.replace('.lean', '.html')
46 |
47 | if outdir:
48 | if not Path(outdir).is_dir():
49 | os.makedirs(outdir)
50 | outpath = str(Path(outdir) / outpath)
51 | for path in module_path.glob('*.css'):
52 | shutil.copy(path, outdir)
53 | for path in module_path.glob('*.css.map'):
54 | shutil.copy(path, outdir)
55 | for path in module_path.glob('*.js'):
56 | shutil.copy(path, outdir)
57 |
58 | lecture_reader = FileReader(lean_exec_path, lean_path,
59 | [HeaderBegin, HeaderEnd,
60 | SectionBegin, SectionEnd,
61 | SubSectionBegin, SubSectionEnd,
62 | TextBegin, TextEnd,
63 | DefinitionBegin, DefinitionEnd,
64 | ExampleBegin, ExampleEnd,
65 | LemmaBegin, LemmaEnd,
66 | TheoremBegin, TheoremEnd,
67 | ProofBegin, ProofEnd, ProofComment])
68 | lecture_reader.read_file(inpath)
69 | renderer = Renderer.from_file(templates)
70 | pc = { 'csss': [css, 'colorful.css'],
71 | 'jss': ['jquery.min.js', 'lean.js'],
72 | 'title': inpath.replace('.lean', ''),
73 | 'lang': dict() }
74 | renderer.render(lecture_reader.output, outpath, page_context=pc)
75 |
76 | if __name__ == '__main__':
77 | Fire(render_lean_file)
78 |
--------------------------------------------------------------------------------
/bin/format_project:
--------------------------------------------------------------------------------
1 | #! /usr/bin/env python3
2 |
3 | from pathlib import Path
4 | import os, sys, shutil, distutils.dir_util
5 |
6 | import regex
7 | from fire import Fire
8 | import toml
9 |
10 | import format_lean
11 | from format_lean.line_reader import FileReader
12 | from format_lean.renderer import Renderer
13 | from format_lean.server import LeanError
14 | from format_lean.objects import (HeaderBegin, HeaderEnd, SectionBegin,
15 | SectionEnd, SubSectionBegin, SubSectionEnd, TextBegin, TextEnd,
16 | DefinitionBegin, DefinitionEnd,
17 | ExampleBegin, ExampleEnd,
18 | LemmaBegin, LemmaEnd,
19 | TheoremBegin, TheoremEnd,
20 | ProofBegin, ProofEnd,
21 | ProofComment, Title,
22 | TradBegin, TradEnd)
23 |
24 | module_path = Path(format_lean.__file__).parent
25 |
26 | def render_lean_project(outdir=None, templates=None, css=None,
27 | debug=False):
28 | try:
29 | leanpkg_toml = toml.load('leanpkg.toml')
30 | except FileNotFoundError:
31 | print("Couldn't find a leanpkg.toml, I give up.")
32 | sys.exit(1)
33 | toolchain = leanpkg_toml['package']['lean_version']
34 | m = regex.match(r'leanprover-community/lean:(.*)', toolchain)
35 | if m:
36 | ver = m.group(1)
37 | if (Path.home() / '.elan/toolchains' / f'leanprover-community-lean-{ver}').exists():
38 | toolchain = f'leanprover-community-lean-{ver}'
39 | elif (Path.home() / '.elan/toolchains' / f'leanprover-community--lean---{ver}').exists():
40 | toolchain = f'leanprover-community--lean---{ver}'
41 |
42 | lean_exec_path = Path.home() / '.elan/toolchains' / toolchain / 'bin/lean'
43 | paths = [str(lean_exec_path.parent / '../lib/lean/library'),
44 | str(Path.cwd() / 'src')]
45 |
46 | for dep, dep_info in leanpkg_toml.get('dependencies', []).items():
47 | if 'git' in dep_info:
48 | paths.append(str(Path('_target/deps') / dep / 'src'))
49 | else:
50 | paths.extend([dep_info['path'], str(Path(dep_info['path'])/'src')])
51 | lean_path = ':'.join(paths)
52 | if debug:
53 | print("Lean executable path:", lean_exec_path)
54 | print("LEAN_PATH:", lean_path)
55 |
56 | try:
57 | format_toml = toml.load('format.toml')
58 | except FileNotFoundError:
59 | print(" I couldn't find format.toml, but I'll continue, "
60 | "hoping you know what you are doing.")
61 | format_toml = dict()
62 |
63 | templates = templates or (format_toml.get('templates') or
64 | str(module_path / 'templates/'))
65 | if debug:
66 | print("Template folder:", templates)
67 |
68 | only = format_toml.get('only', [])
69 | excludes = format_toml.get('exclude', [])
70 |
71 | try:
72 | lang = toml.load('format_lang.toml')
73 | except:
74 | lang = dict()
75 |
76 | outdir = outdir or format_toml.get('outdir', 'html')
77 | if not Path(outdir).is_dir():
78 | os.makedirs(outdir)
79 |
80 | csss = css or format_toml.get('css', ['lecture.css'])
81 | csss += ['colorful.css']
82 | for path in module_path.glob('*.css'):
83 | if path.name in csss:
84 | shutil.copy(path, outdir)
85 | try:
86 | shutil.copy(str(path)+'.map', outdir)
87 | except FileNotFoundError:
88 | pass
89 |
90 | if 'js' in format_toml:
91 | jss = format_toml['js']
92 | for path in jss:
93 | shutil.copy(path, outdir)
94 | shutil.copy(module_path /'jquery.min.js', outdir)
95 | jss = ['jquery.min.js'] + jss
96 | else:
97 | jss = ['jquery.min.js']
98 | for path in module_path.glob('*.js'):
99 | shutil.copy(path, outdir)
100 | if path.name != 'jquery.min.js':
101 | jss.append(path.name)
102 |
103 | assets = format_toml.get('assets', [])
104 | for asset in assets:
105 | if debug:
106 | print("Copying asset:", asset)
107 | if Path(asset).is_dir():
108 | distutils.dir_util.copy_tree(asset, str(Path(outdir)/asset))
109 | else:
110 | shutil.copy(asset, outdir)
111 |
112 | ts_filters = [(regex.compile(s[0]), s[1])
113 | for s in format_toml.get('tactic_state_filters', [])]
114 | if debug:
115 | print('Tactic state filters: ', ts_filters)
116 |
117 |
118 | lecture_reader = FileReader(lean_exec_path, lean_path,
119 | [Title,
120 | HeaderBegin, HeaderEnd,
121 | SectionBegin, SectionEnd,
122 | SubSectionBegin, SubSectionEnd,
123 | TextBegin, TextEnd,
124 | DefinitionBegin, DefinitionEnd,
125 | ExampleBegin, ExampleEnd,
126 | LemmaBegin, LemmaEnd,
127 | TheoremBegin, TheoremEnd,
128 | ProofBegin, ProofEnd, ProofComment,
129 | TradBegin, TradEnd])
130 | renderer = Renderer.from_file(templates, ts_filters=ts_filters)
131 |
132 | for lean_file in Path('src').glob('**/*.lean'):
133 | rel_path = str(lean_file.relative_to('src'))
134 | if (only and rel_path not in only) or rel_path in excludes:
135 | if not only:
136 | print('Excluding ' + str(lean_file))
137 | continue
138 | tgt_dir = Path(outdir) / lean_file.relative_to('src').parent
139 | tgt_dir.mkdir(parents=True, exist_ok=True)
140 | outpath = str(Path(outdir) / lean_file.relative_to('src')).replace('.lean', '.html')
141 | try:
142 | if os.path.getmtime(outpath) > os.path.getmtime(lean_file):
143 | print('Skipping ' + str(lean_file) + ' which is up to date')
144 | continue
145 | except OSError:
146 | pass
147 | print('Rendering ' + str(lean_file))
148 | try:
149 | lecture_reader.read_file(str(lean_file))
150 | except LeanError as ex:
151 | print(ex)
152 | continue
153 | depth = len(lean_file.relative_to('src').parts) - 1
154 | prefix = depth*'../'
155 | css_paths = [prefix + css for css in csss]
156 | if debug:
157 | print('css paths: ', css_paths)
158 | pc = { 'csss': css_paths,
159 | 'jss': [prefix + js for js in jss],
160 | 'title': lecture_reader.metadata.get('title',
161 | lean_file.name.replace('.lean', '')),
162 | 'lang': lang}
163 | renderer.render(lecture_reader.output, outpath, page_context=pc)
164 | lecture_reader.hard_reset()
165 |
166 | if __name__ == '__main__':
167 | Fire(render_lean_project)
168 |
--------------------------------------------------------------------------------
/docs/example/colorful.css:
--------------------------------------------------------------------------------
1 | .highlight .hll { background-color: #ffffcc }
2 | .highlight .c { color: #808080 } /* Comment */
3 | .highlight .err { color: #F00000; background-color: #F0A0A0 } /* Error */
4 | .highlight .k { color: #008000; font-weight: bold } /* Keyword */
5 | .highlight .o { color: #303030 } /* Operator */
6 | .highlight .cm { color: #808080 } /* Comment.Multiline */
7 | .highlight .cp { color: #507090 } /* Comment.Preproc */
8 | .highlight .c1 { color: #808080 } /* Comment.Single */
9 | .highlight .cs { color: #cc0000; font-weight: bold } /* Comment.Special */
10 | .highlight .gd { color: #A00000 } /* Generic.Deleted */
11 | .highlight .ge { font-style: italic } /* Generic.Emph */
12 | .highlight .gr { color: #FF0000 } /* Generic.Error */
13 | .highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */
14 | .highlight .gi { color: #00A000 } /* Generic.Inserted */
15 | .highlight .go { color: #808080 } /* Generic.Output */
16 | .highlight .gp { color: #c65d09; font-weight: bold } /* Generic.Prompt */
17 | .highlight .gs { font-weight: bold } /* Generic.Strong */
18 | .highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
19 | .highlight .gt { color: #0040D0 } /* Generic.Traceback */
20 | .highlight .kc { color: #008000; font-weight: bold } /* Keyword.Constant */
21 | .highlight .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */
22 | .highlight .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */
23 | .highlight .kp { color: #003080; font-weight: bold } /* Keyword.Pseudo */
24 | .highlight .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */
25 | .highlight .kt { color: #303090; font-weight: bold } /* Keyword.Type */
26 | .highlight .m { color: #6000E0; font-weight: bold } /* Literal.Number */
27 | .highlight .s { background-color: #fff0f0 } /* Literal.String */
28 | .highlight .na { color: #0000C0 } /* Name.Attribute */
29 | .highlight .nb { color: #007020 } /* Name.Builtin */
30 | .highlight .nc { color: #B00060; font-weight: bold } /* Name.Class */
31 | .highlight .no { color: #003060; font-weight: bold } /* Name.Constant */
32 | .highlight .nd { color: #505050; font-weight: bold } /* Name.Decorator */
33 | .highlight .ni { color: #800000; font-weight: bold } /* Name.Entity */
34 | .highlight .ne { color: #F00000; font-weight: bold } /* Name.Exception */
35 | .highlight .nf { color: #0060B0; font-weight: bold } /* Name.Function */
36 | .highlight .nl { color: #907000; font-weight: bold } /* Name.Label */
37 | .highlight .nn { color: #0e84b5; font-weight: bold } /* Name.Namespace */
38 | .highlight .nt { color: #007000 } /* Name.Tag */
39 | .highlight .nv { color: #906030 } /* Name.Variable */
40 | .highlight .ow { color: #000000; font-weight: bold } /* Operator.Word */
41 | .highlight .w { color: #bbbbbb } /* Text.Whitespace */
42 | .highlight .mf { color: #6000E0; font-weight: bold } /* Literal.Number.Float */
43 | .highlight .mh { color: #005080; font-weight: bold } /* Literal.Number.Hex */
44 | .highlight .mi { color: #0000D0; font-weight: bold } /* Literal.Number.Integer */
45 | .highlight .mo { color: #4000E0; font-weight: bold } /* Literal.Number.Oct */
46 | .highlight .sb { background-color: #fff0f0 } /* Literal.String.Backtick */
47 | .highlight .sc { color: #0040D0 } /* Literal.String.Char */
48 | .highlight .sd { color: #D04020 } /* Literal.String.Doc */
49 | .highlight .s2 { background-color: #fff0f0 } /* Literal.String.Double */
50 | .highlight .se { color: #606060; font-weight: bold; background-color: #fff0f0 } /* Literal.String.Escape */
51 | .highlight .sh { background-color: #fff0f0 } /* Literal.String.Heredoc */
52 | .highlight .si { background-color: #e0e0e0 } /* Literal.String.Interpol */
53 | .highlight .sx { color: #D02000; background-color: #fff0f0 } /* Literal.String.Other */
54 | .highlight .sr { color: #000000; background-color: #fff0ff } /* Literal.String.Regex */
55 | .highlight .s1 { background-color: #fff0f0 } /* Literal.String.Single */
56 | .highlight .ss { color: #A06000 } /* Literal.String.Symbol */
57 | .highlight .bp { color: #007020 } /* Name.Builtin.Pseudo */
58 | .highlight .vc { color: #306090 } /* Name.Variable.Class */
59 | .highlight .vg { color: #d07000; font-weight: bold } /* Name.Variable.Global */
60 | .highlight .vi { color: #3030B0 } /* Name.Variable.Instance */
61 | .highlight .il { color: #0000D0; font-weight: bold } /* Literal.Number.Integer.Long */
62 |
--------------------------------------------------------------------------------
/docs/example/lean.js:
--------------------------------------------------------------------------------
1 | var dragging = false;
2 |
3 | $('#dragbar').mousedown(function(e){
4 | e.preventDefault();
5 | dragging = true;
6 | var content = $('#content');
7 | var dragbar = $('#dragbar');
8 | var tsw = $('#tactic_state_wrapper');
9 | console.log("Resizing...");
10 | $(document).mousemove(function(ex){
11 | content.css("width", ex.pageX +2);
12 | dragbar.css("left", ex.pageX +2);
13 | tsw.css("margin-left", ex.pageX +2);
14 | });
15 | });
16 |
17 | $(document).mouseup(function(e){
18 | if (dragging)
19 | {
20 | $(document).unbind('mousemove');
21 | dragging = false;
22 | }
23 | });
24 |
25 | $(document).ready(function() {
26 | $("div.definition_text").click(
27 | function() {
28 | $(this).siblings("div.definition_lean").slideToggle()
29 | })
30 | $("div.example_text").click(
31 | function() {
32 | $(this).siblings("div.example_lean").slideToggle()
33 | })
34 | $("div.lemma_text").click(
35 | function() {
36 | $(this).siblings("div.lemma_lean").slideToggle()
37 | })
38 | $("div.theorem_text").click(
39 | function() {
40 | $(this).siblings("div.theorem_lean").slideToggle()
41 | })
42 | $("span.proof_item_text").click(
43 | function() {
44 | $(this).siblings("div.proof_item_lean").slideToggle()
45 | })
46 |
47 | $("span.tactic_left").click(
48 | function() {
49 | var width = $('#content').css("width");
50 | $("div#tactic_state").html(
51 | $(this).siblings("span.tactic_state_left").html());
52 | $('#content').css("width", width);
53 | })
54 |
55 | $("span.tactic_right").click(
56 | function() {
57 | var width = $('#content').css("width");
58 | $("div#tactic_state").html(
59 | $(this).siblings("span.tactic_state_right").html())
60 | $('#content').css("width", width);
61 | })
62 | });
63 |
--------------------------------------------------------------------------------
/docs/example/lecture.css:
--------------------------------------------------------------------------------
1 | @charset "UTF-8";
2 | h1#tactic_state_header {
3 | font-size: 1.2rem;
4 | line-height: 2rem;
5 | margin: 1rem 0;
6 | color: #0f2f48;
7 | }
8 |
9 | #dragbar {
10 | background-color: #0f2f48;
11 | }
12 |
13 | body {
14 | color: #0a0a14;
15 | background-color: #e8e8e8;
16 | }
17 |
18 | html,
19 | body,
20 | div,
21 | span,
22 | applet,
23 | object,
24 | iframe,
25 | h1,
26 | h2,
27 | h3,
28 | h4,
29 | h5,
30 | h6,
31 | p,
32 | blockquote,
33 | pre,
34 | a,
35 | abbr,
36 | acronym,
37 | address,
38 | big,
39 | cite,
40 | code,
41 | del,
42 | dfn,
43 | em,
44 | img,
45 | ins,
46 | kbd,
47 | q,
48 | s,
49 | samp,
50 | small,
51 | strike,
52 | strong,
53 | sub,
54 | sup,
55 | tt,
56 | var,
57 | b,
58 | u,
59 | i,
60 | center,
61 | dl,
62 | dt,
63 | dd,
64 | ol,
65 | ul,
66 | li,
67 | fieldset,
68 | form,
69 | label,
70 | legend,
71 | table,
72 | caption,
73 | tbody,
74 | tfoot,
75 | thead,
76 | tr,
77 | th,
78 | td,
79 | article,
80 | aside,
81 | canvas,
82 | details,
83 | embed,
84 | figure,
85 | figcaption,
86 | footer,
87 | header,
88 | hgroup,
89 | menu,
90 | nav,
91 | output,
92 | ruby,
93 | section,
94 | summary,
95 | time,
96 | mark,
97 | audio,
98 | video {
99 | font: inherit;
100 | font-size: 100%;
101 | margin: 0;
102 | padding: 0;
103 | border: 0;
104 | }
105 |
106 | /* HTML5 display-role reset for older browsers */
107 | article,
108 | aside,
109 | details,
110 | figcaption,
111 | figure,
112 | footer,
113 | header,
114 | hgroup,
115 | menu,
116 | nav,
117 | section {
118 | display: block;
119 | }
120 |
121 | body {
122 | line-height: 1;
123 | overflow-x: hidden;
124 | background: #f4f4f4;
125 | }
126 |
127 | ol,
128 | ul {
129 | list-style: none;
130 | }
131 |
132 | blockquote,
133 | q {
134 | quotes: none;
135 | }
136 |
137 | blockquote:before,
138 | blockquote:after,
139 | q:before,
140 | q:after {
141 | content: "";
142 | content: none;
143 | }
144 |
145 | table {
146 | border-spacing: 0;
147 | border-collapse: collapse;
148 | }
149 |
150 | .clear:after {
151 | font-size: 0;
152 | display: block;
153 | visibility: hidden;
154 | clear: both;
155 | height: 0;
156 | content: " ";
157 | }
158 |
159 | .clear {
160 | display: inline-block;
161 | }
162 |
163 | /* start commented backslash hack \*/
164 | * html .clear {
165 | height: 1%;
166 | }
167 |
168 | .clear {
169 | display: block;
170 | }
171 |
172 | /* close commented backslash hack */
173 | /****************************************
174 | BASIC ELEMENTS
175 | *****************************************/
176 | * {
177 | -webkit-box-sizing: border-box;
178 | -moz-box-sizing: border-box;
179 | box-sizing: border-box;
180 | }
181 |
182 | hr {
183 | clear: both;
184 | border: none;
185 | outline: none;
186 | }
187 |
188 | em {
189 | font-style: italic;
190 | }
191 |
192 | a {
193 | text-decoration: underline;
194 | }
195 |
196 | ul {
197 | list-style: disc;
198 | }
199 |
200 | ol {
201 | list-style: decimal;
202 | }
203 |
204 | ul,
205 | ol {
206 | font-size: 14px;
207 | padding: 0 0 0 33px;
208 | }
209 | ul li,
210 | ol li {
211 | margin: 0;
212 | }
213 |
214 | blockquote {
215 | padding: 0 15px 0 40px;
216 | }
217 |
218 | table {
219 | font-size: 13px;
220 | width: 100%;
221 | margin: 20px 0;
222 | background: white;
223 | }
224 | table th {
225 | font-size: 16px;
226 | font-weight: bold;
227 | }
228 | table tr td {
229 | padding: 7px;
230 | }
231 |
232 | ::selection {
233 | color: white;
234 | background: #000;
235 | }
236 |
237 | ::-moz-selection {
238 | color: white;
239 | background: #000;
240 | }
241 |
242 | html {
243 | position: relative;
244 | }
245 |
246 | body {
247 | margin: 0;
248 | }
249 |
250 | div#wrapper {
251 | width: 100%;
252 | min-height: 100%;
253 | }
254 |
255 | div#content {
256 | padding: 1rem;
257 | width: 70%;
258 | }
259 |
260 | #dragbar {
261 | position: absolute;
262 | top: 0;
263 | min-height: 100%;
264 | left: 70%;
265 | width: 3px;
266 | cursor: col-resize;
267 | }
268 |
269 | div#tactic_state_wrapper {
270 | position: fixed;
271 | margin-left: 70%;
272 | top: 0px;
273 | padding: 1rem;
274 | }
275 |
276 | div.content {
277 | line-height: 1.4rem;
278 | }
279 |
280 | p {
281 | line-height: 1.5rem;
282 | }
283 |
284 | li > p {
285 | margin: 0.28rem 0;
286 | }
287 |
288 | h1, h2, h3, h4, h5, h6 {
289 | font-family: "Lucida Grande", Arial, Helvetica, sans-serif;
290 | }
291 |
292 | h1 {
293 | font-size: 2rem;
294 | line-height: 2rem;
295 | margin: 1rem 0;
296 | color: #0f2f48;
297 | }
298 |
299 | h2 {
300 | font-size: 1.5rem;
301 | margin: 0.8rem 0;
302 | color: #0f2f48;
303 | }
304 |
305 | h3 {
306 | font-size: 1rem;
307 | margin: 0.67rem 0;
308 | color: #0f2f48;
309 | }
310 |
311 | h4 {
312 | font-size: 1rem;
313 | margin: 0.67rem 0;
314 | color: #0f2f48;
315 | }
316 |
317 | p {
318 | font-size: 1rem;
319 | margin: 0.5rem 0;
320 | }
321 |
322 | /**
323 | * Address style set to `bolder` in Firefox 4+, Safari 5, and Chrome.
324 | */
325 | b,
326 | strong {
327 | font-weight: bold;
328 | }
329 |
330 | /**
331 | * Address styling not present in Safari 5 and Chrome.
332 | */
333 | dfn {
334 | font-style: italic;
335 | }
336 |
337 | /**
338 | * Correct font family set oddly in Safari 5 and Chrome.
339 | */
340 | code,
341 | kbd,
342 | pre,
343 | samp {
344 | font-family: monospace, serif;
345 | font-size: 1rem;
346 | }
347 |
348 | /**
349 | * Improve readability of pre-formatted text in all browsers.
350 | */
351 | pre {
352 | white-space: pre-wrap;
353 | }
354 |
355 | /**
356 | * Set consistent quote types.
357 | */
358 | q {
359 | quotes: "“" "”" "‘" "’";
360 | }
361 |
362 | /**
363 | * Address inconsistent and variable font size in all browsers.
364 | */
365 | small {
366 | font-size: 80%;
367 | }
368 |
369 | /**
370 | * Prevent `sub` and `sup` affecting `line-height` in all browsers.
371 | */
372 | sub,
373 | sup {
374 | font-size: 75%;
375 | line-height: 0;
376 | position: relative;
377 | vertical-align: baseline;
378 | }
379 |
380 | sup {
381 | top: -0.5rem;
382 | }
383 |
384 | sub {
385 | bottom: -0.25rem;
386 | }
387 |
388 | /* Font Selection */
389 | .mdseries, .textmf {
390 | font-weight: normal;
391 | }
392 |
393 | .bfseries, .textbf {
394 | font-weight: bold;
395 | }
396 |
397 | .rmfamily, .textrm {
398 | font-family: serif;
399 | }
400 |
401 | .sffamily, .textsf {
402 | font-family: sans-serif;
403 | }
404 |
405 | .ttfamily, .texttt {
406 | font-family: monospace;
407 | }
408 |
409 | .upshape, .textup {
410 | text-transform: uppercase;
411 | }
412 |
413 | .itshape, .textit {
414 | font-style: italic;
415 | }
416 |
417 | .slshape, .textsl {
418 | font-style: oblique;
419 | }
420 |
421 | .scshape, .textsc {
422 | font-variant: small-caps;
423 | }
424 |
425 | small.tiny {
426 | font-size: x-small;
427 | }
428 |
429 | small.scriptsize {
430 | font-size: smaller;
431 | }
432 |
433 | small.footnotesize {
434 | font-size: small;
435 | }
436 |
437 | small.small {
438 | font-size: small;
439 | }
440 |
441 | .normalsize {
442 | font-size: normal;
443 | }
444 |
445 | big.large {
446 | font-size: large;
447 | }
448 |
449 | big.xlarge {
450 | font-size: x-large;
451 | }
452 |
453 | big.xxlarge {
454 | font-size: x-large;
455 | }
456 |
457 | big.huge {
458 | font-size: xx-large;
459 | }
460 |
461 | big.xhuge {
462 | font-size: xx-large;
463 | }
464 |
465 | /* Fonts */
466 | .rm {
467 | font-family: serif;
468 | font-style: normal;
469 | font-weight: normal;
470 | }
471 |
472 | .cal {
473 | font-family: serif;
474 | font-style: italic;
475 | font-weight: normal;
476 | }
477 |
478 | .it {
479 | font-family: serif;
480 | font-style: italic;
481 | font-weight: normal;
482 | }
483 |
484 | .sl {
485 | font-family: serif;
486 | font-style: oblique;
487 | font-weight: normal;
488 | }
489 |
490 | .bf {
491 | font-family: serif;
492 | font-style: normal;
493 | font-weight: bold;
494 | }
495 |
496 | .tt {
497 | font-family: monospace;
498 | font-style: normal;
499 | font-weight: normal;
500 | }
501 |
502 | .underbar {
503 | text-decoration: underline;
504 | }
505 |
506 | /* Boxes */
507 | .fbox, .framebox {
508 | border: 1px black solid;
509 | padding-top: 1px;
510 | padding-bottom: 1px;
511 | padding-left: 3px;
512 | padding-right: 3px;
513 | }
514 |
515 | /* Quotations and Verse */
516 | .quotation p, .quote p, .verse p {
517 | margin-top: 0px;
518 | margin-bottom: 0.5em;
519 | }
520 |
521 | hr {
522 | color: black;
523 | }
524 |
525 | dd {
526 | margin-left: 3rem;
527 | }
528 |
529 | dd p {
530 | padding: 0;
531 | margin: 0 0 1rem 0;
532 | }
533 |
534 | div.definition_wrapper {
535 | margin-top: 1rem;
536 | }
537 |
538 | span.definition_label {
539 | font-weight: bold;
540 | }
541 |
542 | div.definition_content {
543 | margin-left: 0.5rem;
544 | padding-left: 0.5rem;
545 | border-left: 0.15rem solid black;
546 | }
547 |
548 | div.definition_text:hover {
549 | transition: all 0.2s ease;
550 | background: #cfcfcf;
551 | }
552 |
553 | div.definition_lean {
554 | display: none;
555 | }
556 |
557 | div.example_wrapper {
558 | margin-top: 1rem;
559 | }
560 |
561 | span.example_label {
562 | font-weight: bold;
563 | }
564 |
565 | div.example_content {
566 | margin-left: 0.5rem;
567 | padding-left: 0.5rem;
568 | border-left: 0.25rem solid black;
569 | }
570 |
571 | div.example_text:hover {
572 | transition: all 0.2s ease;
573 | background: #cfcfcf;
574 | }
575 |
576 | div.example_lean {
577 | display: none;
578 | }
579 |
580 | div.lemma_wrapper {
581 | margin-top: 1rem;
582 | }
583 |
584 | span.lemma_label {
585 | font-weight: bold;
586 | }
587 |
588 | div.lemma_content {
589 | margin-left: 0.5rem;
590 | padding-left: 0.5rem;
591 | border-left: 0.15rem solid black;
592 | }
593 |
594 | div.lemma_text:hover {
595 | transition: all 0.2s ease;
596 | background: #cfcfcf;
597 | }
598 |
599 | div.lemma_lean {
600 | display: none;
601 | }
602 |
603 | div.theorem_wrapper {
604 | margin-top: 1rem;
605 | }
606 |
607 | span.theorem_label {
608 | font-weight: bold;
609 | }
610 |
611 | div.theorem_content {
612 | margin-left: 0.5rem;
613 | padding-left: 0.5rem;
614 | border-left: 0.25rem solid black;
615 | }
616 |
617 | div.theorem_lean {
618 | display: none;
619 | }
620 |
621 | div.proof_wrapper {
622 | margin-top: 1rem;
623 | width: 100%;
624 | }
625 |
626 | div.proof_wrapper::after {
627 | content: "";
628 | clear: both;
629 | display: table;
630 | }
631 |
632 | span.proof_label {
633 | font-weight: bold;
634 | display: block;
635 | }
636 |
637 | span.proof_qed {
638 | font-weight: bold;
639 | display: block;
640 | }
641 |
642 | div.proof_content {
643 | padding-left: 0.5rem;
644 | }
645 |
646 | div.small_proof_content {
647 | padding-left: 0.5rem;
648 | width: 49%;
649 | float: left;
650 | }
651 |
652 | div.small_tactic_state {
653 | padding-left: 0.5rem;
654 | width: 49%;
655 | float: left;
656 | }
657 |
658 | div.proof_item_lean {
659 | display: none;
660 | }
661 |
662 | div.proof_line {
663 | display: flex;
664 | }
665 |
666 | div.inline_proof_item {
667 | display: inline;
668 | }
669 |
670 | span.tactic_left:hover {
671 | transition: all 0.2s ease;
672 | background: #cfcfcf;
673 | }
674 |
675 | span.tactic_left {
676 | width: 3rem;
677 | background: #dbdbdb;
678 | }
679 |
680 | span.tactic_right {
681 | margin-left: 2rem;
682 | width: 3rem;
683 | background: #dbdbdb;
684 | }
685 |
686 | span.tactic_right:hover {
687 | transition: all 0.2s ease;
688 | background: #cfcfcf;
689 | }
690 |
691 | span[class^=tactic_state_] {
692 | display: none;
693 | }
694 |
695 | /*# sourceMappingURL=lecture.css.map */
696 |
--------------------------------------------------------------------------------
/docs/example/lecture.css.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sourceRoot":"","sources":["../../sass/lecture.scss","../../sass/_reset.scss","../../sass/_big_tactic_state_layout.scss","../../sass/_typography.scss","../../sass/_definitions.scss","../../sass/_examples.scss","../../sass/_lemmas.scss","../../sass/_theorems.scss","../../sass/_proofs.scss"],"names":[],"mappings":";AAOA;EACE;EACA;EACA;EACA,OAXa;;;AAaf;EACG,kBAdY;;;AAgBf;EAEI,OAfc;EAgBd,kBAjBe;;;ACFnB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;EAkFI;EACA;EAEA;EACA;EAEA;;;AAEJ;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;EAYI;;;AAEJ;EAEI;EAEA;EAEA;;;AAEJ;AAAA;EAGI;;;AAEJ;AAAA;EAGI;;;AAEJ;AAAA;AAAA;AAAA;EAKI;EACA;;;AAEJ;EAEI;EACA;;;AAGJ;EAEI;EAEA;EACA;EACA;EAEA;EAEA;;;AAEJ;EAEI;;;AAEJ;AACA;EAEI;;;AAEJ;EAEI;;;AAEJ;AAEA;AAAA;AAAA;AAGA;EAEI;EACG;EACK;;;AAGZ;EAEI;EAEA;EACA;;;AAGJ;EAEI;;;AAGJ;EAEI;;;AAEJ;EAEI;;;AAEJ;EAEI;;;AAEJ;AAAA;EAGI;EAEA;;AAEA;AAAA;EAEI;;;AAIR;EAEI;;;AAGJ;EAEI;EAEA;EACA;EAEA;;AAGA;EAEI;EACA;;AAKA;EAEI;;;AAKZ;EAEI;EACA;;;AAEJ;EAEI;EACA;;;AC1PJ;EACC;;;AAGD;EACI;;;AASJ;EACE;EACA;;;AAGF;EAEE;EACA,OAVW;;;AAab;EACG;EACA;EACA;EACA,MAjBU;EAkBV;EACA;;;AAGH;EAEE;EACA,aAzBW;EA0BX;EACA;;;ACvCF;EAEI,aHGkB;;;AGAtB;EAEC;;;AAGD;EAEI;;;AAGJ;EACI;;;AAIJ;EAEI;EACA;EAEA;EAEA,OH3BW;;;AG8Bf;EAEI;EAEA;EAEA,OHpCW;;;AGuCf;EAEI;EAEA;EAEA,OH7CW;;;AGgDf;EAEI;EAEA;EAEA,OHtDW;;;AGyDf;EAEI;EAEA;;;AAIJ;AAAA;AAAA;AAIA;AAAA;EAGI;;;AAGJ;AAAA;AAAA;AAIA;EAEI;;;AAIJ;AAAA;AAAA;AAIA;AAAA;AAAA;AAAA;EAKI;EACA;;;AAGJ;AAAA;AAAA;AAIA;EAEI;;;AAGJ;AAAA;AAAA;AAIA;EAEI;;;AAGJ;AAAA;AAAA;AAIA;EAEI;;;AAGJ;AAAA;AAAA;AAIA;AAAA;EAGI;EACA;EAEA;EAEA;;;AAGJ;EAEI;;;AAGJ;EAEI;;;AAGJ;AACA;EAAoB;;;AACpB;EAAoB;;;AACpB;EAAoB;;;AACpB;EAAoB;;;AACpB;EAAoB;;;AACpB;EAAoB;;;AACpB;EAAoB;;;AACpB;EAAoB;;;AACpB;EAAoB;;;AAEpB;EAAoB;;;AACpB;EAAoB;;;AACpB;EAAoB;;;AACpB;EAAoB;;;AACpB;EAAoB;;;AACpB;EAAoB;;;AACpB;EAAoB;;;AACpB;EAAoB;;;AACpB;EAAoB;;;AACpB;EAAoB;;;AAEpB;AACA;EACI;EACA;EACA;;;AAEJ;EACI;EACA;EACA;;;AAEJ;EACI;EACA;EACA;;;AAEJ;EACI;EACA;EACA;;;AAEJ;EACI;EACA;EACA;;;AAEJ;EACI;EACA;EACA;;;AAGJ;EAAW;;;AAEX;AACA;EACI;EACA;EACA;EACA;EACA;;;AAGJ;AAGA;EACI;EACA;;;AAGJ;EAAI;;;AAEJ;EACE;;;AAEF;EACE;EACA;;;ACnOF;EAEI;;;AAGJ;EAEI;;;AAGJ;EAEI;EACA;EACA;;;AAGJ;EAEE;EAEA;;;AAGF;EAKC;;;AC9BD;EAEI;;;AAGJ;EAEI;;;AAGJ;EAEI;EACA;EACA;;;AAGJ;EAEE;EAEA;;;AAGF;EAKC;;;AC7BD;EAEI;;;AAGJ;EAEI;;;AAGJ;EAEI;EACA;EACA;;;AAGJ;EAEE;EAEA;;;AAGF;EAEE;;;AC1BF;EAEI;;;AAGJ;EAEI;;;AAGJ;EAEI;EACA;EACA;;;AAYJ;EAKC;;;ACjCD;EAEI;EACF;;;AAEF;EACE;EACA;EACA;;;AAGF;EAEI;EACF;;;AAGF;EAEI;EACF;;;AAIF;EAEI;;;AAGJ;EAEI;EACF;EACA;;;AAGF;EAEI;EACF;EACA;;;AAYF;EAIC;;;AAGD;EACE;;;AAIF;EAEC;;;AAGD;EACE;EACA;;;AAEF;EACE;EACA;;;AACF;EACE;EACA;EACA;;;AACF;EACE;EACA;;;AACF;EACE","file":"lecture.css"}
--------------------------------------------------------------------------------
/docs/example/source.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Format Lean
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 | -- begin header
16 |
17 | -- Everything in the header will be hidden in the HTML file.
18 | import data . real . basic
19 |
20 | notation `|` x `|` := abs x
21 |
22 | @ [ user_attribute ]
23 | meta def ineq_rules : user_attribute :=
24 | { name := ` ineq_rules ,
25 | descr := "lemmas usable to prove inequalities" }
26 |
27 | attribute [ ineq_rules ] add_lt_add le_max_left le_max_right
28 |
29 | meta def obvious_ineq := ` [ linarith <|> apply_rules ineq_rules ]
30 | run_cmd add_interactive [ ` obvious_ineq ]
31 | -- end header
32 |
33 | /-
34 | # The sandwich theorem
35 |
36 | In this demo file, we define limits of sequences of real numbers and prove the sandwich theorem.
37 | -/
38 |
39 | /- Definition
40 | A sequence of real numbers $a_n$ tends to $l$ if
41 | $\forall \varepsilon > 0, \exists N, \forall n \geq N, |a_n - l | \leq \varepsilon$.
42 | -/
43 | definition is_limit ( a : ℕ → ℝ ) ( l : ℝ ) :=
44 | ∀ ε > 0 , ∃ N , ∀ n ≥ N , | a n - l | < ε
45 |
46 | /- Theorem
47 | If $(a_n)$, $(b_n)$, and $(c_n)$ are three real-valued sequences satisfying $a_n ≤ b_n ≤ c_n$ for all $n$, and if furthermore $a_n→ℓ$ and $c_n→ℓ$, then $b_n→ℓ$.
48 | -/
49 | theorem sandwich ( a b c : ℕ → ℝ )
50 | ( l : ℝ ) ( ha : is_limit a l ) ( hc : is_limit c l )
51 | ( hab : ∀ n , a n ≤ b n ) ( hbc : ∀ n , b n ≤ c n ) : is_limit b l :=
52 | begin
53 | -- We need to show that for all $ε>0$ there exists $N$ such that $n≥N$ implies $|b_n-ℓ|<ε$. So choose ε > 0.
54 | intros ε Hε ,
55 | -- we now need an $N$. As usual it is the max of two other N's, one coming from $(a_n)$ and one from $(c_n)$. Choose $N_a$ and $N_c$ such that $|aₙ - l| < ε$ for $n ≥ Na$ and $|cₙ - l| < ε$ for $n ≥ Nc$.
56 | cases ha ε Hε with Na Ha ,
57 | cases hc ε Hε with Nc Hc ,
58 | -- Now let $N$ be the max of $N_a$ and $N_c$; we claim that this works.
59 | let N := max Na Nc ,
60 | use N ,
61 | -- Note that N ≥ Na and N ≥ Nc,
62 | have HNa : Na ≤ N := by obvious_ineq ,
63 | have HNc : Nc ≤ N := by obvious_ineq ,
64 | -- so for all n ≥ N,
65 | intros n Hn ,
66 | -- we have $n≥ N_a$ and $n\geq N_c$, so $aₙ ≤ bₙ ≤ cₙ$, and $|aₙ - l|, |bₙ - l|$ are both less than $\epsilon$.
67 | have h1 : a n ≤ b n := hab n ,
68 | have h2 : b n ≤ c n := hbc n ,
69 | have h3 : | a n - l | < ε := Ha n ( le_trans HNa Hn ),
70 | have h4 : | c n - l | < ε := Hc n ( le_trans HNc Hn ),
71 | -- The result now follows easily from these inequalities (as $l-ε<a_n≤b_n≤c_n<l+ε$).
72 | revert h3 , revert h4 ,
73 | unfold abs , unfold max ,
74 | split_ifs ; intros ; linarith ,
75 | end
76 |
77 |
78 |
79 |
80 |
--------------------------------------------------------------------------------
/docs/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Format Lean
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
21 |
22 |
23 |
24 | This tool is meant to transform Lean files to other documents. Currently what is implemented turns a Lean file with comments into a HTML page. For instance, this webpage was generated from this Lean file .
25 |
26 |
31 |
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/docs/style.css:
--------------------------------------------------------------------------------
1 | /*! normalize.css v3.0.2 | MIT License | git.io/normalize */@import url("https://fonts.googleapis.com/css?family=Open+Sans:400,700");html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:bold}dfn{font-style:italic}h1{font-size:2em;margin:0.67em 0}mark{background:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{box-sizing:content-box;height:0}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace, monospace;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0}input[type="number"]::-webkit-inner-spin-button,input[type="number"]::-webkit-outer-spin-button{height:auto}input[type="search"]{-webkit-appearance:textfield;box-sizing:content-box}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}fieldset{border:1px solid #c0c0c0;margin:0 2px;padding:0.35em 0.625em 0.75em}legend{border:0;padding:0}textarea{overflow:auto}optgroup{font-weight:bold}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}.highlight table td{padding:5px}.highlight table pre{margin:0}.highlight .cm{color:#999988;font-style:italic}.highlight .cp{color:#999999;font-weight:bold}.highlight .c1{color:#999988;font-style:italic}.highlight .cs{color:#999999;font-weight:bold;font-style:italic}.highlight .c,.highlight .cd{color:#999988;font-style:italic}.highlight .err{color:#a61717;background-color:#e3d2d2}.highlight .gd{color:#000000;background-color:#ffdddd}.highlight .ge{color:#000000;font-style:italic}.highlight .gr{color:#aa0000}.highlight .gh{color:#999999}.highlight .gi{color:#000000;background-color:#ddffdd}.highlight .go{color:#888888}.highlight .gp{color:#555555}.highlight .gs{font-weight:bold}.highlight .gu{color:#aaaaaa}.highlight .gt{color:#aa0000}.highlight .kc{color:#000000;font-weight:bold}.highlight .kd{color:#000000;font-weight:bold}.highlight .kn{color:#000000;font-weight:bold}.highlight .kp{color:#000000;font-weight:bold}.highlight .kr{color:#000000;font-weight:bold}.highlight .kt{color:#445588;font-weight:bold}.highlight .k,.highlight .kv{color:#000000;font-weight:bold}.highlight .mf{color:#009999}.highlight .mh{color:#009999}.highlight .il{color:#009999}.highlight .mi{color:#009999}.highlight .mo{color:#009999}.highlight .m,.highlight .mb,.highlight .mx{color:#009999}.highlight .sb{color:#d14}.highlight .sc{color:#d14}.highlight .sd{color:#d14}.highlight .s2{color:#d14}.highlight .se{color:#d14}.highlight .sh{color:#d14}.highlight .si{color:#d14}.highlight .sx{color:#d14}.highlight .sr{color:#009926}.highlight .s1{color:#d14}.highlight .ss{color:#990073}.highlight .s{color:#d14}.highlight .na{color:#008080}.highlight .bp{color:#999999}.highlight .nb{color:#0086B3}.highlight .nc{color:#445588;font-weight:bold}.highlight .no{color:#008080}.highlight .nd{color:#3c5d5d;font-weight:bold}.highlight .ni{color:#800080}.highlight .ne{color:#990000;font-weight:bold}.highlight .nf{color:#990000;font-weight:bold}.highlight .nl{color:#990000;font-weight:bold}.highlight .nn{color:#555555}.highlight .nt{color:#000080}.highlight .vc{color:#008080}.highlight .vg{color:#008080}.highlight .vi{color:#008080}.highlight .nv{color:#008080}.highlight .ow{color:#000000;font-weight:bold}.highlight .o{color:#000000;font-weight:bold}.highlight .w{color:#bbbbbb}.highlight{background-color:#f8f8f8}*{box-sizing:border-box}body{padding:0;margin:0;font-family:"Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;font-size:16px;line-height:1.5;color:#606c71}a{color:#1e6bb8;text-decoration:none}a:hover{text-decoration:underline}.btn{display:inline-block;margin-bottom:1rem;color:rgba(255,255,255,0.7);background-color:rgba(255,255,255,0.08);border-color:rgba(255,255,255,0.2);border-style:solid;border-width:1px;border-radius:0.3rem;transition:color 0.2s, background-color 0.2s, border-color 0.2s}.btn:hover{color:rgba(255,255,255,0.8);text-decoration:none;background-color:rgba(255,255,255,0.2);border-color:rgba(255,255,255,0.3)}.btn+.btn{margin-left:1rem}@media screen and (min-width: 64em){.btn{padding:0.75rem 1rem}}@media screen and (min-width: 42em) and (max-width: 64em){.btn{padding:0.6rem 0.9rem;font-size:0.9rem}}@media screen and (max-width: 42em){.btn{display:block;width:100%;padding:0.75rem;font-size:0.9rem}.btn+.btn{margin-top:1rem;margin-left:0}}.page-header{color:#fff;text-align:center;background-color:#159957;background-image:linear-gradient(120deg, #155799, #159957)}@media screen and (min-width: 64em){.page-header{padding:5rem 6rem}}@media screen and (min-width: 42em) and (max-width: 64em){.page-header{padding:3rem 4rem}}@media screen and (max-width: 42em){.page-header{padding:2rem 1rem}}.project-name{margin-top:0;margin-bottom:0.1rem}@media screen and (min-width: 64em){.project-name{font-size:3.25rem}}@media screen and (min-width: 42em) and (max-width: 64em){.project-name{font-size:2.25rem}}@media screen and (max-width: 42em){.project-name{font-size:1.75rem}}.project-tagline{margin-bottom:2rem;font-weight:normal;opacity:0.7}@media screen and (min-width: 64em){.project-tagline{font-size:1.25rem}}@media screen and (min-width: 42em) and (max-width: 64em){.project-tagline{font-size:1.15rem}}@media screen and (max-width: 42em){.project-tagline{font-size:1rem}}.main-content{word-wrap:break-word}.main-content :first-child{margin-top:0}@media screen and (min-width: 64em){.main-content{max-width:64rem;padding:2rem 6rem;margin:0 auto;font-size:1.1rem}}@media screen and (min-width: 42em) and (max-width: 64em){.main-content{padding:2rem 4rem;font-size:1.1rem}}@media screen and (max-width: 42em){.main-content{padding:2rem 1rem;font-size:1rem}}.main-content img{max-width:100%}.main-content h1,.main-content h2,.main-content h3,.main-content h4,.main-content h5,.main-content h6{margin-top:2rem;margin-bottom:1rem;font-weight:normal;color:#159957}.main-content p{margin-bottom:1em}.main-content code{padding:2px 4px;font-family:Consolas, "Liberation Mono", Menlo, Courier, monospace;font-size:0.9rem;color:#567482;background-color:#f3f6fa;border-radius:0.3rem}.main-content pre{padding:0.8rem;margin-top:0;margin-bottom:1rem;font:1rem Consolas, "Liberation Mono", Menlo, Courier, monospace;color:#567482;word-wrap:normal;background-color:#f3f6fa;border:solid 1px #dce6f0;border-radius:0.3rem}.main-content pre>code{padding:0;margin:0;font-size:0.9rem;color:#567482;word-break:normal;white-space:pre;background:transparent;border:0}.main-content .highlight{margin-bottom:1rem}.main-content .highlight pre{margin-bottom:0;word-break:normal}.main-content .highlight pre,.main-content pre{padding:0.8rem;overflow:auto;font-size:0.9rem;line-height:1.45;border-radius:0.3rem;-webkit-overflow-scrolling:touch}.main-content pre code,.main-content pre tt{display:inline;max-width:initial;padding:0;margin:0;overflow:initial;line-height:inherit;word-wrap:normal;background-color:transparent;border:0}.main-content pre code:before,.main-content pre code:after,.main-content pre tt:before,.main-content pre tt:after{content:normal}.main-content ul,.main-content ol{margin-top:0}.main-content blockquote{padding:0 1rem;margin-left:0;color:#819198;border-left:0.3rem solid #dce6f0}.main-content blockquote>:first-child{margin-top:0}.main-content blockquote>:last-child{margin-bottom:0}.main-content table{display:block;width:100%;overflow:auto;word-break:normal;word-break:keep-all;-webkit-overflow-scrolling:touch}.main-content table th{font-weight:bold}.main-content table th,.main-content table td{padding:0.5rem 1rem;border:1px solid #e9ebec}.main-content dl{padding:0}.main-content dl dt{padding:0;margin-top:1rem;font-size:1rem;font-weight:bold}.main-content dl dd{padding:0;margin-bottom:1rem}.main-content hr{height:2px;padding:0;margin:1rem 0;background-color:#eff0f1;border:0}.site-footer{padding-top:2rem;margin-top:2rem;border-top:solid 1px #eff0f1}@media screen and (min-width: 64em){.site-footer{font-size:1rem}}@media screen and (min-width: 42em) and (max-width: 64em){.site-footer{font-size:1rem}}@media screen and (max-width: 42em){.site-footer{font-size:0.9rem}}.site-footer-owner{display:block;font-weight:bold}.site-footer-credits{color:#819198}.page-header a {color: #fff; text-decoration: none}
2 |
--------------------------------------------------------------------------------
/docs_src/build.sh:
--------------------------------------------------------------------------------
1 | for i in `ls *.md`
2 | do
3 | pandoc -t html --filter ./pandocfilter-pygments $i --template template.html -o ../docs/"${i%.md}.html"
4 | done
5 |
--------------------------------------------------------------------------------
/docs_src/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: A Lean file formatter
3 | ---
4 | This tool is meant to transform Lean files to other documents. Currently
5 | what is implemented turns a Lean file with comments into a HTML page.
6 | For instance, [this webpage](example/sandwich.html) was
7 | generated from [this Lean file](example/source.html).
8 |
--------------------------------------------------------------------------------
/docs_src/pandocfilter-pygments:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 |
3 | """
4 | Pandoc filter to pass all code blocks through pygments highlighter.
5 | """
6 |
7 | from pandocfilters import toJSONFilter, RawBlock
8 | from pygments import highlight
9 | from pygments.lexers import (get_lexer_by_name, guess_lexer, TextLexer)
10 | from pygments.formatters import get_formatter_by_name
11 |
12 | def pygmentize(key, value, format, meta):
13 | if key == 'CodeBlock':
14 | [[ident, classes, keyvals], code] = value
15 | lexer = None
16 | for klass in classes:
17 | try:
18 | lexer = get_lexer_by_name(klass)
19 | break
20 | except:
21 | pass
22 | if lexer is None:
23 | try:
24 | lexer = guess_lexer(code)
25 | except:
26 | lexer = TextLexer()
27 | return [RawBlock(format, highlight(code, lexer, get_formatter_by_name(format)))]
28 |
29 | if __name__ == "__main__":
30 | toJSONFilter(pygmentize)
31 |
--------------------------------------------------------------------------------
/docs_src/template.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Format Lean
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
21 |
22 |
23 |
24 | $body$
25 |
26 |
31 |
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/examples/leanpkg.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "test"
3 | version = "0.1"
4 | lean_version = "leanprover-community/lean:3.16.5"
5 | path = "src"
6 |
7 | [dependencies]
8 | mathlib = {git = "https://github.com/leanprover-community/mathlib", rev = "e7e9f30cd2c79a125322baf4cef4a49d94bf6119"}
9 |
--------------------------------------------------------------------------------
/examples/src/sandwich.lean:
--------------------------------------------------------------------------------
1 | -- begin header
2 |
3 | -- Everything in the header will be hidden in the HTML file.
4 | import data.real.basic
5 |
6 | notation `|` x `|` := abs x
7 |
8 | @[user_attribute]
9 | meta def ineq_rules : user_attribute :=
10 | { name := `ineq_rules,
11 | descr := "lemmas usable to prove inequalities" }
12 |
13 | attribute [ineq_rules] add_lt_add le_max_left le_max_right
14 |
15 | meta def obvious_ineq := `[linarith <|> apply_rules ineq_rules]
16 | run_cmd add_interactive [`obvious_ineq]
17 | -- end header
18 |
19 | /-
20 | # The sandwich theorem
21 |
22 | In this demo file, we define limits of sequences of real numbers and prove the sandwich theorem.
23 | -/
24 |
25 | /- Definition
26 | A sequence of real numbers $a_n$ tends to $l$ if
27 | $\forall \varepsilon > 0, \exists N, \forall n \geq N, |a_n - l | \leq \varepsilon$.
28 | -/
29 | definition is_limit (a : ℕ → ℝ) (l : ℝ) :=
30 | ∀ ε > 0, ∃ N, ∀ n ≥ N, | a n - l | < ε
31 |
32 | /- Theorem
33 | If $(a_n)$, $(b_n)$, and $(c_n)$ are three real-valued sequences satisfying $a_n ≤ b_n ≤ c_n$ for all $n$, and if furthermore $a_n→ℓ$ and $c_n→ℓ$, then $b_n→ℓ$.
34 | -/
35 | theorem sandwich (a b c : ℕ → ℝ)
36 | (l : ℝ) (ha : is_limit a l) (hc : is_limit c l)
37 | (hab : ∀ n, a n ≤ b n) (hbc : ∀ n, b n ≤ c n) : is_limit b l :=
38 | begin
39 | -- We need to show that for all $ε>0$ there exists $N$ such that $n≥N$ implies $|b_n-ℓ|<ε$. So choose ε > 0.
40 | intros ε Hε,
41 | -- we now need an $N$. As usual it is the max of two other N's, one coming from $(a_n)$ and one from $(c_n)$. Choose $N_a$ and $N_c$ such that $|aₙ - l| < ε$ for $n ≥ N_a$ and $|cₙ - l| < ε$ for $n ≥ N_c$.
42 | cases ha ε Hε with Na Ha,
43 | cases hc ε Hε with Nc Hc,
44 | -- Now let $N$ be the max of $N_a$ and $N_c$; we claim that this works.
45 | let N := max Na Nc,
46 | use N,
47 | -- Note that $N ≥ N_a$ and $N ≥ N_c$,
48 | have HNa : Na ≤ N := by obvious_ineq,
49 | have HNc : Nc ≤ N := by obvious_ineq,
50 | -- so for all n ≥ N,
51 | intros n Hn,
52 | -- we have $n≥ N_a$ and $n\geq N_c$, so $aₙ ≤ bₙ ≤ cₙ$, and $|aₙ - l|, |bₙ - l|$ are both less than $\epsilon$.
53 | have h1 : a n ≤ b n := hab n,
54 | have h2 : b n ≤ c n := hbc n,
55 | have h3 : |a n - l| < ε := Ha n (le_trans HNa Hn),
56 | have h4 : |c n - l| < ε := Hc n (le_trans HNc Hn),
57 | -- The result now follows easily from these inequalities (as $l-ε=2.10
2 | regex>=2018.7.11
3 | mistletoe>=0.7.1
4 | beautifulsoup4>=4.7.1
5 |
--------------------------------------------------------------------------------
/sass/_big_tactic_state_layout.scss:
--------------------------------------------------------------------------------
1 | html {
2 | position: relative ;
3 | }
4 |
5 | body {
6 | margin: 0;
7 | }
8 |
9 |
10 | // Main content
11 |
12 |
13 | $main-width: 70%;
14 |
15 | div#wrapper {
16 | width: 100%;
17 | min-height: 100%;
18 | }
19 |
20 | div#content
21 | {
22 | padding: 1rem;
23 | width: $main-width;
24 | }
25 |
26 | #dragbar{
27 | position: absolute;
28 | top: 0;
29 | min-height: 100%;
30 | left: $main-width;
31 | width: 3px;
32 | cursor: col-resize;
33 | }
34 |
35 | div#tactic_state_wrapper
36 | {
37 | position: fixed;
38 | margin-left: $main-width;
39 | top: 0px;
40 | padding: 1rem;
41 | }
42 |
43 |
--------------------------------------------------------------------------------
/sass/_definitions.scss:
--------------------------------------------------------------------------------
1 | // Definitions
2 |
3 |
4 | div.definition_wrapper
5 | {
6 | margin-top: 1rem;
7 | }
8 |
9 | span.definition_label
10 | {
11 | font-weight: bold;
12 | }
13 |
14 | div.definition_content
15 | {
16 | margin-left: .5rem;
17 | padding-left: .5rem;
18 | border-left: .15rem solid black;
19 | }
20 |
21 | div.definition_text:hover
22 | {
23 | transition: all .2s ease;
24 |
25 | background: darken($background-color, 10%);
26 | }
27 |
28 | div.definition_lean
29 | {
30 | @if $show-lean-statements {
31 | display: block;
32 | } @else {
33 | display: none; }
34 | }
35 |
--------------------------------------------------------------------------------
/sass/_examples.scss:
--------------------------------------------------------------------------------
1 | // Examples
2 |
3 | div.example_wrapper
4 | {
5 | margin-top: 1rem;
6 | }
7 |
8 | span.example_label
9 | {
10 | font-weight: bold;
11 | }
12 |
13 | div.example_content
14 | {
15 | margin-left: .5rem;
16 | padding-left: .5rem;
17 | border-left: .25rem solid black;
18 | }
19 |
20 | div.example_text:hover
21 | {
22 | transition: all .2s ease;
23 |
24 | background: darken($background-color, 10%);
25 | }
26 |
27 | div.example_lean
28 | {
29 | @if $show-lean-statements {
30 | display: block;
31 | } @else {
32 | display: none; }
33 | }
34 |
--------------------------------------------------------------------------------
/sass/_lean_elements.scss:
--------------------------------------------------------------------------------
1 | @import 'definitions';
2 | @import 'examples';
3 | @import 'lemmas';
4 | @import 'theorems';
5 | @import 'proofs';
6 |
7 |
--------------------------------------------------------------------------------
/sass/_lemmas.scss:
--------------------------------------------------------------------------------
1 | // Lemmas
2 |
3 | div.lemma_wrapper
4 | {
5 | margin-top: 1rem;
6 | }
7 |
8 | span.lemma_label
9 | {
10 | font-weight: bold;
11 | }
12 |
13 | div.lemma_content
14 | {
15 | margin-left: .5rem;
16 | padding-left: .5rem;
17 | border-left: .15rem solid black;
18 | }
19 |
20 | div.lemma_text:hover
21 | {
22 | transition: all .2s ease;
23 |
24 | background: darken($background-color, 10%);
25 | }
26 |
27 | div.lemma_lean
28 | {
29 | display: none ;
30 | }
31 |
--------------------------------------------------------------------------------
/sass/_proofs.scss:
--------------------------------------------------------------------------------
1 | div.proof_wrapper
2 | {
3 | margin-top: 1rem;
4 | width: 100%;
5 | }
6 | div.proof_wrapper::after {
7 | content: "";
8 | clear: both;
9 | display: table;
10 | }
11 |
12 | span.proof_label
13 | {
14 | font-weight: bold;
15 | display: block;
16 | }
17 |
18 | span.proof_qed
19 | {
20 | font-weight: bold;
21 | display: block;
22 | }
23 |
24 |
25 | div.proof_content
26 | {
27 | padding-left: .5rem;
28 | }
29 |
30 | div.small_proof_content
31 | {
32 | padding-left: .5rem;
33 | width: 49%;
34 | float: left,
35 | }
36 |
37 | div.small_tactic_state
38 | {
39 | padding-left: .5rem;
40 | width: 49%;
41 | float: left;
42 | }
43 |
44 | @if $show-lean-proofs {
45 | span.proof_item_text:hover
46 | {
47 | transition: all .2s ease;
48 |
49 | background: darken($background-color, 10%);
50 | }
51 | }
52 |
53 | div.proof_item_lean {
54 | @if $show-lean-proofs {
55 | display: block;
56 | } @else {
57 | display: none; }
58 | }
59 |
60 | div.proof_line {
61 | display: flex;
62 | }
63 |
64 |
65 | div.inline_proof_item
66 | {
67 | display: inline;
68 | }
69 |
70 | span.tactic_left:hover
71 | { transition: all .2s ease;
72 | background: darken($background-color, 10%); }
73 |
74 | span.tactic_left
75 | { width: 3rem;
76 | background: darken($background-color, 5%);}
77 | span.tactic_right
78 | { margin-left: 2rem;
79 | width: 3rem;
80 | background: darken($background-color, 5%);}
81 | span.tactic_right:hover
82 | { transition: all .2s ease;
83 | background: darken($background-color, 10%); }
84 | span[class^="tactic_state_"] {
85 | display: none;
86 | }
87 |
--------------------------------------------------------------------------------
/sass/_reset.scss:
--------------------------------------------------------------------------------
1 | html,
2 | body,
3 | div,
4 | span,
5 | applet,
6 | object,
7 | iframe,
8 | h1,
9 | h2,
10 | h3,
11 | h4,
12 | h5,
13 | h6,
14 | p,
15 | blockquote,
16 | pre,
17 | a,
18 | abbr,
19 | acronym,
20 | address,
21 | big,
22 | cite,
23 | code,
24 | del,
25 | dfn,
26 | em,
27 | img,
28 | ins,
29 | kbd,
30 | q,
31 | s,
32 | samp,
33 | small,
34 | strike,
35 | strong,
36 | sub,
37 | sup,
38 | tt,
39 | var,
40 | b,
41 | u,
42 | i,
43 | center,
44 | dl,
45 | dt,
46 | dd,
47 | ol,
48 | ul,
49 | li,
50 | fieldset,
51 | form,
52 | label,
53 | legend,
54 | table,
55 | caption,
56 | tbody,
57 | tfoot,
58 | thead,
59 | tr,
60 | th,
61 | td,
62 | article,
63 | aside,
64 | canvas,
65 | details,
66 | embed,
67 | figure,
68 | figcaption,
69 | footer,
70 | header,
71 | hgroup,
72 | menu,
73 | nav,
74 | output,
75 | ruby,
76 | section,
77 | summary,
78 | time,
79 | mark,
80 | audio,
81 | video
82 | {
83 | font: inherit;
84 | font-size: 100%;
85 |
86 | margin: 0;
87 | padding: 0;
88 |
89 | border: 0;
90 | }
91 | /* HTML5 display-role reset for older browsers */
92 | article,
93 | aside,
94 | details,
95 | figcaption,
96 | figure,
97 | footer,
98 | header,
99 | hgroup,
100 | menu,
101 | nav,
102 | section
103 | {
104 | display: block;
105 | }
106 | body
107 | {
108 | line-height: 1;
109 |
110 | overflow-x: hidden;
111 |
112 | background: #f4f4f4;
113 | }
114 | ol,
115 | ul
116 | {
117 | list-style: none;
118 | }
119 | blockquote,
120 | q
121 | {
122 | quotes: none;
123 | }
124 | blockquote:before,
125 | blockquote:after,
126 | q:before,
127 | q:after
128 | {
129 | content: '';
130 | content: none;
131 | }
132 | table
133 | {
134 | border-spacing: 0;
135 | border-collapse: collapse;
136 | }
137 |
138 | .clear:after
139 | {
140 | font-size: 0;
141 |
142 | display: block;
143 | visibility: hidden;
144 | clear: both;
145 |
146 | height: 0;
147 |
148 | content: ' ';
149 | }
150 | .clear
151 | {
152 | display: inline-block;
153 | }
154 | /* start commented backslash hack \*/
155 | * html .clear
156 | {
157 | height: 1%;
158 | }
159 | .clear
160 | {
161 | display: block;
162 | }
163 | /* close commented backslash hack */
164 |
165 | /****************************************
166 | BASIC ELEMENTS
167 | *****************************************/
168 | *
169 | {
170 | -webkit-box-sizing: border-box;
171 | -moz-box-sizing: border-box;
172 | box-sizing: border-box;
173 | }
174 |
175 | hr
176 | {
177 | clear: both;
178 |
179 | border: none;
180 | outline: none;
181 | }
182 |
183 | em
184 | {
185 | font-style: italic;
186 | }
187 |
188 | a
189 | {
190 | text-decoration: underline;
191 | }
192 | ul
193 | {
194 | list-style: disc;
195 | }
196 | ol
197 | {
198 | list-style: decimal;
199 | }
200 | ul,
201 | ol
202 | {
203 | font-size: 14px;
204 |
205 | padding: 0 0 0 33px;
206 |
207 | li
208 | {
209 | margin: 0;
210 | }
211 | }
212 |
213 | blockquote
214 | {
215 | padding: 0 15px 0 40px;
216 | }
217 |
218 | table
219 | {
220 | font-size: 13px;
221 |
222 | width: 100%;
223 | margin: 20px 0;
224 |
225 | background: white;
226 |
227 |
228 | th
229 | {
230 | font-size: 16px;
231 | font-weight: bold;
232 | }
233 |
234 | tr
235 | {
236 | td
237 | {
238 | padding: 7px;
239 | }
240 | }
241 | }
242 |
243 | ::selection
244 | {
245 | color: white;
246 | background: #000;
247 | }
248 | ::-moz-selection
249 | {
250 | color: white;
251 | background: #000;
252 | }
253 |
--------------------------------------------------------------------------------
/sass/_theorems.scss:
--------------------------------------------------------------------------------
1 | // Theorems
2 |
3 | div.theorem_wrapper
4 | {
5 | margin-top: 1rem;
6 | }
7 |
8 | span.theorem_label
9 | {
10 | font-weight: bold;
11 | }
12 |
13 | div.theorem_content
14 | {
15 | margin-left: .5rem;
16 | padding-left: .5rem;
17 | border-left: .25rem solid black;
18 | }
19 |
20 | @if $show-lean-statements {
21 | div.theorem_text:hover
22 | {
23 | transition: all .2s ease;
24 |
25 | background: darken($background-color, 10%);
26 | }
27 | }
28 |
29 | div.theorem_lean
30 | {
31 | @if $show-lean-statements {
32 | display: block;
33 | } @else {
34 | display: none; }
35 | }
36 |
--------------------------------------------------------------------------------
/sass/_tikzcd.scss:
--------------------------------------------------------------------------------
1 | div.tikzcd {
2 | display: block ;
3 | margin: .5rem auto ;
4 | overflow: auto ;
5 | text-align: center ;
6 | }
7 |
--------------------------------------------------------------------------------
/sass/_typography.scss:
--------------------------------------------------------------------------------
1 | div.content
2 | {
3 | line-height: $content-line-height;
4 | }
5 |
6 | p
7 | {
8 | line-height: 1.5rem;
9 | }
10 |
11 | li > p
12 | {
13 | margin: .2*$content-line-height 0;
14 | }
15 |
16 | h1, h2, h3, h4, h5, h6 {
17 | font-family: "Lucida Grande", Arial, Helvetica, sans-serif;
18 | }
19 |
20 |
21 | h1
22 | {
23 | font-size: 2rem;
24 | line-height: 2rem;
25 |
26 | margin: 1rem 0;
27 |
28 | color: $titles-color;
29 | }
30 |
31 | h2
32 | {
33 | font-size: 1.5rem;
34 |
35 | margin: .8rem 0;
36 |
37 | color: $titles-color;
38 | }
39 |
40 | h3
41 | {
42 | font-size: 1rem;
43 |
44 | margin: .67rem 0;
45 |
46 | color: $titles-color;
47 | }
48 |
49 | h4
50 | {
51 | font-size: 1rem;
52 |
53 | margin: .67rem 0;
54 |
55 | color: $titles-color;
56 | }
57 |
58 | p
59 | {
60 | font-size: 1rem;
61 |
62 | margin: .5rem 0;
63 | }
64 |
65 |
66 | /**
67 | * Address style set to `bolder` in Firefox 4+, Safari 5, and Chrome.
68 | */
69 |
70 | b,
71 | strong
72 | {
73 | font-weight: bold;
74 | }
75 |
76 | /**
77 | * Address styling not present in Safari 5 and Chrome.
78 | */
79 |
80 | dfn
81 | {
82 | font-style: italic;
83 | }
84 |
85 |
86 | /**
87 | * Correct font family set oddly in Safari 5 and Chrome.
88 | */
89 |
90 | code,
91 | kbd,
92 | pre,
93 | samp
94 | {
95 | font-family: monospace, serif;
96 | font-size: 1rem;
97 | }
98 |
99 | /**
100 | * Improve readability of pre-formatted text in all browsers.
101 | */
102 |
103 | pre
104 | {
105 | white-space: pre-wrap;
106 | }
107 |
108 | /**
109 | * Set consistent quote types.
110 | */
111 |
112 | q
113 | {
114 | quotes: '\201C' '\201D' '\2018' '\2019';
115 | }
116 |
117 | /**
118 | * Address inconsistent and variable font size in all browsers.
119 | */
120 |
121 | small
122 | {
123 | font-size: 80%;
124 | }
125 |
126 | /**
127 | * Prevent `sub` and `sup` affecting `line-height` in all browsers.
128 | */
129 |
130 | sub,
131 | sup
132 | {
133 | font-size: 75%;
134 | line-height: 0;
135 |
136 | position: relative;
137 |
138 | vertical-align: baseline;
139 | }
140 |
141 | sup
142 | {
143 | top: -.5rem;
144 | }
145 |
146 | sub
147 | {
148 | bottom: -.25rem;
149 | }
150 |
151 | /* Font Selection */
152 | .mdseries, .textmf {font-weight: normal}
153 | .bfseries, .textbf {font-weight: bold}
154 | .rmfamily, .textrm {font-family: serif}
155 | .sffamily, .textsf {font-family: sans-serif}
156 | .ttfamily, .texttt {font-family: monospace}
157 | .upshape, .textup {text-transform: uppercase}
158 | .itshape, .textit {font-style: italic}
159 | .slshape, .textsl {font-style: oblique}
160 | .scshape, .textsc {font-variant: small-caps}
161 |
162 | small.tiny {font-size: x-small}
163 | small.scriptsize {font-size: smaller}
164 | small.footnotesize {font-size: small}
165 | small.small {font-size: small}
166 | .normalsize {font-size: normal}
167 | big.large {font-size: large}
168 | big.xlarge {font-size: x-large}
169 | big.xxlarge {font-size: x-large}
170 | big.huge {font-size: xx-large}
171 | big.xhuge {font-size: xx-large}
172 |
173 | /* Fonts */
174 | .rm {
175 | font-family: serif;
176 | font-style: normal;
177 | font-weight: normal;
178 | }
179 | .cal {
180 | font-family: serif;
181 | font-style: italic;
182 | font-weight: normal;
183 | }
184 | .it {
185 | font-family: serif;
186 | font-style: italic;
187 | font-weight: normal;
188 | }
189 | .sl {
190 | font-family: serif;
191 | font-style: oblique;
192 | font-weight: normal;
193 | }
194 | .bf {
195 | font-family: serif;
196 | font-style: normal;
197 | font-weight: bold;
198 | }
199 | .tt {
200 | font-family: monospace;
201 | font-style: normal;
202 | font-weight: normal;
203 | }
204 |
205 | .underbar {text-decoration: underline}
206 |
207 | /* Boxes */
208 | .fbox, .framebox {
209 | border: 1px black solid;
210 | padding-top: 1px;
211 | padding-bottom: 1px;
212 | padding-left: 3px;
213 | padding-right: 3px;
214 | }
215 |
216 | /* Quotations and Verse */
217 | .quotation, .quote, .verse {
218 | }
219 | .quotation p, .quote p, .verse p {
220 | margin-top: 0px;
221 | margin-bottom: 0.5em;
222 | }
223 |
224 | hr {color: black}
225 |
226 | dd {
227 | margin-left: 3rem;
228 | }
229 | dd p {
230 | padding: 0;
231 | margin: 0 0 1rem 0;
232 | }
233 |
234 |
--------------------------------------------------------------------------------
/sass/lecture.scss:
--------------------------------------------------------------------------------
1 | $titles-color: rgb(15,47,72);
2 |
3 | $background-color: rgb(232, 232, 232);
4 | $main-text-color: rgb(10, 10, 20);
5 |
6 | $content-line-height: 1.4rem;
7 |
8 | h1#tactic_state_header
9 | { font-size: 1.2rem;
10 | line-height: 2rem;
11 | margin: 1rem 0;
12 | color: $titles-color;}
13 |
14 | #dragbar{
15 | background-color: $titles-color;
16 | }
17 | body
18 | {
19 | color: $main-text-color;
20 | background-color: $background-color;
21 | }
22 | $smallskipamount: 1rem;
23 | $show-lean-proofs: false;
24 | $show-lean-statements: false;
25 | @import 'reset';
26 | @import 'big_tactic_state_layout';
27 | @import 'typography';
28 | @import 'lean_elements' ;
29 |
--------------------------------------------------------------------------------
/sass/teach_lean.scss:
--------------------------------------------------------------------------------
1 | $show-lean-proofs: true;
2 | $show-lean-statements: true;
3 | $background-color: #fffff8;
4 | code {
5 | font-size: 1.2rem;
6 | font-weight: bold
7 | }
8 | div#content {
9 | width: 100%;
10 | }
11 |
12 | div#content > p {
13 | width: 80%;
14 | }
15 | @media (max-width: 760px) {
16 | div#content {
17 | width: 100%;
18 | }}
19 |
20 | @import 'lean_elements' ;
21 | div.example_wrapper {
22 | font-size: 1.4rem;
23 | }
24 | div.lemma_wrapper {
25 | font-size: 1.4rem;
26 | }
27 | div.theorem_wrapper {
28 | font-size: 1.4rem;
29 | }
30 | div.definition_wrapper {
31 | font-size: 1.4rem;
32 | }
33 |
34 | pre {
35 | margin-top: .2rem;
36 | margin-bottom: .2rem;
37 | }
38 |
39 | $see_ts: lighten(#111, 80%);
40 |
41 | span.tactic_left
42 | { width: 3rem;
43 | background: $see_ts;}
44 | span.tactic_left:hover
45 | { transition: all .2s ease;
46 | background: darken($see_ts, 10%); }
47 |
48 | span.tactic_right
49 | { margin-left: 2rem;
50 | width: 3rem;
51 | background: $see_ts;}
52 |
53 | span.tactic_right:hover
54 | { transition: all .2s ease;
55 | background: darken($see_ts, 10%); }
56 |
57 | pre {
58 | white-space: pre-wrap;
59 | word-break: keep-all }
60 | @import 'tikzcd' ;
61 |
--------------------------------------------------------------------------------
/sass/with_tufte.scss:
--------------------------------------------------------------------------------
1 | $show-lean-proofs: false;
2 | $show-lean-statements: false;
3 | $background-color: #fffff8;
4 | body {
5 | width: 100%;
6 | max-width: 100%
7 | }
8 |
9 | code {
10 | font-size: 1.2rem;
11 | font-weight: bold
12 | }
13 | div#content {
14 | width: 70%;
15 | }
16 | @media (max-width: 760px) {
17 | div#content {
18 | width: 100%;
19 | }}
20 |
21 | #dragbar{
22 | background-color: #111;
23 | }
24 |
25 | h1#tactic_state_header
26 | { font-size: 2rem;
27 | line-height: 2rem;
28 | margin: 1rem 0;
29 | color: #111;}
30 |
31 | @import 'lean_elements' ;
32 | div.example_wrapper {
33 | font-size: 1.4rem;
34 | }
35 | div.lemma_wrapper {
36 | font-size: 1.4rem;
37 | }
38 | div.theorem_wrapper {
39 | font-size: 1.4rem;
40 | }
41 |
42 | pre {
43 | margin-top: .2rem;
44 | margin-bottom: .2rem;
45 | }
46 |
47 | $see_ts: lighten(#111, 80%);
48 |
49 | span.tactic_left
50 | { display: inline-block;
51 | width: 1rem;
52 | height: 1rem;
53 | background: $see_ts;}
54 |
55 | span.tactic_left:hover
56 | { transition: all .2s ease;
57 | background: darken($see_ts, 10%); }
58 |
59 |
60 | span.tactic_right
61 | { display: inline-block;
62 | width: 1rem;
63 | height: 1rem;
64 | margin-left: 0;
65 | background: $see_ts;}
66 |
67 | span.tactic_right:hover
68 | { transition: all .2s ease;
69 | background: darken($see_ts, 10%); }
70 |
71 | @import 'big_tactic_state_layout' ;
72 |
73 | div#content {
74 | margin:0;
75 | padding-left: 30px;
76 | }
77 |
78 | body {
79 | padding: 0;
80 | }
81 |
--------------------------------------------------------------------------------
/setup.py:
--------------------------------------------------------------------------------
1 | from setuptools import setup, find_packages
2 |
3 | setup(
4 | name='Lean formatter',
5 | version='0.0.2',
6 | author='Patrick Massot',
7 | author_email='patrickmassot@free.fr',
8 | description='A Lean prover text formatter',
9 | packages=find_packages('src'),
10 | package_dir={'': 'src'},
11 | package_data={
12 | '': ['*.css', '*.css.map', '*.js', 'templates/*'],
13 | },
14 | scripts=['bin/format_lean', 'bin/format_project'],
15 | install_requires=['regex >= 2018.7.11', 'jinja2 >= 2.10',
16 | 'mistletoe >= 0.7.1', 'toml >= 0.10.0',
17 | 'fire >= 0.1.3', 'beautifulsoup4 >= 4.7.1'])
18 |
--------------------------------------------------------------------------------
/src/format_lean/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/leanprover-community/format_lean/b8a1eff6922b78185596c4500504fa7edd9b2242/src/format_lean/__init__.py
--------------------------------------------------------------------------------
/src/format_lean/colorful.css:
--------------------------------------------------------------------------------
1 | .highlight .hll { background-color: #ffffcc }
2 | .highlight .c { color: #808080 } /* Comment */
3 | .highlight .err { color: #F00000; background-color: #F0A0A0 } /* Error */
4 | .highlight .k { color: #008000; font-weight: bold } /* Keyword */
5 | .highlight .o { color: #303030 } /* Operator */
6 | .highlight .cm { color: #808080 } /* Comment.Multiline */
7 | .highlight .cp { color: #507090 } /* Comment.Preproc */
8 | .highlight .c1 { color: #808080 } /* Comment.Single */
9 | .highlight .cs { color: #cc0000; font-weight: bold } /* Comment.Special */
10 | .highlight .gd { color: #A00000 } /* Generic.Deleted */
11 | .highlight .ge { font-style: italic } /* Generic.Emph */
12 | .highlight .gr { color: #FF0000 } /* Generic.Error */
13 | .highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */
14 | .highlight .gi { color: #00A000 } /* Generic.Inserted */
15 | .highlight .go { color: #808080 } /* Generic.Output */
16 | .highlight .gp { color: #c65d09; font-weight: bold } /* Generic.Prompt */
17 | .highlight .gs { font-weight: bold } /* Generic.Strong */
18 | .highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
19 | .highlight .gt { color: #0040D0 } /* Generic.Traceback */
20 | .highlight .kc { color: #008000; font-weight: bold } /* Keyword.Constant */
21 | .highlight .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */
22 | .highlight .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */
23 | .highlight .kp { color: #003080; font-weight: bold } /* Keyword.Pseudo */
24 | .highlight .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */
25 | .highlight .kt { color: #303090; font-weight: bold } /* Keyword.Type */
26 | .highlight .m { color: #6000E0; font-weight: bold } /* Literal.Number */
27 | .highlight .s { background-color: #fff0f0 } /* Literal.String */
28 | .highlight .na { color: #0000C0 } /* Name.Attribute */
29 | .highlight .nb { color: #007020 } /* Name.Builtin */
30 | .highlight .nc { color: #B00060; font-weight: bold } /* Name.Class */
31 | .highlight .no { color: #003060; font-weight: bold } /* Name.Constant */
32 | .highlight .nd { color: #505050; font-weight: bold } /* Name.Decorator */
33 | .highlight .ni { color: #800000; font-weight: bold } /* Name.Entity */
34 | .highlight .ne { color: #F00000; font-weight: bold } /* Name.Exception */
35 | .highlight .nf { color: #0060B0; font-weight: bold } /* Name.Function */
36 | .highlight .nl { color: #907000; font-weight: bold } /* Name.Label */
37 | .highlight .nn { color: #0e84b5; font-weight: bold } /* Name.Namespace */
38 | .highlight .nt { color: #007000 } /* Name.Tag */
39 | .highlight .nv { color: #906030 } /* Name.Variable */
40 | .highlight .ow { color: #000000; font-weight: bold } /* Operator.Word */
41 | .highlight .w { color: #bbbbbb } /* Text.Whitespace */
42 | .highlight .mf { color: #6000E0; font-weight: bold } /* Literal.Number.Float */
43 | .highlight .mh { color: #005080; font-weight: bold } /* Literal.Number.Hex */
44 | .highlight .mi { color: #0000D0; font-weight: bold } /* Literal.Number.Integer */
45 | .highlight .mo { color: #4000E0; font-weight: bold } /* Literal.Number.Oct */
46 | .highlight .sb { background-color: #fff0f0 } /* Literal.String.Backtick */
47 | .highlight .sc { color: #0040D0 } /* Literal.String.Char */
48 | .highlight .sd { color: #D04020 } /* Literal.String.Doc */
49 | .highlight .s2 { background-color: #fff0f0 } /* Literal.String.Double */
50 | .highlight .se { color: #606060; font-weight: bold; background-color: #fff0f0 } /* Literal.String.Escape */
51 | .highlight .sh { background-color: #fff0f0 } /* Literal.String.Heredoc */
52 | .highlight .si { background-color: #e0e0e0 } /* Literal.String.Interpol */
53 | .highlight .sx { color: #D02000; background-color: #fff0f0 } /* Literal.String.Other */
54 | .highlight .sr { color: #000000; background-color: #fff0ff } /* Literal.String.Regex */
55 | .highlight .s1 { background-color: #fff0f0 } /* Literal.String.Single */
56 | .highlight .ss { color: #A06000 } /* Literal.String.Symbol */
57 | .highlight .bp { color: #007020 } /* Name.Builtin.Pseudo */
58 | .highlight .vc { color: #306090 } /* Name.Variable.Class */
59 | .highlight .vg { color: #d07000; font-weight: bold } /* Name.Variable.Global */
60 | .highlight .vi { color: #3030B0 } /* Name.Variable.Instance */
61 | .highlight .il { color: #0000D0; font-weight: bold } /* Literal.Number.Integer.Long */
62 |
--------------------------------------------------------------------------------
/src/format_lean/lean.js:
--------------------------------------------------------------------------------
1 | var dragging = false;
2 |
3 | $('#dragbar').mousedown(function(e){
4 | e.preventDefault();
5 | dragging = true;
6 | var content = $('#content');
7 | var dragbar = $('#dragbar');
8 | var tsw = $('#tactic_state_wrapper');
9 | console.log("Resizing...");
10 | $(document).mousemove(function(ex){
11 | content.css("width", ex.pageX +2);
12 | dragbar.css("left", ex.pageX +2);
13 | tsw.css("margin-left", ex.pageX +2);
14 | });
15 | });
16 |
17 | $(document).mouseup(function(e){
18 | if (dragging)
19 | {
20 | $(document).unbind('mousemove');
21 | dragging = false;
22 | }
23 | });
24 |
25 | $(document).ready(function() {
26 | $("div.definition_text").click(
27 | function() {
28 | $(this).siblings("div.definition_lean").slideToggle()
29 | })
30 | $("div.example_text").click(
31 | function() {
32 | $(this).siblings("div.example_lean").slideToggle()
33 | })
34 | $("div.lemma_text").click(
35 | function() {
36 | $(this).siblings("div.lemma_lean").slideToggle()
37 | })
38 | $("div.theorem_text").click(
39 | function() {
40 | $(this).siblings("div.theorem_lean").slideToggle()
41 | })
42 | $("span.proof_item_text").click(
43 | function() {
44 | $(this).siblings("div.proof_item_lean").slideToggle()
45 | })
46 |
47 | $("span.tactic_left").click(
48 | function() {
49 | var width = $('#content').css("width");
50 | $("div#tactic_state").html(
51 | $(this).siblings("span.tactic_state_left").html());
52 | $('#content').css("width", width);
53 | })
54 |
55 | $("span.tactic_right").click(
56 | function() {
57 | var width = $('#content').css("width");
58 | $("div#tactic_state").html(
59 | $(this).siblings("span.tactic_state_right").html())
60 | $('#content').css("width", width);
61 | })
62 | });
63 |
--------------------------------------------------------------------------------
/src/format_lean/lecture.css:
--------------------------------------------------------------------------------
1 | @charset "UTF-8";
2 | h1#tactic_state_header {
3 | font-size: 1.2rem;
4 | line-height: 2rem;
5 | margin: 1rem 0;
6 | color: #0f2f48;
7 | }
8 |
9 | #dragbar {
10 | background-color: #0f2f48;
11 | }
12 |
13 | body {
14 | color: #0a0a14;
15 | background-color: #e8e8e8;
16 | }
17 |
18 | html,
19 | body,
20 | div,
21 | span,
22 | applet,
23 | object,
24 | iframe,
25 | h1,
26 | h2,
27 | h3,
28 | h4,
29 | h5,
30 | h6,
31 | p,
32 | blockquote,
33 | pre,
34 | a,
35 | abbr,
36 | acronym,
37 | address,
38 | big,
39 | cite,
40 | code,
41 | del,
42 | dfn,
43 | em,
44 | img,
45 | ins,
46 | kbd,
47 | q,
48 | s,
49 | samp,
50 | small,
51 | strike,
52 | strong,
53 | sub,
54 | sup,
55 | tt,
56 | var,
57 | b,
58 | u,
59 | i,
60 | center,
61 | dl,
62 | dt,
63 | dd,
64 | ol,
65 | ul,
66 | li,
67 | fieldset,
68 | form,
69 | label,
70 | legend,
71 | table,
72 | caption,
73 | tbody,
74 | tfoot,
75 | thead,
76 | tr,
77 | th,
78 | td,
79 | article,
80 | aside,
81 | canvas,
82 | details,
83 | embed,
84 | figure,
85 | figcaption,
86 | footer,
87 | header,
88 | hgroup,
89 | menu,
90 | nav,
91 | output,
92 | ruby,
93 | section,
94 | summary,
95 | time,
96 | mark,
97 | audio,
98 | video {
99 | font: inherit;
100 | font-size: 100%;
101 | margin: 0;
102 | padding: 0;
103 | border: 0;
104 | }
105 |
106 | /* HTML5 display-role reset for older browsers */
107 | article,
108 | aside,
109 | details,
110 | figcaption,
111 | figure,
112 | footer,
113 | header,
114 | hgroup,
115 | menu,
116 | nav,
117 | section {
118 | display: block;
119 | }
120 |
121 | body {
122 | line-height: 1;
123 | overflow-x: hidden;
124 | background: #f4f4f4;
125 | }
126 |
127 | ol,
128 | ul {
129 | list-style: none;
130 | }
131 |
132 | blockquote,
133 | q {
134 | quotes: none;
135 | }
136 |
137 | blockquote:before,
138 | blockquote:after,
139 | q:before,
140 | q:after {
141 | content: "";
142 | content: none;
143 | }
144 |
145 | table {
146 | border-spacing: 0;
147 | border-collapse: collapse;
148 | }
149 |
150 | .clear:after {
151 | font-size: 0;
152 | display: block;
153 | visibility: hidden;
154 | clear: both;
155 | height: 0;
156 | content: " ";
157 | }
158 |
159 | .clear {
160 | display: inline-block;
161 | }
162 |
163 | /* start commented backslash hack \*/
164 | * html .clear {
165 | height: 1%;
166 | }
167 |
168 | .clear {
169 | display: block;
170 | }
171 |
172 | /* close commented backslash hack */
173 | /****************************************
174 | BASIC ELEMENTS
175 | *****************************************/
176 | * {
177 | -webkit-box-sizing: border-box;
178 | -moz-box-sizing: border-box;
179 | box-sizing: border-box;
180 | }
181 |
182 | hr {
183 | clear: both;
184 | border: none;
185 | outline: none;
186 | }
187 |
188 | em {
189 | font-style: italic;
190 | }
191 |
192 | a {
193 | text-decoration: underline;
194 | }
195 |
196 | ul {
197 | list-style: disc;
198 | }
199 |
200 | ol {
201 | list-style: decimal;
202 | }
203 |
204 | ul,
205 | ol {
206 | font-size: 14px;
207 | padding: 0 0 0 33px;
208 | }
209 | ul li,
210 | ol li {
211 | margin: 0;
212 | }
213 |
214 | blockquote {
215 | padding: 0 15px 0 40px;
216 | }
217 |
218 | table {
219 | font-size: 13px;
220 | width: 100%;
221 | margin: 20px 0;
222 | background: white;
223 | }
224 | table th {
225 | font-size: 16px;
226 | font-weight: bold;
227 | }
228 | table tr td {
229 | padding: 7px;
230 | }
231 |
232 | ::selection {
233 | color: white;
234 | background: #000;
235 | }
236 |
237 | ::-moz-selection {
238 | color: white;
239 | background: #000;
240 | }
241 |
242 | html {
243 | position: relative;
244 | }
245 |
246 | body {
247 | margin: 0;
248 | }
249 |
250 | div#wrapper {
251 | width: 100%;
252 | min-height: 100%;
253 | }
254 |
255 | div#content {
256 | padding: 1rem;
257 | width: 70%;
258 | }
259 |
260 | #dragbar {
261 | position: absolute;
262 | top: 0;
263 | min-height: 100%;
264 | left: 70%;
265 | width: 3px;
266 | cursor: col-resize;
267 | }
268 |
269 | div#tactic_state_wrapper {
270 | position: fixed;
271 | margin-left: 70%;
272 | top: 0px;
273 | padding: 1rem;
274 | }
275 |
276 | div.content {
277 | line-height: 1.4rem;
278 | }
279 |
280 | p {
281 | line-height: 1.5rem;
282 | }
283 |
284 | li > p {
285 | margin: 0.28rem 0;
286 | }
287 |
288 | h1, h2, h3, h4, h5, h6 {
289 | font-family: "Lucida Grande", Arial, Helvetica, sans-serif;
290 | }
291 |
292 | h1 {
293 | font-size: 2rem;
294 | line-height: 2rem;
295 | margin: 1rem 0;
296 | color: #0f2f48;
297 | }
298 |
299 | h2 {
300 | font-size: 1.5rem;
301 | margin: 0.8rem 0;
302 | color: #0f2f48;
303 | }
304 |
305 | h3 {
306 | font-size: 1rem;
307 | margin: 0.67rem 0;
308 | color: #0f2f48;
309 | }
310 |
311 | h4 {
312 | font-size: 1rem;
313 | margin: 0.67rem 0;
314 | color: #0f2f48;
315 | }
316 |
317 | p {
318 | font-size: 1rem;
319 | margin: 0.5rem 0;
320 | }
321 |
322 | /**
323 | * Address style set to `bolder` in Firefox 4+, Safari 5, and Chrome.
324 | */
325 | b,
326 | strong {
327 | font-weight: bold;
328 | }
329 |
330 | /**
331 | * Address styling not present in Safari 5 and Chrome.
332 | */
333 | dfn {
334 | font-style: italic;
335 | }
336 |
337 | /**
338 | * Correct font family set oddly in Safari 5 and Chrome.
339 | */
340 | code,
341 | kbd,
342 | pre,
343 | samp {
344 | font-family: monospace, serif;
345 | font-size: 1rem;
346 | }
347 |
348 | /**
349 | * Improve readability of pre-formatted text in all browsers.
350 | */
351 | pre {
352 | white-space: pre-wrap;
353 | }
354 |
355 | /**
356 | * Set consistent quote types.
357 | */
358 | q {
359 | quotes: "“" "”" "‘" "’";
360 | }
361 |
362 | /**
363 | * Address inconsistent and variable font size in all browsers.
364 | */
365 | small {
366 | font-size: 80%;
367 | }
368 |
369 | /**
370 | * Prevent `sub` and `sup` affecting `line-height` in all browsers.
371 | */
372 | sub,
373 | sup {
374 | font-size: 75%;
375 | line-height: 0;
376 | position: relative;
377 | vertical-align: baseline;
378 | }
379 |
380 | sup {
381 | top: -0.5rem;
382 | }
383 |
384 | sub {
385 | bottom: -0.25rem;
386 | }
387 |
388 | /* Font Selection */
389 | .mdseries, .textmf {
390 | font-weight: normal;
391 | }
392 |
393 | .bfseries, .textbf {
394 | font-weight: bold;
395 | }
396 |
397 | .rmfamily, .textrm {
398 | font-family: serif;
399 | }
400 |
401 | .sffamily, .textsf {
402 | font-family: sans-serif;
403 | }
404 |
405 | .ttfamily, .texttt {
406 | font-family: monospace;
407 | }
408 |
409 | .upshape, .textup {
410 | text-transform: uppercase;
411 | }
412 |
413 | .itshape, .textit {
414 | font-style: italic;
415 | }
416 |
417 | .slshape, .textsl {
418 | font-style: oblique;
419 | }
420 |
421 | .scshape, .textsc {
422 | font-variant: small-caps;
423 | }
424 |
425 | small.tiny {
426 | font-size: x-small;
427 | }
428 |
429 | small.scriptsize {
430 | font-size: smaller;
431 | }
432 |
433 | small.footnotesize {
434 | font-size: small;
435 | }
436 |
437 | small.small {
438 | font-size: small;
439 | }
440 |
441 | .normalsize {
442 | font-size: normal;
443 | }
444 |
445 | big.large {
446 | font-size: large;
447 | }
448 |
449 | big.xlarge {
450 | font-size: x-large;
451 | }
452 |
453 | big.xxlarge {
454 | font-size: x-large;
455 | }
456 |
457 | big.huge {
458 | font-size: xx-large;
459 | }
460 |
461 | big.xhuge {
462 | font-size: xx-large;
463 | }
464 |
465 | /* Fonts */
466 | .rm {
467 | font-family: serif;
468 | font-style: normal;
469 | font-weight: normal;
470 | }
471 |
472 | .cal {
473 | font-family: serif;
474 | font-style: italic;
475 | font-weight: normal;
476 | }
477 |
478 | .it {
479 | font-family: serif;
480 | font-style: italic;
481 | font-weight: normal;
482 | }
483 |
484 | .sl {
485 | font-family: serif;
486 | font-style: oblique;
487 | font-weight: normal;
488 | }
489 |
490 | .bf {
491 | font-family: serif;
492 | font-style: normal;
493 | font-weight: bold;
494 | }
495 |
496 | .tt {
497 | font-family: monospace;
498 | font-style: normal;
499 | font-weight: normal;
500 | }
501 |
502 | .underbar {
503 | text-decoration: underline;
504 | }
505 |
506 | /* Boxes */
507 | .fbox, .framebox {
508 | border: 1px black solid;
509 | padding-top: 1px;
510 | padding-bottom: 1px;
511 | padding-left: 3px;
512 | padding-right: 3px;
513 | }
514 |
515 | /* Quotations and Verse */
516 | .quotation p, .quote p, .verse p {
517 | margin-top: 0px;
518 | margin-bottom: 0.5em;
519 | }
520 |
521 | hr {
522 | color: black;
523 | }
524 |
525 | dd {
526 | margin-left: 3rem;
527 | }
528 |
529 | dd p {
530 | padding: 0;
531 | margin: 0 0 1rem 0;
532 | }
533 |
534 | div.definition_wrapper {
535 | margin-top: 1rem;
536 | }
537 |
538 | span.definition_label {
539 | font-weight: bold;
540 | }
541 |
542 | div.definition_content {
543 | margin-left: 0.5rem;
544 | padding-left: 0.5rem;
545 | border-left: 0.15rem solid black;
546 | }
547 |
548 | div.definition_text:hover {
549 | transition: all 0.2s ease;
550 | background: #cfcfcf;
551 | }
552 |
553 | div.definition_lean {
554 | display: none;
555 | }
556 |
557 | div.example_wrapper {
558 | margin-top: 1rem;
559 | }
560 |
561 | span.example_label {
562 | font-weight: bold;
563 | }
564 |
565 | div.example_content {
566 | margin-left: 0.5rem;
567 | padding-left: 0.5rem;
568 | border-left: 0.25rem solid black;
569 | }
570 |
571 | div.example_text:hover {
572 | transition: all 0.2s ease;
573 | background: #cfcfcf;
574 | }
575 |
576 | div.example_lean {
577 | display: none;
578 | }
579 |
580 | div.lemma_wrapper {
581 | margin-top: 1rem;
582 | }
583 |
584 | span.lemma_label {
585 | font-weight: bold;
586 | }
587 |
588 | div.lemma_content {
589 | margin-left: 0.5rem;
590 | padding-left: 0.5rem;
591 | border-left: 0.15rem solid black;
592 | }
593 |
594 | div.lemma_text:hover {
595 | transition: all 0.2s ease;
596 | background: #cfcfcf;
597 | }
598 |
599 | div.lemma_lean {
600 | display: none;
601 | }
602 |
603 | div.theorem_wrapper {
604 | margin-top: 1rem;
605 | }
606 |
607 | span.theorem_label {
608 | font-weight: bold;
609 | }
610 |
611 | div.theorem_content {
612 | margin-left: 0.5rem;
613 | padding-left: 0.5rem;
614 | border-left: 0.25rem solid black;
615 | }
616 |
617 | div.theorem_lean {
618 | display: none;
619 | }
620 |
621 | div.proof_wrapper {
622 | margin-top: 1rem;
623 | width: 100%;
624 | }
625 |
626 | div.proof_wrapper::after {
627 | content: "";
628 | clear: both;
629 | display: table;
630 | }
631 |
632 | span.proof_label {
633 | font-weight: bold;
634 | display: block;
635 | }
636 |
637 | span.proof_qed {
638 | font-weight: bold;
639 | display: block;
640 | }
641 |
642 | div.proof_content {
643 | padding-left: 0.5rem;
644 | }
645 |
646 | div.small_proof_content {
647 | padding-left: 0.5rem;
648 | width: 49%;
649 | float: left;
650 | }
651 |
652 | div.small_tactic_state {
653 | padding-left: 0.5rem;
654 | width: 49%;
655 | float: left;
656 | }
657 |
658 | div.proof_item_lean {
659 | display: none;
660 | }
661 |
662 | div.proof_line {
663 | display: flex;
664 | }
665 |
666 | div.inline_proof_item {
667 | display: inline;
668 | }
669 |
670 | span.tactic_left:hover {
671 | transition: all 0.2s ease;
672 | background: #cfcfcf;
673 | }
674 |
675 | span.tactic_left {
676 | width: 3rem;
677 | background: #dbdbdb;
678 | }
679 |
680 | span.tactic_right {
681 | margin-left: 2rem;
682 | width: 3rem;
683 | background: #dbdbdb;
684 | }
685 |
686 | span.tactic_right:hover {
687 | transition: all 0.2s ease;
688 | background: #cfcfcf;
689 | }
690 |
691 | span[class^=tactic_state_] {
692 | display: none;
693 | }
694 |
695 | /*# sourceMappingURL=lecture.css.map */
696 |
--------------------------------------------------------------------------------
/src/format_lean/lecture.css.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sourceRoot":"","sources":["../../sass/lecture.scss","../../sass/_reset.scss","../../sass/_big_tactic_state_layout.scss","../../sass/_typography.scss","../../sass/_definitions.scss","../../sass/_examples.scss","../../sass/_lemmas.scss","../../sass/_theorems.scss","../../sass/_proofs.scss"],"names":[],"mappings":";AAOA;EACE;EACA;EACA;EACA,OAXa;;;AAaf;EACG,kBAdY;;;AAgBf;EAEI,OAfc;EAgBd,kBAjBe;;;ACFnB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;EAkFI;EACA;EAEA;EACA;EAEA;;;AAEJ;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;EAYI;;;AAEJ;EAEI;EAEA;EAEA;;;AAEJ;AAAA;EAGI;;;AAEJ;AAAA;EAGI;;;AAEJ;AAAA;AAAA;AAAA;EAKI;EACA;;;AAEJ;EAEI;EACA;;;AAGJ;EAEI;EAEA;EACA;EACA;EAEA;EAEA;;;AAEJ;EAEI;;;AAEJ;AACA;EAEI;;;AAEJ;EAEI;;;AAEJ;AAEA;AAAA;AAAA;AAGA;EAEI;EACG;EACK;;;AAGZ;EAEI;EAEA;EACA;;;AAGJ;EAEI;;;AAGJ;EAEI;;;AAEJ;EAEI;;;AAEJ;EAEI;;;AAEJ;AAAA;EAGI;EAEA;;AAEA;AAAA;EAEI;;;AAIR;EAEI;;;AAGJ;EAEI;EAEA;EACA;EAEA;;AAGA;EAEI;EACA;;AAKA;EAEI;;;AAKZ;EAEI;EACA;;;AAEJ;EAEI;EACA;;;AC1PJ;EACC;;;AAGD;EACI;;;AASJ;EACE;EACA;;;AAGF;EAEE;EACA,OAVW;;;AAab;EACG;EACA;EACA;EACA,MAjBU;EAkBV;EACA;;;AAGH;EAEE;EACA,aAzBW;EA0BX;EACA;;;ACvCF;EAEI,aHGkB;;;AGAtB;EAEC;;;AAGD;EAEI;;;AAGJ;EACI;;;AAIJ;EAEI;EACA;EAEA;EAEA,OH3BW;;;AG8Bf;EAEI;EAEA;EAEA,OHpCW;;;AGuCf;EAEI;EAEA;EAEA,OH7CW;;;AGgDf;EAEI;EAEA;EAEA,OHtDW;;;AGyDf;EAEI;EAEA;;;AAIJ;AAAA;AAAA;AAIA;AAAA;EAGI;;;AAGJ;AAAA;AAAA;AAIA;EAEI;;;AAIJ;AAAA;AAAA;AAIA;AAAA;AAAA;AAAA;EAKI;EACA;;;AAGJ;AAAA;AAAA;AAIA;EAEI;;;AAGJ;AAAA;AAAA;AAIA;EAEI;;;AAGJ;AAAA;AAAA;AAIA;EAEI;;;AAGJ;AAAA;AAAA;AAIA;AAAA;EAGI;EACA;EAEA;EAEA;;;AAGJ;EAEI;;;AAGJ;EAEI;;;AAGJ;AACA;EAAoB;;;AACpB;EAAoB;;;AACpB;EAAoB;;;AACpB;EAAoB;;;AACpB;EAAoB;;;AACpB;EAAoB;;;AACpB;EAAoB;;;AACpB;EAAoB;;;AACpB;EAAoB;;;AAEpB;EAAoB;;;AACpB;EAAoB;;;AACpB;EAAoB;;;AACpB;EAAoB;;;AACpB;EAAoB;;;AACpB;EAAoB;;;AACpB;EAAoB;;;AACpB;EAAoB;;;AACpB;EAAoB;;;AACpB;EAAoB;;;AAEpB;AACA;EACI;EACA;EACA;;;AAEJ;EACI;EACA;EACA;;;AAEJ;EACI;EACA;EACA;;;AAEJ;EACI;EACA;EACA;;;AAEJ;EACI;EACA;EACA;;;AAEJ;EACI;EACA;EACA;;;AAGJ;EAAW;;;AAEX;AACA;EACI;EACA;EACA;EACA;EACA;;;AAGJ;AAGA;EACI;EACA;;;AAGJ;EAAI;;;AAEJ;EACE;;;AAEF;EACE;EACA;;;ACnOF;EAEI;;;AAGJ;EAEI;;;AAGJ;EAEI;EACA;EACA;;;AAGJ;EAEE;EAEA;;;AAGF;EAKC;;;AC9BD;EAEI;;;AAGJ;EAEI;;;AAGJ;EAEI;EACA;EACA;;;AAGJ;EAEE;EAEA;;;AAGF;EAKC;;;AC7BD;EAEI;;;AAGJ;EAEI;;;AAGJ;EAEI;EACA;EACA;;;AAGJ;EAEE;EAEA;;;AAGF;EAEE;;;AC1BF;EAEI;;;AAGJ;EAEI;;;AAGJ;EAEI;EACA;EACA;;;AAYJ;EAKC;;;ACjCD;EAEI;EACF;;;AAEF;EACE;EACA;EACA;;;AAGF;EAEI;EACF;;;AAGF;EAEI;EACF;;;AAIF;EAEI;;;AAGJ;EAEI;EACF;EACA;;;AAGF;EAEI;EACF;EACA;;;AAYF;EAIC;;;AAGD;EACE;;;AAIF;EAEC;;;AAGD;EACE;EACA;;;AAEF;EACE;EACA;;;AACF;EACE;EACA;EACA;;;AACF;EACE;EACA;;;AACF;EACE","file":"lecture.css"}
--------------------------------------------------------------------------------
/src/format_lean/lexer.py:
--------------------------------------------------------------------------------
1 | """
2 | pygments.lexers.theorem
3 | ~~~~~~~~~~~~~~~~~~~~~~~
4 |
5 | Lexers for theorem-proving languages.
6 |
7 | :copyright: Copyright 2006-2022 by the Pygments team, see AUTHORS.
8 | :license: BSD, see LICENSE for details.
9 | """
10 |
11 | import re
12 |
13 | from pygments.lexer import RegexLexer, default, words
14 | from pygments.token import Text, Comment, Operator, Keyword, Name, String, \
15 | Number, Punctuation, Generic
16 |
17 | __all__ = ['LeanLexer']
18 |
19 |
20 | class LeanLexer(RegexLexer):
21 | """
22 | For the Lean theorem prover.
23 |
24 | .. versionadded:: 2.0
25 | """
26 | name = 'Lean'
27 | url = 'https://github.com/leanprover/lean'
28 | aliases = ['lean']
29 | filenames = ['*.lean']
30 | mimetypes = ['text/x-lean']
31 |
32 | tokens = {
33 | 'root': [
34 | (r'\s+', Text),
35 | (r'/--', String.Doc, 'docstring'),
36 | (r'/-', Comment, 'comment'),
37 | (r'--.*?$', Comment.Single),
38 | (words((
39 | 'import', 'renaming', 'hiding',
40 | 'namespace',
41 | 'local',
42 | 'private', 'protected', 'section',
43 | 'include', 'omit', 'section',
44 | 'protected', 'export',
45 | 'open',
46 | 'attribute',
47 | ), prefix=r'\b', suffix=r'\b'), Keyword.Namespace),
48 | (words((
49 | 'lemma', 'theorem', 'def', 'definition', 'example',
50 | 'axiom', 'axioms', 'constant', 'constants',
51 | 'universe', 'universes',
52 | 'inductive', 'coinductive', 'structure', 'extends',
53 | 'class', 'instance',
54 | 'abbreviation',
55 |
56 | 'noncomputable theory',
57 |
58 | 'noncomputable', 'mutual', 'meta',
59 |
60 | 'attribute',
61 |
62 | 'parameter', 'parameters',
63 | 'variable', 'variables',
64 |
65 | 'reserve', 'precedence',
66 | 'postfix', 'prefix', 'notation', 'infix', 'infixl', 'infixr',
67 |
68 | 'begin', 'by', 'end',
69 |
70 | 'set_option',
71 | 'run_cmd',
72 | ), prefix=r'\b', suffix=r'\b'), Keyword.Declaration),
73 | (r'@\[[^\]]*\]', Keyword.Declaration),
74 | (words((
75 | 'forall', 'fun', 'Pi', 'from', 'have', 'show', 'assume', 'suffices',
76 | 'let', 'if', 'else', 'then', 'in', 'with', 'calc', 'match',
77 | 'do',
78 | "On", "Montrons", "Fait", "Par", "Posons", "Soit", "Supposons", "applique", "appliqué", "à", "on", "obtient", "choisit", "que", "tel", "convient", "une", "contradiction", "conclut", "par", "calcule", "dans", "combine", "réécrit", "via", "partout", "contrapose", "simplement", "discute", "selon", "il", "suffit", "de", "montrer", "déplie", "l'absurde", "renomme", "en", "oublie", "reformule", "récurrence", "pousse", "la", "négation", "utilisant", "qui", "devient"
79 | ), prefix=r'\b', suffix=r'\b'), Keyword),
80 | (words(('sorry', 'admit'), prefix=r'\b', suffix=r'\b'), Generic.Error),
81 | (words(('Sort', 'Prop', 'Type'), prefix=r'\b', suffix=r'\b'), Keyword.Type),
82 | (words((
83 | '#eval', '#check', '#reduce', '#exit',
84 | '#print', '#help',
85 | ), suffix=r'\b'), Keyword),
86 | (words((
87 | '(', ')', ':', '{', '}', '[', ']', '⟨', '⟩', '‹', '›', '⦃', '⦄', ':=', ',',
88 | )), Operator),
89 | (r'[A-Za-z_\u03b1-\u03ba\u03bc-\u03fb\u1f00-\u1ffe\u2100-\u214f]'
90 | r'[.A-Za-z_\'\u03b1-\u03ba\u03bc-\u03fb\u1f00-\u1ffe\u2070-\u2079'
91 | r'\u207f-\u2089\u2090-\u209c\u2100-\u214f0-9]*', Name),
92 | (r'0x[A-Za-z0-9]+', Number.Integer),
93 | (r'0b[01]+', Number.Integer),
94 | (r'\d+', Number.Integer),
95 | (r'"', String.Double, 'string'),
96 | (r"'(?:(\\[\\\"'nt])|(\\x[0-9a-fA-F]{2})|(\\u[0-9a-fA-F]{4})|.)'", String.Char),
97 | (r'[~?][a-z][\w\']*:', Name.Variable),
98 | (r'\S', Name.Builtin.Pseudo),
99 | ],
100 | 'comment': [
101 | (r'[^/-]', Comment.Multiline),
102 | (r'/-', Comment.Multiline, '#push'),
103 | (r'-/', Comment.Multiline, '#pop'),
104 | (r'[/-]', Comment.Multiline)
105 | ],
106 | 'docstring': [
107 | (r'[^/-]', String.Doc),
108 | (r'-/', String.Doc, '#pop'),
109 | (r'[/-]', String.Doc)
110 | ],
111 | 'string': [
112 | (r'[^\\"]+', String.Double),
113 | (r"(?:(\\[\\\"'nt])|(\\x[0-9a-fA-F]{2})|(\\u[0-9a-fA-F]{4}))", String.Escape),
114 | ('"', String.Double, '#pop'),
115 | ],
116 | }
117 |
--------------------------------------------------------------------------------
/src/format_lean/line_reader.py:
--------------------------------------------------------------------------------
1 | from typing import List, Dict, Optional, Tuple, TextIO
2 | from pathlib import Path
3 | from io import StringIO
4 |
5 | import regex
6 |
7 | from format_lean.server import Server
8 |
9 | blank_line_regex = regex.compile(r'^\s*$')
10 |
11 | def dismiss_line(file_reader, line):
12 | pass
13 |
14 |
15 | class FileReader:
16 | def __init__(self, lean_exec_path, lean_path, readers: List = None):
17 | self.readers = [reader() for reader in readers]
18 | self.status = ''
19 | self.output = []
20 | self.filename = ''
21 | self.cur_line_nb = 1
22 | self.normal_line_handler = dismiss_line
23 | self.blank_line_handler = dismiss_line
24 | self.server = Server(lean_exec_path, lean_path)
25 | self.metadata = dict()
26 |
27 | def reset(self):
28 | self.status = ''
29 | self.normal_line_handler = dismiss_line
30 | self.blank_line_handler = dismiss_line
31 |
32 | def hard_reset(self):
33 | self.reset()
34 | self.cur_line_nb = 1
35 | self.output = []
36 |
37 | def read_file(self, path):
38 | self.server.sync(path)
39 | self.filename = path
40 | with open(str(path), 'r') as f:
41 | for line in f:
42 | for reader in self.readers:
43 | if reader.read(self, line):
44 | break
45 | else:
46 | if blank_line_regex.match(line):
47 | self.blank_line_handler(self, line)
48 | else:
49 | self.normal_line_handler(self, line)
50 | self.cur_line_nb += 1
51 |
52 | class LineReader:
53 | regex = regex.compile(r'.*')
54 |
55 | def read(self, file_reader, line):
56 | m = self.regex.match(line)
57 | if m:
58 | return self.run(m, file_reader)
59 | else:
60 | return False
61 |
--------------------------------------------------------------------------------
/src/format_lean/objects.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | from typing import List
3 | from dataclasses import dataclass, field
4 | import sys
5 |
6 | import regex
7 |
8 | from format_lean.line_reader import LineReader, dismiss_line
9 |
10 |
11 | ############
12 | # Objects #
13 | ############
14 | @dataclass
15 | class Paragraph:
16 | name: str = 'paragraph'
17 | content: str = ''
18 |
19 | def append(self, line):
20 | self.content = self.content + line
21 |
22 |
23 | @dataclass
24 | class Text:
25 | name: str = 'text'
26 | paragraphs: List[Paragraph] = field(default_factory=list)
27 |
28 |
29 | @dataclass
30 | class Section:
31 | name: str = 'section'
32 | title: str = ''
33 |
34 | def title_append(self, line):
35 | self.title = self.title + line
36 |
37 | @dataclass
38 | class SubSection(Section):
39 | name: str = 'subsection'
40 | title: str = ''
41 |
42 | def title_append(self, line):
43 | self.title = self.title + line
44 |
45 | @dataclass
46 | class Bilingual:
47 | """
48 | Base class for objects that contains both text and Lean code.
49 | """
50 | text: str = ''
51 | lean: str = ''
52 |
53 | def text_append(self, line):
54 | self.text = self.text + line
55 |
56 | def lean_append(self, line):
57 | self.lean = self.lean + line
58 |
59 |
60 | @dataclass
61 | class Definition(Bilingual):
62 | name: str = 'definition'
63 |
64 |
65 | @dataclass
66 | class ProofLine:
67 | name: str = 'proof_line'
68 | lean: str = ''
69 | tactic_state_left: str = ''
70 | tactic_state_right: str = ''
71 |
72 |
73 | @dataclass
74 | class ProofItem:
75 | name: str = 'proof-item'
76 | text: str = ''
77 | lines: List[ProofLine] = field(default_factory=list)
78 |
79 | def text_append(self, line):
80 | self.text = self.text + line
81 |
82 | @dataclass
83 | class Proof:
84 | name: str = 'proof'
85 | items: List[ProofItem] = field(default_factory=list)
86 |
87 |
88 | @dataclass
89 | class Lemma(Bilingual):
90 | name: str = 'lemma'
91 | proof: Proof = field(default_factory=Proof)
92 |
93 | def proof_append(self, item):
94 | self.proof.items.append(item)
95 |
96 |
97 | @dataclass
98 | class Theorem(Bilingual):
99 | name: str = 'theorem'
100 | proof: Proof = field(default_factory=Proof)
101 |
102 | def proof_append(self, item):
103 | self.proof.items.append(item)
104 |
105 |
106 | @dataclass
107 | class Example(Bilingual):
108 | name: str = 'example'
109 | proof: Proof = field(default_factory=Proof)
110 |
111 | def proof_append(self, item):
112 | self.proof.items.append(item)
113 |
114 |
115 | @dataclass
116 | class Trad(Paragraph):
117 | name: str = 'trad'
118 | kind: str = 'Théorème'
119 |
120 | #################
121 | # Line readers #
122 | #################
123 |
124 | class Title(LineReader):
125 | regex = regex.compile(r'^-- Title: (.*)$')
126 |
127 | def run(self, m, file_reader):
128 | file_reader.metadata['title'] = m.group(1)
129 |
130 |
131 | class HeaderBegin(LineReader):
132 | regex = regex.compile(r'-- begin header\s*')
133 |
134 | def run(self, m, file_reader):
135 | file_reader.status = 'header'
136 | file_reader.normal_line_handler = dismiss_line
137 | return True
138 |
139 |
140 | class HeaderEnd(LineReader):
141 | regex = regex.compile(r'-- end header\s*')
142 |
143 | def run(self, m, file_reader):
144 | file_reader.status = ''
145 | return True
146 |
147 |
148 | class TextBegin(LineReader):
149 | regex = regex.compile(r'\s*/-\s*$')
150 |
151 | def run(self, m, file_reader):
152 | file_reader.status = 'text'
153 | text = Text()
154 | text.paragraphs = [Paragraph()]
155 | file_reader.output.append(text)
156 | def normal_line(file_reader, line):
157 | text.paragraphs[-1].append(line)
158 | file_reader.normal_line_handler = normal_line
159 | def blank_line(file_reader, line):
160 | text.paragraphs.append(Paragraph())
161 | file_reader.blank_line_handler = blank_line
162 | return True
163 |
164 |
165 | class TextEnd(LineReader):
166 | regex = regex.compile(r'-/')
167 |
168 | def run(self, m, file_reader):
169 | if file_reader.status is not 'text':
170 | return False
171 | file_reader.reset()
172 | return True
173 |
174 |
175 | class SectionBegin(LineReader):
176 | regex = regex.compile(r'\s*/-\s*Section\s*$')
177 |
178 | def run(self, m, file_reader):
179 | file_reader.status = 'section'
180 | sec = Section()
181 | file_reader.output.append(sec)
182 | def normal_line(file_reader, line):
183 | sec.title_append(line)
184 | file_reader.normal_line_handler = normal_line
185 | file_reader.blank_line_handler = normal_line
186 | return True
187 |
188 |
189 | class SectionEnd(LineReader):
190 | regex = regex.compile(r'-/')
191 |
192 | def run(self, m, file_reader):
193 | if file_reader.status is not 'section':
194 | return False
195 | file_reader.reset()
196 | return True
197 |
198 |
199 | class SubSectionBegin(LineReader):
200 | regex = regex.compile(r'\s*/-\s*Sub-section\s*$')
201 |
202 | def run(self, m, file_reader):
203 | file_reader.status = 'subsection'
204 | sec = SubSection()
205 | file_reader.output.append(sec)
206 | def normal_line(file_reader, line):
207 | sec.title_append(line)
208 | file_reader.normal_line_handler = normal_line
209 | file_reader.blank_line_handler = normal_line
210 | return True
211 |
212 |
213 | class SubSectionEnd(LineReader):
214 | regex = regex.compile(r'-/')
215 |
216 | def run(self, m, file_reader):
217 | if file_reader.status is not 'subsection':
218 | return False
219 | file_reader.reset()
220 | return True
221 |
222 |
223 | class DefinitionBegin(LineReader):
224 | regex = regex.compile(r'\s*/-\s*Definition\s*$')
225 |
226 | def run(self, m, file_reader):
227 | file_reader.status = 'definition_text'
228 | defi = Definition()
229 | file_reader.output.append(defi)
230 | def normal_line(file_reader, line):
231 | defi.text_append(line)
232 | file_reader.normal_line_handler = normal_line
233 | file_reader.blank_line_handler = normal_line
234 | return True
235 |
236 |
237 | class DefinitionEnd(LineReader):
238 | regex = regex.compile(r'-/')
239 |
240 | def run(self, m, file_reader):
241 | if file_reader.status is not 'definition_text':
242 | return False
243 | file_reader.status = 'definition_lean'
244 | defi = file_reader.output[-1]
245 | def normal_line(file_reader, line):
246 | defi.lean_append(line)
247 | file_reader.normal_line_handler = normal_line
248 | def blank_line(file_reader, line):
249 | file_reader.reset()
250 | file_reader.blank_line_handler = blank_line
251 | return True
252 |
253 |
254 | class LemmaBegin(LineReader):
255 | regex = regex.compile(r'\s*/-\s*Lemma\s*$')
256 |
257 | def run(self, m, file_reader):
258 | file_reader.status = 'lemma_text'
259 | lemma = Lemma()
260 | file_reader.output.append(lemma)
261 | def normal_line(file_reader, line):
262 | lemma.text_append(line)
263 | file_reader.normal_line_handler = normal_line
264 | file_reader.blank_line_handler = normal_line
265 | return True
266 |
267 |
268 | class LemmaEnd(LineReader):
269 | regex = regex.compile(r'-/')
270 |
271 | def run(self, m, file_reader):
272 | if file_reader.status is not 'lemma_text':
273 | return False
274 | file_reader.status = 'lemma_lean'
275 | lemma = file_reader.output[-1]
276 | def normal_line(file_reader, line):
277 | lemma.lean_append(line)
278 | file_reader.normal_line_handler = normal_line
279 | return True
280 |
281 |
282 | class TheoremBegin(LineReader):
283 | regex = regex.compile(r'\s*/-\s*Theorem\s*$')
284 |
285 | def run(self, m, file_reader):
286 | file_reader.status = 'theorem_text'
287 | theorem = Theorem()
288 | file_reader.output.append(theorem)
289 | def normal_line(file_reader, line):
290 | theorem.text_append(line)
291 | file_reader.normal_line_handler = normal_line
292 | file_reader.blank_line_handler = normal_line
293 | return True
294 |
295 |
296 | class TheoremEnd(LineReader):
297 | regex = regex.compile(r'-/')
298 |
299 | def run(self, m, file_reader):
300 | if file_reader.status is not 'theorem_text':
301 | return False
302 | file_reader.status = 'theorem_lean'
303 | theorem = file_reader.output[-1]
304 | def normal_line(file_reader, line):
305 | theorem.lean_append(line)
306 | file_reader.normal_line_handler = normal_line
307 | return True
308 |
309 |
310 | class ExampleBegin(LineReader):
311 | regex = regex.compile(r'\s*/-\s*Example\s*$')
312 |
313 | def run(self, m, file_reader):
314 | file_reader.status = 'example_text'
315 | example = Example()
316 | file_reader.output.append(example)
317 | def normal_line(file_reader, line):
318 | example.text_append(line)
319 | file_reader.normal_line_handler = normal_line
320 | file_reader.blank_line_handler = normal_line
321 | return True
322 |
323 |
324 | class ExampleEnd(LineReader):
325 | regex = regex.compile(r'-/')
326 |
327 | def run(self, m, file_reader):
328 | if file_reader.status is not 'example_text':
329 | return False
330 | file_reader.status = 'example_lean'
331 | example = file_reader.output[-1]
332 | def normal_line(file_reader, line):
333 | example.lean_append(line)
334 | file_reader.normal_line_handler = normal_line
335 | return True
336 |
337 |
338 | class ProofBegin(LineReader):
339 | regex = regex.compile(r'^begin\s*$')
340 |
341 | def run(self, m, file_reader):
342 | file_reader.status = 'proof'
343 | file_reader.normal_line_handler = dismiss_line # Proofs shouldn't start with normal line
344 | return True
345 |
346 |
347 | class ProofEnd(LineReader):
348 | regex = regex.compile(r'^end\s*$') # Beware of match end
349 |
350 | def run(self, m, file_reader):
351 | if file_reader.status is not 'proof':
352 | return False
353 | file_reader.reset()
354 | return True
355 |
356 |
357 | class ProofComment(LineReader):
358 | regex = regex.compile(r'^[\s{]*-- (.*)$')
359 |
360 | def run(self, m, file_reader):
361 | if file_reader.status == 'proof':
362 | item = ProofItem()
363 | try:
364 | file_reader.output[-1].proof_append(item)
365 | except:
366 | print(f"Something is wrong on line {file_reader.cur_line_nb}. Maybe we are trying to comment on a proof of a lemma whose statement has no human readable version.")
367 | sys.exit(1)
368 | file_reader.status = 'proof_comment'
369 | elif file_reader.status == 'proof_comment':
370 | item = file_reader.output[-1].proof.items[-1]
371 | else:
372 | return False
373 | item.text_append(' ' + m.group(1))
374 | def normal_line(file_reader, line):
375 | file_reader.status = 'proof'
376 | tsl = file_reader.server.info(file_reader.filename,
377 | file_reader.cur_line_nb, 1)
378 | tsr = file_reader.server.info(file_reader.filename,
379 | file_reader.cur_line_nb, len(line))
380 | item.lines.append(
381 | ProofLine(lean=line,
382 | tactic_state_left=tsl, tactic_state_right=tsr))
383 | file_reader.normal_line_handler = normal_line
384 | return True
385 |
386 | class TradBegin(LineReader):
387 | regex = regex.compile(r'\s*/-\s*trad ([^\s]*)\s*$')
388 |
389 | def run(self, m, file_reader):
390 | file_reader.status = 'trad_text'
391 | thm = Trad(kind=m.group(1))
392 | file_reader.output.append(thm)
393 | def normal_line(file_reader, line):
394 | thm.append(line)
395 | file_reader.normal_line_handler = normal_line
396 | file_reader.blank_line_handler = normal_line
397 | return True
398 |
399 | class TradEnd(LineReader):
400 | regex = regex.compile(r'-/')
401 |
402 | def run(self, m, file_reader):
403 | if file_reader.status is not 'trad_text':
404 | return False
405 | file_reader.reset()
406 | return True
407 |
--------------------------------------------------------------------------------
/src/format_lean/renderer.py:
--------------------------------------------------------------------------------
1 | from dataclasses import dataclass, field
2 | from typing import List
3 | from copy import copy
4 |
5 | from jinja2 import Environment, FileSystemLoader
6 | from mistletoe.html_renderer import HTMLRenderer
7 | from mistletoe.block_token import Document
8 |
9 | from pygments import highlight
10 | from pygments.formatters import HtmlFormatter
11 |
12 | from format_lean.objects import Text, Paragraph
13 | from format_lean.tikzcd import TikzcdRenderer
14 | from format_lean.lexer import LeanLexer
15 |
16 | lexer = LeanLexer(leanstripall=True)
17 | formatter = HtmlFormatter(linenos=False)
18 |
19 | def color(obj):
20 | if hasattr(obj, 'lean'):
21 | obj.lean = highlight(obj.lean, lexer, formatter)
22 | if hasattr(obj, 'proof'):
23 | for proof_item in obj.proof.items:
24 | for line in proof_item.lines:
25 | line.lean = highlight(line.lean, lexer, formatter)
26 | line.tactic_state_left = highlight(line.tactic_state_left, lexer, formatter)
27 | line.tactic_state_right = highlight(line.tactic_state_right, lexer, formatter)
28 | return obj
29 |
30 | def prepare(content):
31 | """ Operates some substitutions before markdown processing. """
32 | for old, new in [('« ', '« '), (' »', ' »'),
33 | (r'\{', r'\\{'), (r'\}', r'\\}'),
34 | (r'\(', r'\\('), (r'\)', r'\\)'),
35 | (r'\;', r'\\;'), (r'\,', r'\\,'),
36 | (r'\!', r'\\!')]:
37 | content = content.replace(old, new)
38 | return content
39 |
40 | @dataclass
41 | class Renderer:
42 | env: Environment = None
43 | markdown_renderer:TikzcdRenderer = field(default_factory=TikzcdRenderer)
44 | ts_filters: List = field(default_factory=list)
45 |
46 | def render_markdown(self, text, par=True):
47 | # par=True mean we strip and
48 | rendered = self.markdown_renderer.render(Document(prepare(text)))
49 | return rendered if par else rendered[3:-5]
50 |
51 | def transform_text(self, text):
52 | return Text(paragraphs=[
53 | Paragraph(content=self.render_markdown(par.content))
54 | for par in text.paragraphs])
55 |
56 | def transform_theorem(self, theorem):
57 | theorem.text = self.render_markdown(theorem.text)
58 | for proof_item in theorem.proof.items:
59 | proof_item.text = self.render_markdown(proof_item.text, par=False)
60 | for proof_line in proof_item.lines:
61 | for r, s in self.ts_filters:
62 | proof_line.tactic_state_left = r.sub(
63 | s, proof_line.tactic_state_left)
64 | proof_line.tactic_state_right = r.sub(
65 | s, proof_line.tactic_state_right)
66 | return theorem
67 |
68 | transform_example = transform_theorem
69 | transform_lemma = transform_theorem
70 |
71 | def transform_trad(self, theorem):
72 | theorem.content = self.render_markdown(theorem.content)
73 | return theorem
74 |
75 | def render(self, objects, out_path, page_context=None, title=None):
76 | """
77 | Renders objects to path
78 | """
79 | objects = [getattr(self, f'transform_{obj.name}', lambda x: x)(obj)
80 | for obj in objects]
81 | page_context = page_context or dict()
82 | page_context['title'] = page_context.get('title', title or 'Lean')
83 | res = '\n'.join([
84 | self.env.get_template(obj.name).render(obj=color(obj),
85 | lang=page_context['lang']) for obj in objects])
86 | page_context['content'] = res
87 | self.env.get_template('page').stream(page_context).dump(out_path)
88 |
89 | @classmethod
90 | def from_file(cls, path, ts_filters=None):
91 | return cls(
92 | env=Environment(loader=FileSystemLoader(path)),
93 | ts_filters=ts_filters or [])
94 |
95 |
--------------------------------------------------------------------------------
/src/format_lean/server.py:
--------------------------------------------------------------------------------
1 | import os, subprocess, json
2 |
3 | class LeanError(Exception):
4 | pass
5 |
6 | class Server:
7 | """
8 | Very rough interface around the Lean server. Will work only if nothing bad
9 | happens/
10 | """
11 | def __init__(self, lean_exec_path, lean_path):
12 | self.proc = subprocess.Popen([lean_exec_path, "-j0", "--server"],
13 | stdin=subprocess.PIPE, stdout=subprocess.PIPE,
14 | universal_newlines=True, bufsize=1,
15 | env={'LEAN_PATH': lean_path})
16 | self.seq_num = 0
17 |
18 | def sync(self, filename):
19 | self.seq_num += 1
20 | s = f'{{"seq_num": {self.seq_num}, "command": "sync", "file_name": "{filename}"}}\n'
21 | self.proc.stdin.write(s)
22 | self.proc.stdout.readline()
23 |
24 | def info(self, filename, line, col):
25 | self.seq_num += 1
26 | s = f'{{"seq_num": {self.seq_num}, "command":"info", ' \
27 | f'"file_name": "{filename}", ' \
28 | f'"line": {line},"column":{col}}}\n'
29 | self.proc.stdin.write(s)
30 | ret = json.loads(self.proc.stdout.readline().rstrip())
31 | if 'record' in ret:
32 | return ret['record']['state']
33 | else:
34 | raise LeanError(ret)
35 |
--------------------------------------------------------------------------------
/src/format_lean/teach_lean.css:
--------------------------------------------------------------------------------
1 | code {
2 | font-size: 1.2rem;
3 | font-weight: bold;
4 | }
5 |
6 | div#content {
7 | width: 100%;
8 | }
9 |
10 | div#content > p {
11 | width: 80%;
12 | }
13 |
14 | @media (max-width: 760px) {
15 | div#content {
16 | width: 100%;
17 | }
18 | }
19 | div.definition_wrapper {
20 | margin-top: 1rem;
21 | }
22 |
23 | span.definition_label {
24 | font-weight: bold;
25 | }
26 |
27 | div.definition_content {
28 | margin-left: 0.5rem;
29 | padding-left: 0.5rem;
30 | border-left: 0.15rem solid black;
31 | }
32 |
33 | div.definition_text:hover {
34 | transition: all 0.2s ease;
35 | background: #ffffc5;
36 | }
37 |
38 | div.definition_lean {
39 | display: block;
40 | }
41 |
42 | div.example_wrapper {
43 | margin-top: 1rem;
44 | }
45 |
46 | span.example_label {
47 | font-weight: bold;
48 | }
49 |
50 | div.example_content {
51 | margin-left: 0.5rem;
52 | padding-left: 0.5rem;
53 | border-left: 0.25rem solid black;
54 | }
55 |
56 | div.example_text:hover {
57 | transition: all 0.2s ease;
58 | background: #ffffc5;
59 | }
60 |
61 | div.example_lean {
62 | display: block;
63 | }
64 |
65 | div.lemma_wrapper {
66 | margin-top: 1rem;
67 | }
68 |
69 | span.lemma_label {
70 | font-weight: bold;
71 | }
72 |
73 | div.lemma_content {
74 | margin-left: 0.5rem;
75 | padding-left: 0.5rem;
76 | border-left: 0.15rem solid black;
77 | }
78 |
79 | div.lemma_text:hover {
80 | transition: all 0.2s ease;
81 | background: #ffffc5;
82 | }
83 |
84 | div.lemma_lean {
85 | display: none;
86 | }
87 |
88 | div.theorem_wrapper {
89 | margin-top: 1rem;
90 | }
91 |
92 | span.theorem_label {
93 | font-weight: bold;
94 | }
95 |
96 | div.theorem_content {
97 | margin-left: 0.5rem;
98 | padding-left: 0.5rem;
99 | border-left: 0.25rem solid black;
100 | }
101 |
102 | div.theorem_text:hover {
103 | transition: all 0.2s ease;
104 | background: #ffffc5;
105 | }
106 |
107 | div.theorem_lean {
108 | display: block;
109 | }
110 |
111 | div.proof_wrapper {
112 | margin-top: 1rem;
113 | width: 100%;
114 | }
115 |
116 | div.proof_wrapper::after {
117 | content: "";
118 | clear: both;
119 | display: table;
120 | }
121 |
122 | span.proof_label {
123 | font-weight: bold;
124 | display: block;
125 | }
126 |
127 | span.proof_qed {
128 | font-weight: bold;
129 | display: block;
130 | }
131 |
132 | div.proof_content {
133 | padding-left: 0.5rem;
134 | }
135 |
136 | div.small_proof_content {
137 | padding-left: 0.5rem;
138 | width: 49%;
139 | float: left;
140 | }
141 |
142 | div.small_tactic_state {
143 | padding-left: 0.5rem;
144 | width: 49%;
145 | float: left;
146 | }
147 |
148 | span.proof_item_text:hover {
149 | transition: all 0.2s ease;
150 | background: #ffffc5;
151 | }
152 |
153 | div.proof_item_lean {
154 | display: block;
155 | }
156 |
157 | div.proof_line {
158 | display: flex;
159 | }
160 |
161 | div.inline_proof_item {
162 | display: inline;
163 | }
164 |
165 | span.tactic_left:hover {
166 | transition: all 0.2s ease;
167 | background: #ffffc5;
168 | }
169 |
170 | span.tactic_left {
171 | width: 3rem;
172 | background: #ffffdf;
173 | }
174 |
175 | span.tactic_right {
176 | margin-left: 2rem;
177 | width: 3rem;
178 | background: #ffffdf;
179 | }
180 |
181 | span.tactic_right:hover {
182 | transition: all 0.2s ease;
183 | background: #ffffc5;
184 | }
185 |
186 | span[class^=tactic_state_] {
187 | display: none;
188 | }
189 |
190 | div.example_wrapper {
191 | font-size: 1.4rem;
192 | }
193 |
194 | div.lemma_wrapper {
195 | font-size: 1.4rem;
196 | }
197 |
198 | div.theorem_wrapper {
199 | font-size: 1.4rem;
200 | }
201 |
202 | div.definition_wrapper {
203 | font-size: 1.4rem;
204 | }
205 |
206 | pre {
207 | margin-top: 0.2rem;
208 | margin-bottom: 0.2rem;
209 | }
210 |
211 | span.tactic_left {
212 | width: 3rem;
213 | background: #dddddd;
214 | }
215 |
216 | span.tactic_left:hover {
217 | transition: all 0.2s ease;
218 | background: #c4c4c4;
219 | }
220 |
221 | span.tactic_right {
222 | margin-left: 2rem;
223 | width: 3rem;
224 | background: #dddddd;
225 | }
226 |
227 | span.tactic_right:hover {
228 | transition: all 0.2s ease;
229 | background: #c4c4c4;
230 | }
231 |
232 | pre {
233 | white-space: pre-wrap;
234 | word-break: keep-all;
235 | }
236 |
237 | div.tikzcd {
238 | display: block;
239 | margin: 0.5rem auto;
240 | overflow: auto;
241 | text-align: center;
242 | }
243 |
244 | /*# sourceMappingURL=teach_lean.css.map */
245 |
--------------------------------------------------------------------------------
/src/format_lean/teach_lean.css.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sourceRoot":"","sources":["../../sass/teach_lean.scss","../../sass/_definitions.scss","../../sass/_examples.scss","../../sass/_lemmas.scss","../../sass/_theorems.scss","../../sass/_proofs.scss","../../sass/_tikzcd.scss"],"names":[],"mappings":"AAGA;EACC;EACA;;;AAED;EACC;;;AAGD;EACC;;;AAED;EACA;IACC;;;ACbD;EAEI;;;AAGJ;EAEI;;;AAGJ;EAEI;EACA;EACA;;;AAGJ;EAEE;EAEA;;;AAGF;EAGC;;;AC5BD;EAEI;;;AAGJ;EAEI;;;AAGJ;EAEI;EACA;EACA;;;AAGJ;EAEE;EAEA;;;AAGF;EAGC;;;AC3BD;EAEI;;;AAGJ;EAEI;;;AAGJ;EAEI;EACA;EACA;;;AAGJ;EAEE;EAEA;;;AAGF;EAEE;;;AC1BF;EAEI;;;AAGJ;EAEI;;;AAGJ;EAEI;EACA;EACA;;;AAIJ;EAEE;EAEA;;;AAIF;EAGC;;;AC/BD;EAEI;EACF;;;AAEF;EACE;EACA;EACA;;;AAGF;EAEI;EACF;;;AAGF;EAEI;EACF;;;AAIF;EAEI;;;AAGJ;EAEI;EACF;EACA;;;AAGF;EAEI;EACF;EACA;;;AAIF;EAEE;EAEA;;;AAIF;EAEC;;;AAKD;EACE;;;AAIF;EAEC;;;AAGD;EACE;EACA;;;AAEF;EACE;EACA;;;AACF;EACE;EACA;EACA;;;AACF;EACE;EACA;;;AACF;EACE;;;ALhEF;EACC;;;AAED;EACC;;;AAED;EACC;;;AAED;EACC;;;AAGD;EACC;EACA;;;AAKD;EACE;EACA,YAJO;;;AAKT;EACE;EACA;;;AAED;EACC;EACA;EACA,YAZO;;;AAcT;EACE;EACA;;;AAED;EACA;EACC;;;AM1DF;EACC;EACA;EACA;EACA","file":"teach_lean.css"}
--------------------------------------------------------------------------------
/src/format_lean/templates/definition:
--------------------------------------------------------------------------------
1 |
2 |
Definition
3 |
4 |
5 | {{ obj.text }}
6 |
7 |
8 | {{ obj.lean }}
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/src/format_lean/templates/example:
--------------------------------------------------------------------------------
1 |
2 |
{{ lang.get('Example', 'Example') }}
3 |
4 |
5 | {{ obj.text }}
6 |
7 |
8 |
9 | {{ obj.lean }}
10 |
11 |
12 |
13 |
14 |
{{ lang.get('Proof', 'Proof') }}
15 |
16 | {% for item in obj.proof.items %}
17 |
18 |
{{ item.text }}
19 |
20 | {% for line in item.lines %}
21 |
22 |
23 | {{ line.lean }}
24 |
25 | {{ line.tactic_state_left }}
26 | {{ line.tactic_state_right }}
27 |
28 | {% endfor %}
29 |
30 |
31 | {% endfor %}
32 |
33 |
QED.
34 |
35 |
36 |
--------------------------------------------------------------------------------
/src/format_lean/templates/lemma:
--------------------------------------------------------------------------------
1 |
2 |
{{ lang.get('Lemma', 'Lemma') }}
3 |
4 |
5 | {{ obj.text }}
6 |
7 |
8 |
9 | {{ obj.lean }}
10 |
11 |
12 |
13 |
14 |
{{ lang.get('Proof', 'Proof') }}
15 |
16 | {% for item in obj.proof.items %}
17 |
18 |
{{ item.text }}
19 |
20 | {% for line in item.lines %}
21 |
22 |
23 | {{ line.lean }}
24 |
25 | {{ line.tactic_state_left }}
26 | {{ line.tactic_state_right }}
27 |
28 | {% endfor %}
29 |
30 |
31 | {% endfor %}
32 |
33 |
QED.
34 |
35 |
36 |
--------------------------------------------------------------------------------
/src/format_lean/templates/page:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | {{ title }}
7 |
15 |
17 | {% for css in csss %}
18 |
19 | {% endfor %}
20 |
21 |
22 |
23 |
24 |
25 | {{ content }}
26 |
27 |
28 |
33 |
34 | {% for js in jss %}
35 |
36 | {% endfor %}
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/src/format_lean/templates/section:
--------------------------------------------------------------------------------
1 | {{ obj.title }}
2 |
--------------------------------------------------------------------------------
/src/format_lean/templates/subsection:
--------------------------------------------------------------------------------
1 | {{ obj.title }}
2 |
--------------------------------------------------------------------------------
/src/format_lean/templates/text:
--------------------------------------------------------------------------------
1 | {% for paragraph in obj.paragraphs %}
2 | {{ paragraph.content }}
3 | {% endfor %}
4 |
--------------------------------------------------------------------------------
/src/format_lean/templates/theorem:
--------------------------------------------------------------------------------
1 |
2 |
{{ lang.get('Theorem', 'Theorem') }}
3 |
4 |
5 | {{ obj.text }}
6 |
7 |
8 |
9 | {{ obj.lean }}
10 |
11 |
12 |
13 |
14 |
{{ lang.get('Proof', 'Proof') }}
15 |
16 | {% for item in obj.proof.items %}
17 |
18 |
{{ item.text }}
19 |
20 | {% for line in item.lines %}
21 |
22 |
23 | {{ line.lean }}
24 |
25 | {{ line.tactic_state_left }}
26 | {{ line.tactic_state_right }}
27 |
28 | {% endfor %}
29 |
30 |
31 | {% endfor %}
32 |
33 |
QED.
34 |
35 |
36 |
--------------------------------------------------------------------------------
/src/format_lean/templates/tikzcd:
--------------------------------------------------------------------------------
1 | \documentclass{standalone}
2 | \usepackage{tikz-cd}
3 |
4 | \usepackage{unicode-math}
5 |
6 | \begin{document}
7 | \begin{tikzcd}{{ cd }}\end{tikzcd}
8 | \end{document}
9 |
--------------------------------------------------------------------------------
/src/format_lean/templates/trad:
--------------------------------------------------------------------------------
1 |
2 |
{{ obj.kind }}
3 |
4 |
5 | {{ obj.content }}
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/src/format_lean/tikzcd.py:
--------------------------------------------------------------------------------
1 | import subprocess
2 | import re
3 | from pathlib import Path
4 | from tempfile import TemporaryDirectory
5 | from bs4 import BeautifulSoup
6 |
7 | from mistletoe import HTMLRenderer
8 | from mistletoe import block_token
9 | from mistletoe.block_token import BlockToken, Heading, BlockCode, Quote, CodeFence, ThematicBreak, List, Table, Footnote, Paragraph, ListItem, HTMLBlock, span_token
10 | from mistletoe.html_renderer import HTMLRenderer
11 | from jinja2 import Template
12 |
13 | import format_lean
14 |
15 | module_path = Path(format_lean.__file__).parent
16 |
17 | class DisplayMath(BlockToken):
18 | """
19 | We don't want markdown to mess with LaTeX displaymath block delimited by
20 | \[ and \], so we need a new block token class.
21 | """
22 | pattern = re.compile(r'^\s*\\\[')
23 |
24 | def __init__(self, lines):
25 | self.content = ''.join(lines)
26 |
27 | @classmethod
28 | def start(cls, line):
29 | return bool(cls.pattern.match(line))
30 |
31 | @staticmethod
32 | def read(lines):
33 | line_buffer = [next(lines)]
34 | for line in lines:
35 | if line.endswith(r'\]'):
36 | break
37 | line_buffer.append(line)
38 | return line_buffer
39 |
40 |
41 | class ParagraphMath(Paragraph):
42 | """
43 | A replacement for mistletoe Paragraph block token class. I don't know how
44 | to extend it to fit DisplayMath, so let's copy-paste.
45 | """
46 | @classmethod
47 | def read(cls, lines):
48 | line_buffer = [next(lines)]
49 | next_line = lines.peek()
50 | while (next_line is not None
51 | and next_line.strip() != ''
52 | and not Heading.start(next_line)
53 | and not CodeFence.start(next_line)
54 | and not Quote.start(next_line)
55 | and not DisplayMath.start(next_line)):
56 |
57 | # check if next_line starts List
58 | list_pair = ListItem.parse_marker(next_line)
59 | if (len(next_line) - len(next_line.lstrip()) < 4
60 | and list_pair is not None):
61 | prepend, leader = list_pair
62 | # non-empty list item
63 | if next_line[:prepend].endswith(' '):
64 | # unordered list, or ordered list starting from 1
65 | if not leader[:-1].isdigit() or leader[:-1] == '1':
66 | break
67 |
68 | # check if next_line starts HTMLBlock other than type 7
69 | html_block = HTMLBlock.start(next_line)
70 | if html_block and html_block != 7:
71 | break
72 |
73 | # check if we see a setext underline
74 | if cls.parse_setext and cls.is_setext_heading(next_line):
75 | line_buffer.append(next(lines))
76 | return SetextHeading(line_buffer)
77 |
78 | # check if we have a ThematicBreak (has to be after setext)
79 | if ThematicBreak.start(next_line):
80 | break
81 |
82 | # no other tokens, we're good
83 | line_buffer.append(next(lines))
84 | next_line = lines.peek()
85 | return line_buffer
86 |
87 |
88 | class TikzcdRenderer(HTMLRenderer):
89 | def __init__(self, *args, **kwargs):
90 |
91 | if 'tikzcd-tpl' in kwargs:
92 | tpl = kwargs.pop('tikzcd-tpl')
93 | else:
94 | tpl = str(module_path / 'templates' / 'tikzcd')
95 | with open(tpl, "r") as file:
96 | self.tikzcd_tpl = Template(file.read())
97 | self.tikz_scale = kwargs.pop('tikz_scale', 1.75)
98 | # Note the next line actually returns None, but changes state (arghh).
99 | res = super().__init__(*args, **kwargs)
100 | # The following 4 lines are a hugly hack to replace Paragraph
101 | # by ParagraphMath and use DisplayMath. The API here is awful,
102 | # modifying a private global variable.
103 | block_token.remove_token(Paragraph)
104 | block_token._token_types.append(ParagraphMath)
105 | block_token._token_types.insert(0, DisplayMath)
106 | self.render_map['DisplayMath'] = self.render_display_math
107 | self.render_map['ParagraphMath'] = self.render_paragraph
108 | return res
109 |
110 | def render_block_code(self, token):
111 | if token.language == 'cd':
112 | code = token.children[0].content
113 | print(code)
114 | with TemporaryDirectory() as name:
115 | tdir = Path(name)
116 | texpath = str(tdir / 'tmp.tex')
117 | pdfpath = str(tdir / 'tmp.pdf')
118 | svgpath = str(tdir / 'tmp.svg')
119 | self.tikzcd_tpl.stream(cd=code).dump(texpath)
120 | print(self.tikzcd_tpl.render(cd=code))
121 | subprocess.call(['xelatex', '--output-dir', name, texpath])
122 | subprocess.call(['pdf2svg', pdfpath, svgpath])
123 | with open(svgpath) as f:
124 | svg_str = f.read()
125 | ident = hash(code)
126 | svg_str = svg_str.replace('glyph', str(ident)[:6])
127 | svg = BeautifulSoup(svg_str, features="html.parser").svg
128 | svg['width'] = f'{self.tikz_scale*float(svg["width"][:-2])}pt'
129 | svg['height'] = f'{self.tikz_scale*float(svg["height"][:-2])}pt'
130 | return f'\n{svg}\n
\n'
131 | else:
132 | return super().render_block_code(token)
133 |
134 | def render_display_math(self, token):
135 | return '\n' + token.content + '
\n'
136 |
137 |
138 |
--------------------------------------------------------------------------------
/src/format_lean/with_tufte.css:
--------------------------------------------------------------------------------
1 | body {
2 | width: 100%;
3 | max-width: 100%;
4 | }
5 |
6 | code {
7 | font-size: 1.2rem;
8 | font-weight: bold;
9 | }
10 |
11 | div#content {
12 | width: 70%;
13 | }
14 |
15 | @media (max-width: 760px) {
16 | div#content {
17 | width: 100%;
18 | }
19 | }
20 | #dragbar {
21 | background-color: #111;
22 | }
23 |
24 | h1#tactic_state_header {
25 | font-size: 2rem;
26 | line-height: 2rem;
27 | margin: 1rem 0;
28 | color: #111;
29 | }
30 |
31 | div.definition_wrapper {
32 | margin-top: 1rem;
33 | }
34 |
35 | span.definition_label {
36 | font-weight: bold;
37 | }
38 |
39 | div.definition_content {
40 | margin-left: 0.5rem;
41 | padding-left: 0.5rem;
42 | border-left: 0.15rem solid black;
43 | }
44 |
45 | div.definition_text:hover {
46 | transition: all 0.2s ease;
47 | background: #ffffc5;
48 | }
49 |
50 | div.definition_lean {
51 | display: none;
52 | }
53 |
54 | div.example_wrapper {
55 | margin-top: 1rem;
56 | }
57 |
58 | span.example_label {
59 | font-weight: bold;
60 | }
61 |
62 | div.example_content {
63 | margin-left: 0.5rem;
64 | padding-left: 0.5rem;
65 | border-left: 0.25rem solid black;
66 | }
67 |
68 | div.example_text:hover {
69 | transition: all 0.2s ease;
70 | background: #ffffc5;
71 | }
72 |
73 | div.example_lean {
74 | display: none;
75 | }
76 |
77 | div.lemma_wrapper {
78 | margin-top: 1rem;
79 | }
80 |
81 | span.lemma_label {
82 | font-weight: bold;
83 | }
84 |
85 | div.lemma_content {
86 | margin-left: 0.5rem;
87 | padding-left: 0.5rem;
88 | border-left: 0.15rem solid black;
89 | }
90 |
91 | div.lemma_text:hover {
92 | transition: all 0.2s ease;
93 | background: #ffffc5;
94 | }
95 |
96 | div.lemma_lean {
97 | display: none;
98 | }
99 |
100 | div.theorem_wrapper {
101 | margin-top: 1rem;
102 | }
103 |
104 | span.theorem_label {
105 | font-weight: bold;
106 | }
107 |
108 | div.theorem_content {
109 | margin-left: 0.5rem;
110 | padding-left: 0.5rem;
111 | border-left: 0.25rem solid black;
112 | }
113 |
114 | div.theorem_lean {
115 | display: none;
116 | }
117 |
118 | div.proof_wrapper {
119 | margin-top: 1rem;
120 | width: 100%;
121 | }
122 |
123 | div.proof_wrapper::after {
124 | content: "";
125 | clear: both;
126 | display: table;
127 | }
128 |
129 | span.proof_label {
130 | font-weight: bold;
131 | display: block;
132 | }
133 |
134 | span.proof_qed {
135 | font-weight: bold;
136 | display: block;
137 | }
138 |
139 | div.proof_content {
140 | padding-left: 0.5rem;
141 | }
142 |
143 | div.small_proof_content {
144 | padding-left: 0.5rem;
145 | width: 49%;
146 | float: left;
147 | }
148 |
149 | div.small_tactic_state {
150 | padding-left: 0.5rem;
151 | width: 49%;
152 | float: left;
153 | }
154 |
155 | div.proof_item_lean {
156 | display: none;
157 | }
158 |
159 | div.proof_line {
160 | display: flex;
161 | }
162 |
163 | div.inline_proof_item {
164 | display: inline;
165 | }
166 |
167 | span.tactic_left:hover {
168 | transition: all 0.2s ease;
169 | background: #ffffc5;
170 | }
171 |
172 | span.tactic_left {
173 | width: 3rem;
174 | background: #ffffdf;
175 | }
176 |
177 | span.tactic_right {
178 | margin-left: 2rem;
179 | width: 3rem;
180 | background: #ffffdf;
181 | }
182 |
183 | span.tactic_right:hover {
184 | transition: all 0.2s ease;
185 | background: #ffffc5;
186 | }
187 |
188 | span[class^=tactic_state_] {
189 | display: none;
190 | }
191 |
192 | div.example_wrapper {
193 | font-size: 1.4rem;
194 | }
195 |
196 | div.lemma_wrapper {
197 | font-size: 1.4rem;
198 | }
199 |
200 | div.theorem_wrapper {
201 | font-size: 1.4rem;
202 | }
203 |
204 | pre {
205 | margin-top: 0.2rem;
206 | margin-bottom: 0.2rem;
207 | }
208 |
209 | span.tactic_left {
210 | display: inline-block;
211 | width: 1rem;
212 | height: 1rem;
213 | background: #dddddd;
214 | }
215 |
216 | span.tactic_left:hover {
217 | transition: all 0.2s ease;
218 | background: #c4c4c4;
219 | }
220 |
221 | span.tactic_right {
222 | display: inline-block;
223 | width: 1rem;
224 | height: 1rem;
225 | margin-left: 0;
226 | background: #dddddd;
227 | }
228 |
229 | span.tactic_right:hover {
230 | transition: all 0.2s ease;
231 | background: #c4c4c4;
232 | }
233 |
234 | html {
235 | position: relative;
236 | }
237 |
238 | body {
239 | margin: 0;
240 | }
241 |
242 | div#wrapper {
243 | width: 100%;
244 | min-height: 100%;
245 | }
246 |
247 | div#content {
248 | padding: 1rem;
249 | width: 70%;
250 | }
251 |
252 | #dragbar {
253 | position: absolute;
254 | top: 0;
255 | min-height: 100%;
256 | left: 70%;
257 | width: 3px;
258 | cursor: col-resize;
259 | }
260 |
261 | div#tactic_state_wrapper {
262 | position: fixed;
263 | margin-left: 70%;
264 | top: 0px;
265 | padding: 1rem;
266 | }
267 |
268 | div#content {
269 | margin: 0;
270 | padding-left: 30px;
271 | }
272 |
273 | body {
274 | padding: 0;
275 | }
276 |
277 | /*# sourceMappingURL=with_tufte.css.map */
278 |
--------------------------------------------------------------------------------
/src/format_lean/with_tufte.css.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sourceRoot":"","sources":["../../sass/with_tufte.scss","../../sass/_definitions.scss","../../sass/_examples.scss","../../sass/_lemmas.scss","../../sass/_theorems.scss","../../sass/_proofs.scss","../../sass/_big_tactic_state_layout.scss"],"names":[],"mappings":"AAGA;EACI;EACA;;;AAGJ;EACC;EACA;;;AAED;EACC;;;AAED;EACA;IACC;;;AAGD;EACG;;;AAGH;EACE;EACA;EACA;EACA;;;ACzBF;EAEI;;;AAGJ;EAEI;;;AAGJ;EAEI;EACA;EACA;;;AAGJ;EAEE;EAEA;;;AAGF;EAKC;;;AC9BD;EAEI;;;AAGJ;EAEI;;;AAGJ;EAEI;EACA;EACA;;;AAGJ;EAEE;EAEA;;;AAGF;EAKC;;;AC7BD;EAEI;;;AAGJ;EAEI;;;AAGJ;EAEI;EACA;EACA;;;AAGJ;EAEE;EAEA;;;AAGF;EAEE;;;AC1BF;EAEI;;;AAGJ;EAEI;;;AAGJ;EAEI;EACA;EACA;;;AAYJ;EAKC;;;ACjCD;EAEI;EACF;;;AAEF;EACE;EACA;EACA;;;AAGF;EAEI;EACF;;;AAGF;EAEI;EACF;;;AAIF;EAEI;;;AAGJ;EAEI;EACF;EACA;;;AAGF;EAEI;EACF;EACA;;;AAYF;EAIC;;;AAGD;EACE;;;AAIF;EAEC;;;AAGD;EACE;EACA;;;AAEF;EACE;EACA;;;AACF;EACE;EACA;EACA;;;AACF;EACE;EACA;;;AACF;EACE;;;ALrDF;EACC;;;AAED;EACC;;;AAED;EACC;;;AAGD;EACC;EACA;;;AAKD;EACE;EACA;EACA;EACA,YANO;;;AAQT;EACE;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA,YAlBO;;;AAoBT;EACE;EACA;;;AMpEF;EACC;;;AAGD;EACI;;;AASJ;EACE;EACA;;;AAGF;EAEE;EACA,OAVW;;;AAab;EACG;EACA;EACA;EACA,MAjBU;EAkBV;EACA;;;AAGH;EAEE;EACA,aAzBW;EA0BX;EACA;;;ANiCF;EACC;EACA;;;AAGD;EACC","file":"with_tufte.css"}
--------------------------------------------------------------------------------