├── .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 ε ,
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 ε  with Na Ha,
57 |   cases hc ε  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 |
29 |

Tactic state

30 |
31 |
32 |
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"} --------------------------------------------------------------------------------