pax_global_header00006660000000000000000000000064142635701120014513gustar00rootroot0000000000000052 comment=c366365aaddeb3a65dc0816c8f93ec209dc9de44 PG-4.5/000077500000000000000000000000001426357011200116715ustar00rootroot00000000000000PG-4.5/.github/000077500000000000000000000000001426357011200132315ustar00rootroot00000000000000PG-4.5/.github/ert.json000066400000000000000000000005531426357011200147210ustar00rootroot00000000000000{ "problemMatcher": [ { "owner": "ert-problem-matcher", "severity": "error", "pattern": [ { "regexp": "^\\s+((?:FAILED|failed|SKIPPED|skipped|ABORTED|aborted|QUIT|quit)\\s+[0-9]+/[0-9]+\\s+.*)$", "message": 1 } ] } ] } PG-4.5/.github/workflows/000077500000000000000000000000001426357011200152665ustar00rootroot00000000000000PG-4.5/.github/workflows/test.yml000066400000000000000000000255741426357011200170050ustar00rootroot00000000000000name: CI on: push: branches: #- master #- hybrid - "**" pull_request: branches: - '**' jobs: ########################################################################### ####### compile and build manual ########################################################################### build: runs-on: ubuntu-latest strategy: matrix: emacs_version: - 25.1 - 25.2 - 25.3 - 26.1 - 26.2 - 26.3 - 27.1 - 27.2 - 28.1 # at most 20 concurrent jobs per free account # cf. https://help.github.com/en/actions/reference/workflow-syntax-for-github-actions#usage-limit max-parallel: 4 # don't cancel all in-progress jobs if one matrix job fails: fail-fast: false steps: - uses: actions/checkout@v2 - uses: purcell/setup-emacs@master with: version: ${{ matrix.emacs_version }} - run: emacs --version - run: make # Erik: Extend this with linting? - name: Install makeinfo run: sudo apt-get update -y -q && sudo DEBIAN_FRONTEND=noninteractive apt-get install -y -q --no-install-recommends texinfo - run: make doc.info ########################################################################### ####### make magic ########################################################################### # Check that the texinfo sources of the manual can be updated # with the documentation strings for variables and functions in # the source code and that the manual is actually up-to-date. # If the final git diff fails, then somebody forgot to update # the manuals with ``make -C doc magic'' after changing a # variable or function documentation that appears in one of the # manuals. check-doc-magic: runs-on: ubuntu-latest strategy: matrix: emacs_version: # I don't think we need to check with all emacs # versions. The latest two should be enough, maybe even # only the latest one. - 26.3 - 27.2 - 28.1 # don't cancel all in-progress jobs if one matrix job fails: fail-fast: false steps: - uses: actions/checkout@v2 - uses: purcell/setup-emacs@master with: version: ${{ matrix.emacs_version }} - run: emacs --version - run: make -C doc magic - run: git diff --exit-code -- doc ########################################################################### ####### first tests: ci/test.sh runs tests in ci/coq-tests.el ########################################################################### test: runs-on: ubuntu-latest strategy: matrix: coq_emacs_version: - coq-8.6-emacs-25.2 - coq-8.6-emacs-27.2 - coq-8.6-emacs-28.1 - coq-8.7-emacs-25.3 - coq-8.7-emacs-27.2 - coq-8.7-emacs-28.1 - coq-8.8-emacs-26.1 - coq-8.8-emacs-27.2 - coq-8.8-emacs-28.1 - coq-8.9-emacs-26.2 - coq-8.9-emacs-27.2 - coq-8.9-emacs-28.1 - coq-8.10-emacs-27.2 - coq-8.10-emacs-28.1 - coq-8.11-emacs-26.3 - coq-8.11-emacs-27.2 - coq-8.11-emacs-28.1 - coq-8.12-emacs-25.2 - coq-8.12-emacs-26.2 - coq-8.12-emacs-26.3 - coq-8.12-emacs-27.1 - coq-8.12-emacs-27.2 - coq-8.12-emacs-28.1 - coq-8.13-emacs-25.2 - coq-8.13-emacs-26.2 - coq-8.13-emacs-26.3 - coq-8.13-emacs-27.1 - coq-8.13-emacs-27.2 - coq-8.13-emacs-28.1 - coq-8.14-emacs-25.2 - coq-8.14-emacs-26.2 - coq-8.14-emacs-26.3 - coq-8.14-emacs-27.1 - coq-8.14-emacs-27.2 - coq-8.14-emacs-28.1 - coq-8.15-emacs-25.2 - coq-8.15-emacs-25.3 - coq-8.15-emacs-26.1 - coq-8.15-emacs-26.2 - coq-8.15-emacs-26.3 - coq-8.15-emacs-27.1 - coq-8.15-emacs-27.2 - coq-8.15-emacs-28.1 # at most 20 concurrent jobs per free account # cf. https://help.github.com/en/actions/reference/workflow-syntax-for-github-actions#usage-limit max-parallel: 6 # don't cancel all in-progress jobs if one matrix job fails: fail-fast: false steps: - uses: actions/checkout@v2 - name: Add ert problem matcher run: echo "::add-matcher::.github/ert.json" - uses: coq-community/docker-coq-action@v1 id: docker-coq-action with: opam_file: 'dummy.opam' custom_image: proofgeneral/coq-emacs:${{matrix.coq_emacs_version}} custom_script: | startGroup Print opam config opam config list; opam repo list; opam list endGroup startGroup other relevant configuration echo getconf _NPROCESSORS_ONLN: $(getconf _NPROCESSORS_ONLN) emacs --version coqc --version ocamlc -v endGroup startGroup Run tests sudo chown -R coq:coq ./ci make tests endGroup ########################################################################### ####### compilation tests: all tests in subdirectories of ci/compile-tests ########################################################################### compile-tests: runs-on: ubuntu-latest strategy: matrix: coq_emacs_version: - coq-8.6-emacs-25.2 - coq-8.6-emacs-27.2 - coq-8.6-emacs-28.1 - coq-8.7-emacs-25.3 - coq-8.7-emacs-27.2 - coq-8.7-emacs-28.1 - coq-8.8-emacs-26.1 - coq-8.8-emacs-27.2 - coq-8.8-emacs-28.1 - coq-8.9-emacs-26.2 - coq-8.9-emacs-27.2 - coq-8.9-emacs-28.1 - coq-8.10-emacs-27.2 - coq-8.10-emacs-28.1 - coq-8.11-emacs-26.3 - coq-8.11-emacs-27.2 - coq-8.11-emacs-28.1 - coq-8.12-emacs-25.2 - coq-8.12-emacs-26.2 - coq-8.12-emacs-26.3 - coq-8.12-emacs-27.1 - coq-8.12-emacs-27.2 - coq-8.12-emacs-28.1 - coq-8.13-emacs-25.2 - coq-8.13-emacs-26.2 - coq-8.13-emacs-26.3 - coq-8.13-emacs-27.1 - coq-8.13-emacs-27.2 - coq-8.13-emacs-28.1 - coq-8.14-emacs-25.2 - coq-8.14-emacs-26.2 - coq-8.14-emacs-26.3 - coq-8.14-emacs-27.1 - coq-8.14-emacs-27.2 - coq-8.14-emacs-28.1 - coq-8.15-emacs-25.2 - coq-8.15-emacs-25.3 - coq-8.15-emacs-26.1 - coq-8.15-emacs-26.2 - coq-8.15-emacs-26.3 - coq-8.15-emacs-27.1 - coq-8.15-emacs-27.2 - coq-8.15-emacs-28.1 # don't cancel all in-progress jobs if one matrix job fails: fail-fast: false steps: - uses: actions/checkout@v2 - name: Add ert problem matcher run: echo "::add-matcher::.github/ert.json" - uses: coq-community/docker-coq-action@v1 id: docker-coq-action with: opam_file: 'dummy.opam' custom_image: proofgeneral/coq-emacs:${{matrix.coq_emacs_version}} custom_script: | startGroup other relevant configuration echo getconf _NPROCESSORS_ONLN: $(getconf _NPROCESSORS_ONLN) emacs --version coqc --version ocamlc -v endGroup startGroup Run tests sudo chown -R coq:coq ./ci make -C ci/compile-tests test endGroup ########################################################################### ####### Additional tests in ci/simple-tests ########################################################################### simple-tests: runs-on: ubuntu-latest strategy: matrix: coq_emacs_version: - coq-8.6-emacs-25.2 - coq-8.6-emacs-27.2 - coq-8.6-emacs-28.1 - coq-8.7-emacs-25.3 - coq-8.7-emacs-27.2 - coq-8.7-emacs-28.1 - coq-8.8-emacs-26.1 - coq-8.8-emacs-27.2 - coq-8.8-emacs-28.1 - coq-8.9-emacs-26.2 - coq-8.9-emacs-27.2 - coq-8.9-emacs-28.1 - coq-8.10-emacs-27.2 - coq-8.10-emacs-28.1 - coq-8.11-emacs-26.3 - coq-8.11-emacs-27.2 - coq-8.11-emacs-28.1 - coq-8.12-emacs-25.2 - coq-8.12-emacs-26.2 - coq-8.12-emacs-26.3 - coq-8.12-emacs-27.1 - coq-8.12-emacs-27.2 - coq-8.12-emacs-28.1 - coq-8.13-emacs-25.2 - coq-8.13-emacs-26.2 - coq-8.13-emacs-26.3 - coq-8.13-emacs-27.1 - coq-8.13-emacs-27.2 - coq-8.13-emacs-28.1 - coq-8.14-emacs-25.2 - coq-8.14-emacs-26.2 - coq-8.14-emacs-26.3 - coq-8.14-emacs-27.1 - coq-8.14-emacs-27.2 - coq-8.14-emacs-28.1 - coq-8.15-emacs-25.2 - coq-8.15-emacs-25.3 - coq-8.15-emacs-26.1 - coq-8.15-emacs-26.2 - coq-8.15-emacs-26.3 - coq-8.15-emacs-27.1 - coq-8.15-emacs-27.2 - coq-8.15-emacs-28.1 # don't cancel all in-progress jobs if one matrix job fails: fail-fast: false steps: - uses: actions/checkout@v2 - name: Add ert problem matcher run: echo "::add-matcher::.github/ert.json" - uses: coq-community/docker-coq-action@v1 id: docker-coq-action with: opam_file: 'dummy.opam' custom_image: proofgeneral/coq-emacs:${{matrix.coq_emacs_version}} custom_script: | startGroup other relevant configuration echo getconf _NPROCESSORS_ONLN: $(getconf _NPROCESSORS_ONLN) emacs --version coqc --version ocamlc -v endGroup startGroup Run tests sudo chown -R coq:coq ./ci make -C ci/simple-tests all endGroup ########################################################################### ####### indentation tests in ci/test-indent ########################################################################### # Run indentation tests in ci/test-indent on all supported emacs # versions without coq installed. test-indent: runs-on: ubuntu-latest strategy: matrix: emacs_version: - 25.2 - 25.3 - 26.1 - 26.2 - 26.3 - 27.1 - 27.2 - 28.1 max-parallel: 4 # don't cancel all in-progress jobs if one matrix job fails: fail-fast: false steps: - uses: actions/checkout@v2 - uses: purcell/setup-emacs@master with: version: ${{ matrix.emacs_version }} - run: emacs --version - run: make -C ci/test-indent # Testing this here because this job runs with all Emacs versions - run: make -C ci/simple-tests test-qrhl.success PG-4.5/.gitignore000066400000000000000000000001611426357011200136570ustar00rootroot00000000000000.byte-compile nohup.out TAGS ChangeLog /proof-general-autoloads.el /proof-general-pkg.el *.elc *~ /ci/.lia.cache PG-4.5/AUTHORS000066400000000000000000000032101426357011200127350ustar00rootroot00000000000000Current Authors/Maintainers: Pierre Courtieu (Coq, lib) Erik Martin-Dorel (Coq, Web site) Clément Pit-Claudel (Coq, packaging) Stefan Monnier (Coq) Dominique Unruh (qrhl-tool) Christophe Raffalli (PhoX) Pierre-Yves Strub (EasyCrypt) Hendrik Tews (Proof Tree) Previous Authors: David Aspinall (all) Makarius Wenzel (Isar, generic) Stefan Berghofer (Isar) Paul Callaghan (Plastic, Lego) Healfdene Goguen (Coq, generic, doc) Thomas Kleymann (Lego, doc, generic) Patrick Loiseleur (Coq) Yves Bertot (generic) David von Oheimb (X-Symbol) Dilip Sequeira (Lego, generic) Graham Dutton (Web support) These are the main "official" authors of Proof General, but many more people have contributed, some very significantly. We're grateful to everyone who has! Please see the CREDITS section in the manual for a more complete list. ==================================================================== Notes regarding the License change to GPLv3+: Contributors who are positively known to be OK with relicensing: Stefan Monnier Clément Pit-Claudel Paul Steckler Erik Martin-Dorel Pierre Courtieu Jim Fehrle stardiviner Pierre-Yves Strub Hendrik Tews David Aspinall Cyril Anaclet Christophe Raffalli Makarius Wenzel ## New provers compared to PG-async: phox easycrypt pghaskell pgocaml pgshell Git history: git log -- phox easycrypt pghaskell pgocaml pgshell | grep 'Author:' | sort -u shows that these have only received contributions from people in the above list. PG-4.5/BUGS000066400000000000000000000066271426357011200123670ustar00rootroot00000000000000-*- outline -*- * Known Bugs and Workarounds for Proof General. The bugs here are split into problems which are generic, and those which only apply to particular provers. The FAQ mentions other issues which are not necessarily PG bugs. This list is incomplete and only occasionally updated, please search on Trac for current issues. * Reporting bugs If you have a problem that is not mentioned here, please visit the Trac at the address above to add a ticket. Please describe your problem carefully, include a short demonstration file and tell us the exact version of Emacs and Proof General that you are using. * General issues ** If the proof assistant goes into a loop displaying lots of information It may be difficult or impossible to interrupt it, because Emacs doesn't get a chance to process the C-c C-c keypress or "Stop" button push (or anything else). In this situation, you will need to send an interrupt to the (e.g.) Isabelle process from another shell. If that doesn't stop things, you can try 'kill -FPE '. This problem can happen with looping rewrite rules in the Isabelle simplifier, when tracing rewriting. It seems to be worse on certain architectures, and slower machines. ** Glitches in display handling, esp with multiple frames Unfortunately the handling of the display is very difficult to manage because the API provided by Emacs is quirky and varies between versions. If the eager display/tear-down of frames is annoying you, you may customize the variable `proof-shell-fiddle-frames' to nil to reduce it a bit. To prevent eagerly displaying new frames at on starting the shell, you can also add a mode hook to set `proof-eagerly-raise' e.g.: (add-hook 'proof-goals-mode-hook (lambda () (setq proof-eagerly-raise nil))) (add-hook 'proof-response-mode-hook (lambda () (setq proof-eagerly-raise nil))) Generally, the best way of working with multiple frames is to try not to stop/start the proof assistant too much (this involves killing buffers, which spoils the frame/buffer correspondence). ** Using C-g can leave script management in a mess (rare). The code is not fully protected from Emacs interrupts. Workaround: Don't type C-g while script management is processing. If you do, use proof-restart-scripting to be sure of synchronizing. ** When proof-rsh-command is set to "ssh host", C-c C-c broken The whole process may be killed instead of interrupted. This isn't a bug in Proof General, but the behaviour of ssh. Try using rsh instead, it is said to forward signals to the remote command. ** In tty mode, the binding C-c C-RET has no effect. Workaround: manually bind C-c RET to 'proof-goto-point instead. ** Prover does not lock/may not notice dirty files Files are not locked when they are being read by the prover, so a long file could be edited and saved as the prover is processing it, resulting in a loss of synchronization between Emacs and the proof assistant. Files ought to be coloured red while they are being processed, just as single lines are. Workaround: be careful not to edit a file as it is being read by the proof assistant. * Problems with Coq ** Multiple file handling and auto-compilation is incomplete ** C-c C-a C-i on long intro lines breaks line the wrong way. ** coqtags doesn't find all declarations. It cannot handle lists e.g., with "Parameter x,y:nat" it only tags x but not y. Workaround: don't rely too much on the etags mechanism. PG-4.5/CHANGES000066400000000000000000000716011426357011200126710ustar00rootroot00000000000000-*- outline -*- This is a summary of main changes. For details, please see the Git ChangeLog, the GitHub repo https://github.com/ProofGeneral/PG * Changes of Proof General 4.5 from Proof General 4.4 ** Generic changes *** License changed to GPLv3+ *** Remove support for the following systems: Twelf, CCC, Lego, Hol-Light, ACL2, Plastic, Lambda-Clam, Isabelle, HOL98. *** require GNU Emacs 25.2 or later The current policy aims at supporting multiple Emacs versions, including those available in distributions Debian Stable (https://packages.debian.org/stable/emacs) and Ubuntu LTS (https://packages.ubuntu.com/emacs), until their End-Of-Support (see also https://wiki.ubuntu.com/Releases). Support for Emacs 25 will be dropped in April 2023 when Ubuntu Bionic reaches end of standard support. *** new command and menu item to easily upgrade all packages - To upgrade all ELPA packages (including ProofGeneral if it was installed via MELPA), do "M-x proof-upgrade-elpa-packages RET" or use the "Proof-General > Upgrade ELPA packages..." menu item *** bug fixes - Using query-replace (or replace-string) in the processed region doesn't wrongly jump to the first match anymore. - cheat face (admit etc) now visible when locked. *** remove key-binding for proof-electric-terminator-toggle - The default key-binding for proof-electric-terminator-toggle (C-c .) was too easy to enter by mistake. And it was not that useful as we can expect users to configure electric-terminator once and for all. Hence the removal of this default key-binding. *** add another (fallback) key-binding for proof-goto-point - The default key-binding for proof-goto-point (C-c ) was not available in TTYs. Now, this function can also be run with "C-c RET", which happens to be automatically trigerred if we type "C-c " in a TTY. *** new proof-priority-action-list Similar to proof-action-list, but holding actions that need to go to the proof assistant at the next opportunity. ** Qrhl-tool Support for qrhl-tool theorem prover has been added by Dominique Unruh. References: - Initial pull request: https://github.com/ProofGeneral/PG/pull/636 - Qrhl-tool web site: https://dominique-unruh.github.io/qrhl-tool ** EasyCrypt Support for EasyCrypt has been added. ** Coq changes *** fix highlighting issues for ssr tactics ending with colon Now, { exact: term. } will always be correctly highlighted. However, only (forall {T: Type}, Type) will be highlighted, unlike term (forall { T: Type }, Type) that has a spurious space. Also in (forall [T: Type], Type), variable T is now highlighted. *** new menu Coq -> Auto Compilation for all background compilation options *** support for 8.11 vos and vok compilation See menu Coq -> Auto Compilation -> vos compilation, option coq-compile-vos and subsection "11.3.3 Quick and inconsistent compilation" in the Coq reference manual. *** support for 8.5 quick compilation See new menu Coq -> Auto Compilation -> Quick compilation. Select "no quick" as long as you have not switched to "Proof using" to compile without -quick. Select "quick no vio2vo" to use -quick without vio2vo (and guess what "quick and vio2vo" means ;-), select "ensure vo" to ensure a sound development. Quick compilation is only supported for Coq < 8.11. See the option `coq-compile-quick' or the subsection "11.3.3 Quick and inconsistent compilation" in the Coq reference manual. *** new option coq-compile-keep-going (in menu Coq -> Auto Compilation) Similar to ``make -k'', with this option enabled, background compilation does not stop at the first error but rather continues as far as possible. *** Automatic insertion of "Proof using" annotations. PG now supports the "Suggest Proof Using" by inserting (automatically or by contextual menu or by a command) the "Proof using" annotation suggested by Coq. This suggestion happens at "Qed" command. By default PG will only highlight the corresponding "Proof" keyword and let the user actively ask for insertion. You can customize this behaviour by setting the coq-accept-proof-using-suggestion to one of these values: 'always, 'highlight, 'ask, 'never. This is also settable from Coq menu. See documentation of this variable for an explanation of the different possible values and some more information. *** Make ProofGeneral/Coq `opam-switch-mode' aware When opam-switch-mode is loaded, the Coq background process can be killed when changing the opam switch through opam-switch-mode, see `coq-kill-coq-on-opam-switch' and https://github.com/ProofGeneral/opam-switch-mode *** Limited extensibility for indentation Coq indentation mechanism is based on a fixed set of tokens and precedence rules. Extensibility is now possible by adding new syntax for a given token (no new token can be added). Typical example: if you define a infix operator xor you may want to define it as a new syntax for token \/ in order to have the indentation rules of or applied to xor. Use: (setq coq-smie-user-tokens '(("xor" . "\\/"))) The set of tokens can be seen in variable smie-grammar. *** Indentation of monadic notations. Using the extensibility for indentation described above we provide a way to define your own monadic operators using the coq-smie-monadic-tokens in the same spirit as coq-smie-user-tokens above. By default two well established syntax are supported: x <- e ;; e and do x <- e ; e *** Clickable Hypothesis in goals buffer to copy/paste hyp names Clicking on a hyp name in goals buffer with button 2 copies its name at current point position (which should be in the scripting buffer). This eases the insertion of hypothesis names in scripts. *** Folding/unfolding hypothesis A cross "-" is displayed to the left of each hypothesis of the goals buffer. Clicking ont it (button 1) hides/unhides the hypothesis. You can also hit "f" while ont he hypothesis. "F" unfolds all hypothesis. Hide/ unhide status remains when goal changes. *** Highlighting of hypothesis You can highlight hypothesis in goals buffer on a per name fashion. Hit "h" while on the hypothesis. "H" removes all highlighting in the buffer. Highlighting status remains when goal changes. **** Automatic highlighting with (search)About. Hypothesis cited in the response buffer after C-c C-a C-a (i.e. M-x coq-SearchAbout) will be highlighted automatically. Any other hypothesis highlighted is unhighlighted. To disable this, do: (setq coq-highlight-hyps-cited-in-response nil) *** Support Coq's feature for highlighting the differences between successive proof steps. See section 11.8 ("Showing Proof Diffs") in the documentation. *** Support Ssreflect's proof style for inserting an intros tactic when doing "C-c C-a TAB": PG inserts "move=> ..." if the current file contains "Require ... ssreflect" on the same line; otherwise PG inserts "intros ..." as before. *** Customizing Search Blacklist (command created and menu entry moved) To change the list of blacklisted string for Search commands during development, use now coq-change-search-blacklist-interactive. The menu for this has moved, it is now in Coq/Other Queries/Search Blacklist. To change the default blacklist, set variable coq-search-blacklist-string (unchanged). *** Proof General can omit complete opaque proofs This speeds up asserting of larger chunks at the price of letting errors in these proofs go unnoticed. Configure `proof-omit-proofs-option' or select "Proof-General -> Quick Options -> Processing -> Omit Proofs". See also section "11.5 Omitting proofs for speed" in the manual. Beware that if lemmas are proved in a section, these lemmas should start with a "Proof using" annotation, otherwise Coq would compute a wrong type for them when this omitting-proofs feature is enabled. *** bug fixes - avoid leaving partial files behind when compilation fails - 123: Parallel background compilation fails to execute some imports - fix error in process filter: Cannot resize window - 54 partially: Buffer coq-compile-response sometimes takes over the whole window - 75, superseded by 352: fix detection of imported libraries for background compilation - 70, 119: Coq trunk + compile before require => « Invalid version syntax: 'trunk' » - 92: Compile before require from current directory failing with 8.5 - fix background compilation for the case of identical time stamps - improve background compilation when both .vio and .vo files are up-to-date - 33: cyclic dependencies - 130: parallel build of Proof General - Prevent non-existent directories from crashing PG - 143: interrupt diverting tactics - 142: Quick compilation mode is not saved - 499: emacs eats up all my RAM while processing imports - various compatibility fixes for various Emacs versions - fix Proof General manual generation - 551: fix Proof General when coqtop is absent - background compilation may break when changing current buffer - check for the case that coqdep does not report an error on unknown file - 527: ProofGeneral freezes when there is a build error in a dependency file - 563: Never send two commands at once - 537: some test in ci/coq-tests.el fails sporadically *** indentation code refactored A big refactoring of the code for indentation has been done. You may experience a few changes in indentation results. Mostly small shifts to the right. Variable `coq-indent-box-style' only affects indentation after quantifiers (used to affect script braces "{"). Variable `coq-indent-align-with-first-arg` governs between these two indentation behaviours: (setq 'coq-indent-align-with-first-arg t) gives somefunciton x y z t u v (setq 'coq-indent-align-with-first-arg nil) give (default): somefunciton x y z t u v *** using github CI with a large test body Proof General uses now the continuous integration infrastructure at github to execute quite a number of tests on each pull request. The tests regularly find issues in Proof General, but also in Coq or Emacs. *** various coqtags improvements *** redesign of automatic background compilation The code for automatic background compilation has been redesigned, the internal logic simplified and big portions were rewritten. * Changes of Proof General 4.4 from Proof General 4.3 ** ProofGeneral has moved to GitHub! https://github.com/ProofGeneral/PG Please submit new bugs there. ** Coq changes *** indentation of ";" tactical: by default the indentation is like this: tac1; tac2; tac3. do this: (setq coq-indent-semicolon-tactical 0) to have this: tac1; tac2; tac3. *** Option to disable the auto resizing of response buffer: By default when the response buffer is on the same column than goals buffer, pg changes its size dynamically to optimize goals displaying. To disable this feature use: (setq coq-optimise-resp-windows-enable nil) *** Option to prefer top of conclusion instead of bottom When display goals that do not fit in the goals window, PG prefers to display the bottom of the goal (where lies it own conclusion. You can make it prefer the top of the conclusion by setting this: (setq coq-prefer-top-of-conclusion t) *** Auto adjusting of printing width On by default. To disable: Coq/Settings/Auto Adapt Printing Width or (setq coq-auto-adapt-printing-width nil). *** Removed the Set Undo 500 at start. This is obsolete. To recover: (setq coq-user-init-cmd `("Set Undo 500.")) *** Option to highlight usual symbols Off by default, enable using: (setq coq-symbol-highlight-enable t) * Changes of Proof General 4.3 from Proof General 4.2 ** Prooftree changes *** Require Prooftree version 0.11 Check the Prooftree website to see which other versions of Prooftree are compatible with Proof General 4.3. *** New features One can now trigger an retraction (undo) by selecting the appropriate sequent in Prooftree. One can further send proof commands or proof scripts from whole proof subtrees to Proof General, which will insert them in the current buffer. Prooftree also supports some recent Coq features, see below. ** Coq changes *** Asynchronous parallel compilation of required modules Proof General has now a second implementation for compiling required Coq modules. Check menu Coq -> Settings -> Compile Parallel In Background to compile modules in parallel in the background while Proof General stays responsive. *** Support for more bullets (coq 8.5): -- --- ++ +++ ** *** Scripting supports bullets of any length. Indentation supports only bullets of length <= 4 (like ----). Longer may be supported if needed. For indentation to work well, please use this precedence: - + * -- ++ ** --- +++ *** ... *** smie indentation is now the only choice. Old code removed. will work only if emacs >= 23.3. *** indentation of modules, sections and proofs are customizable (setq coq-indent-modulestart X) will set indentation width for modules and sections to X characters (setq coq-indent-proofstart X) will set indentation width for modules and sections to X characters *** indentation of match with cases: by default the indentation is like this now: match n with O => ... | S n => ... end do this: (setq coq-match-indent 4) to get back the previous indetation style: match n with O => ... | S n => ... end *** indentation now supports { at end of line: example: assert (h:n = k). { apply foo. reflexivity. } apply h. *** Default indentation of forall and exists is not boxed anymore For instance, this is now indented like this: Lemma foo: forall x y, x = 0 -> ... . instead of: Lemma foo: forall x y, x = 0 -> ... . (do this: (setq coq-indent-box-style t) to bring the box style back). Use (setq coq-smie-after-bolp-indentation 0) for a smaller indentation: Lemma foo: forall x y, x = 0 -> ... . *** Default indentation cases of "match with" are now indented by 2 instead of 4. "|" is indented by zero: match n with 0 => ... | S n => ... end instead of: match n with 0 => ... | S n => ... end do this: (setq coq-match-indent 4) to bring old behaviour back. *** Support for bullets, braces and Grab Existential Variables for Prooftree. *** Support for _Coqproject files According to Coq documentation, it is advised to use coq_makefile -f _CoqProject -o Makefile to build your Makefile automatically from "profect file" _CoqProject. Such a file should contain the options to pass to coq_makefile, i.e. paths to add to coq load path (-I, -R) and other options to pass to coqc/coqtop (-arg). Coqide (and now proofgeneral) do use the information stored in this file to configure the options to add to the coqtop invocation. When opening a coq file, proofgeneral looks for a file _Coqproject in the current directory or a parent directory and reads it. Except for very unlikely situation this should replace the use of local file variables (which remains possible and overrides project file options). *** Support for prettify-symbols-mode. *** Colors in response and goals buffers Experimental: colorize hypothesis names and some parts of error and warning messages, and also evars. For readability. *** Coq Querying facilities **** Minibuffer interactive queries Menu Coq/Other Queries (C-c C-a C-q) allows to send queries (like Print, Locate...) (à la auctex) without inserting them in the buffer. Queries are TAB completed and the usual history mechanism applies. Completion allows only a set of state preserving commands. The list is not exhaustive yet. This should replace the C-c C-v usual command mechanism (which has no completion). **** Mouse Queries This remaps standard emacs key bindings (faces and buffers menus popup), so this is not enabled by default, use (setq coq-remap-mouse-1 t) to enable. - (control mouse-1) on an identifier sends a Print query on that id. - (shift mouse-1) on an identifier sends a About query on that id. - (control shift mouse-1) on an identifier sends a Check query on that id. As most of the bindings, they are active in the three buffer (script, goals, response). Obeys C-u prefix for "Printing all" flag. *** bug fixes - Annoying cursor jump when hitting ".". - random missing output due to the prover left in silent mode by a previously scripted error. - Better display of warnings (less messages lost). * Changes of Proof General 4.2 from Proof General 4.1 ** Generic/misc changes *** Added user option: `proof-next-command-insert-space' Allows the user to turn off the electric behaviour of generating newlines or spaces in the buffer. Turned on by default, set to nil to revert to PG 3.7 behaviour. *** Support proof-tree visualization via the external Prooftree program Currently only Coq (using Coq version 8.4beta or newer) supports proof-tree visualization. If Prooftree is installed, the proof-tree display can be started via the toolbar, the Proof-General menu or by C-c C-d. To get Prooftree, visit http://askra.de/software/prooftree *** Compilation fixes for Emacs 24. *** Fix "pgshell" mode for shell/CLI prover interaction Also add some quick hacks for scripting OCaml and Haskell ** Coq changes *** Smarter three windows mode: In three pane mode, there are three display modes, depending where the three useful buffers are displayed: scripting buffer, goals buffer and response buffer. Here are the three modes: - vertical: the 3 buffers are displayed in one column. - hybrid: 2 columns mode, left column displays scripting buffer and right column displays the 2 others. - horizontal: 3 columns mode, one for each buffer (script, goals, response). By default, the display mode is automatically chosen by considering the current emacs frame width: if it is smaller than `split-width-threshold' then vertical mode is chosen, otherwise if it is smaller than 1.5 * `split-width-threshold' then hybrid mode is chosen, finally if the frame is larger than 1.5 * `split-width-threshold' then the horizontal mode is chosen. You can change the value of `split-width-threshold' at your will (by default it is 160). If you want to force one of the layouts, you can set variable `proof-three-window-mode-policy' to 'vertical, 'horizontal or 'hybrid. The default value is 'smart which sets the automatic behaviour described above. example: (setq proof-three-window-mode-policy 'hybrid). Or via customization menus. *** Multiple file handling for Coq Feature. No more experimental. Set coq-load-path to the list of directories for libraries (you can attach it to the file using menu "coq prog args"). Many thanks to Hendrik Tews for that great peace of code! *** Support proof-tree visualization Many thanks to Hendrik Tews for that too! *** New commands for Print/Check/About/Show with "Printing All" flag Avoids typing "Printing All" in the buffer. See the menu Coq > Other queries. Thanks to Assia Mahboubi and Frederic Chyzak for the suggestion. Shortcut: add C-u before the usual shortcut (example: C-u C-c C-a C-c for: Set Printing All. Check. Unset Printing All. ) *** Coq menus and shortcut in response and goals buffers. Check, Print etc available in these buffers. *** Tooltips hidden by default Flickering when hovering commands is off by default! *** "Insert Requires" now uses completion based on coq-load-path *** New setting for hiding additional goals from the *goals* buffer Coq > Settings > Hide additional subgoals *** Double hit terminator Experimental: Same as electric terminator except you have to type "." twice quickly. Electric terminator will stop getting in the way all the time with module.notations. Coq > Double Hit Electric Terminator. Note 1: Mutually exclusive with usual electric terminator. Note 2: For french keyboard it may be convenient to map ";" instead of ".": (add-hook 'proof-mode-hook (lambda () (define-key coq-mode-map (kbd ";") 'coq-terminator-insert))) *** Indentation improvements using SMIE. Supporting bullets and { }. Still experimental. Please submit bugs. IMPORTANT: Limitations of indentation: - hard-wired precedence between bullets: - < + < * example: Proof. - split. + split. * auto. * auto. + intros. auto. - auto. Qed. - Always use "Proof." when proving an "Instance" (wrong indentation and slow downs otherwise). As a general rule, try to always introduce a proof with "Proof." (or "Next Obligation" with Program). *** "Show" shows the (cached) state of the proof at point. If Show goals (C-c C-a C-s) is performed when point is on a locked region, then it shows the prover state as stored by proofgeneral at this point. This works only when the command at point has been processed by "next step" (otherwise coq was silent at this point and nothing were cached). *** Minor parsing fixes *** Windows resizing fixed ** HOL Light [WORK IN PROGRESS] *** Basic support now works, see hol-light directory [WORK IN PROGRESS] * Changes of Proof General 4.1 from Proof General 4.0 ** Generic changes *** Parsing now uses cache by default (proof-use-parser-cache=t). Speeds up undo/redo in long buffers if no edits are made. ** Isabelle changes *** Unicode tokens enabled by default ** Coq changes *** A new indentation algorithm, using SMIE. This works when SMIE is available (Emacs >= 23.3), but must be enabled by the variable `coq-use-smie'. It also provides improved navigation facilities for things like C-M-t, C-M-f and C-M-b. Addition by Stefan Monnier. *** Experimental multiple file handling for Coq. Proof General is now able to automatically compile files while scripting Require commands, either internally or externally (by running Make). Additionally, it will automatically retract buffers when switching to new files, to model separate compilation properly. For details, see the Coq chapter in the Proof General manual. Addition by Hendrik Tews. *** Fixes for Coq 8.3 * Main Changes for Proof General 4.0 from 3.7.1 ** Install/support changes *** XEmacs is no longer supported; PG only works with GNU Emacs 23.1+ Older GNU Emacs versions after 22.3 may work but are unsupported. *** Primary distribution formats changed The RPM and zip file formats have been removed. We are very grateful to third-party packagers for Debian and Fedora for distributing packaged versions of PG. ** Generic changes *** Font-lock based Unicode Tokens mode replaces X-Symbol Unicode Tokens has been significantly improved since PG 3.7.1, and now works purely at a "presentation" level without changing buffer contents. See Tokens menu for many useful commands. *** Document-centred mechanisms added: - auto raise of prover output buffers can be disabled - output retained for script buffer popups - background colouring for locked region can be disabled - ...but "sticky" colouring for errors can be used - edit on processed region can automatically undo Depending on the prover language and interaction output, this may enable a useful "document centred" way of working, when output buffers can be ignored and hidden. Use "full annotation" to keep output when several steps are taken. Standard values for the options can be set in one go with: Quick Options -> Display -> Document Centred and the defaults set back with Quick Options -> Display -> Default. See the manual for more details. *** Automatic processing mode Quick Options -> Processing -> Send Automatically Sends commands to the prover when Emacs is idle for a while. This only sends commands when the last processing action has been an action moving forward through the buffer. Interrupt by making a keyboard/mouse action. See the manual for more details. *** Fast buffer processing option Quick Options -> Processing -> Fast Process Buffer This affects 'proof-process-buffer' (C-c C-b, toolbar down). It causes commands to be sent to the prover in a tight loop, without updating the display or processing other input. This speeds up processing dramatically on some Emacs implementations. To interrupt, use C-g, which reverts to normal processing mode. (To stop that, use C-c C-c as usual). *** Improved prevention of Undo in locked region With thanks to Erik Martin-Dorel and Stefan Monnier. Undo in read only region follows `proof-strict-read-only' and gives the user the chance to allow edits by retracting first. *** Proof General -> Options menu extended and rearranged - new menu for useful minor modes indicates modes that PG supports *** New query identifier info button and command (C-c C-i, C-M-mouse1) These are convenience commands for looking up identifiers in the running prover. *** New user configuration options (also on Proof General -> Options) proof-colour-locked (use background colour for checked text) proof-auto-raise-buffers (set to nil for manual window control) proof-full-decoration (add full decoration to input text) proof-sticky-errors (add highlighting for commands that caused error) proof-shell-quiet-errors (non-nil to disable beep on error; default=nil) proof-minibuffer-messages (non-nil to show prover messages; default=nil) *** Removed user configuration options proof-toolbar-use-button-enablers (now always used) proof-output-fontify-enable (now always enabled) *** "Movie" output: export an annotated buffer in XML Basic movie output for Proviola, see http://mws.cs.ru.nl/proviola ** Isabelle/Isar changes *** Support undo back into completed proofs (linear_undo). *** Electric terminator works without inserting terminator Hit ; to process the last command. Easier than C-RET. *** Line numbers reported during script management *** Sync problems with bad input prevented by command wrapping *** Isabelle Settings now organised in sub-menus ** Coq changes *** Only supports Coq 8.1+, support for earlier versions dropped. *** Holes mode can be turned on/off and has its own minor mode *** Some keyboard shortcuts are now available in goals buffer C-c C-a C- are now available in goal buffer. *** Experimental storing buffer To store the content of response or goals buffer in a dedicated persistent buffer (for later use), use Coq/Store response or Coq/Store goal. *** bug fixes, bugs - Three panes mode: "window would be too small" error fixed. - Indentation: several error fixed. If you want to indent tactics inside "Instance" or "Add Parametric Relation" etc, please put "Proof." before the tactics, there is no way for emacs to guess whether these commands initiate new goals or not. - coq prog args permanent settings is working again - when a proof is completed, the goals buffer is cleared again. ** Notable internal changes *** Altered prover configuration settings (internal) proof-terminal-char replaced by proof-terminal-string urgent message matching is now anchored; configurations for `proof-shell-clear-response-regexp', etc, must match strings which begin with `proof-shell-eager-annotation-start'. proof-shell-strip-output-markup: added for cut-and-paste proof-electric-terminator-noterminator: allows non-insert of terminator pg-insert-output-as-comment-fn: removed (use p-s-last-output) proof-shell-wakeup-char: removed (special chars deprecated) pg-use-specials-for-fontify: removed (ditto) proof-shell-prompt-pattern: removed (was only for shell UI) proof-shell-abort-goal-regexp: removed (ordinary response) proof-shell-error-or-interrupt-seen: removed, use p-s-last-output-kind proof-script-next-entity-regexps,next-entity-fn: removed (func-menu dead) proof-script-command-separator: removed (always a space) *** Simplified version of comint now used for proof shell (internal) To improve efficiency, a cut-down version of comint is now used. Editing, history and decoration in the shell (*coq*, *isabelle*, etc) are impoverished compared with PG 3.X. PG-4.5/COMPATIBILITY000066400000000000000000000022001426357011200136170ustar00rootroot00000000000000Compatibility of Proof General ============================== This version of Proof General has been tested with these Emacs versions on recent Linux systems: Emacs 25.1 -- minimal supported version Emacs 24.5, earlier -- previous versions, do NOT work and (main) prover versions: Coq 8.9, 8.10, 8.11, 8.12, 8.13 -- tested versions in PG's CI Coq 8.4, 8.5, 8.6, 8.7, 8.8 -- previous versions, should work See below for notes about other operating systems. In the major 4.0 release ** XEmacs compatibility was dropped ** Running on macOS ------------------- We recommend 24.5+ builds of GNU Emacs, which builds natively on macOS. Binaries are available at various websites (e.g., http://emacsformacosx.com), or you can build your own by compiling from the FSF CVS. See the Emacs Wiki at http://www.emacswiki.org/emacs/EmacsForMacOS for more. Note that macOS compatibility isn't thoroughly tested. If you discover problems, please send a report and/or fix to the PG tracker. Please add tips to the wiki page above. Running on Windows ------------------ Note that Windows compatibility isn't tested by the maintainers. PG-4.5/COPYING000066400000000000000000001045151426357011200127320ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: Copyright (C) This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . PG-4.5/FAQ.md000066400000000000000000000250531426357011200126270ustar00rootroot00000000000000FAQs for using/installing Proof General ======================================= With thanks to the anonymous authors of questions/answers below. For latest version, see https://github.com/ProofGeneral/PG/blob/master/FAQ.md Please also check the BUGS file. ----------------------------------------------------------------- Q. I use ProofGeneral with custom installations of Coq, depending on the project I am working on. How can I change `coq-prog-name` accordingly? A. The recommended way to set `coq-prog-name` is to create a file .dir-locals.el in the top-level folder of your Coq project (or if applicable, in the sub-folder containing the Coq source files) with content: ((coq-mode . ((coq-prog-name . ".../path/to/coqtop")))) Then restart Emacs (or just run: `M-x proof-shell-exit RET yes RET`, `M-x normal-mode RET` in the Coq buffer before restarting the Coq process) in order to take this change into account. ----------------------------------------------------------------- Q. The prover process produces some useful output I'd like to keep a note of, how do I do that? A. Some people cut and paste into comments in their source files. But you can easily make new files or temporary buffers in Emacs: * copy text from \*response* or \*goals* buffer * `C-x b RET` * Switch to correct mode, e.g.: `M-x isar-response-mode RET` * Paste text, the highlighting/sumbols should appear correctly. ----------------------------------------------------------------- Q. Proof General fails to load with an error message on start-up, containing text like this: Proof General was compiled for GNU Emacs 23.1 but is running on Emacs 22.3: please run "make clean; make" What's wrong? A. We distribute compiled .elcs for one version of Emacs, but other versions use different bytecode formats. You will have to delete the compiled files and (optionally) recompile for your preferred Emacs version. Using the Makefile: make clean # removes all .elc files. and then a command like this: make EMACS=emacs-22.3 (without the EMACS setting just uses 'emacs'). ----------------------------------------------------------------- Q. I have just installed Emacs, ProofGeneral and a proof assistant. It works but Tokens (e.g. \\<Longrightarrow>) are not being displayed as symbols. A. You need to enable Unicode Tokens by the menu item: Proof-General -> Options -> Unicode Tokens To enable it automatically every time you use Proof General, use Proof-General -> Options -> Save Options after doing this. Note that we don't do this by default, because from the system's perspective it is difficult to determine if this will succeed --- or just produce funny characters that confuse new users even more. If you are using Isabelle, the wrapper script will load Tokens from any location, and you can enable it by passing the option "-x true". ----------------------------------------------------------------- Q. With Unicode symbols enabled, the symbols look a mess, e.g. compressed and overlap one another. A. Unfortunately this is a bug in the display engine inside certain versions of Emacs, for example the default version of emacs, Emacs 23.3.1 on Ubuntu 11.10, suffers. The solution is to switch to another version (e.g. Emacs 23.2). You may be able to get better results with different fonts, even without upgrading Emacs. Proof General uses Deja Vu Sans Mono by default because this often works out-of-the-box. But STIX is better if you install it. See . On Ubuntu try: sudo apt-get install fonts-stix To change to STIX, either M-x customize face RET unicode-tokens-symbol-font-face RET and edit to set the family name to "STIXGeneral", or edit the line beginning `(defface unicode-tokens-symbol-font-face` in lib/unicode-tokens.el. ----------------------------------------------------------------- Q. Help, I'm stuck!! Emacs keeps telling me "Cannot switch buffers in a dedicated window" A. This can happen if you enabled "Use Three Panes" and then change the panes (window) layout manually, typically by deleting another window or frame so you only have a "dedicated" window on the display. Don't kill Emacs! There are many ways of getting out, e.g. * In single window mode, `C-c C-l` (proof-layout-windows) refreshes the display * In multiple window mode, if you have accidently deleted the main window, get a new one with `M-x new-frame RET` ----------------------------------------------------------------- Q. I have a problem installing/using Proof General, what can I do? A. Please check the documentation carefully, particularly the requirements for a full-featured and recent Emacs version, as mentioned in [INSTALL](INSTALL) (see "Dependency on Other Emacs Packages"). If you still cannot solve your problem, try to contact someone else who is using Proof General with a similar setup. The best way to do this may be through the user mailing list for your proof assistant. ----------------------------------------------------------------- Q. I'm using Proof General for prover X, then I load a file for prover Y. I get an error. Why? A. Unfortunately the architecture of Proof General is designed so that you can only use one prover at a time in the same Emacs session. If you want to run more than one prover at a time, you have to run more than one Emacs. ----------------------------------------------------------------- Q. I'm afraid I got stuck very early on. I sent the following line: by (swap_res_tac [psubsetI] 1; Notice that I forgot the right bracket. The line went pink, the buffer went read-only and nothing I tried would let me fix the error. A. The proof process is waiting for more input because of the missing parenthesis, but Proof General doesn't realise this and waits for a response. You should type something in the proof shell buffer (\*isabelle*), or interrupt the process with `C-c C-c` or the Stop button. ----------------------------------------------------------------- Q. How can I keep the Proof General option settings across sessions? A. For options set in the `Proof General -> Options` menu use the "Save Options" menu item (`Proof General -> Options -> Save Options`). For other options set via customize (`Proof General -> Advanced -> Customize`), use the customize buttons, or `M-x customize-save-customized`. ----------------------------------------------------------------- Q. The "Favourites" feature to insert/send fixed strings is great, but I'd like to define a command which takes arguments. A. You can do that in Elisp with a command like this: (proof-definvisible isar-theorem '(format "thm %s" (read-string "theorem: ")) [(control t)]) (NB: it binds the key `C-c C-a C-t`). See the documentation for `proof-definvisible` and `proof-defshortcut`. ----------------------------------------------------------------- Q. Why do I get a warning "Bad version of xml.el found, ..."? A. Your Emacs distribution includes a version of xml.el which has fundamental bugs. The patched version of xml.el, in lib/xml-fixed.el has been loaded instead. This works for Proof General because it fixes the basic bugs, but it may cause compatibility issues in other packages (e.g. it is quite different from the latest xml.el with GNU Emacs development versions). This message is probably nothing to worry about unless you are using the same Emacs session for other packages that heavily use xml.el (e.g. GNUS). ----------------------------------------------------------------- Q. Undo behaviour in Coq seems to stop working with very long sequences of commands. A. Coq has a limited history for Undo. Change Coq -> Settings -> Undo Depth to something higher. Default is 200 (100 outside PG). ----------------------------------------------------------------- Q. Emacs appears to hang when the prover process is started. A. One thing is to check the variable `comint-process-echoes` which might be non-nil for the \*coq* (or other prover) buffer. It should be nil. The default value of comint-process-echoes is nil. Move any modifications of this variable away from the top level (e.g., .emacs file, which affects the \*coq*-buffer), and down to the mode-hooks which require them (e.g. shell-mode-hook). The variable might also have been set by Customize, it can be reset with `M-x customize-variable RET comint-process-echoes RET`. A reason with older versions of Isabelle and Coq (before 2007) was the emergence of UTF-8 support in linuxes with Glibc 2.2 and later, enabled with UTF8 encoded output in your default locale. Proof General used on 8-bit characters which are UTF8 prefixes in the output of proof assistants. These prefix characters were not flushed to stdout individually. As a workaround we can disable interpretation of UTF8 in the C libraries. Doing this inside Proof General is unreliable; locale settings are set/inherited in strange ways. One solution is to run the Emacs process itself with an altered locale setting, e.g., $ LC_CTYPE=en_GB xemacs & (where $ is the shell prompt; this example is for my locale which by default is "en_GB.UTF-8": I see this by typing "locale" at the prompt). (This fix is attempted in the supplied "proofgeneral" script, as well as making an adjustment in Proof General when the string UTF appears in the current value of LC\_CTYPE. Alternatively you can set LC\_CTYPE inside a file ~/.i18n, which will be read the shell. Put a line such as "LC\_CTYPE=en_GB" into this file. However, this action will affect all applications. NB: a related issue is warnings from X-Symbol: "Emacs language environment and system locale specify different encoding, I'll assume `iso-8859-1`". This warning appears to be mostly harmless. Notice that the variable `buffer-file-coding-system` may determine the format that files are saved in. Another way to affect this which has been suggested is to add a line like this to the init.el file on XEmacs: (prefer-coding-system 'ctext) but I haven't tried this. The above fixes should not be necessary with most recent prover versions. Isabelle 2007 has a "Unicode-safe" interaction mode, enabled by default (to disable, customize `proof-shell-unicode`). This is also used by the Isabelle startup scripts. Coq 8.1 and later do not use non-ASCII characters in output. PG-4.5/INSTALL000066400000000000000000000126431426357011200127300ustar00rootroot00000000000000From GitHub =========== Download and install Proof General from GitHub: git clone https://github.com/ProofGeneral/PG ~/.emacs.d/lisp/PG make -C ~/.emacs.d/lisp/PG Then add the following to your .emacs: ;; Open .v files with Proof General's Coq mode (require 'proof-site "~/.emacs.d/lisp/PG/generic/proof-site") This should be enough. Instructions for previous releases are below. Short Instructions for installing Proof General (details below) =============================================================== Proof General runs on a variety of platforms and with a variety of Emacs versions; see COMPATIBILITY for further notes. To install, unpack the distribution somewhere. It will create a top-level directory containing Proof General, called Proof-General-. Put this line in your .emacs file: (load-file "/generic/proof-site.el") Where is replaced by the full path name to Proof-General-. If you prefer not to edit .emacs, you can use the script in bin/proofgeneral to launch Emacs with Proof General loaded. The command above will set the Emacs load path and add auto-loads for proof assistants, for example, visiting a file ending in .v will start Coq Proof General, and a file ending in .ec will start EasyCrypt Proof General. See the manual for a full list of file extensions and proof assistants, and the note below for how to disable those you don't need. In case of difficulty, please check the documentation in doc/, the notes below, the README file for each prover, and the file BUGS. Detailed installation Notes for Proof General ============================================= Supported Emacs Versions. ------------------------- Please see COMPATIBILITY. If you're not sure of your version of Emacs, inspect the variable `emacs-version' by doing: C-h C-v emacs-version RET Other *recent* versions of either Emacs may also work, but please do not send bug reports for any version of Emacs which is more than a year older than the most recent stable release of that Emacs, unless you are reasonably sure that the bug has something to do with Proof General rather than Emacs. Unfortunately, compatibility across different Emacs versions is very difficult to maintain as APIs change frequently and bugs come and go between Emacs releases. Byte Compilation. ----------------- Compilation of the Emacs lisp files improves efficiency but can sometimes cause compatibility problems. In particular, byte compiled files are generally not compatible between different Emacs versions. We distribute .elcs for GNU Emacs 23.1, so you will have to delete them and (optionally) recompile for GNU Emacs 22. Use 'make clean' to remove all .elc files. Use 'make compile' to recompile .elc files. Check that the Makefile sets EMACS to your Emacs executable, or run 'make EMACS=/path/to/your/emacs' Dependency on Other Emacs Packages ---------------------------------- Proof General relies on several other Emacs packages, which are probably already supplied with your version of Emacs. If not, you will need to find them. These are the packages that you need to use Proof General: ESSENTIAL: * cl * custom * font-lock OPTIONAL: * outline * imenu * speedbar Included scripts ---------------- There are some included scripts which have hardwired paths. To try to edit these automatically to point to the right place, run make scripts Site-wide Installation ---------------------- If you are installing Proof General site-wide, you can put the components in the standard directories of the filesystem if you prefer, providing the variables in proof-site.el are adjusted accordingly. Make sure that the generic and assistant-specific elisp files are kept in subdirectories of `proof-home-directory' so that the autoload directory calculations are correct. To save every user needing the line in their .emacs file, you can put that into a site-wide file like default.el, or using an automatically loaded file stored under site-start.d, if your distribution provides that. The provided Makefile will install everything in default locations: make install Will copy elisp, compiled elisp, documentation, and the "proofgeneral" shell script into perhaps sensible places. Try with "-n" or examine the Makefile carefully before use. Removing support for unwanted provers ------------------------------------- You cannot run more than one instance of Proof General at a time in the same Emacs process: e.g. if you're using Coq, you won't be able to run EasyCrypt scripts. If there are some assistants supported that you never want to use, you can remove them from the variable `proof-assistants' to prevent Proof General autoloading for files with particular extensions. This may be useful if you want to use other modes for those files, for example, you may want sml-mode for .ML files or Verilog mode for .v files. The easiest way to do this (and other customization of Proof General) is via the Customize mechanism, see the menu: Options -> Customize -> Emacs -> External -> Proof General or, after loading Proof General, in a proof script buffer Proof-General -> Customize You may need extra customization depending on the proof assistant (for example, the name of the proof assistant binary). See the menu Proof-General -> Customize -> and the manual for more details. -------------------------------------------------------------------------- $Id$ PG-4.5/Makefile000066400000000000000000000243421426357011200133360ustar00rootroot00000000000000## ## Makefile for Proof General. ## ## Author: David Aspinall ## ## make - do "compile" targets ## make compile - make .elc's ## make check - compile with warning flags enabled ## make scripts - edit paths to bash/perl/PGHOME in scripts ## make install - install into system directories ## make clean - return to clean source ## make tests - run the suite of regression tests ## ## Edit the EMACS setting below or call with an explicit one, like this: ## ## make EMACS=/Applications/Emacs.app/Contents/MacOS/Emacs ## ## $Id$ ## ########################################################################### # Set this according to your version of Emacs. # NB: this is also used to set default install path names below. EMACS=$(shell if [ -z "`which emacs`" ]; then echo "Emacs executable not found"; exit 1; else echo emacs; fi) # We default to /usr rather than /usr/local because installs of # desktop and doc files under /usr/local are unlikely to work with # rest of the system. If that's no good for you, edit the paths # individually before the install section. # NB: DEST_PREFIX is used for final destination prefix, in case we're # packaging into a build prefix rather than live root (e.g. in rpmbuild). # NBB: DESTDIR provides for staged installs, for instance when building # Debian packages, see http://www.gnu.org/prep/standards/html_node/DESTDIR.html PREFIX=$(DESTDIR)/usr DEST_PREFIX=$(DESTDIR)/usr # subdirectories for provers: to be compiled and installed PROVERS=coq easycrypt pghaskell pgocaml pgshell phox qrhl # generic lisp code: to be compiled and installed OTHER_ELISP=generic lib # additional lisp code: to be compiled but not installed ADDITIONAL_ELISP:=ci/compile-tests \ $(wildcard ci/compile-tests/[0-9][0-9][0-9]-*) \ ci/simple-tests # directories with lisp code to be installed ELISP_DIRS_INST=${PROVERS} ${OTHER_ELISP} # directories with lisp code to be compiled (superset of ELISP_DIRS_INST ELISP_DIRS_COMP=${ELISP_DIRS_INST} ${ADDITIONAL_ELISP} # to be installed ELISP_EXTRAS= # to be installed EXTRA_DIRS = images DOC_FILES=AUTHORS BUGS COMPATIBILITY CHANGES COPYING INSTALL README doc/*.pdf DOC_EXAMPLES=pgshell/*.pgsh phox/*.phx DOC_SUBDIRS=${DOC_EXAMPLES} */README* */CHANGES */BUGS BATCHEMACS=${EMACS} --batch --no-site-file -q # Scripts to edit paths to shells PERL_SCRIPTS = coq/coqtags # Scripts to install to bin directory BIN_SCRIPTS = coq/coqtags # Setting load path might be better in Elisp, but seems tricky to do # only during compilation. Another idea: put a function in proof-site # to output the compile-time load path and ELISP_DIRS_COMP so these are set # just in that one place. ERROR_ON_WARN = nil BYTECOMP = $(BATCHEMACS) -eval '(setq load-path (append (mapcar (lambda (d) (expand-file-name (symbol-name d))) (quote (\. ${ELISP_DIRS_COMP}))) load-path))' -eval '(progn (require (quote bytecomp)) (require (quote mouse)) (require (quote tool-bar)) (require (quote fontset)) (setq byte-compile-warnings (remove (quote noruntime) byte-compile-warning-types)) (setq byte-compile-error-on-warn $(ERROR_ON_WARN)))' -f batch-byte-compile EL=$(shell for f in $(ELISP_DIRS_COMP); do ls $$f/*.el; done) ELC=$(EL:.el=.elc) .SUFFIXES: .el .elc default: all FORCE: ## ## compile : byte compile all lisp files ## ## Compiling can show up errors in the code, but be wary of fixing obsoletion ## or argument call warnings unless they're valid for all supported Emacsen. ## ## The compile target displays errors as warnings only for compatibility ## with newer Emacs versions (see ticket #458). ## compile: $(EL) @echo "****************************************************************" @echo " Byte compiling... " @echo "****************************************************************" $(MAKE) elc @echo "****************************************************************" @echo " Finished." @echo "****************************************************************" ## ## check : make sure compilation doesn't emit warnings ## ## The check target aborts compilation on any byte-compiler warning. ## Compile with this target once before commiting your changes to ## the repository. ## FIXME: Compilation currently emits many warnings :-( ## check: $(EL) @echo "****************************************************************" @echo " Byte compiling... " @echo "****************************************************************" $(MAKE) ERROR_ON_WARN=t elc @echo "****************************************************************" @echo " Finished." @echo "****************************************************************" ## ## tests : run a selection of regression tests ## .PHONY: tests tests: ci/test.sh ## ## dist-tests : run all regression tests ## .PHONY: dist-tests dist-tests: tests check-doc-magic +$(MAKE) -C ci/simple-tests all +$(MAKE) -C ci/compile-tests test +$(MAKE) -C ci/test-indent ## ## check-doc-magic : check *.texi are up-to-date w.r.t. docstrings ## .PHONY: check-doc-magic check-doc-magic: +$(MAKE) -C doc magic git diff --exit-code -- doc ## ## Make an individual .elc. Building separately means we need to be ## careful to add proper requires in source files and prevent ## evaluating/optimising top-level forms too early. Using a separate ## emacs process for each file is slower but avoids any chance of ## accidently polluting the compilation environment, it also should ## work with make -j n. ## .el.elc: $(BYTECOMP) $*.el elc: $(ELC) ## ## Default targets ## all: compile ## ## Remove generated targets ## clean: cleanscripts rm -f $(ELC) .\#* */.\#* */.autotest.log */.profile.log (cd doc; $(MAKE) clean) distclean: clean ## ## Install files ## DESKTOP_PREFIX=${PREFIX} # Set Elisp directories according to paths used in Red Hat RPMs # (which may or may not be official Emacs policy). We generate # a pg-init.el file which loads the appropriate proof-site.el. ELISPP=share/${EMACS}/site-lisp/ProofGeneral ELISP_START=${PREFIX}/share/${EMACS}/site-lisp/site-start.d ELISP=${PREFIX}/${ELISPP} DEST_ELISP=${DEST_PREFIX}/${ELISPP} BINDIR=${PREFIX}/bin DESKTOP=${PREFIX}/share DOCDIR=${PREFIX}/share/doc/ProofGeneral MANDIR=${PREFIX}/share/man/man1 INFODIR=${PREFIX}/share/info install: install-desktop install-elisp install-bin install-init install-desktop: mkdir -p ${DESKTOP}/icons/hicolor/16x16/apps cp etc/desktop/icons/16x16/proofgeneral.png ${DESKTOP}/icons/hicolor/16x16/apps mkdir -p ${DESKTOP}/icons/hicolor/32x32/apps cp etc/desktop/icons/32x32/proofgeneral.png ${DESKTOP}/icons/hicolor/32x32/apps mkdir -p ${DESKTOP}/icons/hicolor/48x48/apps cp etc/desktop/icons/48x48/proofgeneral.png ${DESKTOP}/icons/hicolor/48x48/apps mkdir -p ${DESKTOP}/icons/hicolor/64x64/apps cp etc/desktop/icons/64x64/proofgeneral.png ${DESKTOP}/icons/hicolor/64x64/apps mkdir -p ${DESKTOP}/icons/hicolor/128x128/apps cp etc/desktop/icons/128x128/proofgeneral.png ${DESKTOP}/icons/hicolor/128x128/apps mkdir -p ${DESKTOP}/applications cp etc/desktop/proofgeneral.desktop ${DESKTOP}/applications mkdir -p ${DESKTOP}/mime-info cp etc/desktop/mime-info/proofgeneral.mime ${DESKTOP}/mime-info cp etc/desktop/mime-info/proofgeneral.keys ${DESKTOP}/mime-info # backwards compatibility with old linuxes mkdir -p ${DESKTOP}/application-registry cp etc/desktop/application-registry/proofgeneral.applications ${DESKTOP}/application-registry # NB: .el files are not strictly necessary, but we package/install them # for the time being to help with debugging, or for users to recompile. install-elisp: install-el install-elc # NB: "elisp" directory actually includes the extra subdirs in EXTRA_DIRS, # i.e. images. FIXME: we could put these elsewhere, but # then we would need to adjust paths in proof-site.el. # FIMXE 3: Michaël Cadilhac pointed out that 'cp -p' when used with # sudo to install will give users ownership instead of root. # Should use install program or fix ownerships afterwards here. install-el: mkdir -p ${ELISP} for f in ${ELISP_DIRS_INST} ${EXTRA_DIRS}; do mkdir -p ${ELISP}/$$f; done for f in ${ELISP_DIRS_INST}; do cp -pf $$f/*.el ${ELISP}/$$f; done for f in ${EXTRA_DIRS}; do cp -prf $$f/* ${ELISP}/$$f; done for f in ${ELISP_EXTRAS}; do cp -pf $$f ${ELISP}/$$f; done install-elc: compile mkdir -p ${ELISP} for f in ${ELISP_DIRS_INST} ${EXTRA_DIRS}; do mkdir -p ${ELISP}/$$f; done for f in ${ELISP_DIRS_INST}; do cp -pf $$f/*.elc ${ELISP}/$$f; done for f in ${ELISP_EXTRAS}; do cp -pf $$f ${ELISP}/$$f; done install-init: mkdir -p ${ELISP_START} echo ';;; pg-init.el --- setup for Proof General' > ${ELISP_START}/pg-init.el echo "(setq load-path (append load-path '(\"${DEST_ELISP}/generic\")))" >> ${ELISP_START}/pg-init.el echo "(require 'proof-site)" >> ${ELISP_START}/pg-init.el install-bin: scripts mkdir -p ${BINDIR} cp -pf ${BIN_SCRIPTS} ${BINDIR} install-doc: doc.info doc.pdf mkdir -p ${MANDIR} cp -pf doc/proofgeneral.1 ${MANDIR} mkdir -p ${INFODIR} cp -pf doc/*.info ${INFODIR} /sbin/install-info ${INFODIR}/ProofGeneral.info* ${INFODIR}/dir /sbin/install-info ${INFODIR}/PG-adapting.info* ${INFODIR}/dir mkdir -p ${DOCDIR} for f in ${DOC_FILES}; do cp -pf $$f ${DOCDIR}; done for f in ${DOC_EXAMPLES}; do mkdir -p ${DOCDIR}/`dirname $$f`; cp -pf $$f ${DOCDIR}/$$f; done doc: FORCE (cd doc; $(MAKE) EMACS=$(EMACS) $*) doc.%: FORCE (cd doc; $(MAKE) EMACS=$(EMACS) $*) ## ## scripts: try to patch bash and perl scripts with correct paths ## .PHONY: scripts scripts: bashscripts perlscripts .PHONY: bashscripts bashscripts: (bash="`which bash`"; \ if [ -z "$$bash" ]; then \ echo "Could not find bash - bash paths not checked" >&2; \ exit 0; \ fi) .PHONY: perlscripts perlscripts: (perl="`which perl`"; \ if [ -z "$$perl" ]; then \ echo "Could not find perl - perl paths not checked" >&2; \ exit 0; \ fi; \ for i in $(PERL_SCRIPTS); do \ sed -i.orig "s|^#.*!.*/bin/perl.*$$|#!$$perl|" $$i; \ done) # Set PGHOME path in scripts back to default location. .PHONY: cleanscripts cleanscripts: (for i in $(PERL_SCRIPTS); do \ if [ -f $$i.rm ] ; then \ rm -f $$i.rm; \ fi; \ if [ -f $$i.orig ] ; then \ mv -f $$i.orig $$i; \ fi; \ done) ## ## Include developer's makefile if it exists here. ## -include Makefile.devel PG-4.5/Makefile.devel000066400000000000000000000457341426357011200144440ustar00rootroot00000000000000## -*- makefile -*- ## ## Makefile for Proof General development. ## ## Author: David Aspinall ## ## Maintainer: Proof General maintainer ## ## Developer use only, not part of user distribution. ## ## make clean - remove intermediate files ## make distclean - remove all generated files ## ## make elisptidy - tidy up elisp files (run whitespace-cleanup) ## ## make ChangeLog - make ChangeLog from git log ## make tags - update TAGS file for Elisp sources ## make autoloads - update autoloads ## ## make tag - tag the sources with GIT_RELEASENAME ## make untag - remove tag GIT_RELEASENAME from the sources ## make dist - make a distribution from sources with above tag ## make rpm - make RPM packages based on etc/ProofGeneral.spec ## make pkg - make Emacs tar file packages (Tromey's package.el) ## ## make release - make tag, dist, and install it in RELEASEDIR. ## make releaseall - make release, local installation and rpmrelease. ## ## make distinstall - install distribution build by 'make dist' ## into DISTINSTALLDIR. ## ## make golive - publish previously built distribution ## ## make links - add some links which help testing web pages ## from the html directory. ## ## make releaseclean - clean up after 'make dist' 'make rpmrelease'. ## ## make testall.emacs23- run all autotest files in Emacs named "emacs23" ## ## ## Notes: ## ## Use 'make releaseclean' if giving up, to remove temp dirs. ## ## NB: no facility to edit html to make a full release in this Makefile. ## Edit download.html by hand, then run ## ## make releaseall VERSION=2.0 ## ## Or similar to make the required version. ## ## To customize the tags in case of a re-release with the same ## official version: ## ## make releaseall VERSION=2.0 FULLVERSION=2.0.1 ## ## ## $Id$ ## ########################################################################### ## TODO: could include prerel tag in web pages, and link using -latest ## sym links. Would avoid needing to edit html below. # Names and real mail addresses of developers # Arguments for rcs2log for ChangeLog target # NB: must use TAB as separator in list below. DEVELOPERS=\ -u "da David Aspinall da@inf.ed.ac.uk" \ -u "gkein Gerwin Klein gklein@in.tum.de" \ -u "sberghof Stefan Berghofer berghofe@in.tum.de" \ -u "markus Makarius makarius@sketis.net" \ -u "makarius Makarius makarius@sketis.net" \ -u "pier Pierre Courtieu courtieu@lri.fr" \ -u "crr Christophe Raffalli Christophe.Raffalli@univ-savoie.fr" \ -u "pxc Paul Callaghan P.C.Callaghan@durham.ac.uk" \ -u "patrl Patrick Loiseleur da+pg-patrl@inf.ed.ac.uk" \ -u "tms Thomas Kleymann da+pg-tms@inf.ed.ac.uk" \ -u "djs Dilip Sequiera da+pg-djs@inf.ed.ac.uk" \ -u "hhg Healfdene Goguen da+pg-hhg@inf.ed.ac.uk" \ -u "gklein Gerwin Klein gerwin.klein@nicta.com.au" \ -u "assia Assia Mahboubi assia.mahboubi@inria.fr" \ -u "monnier Stefan Monnier monnier@iro.umontreal.ca" \ -u "tews Hendrik Tews hendrik@askra.de" # PRERELEASE_PREFIX is used to match PRERELEASE_TAG in sed # line in tag target below, which edits $(DOWNLOADHTML) # The prereltag.txt is kept as a record in the distrib area # of the current pre-release version (currently not used explicitly # anywhere for web pages/whatever). PRERELEASE_PREFIX=4\.5-git PRERELEASE_TAG=4.5-git ### Formerly: PRERELEASE_TAG=4.4pre$(shell date "+%y%m%d") PREREL_TAG_FILE=prereltag.txt # Path to web pages in repository, used for automatically # updating with release information. HTMLDIR=../web DOWNLOADHTMLS=devel.html # This is used for full releases to control the tag name # and distribution name. No editing of html is done # when PRERELEASE_TAG != VERSION VERSION=$(PRERELEASE_TAG) # Date stamp used in file if we're making a full release. DATEMSG=$(shell if [ $(PRERELEASE_TAG) = $(VERSION) ]; then echo; else date "+ on %a %e %b %Y"; fi) # devel just means developer's package, with more files. # bit ambiguous: "development version" means latest version, # in development. # LATESTNAME is linked to the development version. # NAME is linked to the current release. NAME = ProofGeneral LATESTNAME = $(NAME)-latest VERSIONVARIABLE=proof-general-version VERSIONFILE=proof-site.el # Full version number defaults to ordinary version number. FULLVERSION=$(VERSION) # Name of tar file and RPM file. RELEASENAME = $(NAME)-$(VERSION) GIT_RELEASENAME ?= v$(FULLVERSION) # Where to release (i.e. copy) a new distribution to. # This may be the final directory (local) or temporary directory. # # was: RELEASEDIR = /home/proofgen/www RELEASEDIR = /tmp/proofgeneral-www # How to make the release "live". (Could be "true" to do nothing). GOLIVE=rsync -e ssh -auv $(RELEASEDIR)/* ssh.inf.ed.ac.uk:/group/project/proofgeneral/web/releases/ # Emacs for batch compiling BATCHEMACS=$(EMACS) -batch -q -no-site-file # Emacs for interactive use in testing EMACSFLAGS=-q -no-site-file # GNU version of tar, please TAR=tar # Files not to include the distribution area or tarball UNFINISHED_ELISP= ETC_FILES=etc/coq etc/demoisa etc/patches etc/*.txt NONDISTFILES=.gitignore */.gitignore Makefile.devel etc/trac etc/testsuite $(UNFINISHED_ELISP) $(ETC_FILES) DOCDISTFILES=ProofGeneral.info PG-adapting.info # Files not to include in the ordinary distribution tarball, but left # in the server's copy of the distribution. # NB: these are *patterns* to exclude rather than files! IGNOREDFILES=ProofGeneral*/TAGS ProofGeneral*/doc/ProofGeneral.pdf ProofGeneral*/doc/PG-adapting.pdf ProofGeneral*/doc/docstring-magic.el ProofGeneral*/etc/TESTS # Temporary directory to to build a distribution in DISTBUILDIR = /tmp/ProofGeneralRelease # Temporary dmg root for building Mac OS X disk image files. DMGTOPDIR=/tmp/$(NAME)-dmg RELEASENAMETGZ = $(RELEASENAME).tgz RELEASENAMERPM = $(RELEASENAME)-1.noarch.rpm RELEASENAMEDMG = $(RELEASENAME).dmg # Where to install a distribution DISTINSTALLDIR=/usr/local/share/elisp/proofgeneral SUBDIRS=$(ELISP_DIRS_COMP) etc doc images PWD=$(shell pwd) FORCE: # Targets to pre-compile for distribution # Warning: elisp files are incompatible across emacs versions! alldist: distcompile distdocs ############################################################ # # Make tags file # TAGS_EXTRAS= ETAGS=etags tags: $(EL) $(TAGS_EXTRAS) $(ETAGS) $(EL) $(TAGS_EXTRAS) doc/ProofGeneral.texi doc/PG-adapting.texi > TAGS ############################################################ # # Run tests for a particular prover and particular Emacs # run.%: $(EMACS) $(EMACSFLAGS) -l generic/proof-site.el -eval '(proof-visit-example-file "$*")' test.%: if [ -f "$*/$*-autotest.el" ]; then if $(EMACS) $(EMACSFLAGS) -l generic/proof-site.el $*/$*-autotest.el -f eval-current-buffer; then echo "Autotests for $* run successfully on `date`"; else cat $*/.autotest.log; echo "Autotests for $* ran with failures on `date`"; exit 1; fi; fi profile.%: if [ -f "$*/$*-profiling.el" ]; then if $(EMACS) $(EMACSFLAGS) -l generic/proof-site.el $*/$*-profiling.el -f eval-current-buffer; then echo "Profiling for $* run successfully on `date`"; else echo "Profiling for $* ran with failures on `date`"; exit 1; fi; cat $*/.profile.log; fi testall.%: for prover in ${PROVERS}; do $(MAKE) test.$$prover EMACS=$*; done ############################################################ # # Add recent messages to ChangeLog. # # FIXME: this duplicates entries made on the same day: we could do # with a way of cleaning the last day from the ChangeLog. # ChangeLog: FORCE git log --pretty="format:%ad %s" --date=short > ChangeLog ############################################################ # # Clean up intermediate files # devclean: FORCE @echo "***** CLEANING UP INTERMEDIATE FILES ****" rm -f doc/ProofGeneralPortrait.eps.gz rm -f $(HTMLDIR)/ProofGeneral ############################################################ # # Clean up intermediate files, all generated files # and Emacs backups. # distclean: devclean clean @echo "***** CLEANING UP ALL JUNK FILES ****" find . \( -name '*~' -o -name '#*#' -o -name '\.\#*' -o -name '\.*\.log' \) -print | xargs rm -f (cd doc; $(MAKE) distclean) ############################################################ # # autoloads in generic/ # autoloads: $(EL) @echo "***** MAKING AUTOGENERATED AUTOLOADS ****" $(BATCHEMACS) -eval '(setq autoload-package-name "proof" generated-autoload-file "$(PWD)/generic/proof-autoloads.el")' -f batch-update-autoloads generic/ lib/ coq/ qrhl/ ############################################################ # # Elisp tidy # tidy: $(EL) @echo "***** CLEANUP ELISP FILES ****" for f in $(EL); do echo "Cleaning $$f"; $(BATCHEMACS) -eval "(progn (find-file \"$$f\") (whitespace-cleanup) (save-buffer))"; done ############################################################ # # Documentation # distdocs: FORCE @echo "***** MAKING DISTRIBUTION DOCS ****" (cd doc; ln -s $(HTMLDIR)/ProofGeneralPortrait.eps.gz .; $(MAKE) dist) ############################################################ # # Compilation # distcompile: FORCE @echo "***** MAKING ELC FILES ****" $(MAKE) compile ############################################################ ## ## tag: tag the sources of working directory with GIT_RELEASENAME, ## set version stamp in proof-site.el and ProofGeneral.spec ## to VERSION, and edit $(DOWNLOADHTMLS) ## if VERSION matches PRERELEASE_TAG. ## tag: @echo "*************************************************" @echo " Tagging sources... " @echo "*************************************************" if [ -z "$(NOCVS)" ]; then git fetch origin && git log --exit-code master...origin/master || exit 1; fi # Update version in proof-site.el (cd generic; mv $(VERSIONFILE) $(VERSIONFILE).old; sed -e 's/defconst $(VERSIONVARIABLE) \".*\"/defconst $(VERSIONVARIABLE) \"Proof General Version $(FULLVERSION).\"/g' $(VERSIONFILE).old > $(VERSIONFILE); rm $(VERSIONFILE).old) # Tag ProofGeneral.spec (cd etc; mv ProofGeneral.spec ProofGeneral.spec.old; sed -e 's/Version:.*$$/Version: $(VERSION)/g' ProofGeneral.spec.old > ProofGeneral.spec; rm ProofGeneral.spec.old) # Edit $(DOWNLOADHTMLS) only for prereleases. # Careful: the sed command below relies on previous value of PRERELEASE_TAG. # if [ $(PRERELEASE_TAG) = $(VERSION) ]; then \ # (cd $(HTMLDIR); \ # for f in $(DOWNLOADHTMLS); do \ # mv $$f $$f.old; \ # sed -e 's|ProofGeneral\([emacselc-]*\)-$(PRERELEASE_PREFIX)......|ProofGeneral\1-$(PRERELEASE_TAG)|g' $$f.old > $$f; \ # rm $$f.old; \ # done) \ # fi if [ -z "$(NOCVS)" ]; then git add generic/$(VERSIONFILE) etc/ProofGeneral.spec && git commit -m"Set version tag for new release." ; fi if [ -z "$(NOCVS)" ]; then git tag -a "$(GIT_RELEASENAME)"; fi ############################################################ ## ## untag: Remove the GIT_RELEASENAME tag from the sources. ## untag: git tag -d "$(GIT_RELEASENAME)" ############################################################ ## ## dist: make a distribution in DISTBUILDIR from CVS sources ## Builds for user-distribution, from sources tagged ## with GIT_RELEASENAME. ## Moves html files to parent directory, removes ## non-distributed files. ## cvsexport: @echo "*************************************************" @echo " Cleaning build directory and running cvs export..." @echo "*************************************************" rm -rf $(DISTBUILDIR) mkdir -p $(DISTBUILDIR) if [ -z "$(NOCVS)" ]; then \ git archive --format=tar --prefix=$(RELEASENAME)/ $(GIT_RELEASENAME) | (cd "$(DISTBUILDIR)" && tar xf -) \ else \ mkdir -p $(DISTBUILDIR)/$(RELEASENAME); \ cp -pr . $(DISTBUILDIR)/$(RELEASENAME); \ fi dist: cvsexport @echo "*************************************************" @echo " Running 'make alldist' for new release .." @echo "*************************************************" (cd $(DISTBUILDIR)/$(RELEASENAME); $(MAKE) alldist) @echo "*************************************************" @echo " Cleaning and copying doc files .." @echo "*************************************************" (cd $(DISTBUILDIR)/$(RELEASENAME)/doc; cp -pr $(DOCDISTFILES) $(DISTBUILDIR)) (cd $(DISTBUILDIR)/$(RELEASENAME)/doc; $(MAKE) clean) (cd $(DISTBUILDIR); cp -pr $(DOCDISTFILES) $(RELEASENAME)/doc) @echo "*************************************************" @echo " Cleaning non-distributed files .." @echo "*************************************************" (cd $(DISTBUILDIR)/$(RELEASENAME); rm -rf $(NONDISTFILES)) @echo "*************************************************" @echo " Making compressed tar file..." @echo "*************************************************" -(cd $(DISTBUILDIR); ls $(IGNOREDFILES) > ignoredfiles; echo ignoredfiles >> ignoredfiles) # link the long name to short name for convenience of user (cd $(DISTBUILDIR); ln -sf $(RELEASENAME) $(NAME)) $(TAR) cvzf $(DISTBUILDIR)/$(RELEASENAMETGZ) --directory $(DISTBUILDIR) --exclude-from $(DISTBUILDIR)/ignoredfiles $(RELEASENAME) $(NAME) # remove temporary files made for tar/zip only (cd $(DISTBUILDIR); rm -f ignoredfiles $(NAME)) @echo "*************************************************" @echo " Finished making dist." @echo "*************************************************" ############################################################ ## ## release: ## tag the sources, and make a distribution. ## Then install the distribution in RELEASEDIR ## WARNING: RELEASEDIR is not cleaned except to remove ## links, but files there with same names will be overwritten. ## release: check distclean tag dist @echo "*************************************************" @echo " Making release (installing tarball distributions)." @echo "*************************************************" mkdir -p $(RELEASEDIR) (cd $(DISTBUILDIR); rm -f $(NAME)) (cd $(RELEASEDIR); rm -rf $(RELEASENAME)) cp -pfR $(DISTBUILDIR)/* $(RELEASEDIR) (cd $(RELEASEDIR); rm -f $(LATESTNAME); ln -s $(RELEASENAME) $(LATESTNAME)) (cd $(RELEASEDIR); ln -sf $(RELEASENAMETGZ) $(LATESTNAME).tgz) (cd $(RELEASEDIR); echo $(PRERELEASE_TAG) > $(PREREL_TAG_FILE)) @echo "*************************************************" @echo " Finished installing dist." @echo "*************************************************" ############################################################ ## ## rpm: ## Build an RPM binary package from the recently made distribution ## using the tarball. (Any user could do this) ## ## # Temporary RPM topdir for building packages as non-root user. RPMTOPDIR=/tmp/$(NAME)-rpm RPMBUILD=rpmbuild --define '_topdir $(RPMTOPDIR)' rpm: rm -rf $(RPMTOPDIR) mkdir -p $(RPMTOPDIR)/RPMS mkdir -p $(RPMTOPDIR)/SPECS mkdir -p $(RPMTOPDIR)/SOURCES mkdir -p $(RPMTOPDIR)/BUILD $(RPMBUILD) -tb $(DISTBUILDIR)/$(RELEASENAMETGZ) ############################################################ ## ## pkg: ## Build an Emacs .tar file package ## PKGMOVES=doc/dir doc/ProofGeneral.info doc/PG-adapting.info PKGDELETES=obsolete etc doc # Emacs package version is fussy about non-numbers in version, have to make version # from date. PKG_VERSION=$(shell echo $(FULLVERSION) | sed 's/$(PRERELEASE_PREFIX)/20/g' | sed 's/RC/\.0/g') PKG_RELEASENAME=$(NAME)-$(PKG_VERSION) pkg: cvsexport (cd $(DISTBUILDIR); if [ "$(RELEASENAME)" != "$(PKG_RELEASENAME)" ]; then mv $(RELEASENAME) $(PKG_RELEASENAME); fi) (cd $(DISTBUILDIR)/$(PKG_RELEASENAME)/doc; make info) (cd $(DISTBUILDIR)/$(PKG_RELEASENAME); mv $(PKGMOVES) .; rm -rf $(PKGDELETES)) (cd $(DISTBUILDIR)/$(PKG_RELEASENAME); echo '(define-package "ProofGeneral" "$(PKG_VERSION)" "Proof General theorem prover interface")' > ProofGeneral-pkg.el) (cd $(DISTBUILDIR); tar -cf $(PKG_RELEASENAME).tar $(PKG_RELEASENAME)) ############################################################ ## ## rpmrelease: ## Build and install RPM package into RELEASEDIR. ## rpmrelease: rpm cp -pf $(RPMTOPDIR)/RPMS/noarch/* $(RELEASEDIR) ############################################################ ## ## dmg: [experimental] ## Build (on Linux) a Mac OS X dmg disk image file ## This requires sudo powers for mounting, and ## (on Ubuntu), packages hfsplus and hfsprogs ## ## Warning: the following line was removed below so Contents/MacOS'll be empty: ## mv $(NAME)/bin/proofgeneral Contents/MacOS; DMGBUILD=$(DISTBUILDIR)/dmg dmg: rm -rf $(DMGBUILD) mkdir -p $(DMGBUILD) dd if=/dev/zero of=$(DISTBUILDIR)/$(RELEASENAMEDMG) bs=1 count=0 seek=16M /sbin/mkfs.hfsplus -v $(RELEASENAME) -s $(DISTBUILDIR)/$(RELEASENAMEDMG) (cd $(DMGBUILD); mkdir dmgfs; \ sudo mount -t hfsplus -o loop,user $(DISTBUILDIR)/$(RELEASENAMEDMG) dmgfs; \ sudo chown $(LOGNAME) dmgfs; \ $(TAR) -xpzf $(DISTBUILDIR)/$(RELEASENAMETGZ); \ mkdir -p Contents/Resources; \ mkdir -p Contents/MacOS; \ mv $(NAME)/* Contents/Resources; \ rm -rf $(NAME) $(RELEASENAME); \ mkdir $(NAME).app; \ mv Contents $(NAME).app;\ sudo umount dmgfs) # on mac: # hdiutil create -srcfolder $(DISTBUILDIR) ############################################################ ## ## releaseclean: ## Clean up temporary directories after building dist/release. ## releaseclean: rm -rf $(DISTBUILDIR) $(RPMTOPDIR) ############################################################ ## ## fakereleaseall: ## Do everything, but don't access CVS. Just for ## testing on non-live system, really. ## FIXME: does this still make sense now that git is used version control? ## fakereleaseall: $(MAKE) -f Makefile.devel release releaseclean NOCVS="no" ############################################################ ## ## releaseall: ## Do everything! (EXCEPT: ChangeLog.gz update) ## releaseall: release releaseclean golive ############################################################ ## ## golive: ## Execute golive command. ## golive: $(GOLIVE) cd $(HTMLDIR); for f in $(DOWNLOADHTMLS); do $(MAKE) pub.$$f; done; rm -rf $(RELEASEDIR) ############################################################ ## ## releasefinal: ## Do everything for a final release based on a pre-release. ## Except editing download file. ## releasefinal: release releaseclean # Link the latest version # 31.5.13: remove this link from tar file, it is unconventional # (cd $(DISTBUILDIR); rm -f $(NAME); ln -sf $(RELEASENAME) $(NAME)) ############################################################ ## ## distinstall: ## Do everything for a local release. ## distall: distclean tag dist distinstall releaseclean ############################################################ # # distinstall: # Install distribution from $(DISTBUILDIR) into DISTINSTALLDIR # Clean out DISTINSTALLDIR first. ### NB! Simple install, no attempt to put info files, etc, in # special places. # distinstall: rm -rf $(DISTINSTALLDIR)/$(NAME) mkdir -p $(DISTINSTALLDIR) (cd $(DISTINSTALLDIR); \ $(TAR) -xpzf $(DISTBUILDIR)/$(RELEASENAMETGZ); \ mv $(RELEASENAME) $(NAME)) ############################################################ # # links: # # Make some handy links for developers. # links: ln -sf $(HTMLDIR)/ProofGeneralPortrait.eps.gz doc ln -sf ../../ProofGeneral $(HTMLDIR) ################################################################# ## ## Reporting Makefile settings. ## ## Useful for debugging Makefile show.%: @echo $($*) PG-4.5/README.md000066400000000000000000000131411426357011200131500ustar00rootroot00000000000000# Proof General — Organize your proofs! [![CI](https://github.com/ProofGeneral/PG/workflows/CI/badge.svg?branch=master)](https://github.com/ProofGeneral/PG/actions?query=workflow%3ACI) [![MELPA](https://melpa.org/packages/proof-general-badge.svg)](https://melpa.org/#/proof-general) ## Overview Proof General is a generic Emacs interface for proof assistants. The aim of the Proof General project is to provide a powerful, generic environment for using interactive proof assistants. This is version 4.5 of Proof General. ## About Proof General branches Two editions of Proof General are currently available: * the (standard) REPL-based, stable version of Proof General, gathered in the [master](https://github.com/ProofGeneral/PG/tree/master) branch; * the (unmaintained) Coq-specific, experimental version of Proof General, supporting asynchronous proof processing, gathered in the [async](https://github.com/ProofGeneral/PG/tree/async) branch. ## Installing Proof General Proof General requires GNU Emacs `25.2` or later. The current policy aims at supporting multiple Emacs versions, including those available in [Debian Stable](https://packages.debian.org/stable/emacs) as well as in [Ubuntu LTS](https://packages.ubuntu.com/emacs) distributions until their [End-Of-Support](https://wiki.ubuntu.com/Releases). ### Using MELPA (recommended procedure) [MELPA](https://melpa.org/) is a repository of Emacs packages. Skip this step if you already use MELPA. Otherwise, add the following to your `.emacs` and restart Emacs: ```elisp (require 'package) ;; (setq gnutls-algorithm-priority "NORMAL:-VERS-TLS1.3") ; see remark below (add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/") t) (package-initialize) ``` **Remark:** If you have Emacs 26.1 (which is precisely [the packaged version in Debian 10](https://packages.debian.org/emacs)), you may get the error message `Failed to download 'melpa' archive` during the package refresh step. This is a known bug ([debbug #34341](https://debbugs.gnu.org/cgi/bugreport.cgi?bug=34341)) which has been fixed in Emacs 26.3 and 27.1, while a simple workaround consists in uncommenting the line `(setq gnutls-algorithm-priority "NORMAL:-VERS-TLS1.3")` above in your `.emacs`. **Note:** If you switch to MELPA from a previously manually-installed Proof General, make sure you removed the old versions of Proof General from your Emacs context (by removing from your `.emacs` the line loading `PG/generic/proof-site`, or by uninstalling the proofgeneral package provided by your OS package manager). Then, run M-x package-refresh-contents RET followed by M-x package-install RET proof-general RET to install and byte-compile `proof-general`. You can now open a Coq file (`.v`), an EasyCrypt file (`.ec`), or a PhoX file (`.phx`) to automatically load the corresponding major mode. ### Using Git (manual compilation procedure) Remove old versions of Proof General, clone the PG repo from GitHub and byte-compile the sources: ```sh git clone https://github.com/ProofGeneral/PG ~/.emacs.d/lisp/PG cd ~/.emacs.d/lisp/PG make ``` Then add the following to your `.emacs`: ```elisp ;; Open .v files with Proof General's Coq mode (load "~/.emacs.d/lisp/PG/generic/proof-site") ``` If Proof General complains about a version mismatch, make sure that the shell's `emacs` is indeed your usual Emacs. If not, run the Makefile again with an explicit path to Emacs. On macOS in particular you'll probably need something like ```sh make clean; make EMACS=/Applications/Emacs.app/Contents/MacOS/Emacs ``` ## Keeping Proof General up-to-date ### Using MELPA As explained in the [MELPA documentation](https://melpa.org/#/getting-started), updating all MELPA packages in one go is as easy as typing M-x package-list-packages RET then r (**r**efresh the package list), U (mark **U**pgradable packages), and x (e**x**ecute the installs and deletions). ### Using Git Assuming you have cloned the repo in `~/.emacs.d/lisp/PG`, you would have to run: ```sh cd ~/.emacs.d/lisp/PG make clean git pull make ``` ## More info See: * [INSTALL](INSTALL) for installation details * [COPYING](COPYING) for license details * [COMPATIBILITY](COMPATIBILITY) for version compatibility information * [FAQ.md](FAQ.md) for frequently asked questions * [coq/README](coq/README) for additional notes specific to the Coq prover Links: * [https://proofgeneral.github.io/doc](https://proofgeneral.github.io/doc) for online documentation of Proof General * [https://coq.zulipchat.com](https://coq.zulipchat.com/) for chatting with PG maintainers and developers on the Zulip chat of Coq (in streams [Proof General devs](https://coq.zulipchat.com/#narrow/stream/304020-Proof-General.20devs) and [Proof General users](https://coq.zulipchat.com/#narrow/stream/304019-Proof-General.20users)) * [https://coq.gitlab.io/zulip-archive](https://coq.gitlab.io/zulip-archive) for the corresponding public Zulip archive (read-only, no authentication required) Supported proof assistants: * [Coq](https://coq.inria.fr/) * [EasyCrypt](https://www.easycrypt.info/) * [PhoX](https://raffalli.eu/phox/) * [qrhl-tool](https://github.com/dominique-unruh/qrhl-tool/#readme) Proof General used to support other proof assistants, but those instances are no longer maintained nor available in the MELPA package: * Experimental support of: Shell * Obsolete instances: Demoisa * Removed instances: Twelf, CCC, Hol-Light, ACL2, Plastic, Lambda-Clam, HOL98, [LEGO](http://www.dcs.ed.ac.uk/home/lego), [Isabelle](https://www.cl.cam.ac.uk/research/hvg/Isabelle/) A few example proofs are included in each prover subdirectory. PG-4.5/ci/000077500000000000000000000000001426357011200122645ustar00rootroot00000000000000PG-4.5/ci/compile-tests/000077500000000000000000000000001426357011200150545ustar00rootroot00000000000000PG-4.5/ci/compile-tests/001-mini-project/000077500000000000000000000000001426357011200177525ustar00rootroot00000000000000PG-4.5/ci/compile-tests/001-mini-project/Makefile000066400000000000000000000006341426357011200214150ustar00rootroot00000000000000# This file is part of Proof General. # # © Copyright 2020 Hendrik Tews # # Authors: Hendrik Tews # Maintainer: Hendrik Tews # # SPDX-License-Identifier: GPL-3.0-or-later .PHONY: test test: $(MAKE) clean emacs -batch -l ../../../generic/proof-site.el -l ../cct-lib.el \ -l runtest.el -f ert-run-tests-batch-and-exit .PHONY: clean clean: rm -f *.vo *.glob *.vio *.vos *.vok .*.aux PG-4.5/ci/compile-tests/001-mini-project/a.v000066400000000000000000000010331426357011200203560ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2020 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* This is line 21 *) Require b. Require c. (* This is line 24 *) PG-4.5/ci/compile-tests/001-mini-project/b.v000066400000000000000000000005541426357011200203660ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2020 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) Require d e. PG-4.5/ci/compile-tests/001-mini-project/c.v000066400000000000000000000005541426357011200203670ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2020 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) Require e f. PG-4.5/ci/compile-tests/001-mini-project/d.v000066400000000000000000000005701426357011200203660ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2020 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) Definition d : nat := 0. PG-4.5/ci/compile-tests/001-mini-project/e.v000066400000000000000000000005701426357011200203670ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2020 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) Definition e : nat := 1. PG-4.5/ci/compile-tests/001-mini-project/f.v000066400000000000000000000005701426357011200203700ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2020 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) Definition f : nat := 2. PG-4.5/ci/compile-tests/001-mini-project/runtest.el000066400000000000000000000022331426357011200220000ustar00rootroot00000000000000;; This file is part of Proof General. -*- lexical-binding: t; -*- ;; ;; © Copyright 2020 Hendrik Tews ;; ;; Authors: Hendrik Tews ;; Maintainer: Hendrik Tews ;; ;; SPDX-License-Identifier: GPL-3.0-or-later ;;; Commentary: ;; ;; Coq Compile Tests (cct) -- ;; ert tests for parallel background compilation for Coq ;; ;; Test that parallel background compilation works for a simple ;; project and that the right files are recorded for unlocking at the ;; right places. ;; ;; The following graph shows the file dependencies in this test: ;; ;; a ;; / \ ;; b c ;; / \ / \ ;; d e f ;; require cct-lib for the elisp compilation, otherwise this is present already (require 'cct-lib "ci/compile-tests/cct-lib") ;;; set configuration (cct-configure-proof-general) ;;; Define the test (ert-deftest cct-mini-project () "Test successful background compilation and ancestor recording." (find-file "a.v") ; (setq coq--debug-auto-compilation t) (cct-process-to-line 25) (cct-check-locked 24 'locked) (cct-locked-ancestors 22 '("./b.v" "./d.v" "./e.v")) (cct-locked-ancestors 23 '("./c.v" "./f.v"))) PG-4.5/ci/compile-tests/002-require-no-dependencies/000077500000000000000000000000001426357011200220655ustar00rootroot00000000000000PG-4.5/ci/compile-tests/002-require-no-dependencies/Makefile000066400000000000000000000006341426357011200235300ustar00rootroot00000000000000# This file is part of Proof General. # # © Copyright 2020 Hendrik Tews # # Authors: Hendrik Tews # Maintainer: Hendrik Tews # # SPDX-License-Identifier: GPL-3.0-or-later .PHONY: test test: $(MAKE) clean emacs -batch -l ../../../generic/proof-site.el -l ../cct-lib.el \ -l runtest.el -f ert-run-tests-batch-and-exit .PHONY: clean clean: rm -f *.vo *.glob *.vio *.vos *.vok .*.aux PG-4.5/ci/compile-tests/002-require-no-dependencies/a.v000066400000000000000000000010651426357011200224760ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2020 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* This is line 21 *) Require Coq.Bool.Bool. Definition a : nat := 0. (* This is line 24 *) PG-4.5/ci/compile-tests/002-require-no-dependencies/b.v000066400000000000000000000010471426357011200224770ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2020 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* This is line 21 *) Require Coq.Bool.Bool. Require c. (* This is line 24 *) PG-4.5/ci/compile-tests/002-require-no-dependencies/c.v000066400000000000000000000005701426357011200225000ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2020 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) Definition c : nat := 0. PG-4.5/ci/compile-tests/002-require-no-dependencies/runtest.el000066400000000000000000000024101426357011200241100ustar00rootroot00000000000000;; This file is part of Proof General. -*- lexical-binding: t; -*- ;; ;; © Copyright 2020 Hendrik Tews ;; ;; Authors: Hendrik Tews ;; Maintainer: Hendrik Tews ;; ;; SPDX-License-Identifier: GPL-3.0-or-later ;;; Commentary: ;; ;; Coq Compile Tests (cct) -- ;; ert tests for parallel background compilation for Coq ;; ;; Test parallel background compilation when one require command does ;; not produce any dependencies. ;; ;; The following graph shows the file dependencies in this test: ;; ;; a b ;; | ;; c ;; require cct-lib for the elisp compilation, otherwise this is present already (require 'cct-lib "ci/compile-tests/cct-lib") ;;; set configuration (cct-configure-proof-general) ;;; Define the tests (ert-deftest cct-one-require-with-no-dependencies () "Test background compilation with an require with no dependencies." (find-file "a.v") (cct-process-to-line 25) (cct-check-locked 24 'locked) (cct-locked-ancestors 22 '())) (ert-deftest cct-two-requires-first-no-dependencies () "Test background compilation with an require with no dependencies." (find-file "b.v") (cct-process-to-line 25) (cct-check-locked 24 'locked) (cct-locked-ancestors 22 '()) (cct-locked-ancestors 23 '("./c.v"))) PG-4.5/ci/compile-tests/003-require-error/000077500000000000000000000000001426357011200201575ustar00rootroot00000000000000PG-4.5/ci/compile-tests/003-require-error/Makefile000066400000000000000000000006341426357011200216220ustar00rootroot00000000000000# This file is part of Proof General. # # © Copyright 2020 Hendrik Tews # # Authors: Hendrik Tews # Maintainer: Hendrik Tews # # SPDX-License-Identifier: GPL-3.0-or-later .PHONY: test test: $(MAKE) clean emacs -batch -l ../../../generic/proof-site.el -l ../cct-lib.el \ -l runtest.el -f ert-run-tests-batch-and-exit .PHONY: clean clean: rm -f *.vo *.glob *.vio *.vos *.vok .*.aux PG-4.5/ci/compile-tests/003-require-error/a.v000066400000000000000000000010501426357011200205620ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2020 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* This is line 21 *) Require b. Require X c. Require c. (* This is line 25 *) PG-4.5/ci/compile-tests/003-require-error/b.v000066400000000000000000000005701426357011200205710ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2020 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) Definition b : nat := 2. PG-4.5/ci/compile-tests/003-require-error/c.v000066400000000000000000000005701426357011200205720ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2020 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) Definition c : nat := 3. PG-4.5/ci/compile-tests/003-require-error/runtest.el000066400000000000000000000022711426357011200222070ustar00rootroot00000000000000;; This file is part of Proof General. -*- lexical-binding: t; -*- ;; ;; © Copyright 2020 Hendrik Tews ;; ;; Authors: Hendrik Tews ;; Maintainer: Hendrik Tews ;; ;; SPDX-License-Identifier: GPL-3.0-or-later ;;; Commentary: ;; ;; Coq Compile Tests (cct) -- ;; ert tests for parallel background compilation for Coq ;; ;; Test parallel background compilation when coqdep fails on a require ;; command. ;; ;; The following graph shows the file dependencies in this test, where ;; X does not exist: ;; ;; a1 a2 a3 ;; | / \ / ;; b X c ;; ;; and where a1, a2 and a3 are the 3 require commands in file a.v ;; require cct-lib for the elisp compilation, otherwise this is present already (require 'cct-lib "ci/compile-tests/cct-lib") ;;; set configuration (cct-configure-proof-general) ;;; Define the tests (ert-deftest cct-require-error () "Test background compilation with an require that yields a coqdep error." (let ((test-start-time (current-time))) (find-file "a.v") (cct-process-to-line 26) (cct-check-locked 22 'locked) (cct-check-locked 23 'unlocked) (cct-file-newer "b.vo" test-start-time) (cct-file-newer "c.vo" test-start-time))) PG-4.5/ci/compile-tests/004-dependency-cycle/000077500000000000000000000000001426357011200205705ustar00rootroot00000000000000PG-4.5/ci/compile-tests/004-dependency-cycle/Makefile000066400000000000000000000006341426357011200222330ustar00rootroot00000000000000# This file is part of Proof General. # # © Copyright 2020 Hendrik Tews # # Authors: Hendrik Tews # Maintainer: Hendrik Tews # # SPDX-License-Identifier: GPL-3.0-or-later .PHONY: test test: $(MAKE) clean emacs -batch -l ../../../generic/proof-site.el -l ../cct-lib.el \ -l runtest.el -f ert-run-tests-batch-and-exit .PHONY: clean clean: rm -f *.vo *.glob *.vio *.vos *.vok .*.aux PG-4.5/ci/compile-tests/004-dependency-cycle/a.v000066400000000000000000000010331426357011200211740ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2020 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* This is line 21 *) Require b. Require f. (* This is line 24 *) PG-4.5/ci/compile-tests/004-dependency-cycle/b.v000066400000000000000000000005521426357011200212020ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2020 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) Require c. PG-4.5/ci/compile-tests/004-dependency-cycle/c.v000066400000000000000000000005521426357011200212030ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2020 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) Require d. PG-4.5/ci/compile-tests/004-dependency-cycle/d.v000066400000000000000000000005521426357011200212040ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2020 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) Require e. PG-4.5/ci/compile-tests/004-dependency-cycle/e.v000066400000000000000000000005521426357011200212050ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2020 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) Require b. PG-4.5/ci/compile-tests/004-dependency-cycle/f.v000066400000000000000000000005701426357011200212060ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2020 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) Definition b : nat := 2. PG-4.5/ci/compile-tests/004-dependency-cycle/runtest.el000066400000000000000000000034131426357011200226170ustar00rootroot00000000000000;; This file is part of Proof General. -*- lexical-binding: t; -*- ;; ;; © Copyright 2020 Hendrik Tews ;; ;; Authors: Hendrik Tews ;; Maintainer: Hendrik Tews ;; ;; SPDX-License-Identifier: GPL-3.0-or-later ;;; Commentary: ;; ;; Coq Compile Tests (cct) -- ;; ert tests for parallel background compilation for Coq ;; ;; Test parallel background compilation for a dependency cycle. ;; ;; The following graph shows the file dependencies in this test: ;; ;; a1 a2 ;; / | ;; b<-e f ;; | | ;; c->d ;; ;; where a1 and a2 are the 2 require commands in file a.v. ;; require cct-lib for the elisp compilation, otherwise this is present already (require 'cct-lib "ci/compile-tests/cct-lib") ;;; set configuration (cct-configure-proof-general) ;;; Define the tests (ert-deftest cct-require-error () "Test background compilation on cyclic dependencies." (find-file "a.v") (cct-process-to-line 25) (let ((last-message (cct-last-message-line)) message-cycle) (should (equal "Coq compilation error: Circular dependency" (substring last-message 0 42))) (should (string-match (concat "\\./\\([b-e]\\).v -> \\./\\([b-e]\\).v -> " "\\./\\([b-e]\\).v -> \\./\\([b-e]\\).v") last-message)) (setq message-cycle (list (match-string 1 last-message) (match-string 2 last-message) (match-string 3 last-message) (match-string 4 last-message))) (should (or (equal message-cycle '("b" "c" "d" "e")) (equal message-cycle '("c" "d" "e" "b")) (equal message-cycle '("d" "e" "b" "c")) (equal message-cycle '("e" "b" "c" "d")))) (cct-check-locked 21 'locked) (cct-check-locked 22 'unlocked))) PG-4.5/ci/compile-tests/005-change-recompile/000077500000000000000000000000001426357011200205605ustar00rootroot00000000000000PG-4.5/ci/compile-tests/005-change-recompile/Makefile000066400000000000000000000012661426357011200222250ustar00rootroot00000000000000# This file is part of Proof General. # # © Copyright 2020 Hendrik Tews # # Authors: Hendrik Tews # Maintainer: Hendrik Tews # # SPDX-License-Identifier: GPL-3.0-or-later # This test modifies some .v files during the test. The original # versions are in .v.orig files. They are moved to the corresponding # .v files before the test starts. TEST_SOURCES:=a.v b.v c.v d.v e.v f.v g.v h.v .PHONY: test test: $(MAKE) clean $(MAKE) $(TEST_SOURCES) emacs -batch -l ../../../generic/proof-site.el -l ../cct-lib.el \ -l runtest.el -f ert-run-tests-batch-and-exit %.v: %.v.orig cp $< $@ .PHONY: clean clean: rm -f *.vo *.glob *.vio *.vos *.vok .*.aux $(TEST_SOURCES) PG-4.5/ci/compile-tests/005-change-recompile/a.v.orig000066400000000000000000000014041426357011200221250ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2020 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* This is line 21 *) Require Export b. Require Export c. (* This is line 24 *) (* This is line 27 *) Definition sum : nat := 35. (* This is line 31 *) Lemma x : b + c + d + e + f + g + h = sum. Proof using. unfold b, c, d, e, f, g, h, sum in *. simpl. trivial. Qed. (* This is line 38 *) PG-4.5/ci/compile-tests/005-change-recompile/b.v.orig000066400000000000000000000010321426357011200221230ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2020 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) Require Export d. (* This is line 22 *) Definition b : nat := 2. PG-4.5/ci/compile-tests/005-change-recompile/c.v.orig000066400000000000000000000010341426357011200221260ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2020 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) Require Export e f. (* This is line 22 *) Definition c : nat := 3. PG-4.5/ci/compile-tests/005-change-recompile/d.v.orig000066400000000000000000000010341426357011200221270ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2020 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) Require Export g h. (* This is line 22 *) Definition d : nat := 4. PG-4.5/ci/compile-tests/005-change-recompile/e.v.orig000066400000000000000000000006131426357011200221320ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2020 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) Require Export h. Definition e : nat := 5. PG-4.5/ci/compile-tests/005-change-recompile/f.v.orig000066400000000000000000000010321426357011200221270ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2020 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) Require Export h. (* This is line 22 *) Definition f : nat := 6. PG-4.5/ci/compile-tests/005-change-recompile/g.v.orig000066400000000000000000000010071426357011200221320ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2020 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* This is line 20 *) Definition g : nat := 7. PG-4.5/ci/compile-tests/005-change-recompile/h.v.orig000066400000000000000000000010071426357011200221330ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2020 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* This is line 20 *) Definition h : nat := 8. PG-4.5/ci/compile-tests/005-change-recompile/runtest.el000066400000000000000000000154421426357011200226140ustar00rootroot00000000000000;; This file is part of Proof General. -*- lexical-binding: t; -*- ;; ;; © Copyright 2020 Hendrik Tews ;; ;; Authors: Hendrik Tews ;; Maintainer: Hendrik Tews ;; ;; SPDX-License-Identifier: GPL-3.0-or-later ;;; Commentary: ;; ;; Coq Compile Tests (cct) -- ;; ert tests for parallel background compilation for Coq ;; ;; Test that the right files are recompiled when changes are made in ;; the dependency hierarchy and that unaffected ancestors are not ;; touched. ;; ;; The following graph shows the file dependencies in this test: ;; ;; a ;; / \ ;; b c ;; / / \ ;; d e f ;; / \ | / ;; | \ | / ;; | \|/ ;; g h ;; ;; ;; ;; ;; ;; ;; ;; require cct-lib for the elisp compilation, otherwise this is present already (require 'cct-lib "ci/compile-tests/cct-lib") ;;; set configuration (cct-configure-proof-general) ;;; Data and utility functions (defconst b-ancestors '("./b.v" "./d.v" "./g.v" "./h.v") "Ancestors of b.v.") (defconst c-ancestors '("./c.v" "./e.v" "./f.v") "Ancestors of c.v.") (defconst all-ancestors (append b-ancestors c-ancestors) "All ancestors.") (defconst all-compiled-ancestors (mapcar #'cct-library-vo-of-v-file all-ancestors) "All vo ancestors files.") (defun check-main-buffer (vo-times new-sum recompiled-files other-locked-files) "Perform various checks in buffer a.v. See `cct-generic-check-main-buffer'." (cct-generic-check-main-buffer "a.v" ; main-buf 21 ; main-unlocked 37 ; main-locked 28 ; main-sum-line new-sum vo-times recompiled-files `((22 . ,b-ancestors) (23 . ,c-ancestors)) ; require-ancestors other-locked-files 18 ; other-locked-line )) ;;; The test itself (ert-deftest cct-change-recompile () "Test successful recompilation after changes and deletion." (find-file "a.v") ;; 1. process original content - compile everything (message "\n1. process original content - compile everything\n") (cct-process-to-line 38) (cct-check-locked 37 'locked) (cct-locked-ancestors 22 b-ancestors) (cct-locked-ancestors 23 c-ancestors) (let ((vo-times (cct-record-change-times all-compiled-ancestors)) other-locked-files) ;; 2. retract and process again - nothing should be compiled (message "\n2. retract and process again - nothing should be compiled\n") (cct-process-to-line 21) (check-main-buffer vo-times "35" nil nil) ;; 3. change c and process again - only c should be compiled (message "\n3. change c and process again - only c should be compiled\n") (find-file "c.v") (push "c.v" other-locked-files) (cct-check-locked 23 'locked) (cct-replace-last-word 23 "4") (check-main-buffer vo-times "36" '("./c.vo") other-locked-files) ;; 4. change h and process again - everything except g should get compiled (message (concat "\n4. change h and process again - " "everything except g should get compiled\n")) (setq vo-times (cct-record-change-times all-compiled-ancestors)) (find-file "h.v") (push "h.v" other-locked-files) (cct-check-locked 21 'locked) (cct-replace-last-word 21 "10") (check-main-buffer vo-times "38" '("./b.vo" "./c.vo" "./d.vo" "./e.vo" "./f.vo" "./h.vo") other-locked-files) ;; 5. change d and f and process again - ;; only b, c, d and f should get recompiled (message (concat "\n5. change d and f and process again - " "only b, c, d and f should get recompiled")) (setq vo-times (cct-record-change-times all-compiled-ancestors)) (find-file "d.v") (push "d.v" other-locked-files) (cct-check-locked 23 'locked) (cct-replace-last-word 23 "7") (find-file "f.v") (push "f.v" other-locked-files) (cct-check-locked 23 'unlocked) (cct-replace-last-word 23 "10") (check-main-buffer vo-times "45" '("./b.vo" "./c.vo" "./d.vo" "./f.vo") other-locked-files) ;; 6. change d and b and process again - only d and b should get compiled (message (concat "\n6. change d and b and process again - " "only d and b should get compiled\n")) (setq vo-times (cct-record-change-times all-compiled-ancestors)) (find-file "b.v") (push "b.v" other-locked-files) (cct-check-locked 23 'locked) (cct-replace-last-word 23 "7") (set-buffer "d.v") (cct-check-locked 23 'unlocked) (cct-replace-last-word 23 "13") ; increase by 6 (check-main-buffer vo-times "56" '("./b.vo" "./d.vo") other-locked-files) ;; 7. delete b and process again - only b should get compiled (message (concat "\n7. delete b and process again - " "only b should get compiled\n")) (setq vo-times (cct-record-change-times all-compiled-ancestors)) (delete-file "b.vo") (set-buffer "a.v") (cct-process-to-line 21) (check-main-buffer vo-times "56" '("./b.vo") other-locked-files) ;; 8. delete h and process again - everything except g should get compiled (message (concat "\n8. delete h and process again - " "everything except g should get compiled\n")) (setq vo-times (cct-record-change-times all-compiled-ancestors)) (delete-file "h.vo") (set-buffer "a.v") (cct-process-to-line 21) (check-main-buffer vo-times "56" '("./b.vo" "./c.vo" "./d.vo" "./e.vo" "./f.vo" "./h.vo") other-locked-files) ;; 9. change d, delete g and process again - only b, d and g should ;; get compiled (message (concat "\n9. change d, delete g and process again - " "only b, d and g should get compiled\n")) (setq vo-times (cct-record-change-times all-compiled-ancestors)) (set-buffer "d.v") (cct-check-locked 23 'locked) (cct-replace-last-word 23 "20") ; increase by 7 (delete-file "g.vo") (set-buffer "a.v") (cct-process-to-line 21) (check-main-buffer vo-times "63" '("./b.vo" "./d.vo" "./g.vo") other-locked-files) ;; 10. delete d, change g and process again - only b, d and g should ;; get compiled (message (concat "\n10. delete d, change g and process again - " "only b, d and g should get compiled\n")) (setq vo-times (cct-record-change-times all-compiled-ancestors)) (delete-file "d.vo") (find-file "g.v") (push "g.v" other-locked-files) (cct-check-locked 21 'locked) (cct-replace-last-word 21 "15") ; increase by 8 (set-buffer "a.v") (cct-process-to-line 21) (check-main-buffer vo-times "71" '("./b.vo" "./d.vo" "./g.vo") other-locked-files) )) PG-4.5/ci/compile-tests/006-ready-dependee/000077500000000000000000000000001426357011200202325ustar00rootroot00000000000000PG-4.5/ci/compile-tests/006-ready-dependee/Makefile000066400000000000000000000013021426357011200216660ustar00rootroot00000000000000# This file is part of Proof General. # # © Copyright 2020 Hendrik Tews # # Authors: Hendrik Tews # Maintainer: Hendrik Tews # # SPDX-License-Identifier: GPL-3.0-or-later # This test modifies some .v files during the test. The original # versions are in .v.orig files. They are moved to the corresponding # .v files before the test starts. TEST_SOURCES:=a.v b.v c.v d.v e.v f.v g.v h.v i.v j.v k.v .PHONY: test test: $(MAKE) clean $(MAKE) $(TEST_SOURCES) emacs -batch -l ../../../generic/proof-site.el -l ../cct-lib.el \ -l runtest.el -f ert-run-tests-batch-and-exit %.v: %.v.orig cp $< $@ .PHONY: clean clean: rm -f *.vo *.glob *.vio *.vos *.vok .*.aux $(TEST_SOURCES) PG-4.5/ci/compile-tests/006-ready-dependee/a.v.orig000066400000000000000000000013471426357011200216050ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2020 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* This is line 21 *) Require Export b. Require Export c. (* This is line 24 *) (* This is line 27 *) Definition sum : nat := 9. (* This is line 31 *) Lemma x : b + c + k = sum. Proof using. unfold b, c, k, sum in *. simpl. trivial. Qed. (* This is line 38 *) PG-4.5/ci/compile-tests/006-ready-dependee/b.v.orig000066400000000000000000000010321426357011200215750ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2020 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) Require Export d. (* This is line 22 *) Definition b : nat := 2. PG-4.5/ci/compile-tests/006-ready-dependee/c.v.orig000066400000000000000000000010321426357011200215760ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2020 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) Require Export k. (* This is line 22 *) Definition c : nat := 3. PG-4.5/ci/compile-tests/006-ready-dependee/d.v.orig000066400000000000000000000005611426357011200216050ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2020 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) Require Export e. PG-4.5/ci/compile-tests/006-ready-dependee/e.v.orig000066400000000000000000000005611426357011200216060ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2020 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) Require Export f. PG-4.5/ci/compile-tests/006-ready-dependee/f.v.orig000066400000000000000000000005611426357011200216070ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2020 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) Require Export g. PG-4.5/ci/compile-tests/006-ready-dependee/g.v.orig000066400000000000000000000005611426357011200216100ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2020 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) Require Export h. PG-4.5/ci/compile-tests/006-ready-dependee/h.v.orig000066400000000000000000000005611426357011200216110ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2020 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) Require Export i. PG-4.5/ci/compile-tests/006-ready-dependee/i.v.orig000066400000000000000000000005611426357011200216120ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2020 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) Require Export j. PG-4.5/ci/compile-tests/006-ready-dependee/j.v.orig000066400000000000000000000005611426357011200216130ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2020 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) Require Export k. PG-4.5/ci/compile-tests/006-ready-dependee/k.v.orig000066400000000000000000000010071426357011200216100ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2020 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* This is line 20 *) Definition k : nat := 4. PG-4.5/ci/compile-tests/006-ready-dependee/runtest.el000066400000000000000000000105201426357011200222560ustar00rootroot00000000000000;; This file is part of Proof General. -*- lexical-binding: t; -*- ;; ;; © Copyright 2020 Hendrik Tews ;; ;; Authors: Hendrik Tews ;; Maintainer: Hendrik Tews ;; ;; SPDX-License-Identifier: GPL-3.0-or-later ;;; Commentary: ;; ;; Coq Compile Tests (cct) -- ;; ert tests for parallel background compilation for Coq ;; ;; Test recompilation and ancestor registration for the case a ;; dependency is in state ready already. ;; ;; The following graph shows the file dependencies in this test: ;; ;; a ;; / \ ;; b c ;; | |____________ ;; d \ ;; | | ;; e--f--g--h--i--j--k ;; ;; The idea is that the coqdep chain from b to j takes so long, that k ;; has been compiled and is in state ready before the coqdep results ;; from j are processed. This works - unless the disk cache is cold. ;; If it works the test triggers two bugs. First, k is locked with the ;; require command of c. Second, the modification time of k is not ;; propagated to j, such that the whole chain from j to b is not ;; recompiled after k has changed. ;; require cct-lib for the elisp compilation, otherwise this is present already (require 'cct-lib "ci/compile-tests/cct-lib") ;;; set configuration (cct-configure-proof-general) ;;; Data and utility functions (defconst b-ancestors '("./b.v" "./d.v" "./e.v" "./f.v" "./g.v" "./h.v" "./i.v" "./j.v" "./k.v") "Ancestors of b.v.") (defconst c-ancestors '("./c.v") "Ancestors of c.v.") (defconst all-ancestors (append b-ancestors c-ancestors) "All ancestors.") (defconst all-compiled-ancestors (mapcar #'cct-library-vo-of-v-file all-ancestors) "All vo ancestors files.") (defun cct-replace-last-word (line word) "Replace last word in line LINE with WORD. In current buffer, go to the end of line LINE and one word backward. Replace the word there with WORD." (cct-goto-line line) (end-of-line) (backward-word) (kill-word 1) (insert word)) (defun cct-check-main-buffer (vo-times new-sum recompiled-files other-locked-files) "Perform various checks for recompilation in buffer a.v. Combine all the following tests in this order: - line 21 in a.v is unlocked - after replacing the sum on line 28 with NEW-SUM, a.v can be processed until line 38 - files in VO-TIMES not listed in RECOMPILED-FILES have the same last change time as in VO-TIMES - files in RECOMPILED-FILES have a newer change time - the spans in line 22 and 23 hold the ancestors of b and c, respectively. - all the buffers in OTHER-LOCKED-FILES are locked until line 18." (let (splitted) (set-buffer "a.v") (cct-check-locked 21 'unlocked) (cct-replace-last-word 28 new-sum) (cct-process-to-line 38) (cct-check-locked 37 'locked) (setq splitted (cct-split-change-times vo-times recompiled-files)) (cct-unmodified-change-times (car splitted)) (cct-older-change-times (cdr splitted)) (cct-locked-ancestors 22 b-ancestors) (cct-locked-ancestors 23 c-ancestors) (mapc (lambda (b) (set-buffer b) (cct-check-locked 18 'locked)) other-locked-files))) ;;; The test itself (ert-deftest cct-change-recompile () "Test successful recompilation for a dependency in state ready." ;;(setq coq--debug-auto-compilation t) (find-file "a.v") ;; 1. process original content - compile everything (message "\n1. process original content - compile everything\n") (cct-process-to-line 38) (cct-check-locked 37 'locked) (cct-locked-ancestors 22 b-ancestors) (cct-locked-ancestors 23 c-ancestors) (let ((vo-times (cct-record-change-times all-compiled-ancestors)) other-locked-files) ;; 2. retract and process again - nothing should be compiled (message "\n2. retract and process again - nothing should be compiled\n") (cct-process-to-line 21) (cct-check-main-buffer vo-times "9" nil nil) ;; 3. change k and process again - everything should be compiled (message "\n3. change k and process again - everything should be compiled\n") (find-file "k.v") (push "k.v" other-locked-files) (cct-check-locked 21 'locked) (cct-replace-last-word 21 "5") (cct-check-main-buffer vo-times "10" '("./b.vo" "./c.vo" "./d.vo" "./e.vo" "./f.vo" "./g.vo" "./h.vo" "./i.vo" "./j.vo" "./k.vo") other-locked-files) )) PG-4.5/ci/compile-tests/007-slow-require/000077500000000000000000000000001426357011200200165ustar00rootroot00000000000000PG-4.5/ci/compile-tests/007-slow-require/Makefile000066400000000000000000000021511426357011200214550ustar00rootroot00000000000000# This file is part of Proof General. # # © Copyright 2021 Hendrik Tews # # Authors: Hendrik Tews # Maintainer: Hendrik Tews # # SPDX-License-Identifier: GPL-3.0-or-later # This test modifies some .v files during the test. The original # versions are in .v.orig files. They are moved to the corresponding # .v files before the test starts. TEST_SOURCES:=\ a1.v b1.v c1.v d1.v \ a2.v b2.v c2.v d2.v \ a3.v b3.v c3.v d3.v \ a4.v b4.v c4.v d4.v \ a5.v b5.v c5.v d5.v \ a6.v b6.v c6.v d6.v # This test uses ../bin/compile-test-start-delayed to start certain # commands with specified delays to check carfully constructed # internal states. compile-test-start-delayed outputs diagnostics on # file descriptor 9, which bypasses emacs and is joined with stderr of # the current make. Open file descriptor 9 here. .PHONY: test test: $(MAKE) clean $(MAKE) $(TEST_SOURCES) emacs -batch -l ../../../generic/proof-site.el -l ../cct-lib.el \ -l runtest.el -f ert-run-tests-batch-and-exit \ 9>&1 %.v: %.v.orig cp $< $@ .PHONY: clean clean: rm -f *.vo *.glob *.vio *.vos *.vok .*.aux $(TEST_SOURCES) PG-4.5/ci/compile-tests/007-slow-require/a1.v.orig000066400000000000000000000015551426357011200214530ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2021 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* The delay for coqdep is specified in comments with key coqdep-delay, * see compile-test-start-delayed. *) (* This is line 24 *) Require Export b1. Require Export (* coqdep-delay 2 *) c1. (* This is line 27 *) (* This is line 30 *) Definition sum : nat := 9. (* This is line 34 *) Lemma x : b + c + d = sum. Proof using. unfold b, c, d, sum in *. simpl. trivial. Qed. (* This is line 41 *) PG-4.5/ci/compile-tests/007-slow-require/a2.v.orig000066400000000000000000000015301426357011200214450ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2021 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* The delay for coqdep is specified in comments with key coqdep-delay, * see compile-test-start-delayed. *) (* This is line 24 *) Require Export b2. Require Export c2. (* This is line 27 *) (* This is line 30 *) Definition sum : nat := 9. (* This is line 34 *) Lemma x : b + c + d = sum. Proof using. unfold b, c, d, sum in *. simpl. trivial. Qed. (* This is line 41 *) PG-4.5/ci/compile-tests/007-slow-require/a3.v.orig000066400000000000000000000015551426357011200214550ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2021 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* The delay for coqdep is specified in comments with key coqdep-delay, * see compile-test-start-delayed. *) (* This is line 24 *) Require Export (* coqdep-delay 2 *) b3. Require Export c3. (* This is line 27 *) (* This is line 30 *) Definition sum : nat := 9. (* This is line 34 *) Lemma x : b + c + d = sum. Proof using. unfold b, c, d, sum in *. simpl. trivial. Qed. (* This is line 41 *) PG-4.5/ci/compile-tests/007-slow-require/a4.v.orig000066400000000000000000000015301426357011200214470ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2021 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* The delay for coqdep is specified in comments with key coqdep-delay, * see compile-test-start-delayed. *) (* This is line 24 *) Require Export b4. Require Export c4. (* This is line 27 *) (* This is line 30 *) Definition sum : nat := 9. (* This is line 34 *) Lemma x : b + c + d = sum. Proof using. unfold b, c, d, sum in *. simpl. trivial. Qed. (* This is line 41 *) PG-4.5/ci/compile-tests/007-slow-require/a5.v.orig000066400000000000000000000015301426357011200214500ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2021 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* The delay for coqdep is specified in comments with key coqdep-delay, * see compile-test-start-delayed. *) (* This is line 24 *) Require Export b5. Require Export c5. (* This is line 27 *) (* This is line 30 *) Definition sum : nat := 9. (* This is line 34 *) Lemma x : b + c + d = sum. Proof using. unfold b, c, d, sum in *. simpl. trivial. Qed. (* This is line 41 *) PG-4.5/ci/compile-tests/007-slow-require/a6.v.orig000066400000000000000000000015301426357011200214510ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2021 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* The delay for coqdep is specified in comments with key coqdep-delay, * see compile-test-start-delayed. *) (* This is line 24 *) Require Export b6. Require Export c6. (* This is line 27 *) (* This is line 30 *) Definition sum : nat := 9. (* This is line 34 *) Lemma x : b + c + d = sum. Proof using. unfold b, c, d, sum in *. simpl. trivial. Qed. (* This is line 41 *) PG-4.5/ci/compile-tests/007-slow-require/b1.v.orig000066400000000000000000000012021426357011200214410ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2021 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* Specify delays for coqdep and coqc when processing this file: * coqdep-delay 0 * coqc-delay 0 *) Require Export d1. (* This is line 26 *) Definition b : nat := 2. PG-4.5/ci/compile-tests/007-slow-require/b2.v.orig000066400000000000000000000012021426357011200214420ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2021 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* Specify delays for coqdep and coqc when processing this file: * coqdep-delay 0 * coqc-delay 0 *) Require Export d2. (* This is line 26 *) Definition b : nat := 2. PG-4.5/ci/compile-tests/007-slow-require/b3.v.orig000066400000000000000000000012021426357011200214430ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2021 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* Specify delays for coqdep and coqc when processing this file: * coqdep-delay 0 * coqc-delay 0 *) Require Export d3. (* This is line 26 *) Definition b : nat := 2. PG-4.5/ci/compile-tests/007-slow-require/b4.v.orig000066400000000000000000000012021426357011200214440ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2021 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* Specify delays for coqdep and coqc when processing this file: * coqdep-delay 2 * coqc-delay 0 *) Require Export d4. (* This is line 26 *) Definition b : nat := 2. PG-4.5/ci/compile-tests/007-slow-require/b5.v.orig000066400000000000000000000012021426357011200214450ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2021 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* Specify delays for coqdep and coqc when processing this file: * coqdep-delay 0 * coqc-delay 0 *) Require Export d5. (* This is line 26 *) Definition b : nat := 2. PG-4.5/ci/compile-tests/007-slow-require/b6.v.orig000066400000000000000000000012021426357011200214460ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2021 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* Specify delays for coqdep and coqc when processing this file: * coqdep-delay 0 * coqc-delay 0 *) Require Export d6. (* This is line 26 *) Definition b : nat := 2. PG-4.5/ci/compile-tests/007-slow-require/c1.v.orig000066400000000000000000000012021426357011200214420ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2021 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* Specify delays for coqdep and coqc when processing this file: * coqdep-delay 0 * coqc-delay 0 *) Require Export d1. (* This is line 26 *) Definition c : nat := 3. PG-4.5/ci/compile-tests/007-slow-require/c2.v.orig000066400000000000000000000012021426357011200214430ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2021 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* Specify delays for coqdep and coqc when processing this file: * coqdep-delay 2 * coqc-delay 0 *) Require Export d2. (* This is line 26 *) Definition c : nat := 3. PG-4.5/ci/compile-tests/007-slow-require/c3.v.orig000066400000000000000000000012021426357011200214440ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2021 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* Specify delays for coqdep and coqc when processing this file: * coqdep-delay 0 * coqc-delay 0 *) Require Export d3. (* This is line 26 *) Definition c : nat := 3. PG-4.5/ci/compile-tests/007-slow-require/c4.v.orig000066400000000000000000000012021426357011200214450ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2021 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* Specify delays for coqdep and coqc when processing this file: * coqdep-delay 0 * coqc-delay 0 *) Require Export d4. (* This is line 26 *) Definition c : nat := 3. PG-4.5/ci/compile-tests/007-slow-require/c5.v.orig000066400000000000000000000012021426357011200214460ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2021 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* Specify delays for coqdep and coqc when processing this file: * coqdep-delay 0 * coqc-delay 0 *) Require Export d5. (* This is line 26 *) Definition c : nat := 3. PG-4.5/ci/compile-tests/007-slow-require/c6.v.orig000066400000000000000000000012021426357011200214470ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2021 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* Specify delays for coqdep and coqc when processing this file: * coqdep-delay 2 * coqc-delay 0 *) Require Export d6. (* This is line 26 *) Definition c : nat := 3. PG-4.5/ci/compile-tests/007-slow-require/d1.v.orig000066400000000000000000000011601426357011200214460ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2021 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* Specify delays for coqdep and coqc when processing this file: * coqdep-delay 0 * coqc-delay 0 *) (* This is line 26 *) Definition d : nat := 4. PG-4.5/ci/compile-tests/007-slow-require/d2.v.orig000066400000000000000000000011601426357011200214470ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2021 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* Specify delays for coqdep and coqc when processing this file: * coqdep-delay 0 * coqc-delay 0 *) (* This is line 26 *) Definition d : nat := 4. PG-4.5/ci/compile-tests/007-slow-require/d3.v.orig000066400000000000000000000011601426357011200214500ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2021 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* Specify delays for coqdep and coqc when processing this file: * coqdep-delay 0 * coqc-delay 0 *) (* This is line 26 *) Definition d : nat := 4. PG-4.5/ci/compile-tests/007-slow-require/d4.v.orig000066400000000000000000000011601426357011200214510ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2021 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* Specify delays for coqdep and coqc when processing this file: * coqdep-delay 0 * coqc-delay 0 *) (* This is line 26 *) Definition d : nat := 4. PG-4.5/ci/compile-tests/007-slow-require/d5.v.orig000066400000000000000000000011601426357011200214520ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2021 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* Specify delays for coqdep and coqc when processing this file: * coqdep-delay 2 * coqc-delay 0 *) (* This is line 26 *) Definition d : nat := 4. PG-4.5/ci/compile-tests/007-slow-require/d6.v.orig000066400000000000000000000011571426357011200214610ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2021 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* Specify delays for coqdep and coqc when processing this file: * coqdep-delay * coqc-delay 4 *) (* This is line 26 *) Definition d : nat := 4. PG-4.5/ci/compile-tests/007-slow-require/runtest.el000066400000000000000000000176041426357011200220540ustar00rootroot00000000000000;; This file is part of Proof General. -*- lexical-binding: t; -*- ;; ;; © Copyright 2021 Hendrik Tews ;; ;; Authors: Hendrik Tews ;; Maintainer: Hendrik Tews ;; ;; SPDX-License-Identifier: GPL-3.0-or-later ;;; Commentary: ;; ;; Coq Compile Tests (cct) -- ;; ert tests for parallel background compilation for Coq ;; ;; Test two require jobs with different delays such that ;; coq-par-retire-top-level-job happens when the other require job is ;; in each possible state. For specifying the different delays there ;; are 6 mini projects, one for each test in this file. Each project ;; consists of four files, a1.v, b1.v, c1.v and d1.v for the first one ;; and a6.v, b6.v, c6.v and d6.v for the sixth one. Each project is ;; one ert test, described further below. In each project or test, the ;; top level require commands are asserted and retracted several times ;; with changes in different files to test (almost) all possible ;; internal state combinations. ;; ;; The dependencies are the same in all projects: ;; ;; a ;; / \ ;; b c ;; \ / ;; d ;; ;; Test 1 delays coqdep on require c, such that queue kickoff happens ;; in state 'enqueued-coqdep, the dependency link d->c is created when ;; d is ready and kickoff-queue-maybe on require c happens when ;; require b is in state 'ready. ;; ;; Test 2 delays coqdep on c, such that queue kickoff happens in state ;; 'waiting-dep. ;; ;; Test 3 delays coqdep on require b, such that kickoff-queue-maybe on ;; require c happens when require b is in state 'enqueued-coqdep and ;; queue kickoff happens in state 'waiting-queue. ;; ;; Test 4 delays coqdep on b, such that kickoff-queue-maybe on require ;; c happens when require b is in state 'waiting-dep. ;; ;; Test 5 delays coqdep on d, such that the second dependency on d is ;; created when d is in state enqueued-coqdep. ;; ;; Test 6 delays coqdep on c for 2 seconds and coqc on d for 4 ;; seconds, such that the dependency link d->c is created when d is in ;; state enqueued-coqc. ;; require cct-lib for the elisp compilation, otherwise this is present already (require 'cct-lib "ci/compile-tests/cct-lib") ;;; set configuration (cct-configure-proof-general) (configure-delayed-coq) (defconst pre-b-ancestors '("./b" "./d") "Ancestors of b without suffixes.") (defconst pre-c-ancestors '("./c") "Ancestors of c without suffixes.") (defconst pre-all-ancestors (append pre-b-ancestors pre-c-ancestors) "All ancestors without suffixes.") (defun b-ancestors (n) "Ancestors of b for part N." (mapcar (lambda (a) (concat a (format "%d.v" n))) pre-b-ancestors)) (defun c-ancestors (n) "Ancestors of c for part N." (mapcar (lambda (a) (concat a (format "%d.v" n))) pre-c-ancestors)) (defun all-ancestors (n) "All ancestors for part N." (mapcar (lambda (a) (concat a (format "%d.v" n))) pre-all-ancestors)) (defun all-compiled-ancestors (n) "All vo ancestor files for part N." (mapcar #'cct-library-vo-of-v-file (all-ancestors n))) (defun check-main-buffer (n vo-times new-sum recompiled-files other-locked-files) "Perform various checks in buffer aN.v. See `cct-generic-check-main-buffer'." (cct-generic-check-main-buffer (format "a%d.v" n) ; main-buf 25 ; main-unlocked 41 ; main-locked 31 ; main-sum-line new-sum vo-times recompiled-files `((25 . ,(b-ancestors n)) (26 . ,(c-ancestors n))) ; require-ancestors other-locked-files 27 ; other-locked-line )) ;;; Define the test (defun test-slow-require (n) "Test part N of slow require job tests. XXX Test a setting where the second require job is still in state 'enqueued-coqdep when the first one finishes." (let* ;; .v file names are used as file and as buffer names ((av (format "a%d.v" n)) (bv (format "b%d.v" n)) (cv (format "c%d.v" n)) (dv (format "d%d.v" n)) ;; .vo names compared with ancestors, they need a "./" prefix (bvo (concat "./" (cct-library-vo-of-v-file bv))) (cvo (concat "./" (cct-library-vo-of-v-file cv))) (dvo (concat "./" (cct-library-vo-of-v-file dv))) vo-times other-locked-files) ;; (setq cct--debug-tests t) ;; (setq coq--debug-auto-compilation t) (find-file av) (message "coqdep: %s\ncoqc: %s\nPATH %s\nexec-path: %s" coq-dependency-analyzer coq-compiler (getenv "PATH") exec-path) ;; 1. process original content - compile everything (message "\n%d.1. process original content - compile everything\n" n) ;;(setq coq--debug-auto-compilation t) (cct-process-to-line 42) (cct-check-locked 41 'locked) (cct-locked-ancestors 25 (b-ancestors n)) (cct-locked-ancestors 26 (c-ancestors n)) ;; (cl-assert nil nil "exit") (setq vo-times (cct-record-change-times (all-compiled-ancestors n))) ;; 2. retract and process again - nothing should be compiled (message "\n%d.2. retract and process again - nothing should be compiled\n" n) (cct-process-to-line 24) (check-main-buffer n vo-times "9" nil nil) ;; 3. change d and process again - b and c should be compiled (message "\n%d.3. change d and process again - b and c should be compiled\n" n) (find-file dv) (push dv other-locked-files) (cct-check-locked 23 'locked) (cct-replace-last-word 27 "5") (check-main-buffer n vo-times "10" (list bvo cvo dvo) other-locked-files) ;; 4. change b and process again - only b should be compiled (message "\n%d.4. change b and process again - only b should be compiled\n" n) (setq vo-times (cct-record-change-times (all-compiled-ancestors n))) (find-file bv) (push bv other-locked-files) (cct-check-locked 23 'locked) (cct-replace-last-word 27 "4") (check-main-buffer n vo-times "12" (list bvo) other-locked-files) ;; 5. change c and process again - only c should be compiled (message "\n%d.5. change c and process again - only c should be compiled\n" n) (setq vo-times (cct-record-change-times (all-compiled-ancestors n))) (find-file cv) (push cv other-locked-files) (cct-check-locked 23 'locked) (cct-replace-last-word 27 "8") (check-main-buffer n vo-times "17" (list cvo) other-locked-files) ;; 6. delete d and process again - b and c should be compiled (message "\n%d.6. delete d and process again - b and c should be compiled\n" n) (setq vo-times (cct-record-change-times (all-compiled-ancestors n))) (delete-file dvo) (set-buffer av) (cct-process-to-line 24) (check-main-buffer n vo-times "17" (list bvo cvo dvo) other-locked-files) ;; 7. delete b and process again - only b should be compiled (message "\n%d.7. delete b and process again - only b should be compiled\n" n) (setq vo-times (cct-record-change-times (all-compiled-ancestors n))) (delete-file bvo) (set-buffer av) (cct-process-to-line 24) (check-main-buffer n vo-times "17" (list bvo) other-locked-files) ;; 8. delete c and process again - only c should be compiled (message "\n%d.8. delete c and process again - only c should be compiled\n" n) (setq vo-times (cct-record-change-times (all-compiled-ancestors n))) (delete-file cvo) (set-buffer av) (cct-process-to-line 24) (check-main-buffer n vo-times "17" (list cvo) other-locked-files) )) (ert-deftest cct-slow-require-1 () (test-slow-require 1)) (ert-deftest cct-slow-require-2 () (test-slow-require 2)) (ert-deftest cct-slow-require-3 () (test-slow-require 3)) (ert-deftest cct-slow-require-4 () (test-slow-require 4)) (ert-deftest cct-slow-require-5 () (test-slow-require 5)) (ert-deftest cct-slow-require-6 () (test-slow-require 6)) PG-4.5/ci/compile-tests/008-default-dir/000077500000000000000000000000001426357011200175615ustar00rootroot00000000000000PG-4.5/ci/compile-tests/008-default-dir/Makefile000066400000000000000000000017541426357011200212300ustar00rootroot00000000000000# This file is part of Proof General. # # © Copyright 2021 Hendrik Tews # # Authors: Hendrik Tews # Maintainer: Hendrik Tews # # SPDX-License-Identifier: GPL-3.0-or-later # This test modifies some .v files during the test. The original # versions are in .v.orig files. They are moved to the corresponding # .v files before the test starts. TEST_SOURCES:= a.v b.v c.v # This test uses ../bin/compile-test-start-delayed to start certain # commands with specified delays to check carfully constructed # internal states. compile-test-start-delayed outputs diagnostics on # file descriptor 9, which bypasses emacs and is joined with stderr of # the current make. Open file descriptor 9 here. .PHONY: test test: $(MAKE) clean $(MAKE) $(TEST_SOURCES) emacs -batch -l ../../../generic/proof-site.el -l ../cct-lib.el \ -l runtest.el -f ert-run-tests-batch-and-exit \ 9>&1 %.v: %.v.orig cp $< $@ .PHONY: clean clean: rm -f *.vo *.glob *.vio *.vos *.vok .*.aux $(TEST_SOURCES) PG-4.5/ci/compile-tests/008-default-dir/a.v.orig000066400000000000000000000015221426357011200211270ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2021 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* The delay for coqdep is specified in comments with key coqdep-delay, * see compile-test-start-delayed. *) (* This is line 24 *) Require Export (* coqdep-delay 1 *) b. (* This is line 26 *) (* This is line 29 *) Definition sum : nat := 5. (* This is line 33 *) Lemma x : b + c = sum. Proof using. unfold b, c, sum in *. simpl. trivial. Qed. (* This is line 40 *) PG-4.5/ci/compile-tests/008-default-dir/b.v.orig000066400000000000000000000010321426357011200211240ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2021 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) Require Export c. (* This is line 22 *) Definition b : nat := 2. PG-4.5/ci/compile-tests/008-default-dir/c.v.orig000066400000000000000000000010111426357011200211220ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2021 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* This is line 22 *) Definition c : nat := 3. PG-4.5/ci/compile-tests/008-default-dir/runtest.el000066400000000000000000000122051426357011200216070ustar00rootroot00000000000000;; This file is part of Proof General. -*- lexical-binding: t; -*- ;; ;; © Copyright 2021 Hendrik Tews ;; ;; Authors: Hendrik Tews ;; Maintainer: Hendrik Tews ;; ;; SPDX-License-Identifier: GPL-3.0-or-later ;;; Commentary: ;; ;; Coq Compile Tests (cct) -- ;; ert tests for parallel background compilation for Coq ;; ;; Test that default-directory is correctly set independently of the ;; current buffer in the foreground, both for first and second stage ;; compilation. ;; ;; This test fails for Coq 8.15.0, because the test checks .vok files, ;; which, in certain situations, are not created by that coq version. ;; See Coq issue 15773. ;; ;; The dependencies in this test are: ;; ;; a ;; | ;; b ;; | ;; c ;; ;; require cct-lib for the elisp compilation, otherwise this is present already (require 'cct-lib "ci/compile-tests/cct-lib") ;;; set configuration (cct-configure-proof-general) (configure-delayed-coq) (defconst all-ancestors '("./b.v" "./c.v") "All ancestors.") (defconst all-compiled-ancestors (mapcar #'cct-library-vo-of-v-file all-ancestors) "All vo ancestors files.") (defun check-main-buffer (vo-times new-sum recompiled-files other-locked-files) "Perform various checks in buffer a.v. See `cct-generic-check-main-buffer'." (cct-generic-check-main-buffer "a.v" ; main-buf 24 ; main-unlocked 40 ; main-locked 30 ; main-sum-line new-sum vo-times recompiled-files `((25 . ,all-ancestors)) ; require-ancestors other-locked-files 23 ; other-locked-line )) ;;; The test itself (ert-deftest test-default-dir () :expected-result (if (equal (coq-version t) "8.15.0") :failed :passed) "`default-directory' test. Test that `default-directory' is correctly set independently of the current buffer in the foreground. This test fails for Coq 8.15.0, because the test checks .vok files, which are not created by that coq version, in certain situations. See Coq issue 15773." (let (vo-times av-buffer ci-buffer other-locked-files vok-times vos-vio-files) ;; (setq cct--debug-tests t) ;; (setq coq--debug-auto-compilation t) (find-file "a.v") (setq av-buffer (current-buffer)) (message "coqdep: %s\ncoqc: %s\nPATH %s\nexec-path: %s\ndetected coq version: %s" coq-dependency-analyzer coq-compiler (getenv "PATH") exec-path coq-autodetected-version) (find-file "../..") (setq ci-buffer (current-buffer)) (add-hook 'cct-before-busy-waiting-hook (lambda () (set-buffer ci-buffer))) (add-hook 'cct-after-busy-waiting-hook (lambda () (set-buffer av-buffer))) ;; 1. process original content - compile everything (message "\n1. process original content - compile everything\n") (check-main-buffer vo-times "5" nil other-locked-files) (setq vo-times (cct-record-change-times all-compiled-ancestors)) ;; 2. retract and process again - nothing should be compiled (message "\n2. retract and process again - nothing should be compiled\n") (cct-process-to-line 21) (check-main-buffer vo-times "5" nil other-locked-files) ;; 3. change b and process again - only b should get compiled (message "\n3. change b and process again - only b should get compiled\n") (find-file "b.v") (push "b.v" other-locked-files) (cct-check-locked 23 'locked) (cct-replace-last-word 23 "3") (check-main-buffer vo-times "6" '("./b.vo") other-locked-files) (setq vo-times (cct-record-change-times all-compiled-ancestors)) ;; 4. change c and process again - b and c should get compiled (message "\n4. change c and process again - b and c should get compiled\n") (find-file "c.v") (push "c.v" other-locked-files) (cct-check-locked 23 'locked) (cct-replace-last-word 23 "5") (check-main-buffer vo-times "8" '("./b.vo" "./c.vo") other-locked-files) (setq vo-times (cct-record-change-times all-compiled-ancestors)) ;; 5. change b and c and reprocess with vos-and-vok/quick-and-vio2vo (message "\n5. change b and c and reprocess with vos-and-vok/quick-and-vio2vo\n") (if (coq--post-v811) (setq coq-compile-vos 'vos-and-vok vos-vio-files '("./b.vos" "./c.vos") vok-times (cct-record-change-times '("./b.vok" "./c.vok"))) (setq coq-compile-quick 'quick-and-vio2vo vos-vio-files '("./b.vio" "./c.vio"))) (set-buffer "b.v") (cct-check-locked 23 'locked) (cct-replace-last-word 23 "7") (set-buffer "c.v") (cct-check-locked 23 'unlocked) (cct-replace-last-word 23 "10") (check-main-buffer nil "17" nil other-locked-files) (cct-files-are-readable vos-vio-files) ;; this will switch to a different default-directory, see the ;; hooks above (cct-wait-for-second-stage) (if (coq--post-v811) (progn (cct-older-change-times vok-times) (cct-unmodified-change-times vo-times)) (cct-older-change-times vo-times)) )) PG-4.5/ci/compile-tests/009-failure-processing/000077500000000000000000000000001426357011200211635ustar00rootroot00000000000000PG-4.5/ci/compile-tests/009-failure-processing/Makefile000066400000000000000000000026311426357011200226250ustar00rootroot00000000000000# This file is part of Proof General. # # © Copyright 2021 Hendrik Tews # # Authors: Hendrik Tews # Maintainer: Hendrik Tews # # SPDX-License-Identifier: GPL-3.0-or-later # This test modifies some .v files during the test. The original # versions are in .v.orig files. They are moved to the corresponding # .v files before the test starts. TEST_SOURCES:=\ a1.v b1.v c1.v d1.v e1.v f1.v g1.v h1.v \ a2.v b2.v c2.v d2.v e2.v f2.v g2.v h2.v \ a3.v b3.v c3.v d3.v e3.v f3.v g3.v h3.v \ a4.v b4.v c4.v d4.v e4.v f4.v g4.v h4.v \ a5.v b5.v c5.v d5.v e5.v f5.v g5.v h5.v \ a6.v b6.v c6.v d6.v e6.v f6.v g6.v h6.v \ a7.v b7.v c7.v d7.v e7.v f7.v g7.v h7.v \ a8.v b8.v c8.v d8.v e8.v f8.v g8.v h8.v \ a9.v b9.v c9.v d9.v e9.v f9.v g9.v h9.v \ a10.v b10.v c10.v d10.v e10.v f10.v g10.v h10.v # This test uses ../bin/compile-test-start-delayed to start certain # commands with specified delays to check carfully constructed # internal states. compile-test-start-delayed outputs diagnostics on # file descriptor 9, which bypasses emacs and is joined with stderr of # the current make. Open file descriptor 9 here. .PHONY: test test: $(MAKE) clean $(MAKE) $(TEST_SOURCES) emacs -batch -l ../../../generic/proof-site.el -l ../cct-lib.el \ -l runtest.el -f ert-run-tests-batch-and-exit \ 9>&1 %.v: %.v.orig cp $< $@ .PHONY: clean clean: rm -f *.vo *.glob *.vio *.vos *.vok .*.aux *.X $(TEST_SOURCES) PG-4.5/ci/compile-tests/009-failure-processing/a1.v.orig000066400000000000000000000012671426357011200226200ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2021 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See runtest.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT/DELETE ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* The delay for coqdep is specified in comments with key coqdep-delay, * see compile-test-start-delayed. *) (* This is line 24 *) Require Export b1. Require Export c1. Require Export d1. (* This is line 28 *) PG-4.5/ci/compile-tests/009-failure-processing/a10.v.orig000066400000000000000000000012721426357011200226740ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2021 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See runtest.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT/DELETE ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* The delay for coqdep is specified in comments with key coqdep-delay, * see compile-test-start-delayed. *) (* This is line 24 *) Require Export b10. Require Export c10. Require Export d10. (* This is line 28 *) PG-4.5/ci/compile-tests/009-failure-processing/a2.v.orig000066400000000000000000000012671426357011200226210ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2021 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See runtest.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT/DELETE ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* The delay for coqdep is specified in comments with key coqdep-delay, * see compile-test-start-delayed. *) (* This is line 24 *) Require Export b2. Require Export c2. Require Export d2. (* This is line 28 *) PG-4.5/ci/compile-tests/009-failure-processing/a3.v.orig000066400000000000000000000012671426357011200226220ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2021 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See runtest.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT/DELETE ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* The delay for coqdep is specified in comments with key coqdep-delay, * see compile-test-start-delayed. *) (* This is line 24 *) Require Export b3. Require Export c3. Require Export d3. (* This is line 28 *) PG-4.5/ci/compile-tests/009-failure-processing/a4.v.orig000066400000000000000000000012671426357011200226230ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2021 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See runtest.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT/DELETE ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* The delay for coqdep is specified in comments with key coqdep-delay, * see compile-test-start-delayed. *) (* This is line 24 *) Require Export b4. Require Export c4. Require Export d4. (* This is line 28 *) PG-4.5/ci/compile-tests/009-failure-processing/a5.v.orig000066400000000000000000000012671426357011200226240ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2021 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See runtest.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT/DELETE ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* The delay for coqdep is specified in comments with key coqdep-delay, * see compile-test-start-delayed. *) (* This is line 24 *) Require Export b5. Require Export c5. Require Export d5. (* This is line 28 *) PG-4.5/ci/compile-tests/009-failure-processing/a6.v.orig000066400000000000000000000012671426357011200226250ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2021 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See runtest.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT/DELETE ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* The delay for coqdep is specified in comments with key coqdep-delay, * see compile-test-start-delayed. *) (* This is line 24 *) Require Export b6. Require Export c6. Require Export d6. (* This is line 28 *) PG-4.5/ci/compile-tests/009-failure-processing/a7.v.orig000066400000000000000000000012671426357011200226260ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2021 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See runtest.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT/DELETE ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* The delay for coqdep is specified in comments with key coqdep-delay, * see compile-test-start-delayed. *) (* This is line 24 *) Require Export b7. Require Export c7. Require Export d7. (* This is line 28 *) PG-4.5/ci/compile-tests/009-failure-processing/a8.v.orig000066400000000000000000000012671426357011200226270ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2021 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See runtest.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT/DELETE ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* The delay for coqdep is specified in comments with key coqdep-delay, * see compile-test-start-delayed. *) (* This is line 24 *) Require Export b8. Require Export c8. Require Export d8. (* This is line 28 *) PG-4.5/ci/compile-tests/009-failure-processing/a9.v.orig000066400000000000000000000012671426357011200226300ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2021 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See runtest.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT/DELETE ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* The delay for coqdep is specified in comments with key coqdep-delay, * see compile-test-start-delayed. *) (* This is line 24 *) Require Export b9. Require Export c9. Require Export d9. (* This is line 28 *) PG-4.5/ci/compile-tests/009-failure-processing/b1.v.orig000066400000000000000000000011221426357011200226070ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2021 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* Specify delays for coqdep and coqc when processing this file: * coqdep-delay 0 * coqc-delay 0 *) Require Export f1. PG-4.5/ci/compile-tests/009-failure-processing/b10.v.orig000066400000000000000000000011251426357011200226720ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2021 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* Specify delays for coqdep and coqc when processing this file: * coqdep-delay 0 * coqc-delay 1.5 *) Require Export f10. PG-4.5/ci/compile-tests/009-failure-processing/b2.v.orig000066400000000000000000000011221426357011200226100ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2021 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* Specify delays for coqdep and coqc when processing this file: * coqdep-delay 0 * coqc-delay 2 *) Require Export f2. PG-4.5/ci/compile-tests/009-failure-processing/b3.v.orig000066400000000000000000000011221426357011200226110ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2021 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* Specify delays for coqdep and coqc when processing this file: * coqdep-delay 0 * coqc-delay 3 *) Require Export f3. PG-4.5/ci/compile-tests/009-failure-processing/b4.v.orig000066400000000000000000000011221426357011200226120ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2021 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* Specify delays for coqdep and coqc when processing this file: * coqdep-delay 0 * coqc-delay 0 *) Require Export f4. PG-4.5/ci/compile-tests/009-failure-processing/b5.v.orig000066400000000000000000000011241426357011200226150ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2021 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* Specify delays for coqdep and coqc when processing this file: * coqdep-delay 0 * coqc-delay 1.5 *) Require Export f5. PG-4.5/ci/compile-tests/009-failure-processing/b6.v.orig000066400000000000000000000011221426357011200226140ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2021 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* Specify delays for coqdep and coqc when processing this file: * coqdep-delay 0 * coqc-delay 0 *) Require Export f6. PG-4.5/ci/compile-tests/009-failure-processing/b7.v.orig000066400000000000000000000011221426357011200226150ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2021 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* Specify delays for coqdep and coqc when processing this file: * coqdep-delay 0 * coqc-delay 1 *) Require Export f7. PG-4.5/ci/compile-tests/009-failure-processing/b8.v.orig000066400000000000000000000011241426357011200226200ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2021 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* Specify delays for coqdep and coqc when processing this file: * coqdep-delay 0 * coqc-delay 1.5 *) Require Export f8. PG-4.5/ci/compile-tests/009-failure-processing/b9.v.orig000066400000000000000000000011221426357011200226170ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2021 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* Specify delays for coqdep and coqc when processing this file: * coqdep-delay 0 * coqc-delay 0 *) Require Export f9. PG-4.5/ci/compile-tests/009-failure-processing/c1.v.orig000066400000000000000000000011251426357011200226130ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2021 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* Specify delays for coqdep and coqc when processing this file: * coqdep-delay 0 * coqc-delay X *) Require Export e1 g1. PG-4.5/ci/compile-tests/009-failure-processing/c10.v.orig000066400000000000000000000011271426357011200226750ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2021 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* Specify delays for coqdep and coqc when processing this file: * coqdep-delay 0 * coqc-delay X *) Require Export e10 g10. PG-4.5/ci/compile-tests/009-failure-processing/c2.v.orig000066400000000000000000000011251426357011200226140ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2021 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* Specify delays for coqdep and coqc when processing this file: * coqdep-delay 0 * coqc-delay X *) Require Export e2 g2. PG-4.5/ci/compile-tests/009-failure-processing/c3.v.orig000066400000000000000000000011251426357011200226150ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2021 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* Specify delays for coqdep and coqc when processing this file: * coqdep-delay 0 * coqc-delay X *) Require Export e3 g3. PG-4.5/ci/compile-tests/009-failure-processing/c4.v.orig000066400000000000000000000011251426357011200226160ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2021 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* Specify delays for coqdep and coqc when processing this file: * coqdep-delay 0 * coqc-delay X *) Require Export e4 g4. PG-4.5/ci/compile-tests/009-failure-processing/c5.v.orig000066400000000000000000000011251426357011200226170ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2021 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* Specify delays for coqdep and coqc when processing this file: * coqdep-delay 0 * coqc-delay X *) Require Export e5 g5. PG-4.5/ci/compile-tests/009-failure-processing/c6.v.orig000066400000000000000000000011251426357011200226200ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2021 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* Specify delays for coqdep and coqc when processing this file: * coqdep-delay 0 * coqc-delay X *) Require Export e6 g6. PG-4.5/ci/compile-tests/009-failure-processing/c7.v.orig000066400000000000000000000011251426357011200226210ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2021 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* Specify delays for coqdep and coqc when processing this file: * coqdep-delay 0 * coqc-delay X *) Require Export e7 g7. PG-4.5/ci/compile-tests/009-failure-processing/c8.v.orig000066400000000000000000000011251426357011200226220ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2021 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* Specify delays for coqdep and coqc when processing this file: * coqdep-delay 0 * coqc-delay X *) Require Export e8 g8. PG-4.5/ci/compile-tests/009-failure-processing/c9.v.orig000066400000000000000000000011251426357011200226230ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2021 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* Specify delays for coqdep and coqc when processing this file: * coqdep-delay 0 * coqc-delay X *) Require Export e9 g9. PG-4.5/ci/compile-tests/009-failure-processing/d1.v.orig000066400000000000000000000011241426357011200226130ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2021 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* Specify delays for coqdep and coqc when processing this file: * coqdep-delay 0 * coqc-delay 1.5 *) Require Export h1. PG-4.5/ci/compile-tests/009-failure-processing/d10.v.orig000066400000000000000000000011231426357011200226720ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2021 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* Specify delays for coqdep and coqc when processing this file: * coqdep-delay 0 * coqc-delay 0 *) Require Export h10. PG-4.5/ci/compile-tests/009-failure-processing/d2.v.orig000066400000000000000000000011221426357011200226120ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2021 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* Specify delays for coqdep and coqc when processing this file: * coqdep-delay 0 * coqc-delay 3 *) Require Export h2. PG-4.5/ci/compile-tests/009-failure-processing/d3.v.orig000066400000000000000000000011221426357011200226130ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2021 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* Specify delays for coqdep and coqc when processing this file: * coqdep-delay 0 * coqc-delay 2 *) Require Export h3. PG-4.5/ci/compile-tests/009-failure-processing/d4.v.orig000066400000000000000000000011221426357011200226140ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2021 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* Specify delays for coqdep and coqc when processing this file: * coqdep-delay 0 * coqc-delay 0 *) Require Export h4. PG-4.5/ci/compile-tests/009-failure-processing/d5.v.orig000066400000000000000000000011221426357011200226150ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2021 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* Specify delays for coqdep and coqc when processing this file: * coqdep-delay 0 * coqc-delay 0 *) Require Export h5. PG-4.5/ci/compile-tests/009-failure-processing/d6.v.orig000066400000000000000000000011241426357011200226200ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2021 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* Specify delays for coqdep and coqc when processing this file: * coqdep-delay 0 * coqc-delay 1.5 *) Require Export h6. PG-4.5/ci/compile-tests/009-failure-processing/d7.v.orig000066400000000000000000000011241426357011200226210ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2021 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* Specify delays for coqdep and coqc when processing this file: * coqdep-delay 0 * coqc-delay 1.5 *) Require Export h7. PG-4.5/ci/compile-tests/009-failure-processing/d8.v.orig000066400000000000000000000011221426357011200226200ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2021 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* Specify delays for coqdep and coqc when processing this file: * coqdep-delay 0 * coqc-delay 1 *) Require Export h8. PG-4.5/ci/compile-tests/009-failure-processing/d9.v.orig000066400000000000000000000011221426357011200226210ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2021 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* Specify delays for coqdep and coqc when processing this file: * coqdep-delay 0 * coqc-delay 0 *) Require Export h9. PG-4.5/ci/compile-tests/009-failure-processing/e1.v.orig000066400000000000000000000011221426357011200226120ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2021 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* Specify delays for coqdep and coqc when processing this file: * coqdep-delay 0 * coqc-delay 0 *) Require Export b1. PG-4.5/ci/compile-tests/009-failure-processing/e10.v.orig000066400000000000000000000011621426357011200226760ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2021 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* Specify delays for coqdep and coqc when processing this file: * coqdep-delay 0 * coqc-delay 0 *) (* Require Export b10. *) Definition e : nat := 3. PG-4.5/ci/compile-tests/009-failure-processing/e2.v.orig000066400000000000000000000011221426357011200226130ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2021 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* Specify delays for coqdep and coqc when processing this file: * coqdep-delay 0 * coqc-delay 0 *) Require Export b2. PG-4.5/ci/compile-tests/009-failure-processing/e3.v.orig000066400000000000000000000011221426357011200226140ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2021 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* Specify delays for coqdep and coqc when processing this file: * coqdep-delay 0 * coqc-delay 0 *) Require Export b3. PG-4.5/ci/compile-tests/009-failure-processing/e4.v.orig000066400000000000000000000011221426357011200226150ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2021 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* Specify delays for coqdep and coqc when processing this file: * coqdep-delay 0 * coqc-delay 0 *) Require Export b4. PG-4.5/ci/compile-tests/009-failure-processing/e5.v.orig000066400000000000000000000011611426357011200226210ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2021 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* Specify delays for coqdep and coqc when processing this file: * coqdep-delay 0 * coqc-delay 0 *) (* Require Export b5. *) Definition e : nat := 3. PG-4.5/ci/compile-tests/009-failure-processing/e6.v.orig000066400000000000000000000011221426357011200226170ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2021 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* Specify delays for coqdep and coqc when processing this file: * coqdep-delay 0 * coqc-delay 0 *) Require Export b6. PG-4.5/ci/compile-tests/009-failure-processing/e7.v.orig000066400000000000000000000011221426357011200226200ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2021 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* Specify delays for coqdep and coqc when processing this file: * coqdep-delay 0 * coqc-delay 0 *) Require Export b7. PG-4.5/ci/compile-tests/009-failure-processing/e8.v.orig000066400000000000000000000011221426357011200226210ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2021 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* Specify delays for coqdep and coqc when processing this file: * coqdep-delay 0 * coqc-delay 0 *) Require Export b8. PG-4.5/ci/compile-tests/009-failure-processing/e9.v.orig000066400000000000000000000011221426357011200226220ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2021 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* Specify delays for coqdep and coqc when processing this file: * coqdep-delay 0 * coqc-delay 0 *) Require Export b9. PG-4.5/ci/compile-tests/009-failure-processing/f1.v.orig000066400000000000000000000011301426357011200226120ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2021 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* Specify delays for coqdep and coqc when processing this file: * coqdep-delay 0 * coqc-delay 0 *) Definition f : nat := 1. PG-4.5/ci/compile-tests/009-failure-processing/f10.v.orig000066400000000000000000000011301426357011200226720ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2021 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* Specify delays for coqdep and coqc when processing this file: * coqdep-delay 0 * coqc-delay 0 *) Definition f : nat := 1. PG-4.5/ci/compile-tests/009-failure-processing/f2.v.orig000066400000000000000000000011301426357011200226130ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2021 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* Specify delays for coqdep and coqc when processing this file: * coqdep-delay 0 * coqc-delay 0 *) Definition f : nat := 1. PG-4.5/ci/compile-tests/009-failure-processing/f3.v.orig000066400000000000000000000011301426357011200226140ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2021 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* Specify delays for coqdep and coqc when processing this file: * coqdep-delay 0 * coqc-delay 0 *) Definition f : nat := 1. PG-4.5/ci/compile-tests/009-failure-processing/f4.v.orig000066400000000000000000000011301426357011200226150ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2021 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* Specify delays for coqdep and coqc when processing this file: * coqdep-delay 0 * coqc-delay 0 *) Definition f : nat := 1. PG-4.5/ci/compile-tests/009-failure-processing/f5.v.orig000066400000000000000000000011301426357011200226160ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2021 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* Specify delays for coqdep and coqc when processing this file: * coqdep-delay 0 * coqc-delay 0 *) Definition f : nat := 1. PG-4.5/ci/compile-tests/009-failure-processing/f6.v.orig000066400000000000000000000011301426357011200226170ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2021 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* Specify delays for coqdep and coqc when processing this file: * coqdep-delay 0 * coqc-delay 0 *) Definition f : nat := 1. PG-4.5/ci/compile-tests/009-failure-processing/f7.v.orig000066400000000000000000000011301426357011200226200ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2021 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* Specify delays for coqdep and coqc when processing this file: * coqdep-delay 0 * coqc-delay 0 *) Definition f : nat := 1. PG-4.5/ci/compile-tests/009-failure-processing/f8.v.orig000066400000000000000000000011301426357011200226210ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2021 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* Specify delays for coqdep and coqc when processing this file: * coqdep-delay 0 * coqc-delay 0 *) Definition f : nat := 1. PG-4.5/ci/compile-tests/009-failure-processing/f9.v.orig000066400000000000000000000011301426357011200226220ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2021 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* Specify delays for coqdep and coqc when processing this file: * coqdep-delay 0 * coqc-delay 0 *) Definition f : nat := 1. PG-4.5/ci/compile-tests/009-failure-processing/g1.v.orig000066400000000000000000000011471426357011200226230ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2021 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* Specify delays for coqdep and coqc when processing this file: * coqdep-delay 1 * coqc-delay X *) (* coqdep error *) Require Export f1 h1 PG-4.5/ci/compile-tests/009-failure-processing/g10.v.orig000066400000000000000000000011571426357011200227040ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2021 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* Specify delays for coqdep and coqc when processing this file: * coqdep-delay 1 * coqc-delay 0 *) Require Export f10 h10. (* coqc error *) XXX. PG-4.5/ci/compile-tests/009-failure-processing/g2.v.orig000066400000000000000000000011471426357011200226240ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2021 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* Specify delays for coqdep and coqc when processing this file: * coqdep-delay 1 * coqc-delay X *) (* coqdep error *) Require Export f2 h2 PG-4.5/ci/compile-tests/009-failure-processing/g3.v.orig000066400000000000000000000011471426357011200226250ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2021 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* Specify delays for coqdep and coqc when processing this file: * coqdep-delay 1 * coqc-delay X *) (* coqdep error *) Require Export f3 h3 PG-4.5/ci/compile-tests/009-failure-processing/g4.v.orig000066400000000000000000000011471426357011200226260ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2021 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* Specify delays for coqdep and coqc when processing this file: * coqdep-delay 1 * coqc-delay X *) (* coqdep error *) Require Export f4 h4 PG-4.5/ci/compile-tests/009-failure-processing/g5.v.orig000066400000000000000000000011471426357011200226270ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2021 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* Specify delays for coqdep and coqc when processing this file: * coqdep-delay 1 * coqc-delay X *) (* coqdep error *) Require Export f5 h5 PG-4.5/ci/compile-tests/009-failure-processing/g6.v.orig000066400000000000000000000011551426357011200226270ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2021 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* Specify delays for coqdep and coqc when processing this file: * coqdep-delay 0 * coqc-delay 1 *) Require Export f6 h6. (* coqc error *) XXX. PG-4.5/ci/compile-tests/009-failure-processing/g7.v.orig000066400000000000000000000011551426357011200226300ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2021 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* Specify delays for coqdep and coqc when processing this file: * coqdep-delay 0 * coqc-delay 0 *) Require Export f7 h7. (* coqc error *) XXX. PG-4.5/ci/compile-tests/009-failure-processing/g8.v.orig000066400000000000000000000011551426357011200226310ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2021 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* Specify delays for coqdep and coqc when processing this file: * coqdep-delay 0 * coqc-delay 0 *) Require Export f8 h8. (* coqc error *) XXX. PG-4.5/ci/compile-tests/009-failure-processing/g9.v.orig000066400000000000000000000011551426357011200226320ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2021 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* Specify delays for coqdep and coqc when processing this file: * coqdep-delay 0 * coqc-delay 1 *) Require Export f9 h9. (* coqc error *) XXX. PG-4.5/ci/compile-tests/009-failure-processing/h1.v.orig000066400000000000000000000011301426357011200226140ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2021 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* Specify delays for coqdep and coqc when processing this file: * coqdep-delay 0 * coqc-delay 0 *) Definition h : nat := 2. PG-4.5/ci/compile-tests/009-failure-processing/h10.v.orig000066400000000000000000000011301426357011200226740ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2021 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* Specify delays for coqdep and coqc when processing this file: * coqdep-delay 0 * coqc-delay 0 *) Definition h : nat := 2. PG-4.5/ci/compile-tests/009-failure-processing/h2.v.orig000066400000000000000000000011301426357011200226150ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2021 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* Specify delays for coqdep and coqc when processing this file: * coqdep-delay 0 * coqc-delay 0 *) Definition h : nat := 2. PG-4.5/ci/compile-tests/009-failure-processing/h3.v.orig000066400000000000000000000011301426357011200226160ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2021 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* Specify delays for coqdep and coqc when processing this file: * coqdep-delay 0 * coqc-delay 0 *) Definition h : nat := 2. PG-4.5/ci/compile-tests/009-failure-processing/h4.v.orig000066400000000000000000000011301426357011200226170ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2021 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* Specify delays for coqdep and coqc when processing this file: * coqdep-delay 0 * coqc-delay 0 *) Definition h : nat := 2. PG-4.5/ci/compile-tests/009-failure-processing/h5.v.orig000066400000000000000000000011301426357011200226200ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2021 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* Specify delays for coqdep and coqc when processing this file: * coqdep-delay 0 * coqc-delay 0 *) Definition h : nat := 2. PG-4.5/ci/compile-tests/009-failure-processing/h6.v.orig000066400000000000000000000011301426357011200226210ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2021 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* Specify delays for coqdep and coqc when processing this file: * coqdep-delay 0 * coqc-delay 0 *) Definition h : nat := 2. PG-4.5/ci/compile-tests/009-failure-processing/h7.v.orig000066400000000000000000000011301426357011200226220ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2021 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* Specify delays for coqdep and coqc when processing this file: * coqdep-delay 0 * coqc-delay 0 *) Definition h : nat := 2. PG-4.5/ci/compile-tests/009-failure-processing/h8.v.orig000066400000000000000000000011301426357011200226230ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2021 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* Specify delays for coqdep and coqc when processing this file: * coqdep-delay 0 * coqc-delay 0 *) Definition h : nat := 2. PG-4.5/ci/compile-tests/009-failure-processing/h9.v.orig000066400000000000000000000011301426357011200226240ustar00rootroot00000000000000(* This file is part of Proof General. * * © Copyright 2021 Hendrik Tews * * Authors: Hendrik Tews * Maintainer: Hendrik Tews * * SPDX-License-Identifier: GPL-3.0-or-later * * * This file is part of an automatic test case for parallel background * compilation in coq-par-compile.el. See test.el in this directory. *) (* The test script relies on absolute line numbers. * DO NOT INSERT ANY LINE UNLESS YOU KNOW WHAT YOU ARE DOING. *) (* Specify delays for coqdep and coqc when processing this file: * coqdep-delay 0 * coqc-delay 0 *) Definition h : nat := 2. PG-4.5/ci/compile-tests/009-failure-processing/runtest.el000066400000000000000000000116501426357011200232140ustar00rootroot00000000000000;; This file is part of Proof General. -*- lexical-binding: t; -*- ;; ;; © Copyright 2021 Hendrik Tews ;; ;; Authors: Hendrik Tews ;; Maintainer: Hendrik Tews ;; ;; SPDX-License-Identifier: GPL-3.0-or-later ;;; Commentary: ;; ;; Coq Compile Tests (cct) -- ;; ert tests for parallel background compilation for Coq ;; ;; Test a partially successful and partially failing compilation with ;; coq-compile-keep-going. Check that the right files are compiled, ;; locked and unlocked. Check also the case, where unlocking of failed ;; files must be delayed, because some earlier successful require job ;; has not yet locked its ancestors. ;; ;; The dependencies in this test are: ;; ;; Rb Rc Rd ;; | | | ;; | c | ;; | /| | ;; | / | | ;; | e | d ;; | ? | | ;; |? | | ;; b g / ;; | _/| / ;; | _/ | / ;; |/ |/ ;; f h ;; ;; Rb, Rc and Rd are three different require commands in file a. The ;; dependency e -> b is not present in test 5 and test 10 (but in all ;; other tests). The error always happens in file g, for test 1-5 with ;; coqdep, for tests 6-10 with coqc. There are 10 tests, each with ;; slighly different delays, in 10 versions of the sources, e.g., ;; a1-a10, b1-b10, and so on. ;; ;; For tests 1-5 coqdep fails on g, when this happens ;; ;; 1: Rb is ready and d still busy ;; 2: f is ready and b and d are still busy and d finishes last ;; 3: f is ready and b and d are still busy and b finishes last ;; 4: RB is ready and Rd is queue waiting ;; 5: without dependency e -> b: Rc, Rd are queue waiting, b finishes last ;; ;; ;; For tests 6-10 coqc fails on g, when this happens ;; ;; 6: Rb is ready and d still busy ;; 7: f is ready and b and d are still busy and d finishes last ;; 8: f is ready and b and d are still busy and b finishes last ;; 9: RB is ready and Rd is queue waiting ;; 10: without dependency b -> e: Rc, Rd are queue waiting, b finishes last ;; require cct-lib for the elisp compilation, otherwise this is present already (require 'cct-lib "ci/compile-tests/cct-lib") ;;; set configuration (cct-configure-proof-general) (configure-delayed-coq) (defconst pre-b-ancestors '("b" "f") "Ancestors of b without suffixes.") (defconst pre-all-compiled (append pre-b-ancestors '("e" "h" "d")) "All files that get compiled.") (defun pre-not-compiled (n) "List of file name stems for which coqc must not be called. Files for which coqc must not be called have an ``X'' in coqc-delay. For such files `compile-test-start-delayed' would create a ``.X'' file, whose absense is checked in the test." (cond ((< n 6) '("g" "c")) (t '("c")))) (defconst pre-all-unlocked '("c" "d" "e" "g" "h") "All stems of files that should be unlocked after compilation.") (defun b-ancestors (n) "Ancestors of b for part N." (mapcar (lambda (f) (format "./%s%d.v" f n)) pre-b-ancestors)) (defun all-compiled (n) "All files that get compiled for part N." (mapcar (lambda (f) (format "./%s%d.v" f n)) pre-all-compiled)) (defun all-compiled-vo (n) "All vo files for part N." (mapcar #'cct-library-vo-of-v-file (all-compiled n))) (defun not-compiled (n) "Files that should not be compiled for part N, see `pre-not-compiled'." (mapcar (lambda (f) (format "./%s%d.v.X" f n)) (pre-not-compiled n))) (defun all-unlocked (n) "All files that should be unlocked after compilation for part N." (mapcar (lambda (f) (format "./%s%d.v" f n)) pre-all-unlocked)) ;;; Define the test (defun test-failure-processing (n) "Test partially successful and partially failing compilation, part N." ;; (setq cct--debug-tests t) ;; (setq coq--debug-auto-compilation t) (find-file (format "a%d.v" n)) (message "coqdep: %s\ncoqc: %s\nPATH %s\nexec-path: %s" coq-dependency-analyzer coq-compiler (getenv "PATH") exec-path) (message "\n%d. Partially failing compilation part %d\n" n n) (cct-process-to-line 28) (cct-check-locked 25 'locked) (cct-check-locked 26 'unlocked) (cct-locked-ancestors 25 (b-ancestors n)) (cct-check-files-locked 24 'locked (b-ancestors n)) (cct-check-files-locked 1 'unlocked (all-unlocked n)) (cct-files-are-readable (all-compiled-vo n)) (cct-files-dont-exist (not-compiled n))) (ert-deftest cct-failure-processing-01 () (test-failure-processing 1)) (ert-deftest cct-failure-processing-02 () (test-failure-processing 2)) (ert-deftest cct-failure-processing-03 () (test-failure-processing 3)) (ert-deftest cct-failure-processing-04 () (test-failure-processing 4)) (ert-deftest cct-failure-processing-05 () (test-failure-processing 5)) (ert-deftest cct-failure-processing-06 () (test-failure-processing 6)) (ert-deftest cct-failure-processing-07 () (test-failure-processing 7)) (ert-deftest cct-failure-processing-08 () (test-failure-processing 8)) (ert-deftest cct-failure-processing-09 () (test-failure-processing 9)) (ert-deftest cct-failure-processing-10 () (test-failure-processing 10)) PG-4.5/ci/compile-tests/Makefile000066400000000000000000000006271426357011200165210ustar00rootroot00000000000000# This file is part of Proof General. # # © Copyright 2020 Hendrik Tews # # Authors: Hendrik Tews # Maintainer: Hendrik Tews # # SPDX-License-Identifier: GPL-3.0-or-later TOPTARGETS := test clean SUBDIRS := $(wildcard [0-9][0-9][0-9]-*) $(TOPTARGETS): $(SUBDIRS) $(SUBDIRS): $(MAKE) -C $@ $(MAKECMDGOALS) .PHONY: $(TOPTARGETS) $(SUBDIRS) .PHONY: TAGS TAGS: etags *.el */*.el PG-4.5/ci/compile-tests/README.md000066400000000000000000000040241426357011200163330ustar00rootroot00000000000000This directory contains tests for the parallel background compilation feature for Coq. The test check that - files get compiled in the right order, - after changes, precisely those files that need recompilation are compiled - files are locked and registered in the right require commands. Each test comes with a hand-crafted set of Coq source files that implement a particular dependency tree. Therefore, most of the tests have a subdirectory on their own. # Overview of existing tests All tests are for parallel background compilation. 001-mini-project : test compilation for a simple project 002-require-no-dependencies : Test a require that does not produce any dependencies. 003-require-error : coqdep fails on a require 004-dependency-cycle : dependency cycle 005-change-recompile : test that the right files are recompiled when changes are made 006-ready-dependee : dependency in state ready 007-slow-require : test almost all internal state combinations with delay on coqdep and coqc 008-default-dir : test that the default/current directory is set correctly independent of user/emacs changing the current buffer during first and second stage compilation 009-failure-processing : check ancestor unlocking for a failed job with coq-compile-keep-going; test also the case, where the last (failed) require job must be delayed, because some queue dependee is still processing # Tests currently missing - a job depending on a failed dependee, where the dependee has been finished before - coq-par-create-file-job detects a dependency cycle - coq-par-create-file-job finds a job in state waiting-dep - coq-par-kickoff-queue-maybe is done when the queue dependee is in state waiting-queue - coq-par-create-file-job finds a failed job - all tests in all quick and all vos variants - test two coq-par-kickoff-queue-from-action-list entries being active at the same time: assert one region, let compilation fail, assert second region, while first region is still busy, this should fail in some weird way, because failed is not propagated PG-4.5/ci/compile-tests/bin/000077500000000000000000000000001426357011200156245ustar00rootroot00000000000000PG-4.5/ci/compile-tests/bin/compile-test-start-delayed000077500000000000000000000042301426357011200227160ustar00rootroot00000000000000#!/bin/bash # # This file is part of Proof General. # # © Copyright 2021 Hendrik Tews # # Authors: Hendrik Tews # Maintainer: Hendrik Tews # # SPDX-License-Identifier: GPL-3.0-or-later # # See function usage for documentation. set -e #set -x function usage(){ cat <<-EOF usage: compile-test-start-delayed key prog args... Start program prog with arguments args with some delay. There must be at least one argument in args and the last one must be a file or something that becomes a file when ".v" is appended. The delay is taken from a line in that file that contains the key, followed by a space and the delay in seconds (maybe somewhere in the middle of the line). The file must contain at most one line containing key. When there is no line containing key the delay is zero. As a special case, a delay equal to X means to record the fact that prog has been called on file by creating a file with suffix ".X" added to the name of file. The absence of this .X file can then be used, for instance, to check that prog has not been called on file. With delay equal to X, the real delay is 0. Fractional delays are properly handled. EOF } if [ $# -lt 3 ] ; then usage exit 1 fi # echo compile-test-start-delayed "$@" key="$1" file="${@: -1}" #echo key $key file "\"$file\"" shift # vio2vo needs a module name or a .vio file on the command line # support only module names for now if [ ! -f "$file" ] ; then if [ -f "$file.v" ] ; then file="$file.v" else exit 22 fi fi delay=$(sed -ne "/$key/ s/.*$key \([X0-9.]*\).*/\1/p" $file) if [ -z "$delay" ] ; then # echo compile-test-start-delayed: key $key not found in $file >&9 delay=0 elif [ "$delay" = "X" ] ; then echo compile-test-start-delayed: delay X for $file >&9 delay=0 touch $file.X fi # use string comparison on $delay to permit fractional values if [ $delay != 0 ] ; then date "+compile-test-start-delayed %T delay $delay for $*" >&9 sleep $delay date "+compile-test-start-delayed %T start now $*" >&9 else date "+compile-test-start-delayed %T start without delay $*" >&9 fi #set -x #echo "$@" set +e exec "$@" PG-4.5/ci/compile-tests/bin/coqc-delayed000077500000000000000000000001021426357011200200750ustar00rootroot00000000000000#!/bin/bash exec compile-test-start-delayed coqc-delay coqc "$@" PG-4.5/ci/compile-tests/bin/coqdep-delayed000077500000000000000000000001061426357011200204270ustar00rootroot00000000000000#!/bin/bash exec compile-test-start-delayed coqdep-delay coqdep "$@" PG-4.5/ci/compile-tests/cct-lib.el000066400000000000000000000373611426357011200167250ustar00rootroot00000000000000;; This file is part of Proof General. ;; ;; © Copyright 2020 - 2021 Hendrik Tews ;; ;; Authors: Hendrik Tews ;; Maintainer: Hendrik Tews ;; ;; SPDX-License-Identifier: GPL-3.0-or-later ;;; Commentary: ;; ;; Coq Compile Tests (cct) -- ;; ert tests for parallel background compilation for Coq ;; ;; This file contains common definitions for the automated tests of ;; parallel background compilation. ;; Require some libraries for the elisp compilation. When compiling, ;; nothing is loaded, but all Proof General directories are in the ;; load path. When this file is loaded as part of a test, proof-site ;; has been loaded but only the generic subdir is in the load path. ;; This file references variables from coq-compile-common and ;; functions from proof-shell, therefore coq-compile-common must be ;; required for compilation. When running a test, these files would be ;; loaded anyway when the test visits the first Coq file. For ;; executing tests, the coq subdir will only be added to the load path ;; when the first Coq file is visited. Therefore we have to add it ;; here via proof-ready-for-assistant. For compilation, we have to ;; require proof-site, otherwise proof-ready-for-assistant won't be ;; defined. (require 'proof-site) (proof-ready-for-assistant 'coq) (require 'coq-compile-common) (require 'ert) (defvar cct--debug-tests nil "Set to t to get more output during test runs.") (defvar cct-before-busy-waiting-hook nil "Hooks run by ‘cct-process-to-line’ before busy waiting.") (defvar cct-after-busy-waiting-hook nil "Hooks run by ‘cct-process-to-line’ after busy waiting.") (defmacro cct-implies (p q) "Short-circuit logical implication. Evaluate Q only if P is non-nil." `(or (not ,p) ,q)) (defun cct-list-subset (l1 l2) "Return t if all elements of L1 are in L2 (compared by `equal')" (let ((res t)) (while (and l1 res) (unless (member (pop l1) l2) (setq res nil))) res)) ;; Reimplementation of seq-set-equal-p for lists, because ;; seq-set-equal-p is not present before emacs 26. ;; XXX consider seq-set-equal-p when emacs 25 support is dropped. (defun cct-list-set-equal (l1 l2) "Return t if L1 and L2 contain the elements (compared by `equal')" (and (cct-list-subset l1 l2) (cct-list-subset l2 l1))) (defun cct-goto-line (line) "Put point on start of line LINE. Very similar to `goto-line', but the documentation of `goto-line' says, programs should use this piece of code." (goto-char (point-min)) (forward-line (1- line)) (cl-assert (eq (line-number-at-pos) line) nil "point not at required line in cct-goto-line")) (defun cct-library-vo-of-v-file (v-src-file) "Return .vo file name for V-SRC-FILE. Changes the suffix from .v to .vo. V-SRC-FILE must have a .v suffix." (concat v-src-file "o")) (defun cct-record-change-time (file) "Return cons of FILE and its modification time. The modification time is an emacs time value, it's nil if file cannot be accessed." (cons file (nth 5 (file-attributes file)))) (defun cct-record-change-times (files) "Return an assoc list of FILES with their modification times. The modification time is an emacs time value, it's nil if file cannot be accessed." (mapcar 'cct-record-change-time files)) (defun cct-split-change-times (file-change-times files) "Split assoc list FILE-CHANGE-TIMES. FILE-CHANGE-TIMES must be an assoc list and FILES must be a list of some of the keys of FILE-CHANGE-TIMES. This function returns two associations lists (as cons cell). The car contains those associations in FILE-CHANGE-TIMES with keys not in FILES, the cdr contains those with keys in FILES." (let (out in) (dolist (file-time file-change-times (cons out in)) (if (member (car file-time) files) (push file-time in) (push file-time out))))) (defun cct-replace-last-word (line word) "Replace last word in line LINE with WORD. In current buffer, go to the end of line LINE and one word backward. Replace the word there with WORD." (cct-goto-line line) (end-of-line) (backward-word) (kill-word 1) (insert word)) (defun cct-process-to-line (line) "Assert/retract to line LINE and wait until processing completed. Runs `cct-before-busy-waiting-hook' and `cct-after-busy-waiting-hook' before and after busy waiting for the prover. In many tests these hooks are not used." (when cct--debug-tests (message "assert/retrect to line %d in buffer %s" line (buffer-name))) (cct-goto-line line) (proof-goto-point) (run-hooks 'cct-before-busy-waiting-hook) (while (or proof-second-action-list-active (consp proof-action-list)) ;; (message "wait for coq/compilation with %d items queued\n" ;; (length proof-action-list)) ;; ;; accept-process-output without timeout returns rather quickly, ;; apparently most times without process output or any other event ;; to process. (accept-process-output nil 0.1)) (run-hooks 'cct-after-busy-waiting-hook)) (defun cct-wait-for-second-stage () "Wait until second stage compilation is complete. Runs `cct-before-busy-waiting-hook' and `cct-after-busy-waiting-hook' before and after busy waiting." (run-hooks 'cct-before-busy-waiting-hook) (when cct--debug-tests (message "%s start waiting for vok/vio2vo timer %s 2nd-stage-in-progress %s" (current-time-string) coq--par-second-stage-delay-timer coq--par-second-stage-in-progress)) (while (or coq--par-second-stage-delay-timer coq--par-second-stage-in-progress) (accept-process-output nil 0.5) (when cct--debug-tests (message "%s wait for vok/vio2vo timer %s 2nd-stage-in-progress %s" (current-time-string) coq--par-second-stage-delay-timer coq--par-second-stage-in-progress))) (run-hooks 'cct-after-busy-waiting-hook)) (defun cct-get-vanilla-span (line) "Get THE vanilla span for line LINE, report an error if there is none. PG uses a number of overlapping and non-overlapping spans (read overlays) in the asserted and queue region of the proof buffer, see the comments in generic/proof-script.el. Spans of type vanilla (stored at 'type in the span property list) are created for real commands (not for comments). They hold various information that is used, among others, for backtracking. This function returns the vanilla span that covers line LINE and reports a test failure if there is none or more than one vanilla spans." (let (spans) (cct-goto-line line) (setq spans (spans-filter (overlays-at (point)) 'type 'vanilla)) (should (eq (length spans) 1)) (car spans))) (defun cct-last-message-line () "Extract the last line from the *Messages* buffer. Useful if the message is not present in the echo area any more and `current-message' does not return anything." (with-current-buffer "*Messages*" (goto-char (point-max)) (forward-line -1) (buffer-substring (point) (- (point-max) 1)))) (defun cct-check-locked (line locked-state) "Check that line LINE has locked state LOCKED-STATE LOCKED-STATE must be 'locked or 'unlocked. This function checks whether line LINE is inside or outside the asserted (locked) region of the buffer and signals a test failure if not." (let ((locked (eq locked-state 'locked))) (when cct--debug-tests (message (concat "check lock state in buffer %s: line %d should be %s;\n" "\tlocked-span: %s ends at char %s in line %s") (buffer-name) line (if locked "locked" "unlocked") proof-locked-span (if (overlayp proof-locked-span) (span-end proof-locked-span) "") (if (overlayp proof-locked-span) (line-number-at-pos (span-end proof-locked-span)) ""))) (cl-assert (or locked (eq locked-state 'unlocked)) nil "test-check-locked 2nd argument wrong") (cct-goto-line line) (should (cct-implies locked (span-end proof-locked-span))) (should (or (and (not locked) (or (not proof-locked-span) (not (span-end proof-locked-span)))) (and (span-end proof-locked-span) (funcall (if locked '< '>) (point) (span-end proof-locked-span))))))) (defun cct-check-files-locked (line lock-state files) "Check that all FILES at line number LINE have lock state LOCK-STATE. LOCK-STATE must be either 'locked or 'unlocked. FILES must be list of file names." (when cct--debug-tests (message "check files %s at line %d: %s" (if (eq lock-state 'locked) "locked" "unlocked") line files)) (save-current-buffer (mapc (lambda (file) (find-file file) (cct-check-locked line lock-state)) files))) (defun cct-locked-ancestors (line ancestors) "Check that the vanilla span at line LINE has ANCESTORS recorded. The comparison treats ANCESTORS as set but the file names must be `equal' as strings. Ancestors are recoreded in the 'coq-locked-ancestors property of the vanilla spans of require commands, see the in-file documentation of coq/coq-par-compile.el." (let ((locked-ancestors (span-property (cct-get-vanilla-span line) 'coq-locked-ancestors))) (should (cct-list-set-equal locked-ancestors ancestors)))) (defun cct-file-unchanged (file time) "Check that modification time of FILE equals TIME. Used to check that FILE has not been changed since TIME was recorded before." (let ((file-time (nth 5 (file-attributes file)))) (when cct--debug-tests (message "file %s should be unchanged, recorded time: %s now: %s" file (format-time-string "%H:%M:%S.%3N" time) (format-time-string "%H:%M:%S.%3N" file-time))) (should (and file-time (equal time file-time))))) (defun cct-unmodified-change-times (file-time-assoc) "Check that files in FILE-TIME-ASSOC have not been changed. FILE-TIME-ASSOC must be an association list of files and emacs times as returned by `cct-record-change-times' or `cct-split-change-times'. This function checks that the modification time of files in FILE-TIME-ASSOC equals the time recorded in FILE-TIME-ASSOC, i.e., that the file has not been changed since FILE-TIME-ASSOC has been recorded." (when cct--debug-tests (message "Files should be unchanged: %s" (mapconcat (lambda (file-time) (car file-time)) file-time-assoc ", "))) (mapc (lambda (file-time-cons) (cct-file-unchanged (car file-time-cons) (cdr file-time-cons))) file-time-assoc)) (defun cct-file-newer (file time) "Check that FILE exists and its modification time is more recent than TIME." (let ((file-time (nth 5 (file-attributes file)))) (when cct--debug-tests (message "file %s in %s should be changed, recorded time: %s now: %s" file default-directory (if time (format-time-string "%H:%M:%S.%3N" time) "---") (if file-time (format-time-string "%H:%M:%S.%3N" file-time) "---"))) (should (and file-time (time-less-p time file-time))))) (defun cct-older-change-times (file-time-assoc) "Check that files exist and have been changed. FILE-TIME-ASSOC must be an association list of files and emacs times as returned by `cct-record-change-times' or `cct-split-change-times'. This function checks that the files in FILE-TIME-ASSOC do exist and that their modification time is more recent than in the association list, i.e., they have been updated or changed since recording the time in the association." (when cct--debug-tests (message "Files should have been changed: %s" (mapconcat (lambda (file-time) (car file-time)) file-time-assoc ", "))) (mapc (lambda (file-time-cons) (cct-file-newer (car file-time-cons) (cdr file-time-cons))) file-time-assoc)) (defun cct-files-are-readable (files) "Check that FILES exist and are readable." (when cct--debug-tests (message "Files should exist and be readable: %s" files)) (mapc (lambda (fname) (should (file-readable-p fname))) files)) (defun cct-files-dont-exist (files) "Check that FILES don't exist." (when cct--debug-tests (message "Files should not exist: %s" files)) (mapc (lambda (fname) (should-not (file-exists-p fname))) files)) (defun cct-generic-check-main-buffer (main-buf main-unlocked main-locked main-sum-line new-sum vo-times recompiled-files require-ancestors other-locked-files other-locked-line) "Perform various checks for recompilation in MAIN-BUF. MAIN-BUF is a buffer, MAIN-LOCKED and MAIN-SUM-line are line numbers in that buffer. NEW-SUM is a number as string. VO-TIMES is an association list of files and emacs times as returned by `cct-record-change-times' or `cct-split-change-times'. RECOMPILED-FILES is a list of some of the files in VO-TIMES. REQUIRE-ANCESTORS is a list of cons cells, each cons containing a line number in MAIN-BUF (which should contain a require) and a list of ancestor files that should get registered in the span of that require. OTHER-LOCKED-FILES is a list of buffers and OTHER-LOCKED-LINE is a common line number in those files. This function combines all the following tests in this order: - line MAIN-UNLOCKED in MAIN-BUF is unlocked - after replacing the sum on line MAIN-SUM-LINE with NEW-SUM, MAIN-BUF can be processed until line MAIN-LOCKED - files in VO-TIMES not listed in RECOMPILED-FILES have the same last change time as in VO-TIMES - files in RECOMPILED-FILES have a newer change time - the spans in lines in REQUIRE-ANCESTORS have precisely the ancestors registered as specified in REQUIRE-ANCESTORS. - all the buffers in OTHER-LOCKED-FILES are locked until line OTHER-LOCKED-LINE." (let (splitted) (set-buffer main-buf) (cct-check-locked main-unlocked 'unlocked) (cct-replace-last-word main-sum-line new-sum) (cct-process-to-line (1+ main-locked)) (cct-check-locked main-locked 'locked) (setq splitted (cct-split-change-times vo-times recompiled-files)) ;; (message "check file dates, unmodified %s, modified %s" ;; (car splitted) (cdr splitted)) (cct-unmodified-change-times (car splitted)) (cct-older-change-times (cdr splitted)) (mapc (lambda (line-ancestors) (cct-locked-ancestors (car line-ancestors) (cdr line-ancestors))) require-ancestors) (mapc (lambda (b) (set-buffer b) (cct-check-locked other-locked-line 'locked)) other-locked-files))) (defun cct-configure-proof-general () "Configure Proof General for test execution." (setq delete-old-versions t coq-compile-before-require t coq-compile-keep-going t proof-auto-action-when-deactivating-scripting 'retract proof-three-window-enable nil coq-compile-auto-save 'save-coq coq--debug-auto-compilation nil ) (custom-set-variables '(coq-compile-quick 'ensure-vo)) (when (< coq--internal-max-jobs 4) (custom-set-variables '(coq-max-background-compilation-jobs 4))) (message "config coq-max-background-compilation-jobs: %s (means %d)" coq-max-background-compilation-jobs coq--internal-max-jobs)) (defun configure-delayed-coq () "Configure PG to honor artificial delays in background compilation. Configure Proof General to use coqdep-delayed and coqc-delayed from directory ../bin. These scripts delay the start of the real coqdep and coqc as specified in the Coq soure file, see ../bin/compile-test-start-delayed. This function uses relative file names and must be called in a test subdirectory parallel to the bin directory." (let ((bin-dir (file-truename "../bin"))) (add-to-list 'exec-path bin-dir) (setenv "PATH" (concat bin-dir ":" (getenv "PATH"))) (custom-set-variables '(coq-dependency-analyzer "coqdep-delayed") '(coq-compiler "coqc-delayed")))) (provide 'cct-lib) PG-4.5/ci/coq-tests.el000066400000000000000000000322351426357011200145350ustar00rootroot00000000000000;;; coq-tests.el --- integration tests -*- lexical-binding: t; -*- ;;; Commentary: ;; ;;; Eval this to run the tests interactively ;; ;; (progn (load-file "coq-tests.el") (call-interactively #'ert)) (unless (and (boundp 'coq-test-dir) coq-test-dir) ; if set by ./test.sh (if buffer-file-name (setq coq-test-dir (file-name-directory buffer-file-name)) (error "You should set 'coq-test-dir, or run coq-test.el from a file buffer."))) (setq debug-on-error t) ; open the debugger on error -- may be commented-out (setq ert-batch-backtrace-right-margin 79) (require 'subr-x) ;; for (string-trim) ;;(require 'ert-async) ;;(setq ert-async-timeout 2) ;; Load Coq instance of Proof General now. (proof-ready-for-assistant 'coq) (require 'coq) ;;; Code: ; Exemple de code Lisp qui lance des commandes au prouveur en arrière-plan ; (defun has-error () ; "True if error in Proof" ; (eq 'error proof-shell-last-output-kind)) ; ; (defun test-process-invisible-split () ; (proof-shell-invisible-command "split." ; 'waitforit ; #'proof-done-invisible ; 'no-error-display 'no-response-display 'no-goals-display)) ; ; (defun test-process-invisible-tactics-then-reset-and-insert () ; (interactive) ; (let ((reset-cmd ; store backtracking info before proof search ; (format "Backtrack %s %s %s . " ; (int-to-string coq-last-but-one-statenum) ; (int-to-string coq-last-but-one-proofnum) ; 0))) ; ;; Toy example of proof search ; (while (not (has-error)) ; (message "Trying split.") ; (test-process-invisible-split)) ; ;; Reset to the previous state ; (proof-shell-invisible-command reset-cmd 'waitforit #'proof-done-invisible) ; ;; Insert (and re-process) the found script ; (proof-insert-sendback-command "split.\nsplit.\nsplit.\nQed."))) ; ; (test-process-invisible-tactics-then-reset-and-insert) (defun coq-test-full-path (basename) "Return the absolute path of BASENAME (a filename such as ./foo.v)." (concat coq-test-dir basename)) (defconst coq-test-file-prefix "coq_test_") (defun coq-test-init () "Ensure `coq' is loaded." (unless (featurep 'coq) (add-to-list 'load-path (locate-dominating-file coq-test-dir "proof-general.el")) (load "proof-general") (proofgeneral "coq"))) (defun coq-test-exit () "Exit the Coq process." (proof-shell-exit t)) ; (coq-test-on-file nil (message (buffer-file-name)) (message "OK") 42) ;; DEFINITION OF MOCKS, SEE `coq-mock' BELOW ;; Another solution would consist in using el-mock, mentioned in: ;; https://www.gnu.org/software/emacs/manual/html_mono/ert.html#Mocks-and-Stubs (defun coq-mock-proof-display-three-b (&rest rest) (message (concat "Skipping proof-display-three-b on input: " (pp-to-string rest))) ; Result: nil) ;; AVOID THE FOLLOWING ERROR: ;; Hit M-x proof-layout-windows to reset layout ;; Debugger entered--Lisp error: (error "Window # too small for splitting") ;; signal(error ("Window # too small for splitting")) ;; error("Window %s too small for splitting" #) ;; split-window(nil nil) ;; split-window-vertically() ;; proof-safe-split-window-vertically() ;; proof-select-three-b(nil # # smart) ;; proof-display-three-b(smart) ;; proof-layout-windows() ;; proof-multiple-frames-enable() ;; proof-shell-start() ;; proof-shell-ready-prover() (defun coq-mock (f) (require 'pg-response) ; load the feature defining proof-display-three-b first (cl-letf (;((symbol-function 'foo) #'mock-foo) ((symbol-function 'proof-display-three-b) #'coq-mock-proof-display-three-b)) (funcall f))) ;; Run on: ;; (coq-mock #'main) (defun coq-test-cmd (cmd) ;;(coq-test-on-file) ;;(coq-test-init) (proof-shell-invisible-command cmd 'waitforit #'proof-done-invisible 'no-error-display 'no-response-display 'no-goals-display)) (defun coq-set-flags (val flags) (when (member 'show-proof-stepwise flags) (setq coq-show-proof-stepwise val)) (when (member 'diffs-on flags) (if val (setq coq-diffs 'on) (setq coq-diffs 'off)))) (defun coq-fixture-on-file (file body &rest flags) "Fixture to setup the test env: open FILE if non-nil, or a temp file then evaluate the BODY function and finally tear-down (exit Coq)." ;; AVOID THE FOLLOWING ERROR: ;; Starting: -emacs ;; Debugger entered--Lisp error: (wrong-type-argument stringp nil) ;; file-name-directory(nil) ;; scomint-exec-1("coq" # nil ("-emacs")) ;; scomint-exec(# "coq" nil nil ("-emacs")) ;; scomint-make-in-buffer("coq" nil nil nil "-emacs") ;; apply(scomint-make-in-buffer "coq" nil nil nil "-emacs") ;; scomint-make("coq" nil nil "-emacs") ;; apply(scomint-make ("coq" nil nil "-emacs")) ;; proof-shell-start() ;; proof-shell-ready-prover() ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; For info on macros: https://mullikine.github.io/posts/macro-tutorial ;;; (pp (macroexpand '(macro args))) (save-excursion (let* (;; avoids bad width detection in batch mode (coq-auto-adapt-printing-width nil) (openfile (or file (concat (make-temp-file coq-test-file-prefix) ".v"))) ;; if FILE is nil, create a temporary Coq file, removed in the end (rmfile (unless file openfile)) (buffer (find-file openfile))) (message "Opening file %s ..." openfile) (unwind-protect (progn (coq-test-init) (with-current-buffer buffer (setq proof-splash-enable nil) (normal-mode) ;; or (coq-mode) (coq-set-flags t flags) (coq-mock body)))) (coq-test-exit) (coq-set-flags nil flags) (not-modified nil) ; Clear modification (kill-buffer buffer) (when rmfile (message "Removing file %s ..." rmfile)) (ignore-errors (delete-file rmfile))))) (defun coq-test-goto-before (comment) "Go just before COMMENT (a unique string in the .v file). For example, COMMENT could be (*test-definition*)" (goto-char (point-max)) (search-backward comment)) (defun coq-test-goto-after (comment) "Go just before COMMENT (a unique string in the .v file)." (goto-char (point-min)) (search-forward comment)) (defun coq-should-buffer-regexp (regexp &optional buffer-name) "Check REGEXP matches in BUFFER-NAME (*response* if nil)." (should (string-match-p regexp (string-trim (with-current-buffer (or buffer-name "*response*") (buffer-substring-no-properties (point-min) (point-max))))))) (defun coq-should-buffer-string (str &optional buffer-name) "Particular case of `coq-should-buffer-regexp'." (coq-should-buffer-regexp (regexp-quote str) buffer-name)) ;; TODO: Use https://github.com/rejeep/ert-async.el ;; and/or ERT https://www.gnu.org/software/emacs/manual/html_node/ert/index.html (ert-deftest 010_coq-test-running () "Test that the coqtop process is started properly." (coq-fixture-on-file nil (lambda () (coq-test-cmd "Print 0.") ;; (should (process-list)) ; wouldn't be a strong enough assert. (should (get-process "coq"))))) (ert-deftest 020_coq-test-definition () "Test *response* output after asserting a Definition." (coq-fixture-on-file (coq-test-full-path "test_stepwise.v") (lambda () (coq-test-goto-before "(*test-definition*)") (proof-goto-point) (proof-shell-wait) (coq-should-buffer-string "trois is defined")))) (ert-deftest 021_coq-test-regression-goto-point () "Regression test for proof-goto-point after a comment, PR #490" (coq-fixture-on-file (coq-test-full-path "test_stepwise.v") (lambda () (coq-test-goto-after "(*test-definition*)") (proof-goto-point) (proof-shell-wait) t))) (ert-deftest 030_coq-test-position () "Test locked region after Qed." (coq-fixture-on-file (coq-test-full-path "test_stepwise.v") (lambda () (coq-test-goto-before " (*test-lemma*)") (let ((proof-point (point))) (proof-goto-point) (proof-shell-wait) (should (equal (proof-queue-or-locked-end) proof-point)))))) (ert-deftest 040_coq-test-insert () "Test retract on insert from Qed." (coq-fixture-on-file (coq-test-full-path "test_stepwise.v") (lambda () (coq-test-goto-before " (*test-lemma*)") (proof-goto-point) (proof-shell-wait) (let ((proof-point (point))) (coq-test-goto-before "(*test-insert*)") (move-beginning-of-line nil) (insert "\n") ;; The locked end point should go up compared to before (should (< (proof-queue-or-locked-end) proof-point)))))) (ert-deftest 050_coq-test-lemma-false () "Test retract on proof error." (coq-fixture-on-file (coq-test-full-path "test_stepwise.v") (lambda () (coq-test-goto-before " (*test-lemma2*)") (let ((proof-point (save-excursion (coq-test-goto-after "(*error*)")))) (proof-goto-point) (proof-shell-wait) (coq-should-buffer-string "Error: Unable to unify \"false\" with \"true\".") (should (equal (proof-queue-or-locked-end) proof-point)))))) (ert-deftest 060_coq-test-wholefile () "Test `proof-process-buffer'." (coq-fixture-on-file (coq-test-full-path "test_wholefile.v") (lambda () (let ((proof-point (save-excursion (coq-test-goto-before "Theorem") (search-forward "Qed.")))) (proof-process-buffer) (proof-shell-wait) (should (equal (proof-queue-or-locked-end) proof-point)))))) (ert-deftest 070_coq-test-regression-wholefile-no-proof () "Regression test for no proof bug" (coq-fixture-on-file (coq-test-full-path "test_wholefile.v") (lambda () (proof-process-buffer) (proof-shell-wait) (goto-char (point-min)) (insert "(*.*)") (should (equal (proof-queue-or-locked-end) (point-min)))))) (ert-deftest 080_coq-test-regression-show-proof-stepwise() "Regression test for the \"Show Proof\" option" (coq-fixture-on-file (coq-test-full-path "test_stepwise.v") (lambda () (coq-test-goto-before " (*test-insert*)") (proof-goto-point) (proof-shell-wait) (coq-should-buffer-string "(fun (A : Prop) (proof_of_A : A) => ?Goal)")) 'show-proof-stepwise)) (ert-deftest 081_coq-test-regression-show-proof-diffs() "Test for Show Proof Diffs" (coq-fixture-on-file (coq-test-full-path "test_stepwise.v") (lambda () (coq-test-goto-before " (*test-insert*)") (proof-goto-point) (proof-shell-wait) ;; If coq--post-v811, it should be "Show Proof Diffs." otherwise "Show Proof." (if (coq--post-v811) (coq-should-buffer-string "(fun (A : Prop) (proof_of_A : A) => ?Goal)" "*coq*") (coq-should-buffer-string "(fun (A : Prop) (proof_of_A : A) => ?Goal)"))) 'show-proof-stepwise 'diffs-on)) (ert-deftest 090_coq-test-regression-Fail() "Test for Fail" (coq-fixture-on-file (coq-test-full-path "test_stepwise.v") (lambda () (coq-test-goto-before "(*FailNoTrace*)") (proof-goto-point) (proof-shell-wait) (proof-assert-next-command-interactive) ;; pas the comment (proof-assert-next-command-interactive) (proof-shell-wait) (if (coq--version< (coq-version) "8.10.0") (coq-should-buffer-string "The command has indeed failed with message: In nested Ltac calls to \"now (tactic)\" and \"easy\", last call failed. Tactic failure: Cannot solve this goal.") (coq-should-buffer-string "The command has indeed failed with message: Tactic failure: Cannot solve this goal." "*coq*"))))) ;; (coq-should-buffer-regexp (regexp-quote "The command has indeed failed with message: Tactic failure: Cannot solve this goal.") "*response*") (ert-deftest 091_coq-test-regression-Fail() "Test for Fail" (coq-fixture-on-file (coq-test-full-path "test_stepwise.v") (lambda () (coq-test-goto-before "(*FailTrace*)") (proof-goto-point) (proof-shell-wait) (proof-assert-next-command-interactive) ;; pas the comment (proof-assert-next-command-interactive) (proof-shell-wait) ;; If coq--post-v811, it should be "Show Proof Diffs." otherwise "Show Proof." (coq-should-buffer-string "The command has indeed failed with message: In nested Ltac calls to \"now (tactic)\" and \"easy\", last call failed. Tactic failure: Cannot solve this goal.")))) (ert-deftest 100_coq-test-proof-using-proof () "Test for insertion of Proof using annotations" (describe-function 'should) (coq-fixture-on-file (coq-test-full-path "test_proof_using.v") (lambda () (coq-test-goto-after "(*qed*)") (proof-goto-point) (proof-shell-wait) (proof-assert-next-command-interactive) (proof-shell-wait) ;; If coq--post-v811, it should be "Show Proof Diffs." otherwise "Show Proof." ;(coq-should-buffer-string "\"Proof using\" not set. M-x coq-insert-suggested-dependency or right click to add it. See also \‘coq-accept-proof-using-suggestion\’.") (save-excursion (coq-test-goto-before "(*proof*)") (backward-char 3) (should (span-at (point) 'proofusing)))))) (provide 'coq-tests) ;;; coq-tests.el ends here PG-4.5/ci/init-tests.el000066400000000000000000000014161426357011200147130ustar00rootroot00000000000000;;; init-tests.el --- tests init file -*- coding: utf-8; lexical-binding: t; -*- ;;; Commentary: ;; ;; Load this file to setup MELPA and tests-related packages. ;; ;;; Code: ;; Setup MELPA (require 'package) (setq gnutls-algorithm-priority "NORMAL:-VERS-TLS1.3") (add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/") t) (package-initialize) ;; Optionally: bootstrap use-package for declarative package specs ;(unless (package-installed-p 'use-package) ;(package-refresh-contents) ;(package-install 'use-package)) ;(eval-when-compile ; (require 'use-package)) ;; Bootstrap ert-async (unless (package-installed-p 'ert-async) (package-refresh-contents) (package-install 'ert-async)) (eval-when-compile (require 'ert-async)) ;;; init-tests.el ends here PG-4.5/ci/simple-tests/000077500000000000000000000000001426357011200147155ustar00rootroot00000000000000PG-4.5/ci/simple-tests/.gitignore000066400000000000000000000000121426357011200166760ustar00rootroot00000000000000*.success PG-4.5/ci/simple-tests/Makefile000066400000000000000000000007371426357011200163640ustar00rootroot00000000000000# This file is part of Proof General. # # © Copyright 2021 Hendrik Tews # # Authors: Hendrik Tews # Maintainer: Hendrik Tews # # SPDX-License-Identifier: GPL-3.0-or-later TESTS:=$(wildcard test-*.el) SUCCESS:=$(TESTS:.el=.success) all: $(SUCCESS) test-%.success: test-%.el emacs -batch -l ../../generic/proof-site.el -l $< \ -f ert-run-tests-batch-and-exit \ && touch $@ .PHONY: clean clean: rm -f *.vo *.glob *.vio *.vos *.vok .*.aux *.success PG-4.5/ci/simple-tests/README.md000066400000000000000000000012711426357011200161750ustar00rootroot00000000000000This directory contains a number of more simple tests, that can all run in the same directory. # Overview of existing tests test-coqtop-unavailable : open a file with PG when no coqtop is available test-omit-proofs : test the omit proofs feature coq-par-job-needs-compilation-quick : test coq-par-job-needs-compilation-quick by enumerating all possible cases test-prelude-correct : test that the Proof General prelude is correct test-qrhl : tests relating to the qRHL prover # Important conventions The Makefile runs all ERT tests in all `test-*.el` files. Therefore, the test should be written in a file matching this pattern. To run all tests in a single file, do `make test-*.success`. PG-4.5/ci/simple-tests/omit_test.v000066400000000000000000000007761426357011200171250ustar00rootroot00000000000000 Definition classical_logic : Prop := forall(P : Prop), ~~P -> P. (* automatic test marker 1 *) Lemma classic_excluded_middle : (forall(P : Prop), P \/ ~ P) -> classical_logic. Proof. intros H P H0. (* automatic test marker 2 *) specialize (H P). Abort. Lemma classic_excluded_middle : (forall(P : Prop), P \/ ~ P) -> classical_logic. Proof using. intros H P H0. specialize (H P). (* automatic test marker 3 *) destruct H. trivial. contradiction. Qed. (* automatic test marker 4 *) PG-4.5/ci/simple-tests/test-coq-par-job-needs-compilation-quick.el000066400000000000000000001126471426357011200250630ustar00rootroot00000000000000;;; test-coq-par-job-needs-compilation-quick.el --- test compilation internals ;; This file is part of Proof General. ;; Portions © Copyright 1994-2012 David Aspinall and University of Edinburgh ;; Portions © Copyright 2003-2018 Free Software Foundation, Inc. ;; Portions © Copyright 2001-2017 Pierre Courtieu ;; Portions © Copyright 2010, 2016 Erik Martin-Dorel ;; Portions © Copyright 2011-2013, 2016-2017 2021 Hendrik Tews ;; Portions © Copyright 2015-2017 Clément Pit-Claudel ;; Authors: Hendrik Tews ;; Maintainer: Hendrik Tews ;; SPDX-License-Identifier: GPL-3.0-or-later ;;; Commentary: ;; ;; This file file contains tests for `coq-par-job-needs-compilation-quick'. ;; It specifies for all combinations of `coq-compile-quick', existing ;; files and relative file ages the required result and side effects ;; of `coq-par-job-needs-compilation-quick'. There are more than 500 ;; single tests, which are all independent. One could therefore define ;; each of these single tests as an ERT test. However, one line in ;; `coq--par-job-needs-compilation-tests' generates between 1 and 4 of ;; such single tests. Therefore, making each an ERT test is probably ;; not worth the effort. ;; ;; Debugging hints: Set test--coq-par-only-test to the failing test ;; number and set coq--debug-auto-compilation to t. Don't forget to ;; reset all this when done. ;;; Code: (require 'proof-site) (proof-ready-for-assistant 'coq) (require 'coq-par-compile) (eval-when-compile (require 'cl-lib)) (defconst coq--par-job-needs-compilation-tests ;; for documentation see the doc string following the init value '( ;; present files | compilation? | delete | 'req-obj-file ;; ==================================================================== ;; all of src dep vo vio present ((src dep vo vio) (no-quick nil nil vo ) (quick nil nil vo ) (ensure-vo nil vio vo )) ((src dep vio vo) (no-quick nil nil vio) (quick nil nil vio) (ensure-vo nil nil vo )) ((src vo dep vio) (no-quick nil vo vio) (quick nil vo vio) (ensure-vo t nil vo )) ((src vo vio dep) (no-quick t vio vo ) (quick t vo vio) (ensure-vo t vio vo )) ((src vio dep vo) (no-quick nil vio vo ) (quick nil vio vo ) (ensure-vo nil vio vo )) ((src vio vo dep) (no-quick t vio vo ) (quick t vo vio) (ensure-vo t vio vo )) ;; present files | compilation? | delete | 'req-obj-file ((dep src vio vo) (no-quick nil nil vio) (quick nil nil vio) (ensure-vo nil nil vo )) ((dep src vo vio) (no-quick nil nil vo ) (quick nil nil vo ) (ensure-vo nil vio vo )) ((dep vo vio src) (no-quick t vio vo ) (quick t vo vio) (ensure-vo t vio vo )) ((dep vo src vio) (no-quick nil vo vio) (quick nil vo vio) (ensure-vo t nil vo )) ((dep vio vo src) (no-quick t vio vo ) (quick t vo vio) (ensure-vo t vio vo )) ((dep vio src vo) (no-quick nil vio vo ) (quick nil vio vo ) (ensure-vo nil vio vo )) ((vo src dep vio) (no-quick nil vo vio) (quick nil vo vio) (ensure-vo t nil vo )) ;; present files | compilation? | delete | 'req-obj-file ((vo src vio dep) (no-quick t vio vo ) (quick t vo vio) (ensure-vo t vio vo )) ((vo dep src vio) (no-quick nil vo vio ) (quick nil vo vio ) (ensure-vo t nil vo )) ((vo dep vio src) (no-quick t vio vo ) (quick t vo vio) (ensure-vo t vio vo )) ((vo vio src dep) (no-quick t vio vo ) (quick t vo vio ) (ensure-vo t vio vo )) ((vo vio dep src) (no-quick t vio vo ) (quick t vo vio ) (ensure-vo t vio vo )) ((vio src vo dep) (no-quick t vio vo ) (quick t vo vio ) (ensure-vo t vio vo )) ((vio src dep vo) (no-quick nil vio vo ) (quick nil vio vo ) (ensure-vo nil vio vo )) ((vio dep vo src) (no-quick t vio vo ) (quick t vo vio ) (ensure-vo t vio vo )) ;; present files | compilation? | delete | 'req-obj-file ((vio dep src vo) (no-quick nil vio vo ) (quick nil vio vo ) (ensure-vo nil vio vo )) ((vio vo dep src) (no-quick t vio vo ) (quick t vo vio ) (ensure-vo t vio vo )) ((vio vo src dep) (no-quick t vio vo ) (quick t vo vio ) (ensure-vo t vio vo )) ;; only src dep vo present ((src dep vo) (no-quick nil nil vo ) (quick nil nil vo ) (ensure-vo nil nil vo )) ((src vo dep) (no-quick t nil vo ) (quick t vo vio ) (ensure-vo t nil vo )) ((dep src vo) (no-quick nil nil vo ) (quick nil nil vo ) (ensure-vo nil nil vo )) ((dep vo src) (no-quick t nil vo ) (quick t vo vio ) (ensure-vo t nil vo )) ((vo src dep) (no-quick t nil vo ) (quick t vo vio ) (ensure-vo t nil vo )) ((vo dep src) (no-quick t nil vo ) (quick t vo vio ) (ensure-vo t nil vo )) ;; present files | compilation? | delete | 'req-obj-file ;; only src dep vio present ((src dep vio) (no-quick nil nil vio ) (quick nil nil vio ) (ensure-vo t nil vo )) ((src vio dep) (no-quick t vio vo ) (quick t nil vio ) (ensure-vo t vio vo )) ((dep src vio) (no-quick nil nil vio ) (quick nil nil vio ) (ensure-vo t nil vo )) ((dep vio src) (no-quick t vio vo ) (quick t nil vio ) (ensure-vo t vio vo )) ((vio src dep) (no-quick t vio vo ) (quick t nil vio ) (ensure-vo t vio vo )) ((vio dep src) (no-quick t vio vo ) (quick t nil vio ) (ensure-vo t vio vo )) ;; present files | compilation? | delete | 'req-obj-file ;; only src vo vio present ((src vo vio) (no-quick nil nil vo ) (quick nil nil vo ) (ensure-vo nil vio vo )) ((src vio vo) (no-quick nil nil vio) (quick nil nil vio) (ensure-vo nil nil vo )) ((vo src vio) (no-quick nil vo vio ) (quick nil vo vio ) (ensure-vo t nil vo )) ((vo vio src) (no-quick t vio vo ) (quick t vo vio ) (ensure-vo t vio vo )) ((vio src vo) (no-quick nil vio vo ) (quick nil vio vo ) (ensure-vo nil vio vo )) ((vio vo src) (no-quick t vio vo ) (quick t vo vio ) (ensure-vo t vio vo )) ;; present files | compilation? | delete | 'req-obj-file ;; only src dep present ((src dep) (no-quick t nil vo ) (quick t nil vio ) (ensure-vo t nil vo )) ((dep src) (no-quick t nil vo ) (quick t nil vio ) (ensure-vo t nil vo )) ;; only src vo present ((src vo) (no-quick nil nil vo ) (quick nil nil vo ) (ensure-vo nil nil vo )) ((vo src) (no-quick t nil vo ) (quick t vo vio ) (ensure-vo t nil vo )) ;; only src vio present ((src vio) (no-quick nil nil vio ) (quick nil nil vio ) (ensure-vo t nil vo )) ((vio src) (no-quick t vio vo ) (quick t nil vio ) (ensure-vo t vio vo )) ;; only src present ((src) (no-quick t nil vo ) (quick t nil vio ) (ensure-vo t nil vo )) ;; present files | compilation? | delete | 'req-obj-file ;; ;; test cases for some objects with identical time stamp ;; ;; 4 files with same time stamp (((src vo dep vio)) (no-quick t vio vo ) (quick t vo vio) (ensure-vo t vio vo )) ;; 3 files with same time stamp (((src vo dep) vio) (no-quick nil vo vio ) (quick nil vo vio ) (ensure-vo t nil vo )) ((vio (src vo dep)) (no-quick t vio vo ) (quick t vo vio ) (ensure-vo t vio vo )) (((src vo vio) dep) (no-quick t vio vo ) (quick t vo vio ) (ensure-vo t vio vo )) ((dep (src vo vio)) (no-quick t vio vo ) (quick t vo vio ) (ensure-vo t vio vo )) (((src dep vio) vo) (no-quick nil vio vo ) (quick nil vio vo ) (ensure-vo nil vio vo )) ;; present files | compilation? | delete | 'req-obj-file ((vo (src dep vio)) (no-quick t vio vo ) (quick t vo vio ) (ensure-vo t vio vo )) (((vo dep vio) src) (no-quick t vio vo ) (quick t vo vio ) (ensure-vo t vio vo )) ((src (vo dep vio)) (no-quick t vio vo ) (quick t vo vio) (ensure-vo t vio vo )) ;; 2 times 2 files with same time stamp (((src vo) (dep vio)) (no-quick t vio vo ) (quick t vo vio) (ensure-vo t vio vo )) (((dep vio) (src vo)) (no-quick t vio vo ) (quick t vo vio) (ensure-vo t vio vo )) (((src dep) (vo vio)) ;; could also use the vio as 'req-obj-file in the first 2 cases here (no-quick nil nil vo ) (quick nil nil vo ) (ensure-vo nil vio vo )) (((vo vio) (src dep)) (no-quick t vio vo ) (quick t vo vio) (ensure-vo t vio vo )) (((src vio) (vo dep)) (no-quick t vio vo ) (quick t vo vio) (ensure-vo t vio vo )) ;; present files | compilation? | delete | 'req-obj-file (((vo dep) (src vio)) (no-quick t vio vo ) (quick t vo vio) (ensure-vo t vio vo )) ;; 2 files with same time stamp (((src vo) dep vio) (no-quick nil vo vio) (quick nil vo vio) (ensure-vo t nil vo )) (((src vo) vio dep) (no-quick t vio vo ) (quick t vo vio) (ensure-vo t vio vo )) ((dep (src vo) vio) (no-quick nil vo vio) (quick nil vo vio) (ensure-vo t nil vo )) ((dep vio (src vo)) (no-quick t vio vo ) (quick t vo vio) (ensure-vo t vio vo )) ((vio (src vo) dep) (no-quick t vio vo ) (quick t vo vio) (ensure-vo t vio vo )) ((vio dep (src vo)) (no-quick t vio vo ) (quick t vo vio) (ensure-vo t vio vo )) ;; present files | compilation? | delete | 'req-obj-file (((src dep) vo vio) (no-quick nil nil vo ) (quick nil nil vo ) (ensure-vo nil vio vo )) (((src dep) vio vo) (no-quick nil nil vio) (quick nil nil vio) (ensure-vo nil nil vo )) ((vo (src dep) vio) (no-quick nil vo vio) (quick nil vo vio) (ensure-vo t nil vo )) ((vo vio (src dep)) (no-quick t vio vo ) (quick t vo vio) (ensure-vo t vio vo )) ((vio (src dep) vo) (no-quick nil vio vo ) (quick nil vio vo ) (ensure-vo nil vio vo )) ((vio vo (src dep)) (no-quick t vio vo ) (quick t vo vio) (ensure-vo t vio vo )) (((src vio) vo dep) (no-quick t vio vo ) (quick t vo vio) (ensure-vo t vio vo )) (((src vio) dep vo) (no-quick nil vio vo ) (quick nil vio vo ) (ensure-vo nil vio vo )) ((vo (src vio) dep) (no-quick t vio vo ) (quick t vo vio) (ensure-vo t vio vo )) ;; present files | compilation? | delete | 'req-obj-file ((vo dep (src vio)) (no-quick t vio vo ) (quick t vo vio) (ensure-vo t vio vo )) ((dep (src vio) vo) (no-quick nil vio vo ) (quick nil vio vo ) (ensure-vo nil vio vo )) ((dep vo (src vio)) (no-quick t vio vo ) (quick t vo vio) (ensure-vo t vio vo )) (((vo dep) src vio) (no-quick nil vo vio ) (quick nil vo vio ) (ensure-vo t nil vo )) (((vo dep) vio src) (no-quick t vio vo ) (quick t vo vio) (ensure-vo t vio vo )) ((src (vo dep) vio) (no-quick nil vo vio) (quick nil vo vio) (ensure-vo t nil vo )) ((src vio (vo dep)) (no-quick t vio vo ) (quick t vo vio) (ensure-vo t vio vo )) ((vio (vo dep) src) (no-quick t vio vo ) (quick t vo vio) (ensure-vo t vio vo )) ((vio src (vo dep)) (no-quick t vio vo ) (quick t vo vio) (ensure-vo t vio vo )) ;; present files | compilation? | delete | 'req-obj-file (((vo vio) src dep) (no-quick t vio vo ) (quick t vo vio) (ensure-vo t vio vo )) (((vo vio) dep src) (no-quick t vio vo ) (quick t vo vio) (ensure-vo t vio vo )) ((src (vo vio) dep) (no-quick t vio vo ) (quick t vo vio) (ensure-vo t vio vo )) ((src dep (vo vio)) ;; could also use the vio as 'req-obj-file in the first 2 cases here (no-quick nil nil vo ) (quick nil nil vo ) (ensure-vo nil vio vo )) ((dep (vo vio) src) (no-quick t vio vo ) (quick t vo vio) (ensure-vo t vio vo )) ((dep src (vo vio)) ;; could also use the vio as 'req-obj-file in the first 2 cases here (no-quick nil nil vo ) (quick nil nil vo ) (ensure-vo nil vio vo )) (((dep vio) src vo) (no-quick nil vio vo ) (quick nil vio vo ) (ensure-vo nil vio vo )) (((dep vio) vo src) (no-quick t vio vo ) (quick t vo vio) (ensure-vo t vio vo )) ((src (dep vio) vo) (no-quick nil vio vo ) (quick nil vio vo ) (ensure-vo nil vio vo )) ;; present files | compilation? | delete | 'req-obj-file ((src vo (dep vio)) (no-quick t vio vo ) (quick t vo vio) (ensure-vo t vio vo )) ((vo (dep vio) src) (no-quick t vio vo ) (quick t vo vio) (ensure-vo t vio vo )) ((vo src (dep vio)) (no-quick t vio vo ) (quick t vo vio) (ensure-vo t vio vo )) ;; 2 files with the same time stamp out of 3 files ;; without vio (((src dep vo)) (no-quick t nil vo ) (quick t vo vio) (ensure-vo t nil vo )) (((src dep) vo) (no-quick nil nil vo ) (quick nil nil vo ) (ensure-vo nil nil vo )) ((vo (src dep)) (no-quick t nil vo ) (quick t vo vio) (ensure-vo t nil vo )) (((src vo) dep) (no-quick t nil vo ) (quick t vo vio) (ensure-vo t nil vo )) ((dep (src vo)) (no-quick t nil vo ) (quick t vo vio) (ensure-vo t nil vo )) (((dep vo) src) (no-quick t nil vo ) (quick t vo vio) (ensure-vo t nil vo )) ;; present files | compilation? | delete | 'req-obj-file ((src (dep vo)) (no-quick t nil vo ) (quick t vo vio) (ensure-vo t nil vo )) ;; without vo (((src dep vio)) (no-quick t vio vo ) (quick t nil vio) (ensure-vo t vio vo )) (((src dep) vio) (no-quick nil nil vio ) (quick nil nil vio ) (ensure-vo t nil vo )) ((vio (src dep)) (no-quick t vio vo ) (quick t nil vio) (ensure-vo t vio vo )) (((src vio) dep) (no-quick t vio vo ) (quick t nil vio) (ensure-vo t vio vo )) ((dep (src vio)) (no-quick t vio vo ) (quick t nil vio) (ensure-vo t vio vo )) (((dep vio) src) (no-quick t vio vo ) (quick t nil vio) (ensure-vo t vio vo )) ((src (dep vio)) (no-quick t vio vo ) (quick t nil vio) (ensure-vo t vio vo )) ;; without dep (((src vio vo)) (no-quick t vio vo ) (quick t vo vio) (ensure-vo t vio vo )) (((src vio) vo) (no-quick nil vio vo ) (quick nil vio vo ) (ensure-vo nil vio vo )) ((vo (src vio)) (no-quick t vio vo ) (quick t vo vio) (ensure-vo t vio vo )) (((src vo) vio) (no-quick nil vo vio ) (quick nil vo vio ) (ensure-vo t nil vo )) ;; present files | compilation? | delete | 'req-obj-file ((vio (src vo)) (no-quick t vio vo ) (quick t vo vio) (ensure-vo t vio vo )) (((vio vo) src) (no-quick t vio vo ) (quick t vo vio) (ensure-vo t vio vo )) ((src (vio vo)) ;; could also use the vio as 'req-obj-file in the first 2 cases here (no-quick nil nil vo ) (quick nil nil vo ) (ensure-vo nil vio vo )) ;; 2 files with identical time stamp out of 2 files (((src dep)) (no-quick t nil vo ) (quick t nil vio ) (ensure-vo t nil vo )) (((src vo)) (no-quick t nil vo ) (quick t vo vio ) (ensure-vo t nil vo )) (((src vio)) (no-quick t vio vo ) (quick t nil vio ) (ensure-vo t vio vo )) ) "Test and result specification for `coq-par-job-needs-compilation-quick'. List of tests. A test is a list of 4 elements. The first element, a list, specifies the existing files and their relative age. In there, `src' stands for the source (x.v) file, `dep' for a (already compiled) dependency (dep.vo or dep.vio), `vo' for the .vo file (x.vo) and `vio' for the .vio file (x.vio). A label in the list denotes an existing file, a missing label a missing file. The first element is the oldest file, the last element the newest file. A sublist specifies a set of files with identical time stamps. For example, ``(src (vo vio) dep)'' specifies source is older than .vo and .vio, .vo and .vio have identical last modification time stamps and .vo and .vio are older than the dependency. Elements 2-4 of a test specify the results and side effects of `coq-par-job-needs-compilation-quick' for all settings of `coq-compile-quick' on the file configuration described in element 1. The options `quick-no-vio2vo' and `quick-and-vio2vo' are specified together with label `quick'. Each result and side effect specification (also called a variant in the source code below) is itself a list of 4 elements. Element 1 is the value for `coq-compile-quick', where `quick' denotes both `quick-no-vio2vo' and `quick-and-vio2vo'. Element 2 specifies the result of `coq-par-job-needs-compilation-quick', nil for don't compile, t for do compile. Elements 3-4 specify side effects. Element 3 which file must be deleted, where nil means no file must be deleted. Element 4 specifies which file name must be stored in the `required-obj-file' property of the job. This file will be used as the compiled module library. In case compilation is needed (element 2 equals t), this is the target of the compilation. This list contains 1 test for all possible file configuration and relative ages.") (defun coq-par-test-flatten-files (file-descr) "Flatten a file description test case list FILE-DESCR into a list of files." (let (result) (dolist (f file-descr result) (if (listp f) (setq result (append f result)) (push f result))))) (defun test-coq-par-test-data-invarint () "Wellformedness check for the test specifications." (mapc (lambda (test) (let ((test-id (format "%s" (car test)))) ;; a test is a list of 4 elements and the first element is a list itself (should (and (eq (length test) 4) (listp (car test)))) (mapc (lambda (variant) ;; a variant is a list of 4 elements (should (eq (length variant) 4)) (let ((files (coq-par-test-flatten-files (car test))) (quick-mode (car variant)) (compilation-result (nth 1 variant)) (delete-result (nth 2 variant)) (req-obj-result (nth 3 variant))) ;; the delete field, when set, must be a member of the files list (should (or (not delete-result) (member delete-result files))) ;; 8.4 compatibility check (when (and (or (eq quick-mode 'no-quick) (eq quick-mode 'ensure-vo)) (not (member 'vio files))) (should (not delete-result)) (should (eq compilation-result (not (eq (car (last (car test))) 'vo))))))) (cdr test)))) coq--par-job-needs-compilation-tests)) (defun test-coq-par-sym-to-file (dir sym) "Convert a test file symbol SYM to a file name in directory DIR." (let ((file (cond ((eq sym 'src) "a.v") ((eq sym 'dep) "dep.vo") ((eq sym 'vo) "a.vo") ((eq sym 'vio) "a.vio") (t (cl-assert nil))))) (concat dir "/" file))) (defun test-coq-par-one-test (counter dir file-descr variant dep-just-compiled) "Do one test for one specific `coq-compile-quick' value. This function creates the files in DIR, sets up a job with the necessary fields, calls `coq--par-job-needs-compilation-tests' and test the result and side effects wth `assert'." (let ((id (format "%s: %s %s%s" counter (car variant) file-descr (if dep-just-compiled " just" ""))) (job (make-symbol "coq-compile-job-symbol")) (module-vo-file (concat dir "/a.vo")) (quick-mode (car variant)) (compilation-result (nth 1 variant)) (delete-result (nth 2 variant)) (req-obj-result (nth 3 variant)) (different-counter 5) (same-counter 5) (different-not-ok t) (same-not-ok t) (last-different-time-stamp '(0 0)) (file-descr-flattened (coq-par-test-flatten-files file-descr)) same-time-stamp file-list obj-mod-result result) (message "test case %d/576: %s %s just-compiled: %s" counter (car variant) file-descr dep-just-compiled) (when (not compilation-result) (setq obj-mod-result req-obj-result)) (ignore-errors (delete-directory dir t)) (make-directory dir) (setq coq-compile-quick quick-mode) (put job 'vo-file module-vo-file) (put job 'src-file (coq-library-src-of-vo-file module-vo-file)) (put job 'youngest-coqc-dependency '(0 0)) (put job 'name id) ;; create files in order (while different-not-ok ;; (message "enter different loop %s at %s" ;; different-counter (current-time)) (setq different-not-ok nil) (setq different-counter (1- different-counter)) (cl-assert (> different-counter 0) nil "create files with different time stamps failed") (dolist (same-descr file-descr) (when (symbolp same-descr) (setq same-descr (list same-descr))) (setq file-list (mapcar (lambda (sym) (test-coq-par-sym-to-file dir sym)) same-descr)) ;; (message "try %s files %s" same-descr file-list) (setq same-counter 5) (setq same-not-ok t) (while same-not-ok (setq same-counter (1- same-counter)) (cl-assert (> same-counter 0) nil "create files with same time stamp filed") (dolist (file file-list) (with-temp-file file t)) ;; check now that all the files in file-list have the same time stamp (setq same-not-ok nil) (setq same-time-stamp (nth 5 (file-attributes (car file-list)))) ;; (message "got first time stamp %s" same-time-stamp) (dolist (file (cdr file-list)) (let ((ots (nth 5 (file-attributes file)))) ;; (message "got other time stamp %s" ots) (unless (equal same-time-stamp ots) (setq same-not-ok t))))) ;; (message "successful finished %s" same-descr) (when (member 'dep same-descr) (put job 'youngest-coqc-dependency (nth 5 (file-attributes (test-coq-par-sym-to-file dir 'dep))))) ;; (message "XX %s < %s = %s" ;; last-different-time-stamp same-time-stamp ;; (time-less-p last-different-time-stamp same-time-stamp)) (unless (time-less-p last-different-time-stamp same-time-stamp) ;; error - got the same time stamp ;; (message "unsuccsessful - need different retry") (setq different-not-ok t)) (setq last-different-time-stamp same-time-stamp) (sleep-for 0 15))) (when dep-just-compiled (put job 'youngest-coqc-dependency 'just-compiled)) (setq result (coq-par-job-needs-compilation-quick job)) ;; check result (when coq--debug-auto-compilation (message "check result")) (should (eq result compilation-result)) ;; check file deletion (when coq--debug-auto-compilation (message "check file deletion")) (should (or (not delete-result) (not (file-attributes (test-coq-par-sym-to-file dir delete-result))))) ;; check no other file is deleted (when coq--debug-auto-compilation (message "check no other file is deleted")) (dolist (f file-descr-flattened) (unless (eq f delete-result) (should (file-attributes (test-coq-par-sym-to-file dir f))))) ;; check value of 'required-obj-file property (when coq--debug-auto-compilation (message "check value of 'required-obj-file property")) (should (equal (get job 'required-obj-file) (test-coq-par-sym-to-file dir req-obj-result))) ;; check 'obj-mod-time property (when coq--debug-auto-compilation (message "check 'obj-mod-time property with obj-mod-result %s" (if obj-mod-result "set" "unset"))) (if obj-mod-result (should (equal (get job 'obj-mod-time) (nth 5 (file-attributes (test-coq-par-sym-to-file dir obj-mod-result))))) (should (not (get job 'obj-mod-time)))) ;; check 'use-quick property (when coq--debug-auto-compilation (message "check 'use-quick property")) (should (eq (not (not (and compilation-result (eq req-obj-result 'vio)))) (eq (get job 'use-quick) 'vio))) ;; Check vio2vo-needed property: this property is not present in ;; the test specification because it can be logically derived. The ;; property must be present, if and only if vio2vo mode is ;; selected, a vio will be produced and the vo is unusable, either ;; because it is not present or it must be deleted. (when coq--debug-auto-compilation (message "check vio2vo-needed property")) (should (eq (and (eq quick-mode 'quick-and-vio2vo) (eq req-obj-result 'vio) (or (eq delete-result 'vo) (not (member 'vo file-descr-flattened)))) (eq (get job 'second-stage) 'vio2vo))) (ignore-errors (delete-directory dir t)))) (defvar test--coq-par-counter 0 "Stupid counter.") (defconst test--coq-par-only-test nil "If non-nil, run this test only. Must be nil under normal circumstances. Can be set to a number for debugging, then only this test number is run.") (defun test-coq-par-one-test-wrapper (counter dir file-descr variant dep-just-compiled) "Wrapper around `test-coq-par-one-test'." (when (or (not test--coq-par-only-test) (and test--coq-par-only-test (eq test--coq-par-only-test test--coq-par-counter))) (test-coq-par-one-test counter dir file-descr variant dep-just-compiled))) (defun test-coq-par-one-spec (dir files variant dep-just-compiled) "Run one test for one variant and split it for the 2 quick settings." (if (eq (car variant) 'quick) (progn (test-coq-par-one-test-wrapper test--coq-par-counter dir files (cons 'quick-no-vio2vo (cdr variant)) dep-just-compiled) (setq test--coq-par-counter (1+ test--coq-par-counter)) (test-coq-par-one-test-wrapper test--coq-par-counter dir files (cons 'quick-and-vio2vo (cdr variant)) dep-just-compiled)) (test-coq-par-one-test-wrapper test--coq-par-counter dir files variant dep-just-compiled)) (setq test--coq-par-counter (1+ test--coq-par-counter))) (defun test-coq-par-job-needs-compilation-quick-fun (dir) "Check test data wellformedness and run all the tests." (when coq--debug-auto-compilation (message "check coq--par-job-needs-compilation-tests invariant")) (test-coq-par-test-data-invarint) (setq test--coq-par-counter 1) (mapc (lambda (test) (mapc (lambda (variant) (test-coq-par-one-spec dir (car test) variant nil) (when (eq (car (last (car test))) 'dep) (test-coq-par-one-spec dir (car test) variant t))) (cdr test))) coq--par-job-needs-compilation-tests)) (ert-deftest test-coq-par-job-needs-compilation-quick () "Run all tests for coq-par-job-needs-compilation-quick." ;;(setq coq--debug-auto-compilation t) (test-coq-par-job-needs-compilation-quick-fun (make-temp-name "/tmp/coq-par-test"))) ;;; test-coq-par-job-needs-compilation-quick.el ends here PG-4.5/ci/simple-tests/test-coqtop-unavailable.el000066400000000000000000000011311426357011200217760ustar00rootroot00000000000000;; This file is part of Proof General. ;; ;; © Copyright 2021 Hendrik Tews ;; ;; Authors: Hendrik Tews ;; Maintainer: Hendrik Tews ;; ;; SPDX-License-Identifier: GPL-3.0-or-later ;;; Commentary: ;; ;; Test that Proof General can open Coq files even when coqtop is ;; unavailable. (ert-deftest coqtop-unavailable () "Proof General can open Coq files even when coqtop is unavailable.." (setq coq-prog-name "unavailable-program") ;; ensure coq-prog-name cannot be found (should (not (locate-file coq-prog-name exec-path))) (find-file "simple.v") (coq-prog-args)) PG-4.5/ci/simple-tests/test-omit-proofs.el000066400000000000000000000137041426357011200204770ustar00rootroot00000000000000;; This file is part of Proof General. ;; ;; © Copyright 2021 Hendrik Tews ;; ;; Authors: Hendrik Tews ;; Maintainer: Hendrik Tews ;; ;; SPDX-License-Identifier: GPL-3.0-or-later ;;; Commentary: ;; ;; Test the omit proofs feature ;; ;; Test that with proof-omit-proofs-option ;; - the proof _is_ processed when using a prefix argument ;; - in this case the proof as normal locked color ;; - without prefix arg, the proof is omitted ;; - the proof has omitted color then ;; - stuff before the proof still has normal color ;; reimplement seq-some from the seq package ;; seq-some not present in emacs 24 ;; XXX consider to switch to seq-some when support for emacs 24 is dropped (defun list-some (pred list) "Return non-nil if PRED is satisfied for at least one element of LIST. If so, return the first non-nil value returned by PRED." (let (res) (while (and (consp list) (not res)) (setq res (funcall pred (car list))) (setq list (cdr list))) res)) (defun wait-for-coq () "Wait until processing is complete." (while (or proof-second-action-list-active (consp proof-action-list)) ;; (message "wait for coq/compilation with %d items queued\n" ;; (length proof-action-list)) ;; ;; accept-process-output without timeout returns rather quickly, ;; apparently most times without process output or any other event ;; to process. (accept-process-output nil 0.1))) (defun overlay-less (a b) "Compare two overlays. Return t if overlay A has smaller size than overlay B and should therefore have a higher priority." (let ((sa (- (overlay-end a) (overlay-start a))) (sb (- (overlay-end b) (overlay-start b)))) (<= sa sb))) (defun overlays-at-point-sorted () "Return overlays at point in decreasing order of priority. Works only if no overlays has a priority property. Same '(overlays-at (point) t)', except that it also works on Emacs <= 25." (sort (overlays-at (point) t) 'overlay-less)) (defun first-overlay-face () "Return the face of the first overlay/span that has a face property. Properties configured in that face are in effect. Properties not configured there may be taken from faces with less priority." (list-some (lambda (ov) (overlay-get ov 'face)) ;; Need to sort overlays oneself, because emacs 25 returns overlays ;; in increasing instead of decreasing priority. (overlays-at-point-sorted))) (ert-deftest omit-proofs-omit-and-not-omit () "Test the omit proofs feature. In particular, test that with proof-omit-proofs-option configured: - the proof _is_ processed when using a prefix argument - in this case the proof as normal locked color - without prefix arg, the proof is omitted - the proof has omitted color then - stuff before the proof still has normal color " (setq proof-omit-proofs-option t proof-three-window-enable nil) (find-file "omit_test.v") ;; Check 1: check that the proof is valid and omit can be disabled (message "1: check that the proof is valid and omit can be disabled") (should (search-forward "automatic test marker 4" nil t)) (forward-line -1) ;; simulate C-u prefix argument (proof-goto-point '(4)) (wait-for-coq) ;; Look into the *coq* buffer to find out whether the proof was ;; processed fully without error. This is necessary for Coq >= 8.11. ;; Coq < 8.11 prints a defined message, which ends up in *response*, ;; for those versions it would be better to simply check the ;; *response* buffer. However, consolidating all this is not easy, ;; therefore I check the message in *coq* also for Coq < 8.11. (with-current-buffer "*coq*" ;; output *coq* content for debugging ;; (message ;; "*coq* content:\n%s" ;; ;; (max 0 (- (point-max) 400)) ;; (buffer-substring-no-properties (point-min) (point-max))) (goto-char (point-max)) ;; goto second last prompt (should (search-backward "" nil t 2)) ;; move behind prompt (forward-char 9) ;; There should be a Qed with no error or message after it (should (or ;; for Coq 8.11 and later (looking-at "Qed\\.\n\nCoq <") ;; for Coq 8.10 and earlier ;; in 8.9 the message is on 1 line, in 8.10 on 3 (looking-at "Qed\\.\n\n?classic_excluded_middle is defined")))) ;; Check 2: check proof-locked-face is active at marker 2 and 3 (message "2: check proof-locked-face is active at marker 2 and 3") (should (search-backward "automatic test marker 2" nil t)) (should (eq (first-overlay-face) 'proof-locked-face)) (should (search-forward "automatic test marker 3" nil t)) (should (eq (first-overlay-face) 'proof-locked-face)) ;; Check 3: check that the second proof is omitted (message "3: check that the second proof is omitted") ;; first retract (should (search-backward "automatic test marker 1" nil t)) (proof-goto-point) (wait-for-coq) ;; move forward again (should (search-forward "automatic test marker 4" nil t)) (forward-line -1) (proof-goto-point) (wait-for-coq) (with-current-buffer "*response*" (goto-char (point-min)) ;; There should be a declared message. (should (looking-at "classic_excluded_middle is declared"))) ;; Check 4: check proof-omitted-proof-face is active at marker 3 (message "4: check proof-omitted-proof-face is active at marker 3") (should (search-backward "automatic test marker 3" nil t)) ;; debug overlay order ;; (mapc ;; (lambda (ov) ;; (message "OV %d-%d face %s" ;; (overlay-start ov) (overlay-end ov) (overlay-get ov 'face))) ;; (overlays-at-point-sorted)) (should (eq (first-overlay-face) 'proof-omitted-proof-face)) ;; Check 5: check proof-locked-face is active at marker 1 and 2 (message "5: check proof-locked-face is active at marker 1 and 2") (should (search-backward "automatic test marker 1" nil t)) (should (eq (first-overlay-face) 'proof-locked-face)) (should (search-forward "automatic test marker 2" nil t)) (should (eq (first-overlay-face) 'proof-locked-face))) PG-4.5/ci/simple-tests/test-prelude-correct.el000066400000000000000000000053721426357011200213220ustar00rootroot00000000000000;; This file is part of Proof General. ;; ;; © Copyright 2021 Hendrik Tews ;; ;; Authors: Hendrik Tews ;; Maintainer: Hendrik Tews ;; ;; SPDX-License-Identifier: GPL-3.0-or-later ;;; Commentary: ;; ;; Test that the Proof General prelude is correct. ;; ;; I use Proof General prelude here to refer to the initialization ;; commands that Proof General sends to Coq before the first command ;; of the script. ;; This test shows different behaviour before 8.10. When the problem ;; is fixed, I expect that the version distinction is no longer ;; necessary and can be deleted. ;; ;; Load stuff for `coq--version<' (require 'proof-site) (proof-ready-for-assistant 'coq) (require 'coq-system) (defconst coq--post-v810 (coq--post-v810) "t if Coq is more recent than 8.9") (message "goal present tests run with Coq version %s; post-v810: %s" (coq-version t) coq--post-v810) ;;; Coq source code for tests (defconst coq-src-proof "Check 1." "Coq source code for checking the prelude.") ;;; utility functions (defun record-buffer-content (buf) "Record buffer content of BUF via `message' for debugging. BUF should be a string." (with-current-buffer buf (let ((content (buffer-substring-no-properties (point-min) (point-max)))) (message "%s buffer contains %d chars: %s" buf (length content) content)))) (defun wait-for-coq () "Wait until processing is complete." (while (or proof-second-action-list-active (consp proof-action-list)) ;; (message "wait for coq/compilation with %d items queued\n" ;; (length proof-action-list)) ;; ;; accept-process-output without timeout returns rather quickly, ;; apparently most times without process output or any other event ;; to process. (accept-process-output nil 0.1))) ;;; define the test (ert-deftest prelude-correct () :expected-result (if coq--post-v810 :passed :failed) "Test that the Proof Genneral prelude is correct. Check that all the commands that Proof General sends as initialization before the first script command to Coq do not yield an error." (message "prelude-correct test: Check the Proof General prelude") (setq proof-three-window-enable nil) (let (buffer) (unwind-protect (progn (find-file "goals.v") (setq buffer (current-buffer)) (insert coq-src-proof) (proof-goto-point) (wait-for-coq) (record-buffer-content "*coq*") ;; check that there is no error in *coq* (with-current-buffer "*coq*" (goto-char (point-min)) (should (not (re-search-forward "Error:" nil t))))) ;; clean up (when buffer (with-current-buffer buffer (set-buffer-modified-p nil)) (kill-buffer buffer))))) PG-4.5/ci/simple-tests/test-qrhl.el000066400000000000000000000012421426357011200171610ustar00rootroot00000000000000;; This file is part of Proof General. ;; ;; © Copyright 2022 Dominique Unruh ;; ;; Authors: Dominique Unruh ;; Maintainer: Dominique Unruh ;; ;; SPDX-License-Identifier: GPL-3.0-or-later ;;; Commentary: ;; ;; Tests related to the qRHL prover ;; (ert-deftest load-qrhl-input () :expected-result :passed "Test that the qRHL input method loads without errors in .qrhl files" (message "load-qrhl-input test: Check loading of qRHL input method") (find-file "test.qrhl") ;; Ideally we would do some simulated keypresses and check whether they ;; are translated correctly. But I don't know how. (Dominique) (should (string= current-input-method "qrhl")) ) PG-4.5/ci/test-indent/000077500000000000000000000000001426357011200145225ustar00rootroot00000000000000PG-4.5/ci/test-indent/.gitignore000066400000000000000000000000121426357011200165030ustar00rootroot00000000000000indented_*PG-4.5/ci/test-indent/Makefile000066400000000000000000000007001426357011200161570ustar00rootroot00000000000000# This file is part of Proof General. # # © Copyright 2021 Pierre Courtieu # # Authors: Pierre Courtieu # Maintainer: Pierre Courtieu # # SPDX-License-Identifier: GPL-3.0-or-later TESTS:=$(wildcard indent-*.v) INDENTED:=$(subst indent-,indented_indent-, $(TESTS)) all: $(INDENTED) indented_%.v: %.v @echo "### testing indentation of $<..." @./coq-test-indent.sh $< .PHONY: clean clean: rm -f indented_indent* PG-4.5/ci/test-indent/coq-test-indent.el000066400000000000000000000060701426357011200200650ustar00rootroot00000000000000;;; Regression testing of indentation. ;;; Initially the file is indented as it is supposed to be. Each line ;;; is unindented, then indented. If the new indentation differ a ;;; comment is added to signal it. ;;; WARNING: there are relative path names, so this currently works ;;; only frowhen the current directory is the one containin this file. (defun blank-line-p () (= (current-indentation) (- (line-end-position) (line-beginning-position)))) (defun line-fixindent () (save-excursion (let ((end (line-end-position))) (re-search-forward "fixindent" end t)))) (defun test-indent-line (&optional nocomment) (interactive) (unless (or (blank-line-p) (line-fixindent)) (back-to-indentation) (let ((init-col (current-column))) ;; avoid moving comments (unless (proof-inside-comment (point)) (delete-horizontal-space)) (indent-according-to-mode) (let ((res (- (current-column) init-col))) (unless (= 0 res) (save-excursion (end-of-line) (unless nocomment (insert (format " (*<=== %s%d INDENT CHANGED *)" (if (< res 0) "" "+") res)))) res) 0)))) (defun remove-previous-comment () (interactive) (save-excursion (end-of-line) (let* ((com (re-search-backward " (\\*<===" (line-beginning-position) t)) (strt (and com (point))) (end (and com (line-end-position)))) (when com (delete-region strt end))))) (defun test--indent-region (beg end boxed &optional nocomment) (let ((line-move-visual nil) ;; we store the last line number rather than the position ;; since by inderting things we shift the end pos, but not the ;; end line. (last-line (line-number-at-pos end)) (stop nil)) (set (make-local-variable 'coq-indent-box-style) boxed) (goto-char beg) (while (and (<= (line-number-at-pos) last-line) (not stop)) (remove-previous-comment) (test-indent-line nocomment) (setq stop (/= (forward-line) 0))))) (defun remove-comments-region (beg end) (interactive "r") (goto-char beg) (let ((line-move-visual nil)) (while (< (point) end);; loops because end position changes. (remove-previous-comment) (forward-line)))) (defun test-indent-region (beg end &optional boxed nocomment) (interactive "r\nP") (test--indent-region beg end boxed nocomment)) (defun test-indent-region-boxed (beg end &optional nocomment) (interactive "r") (test--indent-region beg end t nocomment)) (defun test-indent-buffer (&optional nocomment) (interactive) (test--indent-region (point-min) (point-max) nil nocomment)) (defun test-indent-buffer-boxed (&optional nocomment) (interactive) (test--indent-region (point-min) (point-max) t nocomment)) (defun launch-test (orig indented &optional boxed) (load-file "../../generic/proof-site.el") (find-file orig) (write-file indented) (if boxed (test-indent-buffer-boxed t) (test-indent-buffer t)) (write-file indented)) PG-4.5/ci/test-indent/coq-test-indent.sh000077500000000000000000000023721426357011200201030ustar00rootroot00000000000000#!/bin/bash # This script should be launched from its own directory, so that file # coq-test-indent.el is accessible. GREEN='\033[1;32m' RED='\033[1;31m' MAGENTA='\033[1;35m' NC='\033[0m' # No Color TESTFILE=$1 INDENTEDTESTFILE=indented_$1 BOXED="nil" if [[ "$1" == *"boxed.v" ]]; then BOXED="t" fi echo "cp $TESTFILE $INDENTEDTESTFILE" cp $TESTFILE $INDENTEDTESTFILE emacs -q -batch --eval "(progn (load-file \"coq-test-indent.el\") (launch-test \"$TESTFILE\" \"$INDENTEDTESTFILE\" $BOXED))" # echo "grep \"INDENT CHANGED\" $INDENTEDTESTFILE" # grep "INDENT CHANGED" $INDENTEDTESTFILE echo -n " diff -q $TESTFILE $INDENTEDTESTFILE..." diff -q $TESTFILE $INDENTEDTESTFILE if [[ "$?" == 1 ]] ; then echo " DIFFERENCES FOUND" diff -u $TESTFILE $INDENTEDTESTFILE printf "${RED} TEST FAILURE ***${NC}\n" echo " *** details can be seen by reproducing the tests:" echo " *** cd ci/test-indent" echo " *** make" echo " *** diff --side-by-side --suppress-common-lines $TESTFILE $INDENTEDTESTFILE" echo " *** or graphically: " echo " *** meld $TESTFILE $INDENTEDTESTFILE" exit 1 # Make the test program fail, so that CI knows. else echo "NO DIFFERENCE" printf "${GREEN} TEST SUCCESS *** ${NC}\n" exit 0 fi PG-4.5/ci/test-indent/indent-commands-boxed.v000066400000000000000000000102111426357011200210630ustar00rootroot00000000000000 Require Export Coq.Lists.List. Module Mod. Module Foo. Axiom X:Set. Axiom Y:Set. Axiom Z:Set. End Foo. Section Sec. Axiom X:Set. Axiom Y:Set. Axiom Z:Set. End Sec. Definition a1 := 1. Definition A2 := 1. Definition arith1:= 1. Definition arith1 := 1. Definition arith1 := 1. Let x := 1. Let y := 2. Notation "[ a ; .. ; b ]" := (a :: .. (b :: []) ..) : list_scope. Inductive test : nat -> Prop := C1 : forall n, test n | C2 : forall n, test n | C3 : forall n, test n | C4 : forall n, test n. Inductive testbar' : nat -> Prop := | Cbar1 : forall n, test n | Cbar2 : forall n, test n | Cbar3 : forall n, test n | Cbar4 : forall n, test n. Inductive test2 : nat -> Prop := | C21 : forall n, test2 n | C22 : forall n, test2 n | C23 : forall n, test2 n | C24 : forall n, test2 n. Inductive test' : nat -> Prop := C1' : forall n, test' n | C2' : forall n, test' n | C3' : forall n, test' n | C4' : forall n, test' n with test2' : nat -> Prop := C21' : forall n, test2' n | C22' : forall n, test2' n | C23' : forall n, test2' n | C24' : forall n, test2' n with test3' : nat -> Prop := C21' : forall n, test2' n | C22' : forall n, test2' n | C23' : forall n, test2' n | C24' : forall n, test2' n with test4' : nat -> Prop := | C21' : forall n, test2' n | C22' : forall n, test2' n | C23' : forall n, test2' n | C24' : forall n, test2' n. Inductive test3 : nat -> Prop := C31 : forall n, test3 n | C32 : forall n, test3 n | C33 : forall n, test3 n . (* Goal parenthesizing. *) Lemma L : True. Proof. idtac. idtac... (* special case of command ender. *) idtac. Qed. (* Goal starter *) Definition Foo:True. exact I. Defined. (* Bullets. *) Lemma L : forall x:nat , Nat.iter x (A:=nat) (plus 2) 0 >= x. Proof. idtac. idtac. idtac. { idtac. idtac. } idtac. { idtac. idtac. } { idtac. idtac. } { idtac. idtac. } { idtac. { idtac. idtac. } idtac. { idtac . { idtac. idtac. } } idtac. } idtac. { idtac. { idtac. idtac. } } idtac. { idtac . { idtac. idtac. } } { idtac. idtac. idtac. { idtac. idtac. } idtac. } Qed. Lemma L : forall x:nat , Nat.iter x (A:=nat) (plus 2) 0 >= x. Proof. idtac. { idtac. idtac. } { idtac. idtac. } { idtac. { idtac. idtac. } idtac. } { idtac. idtac. { idtac. idtac. } idtac. } { idtac. { idtac. { idtac. idtac. } idtac. } } { idtac. { idtac. { idtac. idtac. } idtac. idtac. idtac. } idtac. } { idtac. - idtac. idtac. { idtac. idtac. } idtac. } Qed. Lemma L : forall x:nat , Nat.iter x (A:=nat) (plus 2) 0 >= x. Proof. idtac. - idtac. idtac. - idtac. idtac. + idtac. idtac. + idtac. idtac. * idtac. - idtac. Qed. Lemma L : forall x:nat , Nat.iter x (A:=nat) (plus 2) 0 >= x. Proof. idtac. - idtac. idtac. idtac. idtac. - idtac. { idtac. - idtac. idtac. - idtac. idtac. } - idtac. idtac. { idtac. - idtac. idtac. - idtac. idtac. } idtac. - idtac. Qed. (* goal selectors. *) Lemma L : forall x:nat , Nat.iter x (A:=nat) (plus 2) 0 >= x. Proof. idtac. 2:idtac. 3-6:idtac. 2:{ idtac. idtac. } { idtac. idtac. } [foo]:{ idtac. - idtac. idtac. { idtac. idtac. } idtac. } Qed. End Mod. PG-4.5/ci/test-indent/indent-commands.v000066400000000000000000000102051426357011200177670ustar00rootroot00000000000000 Require Export Coq.Lists.List. Module Mod. Module Foo. Axiom X:Set. Axiom Y:Set. Axiom Z:Set. End Foo. Section Sec. Axiom X:Set. Axiom Y:Set. Axiom Z:Set. End Sec. Definition a1 := 1. Definition A2 := 1. Definition arith1:= 1. Definition arith1 := 1. Definition arith1 := 1. Let x := 1. Let y := 2. Notation "[ a ; .. ; b ]" := (a :: .. (b :: []) ..) : list_scope. Inductive test : nat -> Prop := C1 : forall n, test n | C2 : forall n, test n | C3 : forall n, test n | C4 : forall n, test n. Inductive testbar' : nat -> Prop := | Cbar1 : forall n, test n | Cbar2 : forall n, test n | Cbar3 : forall n, test n | Cbar4 : forall n, test n. Inductive test2 : nat -> Prop := | C21 : forall n, test2 n | C22 : forall n, test2 n | C23 : forall n, test2 n | C24 : forall n, test2 n. Inductive test' : nat -> Prop := C1' : forall n, test' n | C2' : forall n, test' n | C3' : forall n, test' n | C4' : forall n, test' n with test2' : nat -> Prop := C21' : forall n, test2' n | C22' : forall n, test2' n | C23' : forall n, test2' n | C24' : forall n, test2' n with test3' : nat -> Prop := C21' : forall n, test2' n | C22' : forall n, test2' n | C23' : forall n, test2' n | C24' : forall n, test2' n with test4' : nat -> Prop := | C21' : forall n, test2' n | C22' : forall n, test2' n | C23' : forall n, test2' n | C24' : forall n, test2' n. Inductive test3 : nat -> Prop := C31 : forall n, test3 n | C32 : forall n, test3 n | C33 : forall n, test3 n . (* Goal parenthesizing. *) Lemma L : True. Proof. idtac. idtac... (* special case of command ender. *) idtac. Qed. (* Goal starter *) Definition Foo:True. exact I. Defined. (* Bullets. *) Lemma L : forall x:nat , Nat.iter x (A:=nat) (plus 2) 0 >= x. Proof. idtac. idtac. idtac. { idtac. idtac. } idtac. { idtac. idtac. } { idtac. idtac. } { idtac. idtac. } { idtac. { idtac. idtac. } idtac. { idtac . { idtac. idtac. } } idtac. } idtac. { idtac. { idtac. idtac. } } idtac. { idtac . { idtac. idtac. } } { idtac. idtac. idtac. { idtac. idtac. } idtac. } Qed. Lemma L : forall x:nat , Nat.iter x (A:=nat) (plus 2) 0 >= x. Proof. idtac. { idtac. idtac. } { idtac. idtac. } { idtac. { idtac. idtac. } idtac. } { idtac. idtac. { idtac. idtac. } idtac. } { idtac. { idtac. { idtac. idtac. }} } { idtac. { idtac. { idtac. idtac. } idtac. idtac. idtac. } idtac. } { idtac. - idtac. idtac. { idtac. idtac. } idtac. } Qed. Lemma L : forall x:nat , Nat.iter x (A:=nat) (plus 2) 0 >= x. Proof. idtac. - idtac. idtac. - idtac. idtac. + idtac. idtac. + idtac. idtac. * idtac. - idtac. Qed. Lemma L : forall x:nat , Nat.iter x (A:=nat) (plus 2) 0 >= x. Proof. idtac. - idtac. idtac. idtac. idtac. - idtac. { idtac. - idtac. idtac. - idtac. idtac. } - idtac. idtac. { idtac. - idtac. idtac. - idtac. idtac. } idtac. - idtac. Qed. (* goal selectors. *) Lemma L : forall x:nat , Nat.iter x (A:=nat) (plus 2) 0 >= x. Proof. idtac. 2:idtac. 3-6:idtac. 2:{ idtac. idtac. } { idtac. idtac. } [foo]:{ idtac. - idtac. idtac. { idtac. idtac. } idtac. } Qed. End Mod. PG-4.5/ci/test-indent/indent-equations.v000066400000000000000000000055501426357011200202050ustar00rootroot00000000000000(* Needs Equations plugin to work. *) From Coq Require Import Arith Omega Program. From Equations Require Import Equations. Require Import Bvector. Module Equations. Equations neg (b : bool) : bool := neg true := false ; neg false := true. Equations neg' (b : bool) : bool := neg' true := false ; neg' false := true. Lemma neg_inv : forall b, neg (neg b) = b. Proof. intros b. funelim (neg b); now simp neg. Defined. Inductive list {A} : Type := nil : list | cons : A -> list -> list. Arguments list : clear implicits. Notation "x :: l" := (cons x l). Equations tail {A} (l : list A) : list A := | nil := nil ; | (cons a v) := v. Equations tail' {A} (l : list A) : list A := | nil := nil ; | (cons a v) := v. (* The cases inside { } are recognized as record fields, which from an indentation perspective is OK *) Equations filter {A} (l : list A) (p : A -> bool) : list A := filter nil p := nil; filter (cons a l) p with p a => { | true := a :: filter l p ; | false := filter l p }. Equations filter_ {A} (l : list A) (p : A -> bool) : list A := filter nil p := nil; filter (cons a l) p with p a => { | true := a :: filter l p ; | false := filter l p }. Equations filter' {A} (l : list A) (p : A -> bool) : list A := filter' (cons a l) p with p a => { | true := a :: filter' l p ; | false := filter' l p }; filter' nil p := nil. Equations filter' {A} (l : list A) (p : A -> bool) : list A := filter' (cons a l) p with p a => { | true := a :: filter' l p ; | false := filter' l p }; filter' nil p := nil. Equations filter' {A} (l : list A) (p : A -> bool) : list A := filter' (cons a l) p with p a => { true := a :: filter' l p ; false := filter' l p }; filter' nil p := nil. Equations filter' {A} (l : list A) (p : A -> bool) : list A := filter' (cons a l) p with p a => { true := a :: filter' l p ; false := filter' l p }; filter' nil p := nil. Equations filter'' {A} (l : list A) (p : A -> bool) : list A := filter'' (cons a l) p with p a => { | true := a :: filter'' l p ; | false := filter'' l p }; filter'' nil p := nil. Equations unzip {A B} (l : list (A * B)) : list A * list B := unzip nil := (nil, nil) ; unzip (cons p l) with unzip l => { unzip (cons (pair a b) l) (pair la lb) := (a :: la, b :: lb) }. Equations equal (n m : nat) : { n = m } + { n <> m } := equal O O := left eq_refl ; equal (S n) (S m) with equal n m := { equal (S n) (S ?(n)) (left eq_refl) := left eq_refl ; equal (S n) (S m) (right p) := right _ } ; equal x y := right _. End Equations. PG-4.5/ci/test-indent/indent-inside-command-boxed.v000066400000000000000000000031471426357011200221630ustar00rootroot00000000000000 Require Export Coq.Lists.List. Require Export Arith. Module Mod. Module Foo. Axiom X : Set. Axiom Y : Set. Axiom Z: Set. End Foo. Definition a1 := 1. Definition A2 := 1. Definition arith1 := 1. Definition arith1 := 1. Let x := 1. Let y := 2. Notation "[ a ; .. ; b ]" := (a :: .. (b :: []) ..) : list_scope. Definition foo := foo x (y a b) z t (* align with function foo + 2. *) u v. (* align with arg z on bol of previous line *) Inductive test : nat -> Prop := C1 : forall n, test n | C2 : forall n, test n | C3 : forall n, test n | C4 : forall n, test n. (* Goal parenthesizing. *) Lemma L : True. Proof. idtac. idtac... (* special case of command ender. *) idtac. Qed. Lemma L4 : forall x:nat, Nat.iter x (A:=nat) (plus 2) 0 >= x. Proof. idtac. Qed. Lemma L3 : forall x:nat, Nat.iter x (A:=nat) (plus 2) 0 >= x. Proof. idtac. Qed. Lemma L1 : forall x:nat, Nat.iter x (A:=nat) (plus 2) 0 >= x. Proof. idtac. Qed. Lemma L2 : forall x:nat, Nat.iter x (A:=nat) (plus 2) 0 >= x. Proof. idtac. Qed. End Mod. PG-4.5/ci/test-indent/indent-inside-command.v000066400000000000000000000025521426357011200210630ustar00rootroot00000000000000 Require Export Coq.Lists.List. Require Export Arith. Module Mod. Module Foo. Axiom X : Set. Axiom Y : Set. Axiom Z: Set. End Foo. Definition a1 := 1. Definition A2 := 1. Definition arith1 := 1. Definition arith1 := 1. Definition arith1 a (b:nat) c d e := 1. Definition arith1 (b:nat) c d e := 1. Let x := 1. Let y := 2. Notation "[ a ; .. ; b ]" := (a :: .. (b :: []) ..) : list_scope. Inductive test : nat -> Prop := C1 : forall n, test n | C2 : forall n, test n | C3 : forall n, test n | C4 : forall n, test n. Lemma L4 : forall x:nat, Nat.iter x (A:=nat) (plus 2) 0 >= x. Proof. idtac. Qed. Lemma L3 : forall x:nat, Nat.iter x (A:=nat) (plus 2) 0 >= x. Proof. idtac. Qed. Lemma L1 : forall x:nat, Nat.iter x (A:=nat) (plus 2) 0 >= x. Proof. idtac. Qed. Lemma L2 : forall x:nat, Nat.iter x (A:=nat) (plus 2) 0 >= x. Proof. idtac. Qed. End Mod. PG-4.5/ci/test-indent/indent-monadic.v000066400000000000000000000022501426357011200176010ustar00rootroot00000000000000(* Needs ext-lib library to compile. *) Require Import Coq.ZArith.ZArith_base Coq.Strings.Ascii Coq.Strings.String. Require Import ExtLib.Data.Monads.StateMonad ExtLib.Structures.Monads. Import StringSyntax. Open Scope string_scope. Section StateGame. Check Ascii.Space. Import MonadNotation. Local Open Scope Z_scope. Local Open Scope char_scope. Local Open Scope monad_scope. Definition GameValue : Type := Z. Definition GameState : Type := (prod bool Z). Variable m : Type -> Type. Context {Monad_m: Monad m}. Context {State_m: MonadState GameState m}. Print Grammar constr. Fixpoint playGame (s: string) m' {struct s}: m GameValue := match s with | EmptyString => v <- (if true then m' else get) ;; let '(on, score) := v in ret score | String x xs => v <- get ;; let '(on, score) := v in match x, on with | "a"%char, true => put (on, score + 1) | "b"%char, true => put (on, score - 1) | "c"%char, _ => put (negb on, score) | _, _ => put (on, score) end ;; playGame xs m' end. Definition startState: GameState := (false, 0). End StateGame. PG-4.5/ci/test-indent/indent-tac-boxed.v000066400000000000000000000064441426357011200200460ustar00rootroot00000000000000Module foo. Lemma toto:nat. Proof. {{ exact 3. }} Qed. Lemma foo: forall n: nat, exists m:nat, m = n + 1. Proof. intros n. destruct n. { exists 1. reflexivity. } exists (S (S n)). simpl. rewrite Nat.add_1_r. reflexivity. Qed. Lemma L : forall x:nat, Nat.iter x (A:=nat) (plus 2) 0 >= x. Proof with auto with arith. intros x. induction x;simpl;intros... induction x; simpl ; simpl ; simpl ; intros. Qed. Ltac foo:= intros x; induction x; simpl ; intros. Lemma L : forall x:nat , Nat.iter x (A:=nat) (plus 2) 0 >= x. Proof with auto with arith. intros x; induction x; simpl ; intros. idtacjqslkjd;[ intros x ; induction x ; simpl ; intros]. Qed. Lemma L' : forall x:nat , Nat.iter x (A:=nat) (plus 2) 0 >= x with L'' : forall x:nat , Nat.iter x (A:=nat) (plus 2) 0 >= x. Proof with auto with arith. - induction x;simpl;intros... - induction x;simpl;intros... Qed. End foo. Section SET. Definition set (T : Type) := Ensemble T. Require Import Program. Definition eq_n : forall A n (v:Vector.t A n) n', n=n' -> Vector.t A n'. Proof. intros A n v n' H. rewrite <- H. assumption. Defined. End SET. Module curlybracesatend. Lemma foo2: forall n: nat, exists m:nat, m = n + 1. Proof. intros n. destruct n. { exists 1. reflexivity. } exists (S (S n)). simpl. rewrite Nat.add_1_r. reflexivity. Qed. Lemma foo3: forall n: nat, forall n: nat, forall n: nat, forall n: nat, forall n: nat, exists m:nat, m = n + 1 -> m = n + 1 -> m = n + 1 -> m = n + 1 -> m = n + 1 -> m = n + 1. Proof. intros n. cut (n = n). { destruct n. { exists 1. reflexivity. } { exists (S (S n)). simpl. rewrite Nat.add_1_r. reflexivity. } } idtac. reflexivity. Qed. Lemma foooooooooooooooo3: forall n: nat, forall n: nat, forall n: nat, f x -> g y -> f x -> forall n: nat, forall n: nat, forall n: nat, exists m:nat, m = n + 1 -> m = n + 1 -> m = n + 1 -> m = n + 1 -> m = n + 1 -> m = n + 1 -> True. Proof. intros n. cut (n = n). { destruct n. { exists 1. reflexivity. } { exists (S (S n)). simpl. rewrite Nat.add_1_r. reflexivity. } } idtac. reflexivity. Qed. End curlybracesatend. PG-4.5/ci/test-indent/indent-tac.v000066400000000000000000000264201426357011200167430ustar00rootroot00000000000000 Module foo. Lemma toto:nat. Proof. {{ exact 3. }} Qed. Lemma L : forall x:nat , Nat.iter x (A:=nat) (plus 2) 0 >= x. Proof with auto with arith. intros x. induction x;simpl;intros... induction x; simpl ; simpl ; simpl ; intros. Ltac foo:= intros x; induction x; simpl ; simpl ; simpl ; intros. induction x ; simpl ; intros ; intros ; intros . idtac ; [ induction x ; simpl ; intros ]. Ltac foo := intros x ; induction x ; simpl ; intros ; intros . idtac ; [ induction x ; simpl ; simpl | intros ]. Ltac foo := intros x ; induction x ; simpl ; intros ; intros . induction x ; simpl ; intros. induction x ; simpl ; intros. induction x ; simpl ; simpl ; intros. intros x ; induction x ; simpl ; intros. idtac;(intros x ; induction x ; simpl ; intros). idtac;( induction x; simpl ; intros ). idtac;[ intros x ; induction x ; simpl ; intros]. idtac ; [ induction x; simpl ; intros | simpl ; intros ]. idtac;[ intros x ; induction x | simpl ; intros]. idtac;[ intros x ; induction x | simpl ; intros ]. idtac foobar;[ induction x; simpl ; intros ]. Qed. Ltac foo:= intros x; induction x; simpl ; intros. Lemma L : forall x:nat , Nat.iter x (A:=nat) (plus 2) 0 >= x. Proof with auto with arith. intros x; induction x; simpl ; intros. idtacjqslkjd;[ intros x ; induction x ; simpl ; intros]. Qed. Lemma L : forall x:nat , Nat.iter x (A:=nat) (plus 2) 0 >= x. Proof with auto with arith. intros x; [ induction x; [ simpl; intros... ] ]. Qed. Lemma L2 : forall x:nat , Nat.iter x (A:=nat) (plus 2) 0 >= x. Proof with auto with arith. idtac. (* "as" tactical *) induction x as [ | x IHx]. - cbn. apply Nat.le_trans with (n:=0) (* aligning the different closes of a "with". *) (m:=0) (p:=0). + auto with arith. + auto with arith. - simpl. intros. auto with arith. Qed. Lemma L' : forall x:nat , Nat.iter x (A:=nat) (plus 2) 0 >= x with L'' : forall x:nat , Nat.iter x (A:=nat) (plus 2) 0 >= x. Proof with auto with arith. - induction x;simpl;intros... - induction x;simpl;intros... Qed. Lemma L''' : forall x:nat , Nat.iter x (A:=nat) (plus 2) 0 >= x. Proof using Type *. intros x. induction x;simpl;intros. admit. Admitted. Lemma L'''' : forall x:nat , 0 <= x. Proof (fun x : nat => Nat.le_0_l x). (* no indentation here since the proof above closes the proof. *) Definition foo:nat := 0. End Y. Function div2 (n : nat) {struct n}: nat := match n with | 0 => 0 | 1 => 0 | S (S n') => S (div2 n') end. Module M1. Module M2. Lemma l1: forall n:nat, n = n. auto. Qed. Lemma l2: forall n:nat, n = n. auto. Qed. Lemma l3: forall n:nat, n <= n. auto. Qed. (* Lemma l4: forall n:nat, n <= n. Proof. intro. Qed. *) Lemma l5 : forall n:nat, n <= n. Proof. auto. Qed. Lemma l6: forall n:nat, n = n. intros. Lemma l7: forall n:nat, n = n. destruct n. { auto. } { destruct n. { auto. } auto. } Qed. { destruct n. { auto. } { auto. } } Qed. End M2. End M1. Module GoalSelectors. Theorem lt_n_S : (True \/ True \/ True \/ True \/ True ) -> True. Proof. refine (or_ind ?[aa] (or_ind ?[bb] (or_ind ?[cc] (or_ind ?[dd] ?[ee])))). [aa]:{ auto. } 2:{ auto. } [ee]:auto. { auto. } Qed. (* Same without space between "." and "}". *) Theorem lt_n_S2 : (True \/ True \/ True \/ True \/ True ) -> True. Proof. refine (or_ind ?[aa] (or_ind ?[bb] (or_ind ?[cc] (or_ind ?[dd] ?[ee])))). [aa]:{ auto. } 2:{ auto. } [ee]:auto. { auto. } Qed. End GoalSelectors. Module M1'. Module M2'. Lemma l6: forall n:nat, n = n. Proof. intros. Lemma l7: forall n:nat, n = n. Proof. destruct n. intros. { auto. } { destruct n. idtac a ; [ auto; auto | auto; auto. ]. } auto. } Qed. {destruct n. { auto. } {auto. } } Qed. End M2'. End M1'. (* TODO: add multichar bullets once coq 8.5 is out *) Module M4'. Module M2'. Lemma l6: forall n:nat, n = n. Proof. intros. Lemma l7: forall n:nat, n = n. Proof. destruct n. - auto. - destruct n. + idtac;[ auto ]. + destruct n. * auto. * auto. Qed. {destruct n. - auto. - auto. } Qed. End M2'. End M4'. Module M1''. Module M2''. Lemma l7: forall n:nat, n = n. destruct n. { auto. } { destruct n. { idtac; [ auto ]. } auto. } Qed. End M2''. End M1''. Record rec:Set := { fld1:nat; fld2:nat; fld3:bool }. Class cla {X:Set}:Set := { cfld1:nat; cld2:nat; cld3:bool }. Module X. Lemma l: forall r:rec, exists r':rec, r'.(fld1) = r.(fld2)/\ r'.(fld2) = r.(fld1). Proof. idtac. idtac. idtac. intros r. { exists {| fld1:=r.(fld2); fld2:=r.(fld1); fld3:=false |}. split. {auto. } {auto. } } intros r. { exists {| fld1:= r.(fld2); fld2 :=r.(fld1); fld3 := false |}. split. {auto. } {auto. } } auto. auto. Qed. (* Issue #574 *) Goal let x := 1 in True. Proof. intro. match goal with | y := _ : unit |- _ => idtac "unit" | y := _ : nat |- _ => idtac "nat" end. Qed. Lemma l2 : forall r:rec, exists r':rec, r.(fld1) = r'.(fld2) /\ r.(fld2) = r'.(fld1). Proof. intros r. {{ idtac; exists {| fld1:=r.(fld2); fld2:=r.(fld1); fld3:=false |}. (* ltac *) match goal with _:rec |- ?a /\ ?b => split | _ => fail end. match goal with | ?g := _:rec |- ?a /\ ?b => split | _ => fail end. Fail lazymatch goal with _:rec |- ?a /\ ?b => split | _ => fail end. Fail multimatch goal with _:rec |- ?a /\ ?b => split | _ => fail end. { simpl. auto. } { simpl. auto. }}} - split. match goal with X => foo end. - split. match goal with X |- _ => foo | H: X := Y |- _ => foo end. - split. match H with ?a = ?b |- _ => foo | ?a < ?b |- _ => foo end. - split. let x := f y in let foo := idtac x in idtac foo. Qed. End X. Require Import Morphisms. Generalizable All Variables. Local Open Scope signature_scope. Require Import RelationClasses. Module TC. Instance: (@RewriteRelation nat) impl. (* No goal created *) Definition XX := 0. Instance StrictOrder_Asymmetric `(StrictOrder A R) : Asymmetric R. (* One goal created. Then the user MUST put "Proof." to help indentation *) Proof. firstorder. Qed. Program Fixpoint f (x:nat) {struct x} : nat := match x with | 0 => 0 | S y => S (f y) end. Program Instance all_iff_morphism {A : Type} : Proper (pointwise_relation A iff ==> iff) (@all A). Next Obligation. Proof. unfold pointwise_relation, all in *. intro. intros y H. intuition ; specialize (H x0) ; intuition. Qed. End TC. Require Import Sets.Ensembles. Require Import Bool.Bvector. Section SET. Definition set (T : Type) := Ensemble T. Require Import Program. Definition eq_n : forall A n (v:Vector.t A n) n', n=n' -> Vector.t A n'. Proof. intros A n v n' H. rewrite <- H. assumption. Defined. Fixpoint setVecProd (T : Type) (n : nat) (v1:Vector.t (set T) n) {struct v1}: (Vector.t T n) -> Prop := match v1 with Vector.nil _ => fun v2 => match v2 with Vector.nil _ => True | _ => False end | (Vector.cons _ x n' v1') => fun v2 => (* indentation of dependen "match" clause. *) match v2 as X in Vector.t _ n'' return (Vector.t T (pred n'') -> Prop) -> Prop with | Vector.nil _ => fun _ => False | (Vector.cons _ y n'' v2') => fun v2'' => (x y) /\ (v2'' v2') end (setVecProd T n' v1') end. End SET. Module curlybracesatend. Lemma foo: forall n: nat, exists m:nat, m = n + 1. Proof. intros n. destruct n. { exists 1. reflexivity. } exists (S (S n)). simpl. rewrite Nat.add_1_r. reflexivity. Qed. Lemma foo2: forall n: nat, exists m:nat, m = n + 1. Proof. intros n. destruct n. { exists 1. reflexivity. } exists (S (S n)). simpl. rewrite Nat.add_1_r. reflexivity. Qed. Lemma foo3: forall n: nat, forall n: nat, forall n: nat, forall n: nat, forall n: nat, exists m:nat, m = n + 1 -> m = n + 1 -> m = n + 1 -> m = n + 1 -> m = n + 1 -> m = n + 1. Proof. intros n. cut (n = n). { destruct n. { exists 1. reflexivity. } { exists (S (S n)). simpl. rewrite Nat.add_1_r. reflexivity. } } idtac. reflexivity. Qed. Lemma foooooooooooooooo3: forall n: nat, forall n: nat, forall n: nat, f x -> g y -> f x -> forall n: nat, forall n: nat, forall n: nat, exists m:nat, m = n + 1 -> m = n + 1 -> m = n + 1 -> m = n + 1 -> m = n + 1 -> m = n + 1 -> True. Proof. intros n. cut (n = n). { destruct n. { exists 1. reflexivity. } { exists (S (S n)). simpl. rewrite Nat.add_1_r. reflexivity. } } idtac. reflexivity. Qed. End curlybracesatend. PG-4.5/ci/test-indent/tests.sh000077500000000000000000000003011426357011200162150ustar00rootroot00000000000000#!/bin/bash for i in $(find . -name "*.v" -exec basename '{}' \; | grep -v "indented_") ; do echo -n "Testing $i..." ./coq-test-indent.sh $i 2>&1 | tee .$i.log | grep "\*\*\*" done PG-4.5/ci/test.sh000077500000000000000000000017551426357011200136120ustar00rootroot00000000000000#!/bin/bash # Print $1 in green green () { echo -e "\e[32m$1\e[0m" } # Print $1 in red red () { echo -e "\e[31m$1\e[0m" } assert () { if [ $# -lt 1 ]; then red "ERROR, assert expects some args (the code to run)" exit 1 fi /bin/bash -exc '"$@"' bash "$@" ret=$? if [ "$ret" -ne 0 ]; then red "FAILURE, this shell command returned exit status $ret: \$ $(printf "'%s' " "$@")\n" exit $ret fi echo } ############################################################################### assert emacs --version rootdir=$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && cd .. && pwd ) srcdir=$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd ) form="(progn (add-to-list 'load-path \"$rootdir\") (add-to-list 'load-path \"$srcdir\") (setq coq-test-dir \"$srcdir/\"))" # we need a trailing slash here assert emacs --batch -l ert --eval "$form" -l init-tests.el -l proof-general.el -l coq-tests.el -f ert-run-tests-batch-and-exit PG-4.5/ci/test_proof_using.v000066400000000000000000000002641426357011200160460ustar00rootroot00000000000000 Section S. Variable proof:nat. Hypothesis h: proof = proof. Lemma width_nonneg : proof = proof. Proof. (*proof*) pose proof @h. apply H. (*qed*) Qed. End S. PG-4.5/ci/test_stepwise.v000066400000000000000000000012131426357011200153520ustar00rootroot00000000000000Definition trois := 3. (*test-definition*) Print trois. Eval compute in 10 * trois * trois. Lemma easy_proof : forall A : Prop, A -> A. Proof using . intros A. intros proof_of_A. (*test-insert*) exact proof_of_A. Qed. (*test-lemma*) Section failSection. Local Unset Ltac Backtrace. Goal False. Proof. (*FailNoTrace*) Fail (now auto). auto. Abort. Local Set Ltac Backtrace. Goal False. (*FailTrace*) Fail (now auto). auto. Abort. End failSection. Lemma false_proof : forall A B : bool, A = B. Proof. intros A B. destruct A. destruct B. reflexivity. (*error*) reflexivity. Qed. (*test-lemma2*) PG-4.5/ci/test_wholefile.v000066400000000000000000000110631426357011200154710ustar00rootroot00000000000000(* taken from https://coq.inria.fr/distrib/8.2/contribs/QArithSternBrocot.sqrt2.html *) (* Note: this file contains no "Proof" command (invariant to preserve) in order to exercise 070_coq-test-regression-wholefile-no-proof. *) Require Export ArithRing. Require Export Compare_dec. Require Export Wf_nat. Require Export Arith. Require Export Lia. Theorem minus_minus : forall a b c : nat, a - b - c = a - (b + c). intros a; elim a; auto. intros n' Hrec b; case b; auto. Qed. Remark expand_mult2 : forall x : nat, 2 * x = x + x. intros x; ring. Qed. Theorem lt_neq : forall x y : nat, x < y -> x <> y. unfold not in |- *; intros x y H H1; elim (lt_irrefl x); pattern x at 2 in |- *; rewrite H1; auto. Qed. Hint Resolve lt_neq. Theorem monotonic_inverse : forall f : nat -> nat, (forall x y : nat, x < y -> f x < f y) -> forall x y : nat, f x < f y -> x < y. intros f Hmon x y Hlt; case (le_gt_dec y x); auto. intros Hle; elim (le_lt_or_eq _ _ Hle). intros Hlt'; elim (lt_asym _ _ Hlt); apply Hmon; auto. intros Heq; elim (lt_neq _ _ Hlt); rewrite Heq; auto. Qed. Theorem mult_lt : forall a b c : nat, c <> 0 -> a < b -> a * c < b * c. intros a b c; elim c. intros H; elim H; auto. intros c'; case c'. intros; lia. intros c'' Hrec Hneq Hlt; repeat rewrite <- (fun x : nat => mult_n_Sm x (S c'')). lia. Qed. Remark add_sub_square_identity : forall a b : nat, (b + a - b) * (b + a - b) = (b + a) * (b + a) + b * b - 2 * ((b + a) * b). intros a b; rewrite minus_plus. repeat rewrite mult_plus_distr_r || rewrite <- (mult_comm (b + a)). replace (b * b + a * b + (b * a + a * a) + b * b) with (b * b + a * b + (b * b + a * b + a * a)); try (ring; fail). rewrite expand_mult2; repeat rewrite minus_plus; auto with *. Qed. Theorem sub_square_identity : forall a b : nat, b <= a -> (a - b) * (a - b) = a * a + b * b - 2 * (a * b). intros a b H; rewrite (le_plus_minus b a H); apply add_sub_square_identity. Qed. Theorem square_monotonic : forall x y : nat, x < y -> x * x < y * y. intros x; case x. intros y; case y; simpl in |- *; auto with *. intros x' y Hlt; apply lt_trans with (S x' * y). rewrite (mult_comm (S x') y); apply mult_lt; auto. apply mult_lt; lia. Qed. Theorem root_monotonic : forall x y : nat, x * x < y * y -> x < y. exact (monotonic_inverse (fun x : nat => x * x) square_monotonic). Qed. Remark square_recompose : forall x y : nat, x * y * (x * y) = x * x * (y * y). intros; ring. Qed. Remark mult2_recompose : forall x y : nat, x * (2 * y) = x * 2 * y. intros; ring. Qed. Section sqrt2_decrease. Variables (p q : nat) (pos_q : 0 < q) (hyp_sqrt : p * p = 2 * (q * q)). Theorem sqrt_q_non_zero : 0 <> q * q. generalize pos_q; case q. intros H; elim (lt_n_O 0); auto. intros n H. simpl in |- *; discriminate. Qed. Hint Resolve sqrt_q_non_zero. Ltac solve_comparison := apply root_monotonic; repeat rewrite square_recompose; rewrite hyp_sqrt; rewrite mult2_recompose; apply mult_lt; auto with arith. Theorem comparison1 : q < p. replace q with (1 * q); try ring. replace p with (1 * p); try ring. solve_comparison. Qed. Theorem comparison2 : 2 * p < 3 * q. solve_comparison. Qed. Theorem comparison3 : 4 * q < 3 * p. solve_comparison. Qed. Hint Resolve comparison1 comparison2 comparison3: arith. Theorem comparison4 : 3 * q - 2 * p < q. apply plus_lt_reg_l with (2 * p). rewrite <- le_plus_minus; try (simple apply lt_le_weak; auto with arith). replace (3 * q) with (2 * q + q); try ring. apply plus_lt_le_compat; auto. repeat rewrite (mult_comm 2); apply mult_lt; auto with arith. Qed. Remark mult_minus_distr_l : forall a b c : nat, a * (b - c) = a * b - a * c. intros a b c; repeat rewrite (mult_comm a); apply mult_minus_distr_r. Qed. Remark minus_eq_decompose : forall a b c d : nat, a = b -> c = d -> a - c = b - d. intros a b c d H H0; rewrite H; rewrite H0; auto. Qed. Theorem new_equality : (3 * p - 4 * q) * (3 * p - 4 * q) = 2 * ((3 * q - 2 * p) * (3 * q - 2 * p)). repeat rewrite sub_square_identity; auto with arith. repeat rewrite square_recompose; rewrite mult_minus_distr_l. apply minus_eq_decompose; try rewrite hyp_sqrt; ring. Qed. End sqrt2_decrease. Hint Resolve lt_le_weak comparison2: sqrt. Theorem sqrt2_not_rational : forall p q : nat, q <> 0 -> p * p = 2 * (q * q) -> False. intros p q; generalize p; clear p; elim q using (well_founded_ind lt_wf). clear q; intros q Hrec p Hneq; generalize (neq_O_lt _ (sym_not_equal Hneq)); intros Hlt_O_q Heq. apply (Hrec (3 * q - 2 * p) (comparison4 _ _ Hlt_O_q Heq) (3 * p - 4 * q)). apply sym_not_equal; apply lt_neq; apply plus_lt_reg_l with (2 * p); rewrite <- plus_n_O; rewrite <- le_plus_minus; auto with *. apply new_equality; auto. Qed. PG-4.5/coq/000077500000000000000000000000001426357011200124535ustar00rootroot00000000000000PG-4.5/coq/README000066400000000000000000000042641426357011200133410ustar00rootroot00000000000000Coq Proof General Originally written by Healfdene Goguen. Later contributions by Patrick Loiseleur, Pierre Courtieu, David Aspinall, Stefan Monier, Hendrik Tews Status: supported Maintainer: Pierre Courtieu Coq version: 8.5 Coq homepage: http://coq.inria.fr/ =========================================================================== Coq Proof General has support for Unicode Tokens, using simple character sequences rather than a special language of tokens. See notes below. There is a tags program, coqtags. =========================================================================== Installation notes: Check the values of coq-tags and coq-prog-name in coq.el to see that they correspond to the paths for coqtop and the library on your system. Install coqtags in a standard place or add /coq to your PATH. NB: You may need to change the path to perl at the top of the file. Generate a TAGS file for the library by running coqtags `find . -name \*.v -print` in the root directory of the library, $COQTOP/theories. =========================================================================== Grammar for Unicode Tokens: Symbols include sequences naming Greek letters ("Lambda", "lambda", etc), connectives /\, \/, etc. See the token list (Unicode Tokens -> List Tokens) for tokens availabe --- these are just a sample set and you can add your own. See coq-unicode-tokens.el for the tables and further instructions. a symbol is encoded only if - preceded by _ or ' or some space or some symbol **and** - followed by _ or ' or some space or some symbol Grammar for sub/superscript: - a double _ introduces a subscript that ends at the first space - a double ^ introduces a superscript that ends at the first space - a , followed by { introduces a subscript expression that ends at the first } (_{...} was not possible due to coq notation mechanism) - a ^ followed by { introduces a superscript expression that ends at the first } See example-tokens.v in this directory for examples. Please suggest any extensions/improvements on Trac, at http://proofgeneral.inf.ed.ac.uk/trac/ ======================================== $Id$ PG-4.5/coq/TODO000066400000000000000000000011331426357011200131410ustar00rootroot00000000000000-*- outline -*- ** important: deal with different levels of the "in" keyword let x := y in : expression eval x in y : commande unfold x in y : tactique ** important: fix indention of definitions: Current behavior: function foo bar1 bar2 bar3 Should be function foo bar1 bar2 <>bar3 (<> length parameterized by coq-smie-after-bolp-indentation) or function foo bar1 bar2 bar3 depending on an option (coq-indent-box-style). ** Fix indentation of ; Current behavior: idtac ; idtac. but: idtac; idtac; idtac. ** dealing with several project files. PG-4.5/coq/coq-abbrev.el000066400000000000000000000371021426357011200150210ustar00rootroot00000000000000;;; coq-abbrev.el --- coq abbrev table and menus for ProofGeneral mode -*- lexical-binding:t -*- ;; This file is part of Proof General. ;; Portions © Copyright 1994-2012 David Aspinall and University of Edinburgh ;; Portions © Copyright 2003-2018 Free Software Foundation, Inc. ;; Portions © Copyright 2001-2017 Pierre Courtieu ;; Portions © Copyright 2010, 2016 Erik Martin-Dorel ;; Portions © Copyright 2011-2013, 2016-2017 Hendrik Tews ;; Portions © Copyright 2015-2017 Clément Pit-Claudel ;; Authors: Healfdene Goguen, Pierre Courtieu ;; Maintainer: Pierre Courtieu ;; SPDX-License-Identifier: GPL-3.0-or-later ;;; Commentary: ;; ;;; Code: (require 'proof) (require 'coq-syntax) (defun holes-show-doc () (interactive) (describe-function 'holes-mode)) (defun coq-local-vars-list-show-doc () (interactive) (describe-variable 'coq-local-vars-doc)) (defconst coq-tactics-menu (append '("Tactics (menu)" ["Intros (smart)" coq-insert-intros :help "Insert \"intros h1 .. hn.\" where hi are the default names given by Coq."]) (coq-build-menu-from-db (append coq-tactics-db coq-solve-tactics-db)))) (defconst coq-tactics-abbrev-table (coq-build-abbrev-table-from-db (append coq-tactics-db coq-solve-tactics-db))) (defconst coq-tacticals-menu (append '("Tacticals (menu)") (coq-build-menu-from-db coq-tacticals-db))) (defconst coq-tacticals-abbrev-table (coq-build-abbrev-table-from-db coq-tacticals-db)) (defconst coq-commands-menu (append '("Command (menu)" ;["Module/Section (smart)" coq-insert-section-or-module t] ;["Require (smart)" coq-insert-requires t] ) (coq-build-menu-from-db coq-commands-db))) (defconst coq-commands-abbrev-table (coq-build-abbrev-table-from-db coq-commands-db)) (defconst coq-terms-menu (append '("Term (menu)" ["Match (smart)" coq-insert-match t]) (coq-build-menu-from-db coq-terms-db))) (defconst coq-terms-abbrev-table (coq-build-abbrev-table-from-db coq-terms-db)) ;;; The abbrev table built from keywords tables ;#s and @{..} are replaced by holes by holes-abbrev-complete (define-abbrev-table 'coq-mode-abbrev-table (append coq-tactics-abbrev-table coq-tacticals-abbrev-table coq-commands-abbrev-table coq-terms-abbrev-table) "Abbrev table for Coq.") ;; The coq menu partly built from tables ;; Common part (script, response and goals buffers) (defconst coq-menu-common-entries `( ["Toggle 3 Windows Mode" proof-three-window-toggle :style toggle :selected proof-three-window-enable :help "Toggles the use of separate windows or frames for Coq responses and goals." ] ("3 Windows mode layout" ["smart" (progn (customize-set-variable 'proof-three-window-mode-policy 'smart) (proof-layout-windows)) :style radio :selected (eq proof-three-window-mode-policy 'smart) :help "Adapt to frame width (C-c C-l to refresh)"] ["hybrid" (progn (customize-set-variable 'proof-three-window-mode-policy 'hybrid) (proof-layout-windows)) :style radio :selected (eq proof-three-window-mode-policy 'hybrid) :help "two column mode"] ["horizontal" (progn (customize-set-variable 'proof-three-window-mode-policy 'horizontal) (proof-layout-windows)) :style radio :selected (eq proof-three-window-mode-policy 'horizontal) :help "Three column mode"] ["vertical" (progn (customize-set-variable 'proof-three-window-mode-policy 'vertical) (proof-layout-windows)) :style radio :selected (eq proof-three-window-mode-policy 'vertical) :help "One column mode"]) ["Refresh Windows Layout" proof-layout-windows t] ["Toggle tooltips" proof-output-tooltips-toggle :style toggle :selected proof-output-tooltips :help "Toggles Tooltips (popup when hovering commands).\nSet `proof-output-tooltips' to nil to disable it by default."] ["Electric Terminator" proof-electric-terminator-toggle :style toggle :selected proof-electric-terminator-enable :help "Automatically send commands when terminator typed"] ["Double Hit Electric Terminator" coq-double-hit-toggle :style toggle :selected coq-double-hit-enable :help "Automatically send commands when terminator is typed twice quickly."] ("Auto Compilation" ["Compile Before Require" coq-compile-before-require-toggle :style toggle :selected coq-compile-before-require :help "Check dependencies of required modules and compile on the fly."] ["Parallel background compilation" coq-compile-parallel-in-background-toggle :style toggle :selected coq-compile-parallel-in-background :active coq-compile-before-require :help ,(concat "Compile parallel in background or " "sequentially with blocking ProofGeneral.")] ["Keep going" coq-compile-keep-going-toggle :style toggle :selected coq-compile-keep-going :active (and coq-compile-before-require coq-compile-parallel-in-background) :help ,(concat "Continue background compilation after " "the first error as far as possible")] ("vos compilation (coq >= 8.11)" ["unset" (customize-set-variable 'coq-compile-vos nil) :style radio :selected (eq coq-compile-vos nil) :active (and coq-compile-before-require coq-compile-parallel-in-background) :help "Derive behavior from Quick compilation setting above"] ["use -vos and -vok" (customize-set-variable 'coq-compile-vos 'vos-and-vok) :style radio :selected (eq coq-compile-vos 'vos-and-vok) :active (and coq-compile-before-require coq-compile-parallel-in-background) :help "Speedup with -vos, check proofs later, possibly inconsistent"] ["use -vos, no -vok" (customize-set-variable 'coq-compile-vos 'vos) :style radio :selected (eq coq-compile-vos 'vos) :active (and coq-compile-before-require coq-compile-parallel-in-background) :help "Speedup with -vos, don't check proofs, possibly inconsistent"] ["ensure vo" (customize-set-variable 'coq-compile-vos 'ensure-vo) :style radio :selected (eq coq-compile-vos 'ensure-vo) :active (and coq-compile-before-require coq-compile-parallel-in-background) :help "Ensure only vo's are used for consistency"] ) ("Quick compilation (coq < 8.11)" ["no quick" (customize-set-variable 'coq-compile-quick 'no-quick) :style radio :selected (eq coq-compile-quick 'no-quick) :active (and coq-compile-before-require coq-compile-parallel-in-background) :help "Compile without -quick but accept existing .vio's"] ["quick no vio2vo" (customize-set-variable 'coq-compile-quick 'quick-no-vio2vo) :style radio :selected (eq coq-compile-quick 'quick-no-vio2vo) :active (and coq-compile-before-require coq-compile-parallel-in-background) :help "Compile with -quick, accept existing .vo's, don't run vio2vo"] ["quick and vio2vo" (customize-set-variable 'coq-compile-quick 'quick-and-vio2vo) :style radio :selected (eq coq-compile-quick 'quick-and-vio2vo) :active (and coq-compile-before-require coq-compile-parallel-in-background) :help "Compile with -quick, accept existing .vo's, run vio2vo later"] ["ensure vo" (customize-set-variable 'coq-compile-quick 'ensure-vo) :style radio :selected (eq coq-compile-quick 'ensure-vo) :active (and coq-compile-before-require coq-compile-parallel-in-background) :help "Ensure only vo's are used for consistency"] ) ("Auto Save" ["Query coq buffers" (customize-set-variable 'coq-compile-auto-save 'ask-coq) :style radio :selected (eq coq-compile-auto-save 'ask-coq) :active coq-compile-before-require :help "Ask for each coq-mode buffer, except the current buffer"] ["Query all buffers" (customize-set-variable 'coq-compile-auto-save 'ask-all) :style radio :selected (eq coq-compile-auto-save 'ask-all) :active coq-compile-before-require :help "Ask for all buffers"] ["Autosave coq buffers" (customize-set-variable 'coq-compile-auto-save 'save-coq) :style radio :selected (eq coq-compile-auto-save 'save-coq) :active coq-compile-before-require :help "Save all Coq buffers without confirmation, except the current one"] ["Autosave all buffers" (customize-set-variable 'coq-compile-auto-save 'save-all) :style radio :selected (eq coq-compile-auto-save 'save-all) :active coq-compile-before-require :help "Save all buffers without confirmation"] ) ["Lock Ancestors" coq-lock-ancestors-toggle :style toggle :selected coq-lock-ancestors :active coq-compile-before-require :help "Lock files of imported modules"] ["Confirm External Compilation" coq-confirm-external-compilation-toggle :style toggle :selected coq-confirm-external-compilation :active (and coq-compile-before-require (not (equal coq-compile-command ""))) :help "Confirm external compilation command, see `coq-compile-command'."] ["Abort Background Compilation" coq-par-emergency-cleanup :active (and coq-compile-before-require coq-compile-parallel-in-background) :help "Abort background compilation and kill all compilation processes."]) ("Diffs" ["off" (customize-set-variable 'coq-diffs 'off) :style radio :selected (eq coq-diffs 'off) :help "Don't show diffs"] ["on" (customize-set-variable 'coq-diffs 'on) :style radio :selected (eq coq-diffs 'on) :help "Show diffs: only added"] ["removed" (customize-set-variable 'coq-diffs 'removed) :style radio :selected (eq coq-diffs 'removed) :help "Show diffs: added and removed"]) ["Show Proof (Diffs)" coq-show-proof-stepwise-toggle :style toggle :selected coq-show-proof-stepwise :help "Display the proof terms stepwise in the *response* buffer."] ("\"Proof using\" mode..." ["ask" (customize-set-variable 'coq-accept-proof-using-suggestion 'ask) :style radio :selected (eq coq-accept-proof-using-suggestion 'ask) :help "Ask user when a new proof using annotation is suggested"] ["always" (customize-set-variable 'coq-accept-proof-using-suggestion 'always) :style radio :selected (eq coq-accept-proof-using-suggestion 'always) :help "Always update the proof using annotation when suggested"] ["highlight" (customize-set-variable 'coq-accept-proof-using-suggestion 'highlight) :style radio :selected (eq coq-accept-proof-using-suggestion 'highlight) :help "Highight the proof when an auto insert is suggested (right click to insert))"] ["Ignore" (customize-set-variable 'coq-accept-proof-using-suggestion 'ignore) :style radio :selected (eq coq-accept-proof-using-suggestion 'ignore) :help "no highlight (right click insertion still possible)"]) "" ["Print..." coq-Print :help "With prefix arg (C-u): Set Printing All first"] ["Check..." coq-Check :help "With prefix arg (C-u): Set Printing All first"] ["About..." coq-About :help "With prefix arg (C-u): Set Printing All first"] ["Other..." coq-query] [ "Store Response" proof-store-response-win :help "Stores the content of response buffer in a dedicated buffer"] [ "Store Goal" proof-store-goals-win :help "Stores the content of goals buffer in a dedicated buffer"] ("OTHER QUERIES" ["Print Hint" coq-PrintHint t] ["Show ith Goal..." coq-Show t] ["Show ith Goal... (show implicits)" coq-Show-with-implicits t] ["Show ith Goal... (show all)" coq-Show-with-all t] ["Show Tree" coq-show-tree t] ["Show Proof" coq-show-proof t] ["Show Conjectures" coq-show-conjectures t];; maybe not so useful with editing in PG? "" ["Print..." coq-Print :help "With prefix arg (C-u): Set Printing All first"] ["Print... (show implicits)" coq-Print-with-implicits t] ["Print... (show all)" coq-Print-with-all t] ["Check..." coq-Check :help "With prefix arg (C-u): Set Printing All first"] ["Check (show implicits)..." coq-Check-show-implicits t] ["Check (show all)..." coq-Check-show-all t] ["About..." coq-About :help "With prefix arg (C-u): Set Printing All first"] ["About...(show implicits)" coq-About-with-implicits t] ["About...(show all)" coq-About-with-all t] ["Search..." coq-Search t] ["SearchRewrite..." coq-SearchRewrite t] ["SearchPattern..." coq-SearchIsos t] ["Search Blacklist..." coq-change-search-blacklist-interactive t] ["Locate constant..." coq-LocateConstant t] ["Locate Library..." coq-LocateLibrary t] ["Pwd" coq-Pwd t] ["Inspect..." coq-Inspect t] ["Print Section..." coq-PrintSection t] "" ["Locate notation..." coq-LocateNotation t] ["Print Implicit..." coq-Print t] ["Print Scope/Visibility..." coq-PrintScope t]) ("OPTIONS" ["Set Printing All" coq-set-printing-all t] ["Unset Printing All" coq-unset-printing-all t] ["Set Printing Implicit" coq-set-printing-implicit t] ["Unset Printing Implicit" coq-unset-printing-implicit t] ["Set Printing Coercions" coq-set-printing-coercions t] ["Unset Printing Coercions" coq-unset-printing-coercions t] ["Set Printing Compact Contexts" coq-set-printing-implicit t] ["Unset Printing Compact Contexts" coq-unset-printing-implicit t] ["Set Printing Synth" coq-set-printing-synth t] ["Unset Printing Synth" coq-unset-printing-synth t] ["Set Printing Universes" coq-set-printing-universes t] ["Unset Printing Universes" coq-unset-printing-universes t] ["Set Printing Unfocused" coq-set-printing-unfocused t] ["Unset Printing Unfocused" coq-unset-printing-unfocused t] ["Set Printing Wildcards" coq-set-printing-wildcards t] ["Unset Printing Wildcards" coq-unset-printing-wildcards t] ["Set Printing Width" coq-ask-adapt-printing-width-and-show t]))) (setq-default coq-menu-entries (append coq-menu-common-entries `( "" ("INSERT" ["Intros (smart)" coq-insert-intros :help "Insert \"intros h1 .. hn.\" where hi are the default names given by Coq."] "" ["Tactic (interactive)" coq-insert-tactic t] ["Tactical (interactive)" coq-insert-tactical t] ["Command (interactive)" coq-insert-command t] ["Term (interactive)" coq-insert-term t] "" ,coq-tactics-menu ,coq-tacticals-menu ,coq-commands-menu ,coq-terms-menu "" ["Module/Section (smart)" coq-insert-section-or-module t] ["Require (smart)" coq-insert-requires t]) "" ("ABBREVS" ["Expand At Point" expand-abbrev t] ["Unexpand Last" unexpand-abbrev t] ["List Abbrevs" list-abbrevs t] ["Edit Abbrevs" edit-abbrevs t] ["Abbrev Mode" abbrev-mode :style toggle :selected (and (boundp 'abbrev-mode) abbrev-mode)]) "" ("COQ PROG (ARGS)" ["Use project file" coq-toggle-use-project-file :style toggle :selected (and (boundp 'coq-use-project-file) coq-use-project-file) ] ["Set Coq Prog *persistently*" coq-ask-insert-coq-prog-name t] ["help" coq-local-vars-list-show-doc t] ["Compile" coq-Compile t])))) (setq-default coq-help-menu-entries '(["help on setting prog name persistently for a file" coq-local-vars-list-show-doc t])) (setq-default coq-other-buffers-menu-entries coq-menu-common-entries) (provide 'coq-abbrev) ;;; coq-abbrev.el ends here PG-4.5/coq/coq-autotest.el000066400000000000000000000066451426357011200154400ustar00rootroot00000000000000;;; coq-autotest.el --- tests of Coq Proof General (in progress) -*- lexical-binding:t -*- ;; This file is part of Proof General. ;; Portions © Copyright 1994-2012 David Aspinall and University of Edinburgh ;; Portions © Copyright 2003-2018 Free Software Foundation, Inc. ;; Portions © Copyright 2001-2017 Pierre Courtieu ;; Portions © Copyright 2010, 2016 Erik Martin-Dorel ;; Portions © Copyright 2011-2013, 2016-2017 Hendrik Tews ;; Portions © Copyright 2015-2017 Clément Pit-Claudel ;;; Commentary: ;; ;; You can run these by issuing "make test.coq" in PG home dir. ;; ;;; Code: (require 'pg-autotest) (require 'proof-site) (defvar coq-compile-before-require) ;;;###autoload (defun coq-autotest () (interactive) (pg-autotest start 'debug) ;; new multiple file handling for Coq gives interactive queries ;; continually unless we set this. (setq proof-auto-action-when-deactivating-scripting 'retract) (setq proof-no-fully-processed-buffer t) (pg-autotest log ".autotest.log") ; convention (pg-autotest timestart 'total) (pg-autotest remark "Testing standard examples...") (pg-autotest script-wholefile "coq/example.v") (pg-autotest script-wholefile "coq/example-tokens.v") (pg-autotest script-wholefile "coq/ex-module.v") (proof-shell-wait) (pg-autotest remark "Regression testing bug cases...") (pg-autotest script-wholefile "etc/coq/parsingcheck-410.v") ;(pg-autotest script-wholefile "etc/coq/parsingcheck-412.v") (pg-autotest remark "Testing prove-as-you-go (not replay)") (find-file ".autotest.v") (erase-buffer) ; just in case exists (setq buffer-file-name nil) (pg-autotest eval (proof-electric-terminator-toggle 1)) (pg-autotest eval (insert "Module test")) ; no \n (proof-electric-terminator) ;; Note: with new multiple-file code, above fires up process. ;; If we do (proof-shell-wait) here, we get a deadlock. (pg-autotest eval (insert " Goal forall (A B:Prop),(A /\\ B) -> (B /\\ A)")) (proof-electric-terminator) (proof-shell-wait) (pg-autotest eval (insert "\ntauto.")) (backward-char) (proof-electric-terminator) ; shouldn't insert another or delete present (proof-shell-wait) ;; FIXME: next test fails, why? (pg-autotest assert-full) ;; TODO: test switching active scripting buffer after ;; an error (see cvs log for proof-script.el 10.68) ;; FIXME: bug, this causes "region is read only" ;; (pg-autotest eval (insert " End test")) ;; (proof-electric-terminator) (set-buffer-modified-p nil) (kill-buffer ".autotest.v") (proof-shell-wait) ;; TODO: test indentation. E.g., to avoid regression of Trac #416 (pg-autotest script-wholefile "etc/coq/multiple-plain/a.v") (pg-autotest script-wholefile "etc/coq/multiple-plain/b.v") (pg-autotest script-wholefile "etc/coq/multiple-plain/c.v") (pg-autotest script-wholefile "etc/coq/multiple-plain/a.v") (pg-autotest remark "Testing multiple-file recompilation...") (setq coq-compile-before-require t) (pg-autotest script-wholefile "coq/ex/test-cases/multiple-files-single-dir/f.v") (proof-shell-wait) (find-file "d.v") (set-buffer-modified-p t) (save-buffer) (pg-autotest-test-retract-file "coq/ex/test-cases/multiple-files-single-dir/f.v") (proof-shell-wait) (pg-autotest script-wholefile "coq/ex/test-cases/multiple-files-single-dir/f.v") (pg-autotest remark "Complete.") (pg-autotest timetaken 'total) (pg-autotest exit)) (provide 'coq-autotest) ;;; coq-autotest.el ends here PG-4.5/coq/coq-compile-common.el000066400000000000000000000771721426357011200165110ustar00rootroot00000000000000;;; coq-compile-common.el --- common part of compilation feature -*- lexical-binding: t; -*- ;; This file is part of Proof General. ;; Portions © Copyright 1994-2012 David Aspinall and University of Edinburgh ;; Portions © Copyright 2003-2021 Free Software Foundation, Inc. ;; Portions © Copyright 2001-2017 Pierre Courtieu ;; Portions © Copyright 2010, 2016 Erik Martin-Dorel ;; Portions © Copyright 2011-2013, 2016-2017, 2019-2021 Hendrik Tews ;; Portions © Copyright 2015-2017 Clément Pit-Claudel ;; Authors: Hendrik Tews ;; Maintainer: Hendrik Tews ;; SPDX-License-Identifier: GPL-3.0-or-later ;;; Commentary: ;; ;; This file holds constants, options and some general functions for ;; the compilation feature. ;; ;;; Code: (require 'cl-lib) ;cl-every cl-some (require 'proof-shell) (require 'coq-system) (require 'compile) ;;(defvar coq-pre-v85 nil) (defvar coq-confirm-external-compilation); defpacustom (defvar coq-compile-parallel-in-background) ; defpacustom ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Multiple file handling -- sequential compilation of required modules ;; ;;; enable / disable parallel / sequential compilation ;; I would rather put these functions into coq-seq-compile and ;; coq-par-compile, respectively. However, the :initialization ;; function of a defcustom seems to be evaluated when reading the ;; defcustom form. Therefore, these functions must be defined already, ;; when the defcustom coq-compile-parallel-in-background is read. (defun coq-par-enable () "Enable parallel compilation. Must be used together with `coq-seq-disable'." (add-hook 'proof-shell-extend-queue-hook #'coq-par-preprocess-require-commands) (add-hook 'proof-shell-signal-interrupt-hook #'coq-par-user-interrupt) (add-hook 'proof-shell-handle-error-or-interrupt-hook #'coq-par-user-interrupt)) (defun coq-par-disable () "Disable parallel compilation. Must be used together with `coq-seq-enable'." (remove-hook 'proof-shell-extend-queue-hook #'coq-par-preprocess-require-commands) (remove-hook 'proof-shell-signal-interrupt-hook #'coq-par-user-interrupt) (remove-hook 'proof-shell-handle-error-or-interrupt-hook #'coq-par-user-interrupt)) (defun coq-seq-enable () "Enable sequential synchronous compilation. Must be used together with `coq-par-disable'." (add-hook 'proof-shell-extend-queue-hook #'coq-seq-preprocess-require-commands)) (defun coq-seq-disable () "Disable sequential synchronous compilation. Must be used together with `coq-par-enable'." (remove-hook 'proof-shell-extend-queue-hook #'coq-seq-preprocess-require-commands)) (defun coq-switch-compilation-method () "Set function for function ‘coq-compile-parallel-in-background’." (if coq-compile-parallel-in-background (progn (coq-par-enable) (coq-seq-disable)) (coq-par-disable) (coq-seq-enable))) (defun number-of-cpus () (let (status ncpus) (condition-case nil (with-temp-buffer (setq status (call-process "getconf" nil (current-buffer) t "_NPROCESSORS_ONLN")) (setq ncpus (string-to-number (buffer-string)))) (error (setq status -1))) (if (and (eq status 0) (> ncpus 0)) ncpus nil))) (defvar coq--max-background-second-stage-percentage-shadow 40 "Internal shadow value of `coq-max-background-second-stage-percentage'. This variable does always contain the same value as `coq-max-background-second-stage-percentage'. It is used only to break the dependency cycle between `coq-set-max-second-stage-jobs' and `coq-max-background-second-stage-percentage'.") (defvar coq--internal-max-second-stage-jobs 1 "Internal number of second-stage background jobs (vok or vio2vo). This is the internal value, use `coq-max-background-second-stage-percentage' to configure.") (defvar coq--internal-max-jobs 1 "Value of `coq-max-background-compilation-jobs' translated to a number.") (defun coq-set-max-second-stage-jobs () "Set `coq--internal-max-second-stage-jobs'." (setq coq--internal-max-second-stage-jobs (max 1 (round (* coq--internal-max-jobs coq--max-background-second-stage-percentage-shadow 0.01))))) (defun coq-max-second-stage-setter (symbol new-value) ":set function for `coq-max-background-second-stage-percentage'. SYMBOL should be 'coq-max-background-second-stage-percentage" (set-default symbol new-value) (setq coq--max-background-second-stage-percentage-shadow new-value) (coq-set-max-second-stage-jobs)) (defun coq-max-jobs-setter (symbol new-value) ":set function for `coq-max-background-compilation-jobs'. SYMBOL should be 'coq-max-background-compilation-jobs" (set-default symbol new-value) (cond ((eq new-value 'all-cpus) (setq new-value (number-of-cpus)) (unless new-value (setq new-value 1))) ((and (integerp new-value) (> new-value 0)) t) (t (setq new-value 1))) (setq coq--internal-max-jobs new-value) (coq-set-max-second-stage-jobs)) (defun coq-compile-quick-setter (symbol new-value) ":set function for `coq-compile-quick' for pre 8.5 compatibility. Ignore any quick setting for Coq versions before 8.5." (cond ((or (eq new-value 'ensure-vo) (eq new-value 'no-quick)) t) ((coq--pre-v85) (message "Ignore coq-compile-quick setting %s for Coq before 8.5" new-value) (setq new-value 'no-quick))) (set-default symbol new-value)) ;;; user options and variables (defgroup coq-auto-compile () "Customization for automatic compilation of required files" :group 'coq :package-version '(ProofGeneral . "4.1")) (defcustom coq-compile-before-require nil "If non-nil, check dependencies of required modules and compile if necessary. If non-nil ProofGeneral intercepts \"Require\" commands and checks if the required library module and its dependencies are up-to-date. If not, they are compiled from the sources before the \"Require\" command is processed. This option can be set/reset via menu `Coq -> Auto Compilation -> Compile Before Require'." :type 'boolean :safe 'booleanp) (proof-deftoggle coq-compile-before-require) (defcustom coq-compile-parallel-in-background t "Choose the internal compilation method. When Proof General compiles itself, you have the choice between two implementations. If this setting is nil, then Proof General uses the old implementation and compiles everything sequentially with synchronous job. With this old method Proof General is locked during compilation. If this setting is t, then the new method is used and compilation jobs are dispatched in parallel in the background. The maximal number of parallel compilation jobs is set with `coq-max-background-compilation-jobs'. This option can be set/reset via menu `Coq -> Auto Compilation -> Compile Parallel In Background'." :type 'boolean :safe 'booleanp) (proof-deftoggle coq-compile-parallel-in-background) (defun coq-compile-parallel-in-background () (coq-switch-compilation-method)) ;; defpacustom fails to call :eval during inititialization, see trac #456 (coq-switch-compilation-method) (defcustom coq-compile-quick 'quick-and-vio2vo "Control quick compilation, vio2vo and vio/vo files auto compilation. When using coq < 8.11, this option controls whether ``-quick'' is used for parallel background compilation and whether up-date .vo or .vio files are used or deleted. Please use the customization system to change this option to ensure that any ``-quick'' setting is ignored for Coq before 8.5. Please customize `coq-compile-vos' for coq >= 8.11. Note that ``-quick'' can be noticebly slower when your sources do not declare section variables with ``Proof using''. Note that even if you do declare section variables, ``-quick'' is typically slower on small files. Use `no-quick', if you have not yet switched to ``Proof using''. Use `quick-no-vio2vo', if you want quick recompilation without producing .vo files. Value `quick-and-vio2vo' updates missing prerequisites with ``-quick'' and starts vio2vo conversion on a subset of the availables cores (see `coq-compile-vio2vo-percentage') when the quick recompilation finished (but see below for a .vio .vo incompatibility caveat). Note that all the previously described modes might load .vio files and that you therefore might not notice certain universe inconsistencies. Finally, use `ensure-vo' for only importing .vo files with complete universe checks. Detailed description of the 4 modes: no-quick Compile outdated prerequisites without ``-quick'', producing .vo files, but don't compile prerequisites for which an up-to-date .vio file exists. Delete or overwrite outdated .vo files. quick-no-vio2vo Compile outdated prerequisites with ``-quick'', producing .vio files, but don't compile prerequisites for which an up-to-date .vo file exists. Delete or overwrite outdated .vio files. quick-and-vio2vo Same as `quick-no-vio2vo', but start vio2vo processes after the last ``Require'' command has been processed to convert the vio dependencies into vo files. With this mode you might see asynchronous errors from vio2vo compilation while you are processing stuff far below the last require. vio2vo compilation is done on a subset of the available cores, see `coq-compile-vio2vo-percentage'. When `coq-compile-keep-going' is set, vio2vo compilation is scheduled for those files for which coqc compilation was successful. Warning: This mode does only work when you process require commands in batches. Slowly single-stepping through require's might lead to inconsistency errors when loading some libraries, see Coq issue #5223. ensure-vo Ensure that all library dependencies are present as .vo files and delete outdated .vio files or .vio files that are more recent than the corresponding .vo file. This setting is the only one that ensures soundness. This option can be set via menu `Coq -> Auto Compilation -> Quick compilation'." :type '(radio (const :tag "don't use -quick but accept existing vio files" no-quick) (const :tag "use -quick, don't do vio2vo" quick-no-vio2vo) (const :tag "use -quick and do vio2vo" quick-and-vio2vo) (const :tag "ensure vo compilation, delete vio files" ensure-vo)) :safe (lambda (v) (member v '(no-quick quick-no-vio2vo quick-and-vio2vo ensure-vo))) :set #'coq-compile-quick-setter) (defun coq-compile-prefer-quick () "Return t if a .vio file would be prefered." (or (eq coq-compile-quick 'quick-no-vio2vo) (eq coq-compile-quick 'quick-and-vio2vo))) (defcustom coq-compile-vos nil "Control fast compilation, skipping opaque proofs with ``-vos'' and ``-vok''. When using coq >= 8.11, this option controls whether parallel background compilation is done with ``-vos'', skipping opaque proofs, thus being considerably faster and inconsistent. Set this option to `vos' if you want fast background compilation without a second stage ``-vok'' run to check all proofs. Set this option to `vos-and-vok' if you want fast background compilation but also want to check all proofs in a second stage with ``-vok''. Option `vos-and-vok' does not guarantee consistency, because not all universe constraints are checked. Set this option to `ensure-vo' if you want all proofs and universe constraints checked carefully. The second stage ``-vok'' run starts in the background after `coq-compile-second-stage-delay' seconds on `coq-max-background-second-stage-percentage' per cent of the cores used for the first run (configured in `coq-max-background-compilation-jobs'). For upgrading, if this option is `nil' (i.e., not configured), then the value of `coq-compile-quick' is considered and vos compilation is used when `coq-compile-quick' equals `'quick-no-vio2vo'. For coq < 8.11 this option is ignored." :type '(radio (const :tag "unset, derive behavior from `coq-compile-quick'" nil) (const :tag "use -vos, don't do -vok" vos) (const :tag "use -vos and do -vok" vos-and-vok) (const :tag "ensure vo compilation" ensure-vo)) :safe (lambda (v) (member v '(nil vos vos-and-vok ensure-vo)))) (defun coq-compile-prefer-vos () "Decide whether ``-vos'' should be used. This function implements the upgrade path for fast compilation, by checking the value of `coq-compile-quick' if `coq-compile-vos' is nil." (or (eq coq-compile-vos 'vos) (eq coq-compile-vos 'vos-and-vok) (and (not coq-compile-vos) (eq coq-compile-quick 'quick-no-vio2vo)))) (defcustom coq-compile-keep-going t "Continue compilation after the first error as far as possible. Similar to ``make -k'', with this option enabled, the background compilation continues after the first error as far as possible. With this option disabled, background compilation is immediately stopped after the first error. This option can be set/reset via menu `Coq -> Auto Compilation -> Keep going'.") ;; define coq-compile-keep-going-toggle (proof-deftoggle coq-compile-keep-going) (defcustom coq-max-background-compilation-jobs 'all-cpus "Maximal number of parallel jobs, if parallel compilation is enabled. Use the number of available CPU cores if this is set to 'all-cpus. This variable is the user setting. The value that is really used is `coq--internal-max-jobs'. Use `coq-max-jobs-setter' or the customization system to change this variable. Otherwise your change will have no effect, because `coq--internal-max-jobs' is not adapted." :type '(choice (const :tag "use all CPU cores" all-cpus) (integer :tag "fixed number" :value 1)) :safe (lambda (v) (or (eq v 'all-cpus) (and (integerp v) (> v 0)))) :set #'coq-max-jobs-setter) (defcustom coq-max-background-second-stage-percentage (or (and (boundp 'coq-max-background-vio2vo-percentage) coq-max-background-vio2vo-percentage) (and (get 'coq-max-background-vio2vo-percentage 'saved-value) (eval (car (get 'coq-max-background-vio2vo-percentage 'saved-value)))) 40) ;; XXX change in ProofGeneral.texi "Percentage of `coq-max-background-compilation-jobs' for the second stage. This setting configures the maximal number of ``-vok'' or vio2vo background jobs running in a second stage as percentage of `coq-max-background-compilation-jobs'. For backward compatibility, if this option is not customized, it is initialized from the now deprecated option `coq-max-background-vio2vo-percentage'." :type 'number :safe 'numberp :set #'coq-max-second-stage-setter) (defcustom coq-max-background-vio2vo-percentage nil "Deprecated. Please configure `coq-max-background-second-stage-percentage'. This is the old configuration option for Coq < 8.11, used before the ``-vok'' second stage was implemented." :type 'number :safe 'numberp) (defcustom coq-compile-second-stage-delay (or (and (boundp 'coq-compile-vio2vo-delay) coq-compile-vio2vo-delay) (and (get 'coq-compile-vio2vo-delay 'saved-value) (eval (car (get 'coq-compile-vio2vo-delay 'saved-value)))) 2.5) "Delay in seconds before starting the second stage compilation. The delay is applied to both ``-vok'' and vio2vo second stages. For Coq < 8.11 and vio2vo delay helps to avoid running into a library inconsistency with 'quick-and-vio2vo, see Coq issue #5223. For backward compatibility, if this option is not customized, it is initialized from the now deprecated option `coq-compile-vio2vo-delay'." :type 'number :safe 'numberp) (defcustom coq-compile-vio2vo-delay nil ;; XXX replace coq-compile-vio2vo-delay in ../doc/ProofGeneral.texi "Deprecated. Please configure `coq-compile-second-stage-delay'. This is the old configuration option for Coq < 8.11, used before the ``-vok'' second stage was implemented." :type 'number :safe 'numberp) (defcustom coq-compile-command "" "External compilation command. If empty ProofGeneral compiles itself. If unset (the empty string) ProofGeneral computes the dependencies of required modules with coqdep and compiles as necessary. This internal dependency checking does currently not handle ML modules. If a non-empty string, the denoted command is called to do the dependency checking and compilation. Before executing this command the following keys are substituted as follows: %p the (physical) directory containing the source of the required module %o the Coq object file in the physical directory that will be loaded %s the Coq source file in the physical directory whose object will be loaded %q the qualified id of the \"Require\" command %r the source file containing the \"Require\" For instance, \"make -C %p %o\" expands to \"make -C bar foo.vo\" when module \"foo\" from directory \"bar\" is required. After the substitution the command can be changed in the minibuffer if `coq-confirm-external-compilation' is t." :type 'string :safe (lambda (v) (and (stringp v) (or (not (boundp 'coq-confirm-external-compilation)) coq-confirm-external-compilation)))) (defconst coq-compile-substitution-list '(("%p" physical-dir) ("%o" module-object) ("%s" module-source) ("%q" qualified-id) ("%r" requiring-file)) "Substitutions for `coq-compile-command'. Value must be a list of substitutions, where each substitution is a 2-element list. The first element of a substitution is the regexp to substitute, the second the replacement. The replacement is evaluated before passing it to `replace-regexp-in-string', so it might be a string, or one of the symbols `physical-dir', `module-object', `module-source', `qualified-id' and `requiring-file', which are bound to, respectively, the physical directory containing the source file, the Coq object file in 'physical-dir that will be loaded, the Coq source file in 'physical-dir whose object will be loaded, the qualified module identifier that occurs in the \"Require\" command, and the file that contains the \"Require\".") (defcustom coq-compile-auto-save 'ask-coq "Buffers to save before checking dependencies for compilation. There are two orthogonal choices: Firstly one can save all or only the coq buffers, where coq buffers means all buffers in coq mode except the current buffer. Secondly, Emacs can ask about each such buffer or save all of them unconditionally. This makes four permitted values: 'ask-coq to confirm saving all modified Coq buffers, 'ask-all to confirm saving all modified buffers, 'save-coq to save all modified Coq buffers without confirmation and 'save-all to save all modified buffers without confirmation. This option can be set via menu `Coq -> Auto Compilation -> Auto Save'." :type '(radio (const :tag "ask for each coq-mode buffer, except the current buffer" ask-coq) (const :tag "ask for all buffers" ask-all) (const :tag "save all coq-mode buffers except the current buffer without confirmation" save-coq) (const :tag "save all buffers without confirmation" save-all)) :safe (lambda (v) (member v '(ask-coq ask-all save-coq save-all)))) (defcustom coq-lock-ancestors t "If non-nil, lock ancestor module files. If external compilation is used (via `coq-compile-command') then only the direct ancestors are locked. Otherwise all ancestors are locked when the \"Require\" command is processed. This option can be set via menu `Coq -> Auto Compilation -> Lock Ancestors'." :type 'boolean :safe 'booleanp) ;; define coq-lock-ancestors-toggle (proof-deftoggle coq-lock-ancestors) (proof-deftoggle coq-show-proof-stepwise) (defcustom coq-confirm-external-compilation t "If set let user change and confirm the compilation command. Otherwise start the external compilation without confirmation. This option can be set/reset via menu `Coq -> Auto Compilation -> Confirm External Compilation'." :type 'boolean) (defcustom coq-compile-ignored-directories nil "Directories in which ProofGeneral should not compile modules. List of regular expressions for directories in which ProofGeneral should not compile modules. If a library file name matches one of the regular expressions in this list then ProofGeneral does neither compile this file nor check its dependencies for compilation. It makes sense to include non-standard coq library directories here if they are not changed and if they are so big that dependency checking takes noticeable time. The regular expressions in here are always matched against the .vo file name, regardless whether ``-quick'' would be used to compile the file or not." :type '(repeat regexp) :safe (lambda (v) (cl-every #'stringp v))) (defcustom coq-coqdep-error-regexp (concat "^\\*\\*\\* Warning: in file .*, library .* is required " "and has not been found") "Regexp to match errors in the output of coqdep. coqdep indicates errors not always via a non-zero exit status, but sometimes only via printing warnings. This regular expression is used for recognizing error conditions in the output of coqdep (when coqdep terminates with exit status 0). Its default value matches the warning that some required library cannot be found on the load path and ignores the warning for finding a library at multiple places in the load path. If you want to turn the latter condition into an error, then set this variable to \"^\\*\\*\\* Warning\"." :type 'string :safe 'stringp) (defconst coq-require-id-regexp "[ \t\n]*\\([A-Za-z0-9_']+\\(\\.[A-Za-z0-9_']+\\)*\\)[ \t\n]*" "Regular expression matching one Coq module identifier. Should match precisely one complete module identifier and surrounding white space. The module identifier must be matched with group number 1. Note that the trailing dot in \"Require A.\" is not part of the module identifier and should therefore not be matched by this regexp.") (defconst coq-require-command-regexp (concat "^\\(?:From[ \t\n]+\\(?1:[A-Za-z0-9_']+\\(?:\\.[A-Za-z0-9_']+\\)*\\)" "[ \t\n]*\\)?" "\\(?2:Require[ \t\n]+\\(?:Import\\|Export\\)?\\)[ \t\n]*") "Regular expression matching Require commands in Coq. Should match \"Require\" with its import and export variants up to (but not including) the first character of the first required module. The required modules are matched separately with `coq-require-id-regexp'") (defvar coq-compile-history nil "History of external Coq compilation commands.") (defvar coq--compile-response-buffer "*coq-compile-response*" "Name of the buffer to display error messages from coqc and coqdep.") (defvar coq--debug-auto-compilation nil "*Display more messages during compilation.") ;;; basic utilities (defun time-less-or-equal (time-1 time-2) "Return t if time value TIME-1 is earlier or equal to TIME-2. A time value is a list of two, three or four integers of the form (high low micro pico) as returned by `file-attributes' or 'current-time'. First element high contains the upper 16 bits and the second low the lower 16 bits of the time." (not (time-less-p time-2 time-1))) (defun coq-max-dep-mod-time (dep-mod-times) "Return the maximum in DEP-MOD-TIMES. Argument DEP-MOD-TIMES is a list where each element is either a time value (see `time-less-or-equal') or 'just-compiled. The function returns the maximum of the elements in DEP-MOD-TIMES, where 'just-compiled is considered the greatest time value. If DEP-MOD-TIMES is empty it returns nil." (let ((max nil)) (while dep-mod-times (cond ((eq (car dep-mod-times) 'just-compiled) (setq max 'just-compiled dep-mod-times nil)) ((eq max nil) (setq max (car dep-mod-times))) ((time-less-p max (car dep-mod-times)) (setq max (car dep-mod-times)))) (setq dep-mod-times (cdr-safe dep-mod-times))) max)) ;;; ignore library files (defun coq-compile-ignore-file (lib-obj-file) "Check whether ProofGeneral should handle compilation of LIB-OBJ-FILE. Return t if ProofGeneral should skip LIB-OBJ-FILE and nil if ProofGeneral should handle the file. For normal users it does, for instance, not make sense to let ProofGeneral check if the coq standard library is up-to-date. This function is always invoked on the .vo file name, regardless whether the file would be compiled with ``-quick'' or not." (if (cl-some (lambda (dir-regexp) (string-match dir-regexp lib-obj-file)) coq-compile-ignored-directories) (progn (when coq--debug-auto-compilation (message "Ignore %s" lib-obj-file)) t) nil)) ;;; convert .vo files to .v files and module names (defun coq-module-of-src-file (src-file) "Return the module name for SRC-FILE. SRC-FILE must be a .v file." (let ((file (file-name-nondirectory src-file))) (substring file 0 (max 0 (- (length file) 2))))) (defun coq-library-src-of-vo-file (lib-obj-file) "Return source file name for LIB-OBJ-FILE. Chops off the last character of LIB-OBJ-FILE to convert \"x.vo\" to \"x.v\"." (substring lib-obj-file 0 (- (length lib-obj-file) 1))) (defun coq-library-vio-of-vo-file (vo-obj-file) "Return .vio file name for VO-OBJ-FILE. Changes the suffix from .vo to .vio. VO-OBJ-FILE must have a .vo suffix." (concat (coq-library-src-of-vo-file vo-obj-file) "io")) (defun coq-library-vos-of-vo-file (vo-obj-file) "Return .vos file name for VO-OBJ-FILE. Changes the suffix from .vo to .vos. VO-OBJ-FILE must have a .vo suffix." (concat vo-obj-file "s")) (defun coq-library-vok-of-vo-file (vo-obj-file) "Return .vok file name for VO-OBJ-FILE. Changes the suffix from .vo to .vok. VO-OBJ-FILE must have a .vo suffix." (concat vo-obj-file "k")) ;;; ancestor unlocking ;;; (locking is different for sequential and parallel compilation) (defun coq-unlock-ancestor (ancestor-src) "Unlock ANCESTOR-SRC." (let* ((default-directory (buffer-local-value 'default-directory (or proof-script-buffer (current-buffer)))) (true-ancestor (file-truename ancestor-src))) (setq proof-included-files-list (delete true-ancestor proof-included-files-list)) (proof-restart-buffers (proof-files-to-buffers (list true-ancestor))))) (defun coq-unlock-all-ancestors-of-span (span) "Unlock all ancestors that have been locked when SPAN was asserted." (mapc #'coq-unlock-ancestor (span-property span 'coq-locked-ancestors)) (span-set-property span 'coq-locked-ancestors ())) ;;; manage coq--compile-response-buffer ;; XXX apparently nobody calls this with display equal to nil (defun coq-compile-display-error (command error-message display) "Display COMMAND and ERROR-MESSAGE in `coq--compile-response-buffer'. If needed, reinitialize `coq--compile-response-buffer'. Then display COMMAND and ERROR-MESSAGE." (unless (buffer-live-p (get-buffer coq--compile-response-buffer)) (coq-init-compile-response-buffer)) (let ((inhibit-read-only t) (deactivate-mark nil)) (with-current-buffer coq--compile-response-buffer (save-excursion (goto-char (point-max)) (insert command "\n" error-message "\n")))) (when display (coq-display-compile-response-buffer))) (defun coq-init-compile-response-buffer (&optional command) "Initialize the buffer for the compilation output. If `coq--compile-response-buffer' exists, empty it. Otherwise create a buffer with name `coq--compile-response-buffer', put it into `compilation-mode' and store it in `coq--compile-response-buffer' for later use. Argument COMMAND is the command whose output will appear in the buffer." (let ((buffer-object (get-buffer coq--compile-response-buffer))) (if buffer-object (let ((inhibit-read-only t)) (with-current-buffer buffer-object (erase-buffer))) (setq buffer-object (get-buffer-create coq--compile-response-buffer)) (with-current-buffer buffer-object (compilation-mode) ;; read-only-mode makes compilation fail if some messages need ;; to be displayed by compilation. there was a bug in emacs 23 ;; which make it work some time without this, but now it seems ;; mandatory: (read-only-mode 0))) ;; I don't really care if somebody gets the right mode when ;; he saves and reloads this buffer. However, error messages in ;; the first line are not found for some reason ... (let ((inhibit-read-only t)) (with-current-buffer buffer-object (insert "-*- mode: compilation; -*-\n\n") (when command (insert command "\n")))))) (defun coq-display-compile-response-buffer () "Display the errors in `coq--compile-response-buffer'." (with-current-buffer coq--compile-response-buffer ;; fontification enables the error messages (let ((font-lock-verbose nil)) ; shut up font-lock messages (if (fboundp 'font-lock-ensure) (font-lock-ensure) (with-no-warnings (font-lock-fontify-buffer))))) ;; Make it so the next C-x ` will use this buffer. (setq next-error-last-buffer (get-buffer coq--compile-response-buffer)) (proof-display-and-keep-buffer coq--compile-response-buffer 1 t) ;; Partial fix for #54: ensure that the compilation response ;; buffer is not in a dedicated window. (mapc (lambda (w) (set-window-dedicated-p w nil)) (get-buffer-window-list coq--compile-response-buffer nil t))) ;;; enable next-error to find vio2vo errors ;; ;; compilation-error-regexp-alist-alist is an alist mapping symbols to ;; what is expected for compilation-error-regexp-alist. This is ;; element of the form (REGEXP FILE [LINE COLUMN TYPE HYPERLINK ;; HIGHLIGHT...]). If REGEXP matches, the FILE'th subexpression gives ;; the file name, and the LINE'th subexpression gives the line number. ;; The COLUMN'th subexpression gives the column number on that line, ;; see the documentation of compilation-error-regexp-alist. ;; ;; Need to wrap adding the vio2vo error regex in eval-after-load, ;; because compile is loaded on demand and might not be present when ;; the user visits the first Coq file. (eval-after-load 'compile '(progn (push '(coq-vio2vo "File \\(.*\\): proof of [^:]*\\(: chars \\([0-9]*\\)-\\([0-9]*\\)\\)?" 1 nil 3) compilation-error-regexp-alist-alist) (push 'coq-vio2vo compilation-error-regexp-alist))) ;;; save some buffers (defvar coq-compile-buffer-with-current-require "Local variable for two coq-seq-* functions. This only locally used variable communicates the current buffer from `coq-compile-save-some-buffers' to `coq-compile-save-buffer-filter'.") (defun coq-compile-save-buffer-filter () "Filter predicate for `coq-compile-save-some-buffers'. See also `save-some-buffers'. Return t for buffers with major mode 'coq-mode' different from `coq-compile-buffer-with-current-require' and nil for all other buffers. We will also return nil if the buffer is ephemeral, or not backed by a file. The buffer to test must be current." (and (eq major-mode 'coq-mode) (not (string-prefix-p " " (buffer-name))) buffer-file-name (not (eq coq-compile-buffer-with-current-require (current-buffer))))) (defun coq-compile-save-some-buffers () "Save buffers according to `coq-compile-auto-save'. Uses the local variable ‘coq-compile-buffer-with-current-require’ to pass the current buffer (which contains the Require command) to `coq-compile-save-buffer-filter'." (let ((coq-compile-buffer-with-current-require (current-buffer)) unconditionally buffer-filter) (cond ((eq coq-compile-auto-save 'ask-coq) (setq unconditionally nil buffer-filter 'coq-compile-save-buffer-filter)) ((eq coq-compile-auto-save 'ask-all) (setq unconditionally nil buffer-filter nil)) ((eq coq-compile-auto-save 'save-coq) (setq unconditionally t buffer-filter 'coq-compile-save-buffer-filter)) ((eq coq-compile-auto-save 'save-all) (setq unconditionally t buffer-filter nil))) (save-some-buffers unconditionally buffer-filter))) (provide 'coq-compile-common) ;; Local Variables: *** ;; coding: utf-8 *** ;; End: *** ;;; coq-compile-common.el ends here PG-4.5/coq/coq-db.el000066400000000000000000000355551426357011200141570ustar00rootroot00000000000000;;; coq-db.el --- coq keywords database utility functions -*- coding: utf-8; lexical-binding:t -*- ;; This file is part of Proof General. ;; Portions © Copyright 1994-2012 David Aspinall and University of Edinburgh ;; Portions © Copyright 2003-2018 Free Software Foundation, Inc. ;; Portions © Copyright 2001-2017 Pierre Courtieu ;; Portions © Copyright 2010, 2016 Erik Martin-Dorel ;; Portions © Copyright 2011-2013, 2016-2017 Hendrik Tews ;; Portions © Copyright 2015-2017 Clément Pit-Claudel ;; Author: Pierre Courtieu ;; SPDX-License-Identifier: GPL-3.0-or-later ;;; Commentary: ;; ;; We store all information on keywords (tactics or command) in big ;; tables (ex: `coq-tactics-db') From there we get: menus including ;; "smart" commands, completions for command coq-insert-... ;; abbrev tables and font-lock keyword. ;; ;;; Code: (eval-when-compile (require 'cl-lib)) ;decf (require 'holes) (require 'diff-mode) (defconst coq-syntax-db nil "Documentation-only variable, for coq keyword databases. Each element of a keyword database contains the definition of a \"form\", of the form: \(MENUNAME ABBREV INSERT STATECH KWREG INSERT-FUN HIDE) MENUNAME is the name of form (or form variant) as it should appear in menus or completion lists. ABBREV is the abbreviation for completion via \\[expand-abbrev]. INSERT is the complete text of the form, which may contain holes denoted by \"#\" or \"@{xxx}\". If non-nil the optional STATECH specifies that the command is not state preserving for coq. If non-nil the optional KWREG is the regexp to colorize correponding to the keyword. ex: \"simple\\\\s-+destruct\" (\\\\s-+ meaning \"one or more spaces\"). *WARNING*: A regexp longer than another one should be put FIRST. For example: (\"Module Type\" ... ... t \"Module\\s-+Type\") (\"Module\" ... ... t \"Module\") Is ok because the longer regexp is recognized first. If non-nil the optional INSERT-FUN is the function to be called when inserting the form (instead of inserting INSERT, except when using \\[expand-abbrev]). This allows to write functions asking for more information to assist the user. If non-nil the optional HIDE specifies that this form should not appear in the menu but only in interactive completions. Example of what could be in your emacs init file: \(defvar coq-user-tactics-db '( (\"mytac\" \"mt\" \"mytac # #\" t \"mytac\") (\"myassert by\" \"massb\" \"myassert ( # : # ) by #\" t \"assert\") )) Explanation of the first line: the tactic menu entry mytac, abbreviated by mt, will insert \"mytac # #\" where #s are holes to fill, and \"mytac\" becomes a new keyword to colorize.") (defun coq-insert-from-db (db prompt &optional alwaysjump) "Ask for a keyword, with completion on keyword database DB and insert. Insert corresponding string with holes at point. If an insertion function is present for the keyword, call it instead. See `coq-syntax-db' for DB structure. If ALWAYSJUMP is non nil, jump to the first hole even if more than one." (let* ((tac (completing-read (concat prompt " (TAB for completion): ") db nil nil)) (infos (cddr (assoc tac db))) (s (car infos)) ; completion to insert (f (car-safe (cdr-safe (cdr-safe (cdr infos))))) ; insertion function (pt (point))) (if f (funcall f) ; call f if present (insert (or s tac)) ; insert completion and indent otherwise (holes-replace-string-by-holes-backward-jump pt nil alwaysjump) (indent-according-to-mode)))) (defun coq-build-command-from-db (db prompt &optional _preformatquery) "Ask for a keyword, with completion on keyword database DB and send to Coq. See `coq-syntax-db' for DB structure." ;; Next invocation of minibuffer (read-string below) will first recursively ;; ask for a command in db and expand it with holes. This way the cursor will ;; be at the right place. (minibuffer-with-setup-hook (lambda () (coq-insert-from-db db prompt t)) ;; I use recursive edition on the minibuffer here, because I want the cursor ;; to be moved inside the initial content (let ((enable-recursive-minibuffers t)) ; invo (read-string (concat prompt " : ")) ; (read-from-minibuffer (concat prompt " : ")) ))) ; ;(defun coq-build-command-from-db (db prompt &optional preformatquery) ; "Ask for a keyword, with completion on keyword database DB and send to coq. ;See `coq-syntax-db' for DB structure." ; (let* ((query (completing-read (concat prompt " (TAB for completion): ") ; db nil nil)) ; (infos (cddr (assoc query db))) ; (s (car infos)) ; ; default format is add a space at the end of query, for arguments. ; (preformat (or preformatquery '(lambda (s) (concat s " ")))) ; (initialvalue (funcall preformat query)) ; (whole-query ; (minibuffer-with-setup-hook ; 'coq-move-cursor-at-sharp ; (read-string (concat prompt " : ") initialvalue t nil)))) ; whole-query)) ; (defun coq-build-regexp-list-from-db (db &optional filter) "Take a keyword database DB and return the list of regexps for font-lock. If non-nil Optional argument FILTER is a function applying to each line of DB. For each line if FILTER returns nil, then the keyword is not added to the regexp. See `coq-syntax-db' for DB structure." (let ((l db) res) (while l (let* ((hd (car l)) (tl (cdr l)) ; hd is the first infos list (color (nth 4 hd))) ; colorization string ; da: do this below, otherwise we get empty words in result!! ; (color (concat "\\_<" (nth 4 hd) "\\_>"))) ; colorization string ;; TODO delete doublons (when (and color (or (not filter) (funcall filter hd))) (setq res (nconc res (list (concat "\\_<" color "\\_>"))))) (setq l tl))) res)) (defun coq-build-opt-regexp-from-db (db &optional filter) "Take a keyword database DB and return a regexps for font-lock. If non-nil optional argument FILTER is a function applying to each line of DB. For each line if FILTER returns nil, then the keyword is not added to the regexp. See `coq-syntax-db' for DB structure." (let ((l db) res) (while l (let* ((hd (car l)) (tl (cdr l)) ; hd is the first infos list (color (nth 4 hd))) ; colorization string ;; TODO delete doublons (when (and color (or (not filter) (funcall filter hd))) (setq res (nconc res (list color)))) ; careful: nconc destructive! (setq l tl))) ; da: next call is wrong? ; (proof-ids-to-regexp res))) (concat "\\_<\\(?:" (mapconcat #'identity res "\\|") "\\)\\_>"))) ;; Computes the max length of strings in a list (defun max-length-db (db) "Return the length of the longest first element (menu label) of DB. See `coq-syntax-db' for DB structure." (let ((l db) (res 0)) (while l (let ((lgth (length (car (car l))))) (setq res (max lgth res)) (setq l (cdr l)))) res)) (defun coq-build-menu-from-db-internal (db lgth menuwidth) "Take a keyword database DB and return one insertion submenu. Argument LGTH is the max size of the submenu. Argument MENUWIDTH is the width of the largest line in the menu (without abbrev and shortcut specifications). Used by `coq-build-menu-from-db', which you should probably use instead. See `coq-syntax-db' for DB structure." (let ((l db) (res ()) (size lgth) (keybind-abbrev (substitute-command-keys " \\[expand-abbrev]"))) (while (and l (> size 0)) (let* ((hd (pop l)) (menu (nth 0 hd)) ; e1 = menu entry (abbrev (nth 1 hd)) ; e2 = abbreviation (complt (nth 2 hd)) ; e3 = completion ;; (state (nth 3 hd)) ; e4 = state changing ;; (color (nth 4 hd)) ; e5 = colorization string (insertfn (nth 5 hd)) ; e6 = function for smart insertion (menuhide (nth 6 hd)) ; e7 = if non-nil : hide in menu (entry-with (max (- menuwidth (length menu)) 0)) (spaces (make-string entry-with ? )) ;;(restofmenu (coq-build-menu-from-db-internal tl (- size 1) menuwidth)) ) (unless menuhide (let ((menu-entry (vector ;; menu entry label (concat menu (if (not abbrev) "" (concat spaces "(" abbrev keybind-abbrev ")"))) ;;insertion function if present otherwise insert completion (if insertfn insertfn `(holes-insert-and-expand ,complt)) t))) (push menu-entry res))) (cl-decf size))) (nreverse res))) (defun coq-build-title-menu (db size) "Build a title for the first submenu of DB, of size SIZE. Return the string made of the first and the SIZE nth first element of DB, separated by \"...\". Used by `coq-build-menu-from-db'. See `coq-syntax-db' for DB structure." (concat (car-safe (car-safe db)) " ... " (car-safe (car-safe (nthcdr (- size 1) db))))) (defun coq-sort-menu-entries (menu) (sort menu #'(lambda (x y) (string< (downcase (elt x 0)) (downcase (elt y 0)))))) (defun coq-build-menu-from-db (db &optional size) "Take a keyword database DB and return a list of insertion menus for them. Submenus contain SIZE entries (default 30). See `coq-syntax-db' for DB structure." ;; sort is destructive for the list, so copy list before sorting (let* ((l (coq-sort-menu-entries (copy-sequence db))) (res ()) (wdth (+ 2 (max-length-db db))) (sz (or size 30)) (lgth (length l))) (while l (if (<= lgth sz) (setq res ;; careful: nconc destructive! (nconc res (list (cons (coq-build-title-menu l lgth) (coq-build-menu-from-db-internal l lgth wdth))))) (setq res ; careful: nconc destructive! (nconc res (list (cons (coq-build-title-menu l sz) (coq-build-menu-from-db-internal l sz wdth)))))) (setq l (nthcdr sz l)) (setq lgth (length l))) res)) (defcustom coq-holes-minor-mode t "*Whether to apply holes minor mode (see `holes-show-doc') in coq mode." :type 'boolean :group 'coq) (defun coq-build-abbrev-table-from-db (db) "Take a keyword database DB and return an abbrev table. See `coq-syntax-db' for DB structure." (let ((l db) (res ())) (while l (let* ((hd (car l))(tl (cdr l)) ; hd is a list of length 3 or 4 (_e1 (car hd)) (tl1 (cdr hd)) ; e1 = menu entry (e2 (car tl1)) (tl2 (cdr tl1)) ; e2 = abbreviation (e3 (car tl2)) (_tl3 (cdr tl2)) ; e3 = completion ) ;; careful: nconc destructive! (when e2 (push `(,e2 ,e3 ,(if coq-holes-minor-mode #'holes-abbrev-complete) :system t) res)) (setq l tl))) (nreverse res))) (defun filter-state-preserving (l) ; checkdoc-params: (l) "Not documented." (not (nth 3 l))) ; fourth argument is nil --> state preserving command (defun filter-state-changing (l) ; checkdoc-params: (l) "Not documented." (nth 3 l)) ; fourth argument is nil --> state preserving command ;;A new face for tactics which fail when they don't kill the current goal (defface coq-solve-tactics-face `((((background light)) :foreground "red") (((background dark)) :foreground "red1") ()) ; pour le noir et blanc "Face for names of closing tactics in proof scripts." :group 'proof-faces) ;;A face for cheating tactics ;; We use :box in addition to :background because box remains visible in ;; locked-region. :reverse-video is another solution. (defface coq-cheat-face '(;(((class color) (background light)) . (:inverse-video t :foreground "red" :background "black")) ;(((class color) (background dark)) . (:inverse-video t :foreground "red1")) (((class color) (background light)) . (:box (:line-width -1 :color "red" :style nil) :background "red")) (((class color) (background dark)) . (:box (:line-width -1 :color "red1" :style nil) :background "red1")) (t . ())) ; monocolor or greyscale: no highlight "Face for names of cheating tactics in proof scripts." :group 'proof-faces) (defface coq-symbol-binder-face '((t :inherit font-lock-type-face :bold coq-bold-unicode-binders)) "Face for unicode binders, by default a bold version of `font-lock-type-face'." :group 'proof-faces) (defface coq-symbol-face '((t :inherit font-lock-type-face :bold coq-bold-unicode-binders)) "Face for unicode binders, by default a bold version of `font-lock-type-face'." :group 'proof-faces) (defface coq-question-mark-face '((t :inherit font-lock-variable-name-face)) "Face for Ltac binders and evars." :group 'proof-faces) (defface coq-context-qualifier-face '((t :inherit font-lock-preprocessor-face :weight bold)) "Face used for `ltac:', `constr:', and `uconstr:' headers." :group 'proof-faces) ;; This is so quite ugly, better have our own face. ;; (defface coq-button-face ;; '((t :inherit custom-button :background "dark gray" ;; ;; -1 avoids messing with line and column sizes ;; :box (:line-width (-1 . -1) :style key-pressed))) ;; "" ;; :group 'proof-faces) (defface coq-button-face '( (((class color) (background light)) . (:background "light gray")) (((class color) (background dark)) . (:background "gray" :foreground "black"))) "Coq face for the (un)folding hypothesis button" :group 'proof-faces) (defface coq-button-face-pressed '((((class color) (background light)) . (:background "gray")) (((class color) (background dark)) . (:background "dim gray" :foreground "black"))) "Coq face for the (un)folding hypothesis button" :group 'proof-faces) (defface coq-button-face-active '((((class color) (background light)) . (:background "black" :foreground "white")) (((class color) (background dark)) . (:background "grey24" :foreground "black"))) "Coq face for the (un)folding hypothesis button" :group 'proof-faces) (defconst coq-solve-tactics-face 'coq-solve-tactics-face "Expression that evaluates to a face. Required so that 'coq-solve-tactics-face is a proper facename") (defconst coq-cheat-face 'coq-cheat-face "Expression that evaluates to a face. Required so that 'coq-cheat-face is a proper facename") (defconst coq-symbol-binder-face 'coq-symbol-binder-face "Expression that evaluates to a face. Required so that 'coq-symbol-binder-face is a proper facename") (defconst coq-symbol-face 'coq-symbol-face "Expression that evaluates to a face. Required so that 'coq-symbol-binder-face is a proper facename") (defconst coq-question-mark-face 'coq-question-mark-face) (defface coq-diffs-added-face '((t . (:inherit diff-refine-added))) "Face used to highlight added text in diffs" :group 'proof-faces) (defface coq-diffs-removed-face '((t . (:inherit diff-refine-removed))) "Face used to highlight removed text in diffs" :group 'proof-faces) (defface coq-diffs-added-bg-face '((t . (:inherit diff-added))) "Face used to highlight unchanged text in lines showing added text in diffs" :group 'proof-faces) (defface coq-diffs-removed-bg-face '((t . (:inherit diff-removed))) "Face used to highlight unchanged text in lines showing removed text in diffs" :group 'proof-faces) (defvar coq-tag-map '(("diff.added" . coq-diffs-added-face) ("diff.removed" . coq-diffs-removed-face) ("diff.added.bg" . coq-diffs-added-bg-face) ("diff.removed.bg" . coq-diffs-removed-bg-face))) (provide 'coq-db) ;;; coq-db.el ends here ;** Local Variables: *** ;** fill-column: 80 *** ;** End: *** PG-4.5/coq/coq-diffs.el000066400000000000000000000054171426357011200146570ustar00rootroot00000000000000;;; coq-diffs.el --- highlight text marked with XML-like tags for Coq diffs -*- lexical-binding: t; -*- ;; This file is part of Proof General. ;; Portions © Copyright 2019 Jim Fehrle ;; Author: Jim Fehrle ;; SPDX-License-Identifier: GPL-3.0-or-later ;;; Commentary: ;; (require 'coq-db) ;;; Code: (defun coq-highlight-with-face (end face) (if face ;; (put-text-property (point) end 'face face) doesn't work (overlay-put (span-make (point) end) 'face face)) (goto-char end)) (defun coq-search (regex limit) (save-excursion (re-search-forward regex limit t))) (defun coq-insert-tagged-text (str) "Insert text into the current buffer applying faces specified by tags. For example 'foo' inserts 'foo' in the buffer and applies the appropriate face. `coq-tag-map' defines the mapping from tag name to face." ;; Coq inserts tags before splitting into lines. Avoid highlighting ;; white space at the beginning or end of lines in a conclusion or ;; hypothesis that's split across multiple lines. ;; Doesn't handle the unlikely case of escaping regular text ;; that looks like a tag. Unknown tags such as "" are ;; shown as-is. The user can turn off diffs in this very unlikely case. (let* ((fstack) (start (point)) (strend) (lend) (end-white-begin)) (insert str) (setq strend (copy-marker (point))) (goto-char start) (while (< (point) strend) (coq-search "^\\([ \t]*\\).*\\(\n\\)?" strend) (setq lend (copy-marker (match-end 0))) (if (match-end 1) (goto-char (match-end 1))) ;; begin-line white space (let* ((nl (if (match-string 2) 1 0)) (end-white-len ;; length of end-line white space (if (coq-search "[ \t\n]*\\'" lend) (- (match-end 0) (match-beginning 0)) 0))) (setq end-white-begin (copy-marker (- (- lend end-white-len) nl))) (while (and (< (point) lend) (coq-search "<\\(/\\)?\\([a-zA-Z\\.]+\\)>" lend)) (let* ((close-tag (match-beginning 1)) (tag (match-string 2)) (face (cdr (assoc tag coq-tag-map))) (start (match-beginning 0)) (end (match-end 0))) (coq-highlight-with-face start (car fstack)) ;; text before tag (if face (progn (replace-match "") (setq fstack (if close-tag (cdr fstack) (cons face fstack)))) ;; Unknown tag, show as-is! (coq-highlight-with-face end (car fstack))))) (coq-highlight-with-face end-white-begin (car fstack)) ;; text after last tag (goto-char lend))))) ;; end-line white space (provide 'coq-diffs) ;;; coq-diffs.el ends here PG-4.5/coq/coq-indent.el000066400000000000000000001331721426357011200150450ustar00rootroot00000000000000;;; coq-indent.el --- indentation for Coq -*- lexical-binding:t -*- ;; This file is part of Proof General. ;; Portions © Copyright 1994-2012 David Aspinall and University of Edinburgh ;; Portions © Copyright 2003-2021 Free Software Foundation, Inc. ;; Portions © Copyright 2001-2017 Pierre Courtieu ;; Portions © Copyright 2010, 2016 Erik Martin-Dorel ;; Portions © Copyright 2011-2013, 2016-2017 Hendrik Tews ;; Portions © Copyright 2015-2017 Clément Pit-Claudel ;; Authors: Pierre Courtieu ;; Maintainer: Pierre Courtieu ;; Commentary: ;; ;; Indentation for Coq. ;; This is experimental, the code is rather ugly for the moment. ;; ;;; Commentary: ;; ;;; Code: ;; debugging ;(defmacro measure-time (&rest body) ; "Measure the time it takes to evaluate BODY." ; `(let ((time (current-time))) ; ,@body ; (message "%.06f" (float-time (time-since time))))) (defconst coq-comment-start-regexp "(\\*") (defconst coq-comment-end-regexp "\\*)") (defconst coq-comment-start-or-end-regexp (concat coq-comment-start-regexp "\\|" coq-comment-end-regexp)) (defconst coq-bullet-regexp-nospace "\\(-\\)+\\|\\(+\\)+\\|\\(\\*\\)+" "Matches single bullet, WARNING: Lots of false positive. No context checking.") ;; goal selectors are of two forms; ;; 2: ;; [goalname]: (defconst coq-goal-selector-regexp "\\(?:[0-9]+\\|\\[\\w+\\]\\)\\s-*:\\s-*" "regexp of goal selector in coq.") ;;;;;;;;;;;;;;; FORWARD / BACKWARD REGEXP ;;;;;;;;;;;;;;;;; ;; These regexp are used to split the buffer into commands. They make ;; use of the fact that the file is processed from top to bottom. At ;; each step the point is put just after the last recognized chunk, ;; then spaces are jumped, and THEN the regexp for command end is ;; searched. Since bullets are are command ends occurring at command ;; start, we use the "\\=" regexp to tell if we are at the beginning ;; of a command. We don't car for the presence of comments, as the ;; regexp search is launched once coments are passed. ;; On the contrary when going backward we cannot use this trick. ;; NOTE: \\= here allows to fail when the user types a "." just after ;; an already played command with no space. (defconst coq-simple-cmd-ender-prefix-regexp-forward "[^.]\\|\\=\\|\\.\\." "Used internally. Matches the allowed prefixes of coq \".\" command ending.") (defconst coq-simple-cmd-ender-prefix-regexp-backward "[^.]\\|\\.\\." "Used internally. Matches the allowed prefixes of coq \".\" command ending.") ;; bullets must appear after a command end. So when splitting a buffer ;; forward it is enough that they appear at cursor, maybe preceded by ;; a goal selector (defconst coq-bullet-prefix-regexp-forward "\\=") ;; when going backward, we need to check that the bullet is located ;; after a nother command end. (defconst coq-bullet-prefix-regexp-backward (concat "\\(?:\\(?:" coq-simple-cmd-ender-prefix-regexp-backward "\\)\\(?:\\.\\s-+\\)" "\\(?:\\(?:" coq-goal-selector-regexp "\\)?" "{\\|}\\|-\\|+\\|\\*\\)+\\s-*\\)")) ;; matches regular command end (. and ... followed by a space or "}" or buffer end) ;; ". " and "... " are command endings, ".. " is not, same as in ;; proof-script-command-end-regexp in coq.el (defconst coq-period-end-command (concat "\\(?:\\(?2:" coq-simple-cmd-ender-prefix-regexp-forward "\\)\\(?1:\\.\\)\\(?3:\\s-\\|\\}\\|\\'\\)\\)") "Matches coq regular syntax for ending a command (except bullets and curlies). This should match EXACTLY command ending syntax. No false positive should be accepted. \"...\" is matched as \".\" with a left context \"..\". There are 3 substrings (2 and 3 may be nil): * number 1 is the real bullet string, * number 2 is the left context matched that is not part of the bullet * number 3 is the right context matched that is not part of the bullet") ;; captures a lot of false bullets, unless called at the first non ;; space character of a command. The primary use of this variable is ;; to split the buffer into commands, from top to bottom. (defconst coq-bullet-end-command-forward (concat "\\(?:\\=\\(?1:" coq-bullet-regexp-nospace "\\)\\)") "Matches ltac bullets. WARNING: lots of false positive. This matches more than real bullets as - + and * may match this when used in regular expressions. See `coq-bullet-end-command-backward' for a more precise regexp (but only when searching backward).") ;; Context aware detecting regexp, usefull when search backward. (defconst coq-bullet-end-command-backward (concat "\\(?:\\(?2:" coq-bullet-prefix-regexp-backward "\\)\\(?1:\\(-\\)+\\|\\(+\\)+\\|\\(\\*\\)+\\)\\)") "Matches ltac bullets when searching backward. This should match EXACTLY bullets. No false positive should be accepted. There are 2 substrings: * number 1 is the real bullet string, * number 2 is the left context matched that is not part of the bullet" ) (defconst coq-curlybracket-end-command (concat "\\(?:" "\\(?2:" "\\(?:" coq-bullet-prefix-regexp-forward"\\)\\)" "\\(?1:\\(?:" coq-goal-selector-regexp "\\)?{\\)" "\\(?3:\\s-*[^|{]\\)" "\\|" ;; [^|]} "\\(?2:[^|.]\\|\\=\\)\\(?1:}\\)\\)") "Matches ltac curlies when searching backward. Warning: False positive. There are 3 substrings (2 and 3 may be nil): * number 1 is the real bullet string, * number 2 is the left context matched that is not part of the bullet * number 3 is the right context matched that is not part of the bullet This matches more than real ltac curlies. See `coq-bullet-end-command-backward' for a more precise regexp (but only when searching backward).") (defconst coq-curlybracket-end-command-backward (concat "\\(?:\\(?2:" coq-bullet-prefix-regexp-backward "\\)" "\\(?:\\(?:\\(?1:" "\\(?:" coq-goal-selector-regexp "\\)?{\\)" "\\(?3:[^|]\\)\\)" "\\|\\(?1:}\\)\\)\\)") "Matches ltac curly brackets when searching backward. This should match EXACTLY script structuring curlies. No false positive should be accepted. There are 3 substrings (2 and 3 may be nil): * number 1 is the real bullet string, * number 2 is the left context matched that is not part of the bullet * number 3 is the right context matched that is not part of the bullet") (defconst coq-end-command-regexp-forward (concat coq-period-end-command "\\|" coq-bullet-end-command-forward "\\|" coq-curlybracket-end-command) "Matches end of commands (and ltac bullets and curlies). WARNING: False positive. There are 3 substrings: * number 1 is the real coq ending string, * number 2 is the left context matched that is not part of the ending string * number 3 is the right context matched that is not part of the ending string WARNING: this regexp accepts some curly brackets and bullets (+ - *) with no sufficient context verification. Lots of false positive are matched. Currently bullets and curlies are always ending an empty command, so we just need to check that the command ended by the bullet-like regexp is empty. This is done in coq-smie.el, and see `coq-end-command-regexp-backward' for a more precise regexp (but only when searching backward).") ; Order here is significant, when two pattern match with the same ; starting position, the first regexp is preferred. period-command is ; the shorter one so let us have it at the end, but what about curly vs ; bullets? (defconst coq-end-command-regexp-backward (concat coq-bullet-end-command-backward "\\|" coq-curlybracket-end-command-backward "\\|" coq-period-end-command) "Matches end of commands, including bullets and curlies. There are 3 substrings (2 and 3 may be nil): * number 1 is the real coq ending string, * number 2 is the left context matched that is not part of the ending string * number 3 is the right context matched that is not part of the ending string Remark: This regexp is much more precise than `coq-end-command-regexp-forward' but only works when searching backward.") (defconst coq-cmd-end-backward-matcher (concat "\\(?2:" coq-simple-cmd-ender-prefix-regexp-backward "\\)\\.\\s-")) (defun coq-looking-at-comment () "Return non-nil if point is inside a comment." (or (proof-inside-comment (point)) (proof-inside-comment (+ 1 (point))))) (defun coq-find-previous-endcmd () "Internal use, look backward for a \".\" that is an end of command. Go backward and put point exactly after the first \".\" that is an end of command, or at point-min if none found. Return the new position." (re-search-backward (concat "\\(?2:" coq-simple-cmd-ender-prefix-regexp-backward "\\)\\.\\s-") (point-min) 'dummy) (while (coq-looking-at-comment) ;; we are looking for ". " so this is enough (re-search-backward (concat "\\(?2:" coq-simple-cmd-ender-prefix-regexp-backward "\\)\\.\\s-") (point-min) 'dummy)) ;; unless we reached point-min, jump over the "." (when (match-end 2) (goto-char (match-end 2)) (forward-char 1)) (point)) (defun coq-find-start-of-cmd () (let ((p (point)) (something-found)) (coq-find-previous-endcmd) (while (not something-found) (forward-comment (point-max)) (if (and (looking-at "\\({\\|}\\|\\++\\|\\*+\\|-+\\)") (< (point) p) ;; if we are after the starting point then anything is the start of the current command, even "#" or ".". ) (forward-char 1) (setq something-found t)))) (point)) (defun coq-search-comment-delimiter-forward () "Search forward for a comment start (return 1) or end (return -1). Return nil if not found." (when (re-search-forward coq-comment-start-or-end-regexp nil 'dummy) (save-excursion (goto-char (match-beginning 0)) (if (looking-at coq-comment-start-regexp) 1 -1)))) (defun coq-search-comment-delimiter-backward () "Search backward for a comment start (return 1) or end (return -1). Return nil if not found." (when (re-search-backward coq-comment-start-or-end-regexp nil 'dummy) (if (looking-at coq-comment-start-regexp) 1 -1))) (defun coq-skip-until-one-comment-backward () "Skips comments and normal text until finding an unclosed comment start. Return nil if not found. Point is moved to the the unclosed comment start if found, to (point-max) otherwise. Return t if found, nil otherwise." (if (= (point) (point-min)) nil (ignore-errors (backward-char 1)) ; if point is between '(' and '*' (if (looking-at coq-comment-start-regexp) t (forward-char 1) (let ((nbopen 1) (kind nil)) (while (and (> nbopen 0) (setq kind (coq-search-comment-delimiter-backward))) (if (< kind 0) (setq nbopen (+ 1 nbopen)) (setq nbopen (- nbopen 1)))) (= nbopen 0))))) (defun coq-skip-until-one-comment-forward () "Skips comments and normal text until finding an unopened comment end." (ignore-errors (backward-char 1)) ; if point is between '*' and ')' (if (looking-at coq-comment-end-regexp) (progn (forward-char 2) t) (forward-char 1) (let ((nbopen 1) (kind nil)) (while (and (> nbopen 0) (setq kind (coq-search-comment-delimiter-forward))) (if (> kind 0) (setq nbopen (+ 1 nbopen)) (setq nbopen (- nbopen 1)))) (= nbopen 0)))) (defun coq-looking-at-comment () "Return non-nil if point is inside a comment." (or (proof-inside-comment (point)) (proof-inside-comment (+ 1 (point))))) (defun coq-find-comment-start () "Go to the current comment start. If inside nested comments, go to the start of the outer most comment. Return the position of the comment start. If not inside a comment, return nil and does not move the point." (when (coq-looking-at-comment) (let ((prevpos (point)) (init (point))) (while (coq-skip-until-one-comment-backward) (setq prevpos (point))) (goto-char prevpos) (if (= prevpos init) nil prevpos)))) (defun coq-find-comment-end () "Go to the current comment end. If inside nested comments, go to the end of the outer most comment. Return the position of the end of comment end. If not inside a comment, return nil and does not move the point." (let ((prevpos (point)) (init (point))) (while (coq-skip-until-one-comment-forward) (setq prevpos (point))) (goto-char prevpos) (if (= prevpos init) nil prevpos))) ; generic function is wrong when the point in between ( and * ;; (defun coq-looking-at-syntactic-context () ;; "See `proof-looking-at-syntactic-context'. ;; Use this one for coq instead of the generic one." ;; (if (coq-looking-at-comment) 'comment ;; (proof-looking-at-syntactic-context))) ;; (defconst coq-end-command-or-comment-regexp ;; (concat coq-comment-end-regexp "\\|" coq-end-command-regexp)) ;; (defconst coq-end-command-or-comment-start-regexp ;; (concat coq-comment-start-regexp "\\|" coq-end-command-regexp)) ;; (defun coq-find-not-in-comment-backward (reg &optional lim submatch) ;; "Moves to the first not commented occurrence of REG found looking up. ;; The point is put exactly before the occurrence if SUBMATCH is nil, ;; otherwise the point is put before SUBMATCHnth matched ;; sub-expression (see `match-string'). If no occurrence is found, go as ;; far as possible and return nil." ;; (coq-find-comment-start) ; first go out of comment if inside some ;; (let ((found nil) (continue t) ;; (regexp (concat coq-comment-end-regexp "\\|" reg))) ;; (while (and (not found) continue) ;; (setq continue (re-search-backward regexp lim 'dummy)) ;; (when continue ;; (if (coq-looking-at-comment) ;; (progn (coq-skip-until-one-comment-backward)) ;; (progn (when submatch (goto-char (match-beginning submatch))) ;; (setq found t))))) ;; (when found (point)))) ;; (defun coq-find-not-in-comment-forward (reg &optional lim submatch) ;; "Moves to the first not commented occurrence of REG found looking down. ;; The point is put exactly before the occurrence if SUBMATCH is nil, ;; otherwise the point is put before SUBMATCHnth matched sub-expression ;; \(see `match-string'). If no occurrence is found, go as far as possible ;; and return nil." ;; ;; da: PATCH here for http://proofgeneral.inf.ed.ac.uk/trac/ticket/173 ;; ;; (nasty example). But I don't understand this code! ;; ;; Sometimes we're called outside of a comment here. ;; (if (coq-looking-at-comment) ;; (coq-find-comment-end)) ;; (let ((found nil) (continue t) ;; (regexp (concat coq-comment-start-regexp "\\|" reg))) ;; (while (and (not found) continue) ;; (setq continue (re-search-forward regexp lim 'dummy)) ;; (when continue ;; (goto-char (match-beginning 0)) ;; (if (looking-at coq-comment-start-regexp) ;; (progn (forward-char 2) (coq-skip-until-one-comment-forward)) ;; (progn (when (and submatch (match-beginning submatch)) ;; (goto-char (match-beginning submatch))) ;; (setq found t)) ;; ))) ;; (when found (point)))) ;; check if we are in the middle of an command ender. Return the ;; number of shift needed to have to move one char to see the end of a ;; command. typically if we are ( >< is the cursor). intro.>< (defun coq-is-on-ending-context () (cond ((looking-at "}") 0) ((save-excursion (ignore-errors (forward-char -1) ; always nil, don't use "and" (looking-at "{\\|\\."))) 1) (t 0))) (defun coq-empty-command-p () "Test if between point and previous command is empty. Comments are ignored, of course." (forward-comment (- (point))) (unless (bobp) (forward-char -1)) ;; we must find a "." to be sure, because {O} {P} is allowed in definitions ;; with implicits --> this function is recursive (cond ;; "{" can be prefixed by a goal selector (coq-8.8). ;; TODO: looking-back is supposed to be slow. Find something else? ((or (and (looking-at "{")(looking-back "[0-9]+\\s-*:\\s-*" nil t)) (and (looking-at ":\\s-*{")(looking-back "[0-9]+\\s-*" nil t)) (and (looking-at "[0-9]+:\\s-*{") nil t)) (goto-char (match-beginning 0)) ; swallow goal selector (coq-empty-command-p)) ;; other bulleting syntax ((looking-at "{\\|}\\|-\\|\\+\\|\\*") (coq-empty-command-p)) ;; vernacular controls Time, Fail, Redirect, Timeout ((or (and (looking-at "e\\>") (looking-back "\\") (looking-back "\\") (looking-back "\\ (coq-is-on-ending-context) 0) (ignore-errors(forward-char (coq-is-on-ending-context)))) (let (foundbeg) ;; Find end of previous command (while (and (setq foundbeg (and (re-search-backward coq-end-command-regexp-backward limit 'dummy) (match-beginning 1))) ;; Given the form of coq-end-command-regexp-backward ;; - bullets should be correctly detected ;; - match-beginning 1 is the right place to start again ;; to search backward, next time we start from just ;; there, unless we are in a comment (goto-char foundbeg) (let ((ppss (syntax-ppss))) ;; If neither within a string nor a comment, just exit the ;; loop. Otherwise see what kind of syntactic (and (nth 8 ppss) (cond ;; jump directly out of a comment ((nth 4 ppss) (setq foundbeg (goto-char (nth 8 ppss)))) ((nth 3 ppss) t) ;FIXME: Why? ;; nil captured before entering the cond (t (message "assert false")))))) (ignore-errors (goto-char foundbeg))) (if (and foundbeg (goto-char foundbeg) ; move to command end (not (nth 8 (syntax-ppss)))) ;; Found command end outside string/comment 'cmd ;; Didn't find command end nil)))) (defun coq-find-current-start () "Move to the start of command at point. The point is put exactly after the end of previous command, or at the (point-min) if there is no previous command." (coq-script-parse-cmdend-backward) (let ((case-fold-search nil)) (when (looking-at "\\.\\s-\\|{\\|}\\|\\++\\|\\*+\\|-+") (forward-char (- (match-end 0) (match-beginning 0))))) ; else = no match found (point)) (defun coq-find-real-start () "Move to the start of command at point. The point is put exactly before first non comment letter of the command." (coq-find-start-of-cmd)) ;; (defun same-line (pt pt2) ;; (or (= (line-number-at-pos pt) (line-number-at-pos pt2)))) ;; (defun coq-command-at-point (&optional nojumplines) ;; "Return the string of the command at point, nil if none. ;; Can jump line if NOJUMPLINES = nil." ;; (let ((initpos (point))) ;; (save-excursion ;; (let* ((st (coq-find-real-start)) ; va chercher trop loin? OUI ;; (linejumped (not (same-line initpos (point)))) ;; ;(xxx (goto-char (- (point) 1))) ;; (nd (or (if (coq-script-parse-cmdend-forward) (point) nil) ;; (- (point-max) 1)))) ; idem? ;; (if (and st (or (not nojumplines) (not linejumped))) ;; (buffer-substring st nd) ;; nil))))) ;; (defun coq-commands-at-line (&optional nojumplines) ;; "Return the string of each command at current line." ;; (save-excursion ;; ;; we must capture a "." or a "{" at start of the line. So we go at the end of ;; ;; previous line to have a left context to match ;; (let ((initpoint (point)) ;; (forward-char (coq-is-on-ending-context)) ;; (command-found (coq-command-at-point nojumplines)) ;; res ;; ) ;; (if command-found (coq-find-real-start)) ;; (while (and command-found ;; ;; need this second test even with nojumplines: ;; (same-line (point) initpoint)) ;; (setq res (cons command-found res)) ;; (if (and (coq-script-parse-cmdend-forward) ;; ;(ignore-errors (forward-char 1) t);to fit in the "and" ;; (coq-find-real-start)) ;; (setq command-found (coq-command-at-point nojumplines)) ;; (setq command-found nil) ;; )) ;; res))) ;; (defun coq-indent-only-spaces-on-line () ;; "Non-nil if there only spaces (or nothing) on the current line after point. ;; Moves point to first non space char if present, to the end of line otherwise." ;; (skip-chars-forward " \t" (save-excursion (end-of-line) (point))) ;; (eolp)) ;; (defun coq-indent-find-reg (lim reg) ;; "Non-nil if REG occurs between point and LIM, not in a comment or string. ;; Point is moved at the end of the match if found, at LIM otherwise." ;; (let ((oldpt (point)) (limit lim) (found nil)) ;; (if (= limit (point)) nil ;; ;;swap limit and point if necessary ;; ; (message "coq-indent-find-reg...") ;; (when (< limit (point)) (let ((x limit)) (setq limit (point)) (goto-char x))) ;; (prog1 ;; (coq-find-not-in-comment-forward reg limit) ;; (goto-char (match-end 0)))))) ;; (defun coq-find-no-syntactic-on-line () ;; "Return non-nil if there is a not commented non white character on the line. ;; Moves point to this char or to the end of the line if not found (and ;; return nil in this case)." ;; (let ((eol (save-excursion (end-of-line) (point)))) ;; (back-to-indentation) ;; (while (and (coq-looking-at-syntactic-context) ;; (re-search-forward coq-comment-end-regexp eol 'dummy)) ;; (skip-chars-forward " \t")) ;; (not (eolp)))) ;; (defun coq-back-to-indentation-prevline () ;; "Move point back to previous pertinent line for indentation. ;; Move point to the first non white space character. Returns 0 if ;; top of buffer was reached, 3 if inside a comment or string, 4 if ;; inside the {} of a record, 1 if the line found is not in the same ;; command as the point before the function was called, 2 ;; otherwise (point and previous line are in the same command, and ;; not inside the {} of a record)." ;; (if (coq-looking-at-syntactic-context) 3 ;; (let ((oldpt (point)) ;; (topnotreached (= (forward-line -1) 0))) ;;; nil if going one line backward ;; ;;; is not possible ;; (while (and topnotreached ;; (not (coq-find-no-syntactic-on-line)) ;; ) ;; (setq topnotreached (= (forward-line -1) 0)) ;; (end-of-line) ;; (if (proof-looking-at-syntactic-context) ;; (re-search-backward coq-comment-start-regexp nil 'dummy) ;; )) ;; (back-to-indentation) ;; (if (not topnotreached) 0 ;; returns nil if top of buffer was reached ;; ;; if we are at end of a command (dot) find this command ;; ; if there is a "." alone on the line ;; (let ((pos (point))) ;; ;(ignore-errors (forward-char -1)) ;; (if (coq-script-parse-cmdend-forward oldpt) ;; (progn (forward-char -1) ;; ;; one more if "." found, no more if "{" or "}" ;; (when (proof-looking-at "\\.") (forward-char -1)) ;; (coq-find-real-start) ;; (back-to-indentation) ;; 1) ;; (goto-char pos) ;; (if (save-excursion ;; (and ;; (not (= (point) (point-min))) ;; (or (forward-char -1) t) ;; (coq-find-real-start) ;; (proof-looking-at-safe "Record\\|Class\\|Instance"); {struct} should not match this ;; (coq-indent-find-reg oldpt "{[^|]"))) ;; 4 ;; 2))))))) ;; (defun coq-find-unclosed (&optional optlvl limit openreg closereg) ;; "Finds the first unclosed open item (backward). ;; Counter starts to OPTLVL (default 1) and stops when reaching ;; LIMIT (default point-min)." ;; (let* ((lvl (or optlvl 1)) ;; (open-re (if openreg ;; (proof-regexp-alt openreg proof-indent-open-regexp) ;; proof-indent-open-regexp)) ;; (close-re (if closereg ;; (proof-regexp-alt closereg proof-indent-close-regexp) ;; proof-indent-close-regexp)) ;; (both-re (proof-regexp-alt "\\`" close-re open-re)) ;; (nextpt (save-excursion ;; (proof-re-search-backward both-re)))) ;; (while ;; (and (not (= lvl 0)) ;; (>= nextpt (or limit (point-min))) ;; (not (= nextpt (point-min)))) ;; (goto-char nextpt) ;; (cond ;; ((proof-looking-at-syntactic-context) ()) ;; ;; ((proof-looking-at-safe proof-indent-close-regexp) ;; ;; (coq-find-unclosed 1 limit)) ;; recursive call ;; ((proof-looking-at-safe close-re) (setq lvl (+ lvl 1))) ;; ((proof-looking-at-safe open-re) (setq lvl (- lvl 1)))) ;; (setq nextpt (save-excursion (proof-re-search-backward both-re)))) ;; (if (= lvl 0) t ;; (goto-char (or limit (point-min))) ;; nil))) ;; (defun coq-find-at-same-level-zero (limit openreg) ;; "Move to open or openreg (first found) at same parenthesis level as point. ;; Returns point if found." ;; (let* (found ;; min-reached ;; (open-re (if openreg ;; (proof-regexp-alt openreg proof-indent-open-regexp) ;; proof-indent-open-regexp)) ;; (close-re proof-indent-close-regexp) ;; (both-re (proof-regexp-alt "\\`" close-re open-re)) ;; (nextpt (save-excursion ;; (proof-re-search-backward both-re)))) ;; (while ; min-reached is set to t only after we have tested if found. ;; (and (not found) (not min-reached) ;; (>= nextpt (or limit (point-min)))) ;; (goto-char nextpt) ;; (cond ;; ((proof-looking-at-syntactic-context) ()) ;; ((proof-looking-at-safe openreg) (setq found t)) ;; ((proof-looking-at-safe proof-indent-open-regexp) (setq found t));assert false? ;; ;; ((proof-looking-at-safe closereg) (coq-find-unclosed 1 limit)) ;; ((proof-looking-at-safe proof-indent-close-regexp) ;; (coq-find-unclosed 1 limit))) ;; (if (= nextpt (point-min)) (setq min-reached t)) ;; (setq nextpt (save-excursion (proof-re-search-backward both-re)))) ;; (if found (point) nil))) ;; (defun coq-find-unopened (&optional optlvl limit) ;; "Find the last unopened close item (looking forward from point). ;; Counter starts to OPTLVL (default 1) and stops when reaching ;; LIMIT (default ‘point-max’). This function only works inside an ;; expression." ;; (let ((lvl (or optlvl 1)) after nextpt endpt) ;; (save-excursion ;; (proof-re-search-forward ;; (proof-regexp-alt "\\'" ;; proof-indent-close-regexp ;; proof-indent-open-regexp)) ;; (setq after (point)) ;; (goto-char (match-beginning 0)) ;; (setq nextpt (point))) ;; (while ;; (and (not (= lvl 0)) ;; (<= nextpt (or limit (point-max))) ;; (not (= nextpt (point-max)))) ;; (goto-char nextpt) ;; (setq endpt (point)) ;; (cond ;; ((proof-looking-at-syntactic-context) ()) ;; ((proof-looking-at-safe proof-indent-close-regexp) ;; (setq lvl (- lvl 1))) ;; ((proof-looking-at-safe proof-indent-open-regexp) ;; (setq lvl (+ lvl 1)))) ;; (goto-char after) ;; (save-excursion ;; (proof-re-search-forward ;; (proof-regexp-alt "\\'" ;; proof-indent-close-regexp ;; proof-indent-open-regexp)) ;; (setq after (point)) ;; (goto-char (match-beginning 0)) ;; (setq nextpt (point)))) ;; (if (= lvl 0) ;; (goto-char endpt) ;; (goto-char (or limit (point-max))) ;; nil))) ;; (defun coq-find-last-unopened (&optional optlvl limit) ;; "Backward move to and return the point of the last close item, not opened after LIMIT." ;; (let ((last nil)) ;; (while (coq-find-unopened optlvl limit) ;; (setq last (point)) ;; (forward-char 1)); shift one to the right, ;; ; that way the current match won'tbe matched again ;; (if last (goto-char last)) ;; last)) ;; (defun coq-end-offset (&optional limit) ;; "Find the first unclosed open indent item, and return its column. ;; Stop when reaching LIMIT (default to ‘point-min’)." ;; (save-excursion ;; (let ((found nil) ;; (anyreg (proof-regexp-alt "\\`" proof-indent-any-regexp))) ;; (while ;; (and (not found) ;; (> (point) (or limit (point-min)))) ;; (proof-re-search-backward anyreg) ;; (cond ;; ((proof-looking-at-syntactic-context) ()) ;; ((proof-looking-at-safe proof-indent-close-regexp) ;; (coq-find-unclosed)) ;; ((proof-looking-at-safe proof-indent-open-regexp) ;; (setq found t)) ;; (t ()))) ;; (if found (current-column) ;; -1000) ; no unclosed found ;; ))) ;; (defun coq-add-iter (l f) ;; (if (eq l nil) 0 (+ (if (funcall f (car l)) 1 0) (coq-add-iter (cdr l) f)))) ;; (defun coq-goal-count (l) (coq-add-iter l 'coq-indent-goal-command-p)) ;; (defun coq-save-count (l) ;; (coq-add-iter l (lambda (x) ;; (or (coq-save-command-p nil x) ;; (eq (proof-string-match "\\<\\(?:EndSubproof\\)\\>\\|}" x) 0))))) ;; (defun coq-proof-count (l) ;; (coq-add-iter l (lambda (x) ;; (eq (proof-string-match "\\<\\(?:Proof\\|BeginSubproof\\)\\>\\|{" x) 0)))) ;; returns the difference between goal (and assimilate Proof and BeginSubproof) and ;; save commands in a commands list. This is to ;; (defun coq-goal-save-diff-maybe-proof (l) ;; (let ((proofs (coq-proof-count l)) ;; (saves (coq-save-count l)) ;; (goals (coq-goal-count l))) ;; ; (if (= goals 0) (- (if (<= proofs 0) 0 1) (coq-save-count l)) ;; ; (- goals (coq-save-count l))) ;; (- (+ proofs goals) saves) ;; )) ;; (defun coq-indent-command-offset (kind prevcol prevpoint) ;; "Return the indentation offset of the current line. ;; This function indents a *command* line (the first line of a command). ;; Use `coq-indent-expr-offset' to indent a line belonging to an expression." ;; (let ((diff-goal-save-current ;; (coq-goal-save-diff-maybe-proof (coq-commands-at-line t))) ;; (diff-goal-save-prev ;; (save-excursion ;; (goto-char prevpoint) ;; (coq-goal-save-diff-maybe-proof (coq-commands-at-line t)))) ;; (prev-closing-beginning ; t if the closing is at start of the (prev) line ;; (save-excursion ;; (goto-char prevpoint) ;; (back-to-indentation) ;; ;(forward-char -1) ;; (looking-at coq-indent-close-regexp))) ;; (current-closing-beginning ; t if the closing is at start of the (current) line ;; (save-excursion ;; (back-to-indentation) ;; (looking-at coq-indent-close-regexp)))) ;; ;(message "currentkind,prevcol,prevpoint = %d , %d ,%d " kind prevcol prevpoint) ;; (cond ;; ((proof-looking-at-safe "\\") 0);; no indentation at "Proof ..." ;; (t (* proof-indent ;; (let ((res ;; (let ((a diff-goal-save-prev) (b diff-goal-save-current) ;; (a2 prev-closing-beginning) (b2 current-closing-beginning)) ;; ;(message "a,b,a2,b2 = %d,%d,%S,%S" a b a2 b2) ;; (cond ;; ((and (>= a 0) (>= b 0)) a) ;; ((and (>= a 0) (< b 0) b2) (+ a -1)) ; a + b ;; ((and (>= a 0) (< b 0) (not b2)) a) ;; ((and (< a 0) (< b 0) a2 b2) a) ; a +1 -1 ;; ((and (< a 0) (< b 0) a2 (not b2)) (+ a 1)) ;; ((and (< a 0) (< b 0) (not a2) b2) (+ a -1)) ;; ((and (< a 0) (< b 0) (not a2) (not b2)) a) ;; ((and (< a 0) (>= b 0) a2) (+ a 1)) ;; ((and (< a 0) (>= b 0) (not a2)) a) ;; (t (error "Muh?")))))) ;; ;(message "RES = %S" res) ;; ;(message "********************") ;; res)) ;; ) ;; ;; ;; we are at an end command -> one ident left unless previous line is a goal ;; ;; ;; (if goal and save are consecutive, then no indentation at all) ;; ;; ((and (< diff-goal-save-current 0) (<= diff-goal-save-prev 0)) (- proof-indent)) ;; ;; ;; previous command is a goal command -> one indent right unless the current one ;; ;; ;; is an end (consecutive goal and save). ;; ;; ((and (>= diff-goal-save-current 0) (> diff-goal-save-prev 0)) proof-indent) ;; ;; ;; otherwise -> same indent as previous command ;; ;; (t 0) ;; ))) ;; This function is very complex, indentation of a line (inside an ;; expression) is determined by the beginning of this line (current ;; point) and the indentation items found at previous pertinent (not ;; comment, not string, not empty) line. Sometimes we even need the ;; previous line of previous line. ;; prevcol is the indentation column of the previous line, prevpoint ;; is the indentation point of previous line, record tells if we are ;; inside the accolades of a record. ;; (defun coq-indent-expr-offset (kind prevcol prevpoint record) ;; "Return the indentation column of the current line. ;; This function indents a *expression* line (a line inside of a ;; command). Use `coq-indent-command-offset' to indent a line belonging ;; to a command. The fourth argument RECORD must be t if inside the {}s ;; of a record, nil otherwise." ;; ;(message "COQ-INDENT-EXPR-OFFSET") ;; (let ((pt (point)) real-start) ;; (save-excursion ;; (setq real-start (coq-find-real-start))) ;; (cond ;; ;; at a ) -> same indent as the *line* of corresponding ( ;; ((proof-looking-at-safe coq-indent-closepar-regexp) ;; (save-excursion (coq-find-unclosed 1 real-start) ;; (back-to-indentation) ;; (current-column))) ;; ;; at an end -> same indent as the corresponding match or Case ;; ((proof-looking-at-safe coq-indent-closematch-regexp) ;; (save-excursion (coq-find-unclosed 1 real-start) ;; (current-column))) ;; ;; if we find a "|" we indent from the first unclosed ;; ;; or from the command start (if we are in an Inductive type) ;; ((proof-looking-at-safe coq-indent-pattern-regexp) ;; (save-excursion ;; (coq-find-unclosed 1 real-start) ;; (cond ;; ((proof-looking-at-safe "\\s(") ;; (+ (current-indentation) proof-indent)) ;; ((proof-looking-at-safe (proof-regexp-alt-list coq-keywords-defn)) ;; (current-column)) ;; (t (+ (current-column) proof-indent))))) ;; ;; if we find a "then" we indent from the first unclosed if ;; ;; or from the command start (should not happen) ;; ((proof-looking-at-safe "\\") ;; (save-excursion ;; (coq-find-unclosed 1 real-start "\\" "\\") ;; (back-to-indentation) ;; (+ (current-column) proof-indent))) ;; ;; if we find a "else" we indent from the first unclosed if ;; ;; or from the command start (should not happen) ;; ((proof-looking-at-safe "\\") ;; (save-excursion ;; (coq-find-unclosed 1 real-start "\\" "\\") ;; (coq-find-unclosed 1 real-start "\\" "\\") ;; (back-to-indentation) ;; (+ (current-column) proof-indent))) ;; ;; there is an unclosed open in the previous line ;; ;; -> same column if match ;; ;; -> same indent than prev line + indent if ( ;; ((coq-find-unclosed 1 prevpoint ;; coq-indent-openmatch-regexp ;; coq-indent-closematch-regexp) ;; (let ((base (if (proof-looking-at-safe coq-indent-openmatch-regexp) ;; (current-column) ;; prevcol))) ;; (+ base proof-indent))) ;; ;; there is an unclosed '(' in the previous line -> prev line indent + indent ;; ;; ((and (goto-char pt) nil)) ; just for side effect: jump to initial point ;; ;; ((coq-find-unclosed 1 prevpoint ;; ;; coq-indent-openpar-regexp ;; ;; coq-indent-closepar-regexp) ;; ;; (+ prevcol proof-indent)) ;; ((and (goto-char prevpoint) nil)) ; just for side effect: jump to previous line ;; ;; find the last unopened ) -> indentation of line + indent ;; ((coq-find-last-unopened 1 pt) ; side effect, nil if no unopenned found ;; (save-excursion ;; (coq-find-unclosed 1 real-start) ;; (back-to-indentation) ;; (current-column))) ;; ;; just for side effect: jumps to end of previous line ;; ((and (goto-char prevpoint) ;; (or (and (end-of-line) nil) ;; (and (coq-find-not-in-comment-backward "[^[:space:]]") t)) nil)) ;; ;; TODO fix with new use of { for tactics enclosing ;; ;; should be ok if record is ok. ;; ((and (proof-looking-at-safe ";") ;prev line has ";" at the end ;; record) ; and we are inside {}s of a record ;; (save-excursion ;; (coq-find-unclosed 1 real-start) ;; (back-to-indentation) ;; (+ (current-column) proof-indent))) ;; ;; just for side effect: jumps to end of previous line ;; ((and (goto-char prevpoint) (not (= (coq-back-to-indentation-prevline) 0)) ;; (or (and (end-of-line) nil) ;; (and (forward-char -1) t)) nil)) ;; ((and (proof-looking-at-safe ";") ;prev prev line has ";" at the end ;; record) ; and we are inside {}s of a record ;; (save-excursion (+ prevcol proof-indent))) ;; ((and (goto-char pt) nil)) ;; just for side effect: go back to initial point ;; ;; There is a indent keyword (fun, forall etc) ;; ;; and we are not in {}s of a record just after a ";" ;; ((coq-find-at-same-level-zero prevpoint coq-indent-kw) ;; ;(message "COQ-INDENT-KW") ;; (+ prevcol proof-indent)) ;; ((and (goto-char prevpoint) nil)) ;; just for side effect: go back to previous line ;; ;; "|" at previous line ;; ((proof-looking-at-safe coq-indent-pattern-regexp) ;; (+ prevcol proof-indent)) ;; (t prevcol)))) ;; (defun coq-indent-comment-offset () ;; (save-excursion ;; (back-to-indentation) ;; (let ((oldpt (point)) ;; ;; atstart is true if the line to indent starts with a comment start ;; (atstart (proof-looking-at coq-comment-start-regexp))) ;; ;; go back looking for a non empty line ;; (if (/= (forward-line -1) 0) 0 ; we are at beginning of buffer ;; ;; only-space on a non empty line moves the point to first non space char ;; (while (and (coq-indent-only-spaces-on-line) (= (forward-line -1) 0)) ()) ;; ;; now we found the previous non empty line ;; (let ((eol (save-excursion (end-of-line) (point)))) ;; (cond ;; ;; The previous line contains is the comment start ;; ((and (not atstart) (string-match coq-comment-start-regexp ;; (buffer-substring (point) eol))) ;; (re-search-forward coq-comment-start-regexp) ;first '(*' in the line? ;; (+ 1 (current-column))) ;; ;; the previous is in the same comment start or a comment started at that line ;; ((and (not atstart) (proof-looking-at-syntactic-context)) ;; (skip-chars-forward " \t") ;; (current-column)) ;; ;;we were at the first line of a comment and the current line is the ;; ;;previous one ;; (t (goto-char oldpt) ;; (coq-script-parse-cmdend-backward) ;; (coq-find-real-start) ;; (current-column)))))))) ;; (defun coq-indent-offset (&optional notcomments) ;; (let (kind prevcol prevpoint) ;; (save-excursion ;; (setq kind (coq-back-to-indentation-prevline) ;go to previous *command* (assert) ;; prevcol (current-column) ;; prevpoint (point))) ;; ;(message "coq-indent-offset... kind = %s ; prevcol = %s; prevpoint = %s" kind prevcol prevpoint) ;; (cond ;; ((= kind 0) 0 ; top of the buffer reached ;; ) ;; ((= kind 1) ; we are at the command level ;; (+ prevcol (coq-indent-command-offset kind prevcol prevpoint))) ;; ((= kind 2) ; we are at the expression level ;; (coq-indent-expr-offset kind prevcol prevpoint nil)) ;; ((= kind 4) ; we are at the expression level inside {}s of a record ;; (coq-indent-expr-offset kind prevcol prevpoint t)) ;; ((= kind 3) ;; (if notcomments nil (coq-indent-comment-offset)))))) ;; (defun coq-indent-calculate (&optional notcomments) ;; (coq-indent-offset notcomments)) ;; (defun coq-indent-line () ;; "Indent current line of proof script, if indentation enabled." ;; (interactive) ;; (unless (not coq-script-indent) ;; (save-excursion ;; (let ((ind (save-excursion (back-to-indentation) (coq-indent-calculate)))) ;; (indent-line-to (max 0 ind)))) ;; (if (< (current-column) (current-indentation)) ;; (back-to-indentation)))) ;; (defun coq-indent-line-not-comments () ;; "Same as `coq-indent-line' but comments are not indented." ;; (interactive) ;; (unless (not coq-script-indent) ;; (save-excursion ;; (let ((ind (save-excursion (back-to-indentation) (coq-indent-calculate t)))) ;; (when ind (indent-line-to (max 0 ind))))) ;; (if (< (current-column) (current-indentation)) ;; (back-to-indentation)))) ;; (defun coq-indent-region (start end) ;; (let ((deb (min start end)) (fin (max start end))) ;; (goto-char end) ;; (setq fin (point-marker)) ;; to go back there even if shifted ;; (goto-char deb) ;; (while (< (point) fin) ;; (or (and (bolp) (eolp)) ;; (coq-indent-line-not-comments)) ;; (forward-line 1)) ;; (goto-char fin))) ;; Local Variables: *** ;; indent-tabs-mode:nil *** ;; End: *** (provide 'coq-indent) ;;; coq-indent.el ends here PG-4.5/coq/coq-local-vars.el000066400000000000000000000166201426357011200156250ustar00rootroot00000000000000;;; coq-local-vars.el --- local variable list tools for coq -*- lexical-binding:t -*- ;; This file is part of Proof General. ;; Portions © Copyright 1994-2012 David Aspinall and University of Edinburgh ;; Portions © Copyright 2003-2018 Free Software Foundation, Inc. ;; Portions © Copyright 2001-2017 Pierre Courtieu ;; Portions © Copyright 2010, 2016 Erik Martin-Dorel ;; Portions © Copyright 2011-2013, 2016-2017 Hendrik Tews ;; Portions © Copyright 2015-2017 Clément Pit-Claudel ;; Authors: Pierre Courtieu ;; Maintainer: Pierre Courtieu ;;; Commentary: ;; ;;; Code: (require 'local-vars-list) ; in lib directory (defvar coq-prog-name) (defvar coq-load-path) (defconst coq-local-vars-doc nil "Documentation-only variable. PROJECT FILE The recommended way of setting coqtop options (-I, -R and others) is to use a project file. See the coq documentation (\"generating makefile\") for details. The default name of the project file is \"_CoqProject\" (can be configured via `coq-project-filename') and its content should be a list of options to be given to coq_makefile (one option per line). Here is an example: -R foo bar -I foo2 -arg -foo3 ...(optionally followed by all .v files to be compiled) If `coq-use-project-file' is t (default) ProofGeneral reads the project file and sets coqtop options accordingly (via variable `coq-load-path' and variable `coq-prog-args'). In this example the coqtop invocation will be: coqtop -foo3 -R foo bar -I foo2 FILE VARIABLES If for some reason you want to avoid or override the project file method, you can use the file variables. See Info node ‘(emacs)File Variables’. This feature of Emacs allows to set Emacs variables on a per-file basis. File Variables are (usually) written as a list at the end of the file. We provide the following feature to help you: \\[coq-ask-insert-coq-prog-name] builds a standard file variable list for a coq file by asking you some questions. It is accessible in the menu `Coq' -> `COQ PROG (ARGS)' -> `Set coq prog *persistently*'. You should be able to use this feature without reading the rest of this documentation, which explains how it is used for coq. For more precision, refer to the Emacs info manual at ((Emacs)File Variables). In Coq projects involving multiple directories, it is usually necessary to set the variable `coq-load-path' for each file. For example, if the file .../dir/bar/foo.v builds on material in .../dir/theories/, then one would put the following local variable section at the end of foo.v: \(* *** Local Variables: *** coq-load-path: ((\"../util\" \"util\") \"../theories\") *** End: *) This way the necessary \"-I\" options are added to all invocations of `coqtop', `coqdep' and `coqc'. Note that the option \"-I\" \"../theories\" is specific to file foo.v. Setting `coq-load-path' globally via Emacs Customization is therefore usually inappropriate. With this local variables list, Emacs will set `coq-load-path' only when inside a buffer that visits foo.v. Other buffers can have their own value of `coq-load-path' (probably coming from their own local variable lists). If you use `make' for the compilation of coq modules you can set `coq-compile-command' as local variable. For instance, if the makefile is located in \".../dir\", you could set \(* *** Local Variables: *** coq-load-path: (\"../theories\") *** coq-compile-command: \"make -C .. %p/%o\" *** End: *) This way, if foo.v contains the command \"Require bar.\" then \"make -C .. .../theories/bar.vo\" will run, just before the require command is sent to coqtop (assuming that bar.v is found in .../theories). \(Note that `coq-compile-command' is quite flexible because of its use of substitution keys. A file local setting of `coq-compile-command' should therefore usually not be necessary.)") (defun coq-insert-coq-prog-name (progname coqloadpath) "Insert or modify the local variables `coq-prog-name' and `coq-load-path'. Set them to PROGNAME and COQLOADPATH respectively. These variables describe the coqtop command to be launched on this file." (add-file-local-variable 'coq-prog-name progname) (add-file-local-variable 'coq-load-path coqloadpath) ;; coq-guess-command-line uses coq-prog-name, so set it (make-local-variable 'coq-prog-name) (setq coq-prog-name progname) (make-local-variable 'coq-load-path) (setq coq-load-path coqloadpath)) (defun coq-read-directory (prompt &optional default maynotmatch initialcontent) "Ask for (using PROMPT) and return a directory name. Do not insert the default directory." (let* ;; read-file-name here because it is convenient to see .v files when ;; selecting directories to add to the path. Moreover read-directory-name ;; does not seem to exist in fsf emacs?? temporarily disable graphical ;; dialog, as read-file-name does not allow to select a directory ((current-use-dialog-box use-dialog-box) (_dummy (setq use-dialog-box nil)) (fname (file-name-nondirectory default)) (dir (file-name-directory default)) (path (read-file-name prompt dir fname (not maynotmatch) initialcontent))) (setq use-dialog-box current-use-dialog-box) path)) (defun coq-ask-load-path (&optional olddirs) "Ask for and return the information to put into `coq-load-path'. Optional argument OLDDIRS specifies the previous value of `coq-load-path', it will be used to suggest values to the user." (let (loadpath option) ;; first suggest previous directories (dolist (olddir olddirs) (if (y-or-n-p (format "Keep the directory %s? " olddir)) (setq loadpath (cons olddir loadpath)))) ;; then ask for more (setq option (coq-read-directory "Add directory (TAB to complete, empty to stop): -I " "")) (while (not (string-equal option "")) (setq loadpath (cons option loadpath)) ;reversed (setq option (coq-read-directory "Add directory (TAB to complete, empty to stop): -I " ""))) (message "Note: Syntax for option \"-R physicalpath logicalpath\":\ncoq-load-path: ((\"physicalpath\" \"logicalpath\") )") (reverse loadpath))) (defun coq-ask-prog-name (&optional oldvalue) "Ask for and return the local variables `coq-prog-name'. These variable describes the coqtop command to be launched on this file. Optional argument OLDVALUE specifies the previous value of `coq-prog-name', it will be used to suggest a value to the user." (let* ((deflt (or oldvalue "coqtop")) (cmd (coq-read-directory (concat "coq program name (default \"" oldvalue "\"): ") deflt t)) (cmd (if (string-equal cmd "") oldvalue cmd))) (if (and (string-match " " cmd) (not (y-or-n-p "The prog name contains spaces, are you sure ? "))) (coq-ask-prog-name oldvalue) ; retry cmd))) (defun coq-ask-insert-coq-prog-name () "Ask for and insert the local variables `coq-prog-name' and `coq-prog-args'. These variables describe the coqtop command to be launched on this file." (interactive) (let* ((oldname (local-vars-list-get-safe 'coq-prog-name)) (oldpath (local-vars-list-get-safe 'coq-load-path)) (progname (coq-ask-prog-name oldname)) (loadpath (coq-ask-load-path oldpath))) (coq-insert-coq-prog-name progname loadpath))) (provide 'coq-local-vars) ;;; coq-local-vars.el ends here ;; Local Variables: *** ;; fill-column: 79 *** ;; indent-tabs-mode: nil *** ;; End: *** PG-4.5/coq/coq-mode.el000066400000000000000000000214251426357011200145050ustar00rootroot00000000000000;;; coq-mode.el --- Major mode for Coq proof assistant -*- lexical-binding:t -*- ;; This file is part of Proof General. ;; Portions © Copyright 1994-2012 David Aspinall and University of Edinburgh ;; Portions © Copyright 2003, 2012, 2014, 2018 Free Software Foundation, Inc. ;; Portions © Copyright 2001-2017 Pierre Courtieu ;; Portions © Copyright 2010, 2016 Erik Martin-Dorel ;; Portions © Copyright 2011-2013, 2016-2017 Hendrik Tews ;; Portions © Copyright 2015-2017 Clément Pit-Claudel ;; Authors: Healfdene Goguen, Pierre Courtieu ;; Maintainer: Pierre Courtieu ;; SPDX-License-Identifier: GPL-3.0-or-later ;;; Commentary: ;; ;;; Code: (unless (locate-library "coq-mode") (add-to-list 'load-path (expand-file-name (file-name-directory (or load-file-name buffer-file-name))))) ;; (if t (require 'coq nil 'noerror)) (require 'coq-smie) (require 'coq-syntax) ;For font-lock-keywords (defgroup coq-mode () "Major mode to edit Coq code." :group 'programming) ;; prettify is in emacs > 24.4 ;; FIXME: this should probably be done like for smie above. (defvar coq-may-use-prettify (fboundp 'prettify-symbols-mode)) (defcustom coq-prog-name (or (if (executable-find "coqtop") "coqtop") (let ((exec-path (append exec-path '("C:/Program Files/Coq/bin")))) (executable-find "coqtop")) "coqtop") "Name of program to run as Coq. On Windows with latest Coq package you might need something like: C:/Program Files/Coq/bin/coqtop.opt.exe instead of just \"coqtop\". This must be a single program name with no arguments. See option `coq-prog-args' to manually adjust the arguments to the Coq process. See also `coq-prog-env' to adjust the environment." :type 'string :group 'coq :group 'coq-mode) (defun get-coq-library-directory () (let ((default-directory (if (file-accessible-directory-p default-directory) default-directory "/"))) (or (ignore-errors (car (process-lines coq-prog-name "-where"))) "/usr/local/lib/coq"))) (defconst coq-library-directory (get-coq-library-directory) ;; FIXME Should be refreshed more often "The coq library directory, as reported by \"coqtop -where\".") (defcustom coq-tags (expand-file-name "/theories/TAGS" coq-library-directory) "The default TAGS table for the Coq library." :type 'string) (defcustom coq-use-pg t "If non-nil, activate the ProofGeneral backend." :type 'boolean) ;; prettify is in emacs > 24.4 (defvar prettify-symbols-alist) (defconst coq-prettify-symbols-alist '(;;("not" . ?¬) ("/\\" . ?∧) ;; ("/\\" . ?⋀) ("\\/" . ?∨) ;; ("\\/" . ?⋁) ("forall" . ?∀) ;; ("forall" . ?Π) ("fun" . ?λ) ("exists" . ?∃) ("->" . ?→) ("<-" . ?←) ("=>" . ?⇒) ;; ("~>" . ?↝) ;; less desirable ;; ("-<" . ?↢) ;; Paterson's arrow syntax ;; ("-<" . ?⤙) ;; nicer but uncommon ("::" . ?∷) )) (defvar coq-mode-map (let ((map (make-sparse-keymap))) map) "Keymap for `coq-mode'.") (defvar coq-mode-syntax-table (let ((st (make-syntax-table))) (modify-syntax-entry ?\$ "." st) (modify-syntax-entry ?\/ "." st) (modify-syntax-entry ?\\ "." st) (modify-syntax-entry ?+ "." st) (modify-syntax-entry ?- "." st) (modify-syntax-entry ?= "." st) (modify-syntax-entry ?% "." st) (modify-syntax-entry ?< "." st) (modify-syntax-entry ?> "." st) (modify-syntax-entry ?\& "." st) (modify-syntax-entry ?_ "_" st) ; beware: word consituent EXCEPT in head position (modify-syntax-entry ?\' "_" st) ; always word constituent (modify-syntax-entry ?∀ "." st) (modify-syntax-entry ?∃ "." st) (modify-syntax-entry ?λ "." st) ;; maybe a bad idea... lambda is a letter (modify-syntax-entry ?\| "." st) ;; Should maybe be "_" but it makes coq-find-and-forget (in coq.el) bug, ;; hence the coq-with-altered-syntax-table to put "." into "_" class ;; temporarily. (modify-syntax-entry ?\. "." st) (modify-syntax-entry ?\* ". 23n" st) (modify-syntax-entry ?\( "()1" st) (modify-syntax-entry ?\) ")(4" st) st)) ;; FIXME, deal with interactive "Definition" (defvar coq-outline-regexp ;; (concat "(\\*\\|" (concat "[ ]*" (regexp-opt '( "Ltac" "Corr" "Modu" "Sect" "Chap" "Goal" "Definition" "Lemm" "Theo" "Fact" "Rema" "Mutu" "Fixp" "Func") t))) (defvar coq-outline-heading-end-regexp "\\.[ \t\n]") (defun coq-near-comment-region () "Return a list of the forme (BEG END). BEG,END being is the comment region near position PT. Return nil if PT is not near a comment. Near here means PT is either inside or just aside of a comment." (save-excursion (let ((pos (point)) (ppss (syntax-ppss (1- (point))))) (unless (nth 4 ppss) ;; We're not squarely inside a comment, nor at its end. ;; But we may still be at the beginning of a comment. (setq ppss (syntax-ppss (+ pos (if (looking-at comment-start-skip) 2 1))))) (when (nth 4 ppss) (goto-char (nth 8 ppss)) (list (point) (progn (forward-comment 1) (point))))))) (defun coq-fill-paragraph-function (_n) "Coq mode specific fill-paragraph function. Fills only comment at point." (let ((reg (coq-near-comment-region))) (when reg (fill-region (car reg) (cadr reg)))) t);; true to not fallback to standard fill function ;; TODO (but only for paragraphs in comments) ;; Should recognize coqdoc bullets, stars etc... Unplugged for now. (defun coq-adaptive-fill-function () (let ((reg (coq-near-comment-region))) (save-excursion (goto-char (car reg)) (re-search-forward "\\((\\*+ ?\\)\\( *\\)") (let* ((cm-start (match-string 1)) (cm-prefix (match-string 2))) (concat (make-string (length cm-start) ? ) cm-prefix))))) ;;;###autoload (add-to-list 'auto-mode-alist '("\\.v\\'" . coq-mode)) (defun coq--parent-mode () (if coq-use-pg (proof-mode) (prog-mode))) ;;;###autoload (define-derived-mode coq-mode coq--parent-mode "Coq" "Major mode for Coq scripts. \\{coq-mode-map}" ;; SMIE needs this. (set (make-local-variable 'parse-sexp-ignore-comments) t) ;; Coq error messages are thrown off by TAB chars. (set (make-local-variable 'indent-tabs-mode) nil) ;; Coq defninition never start by a parenthesis (set (make-local-variable 'open-paren-in-column-0-is-defun-start) nil) ;; do not break lines in code when filling (set (make-local-variable 'fill-nobreak-predicate) (lambda () (not (nth 4 (syntax-ppss))))) ;; coq mode specific indentation function (set (make-local-variable 'fill-paragraph-function) #'coq-fill-paragraph-function) ;; TODO (but only for paragraphs in comments) ;; (set (make-local-variable 'paragraph-start) "[ ]*\\((\\**\\|$\\)") ;; (set (make-local-variable 'paragraph-separate) "\\**) *$\\|$") ;; (set (make-local-variable 'adaptive-fill-function) ;; #'coq-adaptive-fill-function) (setq-local comment-start "(*") (setq-local comment-end "*)") (set (make-local-variable 'comment-start-skip) "(\\*+ *") (set (make-local-variable 'comment-end-skip) " *\\*+)") (smie-setup coq-smie-grammar #'coq-smie-rules :forward-token #'coq-smie-forward-token :backward-token #'coq-smie-backward-token) (add-hook 'smie-indent-functions #'coq-smie--args nil t) ;; old indentation code. ;; (require 'coq-indent) ;; (setq ;; ;; indentation is implemented in coq-indent.el ;; indent-line-function #'coq-indent-line ;; proof-indent-any-regexp coq-indent-any-regexp ;; proof-indent-open-regexp coq-indent-open-regexp ;; proof-indent-close-regexp coq-indent-close-regexp) ;; (set (make-local-variable 'indent-region-function) #'coq-indent-region) ;; we can cope with nested comments (set (make-local-variable 'comment-quote-nested) nil) ;; FIXME: have abbreviation without holes ;(if coq-use-editing-holes (holes-mode 1)) (if (fboundp 'holes-mode) (holes-mode 1)) ;; Setup Proof-General interface to Coq. (if coq-use-pg (coq-pg-setup)) ;; font-lock (setq-local font-lock-defaults '(coq-font-lock-keywords-1)) ;; outline (setq-local outline-regexp coq-outline-regexp) (setq-local outline-heading-end-regexp coq-outline-heading-end-regexp) ;; tags (if (file-exists-p coq-tags) (set (make-local-variable 'tags-table-list) (cons coq-tags tags-table-list))) (set (make-local-variable 'blink-matching-paren-dont-ignore-comments) t) (when coq-may-use-prettify (set (make-local-variable 'prettify-symbols-alist) coq-prettify-symbols-alist))) (provide 'coq-mode) ;; Local Variables: *** ;; fill-column: 79 *** ;; indent-tabs-mode: nil *** ;; coding: utf-8 *** ;; End: *** ;;; coq-mode.el ends here PG-4.5/coq/coq-par-compile.el000066400000000000000000003247351426357011200160030ustar00rootroot00000000000000;;; coq-par-compile.el --- parallel compilation of required modules -*- lexical-binding: t; -*- ;; This file is part of Proof General. ;; Portions © Copyright 1994-2012 David Aspinall and University of Edinburgh ;; Portions © Copyright 2003-2021 Free Software Foundation, Inc. ;; Portions © Copyright 2001-2017 Pierre Courtieu ;; Portions © Copyright 2010, 2016 Erik Martin-Dorel ;; Portions © Copyright 2011-2013, 2016-2017, 2019-2021 Hendrik Tews ;; Portions © Copyright 2015-2017 Clément Pit-Claudel ;; Authors: Hendrik Tews ;; Maintainer: Hendrik Tews ;; SPDX-License-Identifier: GPL-3.0-or-later ;;; Commentary: ;; ;; This file implements compilation of required modules. The ;; compilation is done in parallel in the background (in contrast to ;; what you find in coq-seq-compile.el). ;; ;; ;;; TODO ;; ;; - fix -I current-dir argument for coqc invocations ;; - on error, try to put location info into the error message ;; - use file-attribute-modification-time and similar functions when ;; dropping support for emacs 25 (emacs 26.1 released on 05/2018) ;; - use define-error when dropping support for emacs 24 (25.1 ;; released on 09/2016) ;; ;; Note that all argument computations inherit `coq-autodetected-version': when ;; changing compilers, all compilation jobs must be terminated. This is ;; consistent with the fact that the _CoqProject file is not reparsed. ;;; Code: (defvar queueitems) ; dynamic scope in p-s-extend-queue-hook (eval-when-compile (require 'cl-lib)) (require 'coq-compile-common) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Multiple file handling -- parallel compilation of required modules ;; ;; This file implements parallel background compilation. It makes sure ;; that only a certain number (`coq-max-background-compilation-jobs') ;; of coqdep and coqc processes are running in the background. ;; ;; In this file, compilation jobs are uninterned lisp symbols that ;; store all important information in their property list. New ;; compilation jobs are created when Require commands are recognized and ;; when the output of coqdep is processed. If there is space, new jobs ;; are directly launched. Otherwise, they are put into a queue ;; (`coq--par-compilation-queue') to be launched when some other ;; process terminates. ;; ;; Dependencies between files are reflected with suitable links. They ;; are established when the coqdep output is processed. A job with ;; dependencies waits for the dependencies to finish before it ;; continues with coqc. ;; ;; There are two differend kinds of compilation jobs. First, ordinary ;; files, whose dependencies must be determined with coqdep and which ;; might need to be compiled after all their dependencies are ready. ;; These compilation jobs are called 'file jobs here. Apart from 'file ;; jobs there are the Require commands in the asserted region. For ;; each Require command one must determine the modules/files (its ;; dependencies) that must be compiled before the Require command can ;; be processed. Require commands are tracked with 'require jobs here. ;; Typically, a 'require job has a number of 'file jobs as ;; dependencies. coqdep must be run on both, 'require and 'file jobs ;; to determine their dependencies. For 'require jobs this is done in ;; a temporary file. coqc must only be run on 'file jobs. ;; ;; It is pretty clear how to process these compilation jobs. The ;; problems are: ;; ;; 1- where to put the Require command itself and the items that follow it ;; 2- make sure ancestors are properly locked ;; 3- error reporting ;; 4- using -quick and the handling of .vo/.vio prerequisites for Coq < 8.11 ;; 5- using -vos for Coq >= 8.11 ;; 6- running vio2vo or -vok to check proofs ;; 7- default-directory / current directory ;; ;; ;; For 1- where to put the Require command and the items that follow it: ;; ;; The Require command and the items that follow cannot stay in ;; proof-action-list, as otherwise they would be sent to the prover ;; long before the compilation finishes. I therefore cut ;; proof-action-list into pieces and leave only the items before the ;; first Require on proof-action-list. The others are put into the ;; 'queueitems property of the 'require command that is created for ;; the Require. When such a 'require job gets ready, it puts the items ;; back into proof-action-list and lets Proof General process them as ;; usual. ;; ;; All 'require commands are linked with so-called 'queue-dependant ;; links, such that later 'require jobs can be delayed until earlier ;; ones are ready. The later 'require job is said to be a queue ;; dependant of the earlier one. ;; ;; ;; For 2- make sure ancestors are properly locked: ;; ;; Consider "Require a. Require b." where a and b depend on c. Locking ;; must be done such that c is only unlocked, when "Require a" is ;; undone and not when "Require b" is undone alone. In case ;; compilation of c fails then c and all its ancestors must be ;; unlocked. During compilation, files are locked just before coqdep ;; is started on them (after they have been identified as a ;; dependency). At that time the 'lock-state property of the job is ;; set to 'locked. When a require job is retired, all ancestors with ;; 'lock-state property 'locked are collected by following the ;; downward links. When the require job was successful, the collected ;; jobs are stored in the 'coq-locked-ancestors property of the span ;; belonging to that require command (in the 'require-span property). ;; Furhter, the 'lock-state is set to 'asserted, such that another ;; collection from a following require job ignores these jobs. A span ;; delete action will unlock all uncestors in the ;; 'coq-locked-ancestors property. ;; ;; When the require job was unsuccessful, all collected jobs are ;; unlocked. ;; ;; ;; For 3- error reporting: ;; ;; Depending on `coq-compile-keep-going' compilation can continue ;; after an error or stop immediately. For stopping immediately, ;; processing is aborted with a signal that eventually leads to ;; `coq-par-emergency-cleanup', which kills all compilation jobs, ;; retracts the queue region and resets all internal data. ;; ;; For `coq-compile-keep-going', the failing job, all ordinary ;; dependants and all queue dependants are marked with 'failed. All ;; ancestors that have already been registered in such a failed job ;; are treated in the following way: If the ancestor is (via a ;; different dependency path) an ancestor of a job that is still being ;; compiled, then the ancestor is kept locked. Otherwise the ancestor ;; is unlocked. Failed jobs continue with their normal state ;; transition, but omit certain steps (eg., running coqc). If a coqc ;; compilation finishes and all dependants are marked as failed, the ;; ancestors are also treated in the way described before. If a failed ;; require job is retired, nothing is done (especially its span is not ;; asserted), unless it is the last compilation job. If the last ;; compilation job is marked as failed when it is retired, then the ;; whole queue region is retracted. ;; ;; When a failing require command follows a bunch of commands that ;; take a while to process, it may happen, that the last failing ;; require command is ready to be retired before the preceeding ;; commands have been processed. In this case the retirement (in ;; particular, unlocking the queue region) must be delayed until proof ;; action list is empty. This is done by adding an empty action into ;; `proof-action-list' that calls the retirement function ;; `coq-par-kickoff-queue-maybe' again. Further ;; `coq--par-delayed-last-job' must be set to disable the cycle ;; detection that is otherwise automatically started if no background ;; job is active and the last require job has not been retired yet. ;; ;; ;; For 4- using -quick and the handling of .vo/.vio prerequisites for Coq < 8.11 ;; ;; There are now two ways available to speed up compilation, ;; -quick/-vio and -vos. For Coq >= 8.5 and < 8.11 -quick/-vio is ;; available and coq-compile-quick is consulted in order to determine ;; whether to use it. For Coq >= 8.11 -vos is available and ;; coq-compile-vos is consulted. The following paragraph descripes the ;; complications with -quick/-vio. ;; Coq accepts both .vo and .vio files for importing modules ;; regardless of it is running with -quick or not. However, it is ;; unclear which file is loaded when both, .vo and .vio, of a ;; dependency are present. Therefore I delete a .vio file when I ;; decide to rebuild a .vo file and vica versa. coqdep delivers ;; dependencies for both, .vio and .vo files. These dependencies are ;; identical for .vio and vo (last checked for coq trunk in October ;; 2016). For deciding whether prerequisites must be recompiled the ;; full path returned form coqdep is relevant. Because it seems odd to ;; store a full path without a .vo or .vio suffix I decided to always ;; store the .vo object file name in the 'vo-file property of ;; compilation jobs. Only when all dependencies are ready, in ;; `coq-par-job-needs-compilation' I decide whether to build a .vio or ;; .vo file and if already present .vo or .vio files must be deleted. ;; Only at that point the relevant property 'required-obj-file is set. ;; ;; ;; For 5- using -vos for Coq >= 8.11 ;; ;; When Coq >= 8.11 is detected, -vos is used and coq-compile-vos is ;; consulted in order to find out whether to compile to .vos or to .vo ;; files. For people switching PG or switching to Coq 8.11, there is a ;; backward compatibility path: When coq-compile-vos is nil, the ;; decision is derived from coq-compile-quick. ;; ;; The logic here to decide whether compilation is needed or not, ;; assumes coq is used consistently without randomly deleting files. ;; Because coqc always produces an empty .vos file when compiling to ;; .vo, it can never happen, that a .vo file is present without .vos ;; file or that a .vo file is more recent then the corresponding .vos ;; file. This simplifies the logic for deciding about recompilation ;; quite a bit. ;; ;; ;; For 6- running vio2vo or -vok to check proofs ;; ;; To check proofs when compilation is done with -quick/-vio or -vok, ;; a second stage can be configured using 'quick-and-vio2vo and ;; 'vos-and-vok. If configured, coq-par-job-needs-compilation sets the ;; 'second-stage property if the job needs a second stage run to check ;; the proofs. Such jobs are stored in `coq--par-second-stage-queue' ;; until first stage compilation and library loading has been done and ;; `coq-compile-second-stage-delay' is over. To ensure the timer ;; starts after loading libraries, it is started in a callback from an ;; otherwise empty action list item when the first stage compilation ;; produced no error. When there was an error, the timer is started ;; directly when retiring the last require job. Jobs that participate ;; in the second stage are in state 'ready. They do not change their ;; state in the second stage. ;; ;; The user can relatively easily achieve that there is more than one ;; action item with a callback to start the delay timer present in ;; `proof-action-list'. To ensure only the last one starts the timer, ;; the callback remembers the value of ;; `coq--par-second-stage-start-id' and only acts if that is still the ;; current value when the callback is executed. ;; ;; ;; For 7- default-directory / current directory ;; ;; `default-directory' determines the current directory for background ;; processes. In a sentinel or process filter, default-directory is ;; taken from the current buffer, which is basically random. Starting ;; with a wrong current directory will cause compilation failures. ;; Therefore all entry points of this library must set ;; default-directory. Entry points are coq-par-process-sentinel, the ;; functions started from timer and those started from an empty entry ;; in `proof-action-list'. To set default-directory in these cases, I ;; record default-directory in 'current-dir inside ;; `coq-par-preprocess-require-commands' and then pass it on to all ;; jobs created. ;; ;; ;; Properties of compilation jobs ;; ;; 'name - some unique string, only used for debugging ;; 'queueitems - holds items from proof-action-list on ;; require jobs ;; 'vo-file - the .vo file for the module that this job has ;; to make up-to-date. This slot is filled when the ;; job is created and independent of whether a .vio ;; or .vo file must be made up-to-date. Only present ;; in file jobs. ;; 'required-obj-file - contains the .vio or .vo to be produced or nil ;; if that has not yet been decided. May contain ;; nil if no file needs to be rebuild at all. Nil ;; on require jobs. ;; 'obj-mod-time - modification time of 'required-obj-file, stored ;; here in case compilation is not needed for file ;; jobs, to avoid double stat calls; ;; 'use-quick - 'vio if `coq-par-job-needs-compilation' decided to use ;; -quick for Coq older than 8.11; 'vos if it decided to ;; to use -vos for Coq 8.11 or newer, nil if it decided ;; to use .vo compilation, no compilation is necessary or ;; for require jobs. ;; 'type - the type of the job, either 'require or 'file ;; 'state - the state of the job, see below ;; 'coqc-dependants - list of parent jobs that depend on this job, ;; when this job finishes it propagates the ;; necessary information to it's parent jobs and ;; decreases their 'coqc-dependency-count ;; 'coqc-dependees - list of child jobs this job depends on ;; reverse links of 'coqc-dependants, needed to ;; efficiently traverse the tree to collect ancestors ;; for locking and unlocking ;; 'coqc-dependency-count - number of unfinished child jobs ;; increased for every subjob spawned ;; during coqdep output processing ;; File job waits with coqc until this ;; count reaches 0 again. Require jobs wait with ;; their transition to 'ready. ;; 'youngest-coqc-dependency - slot to accumulate the most recent ;; modification time of some ancestor ;; value; might be an Emacs time or ;; 'just-compiled; not really needed in require ;; jobs but present there to simplify the code ;; 'queue-dependant - next top-level job, only present in require jobs ;; 'queue-dependant-waiting - t if this is a require job that has ;; to wait until previous require jobs ;; finish. In this waiting time, dependencies ;; are compiled, but queue items are only ;; put back into proof-action-list when ;; this property becomes nil ;; 'queue-dependee - previous top-level job, only present in require jobs ;; reverse link of 'queue-dependant, needed to unlock ;; ancestors in case of error ;; 'src-file - the .v file name, only in file jobs ;; 'load-path - value of coq-load-path, propagated to all ;; dependencies ;; 'lock-state - nil for require jobs, 'unlocked if the file ;; corresponding to job is not locked, 'locked if that ;; file has been locked, 'asserted if it has been ;; registered in some span in the 'coq-locked-ancestors ;; property already ;; 'require-span - holds the span with the require command for require jobs ;; 'second-stage - nil if no second stage is required, otherwise 'vio2vo ;; for <8.11 or 'vok for >=8.11; set in ;; coq-par-job-needs-compilation ;; build the .vo file. Otherwiese nil. ;; 'failed - t if coqdep or coqc for the job or one dependee failed. ;; 'visited - used in the dependency cycle detection to mark ;; visited jobs ;; 'current-dir - current directory or default-directory of the buffer ;; that contained the require command. Passed recursively ;; to all jobs. Used to set default-directory in the ;; sentinel and other functions, because it can otherwise ;; be more or less random. ;; 'temp-require-file - temporary file name just containing the require ;; command of a require job for determining the files ;; needed for that require. Must be deleted after ;; coqdep finished. ;; ;; ;; Properties of processes ;; ;; A lot of the necessary actions are started from inside a process ;; sentinel. The property list of processes stores the necessary ;; information for that in the following properties. ;; ;; 'coq-compilation-job - the compilation job that started ;; this process ;; 'coq-process-continuation - the continuation to be called when ;; the process finishes. Either ;; coq-par-process-coqdep-result or ;; coq-par-coqc-continuation or ;; coq-par-vio2vo-continuation ;; 'coq-process-output - the output of the process ;; 'coq-process-command - the command for error reporting ;; (as string list) ;; 'coq-par-process-killed - t if this process has been killed from PG ;; 'coq-process-rm - if not nil, a file to be deleted when ;; the process does not finish successfully, ;; i.e., when the continuation is not called. ;; ;; ;; State transition of file jobs ;; ;; 'enqueued-coqdep -> 'waiting-dep -> 'enqueued-coqc -> 'ready ;; ;; State transition for require jobs ;; ;; 'enqueued-coqdep -> 'waiting-dep -> 'waiting-queue -> 'ready ;; ;; State explanation ;; ;; 'enqueued-coqdep - coqdep is running or the job enqueued, waiting ;; for a slot to start coqdep ;; 'waiting-dep - coqdep finished, dependencies determined, waiting for ;; the dependencies ;; 'enqueued-coqc - dependencies ready, coqc is running, or the job is ;; enqueued, waiting for a slot to start coqc ;; 'waiting-queue - dependencies ready, waiting for queue dependee ;; to get ready ;; 'ready - ready, the result might be missing when 'failed ;; ;; ;; Over its live time, a compilation job might get passed through the ;; following functions. Some of them might be skipped or executed more ;; then once. ;; ;; | functions for file jobs | state | comment | ;; |----------------------------------+------------------+--------------------------------------| ;; | coq-par-create-file-job | 'enqueued-coqdep | job creation | ;; | coq-par-start-coqdep-on-file | | lock files | ;; | coq-par-process-coqdep-result | 'waiting-dep | create dependee/child jobs | ;; | coq-par-decrease-coqc-dependency | | dependee/child finished coqc | ;; | coq-par-compile-job-maybe | 'enqueued-coqc | | ;; | -- start coqc | | | ;; | coq-par-coqc-continuation | | | ;; | coq-par-kickoff-coqc-dependants | 'ready | | ;; | coq-par-start-vio2vo | | | ;; | coq-par-vio2vo-continuation | | | ;; ;; ;; | function for require jobs | state | comment | ;; |----------------------------------+------------------+--------------------------------------| ;; | coq-par-create-require-job | 'enqueued-coqdep | job creation | ;; | coq-par-start-coqdep-on-require | | lock files | ;; | coq-par-process-coqdep-result | 'waiting-dep | create dependee/child jobs | ;; | coq-par-decrease-coqc-dependency | | dependee/child finished coqc | ;; | coq-par-kickoff-queue-maybe | 'waiting-queue | | ;; | coq-par-retire-top-level-job | | | ;; | coq-par-kickoff-queue-maybe cont | 'ready | | ;; | coq-par-require-processed | | in dummy action in proof-action-list | ;; | coq-par-run-second-stage-queue | | called via timer | ;; ;; ;; The following _is_ outdated. ;; To print the states of the compilation jobs for debugging, eval ;; ;; (let ((clones)) ;; (maphash (lambda (k v) ;; (message "%s type %s for %s state %s dep of %s queue dep of %s" ;; (get v 'name) ;; (get v 'type) ;; (get v 'src-file) ;; (get v 'state) ;; (mapcar (lambda (p) (get p 'name)) ;; (get v 'coqc-dependants)) ;; (get v 'queue-dependant)) ;; (mapc (lambda (p) (when (eq (get p 'type) 'clone) ;; (push p clones))) ;; (get v 'coqc-dependants))) ;; coq--compilation-object-hash) ;; (mapc (lambda (v) ;; (message "%s type %s for %s state %s dep of %s queue dep of %s" ;; (get v 'name) ;; (get v 'type) ;; (get v 'src-file) ;; (get v 'state) ;; (mapcar (lambda (p) (get p 'name)) ;; (get v 'coqc-dependants)) ;; (get v 'queue-dependant))) ;; clones)) ;;; Variables (defvar coq--current-background-jobs 0 "Number of currently running background jobs.") (defvar coq--compilation-object-hash nil "Hash for storing the compilation jobs. This hash only stores file jobs and no require jobs. They are stored in order to avoid double compilation. The jobs stored in here are uninterned symbols that carry all important information in their property list. See the documentation in the source file \"coq-par-compile.el\". The hash always maps .vo file names to compilation jobs, regardless of ``-quick''.") (defvar coq--last-compilation-job nil "Pointer to the last require compilation job. Used to link top-level jobs with queue dependencies.") (defvar coq--par-second-stage-in-progress nil "t iff vio2vo or vok is running in background.") (defvar coq--par-second-stage-delay-timer nil "Holds the timer for the second stage delay.") (defvar coq--par-second-stage-start-id 0 "Integer counter to detect races for `coq-par-require-processed'. Assume the last top-level ``Require'' command is retired, but executing the ``Require'' takes so long that the user can assert a next ``Require'' and that the second require is retired before the first ``Require'' has been processed. In this case there are two `coq-par-require-processed' callbacks active, of which the first one must be ignored. For each new callback this counter is incremented and, when there is a difference, `coq-par-require-processed' does not start the second stage timer. In case the first callback gets executed before the second require is retired, the race is detected with `coq--last-compilation-job' without this counter.") (defvar coq--par-next-id 1 "Increased for every job and process, to get unique job names. The names are only used for debugging.") (defvar coq--par-delayed-last-job nil "Inform the cycle detection that there is a delayed top-level job. The retirement of failing require jobs must be delayed until `proof-action-list' is empty, to avoid retracting commands before the first failing require. This is done by adding the call to `coq-par-kickoff-queue-maybe' to the end of `proof-action-list'. This variable is t during this time to disable cycle detection, which is otherwise started when `coq--last-compilation-job' has not been retired but no compilation process is running in the background.") ;;; utility functions (defun split-list-at-predicate (l pred) "Split L into several lists at points where PRED is t. Splits L into several lists, such that - their concatenation equals the original L - every element for which PRED returns t starts a new list - except for the first list, PRED is t for every car of every result list - the first result list contains the first elements of L for which PRED is nil L is modified in place and the list structure in L is reused for the result." (let ((result (list l)) previous (current l)) (while current (when (funcall pred (car current)) (if previous (progn (setcdr previous nil) (push current result)) ;; handle case where pred is t for the car of the original l (setq result (list l nil)))) (setq previous current) (setq current (cdr current))) (nreverse result))) (defun coq-par-time-less (time-1 time-2) "Compare extended times. The arguments can be an emacs time (a list of 2 to 4 integers, see `current-time') or the symbol 'just-compiled, where the latter is greater then everything else." (cond ((eq time-2 'just-compiled) t) ((eq time-1 'just-compiled) nil) (t (time-less-p time-1 time-2)))) (defun coq-par-init-compilation-hash () "(Re-)Initialize `coq--compilation-object-hash'." (setq coq--compilation-object-hash (make-hash-table :test 'equal))) ;;; generic queues ;; Standard implementation with two lists. (defun coq-par-new-queue () "Create a new empty queue." (cons nil nil)) (defun coq-par-enqueue (queue x) "Insert X in queue QUEUE." (push x (car queue))) (defun coq-par-queue-reverse-if-needed (queue) "Reorganize QUEUE, such that the pop-end contains something. Of course only if necessary and possible." (unless (cdr queue) (setcdr queue (nreverse (car queue))) (setcar queue nil))) (defun coq-par-queue-head (queue) "Return the head of QUEUE, if any, without removing it." (coq-par-queue-reverse-if-needed queue) (cadr queue)) (defun coq-par-dequeue (queue) "Dequeue the next item from QUEUE." (coq-par-queue-reverse-if-needed queue) (pop (cdr queue))) (defun coq-par-queue-length (queue) "Length of QUEUE." (+ (length (car queue)) (length (cdr queue)))) ;;; job queue (defvar coq--par-compilation-queue (coq-par-new-queue) "Queue of compilation jobs that wait for a free core to get started. Use `coq-par-job-enqueue' and `coq-par-job-dequeue' to access the queue.") (defun coq-par-job-enqueue (job) "Insert JOB in the queue of waiting compilation jobs." (coq-par-enqueue coq--par-compilation-queue job) (when coq--debug-auto-compilation (message "%s: enqueue job in waiting queue" (get job 'name)))) (defun coq-par-job-dequeue () "Dequeue the next job from the compilation queue." (let ((res (coq-par-dequeue coq--par-compilation-queue))) (when coq--debug-auto-compilation (if res (message "%s: dequeue" (get res 'name)) (message "compilation queue empty"))) res)) ;;; queue for second stage (vio2vo or vok) (defvar coq--par-second-stage-queue (coq-par-new-queue) "Queue of jobs that need a vio2vo or vok process. Use `coq-par-second-stage-enqueue', `coq-par-second-stage-dequeue' and `coq-par-second-stage-queue-length' to access the queue.") (defun coq-par-second-stage-enqueue (job) "Insert JOB in the queue for second stage processing." (coq-par-enqueue coq--par-second-stage-queue job) (when coq--debug-auto-compilation (message "%s: enqueue job in second stage queue" (get job 'name)))) (defun coq-par-second-stage-head () "Return the head of the second stage queue, if any, without removing it." (coq-par-queue-head coq--par-second-stage-queue)) (defun coq-par-second-stage-dequeue () "Dequeue the next job from the second stage queue." (let ((res (coq-par-dequeue coq--par-second-stage-queue))) (when coq--debug-auto-compilation (if res (message "%s: second stage dequeue" (get res 'name)) (message "second stage queue empty"))) res)) (defun coq-par-second-stage-queue-length () "Return the length of the second stage queue." (coq-par-queue-length coq--par-second-stage-queue)) ;;; error symbols ;; coq-compile-error-coqdep ;; ;; This error is signaled with one data item -- the file name (put 'coq-compile-error-coqdep 'error-conditions '(error coq-compile-error coq-compile-error-coqdep)) (put 'coq-compile-error-coqdep 'error-message "Coq compilation error: coqdep fails in") ;; coq-compile-error-coqc ;; ;; This error is signaled with one data item -- the file name (put 'coq-compile-error-coqc 'error-conditions '(error coq-compile-error coq-compile-error-coqc)) (put 'coq-compile-error-coqc 'error-message "Coq compilation error: coqc fails in") ;; coq-compile-error-command-start ;; ;; This error is signaled with two data items -- ;; a list consisting of the command and the system error message, ;; the command itself is a string list of the command name and the options (put 'coq-compile-error-command-start 'error-conditions '(error coq-compile-error coq-compile-error-command-start)) (put 'coq-compile-error-command-start 'error-message "Coq compilation error:") ;; coq-compile-error-circular-dep ;; ;; This error is signaled with one data item -- an indication about ;; the circularity, which is the error message to be appended to the ;; contents of 'error-message. (put 'coq-compile-error-circular-dep 'error-conditions '(error coq-compile-error coq-compile-error-circular-dep)) (put 'coq-compile-error-circular-dep 'error-message "Coq compilation error: Circular dependency") ;; coq-compile-error-rm ;; ;; Signaled when we have to delete a .vio or .vo file for consistency and ;; that deletion fails. ;; ;; This error is signaled with one data item -- the file-error error ;; description. Its car is the error symbol `file-error' and the cdr are ;; the data items for this error. They seem to be a list of strings with ;; different parts of the error message. (put 'coq-compile-error-rm 'error-conditions '(error coq-compile-error coq-compile-error-rm)) (put 'coq-compile-error-rm 'error-message "Cannot remove outdated file.") ;;; find circular dependencies in non-ready compilation jobs (defun coq-par-find-dependency-circle-for-job (job path) "Find a dependency cycle in the dependency subtree of JOB. Do a depth-first-search to find the cycle. JOB is the current node and PATH the stack of visited nodes. Jobs in state 'enqueue-coqc can be ignored, because they can never participate in a cycle." ;; CORRECTNESS ARGUMENT FOR THIS FUNCTION ;; ;; An outside-cycle job is a job for which the whole upward segment ;; of the dependency graph does not contain any cycle (and therefore ;; neither job itself belongs to any cycle nor is there a path ;; starting in job and leading to a cycle). Any job is either ;; outside-cycle or there exists an upward path containing the job ;; and a cycle above it. ;; The visited-condition is that all jobs marked visited are ;; outside-cycle jobs. ;; ;; The precondition of this function is that ;; - PATH does not contain any job twice, ;; - PATH is an reversed upward path where JOB is a dependant of the ;; head of PATH, and ;; - the visited-condition holds. ;; ;; This function returns nil and the visited condition holds at ;; return, if the precondition holds and JOB is outside-cycle. ;; Proved by induction on the length of the maximal upward path. ;; ;; This function returns a cycle (and not nil) if the precondition ;; holds and JOB is not outside-cycle. Proved by induction on the ;; distance to the first repeated job on the right-most upward path ;; containing a cycle. Here, right is the direction of the head of ;; the 'coqc-dependants list. (let (cycle (p path)) ;; path is reversed. A potential cycle goes from the beginning of ;; path to the first occurence of job. (while p (when (eq (car p) job) (setcdr p nil) (setq cycle path)) (setq p (cdr p))) (if cycle cycle (setq path (cons job path)) (setq p (get job 'coqc-dependants)) (while (and p (not cycle)) ;; XXX when clause does not make sense: job is a dependee or ;; dependency of (car p), therefore (car p) can only be in ;; state 'waiting-dep ;; XXX only recurse for dependants not visited yet (when (eq (get (car p) 'state) 'waiting-dep) ;; XXX should not be called on visited ancestors? (setq cycle (coq-par-find-dependency-circle-for-job (car p) path))) (setq p (cdr p))) (put job 'visited t) cycle))) (defun coq-par-find-dependency-circle () "Find a dependency cycle in compilation jobs of state 'waiting-dep. If no circle is found return nil, otherwise the list of files belonging to the circle. Jobs in state 'enqueue-coqc can be ignored, because they can never participate in a cycle." (let (cycle) (maphash (lambda (_key job) (put job 'visited nil)) coq--compilation-object-hash) (maphash (lambda (_key job) (when (and (not cycle) (not (get job 'visited)) (eq (get job 'state) 'waiting-dep)) (setq cycle (coq-par-find-dependency-circle-for-job job nil)))) coq--compilation-object-hash) (mapcar (lambda (j) (get j 'src-file)) cycle))) ;;; map coq module names to files, using synchronously running coqdep (defun coq-par-coqdep-arguments (lib-src-file clpath) "Compute the command line arguments for invoking coqdep on LIB-SRC-FILE. Argument CLPATH must be `coq-load-path' from the buffer that triggered the compilation, in order to provide correct load-path options to coqdep." (nconc (coq-coqdep-prog-args clpath (file-name-directory lib-src-file) (coq--pre-v85)) (list lib-src-file))) (defun coq-par-coqc-arguments (lib-src-file clpath) "Compute the command line arguments for invoking coqc on LIB-SRC-FILE. Argument CLPATH must be `coq-load-path' from the buffer that triggered the compilation, in order to provide correct load-path options to coqdep." (nconc (coq-coqc-prog-args clpath (file-name-directory lib-src-file) (coq--pre-v85)) (list lib-src-file))) (defun coq-par-analyse-coq-dep-exit (status output command) "Analyse output OUTPUT of coqdep command COMMAND with exit status STATUS. Returns the list of .vo dependencies if there is no error. Otherwise, writes an error message into `coq-compile-response-buffer', makes this buffer visible and returns a string. This function does always return .vo dependencies, regardless of the value of `coq-compile-quick'. If necessary, the conversion into .vio or .vos files must be done elsewhere." ;; (when coq--debug-auto-compilation ;; (message "analyse coqdep output \"%s\"" output)) (if (or (not (eq status 0)) ;; when a file on the command line is missing, coqdep drops it, ;; possibly outputting nothing (equal output "") ;; when a dependency is missing coqdep outputs a warning with status 0 (string-match coq-coqdep-error-regexp output)) (progn ;; display the error (coq-compile-display-error (mapconcat #'identity command " ") (if (equal output "") "No coqdep output - file probably inaccessible" output) t) ;; give back a string to signal error - the string content ;; will only become visible during debugging (cond ((not (eq status 0)) (format "coqdep exit status %d" status)) ((equal output "") "no coqdep output") (t "unsatisfied dependencies"))) ;; In 8.5, coqdep produces two lines. Match with .* here to ;; extract only a part of the first line. ;; We could match against (concat "^[^:]*" obj-file "[^:]*: \\(.*\\)") ;; to select the right line for either .vo or .vio dependencies. ;; However, we want to accept a .vo prerequisite for a .vio target ;; if it is recent enough. Therefore we actually need module dependencies ;; instead of file dependencies and we derive them from the .vo line. (when (string-match "\\`[^:]*: \\(.*\\)" output) (cl-remove-if-not (lambda (f) (string-match-p "\\.vo\\'" f)) (split-string (match-string 1 output)))))) ;;; manage background jobs (defun coq-par-kill-all-processes () "Kill all background coqc, coqdep, vio2vo or vok compilation processes. Return t if some process was killed." ;; need to first mark processes as killed, because delete process ;; starts running sentinels in the order processes terminated, so ;; after the first delete-process we see sentinels of non-killed ;; processes running (let ((kill-needed)) (mapc (lambda (process) (when (process-get process 'coq-compilation-job) (process-put process 'coq-par-process-killed t) (setq kill-needed t))) (process-list)) (when kill-needed (message "Kill all Coq background compilation processes")) (mapc (lambda (process) (when (process-get process 'coq-compilation-job) (process-put process 'coq-par-process-killed t) (delete-process process) (when coq--debug-auto-compilation (message "%s %s: kill it" (get (process-get process 'coq-compilation-job) 'name) (process-name process))))) (process-list)) (setq coq--current-background-jobs 0) kill-needed)) (defun coq-par-unlock-all-ancestors-on-error () "Unlock ancestors which are not in an asserted span. Used for unlocking ancestors on compilation errors." (when coq--compilation-object-hash (maphash (lambda (_key job) (when (eq (get job 'lock-state) 'locked) (coq-unlock-ancestor (get job 'src-file)) (put job 'lock-state 'unlocked))) coq--compilation-object-hash))) (defun coq-par-kill-and-cleanup () "Kill all background compilation, cleanup internal state and unlock ancestors. This is the common core of `coq-par-emergency-cleanup' and `coq-par-user-interrupt'. Returns t if there actually was a background job that was killed." (let (proc-killed) (when coq--debug-auto-compilation (message "kill all jobs and cleanup state")) (setq proc-killed (coq-par-kill-all-processes)) (setq coq--par-compilation-queue (coq-par-new-queue)) (setq coq--last-compilation-job nil) (setq coq--par-second-stage-queue (coq-par-new-queue)) (setq coq--par-second-stage-in-progress nil) (when coq--par-second-stage-delay-timer (cancel-timer coq--par-second-stage-delay-timer) (setq coq--par-second-stage-delay-timer nil)) (coq-par-unlock-all-ancestors-on-error) (setq proof-second-action-list-active nil) (coq-par-init-compilation-hash) proc-killed)) (defun coq-par-emergency-cleanup () "Emergency cleanup for errors in parallel background compilation. This is the function that cleans everything up when some background compilation process detected a severe error. When `coq-compile-keep-going' is nil, all errors are severe. When `coq-compile-keep-going' is t, coqc and coqdep errors are not severe. This function is also used for the user action to kill all background compilation. On top of `coq-par-kill-and-cleanup', this function resets the queue region (and thus `proof-action-list' and signals an interrupt to the proof shell." (interactive) ; needed for menu (when coq--debug-auto-compilation (message "emergency cleanup")) (coq-par-kill-and-cleanup) (when proof-action-list (setq proof-shell-interrupt-pending t)) (proof-release-lock) (proof-detach-queue)) (defun coq-par-user-interrupt () "React to a generic user interrupt with cleaning up everything. This function cleans up background compilation when the proof assistant died (`proof-shell-handle-error-or-interrupt-hook') or when the user interrupted Proof General (with \\[proof-interrupt-process] or `proof-interrupt-process' leading to `proof-shell-signal-interrupt-hook'). On top of `coq-par-kill-and-cleanup', this function only sets the dynamic variable `prover-was-busy' to tell the proof shell that the user actually had a reason to interrupt. However, in the special case where `proof-action-list' is nil and `coq--last-compilation-job' not, this function also clears the queue region and releases the proof shell lock. This has the nice side effect, that `proof-interrupt-process' does not send an interrupt signal to the prover." (let (proc-killed (was-busy (or coq--last-compilation-job coq--par-second-stage-in-progress coq--par-second-stage-delay-timer))) (when coq--debug-auto-compilation (message "cleanup on user interrupt")) (setq proc-killed (coq-par-kill-and-cleanup)) (unless proof-action-list (when coq--debug-auto-compilation (message "clear queue region and proof shell lock")) (proof-release-lock) (proof-detach-queue)) (when (and (boundp 'prover-was-busy) (or proc-killed was-busy)) (setq prover-was-busy t)))) (defun coq-par-process-filter (process output) "Store OUTPUT from coq background compilation." (process-put process 'coq-process-output (concat (process-get process 'coq-process-output) output))) (defun coq-par-start-process (command arguments continuation job file-rm) "Start asynchronous compilation job for COMMAND. This function starts COMMAND with arguments ARGUMENTS for compilation job JOB, making sure that CONTINUATION runs when the process finishes successfully. FILE-RM, if non-nil, denotes a file to be deleted when the process does not finish successfully." ;;(message "CPSP %s %s %s %s %s" command arguments continuation job file-rm) (let ((process-connection-type nil) ; use pipes (process-name (format "pro-%s" coq--par-next-id)) process) (setq coq--par-next-id (1+ coq--par-next-id)) (when coq--debug-auto-compilation (message "%s %s: start %s %s in %s" (get job 'name) process-name command (mapconcat #'identity arguments " ") default-directory)) (condition-case err ;; If the command is wrong, start-process aborts with an ;; error. However, in Emacs 23.4.1. it will leave a process ;; behind, which is in a very strange state: running with no ;; pid. Emacs 24.2 fixes this. (setq process (apply #'start-process process-name nil ; no process buffer command arguments)) (error (when coq--debug-auto-compilation (message "%s %s: error in start process, %s" (get job 'name) process-name (if file-rm (format "rm %s" file-rm) "no file removal"))) (when file-rm (ignore-errors (delete-file file-rm))) (signal 'coq-compile-error-command-start (list (cons command arguments) (nth 2 err))))) (set-process-filter process #'coq-par-process-filter) (set-process-sentinel process #'coq-par-process-sentinel) (set-process-query-on-exit-flag process nil) (setq coq--current-background-jobs (1+ coq--current-background-jobs)) (process-put process 'coq-compilation-job job) (process-put process 'coq-process-continuation continuation) (process-put process 'coq-process-command (cons command arguments)) (process-put process 'coq-process-output "") (process-put process 'coq-process-rm file-rm))) (defun coq-par-process-sentinel (process event) "Sentinel for all kinds of Coq background compilation processes. Runs when process PROCESS terminated because of EVENT. It determines the exit status and calls the continuation function that has been registered with that process. Normal compilation errors are reported with an error message inside the callback. Starts as many queued jobs as possible. Second stage compilation jobs that have been killed, possibly because the user triggered a next first stage compilation, are put back into `coq--par-second-stage-queue'. If, at the end, no job is running in the background but compilation has not been finished, then, either second stage compilation finished (which is reported), or there must be a cycle in the dependencies, which is found and reported here. The cycle detection is skipped, if the retirement of the last compilation job has been delayed per `coq--par-delayed-last-job'. All signals are caught inside this function and reported appropriately." (condition-case err (if (process-get process 'coq-par-process-killed) (progn (when coq--debug-auto-compilation (message "%s %s: skip sentinel, process killed, %s" (get (process-get process 'coq-compilation-job) 'name) (process-name process) (if (process-get process 'coq-process-rm) (format "rm %s" (process-get process 'coq-process-rm)) "no file removal"))) (when (process-get process 'coq-process-rm) (ignore-errors (delete-file (process-get process 'coq-process-rm)))) (when (or (eq (process-get process 'coq-process-continuation) 'coq-par-vok-continuation) (eq (process-get process 'coq-process-continuation) 'coq-par-vio2vo-continuation)) (when coq--debug-auto-compilation (message "%s: reenqueue for second stage" (get (process-get process 'coq-compilation-job) 'name))) (coq-par-second-stage-enqueue (process-get process 'coq-compilation-job)))) ;; process was not killed explicitly by us (let (exit-status (default-directory (get (process-get process 'coq-compilation-job) 'current-dir))) (when coq--debug-auto-compilation (message (concat "%s %s: TTT process status changed to %s " "command: %s\n default-dir: %s curr buf %s") (get (process-get process 'coq-compilation-job) 'name) (process-name process) event (mapconcat 'identity (process-get process 'coq-process-command) " ") default-directory (buffer-name))) (cond ((eq (process-status process) 'exit) (setq exit-status (process-exit-status process))) (t (setq exit-status "abnormal termination"))) (setq coq--current-background-jobs (max 0 (1- coq--current-background-jobs))) (funcall (process-get process 'coq-process-continuation) process exit-status) (coq-par-start-jobs-until-full) (when (and coq--par-second-stage-in-progress (eq coq--current-background-jobs 0)) (setq coq--par-second-stage-in-progress nil) (if (coq--post-v811) (message "vok compilation finished") (message "vio2vo compilation finished"))) (when (and (not coq--par-delayed-last-job) (eq coq--current-background-jobs 0) coq--last-compilation-job) (let ((cycle (coq-par-find-dependency-circle))) (if cycle (signal 'coq-compile-error-circular-dep (mapconcat #'identity cycle " -> ")) (error "Deadlock in parallel compilation")))))) ;; coq-compile-error-start can be signaled inside the continuation ;; function, if that tries to start new jobs ;; XXX catch this error also in coq-par-preprocess-require-commands (coq-compile-error-command-start (coq-par-emergency-cleanup) (message "%s \"%s\" in \"%s\"" (get (car err) 'error-message) (nth 2 err) (mapconcat 'identity (cadr err) " "))) (coq-compile-error (coq-par-emergency-cleanup) (message "%s %s" (get (car err) 'error-message) (cdr err))) (error (message "Error in sentinel of process %s, error %s" (process-name process) err) (coq-par-emergency-cleanup) (signal (car err) (cdr err))))) ;;; second stage compilation (vio2vo and vok) (defun coq-par-run-second-stage-queue () "Start delayed second stage compilation (vio2vo or vok). Set `default-directory' from the 'current-dir property of the head of the second stage queue, such that processes started here run with the right current directory." ;; when the user starts another compilation, the timer for second ;; stage is canceled (cl-assert (not coq--last-compilation-job) nil "normal compilation and second stage in parallel 1") (setq coq--par-second-stage-delay-timer nil) (when coq--debug-auto-compilation (message "Start second stage processing for %d jobs" (coq-par-second-stage-queue-length))) (let ((head (coq-par-second-stage-head)) default-directory) (when head (setq default-directory (get head 'current-dir)) (setq coq--par-second-stage-in-progress t) (coq-par-start-jobs-until-full)))) (defun coq-par-require-processed (race-counter) "Callback for `proof-action-list' to signal completion of the last Require. This function ensures that second stage compilation starts after `coq-compile-second-stage-delay' seconds after the last module has been loaded into Coq. When background compilation is successful, this callback is inserted with a dummy item into proof-action-list somewhere after the last require command. RACE-COUNTER is used to detect more than one active callback, see `coq--par-second-stage-start-id'" ;; When the user asserts new stuff while the (previously) last ;; require command is being processed, `coq--last-compilation-job' ;; might get non-nil. In this case there is a new last compilation ;; job that will eventually trigger the second stage. (unless (or coq--last-compilation-job (not (eq race-counter coq--par-second-stage-start-id))) (setq coq--par-second-stage-delay-timer (run-at-time coq-compile-second-stage-delay nil #'coq-par-run-second-stage-queue)))) (defun coq-par-callback-queue-item (callback) "Create queue item containing just CALLBACK. Create a queue item for `proof-action-list' containing just CALLBACK. CALLBACK must be a function taking a span as argument. The command list in the produced queue item is nil, therefore the item will be processed as comment and only the callback will be called." ;; A proof-action-list item has the form of ;; (SPAN COMMANDS ACTION [DISPLAYFLAGS]) ;; If COMMANDS is nil, the item is processed as comment and not sent ;; to the proof assistant, only the callback is called, see ;; proof-shell.el. (list nil nil callback)) ;;; background job tasks (defun coq-par-dependencies-ready (job) "Return t if all dependencies of compilation job JOB are ready." (eq (get job 'coqc-dependency-count) 0)) (defun coq-par-add-coqc-dependency (dependee dependant count) "Add normal Coq dependency from child job DEPENDEE to parent job DEPENDANT. If argument COUNT is non-nil, the dependency counter in DEPENDANT is increased, such that DEPENDANT waits for the completion of DEPENDEE." (when count (put dependant 'coqc-dependency-count (1+ (get dependant 'coqc-dependency-count)))) (push dependant (get dependee 'coqc-dependants)) (push dependee (get dependant 'coqc-dependees)) (when coq--debug-auto-compilation (message "%s -> %s: add %s coqc dependency" (get dependee 'name) (get dependant 'name) (if count "counted" "uncounted")))) ;; XXX need to propagate 'failed from dependee to dependant ;; Relevant, if user asserts second region when for the first one ;; compilation has failed already, but the queue region is still ;; processing. What happens with coq--par-delayed-last-job and the ;; delayed coq-par-kickoff-queue-maybe call? (defun coq-par-add-queue-dependency (dependee dependant) "Add queue dependency from require job DEPENDEE to require job DEPENDANT. The require item of DEPENDANT comes after those of DEPENDEE. Therefore DEPENDANT must wait for DEPENDEE to finish. " (cl-assert (and (not (get dependant 'queue-dependant-waiting)) (not (get dependee 'queue-dependant))) nil "queue dependency cannot be added") (put dependant 'queue-dependant-waiting t) (put dependee 'queue-dependant dependant) (put dependant 'queue-dependee dependee) (when coq--debug-auto-compilation (message "%s -> %s: add queue dependency" (get dependee 'name) (get dependant 'name)))) (defun coq-par-job-needs-compilation-quick (job) "Determine whether JOB needs to get compiled and do some side effects. This function contains most of the logic nesseary to support quick compilation according to `coq-compile-quick' for coq < 8.11. Taking `coq-compile-quick' into account, it determines if a compilation is necessary. The property 'required-obj-file is set either to the file that we need to produce or to the up-to-date object file. If compilation is needed, property 'use-quick is set to `vio' when -quick/-vio will be used. If no compilation is needed, property 'obj-mod-time remembers the time stamp of 'required-obj-file. Indepent of whether compilation is required, .vo or .vio files that are in the way are deleted. Note that the coq documentation does not contain a statement, about what file is loaded, if both a .vo and a .vio file are present. To be on the safe side, I therefore delete a file if it might be in the way. Sets the 'second-stage property on job if necessary." (let* ((vo-file (get job 'vo-file)) (vio-file (coq-library-vio-of-vo-file vo-file)) (vo-obj-time (nth 5 (file-attributes vo-file))) (vio-obj-time (nth 5 (file-attributes vio-file))) (dep-time (get job 'youngest-coqc-dependency)) (src-time (nth 5 (file-attributes (get job 'src-file)))) file-to-delete max-obj-time vio-is-newer other-file other-obj-time result) (when coq--debug-auto-compilation (message (concat "%s: compare mod times: vo mod %s, vio mod %s, src mod %s, " "youngest dep %s; vo < src : %s, vio < src : %s, " "vo < dep : %s, vio < dep : %s") (get job 'name) (if vo-obj-time (current-time-string vo-obj-time) "-") (if vio-obj-time (current-time-string vio-obj-time) "-") (if src-time (current-time-string src-time) "-") (if (eq dep-time 'just-compiled) "just compiled" (current-time-string dep-time)) (if vo-obj-time (time-less-p vo-obj-time src-time) "-") (if vio-obj-time (time-less-p vio-obj-time src-time) "-") (if vo-obj-time (coq-par-time-less vo-obj-time dep-time) "-") (if vio-obj-time (coq-par-time-less vio-obj-time dep-time) "-"))) ;; the source file must exist (cl-assert src-time nil "internal error - cannot find src file I") ;; Compute first the max of vo-obj-time and vio-obj-time and remember ;; which of both is newer. This is only meaningful if at least one of ;; the .vo or .vio file exists. (cond ((and vio-obj-time vo-obj-time (time-less-or-equal vo-obj-time vio-obj-time)) (setq max-obj-time vio-obj-time) (setq vio-is-newer t)) ((and vio-obj-time vo-obj-time) (setq max-obj-time vo-obj-time)) (vio-obj-time (setq max-obj-time vio-obj-time) (setq vio-is-newer t)) (t (setq max-obj-time vo-obj-time))) ;; Decide if and what to compile. (if (or (eq dep-time 'just-compiled) ; a dep has been just compiled (and (not vo-obj-time) (not vio-obj-time)) ; no obj exists ;; src younger than any obj? (time-less-or-equal max-obj-time src-time) ;; dep younger than any obj? (time-less-or-equal max-obj-time dep-time)) ;; compilation is definitely needed (progn (setq result t) (if (coq-compile-prefer-quick) (progn (put job 'required-obj-file vio-file) (put job 'use-quick 'vio) (when vo-obj-time (setq file-to-delete vo-file)) (when (eq coq-compile-quick 'quick-and-vio2vo) (put job 'second-stage 'vio2vo))) (put job 'required-obj-file vo-file) (when vio-obj-time (setq file-to-delete vio-file))) (when coq--debug-auto-compilation (message (concat "%s: definitely need to compile to %s; delete %s") (get job 'name) (get job 'required-obj-file) (if file-to-delete file-to-delete "noting")))) ;; Either the .vio or the .vo file exists and one of .vio or .vo is ;; younger than the source and the youngest dependency. Might not ;; need to compile. (if (eq coq-compile-quick 'ensure-vo) (progn (put job 'required-obj-file vo-file) (if (or (not vio-is-newer) ; vo is newest (and vo-obj-time ; vo is older than vio ; but still newer than src or dep (time-less-p src-time vo-obj-time) (time-less-p dep-time vo-obj-time))) ;; .vo is newer than src and youngest dep - don't compile (progn (put job 'obj-mod-time vo-obj-time) ;; delete vio if it is outdated or newer than vo (when (and vio-obj-time (or vio-is-newer (time-less-or-equal vio-obj-time src-time) (time-less-or-equal vio-obj-time dep-time))) (setq file-to-delete vio-file)) (when coq--debug-auto-compilation (message "%s: vo up-to-date 1; delete %s" (get job 'name) (if file-to-delete file-to-delete "noting")))) ;; .vo outdated - need to compile (setq result t) ;; delete vio if it is outdated (when (and vio-obj-time (or (time-less-or-equal vio-obj-time src-time) (time-less-or-equal vio-obj-time dep-time))) (setq file-to-delete vio-file)) (when coq--debug-auto-compilation (message "%s: need to compile to vo; delete %s" (get job 'name) (if file-to-delete file-to-delete "noting"))))) ;; There is an up-to-date .vio or .vo file and the user does not ;; insist on either .vio or .vo - no need to compile. ;; Ensure to delete outdated .vio or .vo files. ;; First store the other obj file in other-file and other-obj-time. (if vio-is-newer (setq other-file vo-file other-obj-time vo-obj-time) (setq other-file vio-file other-obj-time vio-obj-time)) (if (and other-obj-time (time-less-p src-time other-obj-time) ;; dep-time is neither nil nor 'just-compiled here (time-less-p dep-time other-obj-time)) ;; Both the .vio and .vo exist and are up-to-date. Coq ;; loads the younger one but we continue with the older ;; one to avoid recompilation for the case where a vio2vo ;; process took a long time for a dependency. (progn (put job 'required-obj-file other-file) (put job 'obj-mod-time other-obj-time) (when coq--debug-auto-compilation (message (concat "%s: .vio and .vo up-to-date, " "continue with the older %s") (get job 'name) (if vio-is-newer ".vio" ".vo")))) ;; The other obj file does not exist or is outdated. ;; Delete the outdated if it exists. (when other-obj-time (setq file-to-delete other-file)) (if vio-is-newer (progn (put job 'required-obj-file vio-file) (put job 'obj-mod-time vio-obj-time) (when (eq coq-compile-quick 'quick-and-vio2vo) (put job 'second-stage 'vio2vo)) (when coq--debug-auto-compilation (message "%s: vio up-to-date; delete %s" (get job 'name) (if file-to-delete file-to-delete "noting")))) (put job 'required-obj-file vo-file) (put job 'obj-mod-time vo-obj-time) (when coq--debug-auto-compilation (message "%s: vo up-to-date 2; delete %s" (get job 'name) (if file-to-delete file-to-delete "noting"))))))) (when file-to-delete (condition-case err (delete-file file-to-delete) (file-error (signal 'coq-compile-error-rm err)))) result)) (defun coq-par-job-needs-compilation-vos (job) "Determine whether JOB needs to get compiled. This function decides whether JOB needs to get compiled for coq >= 8.11 and whether a .vo or a .vos should be produced. For the latter, `coq-compile-vos' is consulted and, if that is `nil', coq-compile-quick, see `coq-compile-prefer-vos'. This function assumes that coq is used consistently and that a .vo file cannot be present without a .vos file that has the same time stamp or has been created more recently. As result, this function sets the property 'use-quick to `vos' if JOB should be compiled with -vos. If compilation is needed, 'required-obj-file is set. If no compilation is needed, 'obj-mod-time is set to the time stamp of the .vos or .vo file, depending on `coq-compile-prefer-vos'. Sets the 'second-stage property on job to 'vok if necessary." (let* ((vo-file (get job 'vo-file)) (vos-file (coq-library-vos-of-vo-file vo-file)) (dep-time (get job 'youngest-coqc-dependency)) (src-time (nth 5 (file-attributes (get job 'src-file)))) (vos-obj-time (nth 5 (file-attributes vos-file))) result) (when coq--debug-auto-compilation (message (concat "%s: compare mod times: vos mod %s, src mod %s, youngest dep %s\n" "\tsrc file %s in %s") (get job 'name) (if vos-obj-time (current-time-string vos-obj-time) "-") (if src-time (current-time-string src-time) "-") (if (eq dep-time 'just-compiled) "just compiled" (current-time-string dep-time)) (get job 'src-file) default-directory)) ;; the source file must exist (cl-assert src-time nil "internal error - cannot find src file II") (if (or (eq dep-time 'just-compiled) ; a dep has been just compiled (not vos-obj-time) ; neither vos nor vo present ;; src younger than vos? (time-less-or-equal vos-obj-time src-time) ;; dep younger than vos? (time-less-or-equal vos-obj-time dep-time)) ;; compilation needed (if (coq-compile-prefer-vos) (progn (put job 'required-obj-file vos-file) (put job 'use-quick 'vos) (when (eq coq-compile-vos 'vos-and-vok) (put job 'second-stage 'vok)) (setq result t)) (put job 'required-obj-file vo-file) (setq result t)) ;; maybe need to compile if vo is required (if (coq-compile-prefer-vos) ;; vo not required and vos is fine - no compilation, but maybe vok (let* ((vok-file (coq-library-vok-of-vo-file vo-file)) (vok-time (nth 5 (file-attributes vok-file)))) (put job 'obj-mod-time vos-obj-time) (when (and (eq coq-compile-vos 'vos-and-vok) (or (not vok-time) ; no vok exists ;; vos/vo is younger than src and dep, see above ;; if vo present, vok and vo have often the same time ;; vos/vo younger than vok? (time-less-p vok-time vos-obj-time))) (put job 'second-stage 'vok))) ;; vo required, may need to compile (let ((vo-obj-time (nth 5 (file-attributes vo-file)))) (when coq--debug-auto-compilation (message "%s: ensure-vo: vo mod %s" (get job 'name) (if vo-obj-time (current-time-string vo-obj-time) "-"))) (if (or (not vo-obj-time) ; vo not present ;; src younger than vo? (time-less-or-equal vo-obj-time src-time) ;; dep younger than vo? (time-less-or-equal vo-obj-time dep-time)) ;; compilation needed (progn (put job 'required-obj-file vo-file) (setq result t)) ;; vo is fine - no compilation (put job 'obj-mod-time vo-obj-time))))) result)) (defun coq-par-job-needs-compilation (job) "Determine if JOB nees to get compiled and possibly do some side effects. This function calls `coq-par-job-needs-compilation-vos for coq >= 8.11 and `coq-par-job-needs-compilation-quick' otherwise. Returns t if a compilation is required and sets the 'use-quick property depending on wheter -quick/-vio or -vos should be used. If compilation is needed, 'required-obj-file is set. Property 'obj-mod-time is set when no compilation is needed." (if (coq--post-v811) (coq-par-job-needs-compilation-vos job) (coq-par-job-needs-compilation-quick job))) (defun coq-par-collect-locked-ancestors-dependees (job) "Collect locked, not-yet-found ancestors from ancestors of JOB. Apply `coq-par-collect-locked-file-ancestors' recursively to all dependees to return those ancestors that are not yet asserted and have not been returned yet by a previous invocation of this function on a different job. This function sets the 'collect-visited property on all returned jobs, which should be cleared before the next collection run." ;; (message "CLAD: job %s: dependees %s" ;; (get job 'name) ;; (mapconcat ;; (lambda (job) (get job 'name)) ;; (get job 'coqc-dependees) " ")) (apply #'nconc (mapcar #'coq-par-collect-locked-file-ancestors (get job 'coqc-dependees)))) (defun coq-par-collect-locked-file-ancestors (job) "Collect locked, not-yet-found ancestors of JOB. Return JOB if JOB is not asserted yet and has not been visited before by this function. Do the same recursively on all ancestors to return all not-yet-asserted ancestors of JOB. This function sets the 'collect-visited property on all returned jobs, which should be cleared before the next collection run." ;; (message "CLFA job %s cv %s ls %s" ;; (get job 'name) (get job 'collect-visited) (get job 'lock-state)) (when (and (not (get job 'collect-visited)) (eq (get job 'lock-state) 'locked)) (put job 'collect-visited t) (cons job (coq-par-collect-locked-ancestors-dependees job)))) (defun coq-par-collect-locked-require-ancestors-rec (job) "Collect locked, not yet found ancestorors for require job JOB. Return all not yet asserted ancestors for successful jobs JOB as well as for failed jobs JOB. For successful jobs, the not yet asserted ancestors of preceeding require jobs have been collected in a previous collection run. For failed jobs, this is not the case, therefore, for failed jobs, this function recureses into the preceeding require job, if it exists." (let ((this-anc (coq-par-collect-locked-ancestors-dependees job)) (q-dep (get job 'queue-dependee)) prev-anc) (when (and q-dep (get q-dep 'failed)) (setq prev-anc (coq-par-collect-locked-require-ancestors-rec q-dep))) (nconc this-anc prev-anc))) (defun coq-par-collect-locked-require-ancestors (job) "Top-level ancestor collection function - collects not asserted ancestors. Return all not yet asserted ancestors for successful jobs JOB as well as for failed jobs JOB. For failed require jobs JOB, this entails visiting the preceeding require job. The recursion internally uses property 'collect-visited to mark already visited jobs in order to avoid an exponential blowup in graphs that are not trees. This property is reset here after collection, such that its use stays internal." (let ((ancs (coq-par-collect-locked-require-ancestors-rec job))) (mapc (lambda (job) (put job 'collect-visited nil)) ancs) (when coq--debug-auto-compilation (message "%s: locked ancestors: %s" (get job 'name) (mapconcat (lambda (job) (get job 'name)) ancs " "))) ancs)) (defun coq-par-retire-top-level-job (job) "Register ancestors and start queue items. JOB must be a successful require job. This function performs the essential tasks for successful require jobs when they transition from 'waiting-queue to 'ready: - Registering ancestors in the span and recording this fact in the 'lock-state property. - Moving queue items back to `proof-action-list' and start their execution. - Insert `coq-par-require-processed' as callback if this is the last top-level job, such that second stage compilation will start eventually." (cl-assert (and (not (get job 'failed)) (eq (get job 'type) 'require)) nil "coq-par-retire-top-level-job precondition failed") (let ((span (get job 'require-span)) (items (get job 'queueitems))) (when coq-lock-ancestors (mapc (lambda (anc-job) (cl-assert (eq (get anc-job 'lock-state) 'locked) nil "bad ancestor lock state") (put anc-job 'lock-state 'asserted) (push (get anc-job 'src-file) (span-property span 'coq-locked-ancestors))) (coq-par-collect-locked-require-ancestors job))) ;; XXX each require job must have items, right? (when items (when (and (eq coq--last-compilation-job job) (or (and (coq--post-v811) (eq coq-compile-vos 'vos-and-vok)) (and (not (coq--post-v811)) (eq coq-compile-quick 'quick-and-vio2vo)))) (let ((2nd-stage-counter (setq coq--par-second-stage-start-id (1+ coq--par-second-stage-start-id)))) ;; Insert a notification callback for when the last require ;; queue item has been processed. (setq items (cons (car items) ; this is the require (cons (coq-par-callback-queue-item (lambda (_span) (coq-par-require-processed 2nd-stage-counter))) (cdr items)))))) (proof-add-to-queue items 'advancing) (when coq--debug-auto-compilation (message "%s: add %s items to action list" (get job 'name) (length items))) ;; this function should only be called once for each require job ;; resetting queueitems is on the save side in any case (put job 'queueitems nil)))) (defun coq-par-kickoff-queue-from-action-list (job) "Trigger `coq-par-kickoff-queue-maybe' from action list. Simple wrapper around `coq-par-kickoff-queue-maybe' to set `default-directory' when entering background compilation functions from `proof-action-list'." (let ((default-directory (get job 'current-dir))) (when coq--debug-auto-compilation (message "%s: TTT retry queue kickoff after processing action list" (get job 'name))) (coq-par-kickoff-queue-maybe job))) (defun coq-par-kickoff-queue-maybe (job) "Transition require job JOB to 'waiting-queue and maybe to 'ready. This function can only be called for require jobs. It further must not be called if JOB is in state 'enqueued-coqdep or in state 'waiting-dep with some not yet finished dependencies. This function is called when all dependencies of JOB are ready to put JOB into state 'waiting-dep. When in state 'waiting-dep, this function is also called, when the queue dependency of JOB has transitioned to 'ready (inside this function). First JOB is put into state 'waiting-dep. If there is still a queue dependency, nothing else happens and JOB waits until the queue dependee calls this function again when it is ready. If there is no queue dependency, then require job JOB must be retired and transition to 'ready. This means: - for successful require jobs, ancestors are registered in the 'queue-span and marked as 'asserted in their 'lock-state property - processing of items in 'queueitems is started (if JOB is successful) - a possible queue dependant gets it's dependency cleared, and, if possible the 'waiting-queue -> 'ready transition is (recursively) done for the dependant - if this job is the last top-level compilation job (`coq--last-compilation-job') then the last compilation job and `proof-second-action-list-active' are cleared and second stage processing is triggered. - If compilation failed, the (failing) last top-level job is delayed until `proof-action-list' is empty, possibly by registering this call as a callback in an empty proof-action-list item. When proof-action-list is empty, the queue span is deleted, remaining spans are cleared and the `proof-shell-busy' lock is freed." (cl-assert (and (eq (get job 'type) 'require) (or (eq (get job 'state) 'waiting-queue) (and (eq (get job 'state) 'waiting-dep) (coq-par-dependencies-ready job)))) nil "coq-par-kickoff-queue-maybe precondition failed") (put job 'state 'waiting-queue) (if (get job 'queue-dependant-waiting) (when coq--debug-auto-compilation (message "%s: no queue kickoff because waiting for queue dependency" (get job 'name))) ;; first require job in the queue of require jobs (when coq--debug-auto-compilation (message "%s: has itself no queue dependency" (get job 'name))) (unless (get job 'failed) (coq-par-retire-top-level-job job)) (when (get job 'failed) ;; Reset coq--par-delayed-last-job for the case that this ;; function was called from a callback in proof-action-list. If ;; called from elsewhere, this does not harm. (setq coq--par-delayed-last-job nil)) (if (and (get job 'failed) (eq coq--last-compilation-job job) proof-action-list) (progn (when coq--debug-auto-compilation (message "%s: delay queue kickoff until action list is empty" (get job 'name))) (setq coq--par-delayed-last-job t) (proof-add-to-queue (list (coq-par-callback-queue-item (lambda (_span) (coq-par-kickoff-queue-from-action-list job)))) 'advancing)) (put job 'state 'ready) (when coq--debug-auto-compilation (message "%s: ready" (get job 'name))) (let ((dependant (get job 'queue-dependant))) (if dependant (progn (cl-assert (not (eq coq--last-compilation-job job)) nil "coq--last-compilation-job invariant error") (put dependant 'queue-dependant-waiting nil) ;; dependant might still wait for dependencies or even ;; for coqdep to finish (if (eq (get dependant 'state) 'waiting-queue) (progn (when coq--debug-auto-compilation (message "%s -> %s: clear queue dependency, kickoff queue at %s" (get job 'name) (get dependant 'name) (get dependant 'name))) (coq-par-kickoff-queue-maybe dependant) (when coq--debug-auto-compilation (message "%s: queue kickoff finished" (get job 'name)))) (when coq--debug-auto-compilation (message "%s -> %s: clear queue dependency, no queue kickoff for %s" (get job 'name) (get dependant 'name) (get dependant 'name))))) ;; XXX no dependant - this must be the last require job (when (eq coq--last-compilation-job job) (when (get job 'failed) ;; proof-action-list is empty, see above ;; unlock ancestors (mapc (lambda (anc-job) (cl-assert (eq (get anc-job 'lock-state) 'locked) nil "bad ancestor lock state") (when coq--debug-auto-compilation (message "%s: %s unlock because of error" (get anc-job 'name) (get anc-job 'src-file))) (coq-unlock-ancestor (get anc-job 'src-file)) (put anc-job 'lock-state 'unlocked)) (coq-par-collect-locked-require-ancestors job)) ;; variables that hold the queue span are buffer local (with-current-buffer (or proof-script-buffer (current-buffer)) (proof-script-clear-queue-spans-on-error nil)) (proof-release-lock) (when (or (and (coq--post-v811) (eq coq-compile-vos 'vos-and-vok)) (and (not (coq--post-v811)) (eq coq-compile-quick 'quick-and-vio2vo))) (cl-assert (not coq--par-second-stage-delay-timer) nil "second stage timer set before last compilation job") (setq coq--par-second-stage-delay-timer (run-at-time coq-compile-second-stage-delay nil #'coq-par-run-second-stage-queue)))) (setq coq--last-compilation-job nil) (setq proof-second-action-list-active nil) (when coq--debug-auto-compilation (message "clear last compilation job")) (message "Library compilation %s" (if (get job 'failed) "failed" "finished successfully"))) (when coq--debug-auto-compilation (message "%s: no queue dependant, queue kickoff finished" (get job 'name)))))))) (defun coq-par-compile-job-maybe (job) "Compile JOB after dependencies are ready or start next transitions. This function can only be called for 'file jobs. It must also be called for failed jobs to finish all necessary transitions. First JOB is put into state 'enqueued-coqc. Then it is determined if JOB needs compilation, what file must be produced (depending on `coq-compile-quick') and if a .vio or .vo file must be deleted. If necessary, deletion happens immediately. If JOB needs compilation, compilation is started or the JOB is enqueued and JOB stays in 'enqueued-coqc for the time being. Otherwise, the transition 'enqueued-coqc -> 'ready is triggered." (cl-assert (eq (get job 'type) 'file) nil "wrong job type in coq-par-compile-job-maybe") (put job 'state 'enqueued-coqc) ;; Note that coq-par-job-needs-compilation sets 'required-obj-file ;; if compilation is needed (but it might also get set if no ;; compilation is needed). For Coq < 8.11 .vo or .vio files that are ;; in the way are deleted. It also sets the 'second-stage property ;; if needed. (if (and (not (get job 'failed)) (coq-par-job-needs-compilation job)) (coq-par-start-or-enqueue job) (when coq--debug-auto-compilation (message "%s: %s, no compilation" (get job 'name) (if (get job 'failed) "failed" "up-to-date"))) (when (get job 'second-stage) (coq-par-second-stage-enqueue job)) (coq-par-kickoff-coqc-dependants job nil))) (defun coq-par-decrease-coqc-dependency (dependant dependee-time) "Clear Coq dependency and update dependee information in DEPENDANT. This function handles a Coq dependency from child dependee to parent dependant when the dependee has finished compilation (ie. is in state 'ready). DEPENDANT must be in state 'waiting-dep. The time of the most recent ancestor is updated, if necessary using DEPENDEE-TIME. DEPENDEE-TIME must be an Emacs time or 'just-compiled. The dependency count of DEPENDANT is decreased and, if it reaches 0, the next transition is triggered for DEPENDANT. For 'file jobs this is 'waiting-dep -> 'enqueued-coqc and for 'require jobs this is 'waiting-dep -> 'waiting-queue. This function must be called for failed jobs to complete all necessary transitions." ;(message "%s: CPDCD with time %s" (get dependant 'name) dependee-time) (cl-assert (eq (get dependant 'state) 'waiting-dep) nil "wrong state of parent dependant job") (when (coq-par-time-less (get dependant 'youngest-coqc-dependency) dependee-time) (put dependant 'youngest-coqc-dependency dependee-time)) (put dependant 'coqc-dependency-count (1- (get dependant 'coqc-dependency-count))) (cl-assert (<= 0 (get dependant 'coqc-dependency-count)) nil "dependency count below zero") (when coq--debug-auto-compilation (message "%s: coqc dependency count down to %d" (get dependant 'name) (get dependant 'coqc-dependency-count))) (when (coq-par-dependencies-ready dependant) (if (eq (get dependant 'type) 'file) (coq-par-compile-job-maybe dependant) (coq-par-kickoff-queue-maybe dependant)))) (defun coq-par-kickoff-coqc-dependants (job just-compiled) "Handle transition to state 'ready for file job JOB. This function can only be called for file jobs and it must also be called for failed jobs to complete all necessary transitions. This function is called after compilation has been finished (with JUST-COMPILED being t) or after determining that compilation was not necessary or failed (with JUST-COMPILED being nil). This function sets 'youngest-coqc-dependency to the maximal (youngest) time stamp of the vo file for this job and all its ancestors. This function also decreases the dependency counter on all dependants, propagates 'youngest-coqc-dependency and starts any necessary state transitions on the dependants. Nothing special happens, if this job is successful but all its dependants are marked failed. Ancestor unlocking will be done when the last require job is retired. For the case that JUST-COMPILED is nil and that JOB has not failed, this function relies on 'obj-mod-time has been set before." (cl-assert (not (eq (get job 'type) 'require)) nil "kickoff-coqc-dependants called for require job") ;; most actions are not relevant for failed jobs, but do not harm (let ((dependant-alive nil) ;; take max (youngest) time of this job and all ancestors ;; ;; If this job has just been compiled then it is clearly ;; 'just-compiled. Otherwise it must be 'obj-mod-time, because ;; if some ancestor were newer, this just would have been ;; compiled. For failed jobs obj-mod-time might be nil, but ;; this does not matter. (dep-time (if just-compiled 'just-compiled (get job 'obj-mod-time)))) (put job 'youngest-coqc-dependency dep-time) (when coq--debug-auto-compilation ;; (let (ancs) (message "%s: kickoff %d coqc dependencies with time %s" (get job 'name) (length (get job 'coqc-dependants)) (if (eq dep-time 'just-compiled) 'just-compiled (current-time-string dep-time)))) ;; In the recursion coq-par-kickoff-coqc-dependants -> ;; coq-par-decrease-coqc-dependency -> coq-par-compile-job-maybe ;; -> coq-par-kickoff-coqc-dependants jobs on the path upwards ;; must be in state 'ready, otherwise coq-par-ongoing-compilation ;; might take one of those as witness for an ongoing compilation. (put job 'state 'ready) (dolist (dependant (get job 'coqc-dependants)) (coq-par-decrease-coqc-dependency dependant dep-time) (unless (get dependant 'failed) (setq dependant-alive t))) (when coq--debug-auto-compilation (message (concat "%s: coqc kickoff finished, %s dependant alive") (get job 'name) (if dependant-alive "some" "no"))))) (defun coq-par-start-coqdep-on-require (job) "Start coqdep for require job JOB. Write the require statement in JOB into a temporary file and start coqdep on it. This function may be called asynchronously, if the require job was queued." ;; get coq-load-path from job ;; check that this really includes the current dir in the arguments (let ((load-path ;; For coq < 8.5 coqdep needs the current working directory ;; in the load path. This differs from the directory containing ;; 'temp-require-file. Therefore we add it here and tweek ;; coq-load-path-include-current such that coq-coqdep-prog-args ;; does not add the directory containing 'temp-require-file to ;; load-path. (if (and coq-load-path-include-current (coq--pre-v85)) (cons (get job 'current-dir) (get job 'load-path)) (get job 'load-path))) (coq-load-path-include-current nil) (require-command (mapconcat #'identity (nth 1 (car (get job 'queueitems))) " ")) (temp-file (make-temp-file "ProofGeneral-coq" nil ".v"))) (put job 'temp-require-file temp-file) (with-temp-file temp-file (insert require-command)) (when coq--debug-auto-compilation (message "%s: TTT start coqdep for require job for file %s" (get job 'name) (get job 'temp-require-file))) (coq-par-start-process coq-dependency-analyzer (coq-par-coqdep-arguments (get job 'temp-require-file) load-path) 'coq-par-process-coqdep-result job (get job 'temp-require-file)))) (defun coq-par-start-coqdep-on-file (job) "Start coqdep for file job JOB. Lock the source file and start the coqdep background process." (when (and coq-lock-ancestors ;; the lock state property is initialized from all as ;; locked registered files in `proof-included-files-list' (eq (get job 'lock-state) 'unlocked)) (proof-register-possibly-new-processed-file (get job 'src-file)) (put job 'lock-state 'locked)) (when coq--debug-auto-compilation (message "%s: TTT start coqdep for file job for file %s" (get job 'name) (get job 'src-file))) (coq-par-start-process coq-dependency-analyzer (coq-par-coqdep-arguments (get job 'src-file) (get job 'load-path)) 'coq-par-process-coqdep-result job nil)) (defun coq-par-start-coqc (job) "Start coqc background compilation for JOB. Depending on property 'use-quick, vos or quick compilation may be used." (message "Recompile %s%s" (cond ((eq (get job 'use-quick) 'vos) "-vos ") ((eq (get job 'use-quick) 'vio) "-quick ") (t "")) (get job 'src-file)) (let ((arguments (coq-par-coqc-arguments (get job 'src-file) (get job 'load-path)))) (cond ((eq (get job 'use-quick) 'vos) (push "-vos" arguments)) ((eq (get job 'use-quick) 'vio) (push "-quick" arguments)) (t t)) (when coq--debug-auto-compilation (message "%s: TTT start coqc compile for file job for file %s" (get job 'name) (get job 'src-file))) (coq-par-start-process coq-compiler arguments 'coq-par-coqc-continuation job (get job 'required-obj-file)))) (defun coq-par-start-vok (job) "Start coqc -vok background compilation for JOB." (when coq--debug-auto-compilation (message "%s start coqc -vok for %s" (get job 'name) (get job 'src-file))) (message "coqc -vok %s" (get job 'src-file)) (when coq--debug-auto-compilation (message "%s: TTT start coqc -vok for file job for file %s" (get job 'name) (get job 'src-file))) (let ((arguments (coq-par-coqc-arguments (get job 'src-file) (get job 'load-path)))) (push "-vok" arguments) (coq-par-start-process coq-compiler arguments 'coq-par-vok-continuation job nil))) (defun coq-par-start-vio2vo (job) "Start vio2vo background job." (let ((arguments (coq-include-options (get job 'load-path))) (module (coq-module-of-src-file (get job 'src-file))) (default-directory (file-name-directory (file-truename (get job 'src-file))))) (when coq--debug-auto-compilation (message "%s: start vio2vo for %s" (get job 'name) (get job 'src-file))) (message "vio2vo %s" (get job 'src-file)) (when coq--debug-auto-compilation (message "%s: TTT start vio2vo for file job for file %s" (get job 'name) (get job 'src-file))) (coq-par-start-process ;; in 8.9.1 and before only coqtop accepts -schedule-vio2vo ;; after change 103f59e only coqc accepts -schedule-vio2vo (if (coq--post-v810) coq-compiler coq-prog-name) (nconc arguments (list "-schedule-vio2vo" "1" module)) 'coq-par-vio2vo-continuation job (get job 'vo-file)))) (defun coq-par-start-task (job) "Start the background job for which JOB is waiting. JOB was at the head of the compilation queue and now either coqdep, coqc, vio2vo or vok is started for it. This function may be called synchronously or asynchronously." (let ((job-state (get job 'state))) (cond ((and (eq job-state 'enqueued-coqdep) (eq (get job 'type) 'require)) (coq-par-start-coqdep-on-require job)) ((eq job-state 'enqueued-coqdep) (coq-par-start-coqdep-on-file job)) ((eq job-state 'enqueued-coqc) (coq-par-start-coqc job)) ((and (eq job-state 'ready) (eq (get job 'second-stage) 'vok)) (coq-par-start-vok job)) ((and (eq job-state 'ready) (eq (get job 'second-stage) 'vio2vo)) (coq-par-start-vio2vo job)) (t (cl-assert nil nil "coq-par-start-task with invalid job"))))) (defun coq-par-start-jobs-until-full () "Start background jobs until the limit is reached. This function may be called synchronously or asynchronously." (let ((max-jobs (if coq--par-second-stage-in-progress coq--internal-max-second-stage-jobs coq--internal-max-jobs)) next-job) (while (and (< coq--current-background-jobs max-jobs) (setq next-job (if coq--par-second-stage-in-progress (coq-par-second-stage-dequeue) (coq-par-job-dequeue)))) (coq-par-start-task next-job)))) (defun coq-par-start-or-enqueue (new-job) "Start NEW-JOB or put it into the queue of waiting jobs. NEW-JOB goes already into the waiting queue, if the number of background jobs is one below the limit. This is in order to leave room for Proof General. This function might be called synchronously or asynchronously." (if (< (1+ coq--current-background-jobs) coq--internal-max-jobs) (coq-par-start-task new-job) (coq-par-job-enqueue new-job))) (defun coq-par-job-init-common (clpath type current-dir) "Common initialization for 'require and 'file jobs. Create a new job of type TYPE and initialize all common fields of require and file jobs that need an initialization different from nil." (let ((new-job (make-symbol "coq-compile-job-symbol"))) (put new-job 'name (format "job-%d" coq--par-next-id)) (setq coq--par-next-id (1+ coq--par-next-id)) (put new-job 'coqc-dependency-count 0) (put new-job 'type type) (put new-job 'state 'enqueued-coqdep) (put new-job 'current-dir current-dir) ;; The ancestor modification time is not really needed in require ;; jobs, however, if the field is present, we can treat require ;; and file jobs more uniformely. (put new-job 'youngest-coqc-dependency '(0 0)) (put new-job 'load-path clpath) new-job)) (defun coq-par-create-require-job (clpath require-items require-span current-dir) "Create a new require job for REQUIRE-SPAN. Create a new require job and initialize its fields. CLPATH is the load path configured for the current scripting buffer, that is passed down to all dependencies and used in all compilations. REQUIRE-ITEMS are the non-require commands following the REQUIRE-SPAN, they are temporarily stored in the new require job outside of `proof-action-list'. The current directory (from `default-directory') is stored in property 'current-dir and propagated to all dependend jobs. This is used to set `default-directory' when entering background compilation from a sentinel or elsewhere. This function is called synchronously when asserting. The new require job is neither started nor enqueued here - the caller must do this." (let* ((coq-load-path clpath) (new-job (coq-par-job-init-common clpath 'require current-dir))) (put new-job 'require-span require-span) (put new-job 'queueitems require-items) (when coq--debug-auto-compilation (let* ((require-item (car require-items)) (require-command (mapconcat #'identity (nth 1 require-item) " "))) (message "%s: create require job for %s" (get new-job 'name) require-command))) new-job)) ;; XXX what happens when job exists but has been unlocked because ;; there was some error and it was not used anywhere back then, but ;; job is now needed as a dependency of some other file? ;; XXX what happens if the job exists and is failed? (defun coq-par-create-file-job (module-vo-file clpath dep-src-file current-dir) "Create a new file job for MODULE-VO-FILE. DEP-SRC-FILE is the source file whose coqdep output we are just processing and which depends on MODULE-VO-FILE. This argument is only used in the error message, when MODULE-VO-FILE happens to coincide with the current scripting buffer (which means we detected a dependency cycle). If there is a file job for MODULE-VO-FILE, just return this. Otherwise, create a new file job and initialize its fields. In particular, initialize its 'lock-state property from the set of as locked registered files in `proof-included-files-list'. If a new job is created it is started or enqueued right away." (cond ((gethash module-vo-file coq--compilation-object-hash)) (t (let* ((coq-load-path clpath) (new-job (coq-par-job-init-common clpath 'file current-dir))) ;; fields 'required-obj-file and obj-mod-time are implicitely set to nil (put new-job 'vo-file module-vo-file) (put new-job 'src-file (coq-library-src-of-vo-file module-vo-file)) (when (equal (get new-job 'src-file) (buffer-file-name proof-script-buffer)) ;; test this error case - maybe need more files participating ;; in the circle? (signal 'coq-compile-error-circular-dep (concat dep-src-file " -> scripting buffer"))) (puthash module-vo-file new-job coq--compilation-object-hash) (when coq--debug-auto-compilation (message "%s: create %s compilation for %s" (get new-job 'name) (get new-job 'type) module-vo-file)) ;; if the user single-steps through multiple requires, then the ;; compilation for the previous require might have been finished ;; and cleared, then we might have visited and locked this file ;; already (if (member (file-truename (get new-job 'src-file)) proof-included-files-list) (put new-job 'lock-state 'asserted) (put new-job 'lock-state 'unlocked)) (message "Check %s" (get new-job 'src-file)) (coq-par-start-or-enqueue new-job) new-job)))) (defun coq-par-mark-queue-failing (job) "Mark require JOB and its queue dependants with 'failed. Mark JOB with 'failed and unlock ancestors as appropriate. Recurse for queue dependants." (unless (get job 'failed) (put job 'failed t) (cl-assert (not (eq (get job 'state) 'ready)) nil "coq-par-mark-queue-failing impossible state") (when coq--debug-auto-compilation (message "%s: mark as failed" (get job 'name))) (when (get job 'queue-dependant) (coq-par-mark-queue-failing (get job 'queue-dependant))))) (defun coq-par-mark-job-failing (job) "Mark all dependants of JOB as failing and unlock ancestors as appropriate. Set the 'failed property on all direct and indirect dependants of JOB. Along the way, unlock ancestors as determined by `coq-par-ongoing-compilation'." (unless (get job 'failed) (put job 'failed t) (when coq--debug-auto-compilation (message "%s: mark as failed" (get job 'name))) (dolist (dependant (get job 'coqc-dependants)) (coq-par-mark-job-failing dependant)) (when (get job 'queue-dependant) (coq-par-mark-queue-failing (get job 'queue-dependant))))) (defun coq-par-process-coqdep-result (process exit-status) "Coqdep continuation function: Process coqdep output. This function analyses the coqdep output of PROCESS. In case of error, the job is marked as failed or compilation is aborted via a signal (depending on `coq-compile-keep-going'). If there was no coqdep error, the following actions are taken. - temp-require-file for require jobs is deleted - the job that started PROCESS is put into sate 'waiting-dep - a new job is created for every dependency. If this new job is not immediately ready, a dependency is registered from the new job to the current job. For dependencies that are 'ready already, the most recent ancestor modification time is propagated. - if there are no dependencies (especially if coqdep failed) or all dependencies are ready already, the next transition is triggered. For file jobs the next transition goes to 'enqueued-coqc, for require jobs it goes to 'waiting-queue. - otherwise the current job is left alone until somebody decreases its dependency count to 0. The argument EXIT-STATUS must be the exit status of PROCESS, it is directly passed to `coq-par-analyse-coq-dep-exit'." (let ((job (process-get process 'coq-compilation-job)) (dependencies-or-error (coq-par-analyse-coq-dep-exit exit-status (process-get process 'coq-process-output) (process-get process 'coq-process-command))) job-max-time dependee-failed) (if (stringp dependencies-or-error) (progn (when coq--debug-auto-compilation (message "%s coqdep error %s" (get job 'name) dependencies-or-error)) (if coq-compile-keep-going (coq-par-mark-job-failing job) (signal 'coq-compile-error-coqdep (get job 'src-file)))) ;; no coqdep error -- work on dependencies (when coq--debug-auto-compilation (message "%s: dependencies of %s are %s" (get job 'name) (if (eq (get job 'type) 'file) (get job 'src-file) (get job 'temp-require-file)) dependencies-or-error)) (when (get job 'temp-require-file) (ignore-errors (delete-file (get job 'temp-require-file)))) (setq job-max-time (get job 'youngest-coqc-dependency)) (dolist (dep-vo-file dependencies-or-error) (unless (coq-compile-ignore-file dep-vo-file) (let* ((dep-job (coq-par-create-file-job dep-vo-file (get job 'load-path) (get job 'src-file) (get job 'current-dir))) (dep-time (get dep-job 'youngest-coqc-dependency))) (when (get dep-job 'failed) (setq dependee-failed t)) (when (and (eq (get dep-job 'state) 'ready) (coq-par-time-less job-max-time dep-time)) ;; the following clause is not needed for require jobs, ;; but it doesn't harm either, so keep the code a little ;; bit more simple (setq job-max-time dep-time)) (coq-par-add-coqc-dependency dep-job job (not (eq (get dep-job 'state) 'ready)))))) (put job 'youngest-coqc-dependency job-max-time) (when dependee-failed (cl-assert coq-compile-keep-going nil "compilation continues without keep going") (coq-par-mark-job-failing job))) ;; common part for job where coqdep was successful and where ;; coqdep failed (when coq-compile-keep-going) (put job 'state 'waiting-dep) (if (coq-par-dependencies-ready job) (progn (when coq--debug-auto-compilation (message "%s: coqc dependencies finished" (get job 'name))) (if (eq (get job 'type) 'file) (coq-par-compile-job-maybe job) ;; require jobs (coq-par-kickoff-queue-maybe job))) (when coq--debug-auto-compilation (message "%s: wait for %d dependencies" (get job 'name) (get job 'coqc-dependency-count)))))) (defun coq-par-coqc-continuation (process exit-status) "Coqc continuation function. If coqc failed, signal an error or mark the job as 'failed, and unlock ancestors as appropriate. If coqc was successful, trigger the transition 'enqueued-coqc -> 'ready for the job behind PROCESS." (let ((job (process-get process 'coq-compilation-job))) (if (eq exit-status 0) (progn ;; coqc success (when (get job 'second-stage) (coq-par-second-stage-enqueue job)) (coq-par-kickoff-coqc-dependants job t)) ;; coqc error (coq-compile-display-error (mapconcat #'identity (process-get process 'coq-process-command) " ") (process-get process 'coq-process-output) t) (if coq-compile-keep-going (progn (coq-par-mark-job-failing job) (coq-par-kickoff-coqc-dependants job nil)) (signal 'coq-compile-error-coqc (get (process-get process 'coq-compilation-job) 'src-file)))))) (defun coq-par-vok-continuation (process exit-status) "Vok continuation function. Nothing to do in case of success. Otherwise display the errors." (let ((job (process-get process 'coq-compilation-job))) (if (eq exit-status 0) ;; success - nothing to do (when coq--debug-auto-compilation (message "%s: vok finished successfully" (get job 'name))) (when coq--debug-auto-compilation (message "%s: vok failed" (get job 'name))) (coq-compile-display-error (mapconcat 'identity (process-get process 'coq-process-command) " ") (process-get process 'coq-process-output) t) ;; don't signal an error or abort other vok processes ))) (defun coq-par-vio2vo-continuation (process exit-status) "Vio2vo continuation function. Nothing to do in case of success. Otherwise display the errors." (let ((job (process-get process 'coq-compilation-job))) (if (eq exit-status 0) ;; success - nothing to do (when coq--debug-auto-compilation (message "%s: vio2vo finished successfully" (get job 'name))) (when coq--debug-auto-compilation (message "%s: vio2vo failed" (get job 'name))) (coq-compile-display-error (concat "cd " (file-name-directory (file-truename (get job 'src-file))) "; " (mapconcat 'identity (process-get process 'coq-process-command) " ")) (process-get process 'coq-process-output) t) ;; don't signal an error or abort other vio2vo processes ))) ;;; handle Require commands when queue is extended (defun coq-par-handle-require-list (require-items) "Start compilation for the required modules in the car of REQUIRE-ITEMS. REQUIRE-ITEMS is a list of queue items, eventually to be added to `proof-action-list', that contains just one require command in the first element. This function starts the compilation process for all modules and their dependencies in this require command. This function creates one require job for the require command, maintains `coq--last-compilation-job' and adds the delete action to delete all ancestors to the span of the require command. Coqdep is directly started on the require job or the job is enqueued. This function must be evaluated with the buffer that triggered the compilation as current, otherwise a wrong `coq-load-path' might be used. This function is called synchronously when asserting." (let ((span (caar require-items)) new-job) (when coq--debug-auto-compilation (let* ((require-item (car require-items)) (require-command (mapconcat 'identity (nth 1 require-item) " "))) (message "handle require command \"%s\"" require-command))) (span-add-delete-action span (lambda () (coq-unlock-all-ancestors-of-span span))) ;; create a new require job and maintain coq--last-compilation-job (setq new-job (coq-par-create-require-job coq-load-path require-items span default-directory)) (when coq--last-compilation-job (coq-par-add-queue-dependency coq--last-compilation-job new-job)) (setq coq--last-compilation-job new-job) (when coq--debug-auto-compilation (message "%s: this job is the last compilation job now" (get coq--last-compilation-job 'name))) (coq-par-start-or-enqueue new-job))) (defun coq-par-item-require-predicate (item) "Return t if ITEM contains a Require command. Predicate for `split-list-at-predicate', used to split the new queue items at each Require command." (let ((string (mapconcat #'identity (nth 1 item) " "))) (and string (string-match coq-require-command-regexp string)))) (defun coq-par-preprocess-require-commands-internal () "Worker for `coq-par-preprocess-require-commands'. This function does all the work for `coq-par-preprocess-require-commands', except for error reporting. If `coq-compile-before-require' is non-nil, this function starts the compilation (if necessary) of the dependencies ansynchronously in parallel in the background. If there already is a last compilation job (`coq--last-compilation-job') then the queue region is extended, while some background compilation is still running. In this case I have to preserve the internal state. Otherwise the hash of the compilation jobs and the ancestor hash are reinitialized. As next action the new queue items are splitted at each Require command. The items before the first Require are appended to the old last compilation job or put back into ‘proof-action-list’. The remaining batches of items that each start with a Require are then processed by `coq-par-handle-require-list', which creates require jobs as necessary. Before processing the first of these batches, buffers are saved with `coq-compile-save-some-buffers' and an possibly ongoing second stage compilation is stopped. Finally, `proof-second-action-list-active' is set if I keep some queue items because they have to wait for a compilation job. Then the maximal number of background compilation jobs is started. This function is called synchronously when asserting." (when coq--debug-auto-compilation (message "%d items were added to the queue, scan for require" (length queueitems))) (unless coq--last-compilation-job (coq-par-init-compilation-hash) (coq-init-compile-response-buffer)) (let ((splitted-items (split-list-at-predicate queueitems 'coq-par-item-require-predicate))) (if coq--last-compilation-job (progn (put coq--last-compilation-job 'queueitems (nconc (get coq--last-compilation-job 'queueitems) (car splitted-items))) (setq queueitems nil) (message "attach first %s items to job %s" (length (car splitted-items)) (get coq--last-compilation-job 'name))) (setq queueitems (car splitted-items)) (when coq--debug-auto-compilation (message "attach first %s items directly to queue" (length (car splitted-items))))) ;; XXX handle external compilation here, compile everything ;; with one command, use compilation-finish-functions to get ;; notification (when (cdr splitted-items) (when coq--par-second-stage-delay-timer (cancel-timer coq--par-second-stage-delay-timer) (setq coq--par-second-stage-delay-timer nil)) (when coq--par-second-stage-in-progress (cl-assert (not coq--last-compilation-job) nil "normal compilation and second stage in parallel 2") ;; there are only second stage background processes (coq-par-kill-all-processes) (setq coq--par-second-stage-in-progress nil)) ;; save buffers before invoking the first coqdep (coq-compile-save-some-buffers) (dolist (require-items (cdr splitted-items)) (coq-par-handle-require-list require-items))) (when coq--last-compilation-job (setq proof-second-action-list-active t)) (coq-par-start-jobs-until-full) (when coq--debug-auto-compilation (if coq--last-compilation-job (message "return control, waiting for background jobs") (message "return control, no background jobs"))))) (defun coq-par-preprocess-require-commands () "Coq function for `proof-shell-extend-queue-hook' doing parallel compilation. If `coq-compile-before-require' is non-nil, this function starts the compilation (if necessary) of the dependencies ansynchronously in parallel in the background. This function only does the error checking/reporting for `coq-par-preprocess-require-commands-internal', which does all the work. This function is called synchronously when asserting." (when coq-compile-before-require (condition-case err (coq-par-preprocess-require-commands-internal) (coq-compile-error (coq-par-emergency-cleanup) (message "%s %s" (get (car err) 'error-message) (cdr err))) (coq-unclassifiable-version (coq-par-emergency-cleanup) (if (equal (cdr err) "trunk") (message (concat "your Coq version \"trunk\" is too unspecific for " "Proof General; please customize coq-pinned-version")) (message "%s \"%s\"; consider customizing coq-pinned-version" (get (car err) 'error-message) (cdr err)))) (file-error (coq-par-emergency-cleanup) (message "Error: %s" (mapconcat 'identity (cdr err) ": "))) (error (message "Unexpected error during parallel compilation: %s" err) (coq-par-emergency-cleanup) (signal (car err) (cdr err)))))) (provide 'coq-par-compile) ;; Local Variables: *** ;; coding: utf-8 *** ;; End: *** ;;; coq-par-compile.el ends here PG-4.5/coq/coq-seq-compile.el000066400000000000000000000442251426357011200160020ustar00rootroot00000000000000;;; coq-seq-compile.el --- sequential compilation of required modules -*- lexical-binding: t; -*- ;; This file is part of Proof General. ;; Portions © Copyright 1994-2012 David Aspinall and University of Edinburgh ;; Portions © Copyright 2003-2021 Free Software Foundation, Inc. ;; Portions © Copyright 2001-2017 Pierre Courtieu ;; Portions © Copyright 2010, 2016 Erik Martin-Dorel ;; Portions © Copyright 2011-2013, 2016-2017 Hendrik Tews ;; Portions © Copyright 2015-2017 Clément Pit-Claudel ;; Authors: Hendrik Tews ;; Maintainer: Hendrik Tews ;; SPDX-License-Identifier: GPL-3.0-or-later ;;; Commentary: ;; ;; This file implements compilation of required modules. The ;; compilation is done synchonously and sequentially. That is, Proof ;; General blocks before putting newly asserted items into ;; proof-action-list and compiles one module after the other. ;; ;;; Code: (eval-when-compile (require 'cl-lib)) (defvar queueitems) ; dynamic scope in p-s-extend-queue-hook (require 'coq-compile-common) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Multiple file handling -- sequential compilation of required modules ;; ;;; ancestor locking ;;; (unlocking is shared in coq-compile-common.el) (defun coq-seq-lock-ancestor (span ancestor-src) "Lock ancestor ANCESTOR-SRC and register it in SPAN. Lock only if `coq-lock-ancestor' is non-nil. Further, do nothing, if ANCESTOR-SRC is already a member of `proof-included-files-list'. Otherwise ANCESTOR-SRC is locked and registered in the 'coq-locked-ancestors property of the SPAN to properly unlock ANCESTOR-SRC on retract." (if coq-lock-ancestors (let ((true-ancestor-src (file-truename ancestor-src))) (unless (member true-ancestor-src proof-included-files-list) (proof-register-possibly-new-processed-file true-ancestor-src) (span-set-property span 'coq-locked-ancestors (cons true-ancestor-src (span-property span 'coq-locked-ancestors))))))) ;;; handle Require commands when queue is extended (defun coq-seq-get-library-dependencies (lib-src-file &optional command-intro) "Compute dependencies of LIB-SRC-FILE. Invoke \"coqdep\" on LIB-SRC-FILE and parse the output to compute the compiled coq library object files on which LIB-SRC-FILE depends. The return value is either a string or a list. If it is a string then an error occurred and the string is the core of the error message. If the return value is a list no error occurred and the returned list is the (possibly empty) list of file names LIB-SRC-FILE depends on. If an error occurs this funtion displays `coq--compile-response-buffer' with the complete command and its output. The optional argument COMMAND-INTRO is only used in the error case. It is prepended to the displayed command. LIB-SRC-FILE should be an absolute file name. If it is, the dependencies are absolute too and the simplified treatment of `coq-load-path-include-current' in `coq-include-options' won't break." (let ((coqdep-arguments ;; FIXME should this use coq-coqdep-prog-args? (nconc (coq-include-options coq-load-path (file-name-directory lib-src-file) (coq--pre-v85)) (list lib-src-file))) coqdep-status coqdep-output) (when coq--debug-auto-compilation (message "call coqdep arg list: %S" coqdep-arguments)) (with-temp-buffer (setq coqdep-status (apply #'call-process coq-dependency-analyzer nil (current-buffer) nil coqdep-arguments)) (setq coqdep-output (buffer-string))) (when coq--debug-auto-compilation (message "coqdep status %s, output on %s: %s" coqdep-status lib-src-file coqdep-output)) (if (or (not (eq coqdep-status 0)) (string-match coq-coqdep-error-regexp coqdep-output)) (let* ((this-command (cons coq-dependency-analyzer coqdep-arguments)) (full-command (if command-intro (cons command-intro this-command) this-command))) ;; display the error (coq-init-compile-response-buffer (mapconcat #'identity full-command " ")) (let ((inhibit-read-only t)) (with-current-buffer coq--compile-response-buffer (insert coqdep-output))) (coq-display-compile-response-buffer) "unsatisfied dependencies") (if (string-match ": \\(.*\\)$" coqdep-output) (cdr-safe (split-string (match-string 1 coqdep-output))) ())))) (defun coq-seq-compile-library (src-file) "Recompile coq library SRC-FILE. Display errors in buffer `coq--compile-response-buffer'." (message "Recompile %s" src-file) (let ((coqc-arguments (nconc (coq-coqc-prog-args coq-load-path (file-name-directory src-file) (coq--pre-v85)) (list src-file))) coqc-status) (coq-init-compile-response-buffer (mapconcat #'identity (cons coq-compiler coqc-arguments) " ")) (when coq--debug-auto-compilation (message "call coqc arg list: %s" coqc-arguments)) (setq coqc-status (apply #'call-process coq-compiler nil coq--compile-response-buffer t coqc-arguments)) (when coq--debug-auto-compilation (message "compilation %s exited with %s, output |%s|" src-file coqc-status (with-current-buffer coq--compile-response-buffer (buffer-string)))) (unless (eq coqc-status 0) (coq-display-compile-response-buffer) (let ((terminated-text (if (numberp coqc-status) "terminated with exit status" "was terminated by signal"))) (error "ERROR: Recompiling coq library %s %s %s" src-file terminated-text coqc-status))))) (defun coq-seq-compile-library-if-necessary (max-dep-obj-time src obj) "Recompile SRC to OBJ if necessary. This function compiles SRC to the coq library object file OBJ if one of the following conditions is true: - a dependency has just been compiled - OBJ does not exist - SRC is newer than OBJ - OBJ is older than the the youngest object file of the dependencies. Argument MAX-DEP-OBJ-TIME provides the information about the dependencies. It is either - 'just-compiled if one of the dependencies of SRC has just been compiled - the time value (see`time-less-or-equal') of the youngest (most recently created) object file among the dependencies - nil if there are no dependencies, or if they are all ignored If this function decides to compile SRC to OBJ it returns 'just-compiled. Otherwise it returns the modification time of OBJ. Note that file modification times inside Emacs have only a precisision of 1 second. To avoid spurious recompilations we do not recompile if the youngest object file of the dependencies and OBJ have identical modification times." (let (src-time obj-time) (if (eq max-dep-obj-time 'just-compiled) (progn (coq-seq-compile-library src) 'just-compiled) (setq src-time (nth 5 (file-attributes src))) (setq obj-time (nth 5 (file-attributes obj))) (if (or (not obj-time) ; obj does not exist (time-less-or-equal obj-time src-time) ; src is newer (and max-dep-obj-time ; there is a youngest dependency ; which is newer than obj (time-less-p obj-time max-dep-obj-time))) (progn (coq-seq-compile-library src) 'just-compiled) (when coq--debug-auto-compilation (message "Skip compilation of %s" src)) obj-time)))) (defun coq-seq-make-lib-up-to-date (coq-obj-hash span lib-obj-file) "Make library object file LIB-OBJ-FILE up-to-date. Check if LIB-OBJ-FILE and all it dependencies are up-to-date compiled coq library objects. Recompile the necessary objects, if not. This function returns 'just-compiled if it compiled LIB-OBJ-FILE. Otherwise it returns the modification time of LIB-OBJ-FILE as time value (see `time-less-or-equal'). Either LIB-OBJ-FILE or its source file (or both) must exist when entering this function. Argument SPAN is the span of the \"Require\" command. LIB-OBJ-FILE and its dependencies are locked and registered in the span for for proper unlocking on retract. Argument COQ-OBJ-HASH remembers the return values of this function." (let ((result (gethash lib-obj-file coq-obj-hash))) (if result (progn (when coq--debug-auto-compilation (message "Checked %s already" lib-obj-file)) result) ;; lib-obj-file has not been checked -- do it now (message "Check %s" lib-obj-file) (if (coq-compile-ignore-file lib-obj-file) ;; return minimal time for ignored files (setq result '(0 0)) (let* ((lib-src-file (expand-file-name (coq-library-src-of-vo-file lib-obj-file))) dependencies deps-mod-time) (if (file-exists-p lib-src-file) ;; recurse into dependencies now (progn (setq dependencies (coq-seq-get-library-dependencies lib-src-file)) (if (stringp dependencies) (error "File %s has %s" lib-src-file dependencies)) (setq deps-mod-time (mapcar (lambda (dep) (coq-seq-make-lib-up-to-date coq-obj-hash span dep)) dependencies)) (setq result (coq-seq-compile-library-if-necessary (coq-max-dep-mod-time deps-mod-time) lib-src-file lib-obj-file))) (message "coq-auto-compile: no source file for %s" lib-obj-file) (setq result ;; 5 value: last modification time (nth 5 (file-attributes lib-obj-file)))) (coq-seq-lock-ancestor span lib-src-file))) ;; at this point the result value has been determined ;; store it in the hash then (puthash lib-obj-file result coq-obj-hash) result))) (defun coq-seq-auto-compile-externally (span q-id absolute-module-obj-file) "Make MODULE up-to-date according to `coq-compile-command'. Start a compilation to make ABSOLUTE-MODULE-OBJ-FILE up-to-date. The compilation command is derived from `coq-compile-command' by substituting certain keys, see `coq-compile-command' for details. If `coq-confirm-external-compilation' is t then the user must confirm the external command in the minibuffer, otherwise the command is executed without confirmation. Argument SPAN is the span of the \"Require\" command. The ancestor ABSOLUTE-MODULE-OBJ-FILE is locked and registered in the span for for proper unlocking on retract. This function uses the low-level interface `compilation-start', therefore the customizations for `compile' do not apply." (unless (coq-compile-ignore-file absolute-module-obj-file) ;; Dynvar list taken from `coq-compile-substitution-list'. (defvar physical-dir) (defvar module-object) (defvar module-source) (defvar qualified-id) (defvar requiring-file) (let* ((local-compile-command coq-compile-command) (qualified-id q-id) (physical-dir (file-name-directory absolute-module-obj-file)) (module-object (file-name-nondirectory absolute-module-obj-file)) (module-source (coq-library-src-of-vo-file module-object)) (requiring-file buffer-file-name)) (mapc (lambda (substitution) (setq local-compile-command (replace-regexp-in-string (car substitution) (eval (car (cdr substitution)) t) local-compile-command))) coq-compile-substitution-list) (if coq-confirm-external-compilation (setq local-compile-command (read-shell-command "Coq compile command: " local-compile-command (if (equal (car coq-compile-history) local-compile-command) '(coq-compile-history . 1) 'coq-compile-history)))) ;; buffers have already been saved before we entered this function ;; the next line is probably necessary to make recompile work (setq-default compilation-directory default-directory) (compilation-start local-compile-command) (coq-seq-lock-ancestor span (coq-library-src-of-vo-file absolute-module-obj-file))))) (defun coq-seq-map-module-id-to-obj-file (module-id _span &optional from) "Map MODULE-ID to the appropriate coq object file. The mapping depends of course on `coq-load-path'. The current implementation invokes coqdep with a one-line require command. This is probably slower but much simpler than modelling coq file loading inside ProofGeneral. Argument SPAN is only used for error handling. It provides the location information of MODULE-ID for a decent error message. A peculiar consequence of the current implementation is that this function returns () if MODULE-ID comes from the standard library." (let ((coq-load-path (if coq-load-path-include-current (cons default-directory coq-load-path) coq-load-path)) (coq-load-path-include-current nil) (temp-require-file (make-temp-file "ProofGeneral-coq" nil ".v")) (coq-string (concat (if from (concat "From " from " ") "") "Require " module-id ".")) result) (unwind-protect (progn (with-temp-file temp-require-file (insert coq-string)) (setq result (coq-seq-get-library-dependencies temp-require-file (concat "echo \"" coq-string "\" > " temp-require-file)))) (delete-file temp-require-file)) (if (stringp result) ;; Error handling: coq-seq-get-library-dependencies was not able to ;; translate module-id into a file name. We insert now a faked error ;; message into coq--compile-response-buffer to make next-error happy. (let ((error-message (format "Cannot find library %s in loadpath" module-id)) (inhibit-read-only t)) ;; Writing a message into coq--compile-response-buffer for next-error ;; does currently not work. We do have exact position information ;; about the span, but we don't know how much white space there is ;; between the start of the span and the start of the command string. ;; Check that coq--compile-response-buffer is a valid buffer! ;; (with-current-buffer coq--compile-response-buffer ;; (insert ;; (format "File \"%s\", line %d\n%s.\n" ;; (buffer-file-name (span-buffer span)) ;; (with-current-buffer (span-buffer span) ;; (line-number-at-pos (span-start span))) ;; error-message))) ;; (coq-display-compile-response-buffer) (error error-message))) (cl-assert (<= (length result) 1) "Internal error in coq-seq-map-module-id-to-obj-file") (car-safe result))) (defun coq-seq-check-module (coq-object-local-hash-symbol span module-id &optional from) "Locate MODULE-ID and compile if necessary. If `coq-compile-command' is not nil the whole task of checking which modules need compilation and the compilation itself is done by an external process. If `coq-compile-command' is nil ProofGeneral computes the dependencies with \"coqdep\" and compiles modules as necessary. This internal checking does currently not handle ML modules. Argument SPAN is the span of the \"Require\" command. Locked ancestors are registered in its 'coq-locked-ancestors property for proper unlocking on retract. Argument COQ-OBJECT-LOCAL-HASH-SYMBOL provides a place to store the coq-obj-hash, which is used during internal compilation (see `coq-seq-make-lib-up-to-date'). This way one hash will be used for all \"Require\" commands added at once to the queue." (let ((module-obj-file (coq-seq-map-module-id-to-obj-file module-id span from))) ;; coq-seq-map-module-id-to-obj-file currently returns () for ;; standard library modules! (when module-obj-file (if (> (length coq-compile-command) 0) (coq-seq-auto-compile-externally span module-id module-obj-file) (unless (symbol-value coq-object-local-hash-symbol) (set coq-object-local-hash-symbol (make-hash-table :test #'equal))) (coq-seq-make-lib-up-to-date (symbol-value coq-object-local-hash-symbol) span module-obj-file))))) (defun coq-seq-preprocess-require-commands () "Coq function for `proof-shell-extend-queue-hook'. If `coq-compile-before-require' is non-nil, this function performs the compilation (if necessary) of the dependencies." (when coq-compile-before-require (defvar coq-object-hash-symbol) (let (;; coq-object-hash-symbol serves as a pointer to the ;; coq-obj-hash (see coq-seq-make-lib-up-to-date). The hash ;; will be initialized when needed and stored in the value ;; cell of coq-object-hash-symbol. The symbol is initialized ;; here to use one hash for all the requires that are added now. ;; FIXME: Why not create the hash table eagerly here and ;; avoid the indirection (and avoid passing dynbound variable ;; names around)? (coq-object-hash-symbol nil)) (dolist (item queueitems) (let ((string (mapconcat 'identity (nth 1 item) " "))) (when (and string (string-match coq-require-command-regexp string)) (let ((span (car item)) (start (match-end 0)) (prefix (match-string 1 string))) (span-add-delete-action span (lambda () (coq-unlock-all-ancestors-of-span span))) (coq-compile-save-some-buffers) ;; now process all required modules (while (string-match coq-require-id-regexp string start) (setq start (match-end 0)) (coq-seq-check-module 'coq-object-hash-symbol span (match-string 1 string) prefix))))))))) (provide 'coq-seq-compile) ;; Local Variables: *** ;; coding: utf-8 *** ;; End: *** ;;; coq-seq-compile.el ends here PG-4.5/coq/coq-smie.el000066400000000000000000001725221426357011200145230ustar00rootroot00000000000000;;; coq-smie.el --- SMIE lexer, grammar, and indent rules for Coq -*- lexical-binding:t -*- ;; This file is part of Proof General. ;; Portions © Copyright 1994-2012 David Aspinall and University of Edinburgh ;; Portions © Copyright 2003-2021 Free Software Foundation, Inc. ;; Portions © Copyright 2001-2017 Pierre Courtieu ;; Portions © Copyright 2010, 2016 Erik Martin-Dorel ;; Portions © Copyright 2011-2013, 2016-2017 Hendrik Tews ;; Portions © Copyright 2015-2017 Clément Pit-Claudel ;; Authors: Pierre Courtieu ;; Stefan Monnier ;; Maintainer: Pierre Courtieu ;; SPDX-License-Identifier: GPL-3.0-or-later ;;; Commentary: ;; Lexer. ;; Due to the verycomplex grammar of Coq, and to the architecture of ;; smie, we deambiguate all kinds of tokens during lexing. This is a ;; complex piece of code but it allows for all smie goodies. ;; Some examples of deambigations: ;; - We distinguish ":=" from ":= inductive" to avoid the circular precedence ;; constraint ":= < | < ; < :=" where ":= < |" is due to Inductive ;; definitions, "| < ;" is due to tactics precedence, "; < :=" is due to ;; "let x:=3; y:=4 in...". ;; - We distinguish the ".-selector" from the terminator "." for ;; obvious reasons. ;; - We consider qualified.names as one single token for obvious reasons. ;; - We distinguish the "Module M." from "Module M := exp." since the first ;; opens a new scope (closed by End) whereas the other doesn't. ;; - We drop "Program" because it's easier to consider "Program Function" ;; as a single token (which behaves like "Function" w.r.t indentation and ;; parsing) than to get the parser to handle it correctly. ;; - We identify the different types of bullets (First approximation). ;; - We distinguish "with match" from other "with". ;;; Code: (require 'coq-indent) (require 'coq-syntax) ;For coq-keywords-save-strict! (require 'smie) ; debugging ;(defmacro measure-time (&rest body) ; "Measure the time it takes to evaluate BODY." ; `(let ((time (current-time))) ; ,@body ; (message "%.06f" (float-time (time-since time))))) (defcustom coq-smie-monadic-tokens '((";;" . ";; monadic")("do" . "let monadic")("<-" . "<- monadic")(";" . "in monadic")); "This contains specific indentation token pairs, similar to `coq-smie-user-tokens' but dedicated to monadic operators. These tokens have no builtin syntax except the one defined by this variable so that users can change the syntax at will. The default value supports ext-lib (x <- e ;; e) and CompCert (do x <- e ; e) styles. There are two types of monadic syntax with specific tokens: one with a starting token (like do): \"let monadic\" E \"<- monadic\" E \"in monadic\" E and the other without: E \"<- monadic\" E \";; monadic\" E Th goal of this variable is to give concrete syntax to these \"xxx monadic\" tokens." :type '(alist :key-type string :value-type string) :group 'coq) (defcustom coq-smie-user-tokens nil "Alist of (syntax . token) pairs to extend the coq smie parser. These are user configurable additional syntax for smie tokens. It allows to define alternative syntax for smie token. Typical example: if you define a infix operator \"xor\" you may want to define it as a new syntax for token \"or\" in order to have the indentation rules of or applied to xor. Other exemple: if you want to define a new notation \"ifb\" ... \"then\" \"else\" then you need to declare \"ifb\" as a new syntax for \"if\" to make indentation work well. An example of cofiguration is: (setq coq-smie-user-tokens '((\"xor\" . \"or\") (\"ifb\" . \"if\"))) to have token \"xor\" and \"ifb\" be considered as having repectively same priority and associativity as \"or\" and \"if\". For monadic notations, see `coq-smie-monadic-tokens' instead." :type '(alist :key-type string :value-type string) :group 'coq) (defalias 'coq--string-suffix-p ;; Replacement for emacs < 24.4, borrowed from sindikat at ;; stackoverflow efficient if bytecompiled, builtin version is ;; probably better when it exists (if (fboundp 'string-suffix-p) 'string-suffix-p (lambda (str1 str2 &optional ignore-case) "Return non-nil if STR1 is a prefix of STR2. If IGNORE-CASE is non-nil, the comparison is done without paying attention to case differences." (let ((begin2 (- (length str2) (length str1))) (end2 (length str2))) (when (< begin2 0) (setq begin2 0)) ; to avoid negative begin2 (eq t (compare-strings str1 nil nil str2 begin2 end2 ignore-case)))))) ;; As any user defined notation ending with "." will break ;; proofgeneral synchronization anyway, let us consider that any ;; combination of symbols ending with "." is an end of command for ;; indentation purposes. One noticeable exception is .. that may ;; happen inside notations and is dealt with by pg synchro. (defun coq-dot-friend-p (s) (and (not (string-equal ".." s)) ;; string-equal because ... should return t. (string-match "[^[:word:]]\\.\\'" s))) ; for debuging (defun coq-time-indent () (interactive) (let ((deb (float-time))) (smie-indent-line) (message "time: %S"(- (float-time) deb)))) (defun coq-time-indent-region (beg end) (interactive "r") (let ((deb (float-time))) (indent-region beg end nil) (message "time: %S"(- (float-time) deb)))) (defun coq-is-inside-enclosing (bound) (save-excursion ;; This may fail but we need to see where we stopped (coq-smie-search-token-backward '("#dummy#" "{") bound) (if (= (point) bound) nil ; we did not cross som paren-like (let ((backtok (coq-smie-backward-token))) (cond ((and (string-equal "" backtok) (eq ?| (char-after))(eq ?{ (char-before))) "{|") ((not (string-equal backtok "")) backtok) (t (char-to-string (char-before)))))))) ;; Fragile: users can define tactics with uppercases... Returns t if ;; we are inside a tactic and not inside a record notation. Ideally we ;; would like to know if the interpretation scope is term or tactic ;; (i.e. detect if we are inside a term inside a tactic) but this is ;; almost impossible sytntactically: how to tell the difference ;; between tactics and tacticals? In "repeat (f x)" and "apply (f x)" ;; f x is a tactic (resp. a terms). Only Coq knows, we could analyse ;; coq grammar tacticals. This is not too problematic here since only ;; in records the indentation changes (maily for ";"). (defun coq-smie-is-tactic () (let* (;; (pos (point)) (cmdstrt (save-excursion (coq-find-real-start))) (enclosing (coq-is-inside-enclosing cmdstrt))) (cond ((string-equal enclosing "{|") nil) ;; only records ((and enclosing (string-match "{" enclosing)) nil) ;; more agressive: record-like notations (t (save-excursion (goto-char cmdstrt) (let ((case-fold-search nil)) (not (looking-at "[[:upper:]]")))))))) (defun coq-smie-is-ltacdef () (let ((case-fold-search nil)) (save-excursion (coq-find-real-start) (looking-at "\\(\\(Local\\|Global\\)\\s-+\\)?\\(Ltac2?\\|Tactic\\s-+Notation\\)\\s-")))) (defun coq-smie-is-inside-parenthesized-tactic () (and (coq-smie-is-tactic) ;; fragile (uppercase test only) (save-excursion (let ((pt (point)) ;; we need to go one character forwardto avoid the ;; coq-smie-search-token-backward below to fail on "{" (strt (and (coq-script-parse-cmdend-backward) (+ 1 (point))))) (goto-char pt) ;; looking for a dummy token to see if we fail before reaching ;; strt, which means that we were in a prenthesized expression. (coq-smie-search-token-backward '("#dummy#") strt) (> (point) strt))))) (defun coq-smie-.-deambiguate () "Return the token of the command terminator of the current command. For example in: Proof. or Proof with ... . the token of the \".\" is \". proofstart\". But in intros. or Proof foo. the token of \".\" is simply \".\"." (save-excursion (let ((p (point))) (coq-find-real-start) ; Move to real start of command. (cond ((looking-at "BeginSubproof\\>") ". proofstart") ((looking-at "Proof\\>") (forward-char 5) (forward-comment (point-max)) (if (looking-at "\\.\\|with\\|using") ". proofstart" ".")) ((or (looking-at "Next\\s-+Obligation\\>") (coq-smie-detect-goal-command)) (save-excursion (goto-char (+ p 1)) (let ((tok (smie-default-forward-token))) (cond ;; If the next token is "Proof", then the current command does ;; introduce a proof, but the user opted to use the explicit ;; "Proof" command, so the current command doesn't itself start ;; the proof. ((equal tok "Proof") ".") ;; If the next command is a new definition, then the current ;; command didn't actually start a proof! ((member tok '("Let" "Definition" "Inductive" "Fixpoint")) ".") (t ". proofstart"))))) ((equal (coq-smie-module-deambiguate) "Module start") ". modulestart") (t "."))))) (defun coq-smie-complete-qualid-backward () "Return the qualid finishing at the current point." (let ((p (point))) (re-search-backward "[^.[:alnum:]_@]") (forward-char 1) (buffer-substring (point) p))) (defun coq-smie-find-unclosed-match-backward () (let ((tok (coq-smie-search-token-backward '("with" "match" "lazymatch" "multimatch" "lazy_match" "mult_match" ".")))) (cond ((null tok) nil) ((equal tok ".") nil) ((equal tok "with") (coq-smie-find-unclosed-match-backward) (coq-smie-find-unclosed-match-backward)) (t t) ;; all variants of match ))) ;; point supposed to be at start of the "with" (defun coq-smie-with-deambiguate() (let ((p (point))) (if (coq-smie-find-unclosed-match-backward) "with match" (goto-char p) (coq-find-real-start) (cond ((looking-at "\\(Co\\)?Inductive") "with inductive") ((looking-at "\\(Co\\)?Fixpoint\\|Function\\|Program\\|Lemma") "with fixpoint") ((looking-at "Module\\|Declare") "with module") (t "with"))))) ;; A variant of smie-default-backward-token that recognize "." and ";" ;; as single token even if glued at the end of another symbols. (defun coq-backward-token-fast-nogluing-dot-friends () (forward-comment (- (point))) (let* ((pt (point)) (tok-punc (skip-syntax-backward ".")) (str-punc (buffer-substring-no-properties pt (point)))) (if (zerop tok-punc) (skip-syntax-backward "w_'")) ;; Special case: if the symbols found end by "." or ";", ;; then consider this last letter alone as a token (when (and (not (zerop tok-punc)) (string-match "\\s.+[.;]" str-punc)) (skip-syntax-forward ".") (forward-char -1)) (buffer-substring-no-properties pt (point)))) (defun coq-forward-token-fast-nogluing-dot-friends () (forward-comment (point-max)) (let* ((pt (point)) (tok-punc (skip-syntax-forward ".")) (str-punc (buffer-substring-no-properties pt (point)))) (if (zerop tok-punc) (skip-syntax-forward "w_'")) ;; Special case: if the symbols found end by "." or ";", ;; then consider this last letter alone as a token (when (and (not (zerop tok-punc)) (string-match "\\s.+[.;]" str-punc)) (forward-char -1)) (buffer-substring-no-properties pt (point)))) ;; ignore-between is a description of pseudo delimiters of blocks that ;; should be jumped when searching. There is a bad interaction when ;; tokens and ignore-bteween are not disjoint (defun coq-smie-search-token-forward (tokens &optional end ignore-between) "Search for one of TOKENS between point and END. If some enclosing parenthesis is reached, stop there and return nil. Token \".\" is considered only if followed by a space. Optional IGNORE-BETWEEN defines opener/closer to ignore during search. Careful: the search for a opener stays inside the current command (and inside parenthesis)." (unless end (setq end (point-max))) (condition-case nil (catch 'found (while (< (point) end) ;; The default lexer is faster and is good enough for our needs. (let* ((next (coq-forward-token-fast-nogluing-dot-friends)) (parop (assoc next ignore-between))) ; if we find something to ignore, we directly jump to the ; corresponding closer (if parop (let ((parops ; corresponding matcher may be a list (if (listp parop) (cdr parop) (cons (cdr parop) nil)))) ; go to corresponding closer (when (member (coq-smie-search-token-forward (append parops (cons "." nil)) end ignore-between) (cons "." nil)) (goto-char (point)) next)) ;; Do not consider "." when not followed by a space (when (or (not (equal next ".")) ; see backward version (looking-at "[[:space:]]")) (cond ((and (zerop (length next)) (or (equal (point) (point-max)) ; protecting char-after next line (equal (char-syntax ?\)) (char-syntax (char-after))))) (throw 'found nil)) ((zerop (length next)) ;; capture other characters than closing parent ;; don't use smmie-forward-sexp here (let ((forward-sexp-function nil)) (forward-sexp 1))) ((member next tokens) (throw 'found next)))))))) (scan-error nil))) ;; ignore-between is a description of pseudo delimiters of blocks that ;; should be jumped when searching. There is a bad interaction when ;; tokens and ignore-bteween are not disjoint (defun coq-smie-search-token-backward (tokens &optional end ignore-between) "Search for one of TOKENS between point and END. If some enclosing parenthesis is reached, stop there and return nil. Token \".\" is considered only if followed by a space. optional IGNORE-BETWEEN defines opener/closer to ignore during search. Careful: the search for a opener stays inside the current command (and inside parenthesis)." (unless end (setq end (point-min))) (condition-case nil (catch 'found (while (> (point) end) ;; The default lexer is faster and is good enough for our needs. (let* ((next (coq-backward-token-fast-nogluing-dot-friends)) (parop (rassoc next ignore-between))) ; if we find something to ignore, we directly jump to the ; corresponding openner (if parop (let ((parops ; corresponding matcher may be a list (if (listp (car parop)) (car parop) (cons (car parop) nil)))) ; go to corresponding closer or meet "." (coq-smie-search-token-backward ;; Add "." at the head of the list, since ;; it's more efficient and ordering is ignored anyway. (cons "." parops) end ignore-between)) ;; Do not consider "." when not followed by a space ;(message "SPACE?: %S , %S , %S" next next (looking-at ".[[:space:]]")) (when (or (not (equal next ".")) (looking-at "\\.[[:space:]]")) (cond ((and (zerop (length next)) (or (equal (point) (point-min)) ; protecting char-before next line (equal (char-syntax ?\() (char-syntax (char-before))))) (throw 'found nil)) ((zerop (length next)) ;; don't use smmie-forward-sexp here (let ((forward-sexp-function nil)) (forward-sexp -1))) ((member next tokens) (throw 'found next)))))))) (scan-error nil))) (defun coq-lonely-:=-in-this-command () "Return t if there is a lonely \":=\" from (point) to end of command. Non lonely \":=\" are those corresponding to \"let\" or \"with\" (module declaration) or those inside parenthesis. this function is used to detect whether a command is a definition or a proof-mode starter in Coq." (equal (coq-smie-search-token-forward '("." ":=") nil '(("with" . (":=" "signature")) ("let" . "in"))) ".")) ;; Heuristic to detect a goal opening command: there must be a lonely ;; ":=" until command end. ;; \\|\\(Declare\\s-+\\)?Instance is not detected as it is not ;; syntactically decidable to know if some goals are created. Same for ;; Program Fixpoint but with Program Next Obligation is mandatory for ;; each goal anyway. (defun coq-smie-detect-goal-command () "Return t if the next command is a goal starting to be indented. The point should be at the beginning of the command name. As false positive are more annoying than false negative, return t only if it is FOR SURE a goal opener. Put a \"Proof.\" when you want to force indentation." (save-excursion ; FIXME add other commands that potentialy open goals (let ((case-fold-search nil)) (when (looking-at "\\(Local\\|Global\\)?\ \\(Definition\\|Lemma\\|Theorem\\|Fact\\|Let\\|Class\ \\|Proposition\\|Remark\\|Corollary\\|Goal\ \\|Add\\(\\s-+Parametric\\)?\\s-+Morphism\ \\|Fixpoint\\)\\>") ;; Yes Fixpoint can start a proof like Definition (coq-lonely-:=-in-this-command))))) ;; Heuristic to detect a goal opening command: there must be a lonely ":=" (defun coq-smie-module-deambiguate () "Return t if the next command is a goal starting command. The point should be at the beginning of the command name." (save-excursion ; FIXME Is there other module starting commands? (let ((case-fold-search nil)) (cond ((looking-back "with\\s-+" nil) "module nodecl") ; Module that is not a declaration keyword (like in with Module) ((looking-at "\\(Module\\|Section\\)\\>") (if (coq-lonely-:=-in-this-command) "Module start" "Module def")))))) ;(defun coq-smie-detect-module-or-section-start-command () ; "Return t if the next command is a goal starting command. ;The point should be at the beginning of the command name." ; (save-excursion ; FIXME Is there other module starting commands? ; (when (and (looking-back "with") ; (proof-looking-at "\\(\\(?:Declare\\s-+\\)?Module\\|Section\\)\\>")) ; (coq-lonely-:=-in-this-command)))) (defconst coq-smie-proof-end-tokens ;; '("Qed" "Save" "Defined" "Admitted" "Abort") (cons "EndSubproof" (remove "End" coq-keywords-save-strict))) (defun coq-is-at-command-real-start() (equal (point) (save-excursion (coq-find-real-start)))) (defun coq-is-bullet-token (tok) (coq--string-suffix-p "bullet" tok)) (defun coq-is-subproof-token (tok) (coq--string-suffix-p "subproof" tok)) (defun coq-is-dot-token (tok) (or (coq--string-suffix-p "proofstart" tok) (string-equal "." tok))) (defun coq-is-cmdend-token (tok) (or (coq-is-bullet-token tok) (coq-is-subproof-token tok) (coq-is-dot-token tok))) ;; Standard synonyms are better here than in the coq-smie-xxxward-token-aux functions. (defconst coq-standard-token-synonyms '( ("SuchThat" . ":") ("As" . ":= def") ;; For "Derive foo SuchThat bar As oof". )) (defun coq-smie-forward-token () (let ((tok (coq-smie-forward-token-aux))) (cond ((assoc tok coq-smie-user-tokens) (let ((res (assoc tok coq-smie-user-tokens))) (cdr res))) ((assoc tok coq-smie-monadic-tokens) (let ((res (assoc tok coq-smie-monadic-tokens))) (cdr res))) ((assoc tok coq-standard-token-synonyms) (let ((res (assoc tok coq-standard-token-synonyms))) (cdr res))) (tok)))) (defun coq-smie-forward-token-aux () (let ((tok (smie-default-forward-token))) (cond ;; @ may be ahead of an id, it is part of the id. ((and (equal tok "@") (looking-at "[[:alpha:]_]")) (let ((newtok (coq-smie-forward-token))) ;; recursive call (concat tok newtok))) ;; detecting if some qualification (dot notation) follows that id and ;; extend it if yes. Does not capture other alphanumerical token (captured ;; below) ((and (string-match "@?[[:alpha:]_][[:word:]]*" tok) (looking-at "\\.[[:alpha:]_]") (progn (forward-char 1) (let ((newtok (coq-smie-forward-token))) ; recursive call (concat tok "." newtok))))) ((member tok '("." "...")) ;; swallow if qualid, call backward-token otherwise (cond ((member (char-after) '(?w ?_)) ;(looking-at "[[:alpha:]_]") ;; extend qualifier (let ((newtok (coq-smie-forward-token))) ;; recursive call (concat tok newtok))) (t (save-excursion (coq-smie-backward-token))))) ;; recursive call ((or (string-match coq-bullet-regexp-nospace tok) (member tok '("=>" ":=" "::=" "exists" "in" "as" "∀" "∃" "→" "∨" "∧" ";" "," ":" "eval" "return"))) ;; The important lexer for indentation's performance is the backward ;; lexer, so for the forward lexer we delegate to the backward one when ;; we can. (save-excursion (coq-smie-backward-token))) ;; match needs to be catpured now to avoid being catpured by "Com start" ((member tok '("match" "lazymatch" "lazy_match" "multimatch" "multi_match")) "match") ;; detect "with signature", otherwies use coq-smie-backward-token ((equal tok "with") (let ((p (point))) (if (equal (smie-default-forward-token) "signature") "with signature" (goto-char p) (save-excursion (coq-smie-backward-token))))) ((member tok '("transitivity" "symmetry" "reflexivity")) (let ((p (point))) (if (and (equal (smie-default-forward-token) "proved") (equal (smie-default-forward-token) "by")) "xxx provedby" (goto-char p) tok))) ; by tactical ((member tok '("Module")) ; TODO: Declare (let ((pos (point)) (next (smie-default-forward-token))) (unless (equal next "Type") (goto-char pos)) (save-excursion (coq-smie-backward-token)))) ((member tok '("End")) (save-excursion (coq-smie-backward-token))) ((member tok '("do")) (save-excursion (coq-smie-backward-token-aux))) ; empty token if a prenthesis is met. ((and (zerop (length tok)) (looking-at "{|")) (goto-char (match-end 0)) "{|") ;; this must be after detecting "{|": ((and (zerop (length tok)) (eq (char-after) ?\{)) (if (equal (save-excursion (forward-char 1) (coq-smie-backward-token)) "{ subproof") (progn (forward-char 1) "{ subproof") tok)) ((and (zerop (length tok)) (eq (char-after) ?\})) (if (equal (save-excursion (forward-char 1) (coq-smie-backward-token)) "} subproof") (progn (forward-char 1) "} subproof") tok)) ((and (equal tok "|") (eq (char-after) ?\})) (goto-char (1+ (point))) "|}") ((member tok coq-smie-proof-end-tokens) "Proof End") ((member tok '("Obligation")) "Proof") ;; FIXME: this case should be useless now that we replace ;; smie-default-forward... by a smarter function. ((coq-dot-friend-p tok) ".") ;; Try to rely on backward-token for non empty tokens: bugs (hangs) ;; ((not (zerop (length tok))) (save-excursion (coq-smie-backward-token))) ;; Com start is a token for the first word of a command (provided it is a word) ((save-excursion (and (smie-default-backward-token) (coq-is-at-command-real-start) (> (length tok) 0) (or (string= "Lu" (get-char-code-property (aref tok 0) 'general-category)) (string= "Ll" (get-char-code-property (aref tok 0) 'general-category))))) "Com start") ;; return it. (tok) ))) (defun coq-is-at-def () ;; This is very approximate and should be used with care (let ((case-fold-search nil)) (looking-at coq-command-defn-regexp))) (defun coq-is-at-def-or-decl () ;; This is very approximate and should be used with care (let ((case-fold-search nil)) (or (looking-at coq-command-defn-regexp) (looking-at coq-command-decl-regexp)))) ;; ":= with module" is really to declare some sub-information ":= ;; with" is for mutual definitions where both sides are of the same ;; level (defun coq-smie-:=-deambiguate () (let* (;; (orig (point)) (cmdstrt (save-excursion (coq-find-real-start))) (corresp (coq-smie-search-token-backward '("let" "Inductive" "CoInductive" "{|" "." "with" "Module" "where" "Equations") cmdstrt '((("let" "with") . ":="))))) (cond ((member corresp '("Equations")) ":= equations") ((equal corresp "with") (let ((corresptok (coq-smie-with-deambiguate))) (cond ;; recursive call if the with found is actually et with match ((equal corresptok "with match") (coq-smie-:=-deambiguate)) ((equal corresptok "with inductive") ":= inductive") ((equal corresptok "with module") ":= with module") (t ":=") ))) ((equal corresp "Module") (let ((p (point))) (if (equal (smie-default-backward-token) "with") ":= with module" (goto-char p) ":= module"))) ((member corresp '("Inductive" "CoInductive" "Variant")) ":= inductive") ((equal corresp "let") ":= let") ((equal corresp "where") ":= inductive") ;; inductive or fixpoint, nevermind ((or (eq ?\{ (char-before))) ":= record") ((equal (point) cmdstrt) ;; we reached the command start: either we were in an Equation, ;; or the ":=" was inpatter of an Ltac match (pattern the form ;; "| H: T := t |- _"). Toherwise we are probably in a Definition. (if (or (looking-at "Equations\\|match\\|let")) ":=" ":= def")) (t ":=")))) (defun coq-smie-semicolon-deambiguate () (let* (;; (pos (point)) (cmdstrt (save-excursion (coq-find-real-start))) (istac (or (coq-smie-is-tactic) (coq-smie-is-ltacdef) (coq-smie-is-inside-parenthesized-tactic))) (enclosing (coq-is-inside-enclosing cmdstrt))) (cond (istac "; tactic") ;; looking for a dummy token to see if we fail before reaching ;; strt, which means that we were in a prenthesized expression. ((string-equal enclosing "{ subproof") "; tactic") ((member enclosing '("{" "{|")) "; record") (t (if (save-excursion (goto-char cmdstrt) (looking-at "Equations")) "; equations" ";"))))) (defun coq-smie-backward-token () (let ((tok (coq-smie-backward-token-aux))) (cond ((assoc tok coq-smie-user-tokens) (let ((res (assoc tok coq-smie-user-tokens))) (cdr res))) ((assoc tok coq-smie-monadic-tokens) (let ((res (assoc tok coq-smie-monadic-tokens))) (cdr res))) ((assoc tok coq-standard-token-synonyms) (let ((res (assoc tok coq-standard-token-synonyms))) (cdr res))) (tok)))) (defun coq-smie-backward-token-aux () (let* ((tok (smie-default-backward-token))) (cond ;; Distinguish between "," from quantification and other uses of ;; "," (tuples, tactic arguments) ;; we cannot distinguish between tuples and tac args, because of: ;; an term (f x , v) and a tactic expecting a tuple (tac x , v) ((equal tok ",") (save-excursion (let ((backtok (coq-smie-search-token-backward '("forall" "∀" "∃" "exists" "|" "match" "lazymatch" "multimatch" "lazy_match" "multi_match" ".")))) (cond ((member backtok '("forall" "∀" "∃")) ", quantif") ((equal backtok "exists") ; there is a tactic called exists (if (equal (coq-smie-forward-token) ;; recursive call "quantif exists") ", quantif" tok)) (t tok))))) ; Same for ";" : record field separator, tactic combinator, etc ((equal tok ";") (save-excursion (coq-smie-semicolon-deambiguate))) ;; trying to discriminate between bollean operator || and tactical ||. ((equal tok "||") (save-excursion (let ((backtok (coq-smie-search-token-backward '("." ";" "Ltac" "Ltac2" "(" "[" "{")))) (cond ((member backtok '("." "Ltac" "Ltac2")) "|| tactic") ((and (equal backtok ";") (or (forward-char) t) (equal (coq-smie-backward-token) "; tactic")) ;; recursive "|| tactic") ;; this is wrong half of the time but should not harm indentation ((and (equal backtok nil) (eq (char-before) '?\()) "||") ((equal backtok nil) (if (or (eq (char-before) '?\[) (and (eq (char-before) '?\{) (equal (coq-smie-backward-token) "{ subproof"))) ;; recursive call "|| tactic" "||")))))) ;; This may be part of monadic notation, so detect other uses of "do". ((equal tok "do") (save-excursion (forward-char 2) (smie-default-forward-token) (smie-default-backward-token) (if (looking-at "[0-9]") "do ltac" "do"))) ; Same for "->" : rewrite or intro arg or term's implication ; FIXME: user defined arrows will be considered a term ((equal tok "->") (save-excursion (let ((backtok (coq-smie-search-token-backward '("intro" "intros" "rewrite" ".")))) (cond ((equal backtok ".") "->") ((equal backtok nil) "->") (t "-> tactic"))))) ;; "<-" is a commonly used token for monadic notations, we should ;; discrimnate between "rewrite ... <-" and other uses of "<-". ((equal tok "<-") (save-excursion (let ((backtok (coq-smie-search-token-backward '("intro" "intros" "rewrite" ".")))) (cond ((equal backtok ".") "<-") ((equal backtok nil) "<-") (t "<- tactic"))))) ((equal tok "Module") (save-excursion ;(coq-find-real-start) (coq-smie-module-deambiguate))) ;; match needs to be catpured now to avoid being catpured by "Com start" ((member tok '("match" "lazy_match" "lazymatch" "multi_match" "multimatch")) "match") ((equal tok "tryif") "if") ;; rhaaa... Some peolple use "End" as a id... ((equal tok "End") (if (coq-is-at-command-real-start) "end module" tok)) ;; FIXME: this is a parenthesis ((and (equal tok "|") (eq (char-before) ?\{)) (goto-char (1- (point))) "{|") ;; curly braces can be beginproof/endproof or record stuff. ((and (zerop (length tok)) (member (char-before) '(?\{ ?\})) (save-excursion (forward-char -1) (if (and (looking-at "{") (looking-back "\\(\\[?\\w+\\]?\\s-*:\\s-*\\)" nil t)) (goto-char (match-beginning 0))) (let ((nxttok (coq-smie-backward-token))) ;; recursive call (coq-is-cmdend-token nxttok)))) (forward-char -1) (if (looking-at "}") "} subproof" (if (and (looking-at "{") (looking-back "\\(\\[?\\w+\\]?\\s-*:\\s-*\\)" nil t)) (goto-char (match-beginning 0))) "{ subproof" )) ;; ((and (zerop (length tok)) (member (char-before) '(?\{ ?\})) ;; (save-excursion ;; (forward-char -1) ;; (let ((nxttok (coq-smie-backward-token))) ;; recursive call ;; (coq-is-cmdend-token nxttok)))) ;; (forward-char -1) ;; (if (looking-at "{") "{ subproof" "} subproof")) ((and (equal tok ":") (looking-back "\\<\\(constr\\|ltac2?\\|uconstr\\)" (- (point) 7))) ": ltacconstr") ((member tok '(":=" "::=")) (save-excursion (save-excursion (coq-smie-:=-deambiguate)))) ((equal tok "=>") (save-excursion (let ((corresp (coq-smie-search-token-backward '("|" "match" "lazymatch" "multimatch" "lazy_match" "multi_match" "fun" ".") nil '((("match" "lazy_match" "multi_match") . "end") ("fun" . "=>"))))) (cond ((member corresp '("fun")) "=> fun") ; fun (t tok))))) ;; FIXME: no token should end with "." except "." itself ; for "unfold in *|-*." ((member tok '("*." "-*." "|-*." "*|-*.")) (forward-char (- (length tok) 1)) (coq-smie-.-deambiguate)) ; for "unfold in *|-*;" ((member tok '("*;" "-*;" "|-*;" "*|-*;")) ;; FIXME; can be "; ltac" too (forward-char (- (length tok) 1)) "; tactic") ;; bullet detected, is it really a bullet? we have to traverse ;; recursively any other bullet or "n:{" "}". this is the work of ;; coq-empty-command-p ((and (string-match coq-bullet-regexp-nospace tok) (save-excursion (coq-empty-command-p))) (concat tok " bullet")) ((and (member tok '("exists" "∃")) (save-excursion ;; recursive call looking at the ptoken immediately before (let ((prevtok (coq-smie-backward-token))) ;; => may be wrong here but rare (have "=> ltac"?) (not (or (coq-is-cmdend-token prevtok) (member prevtok '("; tactic" "[" "]" "|" "=>"))))))) "quantif exists") ((equal tok "∀") "forall") ((equal tok "→") "->") ((equal tok "∨") "\\/") ((equal tok "∧") "/\\") ((equal tok "with") ; "with" is a nightmare: at least 4 different uses (save-excursion (coq-smie-with-deambiguate))) ((equal tok "where") "where") ((and (equal tok "signature") (equal (smie-default-backward-token) "with")) "with signature") ((equal tok "by") (let ((p (point))) (if (and (equal (smie-default-backward-token) "proved") (member (smie-default-backward-token) '("transitivity" "symmetry" "reflexivity"))) "xxx provedby" (goto-char p) tok))) ; by tactical ((equal tok "as") (save-excursion (let ((prev-interesting (coq-smie-search-token-backward '("match" "lazymatch" "multimatch" "lazy_match" "multi_match" "Morphism" "Relation" "." ". proofstart" "{ subproof" "} subproof" "as") nil '((("match" "lazy_match" "multi_match" "let") . "with") ("with" . "signature"))))) (cond ((member prev-interesting '("match" "lazymatch" "multimatch" "lazy_match" "mult_match")) "as match") ((member prev-interesting '("Morphism" "Relation")) "as morphism") (t tok))))) ((equal tok "return") (save-excursion (let ((prev-interesting (coq-smie-search-token-backward '("match" "lazymatch" "multimatch" "lazy_match" "multi_match" "Morphism" "Relation" "." ". proofstart") nil '((("match" "lazy_match" "multi_match" "let") . "with") ("with" . "signature"))))) (cond ((member prev-interesting '("match" "lazymatch" "multimatch" "lazy_match" "mult_match")) "return match") (t tok))))) ((equal tok "by") (let ((p (point))) (if (and (equal (smie-default-backward-token) "proved") (member (smie-default-backward-token) '("transitivity" "symmetry" "reflexivity"))) "xxx provedby" (goto-char p) tok))) ; by tactical ((equal tok "eval") (if (member (save-excursion (forward-char 4) (smie-default-forward-token)) '("red" "hnf" "compute" "simpl" "cbv" "lazy" "unfold" "fold" "pattern")) "eval in" tok)) ((equal tok "in") (save-excursion (let ((prev-interesting (coq-smie-search-token-backward '("let" "match" "lazymatch" "multimatch" "lazy_match" "mult_match" ;"eval" should be "eval in" but this is not supported by search-token-backward "." ) nil '((("match" "lazymatch" "multimatch" "lazy_match" "mult_match") . "with") (("let") ;"eval" . "in"))))) (cond ((member prev-interesting '("." nil)) "in tactic") ((equal prev-interesting "let") "in let") ;((equal prev-interesting "eval in") "in eval"); not detectable by coq-smie-search-token-backward ((equal prev-interesting "match") "in match") (t "in tactic"))))) ((and (eq (char-before) ?@) (member (char-syntax (char-after)) '(?w ?_))) (forward-char -1) (concat "@" tok)) ((member tok coq-smie-proof-end-tokens) "Proof End") ((member tok '("." "...")) ;; Distinguish field-selector "." from terminator "." from module ;; qualifier. (let ((nxtnxt (char-after (+ (point) (length tok))))) (if (eq nxtnxt ?\() ". selector" (if (eq nxtnxt ?}) ;; dot immediately followed by closesubproof. "." (if (or (null nxtnxt) (eq (char-syntax nxtnxt) ?\ )) ;; command terminator: ". proofstart" et al (save-excursion (forward-char (- (length tok) 1)) (coq-smie-.-deambiguate)) (cond ((eq (char-syntax nxtnxt) ?w) (let ((newtok (coq-smie-complete-qualid-backward))) ;; qualified name (concat newtok tok))) (t ". selector"))))))) ;; probably a user defined syntax ((and (and (eq (char-before) ?.) (member (char-syntax (char-after)) '(?w ?_)))) (forward-char -1) (let ((newtok (coq-smie-backward-token))) ; recursive call (concat newtok "." tok))) ((member tok '("lazymatch" "lazy_match" "multimatch" "multi_match")) "match") ((coq-dot-friend-p tok) ".") ;; Default fallback for words at command start position: We use a ;; generic "Com start" token, so that everything in the command ;; is considered a child of this token. This makes indentation ;; never look above the current command start (unless indenting ;; the first line of the command). For now we only apply this to ;; things starting with a letter, because the grammar makes use ;; of non letters token and this would hide them. Other ;; exception: Ltac things like "match" and "let' that need to be ;; recognized as such by the grammar. ((and (coq-is-at-command-real-start) (> (length tok) 0) (not (member tok '("match" "lazymatch" "let"))) ;; match are already captured (or (string= "Lu" (get-char-code-property (aref tok 0) 'general-category)) (string= "Ll" (get-char-code-property (aref tok 0) 'general-category)))) "Com start") (tok)))) (defcustom coq-indent-box-style nil "If non-nil, Coq mode will try to indent with a box style (SMIE code only). Box style looks like this: Lemma foo: forall n, n = n. instead of: Lemma foo: forall n, n = n." :type 'boolean :group 'coq) (make-variable-buffer-local 'coq-indent-box-style) (defun coq-indent-safep (indent) (>= indent 0)) (defcustom coq-indent-proofstart 2 "Number of spaces used to indent after a proof start." :type 'integer :group 'coq :safe #'coq-indent-safep) (defcustom coq-indent-semicolon-tactical 2 "Number of spaces used to indent after the 1st tactical semicolon of a serie. If set to 0, indentation is as follows: tac1; tac2; tac3; tac4. If set to 2 (default): tac1; tac2; tac3; tac4." :type 'integer :group 'coq :safe #'coq-indent-safep) (defcustom coq-indent-modulestart 2 "Number of spaces used to indent after a module or section start." :type 'integer :group 'coq :safe #'coq-indent-safep) (defcustom coq-smie-after-bolp-indentation 2 "Number of spaces used to indent after a quantifier *not* on its own line. the number of space is meant \"from the column on which the quantifier would be if it were on its own line\". for example, if set to 0 the indentation is as follows: Lemma foo: forall x:nat, x <= 0 -> x = 0. If it is set to 2 (default) it is as follows: Lemma foo: forall x:nat, x <= 0 -> x = 0." :type 'integer :group 'coq :safe #'coq-indent-safep) (defcustom coq-match-indent 2 "Number of space used to indent cases of a match expression. If the \"|\" separator is used, indentation will be reduced by 2. For example the default value 2 makes indetation like this: match n with O => ... | S n => ... end Typical values are 2 or 4." :type 'integer :group 'coq :safe #'coq-indent-safep) ;; smie grammar. General Remarks. ;; 1. One oddity (a standard one IIUC) is that the "command end token" ;; is considerd a separator. So any command is the child of the ;; previous one. This may lead to strange things wrt to indentation if ;; we don't take care. For instance the following script ;:; ;; Com1 .(1) ;; Definition foo := bar .(2) ;; ... ;; could easily lead to the grammar tree ;; ;; __.(2) ;; .(1) \ ;; / \ ... ;; / \ ;; Com1 := ;; / \ ;; Def foo bar ;; ;; which means that "(1)" is the parent of ":=", which is the parent ;; of "Def foo". This leads to hell. We need Def to be the parent. But ;; there are hundreds of commands in coq. so we adopt the policy below. ;; ;; 2. the lexer tries to always treat the first word of a command as a ;; dstinguished token "Com start". And a command is of the form ("Com ;; start" exp) in smie grammar. This way the top-node of a command is ;; always this token. ;; ;; This way the above script is parsed as: ;; ;; __.(2) ;; .(1) \ ;; / \ ... ;; / \ ;; Com1 Com start ;; | ;; := ;; / \ ;; foo bar ;; ;; which is much better. Indenting *inside* a command never looks ;; above its own "Com start". This makes indentation rules much ;; simpler, and hopefully speeds up things too since in practice it ;; means indentation never inspect too far. ;; ;; 3. The only exception to "Com start" token at command start is ;; structuring commands like "Proof" "Module", "{ subproof", bullets, ;; goal selectors. ;; ;; 4. All non-word tokens (in particular bullets) are also not seen as ;; "Com start". Thus user-defined commands (or tactics) starting with ;; a non-word token will probably break indentation. ;; ;; 5. KNOWN BUGS: This does not know about Notations, but users can ;; add new syntax for already defined tokens. ;; ;; 6. BUGS: probably dozens of. ;; ;; TODO: factorize infix operators into a series of "opxx" where "xx" ;; is the coq grammar priority. users could then add there own infix ;; operators in a consistent way. (defconst coq-smie-grammar (smie-prec2->grammar (smie-bnf->prec2 '((exp (exp ":= equations" exp) (exp ":= def" exp) (exp ":=" exp) (exp ":= inductive" exp) (exp "||" exp) (exp "|" exp) (exp "=>" exp) (exp "; equations" exp) (exp "xxx provedby" exp) (exp "as morphism" exp) (exp "with signature" exp) ("match" matchexp "with match" exp "end") ;expssss ("let" assigns "in let" exp) ("let monadic" assigns "in monadic" exp) ;;("eval in" assigns "in eval" exp) disabled ("fun" exp "=> fun" exp) ("if" exp "then" exp "else" exp) ("quantif exists" exp ", quantif" exp) ("forall" exp ", quantif" exp) (exp "<- monadic" exp) (exp ";; monadic" exp) ("(" exp ")") ("{|" exps "|}") ("{" exps "}") (exp "; tactic" exp) (exp "in tactic" exp) (exp "as" exp) (exp "by" exp) (exp "with" exp) (exp "|-" exp) (exp ":" exp) (exp ":<" exp) (exp "," exp) (exp "->" exp) (exp "<->" exp) (exp "&" exp) (exp "/\\" exp) (exp "\\/" exp) (exp "==" exp) (exp "=" exp) (exp "<>" exp) (exp "<=" exp) (exp "<" exp) (exp ">=" exp) (exp ">" exp) (exp "=?" exp) (exp "<=?" exp) (exp " b". ;; each line orders tokens by increasing priority ;; | C x => fun a => b | C2 x => ... ;;'((assoc "=>") (assoc "|") (assoc "|-" "=> fun")) ; (assoc ", quantif") '((assoc "- bullet") (assoc "+ bullet") (assoc "* bullet") (assoc "-- bullet") (assoc "++ bullet") (assoc "** bullet") (assoc "--- bullet") (assoc "+++ bullet") (assoc "*** bullet") (assoc "---- bullet") (assoc "++++ bullet") (assoc "**** bullet") (assoc ".") (assoc "with inductive" "with fixpoint" "where")) '((nonassoc "Com start") (assoc ":= equations") (assoc ":= def" ":= inductive") (left "|") (assoc "; equations") (assoc "=>") (assoc ":=") (assoc "as morphism") (assoc "xxx provedby") (assoc "with signature") (assoc "with match") (assoc "in let" "in monadic") (assoc "in eval") (left "=> fun") (left ", quantif") (assoc "then") (assoc "|| tactic") ;; FIXME: detecting "+ tactic" and "|| tactic" seems impossible (left "; tactic") (assoc "in tactic") (assoc "as" "by") (assoc "with") (assoc "|-") (assoc ":" ":<") (left ",") (assoc "else") (assoc "->") (assoc "<->") (left "\\/") (left "&" "/\\") ;; FTR: left (instead of assoc) for "<" makes the hoare triple notation ;; <{ .. }>\n exp \n<{ ... }> indent the two assertions at the same column. (assoc "==") (assoc "=") (left "<" ">" "<=" ">=" "<>") (assoc "=?") (assoc "<=?") (assoc " Oeq ;; as mu_eq_morphism. ;; FIXME: have a different token for := corresponding to a "fix" (not ;; Fixpoint) ;;Definition join l : key -> elt -> t -> t := ;; match l with ;; | Leaf => add ;; | Node ll lx ld lr lh => fun x d => ;; fix join_aux (r:t) : t ;; := match r with <---- ?? ;; | Leaf => add x d l ;; Returns the column of the beginning of current atomic tactic (non ;; composed). Returns the command start column if not found. (defun coq-find-with-related-backward() (let ((cmd-start (save-excursion (coq-find-real-start)))) (save-excursion ;; no point in going further the start of the command ;; let us find a tactical between it and point (let ((tok (coq-smie-search-token-backward '(";" "||" "|" "+") cmd-start))) ;; hopefully we found the start of the current (non composed)tactic ;; move point after the token found (if not found it will not move) (forward-char (length tok)) (forward-comment (point-max)); skip spaces ;; (coq-find-not-in-comment-forward "[^;+[:space:]|]") (current-column))))) (defun coq-is-at-first-line-of-def-decl () (let ((pt (point))) (save-excursion (and (member (coq-smie-backward-token) '(":" ":=")) (equal (line-number-at-pos) (line-number-at-pos pt)) (or (back-to-indentation) t) (looking-at "Lemma\\|Defintion\\|Theorem\\|Corollary"))))) ;; copied from elixir-smie.el (defun coq-smie--same-line-as-parent (parent-pos child-pos) "Return non-nil if PARENT-POS is on same line as CHILD-POS." (= (line-number-at-pos parent-pos) (line-number-at-pos child-pos))) (defcustom coq-indent-basic 2 "Basic indentation step. If nil, default to `proof-indent' if it exists or to `smie-indent-basic'." :group 'coq-mode :type '(choice (const :tag "Fallback on global settings" nil) integer)) ;; otherwise there are some glitches (setq smie-indent-basic coq-indent-basic) ;;;;;;;;;; DEBUG CODE ;;;;;; ;; smie-config-show-indent is sufficient most of the time. (defun coq-debug-smie--parent (point parent &optional num) ;;refresh highlighting? Not a good idea since this is called several times. ;;(hlt-unhighlight-region) (let* ((beg (if (listp (car parent)) (caar parent) (car parent))) (end (cadr parent)) (regi (list (list beg end))) (tok (car (cddr parent))) (face (cond ((equal num 1) 'hlt-regexp-level-1) ((equal num 2) 'hlt-regexp-level-2) (t 'hlt-regexp-level-1)))) ;; uncomment to see visually the region ;;(and parent (hlt-highlight-regions regi face)) ;;(when end (hlt-highlight-regions (list (list end (+ end 1))) 'hlt-regexp-level-1)) ;; and the point considered (hlt-highlight-regions (list (list point (+ point 1))) 'holiday))) ;; Debugging smie rules calls, needs the highlight library and ;; something like this in .emacs: (require 'highlight) ;; (custom-set-faces '(highlight ((((type x) (class color) (background light)) (:background "Wheat"))))) (defun coq-show-smie--parent (parent token parent-token &optional num msg) (ignore-errors (message "%s token: %S ; parent: %S ; parent-token: %S" msg token parent parent-token) (hlt-unhighlight-region) (let* ((beg (if (listp (car parent)) (caar parent) (car parent))) (end (cadr parent)) (regi (list (list beg end))) ;; (tok (car (cddr parent))) (face (cond ((equal num 2) 'hlt-regexp-level-2) (t 'hlt-regexp-level-1)))) (and parent (hlt-highlight-regions regi face))))) ;;;;;;;;;; END DEBUG CODE ;;;;;;;;;;;; (defun coq-indent-categorize-token-after (tk) "Factorize tokens behaving the same \"smie-rules\"-wise (kind:after)." (cond ((coq-is-bullet-token tk) "after bullet") ((member tk '("with" ":" "by" "in tactic" "as" ",")) "tactic infix") ((member tk '("<:" "<+" "with module")) "modulespec infix") ;; ":= inductive" ":= module" and other ":= xxx" ((member tk '(":= record")) tk) ;; avoids capture by next case ((string-prefix-p ":= " tk) "after :=") ;; by default we pass the token name, but maybe it would be safer ;; to simply fail, so that we detect missing tokens in this function? (t tk))) (defun coq-indent-categorize-token-before (tk) "Factorize tokens behaving the same \"smie-rules\"-wise (kind:after)." (cond ((member tk '(". proofstart" ". modulestart")) "dot script parent open") ((member tk '(":" "by" "in tactic" "as" "with" ",")) "tactic infix") ((string-prefix-p ":= " tk) "before :=") ;; by default we pass the token name, but maybe it would be safer ;; to simply fail, so that we detect missing tokens in this function? (t tk))) ;; ";" is a usual operator, with no indentation ;; it would be like this; ;; foo. ;; foo ; ;; bar ; ;; bar. ;; foo. ;; which is confusing. So we indent the first ";" of a sequence ;; if not already inside an ltacdef of parenthesized tactic: ;; foo ; ;; tac ; <--- indented ;; tac ; <--- no indent ;; [ tac2 ; ;; tac1 ; <-- no indentation here ;; now ( tac3 ; <- neither here ;; tac5) ; ;; ] (defun coq-smie-ltac-semicol-indent-first (parent-semicol) (and coq-indent-semicolon-tactical (not parent-semicol) (not (coq-smie-is-ltacdef)) (not (coq-smie-is-inside-parenthesized-tactic)))) ;; this should be called if we already know that parent is a quantif. (defun coq--prev-quantif-at-indent-p () (save-excursion (coq-smie-search-token-backward '("forall" "quantif exists")) (equal (current-column) (current-indentation)))) (defcustom coq-indent-align-with-first-arg nil "Non-nil if indentation should try to align arguments on the first one. With a non-nil value you get let x = List.map (fun x -> 5) my list whereas with a nil value you get let x = List.map (fun x -> 5) my list" :type 'boolean) ;; to be added to smie-indent-functions: this function deals with ;; arguemtns of functions. Explanation: it is hardcoded in SMIE that a ;; list of expressions (with no separator) is actually a single ;; expression. Thus we need an adhoc treatment to deal with the indentation ;; of arguments if they are not on the same line as the function. ;; Definition foo := ;; foo x y ;; z t (* align with function foo + 2. *) ;; u v. (* align with arg z on bol of previous line *) ;; More complex: ;; Definition foo := ;; foo x (y ;; a b) ;; z t (* align with function foo + 2. *) ;; u v. (* align with arg z on bol of previous line *) ;; This function examines these case. The generic situation is this: ;; we want to indent token (tk) ;; ;; ... other sexps? ... ;; (sexp) (se ;; ^ xp) (sexp) ;; | tk ;; | ^ ;; | token to indent (tk) ;; | ;; last skipped token (lstk) ;; The function examines the list of sexps on the left of ;; (point) until reaching a beginning of line. Then it tries to ;; determine what the last token skipped (lstk) is: ;; - if none was skipped it means that (tk) is not an argument, so we ;; give up and let the regular indentation do the job. ;; - if (lstk) is still an argument of something above, indentation ;; should align (tk) with (lstk). ;; - if (lstk) is really a function (no more sexp before it) then we ;; should indent from it (+2 in the example above). ;; Remark: Stefan Monier may make this less adhoc some day. (defun coq-smie--args () ;; PG specifics: some token are like parenthesis in the grammar but ;; are not paren-characters in the syntax table. ". proofstart" and ;; ". module start" mainly. These tokens need a special treatment. ;; We use coq-find-real-start to avoid crossing them (let ((limit (save-excursion (coq-find-real-start)))) (unless (or coq-indent-align-with-first-arg (nth 8 (syntax-ppss)) (looking-at comment-start-skip) (looking-at "[ \t]*$") ; tuareg bug #179 ;; the current token is a special token corresponding to ;; an ends of command, but it is not recognized as such in ;; the grammar, and the 2 tests below wrongly succeed: ;; this token cannot be an argument of anything. (member (nth 0 (save-excursion (smie-indent-forward-token))) '(". proofstart" ". modulestart" "{|" "{|")) (numberp (nth 1 (save-excursion (smie-indent-forward-token)))) (numberp (nth 2 (save-excursion (smie-indent-backward-token))))) (save-excursion (let ((positions nil) arg) (while (and (null (car (smie-backward-sexp))) ;; never go beyond the current command start. ;; otherwise things like this: ;; { tac1. } ;; { tac2. } ;; would be detected as function applications. (>= (point) limit) (push (point) positions) (not (smie-indent--bolp)))) (save-excursion ;; Figure out if the atom we just skipped is an argument rather ;; than a function. (setq arg (let ((left (smie-backward-sexp))) (or (null (car left)) (funcall smie-rules-function :list-intro (funcall smie-backward-token-function)))))) (cond ((null positions) ;; We're the first expression of the list. In that case, the ;; indentation should be (have been) determined by its context. nil) (arg ;; There's a previous element, and it's not special ;; (it's not the function), so let's just align with that one. (goto-char (car positions)) (if (fboundp 'smie-indent--current-column) (smie-indent--current-column) (current-column))) (t ;; There's no previous arg at BOL. Align with the function. ;; TODO: obey boxed style? this was for quantifiers. (goto-char (car positions)) ;; Special case: the function we found is actually next to a command start. ;; We prefer to indent from it. (when (not (= (save-excursion (back-to-indentation) (point)) (point))) (let ((left (save-excursion (smie-backward-sexp)))) (if (equal (nth 2 left) "Com start") (goto-char (nth 1 left))))) (+ (smie-indent--offset 'args) ;; We used to use (smie-indent-virtual), but that ;; doesn't seem right since it might then indent args less than ;; the function itself. (if (fboundp 'smie-indent--current-column) (smie-indent--current-column) (current-column)))))))))) ;; Reminder: (smie-rule-separator kind) only works for *parenthesized* enumerations. ;; and ":= inductive" is not considered a parenthesis so "|" needs special hack ;; below. "," for tuples and for tac args cannot be distinguished, so it cannot be ;; treated like this either. (defun coq-smie-rules (kind token) "Indentation rules for Coq. See `smie-rules-function'. KIND is the situation and TOKEN is the thing w.r.t which the rule applies." (let ((boxed coq-indent-box-style)) ;; smie-rule... short synonyms (cl-flet ((parent-p (&rest x) (apply 'smie-rule-parent-p x)) (parent (&optional x) (smie-rule-parent x))(hang-p () (smie-rule-hanging-p))) (pcase (cons kind token) (`(,_ . (or "; record")) (smie-rule-separator kind)) ;; see also the "before" rule (`(:elem . basic) (or coq-indent-basic (bound-and-true-p proof-indent) 2)) (`(:elem . arg) (if (smie-rule-prev-p "} subproof") 0 nil)) ;; hack: "{} {}"" not an application (`(:close-all . ,_) t) (`(:list-intro . ,_) (member token '("fun" "forall" "quantif exists" "with"))) ;; "Com start" (`(:after . ,_) ;; indent relative to token (parent of token at point). (pcase (coq-indent-categorize-token-after token) ("} subproof" 0) ;;shouldn't be captured by (:elem . args)? (". proofstart" coq-indent-proofstart) (". modulestart" coq-indent-modulestart) ;; decrement indentation when hanging ((and (or "tactic infix" "after :=") (guard (or (hang-p) (smie-rule-bolp)))) 0) ((and "->" (guard (hang-p))) 0) ((or ":=" "with inductive") 2) ((or "." "; equations" "in let" "in monadic" ";; monadic") 0) ((and "; tactic" (guard (hang-p)) (guard (not (parent-p "Com start")))) 0) ("; tactic" 2);; only applies "after" so when ";" is alone at its line ((guard (string-match "^[^][:alnum:](){}\[]" token)) 2); guessing infix operator. ;;((guard (and (message "################### RULES AFTER:DEFAULTING") nil)) nil) )) (`(:before . ,_) ; indent token at point itself (let* ((cat (coq-indent-categorize-token-before token)) (real-start-col (save-excursion (coq-find-real-start) (current-column)))) (pcase cat ;; indenting the ". modulestart" itself, which is a prenthesizing cmd ("dot script parent open" `(column . ,real-start-col)) ;; special case for equations, so that "| xxx\n :=" is indented nicely ((and ":=" (guard (and (not (hang-p)) (parent-p "|")))) 4) ("before :=" (parent 2)) ;; ":= xxx" always introduced by a parent ("tactic infix" (parent 2)) ("|" (cond ((parent-p ":= inductive" ":= equations") -2) (t 0)));((parent-p "|") 0) ;; align quantifiers with the previous one ((and(or "forall" "quantif exists")(guard (parent-p "forall" "quantif exists"))) (parent)) ((and(or "fun")(guard (parent-p "fun"))) (parent)) ;; indent on level after a ";" but only at command level. ((and "; tactic" (guard (parent-p "Com start"))) (parent)) ("; record" 0); is also a smie-rule-separator ;; VIRTUAL INDENTATION for "unboxed" indentation: we are in the "before" ;; section, but we compute the indentation for a token NOT appearing at ;; beginning of line. This happens when not indenting the token itself but ;; rather querying its virtual indentation to compute indentation of another ;; (child) token. unbox ==> indent relative to parent. ;; unboxed indent for "{" not at bol: ((and (or "forall" "quantif exists") (guard (and (not (smie-rule-bolp)) (not boxed)))) (parent coq-smie-after-bolp-indentation)) ((and (or "[" "{") (guard (not (smie-rule-bolp)))) (parent 2)) ((guard (and (smie-rule-prev-p "} subproof" "{ subproof" ".") (not (smie-rule-bolp)))) (cond ((smie-rule-prev-p "} subproof") (parent)) ((smie-rule-prev-p "{ subproof") (coq-smie-backward-token) (+ 2 (smie-indent-virtual))) ((smie-rule-prev-p ".") (smie-backward-sexp 'half) (smie-indent-virtual))))))))))) ;;((guard (and (message "################### RULES BEFORE: DEFAULTING") nil)) nil) (provide 'coq-smie) ;;; coq-smie.el ends here PG-4.5/coq/coq-syntax.el000066400000000000000000002476421426357011200151220ustar00rootroot00000000000000;;; coq-syntax.el --- Font lock expressions for Coq -*- lexical-binding:t -*- ;; This file is part of Proof General. ;; Portions © Copyright 1994-2012 David Aspinall and University of Edinburgh ;; Portions © Copyright 2003-2021 Free Software Foundation, Inc. ;; Portions © Copyright 2001-2017 Pierre Courtieu ;; Portions © Copyright 2010, 2016 Erik Martin-Dorel ;; Portions © Copyright 2011-2013, 2016-2017 Hendrik Tews ;; Portions © Copyright 2015-2017 Clément Pit-Claudel ;; Authors: Thomas Kleymann, Healfdene Goguen, Pierre Courtieu ;; Maintainer: Pierre Courtieu ;; SPDX-License-Identifier: GPL-3.0-or-later ;;; Commentary: ;; ;;; Code: (eval-when-compile (require 'cl-lib)) (require 'coq-db) ;;; keyword databases (defcustom coq-user-tactics-db nil "User defined tactic information. See `coq-syntax-db' for syntax. It is not necessary to add your own tactics here (it is not needed by the synchronizing/backtracking system). You may however do so for the following reasons: 1 your tactics will be colorized by font-lock 2 your tactics will be added to the menu and to completion when calling \\[coq-insert-tactic] 3 you may define an abbreviation for your tactic." :type '(repeat sexp) :group 'coq) (defcustom coq-user-commands-db nil "User defined command information. See `coq-syntax-db' for syntax. It is not necessary to add your own commands here (it is not needed by the synchronizing/backtracking system). You may however do so for the following reasons: 1 your commands will be colorized by font-lock 2 your commands will be added to the menu and to completion when calling \\[coq-insert-command] 3 you may define an abbreviation for your command." :type '(repeat sexp) :group 'coq) (defcustom coq-user-tacticals-db nil "User defined tactical information. See `coq-syntax-db' for syntax. It is not necessary to add your own commands here (it is not needed by the synchronizing/backtracking system). You may however do so for the following reasons: 1 your commands will be colorized by font-lock 2 your commands will be added to the menu and to completion when calling \\[coq-insert-command] 3 you may define an abbreviation for your command." :type '(repeat sexp) :group 'coq) (defcustom coq-user-solve-tactics-db nil "User defined closing tactics. See `coq-syntax-db' for syntax. It is not necessary to add your own commands here (it is not needed by the synchronizing/backtracking system). You may however do so for the following reasons: 1 your commands will be colorized by font-lock 2 your commands will be added to the menu and to completion when calling \\[coq-insert-command] 3 you may define an abbreviation for your command." :type '(repeat sexp) :group 'coq) (defcustom coq-user-cheat-tactics-db nil "User defined closing tactics BY CHEATING (ex: admit). See `coq-syntax-db' for syntax. It is not necessary to add your own commands here (it is not needed by the synchronizing/backtracking system). You may however do so for the following reasons: 1 your commands will be colorized by font-lock 2 your commands will be added to the menu and to completion when calling \\[coq-insert-command] 3 you may define an abbreviation for your command." :type '(repeat sexp) :group 'coq) (defcustom coq-user-reserved-db nil "User defined reserved keywords information. See `coq-syntax-db' for syntax. It is not necessary to add your own commands here (it is not needed by the synchronizing/backtracking system). You may however do so for the following reasons: 1 your commands will be colorized by font-lock 2 your commands will be added to the menu and to completion when calling \\[coq-insert-command] 3 you may define an abbreviation for your command." :type '(repeat sexp) :group 'coq) ;; user shortcuts are prioritized by being put at the end (defvar coq-tactics-db (append '( ("absurd " "abs" "absurd " t "absurd") ("apply" "ap" "apply " t "apply") ("assert by" "assb" "assert ( # : # ) by #" t "assert") ("assert" "ass" "assert ( # : # )" t) ;; ("assumption" "as" "assumption" t "assumption") ("auto with arith" "awa" "auto with arith" t) ("auto with" "aw" "auto with @{db}" t) ("auto" "a" "auto" t "auto") ("autorewrite with in using" "arwiu" "autorewrite with @{db,db...} in @{hyp} using @{tac}" t) ("autorewrite with in" "arwi" "autorewrite with @{db,db...} in @{hyp}" t) ("autorewrite with using" "arwu" "autorewrite with @{db,db...} using @{tac}" t) ("autorewrite with" "ar" "autorewrite with @{db,db...}" t "autorewrite") ("case" nil "case " t "case") ("case_eq" "ceq" "case_eq " t "case_eq") ("case_type" "cty" "case_type " t "case_type") ("cbn" "c" "cbn" t "cbn") ("cbn (with flags)" "cbn" "cbn beta delta [#] iota zeta" t "cbn") ("cbv" "cbv" "cbv beta delta [#] iota zeta" t "cbv") ("change in" "chi" "change # in #" t) ("change with in" "chwi" "change # with # in #" t) ("change with" "chw" "change # with" t) ("change" "ch" "change " t "change") ("clear" "cl" "clear" t "clear") ("clear dependent" "cldep" "clear dependent" t "clear\\s-+dependent") ("clearbody" "cl" "clearbody" t "clearbody") ("cofix" "cof" "cofix" t "cofix") ("coinduction" "coind" "coinduction" t "coinduction") ("compare" "cmpa" "compare # #" t "compare") ("compute" "cmpu" "compute" t "compute") ;; ("congruence" "cong" "congruence" t "congruence") ("constructor" "cons" "constructor" t "constructor") ;; ("contradiction" "contr" "contradiction" t "contradiction") ("cut" "cut" "cut" t "cut") ("cutrewrite" "cutr" "cutrewrite -> # = #" t "cutrewrite") ;; ("decide equality" "deg" "decide equality" t "decide\\s-+equality") ("decide_right" "decr" "decide_right" t "decide\\s-+right") ("decide_left" "decl" "decide_left" t "decide\\s-+left") ("decide" nil "decide" t "decide") ("decompose record" "decr" "decompose record #" t "decompose\\s-+record") ("decompose sum" "decs" "decompose sum #" t "decompose\\s-+sum") ("decompose" "dec" "decompose [#] #" t "decompose") ("dependent inversion" "depinv" "dependent inversion" t "dependent\\s-+inversion") ("dependent inversion with" "depinvw" "dependent inversion # with #" t) ("dependent inversion_clear" "depinvc" "dependent inversion_clear" t "dependent\\s-+inversion_clear") ("dependent inversion_clear with" "depinvw" "dependent inversion_clear # with #" t) ("dependent rewrite ->" "depr" "dependent rewrite -> @{id}" t "dependent\\s-+rewrite") ("dependent rewrite <-" "depr<" "dependent rewrite <- @{id}" t) ("destr_eq" "deseq" "destr_eq " t "destr_eq") ("destruct as" "desa" "destruct # as #" t) ("destruct using" "desu" "destruct # using #" t) ("destruct" "des" "destruct " t "destruct") ("destruct_with_eqn" "deswe" "destruct_with_eqn " t "destruct_with_eqn") ("destruct_all" "desall" "destruct_all " t "destruct_all") ;; ("discriminate" "dis" "discriminate" t "discriminate") ("discrR" "discrR" "discrR" t "discrR") ("double induction" "dind" "double induction # #" t "double\\s-+induction") ("eapply" "eap" "eapply #" t "eapply") ("eauto with arith" "eawa" "eauto with arith" t) ("eauto with" "eaw" "eauto with @{db}" t) ("eauto" "ea" "eauto" t "eauto") ("econstructor" "econs" "econstructor" t "econstructor") ("edestruct" "edes" "edestruct " t "edestruct") ("eexists" "eex" "eexists" t "eexists") ("eleft" "eleft" "eleft" t "eleft") ("elim using" "elu" "elim # using #" t) ("elim" "e" "elim #" t "elim") ("elimtype" "elt" "elimtype" t "elimtype") ("enough" "eng" "enough (#: #).\n{ #\n}" t "enough") ("erewrite" "er" "erewrite #" t "erewrite") ("eright" "erig" "eright" "eright") ("esplit" "esp" "esplit" t "esplit") ("etransitivity" "etr" "etransitivity" t "etransitivity") ;; ("exact" "exa" "exact" t "exact") ("exfalso" "exf" "exfalso" t "exfalso") ("exists" "ex" "exists #" t "exists") ;; ("fail" "fa" "fail" nil) ("field" "field" "field" t "field") ("false_hyp" nil "false_hyp @{H} @{G}" t "false_hyp") ("firstorder" "fsto" "firstorder" t "firstorder") ("firstorder with" "fsto" "firstorder with #" t) ("firstorder with using" "fsto" "firstorder # with #" t) ("fold" "fold" "fold #" t "fold") ;; ("fourier" "four" "fourier" t "fourier") ("functional induction" "fi" "functional induction @{f} @{args}" t "functional\\s-+induction") ("functional inversion" "finv" "functional inversion @{H}" t "functional\\s-+inversion") ("generalize dependent" "gd" "generalize dependent #" t "generalize\\s-+dependent") ("generalize" "g" "generalize #" t "generalize") ("hnf" "hnf" "hnf" t "hnf") ("idtac" "id" "idtac" nil "idtac") ; also in tacticals with abbrev id ("idtac \"" "id\"" "idtac \"#\"") ; also in tacticals ("induction" "ind" "induction #" t "induction") ("induction using" "indu" "induction # using #" t) ("injection" "inj" "injection #" t "injection") ("instantiate" "inst" "instantiate" t "instantiate") ("intro" "i" "intro" t "intro") ("intro after" "ia" "intro # after #" t) ("intros" "is" "intros #" t "intros") ("intros! (guess names)" nil "intros #" nil nil coq-insert-intros) ("intros until" "isu" "intros until #" t) ("intuition" "intu" "intuition #" t "intuition") ("inversion" "inv" "inversion #" t "inversion") ("inversion in" "invi" "inversion # in #" t) ("inversion using" "invu" "inversion # using #" t) ("inversion using in" "invui" "inversion # using # in #" t) ("inversion_clear" "invcl" "inversion_clear" t "inversion_clear") ("lapply" "lap" "lapply" t "lapply") ("lazy" "lazy" "lazy beta delta [#] iota zeta" t "lazy") ("lazymatch with" "lazym" "lazymatch # with\n| # => #\nend") ("lazy_match! with" "lazy_m" "lazy_match! # with\n| # => #\nend") ("left" "left" "left" t "left") ("lia" nil "lia" t "lia") ("linear" "lin" "linear" t "linear") ("load" "load" "load" t "load") ("lra" nil "lra" t "lra") ("move after" "mov" "move # after #" t "move") ("multimatch with" "mm" "multimatch # with\n| # => #\nend") ("multi_match! with" "multi_m" "multi_match! # with\n| # => #\nend") ("nia" nil "nia" t "nia") ("now_show" nil "now_show" t "now_show") ("nra" nil "nra" t "nra") ("nsatz" nil "nsatz" t "nsatz") ("omega" "o" "omega" t "omega") ("pattern" "pat" "pattern" t "pattern") ("pattern(s)" "pats" "pattern # , #" t) ("pattern at" "pata" "pattern # at #" t) ("pose" "po" "pose ( # := # )" t "pose") ("prolog" "prol" "prolog" t "prolog") ("psatz" nil "psatz" t "psatz") ("quote" "quote" "quote" t "quote") ("quote []" "quote2" "quote # [#]" t) ("red" "red" "red" t "red") ("rapply" "rap" "rapply #" t "rapply") ("refine" "ref" "refine" t "refine") ;; ("reflexivity" "refl" "reflexivity #" t "reflexivity") ("remember" "rem" "remember # as #" t "remember") ("rename into" "ren" "rename # into #" t "rename") ("replace with" "rep" "replace # with #" t "replace") ("replace with in" "repi" "replace # with # in #" t) ("revert dependent" "r" "revert dependent" t "revert\\s-+dependent") ("revert" "r" "revert" t "revert") ("rewrite_all" nil "rewrite_all" t "rewrite_all") ("rewrite_all <-" nil "rewrite_all" t "rewrite_all") ("rewrite <- in" "ri<" "rewrite <- # in #" t) ("rewrite <-" "r<" "rewrite <- #" t) ("rewrite in" "ri" "rewrite # in #" t) ("rewrite" "r" "rewrite #" t "rewrite") ("right" "rig" "right" t "right") ;; ("ring" "ring" "ring #" t "ring") ("romega" nil "romega" t "romega") ("set in * |-" "seth" "set ( # := #) in * |-" t) ("set in *" "set*" "set ( # := #) in *" t) ("set in |- *" "setg" "set ( # := #) in |- *" t) ("set in" "seti" "set ( # := #) in #" t) ("set" "set" "set ( # := #)" t "set") ("setoid_replace with" "strep2" "setoid_replace # with #" t "setoid_replace") ("setoid replace with" "strep" "setoid replace # with #" t "setoid\\s-+replace") ("setoid_rewrite" "strew" "setoid_rewrite #" t "setoid_rewrite") ("setoid rewrite" "strew" "setoid rewrite #" t "setoid\\s-+rewrite") ("simpl" "s" "simpl" t "simpl") ("simpl at" "sa" "simpl # at #" t) ("simpl (all flags)" "simpl" "simpl beta delta [#] iota zeta" t) ("simple destruct" "sdes" "simple destruct" t "simple\\s-+destruct") ("simple inversion" "sinv" "simple inversion" t "simple\\s-+inversion") ("simple induction" "sind" "simple induction" t "simple\\s-+induction") ("simplify_eq" "simeq" "simplify_eq @{hyp}" t "simplify_eq") ("specialize" "spec" "specialize" t "specialize") ("split" "sp" "split" t "split") ("split_Rabs" "spra" "splitRabs" t "split_Rabs") ("split_Rmult" "sprm" "splitRmult" t "split_Rmult") ("stepl" "stl" "stepl #" t "stepl") ("stepl by" "stlb" "stepl # by #" t) ("stepr" "str" "stepr #" t "stepr") ("stepr by" "strb" "stepr # by #" t) ("subst" "su" "subst #" t "subst") ("symmetry" "sy" "symmetry" t "symmetry") ("symmetry in" "syi" "symmetry in #" t) ;; ("tauto" "ta" "tauto" t "tauto") ("transitivity" "trans" "transitivity #" t "transitivity") ("trivial" "t" "trivial" t "trivial") ("trivial with" "tw" "trivial with @{db}" t) ("unfold" "u" "unfold #" t "unfold") ("unfold(s)" "us" "unfold # , #" t) ("unfold in" "unfi" "unfold # in #" t) ("unfold at" "unfa" "unfold # at #" t) ("vm_compute" "vmc" "vm_compute." t "vm_compute") ;; SSReflect tactics. ("nat_congr" "ncongr" "nat_congr" t "nat_congr") ("nat_norm" "nnorm" "nat_norm" t "nat_norm") ("bool_congr" "bcongr" "bool_congr" t "bool_congr") ("prop_congr" "prcongr" "prop_congr" t "prop_congr") ("move" "m" "move" t "move") ("pose" "po" "pose # := #" t "pose") ("set" "set" "set # := #" t "set") ("have" "hv" "have # : #" t "have") ("congr" "con" "congr #" t "congr") ("wlog" "wlog" "wlog : / #" t "wlog") ("without loss" "wilog" "without loss #" t "without loss") ("unlock" "unlock" "unlock #" t "unlock") ("suffices" "suffices" "suffices # : #" t "suffices") ("suff" "suff" "suff # : #" t "suff") ("zify" nil "zify" t "zify") ) coq-user-tactics-db) "Coq tactics information list. See `coq-syntax-db' for syntax." ) ;; user shortcuts are prioritized by being put at the end (defvar coq-solve-tactics-db (append '( ("assumption" "as" "assumption" t "assumption") ("eassumption" "eas" "eassumption" t "eassumption") ("easy" nil "easy" t "easy") ("now" nil "now" t "now") ("by" "by" "by #" t "by") ("congruence" "cong" "congruence" t "congruence") ("contradict" "contr" "contradict" t "contradict") ("contradiction" "contr" "contradiction" t "contradiction") ("decide equality" "deg" "decide equality" t "decide\\s-+equality") ("discriminate" "dis" "discriminate" t "discriminate") ("exact" "exa" "exact" t "exact") ("fourier" "four" "fourier" t "fourier") ("fail" "fa" "fail" nil) ("gfail" "gfa" "gfail" nil "gfail") ("lia" nil "lia" t "lia") ("lra" nil "lra" t "lra") ("nia" nil "nia" t "nia") ("nra" nil "nra" t "nra") ("nsatz" nil "nsatz" t "nsatz") ("omega" "o" "omega" t "omega") ("romega" nil "romega" t "romega") ("psatz" nil "psatz" t "psatz") ("reflexivity" "refl" "reflexivity #" t "reflexivity") ("ring" "ring" "ring #" t "ring") ("solve" nil "solve [ # | # ]" nil "solve") ("tauto" "ta" "tauto" t "tauto") ;; SSReflect solving tactics. ("done" nil "done" nil "done") ) coq-user-solve-tactics-db) "Coq tactic(al)s that solve a subgoal." ) (defvar coq-solve-cheat-tactics-db (append '(("admit" nil "admit" t "admit") ("Admitted" nil "Admitted" t "Admitted") ("Abort" nil "Abort" t "Abort")) coq-user-cheat-tactics-db) "Coq tactic(al)s that solve a subgoal." ) ;; FIXME is this needed? (defvar develock-coq-font-lock-keywords '((develock-find-long-lines (1 'develock-long-line-1 t) (2 'develock-long-line-2 t)) ("[^ \n ]\\([ ]+\\)$" (1 'develock-whitespace-1 t)) ("^[ ]+$" (0 'develock-whitespace-2 append)) ("\\.[{}]" 0 'develock-whitespace-2 nil nil))) (defvar coq-tacticals-db (append '( ("info" nil "info #" nil "info") ("first" nil "first [ # | # ]" nil "first") ("abstract" nil "abstract @{tac} using @{name}." nil "abstract") ("do" nil "do @{num} @{tac}" nil "do") ("idtac" nil "idtac") ; also in tactics ; ("idtac \"" nil "idtac \"#\"") ; also in tactics ("fail" "fa" "fail" nil "fail") ; ("fail \"" "fa\"" "fail" nil) ; ; ("orelse" nil "orelse #" t "orelse") ("repeat" nil "repeat #" nil "repeat") ("try" nil "try #" nil "try") ("tryif" "tryif" "tryif # then # else #" nil "tryif") ("progress" nil "progress #" nil "progress") ("|" nil "[ # | # ]" nil) ("||" nil "# || #" nil) ;; SSReflect tacticals. ("last" "lst" nil t "last") ) coq-user-tacticals-db) "Coq tacticals information list. See `coq-syntax-db' for syntax.") (defvar coq-decl-db '( ("Local Axiom" nil "Local Axiom # : #" t "Local\\s-+Axiom") ("Local Axioms" nil "Local Axioms # , #: #" t "Local\\s-+Axioms") ("Axiom" "ax" "Axiom # : #" t "Axiom") ("Axioms" "axs" "Axioms # , #: #" t "Axioms") ("Global Variable" "gv" "Global Variable #: #." t "Global\\s-+Variable") ("Global Variables" "gvs" "Global Variables # , #: #." t "Global\\s-+Variables") ("Hint Constructors" "hc" "Hint Constructors # : #." t "Hint\\s-+Constructors") ("Hint Extern" "he" "Hint Extern @{cost} @{pat} => @{tac} : @{db}." t "Hint\\s-+Extern") ("Hint Mode" "hm" "Hint Mode # @{mode...} : @{db}." t "Hint\\s-+Mode") ("Hint Immediate" "hi" "Hint Immediate # : @{db}." t "Hint\\s-+Immediate") ("Hint Resolve" "hr" "Hint Resolve # : @{db}." t "Hint\\s-+Resolve") ("Hint Rewrite ->" "hrw" "Hint Rewrite -> @{t1,t2...} using @{tac} : @{db}." t "Hint\\s-+Rewrite") ("Hint Rewrite <-" "hrw" "Hint Rewrite <- @{t1,t2...} using @{tac} : @{db}." t ) ("Hint Unfold" "hu" "Hint Unfold # : #." t "Hint\\s-+Unfold") ("Existing Class" nil "Existing Class " t "Existing\\s-+Class") ("Existing Instance" nil "Existing Instance " t "Existing\\s-+Instance") ("Existing Instances" nil "Existing Instances " t "Existing\\s-+Instances") ("Hypothesis" "hyp" "Hypothesis #: #" t "Hypothesis") ("Hypotheses" "hyp" "Hypotheses #: #" t "Hypotheses") ("Parameter" "par" "Parameter #: #" t "Parameter") ("Parameters" "par" "Parameters #: #" t "Parameters") ("Conjecture" "conj" "Conjecture #: #." t "Conjecture") ("Variable" "v" "Variable #: #." t "Variable") ("Variables" "vs" "Variables # , #: #." t "Variables") ("Context" nil "Context #, (# : #)." t "Context") ("Local Coercion" nil "Local Coercion @{id} : @{typ1} >-> @{typ2}." t "Local\\s-+Coercion") ("Coercion" "coerc" "Coercion @{id} : @{typ1} >-> @{typ2}." t "Coercion") ) "Coq declaration keywords information list. See `coq-syntax-db' for syntax." ) (defvar coq-defn-db '( ("Canonical Structure" nil "Canonical Structure #." t "Canonical\\s-+Structure") ("CoFixpoint" "cfix" "CoFixpoint # (#:#) : # :=\n#." t "CoFixpoint") ("CoInductive" "coindv" "CoInductive # : # :=\n|# : #." t "CoInductive") ("Class" "class" "Class [ # ] := \n# : #;\n# : #." t "Class") ("Declare Module : :=" "dm" "Declare Module # : # := #." t "Declare\\s-+Module") ("Declare Module <: :=" "dm2" "Declare Module # <: # := #." t);; careful ("Declare Module Import : :=" "dmi" "Declare Module # : # := #." t) ("Declare Module Import <: :=" "dmi2" "Declare Module # <: # := #." t);; careful ("Declare Module Export : :=" "dme" "Declare Module # : # := #." t) ("Declare Module Export <: :=" "dme2" "Declare Module # <: # := #." t);; careful ("Local Definition" nil "Local Definition #:# := #." t "Local\\s-+Definition");; careful ("Definition" "def" "Definition #:# := #." t "Definition");; careful ("Definition (2 args)" "def2" "Definition # (# : #) (# : #):# := #." t) ("Definition (3 args)" "def3" "Definition # (# : #) (# : #) (# : #):# := #." t) ("Definition (4 args)" "def4" "Definition # (# : #) (# : #) (# : #) (# : #):# := #." t) ("Program Definition" "pdef" "Program Definition #:# := #." t "Program\\s-+Definition");; careful ? ("Program Definition (2 args)" "pdef2" "Program Definition # (# : #) (# : #):# := #." t) ("Program Definition (3 args)" "pdef3" "Program Definition # (# : #) (# : #) (# : #):# := #." t) ("Program Definition (4 args)" "pdef4" "Program Definition # (# : #) (# : #) (# : #) (# : #):# := #." t) ("Derive Inversion" nil "Derive Inversion @{id} with # Sort #." t "Derive\\s-+Inversion") ("Derive Dependent Inversion" nil "Derive Dependent Inversion @{id} with # Sort #." t "Derive\\s-+Dependent\\s-+Inversion") ("Derive Inversion_clear" nil "Derive Inversion_clear @{id} with # Sort #." t) ("Derive SuchThat" nil "Derive @[id] SuchThat # As @{id}." t "Derive") ("Example" "ex" "Example #:# := #." t "Example");; careful ("Equations" "eqs" "Equations #:# := #." t "Equations") ("Fixpoint" "fix" "Fixpoint # (#:#) {struct @{arg}} : # :=\n#." t "Fixpoint") ("Program Fixpoint" "pfix" "Program Fixpoint # (#:#) {struct @{arg}} : # :=\n#." t "Program\\s-+Fixpoint") ("Program Fixpoint measure" "pfixm" "Program Fixpoint # (#:#) {measure @{arg} @{f}} : # :=\n#." t) ("Program Fixpoint wf" "pfixwf" "Program Fixpoint # (#:#) {wf @{arg} @{f}} : # :=\n#." t) ("Function" "func" "Function # (#:#) {struct @{arg}} : # :=\n#." t "Function") ("Function measure" "funcm" "Function # (#:#) {measure @{f} @{arg}} : # :=\n#." t) ("Function wf" "func wf" "Function # (#:#) {wf @{R} @{arg}} : # :=\n#." t) ("Functional Scheme with" "fsw" "Functional Scheme @{name} := Induction for @{fun} with @{mutfuns}." t ) ("Functional Scheme" "fs" "Functional Scheme @{name} := Induction for @{fun}." t "Functional\\s-+Scheme") ("Inductive" "indv" "Inductive # : # := # : #." t "Inductive") ("Inductive (2 args)" "indv2" "Inductive # : # :=\n| # : #\n| # : #." t ) ("Inductive (3 args)" "indv3" "Inductive # : # :=\n| # : #\n| # : #\n| # : #." t ) ("Inductive (4 args)" "indv4" "Inductive # : # :=\n| # : #\n| # : #\n| # : #\n| # : #." t ) ("Inductive (5 args)" "indv5" "Inductive # : # :=\n| # : #\n| # : #\n| # : #\n| # : #\n| # : #." t ) ("Instance" nil "Instance #:#.\nProof.\n#Defined." t "Instance") ("Program Instance" "pinstance" "Program Instance [ # ] => # where \n# := #;\n# := #." t "Program\\s-+Instance") ("Let" "Let" "Let # : # := #." t "Let") ("Local Ltac2" nil "Local Ltac2 # := #." t "Local\\s-+Ltac2") ("Ltac2 Type" "lt2rty" "Ltac2 Type rec # := #." t "Ltac2 Type rec") ("Ltac2 Type" "lt2ty" "Ltac2 Type # := #." t "Ltac2 Type") ("Ltac2 Type" "lt2oty" "Ltac2 Type # ::= #." t "Ltac2 Type") ("Ltac2 Type" "lt2wty" "Ltac2 Type #." t "Ltac2 Type") ("Ltac2" "lt2mr" "Ltac2 mutable rec # := #." t "Ltac2 mutable rec") ("Ltac2" "lt2m" "Ltac2 mutable # := #." t "Ltac2 mutable") ("Ltac2" "lt2r" "Ltac2 rec # := #." t "Ltac2 rec") ("Ltac2" "lt2s" "Ltac2 Set # := #." t "Ltac2 Set") ("Ltac2" "lt2" "Ltac2 # := #." t "Ltac2") ("Local Ltac" nil "Local Ltac # := #." t "Local\\s-+Ltac") ("Ltac" "ltac" "Ltac # := #." t "Ltac") ("Module :=" "mo" "Module # : # := #." t ) ; careful ("Module <: :=" "mo2" "Module # <: # := #." t ) ; careful ("Module Import :=" "moi" "Module Import # : # := #." t ) ; careful ("Module Import <: :=" "moi2" "Module Import # <: # := #." t ) ; careful ("Module Export :=" "moe" "Module Export # : # := #." t ) ; careful ("Module Export <: :=" "moe2" "Module Export# <: # := #." t ) ; careful ("Record" "rec" "Record # : # := {\n# : #;\n# : # }" t "Record") ("Scheme" "sc" "Scheme @{name} := #." t "Scheme") ("Scheme Induction" "sci" "Scheme @{name} := Induction for # Sort #." t) ("Scheme Minimality" "scm" "Scheme @{name} := Minimality for # Sort #." t) ("Structure" "str" "Structure # : # := {\n# : #;\n# : # }" t "Structure") ("Typeclasses eauto" nil "Typeclasses eauto := #." t "Typeclasses\\s-+eauto") ("Variant" "varv" "Variant # : # := # : #." t "Variant") ) "Coq definition keywords information list. See `coq-syntax-db' for syntax." ) ;; modules and section are indented like goal starters ;; PC TODO: this category is used only for indentation, because ;; scripting uses information from coq to decide if a goal is ;; started. Since it is impossible for some commands to know ;; syntactically if they start something (ex: Instance), the ;; right thing to do would be to indent only on "Proof." and forget ;; about this category for indentation. (defvar coq-goal-starters-db '( ("Add Morphism" "addmor" "Add Morphism @{f} : @{id}" t "Add\\s-+Morphism") ("Add Parametric Morphism" nil "Add Parametric Morphism : " t "Add\\s-+Parametric\\s-+Morphism") ("Chapter" "chp" "Chapter # : #." t "Chapter") ("Corollary" "cor" "Corollary # : #.\nProof.\n#\nQed." t "Corollary") ("Declare Module :" "dmi" "Declare Module # : #.\n#\nEnd #." t) ("Declare Module <:" "dmi2" "Declare Module # <: #.\n#\nEnd #." t) ("Definition goal" "defg" "Definition #:#.\n#\nDefined." t);; careful ("Fact" "fct" "Fact # : #." t "Fact") ("Goal" nil "Goal #." t "Goal") ("Instance goal" "instg" "Instance #:#.\n#\nDefined." t);; careful ("Lemma" "l" "Lemma # : #.\nProof.\n#\nQed." t "Lemma") ("Program Lemma" "pl" "Program Lemma # : #.\nProof.\n#\nQed." t "Program\\s-+Lemma") ("Proposition" "pr" "Proposition # : #.\nProof.\n#\nQed." t "Proposition") ("Module! (interactive)" nil "Module # : #.\n#\nEnd #." nil nil coq-insert-section-or-module) ("Module Type" "mti" "Module Type #.\n#\nEnd #." t "Module\\s-+Type") ; careful ("Module :" "moi" "Module # : #.\n#\nEnd #." t "Module") ; careful ("Module <:" "moi2" "Module # <: #.\n#\nEnd #." t ) ; careful ("Remark" "rk" "Remark # : #.\n#\nQed." t "Remark") ("Section" "sec" "Section #." t "Section") ("Theorem" "th" "Theorem # : #.\n#\nQed." t "Theorem") ("Program Theorem" "pth" "Program Theorem # : #.\nProof.\n#\nQed." t "Program\\s-+Theorem") ("Obligation" "obl" "Obligation #.\n#\nQed." t "Obligation") ("Obligations" "obls" "Obligations #.\n#\nQed." nil "Obligations") ("Next Obligation" "nobl" "Next Obligation.\n#\nQed." t "Next Obligation") ) "Coq goal starters keywords information list. See `coq-syntax-db' for syntax." ) ;; TODO: dig other queries from the refman. ;; Extraction command may go here ;; all Print, Show and Test stuff ;; Some of the Set/Unset (like Set Printing All, Set Extraction Inline etc) (defvar coq-queries-commands-db '( ("About" nil "About #." nil "About") ("Check" nil "Check" nil "Check") ("Compute" nil "Compute" nil "Compute") ("Fail" nil "Fail" nil "fail") ("Inspect" nil "Inspect #." nil "Inspect") ("Locate File" nil "Locate File \"#\"." nil "Locate\\s-+File") ("Locate Library" nil "Locate Library #." nil "Locate\\s-+Library") ("Locate Notation" nil "Locate Notation (#) #" nil "Locate\\s-+Notation") ("Locate" nil "Locate" nil "Locate") ("Print Coercions" nil "Print Coercions." nil "Print\\s-+Coercions") ("Print Hint" nil "Print Hint." nil "Print\\s-+Hint" coq-PrintHint) ("Print Ltac2" "lt2p" "Print Ltac2 #." nil "Print Ltac2") ("Print" "p" "Print #." nil "Print") ("Pwd" nil "Pwd." nil "Pwd") ("Search" nil "Search #" nil "Search") ("SearchPattern" nil "SearchPattern (#)" nil "SearchPattern") ("SearchRewrite" nil "SearchRewrite #" nil "SearchRewrite") ("Show" nil "Show #." nil "Show") ("Test" nil "Test" nil "Test" nil t) ; let us not highlight all possible options for Test ("Timeout" nil "Timeout" nil "Timeout") ) "Coq queries command. They deserve a separate menu for sending them to Coq without insertion.") ;; command that are not declarations, definition or goal starters (defvar coq-other-commands-db '( ("Add Parametric Relation" nil "Add Parametric Relation : " t "Add\\s-+Parametric\\s-+Relation") ;; ("Abort" nil "Abort." t "Abort" nil nil);don't appear in menu ;; ("Add" nil "Add #." nil "Add" nil t) ("Add Abstract Ring" nil "Add Abstract Ring #." t "Add\\s-+Abstract\\s-+Ring") ("Add Abstract Semi Ring" nil "Add Abstract Semi Ring #." t "Add\\s-+Abstract\\s-+Semi\\s-+Ring") ("Add Field" nil "Add Field #." t "Add\\s-+Field") ("Add LoadPath" nil "Add LoadPath #." nil "Add\\s-+LoadPath") ("Add ML Path" nil "Add ML Path #." nil "Add\\s-+ML\\s-+Path") ("Add Printing" nil "Add Printing #." t "Add\\s-+Printing") ("Add Printing If" nil "Add Printing If #." t "Add\\s-+Printing\\s-+If") ("Add Printing Let" nil "Add Printing Let #." t "Add\\s-+Printing\\s-+Let") ("Add Rec LoadPath" nil "Add Rec LoadPath #." nil "Add\\s-+Rec\\s-+LoadPath") ("Add Rec ML Path" nil "Add Rec ML Path #." nil "Add\\s-+Rec\\s-+ML\\s-+Path") ("Add Ring" nil "Add Ring #." t "Add\\s-+Ring") ("Add Semi Ring" nil "Add Semi Ring #." t "Add\\s-+Semi\\s-+Ring") ("Add Setoid" nil "Add Setoid #." t "Add\\s-+Setoid") ("Admit Obligations" "oblsadmit" "Admit Obligations." nil "Admit\\s-+Obligations") ("Arguments Scope" "argsc" "Arguments Scope @{id} [ @{_} ]" t "Arguments\\s-+Scope") ("Local Arguments" nil "Local Arguments @{id} : @{rule}" t "Local\\s-+Arguments") ("Arguments" "args" "Arguments @{id} : @{rule}" t "Arguments") ("Bind Scope" "bndsc" "Bind Scope @{scope} with @{type}" t "Bind\\s-+Scope") ("Canonical" nil "Canonical #." t "Canonical") ("Cd" nil "Cd #." nil "Cd") ("Local Close Scope" "lclsc" "Local Close Scope #" t "Local\\s-+Close\\s-+Scope") ("Close Scope" "clsc" "Close Scope #" t "Close\\s-+Scope") ("Comments" nil "Comments #." nil "Comments") ("Declare" nil "Declare #." nil "Declare") ("Delimit Scope" "delsc" "Delimit Scope @{scope} with @{id}." t "Delimit\\s-+Scope" ) ("Eval" nil "Eval #." nil "Eval") ("Export" nil "Export #." t "Export") ("Extract Constant" "extrc" "Extract Constant @{id} => \"@{id}\"." nil "Extract\\s-+Constant") ("Extract Inlined Constant" "extric" "Extract Inlined Constant @{id} => \"@{id}\"." nil "Extract\\s-+Inlined\\s-+Constant") ("Extract Inductive" "extri" "Extract Inductive @{id} => \"@{id}\" [\"@{id}\" \"@{id...}\"]." nil "Extract") ("Extraction (in a file)" "extrf" "Extraction \"@{file}\" @{id}." nil) ("Extraction Inline" nil "Extraction Inline #." t "Extraction\\s-+Inline") ("Extraction NoInline" nil "Extraction NoInline #." t "Extraction\\s-+NoInline") ("Extraction Language" "extrlang" "Extraction Language #." t "Extraction\\s-+Language") ("Extraction Library" "extrl" "Extraction Library @{id}." nil "Extraction\\s-+Library") ("Extraction" "extr" "Extraction @{id}." nil "Extraction") ("Focus" nil "Focus #." nil "Focus") ("From" nil "From #." nil "From") ("Generalizable Variables" nil "Generalizable Variables #." t "Generalizable\\s-+Variables") ("Generalizable All Variables" nil "Generalizable All Variables." t "Generalizable\\s-+All\\s-+Variables") ("Identity Coercion" nil "Identity Coercion #." t "Identity\\s-+Coercion") ("Implicit Arguments Off" nil "Implicit Arguments Off." t "Implicit\\s-+Arguments\\s-+Off") ("Implicit Arguments On" nil "Implicit Arguments On." t "Implicit\\s-+Arguments\\s-+On") ("Implicit Arguments" nil "Implicit Arguments # [#]." t "Implicit\\s-+Arguments") ("Implicit Types" nil "Implicit Types # : #." t "Implicit\\s-+Types") ("Implicit Type" nil "Implicit Type # : #." t "Implicit\\s-+Type") ("Import" nil "Import #." t "Import") ("Include" nil "Include #." t "Include") ("Infix" "inf" "Infix \"#\" := # (at level #) : @{scope}." t "Infix") ("Ltac2 Notation" "lt2n" "Ltac2 Notation # := #." t "Ltac2 Notation") ("Ltac2 Eval" "lt2e" "Ltac2 Eval #." nil "Ltac2 Eval") ("Notation (assoc)" "notas" "Notation \"#\" := # (at level #, # associativity)." t) ("Notation (at assoc)" "notassc" "Notation \"#\" := # (at level #, # associativity) : @{scope}." t) ("Notation (at at scope)" "notasc" "Notation \"#\" := # (at level #, # at level #) : @{scope}." t) ("Notation (at at)" "nota" "Notation \"#\" := # (at level #, # at level #)." t) ("Notation (only parsing)" "notsp" "Notation # := # (only parsing)." t) ("Local Notation" "lnots" "Local Notation # := #." t "Local\\s-+Notation") ("Local Notation (only parsing)" "lnotsp" "Local Notation # := # (only parsing)." t) ("Notation (simple)" "nots" "Notation # := #." t "Notation") ("Typeclasses Opaque" nil "Typeclasses Opaque #." nil "Typeclasses\\s-+Opaque") ("Opaque" nil "Opaque #." nil "Opaque") ("Obligation Tactic" nil "Obligation Tactic := #." t "Obligation\\s-+Tactic") ("Local Open Scope" nil "Local Open Scope #" t "Local\\s-+Open\\s-+Scope") ("Open Local Scope" nil "Open Local Scope #" t "Open\\s-+Local\\s-+Scope") ("Open Scope" "opsc" "Open Scope #" t "Open\\s-+Scope") ("Preterm" nil "Preterm." nil "Preterm") ("Qed" nil "Qed." nil "Qed") ("Recursive Extraction" "recextr" "Recursive Extraction @{id}." nil "Recursive\\s-+Extraction") ("Recursive Extraction Library" "recextrl" "Recursive Extraction Library @{id}." nil "Recursive\\s-+Extraction\\s-+Library") ("Recursive Extraction Module" "recextrm" "Recursive Extraction Module @{id}." nil "Recursive\\s-+Extraction\\s-+Module") ("Remove Hints" nil "Remove Hints #: #." nil "Remove\\s-+Hints") ("Remove LoadPath" nil "Remove LoadPath" nil "Remove\\s-+LoadPath") ("Remove LoadPath" nil "Remove LoadPath" nil "Remove\\s-+LoadPath") ("Remove Printing If" nil "Remove Printing If #." t "Remove\\s-+Printing\\s-+If") ("Remove Printing Let" nil "Remove Printing Let #." t "Remove\\s-+Printing\\s-+Let") ("Require Export" nil "Require Export #." t "Require\\s-+Export") ("Require Import" nil "Require Import #." t "Require\\s-+Import") ("Require" nil "Require #." t "Require") ("Reserved Infix" nil "Reserved Infix" nil "Reserved\\s-+Infix") ("Reserved Notation" nil "Reserved Notation" nil "Reserved\\s-+Notation") ("Reset Extraction Inline" nil "Reset Extraction Inline." t "Reset\\s-+Extraction\\s-+Inline") ("Save" nil "Save." t "Save") ("Set Asymmetric Patterns" nil "Set Asymmetric Patterns" t "Set Asymmetric\\s-+Patterns") ("Set Atomic Load" nil "Set Atomic Load" t "Set Atomic\\s-+Load") ("Set Automatic Coercions Import" nil "Set Automatic Coercions Import" t "Set Automatic\\s-+Coercions\\s-+Import") ("Set Automatic Introduction" nil "Set Automatic Introduction" t "Set Automatic\\s-+Introduction") ("Set Boolean Equality Schemes" nil "Set Boolean Equality Schemes" t "Set Boolean\\s-+Equality\\s-+Schemes") ("Set Bracketing Last Introduction Pattern" nil "Set Bracketing Last Introduction Pattern" t "Set Bracketing\\s-+Last\\s-+Introduction\\s-+Pattern") ("Set Bullet Behavior" nil "Set Bullet Behavior" t "Set Bullet\\s-+Behavior") ("Set Case Analysis Schemes" nil "Set Case Analysis Schemes" t "Set Case\\s-+Analysis\\s-+Schemes") ("Set Compat Notations" nil "Set Compat Notations" t "Set Compat\\s-+Notations") ("Set Congruence Depth" nil "Set Congruence Depth" t "Set Congruence\\s-+Depth") ("Set Congruence Verbose" nil "Set Congruence Verbose" t "Set Congruence\\s-+Verbose") ("Set Contextual Implicit" nil "Set Contextual Implicit" t "Set Contextual\\s-+Implicit") ("Set Debug Auto" nil "Set Debug Auto" t "Set Debug\\s-+Auto") ("Set Debug Eauto" nil "Set Debug Eauto" t "Set Debug\\s-+Eauto") ("Set Debug RAKAM" nil "Set Debug RAKAM" t "Set Debug\\s-+RAKAM") ("Set Debug Tactic Unification" nil "Set Debug Tactic Unification" t "Set Debug\\s-+Tactic\\s-+Unification") ("Set Debug Trivial" nil "Set Debug Trivial" t "Set Debug\\s-+Trivial") ("Set Debug Unification" nil "Set Debug Unification" t "Set Debug\\s-+Unification") ("Set Decidable Equality Schemes" nil "Set Decidable Equality Schemes" t "Set Decidable\\s-+Equality\\s-+Schemes") ("Set Default Clearing Used Hypotheses" nil "Set Default Clearing Used Hypotheses" t "Set Default\\s-+Clearing\\s-+Used\\s-+Hypotheses") ("Set Default Goal Selector" nil "Set Default Goal Selector" t "Set Default\\s-+Goal\\s-+Selector") ("Set Default Proof Mode" nil "Set Default Proof Mode" t "Set Default\\s-+Proof\\s-+Mode") ("Set Default Proof Using" nil "Set Default Proof Using" t "Set Default\\s-+Proof\\s-+Using") ("Set Default Timeout" nil "Set Default Timeout" t "Set Default\\s-+Timeout") ("Set Dependent Propositions Elimination" nil "Set Dependent Propositions Elimination" t "Set Dependent\\s-+Propositions\\s-+Elimination") ("Set Discriminate Introduction" nil "Set Discriminate Introduction" t "Set Discriminate\\s-+Introduction") ("Set Dump Bytecode" nil "Set Dump Bytecode" t "Set Dump\\s-+Bytecode") ("Set Elimination Schemes" nil "Set Elimination Schemes" t "Set Elimination\\s-+Schemes") ("Set Equality Scheme" nil "Set Equality Scheme" t "Set Equality\\s-+Scheme") ("Set Extraction AccessOpaque" nil "Set Extraction AccessOpaque" t "Set Extraction\\s-+AccessOpaque") ("Set Extraction AutoInline" nil "Set Extraction AutoInline" t "Set Extraction\\s-+AutoInline") ("Set Extraction Conservative Types" nil "Set Extraction Conservative Types" t "Set Extraction\\s-+Conservative\\s-+Types") ("Set Extraction File Comment" nil "Set Extraction File Comment" t "Set Extraction\\s-+File\\s-+Comment") ("Set Extraction Flag" nil "Set Extraction Flag" t "Set Extraction\\s-+Flag") ("Set Extraction KeepSingleton" nil "Set Extraction KeepSingleton" t "Set Extraction\\s-+KeepSingleton") ("Set Extraction Optimize" nil "Set Extraction Optimize" t "Set Extraction\\s-+Optimize") ("Set Extraction SafeImplicits" nil "Set Extraction SafeImplicits" t "Set Extraction\\s-+SafeImplicits") ("Set Extraction TypeExpand" nil "Set Extraction TypeExpand" t "Set Extraction\\s-+TypeExpand") ("Set Firstorder Depth" nil "Set Firstorder Depth" t "Set Firstorder\\s-+Depth") ("Set Hide Obligations" nil "Set Hide Obligations" t "Set Hide\\s-+Obligations") ("Set Implicit Arguments" nil "Set Implicit Arguments" t "Set Implicit\\s-+Arguments") ("Set Info Auto" nil "Set Info Auto" t "Set Info\\s-+Auto") ("Set Info Eauto" nil "Set Info Eauto" t "Set Info\\s-+Eauto") ("Set Info Level" nil "Set Info Level" t "Set Info\\s-+Level") ("Set Info Trivial" nil "Set Info Trivial" t "Set Info\\s-+Trivial") ("Set Injection L2R Pattern Order" nil "Set Injection L2R Pattern Order" t "Set Injection\\s-+L2R\\s-+Pattern\\s-+Order") ("Set Injection On Proofs" nil "Set Injection On Proofs" t "Set Injection\\s-+On\\s-+Proofs") ("Set Inline Level" nil "Set Inline Level" t "Set Inline\\s-+Level") ("Set Intuition Iff Unfolding" nil "Set Intuition Iff Unfolding" t "Set Intuition\\s-+Iff\\s-+Unfolding") ("Set Intuition Negation Unfolding" nil "Set Intuition Negation Unfolding" t "Set Intuition\\s-+Negation\\s-+Unfolding") ("Set Kernel Term Sharing" nil "Set Kernel Term Sharing" t "Set Kernel\\s-+Term\\s-+Sharing") ("Set Keyed Unification" nil "Set Keyed Unification" t "Set Keyed\\s-+Unification") ("Set Loose Hint Behavior" nil "Set Loose Hint Behavior" t "Set Loose\\s-+Hint\\s-+Behavior") ("Set Maximal Implicit Insertion" nil "Set Maximal Implicit Insertion" t "Set Maximal\\s-+Implicit\\s-+Insertion") ("Set Nonrecursive Elimination Schemes" nil "Set Nonrecursive Elimination Schemes" t "Set Nonrecursive\\s-+Elimination\\s-+Schemes") ("Set Parsing Explicit" nil "Set Parsing Explicit" t "Set Parsing\\s-+Explicit") ("Set Primitive Projections" nil "Set Primitive Projections" t "Set Primitive\\s-+Projections") ("Set Printing All" nil "Set Printing All" t "Set\\s-+Printing\\s-+All") ("Set Printing Coercions" nil "Set Printing Coercions" t "Set\\s-+Printing\\s-+Coercions") ("Set Printing Compact Contexts" nil "set Printing Compact Contexts" t "set\\s-+Printing\\s-+Compact\\s-+Contexts") ("Set Printing Depth" nil "Set Printing Depth" t "Set\\s-+Printing\\s-+Depth") ("Set Printing Existential Instances" nil "Set Printing Existential Instances" t "Set\\s-+Printing\\s-+Existential\\s-+Instances") ("Set Printing Goal Tags" nil "Set Printing Goal Tags" t "Set\\s-+Printing\\s-+Goal\\s-+Tags") ("Set Printing Goal Names" nil "Set Printing Goal Names" t "Set\\s-+Printing\\s-+Goal\\s-+Names") ("Set Printing Implicit" nil "Set Printing Implicit" t "Set\\s-+Printing\\s-+Implicit") ("Set Printing Implicit Defensive" nil "Set Printing Implicit Defensive" t "Set\\s-+Printing\\s-+Implicit\\s-+Defensive") ("Set Printing Matching" nil "Set Printing Matching" t "Set\\s-+Printing\\s-+Matching") ("Set Printing Notations" nil "Set Printing Notations" t "Set\\s-+Printing\\s-+Notations") ("Set Printing Primitive Projection Compatibility" nil "Set Printing Primitive Projection Compatibility" t "Set\\s-+Printing\\s-+Primitive\\s-+Projection\\s-+Compatibility") ("Set Printing Primitive Projection Parameters" nil "Set Printing Primitive Projection Parameters" t "Set\\s-+Printing\\s-+Primitive\\s-+Projection\\s-+Parameters") ("Set Printing Projections" nil "Set Printing Projections" t "Set\\s-+Printing\\s-+Projections") ("Set Printing Records" nil "Set Printing Records" t "Set\\s-+Printing\\s-+Records") ("Set Printing Synth" nil "Set Printing Synth" t "Set\\s-+Printing\\s-+Synth") ("Set Printing Unfocused" nil "Set Printing Unfocused" t "Set\\s-+Printing\\s-+Unfocused") ("Set Printing Universes" nil "Set Printing Universes" t "Set\\s-+Printing\\s-+Universes") ("Set Printing Width" nil "Set Printing Width" t "Set\\s-+Printing\\s-+Width") ("Set Printing Wildcard" nil "Set Printing Wildcard" t "Set\\s-+Printing\\s-+Wildcard") ("Set Program Mode" nil "Set Program Mode" t "Set Program\\s-+Mode") ("Set Proof Using Clear Unused" nil "Set Proof Using Clear Unused" t "Set Proof\\s-+Using\\s-+Clear\\s-+Unused") ("Set Record Elimination Schemes" nil "Set Record Elimination Schemes" t "Set Record\\s-+Elimination\\s-+Schemes") ("Set Refine Instance Mode" nil "Set Refine Instance Mode" t "Set Refine\\s-+Instance\\s-+Mode") ("Set Regular Subst Tactic" nil "Set Regular Subst Tactic" t "Set Regular\\s-+Subst\\s-+Tactic") ("Set Reversible Pattern Implicit" nil "Set Reversible Pattern Implicit" t "Set Reversible\\s-+Pattern\\s-+Implicit") ("Set Rewriting Schemes" nil "Set Rewriting Schemes" t "Set Rewriting\\s-+Schemes") ("Set Short Module Printing" nil "Set Short Module Printing" t "Set Short\\s-+Module\\s-+Printing") ("Set Shrink Obligations" nil "Set Shrink Obligations" t "Set Shrink\\s-+Obligations") ("Set SimplIsCbn" nil "Set SimplIsCbn" t "Set SimplIsCbn") ("Set Standard Proposition Elimination Names" nil "Set Standard Proposition Elimination Names" t "Set Standard\\s-+Proposition\\s-+Elimination\\s-+Names") ("Set Strict Proofs" nil "Set Strict Proofs" t "Set Strict\\s-+Proofs") ("Set Strict Universe Declaration" nil "Set Strict Universe Declaration" t "Set Strict\\s-+Universe\\s-+Declaration") ("Set Strongly Strict Implicit" nil "Set Strongly Strict Implicit" t "Set Strongly\\s-+Strict\\s-+Implicit") ("Set Suggest Proof Using" nil "Set Suggest Proof Using" t "Set Suggest\\s-+Proof\\s-+Using") ("Set Tactic Compat Context" nil "Set Tactic Compat Context" t "Set Tactic\\s-+Compat\\s-+Context") ("Set Tactic Evars Pattern Unification" nil "Set Tactic Evars Pattern Unification" t "Set Tactic\\s-+Evars\\s-+Pattern\\s-+Unification") ("Set Tactic Pattern Unification" nil "Set Tactic Pattern Unification" t "Set Tactic\\s-+Pattern\\s-+Unification") ("Set Transparent Obligations" nil "Set Transparent Obligations" t "Set Transparent\\s-+Obligations") ("Set Typeclass Resolution After Apply" nil "Set Typeclass Resolution After Apply" t "Set Typeclass\\s-+Resolution\\s-+After\\s-+Apply") ("Set Typeclass Resolution For Conversion" nil "Set Typeclass Resolution For Conversion" t "Set Typeclass\\s-+Resolution\\s-+For\\s-+Conversion") ("Set Typeclasses Debug" nil "Set Typeclasses Debug" t "Set Typeclasses\\s-+Debug") ("Set Typeclasses Dependency Order" nil "Set Typeclasses Dependency Order" t "Set Typeclasses\\s-+Dependency\\s-+Order") ("Set Typeclasses Depth" nil "Set Typeclasses Depth" t "Set Typeclasses\\s-+Depth") ("Set Typeclasses Modulo Eta" nil "Set Typeclasses Modulo Eta" t "Set Typeclasses\\s-+Modulo\\s-+Eta") ("Set Typeclasses Strict Resolution" nil "Set Typeclasses Strict Resolution" t "Set Typeclasses\\s-+Strict\\s-+Resolution") ("Set Typeclasses Unique Instances" nil "Set Typeclasses Unique Instances" t "Set Typeclasses\\s-+Unique\\s-+Instances") ("Set Typeclasses Unique Solutions" nil "Set Typeclasses Unique Solutions" t "Set Typeclasses\\s-+Unique\\s-+Solutions") ("Set Universal Lemma Under Conjunction" nil "Set Universal Lemma Under Conjunction" t "Set Universal\\s-+Lemma\\s-+Under\\s-+Conjunction") ("Set Universe Minimization ToSet" nil "Set Universe Minimization ToSet" t "Set Universe\\s-+Minimization\\s-+ToSet") ("Set Universe Polymorphism" nil "Set Universe Polymorphism" t "Set Universe\\s-+Polymorphism") ("Set Verbose Compat Notations" nil "Set Verbose Compat Notations" t "Set Verbose\\s-+Compat\\s-+Notations") ("Set Function_debug" nil "Set Function_debug" t "Set Function_debug") ("Set Function_raw_tcc" nil "Set Function_raw_tcc" t "Set Function_raw_tcc") ("Set Functional Induction Rewrite Dependent" nil "Set Functional Induction Rewrite Dependent" t "Set Functional\\s-+Induction\\s-+Rewrite\\s-+Dependent") ("Set Hyps Limit" nil "Set Hyps Limit" t "Set Hyps\\s-+Limit") ("Set Ltac Debug" nil "Set Ltac Debug" t "Set Ltac\\s-+Debug") ("Set Silent" nil "Set Silent" t "Set Silent") ("Set Undo" nil "Set Undo" t "Set Undo") ("Set Search Blacklist" nil "Set Search Blacklist" t "Set Search\\s-+Blacklist") ("Set Printing Coercion" nil "Set Printing Coercion" t "Set\\s-+Printing\\s-+Coercion") ("Set Printing If" nil "Set Printing If" t "Set\\s-+Printing\\s-+If") ("Set Printing Let" nil "Set Printing Let" t "Set\\s-+Printing\\s-+Let") ("Set Printing Record" nil "Set Printing Record" t "Set\\s-+Printing\\s-+Record") ("Set Printing Constructor" nil "Set Printing Constructor" t "Set\\s-+Printing\\s-+Constructor") ("Solve Obligations" "oblssolve" "Solve Obligations using #." t "Solve\\s-+Obligations") ("Local Strategy" nil "Local Strategy # [#]." t "Local\\s-+Strategy") ("Strategy" nil "Strategy # [#]." t "Strategy") ("Tactic Notation" nil "Tactic Notation # := #." t "Tactic\\s-+Notation") ("Transparent" nil "Transparent #." nil "Transparent") ("Unfocus" nil "Unfocus." nil "Unfocus") ("Unset Asymmetric Patterns" nil "Unset Asymmetric Patterns" t "Unset Asymmetric\\s-+Patterns") ("Unset Atomic Load" nil "Unset Atomic Load" t "Unset Atomic\\s-+Load") ("Unset Automatic Coercions Import" nil "Unset Automatic Coercions Import" t "Unset Automatic\\s-+Coercions\\s-+Import") ("Unset Automatic Introduction" nil "Unset Automatic Introduction" t "Unset Automatic\\s-+Introduction") ("Unset Boolean Equality Schemes" nil "Unset Boolean Equality Schemes" t "Unset Boolean\\s-+Equality\\s-+Schemes") ("Unset Bracketing Last Introduction Pattern" nil "Unset Bracketing Last Introduction Pattern" t "Unset Bracketing\\s-+Last\\s-+Introduction\\s-+Pattern") ("Unset Bullet Behavior" nil "Unset Bullet Behavior" t "Unset Bullet\\s-+Behavior") ("Unset Case Analysis Schemes" nil "Unset Case Analysis Schemes" t "Unset Case\\s-+Analysis\\s-+Schemes") ("Unset Compat Notations" nil "Unset Compat Notations" t "Unset Compat\\s-+Notations") ("Unset Congruence Depth" nil "Unset Congruence Depth" t "Unset Congruence\\s-+Depth") ("Unset Congruence Verbose" nil "Unset Congruence Verbose" t "Unset Congruence\\s-+Verbose") ("Unset Contextual Implicit" nil "Unset Contextual Implicit" t "Unset Contextual\\s-+Implicit") ("Unset Debug Auto" nil "Unset Debug Auto" t "Unset Debug\\s-+Auto") ("Unset Debug Eauto" nil "Unset Debug Eauto" t "Unset Debug\\s-+Eauto") ("Unset Debug RAKAM" nil "Unset Debug RAKAM" t "Unset Debug\\s-+RAKAM") ("Unset Debug Tactic Unification" nil "Unset Debug Tactic Unification" t "Unset Debug\\s-+Tactic\\s-+Unification") ("Unset Debug Trivial" nil "Unset Debug Trivial" t "Unset Debug\\s-+Trivial") ("Unset Debug Unification" nil "Unset Debug Unification" t "Unset Debug\\s-+Unification") ("Unset Decidable Equality Schemes" nil "Unset Decidable Equality Schemes" t "Unset Decidable\\s-+Equality\\s-+Schemes") ("Unset Default Clearing Used Hypotheses" nil "Unset Default Clearing Used Hypotheses" t "Unset Default\\s-+Clearing\\s-+Used\\s-+Hypotheses") ("Unset Default Goal Selector" nil "Unset Default Goal Selector" t "Unset Default\\s-+Goal\\s-+Selector") ("Unset Default Proof Mode" nil "Unset Default Proof Mode" t "Unset Default\\s-+Proof\\s-+Mode") ("Unset Default Proof Using" nil "Unset Default Proof Using" t "Unset Default\\s-+Proof\\s-+Using") ("Unset Default Timeout" nil "Unset Default Timeout" t "Unset Default\\s-+Timeout") ("Unset Dependent Propositions Elimination" nil "Unset Dependent Propositions Elimination" t "Unset Dependent\\s-+Propositions\\s-+Elimination") ("Unset Discriminate Introduction" nil "Unset Discriminate Introduction" t "Unset Discriminate\\s-+Introduction") ("Unset Dump Bytecode" nil "Unset Dump Bytecode" t "Unset Dump\\s-+Bytecode") ("Unset Elimination Schemes" nil "Unset Elimination Schemes" t "Unset Elimination\\s-+Schemes") ("Unset Equality Scheme" nil "Unset Equality Scheme" t "Unset Equality\\s-+Scheme") ("Unset Extraction AccessOpaque" nil "Unset Extraction AccessOpaque" t "Unset Extraction\\s-+AccessOpaque") ("Unset Extraction AutoInline" nil "Unset Extraction AutoInline" t "Unset Extraction\\s-+AutoInline") ("Unset Extraction Conservative Types" nil "Unset Extraction Conservative Types" t "Unset Extraction\\s-+Conservative\\s-+Types") ("Unset Extraction File Comment" nil "Unset Extraction File Comment" t "Unset Extraction\\s-+File\\s-+Comment") ("Unset Extraction Flag" nil "Unset Extraction Flag" t "Unset Extraction\\s-+Flag") ("Unset Extraction KeepSingleton" nil "Unset Extraction KeepSingleton" t "Unset Extraction\\s-+KeepSingleton") ("Unset Extraction Optimize" nil "Unset Extraction Optimize" t "Unset Extraction\\s-+Optimize") ("Unset Extraction SafeImplicits" nil "Unset Extraction SafeImplicits" t "Unset Extraction\\s-+SafeImplicits") ("Unset Extraction TypeExpand" nil "Unset Extraction TypeExpand" t "Unset Extraction\\s-+TypeExpand") ("Unset Firstorder Depth" nil "Unset Firstorder Depth" t "Unset Firstorder\\s-+Depth") ("Unset Hide Obligations" nil "Unset Hide Obligations" t "Unset Hide\\s-+Obligations") ("Unset Implicit Arguments" nil "Unset Implicit Arguments" t "Unset Implicit\\s-+Arguments") ("Unset Info Auto" nil "Unset Info Auto" t "Unset Info\\s-+Auto") ("Unset Info Eauto" nil "Unset Info Eauto" t "Unset Info\\s-+Eauto") ("Unset Info Level" nil "Unset Info Level" t "Unset Info\\s-+Level") ("Unset Info Trivial" nil "Unset Info Trivial" t "Unset Info\\s-+Trivial") ("Unset Injection L2R Pattern Order" nil "Unset Injection L2R Pattern Order" t "Unset Injection\\s-+L2R\\s-+Pattern\\s-+Order") ("Unset Injection On Proofs" nil "Unset Injection On Proofs" t "Unset Injection\\s-+On\\s-+Proofs") ("Unset Inline Level" nil "Unset Inline Level" t "Unset Inline\\s-+Level") ("Unset Intuition Iff Unfolding" nil "Unset Intuition Iff Unfolding" t "Unset Intuition\\s-+Iff\\s-+Unfolding") ("Unset Intuition Negation Unfolding" nil "Unset Intuition Negation Unfolding" t "Unset Intuition\\s-+Negation\\s-+Unfolding") ("Unset Kernel Term Sharing" nil "Unset Kernel Term Sharing" t "Unset Kernel\\s-+Term\\s-+Sharing") ("Unset Keyed Unification" nil "Unset Keyed Unification" t "Unset Keyed\\s-+Unification") ("Unset Loose Hint Behavior" nil "Unset Loose Hint Behavior" t "Unset Loose\\s-+Hint\\s-+Behavior") ("Unset Maximal Implicit Insertion" nil "Unset Maximal Implicit Insertion" t "Unset Maximal\\s-+Implicit\\s-+Insertion") ("Unset Nonrecursive Elimination Schemes" nil "Unset Nonrecursive Elimination Schemes" t "Unset Nonrecursive\\s-+Elimination\\s-+Schemes") ("Unset Parsing Explicit" nil "Unset Parsing Explicit" t "Unset Parsing\\s-+Explicit") ("Unset Primitive Projections" nil "Unset Primitive Projections" t "Unset Primitive\\s-+Projections") ("Unset Printing All" nil "Unset Printing All" t "Unset Printing\\s-+All") ("Unset Printing Coercions" nil "Unset Printing Coercions" t "Unset\\s-+Printing\\s-+Coercions") ("Unset Printing Compact Contexts" nil "Unset Printing Compact Contexts" t "Unset\\s-+Printing\\s-+Compact\\s-+Contexts") ("Unset Printing Depth" nil "Unset Printing Depth" t "Unset Printing\\s-+Depth") ("Unset Printing Existential Instances" nil "Unset Printing Existential Instances" t "Unset Printing\\s-+Existential\\s-+Instances") ("Unset Printing Implicit" nil "Unset Printing Implicit" t "Unset Printing\\s-+Implicit") ("Unset Printing Implicit Defensive" nil "Unset Printing Implicit Defensive" t "Unset Printing\\s-+Implicit\\s-+Defensive") ("Unset Printing Matching" nil "Unset Printing Matching" t "Unset Printing\\s-+Matching") ("Unset Printing Notations" nil "Unset Printing Notations" t "Unset Printing\\s-+Notations") ("Unset Printing Primitive Projection Compatibility" nil "Unset Printing Primitive Projection Compatibility" t "Unset Printing\\s-+Primitive\\s-+Projection\\s-+Compatibility") ("Unset Printing Primitive Projection Parameters" nil "Unset Printing Primitive Projection Parameters" t "Unset Printing\\s-+Primitive\\s-+Projection\\s-+Parameters") ("Unset Printing Projections" nil "Unset Printing Projections" t "Unset Printing\\s-+Projections") ("Unset Printing Records" nil "Unset Printing Records" t "Unset Printing\\s-+Records") ("Unset Printing Synth" nil "Unset Printing Synth" t "Unset Printing\\s-+Synth") ("Unset Printing Universes" nil "Unset Printing Universes" t "Unset Printing\\s-+Universes") ("Unset Printing Width" nil "Unset Printing Width" t "Unset Printing\\s-+Width") ("Unset Printing Wildcard" nil "Unset Printing Wildcard" t "Unset Printing\\s-+Wildcard") ("Unset Program Mode" nil "Unset Program Mode" t "Unset Program\\s-+Mode") ("Unset Proof Using Clear Unused" nil "Unset Proof Using Clear Unused" t "Unset Proof\\s-+Using\\s-+Clear\\s-+Unused") ("Unset Record Elimination Schemes" nil "Unset Record Elimination Schemes" t "Unset Record\\s-+Elimination\\s-+Schemes") ("Unset Refine Instance Mode" nil "Unset Refine Instance Mode" t "Unset Refine\\s-+Instance\\s-+Mode") ("Unset Regular Subst Tactic" nil "Unset Regular Subst Tactic" t "Unset Regular\\s-+Subst\\s-+Tactic") ("Unset Reversible Pattern Implicit" nil "Unset Reversible Pattern Implicit" t "Unset Reversible\\s-+Pattern\\s-+Implicit") ("Unset Rewriting Schemes" nil "Unset Rewriting Schemes" t "Unset Rewriting\\s-+Schemes") ("Unset Short Module Printing" nil "Unset Short Module Printing" t "Unset Short\\s-+Module\\s-+Printing") ("Unset Shrink Obligations" nil "Unset Shrink Obligations" t "Unset Shrink\\s-+Obligations") ("Unset SimplIsCbn" nil "Unset SimplIsCbn" t "Unset SimplIsCbn") ("Unset Standard Proposition Elimination Names" nil "Unset Standard Proposition Elimination Names" t "Unset Standard\\s-+Proposition\\s-+Elimination\\s-+Names") ("Unset Strict Proofs" nil "Unset Strict Proofs" t "Unset Strict\\s-+Proofs") ("Unset Strict Universe Declaration" nil "Unset Strict Universe Declaration" t "Unset Strict\\s-+Universe\\s-+Declaration") ("Unset Strongly Strict Implicit" nil "Unset Strongly Strict Implicit" t "Unset Strongly\\s-+Strict\\s-+Implicit") ("Unset Suggest Proof Using" nil "Unset Suggest Proof Using" t "Unset Suggest\\s-+Proof\\s-+Using") ("Unset Tactic Compat Context" nil "Unset Tactic Compat Context" t "Unset Tactic\\s-+Compat\\s-+Context") ("Unset Tactic Evars Pattern Unification" nil "Unset Tactic Evars Pattern Unification" t "Unset Tactic\\s-+Evars\\s-+Pattern\\s-+Unification") ("Unset Tactic Pattern Unification" nil "Unset Tactic Pattern Unification" t "Unset Tactic\\s-+Pattern\\s-+Unification") ("Unset Transparent Obligations" nil "Unset Transparent Obligations" t "Unset Transparent\\s-+Obligations") ("Unset Typeclass Resolution After Apply" nil "Unset Typeclass Resolution After Apply" t "Unset Typeclass\\s-+Resolution\\s-+After\\s-+Apply") ("Unset Typeclass Resolution For Conversion" nil "Unset Typeclass Resolution For Conversion" t "Unset Typeclass\\s-+Resolution\\s-+For\\s-+Conversion") ("Unset Typeclasses Debug" nil "Unset Typeclasses Debug" t "Unset Typeclasses\\s-+Debug") ("Unset Typeclasses Dependency Order" nil "Unset Typeclasses Dependency Order" t "Unset Typeclasses\\s-+Dependency\\s-+Order") ("Unset Typeclasses Depth" nil "Unset Typeclasses Depth" t "Unset Typeclasses\\s-+Depth") ("Unset Typeclasses Modulo Eta" nil "Unset Typeclasses Modulo Eta" t "Unset Typeclasses\\s-+Modulo\\s-+Eta") ("Unset Typeclasses Strict Resolution" nil "Unset Typeclasses Strict Resolution" t "Unset Typeclasses\\s-+Strict\\s-+Resolution") ("Unset Typeclasses Unique Instances" nil "Unset Typeclasses Unique Instances" t "Unset Typeclasses\\s-+Unique\\s-+Instances") ("Unset Typeclasses Unique Solutions" nil "Unset Typeclasses Unique Solutions" t "Unset Typeclasses\\s-+Unique\\s-+Solutions") ("Unset Universal Lemma Under Conjunction" nil "Unset Universal Lemma Under Conjunction" t "Unset Universal\\s-+Lemma\\s-+Under\\s-+Conjunction") ("Unset Universe Minimization ToUnset" nil "Unset Universe Minimization ToUnset" t "Unset Universe\\s-+Minimization\\s-+ToUnset") ("Unset Universe Polymorphism" nil "Unset Universe Polymorphism" t "Unset Universe\\s-+Polymorphism") ("Unset Verbose Compat Notations" nil "Unset Verbose Compat Notations" t "Unset Verbose\\s-+Compat\\s-+Notations") ("Unset Function_debug" nil "Unset Function_debug" t "Unset Function_debug") ("Unset Function_raw_tcc" nil "Unset Function_raw_tcc" t "Unset Function_raw_tcc") ("Unset Functional Induction Rewrite Dependent" nil "Unset Functional Induction Rewrite Dependent" t "Unset Functional\\s-+Induction\\s-+Rewrite\\s-+Dependent") ("Unset Hyps Limit" nil "Unset Hyps Limit" t "Unset Hyps\\s-+Limit") ("Unset Ltac Debug" nil "Unset Ltac Debug" t "Unset Ltac\\s-+Debug") ("Unset Silent" nil "Unset Silent" t "Unset Silent") ("Unset Undo" nil "Unset Undo" t "Unset Undo") ("Unset Search Blacklist" nil "Unset Search Blacklist" t "Unset Search\\s-+Blacklist") ("Unset Printing Coercion" nil "Unset Printing Coercion" t "Unset Printing\\s-+Coercion") ("Unset Printing If" nil "Unset Printing If" t "Unset Printing\\s-+If") ("Unset Printing Let" nil "Unset Printing Let" t "Unset Printing\\s-+Let") ("Unset Printing Record" nil "Unset Printing Record" t "Unset Printing\\s-+Record") ("Unset Printing Constructor" nil "Unset Printing Constructor" t "Unset Printing\\s-+Constructor") ; ("print" "pr" "print #" "print") ) "Command that are not declarations, definition or goal starters." ) (defvar coq-ssreflect-commands-db '(("Unset Strict Implicit" "unsti" nil t "Strict\\s-+Implicit") ("Prenex Implicits" "pi" "Prenex Implicits #" t "Prenex\\s-+Implicits") ("Hint View for" "hv" "Hint View for #" t "Hint\\s-+View\\s-+for"))) (defvar coq-commands-db (append coq-decl-db coq-defn-db coq-goal-starters-db coq-queries-commands-db coq-other-commands-db coq-ssreflect-commands-db coq-user-commands-db) "Coq all commands keywords information list. See `coq-syntax-db' for syntax." ) (defvar coq-terms-db '( ("fun (1 args)" "f" "fun #:# => #" nil "fun") ("fun (2 args)" "f2" "fun (#:#) (#:#) => #") ("fun (3 args)" "f3" "fun (#:#) (#:#) (#:#) => #") ("fun (4 args)" "f4" "fun (#:#) (#:#) (#:#) (#:#) => #") ("forall" "fo" "forall #:#,#" nil "forall") ("forall (2 args)" "fo2" "forall (#:#) (#:#), #") ("forall (3 args)" "fo3" "forall (#:#) (#:#) (#:#), #") ("forall (4 args)" "fo4" "forall (#:#) (#:#) (#:#) (#:#), #") ("if" "if" "if # then # else #" nil "if") ("let in" "li" "let # := # in #" nil "let") ("match?" nil "" nil "match" coq-insert-match) ("match with" "m" "match # with\n| # => #\nend") ("match with 2" "m2" "match # with\n| # => #\n| # => #\nend") ("match with 3" "m3" "match # with\n| # => #\n| # => #\n| # => #\nend") ("match with 4" "m4" "match # with\n| # => #\n| # => #\n| # => #\n| # => #\nend") ("match with 5" "m5" "match # with\n| # => #\n| # => #\n| # => #\n| # => #\n| # => #\nend") ) "Coq terms keywords information list. See `coq-syntax-db' for syntax." ) ;;; Goals (and module/sections) starters detection ;; FIXME da: this one function breaks the nice configuration of Proof General: ;; would like to have proof-goal-regexp instead. ;; Unfortunately Coq allows "Definition" and friends to perhaps have a goal, ;; so it appears more difficult than just a proof-goal-regexp setting. ;; Future improvement may simply to be allow a function value for ;; proof-goal-regexp. ;; FIXME Pierre: the right way IMHO here would be to set a span ;; property 'goalcommand when coq prompt says it (if the name of ;; current proof has changed). ;; excerpt of Jacek Chrzaszcz, implementer of the module system: sorry ;; for the french: ;;*) suivant les suggestions de Chritine, pas de mode preuve dans un type de ;; module (donc pas de Definition truc:machin. Lemma, Theorem ... ) ;; ;; *) la commande Module M [ ( : | <: ) MTYP ] [ := MEXPR ] est valable ;; uniquement hors d'un MT ;; - si :=MEXPR est absent, elle demarre un nouveau module interactif ;; - si :=MEXPR est present, elle definit un module ;; (la fonction vernac_define_module dans toplevel/vernacentries) ;; ;; *) la nouvelle commande Declare Module M [ ( : | <: ) MTYP ] [ := MEXPR ] ;; est valable uniquement dans un MT ;; - si :=MEXPR absent, :MTYP absent, elle demarre un nouveau module ;; interactif ;; - si (:=MEXPR absent, :MTYP present) ;; ou (:=MEXPR present, :MTYP absent) ;; elle declare un module. ;; (la fonction vernac_declare_module dans toplevel/vernacentries) (defun coq-count-match (regexp str) "Count the number of max. non-overlapping substring of STR matching REGEXP. Empty matches are counted once." (let ((nbmatch 0) (pos 0) (end (length str)) (case-fold-search nil)) (while (and (< pos end) (string-match regexp str pos)) (cl-incf nbmatch) (setq pos (max (match-end 0) (1+ pos)))) nbmatch)) ;; Module and or section openings are detected syntactically. Module ;; *openings* are difficult to detect because there can be Module ;; ...with X := ... . So we need to count :='s to detect real openings. ;; TODO: have opened section/chapter in the prompt too, and get rid of ;; syntactical tests everywhere (defun coq-module-opening-p (str) "Decide whether STR is a module or section opening or not. Used by `coq-goal-command-p'" (let* ((match (coq-count-match "\\_" str)) (with (coq-count-match "\\_" str)) (letwith (+ (coq-count-match "\\_" str) (- with match))) (affect (coq-count-match ":=" str)) (case-fold-search nil)) (and (string-match "\\`\\(Module\\)\\_>" str) (= letwith affect)))) (defun coq-section-command-p (str) (let ((case-fold-search nil)) (string-match "\\`\\(Section\\|Chapter\\)\\_>" str))) (defvar coq-goal-command-regexp) ;; unused anymore (for good) (defun coq-goal-command-str-p (str) "Decide syntactically whether STR is a goal start or not. Use ‘coq-goal-command-p’ on a span instead if possible." (let* ((match (coq-count-match "\\_" str)) (with (- (coq-count-match "\\_" str) (coq-count-match "\\_" str))) (letwith (+ (coq-count-match "\\_" str) (- with match))) (affect (coq-count-match ":=" str)) (case-fold-search nil)) (and (string-match coq-goal-command-regexp str) (not (and (string-match (concat "\\`\\(Local\\|Definition\\|Lemma\\|Theorem\\|Fact\\|Add\\|Let\\|Program\\|Module\\|Class\\|Instance\\)\\_>") str) (not (= letwith affect)))) (not (string-match "\\`Declare\\s-+Module\\(\\w\\|\\s-\\|<\\)*:" str))))) ;; This is the function that tests if a SPAN is a goal start. All it ;; has to do is look at the 'goalcmd attribute of the span. ;; It also looks if this is not a module start. ;; TODO: have also attributes 'modulecmd and 'sectioncmd. This needs ;; something in the coq prompt telling the name of all opened modules ;; (like for open goals), and use it to set goalcmd --> no more need ;; to look at Modules and section (actually indentation will still ;; need it) (defun coq-goal-command-p (span) (or (overlay-get span 'goalcmd) ;; module and section starts are detected here (let ((str (or (overlay-get span 'cmd) ""))) (or (coq-section-command-p str) (coq-module-opening-p str))))) ;; TODO: rely on coq response nistead for span grouping Or better have ;; coq change its syntax for something better. (defvar coq-keywords-save-strict '("Defined" "Save" "Qed" "End" "Admitted" "Abort" ) "This regexp must match *exactly* commands that close a goal/Module. It is used: 1) for grouping spans into one when scripting 2) for indentation.") (defvar coq-keywords-save (append coq-keywords-save-strict '("Proof")) ) ;; According to Coq, "Definition" is both a declaration and a goal. ;; It is understood here as being a goal. This is important for ;; recognizing global identifiers, see coq-global-p. (defconst coq-save-command-regexp-strict (concat "\\`\\(?:Time\\s-+\\|Timeout\\s-+[[:digit:]]+\\s-+\\)*\\(" "\\_<" (regexp-opt coq-keywords-save-strict) "\\_>" "\\)")) (defun coq-save-command-p (_span str) "Decide whether argument is a Save command or not." (let ((case-fold-search nil)) (or (string-match coq-save-command-regexp-strict str) (and (string-match "\\`Proof\\_>" str) (not (string-match "\\`Proof\\s-*\\(\\.\\|\\_\\|\\_\\)" str)))))) ;; ----- regular expressions for the proof omit feature ;; see `proof-omit-proofs-configured' in generic/proof-config (defcustom coq-proof-start-regexp "^Proof\\(\\.\\| \\)" "Value for `proof-script-proof-start-regexp'." :type 'regexp :group 'coq) (defcustom coq-proof-end-regexp "^\\(Qed\\|Admitted\\)\\." "Value for `proof-script-proof-end-regexp'. This is similar to `coq-save-command-regexp-strict' but slightly different." :type 'regexp :group 'coq) (defcustom coq-definition-end-regexp "^\\(Defined\\|Abort\\)\\(\\.\\| \\)" "Value for `proof-script-definition-end-regexp'." :type 'regexp :group 'coq) (defcustom coq-omit-proof-admit-command "Admitted." "Value for `proof-script-proof-admit-command'." :type 'string :group 'coq) ;; ----- keywords for font-lock. (defvar coq-keywords-kill-goal '("Abort")) ;; Following regexps are all state changing (defvar coq-keywords-state-changing-misc-commands (coq-build-regexp-list-from-db coq-commands-db 'filter-state-changing)) (defvar coq-keywords-goal (coq-build-regexp-list-from-db coq-goal-starters-db)) (defvar coq-keywords-decl (coq-build-regexp-list-from-db coq-decl-db)) (defvar coq-keywords-defn (coq-build-regexp-list-from-db coq-defn-db)) (defvar coq-keywords-state-changing-commands (append coq-keywords-state-changing-misc-commands coq-keywords-decl ; all state changing coq-keywords-defn ; idem coq-keywords-goal)) ; idem ;; (defvar coq-keywords-state-preserving-commands (coq-build-regexp-list-from-db coq-commands-db 'filter-state-preserving)) ;; concat this is faster that redoing coq-build-regexp-list-from-db on ;; whole commands-db (defvar coq-keywords-commands (append coq-keywords-state-changing-commands coq-keywords-state-preserving-commands) "All commands keyword.") (defvar coq-solve-tactics (coq-build-regexp-list-from-db coq-solve-tactics-db) "Keywords for closing tactic(al)s.") (defvar coq-solve-tactics-regexp (coq-build-opt-regexp-from-db coq-solve-tactics-db) "Keywords regexp for closing tactic(al)s.") (defvar coq-solve-cheat-tactics (coq-build-regexp-list-from-db coq-solve-cheat-tactics-db) "Keywords for closing by cheating tactic(al)s.") (defvar coq-solve-cheat-tactics-regexp (coq-build-opt-regexp-from-db coq-solve-cheat-tactics-db) "Keywords regexp for closing by cheating tactic(al)s.") (defvar coq-tacticals (coq-build-regexp-list-from-db coq-tacticals-db) "Keywords for tacticals in a Coq script.") (defvar coq-symbol-binders "∀\\|∃\\|λ") ;; From JF Monin: (defvar coq-reserved (append '( "False" "True" "after" "as" "cofix" "fix" "forall" "fun" "match" "lazymatch" "multimatch" "lazy_match" "multi_match" "return" "struct" "else" "end" "if" "in" "into" "let" "then" "using" "with" "beta" "delta" "iota" "zeta" "after" "until" "at" "Sort" "Time" "dest" "where" ;; SSReflect user reserved. "is" "nosimpl" "of" ;; Derive reserved "SuchThat" "As" ;; I don't like these two: they start with ;; capitals but they are not at beginning of a ;; sentence ) coq-user-reserved-db) "Reserved keywords of Coq.") ;; FIXME: ∀ and ∃ should be followed by a space in coq syntax. ;; FIXME: actually these are not exactly reserved keywords, find ;; another classification of keywords. (defvar coq-reserved-regexp (concat "\\_<" "\\(?:with\\s-+signature\\|" (regexp-opt coq-reserved) "\\)" "\\_>")) (defvar coq-state-changing-tactics (coq-build-regexp-list-from-db coq-tactics-db 'filter-state-changing)) (defvar coq-state-preserving-tactics (coq-build-regexp-list-from-db coq-tactics-db 'filter-state-preserving)) (defvar coq-tactics (append coq-state-changing-tactics coq-state-preserving-tactics)) (defvar coq-tactics-regexp (coq-build-opt-regexp-from-db coq-tactics-db)) ;(defvar coq-tactics-regexp-symb (coq-build-opt-regexp-from-db coq-tactics-db)) (defvar coq-retractable-instruct (append coq-state-changing-tactics coq-keywords-state-changing-commands)) (defvar coq-non-retractable-instruct (append coq-state-preserving-tactics coq-keywords-state-preserving-commands)) (defvar coq-keywords (append coq-keywords-goal coq-keywords-save coq-keywords-decl coq-keywords-defn coq-keywords-commands) "All keywords in a Coq script.") ;; coq-build-opt-regexp-from-db already adds "\\_<" "\\_>" (defun coq--regexp-alt-list-symb (args) (concat "\\_<\\(?:" (mapconcat #'identity args "\\|") "\\)\\_>")) (defun coq--regexp-alt-list (args) (concat "\\(?:" (mapconcat #'identity args "\\|") "\\)")) (defvar coq-keywords-regexp (coq--regexp-alt-list-symb coq-keywords)) (defvar coq-symbols '("|" "||" ":" ";" "," "(" ")" "[" "]" "{" "}" ":=" "=>" "==>" "++>" "@" "->" "." "∧" "∨" "→" "\\/" "/\\" "->") "Punctuation Symbols used by Coq.") (defvar coq-symbols-regexp (regexp-opt coq-symbols)) ;; HACKISH: This string matches standard error regexp UNLESS there is ;; the standard header of the "Fail" command (which is "The command ;; blah has indeed failed with message:\n"). The case where the error ;; header has nothing before it is treated using "empty string at ;; start" regexp. BUT coq-error-regexp (and hence ;; proof-shell-error-regexp) must be correct either when searching in ;; a string or when searching in the proof-shell-buffer when point is ;; at the start of the last output. Hence when we use \\` (empty ;; string at start of the string) we should also accept \\= (empty ;; string at point). (defvar coq--prefix-not-regexp "\\(\\(\\`\\|\\=\\)\n?\\)\\|\\(?:\\(?:[^:]\\|[^e]:\\|[^g]e:\\|[^a]ge:\\|[^s]age:\\|[^s]sage:\\|[^e]ssage:\\|[^m]essage:\\)\n\\)" "A regexp matching allowed text before coq error.") (defvar coq--error-header-re-list '("In nested Ltac call" "Discarding pattern" "Syntax error:" "System Error:" "User Error:" "User error:" "Anomaly[:.]" "Toplevel input" "\\ and around all messages except errors. ;; We let our legacy regexp for some years and remove them, say, in 2020. (defvar coq-shell-eager-annotation-start "\376\\|\\[Reinterning\\|Warning:\\|TcDebug \\|\\|") (defvar coq-shell-eager-annotation-end "\377\\|done\\]\\|\\|\\|\\*\\*\\*\\*\\*\\*\\|) >") (defvar coq-id "\\(@\\|_\\|\\w\\)\\(\\w\\|\\s_\\)*") ;; Coq ca start an id with @ or _ (defvar coq-id-shy "\\(?:@\\|_\\|\\w\\)\\(?:\\w\\|\\s_\\)*") ; do not use proof-ids with a space separator! (defvar coq-ids (concat coq-id "\\(" "\\s-+" coq-id "\\)*")) (defun coq-first-abstr-regexp (paren end) (concat paren "\\s-*\\(" coq-ids "\\)\\s-*" end)) (defun coq-first-abstr-without-space-regexp (paren end) "Variant of `coq-first-abstr-regexp' without space between PAREN & `coq-ids'." (concat paren "\\(" coq-ids "\\)\\s-*" end)) (defcustom coq-variable-highlight-enable t "Activates partial bound variable highlighting." :type 'boolean :group 'coq) (defcustom coq-symbol-highlight-enable nil "Activates symbol highlighting." :type 'boolean :group 'coq) (defconst coq-lambda-regexp "\\(?:\\_\\|λ\\)") (defconst coq-forall-regexp "\\(?:\\_\\|∀\\)") (defconst coq-exists-regexp "\\(?:\\_\\|∃\\)") (defvar coq-font-lock-terms (append (list ;; flattened by append above (cons coq-symbol-binders 'coq-symbol-binder-face)) (when coq-symbol-highlight-enable (list (cons coq-symbols-regexp 'coq-symbol-face))) (when coq-variable-highlight-enable (list ;; lambda binders (list (coq-first-abstr-regexp coq-lambda-regexp "\\(?:=>\\|:\\|,\\)") 1 'font-lock-variable-name-face) ;; forall binder (list (coq-first-abstr-regexp coq-forall-regexp "\\(?:,\\|:\\)") 1 'font-lock-variable-name-face) (list (coq-first-abstr-regexp coq-exists-regexp "\\(?:,\\|:\\)") 1 'font-lock-variable-name-face) ;; (list "\\" ;; (list 0 font-lock-type-face) ;; (list (concat "[^ :]\\s-*\\(" coq-ids "\\)\\s-*") nil nil ;; (list 0 font-lock-variable-name-face))) ;; parenthesized binders (list (coq-first-abstr-regexp "(" ":[ a-zA-Z]") 1 'font-lock-variable-name-face) ;; Don't use coq-first-abstr-regexp here, see ProofGeneral/PG#581: (list (coq-first-abstr-without-space-regexp "{" ":[ a-zA-Z]") 1 'font-lock-variable-name-face) ;; Likewise, for https://coq.github.io/doc/V8.12.0/refman/language/extensions/implicit-arguments.html#implicit-argument-binders : (list (coq-first-abstr-without-space-regexp "\\[" ":[ a-zA-Z]") 1 'font-lock-variable-name-face) ))) "*Font-lock table for Coq terms.") (defconst coq-show-proof-diffs-regexp "\\`Show Proof\\(?: Diffs\\| Diffs removed\\)?\\.\\'") (defconst coq-save-command-regexp ;; FIXME: The surrounding grouping parens are probably not needed. (concat "\\`\\(\\(?:Time\\s-+\\|Timeout\\s-+[[:digit:]]+\\s-+\\)*\\_<" (regexp-opt coq-keywords-save t) "\\_>\\)")) (defconst coq-save-with-hole-regexp (concat "\\(?:Time\\s-+\\|Timeout\\s-+[[:digit:]]+\\s-+\\)*\\(" (regexp-opt coq-keywords-save-strict) "\\)\\s-+\\(" coq-id "\\)\\s-*\\.")) (defconst coq-goal-command-regexp (concat "\\`\\(?:" (mapconcat #'identity coq-keywords-goal "\\|") "\\)")) (defconst coq-goal-with-hole-regexp (concat "\\(" (mapconcat #'identity coq-keywords-goal "\\|") "\\)\\s-+\\(" coq-id "\\)\\s-*:?")) (defconst coq-decl-with-hole-regexp (concat "\\(" (mapconcat #'identity coq-keywords-decl "\\|") "\\)\\s-+\\(" coq-ids "\\)\\s-*:")) ;; (defconst coq-decl-with-hole-regexp ;; (if coq-variable-highlight-enable coq-decl-with-hole-regexp-1 'nil)) (defconst coq-defn-with-hole-regexp (concat "\\(" (mapconcat #'identity coq-keywords-defn "\\|") "\\)\\s-+\\(" coq-id "\\)")) ;; Any command can be prefixed with Local, Global of #[anyhting,anything,...] (defconst coq-command-prefix-regexp "\\(Local\\s-\\|Global\\s-\\|#[[][^]]*[]]\\)") ;; FIXME: incomplete (defun coq-add-command-prefix (reg) (concat "\\(" coq-command-prefix-regexp "\\)?" (mapconcat #'identity reg "\\|"))) (defconst coq-command-decl-regexp (coq-add-command-prefix coq-keywords-decl)) (defconst coq-command-defn-regexp (coq-add-command-prefix coq-keywords-defn)) ;; must match: ;; "with f x y :" (followed by = or not) ;; "with f x y (z:" (not followed by =) ;; BUT NOT: ;; "with f ... (x:=" ;; "match ... with .. => " (defconst coq-with-with-hole-regexp (concat "\\(with\\)\\s-+\\(" coq-id "\\)\\s-*\\([^=(.]*:\\|[^(]*(\\s-*" coq-id "\\s-*:[^=]\\)")) ;; marche aussi a peu pres ;; (concat "\\(with\\)\\s-+\\(" coq-id "\\)\\s-*\\([^(.]*:\\|.*)[^(.]*:=\\)")) ;;"\\\\|\\\\|\\" (defconst coq-context-marker-regexp (concat (regexp-opt '("ltac" "constr" "uconstr" "ltac1" "ltac2") 'symbols) ":")) ;; ;; font-lock ;; (defvar coq-font-lock-keywords-1 (append coq-font-lock-terms `((,coq-solve-tactics-regexp . 'coq-solve-tactics-face) (,coq-solve-cheat-tactics-regexp . 'coq-cheat-face) (,coq-keywords-regexp . 'font-lock-keyword-face) (,coq-reserved-regexp . 'font-lock-type-face) (,coq-tactics-regexp . 'proof-tactics-name-face) (,(mapconcat #'identity coq-tacticals "\\|") . 'proof-tacticals-name-face) (,(coq--regexp-alt-list-symb (list "Set" "Type" "Prop")) . 'font-lock-type-face) ("============================" . 'font-lock-keyword-face) (,coq-goal-with-hole-regexp 2 'font-lock-function-name-face) (,coq-context-marker-regexp 1 'coq-context-qualifier-face)) (if coq-variable-highlight-enable `((,coq-decl-with-hole-regexp 2 'font-lock-variable-name-face))) `((,coq-defn-with-hole-regexp 2 'font-lock-function-name-face) (,coq-with-with-hole-regexp 2 'font-lock-function-name-face) (,coq-save-with-hole-regexp 2 'font-lock-function-name-face) ;; Remove spurious variable and function faces on commas. (proof-zap-commas)))) ;; ", " is for multiple hypothesis displayed in v8.5. ;; exactly no space after start of line = hyps names in ;; Search results (and when we get a more compact display of hyps) ;; exactly 2 spaces at start of line = is for normal goal display at ;; start of line ;; exactly 3 spaces at start of line = hyps on the same line (Set ;; Printing Compact Goals". ;; If more than 3 spaces: not a hyp. ;; we used to have: "^ " for goals in debug mode but it does not seem ;; necessary anymore. (defvar coq-hyp-name-in-goal-or-response-regexp "\\(?:\\(?1:^\\)\\|\\(?1:^ \\)\\|\\(?:[^ ] \\)\\(?1: \\)\\)\\(?2:\\(?:[^\n :(),=]\\|, \\)+\\)\\(?: *:=?[ \n]\\|,$\\)" "Regexp matching hypothesis names in goal or response buffer. Subexpr 2 contains the real name of the function. Subexpr 1 contains the prefix context (spaces mainly) that is not part of another hypothesis.") ; Matches the end of the last hyp, before the ======... separator. (defvar coq-hyp-name-or-goalsep-in-goal-or-response-regexp (concat coq-hyp-name-in-goal-or-response-regexp "\\|\\(?1:^\\s-+========\\)")) (defun coq-find-first-hyp () (save-excursion (goto-char (point-min)) (search-forward-regexp coq-hyp-name-in-goal-or-response-regexp nil t) (match-beginning 2))) (defun coq-detect-hyps-positions (buf &optional limit) "Detect all hypotheses displayed in buffer BUF and returns positions. 5 positions are created for each hyp: (begcross beghypname endhypname beg end)." (with-current-buffer buf (save-excursion (goto-char (point-min)) (let ((res '())) (goto-char (point-min)) (while (search-forward-regexp coq-hyp-name-in-goal-or-response-regexp limit t) (let* ((str (replace-regexp-in-string "\\`[ \r\n\t]+\\|[ \r\n\t]+\\'" "" (match-string 2) t t)) (beghypname (match-beginning 2)) (beg (match-end 0)) (begcross (match-beginning 1)) (endhypname (match-end 2)) (splitstr (split-string str ",\\|,$\\|:" t)) ; 4th arg of split-string errors in emacs24 (end (save-excursion ; looking for next hyp and return its leftest part (search-forward-regexp coq-hyp-name-or-goalsep-in-goal-or-response-regexp nil t) (goto-char (match-beginning 1)) ;; if previous is a newline, don't include it i the overklay (when (looking-back "\\s-" (1- (point))) (goto-char (- (point) 1))) (point)))) ; if several hyp names, we name the overlays with the first hyp name (setq res (cons (cons (mapcar (lambda (s) (substring-no-properties s)) splitstr) (list begcross beghypname endhypname beg end)) res)))) res)))) ;; Don't look at the conclusion of the goal (defun coq-detect-hyps-positions-in-goals () (goto-char (point-min)) (coq-detect-hyps-positions (current-buffer) (if (search-forward-regexp "==========" nil t) (point) nil))) ;; We define a slightly different set of keywords for response buffer. (defvar coq-response-font-lock-keywords (append coq-font-lock-terms (list (cons coq-reserved-regexp 'font-lock-type-face) (cons coq-keywords-regexp 'font-lock-keyword-face) (cons coq-shell-eager-annotation-start 'proof-warning-face) (cons coq-error-regexp 'proof-error-face) (cons (coq--regexp-alt-list-symb (list "In environment" "The term" "has type")) 'proof-error-face) (cons (coq--regexp-alt-list-symb (list "Set" "Type" "Prop")) 'font-lock-type-face) (list (concat "[?]" coq-id) 0 'coq-question-mark-face) ;; highlight evars and Ltac variables (list coq-hyp-name-in-goal-or-response-regexp 2 'proof-declaration-name-face) (list "^\\([^ \n]+\\) \\(is defined\\)" (list 1 'font-lock-function-name-face t))))) (defvar coq-goals-font-lock-keywords (append coq-font-lock-terms (list (cons coq-reserved-regexp 'font-lock-type-face) (list (concat "[?]" coq-id) 0 'coq-question-mark-face) ;; highlight evars and Ltac variables (list coq-hyp-name-in-goal-or-response-regexp 2 'proof-declaration-name-face) (cons (coq--regexp-alt-list-symb (list "Set" "Type" "Prop")) 'font-lock-type-face)))) ;; Use this to evaluate code with "." being consisdered a symbol ;; constituent (better behavior for thing-at and maybe font-lock too, ;; for indentation we use ad hoc smie lexers). (defmacro coq-with-altered-syntax-table (&rest code) (declare (debug t)) `(unwind-protect (progn (modify-syntax-entry ?\. "_") ,@code) (modify-syntax-entry ?\. "."))) (defconst coq-generic-expression (mapcar (lambda (kw) (list (capitalize kw) ; (concat "\\<" kw "\\>" "\\s-+\\(\\w+\\)\\W" ) ; da: that seems buggy (kw already in \\<,\\>; want symbols, not words) (concat kw "\\s-+\\(\\_<\\(?:\\sw\\|\\s_\\)+\\_>\\)") 1)) (append coq-keywords-decl coq-keywords-defn coq-keywords-goal))) ;; Local Variables: *** ;; indent-tabs-mode: nil *** ;; End: *** (provide 'coq-syntax) ;;; coq-syntax.el ends here PG-4.5/coq/coq-system.el000066400000000000000000000734741426357011200151200ustar00rootroot00000000000000;;; coq-system.el --- common part of compilation feature -*- lexical-binding:t -*- ;; This file is part of Proof General. ;; Portions © Copyright 1994-2012 David Aspinall and University of Edinburgh ;; Portions © Copyright 2003-2021 Free Software Foundation, Inc. ;; Portions © Copyright 2001-2017 Pierre Courtieu ;; Portions © Copyright 2010, 2016 Erik Martin-Dorel ;; Portions © Copyright 2011-2013, 2016-2017 Hendrik Tews ;; Portions © Copyright 2015-2017 Clément Pit-Claudel ;; Authors: Hendrik Tews, Pierre Courtieu ;; Maintainer: Pierre.Courtieu ;; SPDX-License-Identifier: GPL-3.0-or-later ;;; Commentary: ;; ;; This file holds constants, options and some general functions for ;; setting coq command arguments. Some code is dedicated as a light ;; support for older versions of coq. ;; ;;; Code: (require 'proof) (require 'coq-mode) ;for coq-prog-name (defvar coq-prog-args) (defvar coq-debug) ;; Arbitrary arguments can already be passed through _CoqProject. ;; However this is not true for all assistants, so we don't modify the ;; (defpgcustom prog-args) declaration. (defun coq--string-list-p (obj) "Determine if OBJ is a list of strings." (or (null obj) (and (consp obj) (stringp (car obj)) (coq--string-list-p (cdr obj))))) (put 'coq-prog-args 'safe-local-variable #'coq--string-list-p) (defcustom coq-prog-env nil "List of environment settings to pass to Coq process. On Windows you might need something like: (setq coq-prog-env '(\"HOME=C:\\Program Files\\Coq\\\"))" :group 'coq) (defcustom coq-dependency-analyzer (if (executable-find "coqdep") "coqdep" (proof-locate-executable "coqdep" t '("C:/Program Files/Coq/bin"))) "Command to invoke coqdep." :type 'string :group 'coq) (defcustom coq-compiler (if (executable-find "coqc") "coqc" (proof-locate-executable "coqc" t '("C:/Program Files/Coq/bin"))) "Command to invoke the coq compiler." :type 'string :group 'coq) (defcustom coq-pinned-version nil "Manual coq version override (rarely needed). There should be no need to set this value unless you use old trunk versions from the Coq github repository. For Coq versions with decent version numbers Proof General detects the version automatically and adjusts itself. This variable should contain nil or a version string." :type 'string :group 'coq) (defvar coq-autodetected-version nil "Version of Coq, as autodetected by `coq-autodetect-version'.") (defvar coq-autodetected-help nil "Options of Coq, as autodetected by `coq-autodetect-options'. This variable contains the output of \"coqtop -help\"") ;;; error symbols ;; coq-unclassifiable-version ;; ;; This error is signaled with one data item -- the bad version string (put 'coq-unclassifiable-version 'error-conditions '(error coq-unclassifiable-version)) (put 'coq-unclassifiable-version 'error-message "Proof General cannot classify your Coq version") ;;; version detection code (defun coq-version (&optional may-recompute) "Return the precomputed version of the current Coq toolchain. With MAY-RECOMPUTE, try auto-detecting it if it isn't available." (or coq-pinned-version coq-autodetected-version (when may-recompute (coq-autodetect-version)))) (defun coq-show-version () "Show the version of Coq currently in use. If it doesn't look right, try `coq-autodetect-version'." (interactive) (let ((version (coq-version nil))) (if version (message "Using Coq v%s" coq-autodetected-version) (message "Coq version unknown at this time. Use `coq-autodetect-version' to autodetect.")))) (defun coq-callcoq (option &optional expectedretv) "Call coqtop with the given OPTION and return the output. The given option should make coqtop return immediately. Optionally check the return code and return nil if the check fails. Return also nil on other kinds of errors (e.g., `coq-prog-name' not found). This function supports calling coqtop via tramp." (let ((coq-command (or coq-prog-name "coqtop")) retv) (condition-case nil (with-temp-buffer (setq retv (if option (process-file coq-command nil t nil option) (process-file coq-command nil t nil))) (if (or (not expectedretv) (equal retv expectedretv)) (buffer-string))) (error nil)))) (defun coq-autodetect-version (&optional interactive-p) "Detect and record the version of Coq currently in use. Interactively (with INTERACTIVE-P), show that number." (interactive '(t)) (setq coq-autodetected-version nil) (let* ((str (coq-callcoq "-v" 0)) (mtch (and str (string-match "version \\([^ \r\n]+\\)" str)))) (when mtch (setq coq-autodetected-version (match-string 1 str)))) (when interactive-p (coq-show-version)) coq-autodetected-version) (defun coq-autodetect-help (&optional _interactive-p) "Record the output of coqtop -help in `coq-autodetected-help'." (interactive '(t)) (let ((coq-output (coq-callcoq "-help"))) (setq coq-autodetected-help (or coq-output "")))) (defun coq--version< (v1 v2) "Compare Coq versions V1 and V2." ;; -snapshot is only supported by Emacs 24.5, not 24.3 (let ((version-regexp-alist `(("^[-_+ ]?snapshot$" . -4) ("^pl$" . 0) ,@version-regexp-alist))) (version< v1 v2))) (defcustom coq-pre-v85 nil "Deprecated. Use `coq-pinned-version' if you want to bypass the version detection that Proof General does automatically." :type 'boolean :group 'coq) (defun coq--pre-v85 () "Return non-nil if the auto-detected version of Coq is < 8.5. Returns nil if the version can't be detected." (let ((coq-version-to-use (or (coq-version t) "8.5"))) (condition-case err (coq--version< coq-version-to-use "8.5snapshot") (error (cond ((equal (substring (cadr err) 0 15) "Invalid version") (signal 'coq-unclassifiable-version coq-version-to-use)) (t (signal (car err) (cdr err)))))))) (defun coq--post-v86 () "Return t if the auto-detected version of Coq is >= 8.6. Return nil if the version cannot be detected." (let ((coq-version-to-use (or (coq-version t) "8.5"))) (condition-case err (not (coq--version< coq-version-to-use "8.6")) (error (cond ((equal (substring (cadr err) 0 15) "Invalid version") (signal 'coq-unclassifiable-version coq-version-to-use)) (t (signal (car err) (cdr err)))))))) (defun coq--post-v810 () "Return t if the auto-detected version of Coq is >= 8.10. Return nil if the version cannot be detected." (let ((coq-version-to-use (or (coq-version t) "8.9"))) (condition-case err (not (coq--version< coq-version-to-use "8.10alpha")) (error (cond ((equal (substring (cadr err) 0 15) "Invalid version") (signal 'coq-unclassifiable-version coq-version-to-use)) (t (signal (car err) (cdr err)))))))) (defun coq--post-v811 () "Return t if the auto-detected version of Coq is >= 8.11. Return nil if the version cannot be detected." (let ((coq-version-to-use (or (coq-version t) "8.10"))) (condition-case err (not (coq--version< coq-version-to-use "8.11")) (error (cond ((equal (substring (cadr err) 0 15) "Invalid version") (signal 'coq-unclassifiable-version coq-version-to-use)) (t (signal (car err) (cdr err)))))))) (defun coq--supports-topfile () "Return t if \"-topfile\" appears in coqtop options" (string-match "-topfile" coq-autodetected-help) ) (defcustom coq-use-makefile nil "Whether to look for a Makefile to attempt to guess the command line. Set to t if you want this feature, but note that it is deprecated." :type 'string :group 'coq) (defcustom coq-www-home-page "http://coq.inria.fr/" "Coq home page URL." :type 'string :group 'coq) ;;; utility functions for variables (defun coq-load-path-safep (path) "Check if PATH is a safe value for `coq-load-path'." (and (listp path) (cl-every (lambda (entry) (or (stringp entry) (and (listp entry) (eq (car entry) 'rec) (cl-every 'stringp (cdr entry)) (equal (length entry) 3)) (and (listp entry) (eq (car entry) 'nonrec) (cl-every 'stringp (cdr entry)) (equal (length entry) 3)) (and (listp entry) (eq (car entry) 'recnoimport) (cl-every 'stringp (cdr entry)) (equal (length entry) 3)) (and (listp entry) (eq (car entry) 'ocamlimport) (cl-every 'stringp (cdr entry)) (equal (length entry) 2)) (and (listp entry) (cl-every 'stringp entry) (equal (length entry) 2)))) path))) (defcustom coq-load-path nil "Non-standard coq library load path. This list specifies the LoadPath extension for coqdep, coqc and coqtop. Usually, the elements of this list are strings (for \"-I\") or lists of two strings (for \"-R\" dir path and \"-Q\" dir path). The possible forms of elements of this list correspond to the 4 forms of include options (`-I' `-Q' and `-R'). An element can be - A list of the form `(\\='ocamlimport dir)', specifying (in 8.5) a directory to be added to ocaml path (`-I'). - A list of the form `(\\='rec dir path)' (where dir and path are strings) specifying a directory to be recursively mapped to the logical path `path' (`-R dir path'). - A list of the form `(\\='recnoimport dir path)' (where dir and path are strings) specifying a directory to be recursively mapped to the logical path `path' (`-Q dir path'), but not imported (modules accessible for import with qualified names only). Note that -Q dir \"\" has a special, nonrecursive meaning. - A list of the form (8.4 only) `(\\='nonrec dir path)', specifying a directory to be mapped to the logical path 'path' ('-I dir -as path'). For convenience the symbol `rec' can be omitted and entries of the form `(dir path)' are interpreted as `(rec dir path)'. A plain string maps to -Q ... \"\" in 8.5, and -I ... in 8.4. Under normal circumstances this list does not need to contain the coq standard library or \".\" for the current directory (see `coq-load-path-include-current'). WARNING: if you use coq <= 8.4, the meaning of these options is not the same (-I is for coq path)." :type '(repeat (choice (string :tag "simple directory without path (-Q \"\") in 8.5, -I in 8.4") (list :tag "recursive directory with path (-R ... ...)" (const rec) (string :tag "directory") (string :tag "log path")) (list :tag "recursive directory without recursive import with path (-Q ... ...)" (const recnoimport) (string :tag "directory") (string :tag "log path")) (list :tag "compatibility for of -I (-I ... -as ... in coq<=8.4)" (const nonrec) (string :tag "directory") (string :tag "log path")) (list :tag "ocaml path (-I ...)" (const ocamlimport) (string :tag "directory") (string :tag "log path")))) :safe 'coq-load-path-safep :group 'coq-auto-compile) (make-variable-buffer-local 'coq-load-path) (defcustom coq-load-path-include-current t "If t, let coqdep search the current directory too. Should be t for normal users. If t, pass -Q dir \"\" to coqdep when processing files in directory \"dir\" in addition to any entries in `coq-load-path'. This setting is only relevant with Coq < 8.5." :type 'boolean :safe 'booleanp :group 'coq-auto-compile) (make-obsolete-variable 'coq-load-path-include-current "Coq 8.5 does not need it" "4.3") (defun coq-option-of-load-path-entry (entry &optional pre-v85) "Translate a single ENTRY from `coq-load-path' into options. See `coq-load-path' for the possible forms of ENTRY and to which options they are translated. Use a non-nil PRE-V85 flag to request compatibility handling of flags." (if pre-v85 ;; FIXME Which base directory do we expand against? Should the entries of ;; load-path just always be absolute? ;; NOTE we don't handle 'recnoimport in 8.4, and we don't handle 'nonrec ;; in 8.5. (pcase entry ((or (and (pred stringp) dir) `(ocamlimport ,dir)) (list "-I" (expand-file-name dir))) (`(nonrec ,dir ,alias) (list "-I" (expand-file-name dir) "-as" alias)) ((or `(rec ,dir ,alias) `(,dir ,alias)) (list "-R" (expand-file-name dir) alias))) (pcase entry ((and (pred stringp) dir) (list "-Q" (expand-file-name dir) "")) (`(ocamlimport ,dir) (list "-I" (expand-file-name dir))) (`(recnoimport ,dir ,alias) (list "-Q" (expand-file-name dir) alias)) ((or `(rec ,dir ,alias) `(,dir ,alias)) (list "-R" (expand-file-name dir) alias))))) (defun coq-include-options (loadpath &optional current-directory pre-v85) "Build the base list of include options for coqc, coqdep and coqtop. The options list includes all entries from argument LOADPATH \(which should be `coq-load-path' of the buffer that invoked the compilation) prefixed with suitable options and (for coq<8.5), if `coq-load-path-include-current' is enabled, the directory base of FILE. The resulting list is fresh for every call, callers can append more arguments with `nconc'. CURRENT-DIRECTORY should be an absolute directory name. It can be nil if `coq-load-path-include-current' is nil. A non-nil PRE-V85 flag requests compatibility handling of flags." (unless (coq-load-path-safep loadpath) (error "Invalid value in coq-load-path")) (when (and pre-v85 coq-load-path-include-current) (cl-assert current-directory) (push current-directory loadpath)) (cl-loop for entry in loadpath append (coq-option-of-load-path-entry entry pre-v85))) (defun coq--options-test-roundtrip-1 (coq-project parsed pre-v85) "Run a sanity check on COQ-PROJECT's PARSED options. If PRE-V85 is non-nil, use compatibility mode." (let* ((concatenated (apply #'append parsed)) (coq-load-path-include-current nil) (extracted (coq--extract-load-path parsed nil)) (roundtrip (coq-include-options extracted nil pre-v85))) (princ (format "[%s] with compatibility flag set to %S: " coq-project pre-v85)) (if (equal concatenated roundtrip) (princ "OK\n") (princ (format "Failed.\n:: Original: %S\n:: LoadPath: %S\n:: Roundtrip: %S\n" concatenated extracted roundtrip))))) (defun coq--options-test-roundtrip (coq-project &optional v85-only) "Run a sanity check on COQ-PROJECT. If V85-ONLY is non-nil, do not check the compatibility code." (let ((parsed (coq--read-options-from-project-file coq-project))) (coq--options-test-roundtrip-1 coq-project parsed nil) (unless v85-only (coq--options-test-roundtrip-1 coq-project parsed t)))) (defun coq--options-test-roundtrips () "Run sanity tests on coq-project parsing code. More precisely, check that parsing and reprinting the include options of a few coq-project files does the right thing." (with-output-to-temp-buffer "*tests*" (coq--options-test-roundtrip "-Q /test Test") (coq--options-test-roundtrip "-Q /test \"\"") (coq--options-test-roundtrip "-R /test Test") (coq--options-test-roundtrip "-I /test"))) (defun coq-coqdep-prog-args (loadpath &optional current-directory pre-v85) "Build a list of options for coqdep. LOADPATH, CURRENT-DIRECTORY, PRE-V85: see `coq-include-options'." (coq-include-options loadpath current-directory pre-v85)) (defun coq--clean-prog-args (args) "Return ARGS without the entries added by `coq-coqtop-prog-args'. Such entries are currently -emacs and -topfile." (pcase args ((or `("-emacs" . ,rest) `("-topfile" . (,(pred (apply-partially #'equal buffer-file-name)) . ,rest))) (coq--clean-prog-args rest)) (`(,car . ,cdr) (cons car (coq--clean-prog-args cdr))) (_ args))) (defun coq-coqc-prog-args (loadpath &optional current-directory pre-v85) "Build a list of options for coqc. LOADPATH, CURRENT-DIRECTORY, PRE-V85: see `coq-include-options'." ;; coqtop always adds the current directory to the LoadPath, so don't ;; include it in the -Q options. (append (coq--clean-prog-args coq-prog-args) (let ((coq-load-path-include-current nil)) ; Not needed in >=8.5beta3 (coq-coqdep-prog-args loadpath current-directory pre-v85)))) ;;XXXXXXXXXXXXXX ;; coq-coqtop-prog-args is the user-set list of arguments to pass to ;; Coq process, see 'defpacustom prog-args' in pg-custom.el for ;; documentation. ;; Regular files should be of the form "valid_modulename.v" coq ;; accepts lots of things as letter, this is probably much stricter. ;; In practice it should be OK though, except maybe for non latin ;; characters. (defun coq-regular-filename-p (s) (let ((noext (file-name-base s))) (string-match-p "\\`[[:alpha:]_][[:alnum:]_]*\\'" noext))) (defun coq-coqtop-prog-args (loadpath &optional current-directory pre-v85) ;; coqtop always adds the current directory to the LoadPath, so don't ;; include it in the -Q options. This is not true for coqdep. "Build a list of options for coqc. LOADPATH, CURRENT-DIRECTORY, PRE-V85: see `coq-coqc-prog-args'." (let ((topfile-supported (coq--supports-topfile))) (append ;; it is better to inform coqtop of the name of the current module ;; using the -topfile option, so that coqtop understands references ;; to it. But don't insist if this would fail (because of wrong ;; file name): Some people want to script .v files without ever ;; compiling them. (if (and topfile-supported buffer-file-name (coq-regular-filename-p buffer-file-name)) (cons "-topfile" (cons buffer-file-name nil)) (if (and topfile-supported buffer-file-name) (message "Warning: this Coq buffer is probably not compilable \ because of its name, no -topfile option set.")) nil) (cons "-emacs" (coq-coqc-prog-args loadpath current-directory pre-v85))))) (defun coq-prog-args () "Recompute `coq-load-path' before calling `coq-coqtop-prog-args'." (coq-load-project-file) (coq-autodetect-version) (coq-autodetect-help) (coq-coqtop-prog-args coq-load-path)) (defcustom coq-use-project-file t "If t, when opening a Coq file read the dominating _CoqProject. If t, when a Coq file is opened, Proof General will look for a project file (see `coq-project-filename') somewhere in the current directory or its parent directories. If there is one, its contents are read and used to determine the arguments that must be given to coqtop. In particular it sets the load path (including the -R lib options) (see `coq-load-path')." :type 'boolean :safe 'booleanp :group 'coq) (defcustom coq-project-filename "_CoqProject" "The name of coq project file. The coq project file of a coq development (cf. Coq documentation on \"makefile generation\") should contain the arguments given to coq_makefile. In particular it contains the -I and -R options (preferably one per line). If `coq-use-coqproject' is t (default) the content of this file will be used by Proof General to infer the `coq-load-path' and the `coq-prog-args' variables that set the coqtop invocation by Proof General. This is now the recommended way of configuring the coqtop invocation. Local file variables may still be used to override the coq project file's configuration. .dir-locals.el files also work and override project file settings." :type 'string :safe 'stringp :group 'coq) (defun coq-find-project-file () "Return '(buf alreadyopen) where buf is the buffer visiting coq project file. alreadyopen is t if buffer already existed." (when buffer-file-name (let* ((projectfiledir (locate-dominating-file buffer-file-name coq-project-filename))) (when projectfiledir (let* ((projectfile (expand-file-name coq-project-filename projectfiledir)) ;; we store this intermediate result to know if we have to kill ;; the coq project buffer at the end (projectbufferalreadyopen (find-buffer-visiting projectfile)) (projectbuffer (or projectbufferalreadyopen (find-file-noselect projectfile t t)))) (list projectbuffer projectbufferalreadyopen)))))) (defconst coq--project-file-separator "[\r\n[:space:]]+") (defconst coq--makefile-switch-arities '(("-R" . 2) ("-Q" . 2) ("-I" . 1) ("-arg" . 1) ("-opt" . 0) ("-byte" . 0))) (defun coq--read-one-option-from-project-file (switch arity raw-args) "Cons SWITCH with ARITY arguments from RAW-ARGS. If ARITY is nil, return SWITCH." (if arity (let ((arguments (condition-case-unless-debug nil (cl-subseq raw-args 0 arity) (warn "Invalid _CoqProject: not enough arguments for %S" switch)))) (cons switch arguments)) switch)) (defun coq--read-options-from-project-file (contents) "Read options from CONTENTS of _CoqProject. Returns a mixed list of option-value pairs and strings." (let ((raw-args (split-string-and-unquote contents coq--project-file-separator)) (options nil)) (while raw-args (let* ((switch (pop raw-args)) (arity (cdr (assoc switch coq--makefile-switch-arities)))) (push (coq--read-one-option-from-project-file switch arity raw-args) options) (setq raw-args (nthcdr (or arity 0) raw-args)))) (nreverse options))) ; Order of options is important sometimes (Cf. #7980) (defun coq--extract-prog-args (options) "Extract coqtop arguments from _CoqProject options OPTIONS. OPTIONS is a list or conses (switch . argument) and strings. Note that the semantics of the -arg flags in coq project files are weird: -arg \"a b\" means pass a and b, separately, to coqtop. But -arg \"'a b'\" means to pass a and b together." (let ((args nil)) (dolist (opt options) (pcase opt ((or "-byte" "-op") (push opt args)) (`("-arg" ,concatenated-args) (if (and (string-prefix-p "'" concatenated-args) (string-suffix-p "'" concatenated-args)) (setq args (append args (list (substring concatenated-args 1 -1)))) (setq args (append args (split-string-and-unquote concatenated-args coq--project-file-separator))))))) (cons "-emacs" args))) (defun coq--extract-load-path-1 (option base-directory) "Convert one _CoqProject OPTION, relative to BASE-DIRECTORY." (pcase option (`("-I" ,path) (list 'ocamlimport (expand-file-name path base-directory))) (`("-R" ,path ,alias) (list 'rec (expand-file-name path base-directory) alias)) (`("-Q" ,path ,alias) (list 'recnoimport (expand-file-name path base-directory) alias)))) (defun coq--extract-load-path (options base-directory) "Extract loadpath from _CoqProject options OPTIONS. OPTIONS is a list or conses (switch . arguments) and strings. Paths are taken relative to BASE-DIRECTORY." (cl-loop for opt in options for extracted = (coq--extract-load-path-1 opt base-directory) when extracted collect extracted)) ;; optional args allow to implement the precedence of dir/file local vars (defun coq-load-project-file-with-avoid (&optional avoidargs avoidpath) "Set `coq-prog-args' and `coq-load-path' from _CoqProject. If AVOIDARGS or AVOIDPATH is set, do not set the corresponding variable." (pcase-let* ((`(,proj-file-buf ,no-kill) (coq-find-project-file))) (if (not proj-file-buf) (message "Coq project file not detected.") (let* ((contents (with-current-buffer proj-file-buf (buffer-string))) (options (coq--read-options-from-project-file contents)) (proj-file-name (buffer-file-name proj-file-buf)) (proj-file-dir (file-name-directory proj-file-name)) (proj-file-local-dir (or (file-remote-p proj-file-dir 'localname) proj-file-dir))) (unless avoidargs (setq coq-prog-args (coq--extract-prog-args options))) (unless avoidpath (setq coq-load-path (coq--extract-load-path options proj-file-local-dir))) (let ((msg (cond ((and avoidpath avoidargs) "Coqtop args and load path") (avoidpath "Coqtop load path") (avoidargs "Coqtop args") (t "")))) (message "Coq project file detected: %s%s." proj-file-name (if (or avoidpath avoidargs) (concat "\n(" msg " overridden by dir/file local values)") ""))) (when coq-debug (message "coq-prog-args: %S" coq-prog-args) (message "coq-load-path: %S" coq-load-path)) (unless no-kill (kill-buffer proj-file-buf)))))) (defun coq-load-project-file () "Set `coq-prog-args' and `coq-load-path' according to _CoqProject file. Obeys `coq-use-project-file'. Note that if a variable is already set by dir/file local variables, this function will not override its value. See `coq-project-filename' to change the name of the project file, and `coq-use-project-file' to disable this feature." (when coq-use-project-file ;; Let us reread dir/file local vars, in case the user mmodified them (let* ((oldargs (assoc 'coq-prog-args file-local-variables-alist)) (oldpath (assoc 'coq-load-path file-local-variables-alist))) (coq-load-project-file-with-avoid oldargs oldpath)))) (defun coq-load-project-file-rehack () "Reread file/dir local vars and call `coq-load-project-file'. Does nothing if `coq-use-project-file' is nil." (when coq-use-project-file ;; Let us reread dir/file local vars, in case the user mmodified them (hack-local-variables) ;; Useless since coq-load-project-file is in hack-local-variables-hook: ;;(coq-load-project-file) )) ;; Since coq-project-filename can be set via .dir-locals.el or file variable, ;; we need to call coq-load-coq-project-file only *after* local variables are ;; set. But coq-mode-hook is called BEFORE local variables are read. Therefore ;; coq-load-coq-project-file is added to hack-local-variables-hook instead. To ;; avoid adding for other modes , the setting is performed inside ;; coq-mode-hook. This is described in www.emacswiki.org/emacs/LocalVariables ;; TODO: also read COQBIN somewhere? ;; Note: this does not need to be at a particular place in the hook, but we ;; need to make this hook local. ;; hack-local-variables-hook seems to hack local and dir local vars. (add-hook 'coq-mode-hook (lambda () (add-hook 'hack-local-variables-hook #'coq-load-project-file nil t))) ; detecting coqtop args should happen at the last moment before ; calling the process. In particular it should ahppen after that ; proof-prog-name-ask is performed, this hook is at the right place. (add-hook 'proof-shell-before-process-hook (lambda () ;; It seems coq-prog-name and proof-prog-name are not correctly linked ;; so let us make sure they are the same before computing options (setq coq-prog-name proof-prog-name) (setq coq-prog-args (coq-prog-args)))) ;; smie's parenthesis blinking is too slow, let us have the default one back (add-hook 'coq-mode-hook (lambda () (when (and (fboundp 'show-paren--default) (boundp 'show-paren-data-function)) (setq show-paren-data-function #'show-paren--default)))) (defun coq-toggle-use-project-file () (interactive) (setq coq-use-project-file (not coq-use-project-file)) (when coq-use-project-file (coq-load-project-file-rehack)) ;; FIXME What should we do when disabling project file? since ;; local variables override project file anyway, reading them ;; again is useless. Let us do nothing. ;;(setq coq-load-path nil) ;;(setq coq-prog-args nil) ) (provide 'coq-system) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; To guess the command line options ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; OBSOLETE, should take _CoqProject into account. (defun coq-guess-command-line (filename) "Guess the right command line options to compile FILENAME using `make -n'. This function is obsolete, the recommended way of setting the coqtop options is to use a _Coqproject file as described in coq documentation. ProofGeneral reads this file and sets compilation options according to its contents. See `coq-project-filename'. Per file configuration may then be set using local file variables." (if (local-variable-p 'coq-prog-name (current-buffer)) coq-prog-name (let* ((dir (or (file-name-directory filename) ".")) (makedir (cond ((file-exists-p (concat dir "Makefile")) ".") ;; ((file-exists-p (concat dir "../Makefile")) "..") ;; ((file-exists-p (concat dir "../../Makefile")) "../..") (t nil)))) (if (and coq-use-makefile makedir) (let* ;;TODO, add dir name when makefile is in .. or ../.. ;; ;; da: FIXME: this code causes problems if the make ;; command fails. It should not be used by default ;; and should be made more robust. ;; ((compiled-file (concat (substring filename 0 (string-match ".v$" filename)) ".vo")) (command (shell-command-to-string (concat "cd " dir ";" "make -n -W " filename " " compiled-file "| sed s/coqc/coqtop/")))) (message command) (setq coq-prog-args nil) (concat (substring command 0 (string-match " [^ ]*$" command)) "-emacs")) coq-prog-name)))) ;;; coq-system.el ends here PG-4.5/coq/coq-unicode-tokens.el000066400000000000000000000175311426357011200165130ustar00rootroot00000000000000;;; coq-unicode-tokens.el --- (No) Tokens for Unicode Tokens package -*- coding: utf-8; lexical-binding: t; -*- ;; This file is part of Proof General. ;; Portions © Copyright 1994-2012 David Aspinall and University of Edinburgh ;; Portions © Copyright 2003-2021 Free Software Foundation, Inc. ;; Portions © Copyright 2001-2017 Pierre Courtieu ;; Portions © Copyright 2010, 2016 Erik Martin-Dorel ;; Portions © Copyright 2011-2013, 2016-2017 Hendrik Tews ;; Portions © Copyright 2015-2017 Clément Pit-Claudel ;; Author: David Aspinall ;;; Commentary: ;; ;; This file is loaded by `proof-unicode-tokens.el'. ;; ;; It sets the variables defined at the top of unicode-tokens.el, ;; unicode-tokens- is set from coq-. See the corresponding ;; variable for documentation. ;; ;; For Coq, there is no dedicated token syntax, it's probably ;; preferable to use UTF-8 notation directly (see utf8.v). ;; ;; On the other hand, for easily portable files, one can fix ;; ordinary character sequences as tokens, like the old X-Symbol ;; configuration for Coq did. ;; ;; The configuration here is an example which (for added confusion) ;; does both things. Keyboard shortcuts get replaced by "real" ;; Unicode characters, whereas ordinary character sequences are ;; displayed as those characters. ;; ;; Recommended ways to work: ;; ;; 1) UTF-8 buffers: ☑ Show Symbol Tokens (ON) ;; ☑ Enable Shortcuts (ON) ;; ;; 2) ASCII buffers: ☐ Enable Shortcuts (OFF) ;; ☐ Show Symbol Tokens (OFF) ;; ;; The (confusing!) default is to enable shortcuts and display tokens. ;; Use Tokens -> Highlight Real Unicode Chars to help understand the ;; buffer contents. Hovering on a token shows its underlying text. (require 'proof-unicode-tokens) ;;; Code: (defconst coq-token-format "") ; Let generic code do the job (defconst coq-token-match nil) (defconst coq-hexcode-match nil) (defun coq-unicode-tokens-set (sym val) "Change a Unicode Tokens configuration variable and restart." (set-default sym val) (when (featurep 'coq-unicode-tokens) ; not during loading (proof-unicode-tokens-configure))) (defcustom coq-token-symbol-map '(;; Greek letters ("alpha" "α") ("beta" "β") ("gamma" "γ") ("delta" "δ") ("epsilon" "ε") ("zeta" "ζ") ("eta" "η") ("theta" "θ") ("iota" "ι") ("kappa" "κ") ("lambda" "λ") ("mu" "μ") ("nu" "ν") ("xi" "ξ") ("pi" "π") ("rho" "ρ") ("sigma" "σ") ("tau" "τ") ("upsilon" "υ") ("phi" "ϕ") ("chi" "χ") ("psi" "ψ") ("omega" "ω") ("Gamma" "Γ") ("Delta" "Δ") ("Theta" "Θ") ("Lambda" "Λ") ("Xi" "Ξ") ("Pi" "Π") ("Sigma" "Σ") ("Upsilon" "Υ") ("Phi" "Φ") ("Psi" "Ψ") ("Omega" "Ω") ;; logic ("forall" "∀") ("exists" "∃") ("nat" "ℕ" type) ("complex" "ℂ" type) ("real" "ℝ" type) ("int" "ℤ" type) ("rat" "ℚ" type) ("bool" "B" underline type) ("false" "false" bold sans) ("true" "true" bold sans) ;; example tokens used in Benjamin C. Pierce et al's ;; Software Foundations course ("WHILE" "WHILE" bold sans) ("DO" "DO" bold sans) ("END" "END" bold sans) ("SKIP" "SKIP" bold sans) ("THEN" "THEN" bold sans) ("ELSE" "ELSE" bold sans) ("IFB" "IFB" bold sans) ("FI" "FI" bold sans) ("{{" "⦃" bold) ("}}" "⦄" bold) ;; symbols without utf8.v (but also without context) ("lhd" "⊲") ("rhd" "⊳") ("<=" "≤") (">=" "≥") ("=>" "⇒") ("->" "→") ; or ⟶ or ⟹ if you prefer ("<-" "←") ; or ⟵ or ⟸ ("<->" "↔") ; or ⟷ ... ("++" "⧺") ("<<" "《") (">>" "》") ;; Equivalence ("===" "≡") ; equiv ("=/=" "≢") ; complement equiv ("=~=" "≅") ; pequiv ("==b" "≡") ; NB: same presentation ("<>b" "≢") ; NB: same presentation ;; ("==" "≡") ; Setoid equiv (NB: same presentation, pot confusing) ("-->" "⟹-") ; Morphisms ("++>" "⟹+") ; ("==>" "⟹") ; (":=" "≔") ("|-" "⊢") ("<>" "≠") ("-|" "⊣") ("\\/" "∨") ("/\\" "∧") ("~" "¬") ;; A dirty hack for the goals window, shouldn't be input syntax! ("============================" "⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯" bold tactical) ) ;; an alist of token name, unicode char sequence "Table mapping Coq tokens to Unicode strings. You can adjust this table to add entries, or to change entries for glyphs that not are available in your Emacs or chosen font. When a file is visited, tokens are replaced by the strings in this table. When the file is saved, the reverse is done. The string mapping can be anything, but should be such that tokens can be uniquely recovered from a decoded text; otherwise results will be undefined when files are saved." :type 'unicode-tokens-token-symbol-map :set #'coq-unicode-tokens-set :group 'coq :tag "Coq Unicode Token Mapping") (defcustom coq-shortcut-alist '(; short cut, REAL unicode string ("<>" . "⋄") ("|>" . "⊳") ("\\/" . "∨") ("/\\" . "∧") ("+O" . "⊕") ("-O" . "⊖") ("xO" . "⊗") ("/O" . "⊘") ;(".O" . "⊙") ; bad interaction with electric terminatore and double hit terminator ("|+" . "†") ("|++" . "‡") ("<=" . "≤") ("|-" . "⊢") (">=" . "≥") ("-|" . "⊣") ("||" . "∥") ("==" . "≡") ("~=" . "≃") ("~~~" . "≍") ("~~" . "≈") ("~==" . "≅") ("|<>|" . "⋈") ("|=" . "⊨") ("=." . "≐") ("_|_" . "⊥") ("=/" . "≱") ("=/" . "≠") ("==/" . "≢") ("~/" . "≁") ("~=/" . "≄") ("~~/" . "≉") ("~==/" . "≇") ("<-" . "←") ("<=" . "⇐") ("->" . "→") ("=>" . "⇒") ("<->" . "↔") ("<=>" . "⇔") ("|->" . "↦") ("<--" . "⟵") ("<==" . "⟸") ("-->" . "⟶") ("==>" . "⟹") ("<==>" . "⟷") ("|-->" . "⟼") ("<--" . "←⎯") ("<-->" . "⟷") ("<<" . "⟪") ("[|" . "⟦") (">>" . "⟫") ("|]" . "⟧") ("``" . "”") ("''" . "“") ("--" . "–") ("---" . "—") ("''" . "″") ("'''" . "‴") ("''''" . "⁗") (":=" . "≔") ;; some word shortcuts, started with backslash otherwise ;; too annoying, perhaps. ("\\int" . "ℤ") ("\\rat" . "ℚ") ("\\complex" . "ℂ") ("\\euro" . "€") ("\\yen" . "¥") ("\\cent" . "¢")) "Shortcut key sequence table for Unicode strings. You can adjust this table to add more entries, or to change entries for glyphs that not are available in your Emacs or chosen font. These shortcuts are only used for input; no reverse conversion is performed. This means that the target strings need to have a defined meaning to be useful." :type '(repeat (cons (string :tag "Shortcut sequence") (string :tag "Unicode string"))) :set #'coq-unicode-tokens-set :group 'coq :tag "Coq Unicode Input Shortcuts") ;; ;; Controls ;; (defconst coq-control-char-format-regexp ;; FIXME: fix Coq identifier syntax below ;; "\\(\s_*%s\s_*\\)\\([a-zA-Z0-9']+\\)" "\\(%s\\)\\(\\sw*\\)" ) ;; (defconst coq-control-char-format " %s ") (defconst coq-control-characters '(("Subscript" "__" sub) ("Superscript" "^^" sup))) ;(defconst coq-control-region-format-regexp "\\(\s*%s\{\\)\\([^}]*\\)\\(\}\s*\\)") (defconst coq-control-region-format-regexp "\\(%s{\\)\\([^}]*\\)\\(}\\)") (defconst coq-control-regions '(("Subscript" "," "" sub) ("Subscript" "_" "" sub) ("Superscript" "^" "" sup) ; ("Bold" "BOLD" "" bold) ; ("Italic" "ITALIC" "" italic) ; ("Script" "SCRIPT" "" script) ; ("Frakt" "FRACT" "" frakt) ; ("Roman" "ROMAN" "" serif) )) (provide 'coq-unicode-tokens) ;;; coq-unicode-tokens.el ends here PG-4.5/coq/coq.el000066400000000000000000004316471426357011200135760ustar00rootroot00000000000000;;; coq.el --- Major mode for Coq proof assistant -*- coding: utf-8; lexical-binding: t; -*- ;; This file is part of Proof General. ;; Portions © Copyright 1994-2012 David Aspinall and University of Edinburgh ;; Portions © Copyright 2003-2021 Free Software Foundation, Inc. ;; Portions © Copyright 2001-2017 Pierre Courtieu ;; Portions © Copyright 2010, 2016 Erik Martin-Dorel ;; Portions © Copyright 2011-2013, 2016-2017 Hendrik Tews ;; Portions © Copyright 2015-2017 Clément Pit-Claudel ;; Authors: Healfdene Goguen, Pierre Courtieu ;; Maintainer: Pierre Courtieu ;; SPDX-License-Identifier: GPL-3.0-or-later ;;; Commentary: ;; ;;; Code: ;; PG doesn't support using several backends at the same time. ;; FIXME: We really should set proof-assistant just because this file is ;; loaded (e.g. we should set it within coq-pg-setup instead), but ;; defpacustom and various others fail if executed before proof-assistant ;; is set. (if (and (boundp 'proof-assistant) (member proof-assistant '(nil "" "Coq" "coq"))) (proof-ready-for-assistant 'coq) (message "Coq-PG error: Proof General already in use for %s" proof-assistant)) (require 'cl-lib) (require 'span) (eval-when-compile (require 'proof-utils) (require 'span) (require 'outline) (require 'newcomment) (require 'etags)) (defvar proof-info) ; dynamic scope in proof-tree-urgent-action (defvar action) ; dynamic scope in coq-insert-as stuff (defvar string) ; dynamic scope in coq-insert-as stuff (defvar old-proof-marker) (defvar coq-keymap) (defvar coq-one-command-per-line) (defvar coq-auto-insert-as) ; defpacustom (defvar coq-time-commands) ; defpacustom (defvar coq-use-project-file) ; defpacustom (defvar coq-use-editing-holes) ; defpacustom (defvar coq-hide-additional-subgoals) (require 'proof) (require 'coq-system) ; load path, option, project file etc. (require 'coq-syntax) ; font-lock, syntax categories (tactics, commands etc) (require 'coq-local-vars) ; setting coq args via file variables ; (prefer _CoqProject file instead) (require 'coq-abbrev) ; abbrev and coq specific menu (require 'coq-seq-compile) ; sequential compilation of Requires (require 'coq-par-compile) ; parallel compilation of Requires (require 'coq-diffs) ; highlight proof diffs (defvar prettify-symbols-alist) ;; ----- coq-shell configuration options ;;; Code: ;; debugging functions ;; (defun proofstack () (coq-get-span-proofstack (span-at (point) 'type))) (defvar coq-debug nil) ;; End debugging ;; Obsolete ;;(defcustom coq-default-undo-limit 500 ;; "Maximum number of Undo's possible when doing a proof." ;; :type 'number ;; :group 'coq) (defcustom coq-user-init-cmd nil "User defined init commands for Coq. These are appended at the end of `coq-shell-init-cmd'." :type '(repeat (cons (string :tag "command"))) :group 'coq) (defcustom coq-optimise-resp-windows-enable t "If non-nil (default) resize vertically response windw after each command." :type 'boolean :group 'coq) ;; Default coq is only Private_ and _subproof (defcustom coq-search-blacklist-string ; add this? \"_ind\" \"_rect\" \"_rec\" "\"Private_\" \"_subproof\"" "Initial strings to blacklist in requests to Coq environment. If you are setting this via emacs cutomization menus, you should restart Coq to see the effect. To change blacklist during a coq development, please use \\[coq-change-search-blacklist-interactive] instead (or menu: Coq/Settings/Search Blacklist)." :type 'string :group 'coq) ;; Coq has no command to overwrite the current blacklist, only to add or remove ;; particular strings. To provide the overwrite feature to the user we thus need ;; to know the current value of blacklist to first remove everything, then add ;; the new values. ;;; TODO: retrieve the value from coq itself and remove this variable? (defvar coq-search-blacklist-current-string coq-search-blacklist-string "Current value of Coq Search Blacklist. This may become desynchronized with Coq if you use the command \"Add/Remove Search Blacklist\" in you script." ) (defcustom coq-prefer-top-of-conclusion nil "Prefer start of the conclusion over its end when displaying large goals. Namely, goals that do not fit in the goals window." :type 'boolean :group 'coq) (defconst coq-shell-init-cmd (append `( ;; Should this variable be buffer-local? No opinion on that but if yes we ;; should re-intialize to coq-search-blacklist-string instead of ;; keeping the current value (that may come from another file). ,(format "Add Search Blacklist %s. " coq-search-blacklist-current-string)) '("Set Suggest Proof Using. ") coq-user-init-cmd) "Command to initialize the Coq Proof Assistant.") ;; FIXME: Even if we don't use coq-indent for indentation, we still need it for ;; coq-script-parse-cmdend-forward/backward and coq-find-real-start. (require 'coq-indent) ;; Command to reset the Coq Proof Assistant (defconst coq-shell-restart-cmd "Reset Initial.\n ") (defvar coq-shell-prompt-pattern "\\(?:\n\\(?:[^\n\371]+\371\\|[^\n]+\\)\\)" "*The prompt pattern for the inferior shell running coq.") ;; FIXME da: this was disabled (set to nil) -- why? ;; da: 3.5: add experimental ;; am:answer: because of bad interaction ;; with coq -R option. (defvar coq-shell-cd nil ;; "Add LoadPath \"%s\"." ;; fixes unadorned Require (if .vo exists). "*Command of the inferior process to change the directory.") (defvar coq-shell-proof-completed-regexp "No\\s-+more\\s-+\\(?:sub\\)?goals\\.\\|Subtree\\s-proved!\\|Proof\\s-completed"; \\|This subproof is complete "*Regular expression indicating that the proof has been completed.") (defvar coq-goal-regexp "\\(============================\\)\\|\\(\\(?:sub\\)?goal [0-9]+\\)\n") (defconst coq-interrupt-regexp "User Interrupt." "Regexp corresponding to an interrupt.") (defcustom coq-end-goals-regexp-show-subgoals "\n(dependent evars:" "Regexp for `proof-shell-end-goals-regexp' when showing all subgoals. A setting of nil means show all output from Coq. See also option `coq-hide-additional-subgoals'." :type '(choice regexp (const nil)) :group 'coq) (defcustom coq-end-goals-regexp-hide-subgoals (concat "\\(\n\\(?:sub\\)?goal 2 \\)\\|\\(" coq-end-goals-regexp-show-subgoals "\\)") "Regexp for `proof-shell-end-goals-regexp' when hiding additional subgoals. See also option `coq-hide-additional-subgoals'." :type '(choice regexp (const nil)) :group 'coq) (defcustom coq-show-proof-stepwise nil "Display the proof terms stepwise in the *response* buffer. This option can be combined with option `coq-diffs'. It is mostly useful in three window mode, see also `proof-three-window-mode-policy' for details." :type 'boolean :safe 'booleanp :group 'coq-auto-compile) ;; ;; prooftree customization ;; (defgroup coq-proof-tree () "Coq specific customization for prooftree." :group 'coq-config :package-version '(ProofGeneral . "4.2")) ;; Ignore all commands that start a proof. Otherwise "Proof" will appear ;; as superfluous node in the proof tree. Note that we cannot ignore Proof, ;; because, Fixpoint does not display the proof goal, see Coq bug #2776. (defcustom coq-proof-tree-ignored-commands-regexp (concat "^\\(\\(Show\\)\\|\\(Locate\\)\\|" "\\(Theorem\\)\\|\\(Lemma\\)\\|\\(Remark\\)\\|\\(Fact\\)\\|" "\\(Corollary\\)\\|\\(Proposition\\)\\|\\(Definition\\)\\|" "\\(Let\\)\\|\\(Fixpoint\\)\\|\\(CoFixpoint\\)\\)") "Regexp for `proof-tree-ignored-commands-regexp'." :type 'regexp :group 'coq-proof-tree) (defcustom coq-navigation-command-regexp (concat "^\\(\\(Focus\\)\\|\\(Unfocus\\)\\|" "\\(all\\s-*:\\s-*\\(cycle\\|swap\\|revgoals\\)\\)\\|" "\\(\\+\\)\\|\\(-\\)\\|\\(\\*\\)\\|\\({\\)\\|\\(}\\)\\)") "Regexp for `proof-tree-navigation-command-regexp'." :type 'regexp :group 'coq-proof-tree) (defcustom coq-proof-tree-cheating-regexp "\\(?:admit\\)\\|\\(?:give_up\\)" "Regexp for `proof-tree-cheating-regexp'." :type 'regexp :group 'coq-proof-tree) (defcustom coq-proof-tree-new-layer-command-regexp "^\\(\\(Proof\\)\\|\\(Grab Existential Variables\\)\\)" "Regexp for `proof-tree-new-layer-command-regexp'." :type 'regexp :group 'coq-proof-tree) (defcustom coq-proof-tree-current-goal-regexp (concat "^[0-9]+ \\(?:focused \\)?\\(?:sub\\)?goal\\(?:s\\)?\\s-*" "\\(?:(\\(?:unfocused: [-0-9]+\\)?,?" "\\s-*\\(?:shelved: [-0-9]+\\)?)\\)?\\(?:\\s-*, \\(?:sub\\)?goal 1\\)? " "(ID \\([0-9]+\\))\n\\s-*\n\\(\\(?: .*\n\\)+\\)\\(?:\n\\|$\\)") "Regexp for `proof-tree-current-goal-regexp'." :type 'regexp :group 'coq-proof-tree) (defcustom coq-proof-tree-update-goal-regexp (concat "^goal / evar \\([0-9]+\\) is:\n" "\\s-*\n\\(\\(?:.+\n\\)*\\)\\(?:\n\\|$\\)") "Regexp for `proof-tree-update-goal-regexp'." :type 'regexp :group 'coq-proof-tree) (defcustom coq-proof-tree-additional-subgoal-ID-regexp "^\\(?:sub\\)?goal [0-9]+ (ID \\([0-9]+\\)) is:" "Regexp for `proof-tree-additional-subgoal-ID-regexp'." :type 'regexp :group 'coq-proof-tree) (defcustom coq-proof-tree-existential-regexp "\\(\\?[0-9]+\\)" "Regexp for `proof-tree-existential-regexp'." :type 'regexp :group 'coq-proof-tree) (defcustom coq-proof-tree-instantiated-existential-regexp (concat coq-proof-tree-existential-regexp " using") "Regexp for recognizing an instantiated existential variable." :type 'regexp :group 'coq-proof-tree) (defcustom coq-proof-tree-existentials-state-start-regexp "^(dependent evars:" "Coq instance of `proof-tree-existentials-state-start-regexp'." :type 'regexp :group 'coq-proof-tree) (defcustom coq-proof-tree-existentials-state-end-regexp ")\n" "Coq instance of `proof-tree-existentials-state-end-regexp'." :type 'regexp :group 'coq-proof-tree) ;; 8.4: ;; This subproof is complete, but there are still unfocused goals. ;; ;; 8.5: ;; ;; This subproof is complete, but there are some unfocused goals. ;; Focus next goal with bullet *. ;; ;; ;; No more subgoals, but there are some goals you gave up: ;; ;; All the remaining goals are on the shelf. (defcustom coq-proof-tree-branch-finished-regexp (concat "^\\(\\(?:Proof completed\\.\\)\\|" "\\(?:\\(?:\\)?No more \\(?:sub\\)?goals\\)\\|" "\\(No more \\(?:sub\\)?goals but non-instantiated " "existential variables:\\)\\|" "\\(?:All the remaining goals are on the shelf\\)\\|" "\\(\\s-*This subproof is complete, but there are " "\\(?:still\\|some\\) unfocused goals.\\)\\)") "Regexp for `proof-tree-branch-finished-regexp'." :type 'regexp :group 'coq-proof-tree) ;; ;; Outline mode ;; (defvar coq-shell-outline-regexp coq-goal-regexp) (defvar coq-shell-outline-heading-end-regexp coq-goal-regexp) (defconst coq-state-preserving-tactics-regexp (proof-regexp-alt-list coq-state-preserving-tactics)) (defconst coq-state-changing-commands-regexp (proof-regexp-alt-list coq-keywords-state-changing-commands)) (defconst coq-state-preserving-commands-regexp (proof-regexp-alt-list coq-keywords-state-preserving-commands)) (defconst coq-commands-regexp (proof-regexp-alt-list coq-keywords-commands)) (defvar coq-retractable-instruct-regexp (proof-regexp-alt-list coq-retractable-instruct)) (defvar coq-non-retractable-instruct-regexp (proof-regexp-alt-list coq-non-retractable-instruct)) ;; ;; Derived modes ;; (defvar coq-shell-mode-syntax-table coq-mode-syntax-table) (defvar coq-response-mode-syntax-table coq-mode-syntax-table) (defvar coq-goals-mode-syntax-table coq-mode-syntax-table) (define-derived-mode coq-shell-mode proof-shell-mode "Coq Shell" nil (coq-shell-mode-config)) (define-derived-mode coq-response-mode proof-response-mode "Coq Response" nil (coq-response-config)) (define-derived-mode coq-goals-mode proof-goals-mode "Coq Goals" nil (coq-goals-mode-config)) ;; ;; Auxiliary code for Coq modes ;; ;; finding the main frame of pg. (defun coq-find-threeb-frames () "Return a list of frames displaying both response and goals buffers." (let* ((wins-resp (get-buffer-window-list proof-response-buffer nil t)) (wins-gls (get-buffer-window-list proof-goals-buffer nil t)) (frame-resp (mapcar #'window-frame wins-resp)) (frame-gls (mapcar #'window-frame wins-gls))) (filtered-frame-list (lambda (x) (and (member x frame-resp) (member x frame-gls)))))) (defun coq-remove-trailing-blanks (s) (let ((pos (string-match "\\s-*\\'" s))) (substring s 0 pos))) (defun coq-remove-starting-blanks (s) (string-match "\\`\\s-*" s) (substring s (match-end 0) (length s))) ;; Messages dispalyed by "Time" are always following or preceding the real ;; result, if it follows we want it to be non urgent, otherwise the result ;; would not be shown in response buffer. If it is before, then we want it ;; urgent so that it is displayed. (defvar coq-eager-no-urgent-regex "\\s-*Finished " "Regexp of commands matching ‘proof-shell-eager-annotation-start’ that should maybe not be classified as urgent messages.") ;; return the end position if found, nil otherwise (defun coq-non-urgent-eager-annotation () (save-excursion (when (and (looking-at coq-eager-no-urgent-regex) (re-search-forward proof-shell-eager-annotation-end nil t)) (let ((res (match-end 0))); robustify ;; if there is something else than a prompt here then this eager ;; annotation is left urgent (return nil), otherwise it is not urgent ;; (return position of the end of the annotation) (when (looking-at (concat "\\s-*" proof-shell-annotated-prompt-regexp)) res))))) ;; Looking for eager annotation which does not match coq-eager-no-urgent-regex (defun coq-search-urgent-message () "Find forward the next really urgent message. Return the position of the beginning of the message (after the annotation-start) if found." (let ((again t) (start-start nil) (end-end nil) ;; (found nil) (eager proof-shell-eager-annotation-start)) (while again (setq start-start (and (re-search-forward eager nil 'limit) (match-beginning 0))) (setq end-end (and start-start (coq-non-urgent-eager-annotation))) (unless end-end (setq again nil) ; exit while ;; display message (this prints the message once now but it will be ;; reprinted as a normal output, bad?) ;;(proof-shell-process-urgent-message start-start end-end) )) (and start-start (goto-char start-start)))) ;; This is a modified version of the same function in generic/proof-shell.el. ;; Using function coq-search-urgent-message instead of regex ;; proof-shell-eager-annotation-start, in order to let non urgent message as ;; such. i.e. "Time" messages. (defun proof-shell-process-urgent-messages () "Scan the shell buffer for urgent messages. Scanning starts from `proof-shell-urgent-message-scanner' or `scomint-last-input-end', which ever is later. We deal with strings between regexps `proof-shell-eager-annotation-start' and `proof-shell-eager-annotation-end'. We update `proof-shell-urgent-message-marker' to point to last message found. This is a subroutine of `proof-shell-filter'." (let ((pt (point)) (end t) lastend laststart (initstart (max (marker-position proof-shell-urgent-message-scanner) (marker-position scomint-last-input-end)))) (goto-char initstart) (while (and end (setq laststart (coq-search-urgent-message)) ) ; (setq laststart (match-beginning 0)) (if (setq end (re-search-forward proof-shell-eager-annotation-end nil t)) (save-excursion (setq lastend end) ;; Process the region including the annotations (proof-shell-process-urgent-message laststart lastend)))) (set-marker proof-shell-urgent-message-scanner (if end ;; couldn't find message start; move forward to avoid rescanning (max (or lastend 1) ;; goto after last end urgent msg ;; or near the end of current output if that jumps farther. (- (point) (1+ proof-shell-eager-annotation-start-length))) ;; incomplete message; leave marker at start of message laststart)) ;; Set position of last urgent message found (if lastend (set-marker proof-shell-urgent-message-marker lastend)) (goto-char pt))) ;; Due to the architecture of proofgeneral, informative message put *before* ;; the goal disappear unless marked as "urgent", i.e. being enclosed with ;; "eager-annotation" syntax. Since we don't want the Warning color to be used ;; for simple informative message, we have to redefine this function to use ;; normal face when the "eager annotation" is acutally not a warning. This is a ;; modified version of the same function in generic/proof-shell.el. (defun proof-shell-process-urgent-message-default (start end) "A subroutine of `proof-shell-process-urgent-message'." ;; Clear the response buffer this time, but not next, leave window. (pg-response-maybe-erase nil nil) (proof-minibuffer-message (buffer-substring-no-properties (save-excursion (re-search-forward proof-shell-eager-annotation-start end nil) (point)) (min end (save-excursion (end-of-line) (point)) (+ start 75)))) (goto-char start) (let* (;; (face (if (looking-at "") 'default ;; 'proof-eager-annotation-face)) (str (proof-shell-strip-eager-annotations start end)) (strnotrailingspace (coq-remove-starting-blanks (coq-remove-trailing-blanks str)))) (pg-response-display-with-face strnotrailingspace))) ; face ;; slight modification of proof-script-generic-parse-cmdend (one of the ;; candidate for proof-script-parse-function), to allow "{" and "}" to be ;; command terminator when the command is empty. TO PLUG: swith the comment ;; below and rename coq-script-parse-function2 into coq-script-parse-function (defun coq-script-parse-function () "For `proof-script-parse-function' if `proof-script-command-end-regexp' set." (coq-script-parse-cmdend-forward)) ;;;;;;;;;;;;;;;;;;;;;;;;;; End of "{" and "} experiments ;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;; Freeze buffers ;;;;;;;;;;;; ;; For storing output of respnse and goals buffers into a permanent buffer. (defun coq-clone-buffer-response-mode (s &optional erase) (let ((already-existing (get-buffer s)) (nb (get-buffer-create s))) (save-window-excursion (switch-to-buffer nb) (unless already-existing (coq-response-mode) (read-only-mode 0)) (goto-char (point-min)) (insert "\n************************************\n") (goto-char (point-min))) (if erase (copy-to-buffer nb (point-min) (point-max)) (append-to-buffer nb (point-min) (point-max))) ;; (set-window-point window pos) nb)) ;; copy the content of proof-response-buffer into the "response-freeze" buffer, ;; resetting its content if ERASE non nil. (defun proof-store-buffer-win (buffer &optional erase) (proof-with-current-buffer-if-exists buffer (let ((newbuffer nil)) (set-buffer buffer) (setq newbuffer (coq-clone-buffer-response-mode "*response-freeze*" erase)) (let ((win (display-buffer-other-frame newbuffer)) (win-point-min (save-window-excursion (switch-to-buffer-other-frame newbuffer) (point-min)))) (set-window-point win win-point-min))))) (defun proof-store-response-win (&optional erase) (interactive "P") (proof-store-buffer-win proof-response-buffer erase)) (defun proof-store-goals-win (&optional erase) (interactive "P") (proof-store-buffer-win proof-goals-buffer erase)) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; make this non recursive? (defun build-list-id-from-string (s) "Build a list of string from a string S of the form \"id1|id2|...|idn\"." (if (or (not s) (string= s "")) '() (let ((x (string-match (concat "\\(" coq-id-shy "\\)\\(?:|\\|\\'\\)\\(.*\\)") s))) (if (not x) (error "Cannot extract list of ids from string") (cons (match-string 1 s) (build-list-id-from-string (match-string 2 s))))))) ;; Use the statenumber inside the coq prompt to backtrack more easily (defun coq-last-prompt-info (s) "Extract info from the coq prompt S. See `coq-last-prompt-info-safe'." (let ((lastprompt (or s (error "No prompt !!?"))) (regex (concat ">\\(" coq-id-shy "\\) < \\([0-9]+\\) |\\(\\(?:" coq-id-shy "|?\\)*\\)| \\([0-9]+\\) < "))) (when (string-match regex lastprompt) (let ((current-proof-name (match-string 1 lastprompt)) (state-number (string-to-number (match-string 2 lastprompt))) (proof-state-number (string-to-number (match-string 4 lastprompt))) ;; bind pending-proofs last, because build-list-id-from-string ;; modifies the match data (pending-proofs (build-list-id-from-string (match-string 3 lastprompt)))) (list state-number proof-state-number pending-proofs (if pending-proofs current-proof-name nil)))))) (defun coq-last-prompt-info-safe () "Return a list with all informations from the last prompt. The list contains in the following order the state number, the proof stack depth, a list with the names of all pending proofs, and as last element the name of the current proof (or nil if there is none)." (coq-last-prompt-info proof-shell-last-prompt)) (defvar coq-last-but-one-statenum 1 "The state number we want to put in a span. This is the prompt number given *just before* the command was sent. This variable remembers this number and will be updated when used see coq-set-state-number. Initially 1 because Coq initial state has number 1.") (defvar coq-last-but-one-proofnum 1 "As for `coq-last-but-one-statenum' but for stack depth.") (defvar coq-last-but-one-proofstack '() "As for `coq-last-but-one-statenum' but for proof stack symbols.") (defvar coq--retract-naborts 0 "The number of (possibly nested) goals to abort on retract. This temporary variable is written by function `coq-find-and-forget' and read by function `coq-empty-action-list-command'.") (defsubst coq-get-span-statenum (span) "Return the state number of the SPAN." (span-property span 'statenum)) (defsubst coq-get-span-proofnum (span) "Return the proof number of the SPAN." (span-property span 'proofnum)) (defsubst coq-get-span-proofstack (span) "Return the proof stack (names of pending proofs) of the SPAN." (span-property span 'proofstack)) (defsubst coq-set-span-statenum (span val) "Set the state number of the SPAN to VAL." (span-set-property span 'statenum val)) (defsubst coq-get-span-goalcmd (span) "Return the 'goalcmd flag of the SPAN." (span-property span 'goalcmd)) (defsubst coq-set-span-goalcmd (span val) "Set the 'goalcmd flag of the SPAN to VAL." (span-set-property span 'goalcmd val)) (defsubst coq-set-span-proofnum (span val) "Set the proof number of the SPAN to VAL." (span-set-property span 'proofnum val)) (defsubst coq-set-span-proofstack (span val) "Set the proof stack (names of pending proofs) of the SPAN to VAL." (span-set-property span 'proofstack val)) (defsubst proof-last-locked-span () (with-current-buffer proof-script-buffer (span-at (- (proof-unprocessed-begin) 1) 'type))) ;; Each time the state changes (hook below), (try to) put the state number in ;; the last locked span (will fail if there is already a number which should ;; happen when going back in the script). The state number we put is not the ;; last one because the last one has been sent by Coq *after* the change. We ;; use `coq-last-but-one-statenum' instead and then update it. ;;TODO update docstring and comment (defun coq-open-goals-p () "Return non nil if we are inside a proof, see `proof-shell-open-goals-p'." (car (cdr (cdr (coq-last-prompt-info-safe))))) (defun coq-set-state-infos () "Set the last locked span's state number to the number found last time. This number is in the *last but one* prompt (variable `coq-last-but-one-statenum'). If locked span already has a state number, then do nothing. Also updates `coq-last-but-one-statenum' to the last state number for next time." (if proof-shell-last-prompt ;; da: did test proof-script-buffer here, but that seems wrong ;; since restart needs to reset these values. ;; infos = promt infos of the very last prompt ;; sp = last locked span, which we want to fill with prompt infos (let ((sp (if proof-script-buffer (proof-last-locked-span))) (infos (or (coq-last-prompt-info-safe) ;; the line above seems to return nil sometimes, let us ;; issue a warning when this happens, so that we ;; understand why. (and (display-warning 'proof-general "oops nothing returned by (coq-last-prompt-info-safe)!!!" :debug) nil) '(0 0 nil nil)))) (unless (or (not sp) (coq-get-span-statenum sp)) (coq-set-span-statenum sp coq-last-but-one-statenum)) (setq coq-last-but-one-statenum (car infos)) ;; set goalcmd property if this is a goal start ;; (ie proofstack has changed and not a save cmd) (unless (or (not sp) (equal (span-property sp 'type) 'goalsave) (<= (length (car (cdr (cdr infos)))) (length coq-last-but-one-proofstack))) (coq-set-span-goalcmd sp t)) ;; testing proofstack=nil is not good here because nil is the empty list OR ;; the no value, so we test proofnum as it is always set at the same time. ;; This is why this test is done before the next one (which sets proofnum) (unless (or (not sp) (coq-get-span-proofnum sp)) (coq-set-span-proofstack sp coq-last-but-one-proofstack)) (setq coq-last-but-one-proofstack (car (cdr (cdr infos)))) (unless (or (not sp) (coq-get-span-proofnum sp)) (coq-set-span-proofnum sp coq-last-but-one-proofnum)) (setq coq-last-but-one-proofnum (car (cdr infos)))))) ;; This hook seems the one we want. ;; WARNING! It is applied once after each command PLUS once before a group of ;; commands is started (add-hook 'proof-state-change-pre-hook #'coq-set-state-infos) (defun count-not-intersection (l notin) "Return the number of elts of L that are not in NOTIN." (let ((l1 l) (l2 notin) (res 0)) (while l1 (if (member (car l1) l2) () (setq res (+ res 1))) ; else (setq l1 (cdr l1))) res )) ;; Simplified version of backtracking which uses state numbers (Coq >= 8.4). ;; It uses the new coq command ;; "BackTo". The prompt is like this: ;; state proof stack ;; num depth ;; __ _ ;; aux < 12 |aux|SmallStepAntiReflexive| 4 < \371 ;; ^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^ ;; usual pending proofs usual ;; special char ;; exemple: ;; to go (back) from 12 |lema1|lema2...|leman| xx ;; to 8 |lemb1|lemb2...|lembm| 5 ;; we must do "BackTo 8" and set `coq--retract-naborts' to ;; naborts, i.e., the number of lemais that are not lembis ;; Rem: We could deal with suspend and resume with more work. We would need a new coq ;; command, because it is better to backtrack with *one* command (because ;; proof-change-hook used above is not exactly called at right times). (defun coq-find-and-forget (span) "Backtrack to SPAN. Using the \"BackTo n\" coq command." (if (eq (span-property span 'type) 'proverproc) ;; processed externally (i.e. Require, etc), nothing to do ;; (should really be unlocked when we undo the Require). nil (let* (;; (naborts 0) (proofdepth (coq-get-span-proofnum span)) (proofstack (coq-get-span-proofstack span)) (span-staten (coq-get-span-statenum span)) (naborts (count-not-intersection coq-last-but-one-proofstack proofstack))) ;; if we move outside of any proof, coq does not print anything, so clean ;; the goals buffer otherwise the old one will still be displayed (if (= proofdepth 0) (proof-clean-buffer proof-goals-buffer)) (setq coq--retract-naborts naborts) (list (format "BackTo %s . " (int-to-string span-staten)))))) (defvar coq-current-goal 1 "Last goal that Emacs looked at.") (defun coq-goal-hyp () (cond ((looking-at "============================\n") (goto-char (match-end 0)) (cons 'goal (int-to-string coq-current-goal))) ((looking-at "\\(?:sub\\)?goal \\([0-9]+\\) is:\n") (goto-char (match-end 0)) ;; (cons 'goal (match-string 1)) ;FIXME: This is dead-code!? --Stef (setq coq-current-goal (string-to-number (match-string 1)))) ((proof-looking-at proof-shell-assumption-regexp) (cons 'hyp (match-string 1))) (t nil))) (defun coq-state-preserving-p (cmd) ;; (or (proof-string-match coq-non-retractable-instruct-regexp cmd)) ;; (and ;; (not (proof-string-match coq-retractable-instruct-regexp cmd)) ;; (or ;; (message "Unknown command, hopes this won't desynchronize ProofGeneral") ;; t)))) (defun coq-hide-additional-subgoals-switch () "Function invoked when the user switches option `coq-hide-additional-subgoals'." (if coq-time-commands (progn (setq coq-hide-additional-subgoals nil) (error "You must disable ``Time Commands'' (var coq-time-commands) first")) (if coq-hide-additional-subgoals (setq proof-shell-end-goals-regexp coq-end-goals-regexp-hide-subgoals) (setq proof-shell-end-goals-regexp coq-end-goals-regexp-show-subgoals)))) (defun coq-time-commands-switch () "Function invoked when the user switches option `coq-time-commands'. Reset option `coq-hide-additional-subgoals' and puts nil into `proof-shell-end-goals-regexp' to ensure the timing is visible in the *goals* buffer." (if coq-time-commands (progn (let ((coq-time-commands nil)) (customize-set-variable 'coq-hide-additional-subgoals nil)) (setq proof-shell-end-goals-regexp nil)) (coq-hide-additional-subgoals-switch))) ;; ;; Commands for Coq ;; (defconst notation-print-kinds-table '(("Print Scope(s)" 0) ("Print Visibility" 1)) "Enumerates the different kinds of notation information one can ask to coq.") (defun coq-PrintScope () "Show information on notations. Coq specific." (interactive) (let* ((mods (completing-read "Infos on notation (TAB to see list): " notation-print-kinds-table)) (s (read-string "Name (empty for all): ")) ;; (all (string-equal s "")) ) (cond ((and (string-equal mods "Print Scope(s)") (string-equal s "")) (proof-shell-invisible-command (format "Print Scopes."))) (t (proof-shell-invisible-command (format "%s %s ." mods s)))))) (defun coq-remove-trailing-dot (s) "Return the string S without its trailing \".\" if any. Return nil if S is nil." (if (and s (string-match "\\.\\'" s)) (substring s 0 (- (length s) 1)) s)) (defun coq-remove-heading-quote (s) "Return the string S without its heading \"\'\" if any. Return nil if S is nil." (if (and s (string-match "\\`'" s)) (substring s 1 (length s)) s)) (defun coq-clean-id-at-point (s) (coq-remove-heading-quote (coq-remove-trailing-dot s))) (defun coq-is-symbol-or-punct (c) "Return non nil if character C is a punctuation or a symbol constituent. If C is nil, return nil." (when c (or (equal (char-syntax c) ?\.) (equal (char-syntax c) ?\_)))) (defun coq-grab-punctuation-left (pos) "Return a string made of punctuations chars found immediately before position POS." (let ((res nil) (currpos pos)) (while (coq-is-symbol-or-punct (char-before currpos)) (setq res (concat (char-to-string (char-before currpos)) res)) (setq currpos (- currpos 1))) res)) (defun coq-grab-punctuation-right (pos) "Return a string made of punctuations chars found immediately after position POS." (let ((res nil) (currpos pos)) (while (coq-is-symbol-or-punct (char-after currpos)) (setq res (concat res (char-to-string (char-after currpos)))) (setq currpos (+ currpos 1))) res)) (defun coq-notation-at-position (pos) "Return the notation at current point. Support dot.notation.of.modules." (coq-with-altered-syntax-table (when (or (coq-grab-punctuation-left pos) (coq-grab-punctuation-right pos)) (concat (coq-grab-punctuation-left pos) (coq-grab-punctuation-right pos))))) (defun coq-string-starts-with-symbol (s) (eq 0 (string-match "\\s_" s))) ;; remove trailing dot if any. (defun coq-id-at-point () "Return the identifier at current point. Support dot.notation.of.modules." (coq-with-altered-syntax-table (let* ((symb (cond ((fboundp 'symbol-near-point) (symbol-near-point)) ((fboundp 'symbol-at-point) (symbol-at-point)))) (symbclean (when symb (coq-clean-id-at-point (symbol-name symb))))) (when (and symb (not (zerop (length symbclean)))) symbclean)))) (defun coq-id-or-notation-at-point () (or (coq-id-at-point) (let ((notation (coq-notation-at-position (point)))) (if notation (concat "\"" notation "\"") "")))) (defcustom coq-remap-mouse-1 nil "Whether Coq mode should remap mouse button 1 to Coq queries. This overrides the default global binding of (control mouse-1) and \(shift mouse-1) (buffers and faces menus). Hence it is nil by default." :type 'boolean :group 'coq) ;; On a mouse event, try to query the id at point clicked. (defun coq-id-under-mouse-query (event) "Query the prover about the identifier or notation near mouse click EVENT. This is mapped to control/shift mouse-1, unless coq-remap-mouse-1 is nil (t by default)." (interactive "e") (save-selected-window (save-excursion (mouse-set-point event) (let* ((id (coq-id-at-point)) (notat (coq-notation-at-position (point))) (modifs (event-modifiers event)) (shft (member 'shift modifs)) (ctrl (member 'control modifs)) (cmd (when (or id notat) (if (and ctrl shft) (if id "Check" "Locate") (if shft (if id "About" "Locate") (if ctrl (if id "Print" "Locate"))))))) (proof-shell-invisible-command (format (concat cmd " %s . ") ;; Notation need to be surrounded by "" (if id id (concat "\"" notat "\"")))))))) (defun coq-guess-or-ask-for-string (s &optional dontguess) "Asks for a coq identifier with message S. If DONTGUESS is non nil, propose a default value as follows: If region is active, propose its containt as default value. Otherwise propose identifier at point if any." (let* ((guess (cond (dontguess nil) ((use-region-p) (buffer-substring-no-properties (region-beginning) (region-end))) (t (coq-id-or-notation-at-point))))) (read-string (if guess (concat s " (default " guess "): ") (concat s ": ")) nil 'proof-minibuffer-history guess))) (defun coq-ask-do (ask do &optional dontguess postformatcmd wait) "Ask for an ident and print the corresponding term." (let* ((cmd) (postform (if (eq postformatcmd nil) 'identity postformatcmd))) (proof-shell-ready-prover) (setq cmd (coq-guess-or-ask-for-string ask dontguess)) (proof-shell-invisible-command (format (concat do " %s . ") (funcall postform cmd)) wait))) (defun coq-flag-is-on-p (testcmd) (proof-shell-ready-prover) (proof-shell-invisible-command (format testcmd) 'wait) (let ((resp proof-shell-last-response-output)) (string-match "is on\\>" resp))) (defun coq-command-with-set-unset (setcmd cmd unsetcmd &optional postformatcmd testcmd) "Play commands SETCMD then CMD and then silently UNSETCMD. The last UNSETCMD is performed with tag 'empty-action-list so that it does not trigger ‘proof-shell-empty-action’ (which does \"Show\" at the time of writing this documentation)." (let* ((postform (if (eq postformatcmd nil) 'identity postformatcmd)) (flag-is-on (and testcmd (coq-flag-is-on-p testcmd)))) ;; We put 'empty-action-list tags on all three commands since we don't want ;; to trigger "Show" or anything that we usually insert after a group of ;; commands. (unless flag-is-on (proof-shell-invisible-command (format " %s . " (funcall postform setcmd)) nil nil 'no-response-display 'empty-action-list)) (proof-shell-invisible-command (format " %s . " (funcall postform cmd)) 'wait nil 'empty-action-list) (unless flag-is-on (proof-shell-invisible-command (format " %s . " (funcall postform unsetcmd)) 'waitforit nil 'no-response-display 'empty-action-list)))) (defun coq-ask-do-set-unset (ask do setcmd unsetcmd &optional dontguess postformatcmd _tescmd) "Ask for an ident id and execute command DO in SETCMD mode. More precisely it executes SETCMD, then DO id and finally silently UNSETCMD. See `coq-command-with-set-unset'." (let* ((cmd) ;; (postform (if (eq postformatcmd nil) 'identity postformatcmd tescmd)) ) (proof-shell-ready-prover) (setq cmd (coq-guess-or-ask-for-string ask dontguess)) (coq-command-with-set-unset setcmd (concat do " " cmd) unsetcmd postformatcmd))) (defun coq-ask-do-show-implicits (ask do &optional dontguess postformatcmd) "Ask for an ident and print the corresponding term." (coq-ask-do-set-unset ask do "Set Printing Implicit" "Unset Printing Implicit" dontguess postformatcmd "Test Printing Implicit")) (defun coq-ask-do-show-all (ask do &optional dontguess postformatcmd) "Ask for an ident and print the corresponding term." (coq-ask-do-set-unset ask do "Set Printing All" "Unset Printing All" dontguess postformatcmd "Test Printing All")) ;; (let* ((cmd) (postform (if (eq postformatcmd nil) 'identity postformatcmd))) ;; (proof-shell-ready-prover) ;; (setq cmd (coq-guess-or-ask-for-string ask dontguess)) ;; (coq-command-with-set-unset ;; "Set Printing Implicit" ;; (format (concat do " %s . ") cmd) ;; "Unset Printing Implicit" ) ;; )) (defsubst coq-put-into-brackets (s) (concat "[ " s " ]")) (defsubst coq-put-into-double-quote-if-notation (s) (if (coq-is-symbol-or-punct (string-to-char s)) (concat "\"" s "\"") s)) (defun coq-build-removed-pattern (s) (concat " -\"" s "\"")) (defun coq-build-removed-patterns (l) (mapcar #'coq-build-removed-pattern l)) (defsubst coq-put-into-quotes (s) (concat "\"" s "\"")) (defun coq-SearchIsos () "Search a term whose type is isomorphic to given type. This is specific to `coq-mode'." (interactive) (coq-ask-do "SearchPattern (parenthesis mandatory), ex: (?X1 + _ = _ + ?X1)" "SearchPattern" nil)) (defun coq-SearchRewrite () (interactive) (coq-ask-do "SearchRewrite" "SearchRewrite" nil)) (defun coq-Print (withprintingall) "Ask for an ident and print the corresponding term. With flag Printing All if some prefix arg is given (C-u)." (interactive "P") (if withprintingall (coq-ask-do-show-all "Print" "Print") (coq-ask-do "Print" "Print"))) (defun coq-Print-Ltac () "Ask for an ident and print the corresponding Ltac term." (interactive) (coq-ask-do "Print Ltac" "Print Ltac")) (defun coq-Print-with-implicits () "Ask for an ident and print the corresponding term." (interactive) (coq-ask-do-show-implicits "Print" "Print")) (defun coq-Print-with-all () "Ask for an ident and print the corresponding term." (interactive) (coq-ask-do-show-all "Print" "Print")) (defun coq-About (withprintingall) "Ask for an ident and print information on it." (interactive "P") (if withprintingall (coq-ask-do-show-all "About" "About") (coq-ask-do "About" "About"))) (defun coq-About-with-implicits () "Ask for an ident and print information on it." (interactive) (coq-ask-do-show-implicits "About" "About")) (defun coq-About-with-all () "Ask for an ident and print information on it." (interactive) (coq-ask-do-show-all "About" "About")) (defun coq-LocateConstant () "Locate a constant." (interactive) (coq-ask-do "Locate" "Locate")) (defun coq-LocateLibrary () "Locate a library." (interactive) (coq-ask-do "Locate Library" "Locate Library")) (defun coq-LocateNotation () "Locate a notation. Put it automatically into quotes. This is specific to `coq-mode'." (interactive) (coq-ask-do "Locate notation (ex: \'exists\' _ , _)" "Locate" )) (defun coq-set-undo-limit (undos) (proof-shell-invisible-command (format "Set Undo %s . " undos))) (defun coq-Pwd () "Display the current Coq working directory." (interactive) (proof-shell-invisible-command "Pwd.")) (defun coq-Inspect () (interactive) (coq-ask-do "Inspect how many objects back?" "Inspect" t)) (defun coq-PrintSection() (interactive) (coq-ask-do "Print Section" "Print Section" t)) (defun coq-Print-implicit () "Ask for an ident and print the corresponding term." (interactive) (coq-ask-do "Print Implicit" "Print Implicit")) (defun coq-Check (withprintingall) "Ask for a term and print its type. With flag Printing All if some prefix arg is given (C-u)." (interactive "P") (if withprintingall (coq-ask-do-show-all "Check" "Check") (coq-ask-do "Check" "Check"))) (defun coq-Check-show-implicits () "Ask for a term and print its type." (interactive) (coq-ask-do-show-implicits "Check" "Check")) (defun coq-Check-show-all () "Ask for a term and print its type." (interactive) (coq-ask-do-show-all "Check" "Check")) (defun coq-get-response-string-at (&optional pt) "Go forward from PT until reaching a 'response property, and return it. Response span only starts at first non space character of a command, so we may have to go forward to find it. Starts from (point) if pt is nil. Precondition: pt (or point if nil) must be in locked region." (let ((pt (or pt (point)))) (save-excursion (goto-char pt) (while (and (not (eq (point) (point-max))) (not (span-at (point) 'response))) (forward-char)) (span-property (span-at (point) 'response) 'response)))) (defun coq-Show (withprintingall) "Ask for a number I and show the Ith goal. Ask for a number I and show the ith current goal. With non-nil prefix argument and not on the locked span, show the goal with flag Printing All set." ; Disabled: ; "Ask for a number i and show the ith goal, or show ancient goal. ;If point is on a locked span, show the corresponding coq ;output (i.e. for tactics: the goal after the tactic). Otherwise ;ask for a number i and show the ith current goal. With non-nil ;prefix argument and not on the locked span, show the goal with ;flag Printing All set." ; (interactive "P") ;; Disabling this as this relies on 'response attribute that is empty when ;; the command was processed silently. We should first have a coq command ;; asking to print the goal at a given state. (if (proof-in-locked-region-p) (let ((s (coq-get-response-string-at))) (if (zerop (length (coq-get-response-string-at))) (message "Cannot show the state at this point: Coq was silent during this command.") (set-buffer proof-response-buffer) (let ((inhibit-read-only 'titi)) (pg-response-display s) (proof-display-and-keep-buffer proof-response-buffer) (coq-optimise-resp-windows)))) (if withprintingall (coq-ask-do-show-all "Show goal number" "Show" t) (coq-ask-do "Show goal number" "Show" t)))) (defun coq-Show-with-implicits () "Ask for a number i and show the ith goal." (interactive) (coq-ask-do-show-implicits "Show goal number" "Show" t)) (defun coq-Show-with-all () "Ask for a number i and show the ith goal." (interactive) (coq-ask-do-show-all "Show goal number" "Show" t)) ;; Since Printing Width is a synchronized option in coq (?) it is retored ;; silently to a previous value when retracting. So we reset the stored width ;; when retracting, so that it will be auto-adapted at the next command. Not ;; perfect: we have to forward one step to see the effect. ;; FIXME: hopefully this will eventually become a non synchronized option and ;; we can remove this. ;; This obeyx coq-auto-adapt-printing-width (add-hook 'proof-assert-command-hook #'coq-adapt-printing-width) (add-hook 'proof-retract-command-hook #'coq-reset-printing-width) (defun coq--show-proof-stepwise-cmds () (when coq-show-proof-stepwise (if (coq--post-v811) (pcase coq-diffs ('off '("Show Proof.")) ('on '("Show Proof Diffs.")) ('removed '("Show Proof Diffs removed."))) '("Show Proof.")))) ;; In case of nested proofs (which are announced as obsolete in future versions ;; of coq) Coq does not show the goals of enclosing proof when closing a nested ;; proof. This is coq's proof-shell-empty-action-list-command function which ;; inserts a "Show" if the last command of an action list is a save command and ;; there is more than one open proof before that save. If you want to issue a ;; command and *not* have the goal redisplayed, the command must be tagged with ;; 'empty-action-list. (defun coq-empty-action-list-command (cmd) "Return the list of commands to send to Coq after CMD if it is the last command of the action list. If CMD is tagged with 'empty-action-list then this function won't be called and no command will be sent to Coq. Note: the last command added if `coq-show-proof-stepwise' is set should match the `coq-show-proof-diffs-regexp'." (cond ((or ;; If closing a nested proof, Show the enclosing goal. (and (string-match-p coq-save-command-regexp-strict cmd) (> (length coq-last-but-one-proofstack) 1)) ;; If user issued a printing option then t printing. (and (string-match-p "\\(S\\|Uns\\)et\\s-+Printing" cmd) (> (length coq-last-but-one-proofstack) 0))) `("Show." . ,(coq--show-proof-stepwise-cmds))) ((or ;; If we go back in the buffer and the number of abort is less than ;; the number of nested goals, then Unset Silent and Show the goal (and (string-match-p "BackTo\\s-" cmd) (> (length coq-last-but-one-proofstack) coq--retract-naborts))) `("Unset Silent." ,(if (coq--post-v810) (coq-diffs) "Show.") . ,(coq--show-proof-stepwise-cmds))) ((or ;; If we go back in the buffer and not in the above case, then only Unset ;; silent (there is no goal to show). Still, we need to "Set Diffs" again (string-match-p "BackTo\\s-" cmd)) (if (coq--post-v810) (list "Unset Silent." (coq-diffs) ) (list "Unset Silent."))) ((or ;; If starting a proof, Show Proof if need be (coq-goal-command-str-p cmd) ;; If doing (not closing) a proof, Show Proof if need be (and (not (string-match-p coq-save-command-regexp-strict cmd)) (> (length coq-last-but-one-proofstack) 0))) (coq--show-proof-stepwise-cmds)))) ;; This does not Set Printing Width, it rather tells pg to do that before each ;; command (if necessary) (defpacustom auto-adapt-printing-width t "If non-nil, adapt automatically printing width of goals window. Each time the user sends a bunch of commands to Coq, check if the width of the goals window changed, and adapt coq printing width. WARNING: If several windows are displaying the goals buffer, one is chosen arbitrarily. WARNING 2: when backtracking the printing width is synchronized by coq (?!)." :type 'boolean :safe 'booleanp :group 'coq) (defvar coq-shell-current-line-width nil "Current line width of the Coq printing width. Its value will be updated whenever a command is sent if necessary.") ;; Resetting the known printing width (for when we don't know it, for example ;; when retracting. (defun coq-reset-printing-width () (setq coq-shell-current-line-width nil)) (defun coq-buffer-window-width (buffer) "Return the width of a window currently displaying BUFFER." (let* ((buf-wins (get-buffer-window-list buffer nil t)) (_ (if (not (eq 1 (length buf-wins))) (display-warning 'proof-general "Zero or more than one goals window, guessing window width." :debug))) (buf-win (car buf-wins)));; TODO return the widest one instead of the first? ;; return nil if no goal buffer found (and buf-win (window-width buf-win)))) (defun coq-goals-window-width () (coq-buffer-window-width proof-goals-buffer)) (defun coq-response-window-width () (coq-buffer-window-width proof-response-buffer)) (defun coq-guess-goal-buffer-at-next-command () "Return the probable width of goals buffer if it pops up now. This is a guess based on the current width of goals buffer if present, current pg display mode and current geometry otherwise." (let ((pol (proof-guess-3win-display-policy proof-three-window-mode-policy))) (cond ;; goals buffer is visible, bingo ((coq-goals-window-width)) ;; Below is the heuristic to guess the good width for goals ;; 2 windows mode, response-buffer visible, use this width ((and (not proof-three-window-enable) (coq-response-window-width))) ;; 2 windows mode, response buffer not visible, give up ((not proof-three-window-enable) nil) ;; 3 windows mode, one frame, and vertical policy ((and proof-three-window-enable (not proof-multiple-frames-enable) (eq pol 'vertical)) (window-width)) ;; 3 windows mode, one frame, other policies, give up ((and proof-three-window-enable (not proof-multiple-frames-enable)) nil) ;; multiple frames. If goals buffer pops up it will have frame default ;; size. Falling back to X default window size if not specified. ;; This is hard to mimick, let us give up (proof-multiple-frames-enable nil) (t nil) ;; assert false? ))) (defun coq-adapt-printing-width (&optional show width) "Sends a Set Printing Width command to Coq to fit the response window's WIDTH. A Show command is also issued if SHOW is non-nil, so that the goal is redisplayed." (interactive) (when coq-auto-adapt-printing-width (let ((wdth (or width (coq-guess-goal-buffer-at-next-command)))) ;; if no available width, or unchanged, do nothing (when (and wdth (not (equal wdth coq-shell-current-line-width))) (proof-shell-invisible-command (format "Set Printing Width %S." (- wdth 1)) t) (setq coq-shell-current-line-width wdth) ;; Show iff show non nil and some proof is under way (when (and show (not (null (cl-caddr (coq-last-prompt-info-safe))))) (proof-shell-invisible-command (format "Show.") t nil 'no-error-display)))))) (defun coq-adapt-printing-width-and-show (&optional _show width) (interactive) (coq-adapt-printing-width t width)) (defun coq-ask-adapt-printing-width-and-show () (interactive) (let* ((deflt (coq-goals-window-width)) (rd (read-number (format "Width (%S): " deflt) deflt))) (coq-adapt-printing-width t rd))) ;;;;; utils fo overlays (defun coq-overlays-at (pt prop) (let ((overlays (overlays-at pt)) found) (while overlays (let ((overlay (car overlays))) (if (overlay-get overlay prop) (setq found (cons overlay found)))) (setq overlays (cdr overlays))) found)) ;;;;;;;;;; Hypothesis tracking ;;;;;;;;;; ;;; Facilities to build overlays for hyp names and hyp+type + hypcross ;;; ((un)folding buttons). (defvar coq-hypname-map (make-sparse-keymap) "Keymap for visible hypothesis.") (defvar coq-hypcross-map (make-sparse-keymap) "Keymap for visible hypothesis.") (defvar coq-hypcross-hovering-help t "Whether hyps fold cross pops up a help when hovered.") (defvar coq-hyps-positions nil "The list of positions of hypothesis in the goals buffer. Maintained by a hook in `proof-shell-handle-delayed-output-hook'.") ;; Hyps name are clickable and have a special keymap. (defun coq-make-hypname-overlay (beg end h buf) (let ((ov (make-overlay beg end buf))) (when ov (overlay-put ov 'evaporate t) (overlay-put ov 'is-hypname t) (overlay-put ov 'hyp-name h) (overlay-put ov 'keymap coq-hypname-map)) ov)) ;; Hyps types are clickable only when folded (defun coq-make-hyp-overlay (beg end h buf) (let ((ov (make-overlay beg end buf))) (when ov (overlay-put ov 'evaporate t) (overlay-put ov 'is-hyp t) (overlay-put ov 'hyp-name h)) ov)) (defun coq-hypcross-unfolded-string() (propertize "-" 'face 'coq-button-face 'mouse-face 'coq-button-face-active)) (defun coq-hypcross-folded-string() (propertize "+" 'face 'coq-button-face-pressed 'mouse-face 'coq-button-face-active)) ;; hypcross is displayerd with a "-" when unfolded and a "+" when unfolded. ;; It is highlighted when hovered, is clickable and have a special ;; keymap (f toggles folding, h toggles highlighting...). ;; PC: using button faces of make-button makes the button larger than a ;; characters, which messes columns. So we use simple background colors in ;; coq-hyp...faces (defun coq-make-hypcross-overlay (beg end h buf) (let ((ov (make-overlay beg end buf))) (when ov (overlay-put ov 'evaporate t) (overlay-put ov 'is-hypcross t) (overlay-put ov 'hyp-name h) (overlay-put ov 'keymap coq-hypcross-map) (overlay-put ov 'display (coq-hypcross-unfolded-string)) ;(overlay-put ov 'face 'coq-button-face) ;(overlay-put ov 'mouse-face 'coq-button-face-pressed) ;(overlay-put ov 'width .6) ;(overlay-put ov 'height -1) (when (eq coq-hypcross-hovering-help t) (overlay-put ov 'help-echo "MOUSE-1: (un)fold ; MOUSE-2 copy hyp name at point"))) ov)) ;; Once we have created the 3 overlays, each recieves a reference to the 2 ;; others. (defun coq-hyp-overlay-build-cross-refs (hypnameov hypov crosshypov) (overlay-put hypnameov 'hypcross-ov crosshypov) (overlay-put hypov 'hypcross-ov crosshypov) (overlay-put hypnameov 'hyp-ov hypov) (overlay-put crosshypov 'hyp-ov hypov) (overlay-put hypov 'hypname-ov hypnameov) (overlay-put crosshypov 'hypname-ov hypnameov)) (defun coq-build-hyp-overlay (hyp-positions buf) (let* ((names (car hyp-positions)) (fstname (car names)) (positions (cdr hyp-positions)) (begcross (car positions)) (beghypname (cadr positions)) (endhypname (cl-caddr positions)) (beg (cl-cadddr positions)) (end (cl-cadddr (cdr positions)))) (let ((hypnameov (coq-make-hypname-overlay beghypname endhypname fstname buf)) (hypov (coq-make-hyp-overlay beg end fstname buf)) (crosshypov (coq-make-hypcross-overlay begcross (+ 1 begcross) fstname buf)) res) (coq-hyp-overlay-build-cross-refs hypnameov hypov crosshypov) (mapc (lambda (s) (setq res (cons (cons (substring-no-properties s) (cons hypov (cons hypnameov (cons crosshypov nil)) )) res))) names) res))) (defun coq-build-hyps-overlays (hyp-positions buf) (let ((res)) (mapc (lambda (x) (let ((lassoc (coq-build-hyp-overlay x buf))) (setq res (append lassoc res)))) hyp-positions) res)) ; builds the list of names from one hyp position (which may contained several ; hyp names) (defun coq-build-hyp-name (hyp-positions) (let* ((names (car hyp-positions)) res) (mapc (lambda (s) (setq res (cons (substring-no-properties s) res))) names) res)) ;; Build the list of hyps names (defun coq-build-hyps-names (hyp-positions) (let ((res)) (mapc (lambda (x) (let ((lassoc (coq-build-hyp-name x))) (setq res (append lassoc res)))) hyp-positions) res)) (defun coq-detect-hyps-in-goals () "Detect all hypotheses displayed in goals buffer and create overlays. Three overlays are created for each hyp: (hypov hypnameov hypcrossov), respectively for the whole hyp, only its name and the overlay for fold/unfold cross. Return the list of mappings hypname -> overlays." ;; FIXME: Consolidate the `with-current-buffer proof-goals-buffer's. (let* ((fsthyp-pos (with-current-buffer proof-goals-buffer (coq-find-first-hyp))) (fsthyp-ov (when fsthyp-pos (with-current-buffer proof-goals-buffer (overlays-at fsthyp-pos)))) ; is there at least one hyp overlay there? (fsthyp-hypov (when fsthyp-ov (cl-some (lambda(x) (overlay-get x 'hyp-name)) fsthyp-ov)))) (if fsthyp-hypov coq-hyps-positions ;overlays are already there (with-current-buffer proof-goals-buffer (coq-build-hyps-overlays (coq-detect-hyps-positions-in-goals) proof-goals-buffer))))) (defun coq-find-hyp-overlay (h) (cadr (assoc h coq-hyps-positions))) ;;;;;;;;;;;;;; Highlighting hypothesis ;;;;;;;; ;; Feature: highlighting of hypothesis that remains when the script is played ;; (and goals buffer is updated). ;; On by default. This only works with the Search function for now. (defvar coq-highlight-hyps-cited-in-response t "If non-nil, try to highlight in goals buffers hyps cited in response.") (defvar coq-highlight-hyps-sticky nil "If non-nil, try to make hypothesis highlighting sticky. The is try to re-highlight the hypothesis with same names after a refreshing of the response buffer.") ;; We maintain a list of hypothesis names that must be highlighted at each ;; regeneration of goals buffer. (defvar coq-highlighted-hyps nil "List of hypothesis names that must be highlighted. These are rehighlighted at each regeneration of goals buffer using a hook in `proof-shell-handle-delayed-output-hook'.") (defvar coq-highlighted-hyps-bg "gray" "background color for highlighted hyps.") (defun coq-highlight-hyp-aux (h) "Auxiliary function, use `coq-highlight-hyp' for sticky highlighting. Unless you want the highlighting to disappear after the goals buffer is updated." (let ((hyp-overlay (coq-find-hyp-overlay h))) (when hyp-overlay (overlay-put hyp-overlay 'face `(:background ,coq-highlighted-hyps-bg))))) (defun coq-unhighlight-hyp-aux (h) "Auxiliary function, use `coq-unhighlight-hyp' for sticky highlighting. Unless you want the highlighting to disappear after the goals buffer is updated." (let* ((hyp-overlay (coq-find-hyp-overlay h))) (when hyp-overlay (overlay-put hyp-overlay 'face nil)))) (defun coq-highlight-hyp (h) "Highlight hypothesis named H (sticky). use `coq-unhighlight-hyp' to unhighlight." (unless (member h coq-highlighted-hyps) (setq coq-highlighted-hyps (cons h coq-highlighted-hyps))) (coq-highlight-hyp-aux h)) (defun coq-unhighlight-hyp (h) "Unhighlight hypothesis named H." (when (member h coq-highlighted-hyps) (setq coq-highlighted-hyps (delete h coq-highlighted-hyps)) (coq-unhighlight-hyp-aux h))) (defun coq-highlight-hyps (lh) (mapc #'coq-highlight-hyp lh)) (defun coq-unhighlight-hyps (lh) (mapc #'coq-unhighlight-hyp-aux lh)) (defun coq-highlight-selected-hyps () "Highlight all hyps stored in `coq-highlighted-hyps'. This used in hook to rehilight hypothesis after goals buffer is updated." (interactive) (coq-highlight-hyps coq-highlighted-hyps)) (defun coq-unhighlight-selected-hyps () "Unhighlight all hyps stored in `coq-highlighted-hyps'. This used before updating `coq-highlighted-hyps' with a new set of hypothesis to highlight." (interactive) (coq-unhighlight-hyps coq-highlighted-hyps) (setq coq-highlighted-hyps nil)) (defun coq-get-hyps-cited-in-response () "Returns locations of hyps in goals buffer that are cited in response buffer. See `coq-highlight-hyps-cited-in-response' and `Search'." (let* ((hyps-cited-pos (coq-detect-hyps-positions proof-response-buffer)) (hyps-cited (coq-build-hyps-names hyps-cited-pos))) (cl-remove-if-not (lambda (e) (cl-some;seq-find (lambda (f) (string-equal (car e) f)) hyps-cited)) coq-hyps-positions))) (defun coq-highlight-hyps-cited-in-response () "Highlight hypothesis cited in response buffer. Highlight always takes place in goals buffer." (let ((inters (coq-get-hyps-cited-in-response))) (coq-unhighlight-selected-hyps) (setq coq-highlighted-hyps (mapcar #'car inters)) (coq-highlight-selected-hyps))) (defun coq-toggle-highlight-hyp (h) "Toggle the highlighting status of hypothesis H. See `coq-highlight-hyp'." (interactive "sHypothesis name to highlight:") (if (member h coq-highlighted-hyps) (coq-unhighlight-hyp h) (coq-highlight-hyp h))) (defun coq-toggle-highlight-hyp-at (pt) "Toggle hiding the hypothesis at point." (interactive) (let* ((ov (or (car (coq-overlays-at pt 'hyp-name)) ;; we may be between hypname and hyp, so skip backward to ;; something meaningful (save-excursion (goto-char pt) (search-backward-regexp "[^ :=]\\|\n") (car (coq-overlays-at (point) 'hyp-name))))) (hypname (and ov (overlay-get ov 'hyp-name)))) (when hypname (if (member hypname coq-highlighted-hyps) (coq-unhighlight-hyp hypname) (coq-highlight-hyp hypname))))) (defun coq-toggle-highlight-hyp-at-point () (interactive) (coq-toggle-highlight-hyp-at (point))) (defun coq-insert-at-point-hyp-at-mouse (event) (interactive "e") (let ((hyp-name (save-excursion (with-current-buffer proof-goals-buffer (save-excursion (overlay-get (car (overlays-at (posn-point (event-start event)))) 'hyp-name)))))) (insert hyp-name))) ;;;;;;;;;;; Hiding Hypothesis ;;;;;;;;;;; (defvar coq-hidden-hyp-map (make-sparse-keymap) "Keymap for hidden hypothesis.") (defvar coq-hidden-hyps nil "List of hypothesis that should be hidden in goals buffer. These are re-hidden at each regeneration of goals buffer using a hook in `proof-shell-handle-delayed-output-hook'.") (defun coq-toggle-fold-hyp-at (pt) "Toggle hiding the hypothesis at point." (interactive) (let* ((ov (car (coq-overlays-at pt 'hyp-name))) (hypname (and ov (overlay-get ov 'hyp-name)))) (when hypname (if (member hypname coq-hidden-hyps) (coq-unfold-hyp hypname) (coq-fold-hyp hypname))))) (defun coq-toggle-fold-hyp-at-point () (interactive) (coq-toggle-fold-hyp-at (point))) (defun coq-toggle-fold-hyp-at-mouse (event) "Toggle hiding the hypothesis at mouse click. Used on hyptohesis overlays in goals buffer mainly." (interactive "e") (save-excursion (with-current-buffer proof-goals-buffer (save-excursion (coq-toggle-fold-hyp-at (posn-point (event-start event))))))) (defun coq-configure-hyp-overlay-hidden (hyp-overlay h) (when hyp-overlay (let* ((lgthhyp (- (overlay-end hyp-overlay) (overlay-start hyp-overlay))) (prefx (make-string (min 8 lgthhyp) ?.)) (hypcross-ov (overlay-get hyp-overlay 'hypcross-ov))) (overlay-put hyp-overlay 'display prefx ;(propertize prefx 'keymap coq-hidden-hyp-map) ) (overlay-put hyp-overlay 'evaporate t) (overlay-put hyp-overlay 'mouse-face 'proof-command-mouse-highlight-face) (overlay-put hyp-overlay 'help-echo "MOUSE-1: unfold; MOUSE-2 copy name at point") (overlay-put hyp-overlay 'hyp-name h) (overlay-put hyp-overlay 'keymap coq-hidden-hyp-map) (overlay-put hypcross-ov 'display (coq-hypcross-folded-string))))) (defun coq-configure-hyp-overlay-visible (hyp-overlay _h) (when hyp-overlay (overlay-put hyp-overlay 'display nil) (overlay-put hyp-overlay 'evaporate t) (overlay-put hyp-overlay 'mouse-face nil) (overlay-put hyp-overlay 'help-echo nil) (overlay-put hyp-overlay 'keymap nil) (overlay-put (overlay-get hyp-overlay 'hypcross-ov) 'display (coq-hypcross-unfolded-string)))) (defun coq-fold-hyp-aux (h) "Fold hypothesis H's type from the context temporarily. Displays \".......\" instead. This function relies on variable coq-hyps-positions. The hiding is cancelled as soon as the goals buffer is changed, consider using `coq-fold-hyp' if you want the hiding to be maintain when scripting/undoing." (let ((hyp-overlay (coq-find-hyp-overlay h))) (when hyp-overlay (coq-configure-hyp-overlay-hidden hyp-overlay h)))) (defun coq-fold-hyp (h) "Fold hypothesis H's type from the context durably. \(displays \".......\" instead). This function relies on variable ‘coq-hyps-positions’. The hiding maintained as the goals buffer is changed, thanks to a hook on `proof-shell-handle-delayed-output-hook', consider using `coq-fold-hyp' if you want the hiding to be maintain when scripting/undoing." (interactive) (unless (member h coq-hidden-hyps) (setq coq-hidden-hyps (cons h coq-hidden-hyps)) (coq-fold-hyp-aux h))) (defun coq-unfold-hyp-aux (h) "Unfold hypothesis H temporarily. See `coq-fold-hyp-aux'." (let ((hyp-overlay (coq-find-hyp-overlay h))) (coq-configure-hyp-overlay-visible hyp-overlay h))) (defun coq-unfold-hyp (h) "Unfold hypothesis H durably. See `coq-fold-hyp'." (interactive) (when (member h coq-hidden-hyps) (setq coq-hidden-hyps (delete h coq-hidden-hyps)) (coq-unfold-hyp-aux h))) (defun coq-unfold-hyp-list (lh) "Fold the type of hypothesis in LH temporarily. See `coq-unfold-hyp-aux'." (mapc #'coq-unfold-hyp-aux lh)) (defun coq-fold-hyp-list (lh) "Fold the type of hypothesis in LH temporarily. See `coq-fold-hyp-aux'." (mapc #'coq-fold-hyp-aux lh)) (defun coq-fold-hyps () "Fold the type of hypothesis in LH durably. See `coq-fold-hyp'." (interactive) (coq-fold-hyp-list coq-hidden-hyps)) (defun coq-unfold-hyps () "Unfold the type of hypothesis in LH durably. See `coq-unfold-hyp'." (interactive) (coq-unfold-hyp-list coq-hidden-hyps) (setq coq-hidden-hyps nil)) (defun coq-toggle-fold-hyp (h) "Toggle the hiding status of hypothesis H (asked interactively). See `coq-fold-hyp'." (interactive "sHypothesis to fold: ") (if (member h coq-hidden-hyps) (coq-unfold-hyp h) (coq-fold-hyp h))) ;;;;;;; (proof-definvisible coq-PrintHint "Print Hint. ") ;; Items on show menu (proof-definvisible coq-show-tree "Show Tree.") (proof-definvisible coq-show-proof "Show Proof.") (proof-definvisible coq-show-conjectures "Show Conjectures.") (proof-definvisible coq-show-intros "Show Intros.") ; see coq-insert-intros below (proof-definvisible coq-set-printing-implicit "Set Printing Implicit.") (proof-definvisible coq-unset-printing-implicit "Unset Printing Implicit.") (proof-definvisible coq-set-printing-all "Set Printing All.") (proof-definvisible coq-unset-printing-all "Unset Printing All.") (proof-definvisible coq-set-printing-synth "Set Printing Synth.") (proof-definvisible coq-unset-printing-synth "Unset Printing Synth.") (proof-definvisible coq-set-printing-coercions "Set Printing Coercions.") (proof-definvisible coq-unset-printing-coercions "Unset Printing Coercions.") (proof-definvisible coq-set-printing-compact-contexts "Set Printing Compact Contexts.") (proof-definvisible coq-unset-printing-compact-contexts "Unset Printing Compact Contexts.") (proof-definvisible coq-set-printing-unfocused "Set Printing Unfocused.") (proof-definvisible coq-unset-printing-unfocused "Unset Printing Unfocused.") (proof-definvisible coq-set-printing-universes "Set Printing Universes.") (proof-definvisible coq-unset-printing-universes "Unset Printing Universes.") (proof-definvisible coq-set-printing-wildcards "Set Printing Wildcard.") (proof-definvisible coq-unset-printing-wildcards "Unset Printing Wildcard.") ; Takes an argument ;(proof-definvisible coq-set-printing-printing-depth "Set Printing Printing Depth . ") ;(proof-definvisible coq-unset-printing-printing-depth "Unset Printing Printing Depth . ") ;; Persistent setting, non-boolean, non cross-version compatible (Coq >= 8.10) (defconst coq-diffs--function #'coq-diffs "Symbol corresponding to the function `coq-diffs'. Required to benefit from delayed evaluation when `proof-assistant-format-lambda' calls (funcall coq-diffs--function) at `proof-assistant-settings-cmds' evaluation time.") (add-to-list 'proof-assistant-settings '(diffs--function "%l" string "Show Diffs in Coq") t) (defun coq-Compile () "Compiles current buffer." (interactive) (let* ((n (buffer-name)) (l (string-match ".v" n))) (compile (concat "make " (substring n 0 l) ".vo")))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Holes mode switch ;; TODO: have this plugged agian when we have abbreviation without holes ;; For now holes are always enabled. ;(defpacustom use-editing-holes t ; "Enable holes for editing." ; :type 'boolean) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Configuring proof and pbp mode and setting up various utilities ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; General consensus among users: flickering spans are much too annoying ;; compared to the usefulness of tooltips. ;; Set to t to bring it back%% ;; ;; FIXME: this always sets proof-output-tooltips to nil, even if the user puts ;; explicitly the reverse in it sconfig file. I just want to change the ;; *default* value to nil. (custom-set-default 'proof-output-tooltips nil) ;;;;;;;;;;;;;;;;;;;;;;;attempt to deal with debug mode ;;;;;;;;;;;;;;;; ;; tries to extract the last debug goal and display it in goals buffer (defun coq-display-debug-goal () (interactive) (with-current-buffer proof-shell-buffer (let ((pt (progn (save-excursion (forward-line -1) (point))))) (save-excursion (re-search-backward "^TcDebug" pt t) (re-search-backward "\\|^TcDebug\\|^" nil t) (when (looking-at "") (let ((pt2 (point))) (re-search-backward "Goal:\\|^TcDebug\\|^" nil t) (when (looking-at "Goal") (pg-goals-display (buffer-substring (point) pt2) nil)))))))) ;; overwrite the generic one, interactive prompt is Debug mode;; try to display ;; the debug goal in the goals buffer. (defun proof-shell-process-interactive-prompt-regexp () "Action taken when `proof-shell-interactive-prompt-regexp' is observed." (when (and (proof-shell-live-buffer) ; not already visible t) (switch-to-buffer proof-shell-buffer) (coq-display-debug-goal) (message "Prover expects input in %s buffer (if debug mode: h for help))" proof-shell-buffer))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (defvar coq-pg-mode-map (let ((map (make-sparse-keymap))) (set-keymap-parent map proof-mode-map) ;;(define-key coq-mode-map coq-double-hit-hot-key 'coq-terminator-insert) ;; Setting the new mapping for terminator, overrides the following in ;; proof-script: ;; (define-key proof-mode-map (vector (aref proof-terminal-string 0)) ;; #'proof-electric-terminator) ;;(define-key proof-mode-map (kbd coq-double-hit-hot-key) ;; #'coq-terminator-insert) (define-key map (kbd ".") #'coq-terminator-insert) ;;(define-key map (kbd ";") #'coq-terminator-insert) ; for french keyboards map)) ;;;###autoload (defun coq-pg-setup () (set-keymap-parent (current-local-map) coq-pg-mode-map) ;; coq-mode colorize errors better than the generic mechanism (setq proof-script-color-error-messages nil) (setq proof-terminal-string ".") ;; superseded by coq-script-parse-function ;;(setq proof-script-command-end-regexp coq-script-command-end-regexp) (setq proof-script-parse-function #'coq-script-parse-function) (setq proof-script-comment-start comment-start) (setq proof-script-comment-end comment-end) (setq proof-script-insert-newlines nil) (setq proof-unnamed-theorem-name "Unnamed_thm") ; Coq's default name (setq proof-assistant-home-page coq-www-home-page) (setq proof-prog-name coq-prog-name) (setq proof-guess-command-line #'coq-guess-command-line) (setq proof-prog-name-guess t) ;; We manage file saveing via coq-compile-auto-save and for coq ;; it is not necessary to save files when starting a new buffer. (setq proof-query-file-save-when-activating-scripting nil) ;; Commands sent to proof engine (setq proof-showproof-command "Show. " proof-context-command "Print All. " proof-goal-command "Goal %s. " proof-save-command "Save %s. " proof-find-theorems-command "Search %s. ") (setq proof-show-proof-diffs-regexp coq-show-proof-diffs-regexp) (setq proof-shell-empty-action-list-command 'coq-empty-action-list-command) ;; FIXME da: Does Coq have a help or about command? ;; proof-info-command "Help" ;; Settings not defined with defpacustom because they have an unsupported ;; type. (setq proof-assistant-additional-settings '(coq-compile-quick coq-compile-keep-going coq-compile-auto-save coq-lock-ancestors coq-diffs)) (setq proof-goal-command-p #'coq-goal-command-p proof-shell-last-cmd-left-goals-p #'coq-open-goals-p proof-find-and-forget-fn #'coq-find-and-forget pg-topterm-goalhyplit-fn #'coq-goal-hyp proof-state-preserving-p #'coq-state-preserving-p) (setq proof-query-identifier-command "Check %s.") ;;TODO: from v8.5 this wold be better: ;;(setq proof-query-identifier-command "About %s.") (setq proof-save-command-regexp coq-save-command-regexp proof-really-save-command-p #'coq-save-command-p ;pierre:deals with Proof . proof-save-with-hole-regexp coq-save-with-hole-regexp proof-goal-with-hole-regexp coq-goal-with-hole-regexp proof-nested-undo-regexp coq-state-changing-commands-regexp proof-script-imenu-generic-expression coq-generic-expression) ;; span menu (setq proof-script-span-context-menu-extensions #'coq-create-span-menu) (setq proof-shell-start-silent-cmd "Set Silent. " proof-shell-stop-silent-cmd "Unset Silent. ") ;; prooftree config (setq proof-tree-configured t proof-tree-get-proof-info 'coq-proof-tree-get-proof-info proof-tree-find-begin-of-unfinished-proof 'coq-find-begin-of-unfinished-proof) ;; proof-omit-proofs config (setq proof-omit-proofs-configured t proof-script-proof-start-regexp coq-proof-start-regexp proof-script-proof-end-regexp coq-proof-end-regexp proof-script-definition-end-regexp coq-definition-end-regexp proof-script-proof-admit-command coq-omit-proof-admit-command) (setq proof-cannot-reopen-processed-files nil) (proof-config-done) ) (defun coq-shell-mode-config () (setq proof-shell-cd-cmd coq-shell-cd proof-shell-filename-escapes '(("\\\\" . "\\\\") ("\"" . "\\\"")) proof-shell-clear-goals-regexp coq-shell-proof-completed-regexp proof-shell-proof-completed-regexp coq-shell-proof-completed-regexp proof-shell-error-regexp coq-error-regexp proof-shell-interrupt-regexp coq-interrupt-regexp proof-shell-assumption-regexp coq-id proof-shell-theorem-dependency-list-regexp coq-shell-theorem-dependency-list-regexp pg-subterm-first-special-char ?\360 ;; The next three represent path annotation information pg-subterm-start-char ?\372 ; not done pg-subterm-sep-char ?\373 ; not done pg-subterm-end-char ?\374 ; not done pg-topterm-regexp "\375" ;; FIXME: ideally, the eager annotation should just be a single "special" char, ;; this requires changes in Coq. proof-shell-eager-annotation-start coq-shell-eager-annotation-start proof-shell-eager-annotation-start-length 32 proof-shell-interactive-prompt-regexp "TcDebug " ;; ****** is added at the end of warnings in emacs mode, this is temporary I ;; want xml like tags, and I want them removed before warning display. ;; I want the same for errors -> pgip proof-shell-eager-annotation-end coq-shell-eager-annotation-end ; done proof-shell-annotated-prompt-regexp coq-shell-prompt-pattern proof-shell-result-start "\372 Pbp result \373" proof-shell-result-end "\372 End Pbp result \373" ; proof-shell-start-goals-regexp "^\\(?:(dependent evars:[^)]*)\\s-+\\)?[0-9]+\\(?: focused\\)? subgoals?" proof-shell-start-goals-regexp "[0-9]+\\(?: focused\\)? \\(?:sub\\)?goals?" proof-shell-end-goals-regexp (if coq-hide-additional-subgoals (setq proof-shell-end-goals-regexp coq-end-goals-regexp-hide-subgoals) (setq proof-shell-end-goals-regexp coq-end-goals-regexp-show-subgoals)) proof-shell-init-cmd coq-shell-init-cmd proof-no-fully-processed-buffer t proof-dependency-menu-system-specific coq-dependency-menu-system-specific proof-dependencies-system-specific coq-dependencies-system-specific ;; Coq has no global settings? ;; (proof-assistant-settings-cmd) proof-shell-restart-cmd coq-shell-restart-cmd pg-subterm-anns-use-stack t) ;; (holes-mode 1) da: does the shell really need holes mode on? (setq proof-shell-font-lock-keywords 'coq-font-lock-keywords-1) ;; prooftree config (setq proof-tree-ignored-commands-regexp coq-proof-tree-ignored-commands-regexp proof-tree-navigation-command-regexp coq-navigation-command-regexp proof-tree-cheating-regexp coq-proof-tree-cheating-regexp proof-tree-new-layer-command-regexp coq-proof-tree-new-layer-command-regexp proof-tree-current-goal-regexp coq-proof-tree-current-goal-regexp proof-tree-update-goal-regexp coq-proof-tree-update-goal-regexp proof-tree-existential-regexp coq-proof-tree-existential-regexp proof-tree-existentials-state-start-regexp coq-proof-tree-existentials-state-start-regexp proof-tree-existentials-state-end-regexp coq-proof-tree-existentials-state-end-regexp proof-tree-additional-subgoal-ID-regexp coq-proof-tree-additional-subgoal-ID-regexp proof-tree-branch-finished-regexp coq-proof-tree-branch-finished-regexp proof-tree-extract-instantiated-existentials 'coq-extract-instantiated-existentials proof-tree-show-sequent-command 'coq-show-sequent-command proof-tree-find-undo-position 'coq-proof-tree-find-undo-position ) (proof-shell-config-done)) (proof-eval-when-ready-for-assistant (easy-menu-define proof-goals-mode-aux-menu proof-goals-mode-map "Menu for Proof General goals buffer." (cons "Coq" coq-other-buffers-menu-entries))) (proof-eval-when-ready-for-assistant (easy-menu-define proof-goals-mode-aux-menu proof-response-mode-map "Menu for Proof General response buffer." (cons "Coq" coq-other-buffers-menu-entries))) (defun coq-goals-mode-config () (setq pg-goals-change-goal "Show %s . ") (setq pg-goals-error-regexp coq-error-regexp) (setq proof-goals-font-lock-keywords coq-goals-font-lock-keywords) (proof-goals-config-done)) (defun coq-response-config () (setq proof-response-font-lock-keywords coq-response-font-lock-keywords) ;; The line wrapping in this buffer just seems to make it less readable. (setq truncate-lines t) (proof-response-config-done)) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Flags and other settings for Coq. ;; These appear on the Coq -> Setting menu. ;; ;; FIXME da: we should send this command only inside a proof, ;; otherwise it gives an error message. It should be on ;; a different menu command. ;; (defpacustom print-only-first-subgoal nil ;; "Whether to just print the first subgoal in Coq." ;; :type 'boolean ;; :setting ("Focus. " . "Unfocus. ")) (defpacustom hide-additional-subgoals nil "Show all subgoals if off, show only the current goal if on." :type 'boolean :safe 'booleanp :eval (coq-hide-additional-subgoals-switch)) ; ;; FIXME: to handle "printing all" properly, we should change the state ;; of the variables that also depend on it. ;; da: ;; pc: removed it and others of the same kind. Put an "option" menu instead, ;; with no state variable. To have the state we should use coq command that ;; output the value of the variables. ;(defpacustom print-fully-explicit nil ; "Print fully explicit terms." ; :type 'boolean ; :setting ("Set Printing All. " . "Unset Printing All. ")) ; (defpacustom printing-depth 50 "Depth of pretty printer formatting, beyond which dots are displayed." :type 'integer :setting "Set Printing Depth %i . ") (defun coq-diffs () "Return string for setting Coq Diffs. Return the empty string if the version of Coq < 8.10." (setq pg-insert-text-function #'coq-insert-tagged-text) (if (coq--post-v810) (format "Set Diffs \"%s\". " (symbol-name coq-diffs)) "")) (defun coq-diffs--setter (symbol new-value) ":set function fo `coq-diffs'. Set Diffs setting if Coq is running and has a version >= 8.10." (set symbol new-value) (if (proof-shell-available-p) (let ((cmd (coq-diffs))) (if (equal cmd "") (message "Ignore coq-diffs setting %s for Coq before 8.10" (symbol-name coq-diffs)) (proof-shell-invisible-command cmd))))) (defcustom coq-diffs 'off "Controls Coq Diffs option" :type '(radio (const :tag "Don't show diffs" off) (const :tag "Show diffs: only added" on) (const :tag "Show diffs: added and removed" removed)) :safe (lambda (v) (member v '(off on removed))) :set #'coq-diffs--setter :group 'coq) ;; Obsolete: ;;(defpacustom undo-depth coq-default-undo-limit ;; "Depth of undo history. Undo behaviour will break beyond this size." ;; :type 'integer ;; :setting "Set Undo %i . ") ;; Problem if the Remove or Add fails we leave Coq's blacklist in a strange ;; state: unnoticed by the user, and desynched from ;; coq-search-blacklist-current-string. ;; TODO: have a way to detect error and re-set old value. (defun coq-change-search-blacklist (s) (let* ((cmd-clean (list (format "Remove Search Blacklist %s." coq-search-blacklist-current-string))) (item-clean `(nil ,cmd-clean proof-done-invisible 'invisible)) (cmd-set (list (format "Add Search Blacklist %s." s))) (item-set `(nil ,cmd-set proof-done-invisible 'invisible))) (proof-add-to-queue `(,item-clean ,item-set) 'advancing))) (defun coq-change-search-blacklist-interactive () (interactive) (proof-shell-ready-prover) (let* ((current-value coq-search-blacklist-current-string) (s (read-string "Set search blacklist to: " current-value 'proof-minibuffer-history))) (coq-change-search-blacklist s) (setq coq-search-blacklist-current-string s))) ;; (defpacustom search-blacklist coq-search-blacklist-string ;; "Strings to blacklist in requests to Coq environment." ;; :type 'string ;; :get 'coq-get-search-blacklist ;; :setting coq-set-search-blacklist) (defpacustom time-commands nil "Whether to display timing information for each command." :type 'boolean :eval (coq-time-commands-switch)) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; prooftree support ;; (defun coq-proof-tree-get-proof-info () "Coq instance of `proof-tree-get-proof-info'." (let* ((info (or (coq-last-prompt-info-safe) '(0 0 nil nil)))) ;; info is now a list with ;; * the state number ;; * the proof stack depth ;; * the list of all open proofs ;; * the name of the current proof or nil (list (car info) (nth 3 info)))) (defun coq-extract-instantiated-existentials (start end) "Coq specific function for `proof-tree-extract-instantiated-existentials'. Return the list of currently instantiated existential variables." (proof-tree-extract-list start end coq-proof-tree-existentials-state-start-regexp coq-proof-tree-existentials-state-end-regexp coq-proof-tree-instantiated-existential-regexp)) (defun coq-show-sequent-command (sequent-id) "Coq specific function for `proof-tree-show-sequent-command'." (format "Show Goal \"%s\"." sequent-id)) (defun coq-proof-tree-get-new-subgoals () "Check for new subgoals and issue appropriate Show commands. This is a hook function for `proof-tree-urgent-action-hook'. This function examines the current goal output and searches for new unknown subgoals. Those subgoals have been generated by the last proof command and we must send their complete sequent text eventually to prooftree. Because subgoals may change with the next proof command, we must execute the additionally needed Show commands before the next real proof command. The ID's of the open goals are checked with `proof-tree-sequent-hash' in order to find out if they are new. For any new goal an appropriate Show Goal command with a 'proof-tree-show-subgoal flag is inserted into `proof-action-list'. Then, in the normal delayed output processing, the sequent text is send to prooftree as a sequent update (see `proof-tree-update-sequent') and the ID of the sequent is registered as known in `proof-tree-sequent-hash'. Searching for new subgoals must only be done when the proof is not finished, because Coq 8.5 lists open existential variables as (new) open subgoals. For this test we assume that `proof-marker' has not yet been moved. The `proof-tree-urgent-action-hook' is also called for undo commands. For those, nothing is done. The not yet delayed output is in the region \[proof-shell-delayed-output-start, proof-shell-delayed-output-end]." ;; (message "CPTGNS start %s end %s" ;; proof-shell-delayed-output-start ;; proof-shell-delayed-output-end) (let ((start proof-shell-delayed-output-start) (end proof-shell-delayed-output-end) (state (car proof-info))) (when (> state proof-tree-last-state) (with-current-buffer proof-shell-buffer ;; The message "All the remaining goals are on the shelf" is processed as ;; urgent message and is therefore before ;; proof-shell-delayed-output-start. We therefore need to go back to ;; proof-marker. (goto-char proof-marker) (unless (proof-re-search-forward coq-proof-tree-branch-finished-regexp end t) (goto-char start) (while (proof-re-search-forward coq-proof-tree-additional-subgoal-ID-regexp end t) (let ((subgoal-id (match-string-no-properties 1))) (unless (gethash subgoal-id proof-tree-sequent-hash) ;; (message "CPTGNS new sequent %s found" subgoal-id) (push (proof-shell-action-list-item (coq-show-sequent-command subgoal-id) (proof-tree-make-show-goal-callback (car proof-info)) '(no-goals-display no-response-display proof-tree-show-subgoal)) proof-action-list))))))))) (add-hook 'proof-tree-urgent-action-hook #'coq-proof-tree-get-new-subgoals) (defun coq-find-begin-of-unfinished-proof () "Return start position of current unfinished proof or nil." (let ((span (span-at (1- (proof-unprocessed-begin)) 'type))) ;; go backward as long as we are inside the proof ;; the proofstack property is set inside the proof ;; the command before the proof has the goalcmd property (while (and span (span-property span 'proofstack) (not (span-property span 'goalcmd))) (setq span (span-at (1- (span-start span)) 'type))) ;; Beware of completed proofs! They have type goalsave and for ;; strange reasons the whole completed proof has the goalcmd property. (if (and span (not (eq 'goalsave (span-property span 'type))) (span-property span 'goalcmd)) (span-start span) nil))) (defun coq-proof-tree-find-undo-position (state) "Return the position for undo state STATE. This is the Coq incarnation of `proof-tree-find-undo-position'." (let ((span-res nil) (span-cur (span-at (1- (proof-unprocessed-begin)) 'type)) (state (1- state))) ;; go backward as long as the statenum property in the span is greater or ;; equal than state (while (<= state (span-property span-cur 'statenum)) (setq span-res span-cur) (setq span-cur (span-at (1- (span-start span-cur)) 'type))) (span-start span-res))) ;; In Coq 8.6 the evar line is disabled by default because on some proofs it ;; causes a severe performance hit. The disabled evar line causes prooftree to ;; crash with a parsing error. Proof General must therefore turn on the evar ;; output with the command "Set Printing Dependent Evars Line". Of course, ;; after the proof, the evar line must be set back to what it was before the ;; proof. I therefore look in the urgent action hook if proof display is ;; switched on or off. When switched on, I test the current evar printing ;; status with the undocumented command "Test Printing Dependent Evars Line" to ;; remember if I have to switch evar printing off eventually. (defvar coq--proof-tree-must-disable-evars nil "Remember if evar printing must be disabled when leaving the current proof.") (defun coq-proof-tree-enable-evar-callback (_span) "Callback for the evar printing status test. This is the callback for the command ``Test Printing Dependent Evars Line''. It checks whether evar printing was off and remembers that fact in `coq--proof-tree-must-disable-evars'." (with-current-buffer proof-shell-buffer (save-excursion ;; When the callback runs, the next item is sent to Coq already and ;; therefore proof-marker points to the end of the next command ;; already. proof-shell-filter-manage-output sets old-proof-marker ;; before calling proof-shell-exec-loop, this therefore points to the ;; end of the command of this callback. (goto-char old-proof-marker) (when (re-search-forward "The Printing Dependent Evars Line mode is " nil t) (if (looking-at "off") (progn ;; (message "CPTEEC evar line mode was off") (setq coq--proof-tree-must-disable-evars t)) ;; (message "CPTEEC evar line mode was on") (setq coq--proof-tree-must-disable-evars nil)))))) (defun coq-proof-tree-insert-evar-command (cmd &optional callback) "Insert an evar printing command at the head of `proof-action-list'." (push (proof-shell-action-list-item (concat cmd " Printing Dependent Evars Line.") (if callback callback 'proof-done-invisible) (list 'invisible)) proof-action-list)) (defun coq-proof-tree-enable-evars () "Enable the evar status line for Coq >= 8.6. Test the status of evar printing to be able to set it back properly after the proof and enable the evar printing." (when (coq--post-v86) ;; We push to proof-action-list --- therefore we need to push in reverse ;; order! (coq-proof-tree-insert-evar-command "Set") (coq-proof-tree-insert-evar-command "Test" 'coq-proof-tree-enable-evar-callback))) (defun coq-proof-tree-disable-evars () "Disable evar printing if necessary. This function switches off evar printing after the proof, if it was off before the proof. For undo commands, we rely on the fact that Coq itself undoes the effect of the evar printing change that we inserted after the goal statement. We also rely on the fact that Proof General never backtracks into the middle of a proof. (If this would happen, Coq would switch evar printing on and the code here would not switch it off after the proof.) Being called from `proof-tree-urgent-action-hook', this function can rely on `proof-info' being dynamically bound to the last result of `coq-proof-tree-get-proof-info'." (when coq--proof-tree-must-disable-evars (when (> (car proof-info) proof-tree-last-state) (coq-proof-tree-insert-evar-command "Unset")) (setq coq--proof-tree-must-disable-evars nil))) (defun coq-proof-tree-evar-display-toggle () "Urgent action hook function for changing the evar printing status in Coq. This function is for `proof-tree-urgent-action-hook' (which is called only if external proof display is switched on). It checks whether a proof was started or stopped and inserts commands for enableing and disabling the evar status line for Coq 8.6 or later. Without the evar status line being enabled, prooftree crashes. Must only be called via `proof-tree-urgent-action-hook' to ensure that the dynamic variable `proof-info' is bound to the current result of `coq-proof-tree-get-proof-info'." (let ((current-proof-name (cadr proof-info))) (cond ((and (null proof-tree-current-proof) current-proof-name) ;; started a new proof (coq-proof-tree-enable-evars)) ((and proof-tree-current-proof (null current-proof-name)) ;; finished the current proof (coq-proof-tree-disable-evars))))) (add-hook 'proof-tree-urgent-action-hook #'coq-proof-tree-evar-display-toggle) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Pre-processing of input string ;; (defconst coq--time-prefix "Time " "Coq command prefix for displaying timing information.") (defun coq-bullet-p (s) (string-match coq-bullet-regexp-nospace s)) ;; Remark: `action' and `string' are known by `proof-shell-insert-hook' (defun coq-preprocessing () (when coq-time-commands (with-no-warnings ;; NB: dynamic scoping of `string' and `action' ;; Don't add the prefix if this is a command sent internally (unless (or (eq action 'proof-done-invisible) (coq-bullet-p string)) ;; coq does not accept "Time -". (setq string (concat coq--time-prefix string)))))) (add-hook 'proof-shell-insert-hook #'coq-preprocessing) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Subterm markup -- it was added to Coq by Healf, but got removed. ;; Let's try faking something by regexp matching. ;; FIXME: not operational yet (defun coq-fake-constant-markup () "Markup constants in Coq goal output by matching on regexps. This is a horrible and approximate way of doing subterm markup. \(Code used to be in Coq, but got lost between versions 5 and 7). This is a hook setting for `pg-after-fontify-output-hook' to enable identifiers to be highlighted and allow useful mouse activation." (goto-char (point-min)) ;; FIXME: This regexp is obviously wrong. The backslashes have no effect ;; (for lack of being doubled), so Emacs searches for "(w+[^w])" :-( ;; Also the \w regexp operator cannot be used within a [...] char range. (while (re-search-forward "\(\w+[^\w]\)" nil t) (replace-match "\372\200\373\\1\374" nil t))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Context-senstive in-span menu additions ;; (defun coq-create-span-menu (span idiom _name) (if (eq idiom 'proof) (let ((thm (span-property span 'name))) (list (vector "Check" ; useful? `(proof-shell-invisible-command ,(format "Check %s." thm))) (vector "Print" `(proof-shell-invisible-command ,(format "Print %s." thm))))))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Some smart insertion functions ;; (defconst module-kinds-table '(("Section" 0) ("Module" 1) ("Module Type" 2) ("Declare Module" 3)) "Enumerates the different kinds of modules.") (defconst modtype-kinds-table '(("" 1) (":" 2) ("<:" 3)) "Enumerates the different kinds of type information for modules.") (defun coq-postfix-.v-p (s) (string-match-p "\\.v\\'" s)) (defun coq-directories-files (l) (let* ((file-list-list (mapcar #'directory-files l)) (file-list (apply #'append file-list-list)) (filtered-list (cl-remove-if-not #'coq-postfix-.v-p file-list))) filtered-list)) (defun coq-remove-dot-v-extension (s) (substring s 0 -2)) (defun coq-load-path-to-paths (ldpth) (if (listp ldpth) (car ldpth) ldpth)) (defun coq-build-accessible-modules-list () (let* ((pth (or coq-load-path '("."))) (cleanpth (mapcar #'coq-load-path-to-paths pth)) (existingpth (cl-remove-if-not #'file-exists-p cleanpth)) (file-list (coq-directories-files existingpth))) (mapcar #'coq-remove-dot-v-extension file-list))) (defun coq-insert-section-or-module () "Insert a module or a section after asking right questions." (interactive) (let* ((mods (completing-read "Kind of module (TAB to see list): " module-kinds-table)) (s (read-string "Name: ")) (typkind (if (string-equal mods "Section") "" ;; if not a section (completing-read "Kind of type (optional, TAB to see list): " modtype-kinds-table))) (p (point))) (if (string-equal typkind "") (progn (insert mods " " s ".\n#\nEnd " s ".") (holes-replace-string-by-holes-backward p) (goto-char p)) (insert mods " " s " " typkind " #.\n#\nEnd " s ".") (holes-replace-string-by-holes-backward p) (goto-char p) (holes-set-point-next-hole-destroy)))) (defconst reqkinds-kinds-table '(("Require Import") ("Require Export") ("Require") ("Import")) "Enumerates the different kinds of requiring a module.") (defun coq-insert-requires () "Insert requires to modules, iteratively." (interactive) (let* ((s) (reqkind (completing-read "Command (TAB to see list, default Require Import) : " reqkinds-kinds-table nil nil nil nil "Require Import"))) (cl-loop do (setq s (completing-read "Name (empty to stop) : " (coq-build-accessible-modules-list))) (unless (zerop (length s)) (insert (format "%s %s.\n" reqkind s))) while (not (string-equal s ""))))) ;; TODO add module closing (defun coq-end-Section () "Ends a Coq section." (interactive) (let ((count 1)) ; The number of section already "Ended" + 1 (let ((section (save-excursion (progn (while (and (> count 0) (search-backward-regexp "Chapter\\|Section\\|End" 0 t)) (if (char-equal (char-after (point)) ?E) (setq count (1+ count)) (setq count (1- count)))) (buffer-substring-no-properties (progn (beginning-of-line) (forward-word 1) (point)) (progn (end-of-line) (point))))))) (insert (concat "End" section))))) (defun coq--format-intros (output) "Create an “intros” or ”move” form from the OUTPUT of “Show Intros”." (let* ((shints1 (replace-regexp-in-string "^[0-9] \\(?:sub\\)?goal\\(.\\|\n\\|\r\\)*" "" output)) (shints (replace-regexp-in-string "[\r\n ]*\\'" "" shints1))) (if (or (string= "" shints) (string-match coq-error-regexp shints)) (error "Don't know what to intro") (save-excursion (if (re-search-backward "Require.*ssreflect" nil t) (format "move=> %s" shints) (format "intros %s" shints)))))) (defun coq-insert-intros () "Insert an intros or move command with names given by Show Intros. Based on idea mentioned in Coq reference manual." (interactive) (let* ((output (proof-shell-invisible-cmd-get-result "Show Intros."))) (indent-region (point) (progn (insert (coq--format-intros output)) (save-excursion (insert (if coq-one-command-per-line "\n" " ")) (point)))) ;; `proof-electric-terminator' moves the point in all sorts of strange ;; ways, so we run it last (let ((last-command-event ?.)) ;; Insert a dot (proof-electric-terminator)))) (defvar coq-keywords-accepting-as-regex (regexp-opt '("induction" "destruct" "inversion" "injection"))) ;; destruct foo., where foo is a name. (defvar coq-auto-as-hack-hyp-name-regex (concat "\\(" "induction\\|destruct" "\\)\\s-+\\(" coq-id-shy "\\)\\s-*\\.") "Regexp of commands needing a hack to generate correct \"as\" close. tacitcs like destruct and induction reuse hypothesis names by default, which makes the detection of new hypothesis incorrect. the hack consists in adding the \"!\" modifier on the argument destructed, so that it is left in the goal and the name cannot be reused. We also had a \"clear\" at the end of the tactic so that the whole tactic behaves correctly. Warning: this makes the error messages (and location) wrong.") (defun coq-hack-cmd-for-infoH (s) "return the tactic S hacked with infoH tactical." (cond ((string-match ";" s) s) ;; composed tactic cannot be treated ((string-match coq-auto-as-hack-hyp-name-regex s) (concat "infoH " (match-string 1 s) " (" (match-string 2 s) ").")) ((string-match coq-keywords-accepting-as-regex s) (concat "infoH " s)) (t (concat "infoH " s)))) ;; Point supposed to be at the end of locked region, that is ;; (proof-assert-next-command-interactive) has just finished (defun coq-tactic-already-has-an-as-close(s) "Return t if the last tactic of locked region contains an \"as\" close." (save-excursion (string-match "\\" s))) ;::::::::::::: inserting suggested Proof using XXX... ;;;;;;;;;; ;; global mechanism: ;; When some dependency oinformation is detected (see ;; `coq-shell-theorem-dependency-list-regexp') a hook is triggered by pg. We ;; configure this hook to perform the following: if the user set ;; `coq-accept-proof-using-suggestion' to 'always, then perform the insertion ;; immediately via using `coq-insert-proof-using', otherwise add the menu entry ;; to make it later (actually the current impolementation always adds the menu ;; entry, which is wrong because the span is not there if the insertion was ;; already performed.). ;; This variable is used by generic pg code. Every time this is detected in the ;; output, it sets the `proof-last-theorem-dependencies' variable. Substring 1 ;; should contain the name of the theorem, and substring 2 should contain its ;; dependencies. The content of `proof-last-theorem-dependencies' is then used ;; by pg generic code to trigger `proof-depends-process-dependencies', which ;; itself sets the 'dependencies property of the span, and calls ;; `proof-dependencies-system-specific'. The latter is bound to ;; `coq-dependencies-system-specific' below. (defconst coq-shell-theorem-dependency-list-regexp "\n?The proof of \\(?1:[^ \n]+\\)\\(?: \\|\n\\)should start with one of the following commands:\\(?: \\|\n\\)Proof using\\(?2:[^.]*\\)\\.") (defcustom coq-accept-proof-using-suggestion 'highlight "Whether and how proofgeneral should insert \"Proof using\" suggestions. Suggestions are emitted by Coq at Qed time. The possible values of this variable are: - 'always: always insert the suggested annotation - 'highlight (default value): highlight the Proof command and have a contextual menu for insertion (or M-x coq-insert-suggested-dependency when point is on the proof considered) - 'ask: asks the user each time. If yes then do as 'always, else do as 'highlight - 'never: ignore completely the suggestions. Remarks and limitations: - do not support nested proofs. - always use the *first* annotation suggested by coq. - the proof is not replayed, which is consistent with the fact that pg currently do not deal with async proofs. - if there is already a \"Proof using\" annotation, then either it is correct and nothing happens, or it is incorrect and coq generates an error. PG won't try to replace the erroneous annotation in this case, but you can always go back, remove it by hand, and let pg insert the good one. - instead of the menu you can do M-x coq-insert-suggested-dependency when point is on the proof considered. " :type '(choice (const :tag "Ask user" ask) (const :tag "Always accept" always) (const :tag "Higihlight" never) (const :tag "Ignore completely" ignore)) :group 'coq) ;; putting "Type" instead of nothing, otherwise Coq may fail if a "with" ;; anotation is also present: (Proof using with auto raises an error in ;; coq<=8.12 at least). (defun coq-hack-proofusing-suggestion (suggested) (if (string-equal "" suggested) "Type" suggested)) ;; the additional menu for "proof using". highlights the "Proof." command, and ;; have a entry to insert the annotation and remove the highlight. (defvar coq-dependency-menu-system-specific (lambda (span) (let* ((deps (span-property-safe span 'dependencies)) (specialspans (spans-at-region-prop (span-start span) (span-end span) 'proofusing)) (specialspan (and specialspans (not (cdr specialspans)) (car specialspans))) (suggested (mapconcat #'identity deps " ")) (suggested (coq-hack-proofusing-suggestion suggested)) (name (concat " insert \"proof using " suggested "\"")) (fn (lambda (sp) (coq-insert-proof-using-suggestion sp t) (and specialspan (span-delete specialspan))))) (list "-------------" (vector name `(,fn ,span) t)))) "Coq specific additional menu entry for \"Proof using\". annotation. See `proof-dependency-menu-system-specific'." ) (defconst coq-proof-using-regexp "\\_\\([^<]*\\)" ;; proof-shell-last-response-output would be ;; smaller/faster but since this message is output ;; *before* resulting goals, it is not detected as ;; a response message. proof-shell-last-output)) (substr (or (and str (match-string 1 proof-shell-last-output)) "")) ;; emptysubstr = t if substr is empty or contains only spaces and | (emptysubstr (and (string-match "\\(\\s-\\||\\)*" substr) (eq (length substr) (length (match-string 0 substr)))))) ; idem (unless (or emptysubstr (coq-tactic-already-has-an-as-close newcmd)) ;; FIXME (save-excursion ;; TODO: look for eqn:XX and go before it. ;; Go just before the last "." (goto-char (proof-unprocessed-begin)) (coq-script-parse-cmdend-forward) (coq-script-parse-cmdend-backward) (insert (concat " as [" substr "]"))))))))) ;; Trying to propose insertion of "as" for a whole region. But iterating ;; proof-assert-next-command-interactive is probably wrong if some error occur ;; during scripting. ;; (defun coq-insert-as-in-region (&optional beg end) ;; (interactive "r") ;; (let ((beg (or beg (point-min))) ;; (end (or end (point-max)))) ;; (goto-char beg) ;; (while (< (point) end) ;; (coq-script-parse-cmdend-forward) ;; (coq-insert-as-in-next-command) ;; (proof-assert-next-command-interactive)))) (defun coq-insert-match () "Insert a match expression from a type name by Show Match. Based on idea mentioned in Coq reference manual. Also insert holes at insertion positions." (interactive) (proof-shell-ready-prover) (let* ((cmd)) (setq cmd (read-string "Build match for type: ")) (let* ((thematch (proof-shell-invisible-cmd-get-result (concat "Show Match " cmd "."))) (match (replace-regexp-in-string "=> *\n" "=> #\n" thematch))) ;; if error, it will be displayed in response buffer (see def of ;; proof-shell-invisible-cmd-get-result), otherwise: (unless (proof-string-match coq-error-regexp match) (let ((start (point))) (insert match) (indent-region start (point) nil) (let ((n (holes-replace-string-by-holes-backward start))) (pcase n (0 nil) ; no hole, stay here. (1 (goto-char start) (holes-set-point-next-hole-destroy)) ; if only one hole, go to it. (_ (goto-char start) (message (substitute-command-keys "\\[holes-set-point-next-hole-destroy] to jump to active hole. \\[holes-short-doc] to see holes doc.")))))))))) (defun coq-insert-solve-tactic () "Ask for a closing tactic name, with completion, and insert at point. Completion is on a quasi-exhaustive list of Coq closing tactics." (interactive) (coq-insert-from-db coq-solve-tactics-db "Closing tactic")) (defun coq-insert-tactic () "Insert a tactic name at point, with completion. Questions may be asked to the user to select the tactic." (interactive) (coq-insert-from-db coq-tactics-db "Tactic")) (defun coq-insert-tactical () "Ask for a closing tactic name, with completion, and insert at point. Completion is on a quasi-exhaustive list of Coq tacticals." (interactive) (coq-insert-from-db coq-tacticals-db "Tactical")) (defun coq-insert-command () "Ask for a command name, with completion, and insert it at point." (interactive) (coq-insert-from-db coq-commands-db "Command")) (defun coq-insert-term () "Ask for a term kind, with completion, and insert it at point." (interactive) (coq-insert-from-db coq-terms-db "Kind of term")) (defun coq-query (showall) "Ask for a query, with completion, and send to Coq." (interactive "P") (let ((q (coq-build-command-from-db coq-queries-commands-db "which Query?"))) (if showall (coq-command-with-set-unset "Set Printing All" q "Unset Printing All" nil "Test Printing All") (proof-shell-invisible-command q)))) (defun coq-Search () (interactive) (coq-ask-do ;; TODO: use [Add Search Blacklist "foo"] to exclude optionaly some patterns: ;; "_ind" "_rec" "R_" "_equation" "Search (ex: \"eq_\" eq -bool)" "Search" nil nil t) (when coq-highlight-hyps-cited-in-response (coq-highlight-hyps-cited-in-response) (message "M-x coq-unhighlight-selected-hyps to remove highlighting, [Coq/Settings/Search Blacklist] to change blacklisting.")) (unless coq-highlight-hyps-cited-in-response (message "[Coq/Settings/Search Blacklist] to change blacklisting."))) ;; Insertion commands (define-key coq-keymap [(control ?i)] #'coq-insert-intros) (define-key coq-keymap [(control ?m)] #'coq-insert-match) (define-key coq-keymap [(control ?\()] #'coq-insert-section-or-module) (define-key coq-keymap [(control ?\))] #'coq-end-Section) (define-key coq-keymap [(control ?t)] #'coq-insert-tactic) (define-key coq-keymap [?t] #'coq-insert-tactical) (define-key coq-keymap [?!] #'coq-insert-solve-tactic) ; will work in tty (define-key coq-keymap [(control ?\s)] #'coq-insert-term) (define-key coq-keymap [(control return)] #'coq-insert-command) (define-key coq-keymap [(control ?q)] #'coq-query) (define-key coq-keymap [(control ?r)] #'coq-insert-requires) ; [ for "as [xxx]" is easy to remember, ccontrol-[ would be better but hard to type on french keyboards ; anyway company-coq should provide an "as!". (define-key coq-keymap [(?\[)] #'coq-insert-as-in-next-command) ;; not for goal/response buffer? ; Query commands (define-key coq-keymap [(control ?s)] #'coq-Show) (define-key coq-keymap [?r] #'proof-store-response-win) (define-key coq-keymap [?g] #'proof-store-goals-win) (define-key coq-keymap [(control ?o)] #'coq-SearchIsos) (define-key coq-keymap [(control ?p)] #'coq-Print) (define-key coq-keymap [(control ?b)] #'coq-About) (define-key coq-keymap [(control ?a)] #'coq-Search) (define-key coq-keymap [(control ?c)] #'coq-Check) (define-key coq-keymap [?h] #'coq-PrintHint) (define-key coq-keymap [(control ?l)] #'coq-LocateConstant) (define-key coq-keymap [(control ?n)] #'coq-LocateNotation) (define-key coq-keymap [(control ?w)] #'coq-ask-adapt-printing-width-and-show) ;(proof-eval-when-ready-for-assistant ; (define-key ??? [(control c) (control a)] (proof-ass keymap))) ;(proof-eval-when-ready-for-assistant ; (define-key ??? [(control c) (control a)] (proof-ass keymap))) (define-key coq-goals-mode-map [(control ?c)(control ?a)(control ?c)] #'coq-Check) (define-key coq-goals-mode-map [(control ?c)(control ?a)(control ?p)] #'coq-Print) (define-key coq-goals-mode-map [(control ?c)(control ?a)(control ?o)] #'coq-SearchIsos) (define-key coq-goals-mode-map [(control ?c)(control ?a)(control ?b)] #'coq-About) (define-key coq-goals-mode-map [(control ?c)(control ?a)(control ?a)] #'coq-Search) (define-key coq-goals-mode-map [(control ?c)(control ?a)(control ?s)] #'coq-Show) (define-key coq-goals-mode-map [(control ?c)(control ?a)?r] #'proof-store-response-win) (define-key coq-goals-mode-map [(control ?c)(control ?a)?g] #'proof-store-goals-win) (define-key coq-goals-mode-map [(control ?c)(control ?a)?h] #'coq-PrintHint) (define-key coq-goals-mode-map [(control ?c)(control ?a)(control ?q)] #'coq-query) (define-key coq-goals-mode-map [(control ?c)(control ?a)(control ?w)] #'coq-ask-adapt-printing-width-and-show) (define-key coq-goals-mode-map [(control ?c)(control ?a)(control ?l)] #'coq-LocateConstant) (define-key coq-goals-mode-map [(control ?c)(control ?a)(control ?n)] #'coq-LocateNotation) ;; specific to goals buffer: (un)foldinng and (un)highlighting shortcuts (define-key coq-goals-mode-map [?f] #'coq-toggle-fold-hyp-at-point) (define-key coq-goals-mode-map [?F] #'coq-unfold-hyps) (define-key coq-goals-mode-map [?h] #'coq-toggle-highlight-hyp-at-point) (define-key coq-goals-mode-map [?H] #'coq-unhighlight-selected-hyps) (define-key coq-response-mode-map [(control ?c)(control ?a)(control ?c)] #'coq-Check) (define-key coq-response-mode-map [(control ?c)(control ?a)(control ?p)] #'coq-Print) (define-key coq-response-mode-map [(control ?c)(control ?a)(control ?o)] #'coq-SearchIsos) (define-key coq-response-mode-map [(control ?c)(control ?a)(control ?b)] #'coq-About) (define-key coq-response-mode-map [(control ?c)(control ?a)(control ?a)] #'coq-Search) (define-key coq-response-mode-map [(control ?c)(control ?a)(control ?s)] #'coq-Show) (define-key coq-response-mode-map [(control ?c)(control ?a)(control ?r)] #'proof-store-response-win) (define-key coq-response-mode-map [(control ?c)(control ?a)(control ?g)] #'proof-store-goals-win) (define-key coq-response-mode-map [(control ?c)(control ?a)?h] #'coq-PrintHint) (define-key coq-response-mode-map [(control ?c)(control ?a)(control ?q)] #'coq-query) (define-key coq-response-mode-map [(control ?c)(control ?a)(control ?w)] #'coq-ask-adapt-printing-width-and-show) (define-key coq-response-mode-map [(control ?c)(control ?a)(control ?l)] #'coq-LocateConstant) (define-key coq-response-mode-map [(control ?c)(control ?a)(control ?n)] #'coq-LocateNotation) (when coq-remap-mouse-1 (define-key proof-mode-map [(control down-mouse-1)] #'coq-id-under-mouse-query) (define-key proof-mode-map [(shift down-mouse-1)] #'coq-id-under-mouse-query) (define-key proof-mode-map [(control mouse-1)] #'ignore) (define-key proof-mode-map [(shift mouse-1)] #'ignore) (define-key proof-mode-map [(control shift down-mouse-1)] #'coq-id-under-mouse-query) (define-key proof-mode-map [(control shift mouse-1)] #'ignore) (define-key proof-response-mode-map [(control down-mouse-1)] #'coq-id-under-mouse-query) (define-key proof-response-mode-map [(shift down-mouse-1)] #'coq-id-under-mouse-query) (define-key proof-response-mode-map [(control mouse-1)] #'ignore) (define-key proof-response-mode-map [(shift mouse-1)] #'ignore) (define-key proof-response-mode-map [(control shift down-mouse-1)] #'coq-id-under-mouse-query) (define-key proof-response-mode-map [(control shift mouse-1)] #'ignore) (define-key proof-goals-mode-map [(control down-mouse-1)] #'coq-id-under-mouse-query) (define-key proof-goals-mode-map [(shift down-mouse-1)] #'coq-id-under-mouse-query) (define-key proof-goals-mode-map [(control mouse-1)] #'ignore) (define-key proof-goals-mode-map [(shift mouse-1)] #'ignore) (define-key proof-goals-mode-map [(control shift down-mouse-1)] #'coq-id-under-mouse-query) (define-key proof-goals-mode-map [(control shift mouse-1)] #'ignore)) ;; Default binding on hypothesis names: clicking on the name of an hyp with ;; button 3 folds it. Click on it with button 2 copies the names at current ;; point. (when coq-hypname-map (define-key coq-hypname-map [(mouse-3)] #'coq-toggle-fold-hyp-at-mouse) (define-key coq-hypcross-map [(return)] #'coq-toggle-fold-hyp-at-point) (define-key coq-hypname-map [(mouse-2)] #'coq-insert-at-point-hyp-at-mouse)) ;; Default binding: clicking on the cross to folds/unfold hyp. ;; Click on it with button 2 copies the names at current point. (when coq-hypname-map (define-key coq-hypcross-map [(mouse-1)] #'coq-toggle-fold-hyp-at-mouse) (define-key coq-hypcross-map [(return)] #'coq-toggle-fold-hyp-at-point) (define-key coq-hypcross-map [(mouse-2)] #'coq-insert-at-point-hyp-at-mouse)) ;; Ddefault binding: clicking on a hidden hyp with button 3 unfolds it, with ;; button 2 it copies hyp name at current point. (when coq-hidden-hyp-map (define-key coq-hidden-hyp-map [(mouse-1)] #'coq-toggle-fold-hyp-at-mouse) (define-key coq-hypcross-map [(return)] #'coq-toggle-fold-hyp-at-point) (define-key coq-hidden-hyp-map [(mouse-2)] #'coq-insert-at-point-hyp-at-mouse)) ;;;;;;;;;;;;;;;;;;;;;;;; ;; error handling ;;;;;;;;;;;;;;;;;;;;;;;; (defvar last-coq-error-location nil "Last error from `coq-get-last-error-location' and `coq-highlight-error'.") (defvar coq--error-location-regexp "^Toplevel input[^:]+:\n> \\(.*\\)\n> \\([^^]*\\)\\(\\^+\\)\n" "A regexp to search the header of coq error locations.") ;; I don't use proof-shell-last-output here since it is not always set to the ;; really last output (specially when a *tactic* gives an error) instead I go ;; directly to the response buffer. This allows also to clean the response ;; buffer (better to only scroll it?) (defun coq-get-last-error-location (&optional parseresp clean) "Return location information on last error sent by coq. Return a two elements list (POS LEN) if successful, nil otherwise. POS is the number of characters preceding the underlined expression, and LEN is its length. Coq error message must be like this: \" > command with an error here ... > ^^^^ \" If PARSERESP is nil, don't really parse response buffer but take the value of `last-coq-error-location' instead, otherwise parse response buffer and updates `last-coq-error-location'. If PARSERESP and CLEAN are non-nil, delete the error location from the response buffer." (if (not parseresp) last-coq-error-location ;; proof-shell-handle-error-or-interrupt-hook is called from shell buffer ;; then highlight the corresponding error location (proof-with-current-buffer-if-exists proof-response-buffer (goto-char (point-max)) ;\nToplevel input, character[^:]:\n (when (re-search-backward coq--error-location-regexp nil t) (let ((text (match-string 1)) (pos (length (match-string 2))) (len (length (match-string 3)))) ;; clean the response buffer from ultra-ugly underlined command line ;; parsed above. Don't kill the first \n (let ((inhibit-read-only t)) (when clean (delete-region (match-beginning 0) (match-end 0)))) (when proof-shell-unicode ;; TODO: remove this (when...) when coq-8.3 is out. ;; `pos' and `len' are actually specified in bytes, apparently. So ;; let's convert them, assuming the encoding used is utf-8. ;; Presumably in Emacs-23 we could use `string-bytes' for that ;; since the internal encoding happens to use utf-8 as well. ;; Actually in coq-8.3 one utf8 char = one space so we do not need ;; this at all (let ((bytes text)) ;(encode-coding-string text 'utf-8-unix) ;; Check that pos&len make sense in `bytes', if not give up. (when (>= (length bytes) (+ pos len)) ;; We assume here that `text' is a single line and use \n as ;; a marker so we can find it back after decoding. (setq bytes (concat (substring bytes 0 pos) "\n" (substring bytes pos (+ pos len)))) (let ((chars (decode-coding-string bytes 'utf-8-unix))) (setq pos (string-match "\n" chars)) (setq len (- (length chars) pos 1)))))) (setq last-coq-error-location (list pos len))))))) (defun coq-highlight-error (&optional parseresp clean) "Parse the last Coq output looking at an error message. Highlight the text pointed by it. Coq error message must be like this: \" > command with an error here ... > ^^^^ \" If PARSERESP is nil, don't really parse response buffer but take the value of `last-coq-error-location' instead, otherwise parse response buffer and updates `last-coq-error-location'. If PARSERESP and CLEAN are non-nil, delete the error location from the response buffer." (proof-with-current-buffer-if-exists proof-script-buffer (let ((mtch (coq-get-last-error-location parseresp clean))) (when mtch (let ((pos (car mtch)) (lgth (cadr mtch))) (goto-char (+ (proof-unprocessed-begin) 1)) (coq-find-real-start) ;; utf8 adaptation is made in coq-get-last-error-location above (let ((time-offset (if coq-time-commands (length coq--time-prefix) 0))) (goto-char (+ (point) pos)) (span-make-self-removing-span (point) (+ (point) (- lgth time-offset)) 'face 'proof-warning-face))))))) (defun coq-highlight-error-hook () (coq-highlight-error t t)) (add-hook 'proof-shell-handle-error-or-interrupt-hook #'coq-highlight-error-hook t) ;; ;; Scroll response buffer to maximize display of first goal ;; (defun coq-first-word-before (reg) "Get the word before first string matching REG in current buffer." (save-excursion (goto-char (point-min)) (re-search-forward reg nil t) (goto-char (match-beginning 0)) (backward-word 1) (buffer-substring (point) (progn (forward-word 1) (point))))) (defun coq-get-from-to-paren (reg) "Get the word after first string matching REG in current buffer." (save-excursion (goto-char (point-min)) (if (null (re-search-forward reg nil t)) "" (goto-char (match-end 0)) (let ((p (point))) (if (null (re-search-forward ")" nil t)) "" (goto-char (match-beginning 0)) (buffer-substring p (point))))))) (defun coq-show-first-goal () "Scroll the goal buffer so that the first goal is visible. First goal is displayed on the bottom of its window, maximizing the number of hypothesis displayed, without hiding the goal" (interactive) ;; CPC 2015-12-31: Added the check below: if the command that caused this ;; call was silent, we shouldn't touch the goals buffer. See GitHub issues ;; https://github.com/cpitclaudel/company-coq/issues/32 and ;; https://github.com/cpitclaudel/company-coq/issues/8. (unless (memq 'no-goals-display proof-shell-delayed-output-flags) (let ((pg-frame (car (coq-find-threeb-frames)))) ; selecting the good frame (with-selected-frame (or pg-frame (window-frame (selected-window))) ;; prefer current frame (let ((goal-win (or (get-buffer-window proof-goals-buffer) (get-buffer-window proof-goals-buffer t)))) (if goal-win (with-selected-window goal-win ;; find snd goal or buffer end, if not found this goes to the ;; end of buffer (search-forward-regexp "\\(?:sub\\)?goal 2\\|\\*\\*\\* Unfocused goals:\\|\\'") (beginning-of-line) ;; find something backward else than a space: bottom of concl (ignore-errors (search-backward-regexp "\\S-")) (recenter (- 1)) ; put bot of concl at bottom of window (beginning-of-line) ;; if the top of concl is hidden we may want to show it instead ;; of bottom of concl (when (and coq-prefer-top-of-conclusion ;; return nil if === is not visible (not (save-excursion (re-search-backward "========" (window-start) t)))) (re-search-backward "========" nil t) (recenter 0)) (beginning-of-line)))))))) (defvar coq-modeline-string2 ")") (defvar coq-modeline-string1 ")") (defvar coq-modeline-string0 " Script(") (defun coq-build-subgoals-string (n s) (concat coq-modeline-string0 (int-to-string n) "-" s (if (> n 1) coq-modeline-string2 coq-modeline-string1))) (defun coq-update-minor-mode-alist () "Modify `minor-mode-alist' to display the number of subgoals in the modeline." (when (and proof-goals-buffer proof-script-buffer) (let ((nbgoals (with-current-buffer proof-goals-buffer (string-to-number (coq-first-word-before "focused\\|\\(?:sub\\)?goal")))) (nbunfocused (with-current-buffer proof-goals-buffer (coq-get-from-to-paren "unfocused: ")))) (with-current-buffer proof-script-buffer (let ((toclean (assq 'proof-active-buffer-fake-minor-mode minor-mode-alist))) (while toclean ;; clean minor-mode-alist (setq minor-mode-alist (remove toclean minor-mode-alist)) (setq toclean (assq 'proof-active-buffer-fake-minor-mode minor-mode-alist))) (setq minor-mode-alist (append (list (list 'proof-active-buffer-fake-minor-mode (coq-build-subgoals-string nbgoals nbunfocused))) minor-mode-alist))))))) ;; This hook must be added before coq-optimise-resp-windows, in order to be evaluated ;; *after* windows resizing. (add-hook 'proof-shell-handle-delayed-output-hook #'coq-show-first-goal) (add-hook 'proof-shell-handle-delayed-output-hook #'coq-update-minor-mode-alist) (add-hook 'proof-shell-handle-delayed-output-hook (lambda () (if (proof-string-match coq-shell-proof-completed-regexp proof-shell-last-output) (proof-clean-buffer proof-goals-buffer)))) (add-hook 'proof-shell-handle-delayed-output-hook (lambda () (setq coq-hyps-positions (coq-detect-hyps-in-goals)) (when coq-highlight-hyps-sticky (coq-highlight-selected-hyps)) (coq-fold-hyps) )) (defun is-not-split-vertic (_selected-window) (<= (- (frame-height) (window-height)) 2)) ;; bug fixed in generic ocde, useless now: ;(add-hook 'proof-activate-scripting-hook (lambda () (when proof-three-window-enable (proof-layout-windows)))) ;; *Experimental* auto shrink response buffer in three windows mode. Things get ;; a bit messed up if the response buffer is not at the right place (below ;; goals buffer) TODO: Have this linked to proof-resize-window-tofit in ;; proof-utils.el + customized by the "shrink to fit" menu entry ;; + have it on by default when in three windows mode. ;; The philosophy is that if goals and response are on the same column, their ;; cumulated size should not change. (defun coq-optimise-resp-windows () "Resize response buffer to optimal size. Only when three-buffer-mode is enabled." ;; CPC 2015-12-31: Added the check below: if the command that caused this ;; call was silent, we shouldn't touch the response buffer. See GitHub ;; issues https://github.com/cpitclaudel/company-coq/issues/32 and ;; https://github.com/cpitclaudel/company-coq/issues/8. (unless (memq 'no-response-display proof-shell-delayed-output-flags) ;; If there is no frame with goql+response then do nothing (when proof-three-window-enable (let ((threeb-frames (coq-find-threeb-frames))) (when threeb-frames (let ((pg-frame (car threeb-frames))) ; selecting one adequate frame (with-selected-frame pg-frame (let ((response-window (get-buffer-window proof-response-buffer t)) (goals-window (get-buffer-window proof-goals-buffer t))) (when (and response-window (> (frame-height) 10)) (with-selected-window response-window (with-current-buffer proof-response-buffer (let* ((response-height (window-text-height response-window)) (goals-height (window-text-height goals-window)) (maxhgth (- (+ response-height goals-height) window-min-height)) (nline-resp ; number of lines we want for response buffer (min maxhgth (max window-min-height ; + 1 for comfort (+ 1 (count-lines (point-max) (point-min))))))) (unless (is-not-split-vertic (selected-window)) (shrink-window (- response-height nline-resp))) (goto-char (point-min)) (recenter))))))))))))) ;; TODO: remove/add hook instead? (defun coq-optimise-resp-windows-if-option () (when coq-optimise-resp-windows-enable (coq-optimise-resp-windows))) ;; TODO: I would rather have a response-insert-hook thant this two hooks ;; Careful: coq-optimise-resp-windows must be called BEFORE proof-show-first-goal, ;; i.e. added in hook AFTER it. ;; Adapt when displaying a normal message (add-hook 'proof-shell-handle-delayed-output-hook #'coq-optimise-resp-windows-if-option) ;; Adapt when displaying an error or interrupt (add-hook 'proof-shell-handle-error-or-interrupt-hook #'coq-optimise-resp-windows-if-option) ;;; DOUBLE HIT ELECTRIC TERMINATOR ;; Trying to have double hit on colon behave like electric terminator. The "." ;; is used for records and modules qualified notatiohns, so electric terminator ;; is not pertinent. ;; TODO: make this a minor mode with something in the modeline, like in ;; pg-user.el for electric-terminator. ;; TODO: Have the same for other commands, but with insertion at all. (defcustom coq-double-hit-enable nil "* Experimental: Whether or not double hit should be enabled in coq mode. A double hit is performed by pressing twice a key quickly. If this variable is not nil, then 1) it means that electric terminator is off and 2) a double hit on the terminator act as the usual electric terminator. See `proof-electric-terminator'." :type 'boolean :set #'proof-set-value :group 'proof-user-options) (defvar coq-double-hit-hot-key "." "The key used for double hit electric terminator. By default this is the coq terminator \".\" key. For example one can do this: \(setq coq-double-hit-hot-key (kbd \";\")) to use semi-colon instead (on French keyboard, it is the same key as \".\" but without shift.") (defvar coq-double-hit-hot-keybinding nil "The keybinding that was erased by double hit terminator enabling. It will be restored if double hit terminator is toggle off.") ;; We redefine the keybinding when we go in and out of double hit mode, even if ;; in principle coq-terminator-insert is compatible with ;; proof-electric-terminator. This may be overprudent but I suspect that (defun coq-double-hit-enable () "Disables electric terminator since double hit is a replacement. This function is called by `proof-set-value' on `coq-double-hit-enable'." (when (and coq-double-hit-enable proof-electric-terminator-enable) (proof-electric-terminator-toggle 0)) ;; this part switch between bindings of coq-double-hit-hot-key: the nominal ;; one and coq-terminator-insert ; (if (not coq-double-hit-enable) ; (define-key coq-mode-map (kbd coq-double-hit-hot-key) coq-double-hit-hot-keybinding) ; (setq coq-double-hit-hot-keybinding (key-binding coq-double-hit-hot-key)) ; (define-key coq-mode-map (kbd coq-double-hit-hot-key) 'coq-terminator-insert)) ) (proof-deftoggle coq-double-hit-enable coq-double-hit-toggle) (defadvice proof-electric-terminator-enable (after coq-unset-double-hit-advice) "Disable double hit terminator since electric terminator is a replacement. This is an advice to pg `proof-electric-terminator-enable' function." (when (and coq-double-hit-enable proof-electric-terminator-enable) (coq-double-hit-toggle 0) (message "Hit M-1 . to enter a real \".\"."))) (ad-activate 'proof-electric-terminator-enable) (defvar coq-double-hit-delay 0.25 "The maximum delay between the two hit of a double hit in coq/proofgeneral.") (defvar coq-double-hit-timer nil "The timer used to watch for double hits.") (defvar coq-double-hit-hot nil "The variable telling that a double hit is still possible.") (defun coq-unset-double-hit-hot () "Disable timer `coq-double-hit-timer' and set it to nil. Shut off the current double hit if any. This function is supposed to be called at double hit timeout." (when coq-double-hit-timer (cancel-timer coq-double-hit-timer)) (setq coq-double-hit-hot nil) (setq coq-double-hit-timer nil)) (defun coq-colon-self-insert () "Detect a double hit and act as electric terminator if detected. Starts a timer for a double hit otherwise." (interactive) (if (and coq-double-hit-hot (not (proof-inside-comment (point))) (not (proof-inside-string (point)))) (progn (coq-unset-double-hit-hot) (delete-char -1) ; remove previously typed char (proof-assert-electric-terminator)); insert the terminator (self-insert-command 1) (setq coq-double-hit-hot t) (setq coq-double-hit-timer (run-with-timer coq-double-hit-delay nil #'coq-unset-double-hit-hot)))) (defun coq-terminator-insert (&optional count) "A wrapper on `proof-electric-terminator'. Used to accept double hits instead if enabled. If by accident option `proof-electric-terminator-enable' and option `coq-double-hit-enable' are non-nil at the same time, this gives priority to the former." (interactive) (if (and (not proof-electric-terminator-enable) coq-double-hit-enable (null count)) (coq-colon-self-insert) ;; otherwise call this, which checks proof-electric-terminator-enable (proof-electric-terminator count))) (put 'coq-terminator-insert 'delete-selection t) ;;;;;;;;;;;;;; kill coq background process on different occasions ;;;;;;;;;;;;;; ;; This originates from background compilation, but it is actually a good idea ;; even when "compile when require" is off. When switching scripting buffer, ;; let us restart the coq shell process, so that it applies local coqtop ;; options. (defun coq-kill-proof-shell () "Kill the proof shell without asking the user. This function is for `proof-deactivate-scripting-hook'. It kills the proof shell without asking the user for confirmation (assuming she agreed already on switching the active scripting buffer). This is needed to ensure the load path is correct in the new scripting buffer." (unless proof-shell-exit-in-progress (proof-shell-exit t))) (add-hook 'proof-deactivate-scripting-hook #'coq-kill-proof-shell t) (defcustom coq-kill-coq-on-opam-switch t "If t kill coq when the opam switch changes (requires `opam-switch-mode'). When `opam-switch-mode' is loaded and the user changes the opam switch through `opam-switch-mode' then this option controls whether the coq background process (the proof shell) is killed such that the next assert command starts a new proof shell, probably using a different coq version from a different opam switch. See https://github.com/ProofGeneral/opam-switch-mode for `opam-switch-mode'" :type 'boolean :group 'coq) (defun coq-kill-proof-shell-on-opam-switch () "Kill proof shell when the opam switch changes (requires `opam-switch-mode'). This function is for the `opam-switch-mode' hook `opam-switch-change-opam-switch-hook', which runs when the user changes the opam switch through `opam-switch-mode'. If `coq-kill-coq-on-opam-switch' is t, then the proof shell is killed such that the next assert starts a new proof shell, using coq from the new opam switch." (when (and coq-kill-coq-on-opam-switch proof-script-buffer) (coq-kill-proof-shell))) (add-hook 'opam-switch-change-opam-switch-hook #'coq-kill-proof-shell-on-opam-switch t) ;;;;;;;;;;;;;;; ;; overwriting the default behavior, this is an experiment, *frames* will be ;; deleted only if only displaying associated buffers. If this is OK the ;; function itself will replace the other in generic. (defun proof-delete-other-frames () (proof-delete-all-associated-windows)) (provide 'coq) ;; Local Variables: *** ;; fill-column: 79 *** ;; indent-tabs-mode: nil *** ;; coding: utf-8 *** ;; End: *** ;;; coq.el ends here PG-4.5/coq/coqtags000077500000000000000000000105031426357011200140410ustar00rootroot00000000000000#!/usr/bin/perl # # Or perhaps: /usr/local/bin/perl # # undef $/; # undef input file separator; $_ gives the whole file if($#ARGV<$[) {die "No Files\n";} open($tagfile,">TAGS") || die "Couldn't open TAGS: $!\n"; while(<>) { print "Tagging $ARGV\n"; $a=$_; # read the whole file into $a $cp=1; # emacs char number of the start of # the current line $lp=1; # line number $tagstring=""; # accumulate all tags of one file here while(1) { # ---- Get the next statement starting on a newline ---- # read over balanced comments if($a=~/^[ \t\n]*\(\*/) { while($a=~/^\s*\(\*/) { $d=1; $a=$'; $cp+=length $&; $lp+=(($wombat=$&)=~tr/\n/\n/); while($d>0 && $a=~/\(\*|\*\)/) { $a=$'; $cp+=2+length $`; $lp+=(($wombat=$`)=~tr/\n/\n/); if($& eq "(*") {$d++} else {$d--}; } if($d!=0) {die "Unbalanced Comment?";} } } # skip remainder of a line after a comment or a statement if($cp>1 && $a=~/.*\n/) {$a=$'; $cp+=length $&; $lp++;} # skip white space lines while($a=~/^[ \t]*\n/) {$cp+=length $&;$lp++;$a=$'} # match the next statement if($a=~/^[^\.]*\./) { $stmt=$&; $newa=$'; $newcp=$cp+length $&; $newlp=$lp+(($wombat=$&)=~tr/\n/\n/); } else { last;} # ---- The above embarrasses itself if there are semicolons inside comments # ---- inside commands. Could do better. # print "----- (",$lp,",",$cp,")\n", $stmt, "\n"; if($stmt=~/^([ \t]*((Fact)|(Goal)|(Lemma)|(Remark)|(Theorem)|(Proposition)|(Corollary))\s+([\w\']+)).*:/) { $tagstring.=$1."\177".$10."\001".$lp.",".$cp."\n"; } elsif($stmt=~/^([ \t]*((Axiom)|(Hypothesis)|(Parameter)|(Variable))\s+[\w\']+)/) { adddecs($stmt,$1); } elsif($stmt=~/^([ \t]*((Definition)|(Fixpoint)|(Inductive)|(CoInductive)|(Record)|(Variant))\s+([\w\']+))/) { $tagstring.=$1."\177".$9."\001".$lp.",".$cp."\n"; if($2 eq "Inductive" || $2 eq "CoInductive" || $2 eq "Variant"){ add_constructors($stmt); } elsif($2 eq "Record"){ add_record_labels($stmt, $8); } } $cp=$newcp; $lp=$newlp; $a=$newa; } print $tagfile "\f\n".$ARGV.",".(length $tagstring)."\n".$tagstring; } close $tagfile; sub adddecs { $wk=$_[0]; $tag=$_[1]; $sep=","; while($tst=($wk=~/\s*([\w\']+)\s*([,:\[])/) && $sep eq ",") { $sep=$2; $tagstring.=$tag."\177".$1."\001".$lp.",".$cp."\n"; $wk=$'; } 0; } sub add_constructors { my ($stmt) = @_; my ($line, $tag); my $current=0; # skip to the body of the inductive definition # and match the first constructor if($stmt=~/:=\s*(?:\|\s*)?([\w\']+)/gc){ do { $tag=$1; $line=substr($stmt, $current, pos($stmt)-$current); # the previous match may span several lines # need to remove all but the last line if($line=~/^.*\n/s){ $current+= length($&); $cp+= length($&); $lp+= (($wombat=$&)=~ tr/\n/\n/); $line=substr($stmt, $current, pos($stmt)-$current); } # print "C $tag in line $lp at $cp\n\tline: $line\n"; $tagstring.=$line."\177".$tag."\001".$lp.",".$cp."\n"; # match now the next constructor } while($stmt=~/\G.*?\|\s*([\w\']+)/sgc); } } sub add_record_labels { my ($stmt, $record_name) = @_; my ($line, $tag); my $current=0; # skip to the body of the record and match the record constructor if($stmt=~/:=\s*([\w\']+)?/gc){ if(defined($1)){ $tag=$1; } else { $tag="Build_".$record_name; } $line=substr($stmt, $current, pos($stmt)-$current); # the previous match may span several lines # need to remove all but the last line if($line=~/^.*\n/s){ $current+= length($&); $cp+= length($&); $lp+= (($wombat=$&)=~ tr/\n/\n/); $line=substr($stmt, $current, pos($stmt)-$current); } $tagstring.=$line."\177".$tag."\001".$lp.",".$cp."\n"; # match the first record label if($stmt=~/\G\s*{\s*([\w\']+)/gc){ do { $tag=$1; $line=substr($stmt, $current, pos($stmt)-$current); # the previous match may span several lines # need to remove all but the last line if($line=~/^.*\n/s){ $current+= length($&); $cp+= length($&); $lp+= (($wombat=$&)=~ tr/\n/\n/); $line=substr($stmt, $current, pos($stmt)-$current); } $tagstring.=$line."\177".$tag."\001".$lp.",".$cp."\n"; # match now the next record label } while($stmt=~/\G.*?;\s*([\w\']+)/sgc); } } } PG-4.5/coq/ex-module.v000066400000000000000000000022641426357011200145450ustar00rootroot00000000000000(* Some scripting tests for modules. Pierre Courtieu. *) Module Type O1. Parameter A:Set. Parameter B:Set. End O1. Module R:O1. Definition A:=nat. Definition B:=bool. End R. Module R2: O1 with Definition A:=nat. Definition A:=nat. Definition B:=bool. End R2. Module R4. Module R3: O1 with Definition A:=nat :=R2. End R4. Module M. Module Type SIG. Parameter T:Set. Parameter x:T. End SIG. Module Type SIG'. Parameter T:Set. Parameter x:T. End SIG'. Lemma toto : O=O. Definition t:=nat. trivial. Save. Module N:SIG. Definition T:=nat. Definition x:=O. End N. Module O:=N. End M. Import M. Print t. Definition t:O=O. trivial. Save. Section toto. Print M. End toto. Module N:=M. Module Type typ. Parameter T:Set. Parameter a:T. End typ. Module Type N'. Module Type M'. Declare Module K:N.SIG. End M'. (* Declare Module N''. *) Definition T:=nat. Definition x:=O. (* End N''. *) Declare Module N':M.SIG. (* no interactive def started *) Declare Module N''' :M.SIG. (* no interactive def started *) End N'. Lemma titi : O=O. trivial. Module Type K:=N'. Module N''':=M. Save. PG-4.5/coq/ex/000077500000000000000000000000001426357011200130675ustar00rootroot00000000000000PG-4.5/coq/ex/KnasterTarski.v000066400000000000000000000016021426357011200160420ustar00rootroot00000000000000(* A sample tarski theorem proof, for f: A -> A. Syntax is for coq v8. *) Parameter A : Set. Variable R : A -> A -> Prop. Variable Eq : A -> A -> Prop. Axiom Assym : forall x y : A, R x y -> R y x -> Eq x y. Axiom Trans : forall x y z : A, R x y -> R y z -> R x z. Variable f : A -> A. Axiom Incr : forall x y : A, R x y -> R (f x) (f y). Variable M : A. Hypothesis Up : forall x : A, R x (f x) -> R x M. Hypothesis Least : forall x : A, (forall y : A, R y (f y) -> R y x) -> R M x. Hint Resolve Up Assym Incr Least Incr Up Trans : db. Theorem Tarski_lemma : Eq M (f M). (* We can prove the theorem in one line: *) (* eauto 15 with db. *) (* But we rather use basic tactics in this sample file: *) cut (R M (f M)). intro. apply Assym; trivial. apply Up. apply Incr; trivial. apply Least. intros. apply Trans with (f y); trivial. apply Incr. apply Up; trivial. Qed. PG-4.5/coq/ex/ex-ssreflect.v000066400000000000000000000073371426357011200156740ustar00rootroot00000000000000(* An example of customization file for the hightlight of the Coq Mode *) (*Supposing you .emacs contains the following lines: (load-file "/generic/proof-site.el") (load-file "/pg-ssr.el") And that the file my-tacs.el contains for instance: --- (defcustom coq-user-tactics-db '(("nat_congr" "ncongr" "nat_congr" t "nat_congr") ("nat_norm" "nnorm" "nat_norm" t "nat_norm") ("bool_congr" "bcongr" "bool_congr" t "bool_congr") ("prop_congr" "prcongr" "prop_congr" t "prop_congr") ("move" "m" "move" t "move") ("pose" "po" "pose # := #" t "pose") ("set" "set" "set # := #" t "set") ("have" "hv" "have # : #" t "have") ("congr" "con" "congr #" t "congr") ("wlog" "wlog" "wlog : / #" t "wlog") ("without loss" "wilog" "without loss #" t "without loss") ("unlock" "unlock" "unlock #" t "unlock") ("suffices" "suffices" "suffices # : #" t "suffices") ("suff" "suff" "suff # : #" t "suff") ) "Extended list of tactics, includings ssr and user defined ones") (defcustom coq-user-commands-db '(("Prenex Implicits" "pi" "Prenex Implicits #" t "Prenex\\s-+Implicits") ("Hint View for" "hv" "Hint View for #" t "Hint\\s-+View\\s-+for") ("inside" "ins" nil f "inside") ("outside" "outs" nil f "outside") ) "Extended list of commands, includings ssr and user defined ones") (defcustom coq-user-tacticals-db '(("last" "lst" nil t "last")) "Extended list of tacticals, includings ssr and user defined ones") (defcustom coq-user-reserved-db '("is" "nosimpl" "of") "Extended list of keywords, includings ssr and user defined ones") (defcustom coq-user-solve-tactics-db '(("done" nil "done" nil "done") ) "Extended list of closing tactic(al)s, includings ssr and user defined ones") --- Below is a sample script file coloured by this customised mode: *) Require Import ssreflect. Require Import ssrbool. Require Import ssrnat. Set Implicit Arguments. Unset Strict Implicit. Import Prenex Implicits. Inductive mylist (A : Type) : Type := mynil | mycons of A & mylist A. (***************** The stack******************) Goal forall A B : Prop, A -> (A -> B) -> B. Proof. move=> A B Ha; exact. Qed. (***************** Bookkeeping **************) Lemma my_mulnI : forall x y, mult x y = muln x y. Proof. elim=> // m Hrec n /=; congr addn; done. Qed. (* Warning : corecion bool >-> Prop *) Lemma demo_bool : forall x y z: bool, x && y -> z -> x && y && z. Proof. by move=> x y z -> ->. Qed. (* com + assoc *) Lemma my_addnCA : forall m n p, m + (n + p) = n + (m + p). Proof. by move=> m n; elim: m => [|m Hrec] p; rewrite ?addSnnS -?addnS. Qed. (*** Rotation of subgoals *) Inductive test : nat -> Prop := C1 : forall n, test n | C2 : forall n, test n | C3 : forall n, test n | C4 : forall n, test n. Goal forall n, test n -> True. move=> n t; case: t; last 1 [move=> k| move=> l]; last first. Admitted. (*** Selection of subgoals *) Goal forall n, test n -> True. move=> n t; case E: t; first 1 last. Admitted. (*** Forward chaining *) Lemma demo_fwd : forall x y : nat, x = y. Proof. move=> x y. suff [H1 H2] : (x, y) = (x * 1, y + 0). Admitted. Lemma demo_fwd2 : forall x y : nat, x = y. Proof. move=> x y. wlog : x / x <= y. Admitted. Lemma rwtest1 : let x := 3 in x * 2 = 6. Proof. move=> x. rewrite /x //=. Qed. (* => unfold + simpl *) Lemma rwtest2 : forall x, 0 * x = 0. Proof. move=> x. rewrite -[0 * x]/0 //. Qed. (* => conversion *) Goal (forall t u, t + u = u + t) -> forall x y, x + y = y + x. Proof. by move=> H x y; rewrite (*[x + _ ]H *) [_ + y]H. Qed. (* => with patterns *) Goal (forall t u, t + u = u + t) -> forall x y, x + y + (y + x) = y + x. move=> H x y; rewrite {2}(H y). Admitted. (* => occurrence selection *) PG-4.5/coq/ex/example-utf8.v000066400000000000000000000006601426357011200155770ustar00rootroot00000000000000(* -*- coding: utf-8; -*- *) Require Import Utf8. (* Printing of unicode notation, in *goals* *) Lemma test : ∀ A:Prop, A -> A. auto. Qed. (* Parsing of unicode notation here, printing in *goals* *) Lemma test2 : ∀ A:Prop, A → A. intro. intro. auto. Qed. (* Printing of unicode notation, in *response* *) Check (fun (X:Set)(x:X) => x). (* Parsing of unicode notation here, printing in *response* *) Check (∀A, A→A). PG-4.5/coq/ex/indent.v000066400000000000000000000234561426357011200145510ustar00rootroot00000000000000(* First check that ".." is not considered as a command end. *) Require Export Coq.Lists.List. Notation "[ ]" := nil : list_scope. Notation "[ a ; .. ; b ]" := (a :: .. (b :: []) ..) : list_scope. Require Import Arith. Open Scope nat_scope. Definition arith1:= 1 + 3 * 4. Definition arith2 := 1 * 3 + 4. Definition logic1 := True \/ False /\ False. Definition logic2 := True /\ False \/ False. Definition logic3 := let x := True /\ False in True \/ False . Definition logic4 := (let x := True /\ False in True) \/ False . Record a : Type := make_a { aa : nat }. Module foo. Inductive test : nat -> Prop := C1 : forall n, test n | C2 : forall n, test n | C3 : forall n, test n | C4 : forall n, test n. Inductive testbar' : nat -> Prop := | Cbar1 : forall n, test n | Cbar2 : forall n, test n | Cbar3 : forall n, test n | Cbar4 : forall n, test n. Inductive test2 : nat -> Prop := | C21 : forall n, test2 n | C22 : forall n, test2 n | C23 : forall n, test2 n | C24 : forall n, test2 n. Inductive test' : nat -> Prop := C1' : forall n, test' n | C2' : forall n, test' n | C3' : forall n, test' n | C4' : forall n, test' n with test2' : nat -> Prop := C21' : forall n, test2' n | C22' : forall n, test2' n | C23' : forall n, test2' n | C24' : forall n, test2' n with test3' : nat -> Prop := C21' : forall n, test2' n | C22' : forall n, test2' n | C23' : forall n, test2' n | C24' : forall n, test2' n with test4' : nat -> Prop := | C21' : forall n, test2' n | C22' : forall n, test2' n | C23' : forall n, test2' n | C24' : forall n, test2' n. Let x := 1. Let y := 2. Let y2 := (1, 2, 3, 4, 5). Inductive test3 (* fixindent *) : nat -> Prop := C31 : forall n, test3 n | C32 : forall n, test3 n. End foo. Lemma toto:nat. Proof. {{ exact 3. }} Qed. Let xxx (* Precedence of "else" w.r.t "," and "->"! *) : if true then nat * nat else nat -> nat := (if true then 1 else 2, 3). Module Y. Lemma L : forall x:nat , Nat.iter x (A:=nat) (plus 2) 0 >= x. Proof with auto with arith. intros x. induction x;simpl;intros... Qed. Lemma L2 : forall x:nat , Nat.iter x (A:=nat) (plus 2) 0 >= x. Proof with auto with arith. idtac. (* "as" tactical *) induction x as [ | x IHx]. - cbn. apply Nat.le_trans with (n:=0) (* aligning the different closes of a "with". *) (m:=0) (p:=0). + auto with arith. + auto with arith. - simpl. intros. auto with arith. Qed. Lemma L' : forall x:nat , Nat.iter x (A:=nat) (plus 2) 0 >= x with L'' : forall x:nat , Nat.iter x (A:=nat) (plus 2) 0 >= x. Proof with auto with arith. - induction x;simpl;intros... - induction x;simpl;intros... Qed. Lemma L''' : forall x:nat , Nat.iter x (A:=nat) (plus 2) 0 >= x. Proof using Type *. intros x. induction x;simpl;intros. admit. Admitted. Lemma L'''' : forall x:nat , 0 <= x. Proof (fun x : nat => Nat.le_0_l x). (* no indentation here since the proof above closes the proof. *) Definition foo:nat := 0. End Y. Function div2 (n : nat) {struct n}: nat := match n with | 0 => 0 | 1 => 0 | S (S n') => S (div2 n') end. Module M1. Module M2. Lemma l1: forall n:nat, n = n. auto. Qed. Lemma l2: forall n:nat, n = n. auto. Qed. Lemma l3: forall n:nat, n <= n. auto. Qed. (* Lemma l4: forall n:nat, n <= n. Proof. intro. Qed. *) Lemma l5 : forall n:nat, n <= n. Proof. auto. Qed. Lemma l6: forall n:nat, n = n. intros. Lemma l7: forall n:nat, n = n. destruct n. { auto. } { destruct n. { auto. } auto. } Qed. { destruct n. { auto. } { auto. } } Qed. End M2. End M1. Module GoalSelectors. Theorem lt_n_S : (True \/ True \/ True \/ True \/ True ) -> True. Proof. refine (or_ind ?[aa] (or_ind ?[bb] (or_ind ?[cc] (or_ind ?[dd] ?[ee])))). [aa]:{ auto. } 2:{ auto. } [ee]:auto. { auto.} Qed. (* Same without space between "." and "}". *) Theorem lt_n_S2 : (True \/ True \/ True \/ True \/ True ) -> True. Proof. refine (or_ind ?[aa] (or_ind ?[bb] (or_ind ?[cc] (or_ind ?[dd] ?[ee])))). [aa]:{ auto.} 2:{ auto.} [ee]:auto. { auto.} Qed. End GoalSelectors. Module M1'. Module M2'. Lemma l6: forall n:nat, n = n. Proof. intros. Lemma l7: forall n:nat, n = n. Proof. destruct n. { auto. } { destruct n. { idtac;[ auto ]. } auto. } Qed. {destruct n. { auto. } {auto. } } Qed. End M2'. End M1'. (* TODO: add multichar bullets once coq 8.5 is out *) Module M4'. Module M2'. Lemma l6: forall n:nat, n = n. Proof. intros. Lemma l7: forall n:nat, n = n. Proof. destruct n. - auto. - destruct n. + idtac;[ auto ]. + destruct n. * auto. * auto. Qed. {destruct n. - auto. - auto. } Qed. End M2'. End M4'. Module M1''. Module M2''. Lemma l7: forall n:nat, n = n. destruct n. { auto. } { destruct n. { idtac; [ auto ]. } auto. } Qed. End M2''. End M1''. Record rec:Set := { fld1:nat; fld2:nat; fld3:bool }. Class cla {X:Set}:Set := { cfld1:nat; cld2:nat; cld3:bool }. Module X. Lemma l : forall r:rec, exists r':rec, r'.(fld1) = r.(fld2)/\ r'.(fld2) = r.(fld1). Proof. intros r. { exists {| fld1:=r.(fld2); fld2:=r.(fld1); fld3:=false |}. split. {auto. } {auto. } } Qed. Lemma l2 : forall r:rec, exists r':rec, r.(fld1) = r'.(fld2) /\ r.(fld2) = r'.(fld1). Proof. intros r. {{ idtac; exists {| fld1:=r.(fld2); fld2:=r.(fld1); fld3:=false |}. (* ltac *) match goal with _:rec |- ?a /\ ?b => split | _ => fail end. match goal with | ?g := _:rec |- ?a /\ ?b => split | _ => fail end. Fail lazymatch goal with _:rec |- ?a /\ ?b => split | _ => fail end. Fail multimatch goal with _:rec |- ?a /\ ?b => split | _ => fail end. { simpl. auto. } { simpl. auto. }}} Qed. End X. Require Import Morphisms. Generalizable All Variables. Local Open Scope signature_scope. Require Import RelationClasses. Module TC. Instance: (@RewriteRelation nat) impl. (* No goal created *) Definition XX := 0. Instance StrictOrder_Asymmetric `(StrictOrder A R) : Asymmetric R. (* One goal created. Then the user MUST put "Proof." to help indentation *) Proof. firstorder. Qed. Program Fixpoint f (x:nat) {struct x} : nat := match x with | 0 => 0 | S y => S (f y) end. Program Instance all_iff_morphism {A : Type} : Proper (pointwise_relation A iff ==> iff) (@all A). Next Obligation. Proof. unfold pointwise_relation, all in *. intro. intros y H. intuition ; specialize (H x0) ; intuition. Qed. End TC. Require Import Sets.Ensembles. Require Import Bool.Bvector. Section SET. Definition set (T : Type) := Ensemble T. Require Import Program. Definition eq_n : forall A n (v:Vector.t A n) n', n=n' -> Vector.t A n'. Proof. intros A n v n' H. rewrite <- H. assumption. Defined. Fixpoint setVecProd (T : Type) (n : nat) (v1:Vector.t (set T) n) {struct v1}: (Vector.t T n) -> Prop := match v1 with Vector.nil _ => fun v2 => match v2 with Vector.nil _ => True | _ => False end | (Vector.cons _ x n' v1') => fun v2 => (* indentation of dependen "match" clause. *) match v2 as X in Vector.t _ n'' return (Vector.t T (pred n'') -> Prop) -> Prop with | Vector.nil _ => fun _ => False | (Vector.cons _ y n'' v2') => fun v2'' => (x y) /\ (v2'' v2') end (setVecProd T n' v1') end. End SET. Module curlybracesatend. Lemma foo: forall n: nat, exists m:nat, m = n + 1. Proof. intros n. destruct n. { exists 1. reflexivity. } exists (S (S n)). simpl. rewrite Nat.add_1_r. reflexivity. Qed. Lemma foo2: forall n: nat, exists m:nat, (* This is strange compared to the same line in the previous lemma *) m = n + 1. Proof. intros n. destruct n. { exists 1. reflexivity. } exists (S (S n)). simpl. rewrite Nat.add_1_r. reflexivity. Qed. Lemma foo3: forall n: nat, exists m:nat, (* This is strange compared to the same line in the previous lemma *) m = n + 1. Proof. intros n. cut (n = n). { destruct n. { exists 1. reflexivity. } { exists (S (S n)). simpl. rewrite Nat.add_1_r. reflexivity. } } idtac. reflexivity. Qed. End curlybracesatend. PG-4.5/coq/ex/indent_equations.v000066400000000000000000000035721426357011200166360ustar00rootroot00000000000000(* Needs Equations plugin to work. *) From Coq Require Import Arith Omega Program. From Equations Require Import Equations. Require Import Bvector. Module Equations. Equations neg (b : bool) : bool := neg true := false ; neg false := true. Lemma neg_inv : forall b, neg (neg b) = b. Proof. intros b. funelim (neg b); now simp neg. Defined. Inductive list {A} : Type := nil : list | cons : A -> list -> list. Arguments list : clear implicits. Notation "x :: l" := (cons x l). Equations tail {A} (l : list A) : list A := | nil := nil ; | (cons a v) := v. Equations tail' {A} (l : list A) : list A := | nil := nil ; | (cons a v) := v. (* The cases inside { } are recognized as record fields, which from an indentation perspective is OK *) Equations filter {A} (l : list A) (p : A -> bool) : list A := filter nil p := nil; filter (cons a l) p with p a => { | true := a :: filter l p ; | false := filter l p }. Equations filter' {A} (l : list A) (p : A -> bool) : list A := filter' (cons a l) p with p a => { | true := a :: filter' l p ; | false := filter' l p }; filter' nil p := nil. Equations filter'' {A} (l : list A) (p : A -> bool) : list A := filter'' (cons a l) p with p a => { | true := a :: filter'' l p ; | false := filter'' l p }; filter'' nil p := nil. Equations unzip {A B} (l : list (A * B)) : list A * list B := unzip nil := (nil, nil) ; unzip (cons p l) with unzip l => { unzip (cons (pair a b) l) (pair la lb) := (a :: la, b :: lb) }. Equations equal (n m : nat) : { n = m } + { n <> m } := equal O O := left eq_refl ; equal (S n) (S m) with equal n m := { equal (S n) (S ?(n)) (left eq_refl) := left eq_refl ; equal (S n) (S m) (right p) := right _ } ; equal x y := right _. End Equations. PG-4.5/coq/ex/indent_monadic.v000066400000000000000000000022371426357011200162350ustar00rootroot00000000000000(* Needs ext-lib library to compile. *) Require Import Coq.ZArith.ZArith_base Coq.Strings.Ascii Coq.Strings.String. Require Import ExtLib.Data.Monads.StateMonad ExtLib.Structures.Monads. Import StringSyntax. Open Scope string_scope. Section StateGame. Check Ascii.Space. Import MonadNotation. Local Open Scope Z_scope. Local Open Scope char_scope. Local Open Scope monad_scope. Definition GameValue : Type := Z. Definition GameState : Type := (prod bool Z). Variable m : Type -> Type. Context {Monad_m: Monad m}. Context {State_m: MonadState GameState m}. Print Grammar constr. Fixpoint playGame (s: string) m' {struct s}: m GameValue := match s with | EmptyString => v <- (if true then m' else get) ;; let '(on, score) := v in ret score | String x xs => v <- get ;; let '(on, score) := v in match x, on with | "a"%char, true => put (on, score + 1) | "b"%char, true => put (on, score - 1) | "c"%char, _ => put (negb on, score) | _, _ => put (on, score) end ;; playGame xs m' end. Definition startState: GameState := (false, 0). End StateGame. PG-4.5/coq/ex/mult1.v000066400000000000000000000000711426357011200143160ustar00rootroot00000000000000 Require Import Arith. Definition foo:nat := 1%nat. PG-4.5/coq/ex/mult2.v000066400000000000000000000001471426357011200143230ustar00rootroot00000000000000Require Import Arith. Require mult1. Definition bar:bool := if le_lt_dec foo 0 then true else false. PG-4.5/coq/ex/mult3.v000066400000000000000000000001111426357011200143130ustar00rootroot00000000000000 Require Import mult2. Definition foobar := if bar then foo else 2. PG-4.5/coq/ex/test-cases/000077500000000000000000000000001426357011200151425ustar00rootroot00000000000000PG-4.5/coq/ex/test-cases/README000066400000000000000000000014011426357011200160160ustar00rootroot00000000000000This directory contains test cases for coq ProofGeneral, especially for its multi-file support. Each test case is in one subdirectory. Each such subdirectory has a README file, describing the test case. Overview of the test cases: add-load-path-unsupported Add LoadPath is not supported change-ancestor assert something just added to an completely locked ancestor multiple-files-multiple-dir working with multiple files in multiple directories multiple-files-single-dir working with multiple files in a single directory require-string test Require "x.vo" (triggers known bugs) retract-completely-asserted test how proof-no-fully-processed-buffer retracts fully asserted buffers stale-load-path test switching between files with different load path. PG-4.5/coq/ex/test-cases/add-load-path-unsupported/000077500000000000000000000000001426357011200221275ustar00rootroot00000000000000PG-4.5/coq/ex/test-cases/add-load-path-unsupported/README000066400000000000000000000006061426357011200230110ustar00rootroot00000000000000b/b.v depends on a/a.v and the code is correct because of Add LoadPath in b. Scripting b/b.v works if coq-recompile-before-require is set to nil and if a/a.v is compiled manually. This problem is not considered a bug, but a feature that does not make much sense to implement, because apparently nobody is using Add LoadPath. Note that not even coqdep is able to handle b/b.v correctly! PG-4.5/coq/ex/test-cases/add-load-path-unsupported/a/000077500000000000000000000000001426357011200223475ustar00rootroot00000000000000PG-4.5/coq/ex/test-cases/add-load-path-unsupported/a/a.v000066400000000000000000000000701426357011200227530ustar00rootroot00000000000000(* This file depends on nothing. *) Definition a := 0. PG-4.5/coq/ex/test-cases/add-load-path-unsupported/b/000077500000000000000000000000001426357011200223505ustar00rootroot00000000000000PG-4.5/coq/ex/test-cases/add-load-path-unsupported/b/b.v000066400000000000000000000001211426357011200227520ustar00rootroot00000000000000(* This file depends on ../a/a.v *) Add LoadPath "../a". Require a. Print a.a.PG-4.5/coq/ex/test-cases/change-ancestor/000077500000000000000000000000001426357011200202035ustar00rootroot00000000000000PG-4.5/coq/ex/test-cases/change-ancestor/.cvsignore000066400000000000000000000000141426357011200221760ustar00rootroot00000000000000*.glob *.vo PG-4.5/coq/ex/test-cases/change-ancestor/README000066400000000000000000000017471426357011200210740ustar00rootroot00000000000000One can add text at the end of an completely locked ancestor. When this text is asserted the following should happen - retract the current scripting buffer, thereby unlocking all ancestors - restart Coq - start asserting at the beginning of the ancestor To reproduce the test do the following: - visit b.v and assert at least the initial Require command in it (this will lock the ancestor a.v) - visit the ancestor a.v and add the following text at the end Definition b := a. - assert that with proof-assert-next-command-interactive or proof-goto-point This test case triggers a bug in the cvs version from 2011-05-12 12:10:00 UTC. The bug has been fixed, see issue http://proofgeneral.inf.ed.ac.uk/trac/ticket/400 . The bug is that after unlocking the ancestor a.v, only the newly added text is sent to Coq. Therefore Coq responds with an error (reference a was not found in the current environment). When one asserts a.v from the beginning, the definition of b is of course accepted. PG-4.5/coq/ex/test-cases/change-ancestor/a.v000066400000000000000000000000251426357011200206070ustar00rootroot00000000000000 Definition a := 0. PG-4.5/coq/ex/test-cases/change-ancestor/b.v000066400000000000000000000000501426357011200206060ustar00rootroot00000000000000 Require Import a. Definition b := a. PG-4.5/coq/ex/test-cases/multiple-files-multiple-dir/000077500000000000000000000000001426357011200225025ustar00rootroot00000000000000PG-4.5/coq/ex/test-cases/multiple-files-multiple-dir/README000066400000000000000000000006241426357011200233640ustar00rootroot00000000000000Test multiple file support when files are distributed over different directories. Dependency graph a/a.v \ \ b/b1.v --- b/b2.v \ \ c/c.v That is, c depends on b2, which depends on b1, which depends on a. Script c.v and watch the compilation messages in *Messages*. Touch any file and retract and assert the Require in c. PG-4.5/coq/ex/test-cases/multiple-files-multiple-dir/a/000077500000000000000000000000001426357011200227225ustar00rootroot00000000000000PG-4.5/coq/ex/test-cases/multiple-files-multiple-dir/a/a.v000066400000000000000000000000661426357011200233330ustar00rootroot00000000000000(* this file depends on nothing *) Definition a := 0.PG-4.5/coq/ex/test-cases/multiple-files-multiple-dir/b/000077500000000000000000000000001426357011200227235ustar00rootroot00000000000000PG-4.5/coq/ex/test-cases/multiple-files-multiple-dir/b/b1.v000066400000000000000000000002211426357011200234070ustar00rootroot00000000000000(* this file depends on ../a/a.v *) Definition a := 1. Require a. (*** Local Variables: ***) (*** coq-load-path: ("../a") ***) (*** End: ***) PG-4.5/coq/ex/test-cases/multiple-files-multiple-dir/b/b2.v000066400000000000000000000002611426357011200234140ustar00rootroot00000000000000(* this file depends on b1 and therefore indirectly on ../a/a.v *) Definition a := 2. Require b1. (*** Local Variables: ***) (*** coq-load-path: ("../a") ***) (*** End: ***) PG-4.5/coq/ex/test-cases/multiple-files-multiple-dir/c/000077500000000000000000000000001426357011200227245ustar00rootroot00000000000000PG-4.5/coq/ex/test-cases/multiple-files-multiple-dir/c/c.v000066400000000000000000000003171426357011200233360ustar00rootroot00000000000000(* this file depends on ../b/b2 and therefore indirectly * on ../b/b1 and ../a/a.v *) Definition a := 2. Require b2. (*** Local Variables: ***) (*** coq-load-path: ("../a" "../b") ***) (*** End: ***) PG-4.5/coq/ex/test-cases/multiple-files-single-dir/000077500000000000000000000000001426357011200221305ustar00rootroot00000000000000PG-4.5/coq/ex/test-cases/multiple-files-single-dir/.cvsignore000066400000000000000000000000141426357011200241230ustar00rootroot00000000000000*.glob *.vo PG-4.5/coq/ex/test-cases/multiple-files-single-dir/README000066400000000000000000000020321426357011200230050ustar00rootroot00000000000000Test multiple file support for the simple case in which all files are in one directory. Dependency graph: a.v b.v c.v \ / \ / \ / \ / d.v e.v \ / \ / f.v That is, d.v depends on a.v and b.v, and so on. Some tests: - first visit f.v and display the *Message* buffer in some other frame - script f.v and watch the recompilation messages in the *Message* buffer - Change now an arbitrary file (either from within emacs or simply do touch), retract the Require in f.v, and watch the compilation messages when you assert it again. The following two problems have been fixed with the commit around 2011-01-17 07:45:00 UTC. The implementation in Proof General cvs at 2011-01-14 20:03:51 UTC has an embarrassing bug: Touching b.v causes recompilation of b.v and d.v but not of e.v! Another problem is the following: After a consistent compilation, change b.v and recompile it outside of Proof General. Then script f.v -- Proof General will not recompile d and e! PG-4.5/coq/ex/test-cases/multiple-files-single-dir/a.v000066400000000000000000000000661426357011200225410ustar00rootroot00000000000000(* this file depends on nothing *) Definition a := 0.PG-4.5/coq/ex/test-cases/multiple-files-single-dir/b.v000066400000000000000000000000661426357011200225420ustar00rootroot00000000000000(* this file depends on nothing *) Definition a := 1.PG-4.5/coq/ex/test-cases/multiple-files-single-dir/c.v000066400000000000000000000000661426357011200225430ustar00rootroot00000000000000(* this file depends on nothing *) Definition a := 2.PG-4.5/coq/ex/test-cases/multiple-files-single-dir/d.v000066400000000000000000000001171426357011200225410ustar00rootroot00000000000000(* this file depends on a.v and b.v *) Require Import a b. Definition a := 3.PG-4.5/coq/ex/test-cases/multiple-files-single-dir/e.v000066400000000000000000000001171426357011200225420ustar00rootroot00000000000000(* this file depends on b.v and c.v *) Require Import b c. Definition a := 4.PG-4.5/coq/ex/test-cases/multiple-files-single-dir/f.v000066400000000000000000000002061426357011200225420ustar00rootroot00000000000000(* this file depends on d.v and e.v and therefore * indirectly also on a.v, b.v and c.v *) Require Import d e. Definition a := 5.PG-4.5/coq/ex/test-cases/require-string/000077500000000000000000000000001426357011200201225ustar00rootroot00000000000000PG-4.5/coq/ex/test-cases/require-string/README000066400000000000000000000001341426357011200210000ustar00rootroot00000000000000The "Require string" variant is currently not supported. Here b.v contains Require "a.vo". PG-4.5/coq/ex/test-cases/require-string/a.v000066400000000000000000000000701426357011200205260ustar00rootroot00000000000000(* This file has no dependencies. *) Definition a := 0.PG-4.5/coq/ex/test-cases/require-string/b.v000066400000000000000000000003471426357011200205360ustar00rootroot00000000000000(* This file depends on a.v. *) (* The following works in Proof General 4.0, if a.v has been compiled and * if the path is the correct absolute path. *) Require "/home/tews/src/pg/coq/ex/test-cases/require-string/a". Print a.a.PG-4.5/coq/ex/test-cases/retract-completely-asserted/000077500000000000000000000000001426357011200225715ustar00rootroot00000000000000PG-4.5/coq/ex/test-cases/retract-completely-asserted/.cvsignore000066400000000000000000000000141426357011200245640ustar00rootroot00000000000000*.vo *.glob PG-4.5/coq/ex/test-cases/retract-completely-asserted/README000066400000000000000000000027311426357011200234540ustar00rootroot00000000000000In coq different modules may contain definition with the same name, because for coq they have different "absolute names" because they are in different modules. To provoke an error inside ProofGeneral on correct coq input, do the following: - Start a fresh emacs and delete (or comment out) the lines (add-hook 'proof-deactivate-scripting-hook 'coq-switch-buffer-kill-proof-shell t) in coq/coq.el. Safe that file. - Visit a.v and script the initial comment. - Set proof-no-fully-processed-buffer to nil. - assert buffer a.v completely - switch to b.v - scripting "Definition a" in b.v will give the error "a already exists" Now retract a.v, set proof-no-fully-processed-buffer to t and try again. To see that the example is indeed valid, script c.v. (For c.v you either have to switch coq-recompile-before-require to t or you have to compile modules a and b yourself with "coqc a" and "coqc b".) The following problem has been fixed by the commit of David Aspinall around 2011-01-25 20:54:54 UTC. It can no longer be reproduced. There is a bug present on 2011-01-21 09:49:36 UTC, to reproduce: - visit a.v, do C-c C-n twice to fully assert the buffer - kill buffer a.v, notice that there is no "coq killed" message apprears, and that the *coq* buffer is still live and that there is no undo command in it - visit b.v, do C-c C-n twice to get the error "a already exists" See "no deactivation-hooks when killing fully asserted active buffer" on the pg-devel list. PG-4.5/coq/ex/test-cases/retract-completely-asserted/a.v000066400000000000000000000001061426357011200231750ustar00rootroot00000000000000 (* The following defines the absolute name a.a *) Definition a := 0.PG-4.5/coq/ex/test-cases/retract-completely-asserted/b.v000066400000000000000000000001061426357011200231760ustar00rootroot00000000000000 (* The following defines the absolute name b.a *) Definition a := 1.PG-4.5/coq/ex/test-cases/retract-completely-asserted/c.v000066400000000000000000000002511426357011200232000ustar00rootroot00000000000000 Require Import a. Require Import b. (* b.a hides a.a, therefore the partial name "a" refers to b.a *) Print a. (* a.a is available under its longer name *) Print a.a.PG-4.5/coq/ex/test-cases/stale-load-path/000077500000000000000000000000001426357011200201215ustar00rootroot00000000000000PG-4.5/coq/ex/test-cases/stale-load-path/README000066400000000000000000000014451426357011200210050ustar00rootroot00000000000000Here we have three projects a, b and c. The projects b and c are totally independent from each other. Strangely, project a contains a module Le, which clashes with Coq.Arith.Le from the standard library. Project b depends on a, more precisely, b/b.v requires a/Le.v. File c/c.v require Le, but this refers to Coq.Arith.Le!! The resulting LoadPath confusion bug, which is described in the following, has been fixed with the commit around 2011-01-18 21:45:00 UTC. Currently coqtop is not able to reset the LoadPath, therefore, when first scripting b/b.v and then switching to c/c.v, coq wrongly loads a/Le.vo! Vice versa, when first scripting c/c.v and then switching to b/b.v, coq loads Coq.Arith.Le instead of a/Le.vo! Because coq-load-path is file-local, the dependency analysis works correctly. PG-4.5/coq/ex/test-cases/stale-load-path/a/000077500000000000000000000000001426357011200203415ustar00rootroot00000000000000PG-4.5/coq/ex/test-cases/stale-load-path/a/.cvsignore000066400000000000000000000000141426357011200223340ustar00rootroot00000000000000*.glob *.vo PG-4.5/coq/ex/test-cases/stale-load-path/a/Le.v000066400000000000000000000001051426357011200210640ustar00rootroot00000000000000(* This file intentionally hides Coq.Arith.Le *) Definition a := 0. PG-4.5/coq/ex/test-cases/stale-load-path/b/000077500000000000000000000000001426357011200203425ustar00rootroot00000000000000PG-4.5/coq/ex/test-cases/stale-load-path/b/b.v000066400000000000000000000003501426357011200207500ustar00rootroot00000000000000(* This file depends on ../a/Le.v *) Require Le. (* The next print should work. *) Print Le.a. (* The next print should not work. *) Print Le.le_refl. (*** Local Variables: ***) (*** coq-load-path: ("../a") ***) (*** End: ***) PG-4.5/coq/ex/test-cases/stale-load-path/c/000077500000000000000000000000001426357011200203435ustar00rootroot00000000000000PG-4.5/coq/ex/test-cases/stale-load-path/c/c.v000066400000000000000000000002701426357011200207530ustar00rootroot00000000000000(* This file depends on Coq.Arith.Le from the standard library. *) Require Le. (* The next print should work. *) Print Le.le_refl. (* The next print should not work. *) Print Le.a. PG-4.5/coq/example-tokens.v000066400000000000000000000040441426357011200156000ustar00rootroot00000000000000(* Example uses of Unicode Tokens symbols in Coq. See README. Trac this at http://proofgeneral.inf.ed.ac.uk/trac/ticket/313 Pierre Courtieu, David Aspinall. Turn on with Proof-General → Quick Options → Display → Unicode Tokens $Id$ *) Module ExampleTokens. Fixpoint toto (x:nat) {struct x} : nat := (* n a t should appear as |N *) match x with | O => O (* double arrow here *) | S y => toto y (* double arrow here *) end. Lemma titi : forall x:nat,x=x. (* symbolique for-all and n at *) Admitted. (* X-Symbol: this previously appeared as foo'a'1_B_3 where a and B are greek. Unicode Tokens: this doesn't happen because the regexp used to match is matching on sequences limited by word. Syntax table matters here: try (modify-syntax-entry ?\' ".") (modify-syntax-entry ?\_ ".") *) Variable foo'alpha'1__beta__3 : Set. Fixpoint pow (n m:nat) {struct n} : nat := match n with | O => 0 | S p => m * pow p m end. Variable a b : nat. Notation "a,{b}" := (a - b) (at level 1, no associativity). Notation "a^^b" := (pow a b) (at level 1, no associativity). Notation "a^{b}" := (pow a b) (at level 1, no associativity, only parsing). Variable delta:nat. (* greek delta with a sub 1 and the same with super 1 *) Definition delta__1 := 0. (*Definition delta__2 := delta^^1. *) (* Definition delta__3:= delta__2^{delta}. *) Parameter x:nat. (* x with a+b subscripted and then superscripted *) (*Definition x_a_b' := x^{a+b}. *) (*Definition x_a_b := x,{a+b}. *) (*Definition x_a_b'' := x,{a+b}^{a*b}.*) (* no greek letter should appear on this next line! *) Variable philosophi : Set. (* same here *) Variable aalpha alphaa : Set. (* _a where a is greek *) Variable _alpha : Set. (* a_ where a is greek *) Variable alpha_ : Set. Lemma gamma__neqn : forall n__i:nat, n__i=n__i. Abort All. (* Tests of things that shouldn't be should be unicode characters: alpha lhd rhd lambda forall exists exists shouldn't be altered: exist foral *) End ExampleTokens.PG-4.5/coq/example.v000066400000000000000000000003731426357011200143000ustar00rootroot00000000000000(* Example proof script for Coq Proof General. $Id$ *) Module Example. Lemma and_commutative : forall (A B:Prop),(A /\ B) -> (B /\ A). Proof. intros A B H. destruct H. split. trivial. trivial. Qed. End Example. PG-4.5/coq/faq000066400000000000000000000201251426357011200131450ustar00rootroot00000000000000-*- outline -*- This is a small FAQ for users of coq proof general. * Configuration of coqtop ** How do I configure the options for coqtop? *** Answer 1: Recommended way of setting coqtop options: use coq project file _CoqProject The recommended way is to have a _CoqProject file in the root directory of your develpment, as recommended by the coq documentation (section "Creating a Makefile for Coq modules"). This file should contain, among other things, lines like these: -I foo -R bar baz -arg -fuo which will be read by proofgeneral to set up the coqtop command line. In this example it will be: coqtop -I foo -R bar baz -fuo The -emacs option will be added automatically too. File variables (see below) can be used to overwrite this configuration. *** Answer 2: Alternative way (also allows to overwrite file project file settings) In the case you need to configure a specific file differently than others, or if you have only one file, you may use the "File Variables" mechanism of emacs to set the value of the variable coq-load-path and coq-prog-args using this syntax: (* *** Local Variables: *** *** coq-load-path: ("foo" ("bar" "baz")) *** *** coq-prog-args: ("-fuo") *** *** End: *** *) This must be at the end of the file. See emacs documentation on File Variables for more details. See also ProofGeneral documentation section "Using file varaiables". ** How to configure the coqtop binary? Add the following line to the local variables explained above to set the binary to use for coqtop (if not in the path): *** coq-prog-name: ("xxx/bin/coqtop") *** ** OK I want to use a coq project file but with another name, can I? Yes you can: (setq coq-project-filename "myprojectfile") or: (setq (make-local-variable 'coq-project-filename) "myprojectfile") If this is for a whole project, the best is probably to have a .dir-locals.el file as explained in the section of proofgeneral manual (section "Using file variables"). This file should contain something like: ((coq-mode . ((coq-project-filename . "myprojectfile")))) or equivalently: ((coq-mode . ((eval . (progn (make-local-variable 'coq-project-filename) (setq coq-project-filename "myprojectfile")))))) * Ergonomy ** What are the shortcuts I should know? The one for navigation: *** C-c C-n for one step *** C-c C-enter to go to cursor. You may want to bind these to more convenient non-standard shortcuts. ProofGeneral follows emacs policy: it avoids polluting the "short" shortcuts with its bindings and let the user configure them at will instead. Other useful shortcuts for queries to coq: *** C-c C-a C-i Inserts ``intros '' and also introduces the name of the hypothesis proposed by coq on the current goal. *** C-c C-a C-s Show the goal (enter for the current goal, i for the ith goal). IMPORTANT: Add the prefix C-u to see the answer with all pretty printing options temporarily disable (Set Printing All). *** C-c C-a C-c Prompts for ``Check '' query arguments, the default input name is built from the identifier under the cursor. IMPORTANT: Add the prefix C-u to see the answer with all pretty printing options temporarily disable (Set Printing All). *** C-c C-a C-p The same for a ``Print '' query. *** C-c C-a C-b The same for a ``About '' query. *** C-c C-a C-a The same for a ``Search '' query (no C-u prefix). *** C-c C-a C-o The same for a Search ``SearchIsos'' (no C-u prefix). ** I hate menus, why do you have menus? Indeed, very few emacs users use menus, which is understandable. However you should have a look at Coq menu and PG menu from time to time to see the features they propose, then remember the shortcut and hide the menu again. ** How can I tell coq to recompile the files that need to be recompiled? Use option Coq > Settings > Compile before Require Each time ProofGeneral scripts a "Require" command, it will decide if the file needs to be recompiled by computing the dependencies between files and comparing modification dates of files. A special Thanks to Hendrik Tews for this cool feature. Notice that this feature will only work if the the coq load path is the same for all files. To configure the load path, see the question "How do I configure the options for coqtop?" in this faq. ** Why does library compilation lock up my Emacs? Can it use more than one core for compilation? Enable Coq > Settings > Compile Parallel in Background to use the more recent compilation engine, which compiles in parallel (in case your dependencies permit this) and in the background. ** How can I display the proof tree of some proof? Install Prooftree from http://askra.de/software/prooftree/, restart Proof General and select menu entry Proof-General > Start/Stop Prooftree or type C-c C-d . * Three windows mode It has been cleaned up. Here is how it works now. ** How do I enable three windows mode? Menu Coq > toggle 3 windows mode or Proof-General > Quick Options > Display > Use Three Panes. ** How do I enable three windows mode by default? Choose Proof-General > Quick Options > Save Options Alternatively, put this in you configuration file: (setq proof-three-window-enable t) ** What are the possible layouts in 3 windows mode The are three layouts: - vertical: the 3 buffers are displayed in one column. - hybrid: 2 columns mode, left column displays scripting buffer and right column displays the 2 others. - horizontal: 3 columns mode, one for each buffer (script, goals, response). ** What is the default layout? The default layout is a "smart" one. One of the three layouts is chosen depending on the current width of your emacs frame. The threshold between is given by variable split-width-threshold: width < split-width-threshold ===> vertical mode split-width-threshold <= width < 1.5 * split-width-threshold ===> hybrid mode width <= split-width-threshold ===> horizontal mode ** How do I change the theshold between display modes in default mode? You can change the value of `split-width-threshold' at your will by putting this in your emacs configuration file: (setq split-width-threshold 140) Note that this is a global emacs setting, that may affect the way frames are split by other modes. See description of function `split-window-sensibly' for details. ** I changed the size of my frame and layout did not changed, what happened? Hit C-c C-l to refresh layout, it will adapt to the new frame width. ** I don't like the default layout of three windows mode, how can I force it? If you want to force one layout instead of letting emacs chose it for you (see above question "what is the default layout?"), you can set the variable `proof-three-window-mode-policy'. The three possible values are: 'smart (default), 'vertical, 'horizontal, 'hybrid. For example, putting this in your configuration file will force hybrid mode: (setq proof-three-window-mode-policy 'hybrid) * other interface questions ** How do I disable the splash screen? Choose Proof-General > Customize Options and disable "Proof Splash Enable" (at the bottom) and choose "Save for Future Sessions" by clicking on the state button. Alternatively, put this in your configuration file: (setq proof-splash-enable nil) Type M-x proof-splash-display-screen to enjoy the splash screen once. ** How do I enable the "compile before require" mode by default? Choose Coq > Settings > Save Settings. Alternatively, put this in your configuration file: (setq coq-compile-before-require t) ** Until now hovering the mouse cursor on the locked region was popping up some windows showing coq output, how do I bring this back? This was removed because it was considered by many as more annoying than useful, you can bring it back by: Menu Coq / toggle tooltips. ** Electric terminator always goes to next line, how do I change this? You can disable this by putting this in your configuration file: (setq coq-one-command-per-line nil) ** How do I change the color of the queue/locked region? (custom-set-faces '(proof-queue-face ((((type x) (class color) (background light)) (:background "darksalmon"))) t) '(proof-locked-face ((((type x) (class color) (background light)) (:background "SlateGray3"))) t)) PG-4.5/doc/000077500000000000000000000000001426357011200124365ustar00rootroot00000000000000PG-4.5/doc/.gitignore000066400000000000000000000014611426357011200144300ustar00rootroot00000000000000ProofGeneral.log ProofGeneral.dvi ProofGeneral.ps ProofGeneral.pdf ProofGeneral.ps.gz ProofGeneral.kys ProofGeneral.aux ProofGeneral.cp ProofGeneral.fn ProofGeneral.vr ProofGeneral.tp ProofGeneral.ky ProofGeneral.pg ProofGeneral.toc ProofGeneral.info ProofGeneral.cps ProofGeneral.fns ProofGeneral.vrs ProofGeneral.info-* ProofGeneral.txt ProofGeneral PG-adapting PG-adapting.log PG-adapting.dvi PG-adapting.ps PG-adapting.pdf PG-adapting.ps.gz PG-adapting.kys PG-adapting.aux PG-adapting.cp PG-adapting.fn PG-adapting.vr PG-adapting.tp PG-adapting.ky PG-adapting.pg PG-adapting.toc PG-adapting.info PG-adapting.cps PG-adapting.fns PG-adapting.vrs PG-adapting.info-* PG-adapting.txt PG-adapting_*.html PG-adapting_toc.html PG-adapting_foot.html ProofGeneralPortrait.eps ProofGeneralPortrait.pdf PG-4.5/doc/Makefile000066400000000000000000000014531426357011200141010ustar00rootroot00000000000000## ## Makefile for Proof General doc directory. ## ## Author: David Aspinall ## ## Maintainer: Proof General maintainer ## ## $Id$ ## ########################################################################### ## ## Use: ## make info,pdf,html - build respective docs from texi source. ## make doc - make default kinds of doc (, info). ## ########################################################################### default: $(MAKE) doc %: $(MAKE) -f Makefile.doc DOCNAME=PG-adapting MAKE="$(MAKE) -f Makefile.doc" $@ $(MAKE) -f Makefile.doc DOCNAME=ProofGeneral MAKE="$(MAKE) -f Makefile.doc" $@ ## ## man page for proofgeneral script ## # man: proofgeneral.1 # proofgeneral.1: ../bin/proofgeneral help2man --output=$@ ../bin/proofgeneral PG-4.5/doc/Makefile.doc000066400000000000000000000051631426357011200146470ustar00rootroot00000000000000## ## Makefile for Proof General doc directory. ## ## Author: David Aspinall ## ## Maintainer: Proof General maintainer ## ## $Id$ ## ########################################################################### ## ## Use: ## make info,pdf,html - build respective docs from texi source. ## make doc - make default kinds of doc (pdf, info). ## ########################################################################### MAKE = make -f Makefile.doc MAKEINFO = makeinfo TEXI2HTML = makeinfo --html --ifinfo --number-sections --split=chapter --no-headers --css-include=proofgen.css # `texinfo-tex' package contains texi2pdf TEXI2PDF = texi2pdf # `dviutils' package contains these useful utilities. # "make rearrange" will only be called if you have dviselect. DVISELECT = dviselect DVICONCAT = dviconcat # Assumes actual first two pages belong to titlepage TITLERANGE = =1,=2 # Assumes that main document starts on third actual page MAINRANGE = =3,=4,3: TOC = :_1 EMACS = emacs EMACSFLAGS = -q -no-site-file TMPFILE=pgt .SUFFIXES: .texi .info .html .pdf .gz default: doc .texi.info: $(MAKEINFO) $< .texi.pdf: $(TEXI2PDF) $< .texi.html: $(TEXI2HTML) $< default: doc FORCE: %.gz : % gzip -f -9 $* ## ## doc : build pdf, info files from $(DOCNAME).texi ## doc: pdf info ## ## all : build all documentation targets ## all: html info pdf ## ## dist: build distribution targets ## dist: info html pdf pdf: $(DOCNAME).pdf # da: target is a fake: we actually make in a subdir html: $(DOCNAME).html info: $(DOCNAME).info # NB: for info, could make localdir automatically from # START-INFO-DIR-ENTRY / END-INFO-DIR-ENTRY. # Does some utility do this? ## ## clean: Remove subsidiary documentation files ## CLEANTARGS:=$(DOCNAME).cp $(DOCNAME).fn $(DOCNAME).vr $(DOCNAME).tp $(DOCNAME).ky $(DOCNAME).kys $(DOCNAME).pg $(DOCNAME).fns $(DOCNAME).vrs $(DOCNAME).cps $(DOCNAME).aux $(DOCNAME).log $(DOCNAME).cp $(DOCNAME).cp0 $(DOCNAME).toc clean: rm -f $(CLEANTARGS) ## ## distclean: Remove documentation targets ## distclean: clean rm -rf $(DOCNAME).info* $(DOCNAME).pdf $(DOCNAME) rm -f *~ ## ## texi: update magic comments in texi from docstrings in code. ## (developer use only!) ## Must be run from source .els otherwise function arguments lost ## $(DOCNAME).texi: $(MAKE) magic magic: (cd ..; make clean) $(EMACS) $(EMACSFLAGS) -batch -l ./docstring-magic.el $(DOCNAME).texi -f texi-docstring-magic -f save-buffer debugmagic: $(EMACS) $(EMACFLAGS) -eval '(setq debug-on-error t)' -l ./docstring-magic.el $(DOCNAME).texi -f texi-docstring-magic -f save-buffer PG-4.5/doc/PG-adapting.texi000066400000000000000000006012401426357011200154270ustar00rootroot00000000000000\input texinfo @c TODO: setting for configuring proof hidden regions. @c @c $Id$ @c @c NB: the first line of this file uses a non-standard TeXinfo @c hack to print in Serifa fonts. It has no effect if you don't have @c my hacked version of TeXinfo - da. @c @c @setfilename PG-adapting.info @settitle Adapting Proof General @setchapternewpage odd @paragraphindent 0 @iftex @afourpaper @end iftex @c @c Some URLs. @c FIXME: unfortunately, broken in buggy pdftexinfo. @c so removed for now. @set URLisamode http://homepages.inf.ed.ac.uk/da/isamode @set URLpghome https://proofgeneral.github.io @set URLpglatestrpm http://proofgeneral.inf.ed.ac.uk/releases/ProofGeneral-latest.noarch.rpm @set URLpglatesttar http://proofgeneral.inf.ed.ac.uk/releases/ProofGeneral-latest.tar.gz @set URLpglatestdev http://proofgeneral.inf.ed.ac.uk/releases/ProofGeneral-devel-latest.tar.gz @c @c @c @c IMPORTANT NOTE ABOUT THIS TEXINFO FILE: @c I've tried keep full node lines *out* of this file because Emacs makes a @c mess of updating them and they are a nuisance to do by hand. @c Instead, rely on makeinfo and friends to do the equivalent job. @c For this to work, we must follow each node @c immediately with a section command, i.e.: @c @c @node node-name @c @c @c And each section with lower levels must have a menu command in @c it. Menu updating with Emacs is a bit better than node updating, @c but tends to delete the first section of the file in XEmacs! @c (it's better in GNU Emacs at the time of writing). @c @c @c reminder about references: @c @xref{node} blah start of sentence: See [ref] @c blah (@pxref{node}) blah bla (see [ref]), best at end of sentence @c @ref{node} without "see". Careful for info. @set version 4.5 @set emacsversion 24.3 @set last-update July 2022 @set rcsid $Id$ @dircategory Theorem proving @direntry * Adapting PG: (PG-adapting). Adapt Proof General to new provers END-INFO-DIR-ENTRY @end direntry @c @c MACROS @c @c define one here for a command with a key-binding? @c @c I like the idea, but it's maybe against the TeXinfo @c style to fix together a command and its key-binding. @c @c merge functions and variables into concept index. @c @syncodeindex fn cp @c @syncodeindex vr cp @c merge functions into variables index @c @syncodeindex fn vr @finalout @titlepage @title Adapting Proof General @subtitle Proof General --- Organize your proofs! @sp 1 @subtitle Adapting Proof General @value{version} to new provers @subtitle @value{last-update} @subtitle @b{proofgeneral.github.io} @iftex @vskip 1cm @image{ProofGeneral-image} @end iftex @author David Aspinall with T. Kleymann @page @vskip 0pt plus 1filll This manual and the program Proof General are Copyright @copyright{} 2000-2011 by members of the Proof General team, LFCS Edinburgh. @c @c COPYING NOTICE @c @ignore Permission is granted to process this file through TeX and print the results, provided the printed document carries copying permission notice identical to this one except for the removal of this paragraph (this paragraph not being relevant to the printed manual). @end ignore @sp 2 Permission is granted to make and distribute verbatim copies of this manual provided the copyright notice and this permission notice are preserved on all copies. @sp 2 This manual documents Proof General, Version @value{version}, for use GNU Emacs @value{emacsversion} or (as far as possible) later versions. Proof General is distributed under the terms of the GNU General Public License (GPL), version 3 or later; please check the accompanying file @file{COPYING} for more details. @sp 1 Visit Proof General on the web at @code{https://proofgeneral.github.io} @c (commented; dates from CVS) Version control: @code{@value{rcsid}} @end titlepage @page @ifinfo @node Top @top Proof General This file documents configuration mechanisms for version @value{version} of @b{Proof General}, a generic Emacs interface for proof assistants. Proof General @value{version} has been tested with GNU Emacs @value{emacsversion}. It is supplied ready customized for the proof assistants Coq, EasyCrypt, and PhoX. This manual contains information for customizing to new proof assistants; see the user manual for details about how to use Proof General. @menu * Introduction:: * Beginning with a New Prover:: * Menus and Toolbar and User-level Commands:: * Proof Script Settings:: * Proof Shell Settings:: * Goals Buffer Settings:: * Splash Screen Settings:: * Global Constants:: * Handling Multiple Files:: * Configuring Editing Syntax:: * Configuring Font Lock:: * Configuring Tokens:: * Configuring Proof-Tree Visualization:: * Writing More Lisp Code:: * Internals of Proof General:: * Plans and Ideas:: * Demonstration Instantiations:: * Function Index:: * Variable Index:: * Concept Index:: @end menu @end ifinfo @node Introduction @unnumbered Introduction Welcome to Proof General! Proof General a generic Emacs-based interface for proof assistants. This manual contains information for adapting Proof General to new proof assistants, and some sketches of the internal implementation. It is not intended for most ordinary users of the system. For full details about how to use Proof General, and information on its availability and installation, please see the main Proof General manual which should accompany this one. We positively encourage the support of new systems. Proof General has grown more flexible and useful as it has been adapted to more proof assistants. Typically, adding support for a new prover improves support for others, both because the code becomes more robust, and because new ideas are brought into the generic setting. Notice that the Proof General framework has been built as a "product line architecture": generality has been introduced step-by-step in a demand-driven way, rather than at the outset as a grand design. Despite this strategy, the interface has a surprisingly clean structure. The approach means that we fully expect hiccups when adding support for new assistants, so the generic core may need extension or modification. To support this we have an open development method: if you require changes in the generic support, please contact us (or make adjustments yourself and send them to us). Proof General has a home page at @uref{https://proofgeneral.github.io}. Visit this page for the latest version of the manuals, other documentation, system downloads, etc. @menu * Future:: * Credits:: @end menu @node Future @unnumberedsec Future @cindex Proof General Kit @cindex Future The aim of the Proof General project is to provide a powerful and configurable interfaces which help user-interaction with interactive proof assistants. The strategy Proof General uses is to targets power users rather than novices; other interfaces have often neglected this class of users. But we do include general user interface niceties, such as toolbar and menus, which make use easier for all. Proof General has been Emacs based so far, but plans are afoot to liberate it from the points and parentheses of Emacs Lisp. The successor project Proof General Kit proposes that proof assistants use a @i{standard} XML-based protocol for interactive proof, dubbed @b{PGIP}. PGIP enables middleware for interactive proof tools and interface components. Rather than configuring Proof General for your proof assistant, you will need to configure your proof assistant to understand PGIP. There is a similarity however; the design of PGIP was based heavily on the Emacs Proof General framework. This means that effort on customizing Emacs Proof General to a new proof assistant is worthwhile even in the light of PGIP: it will help you to understand Proof General's model of interaction, and moreover, we hope to use the Emacs customizations to provide experimental filters which allow supported provers to communicate using PGIP. At the time of writing, these ideas are in early stages. For latest details, or to become involved, see @uref{http://proofgeneral.inf.ed.ac.uk/kit, the Proof General Kit webpage}. @node Credits @unnumberedsec Credits David Aspinall put together and wrote most of this manual. Thomas Kleymann wrote some of the text in Chapter 8. Much of the content is generated automatically from Emacs docstrings, some of which have been written by other Proof General developers. @node Beginning with a New Prover @chapter Beginning with a New Prover Proof General has about 100 configuration variables which are set on a per-prover basis to configure the various features. It may sound like a lot but don't worry! Many of the variables occur in pairs (typically regular expressions matching the start and end of some text), and you can begin by setting just a fraction of the variables to get the basic features of script management working. The bare minimum for a working prototype is about 25 simple settings. For more advanced features you may need (or want) to write some Emacs Lisp. If you're adding new functionality please consider making it generic for different proof assistants, if appropriate. When writing your modes, please follow the Emacs Lisp conventions, @inforef{Tips, ,Elisp}. The configuration variables are declared in the file @file{generic/proof-config.el}. The details in the central part of this manual are based on the contents of that file, beginning in @ref{Menus and Toolbar and User-level Commands}, and continuing until @ref{Global Constants}. Other chapters cover the details of configuring for multiple files and for supporting the other Emacs packages mentioned in the user manual (@i{Support for other Packages}). If you write additional Elisp code interfacing to Proof General, you can find out about some useful functions by reading @ref{Writing More Lisp Code}. The last chapter of this manual describes some of the internals of Proof General, in case you are interested, maybe because you need to extend the generic core to do something new. In the rest of this chapter we describe the general mechanisms for instantiating Proof General. We assume some knowledge of the content of the main Proof General manual. @menu * Overview of adding a new prover:: * Demonstration instance and easy configuration:: * Major modes used by Proof General:: @end menu @node Overview of adding a new prover @section Overview of adding a new prover Each proof assistant supported has its own subdirectory under @code{proof-home-directory}, used to store a root elisp file and any other files needed to adapt the proof assistant for Proof General. @c Here we show how a minimal configuration of Proof General works for @c Isabelle, without any special changes to Isabelle. Here is how to go about adding support for a new prover. @enumerate @item Make a directory called @file{myassistant/} under the Proof General home directory @code{proof-home-directory}, to put the specific customization and associated files in. @item Add a file @file{myassistant.el} to the new directory. @item Edit @file{proof-site.el} to add a new entry to the @code{proof-assistants-table} variable. The new entry should look like this: @lisp (myassistant "My Proof Assistant" "\\.myasst$") @end lisp The first item is used to form the name of the internal variables for the new mode as well as the directory and file where it loads from. The second is a string, naming the proof assistant. The third item is a regular expression to match names of proof script files for this assistant. See the documentation of @code{proof-assistant-table} for more details. @item Define the new Proof General modes in @file{myassistant.el}, by setting configuration variables to customize the behaviour of the generic modes. @end enumerate @c You could begin by setting a minimum number of the variables, then @c adjust the settings via the customize menus, under Proof-General -> @c Internals. @c TEXI DOCSTRING MAGIC: proof-assistant-table @defvar proof-assistant-table Proof General's table of supported proof assistants.@* This is copied from @samp{@code{proof-assistant-table-default}} at load time, removing any entries that do not have a corresponding directory under @samp{@code{proof-home-directory}}. Each entry is a list of the form @lisp (@var{symbol} @var{name} @var{file-extension} [AUTOMODE-REGEXP] [IGNORED-EXTENSIONS-LIST]) @end lisp The @var{name} is a string, naming the proof assistant. The @var{symbol} is used to form the name of the mode for the assistant, @samp{SYMBOL-mode}, run when files with @var{automode-regexp} (or with extension @var{file-extension}) are visited. If present, @var{ignored-extensions-list} is a list of file-name extensions to be ignored when doing file-name completion (@var{ignored-extensions-list} is added to @samp{@code{completion-ignored-extensions}}). @var{symbol} is also used to form the name of the directory and elisp file for the mode, which will be @lisp @var{proof-home-directory}/@var{symbol}/@var{symbol}.el @end lisp where @var{proof-home-directory} is the value of the variable @samp{@code{proof-home-directory}}. @end defvar The final step of the description above is where the work lies. There are two basic methods. You can write some Emacs lisp functions and define the modes using the macro @code{define-derived-mode}. Or you can use the new easy configuration mechanism of Proof General 3.0 described in the next section, which calls @code{define-derived-mode} for you. You still need to know which configuration variables should be set, and how to set them. The documentation below (and inside Emacs) should help with that, but the best way to begin might be to use an existing Proof General instance as an example. @node Demonstration instance and easy configuration @section Demonstration instance and easy configuration Proof General is supplied with a demonstration instance for Isabelle which configures the basic features. This is a whittled down version of Isabelle Proof General, which you can use as a template to get support for a new assistant going. Check the directory @file{demoisa} for the two files @file{demoisa.el} and @file{demoisa-easy.el}. The file @file{demoisa.el} follows the scheme described in @ref{Major modes used by Proof General}. It uses the Emacs Lisp macro @code{define-derived-mode} to define the four modes for a Proof General instance, by inheriting from the generic code. Settings which configure Proof General are made by functions called from within each mode, as appropriate. The file @file{demoisa-easy.el} uses a new simplified mechanism to achieve (virtually) the same result. It uses the macro @code{proof-easy-config} defined in @file{proof-easy-configl.el} to make all of the settings for the Proof General instance in one go, defining the derived modes automatically using a regular naming scheme. No lisp code is used in this file except the call to this macro. The minor difference in the end result is that all the variables are set at once, rather than inside each mode. But since the configuration variables are all global variables anyway, this makes no real difference. The macro @code{proof-easy-config} is called like this: @lisp (proof-easy-config @var{myprover} "@var{MyProver}" @var{config_1} @var{val_1} ... @var{config_n} @var{val_n}) @end lisp The main body of the macro call is like the body of a @code{setq}. It contains pairs of variables and value settings. The first argument to the macro is a symbol defining the mode root, the second argument is a string defining the mode name. These should be the same as the first part of the entry in @code{proof-assistant-table} for your prover. @xref{Overview of adding a new prover}. After the call to @code{proof-easy-config}, the new modes @code{@var{myprover}-mode}, @code{@var{myprover}-shell-mode}, @code{@var{myprover}-response-mode}, and @code{@var{myprover}-goals-mode} will be defined. The configuration variables in the body will be set immediately. This mechanism is in fact recommended for new instantiations of Proof General since it follows a regular pattern, and we can more easily adapt it in the future to new versions of Proof General. Even Emacs Lisp experts should prefer the simplified mechanism. If you want to set some buffer-local variables in your Proof General modes, or invoke supporting lisp code, this can easily be done by adding functions to the appropriate mode hooks after the @code{proof-easy-config} call. For example, to add extra settings for the shell mode for @code{demoisa}, we could do this: @lisp (defun demoisa-shell-extra-config () @var{extra configuration ...} ) (add-hook 'demoisa-shell-mode-hook 'demoisa-shell-extra-config) @end lisp The function to do extra configuration @code{demoisa-shell-extra-config} is then called as the final step when @code{demoisa-shell-mode} is entered (be wary, this will be after the generic @code{proof-shell-config-done} is called, so it will be too late to set normal configuration variables which may be examined by @code{proof-shell-config-done}). @node Major modes used by Proof General @section Major modes used by Proof General There are four major modes used by Proof General, one for each type of buffer it handles. The buffer types are: script, shell, response and goals. Each of these has a generic mode, respectively: @code{proof-mode}, @code{proof-shell-mode}, @code{proof-response-mode}, and @code{proof-goals-mode}. The pattern for defining the major mode for an instance of Proof General is to use @code{define-derived-mode} to define a specific mode to inherit from each generic one, like this: @lisp (define-derived-mode myass-shell-mode proof-shell-mode "MyAss shell" nil (myass-shell-config) (proof-shell-config-done)) @end lisp Where @code{myass-shell-config} is a function which sets the configuration variables for the shell (@pxref{Proof Shell Settings}). It's important that each of your modes invokes one of the functions @code{proof-config-done}, @code{proof-shell-config-done}, @code{proof-response-config-done}, or @code{proof-goals-config-done} once it has set its configuration variables. These functions finalize the configuration of the mode. The modes must be named standardly, replacing @code{proof-} with the prover's symbol name, @code{@var{PA}-}. In other words, you must define @code{@var{PA}-mode}, @code{@var{PA}-shell-mode}, etc. See the file @file{demoisa.el} for an example of the four calls to @code{define-derived-mode}. Aside: notice that the modes are selected using stub functions inside @code{proof-site.el}, which set the variables @code{proof-mode-for-script}, @code{proof-mode-for-shell}, etc, that actually select the right mode. These variables are declared in @code{pg-vars.el}. @node Menus and Toolbar and User-level Commands @chapter Menus, toolbar, and user-level commands The variables described in this chapter configure the menus, toolbar, and user-level commands. They should be set in the script mode before @code{proof-config-done} is called. (Toolbar configuration must be made before @file{proof-toolbar.el} is loaded, which usually is triggered automatically by an attempt to display the toolbar). @menu * Settings for generic user-level commands:: * Menu configuration:: * Toolbar configuration:: @end menu @node Settings for generic user-level commands @section Settings for generic user-level commands @c TEXI DOCSTRING MAGIC: proof-assistant-home-page @defvar proof-assistant-home-page Web address for information on proof assistant.@* Used for Proof General's help menu. @end defvar @c TEXI DOCSTRING MAGIC: proof-context-command @defvar proof-context-command Command to display the context in proof assistant. @end defvar @c TEXI DOCSTRING MAGIC: proof-info-command @defvar proof-info-command Command to ask for help or information in the proof assistant.@* String or fn. If a string, the command to use. If a function, it should return the command string to insert. @end defvar @c TEXI DOCSTRING MAGIC: proof-showproof-command @defvar proof-showproof-command Command to display proof state in proof assistant. @end defvar @c TEXI DOCSTRING MAGIC: proof-goal-command @defvar proof-goal-command Command to set a goal in the proof assistant. String or fn.@* If a string, the format character @samp{%s} will be replaced by the goal string. If a function, it should return the command string to insert. @end defvar @c TEXI DOCSTRING MAGIC: proof-save-command @defvar proof-save-command Command to save a proved theorem in the proof assistant. String or fn.@* If a string, the format character @samp{%s} will be replaced by the theorem name. If a function, it should return the command string to insert. @end defvar @c TEXI DOCSTRING MAGIC: proof-find-theorems-command @defvar proof-find-theorems-command Command to search for a theorem containing a given term. String or fn.@* If a string, the format character @samp{%s} will be replaced by the term. If a function, it should return the command string to send. @end defvar @node Menu configuration @section Menu configuration As well as the generic Proof General menu, each proof assistant is provided with a specific menu which can have prover-specific commands. Proof General puts some default things on this menu, including the commands to start/stop the prover, and the user-extensible "Favourites" menu. @c TEXI DOCSTRING MAGIC: PA-menu-entries @defvar PA-menu-entries Extra entries for proof assistant specific menu.@* A list of menu items [@var{name} @var{callback} @var{enabler} ...]. See the documentation of @samp{@code{easy-menu-define}} for more details. @end defvar @c TEXI DOCSTRING MAGIC: PA-help-menu-entries @defvar PA-help-menu-entries Extra entries for help submenu for proof assistant specific help menu.@* A list of menu items [@var{name} @var{callback} @var{enabler} ...]. See the documentation of @samp{@code{easy-menu-define}} for more details. @end defvar @node Toolbar configuration @section Toolbar configuration Unlike the menus, Proof General has only one toolbar. For the "generic" aspect of Proof General to work well, we shouldn't change (the meaning of) the existing toolbar buttons too far. This would discourage people from experimenting with different proof assistants when they don't really know them, which is one of the advantages that Proof General brings. But in case it is hard to map some of the generic buttons onto functions in particular provers, and to allow extra buttons, there is a mechanism for adjustment. I used The Gimp to create the buttons for Proof General. The development distribution includes a button blank and some notes in @file{etc/notes.txt} about making new buttons. @c TEXI DOCSTRING MAGIC: proof-toolbar-entries-default @defvar proof-toolbar-entries-default Example value for proof-toolbar-entries. Also used to define scripting menu.@* This gives a bare toolbar that works for any prover, providing the appropriate configuration variables are set. To add/remove prover specific buttons, adjust the @samp{-toolbar-entries} variable, and follow the pattern in @samp{proof-toolbar.el} for defining functions, images. @end defvar @c TEXI DOCSTRING MAGIC: PA-toolbar-entries @defvar PA-toolbar-entries List of entries for Proof General toolbar and Scripting menu.@* Format of each entry is (@var{token} @var{menuname} @var{tooltip} @var{toolbar-p} [VISIBLE-P]). For each @var{token}, we expect an icon with base filename @var{token}, a function proof-toolbar-, and (optionally) a dynamic enabler proof-toolbar--enable-p. If @var{visible-p} is absent, or evaluates to non-nil, the item will appear on the toolbar or menu. If it evaluates to nil, the item is not shown. If @var{menuname} is nil, item will not appear on the scripting menu. If @var{toolbar-p} is nil, item will not appear on the toolbar. The default value is @samp{@code{proof-toolbar-entries-default}} which contains the standard Proof General buttons. @end defvar Here's an example of how to remove a button, from @file{af2.el}: @lisp (setq af2-toolbar-entries (assq-delete-all 'state af2-toolbar-entries)) @end lisp @c defgroup proof-script @node Proof Script Settings @chapter Proof Script Settings The variables described in this chapter should be set in the script mode before @code{proof-config-done} is called. These variables configure recognition of commands in the proof script, and also control some of the behaviour of script management. @menu * Recognizing commands and comments:: * Recognizing proofs:: * Recognizing other elements:: * Configuring undo behaviour:: * Nested proofs:: * Omitting proofs for speed:: * Safe (state-preserving) commands:: * Activate scripting hook:: * Automatic multiple files:: * Completely asserted buffers:: * Completions:: @end menu @node Recognizing commands and comments @section Recognizing commands and comments The first four settings configure the generic parsing strategy for commands in the proof script. Usually only one of these three needs to be set. If the generic parsing functions are not flexible for your needs, you can supply a value for @code{proof-script-parse-function}. Note that for the generic functions to work properly, it is @strong{essential} that you set the syntax table for your mode properly, so that comments and strings are recognized. See the Emacs documentation to discover how to do this (particularly for the function @code{modify-syntax-entry}, (@inforef{Syntax Tables, ,Elisp}). @xref{Proof script mode}, for more details of the parsing functions. @c TEXI DOCSTRING MAGIC: proof-terminal-string @defvar proof-terminal-string String that terminates commands sent to prover; nil if none. To configure command recognition properly, you must set at least one of these: @samp{@code{proof-script-sexp-commands}}, @samp{@code{proof-script-command-end-regexp}}, @samp{@code{proof-script-command-start-regexp}}, @samp{@code{proof-terminal-string}}, or @samp{@code{proof-script-parse-function}}. @end defvar @c TEXI DOCSTRING MAGIC: proof-electric-terminator-noterminator @defvar proof-electric-terminator-noterminator If non-nil, electric terminator does not actually insert a terminator. @end defvar @c TEXI DOCSTRING MAGIC: proof-script-sexp-commands @defvar proof-script-sexp-commands Non-nil if script has Lisp-like syntax: commands are @code{top-level} sexps.@* You should set this variable in script mode configuration. To configure command recognition properly, you must set at least one of these: @samp{@code{proof-script-sexp-commands}}, @samp{@code{proof-script-command-end-regexp}}, @samp{@code{proof-script-command-start-regexp}}, @samp{@code{proof-terminal-string}}, or @samp{@code{proof-script-parse-function}}. @end defvar @c TEXI DOCSTRING MAGIC: proof-script-command-start-regexp @defvar proof-script-command-start-regexp Regular expression which matches start of commands in proof script.@* You should set this variable in script mode configuration. To configure command recognition properly, you must set at least one of these: @samp{@code{proof-script-sexp-commands}}, @samp{@code{proof-script-command-end-regexp}}, @samp{@code{proof-script-command-start-regexp}}, @samp{@code{proof-terminal-string}}, or @samp{@code{proof-script-parse-function}}. @end defvar @c TEXI DOCSTRING MAGIC: proof-script-command-end-regexp @defvar proof-script-command-end-regexp Regular expression which matches end of commands in proof script.@* You should set this variable in script mode configuration. The end of the command is considered to be the end of the match of this regexp. The regexp may include a nested group, which can be used to recognize the start of the following command (or white space). If there is a nested group, the end of the command is considered to be the start of the nested group, i.e. (@code{match-beginning} 1), rather than (@code{match-end} 0). To configure command recognition properly, you must set at least one of these: @samp{@code{proof-script-sexp-commands}}, @samp{@code{proof-script-command-end-regexp}}, @samp{@code{proof-script-command-start-regexp}}, @samp{@code{proof-terminal-string}}, or @samp{@code{proof-script-parse-function}}. @end defvar The next four settings configure the comment syntax. Notice that to get reliable behaviour of the parsing functions, you may need to modify the syntax table for your prover's mode. Read the Elisp manual (@inforef{Syntax Tables, ,Elisp}) for details about that. @c TEXI DOCSTRING MAGIC: proof-script-comment-start @defvar proof-script-comment-start String which starts a comment in the proof assistant command language.@* The script buffer's @samp{@code{comment-start}} is set to this string plus a space. Moreover, comments are usually ignored during script management, and not sent to the proof process. You should set this variable for reliable working of Proof General, as well as @samp{@code{proof-script-comment-end}}. @end defvar @c TEXI DOCSTRING MAGIC: proof-script-comment-start-regexp @defvar proof-script-comment-start-regexp Regexp which matches a comment start in the proof command language. The default value for this is set as (@code{regexp-quote} @samp{@code{proof-script-comment-start}}) but you can set this variable to something else more precise if necessary. @end defvar @c TEXI DOCSTRING MAGIC: proof-script-comment-end @defvar proof-script-comment-end String which ends a comment in the proof assistant command language.@* Should be an empty string if comments are terminated by @samp{@code{end-of-line}} The script buffer's @samp{@code{comment-end}} is set to a space plus this string, if it is non-empty. See also @samp{@code{proof-script-comment-start}}. You should set this variable for reliable working of Proof General. @end defvar @c TEXI DOCSTRING MAGIC: proof-script-comment-end-regexp @defvar proof-script-comment-end-regexp Regexp which matches a comment end in the proof command language. The default value for this is set as (@code{regexp-quote} @samp{@code{proof-script-comment-end}}) but you can set this variable to something else more precise if necessary. @end defvar @c TEXI DOCSTRING MAGIC: proof-case-fold-search @defvar proof-case-fold-search Value for @samp{@code{case-fold-search}} when recognizing portions of proof scripts.@* Also used for completion, via @samp{@code{proof-script-complete}}. The default value is nil. If your prover has a case @strong{insensitive} input syntax, @samp{@code{proof-case-fold-search}} should be set to t instead. NB: This setting is not used for matching output from the prover. @end defvar Finally, the function @code{proof-looking-at-syntactic-context} is used internally to help determine the syntactic structure of the buffer. You can test it to check the settings above. If necessary, you can override this with a system-specific function. @c TEXI DOCSTRING MAGIC: proof-looking-at-syntactic-context @defun proof-looking-at-syntactic-context Determine if current point is at beginning or within comment/string context.@* If so, return a symbol indicating this ('comment or @code{'string}). This function invokes if that is defined, otherwise it calls @samp{@code{proof-looking-at-syntactic-context}}. @end defun @node Recognizing proofs @section Recognizing proofs Several settings each may be supplied for recognizing goal-like and save-like commands. The @code{-with-hole-} settings are used to make a record of the name of the theorem proved. The @code{-p} subsidiary predicates were added to allow more discriminating behaviour for particular proof assistants. (This is a typical example of where the core framework needs some additional generalization, to simplify matters, and allow for a smooth handling of nested proofs; the present state is only part of the way there). @c TEXI DOCSTRING MAGIC: proof-goal-command-regexp @defvar proof-goal-command-regexp Matches a goal command in the proof script.@* This is used to make the default value for @samp{@code{proof-goal-command-p}}, used as an important part of script management to find the start of an atomic undo block. @end defvar @c TEXI DOCSTRING MAGIC: proof-goal-command-p @defvar proof-goal-command-p A function to test: is this really a goal command span? This is added as a more refined addition to @samp{@code{proof-goal-command-regexp}}, to solve the problem that Coq and some other provers can have goals which look like definitions, etc. (In the future we may generalize @samp{@code{proof-goal-command-regexp}} instead). @end defvar @c TEXI DOCSTRING MAGIC: proof-goal-with-hole-regexp @defvar proof-goal-with-hole-regexp Regexp which matches a command used to issue and name a goal.@* The name of the theorem is built from the variable @samp{@code{proof-goal-with-hole-result}} using the same convention as for @samp{@code{query-replace-regexp}}. Used for setting names of goal..save regions and for default configuration of other modes (function menu, imenu). It's safe to leave this setting as nil. @end defvar @c TEXI DOCSTRING MAGIC: proof-goal-with-hole-result @defvar proof-goal-with-hole-result How to get theorem name after @samp{@code{proof-goal-with-hole-regexp}} match.@* String or Int. If an int N, use @samp{@code{match-string}} to get the value of the Nth parenthesis matched. If a string, use @samp{@code{replace-match}}. In this case, @samp{@code{proof-goal-with-hole-regexp}} should match the entire command. @end defvar @c TEXI DOCSTRING MAGIC: proof-save-command-regexp @defvar proof-save-command-regexp Matches a save command. @end defvar @c TEXI DOCSTRING MAGIC: proof-save-with-hole-regexp @defvar proof-save-with-hole-regexp Regexp which matches a command to save a named theorem.@* The name of the theorem is built from the variable @samp{@code{proof-save-with-hole-result}} using the same convention as @samp{@code{query-replace-regexp}}. Used for setting names of goal..save and proof regions. It's safe to leave this setting as nil. @end defvar @c TEXI DOCSTRING MAGIC: proof-completed-proof-behaviour @defvar proof-completed-proof-behaviour Indicates how Proof General treats commands beyond the end of a proof.@* Normally goal...save regions are "closed", i.e. made atomic for undo. But once a proof has been completed, there may be a delay before the "save" command appears --- or it may not appear at all. Unless nested proofs are supported, this can spoil the undo-behaviour in script management since once a new goal arrives the old undo history may be lost in the prover. So we allow Proof General to close off the goal..[save] region in more flexible ways. The possibilities are: @lisp nil - nothing special; close only when a save arrives @code{'closeany} - close as soon as the next command arrives, save or not @code{'closegoal} - close when the next "goal" command arrives @code{'extend} - keep extending the closed region until a save or goal. @end lisp If your proof assistant allows nested goals, it will be wrong to close off the portion of proof so far, so this variable should be set to nil. NB: @code{'extend} behaviour is not currently compatible with appearance of save commands, so don't use that if your prover has save commands. @end defvar @c TEXI DOCSTRING MAGIC: proof-really-save-command-p @defvar proof-really-save-command-p Is this really a save command? This is a more refined addition to @samp{@code{proof-save-command-regexp}}. It should be a function taking a span and command as argument, and can be used to track nested proofs. @end defvar @node Recognizing other elements @section Recognizing other elements @vindex proof-goal-with-hole-regexp @vindex proof-goal-with-hole-result To configure @i{Imenu} (which in turn configures @i{Speedbar}), you may use the following setting. If this is unset, a generic setting based on @code{proof-goal-with-hole-regexp} is configured. @c TEXI DOCSTRING MAGIC: proof-script-imenu-generic-expression @defvar proof-script-imenu-generic-expression Regular expressions to help find definitions and proofs in a script.@* Value for @samp{@code{imenu-generic-expression}}, see documentation of Imenu and that variable for details. @end defvar @c This is _not_ docstring magic, but docstring-by-hand from @c imenu.el in XEmacs 21.4.12 @defvar imenu-generic-expression The regex pattern to use for creating a buffer index. If non-nil this pattern is passed to @samp{imenu--generic-function} to create a buffer index. The value should be an alist with elements that look like this: @lisp (@var{menu-title} @var{regexp} @var{index}) @end lisp or like this: @lisp (@var{menu-title} @var{regexp} @var{index} @var{function} ARGUMENTS...) @end lisp with zero or more ARGUMENTS. The former format creates a simple element in the index alist when it matches; the latter creates a special element of the form (@var{name} @var{function} @var{position-marker} ARGUMENTS...) with @var{function} and @var{arguments} beiong copied from @samp{imenu-generic-expression}. @var{menu-title} is a string used as the title for the submenu or nil if the entries are not nested. @var{regexp} is a regexp that should match a construct in the buffer that is to be displayed in the menu; i.e., function or variable definitions, etc. It contains a substring which is the name to appear in the menu. See the info section on Regexps for more information. @var{index} points to the substring in @var{regexp} that contains the name (of the function, variable or type) that is to appear in the menu. The variable is buffer-local. The variable @samp{imenu-case-fold-search} determines whether or not the regexp matches are case sensitive. and @samp{imenu-syntax-alist} can be used to alter the syntax table for the search. For example, see the value of @samp{lisp-imenu-generic-expression} used by @samp{lisp-mode} and @samp{emacs-lisp-mode} with @samp{imenu-syntax-alist} set locally to give the characters which normally have \"punctuation\" syntax \"word\" syntax during matching." @end defvar @node Configuring undo behaviour @section Configuring undo behaviour The settings here are used to configure the way "undo" commands are calculated. @c TEXI DOCSTRING MAGIC: proof-non-undoables-regexp @defvar proof-non-undoables-regexp Regular expression matching commands which are @strong{not} undoable.@* These are commands which should not appear in proof scripts, for example, undo commands themselves (if the proof assistant cannot "redo" an "undo"). Used in default functions @samp{@code{proof-generic-state-preserving-p}} and @samp{@code{proof-generic-count-undos}}. If you don't use those, may be left as nil. @end defvar @c TEXI DOCSTRING MAGIC: proof-undo-n-times-cmd @defvar proof-undo-n-times-cmd Command to undo n steps of the currently open goal.@* String or function. If this is set to a string, @samp{%s} will be replaced by the number of undo steps to issue. If this is set to a function, it should return a list of the appropriate commands (given the number of undo steps). This setting is used for the default @samp{@code{proof-generic-count-undos}}. If you set @samp{@code{proof-count-undos-fn}} to some other function, there is no need to set this variable. @end defvar @c TEXI DOCSTRING MAGIC: proof-ignore-for-undo-count @defvar proof-ignore-for-undo-count Matcher for script commands to be ignored in undo count.@* May be left as nil, in which case it will be set to @samp{@code{proof-non-undoables-regexp}}. Used in default function @samp{@code{proof-generic-count-undos}}. @end defvar @c TEXI DOCSTRING MAGIC: proof-count-undos-fn @defvar proof-count-undos-fn Function to calculate a list of commands to undo to reach a target span.@* The function takes a span as an argument, and should return a string which is the command to undo to the target span. The target is guaranteed to be within the current (open) proof. This is an important function for script management. The default setting @samp{@code{proof-generic-count-undos}} is based on the settings @samp{@code{proof-non-undoables-regexp}} and @samp{@code{proof-non-undoables-regexp}}. @end defvar @c TEXI DOCSTRING MAGIC: proof-generic-count-undos @defun proof-generic-count-undos span Count number of undos in @var{span}, return commands needed to undo that far.@* Command is set using @samp{@code{proof-undo-n-times-cmd}}. A default value for @samp{@code{proof-count-undos-fn}}. For this function to work properly, you must configure @samp{@code{proof-undo-n-times-cmd}} and @samp{@code{proof-ignore-for-undo-count}}. @end defun @c TEXI DOCSTRING MAGIC: proof-find-and-forget-fn @defvar proof-find-and-forget-fn Function to return list of commands to forget to before its argument span.@* This setting is used to for retraction (undoing) in proof scripts. It should undo the effect of all settings between its target span up to (@code{proof-unprocessed-begin}). This may involve forgetting a number of definitions, declarations, or whatever. If return value is nil, it means there is nothing to do. This is an important function for script management. Study one of the existing instantiations for examples of how to write it, or leave it set to the default function @samp{@code{proof-generic-find-and-forget}} (which see). @end defvar @c TEXI DOCSTRING MAGIC: proof-generic-find-and-forget @defun proof-generic-find-and-forget span Calculate a forget/undo command to forget back to @var{span}.@* This is a long-range forget: we know that there is no open goal at the moment, so forgetting involves unbinding declarations, etc, rather than undoing proof steps. This generic implementation assumes it is enough to find the nearest following span with a @samp{name} property, and retract that using @samp{@code{proof-forget-id-command}} with the given name. If this behaviour is not correct, you must customize the function with something different. @end defun @c TEXI DOCSTRING MAGIC: proof-forget-id-command @defvar proof-forget-id-command Command to forget back to a given named span.@* A string; @samp{%s} will be replaced by the name of the span. This is only used in the implementation of @samp{@code{proof-generic-find-and-forget}}, you only need to set if you use that function (by not customizing @samp{@code{proof-find-and-forget-fn}}. @end defvar @c TEXI DOCSTRING MAGIC: pg-topterm-goalhyplit-fn @defvar pg-topterm-goalhyplit-fn Function to return cons if point is at a goal/hypothesis/literal.@* This is used to parse the proofstate output to mark it up for proof-by-pointing or literal command insertion. It should return a cons or nil. First element of the cons is a symbol, @code{'goal'}, @code{'hyp'} or @code{'lit'}. The second element is a string: the goal, hypothesis, or literal command itself. If you leave this variable unset, no proof-by-pointing markup will be attempted. @end defvar @c TEXI DOCSTRING MAGIC: proof-kill-goal-command @defvar proof-kill-goal-command Command to kill the currently open goal. If this is set to nil, PG will expect @samp{@code{proof-find-and-forget-fn}} to do all the work of retracting to an arbitrary point in a file. Otherwise, the generic split-phase mechanism will be used: 1. If inside an unclosed proof, use @samp{proof-count-undos}. 2. If retracting to before an unclosed proof, use @samp{@code{proof-kill-goal-command}}, followed by @samp{@code{proof-find-and-forget-fn}} if necessary. @end defvar @node Nested proofs @section Nested proofs Proof General allows configuration for provers which have particular notions of nested proofs. The right thing may happen automatically, or you may need to adjust some of the following settings. First, you should alter the next setting if the prover retains history for nested proofs. @c TEXI DOCSTRING MAGIC: proof-nested-goals-history-p @defvar proof-nested-goals-history-p Whether the prover supports recovery of history for nested proofs.@* If it does (non-nil), Proof General will retain history inside nested proofs. If it does not, Proof General will amalgamate nested proofs into single steps within the outer proof. @end defvar Second, it may happen (i.e. it does for Coq) that the prover has a history mechanism which necessitates keeping track of the number of nested "undoable" commands, even if the history of the proof itself is lost. @c TEXI DOCSTRING MAGIC: proof-nested-undo-regexp @defvar proof-nested-undo-regexp Regexp for commands that must be counted in nested goal-save regions. Used for provers which allow nested atomic goal-saves, but with some nested history that must be undone specially. At the moment, the behaviour is that a goal-save span has a @code{'nestedundos} property which is set to the number of commands within it which match this regexp. The idea is that the prover-specific code can create a customized undo command to retract the goal-save region, based on the @code{'nestedundos} setting. Coq uses this to forget declarations, since declarations in Coq reside in a separate context with its own (flat) history. @end defvar @node Omitting proofs for speed @section Omitting proofs for speed In normal operation, the commands in an asserted region are sent successively to the proof assistant. When the proof assistant reports an error, processing stops. This ensures the consistency of the development. Proof General supports omitting portions of the asserted region to speed processing up at the cost of consistency. Portions that can be potentially omitted are called @emph{opaque proofs} in Proof General, because usually only opaque proofs (in the sense of Coq) can be omitted without risking to break the following code. This feature is also described in the Proof General manual, @inforef{Script processing commands, ,ProofGeneral} and @inforef{Omitting proofs for speed, ,ProofGeneral}. The omit proofs feature works in a simple, straightforward way: After parsing the asserted region, Proof General uses regular expressions to search for commands that start (@code{proof-script-proof-start-regexp}) and end (@code{proof-script-proof-end-regexp}) an opaque proof. If one is found, the opaque proof is replaced with a cheating command (@code{proof-script-proof-admit-command}). From this description it is immediate, that the omit proof feature does only work if proofs are not nested. If a nested proof is found, a warning is displayed and omitting proofs stops at that location for the currently asserted region. To enable the omit proofs feature, the following settings must be configured. @c TEXI DOCSTRING MAGIC: proof-omit-proofs-configured @defvar proof-omit-proofs-configured t if the omit proofs feature has been configured by the proof assitant.@* See also @samp{@code{proof-omit-proofs-option}} or the Proof General manual for a description of the feature. This option can only be set, if all of @samp{@code{proof-script-proof-start-regexp}}, @samp{@code{proof-script-proof-end-regexp}}, @samp{@code{proof-script-definition-end-regexp}} and @samp{@code{proof-script-proof-admit-command}} have been configured. The omit proofs feature skips over opaque proofs in the source code, admitting the theorems, to speed up processing. If @samp{@code{proof-omit-proofs-option}} is set by the user, all proof commands in the source following a match of @samp{@code{proof-script-proof-start-regexp}} up to and including the next match of @samp{@code{proof-script-proof-end-regexp}}, are omitted (not send to the proof assistant) and replaced by @samp{@code{proof-script-proof-admit-command}}. If a match for @samp{@code{proof-script-definition-end-regexp}} is found while searching forward for the proof end, the current proof (up to and including the match of @samp{@code{proof-script-definition-end-regexp}}) is considered to be not opaque and not omitted, thus all these proof commands _are_ sent to the proof assistant. The feature does not work for nested proofs. If a match for @samp{@code{proof-script-proof-start-regexp}} is found before the next match for @samp{@code{proof-script-proof-end-regexp}} or @samp{@code{proof-script-definition-end-regexp}}, the search for opaque proofs immediately stops and all commands following the previous match of @samp{@code{proof-script-proof-start-regexp}} are sent verbatim to the proof assistant. All the regular expressions for this feature are matched against the commands inside proof action items, that is as strings, without surrounding space. @end defvar @c TEXI DOCSTRING MAGIC: proof-script-proof-start-regexp @defvar proof-script-proof-start-regexp Regular expression for the start of a proof for the omit proofs feature.@* See @samp{@code{proof-omit-proofs-configured}}. @end defvar @c TEXI DOCSTRING MAGIC: proof-script-proof-end-regexp @defvar proof-script-proof-end-regexp Regular expression for the end of an opaque proof for the omit proofs feature.@* See @samp{@code{proof-omit-proofs-configured}}. @end defvar @c TEXI DOCSTRING MAGIC: proof-script-definition-end-regexp @defvar proof-script-definition-end-regexp Regexp for the end of a non-opaque proof for the omit proofs feature.@* See @samp{@code{proof-omit-proofs-configured}}. @end defvar @c TEXI DOCSTRING MAGIC: proof-script-proof-admit-command @defvar proof-script-proof-admit-command Proof command to be inserted instead of omitted proofs. @end defvar @node Safe (state-preserving) commands @section Safe (state-preserving) commands A proof command is "safe" if it can be issued away from the proof script. For this to work it should be state-preserving in the proof assistant (with respect to an on-going proof). @c TEXI DOCSTRING MAGIC: proof-state-preserving-p @defvar proof-state-preserving-p A predicate, non-nil if its argument (a command) preserves the proof state.@* This is a safety-test used by @samp{@code{proof-minibuffer-cmd}} to filter out scripting commands which should be entered directly into the script itself. The default setting for this function, @samp{@code{proof-generic-state-preserving-p}} tests by negating the match on @samp{@code{proof-non-undoables-regexp}}. @end defvar @c TEXI DOCSTRING MAGIC: proof-generic-state-preserving-p @defun proof-generic-state-preserving-p cmd Is @var{cmd} state preserving? Match on @samp{@code{proof-non-undoables-regexp}}. @end defun @node Activate scripting hook @section Activate scripting hook @c TEXI DOCSTRING MAGIC: proof-activate-scripting-hook @defvar proof-activate-scripting-hook Hook run when a buffer is switched into scripting mode.@* The current buffer will be the newly active scripting buffer. This hook may be useful for synchronizing with the proof assistant, for example, to switch to a new theory (in case that isn't already done by commands in the proof script). When functions in this hook are called, the variable @samp{activated-interactively} will be non-nil if @samp{@code{proof-activate-scripting}} was called interactively (rather than as a side-effect of some other action). If a hook function sends commands to the proof process, it should wait for them to complete (so the queue is cleared for scripting commands), unless activated-interactively is set. @end defvar @node Automatic multiple files @section Automatic multiple files @xref{Handling Multiple Files}, for more details about this setting. @c TEXI DOCSTRING MAGIC: proof-auto-multiple-files @defvar proof-auto-multiple-files Whether to use automatic multiple file management.@* If non-nil, Proof General will automatically retract a script file whenever another one is retracted which it depends on. It assumes a simple linear dependency between files in the order which they were processed. If your proof assistant has no management of file dependencies, or one which depends on a simple linear context, you may be able to use this setting to good effect. If the proof assistant has more complex file dependencies then you should configure it to communicate with Proof General about the dependencies rather than using this setting. @end defvar @node Completely asserted buffers @section Completely asserted buffers When switching scripting from buffer A to buffer B Proof General normally offers the choice of either completely retracting or completely asserting buffer A. The option to completely assert buffer A is offered, because the material in B may depend on A. Even if B does not depend on A, it does no harm if one keeps the development of A loaded in the proof assistant. This observation is true for many proof assistants. One exception is Coq. Assume file B depends on file A. When Coq processes B it does not read the sources of A. Instead it loads a compiled object representation of A. Therefore, when switching from A to B, it does make no sense to keep the material of A loaded in the proof assistant. For Coq, the material of A may even provoke errors on correct input. Therefore, for coq, the right behaviour is to completely retract buffer A before switching to B. @c TEXI DOCSTRING MAGIC: proof-no-fully-processed-buffer @defvar proof-no-fully-processed-buffer Set to t if buffers should always retract before scripting elsewhere.@* Leave at nil if fully processed buffers make sense for the current proof assistant. If nil the user can choose to fully assert a buffer when starting scripting in a different buffer. If t there is only the choice to fully retract the active buffer before starting scripting in a different buffer. This last behavior is needed for Coq. @end defvar @node Completions @section Completions Proof General allows provers to create a @i{completion table} to help writing keywords and identifiers in proof scripts. This is documented in the main @i{Proof General} user manual but summarized here for (a different kind of) completion. Completions are filled in according to what has been recently typed, from a database of symbols. The database is automatically saved at the end of a session. Completion is usually a hand-wavy thing, so we don't make any attempt to maintain a precise completion table or anything. The completion table maintained by @file{complete.el} is initialized from @code{PA-completion-table} when @file{proof-script.el} is loaded. This is done with the function @code{proof-add-completions} which you may want to call at other times. @c TEXI DOCSTRING MAGIC: PA-completion-table @defvar PA-completion-table List of identifiers to use for completion for this proof assistant.@* Completion is activated with M-x complete. If this table is empty or needs adjusting, please make changes using @samp{@code{customize-variable}} and post suggestions at https://github.com/ProofGeneral/PG/issues @end defvar @c TEXI DOCSTRING MAGIC: proof-add-completions @deffn Command proof-add-completions Add completions from -completion-table to completion database.@* Uses @samp{@code{add-completion}} with a negative number of uses and ancient last use time, to discourage saving these into the users database. @end deffn @node Proof Shell Settings @chapter Proof Shell Settings The variables in this chapter concern the proof shell mode, and are the largest group. They are split into several subgroups. The first subgroup are commands invoked at various points. The second subgroup of variables are concerned with matching the output from the proof assistant. The final subgroup contains various hooks which you can set to add lisp customization to Proof General in various points (some of them are also used internally for behaviour you may wish to adjust). Variables for configuring the proof shell are put into the customize group @code{proof-shell}. These should be set in the shell mode configuration, before @code{proof-shell-config-done} is called. To understand the way the proof assistant runs inside Emacs, you may want to refer to the @code{comint.el} (Command interpreter) package distributed with Emacs. This package controls several shell-like modes available in Emacs, including the @code{proof-shell-mode} and all specific shell modes derived from it. @menu * Proof shell commands:: * Script input to the shell:: * Settings for matching various output from proof process:: * Settings for matching urgent messages from proof process:: * Hooks and other settings:: @end menu @node Proof shell commands @section Commands Settings in this section configure Proof General with commands to send to the prover to activate certain actions. @c TEXI DOCSTRING MAGIC: proof-prog-name @defvar proof-prog-name System command to run the proof assistant in the proof shell.@* May contain arguments separated by spaces, but see also the prover specific settings @samp{-prog-args} and @samp{-prog-env}. Remark: if @samp{-prog-args} is non-nil, then @samp{@code{proof-prog-name}} is considered strictly: it must contain @strong{only} the program name with no option, spaces are interpreted literally as part of the program name. @end defvar @c TEXI DOCSTRING MAGIC: PA-prog-args @defvar PA-prog-args Arguments to be passed to @samp{@code{proof-prog-name}} to run the proof assistant.@* If non-nil, will be treated as a list of arguments for @samp{@code{proof-prog-name}}. Otherwise @samp{@code{proof-prog-name}} will be split on spaces to form arguments. Remark: Arguments are interpreted strictly: each one must contain only one word, with no space (unless it is the same word). For example if the arguments are -x foo -y bar, then the list should be '("-x" "foo" "-y" "bar"), notice that '("-x foo" "-y bar") is @strong{wrong}. @end defvar @c TEXI DOCSTRING MAGIC: PA-prog-env @defvar PA-prog-env Modifications to @samp{@code{process-environment}} made before running @samp{@code{proof-prog-name}}.@* Each element should be a string of the form ENVVARNAME=@var{value}. They will be added to the environment before launching the prover (but not pervasively). For example for coq on Windows you might need something like: (setq @code{coq-prog-env} '("HOME=C:\Program Files\Coq\")) @end defvar @c TEXI DOCSTRING MAGIC: proof-shell-auto-terminate-commands @defvar proof-shell-auto-terminate-commands Non-nil if Proof General should try to add terminator to every command.@* If non-nil, whenever a command is sent to the prover using @samp{@code{proof-shell-invisible-command}}, Proof General will check to see if it ends with @samp{@code{proof-terminal-string}}, and add it if not. If @samp{@code{proof-terminal-string}} is nil, this has no effect. @end defvar @c TEXI DOCSTRING MAGIC: proof-shell-pre-sync-init-cmd @defvar proof-shell-pre-sync-init-cmd The command for configuring the proof process to gain synchronization.@* This command is sent before Proof General's synchronization mechanism is engaged, to allow customization inside the process to help gain syncrhonization (e.g. engaging special markup). It is better to configure the proof assistant for this purpose via command line options if possible, in which case this variable does not need to be set. See also @samp{@code{proof-shell-init-cmd}}. @end defvar @c TEXI DOCSTRING MAGIC: proof-shell-init-cmd @defvar proof-shell-init-cmd The command(s) for initially configuring the proof process.@* This command is sent to the process as soon as synchronization is gained (when an annotated prompt is first recognized). It can be used to configure the proof assistant in some way, or print a welcome message (since output before the first prompt is discarded). See also @samp{@code{proof-shell-pre-sync-init-cmd}}. @end defvar @c TEXI DOCSTRING MAGIC: proof-shell-restart-cmd @defvar proof-shell-restart-cmd A command for re-initialising the proof process. @end defvar @c TEXI DOCSTRING MAGIC: proof-shell-quit-cmd @defvar proof-shell-quit-cmd A command to quit the proof process. If nil, send EOF instead. @end defvar @c TEXI DOCSTRING MAGIC: proof-shell-cd-cmd @defvar proof-shell-cd-cmd Command to the proof assistant to change the working directory.@* The format character @samp{%s} is replaced with the directory, and the escape sequences in @samp{@code{proof-shell-filename-escapes}} are applied to the filename. This setting is used to define the function @samp{@code{proof-cd}} which changes to the value of (@code{default-directory}) for script buffers. For files, the value of (@code{default-directory}) is simply the directory the file resides in. NB: By default, @samp{@code{proof-cd}} is called from @samp{@code{proof-activate-scripting-hook}}, so that the prover switches to the directory of a proof script every time scripting begins. @end defvar @c TEXI DOCSTRING MAGIC: proof-shell-start-silent-cmd @defvar proof-shell-start-silent-cmd Command to turn prover goals output off when sending many script commands.@* If non-nil, Proof General will automatically issue this command to help speed up processing of long proof scripts. See also @samp{@code{proof-shell-stop-silent-cmd}}. NB: terminator not added to command. @end defvar @c TEXI DOCSTRING MAGIC: proof-shell-stop-silent-cmd @defvar proof-shell-stop-silent-cmd Command to turn prover output on.@* If non-nil, Proof General will automatically issue this command to help speed up processing of long proof scripts. See also @samp{@code{proof-shell-start-silent-cmd}}. NB: Terminator not added to command. @end defvar @c TEXI DOCSTRING MAGIC: proof-shell-silent-threshold @defvar proof-shell-silent-threshold Number of waiting commands in the proof queue needed to trigger silent mode.@* Default is 2, but you can raise this in case switching silent mode on or off is particularly expensive (or make it ridiculously large to disable silent mode altogether). @end defvar @xref{Handling Multiple Files}, for more details about the final two settings in this group, @c TEXI DOCSTRING MAGIC: proof-shell-inform-file-processed-cmd @defvar proof-shell-inform-file-processed-cmd Command to the proof assistant to tell it that a file has been processed.@* The format character @samp{%s} is replaced by a complete filename for a script file which has been fully processed interactively with Proof General. See @samp{@code{proof-format-filename}} for other possibilities to process the filename. This setting used to interface with the proof assistant's internal management of multiple files, so the proof assistant is kept aware of which files have been processed. Specifically, when scripting is deactivated in a completed buffer, it is added to Proof General's list of processed files, and the prover is told about it by issuing this command. If this is set to nil, no command is issued. See also: @samp{@code{proof-shell-inform-file-retracted-cmd}}, @samp{@code{proof-shell-process-file}}, @samp{@code{proof-shell-compute-new-files-list}}. @end defvar @c TEXI DOCSTRING MAGIC: proof-shell-inform-file-retracted-cmd @defvar proof-shell-inform-file-retracted-cmd Command to the proof assistant to tell it that a file has been retracted.@* The format character @samp{%s} is replaced by a complete filename for a script file which Proof General wants the prover to consider as not completely processed. See @samp{@code{proof-format-filename}} for other possibilities to process the filename. This is used to interface with the proof assistant's internal management of multiple files, so the proof assistant is kept aware of which files have been processed. Specifically, when scripting is activated, the file is removed from Proof General's list of processed files, and the prover is told about it by issuing this command. The action may cause the prover in turn to suggest to Proof General that files depending on this one are also unlocked. If this is set to nil, no command is issued. It is also possible to set this value to a function which will be invoked on the name of the retracted file, and should remove the ancestor files from @samp{@code{proof-included-files-list}} by some other calculation. See also: @samp{@code{proof-shell-inform-file-processed-cmd}}, @samp{@code{proof-shell-process-file}}, @samp{@code{proof-shell-compute-new-files-list}}. @end defvar @node Script input to the shell @section Script input to the shell Generally, commands from the proof script are sent verbatim to the proof process running in the proof shell. For historical reasons, carriage returns are stripped by default. You can set @code{proof-shell-strip-crs-from-input} to adjust that. For more sophisticated pre-processing of the sent string, you may like to set @code{proof-shell-insert-hook}. @c TEXI DOCSTRING MAGIC: proof-shell-strip-crs-from-input @defvar proof-shell-strip-crs-from-input If non-nil, replace carriage returns in every input with spaces.@* This is enabled by default: it is appropriate for many systems based on human input, because several CR's can result in several prompts, which may mess up the display (or even worse, the synchronization). If the prover can be set to output only one prompt for every chunk of input, then newlines can be retained in the input. @end defvar @c TEXI DOCSTRING MAGIC: proof-shell-insert-hook @defvar proof-shell-insert-hook Hook run by @samp{@code{proof-shell-insert}} before inserting a command.@* Can be used to configure the proof assistant to the interface in various ways -- for example, to observe or alter the commands sent to the prover, or to sneak in extra commands to configure the prover. This hook is called inside a @samp{@code{save-excursion}} with the @samp{@code{proof-shell-buffer}} current, just before inserting and sending the text in the variable @samp{string}. The hook can massage @samp{string} or insert additional text directly into the @samp{@code{proof-shell-buffer}}. Before sending @samp{string}, it will be stripped of carriage returns. Additionally, the hook can examine the variable @samp{action}. It will be a symbol, set to the callback command which is executed in the proof shell filter once @samp{string} has been processed. The @samp{action} variable suggests what class of command is about to be inserted, the first two are normally the ones of interest: @lisp @code{'proof-done-advancing} A "forward" scripting command @code{'proof-done-retracting} A "backward" scripting command @code{'proof-done-invisible} A non-scripting command @code{'proof-shell-set-silent} Indicates prover output has been surpressed @code{'proof-shell-clear-silent} Indicates prover output has been restored @code{'init-cmd} Early initialization command sent to prover @end lisp Caveats: You should be very careful about setting this hook. Proof General relies on a careful synchronization with the process between inputs and outputs. It expects to see a prompt for each input it sends from the queue. If you add extra input here and it causes more prompts than expected, things will break! Extending the variable @samp{string} may be safer than inserting text directly, since it is stripped of carriage returns before being sent. Example uses: Lego used this hook for setting the pretty printer width if the window width has changed; Plastic used it to remove literate-style markup from @samp{string}. See also @samp{@code{proof-script-preprocess}} which can munge text when it is added to the queue of commands. @end defvar @node Settings for matching various output from proof process @section Settings for matching various output from proof process These settings control the way Proof General reacts to process output. The single most important setting is @code{proof-shell-annotated-prompt-regexp}, which @b{must} be set as part of the prover configuraton. This is used to configure the communication with the prover process. @c TEXI DOCSTRING MAGIC: pg-subterm-first-special-char @defvar pg-subterm-first-special-char First special character.@* Codes above this character can have special meaning to Proof General, and are stripped from the prover's output strings. Leave unset if no special characters are being used. @end defvar @c TEXI DOCSTRING MAGIC: proof-shell-annotated-prompt-regexp @defvar proof-shell-annotated-prompt-regexp Regexp matching a (possibly annotated) prompt pattern. @var{this} IS THE @var{most} @var{important} @var{setting} TO @var{configure}!! Output is grabbed between pairs of lines matching this regexp, and the appearance of this regexp is used by Proof General to recognize when the prover has finished processing a command. To help speed up matching you may be able to annotate the proof assistant prompt with a special character not appearing in ordinary output, which should appear in this regexp. @end defvar @c TEXI DOCSTRING MAGIC: proof-shell-error-regexp @defvar proof-shell-error-regexp Regexp matching an error report from the proof assistant. We assume that an error message corresponds to a failure in the last proof command executed. So don't match mere warning messages with this regexp. Moreover, an error message should @strong{not} be matched as an eager annotation (see @samp{@code{proof-shell-eager-annotation-start}}) otherwise it will be lost. Error messages are considered to begin from @samp{@code{proof-shell-error-regexp}} and continue until the next prompt. The variable @samp{@code{proof-shell-truncate-before-error}} controls whether text before the error message is displayed. The engine matches interrupts before errors, see @samp{@code{proof-shell-interrupt-regexp}}. It is safe to leave this variable unset (as nil). @end defvar @c TEXI DOCSTRING MAGIC: proof-shell-interrupt-regexp @defvar proof-shell-interrupt-regexp Regexp matching output indicating the assistant was interrupted.@* We assume that an interrupt message corresponds to a failure in the last proof command executed. So don't match mere warning messages with this regexp. Moreover, an interrupt message should not be matched as an eager annotation (see @samp{@code{proof-shell-eager-annotation-start}}) otherwise it will be lost. The engine matches interrupts before errors, see @samp{@code{proof-shell-error-regexp}}. It is safe to leave this variable unset (as nil). @end defvar @c TEXI DOCSTRING MAGIC: proof-shell-truncate-before-error @defvar proof-shell-truncate-before-error Non-nil means truncate output that appears before error messages.@* If nil, the whole output that the prover generated before the last error message will be shown. NB: the default setting for this is t to be compatible with behaviour in Proof General before version 3.4. The more obvious setting for new instances is probably nil. Interrupt messages are treated in the same way. See @samp{@code{proof-shell-error-regexp}} and @samp{@code{proof-shell-interrupt-regexp}}. @end defvar @c TEXI DOCSTRING MAGIC: proof-shell-proof-completed-regexp @defvar proof-shell-proof-completed-regexp Regexp matching output indicating a finished proof. When output which matches this regexp is seen, we clear the goals buffer in case this is not also marked up as a @samp{goals} type of message. We also enable the QED function (save a proof) and we may automatically close off the proof region if another goal appears before a save command, depending on whether the prover supports nested proofs or not. @end defvar @c TEXI DOCSTRING MAGIC: proof-shell-start-goals-regexp @defvar proof-shell-start-goals-regexp Regexp matching the start of the proof state output.@* This is an important setting. Output between @samp{@code{proof-shell-start-goals-regexp}} and @samp{@code{proof-shell-end-goals-regexp}} will be pasted into the goals buffer and possibly analysed further for proof-by-pointing markup. If it is left as nil, the goals buffer will not be used. The goals display starts at the beginning of the match on this regexp, unless it has a match group, in which case it starts at (@code{match-end} 1). @end defvar @c TEXI DOCSTRING MAGIC: proof-shell-end-goals-regexp @defvar proof-shell-end-goals-regexp Regexp matching the end of the proof state output, or nil.@* This allows a shorter form of the proof state output to be displayed, in case several messages are combined in a command output. The portion treated as the goals output will be that between the match on @samp{@code{proof-shell-start-goals-regexp}} (which see) and the start of the match on @samp{@code{proof-shell-end-goals-regexp}}. If nil, use the whole of the output from the match on @samp{@code{proof-shell-start-goals-regexp}} up to the next prompt. @end defvar @c TEXI DOCSTRING MAGIC: proof-shell-assumption-regexp @defvar proof-shell-assumption-regexp A regular expression matching the name of assumptions. At the moment, this setting is not used in the generic Proof General. Future use may provide a generic implementation for @samp{@code{pg-topterm-goalhyplit-fn}}, used to help parse the goals buffer to annotate it for proof by pointing. @end defvar @node Settings for matching urgent messages from proof process @section Settings for matching urgent messages from proof process Among the various dialogue messages that the proof assistant outputs during proof, Proof General can consider certain messages to be "urgent". When processing many lines of a proof, Proof General will normally supress the output, waiting until the final message appears before displaying anything to the user. Urgent messages escape this: typically they include messages that the prover wants the user to notice, for example, perhaps, file loading messages, timing statistics or dedicated tracing messages which can be sent to the @code{*trace*} buffer. So that Proof General notices, these urgent messages should be marked-up with "eager" annotations. @c TEXI DOCSTRING MAGIC: proof-shell-eager-annotation-start @defvar proof-shell-eager-annotation-start Eager annotation field start. A regular expression or nil.@* An "eager annotation indicates" to Proof General that some following output should be displayed (or processed) immediately and not accumulated for parsing later. Note that this affects processing of output which is ordinarily accumulated: output which appears before the eager annotation start will be discarded. The start/end annotations can be used to hilight the output, but are stripped from display of the message in the minibuffer. It is useful to recognize (starts of) warnings or file-reading messages with this regexp. You must also recognize any special messages from the prover to PG with this regexp (e.g. @samp{@code{proof-shell-clear-goals-regexp}}, @samp{@code{proof-shell-retract-files-regexp}}, etc.) See also @samp{@code{proof-shell-eager-annotation-start-length}}, @samp{@code{proof-shell-eager-annotation-end}}. Set to nil to disable this feature. @end defvar @c TEXI DOCSTRING MAGIC: proof-shell-eager-annotation-start-length @defvar proof-shell-eager-annotation-start-length Maximum length of an eager annotation start.@* Must be set to the maximum length of the text that may match @samp{@code{proof-shell-eager-annotation-start}} (at least 1). If this value is too low, eager annotations may be lost! This value is used internally by Proof General to optimize the process filter to avoid unnecessary searching. @end defvar @c TEXI DOCSTRING MAGIC: proof-shell-eager-annotation-end @defvar proof-shell-eager-annotation-end Eager annotation field end. A regular expression or nil.@* An eager annotation indicates to Emacs that some following output should be displayed or processed immediately. See also @samp{@code{proof-shell-eager-annotation-start}}. It is nice to recognize (ends of) warnings or file-reading messages with this regexp. You must also recognize (ends of) any special messages from the prover to PG with this regexp (e.g. @samp{@code{proof-shell-clear-goals-regexp}}, @samp{@code{proof-shell-retract-files-regexp}}, etc.) The default value is "\n" to match up to the end of the line. @end defvar The default action for urgent messages is to display them in the response buffer, highlighted. But we also allow for some control messages, issued from the proof assistant to Proof General and not intended for the user to see. These are recognized in the same way as urgent messages (marked with eager annotations), so they will be acted on as soon as they are issued by the prover. @c TEXI DOCSTRING MAGIC: proof-shell-clear-response-regexp @defvar proof-shell-clear-response-regexp Regexp matching output telling Proof General to clear the response buffer. More precisely, this should match a string which is bounded by matches on @samp{@code{proof-shell-eager-annotation-start}} and @samp{@code{proof-shell-eager-annotation-end}}. This feature is useful to give the prover more control over what output is shown to the user. Set to nil to disable. @end defvar @c TEXI DOCSTRING MAGIC: proof-shell-clear-goals-regexp @defvar proof-shell-clear-goals-regexp Regexp matching output telling Proof General to clear the goals buffer. More precisely, this should match a string which is bounded by matches on @samp{@code{proof-shell-eager-annotation-start}} and @samp{@code{proof-shell-eager-annotation-end}}. This feature is useful to give the prover more control over what output is shown to the user. Set to nil to disable. @end defvar @c TEXI DOCSTRING MAGIC: proof-shell-interactive-prompt-regexp @defvar proof-shell-interactive-prompt-regexp Matches output from the prover which indicates an interactive prompt.@* If we match this, we suppose that the prover has switched to an interactive diagnostic mode which requires direct interaction with the shell rather than via script management. In this case, the shell buffer will be displayed and the user left to their own devices. Note: this should match a string which is bounded by matches on @samp{@code{proof-shell-eager-annotation-start}} and @samp{@code{proof-shell-eager-annotation-end}}. @end defvar @c TEXI DOCSTRING MAGIC: proof-shell-trace-output-regexp @defvar proof-shell-trace-output-regexp Matches tracing output which should be displayed in trace buffer.@* Each line which matches this regexp but would otherwise be treated as an ordinary response, is sent to the trace buffer instead of the response buffer. This is intended for unusual debugging output from the prover, rather than ordinary output from final proofs. This should match a string which is bounded by matches on @samp{@code{proof-shell-eager-annotation-start}} and @samp{@code{proof-shell-eager-annotation-end}}. Set to nil to disable. @end defvar @c TEXI DOCSTRING MAGIC: proof-shell-theorem-dependency-list-regexp @defvar proof-shell-theorem-dependency-list-regexp Matches output telling Proof General about dependencies.@* This is to allow navigation and display of dependency information. The output from the prover should be a message with the form @lisp @var{dependencies} OF X Y Z ARE A B C @end lisp with X Y Z, A B C separated by whitespace or somehow else (see @samp{@code{proof-shell-theorem-dependency-list-split}}. This variable should be set to a regexp to match the overall message (which should be an urgent message), with two sub-matches for X Y Z and A B C. This is an experimental feature, currently work-in-progress. @end defvar Two important control messages are recognized by @code{proof-shell-process-file} and @code{proof-shell-retract-files-regexp}, used for synchronizing Proof General with a file loading mechanism built into the proof assistant. @xref{Handling Multiple Files}, for more details about how to use the final four settings described here. @vindex proof-included-files-list @c TEXI DOCSTRING MAGIC: proof-shell-process-file @defvar proof-shell-process-file A pair (@var{regexp} . @var{function}) to match a processed file name. If @var{regexp} matches output, then the function @var{function} is invoked. It must return the name of a script file (with complete path) that the system has successfully processed. In practice, @var{function} is likely to inspect the match data. If it returns the empty string, the file name of the scripting buffer is used instead. If it returns nil, no action is taken. More precisely, @var{regexp} should match a string which is bounded by matches on @samp{@code{proof-shell-eager-annotation-start}} and @samp{@code{proof-shell-eager-annotation-end}}. Care has to be taken in case the prover only reports on compiled versions of files it is processing. In this case, @var{function} needs to reconstruct the corresponding script file name. The new (true) file name is added to the front of @samp{@code{proof-included-files-list}}. @end defvar @c TEXI DOCSTRING MAGIC: proof-shell-retract-files-regexp @defvar proof-shell-retract-files-regexp Matches a message that the prover has retracted a file. More precisely, this should match a string which is bounded by matches on @samp{@code{proof-shell-eager-annotation-start}} and @samp{@code{proof-shell-eager-annotation-end}}. At this stage, Proof General's view of the processed files is out of date and needs to be updated with the help of the function @samp{@code{proof-shell-compute-new-files-list}}. @end defvar @vindex proof-included-files-list @c TEXI DOCSTRING MAGIC: proof-shell-compute-new-files-list @defvar proof-shell-compute-new-files-list Function to update @samp{proof-included-files list}. It needs to return an up-to-date list of all processed files. The result will be stored in @samp{@code{proof-included-files-list}}. This function is called when @samp{@code{proof-shell-retract-files-regexp}} has been matched in the prover output. In practice, this function is likely to inspect the previous (global) variable @samp{@code{proof-included-files-list}} and the match data triggered by @samp{@code{proof-shell-retract-files-regexp}}. @end defvar @c TEXI DOCSTRING MAGIC: proof-cannot-reopen-processed-files @defvar proof-cannot-reopen-processed-files Non-nil if the prover allows re-opening of already processed files. If the user has used Proof General to process a file incrementally, then PG will retain the spans recording undo history in the buffer corresponding to that file (provided it remains visited in Emacs). If the prover allows, it will be possible to undo to a position within this file. If the prover does @strong{not} allow this, this variable should be set non-nil, so that when a completed file is activated for scripting (to do undo operations), the whole history is discarded. @end defvar @node Hooks and other settings @section Hooks and other settings @c TEXI DOCSTRING MAGIC: proof-shell-filename-escapes @defvar proof-shell-filename-escapes A list of escapes that are applied to %s for filenames.@* A list of cons cells, car of which is string to be replaced by the cdr. For example, when directories are sent to Isabelle, HOL, and Coq, they appear inside ML strings and the backslash character and quote characters must be escaped. The setting @lisp '(("@var{\\\\}" . "@var{\\\\}") ("\"" . "\\\"")) @end lisp achieves this. This setting is used inside the function @samp{@code{proof-format-filename}}. @end defvar @c TEXI DOCSTRING MAGIC: proof-shell-process-connection-type @defvar proof-shell-process-connection-type The value of @samp{@code{process-connection-type}} for the proof shell.@* Set non-nil for ptys, nil for pipes. @var{note}: In Emacs >= 24 (checked for 24 and 25.0.50.1), t is not a good choice: input is cut after @var{4095} chars, which hangs pg. @end defvar @c TEXI DOCSTRING MAGIC: proof-shell-handle-error-or-interrupt-hook @defvar proof-shell-handle-error-or-interrupt-hook Run after an error or interrupt has been reported in the response buffer.@* Hook functions may inspect @samp{@code{proof-shell-last-output-kind}} to determine whether the cause was an error or interrupt. Possible values for this hook include: @lisp @samp{@code{proof-goto-end-of-locked-on-error-if-pos-not-visible-in-window}} @samp{@code{proof-goto-end-of-locked-if-pos-not-visible-in-window}} @end lisp which move the cursor in the scripting buffer on an error or error/interrupt. Remark: This hook is called from shell buffer. If you want to do something in scripting buffer, @samp{@code{save-excursion}} and/or @samp{@code{set-buffer}}. @end defvar @c TEXI DOCSTRING MAGIC: proof-shell-pre-interrupt-hook @defvar proof-shell-pre-interrupt-hook Run immediately after @samp{@code{comint-interrupt-subjob}} is called.@* This hook is added to allow customization for systems that query the user before returning to the top level. @end defvar @c TEXI DOCSTRING MAGIC: proof-shell-handle-output-system-specific @defvar proof-shell-handle-output-system-specific Set this variable to handle system specific output.@* Errors and interrupts are recognised in the function @samp{@code{proof-shell-handle-immediate-output}}. Later output is handled by @samp{@code{proof-shell-handle-delayed-output}}, which displays messages to the user in @strong{goals} and @strong{response} buffers. This hook can run between the two stages to take some effect. It should be a function which is passed (cmd string) as arguments, where @samp{cmd} is a string containing the currently processed command and @samp{string} is the response from the proof system. If action is taken and goals/response display should be prevented, the function should update the variable @samp{@code{proof-shell-last-output-kind}} to some non-nil symbol. The symbol will be compared against standard ones, see documentation of @samp{@code{proof-shell-last-output-kind}}. A suggested canonical non-standard symbol is @code{'systemspecific}. @end defvar @node Goals Buffer Settings @chapter Goals Buffer Settings The goals buffer settings allow configuration of Proof General for proof by pointing or similar features. See the Proof General @uref{https://proofgeneral.github.io/doc, documentation web page} for a link to the technical report ECS-LFCS-97-368 which hints at how to use these settings. @c At the moment these settings are disabled. @c TEXI DOCSTRING MAGIC: pg-goals-change-goal @defvar pg-goals-change-goal Command to change to the goal @samp{%s}. @end defvar @c TEXI FIX DOCSTRING MAGIC: pbp-goal-command @defvar pbp-goal-command Command sent when @samp{pg-goals-button-action} is requested on a goal. @end defvar @c TEXI FIX DOCSTRING MAGIC: pbp-hyp-command @defvar pbp-hyp-command Command sent when @samp{pg-goals-button-action} is requested on an assumption. @end defvar @c TEXI DOCSTRING MAGIC: pg-goals-error-regexp @defvar pg-goals-error-regexp Regexp indicating that the proof process has identified an error. @end defvar @c TEXI DOCSTRING MAGIC: proof-shell-result-start @defvar proof-shell-result-start Regexp matching start of an output from the prover after pbp commands.@* In particular, after a @samp{@code{pbp-goal-command}} or a @samp{@code{pbp-hyp-command}}. @end defvar @c TEXI DOCSTRING MAGIC: proof-shell-result-end @defvar proof-shell-result-end Regexp matching end of output from the prover after pbp commands.@* In particular, after a @samp{@code{pbp-goal-command}} or a @samp{@code{pbp-hyp-command}}. @end defvar @c TEXI DOCSTRING MAGIC: pg-subterm-start-char @defvar pg-subterm-start-char Opening special character for subterm markup.@* Subsequent special characters with values @strong{below} @samp{@code{pg-subterm-first-special-char}} are assumed to be subterm position indicators. Annotations should be finished with @samp{@code{pg-subterm-sep-char}}; the end of the concrete syntax is indicated by @samp{@code{pg-subterm-end-char}}. If @samp{@code{pg-subterm-start-char}} is nil, subterm markup is disabled. @end defvar @c TEXI DOCSTRING MAGIC: pg-subterm-sep-char @defvar pg-subterm-sep-char Finishing special for a subterm markup.@* See doc of @samp{@code{pg-subterm-start-char}}. @end defvar @c TEXI DOCSTRING MAGIC: pg-topterm-regexp @defvar pg-topterm-regexp Annotation regexp that indicates the beginning of a "top" element.@* A "top" element may be a sub-goal to be proved or a named hypothesis, for example. It could also be a literal command to insert and send back to the prover. The function @samp{@code{pg-topterm-goalhyplit-fn}} examines text following this special character, to determine what kind of top element it is. This setting is also used to see if proof-by-pointing features are configured. If it is unset, some of the code for parsing the prover output is disabled. @end defvar @c TEXI DOCSTRING MAGIC: pg-subterm-end-char @defvar pg-subterm-end-char Closing special character for subterm markup.@* See @samp{@code{pg-subterm-start-char}}. @end defvar @node Splash Screen Settings @chapter Splash Screen Settings The splash screen can be configured, in a rather limited way. @c TEXI DOCSTRING MAGIC: proof-splash-time @defvar proof-splash-time Minimum number of seconds to display splash screen for.@* The splash screen may be displayed for a wee while longer than this, depending on how long it takes the machine to initialise Proof General. @end defvar @c TEXI DOCSTRING MAGIC: proof-splash-contents @defvar proof-splash-contents Evaluated to configure splash screen displayed when entering Proof General.@* A list of the screen contents. If an element is a string or an image specifier, it is displayed centred on the window on its own line. If it is nil, a new line is inserted. @end defvar @node Global Constants @chapter Global Constants The settings here are internal constants used by Proof General. You don't need to configure these for your proof assistant unless you want to modify or extend the defaults. @c TEXI DOCSTRING MAGIC: proof-general-name @defvar proof-general-name Proof General name used internally and in menu titles. @end defvar @c TEXI DOCSTRING MAGIC: proof-general-home-page @defopt proof-general-home-page Web address for Proof General. The default value is @code{"https://proofgeneral.github.io"}. @end defopt @c TEXI DOCSTRING MAGIC: proof-universal-keys @defvar proof-universal-keys List of key bindings made for all proof general buffers.@* Elements of the list are tuples @samp{(k . f)} where @samp{k} is a key binding (vector) and @samp{f} the designated function. @end defvar @node Handling Multiple Files @chapter Handling Multiple Files @cindex Multiple files Large proof developments are typically spread across multiple files. Many provers support such developments by keeping track of dependencies and automatically processing scripts. Proof General supports this mechanism. The user's point of view is considered in the user manual. Here, we describe the more technical nitty gritty. This is what you need to know when you customise another proof assistant to work with Proof General. Documentation for the configuration settings mentioned here appears in the previous sections, this section is intended to help explain the use of those settings. Proof General maintains a list @code{proof-included-files-list} of files which it thinks have been processed by the proof assistant. When a file which is on this list is visited in Emacs, it will be coloured entirely blue to indicate that it has been processed. No editing of the file will be allowed (unless @code{proof-strict-read-only} allows it). @c TEXI DOCSTRING MAGIC: proof-included-files-list @defvar proof-included-files-list List of files currently included in proof process.@* This list contains files in canonical truename format (see @samp{@code{file-truename}}). Whenever a new file is being processed, it gets added to this list via the @samp{@code{proof-shell-process-file}} configuration settings. When the prover retracts a file, this list is resynchronised via the @samp{@code{proof-shell-retract-files-regexp}} and @samp{@code{proof-shell-compute-new-files-list}} configuration settings. Only files which have been @strong{fully} processed should be included here. Proof General itself will automatically add the filenames of a script buffer which has been completely read when scripting is deactivated. It will automatically remove the filename of a script buffer which is completely unread when scripting is deactivated. NB: Currently there is no generic provision for removing files which are only partly read-in due to an error, so ideally the proof assistant should only output a processed message when a file has been successfully read. @end defvar The way that @code{proof-included-files-list} is maintained is the key to multiple file management. Ideally you should not set this variable directly, but instead use (some of) the various configuration settings that enable functionality inside Proof General for managing @code{proof-included-files-list} (see below if the configuration setting do not suffice). @vindex proof-shell-process-file @vindex proof-shell-retract-files-regexp @vindex proof-shell-compute-new-files-list @vindex proof-cannot-reopen-processed-files There is a range of strategies for managing multiple files. Ideally, file dependencies should be managed by the proof assistant. Proof General will use the prover's low-level commands to process a whole file and its requirements non-interactively, without going through script management. So that the user knows which files have been processed, the proof assistant should issue messages which Proof General can recognize (``file @code{foo} has been processed'') --- see @code{proof-shell-process-file}. When the user wants to edit a file which has been processed, the file must be retracted (unlocked). The proof assistant should provide a command corresponding to this action, which undoes a given file and all its dependencies. As each file is undone, a message should be issued which Proof General can recognize (``file @code{foo} has been undone'') -- see @code{proof-shell-retract-files-regexp}. (The function @code{proof-shell-compute-new-files-list} should be set to calculate the new value for @code{proof-included-files-list} after a retract message has been seen). @c The key idea is that we leave it to the specific proof assistant to @c worry about managing multiple files, as far as possible. Whenever the @c proof assistant processes or retracts a file it must clearly say so, so @c that Proof General can register this. As well as this communication from the assistant to Proof General about processed or retracted files, Proof General can communicate the other way: it will tell the proof assistant when it has processed or retracted a file via script management. This is because during script management, the proof assistant may not be aware that it is actually dealing with a file of proof commands (rather than just terminal input). Proof General will provide this information in two special instances. First, when scripting is turned off in a file that has been completely processed, Proof General will tell the proof assistant using @code{proof-shell-inform-file-processed-cmd}. Second, when scripting is turned on in a file which is completely processed, Proof General will tell the proof assistant to reconsider: the file should not be considered completely processed yet. This uses the setting @code{proof-shell-inform-file-retracted-cmd}. This second, retracting, case might lead to a series of messages from the prover telling Proof General to unlock files which depend on the present one, again via @code{proof-shell-retract-files-regexp}. The special case for retracting is the primary file the user wishes to edit: this is automatically removed from @code{proof-included-files-list}, but it depends on the proof assistant whether or not it is possible to revert to a partially processed version of the file (or "undo into" it). This is the reason for the setting @code{proof-cannot-reopen-processed-files}. If this is non-nil, any attempt to undo a fully processed file will unlock the entire file (whether or not Proof General itself has history information for the file). What we have described so far is the ideal case, but it may require some support from the proof assistant to set up (for example, if file-level undo is not normally supported, or the messages during file processing are not suitable). Moreover, some proof assistants may not have file handling with dependencies, or may have a particularly simple case of a linear context: each file depends on all the ones processed before it. Proof General allows you a shortcut to get automatic management of multiple files in these cases by setting the flag @code{proof-auto-multiple-files}. This setting is probably an approximation to the right thing for any proof assistant. More files than necessary will be retracted if the prover has a tree-like file dependency rather than a linear one. @vindex proof-shell-eager-annotation-start @vindex proof-shell-eager-annotation-end Finally, we should mention how Proof General recognizes file processing messages from the proof assistant. Proof General considers @var{output} delimited by the the two regular expressions @code{proof-shell-eager-annotation-start} and @code{proof-shell-eager-annotation-end} as being important. It displays the @var{output} in the Response buffer and analyses the contents further. Among other important messages characterised by these regular expressions (warnings, errors, or information), the prover can tell the interface whenever it processes or retracts a file. To summarize, the settings for multiple file management that may be customized are as follows. To recognize file-processing, @code{proof-shell-process-file}. To recognize messages about file undoing, @code{proof-shell-retract-files-regexp} and @code{proof-shell-compute-new-files-list}. @xref{Settings for matching urgent messages from proof process}. To tell the prover about files handled with script management, use @code{proof-shell-inform-file-processed-cmd} and @code{proof-shell-inform-file-retracted-cmd}. @xref{Proof shell commands}. If your prover does not allow re-opening of closed files, set @code{proof-cannot-reopen-processed-files} to @code{t}. Finally, set the flag @code{proof-auto-multiple-files} for a automatic approximation to multiple file handling. @xref{Proof Script Settings}. Internally Proof General uses @code{proof-register-possibly-new-processed-file} to add a file to @code{proof-included-files-list} and to possibly inform the prover about this fact, @xref{Proof script mode}. The function @code{proof-shell-process-urgent-message-retract} is responsible for taking (possibly several) files off @code{proof-included-files-list}. It relies on @code{proof-shell-compute-new-files-list} (@pxref{Settings for matching urgent messages from proof process}) to compute the new value of @code{proof-included-files-list} and then calls @code{proof-restart-buffers} on all those buffers that have been taken off from @code{proof-included-files-list}, @xref{Proof script mode}. @node Configuring Editing Syntax @chapter Configuring Editing Syntax @cindex syntax table Emacs has some standard settings which configure the syntax of major modes. The main setting is the @i{syntax table}, which determines the syntax of programming elements such as strings, comments, and parentheses. To configure the syntax table, you can either write calls to @code{modify-syntax-entry} in your mode functions, or set the following variables to contain the tables for each mode. (The main mode to be concerned about is of course the proof script, where user editing takes place). @c TEXI DOCSTRING MAGIC: proof-script-syntax-table-entries @defvar proof-script-syntax-table-entries List of syntax table entries for proof script mode.@* A flat list of the form @lisp (@var{char} @var{syncode} @var{char} @var{syncode} ...) @end lisp See doc of @samp{@code{modify-syntax-entry}} for details of characters and syntax codes. At present this is used only by the @samp{@code{proof-easy-config}} macro. @end defvar @c TEXI DOCSTRING MAGIC: proof-shell-syntax-table-entries @defvar proof-shell-syntax-table-entries List of syntax table entries for proof script mode.@* A flat list of the form @lisp (@var{char} @var{syncode} @var{char} @var{syncode} ...) @end lisp See doc of @samp{@code{modify-syntax-entry}} for details of characters and syntax codes. At present this is used only by the @samp{@code{proof-easy-config}} macro. @end defvar Some additional useful settings are: @c magic by hand: comment-quote-nested @defvar comment-quote-nested Non-nil if nested comments should be quoted. This should be locally set by each major mode if needed. The default setting is non-nil: modes which allow nested comments may set this to nil. @end defvar @defvar outline-regexp Regular expression to match the beginning of a heading. Any line whose beginning matches this regexp is considered to start a heading. @end defvar @defvar outline-heading-end-regexp Regular expression to match the beginning of a heading. Any line whose beginning matches this regexp is considered to start a heading. @end defvar @node Configuring Font Lock @chapter Configuring Font Lock @cindex font lock Support for Font Lock in Proof General is described in the user manual (see the @i{Syntax highlighting} section). To configure Font Lock for a new proof assistant, you need to set the variable @code{font-lock-keywords} in each of the mode functions you want highlighting for. Proof General will automatically install these settings, and use font lock minor mode (for syntax highlighting as you type) in script buffers. @c nope: too big. TEXI DOCSTRING MAGIC: font-lock-keywords To understand its format, check the documentation of @code{font-lock-keywords} inside Emacs. Instead of setting @code{font-lock-keywords} in each mode function, you can use the following four variables to make the settings in place. This is particularly useful if use the easy configuration mechanism for Proof General, @pxref{Demonstration instance and easy configuration}. @c TEXI DOCSTRING MAGIC: proof-script-font-lock-keywords @defvar proof-script-font-lock-keywords Value of @samp{@code{font-lock-keywords}} used to fontify proof scripts.@* The proof script mode should set this before calling @samp{@code{proof-config-done}}. Used also by @samp{@code{proof-easy-config}} mechanism. See also @samp{@code{proof-goals-font-lock-keywords}} and @samp{@code{proof-response-font-lock-keywords}}. @end defvar @c TEXI DOCSTRING MAGIC: proof-goals-font-lock-keywords @defvar proof-goals-font-lock-keywords Value of @samp{@code{font-lock-keywords}} used to fontify the goals output.@* The goals shell mode should set this before calling @samp{@code{proof-goals-config-done}}. Used also by @samp{@code{proof-easy-config}} mechanism. See also @samp{@code{proof-script-font-lock-keywords}} and @samp{@code{proof-response-font-lock-keywords}}. @end defvar @c TEXI DOCSTRING MAGIC: proof-response-font-lock-keywords @defvar proof-response-font-lock-keywords Value of @samp{@code{font-lock-keywords}} used to fontify the response output.@* The response mode should set this before calling @samp{@code{proof-response-config-done}}. Used also by @samp{@code{proof-easy-config}} mechanism. See also @samp{@code{proof-script-font-lock-keywords}} and @samp{@code{proof-goals-font-lock-keywords}}. @end defvar Proof General provides a special function, @code{proof-zap-commas}, for tweaking the font lock behaviour of provers which have declarations of the form @code{x,y,z:Ty}. This function removes highlighting on the commas, and can be added as the last element of @code{font-lock-keywords}. Further manipulation of font lock behaviour can be achieved via two hook functions which are run before and after fontifying the output buffers. @c TEXI DOCSTRING MAGIC: proof-zap-commas @defun proof-zap-commas limit Remove the face of all @samp{,} from point to @var{limit}.@* Meant to be used from @samp{@code{font-lock-keywords}} as a way to unfontify commas in declarations and definitions. Useful for provers which have declarations of the form x,y,z:Ty All that can be said for it is that the previous ways of doing this were even more bogus.... @end defun @c TEXI DOCSTRING MAGIC: pg-before-fontify-output-hook @defvar pg-before-fontify-output-hook This hook is called before fontifying a region in an output buffer.@* A function on this hook can alter the region of the buffer within the current restriction, and must return the final value of (@code{point-max}). [This hook is presently only used by phox-sym-lock]. @end defvar @c TEXI DOCSTRING MAGIC: pg-after-fontify-output-hook @defvar pg-after-fontify-output-hook This hook is called before fonfitying a region in an output buffer.@* [This hook is presently only used by Isabelle]. @end defvar @node Configuring Tokens @chapter Configuring Tokens @cindex Unicode Tokens @cindex Tokens Unicode Tokens is basically an overly complicated way of configuring font-lock, along with some helpful menus. The font lock configuration makes use of recent Emacs features, particularly including @code{compose-region} which allows the presentation of the buffer be different from the underlying buffer contents. Compared with the X-Symbol package used previously by Proof General, this has the huge advantage of not requiring the underlying text to be changed to display symbols. Usage of the Unicode Tokens package is described in the Proof General user manual, @inforef{Unicode support, ,ProofGeneral}. @c FIXME TODO: add documentation here to explain config of Unicode Tokens @c TEXI DOCSTRING MAGIC: proof-tokens-activate-command @defvar proof-tokens-activate-command Command to activate token input/output for prover.@* If non-nil, this command is sent to the proof assistant when Unicode Tokens support is activated. @end defvar @c TEXI DOCSTRING MAGIC: proof-tokens-deactivate-command @defvar proof-tokens-deactivate-command Command to deactivate token input/output for prover.@* If non-nil, this command is sent to the proof assistant when Unicode Tokens support is deactivated. @end defvar We expect tokens to be used uniformly, so that along with each script mode buffer, the response buffer and goals buffer also invoke Tokens to display special characters in the same token language. This happens automatically. If you want additional modes to use Tokens with the token language for your proof assistant, you can set @code{proof-tokens-extra-modes}. @c TEXI DOCSTRING MAGIC: proof-tokens-extra-modes @defvar proof-tokens-extra-modes List of additional mode names to use with Proof General tokens.@* These modes will have Tokens enabled for the proof assistant token language, in addition to the four modes for Proof General (script, shell, response, pbp). Set this variable if you want additional modes to also display tokens (for example, editing documentation or source code files). @end defvar @node Configuring Proof-Tree Visualization @chapter Configuring Proof-Tree Visualization The proof-tree visualization feature was written with the idea of supporting Coq as well as other proof assistants. Nevertheless, supporting proof-tree visualization for a second proof assistant will almost certainly require changes in the generic Elisp code in @code{generic/proof-tree.el} as well as in the Prooftree program. @menu * A layered set of proof trees:: * Prerequisites:: * Proof-Tree Display Internals:: * Configuring Prooftree for a New Proof Assistant:: @end menu @node A layered set of proof trees @section A layered set of proof trees Prooftree can actually display more than one proof tree per proof. This is necessary to support the @code{Grab Existential Variables} command in Coq. When the main goal has been proved, this command turns all open existential variables into new proof obligations. All these new proof obligations become root nodes for their own proof trees. When they all have been proved one can again grab the open existential variables... For each proof, Prooftree can therefore display several layers, where each layer can contain several (graphically) independent proof trees. The first layer contains one tree for the original proof goal. The second layer contains proof trees for goals that have been added to the proof after the first proof tree was completed. And so on. To organize the layers, Prooftree must identify those proof commands that add new goals to a proof. @c TEXI DOCSTRING MAGIC: proof-tree-new-layer-command-regexp @defvar proof-tree-new-layer-command-regexp Regexp to match proof commands that add new goals to a proof.@* This regexp must match the command that turns the proof assistant into prover mode, which adds the initial goal to the proof. It must further match commands that add additional goals after all previous goals have been proved. @end defvar @node Prerequisites @section Prerequisites Proof-tree visualization requires certain support from the proof assistant. Patching the proof assistant is therefore the first step of adding support for proof-tree visualization. The following features are needed. @table @asis @item Unique goal identification The proof assistant must assign and output a unique string for each goal. For Coq the internal @code{evar} index number is used, which is printed for each goal in the form @code{(ID XXX)} when Coq is started with the option @code{-emacs}. The unique goal identification is needed to distinguish newly spawned subgoals from older open subgoals and to mark the current goal in the proof-tree display. @item Indication of newly generated subgoals A proof command that spawns additional subgoals must somehow indicate the goal ID's of these new subgoals. Otherwise the proof-tree display will not be able to reconstruct the proof-tree structure. For Coq the newly spawned subgoals appear always in the list of additional subgoals below the current goal. Note, that it is not required to mark the newly spawned subgoals. They may appear in a mixed list with older open subgoals. Note further, that it is not required that always the complete set of all open subgoals is printed (which is indeed not the case after of @code{Focus} command in Coq). It is only required that the goal ID's of all newly spawned subgoals is somehow printed. @item State number for undo There must be a state number that is strictly increasing when asserting proof commands and that is reset to the appropriate number after retracting some proof commands. For Coq the state number in the extended prompt (visible only with option @code{-emacs}) is used. @item Information about existential variables Existential variables are placeholders that might or must be instantiated later in the proof. Prooftree supports existential variables with three features. Firstly, it can update goals when existential variables get instantiated. Secondly, it can mark the proof commands that introduced or instantiated existential variables and, thirdly, it can display and track dependencies between existential variables. For the first feature, the proof assistant must list the currently instantiated existential variables for every goal. For the second feature it must additionally list the not instantiated existential variables. Finally, for the third feature, it must display the dependencies for instantiated existential variables. For Coq, all necessary information is provided in the existential evar line, that is printed with the @code{-emacs} switch. @end table @node Proof-Tree Display Internals @section Proof-Tree Display Internals This section gives some information about the inner structure of the code that realizes the proof-tree display. The idea here is that this section provides the background information to make the documentation of the customizable variables of the proof-tree Elisp code easy to understand. @menu * Organization of the Code:: * Communication:: * Guards:: * Urgent and Delayed Actions:: * Full Annotation:: @end menu @node Organization of the Code @subsection Organization of the Code The proof-tree display is realized by Proof General in cooperation with the external Prooftree program. The latter is a GTK application in OCaml. Both, the Elisp code in Proof General and the Prooftree OCaml code is divided into a generic and a proof assistant specific part. The generic Elisp code lives in @code{generic/proof-tree.el}. As usual in Proof General, it contains various customizable variables, which the proof assistant specific code must set. Most of these variables contain regular expressions, but there are also some that hold functions. The Coq specific code for the proof-tree display is distributed in a few chunks over @code{coq/coq.el}. The main task of the Elisp code is to extract goals, undo events and information about existential variables from the proof-assistant output and to send all this data to Prooftree. The Elisp code does also determine if additional output must be requested from the proof assistant. In that case it adds appropriate commands to @code{proof-action-list}, @pxref{Proof script mode}. These additional commands are flagged with @code{proof-tree-show-subgoal}, @code{no-goals-display} and @code{no-response-display}. The flag @code{proof-tree-show-subgoal} ensures that a number of internal functions ignore these additional commands. The other two flags ensure that their output is neither displayed in the goals nor the response buffer. For the decision about which goals must be sent to Prooftree, the Elisp code maintains the following two state variables. @c TEXI DOCSTRING MAGIC: proof-tree-sequent-hash @defvar proof-tree-sequent-hash Hash table to remember sequent ID's.@* Needed because some proof assistants do not distinguish between new subgoals, which have been created by the last proof command, and older, currently unfocussed subgoals. If Proof General meets a goal, it is treated as new subgoal if it is not in this hash yet. The hash is mostly used as a set of sequent ID's. However, for undo operations it is necessary to delete all those sequents from the hash that have been created in a state later than the undo state. For this purpose this hash maps sequent ID's to the state number in which the sequent has been created. The hash table is initialized in @samp{@code{proof-tree-start-process}}. @end defvar @c TEXI DOCSTRING MAGIC: proof-tree-existentials-alist @defvar proof-tree-existentials-alist Alist mapping existential variables to sequent ID's.@* Used to remember which goals need a refresh when an existential variable gets instantiated. To support undo commands the old contents of this list must be stored in @samp{@code{proof-tree-existentials-alist-history}}. To ensure undo is properly working, this variable should only be changed by using @samp{@code{proof-tree-delete-existential-assoc}}, @samp{@code{proof-tree-add-existential-assoc}} or @samp{@code{proof-tree-clear-existentials}}. @end defvar When retracting these two variables must be set to their previous state. For @code{proof-tree-sequent-hash} this is done with the state numbers that are stored in the hash. For @code{proof-tree-existentials-alist} a separate alist stores previous states. @c TEXI DOCSTRING MAGIC: proof-tree-existentials-alist-history @defvar proof-tree-existentials-alist-history Alist mapping state numbers to old values of @samp{@code{proof-tree-existentials-alist}}.@* Needed for undo. @end defvar In Prooftree the separation between generic and proof-assistant specific code is less obvious. The Coq specific code is in the file @code{coq.ml}. All the remaining code is generic. Prooftree opens for each proof a separate window. It reconstructs the proof tree and orders the existential variables in a dependency hierarchy. It stores a complete history of previous states to support arbitrary undo operations. Under normal circumstances one starts just one Prooftree process that keeps running for the remainder of the Proof General session, regardless of how many proof-tree windows are displayed. A fair amount of the Prooftree code is documented with @code{ocamldoc} documentation comments. With @code{make doc} they can be converted into a set of html pages in the @code{doc} subdirectory. @node Communication @subsection Communication Prooftree is a standard Emacs subprocess that reads goals and other proof status messages from its standard input. The communication between Proof General and Prooftree is almost one way only. Proof General sends proof status messages to Prooftree, from which Prooftree reconstructs the current proof status and the complete proof tree. Prooftree never requests additional information from Proof General. There are only a few messages that Prooftree sends to Proof General. These messages communicate user requests to Proof General, for instance, when the user selects the undo menu item, or when he closes the Prooftree window. The communication protocol is completely described in the @code{ocamldoc} documentation of @code{input.ml} in the Prooftree sources. All messages consist of UTF-8 encoded human-readable strings. The strings have either a fixed length or their byte-length is encoded in the message before the string itself. For debugging purposes Prooftree can save all input in a file. This feature can be turned on in the @code{Debug} tab of the Prooftree configuration dialog or with option @code{-tee}. The text that Prooftree sends to Proof General can be found in buffer @code{*proof-tree*}. @node Guards @subsection Guards The proof-tree display code inside Proof General uses two guard variables. @c TEXI DOCSTRING MAGIC: proof-tree-configured @defvar proof-tree-configured Whether external proof-tree display is configured.@* This boolean enables the proof-tree menu entry and the function that starts external proof-tree display. @end defvar @c TEXI DOCSTRING MAGIC: proof-tree-external-display @defvar proof-tree-external-display Display proof trees in external prooftree windows if t.@* Actually, if this variable is t then the user requested an external proof-tree display. If there was no unfinished proof when proof-tree display was requested and if no proof has been started since then, then there is obviously no proof-tree display. In this case, this variable stays t and the proof-tree display will be started for the next proof. Controlled by @samp{@code{proof-tree-external-display-toggle}}. @end defvar In Proof General, the code for the external proof-tree display is called from the proof-shell filter function in @code{proof-shell-exec-loop} and @code{proof-shell-filter-manage-output}, @pxref{Proof shell mode}. The variable @code{proof-tree-external-display} is a guard for these calls, to ensure that the proof-tree specific code is only called if the user requested a proof-tree display. The whole proof-tree package contains only one function that can be called interactively: @code{proof-tree-external-display-toggle}, which switches @code{proof-tree-external-display} on and off. When @code{proof-tree-configured} is @code{nil}, @code{proof-tree-external-display-toggle} aborts with an error message. @c TEXI DOCSTRING MAGIC: proof-tree-external-display-toggle @deffn Command proof-tree-external-display-toggle Toggle the external proof-tree display.@* When called outside a proof the external proof-tree display will be enabled for the next proof. When called inside a proof the proof display will be created for the current proof. If the external proof-tree display is currently on, then this toggle will switch it off. At the end of the proof the proof-tree display is switched off. @end deffn @node Urgent and Delayed Actions @subsection Urgent and Delayed Actions The proof-shell filter functions contains two calls to proof-tree specific code. One for urgent actions and one for all remaining actions, that can be delayed. Urgent actions are those that must be executed before @code{proof-shell-exec-loop} sends the next item from @code{proof-action-list} to the proof assistant. For execution speed, the amount of urgent code should be kept small. @c TEXI DOCSTRING MAGIC: proof-tree-urgent-action @defun proof-tree-urgent-action flags Handle urgent points before the next item is sent to the proof assistant.@* Schedule goal updates when existential variables have changed and call @samp{@code{proof-tree-urgent-action-hook}}. All this is only done if the current output does not come from a command (with the @code{'proof-tree-show-subgoal} flag) that this package inserted itself. Urgent actions are only needed if the external proof display is currently running. Therefore this function should not be called when @samp{@code{proof-tree-external-display}} is nil. This function assumes that the prover output is not suppressed. Therefore, @samp{@code{proof-tree-external-display}} being t is actually a necessary precondition. The not yet delayed output is in the region [@code{proof-shell-delayed-output-start}, @code{proof-shell-delayed-output-end}]. @end defun The function @code{proof-tree-urgent-action} is called at a point where it is save to manipulate @code{proof-action-list}. This is essential, because @code{proof-tree-urgent-action} inserts goal display commands into @code{proof-action-list} when existential variables got instantiated and when the sequent text from newly created subgoals is missing. Most of the proof-tree specific code runs when the proof assistant is already busy with the next item from @code{proof-action-list}. @c TEXI DOCSTRING MAGIC: proof-tree-handle-delayed-output @defun proof-tree-handle-delayed-output old-proof-marker cmd flags _span Process delayed output for prooftree.@* This function is the main entry point of the Proof General prooftree support. It examines the delayed output in order to take appropriate actions and maintains the internal state. The delayed output to handle is in the region [@code{proof-shell-delayed-output-start}, @code{proof-shell-delayed-output-end}]. Urgent messages might be before that, following @var{old-proof-marker}, which contains the position of @samp{@code{proof-marker}}, before the next command was sent to the proof assistant. All other arguments are (former) fields of the @samp{@code{proof-action-list}} entry that is now finally retired. @var{cmd} is the command, @var{flags} are the flags and @var{span} is the span. @end defun The function @code{proof-tree-handle-delayed-output} does all the communication with Prooftree. @node Full Annotation @subsection Full Annotation In the default configuration Proof General switches the proof assistant into quiet mode if there are more than @code{proof-shell-silent-threshold} items in @code{proof-action-list}, see Section @i{Document centred working} (in Chapter @i{Advanced Script Management and Editing}) in the @i{Proof General} users manual. The proof-tree display needs of course the full output from the proof assistant. Therefore @code{proof-shell-should-be-silent} keeps the proof assistant noisy when the proof-tree display is switched on. @node Configuring Prooftree for a New Proof Assistant @section Configuring Prooftree for a New Proof Assistant To get the proof-tree display running for a new proof assistant one has to configure the proof-tree Elisp code and adapt the Prooftree program. @menu * Proof Tree Elisp configuration:: * Prooftree Adaption:: @end menu @node Proof Tree Elisp configuration @subsection Proof Tree Elisp configuration All variables that need to be configured are in the customization group @code{proof-tree-internals}. Most of these variables are regular expressions for extracting various parts from the proof assistant output. However, some are functions that need to be implemented as prover specific part of the proof display code. The variables @code{proof-tree-configured}, @code{proof-tree-get-proof-info} and @code{proof-tree-find-begin-of-unfinished-proof} might be used before the proof assistant is running inside a proof shell. They must therefore be configured as part of the proof assistant editing mode. The other variables are only used when the proof shell is running. They can therefore be configured with the proof assistant proof-shell mode. @node Prooftree Adaption @subsection Prooftree Adaption To make the new proof assistant known to Prooftree, the match in function @code{configure_prooftree} in @code{input.ml} must be extended. If the new proof assistant does not support existential variables adding a line @example | "new-pa-name" -> () @end example suffices. If the new prover supports existential variables, Prooftree must be extended with a parser for the existential variable information printout of the proof assistant. The parser for Coq is contained in the file @code{coq.ml}. Then the function @code{configure_prooftree} must assign this new parser to the reference @code{parse_existential_info}. @node Writing More Lisp Code @chapter Writing More Lisp Code You may want to add some extra features to your instance of Proof General which are not supported in the generic core. To do this, you can use the settings described above, plus a small number of fundamental functions in Proof General which you can consider as exported in the generic interface. Be careful using more functions than are mentioned here because the internals of Proof General may change between versions. @menu * Default values for generic settings:: * Adding prover-specific configurations:: * Useful variables:: * Useful functions and macros:: @end menu @node Default values for generic settings @section Default values for generic settings Several generic settings are defined using @code{defpgcustom} in @file{proof-config.el}. This introduces settings of the form @code{-name} for each proof assistant @var{PA}. To set the default value for these settings in prover-specific cases, you should use the special @code{defpgdefault} macro: @c TEXI DOCSTRING MAGIC: defpgdefault @deffn Macro defpgdefault Set default for the proof assistant specific variable @var{-sym} to @var{value}.@* This should be used in prover-specific code to alter the default values for prover specific settings. Usage: (defpgdefault SYM @var{value}) @end deffn In your prover-specific code you can simply use the setting @code{-sym} directly, i.e., write @code{myprover-home-page}. In the generic code, you can use a macro, writing @code{(proof-ass home-page)} to refer to the @code{-home-page} setting for the currently running instance of Proof General. @xref{Configuration variable mechanisms}, for more details on this mechanism. @node Adding prover-specific configurations @section Adding prover-specific configurations Apart from the generic settings, your prover instance will probably need some specific customizable settings. Defining new prover-specific settings using customize is pretty easy. You should do it at least for your prover-specific user options. The code in @file{proof-site.el} provides each prover with two customization groups automatically (based on the name of the assistant): @code{} for user options for prover @var{PA} and @code{-config} for configuration of prover @var{PA}. Typically @code{-config} holds settings which are constants but which may be nice to tweak. The first group appears in the menu @lisp ProofGeneral -> Advanced -> Customize -> @end lisp The second group appears in the menu: @lisp ProofGeneral -> Internals -> config @end lisp A typical use of @code{defcustom} looks like this: @lisp (defcustom myprover-search-page "http://findtheorem.myprover.org" "URL of search web page for myprover." :type 'string :group 'myprover-config) @end lisp This introduces a new customizable setting, which you might use to make a menu entry, for example. The default value is the string @code{"http://findtheorem.myprover.org"}. @node Useful variables @section Useful variables In @file{proof-site}, some architecture flags are defined. These can be used to write conditional pieces of code for different Emacs and operating systems. They are referred to mainly in @file{proof-compat} (which helps to keep the architecture and version dependent code in one place). @node Useful functions and macros @section Useful functions and macros The recommended functions you may invoke are these: @itemize @bullet @item Any of the interactive commands (i.e. anything you can invoke with @kbd{M-x}, including all key-bindings) @item Any of the internal functions and macros mentioned below @end itemize To insert text into the current (usually script) buffer, the function @code{proof-insert} is useful. There's also a handy macro @code{proof-defshortcut} for defining shortcut functions using it. @c TEXI DOCSTRING MAGIC: proof-insert @defun proof-insert text Insert @var{text} into the current buffer.@* @var{text} may include these special characters: @lisp %p - place the point here after input @end lisp Any other %-prefixed character inserts itself. @end defun @c TEXI DOCSTRING MAGIC: proof-defshortcut @deffn Macro proof-defshortcut Define shortcut function FN to insert @var{string}, optional keydef KEY.@* This is intended for defining proof assistant specific functions. @var{string} is inserted using @samp{@code{proof-insert}}, which see. KEY is added onto proof assistant map. @end deffn The function @code{proof-shell-invisible-command} is a useful utility for sending a single command to the process. You should use this to implement user-level or internal functions rather than attempting to directly manipulate the proof action list, or insert into the shell buffer. @c TEXI DOCSTRING MAGIC: proof-shell-invisible-command @defun proof-shell-invisible-command cmd &optional wait invisiblecallback &rest flags Send @var{cmd} to the proof process.@* The @var{cmd} is @samp{invisible} in the sense that it is not recorded in buffer. @var{cmd} may be a string or a string-yielding expression. Automatically add @samp{@code{proof-terminal-string}} if necessary, examining @samp{proof-shell-no-auto-terminate-commands}. By default, let the command be processed asynchronously. But if optional @var{wait} command is non-nil, wait for processing to finish before and after sending the command. In case @var{cmd} is (or yields) nil, do nothing. @var{invisiblecallback} will be invoked after the command has finished, if it is set. It should probably run the hook variables @samp{@code{proof-state-change-hook}}. @var{flags} are additional flags to put onto the @samp{@code{proof-action-list}}. The flag @code{'invisible} is always added to @var{flags}. @end defun There are several handy macros to help you define functions which invoke @code{proof-shell-invisible-command}. @c TEXI DOCSTRING MAGIC: proof-definvisible @deffn Macro proof-definvisible Define function FN to send @var{string} to proof assistant, optional keydef KEY.@* This is intended for defining proof assistant specific functions. @var{string} is sent using @samp{@code{proof-shell-invisible-command}}, which see. @var{string} may be a string or a function which returns a string. KEY is added onto proof assistant map. @end deffn @c TEXI DOCSTRING MAGIC: proof-define-assistant-command @deffn Macro proof-define-assistant-command Define FN (docstring DOC): check if @var{cmdvar} is set, then send @var{body} to prover.@* @var{body} defaults to @var{cmdvar}, a variable. @end deffn @c TEXI DOCSTRING MAGIC: proof-define-assistant-command-witharg @deffn Macro proof-define-assistant-command-witharg Define FN (arg) with DOC: check @var{cmdvar} is set, @var{prompt} a string and eval @var{body}.@* The @var{body} can contain occurrences of arg. @var{cmdvar} is a variable holding a function or string. Automatically has history. @end deffn @c TEXI DOCSTRING MAGIC: proof-format-filename @defun proof-format-filename string filename Format @var{string} by replacing quoted chars by escaped version of @var{filename}. %e uses the canonicalized expanded version of filename (including directory, using @samp{@code{default-directory}} -- see @samp{@code{expand-file-name}}). %r uses the unadjusted (possibly relative) version of @var{filename}. %m ('module') uses the basename of the file, without directory or extension. %s means the same as %e. Using %e can avoid problems with dumb proof assistants who don't understand ~, for example. For all these cases, the escapes in @samp{@code{proof-shell-filename-escapes}} are processed. If @var{string} is in fact a function, instead invoke it on @var{filename} and return the resulting (string) value. @end defun @node Internals of Proof General @chapter Internals of Proof General This chapter sketches some of the internal functions and variables of Proof General, to help developers who wish to understand or modify the code. Most of the documentation below is generated automatically from the comments in the code. Because Emacs lisp is interpreted and self-documenting, the best way to find your way around the source is inside Emacs once Proof General is loaded. Read the source files, and use functions such as @kbd{C-h v} and @kbd{C-h f}. The code is split into files. The following sections document the important files, kept in the @file{generic/} subdirectory. @menu * Spans:: * Proof General site configuration:: * Configuration variable mechanisms:: * Global variables:: * Proof script mode:: * Proof shell mode:: * Debugging:: @end menu @c @c SECTION: Global variables @c @node Spans @section Spans @cindex spans @cindex extents @cindex overlays @dfn{Spans} are an abstraction of Emacs @dfn{overlays} originally used to help bridge the gulf between GNU Emacs and XEmacs. See the file @file{lib/span.el}. XEmacs calls these @dfn{extents} which is a name still used in some parts of the code. @c @c SECTION: Proof General site configuration @c @node Proof General site configuration @section Proof General site configuration @cindex installation directories @cindex site configuration The file @file{proof-site.el} contains the initial configuration for Proof General for the site (or user) and the choice of provers. The first part of the configuration is to set @code{proof-home-directory} to the directory that @file{proof-site.el} is located in, or to the variable of the environment variable @code{PROOFGENERAL_HOME} if that is set. @c TEXI DOCSTRING MAGIC: proof-home-directory @defvar proof-home-directory Directory where Proof General is installed.@* Based on where the file @samp{proof-site.el} was loaded from. Falls back to consulting the environment variable @samp{PROOFGENERAL_HOME} if proof-site.el couldn't know where it was executed from. @end defvar @c They're no longer options. @c The default value for @code{proof-home-directory} mentioned above is the @c one for the author's system, it won't be the same for you! Further directory variables allow the files of Proof General to be split up and installed across a system if need be, rather than under the @code{proof-home-directory} root. @c TEXI DOCSTRING MAGIC: proof-images-directory @defvar proof-images-directory Where Proof General image files are installed. Ends with slash. @end defvar @c TEXI DOCSTRING MAGIC: proof-info-directory @defvar proof-info-directory Where Proof General Info files are installed. Ends with slash. @end defvar @cindex mode stub After defining these settings, we define a @dfn{mode stub} for each proof assistant enabled. The mode stub will autoload Proof General for the right proof assistant when a file is visited with the corresponding extension. The proof assistants enabled are the ones listed in the @code{proof-assistants} setting. @c TEXI DOCSTRING MAGIC: proof-assistants @defvar proof-assistants Choice of proof assistants to use with Proof General.@* A list of symbols chosen from: @samp{coq} @samp{easycrypt} @samp{phox} @samp{qrhl} @samp{pgshell} @samp{pgocaml} @samp{pghaskell}. If nil, the default will be ALL available proof assistants. Each proof assistant defines its own instance of Proof General, providing session control, script management, etc. Proof General will be started automatically for the assistants chosen here. To avoid accidently invoking a proof assistant you don't have, only select the proof assistants you (or your site) may need. You can select which proof assistants you want by setting this variable before @samp{proof-site.el} is loaded, or by setting the environment variable @samp{PROOFGENERAL_ASSISTANTS} to the symbols you want, for example "coq easycrypt". Or you can edit the file @samp{proof-site.el} itself. Note: to change proof assistant, you must start a new Emacs session. @end defvar The file @file{proof-site.el} also defines a version variable. @c TEXI DOCSTRING MAGIC: proof-general-version @defvar proof-general-version Version string identifying Proof General release. @end defvar @c @c SECTION: Configuration variable mechanisms @c @node Configuration variable mechanisms @section Configuration variable mechanisms @cindex conventions @cindex user options @cindex configuration @cindex settings The file @file{proof-config.el} defines the configuration variables for Proof General, including instantiation parameters and user options. See previous chapters for details of its contents. Here we mention some conventions for declaring user options. Global user options and instantiation parameters are declared using @code{defcustom} as usual. User options should have `@code{*}' as the first character of their docstrings (standard Emacs convention) and live in the customize group @code{proof-user-options}. See @file{proof-config.el} for the groups for instantiation parameters. User options which are generic (having separate instances for each prover) and instantiation parameters (by definition generic) can be declared using the special macro @code{defpgcustom}. It is used in the same way as @code{defcustom}, except that the symbol declared will automatically be prefixed by the current proof assistant symbol. @c TEXI DOCSTRING MAGIC: defpgcustom @deffn Macro defpgcustom Define a new customization variable @var{-sym} for the current proof assistant.@* This is intended for defining settings which are useful for any prover, but which the user may require different values of across provers. The function proof-assistant- is also defined, which can be used in the generic portion of Proof General to access the value for the current prover. Arguments @var{args} are as for @samp{defcustom}, which see. If a :group argument is not supplied, the setting will be added to the internal settings for the current prover (named -config). @end deffn In specific instances of Proof General, the macro @code{defpgdefault} can be used to give a default value for a generic setting. @c TEXI DOCSTRING MAGIC: defpgdefault @deffn Macro defpgdefault Set default for the proof assistant specific variable @var{-sym} to @var{value}.@* This should be used in prover-specific code to alter the default values for prover specific settings. Usage: (defpgdefault SYM @var{value}) @end deffn All new instantiation variables are best declared using the @code{defpgcustom} mechanism (old code may be converted gradually). Customizations which are liable to be different for different instances of Proof General are also best declared in this way. An example is the use of X Symbol, controlled by @code{@emph{PA}-x-symbol-enable}, since it works poorly or not at all with some provers. To access the generic settings, the following four functions and macros are useful. @c TEXI DOCSTRING MAGIC: proof-ass @deffn Macro proof-ass Return the value for SYM for the current prover.@* This macro should only be invoked once a specific prover is engaged. @end deffn @c TEXI DOCSTRING MAGIC: proof-ass-sym @deffn Macro proof-ass-sym Return the symbol for SYM for the current prover. SYM not evaluated.@* This macro should only be called once a specific prover is known. @end deffn @c TEXI DOCSTRING MAGIC: proof-ass-symv @deffn Macro proof-ass-symv Return the symbol for SYM for the current prover. SYM evaluated.@* This macro should only be invoked once a specific prover is engaged. @end deffn If changing a user option setting amounts to more than just setting a variable (it may have some dynamic effect), we can set the @code{custom-set} property for the variable to the function @code{proof-set-value} which does an ordinary @code{set-default} to set the variable, and then calls a function with the same name as the variable, to do whatever is necessary according to the new value for the variable. There are several settings which can be switched on or off by the user, which use this @code{proof-set-value} mechanism. They are controlled by boolean variables with names like @code{proof-@var{foo}-enable}, and appear at the start of the customize group @code{proof-user-options}. They should be edited by the user through the customization mechanism, and set in the code using @code{customize-set-variable}. In @code{proof-utils.el} there is a handy macro, @code{proof-deftoggle}, which constructs an interactive function for toggling boolean customize settings. We can use this to make an interactive function @code{proof-@var{foo}-toggle} to put on a menu or bind to a key, for example. This general scheme is followed as far as possible, to give uniform behaviour and appearance for boolean user options, as well as interfacing properly with the @code{customize} mechanism. @c TEXI DOCSTRING MAGIC: proof-set-value @defun proof-set-value sym value Set a customize variable using @samp{@code{set-default}} and a function.@* We first call @samp{@code{set-default}} to set @var{sym} to @var{value}. Then if there is a function @var{sym} (i.e. with the same name as the variable @var{sym}), it is called to take some dynamic action for the new setting. If there is no function @var{sym}, we try stripping @samp{@code{proof-assistant-symbol}} and adding "proof-" instead to get a function name. This extends @code{proof-set-value} to work with generic individual settings. The dynamic action call only happens when values @strong{change}: as an approximation we test whether proof-config is fully-loaded yet. @end defun @c TEXI DOCSTRING MAGIC: proof-deftoggle @deffn Macro proof-deftoggle Define a function VAR-toggle for toggling a boolean customize setting VAR.@* The toggle function uses @samp{@code{customize-set-variable}} to change the variable. @var{othername} gives an alternative name than the default -toggle. The name of the defined function is returned. @end deffn @c @c SECTION: Global variables @c @node Global variables @section Global variables @cindex variables Global variables are defined in @file{proof.el}. The same file defines a few utility functions and some triggers to load in the other files. @c TEXI DOCSTRING MAGIC: proof-script-buffer @defvar proof-script-buffer The currently active scripting buffer or nil if none. @end defvar @c TEXI DOCSTRING MAGIC: proof-shell-buffer @defvar proof-shell-buffer Process buffer where the proof assistant is run. @end defvar @c TEXI DOCSTRING MAGIC: proof-response-buffer @defvar proof-response-buffer The response buffer. @end defvar @c TEXI DOCSTRING MAGIC: proof-goals-buffer @defvar proof-goals-buffer The goals buffer. @end defvar @c TEXI DOCSTRING MAGIC: proof-buffer-type @defvar proof-buffer-type Symbol for the type of this buffer: @code{'script}, @code{'shell}, @code{'goals}, or @code{'response}. @end defvar @c TEXI DOCSTRING MAGIC: proof-included-files-list @defvar proof-included-files-list List of files currently included in proof process.@* This list contains files in canonical truename format (see @samp{@code{file-truename}}). Whenever a new file is being processed, it gets added to this list via the @samp{@code{proof-shell-process-file}} configuration settings. When the prover retracts a file, this list is resynchronised via the @samp{@code{proof-shell-retract-files-regexp}} and @samp{@code{proof-shell-compute-new-files-list}} configuration settings. Only files which have been @strong{fully} processed should be included here. Proof General itself will automatically add the filenames of a script buffer which has been completely read when scripting is deactivated. It will automatically remove the filename of a script buffer which is completely unread when scripting is deactivated. NB: Currently there is no generic provision for removing files which are only partly read-in due to an error, so ideally the proof assistant should only output a processed message when a file has been successfully read. @end defvar @c TEXI DOCSTRING MAGIC: proof-shell-proof-completed @defvar proof-shell-proof-completed Flag indicating that a completed proof has just been observed.@* If non-nil, the value counts the commands from the last command of the proof (starting from 1). @end defvar @c TEXI DOCSTRING MAGIC: proof-shell-error-or-interrupt-seen @defvar proof-shell-error-or-interrupt-seen Flag indicating that an error or interrupt has just occurred.@* Set to @code{'error} or @code{'interrupt} if one was observed from the proof assistant during the last group of commands. @end defvar @c @c SECTION: Proof script mode @c @node Proof script mode @section Proof script mode The file @file{proof-script.el} contains the main code for proof script mode, as well as definitions of menus, key-bindings, and user-level functions. Proof scripts have two important variables for the locked and queue regions. These variables are local to each script buffer (although we only really need one queue span in total rather than one per buffer). @c TEXI DOCSTRING MAGIC: proof-locked-span @defvar proof-locked-span The locked span of the buffer.@* Each script buffer has its own locked span, which may be detached from the buffer. Proof General allows buffers in other modes also to be locked; these also have a non-nil value for this variable. @end defvar @c TEXI DOCSTRING MAGIC: proof-queue-span @defvar proof-queue-span The queue span of the buffer. May be detached if inactive or empty.@* Each script buffer has its own queue span, although only the active scripting buffer may have an active queue span. @end defvar Various utility functions manipulate and examine the spans. An important one is @code{proof-init-segmentation}. @c TEXI DOCSTRING MAGIC: proof-init-segmentation @defun proof-init-segmentation Initialise the queue and locked spans in a proof script buffer.@* Allocate spans if need be. The spans are detached from the buffer, so the regions are made empty by this function. Also clear list of script portions. @end defun For locking files loaded by a proof assistant, we use the next function. @c TEXI DOCSTRING MAGIC: proof-complete-buffer-atomic @defun proof-complete-buffer-atomic buffer Ensure @var{buffer} marked completely processed, completing with a single step. If buffer already contains a locked region, only the remainder of the buffer is closed off atomically (although undo for the initial portion is unlikely to work, the decoration may be worth retaining). This works for buffers which are not in proof scripting mode too, to allow other files loaded by proof assistants to be marked read-only. @end defun Atomic locking is instigated by the next function, which uses the variables @code{proof-included-files-list} documented earlier (@pxref{Handling Multiple Files} and @pxref{Global variables}). @c TEXI DOCSTRING MAGIC: proof-register-possibly-new-processed-file @defun proof-register-possibly-new-processed-file file &optional informprover noquestions Register a possibly new @var{file} as having been processed by the prover. If @var{informprover} is non-nil, the proof assistant will be told about this, to co-ordinate with its internal file-management. (Otherwise we assume that it is a message from the proof assistant which triggers this call). In this case, the user will be queried to save some buffers, unless @var{noquestions} is non-nil. No action is taken if the file is already registered. A warning message is issued if the register request came from the proof assistant and Emacs has a modified buffer visiting the file. @end defun (Unlocking is done by @code{proof-shell-process-urgent-message-retract} together with @code{proof-restart-buffers}.) An important pair of functions activate and deactivate scripting for the current buffer. A change in the state of active scripting can trigger various actions, such as starting up the proof assistant, or altering @code{proof-included-files-list}. @c TEXI DOCSTRING MAGIC: proof-activate-scripting @deffn Command proof-activate-scripting &optional nosaves queuemode Ready prover and activate scripting for the current script buffer. The current buffer is prepared for scripting. No changes are necessary if it is already in Scripting minor mode. Otherwise, it will become the new active scripting buffer, provided scripting can be switched off in the previous active scripting buffer with @samp{@code{proof-deactivate-scripting}}. Activating a new script buffer is a good time to ask if the user wants to save some buffers; this is done if the user option @samp{@code{proof-query-file-save-when-activating-scripting}} is set and provided the optional argument @var{nosaves} is non-nil. The optional argument @var{queuemode} relaxes the test for a busy proof shell to allow one which has mode @var{queuemode}. In all other cases, a proof shell busy error is given. Finally, the hooks @samp{@code{proof-activate-scripting-hook}} are run. This can be a useful place to configure the proof assistant for scripting in a particular file, for example, loading the correct theory, or whatever. If the hooks issue commands to the proof assistant (via @samp{@code{proof-shell-invisible-command}}) which result in an error, the activation is considered to have failed and an error is given. @end deffn @c TEXI DOCSTRING MAGIC: proof-deactivate-scripting @deffn Command proof-deactivate-scripting &optional forcedaction Try to deactivate scripting for the active scripting buffer. Aims to set @samp{@code{proof-script-buffer}} to nil and turn off the modeline indicator. No action is required there is no active scripting buffer. We make sure that the active scripting buffer either has no locked region or a full locked region (everything in it has been processed). If this is not already the case, we question the user whether to retract or assert, or automatically take the action indicated in the user option @samp{@code{proof-auto-action-when-deactivating-scripting}}. If @samp{@code{proof-no-fully-processed-buffer}} is t there is only the choice to fully retract the active scripting buffer. In this case the active scripting buffer is retracted even if it was fully processed. Setting @samp{@code{proof-auto-action-when-deactivating-scripting}} to @code{'process} is ignored in this case. If the scripting buffer is (or has become) fully processed, and it is associated with a file, it is registered on @samp{@code{proof-included-files-list}}. Conversely, if it is (or has become) empty, we make sure that it is @strong{not} registered. This is to be certain that the included files list behaves as we might expect with respect to the active scripting buffer, in an attempt to harmonize mixed scripting and file reading in the prover. This function either succeeds, fails because the user refused to process or retract a partly finished buffer, or gives an error message because retraction or processing failed. If this function succeeds, then @samp{@code{proof-script-buffer}} is nil afterwards. The optional argument @var{forcedaction} overrides the user option @samp{@code{proof-auto-action-when-deactivating-scripting}} and prevents questioning the user. It is used to make a value for the @samp{@code{kill-buffer-hook}} for scripting buffers, so that when a scripting buffer is killed it is always retracted. @end deffn The function @code{proof-segment-up-to} is the main one used for parsing the proof script buffer. There are several variants of this function available corresponding to different parsing strategies; the appropriate one is aliased to @code{proof-segment-up-to} according to which configuration variables have been set. @itemize @bullet @item If @code{proof-script-sexp-commands} is set, the choice is @code{proof-script-generic-parse-sexp}. @ item If only @code{proof-script-command-end-regexp} or @code{proof-terminal-string} are set, then the default is @code{proof-script-generic-parse-cmdend}. @item If @code{proof-script-command-start-regexp} is set, the choice is @code{proof-script-generic-parse-cmdstart}. @end itemize The function @code{proof-semis-to-vanillas} uses @code{proof-segment-up-to} to convert a parsed region of the script into a series of commands to be sent to the proof assistant. @c TEXI DOCSTRING MAGIC: proof-script-generic-parse-cmdend @defun proof-script-generic-parse-cmdend For @samp{@code{proof-script-parse-function}} if @samp{@code{proof-script-command-end-regexp}} set. @end defun @c TEXI DOCSTRING MAGIC: proof-script-generic-parse-cmdstart @defun proof-script-generic-parse-cmdstart For @samp{@code{proof-script-parse-function}} if @samp{@code{proof-script-command-start-regexp}} is set. @end defun @c TEXI DOCSTRING MAGIC: proof-script-generic-parse-sexp @defun proof-script-generic-parse-sexp Used for @samp{@code{proof-script-parse-function}} if @samp{@code{proof-script-sexp-commands}} is set. @end defun @c TEXI DOCSTRING MAGIC: proof-semis-to-vanillas @defun proof-semis-to-vanillas semis &optional queueflags Create vanilla spans for @var{semis} and a list for the queue.@* Proof terminator positions @var{semis} has the form returned by the function @samp{proof-segment-up-to}. The argument list is destroyed. The callback in each queue element is @samp{@code{proof-done-advancing}}. If the variable @samp{@code{proof-script-preprocess}} is set (to the name of a function), call that function to construct the first element of each queue item. The optional @var{queueflags} are added to each queue item. @end defun The function @code{proof-assert-until-point} is the main one used to process commands in the script buffer. It's actually used to implement the assert-until-point, electric terminator keypress, and find-next-terminator behaviours. In different cases we want different things, but usually the information (i.e. are we inside a comment) isn't available until we've actually run @code{proof-segment-up-to (point)}, hence all the different options when we've done so. @c TEXI DOCSTRING MAGIC: proof-assert-until-point @defun proof-assert-until-point &optional displayflags Process the region from the end of the locked-region until point. @end defun The main command for retracting parts of a script is @code{proof-retract-until-point}. @c TEXI DOCSTRING MAGIC: proof-retract-until-point @defun proof-retract-until-point &optional undo-action displayflags Set up the proof process for retracting until point.@* This calculates the commands to undo to the current point within the locked region. If invoked outside the locked region, undo the last successfully processed command. See @samp{@code{proof-retract-target}}. After retraction has succeeded in the prover, the filter will call @samp{@code{proof-done-retracting}}. If @var{undo-action} is non-nil, it will then be invoked on the region in the proof script corresponding to the proof command sequence. @var{displayflags} control output shown to user, see @samp{@code{proof-action-list}}. Before the retraction is calculated, we enforce the file-level protocol with @samp{@code{proof-activate-scripting}}. This has a couple of effects: 1. If the file is completely processed, we have to re-open it for scripting again which may involve retracting other (dependent) files. 2. We may query the user whether to save some buffers. Step 2 may seem odd -- we're undoing (in) the buffer, after all -- but what may happen is that when scripting starts going forward again, we hit a command that loads other files, but the user hasn't saved the latest edits. Therefore it is right to query saves here. @end defun To clean up when scripting is stopped, a script buffer is killed, a file is retract (and thus must be unlocked), or the proof assistant exits, we use the functions @code{proof-restart-buffers} and @code{proof-script-remove-all-spans-and-deactivate}. @c TEXI DOCSTRING MAGIC: proof-restart-buffers @defun proof-restart-buffers buffers Remove all extents in @var{buffers} and maybe reset @samp{@code{proof-script-buffer}}.@* The high-level effect is that all members of @var{buffers} are completely unlocked, including all the necessary cleanup. No effect on a buffer which is nil or killed. If one of the buffers is the current scripting buffer, then @samp{@code{proof-script-buffer}} will deactivated. @end defun @c TEXI DOCSTRING MAGIC: proof-script-remove-all-spans-and-deactivate @defun proof-script-remove-all-spans-and-deactivate Remove all spans from scripting buffers via @samp{@code{proof-restart-buffers}}. @end defun @c @c SECTION: Proof Shell Mode @c @node Proof shell mode @section Proof shell mode @cindex proof shell mode @cindex comint-mode @cindex scomint-mode The proof shell mode code is in the file @file{proof-shell.el}. Proof shell mode is defined to inherit from @code{scomint-mode} using @code{define-derived-mode} near the end of the file. The @file{scomint.el} package stands for ``simplified comint'', where @code{comint-mode} is the standard Emacs mode for running an embedded command interpreter. In @code{scomint}, many of the interactive commands have been removed to speed up the process handling, because it isn't intended that the user interacts directly with the shell in Proof General. The bulk of the code in the @code{proof-shell} package is concerned with sending code to and from the shell, and processing output for the associated buffers (goals and response). Good process handling is a tricky issue. Proof General attempts to manage the process strictly, by maintaining a queue of commands to send to the process. Once a command has been processed, another one is popped off the queue and sent. There are several important internal variables which control interaction with the process. @c TEXI DOCSTRING MAGIC: proof-shell-busy @defvar proof-shell-busy A lock indicating that the proof shell is processing. The lock notes that we are processing a queue of commands being sent to the prover, and indicates whether the commands correspond to script management from a buffer (rather than being ad-hoc query commands to the prover). When processing commands from a buffer for script management, this will be set to the queue mode @code{'advancing} or @code{'retracting} to indicate the direction of movement. When this is non-nil, @samp{@code{proof-shell-ready-prover}} will give an error if called with a different requested queue mode. See also functions @samp{@code{proof-activate-scripting}} and @samp{@code{proof-shell-available-p}}. @end defvar @c TEXI DOCSTRING MAGIC: proof-marker @defvar proof-marker Marker in proof shell buffer pointing to previous command input. @end defvar @c TEXI DOCSTRING MAGIC: proof-action-list @defvar proof-action-list The main queue of things to do: spans, commands and actions.@* The value is a list of lists of the form @lisp (@var{span} @var{commands} @var{action} [DISPLAYFLAGS]) @end lisp which is the queue of things to do. @var{span} is a region in the sources, where @var{commands} come from. Often, additional properties are recorded as properties of @var{span}. @var{commands} is a list of strings, holding the text to be send to the prover. It might be the empty list if nothing needs to be sent to the prover, such as, for comments. Usually @var{commands} contains just 1 string, but it might also contains more elements. The text should be obtained with @samp{(mapconcat }identity @var{commands} " ")', where the last argument is a space. @var{action} is the callback to be invoked when this item has been processed by the prover. For normal scripting items it is @samp{@code{proof-done-advancing}}, for retract items @samp{@code{proof-done-retracting}}, but there are more possibilities (e.g. @samp{@code{proof-done-invisible}}, @samp{@code{proof-shell-set-silent}}, @samp{@code{proof-shell-clear-silent}} and @samp{@code{proof-tree-show-goal-callback}}). The @var{displayflags} are set for non-scripting commands or for when scripting should not bother the user. They may include @lisp @code{'invisible} non-script command (@samp{@code{proof-shell-invisible-command}}) @code{'no-response-display} do not display messages in @strong{response} buffer @code{'no-error-display} do not display errors/take error action @code{'no-goals-display} do not goals in @strong{goals} buffer @code{'proof-tree-show-subgoal} item inserted by the proof-tree package @code{'priority-action} item added via @code{proof-add-to-priority-queue} @end lisp Note that @code{'invisible} does not imply any of the others. If flags are non-empty, interactive cues will be surpressed. (E.g., printing hints). See the functions @samp{@code{proof-start-queue}} and @samp{@code{proof-shell-exec-loop}}. @end defvar In Proof General 4.2 and earlier it was always the case that all items from the queue region were present in @code{proof-action-list}. Because of the new parallel background compilation for Coq, this is no longer the case. Prover specific code may now store items from the queue region somewhere else. To notify generic Proof General about this, it must set @code{proof-second-action-list-active} for the time where some queue items are missing from @code{proof-action-list}. In this case Proof General keeps the proof shell lock and the queue span even in case @code{proof-action-list} gets empty. Coq uses this feature to hold back Require commands and the following text until the asynchronous background compilation finishes. @c TEXI DOCSTRING MAGIC: proof-second-action-list-active @defvar proof-second-action-list-active Signals that some items are waiting outside of @samp{@code{proof-action-list}}.@* If this is t it means that some items from the queue region are waiting for being processed in a place different from @samp{@code{proof-action-list}}. In this case Proof General must behave as if @samp{@code{proof-action-list}} would be non-empty, when it is, in fact, empty. This is used, for instance, for parallel background compilation for Coq: The Require command and the following items are not put into @samp{@code{proof-action-list}} and are stored somewhere else until the background compilation finishes. Then those items are put into @samp{@code{proof-action-list}} for getting processed. @end defvar @c TEXI DOCSTRING MAGIC: pg-subterm-anns-use-stack @defvar pg-subterm-anns-use-stack Choice of syntax tree encoding for terms. If nil, prover is expected to make no optimisations. If non-nil, the pretty printer of the prover only reports local changes. For Coq 6.2, use t. @end defvar The function @code{proof-shell-start} is used to initialise a shell buffer and the associated buffers. @c TEXI DOCSTRING MAGIC: proof-shell-start @deffn Command proof-shell-start Initialise a shell-like buffer for a proof assistant.@* Does nothing if proof assistant is already running. Also generates goal and response buffers. If @samp{@code{proof-prog-name-ask}} is set, query the user for the process command. @end deffn The function @code{proof-shell-kill-function} performs the converse function of shutting things down; it is used as a hook function for @code{kill-buffer-hook}. Then no harm occurs if the user kills the shell directly, or if it is done more cautiously via @code{proof-shell-exit}. The function @code{proof-shell-restart} allows a less drastic way of restarting scripting, other than killing and restarting the process. @c TEXI DOCSTRING MAGIC: proof-shell-kill-function @defun proof-shell-kill-function Function run when a proof-shell buffer is killed.@* Try to shut down the proof process nicely and clear locked regions and state variables. Value for @samp{@code{kill-buffer-hook}} in shell buffer, called by @samp{@code{proof-shell-bail-out}} if process exits. @end defun @c TEXI DOCSTRING MAGIC: proof-shell-exit @deffn Command proof-shell-exit &optional dont-ask Query the user and exit the proof process. This simply kills the @samp{@code{proof-shell-buffer}} relying on the hook function @samp{@code{proof-shell-kill-function}} to do the hard work. If optional argument @var{dont-ask} is non-nil, the proof process is terminated without confirmation. The kill function uses @samp{-quit-timeout} as a timeout to wait after sending @samp{@code{proof-shell-quit-cmd}} before rudely killing the process. This function should not be called if @samp{@code{proof-shell-exit-in-progress}} is t, because a recursive call of @samp{@code{proof-shell-kill-function}} will give strange errors. @end deffn @c TEXI DOCSTRING MAGIC: proof-shell-bail-out @defun proof-shell-bail-out process event Value for the process sentinel for the proof assistant @var{process}.@* If the proof assistant dies, run @samp{@code{proof-shell-kill-function}} to cleanup and remove the associated buffers. The shell buffer is left around so the user may discover what killed the process. @var{event} is the string describing the change. @end defun @c TEXI DOCSTRING MAGIC: proof-shell-restart @deffn Command proof-shell-restart Clear script buffers and send @samp{@code{proof-shell-restart-cmd}}.@* All locked regions are cleared and the active scripting buffer deactivated. If the proof shell is busy, an interrupt is sent with @samp{@code{proof-interrupt-process}} and we wait until the process is ready. The restart command should re-synchronize Proof General with the proof assistant, without actually exiting and restarting the proof assistant process. It is up to the proof assistant how much context is cleared: for example, theories already loaded may be "cached" in some way, so that loading them the next time round only performs a re-linking operation, not full re-processing. (One way of caching is via object files, used by Coq). @end deffn @c @c INPUT @c @subsection Input to the shell Input to the proof shell via the queue region is managed by the functions @code{proof-extend-queue} and @code{proof-shell-exec-loop}. @c TEXI DOCSTRING MAGIC: proof-extend-queue @defun proof-extend-queue end queueitems Extend the current queue with @var{queueitems}, queue end @var{end}.@* To make sense, the commands should correspond to processing actions for processing a region from (buffer-queue-or-locked-end) to @var{end}. The queue mode is set to @code{'advancing} @end defun @c TEXI DOCSTRING MAGIC: proof-extend-queue @defun proof-extend-queue end queueitems Extend the current queue with @var{queueitems}, queue end @var{end}.@* To make sense, the commands should correspond to processing actions for processing a region from (buffer-queue-or-locked-end) to @var{end}. The queue mode is set to @code{'advancing} @end defun @vindex proof-action-list @c TEXI DOCSTRING MAGIC: proof-shell-exec-loop @defun proof-shell-exec-loop Main loop processing the @samp{@code{proof-action-list}}, called from shell filter. @samp{@code{proof-action-list}} contains a list of (@var{span} @var{command} @var{action} [FLAGS]) lists. If this function is called with a non-empty @samp{@code{proof-action-list}}, the head of the list is the previously executed command which succeeded. We execute the callback (@var{action} @var{span}) on the first item, then (@var{action} @var{span}) on any following items which have null as their cmd components. If a there is a next command after that, send it to the process. If the action list becomes empty, unlock the process and remove the queue region. The return value is non-nil if the action list is now empty or contains only invisible elements for Prooftree synchronization. @end defun Input is actually inserted into the shell buffer and sent to the process by the low-level function @code{proof-shell-insert}. @c TEXI DOCSTRING MAGIC: proof-shell-insert @defun proof-shell-insert strings action &optional scriptspan Insert @var{strings} at the end of the proof shell, call @samp{@code{scomint-send-input}}. @var{strings} is a list of strings (which will be concatenated), or a single string. The @var{action} argument is a symbol which is typically the name of a callback for when each string has been processed. This calls @samp{@code{proof-shell-insert-hook}}. The arguments @var{action} and @var{scriptspan} may be examined by the hook to determine how to modify the string variable (exploiting dynamic scoping) which will be the command actually sent to the shell. Note that the hook is not called for the empty (null) string or a carriage return. We strip the string of carriage returns before inserting it and updating @samp{@code{proof-marker}} to point to the end of the newly inserted text. Do not use this function directly, or output will be lost. It is only used in @samp{@code{proof-add-to-queue}} when we start processing a queue, and in @samp{@code{proof-shell-exec-loop}}, to process the next item. @end defun When Proof General is processing a queue of commands, the lock is managed using a couple of utility functions. You should not need to use these directly. @c TEXI DOCSTRING MAGIC: proof-grab-lock @defun proof-grab-lock &optional queuemode Grab the proof shell lock, starting the proof assistant if need be.@* Runs @samp{@code{proof-state-change-hook}} to notify state change. If @var{queuemode} is supplied, set the lock to that value. @end defun @c TEXI DOCSTRING MAGIC: proof-release-lock @defun proof-release-lock Release the proof shell lock. Clear @samp{@code{proof-shell-busy}}. @end defun @c @c OUTPUT @c @subsection Output from the shell Two main functions deal with output, @code{proof-shell-classify-output} and @code{proof-shell-process-urgent-message}. In effect we consider the output to be two streams intermingled: the "urgent" messages which have "eager" annotations, as well as the ordinary ruminations from the prover. The idea is to conceal as much irrelevant information from the user as possible; only the remaining output between prompts and after the last urgent message will be a candidate for the goal or response buffer. The internal variable @code{proof-shell-urgent-message-marker} tracks the last urgent message seen. When output is grabbed from the prover process, the first action is to strip spurious carriage return characters from the end of lines, if @code{proof-shell-strip-crs-from-output} requires it. Then the output is stored into @code{proof-shell-last-output}, and its type is stored in @code{proof-shell-last-output-kind}. Output which is deferred or possibly discarded until the queue is empty is copied into @code{proof-shell-delayed-output}, with type @code{proof-shell-delayed-output-kind}. A record of the last prompt seen from the prover process is also kept, in @code{proof-shell-last-prompt}. @c TEXI DOCSTRING MAGIC: proof-shell-strip-crs-from-output @defvar proof-shell-strip-crs-from-output If non-nil, remove carriage returns (^M) at the end of lines from output.@* This is enabled for cygwin32 systems by default. You should turn it off if you don't need it (slight speed penalty). @end defvar @c TEXI DOCSTRING MAGIC: proof-shell-last-prompt @defvar proof-shell-last-prompt A raw record of the last prompt seen from the proof system.@* This is the string matched by @samp{@code{proof-shell-annotated-prompt-regexp}}. @end defvar @c TEXI DOCSTRING MAGIC: proof-shell-last-output @defvar proof-shell-last-output A record of the last string seen from the proof system.@* This is raw string, for internal use only. @end defvar @c TEXI DOCSTRING MAGIC: proof-shell-last-output-kind @defvar proof-shell-last-output-kind A symbol denoting the type of the last output string from the proof system.@* Specifically: @lisp @code{'interrupt} An interrupt message @code{'error} An error message @code{'loopback} A command sent from the PA to be inserted into the script @code{'response} A response message @code{'goals} A goals (proof state) display @code{'systemspecific} Something specific to a particular system, -- see @samp{@code{proof-shell-handle-output-system-specific}} @end lisp The output corresponding to this will be in @samp{@code{proof-shell-last-output}}. See also @samp{@code{proof-shell-proof-completed}} for further information about the proof process output, when ends of proofs are spotted. This variable can be used for instance specific functions which want to examine @samp{@code{proof-shell-last-output}}. @end defvar @c TEXI DOCSTRING MAGIC: proof-shell-last-output-kind @defvar proof-shell-last-output-kind A symbol denoting the type of the last output string from the proof system.@* Specifically: @lisp @code{'interrupt} An interrupt message @code{'error} An error message @code{'loopback} A command sent from the PA to be inserted into the script @code{'response} A response message @code{'goals} A goals (proof state) display @code{'systemspecific} Something specific to a particular system, -- see @samp{@code{proof-shell-handle-output-system-specific}} @end lisp The output corresponding to this will be in @samp{@code{proof-shell-last-output}}. See also @samp{@code{proof-shell-proof-completed}} for further information about the proof process output, when ends of proofs are spotted. This variable can be used for instance specific functions which want to examine @samp{@code{proof-shell-last-output}}. @end defvar @c TEXI DOCSTRING MAGIC: proof-shell-delayed-output-start @defvar proof-shell-delayed-output-start A record of the start of the previous output in the shell buffer.@* The previous output is held back for processing at end of queue. @end defvar @c TEXI DOCSTRING MAGIC: proof-shell-delayed-output-end @defvar proof-shell-delayed-output-end A record of the start of the previous output in the shell buffer.@* The previous output is held back for processing at end of queue. @end defvar @c TEXI DOCSTRING MAGIC: proof-shell-delayed-output-flags @defvar proof-shell-delayed-output-flags A copy of the @samp{@code{proof-action-list}} flags for @samp{proof-shell-delayed-output}. @end defvar @vindex proof-action-list @c TEXI DOCSTRING MAGIC: proof-shell-handle-immediate-output @defun proof-shell-handle-immediate-output cmd start end flags See if the output between @var{start} and @var{end} must be dealt with immediately.@* To speed up processing, PG tries to avoid displaying output that the user will not have a chance to see. Some output must be handled immediately, however: these are errors, interrupts, goals and loopbacks (proof step hints/proof by pointing results). In this function we check, in turn: @lisp @samp{@code{proof-shell-interrupt-regexp}} @samp{@code{proof-shell-error-regexp}} @samp{@code{proof-shell-proof-completed-regexp}} @samp{@code{proof-shell-result-start}} @end lisp Other kinds of output are essentially display only, so only dealt with if necessary. To extend this, set @samp{@code{proof-shell-handle-output-system-specific}}, which is a hook to take particular additional actions. This function sets variables: @samp{@code{proof-shell-last-output-kind}}, and the counter @samp{@code{proof-shell-proof-completed}} which counts commands after a completed proof. @end defun @c TEXI DOCSTRING MAGIC: proof-shell-handle-delayed-output @defun proof-shell-handle-delayed-output Display delayed goals/responses, when queue is stopped or completed.@* This function handles the cases of @samp{proof-shell-output-kind} which are not dealt with eagerly during script processing, namely @code{'response} and @code{'goals} types. This is useful even with empty delayed output as it will empty the buffers. The delayed output is in the region [@code{proof-shell-delayed-output-start},@code{proof-shell-delayed-output-end}]. If no goals classified output is found, the whole output is displayed in the response buffer. If goals output is found, the last matching instance, possibly bounded by @samp{@code{proof-shell-end-goals-regexp}}, will be displayed in the goals buffer (and may be further analysed by Proof General). Any output that appears @strong{before} the last goals output (but after messages classified as urgent, see @samp{@code{proof-shell-filter}}) will also be displayed in the response buffer. For example, if @var{output} has this form: @lisp @var{messsage-1} @var{goals-1} @var{message-2} @var{goals-2} @var{junk} @end lisp then @var{goals-2} will be displayed in the goals buffer, and @var{message-2} in the response buffer. @var{junk} will be ignored. Notice that the above alternation (and separation of @var{junk}) can only be distinguished if both @samp{@code{proof-shell-start-goals-regexp}} and @samp{@code{proof-shell-end-goals-regexp}} are set. With just the start goals regexp set, @var{goals-2} @var{junk} will appear in the goals buffer and no response output would occur. @lisp @end lisp The goals and response outputs are copied into @samp{@code{proof-shell-last-goals-output}} and @samp{@code{proof-shell-last-response-output}} respectively. The value returned is the value for @samp{@code{proof-shell-last-output-kind}}, i.e., @code{'goals} or @code{'response}. @end defun @c TEXI DOCSTRING MAGIC: proof-shell-urgent-message-marker @defvar proof-shell-urgent-message-marker Marker in proof shell buffer pointing to end of last urgent message. @end defvar @c TEXI DOCSTRING MAGIC: proof-shell-process-urgent-message @defun proof-shell-process-urgent-message start end Analyse urgent message between @var{start} and @var{end} for various cases. Cases are: @strong{trace} output, included/retracted files, cleared goals/response buffer, variable setting, xml-encoded @var{pgip} response, theorem dependency message or interactive output indicator. If none of these apply, display the text between @var{start} and @var{end}. The text between @var{start} and @var{end} should be a string that starts with text matching @samp{@code{proof-shell-eager-annotation-start}} and ends with text matching @samp{@code{proof-shell-eager-annotation-end}}. @end defun The main processing point which triggers other actions is @code{proof-shell-filter}. It is called from @code{proof-shell-filter-wrapper}, which itself is called from an ordinary Emacs process filter inside the simplified @code{comint} library that is distributed with Proof General (in @code{lib/scomint.el}). @c TEXI DOCSTRING MAGIC: proof-shell-filter @defun proof-shell-filter Master filter for the proof assistant shell-process.@* A function for @samp{@code{scomint-output-filter-functions}}. Deal with output and issue new input from the queue. This is an important internal function. The output must be collected from @samp{@code{proof-shell-buffer}} for the following reason. This function might block inside @samp{@code{process-send-string}} when sending input to the proof assistant or to prooftree. In this case Emacs might call the process filter again while the previous instance is still running. @samp{@code{proof-shell-filter-wrapper}} detects and delays such calls but does not buffer the output. Handle urgent messages first. As many as possible are processed, using the function @samp{@code{proof-shell-process-urgent-messages}}. If a prompt is seen, run @samp{@code{proof-shell-filter-manage-output}} on the output between the new prompt and the last input (position of @samp{@code{proof-marker}}) or the last urgent message (position of @samp{@code{proof-shell-urgent-message-marker}}), whichever is later. For example, in this case: @lisp PROMPT> @var{input} @var{output-1} @var{urgent-message-1} @var{output-2} @var{urgent-message-2} @var{output-3} PROMPT> @end lisp @samp{@code{proof-marker}} points after @var{input}. @samp{@code{proof-shell-urgent-message-marker}} points after @var{urgent-message-2}, after both urgent messages have been processed by @samp{@code{proof-shell-process-urgent-messages}}. Urgent messages always processed; they are intended to correspond to informational notes that the prover makes to inform the user or interface on progress. In this case, the ordinary outputs @var{output-1} and @var{output-2} are ignored; only @var{output-3} will be processed by @samp{@code{proof-shell-filter-manage-output}}. Error or interrupt messages are expected to terminate an interactive output and appear last before a prompt and will always be processed. Error messages and interrupt messages are therefore @strong{not} considered as urgent messages. The first time that a prompt is seen, @samp{@code{proof-marker}} is initialised to the end of the prompt. This should correspond with initializing the process. After that, @samp{@code{proof-marker}} is only changed when input is sent in @samp{@code{proof-shell-insert}}. @end defun @c TEXI DOCSTRING MAGIC: proof-shell-filter-manage-output @defun proof-shell-filter-manage-output start end Subroutine of @samp{@code{proof-shell-filter}} for output between @var{start} and @var{end}. First, we invoke @samp{@code{proof-shell-handle-immediate-output}} which classifies and handles output that must be dealt with immediately. Other output (user display) is only displayed when the proof action list becomes empty, to avoid a confusing rapidly changing output that slows down processing. After processing the current output, the last step undertaken by the filter is to send the next command from the queue. @end defun @c TEXI DOCSTRING MAGIC: proof-shell-filter-wrapper @defun proof-shell-filter-wrapper str-do-not-use Wrapper for @samp{@code{proof-shell-filter}}, protecting against parallel calls.@* In Emacs a process filter function can be called while the same filter is currently running for the same process, for instance, when the filter blocks on I/O. This wrapper protects the main entry point, @samp{@code{proof-shell-filter}} against such parallel, overlapping calls. The argument @var{str-do-not-use} contains the most recent output, but is discarded. @samp{@code{proof-shell-filter}} collects the output from @samp{@code{proof-shell-buffer}} (where it is inserted by @samp{@code{scomint-output-filter}}), relieving this function from the task to buffer the output that arrives during parallel, overlapping calls. @end defun @c @c SECTION: Debugging @c @node Debugging @section Debugging @cindex debugging @c FIXME: better to have general hints on Elisp earlier, plus some @c links to helpful docs. To debug Proof General, it may be helpful to set the configuration variable @code{proof-general-debug}. @c TEXI DOCSTRING MAGIC: proof-general-debug @defopt proof-general-debug Non-nil to run Proof General in debug mode.@* This changes some behaviour (e.g. markup stripping) and displays debugging messages in the response buffer. To avoid erasing messages shortly after they're printed, set @samp{@code{proof-tidy-response}} to nil. This is only useful for PG developers. The default value is @code{nil}. @end defopt For more information about debugging Emacs lisp, consult the Emacs Lisp Reference Manual. I recommend using the source-level debugger @code{edebug}. @c @c @c APPENDIX: Plans and Ideas @c @c @node Plans and Ideas @appendix Plans and Ideas This appendix contains some tentative plans and ideas for improving Proof General. This appendix is no longer extended: instead we keep a list of Proof General projects on the web, and forthcoming plans and ideas in the @file{TODO} and @file{todo} files included in the ordinary and developers PG distributions, respectively. Once the items mentioned below are implemented, they will be removed from here. Please send us contributions to our wish lists, or better still, an offer to implement something from them! @menu * Proof by pointing and similar features:: * Granularity of atomic command sequences:: * Browser mode for script files and theories:: @end menu @node Proof by pointing and similar features @section Proof by pointing and similar features @cindex proof by pointing This is a note by David Aspinall about proof by pointing and similar features. Proof General already supports proof by pointing, and experimental support was provided in LEGO. We would like to extend this support to other proof assistants. Unfortunately, proof by pointing requires rather heavy support from the proof assistant. There are two aspects to the support: @itemize @bullet @item term structure mark-up @item proof by pointing command generation @end itemize Term structure mark-up is useful in itself: it allows the user to explore the structure of a term using the mouse (the smallest subexpression that the mouse is over is highlighted), and easily copy subterms from the output to a proof script. Command generation for proof by pointing is usually specific to a particular logic in use, if we hope to generate a good proof command unambiguously for any particular click. However, Proof General could easily be generalised to offer the user a context-sensitive choice of next commands to apply, which may be more useful in practice, and a worthy addition to Proof General. Implementors of new proof assistants should be encouraged to consider supporting term-structure mark up from the start. Command generation should be something that the logic-implementor can specify in some way. Of the supported provers, we can certainly hope for proof-by-pointing support from Coq, since the CtCoq proof-by-pointing code has been moved into the Coq kernel lately. I hope the Coq community can encourage somebody to do this. @node Granularity of atomic command sequences @section Granularity of atomic command sequences @c @cindex Granularity of Atomic Sequences @c @cindex Retraction @c @cindex Goal @cindex ACS (Atomic Command Sequence) This is a proposal by Thomas Kleymann for generalising the way Proof General handles sequences of proof commands (see @i{Goal-save sequences} in the user manual), particularly to make retraction more flexible. The blue region of a script buffer contains the initial segment of the proof script which has been processed successfully. It consists of atomic sequences of commands (ACS). Retraction is supported to the beginning of every ACS. By default, every command is an ACS. But the granularity of atomicity should be able to be adjusted. This is essential when arbitrary retraction is not supported. Usually, after a theorem has been proved, one may only retract to the start of the goal. One needs to mark the proof of the theorem as an ACS. At present, support for goal-save sequences (see @i{Goal-save sequences} in the user manual), has been hard wired. No other ACS are currently supported. We propose the following to overcome this deficiency: @vtable @code @item proof-atomic-sequents-list is a list of instructions for setting up ACSs. Each instruction is a list of the form @code{(@var{end} @var{start} &optional @var{forget-command})}. @var{end} is a regular expression to recognise the last command in an ACS. @var{start} is a function. Its input is the last command of an ACS. Its output is a regular expression to recognise the first command of the ACS. It is evaluated once and, starting with the command matched by @var{end}, the output is successively matched against previously processed commands until a match occurs (or the beginning of the current buffer is reached). The region determined by (@var{start},@var{end}) is locked as an ACS. Optionally, the ACS is annotated with the actual command to retract the ACS. This is computed by applying @var{forget-command} to the first and last command of the ACS. For convenience one might also want to allow @var{start} to be the symbol @samp{t} as a convenient short-hand for @code{'(lambda (str) ".")} which always matches. @end vtable @node Browser mode for script files and theories @section Browser mode for script files and theories This is a proposal by David Aspinall for a browser window. A browser window should provide support for browsing script files and theories. We should be able to inspect data in varying levels of detail, perhaps using outlining mechanisms. For theories, it would be nice to query the running proof assistant. This may require support from the assistant in the form of output which has been specially marked-up with an SGML like syntax, for example. A browser would be useful to: @itemize @bullet @item Provide impoverished proof assistants with a browser @item Extend the uniform interface of Proof General to theory browsing @item Interact closely with proof script writing @end itemize The last point is the most important. We should be able to integrate a search mechanism for proofs of similar theorems, theorems containing particular constants, etc. @c @c @c APPENDIX: Demonstration instantiation for Isabelle @c @c @node Demonstration Instantiations @appendix Demonstration Instantiations This appendix contains the code for the two demonstration instantiations of Proof General, for Isabelle. These instantiations make an almost-bare minimum of settings to get things working. To add embellishments, you should refer to the instantiations for other systems distributed with Proof General. @menu * demoisa-easy.el:: * demoisa.el:: @end menu @node demoisa-easy.el @section demoisa-easy.el @lisp @c FIXME: MAGIC NEEDED TO INCLUDE FILE VERBATIM @c @includeverbatim ../demoisa/demoisa-easy.el ;; demoisa-easy.el Example Proof General instance for Isabelle ;; ;; Copyright (C) 1999 LFCS Edinburgh. ;; ;; Author: David Aspinall ;; ;; $Id$ ;; ;; This is an alternative version of demoisa.el which uses the ;; proof-easy-config macro to do the work of declaring derived modes, ;; etc. ;; ;; See demoisa.el and the Proof General manual for more documentation. ;; ;; To test this file you must rename it demoisa.el. ;; (require 'proof-easy-config) ; easy configure mechanism (proof-easy-config 'demoisa "Isabelle Demo" proof-prog-name "isabelle" proof-terminal-string ";" proof-script-comment-start "(*" proof-script-comment-end "*)" proof-goal-command-regexp "^Goal" proof-save-command-regexp "^qed" proof-goal-with-hole-regexp "qed_goal \"\\(\\(.*\\)\\)\"" proof-save-with-hole-regexp "qed \"\\(\\(.*\\)\\)\"" proof-non-undoables-regexp "undo\\|back" proof-goal-command "Goal \"%s\";" proof-save-command "qed \"%s\";" proof-kill-goal-command "Goal \"PROP no_goal_set\";" proof-showproof-command "pr()" proof-undo-n-times-cmd "pg_repeat undo %s;" proof-auto-multiple-files t proof-shell-cd-cmd "cd \"%s\"" proof-shell-interrupt-regexp "Interrupt" proof-shell-start-goals-regexp "Level [0-9]" proof-shell-end-goals-regexp "val it" proof-shell-quit-cmd "quit();" proof-assistant-home-page "http://www.cl.cam.ac.uk/Research/HVG/Isabelle/" proof-shell-annotated-prompt-regexp "^\\(val it = () : unit\n\\)?ML>? " proof-shell-error-regexp "\\*\\*\\*\\|^.*Error:\\|^uncaught exception \\|^Exception- " proof-shell-init-cmd "fun pg_repeat f 0 = () | pg_repeat f n = (f(); pg_repeat f (n-1));" proof-shell-proof-completed-regexp "^No subgoals!" proof-shell-eager-annotation-start "^\\[opening \\|^###\\|^Reading") (provide 'demoisa) @end lisp @node demoisa.el @section demoisa.el @lisp @c FIXME: MAGIC NEEDED TO INCLUDE FILE VERBATIM @c @includeverbatim ../demoisa/demoisa.el ;; demoisa.el Example Proof General instance for Isabelle ;; ;; Copyright (C) 1999 LFCS Edinburgh. ;; ;; Author: David Aspinall ;; ;; $Id$ ;; ;; ================================================================= ;; ;; See README in this directory for an introduction. ;; ;; Basic configuration is controlled by one line in `proof-site.el'. ;; It has this line in proof-assistant-table: ;; ;; (demoisa "Isabelle Demo" "\\.ML$") ;; ;; From this it loads this file "demoisa/demoisa.el" whenever ;; a .ML file is visited, and sets the mode to `demoisa-mode' ;; (defined below). ;; ;; I've called this instance "Isabelle Demo Proof General" just to ;; avoid confusion with the real "Isabelle Proof General" in case the ;; demo gets loaded by accident. ;; ;; To make the line above take precedence over the real Isabelle mode ;; later in the table, set PROOFGENERAL_ASSISTANTS=demoisa in the ;; shell before starting Emacs (or customize proof-assistants). ;; (require 'proof) ; load generic parts ;; ======== User settings for Isabelle ======== ;; ;; Defining variables using customize is pretty easy. ;; You should do it at least for your prover-specific user options. ;; ;; proof-site provides us with two customization groups ;; automatically: (based on the name of the assistant) ;; ;; 'isabelledemo - User options for Isabelle Demo Proof General ;; 'isabelledemo-config - Configuration of Isabelle Proof General ;; (constants, but may be nice to tweak) ;; ;; The first group appears in the menu ;; ProofGeneral -> Advanced -> Customize -> Isabelledemo ;; The second group appears in the menu: ;; ProofGeneral -> Internals -> Isabelledemo config ;; (defcustom isabelledemo-prog-name "isabelle" "*Name of program to run Isabelle." :type 'file :group 'isabelledemo) (defcustom isabelledemo-web-page "http://www.cl.cam.ac.uk/Research/HVG/isabelle.html" "URL of web page for Isabelle." :type 'string :group 'isabelledemo-config) ;; ;; ======== Configuration of generic modes ======== ;; (defun demoisa-config () "Configure Proof General scripting for Isabelle." (setq proof-terminal-string ";" proof-script-comment-start "(*" proof-script-comment-end "*)" proof-goal-command-regexp "^Goal" proof-save-command-regexp "^qed" proof-goal-with-hole-regexp "qed_goal \"\\(\\(.*\\)\\)\"" proof-save-with-hole-regexp "qed \"\\(\\(.*\\)\\)\"" proof-non-undoables-regexp "undo\\|back" proof-undo-n-times-cmd "pg_repeat undo %s;" proof-showproof-command "pr()" proof-goal-command "Goal \"%s\";" proof-save-command "qed \"%s\";" proof-kill-goal-command "Goal \"PROP no_goal_set\";" proof-assistant-home-page isabelledemo-web-page proof-auto-multiple-files t)) (defun demoisa-shell-config () "Configure Proof General shell for Isabelle." (setq proof-shell-annotated-prompt-regexp "^\\(val it = () : unit\n\\)?ML>? " proof-shell-cd-cmd "cd \"%s\"" proof-shell-interrupt-regexp "Interrupt" proof-shell-error-regexp "\\*\\*\\*\\|^.*Error:\\|^uncaught exception \\|^Exception- " proof-shell-start-goals-regexp "Level [0-9]" proof-shell-end-goals-regexp "val it" proof-shell-proof-completed-regexp "^No subgoals!" proof-shell-eager-annotation-start "^\\[opening \\|^###\\|^Reading" proof-shell-init-cmd ; define a utility function, in a lib somewhere? "fun pg_repeat f 0 = () | pg_repeat f n = (f(); pg_repeat f (n-1));" proof-shell-quit-cmd "quit();")) ;; ;; ======== Defining the derived modes ======== ;; ;; The name of the script mode is always -script, ;; but the others can be whatever you like. ;; ;; The derived modes set the variables, then call the ;; -config-done function to complete configuration. (define-derived-mode demoisa-mode proof-mode "Isabelle Demo script" nil (demoisa-config) (proof-config-done)) (define-derived-mode demoisa-shell-mode proof-shell-mode "Isabelle Demo shell" nil (demoisa-shell-config) (proof-shell-config-done)) (define-derived-mode demoisa-response-mode proof-response-mode "Isabelle Demo response" nil (proof-response-config-done)) (define-derived-mode demoisa-goals-mode proof-goals-mode "Isabelle Demo goals" nil (proof-goals-config-done)) ;; The response buffer and goals buffer modes defined above are ;; trivial. In fact, we don't need to define them at all -- they ;; would simply default to "proof-response-mode" and "pg-goals-mode". ;; A more sophisticated instantiation might set font-lock-keywords to ;; add highlighting, or some of the proof by pointing markup ;; configuration for the goals buffer. (provide 'demoisa) @end lisp @node Function Index @unnumbered Function and Command Index @printindex fn @node Variable Index @unnumbered Variable and User Option Index @printindex vr @c Nothing in this one! @c @node Keystroke Index @c @unnumbered Keystroke Index @c @printindex ky @node Concept Index @unnumbered Concept Index @printindex cp @page @contents @bye PG-4.5/doc/ProofGeneral-image.jpg000066400000000000000000001101311426357011200166000ustar00rootroot00000000000000JFIFC       C "  b  !1AQ "aq2B#RbrC$3DS4Tcs%'5V&6FUdeft=!1A"Qa2q3#BR$4Cbr ?ښ" """ """ """ """ """ """ """ """ """ ".cx#[L\ed,{@@vh} O;Hzoin$x0r9EmN#Nr;FIS,twPE%=Ѵa󶢩{-rHYO3mQYcpA/@]%R9ʵ8zRKnz$q4W`)w;E[o4w{a6D-ɒ=ޤv[m8­ /eJ&\"opP=Y7=j!5ĭ տUӿhN?U{OW'(.ⶫ}݅ӏ rۼ@%?Ң7/IvIT[OlvkZChl߯PGsa )GĨ93nO6[mű^rJcl?t^$AAN-pL8C1e}ۀaL8ſ+G4|jHe8foƳ/QG0c63yJFmfrH5wO/24cF{7)1X`?Xљp@3m3?ŏtpP*h`|MNJ쾕^/ 6[ڤ|̵z c6 %¨Ҭ zotlt+~3IʪVwhjLamN;[.8n3H6]G%}# s5昽@5&ov#p#]c(K֏b-^nPgY% ?W#|k頺ۧ׮:@6lvǙe 輓i֧WВfW"ׅg㚗EnM9/Y9}{Gv,vµ7?uS5>s?,h hSS՗EWןDۢE wS boAannۮI֩?JLR_NMOAyD\!D@DDD@DDp.[u’;W=SiM3)}mnİ.mvÇ٘8ԛ]"p7oI9c)=SUY*Ѽˇz<!klfIt4ρq.-iFi[x |9(|N[xs>(-`x},ˮ6K30Ժ'4AU+OI[QtxP n-:G~C@ͣzfZg}I[,n%4_K._P- |.n=ji5%dDY2DDD@DDD@DDD@DDu>Elq˦Szl9kjdq68\٪kXէ W WepDZo 5k[ݵ^k}bGR5q'h=̌>Jh_c,23iY2? V^֫}ה-""C""" """ ""{#K{^Ȁ*rWn?4Jy;I N؍mntU܇VQ\`u5},SŠEqY6d;3HL5^Ӹ:Y> ?-K5+s>uޕ̩>$ѽ<|拏TҪO"4WFc&ahiV/Җ4Lw,Yb>mJS(jbw{$o(?IzCMqһS7Ťw=Ůj OF^[qJu{4TyHujjM;FSbYH"k%dܯ5pA槖" """ """ """ QLYI)&+}0zv-qvsc?s.H9x#yt?ή( l1X֏ "LJ""" """ """ """ "Yٲ@h0oTccwՀ#w"$͆I{{7HGOVy,X6.F;>nʇvZIJ3|?/Q)g%e8ͻ,KiKo,?E/eiEi{Y L>?ZYՍw8+ bj ]s $n'DޠӦr\ѱW~՗<+H/>kU4$uXǥΊ5NggBJ5zYUsS8N6Iܝy. >n.~/xMT%FG><IuQ"kB…ya[OTƌh`#- L f|6>H,Zk,3i 7UgwB)Np8 %iʣ3GU2 ݙ>\nq=|/1M ,{ծElW#o8mBh*82+Mbwv}W?:T޶iAĸ:u-%ѕQpJ*tSC+ydVkҵ-DD0DDD@DDD@DDGQpxXh{QГO؇)W7o>Iې,`|:cr]:mzէu^u1zz?< Ğ5[s򷪵/J[S0m{8YVs3֍~\ô9WҔ9%正~cKVk@_u~}(" )7u4yݢEg\+"VX\-qfe:z͞gxJg fEvSTRYwԳ hF׿yiz=v =\*?扢(u6tïB+IXUC'IFͨ+woWvk&H thuIQ%i?bM5883",""" """ X73=k Dv8'Z\`5ڌZa.@9<>#qVq˗X-F9pu'nbxݮ"3cty]X;F+mrG[qSPȩt8w^i>{moYnWo>O^BDE4""" """ ,GFZ8K\{8b]K޶0LnOe@~w/MuѬZ ՎZvE8y`gS#zO^NݝWHmUB<֗-EU#d{zܒc|Vϳm Ԕ*˜[㧛8!ӿ. wo|9򢹶WAe 6z jww)s٣EU~捱WJj&q+Oĕ\;5!PߨdSGWH_+yw>|`@ȡa=nJvJzW&\Zj>>'ZG[X)_.Ǻ&Ew_emUe>$,>ǚ8-x~Rҭ@>mq?d:aQ;)|"8Kd>n^fݱ^ok.8嬻|celt!lU_U;wJӷSaGEOH"dc^Z_%KD_5U\yzm$arVu;K#񬏳X=Hw{U+8^xmk]MŠK%` PItD~pWv7輣xòF)ylY5j{ RBrqWq^ztz}FغMm@R>j9E.ImNzY` WCG]9=XKӏOv?OAs]!*?Z)ܹJqҫ+5)-]JI :EPOOѷvS vP ~Od4Q FW Z+;Tdc :r%JS5D@DDD@=n+kZ MpC#ΞI JK,d6 <Xi{OmWI)7f=02Ku\HFF}xs~Jfg Ƨz O,elzcD@DDD@DDD@𮢤QOn'C4R7v +F%xPG#y~w۴+~jzIj ٨DNmcw|=9`Z \_SJX8Kfj8oqNw~qTSNY}NLE|ypIaCMufpݰ})]7 >)Sˡ_+[w' i>~AsmNǾ3ik曩hY#GGlr6)2=d>Gy K&guZb q/`q*4ƯݩKߴfNRXqf uޞͦWk'Tj.}}wCp! 7[L[5R\sɩA@ة=~,I i `ٱFBOid2d3$gD]7S@[[1ZOC}wx nld'״iFi>rӛk^ROø :jmV:x;6(^\|ܲ4KGML&=gm'ܺ;f/\`lmJ7 ~J H/s&gͱxޥEJfio  Ifj-hlxI?s>ӻ o.iu9W9Ww/Ҍhǧ߮EUXҬrsa\ײp34yXn(B擥Qe2-yUi4lcQ4 x5`;iuNOg"]Բ||ΪYon0q񃿪NLvǫ~K9Ubx+P2[E炮mOz)T.r={g5ԩ68Imy<q%e%t51O v~a|mtU:xM^ ]>_n{3Os )UۺkmFϝ~YܮZyY/754_}KAnB8NHS@" ""Ie{+~][ ݟxݧ5go^qxk5iwQݩ m;u4i߯:å ˨UHjj(tU-=Lm+ͺӊJΊi(396| [㎜޿\RW}I8{AzZK\ A(JIK)(שo5REøfTl JkE V ԼJ|"z 1tTp?b'6]Gdul4>A7mG?,2u aEMW c匯Ş I,Uߚ63qc4:ӖOcܻ[{m%ɣa~[.%K{Y5I\~IS&aGt+V(9?wՓƥГ~z4R0Z*kbߥ]S 4q{ؼŢIkjd?5[V:uՑ=-==#TkXʿW^bz*#Ĺh˒tyQabY℥.yVtHݠۚ'OFo֪q?ghaɻ]y<|VG^Lu.d_uˁ[پy\.=/ڊU jQ0qu* yClr:LڈnϩoGCcܽ4;S4JHnͭʪ[shΧhq٭nu߯fij}&68HJ{q.e+{ZxROy߇7U3-c׎j .ꢊUL^m#DcF!k~A"c]߶7]SyqWڻے=hZ>vinܧAH־y7$=]ex= J#ц/X>uØb3ha#+b%4jٓ{::]m'`Zw'$oo*nk'OVV?}Eߊ^+Qk`x{Akv ..}UyTS)E<UB9#xp;G+@=k,n(W:6IlC TcYY#7 \ $SRJXs]q\k._9ϕ"-MB" "" m ڤa^cSѶGoF#w´zna1>OJo/!vC翙^f<8놬H_Ydc:d?Y7p:XSlH_zZZ<1Xw=6v3vzJ_bF+;o=<׃z+Y{^jb=V0օ}mҽOǪ_yӚ~DϫVJ̓9ݰ.o #jrQOdƳJcHRyZA wlu?lۙ՟ў}(w AT8D&G;6"ݹ1[tA?օ}8sW6z{?kX;{v#s (1\nESh; >WSY'C%|yԀ߹cKSUNo ;*)#u:/ ZZ)[|S7uۯ *nOGOI߸>o?旮R Jdgi8|{0w2Jv?xRŃQepnᏻ#g!Ɔ쒃bgl`O=P,poP]\vC[p1*I?GܫZ.r|:_ر3, J5+.pjR([vUlG)/o>$Xg➏ܥ-ê7Ic?}aMnI7-#WE`{#W_IөH&X[ VcDXoFѸ}`GGP \5-U `;UdpϞ.IʦDq^kmSs6J1Yu[Z:+5|~)ךڦtxnz}캓ԒzWkp^rל/%G/;+7R-їZxŧ:gE]h*ucfT/5"ߞ:\{M%8fE5Jz:58huɪ+QlUcOةe5U5d-h7kpsO/|UKVZ?vTο忙-l͝7e}.~9n5DVƔ8+TYt4""" 3=g öGocɸpQns6슪0!v@BxNMuln?',chvyL/[8OnlՊ9#_1!`nʹY wdϥ+|A(=QrJ]iJYKyspOKspo3\u߿WtK.ZpmwOypa)GZsw|A ڪgiA/tT mRX77zځ:Tr|+YJ++Uy se,T2w;s;8},i +fWv^d}H;^¦?hf;/2N4+jCתV;3$wT?^$HZ??`^ Vr1ٲ@>n/Sq?͝oftҏ*'JͼһܨֶڰO*L ~ȭdyT,g6Rл""" """ ^$]×+C֛>ۍo&j?C40>\K]\4tVn n"pZB8 =ZQJ/7c|]n.1]Glmu;O, |KE.Is>BR$/Mgʛ+5kqk͆d?3ԁk4wXg!$tJ­lOnG!s|'#+M/Ңx޹E♝n owzZ2 A B/Ye4660n8%F՗Sij:FXz71e֕Vxޅ%z]}>m^/Y$pFdw;ru-z<8Tpƺ9r<<[Q͙wpûu\34y>D)ﺅ]]授я,OIoo hr""H""" """ ^=YQP\nW*{*Hg{3A; U2OFOpn,e};:1+bx x hWzw qSsZ"讓I3~]T?C .ҲCQHy{]AE9M$e'-]>cVfmt:&ZI=O^¼Yehҭ9vYKLcfq?J?C%#=aohW٬G0^?Yaܣv|KŔYmQ6B|! D(UG\5GSe3))3\zVZvs@}E{8uWQҎ/q-?Nݴ_1F3x `CI?D=w&;m3Eu}[M$*VU݃}Zb~8xt#TÇmq-OZM%P1ךH$E6ggw9؎Oy_jT_e8,tz{pS{{H3ڊ8̐aIJX\s-Ueok:y.EXOHk <,2^(82vs7Mduk%n=7w6-k}nYGgkaj[iG)h#kv'E'+kR3j5r>fioSlySuk9o-kvQpf`)Ǵ #{3nl oë< iÇ|\*/ENs5N5TK&-?YerZ?)^UG~>o6LσrWY`>şk&ZHZO1Jǒ=#|R|ʨ(-|-;w(vOþ%F렣i]F?.A!-w2ORCSOVDMaꊃp\Hw!I3p[X3\7[L7Gܶniu~Hm-kRĸg-h/Lo?r^3<~uHO+KC 6[btQk٠쫊HF$F9)E|kcʤ"^f烝{oI;kTnlonDMf~^!n.,QX*cE}ڡu/wh>aQ¾#zQߥ9-,CٖGo+U8`ɰ-P7l?r׷ W>qG.KH'tHUI`~ily;mU,uu1,Ohs\>G"VZ[uFn56wDH<ǹd}eŬЭ]+hv:KuQYweN _6PsU\;4CNP{ؖovzl͎сVȋi<>悫%w KsZyDwj$9Te)gg忻4!Yl%~I-p)kI_YV}ddSe_x쾛/w',ZJ9XThfoV}!Dh&by9]r֦pu%4,20$FlzH1{"VDjŒoB ǯh :l3H i{ĝ1=iԛ/ްzwVQ@A±Seʗ [PFt9gdk/Q?8xYO5J5f4P9shkY$FpɨybLrjNclF7+9$=ÿrBQ3Z 1л1pv^zdwDzmHU`pwF s/^0tW:},ر g5O5-͚͌O:iD(!5oRo##(*cê[4SkOĬ^(nƞLt z ͛-X'x;H%_\vʭR_FCsWPmV)sfRw/3~D(C/DtT[N#{FeŞ ].Hh+Ӛ]ZHreӧ5h\[Ԕ/bs$ufmovj]Z3oeLc}4j}EŲ<.65;s^ZA]W<jSֺuPҵ3QLxixmF+æ j :]]Ztbv>+u l-ivr)dn%.q%8,Kjg6lC:9ńR;C=C ]%K sAȓ'yuE`Xw;0UUZ+,9٤ݾV9uJ|wk$` #?:Ǩ [llNac`{v]0F=iů,e|6]h4255;0Gz siIivlx3AG9ۺx&Dc,"}YEM 1ߣ q\]&WUkN=[*/ <*N0+du9i(n0C<1VDƏ }„""" """ """ y/1UƊ<'] p譂'?Ю8PQiq)jڄQ˿!ĺw;d ,\U"*~#Qc?E=lNYCcӫZˆM#Þ>]mv$z,|ןin3Y\GyUK~GqSUIzQ}Ћ&&맷)%U\\9;.~Ӽ`:mhCa+X61LjmEm3>5VOt6F^?Z]-HସSuVpUwSCKIN{;py:FG^BmytTǨTw.5fSN@{#=mM@VqIz):}Eu3CM,c7hq'aF 'G?ҵ:w>TɷXMյ)ѵ/- BD@#StCIumzl.RIUL ~gc '5z$p;>iþpkCjުekY`~.z`NuV[L5Sks=T>v5㔖!mkOҩiϭ'5 =mR7QsrOWV#""?8spoHˊl.YQ[AM3cc1ܮ:"QRܱVJS3'׽Oм p٭+tX \yKiNOvoW!CX.v\xpӿڵdOvMN!6-zg(O}W^Gx^?BO._xesz;[}, F4+:?W?+7zX 3FbX{~l`Ɉaz^]ǯm>~y+-z&4qoC3 ):KX'wR6Z:k|QTOz-D(懟[1knp<-A hFB8O=j;D]D@DDD@DDD@DDsR,C(̟7K=ey!sGB?{NaӿimxD004@p-#pzϤhZ=ZS!ܲ ɹ{Uf c.J.\څt:kX21o`' 3l|ʭE P覲3C\tώTKYuZ ٞm>f<[QZdeXu_.`BsZOu-+ F7),s;0fxZ/acq(tzopuWof7rzo&K*'ռ*845TO=ŮiZ;ћ}N)t4s {`Y[~Чph?2M[-,Ѽn*!A+e-! ?{35w$Os;f=Hr Tf5WE=?ΈDDD@Rx|紌qiZ;|?gʱGb5|M- |}n÷59r3h*_SZ6\Է,4r@4. n[Mճ}A:uOr :]5;{H~^0r?2[;р O@ ޳sojc߼_Zޭ|VU6ȹ(,Xu,n5=qNţuY!ƱF9O*AODΛ{1FV|vH>;a|I ݥkcC{S zc-ʺze+>5>oVӌO"t6dB cg=#qjycl^PVq*8ENIwQiבV3"-KPxCtWsS"S[k>B6AյM[Һ.mFEf'[2i&[ڧ|'5K/%%D>j* ~۰@ëxffYt_'r{G) ÕXX<''""ɨDDD@DDD@DDD@Zڿ?U#5IMNR~+m_=58۠ޫvSH6 yaBNR] dUmZƵŧV95ŨZW1} x{\W*qWn;Z*污԰kZ,Ĕо Z|ZAk(z**˚pђT g9wUlA؏z8ZzE-Lyf=Gϟ0֖^ͭ-[f8L!Y["}Uw(>c{FޞH4k 0&=g/7y\>2ĪF\pFbܱӺwdvpڨZguF]N;}N{i$] ɫԽ'=~y̶ZبnS3O|086v5"O .̰W܄5'Ѝ۬;L1^ dEשtkR[EeiR\rEsbKO[#H}ʺ*mx5Qd8cv7ۢt9b|g߭ƕ`uZ.Mq7֟W_?S.?v?j vmd;b*<.TNjgبfx9 D@DDD@DDD@DD*mcLMckzM>4s~R5""N~¦{OLk.lT+nw;Xw[m}6ܮv;PZ>eo6.U :}O*/ݽό@zsos!q^.hקpzngz]5EHI#zp%4SwGn> j#<`.\ƚ۩icWl˭q& 3O4hqTq*B" """ 2 R;ľ7kD0p<r/sX9+(q1PЎX-HϠ֍P S]Aˆ߅D@ؕUlYOܵi;[6M%;̧nµ[ʭjU럩`3XhcN25uuEcwߤ~xJ"-j0٦QվLRHal mdr##w\_x*~Nz!ɿ8қ6o]#6IrtH9]7h>VRcSx) mx=D}fO,\wB'%FɧOuI116kkGo[Z^v܄ w:}cӸ# <TNەq+{'^G|eEwZT̨d-sH 63]'_,>zF/0~\.Um~ƮC8Re/7YwBRT c{z9i|AX%n#E5nz.U:KZeyFI>J3jwYwÞ&]-Z'{N'ku_2jy X.6+B;p;pG 5E=ve qXO#3ft  =Y ]%Tm x|rpt M8+7 ܧ{a'5U 2nNF`ś [Ў6x|iL ui,wg j?ŭk,|XJTu[喌" 8k YzN!R 䍍.sNzOZ_8N47^K6Xݳ? i$q{ \ ÁxJol&֎ ѦTնrZc5ߨ [E'4,Y|*)䫫8 I%c@ܸU[LfiyP8QVt$nw.}㇌YQĖu89]-Ӻx/#ϚJS5w%x纱3ܰ?ZBL(CKڲ_s!nP\75>ݭW`p`kdɾE1pX!}^Szݤi Sw+^JJ ?n88 ` j\nzўO?Ov>kSuIpqtI$J9@^Cc~8ByY~XEY]ah`sp:MrbRmxtܳ>Mbl>KqnQ<`֏Op$Li."6=amb01[tړZsܲl0OpPU4(!}fyu=<GKM "Gk@<N\nw$K[yWZp th}م|kC_W{[ٵ3moO2ThaTDbc={5kCZqr|`C]ͯ/ȬܤG.yY 4S6AG)_Cmmo,Ela+ Rj=a\7i]9)c~<;W*JqqNVKOt Imܲw ~zk-U.ɹo>ݖ zh*u k(OYBdn}ˌ9n,i^ƊNėUֿSi_nCSj}4n3OYx1H:[Otl?Zk*y8?YSVe1\L6gX/ht 2TOqAgŵKEK%;>է`NӋ[z뿻b-%4t*]!̲ n]@;;whF,p ;[,zLJ/sl1AiJ$O'.%p'J瓷$G^c LךsnSTԞNxc۸gxn>6$4 &;Ypݽ׺kӆsK `pWMC51"vU[a#fTtbw>ץIrMuqONH`xlU*r$mǿ LߎKx zPxCv:Q\G-1P?Ff[v}_iͽ٧JQֺ)gs᳞˷p-x~ыϣ'/wgdq.W ~ks/Ԯ/K6ݞ3W׻[Ihkyu2zD,-3Pnw+lDRl`ՏQQw)Y` #Ѧc35= hںO8d.6Uߵۦvl81+~CJ܅5?R\!nnQ.\kI'RKlVF×~}蟢ajjJ@2R|7 R.a8\yD[PWWlFpTE i];s×s`zUZlT6ُӻj8mI]~ %v+T!$Id;8}6azůU|=G]=(v}J{+HFCZZE )ÓEZ#Hkb#;:@E:u{3IT$v񰏮fH[ӊ5'Fqȟ* p)3C桬TBǓy 9CQt~eeo覉º2y}mS&gzy56aǸw8s8x8“ 3YE= kn[oL+Dxr#Vk]B] aAz363Gk_fpT۪.Y}LfIjCKZ?4>7~Q؟h񳫙?z49!wA%  :{!u*dijERxS jOykC w0 si<{O+]ACL؁>IR4[" """ """ """ "" 5Ŧ w-A=ˮ3z+[96o ֢5 6;:pӜmv;TCr*#>2Ӭr75ؤw_bbMR1|Y#{]<eX(FV >CS# &WLscyr.hq<n_Yhݺ_S- 'fCm>߳uz-&Tali; DP-Ǣvji&& NgNnm"f8i,B)|MIƲk ܬGEO/p?ܽ3 xM K~ˮeZmUfY_zMd7J'2sט{D s,7GCF}#,-g(Ea,$SNZퟢ#6|b D.Ӹ'{./~xmܹY}F[z sQyJ 5D~CGyj+=-6Ʒ+!7gQsLK|NY.2)#e(wwIW5_tHk=۔0(:n7ەu+n48wqS$ Tf}*g<AQ˹]j7glxq1AVcC?([p;wu)Ԋk=R3ZUeN׃~ᎷQBy SKH;tu:ӊqK~`ٴ׸7~BVu?/% Ϋ)a[I\=b! .yvy)m0=j;]3ts^ ٕ p!0KgTsf< ۷Nv1mt$uTW,ܾŻ|nJՇo%d,Nem5EC\ca^TKD>Z4Ϫ ɥu=;j$Tpq8k6w] JyuZ{uME;۵6،Ύ̫1=,"nnOo'*=GQjsH#ؑd+6tˆ<嚑K^+4ANg!/r4bGOh㲵w[4&;lcf]BD\Jꖑ_,4a[Qv$uKWaOŶZWC|>X]Kkv歫8:r7osЬE󊁰g 4Vɿ˟i_k{)~ܙVia]h(%Ζ6po_=իQ= }rs  .4=/o9 lӦZq`dl`8V)r R"VYV.int^F-&'fD>akZƆw6 ," """ """ """ """ ""_wUn5\bF֟hӴ˰~ͧZN2-<[NZdg Y˒.F,[*MZh*$sSxՏ,,')ّQim1hY[emߦg0]-L3;4Ǖ=yت !?\Ƥp`OL%̼fZɧ؝_(%溦3]2].~ ibcPmh$_<~ v[# ma  ?x;A5W3֫_9ncVV|GFK2&ՌvM$oӻMriq"o36 4uܯ[V G1墬;Hy)}ĺG}AQSԾ>w;;n^vpi&дXWUtykћx2]jП>$4}K+Ynˬ-ަHCX@8o"AT58]/WJ1Svɥ͡i$pHz,g蒾T3EwޠFG#0x!M!y!X-VRk2씬4O;1^p*R\,QJ kuP8Yd7uRj2׆;'~HH۬/}im j-w *Z|%MW.cØ$iã(︶joyQSOEbϒG̒TU.Y5ZI/RK Çx}E65#ik vSPigwx7wc[몯U[|t=U}Zn7f9uj-^K] yK-6)kF 0a |y\'QI.}M̅"YJ$R)TY7∊ĞDDD@DDD@DDD@DDD@DDD@DDrګ/SPS35is ж-.\ϑg{r퇐-qUU"LwؗԻv߰^~KRYiZ`xI7hQcďs,C$,Z煍|5q>Xzn6TϏNoȂ)m5tyCI+4feuVvNf#8q.#o> aCQ2FCM !jNԔ;Q|WF|FHCKv=:iFBuEBfaJó'mNdq$qa;.seW.9C,j"O=#9To&\;[<;L- 2RFTWF(Be1eZ!e>SֳiEܚS\a }S6kZܤ^:[NM ĥeӼ0\~? eV٫*,OCZ͖ҳ!k5GxagG#)覂MlzBd̅lCH,0*sIc:7W=]՞׮v#ͺIK/ ׇzoaYC K۴9N%(Z~0 -GC# 4Noѱ'񬶺=nkPkj,W זICgga-,<5w<+]Vϡ%%e9 REo#)Rѿ,'~<tig`՝-dSb ~v;nAo~w*LfQ6MG~̍8@$g}**9r9aY!mg'DLn]c9Sak;FZ%uf(MͲDmnQDEhXD@DDD@DDD@DDD@DDD@DDD@?Lm+ <&=fy )!"`cG`{ Ԯ:ec-kٹyoP_w,Du,"UOˣcvϨoC|َh:DqVI%q`c<Ųt;]]eZ-+w;\,kFHw080V !.H)5t^qL-W :[Jdu$r"y49-TOY{tU_K4;?hc`lq}64jBۙjHV~OČ8?hiu߽e,n$SVMZ1TY+} P:(.wnp_ۅW6۩li]HwpaTƞx4&F \\:FK3yİHގi~GuqV e ' V,]%6qOdém[l5s틚I o@|Vjc{Ʊ~%S lbd;xZ:}O 4}-jTk$2`ΣwNBC^CU 3 ʒh[ v-\Owq+HӔ"İia녮]w&ZѧQ82W8(-7nOC]+%]}˜վ'$nww῏\%7,Q2YEڴ9fl|GxlSz݃}= ~!pÕHZ꬇%ayu-U[9֘ʭcn6*0eKf:h?fd8:2G+eYÎ]ŮDAYǻM'kF7pvMOOq3,z2[c;ji$orQ? M䗉ә!L?uZuZn9hDDD@DDD@DDD@DDD@DDD@DDpWj+ qR[;KOUKc~rj;+VXv;;]̤k 5i_QW+&Gzï){G4|G416kpQo|Km]SQSk-v6nZ=UI);S'[-ҶhN nx QjvpQ{;APkBpbzC9 n(Vz+sv*Ҳ6#Y;QIJD4?N{K}(m14 y6A$'1>=Uhӭ`'_qI؝} t]VQ=QbKjЊ:˥ڂ%[]q :ӇC}H߆;d:yo_lj++#}bwSeCd8<MˢNٲjZHdÜNڈ3G# X$cskvRJ.7~|X<2[mC]o璜ScO8pc[t]{J2kﳷڅ.Yb{'Zc}+X4Kv3F*NVW68˛KO'+9{j:RX-rNhhjZ 6=:)7zO, Yՙ-L-zFӽq 'go;%/ xe9k2i)+{]H? XnlA%[~T9X|soZrcs aiGuS-ӜK{Z$d*~i#ZD{+^츊UPuS3\bMt\Uh n(7z|mTlR}ā]R,n_6HFA^]rqSR/I[J24A-⮽۫؛7}Mݒ-VH" """ """ """ """ """ T|L^FΣ\[%ȠIjUt\)G%KwouӽnLL4z?XM`I)$;J5A]qYR\i{䫢n_ao,2]{֏DSz?"/ pHh)*ٺ8֜rinuWڌi,KP$l7恻5i h!xxfv_( `Vq':/peIw?קV\YtҴKtl{{S(A#oך+dc+dc7'0ȭ쥦Ņ=9 Uv 5#;S%wT{It (mQAY wsn}4!^hvQ 7 8PttF9h4D0Hii|b}O֍2ZF*DI^~K|SKOdP`>ckSωamC'@DDD@DDD@DDD@DDD@DDD@DDCoIp}nzuVx|i>Ycw{OPLQ]|Xx'9 zK&-2Qz2Q<~] (􍬲\cPӳ-=A[ʽY,%Ő[)n6 M-LBHa \I&i[S}6&Y1깈 jjdzzYcܒz%{T]>Yjy[Q,k$5CjEO󴎜iPgFpJpSEK.K#kEH%#N?c͵K1[32z)* f!{%w쁿^EGf-Nk%*Fwa/d{ wrki+ʲnw­u{%EwST22hZGPv궕eN^-h:KeF֟Htͧ=!m'0ܮj9s{<uG^q['.RDv-w="zvxݮTOQk-vRG\|6YX)%̰` u ;5BǺiMiI!gqCp?yRUҫ**eU ΎX)i`rjO'jO!'|JIsB7 SS%Eױߪ Au0ٿ̬ʋ} ,mUxj);5sYN-~ڜNZZޮt-#1..XМGѻIb<=F2~M?jS>EK[ON'a}rU^gTl{cw;y'YYFi)歕((D>E޽ۀ~Y @c @c And each section with lower levels must have a menu command in @c it. Menu updating with Emacs is a bit better than node updating. @c @c LINE BREAKS: For html generated from this to look good, it is @c important that there are lots of line breaks/blank lines, esp @c after @enddefn's and similar. Otherwise text flows on the same @c paragraph but gets coloured wrongly with Netscape's handling of @c style sheets. @c @c reminder about references: @c @xref{node} blah start of sentence: See [ref] @c blah (@pxref{node}) blah bla (see [ref]), best at end of sentence @c @ref{node} without "see". Careful for info. @c @set version 4.5 @set emacsversion 25.2 @set last-update July 2022 @set rcsid $Id$ @dircategory Theorem proving @direntry * ProofGeneral: (ProofGeneral). Organize your proofs with Emacs! @end direntry @c @c MACROS @c @c define one here for a command with a key-binding? @c @c I like the idea, but it's maybe against the TeXinfo @c style to fix together a command and its key-binding. @c @c merge functions and variables into concept index. @c @syncodeindex fn cp @c @syncodeindex vr cp @c merge functions into variables index @c @syncodeindex fn vr @finalout @titlepage @title Proof General @subtitle Organize your proofs! @sp 1 @subtitle User Manual for Proof General @value{version} @subtitle @value{last-update} @subtitle @b{proofgeneral.github.io} @iftex @vskip 1cm @image{ProofGeneral-image} @end iftex @author D. Aspinall, P. Courtieu, E. Martin-Dorel, C. Pit--Claudel, @author T. Kleymann, H. Goguen, D. Sequeira, M. Wenzel @page @vskip 0pt plus 1filll This manual and the program Proof General are Copyright @copyright{} 1998-2011 Proof General team, LFCS Edinburgh. @c @c COPYING NOTICE @c @ignore Permission is granted to process this file through TeX and print the results, provided the printed document carries copying permission notice identical to this one except for the removal of this paragraph (this paragraph not being relevant to the printed manual). @end ignore @sp 2 Permission is granted to make and distribute verbatim copies of this manual provided the copyright notice and this permission notice are preserved on all copies. @sp 2 This manual documents Proof General, Version @value{version}, for use with GNU Emacs @value{emacsversion} or later versions (subject to Emacs API changes). Proof General is distributed under the terms of the GNU General Public License (GPL), version 3 or later; please check the accompanying file @file{COPYING} for more details. @sp 1 Visit Proof General on the web at @code{https://proofgeneral.github.io} @sp 1 @c (commented; dates from CVS) @code{@value{rcsid}} @end titlepage @page @ifinfo @node Top @top Proof General This file documents version @value{version} of @b{Proof General}, a generic Emacs interface for proof assistants. Proof General @value{version} has been tested with GNU Emacs @value{emacsversion} on Linux. It is supplied ready to use for the proof assistants Coq, EasyCrypt, and PhoX. @menu * Preface:: * Introducing Proof General:: * Basic Script Management:: * Advanced Script Management and Editing:: * Unicode symbols and special layout support:: * Support for other Packages:: * Subterm Activation and Proof by Pointing:: * Graphical Proof-Tree Visualization:: * Customizing Proof General:: * Hints and Tips:: * Coq Proof General:: * EasyCrypt Proof General:: * Shell Proof General:: @c * PhoX Proof General:: * Obtaining and Installing:: * Bugs and Enhancements:: * References:: * History of Proof General:: * Function Index:: * Variable Index:: * Keystroke Index:: * Concept Index:: @end menu @end ifinfo @node Preface @unnumbered Preface Welcome to Proof General! This preface has some news about the current release, future plans, and acknowledgements to those who have helped along the way. The appendix @ref{History of Proof General} contains old news about previous releases, and notes on the development of Proof General. Proof General has a home page at @uref{https://proofgeneral.github.io}. Visit this page for the latest version of this manual, other documentation, system downloads, etc. @menu * News for Version 4.5:: * News for Version 4.4:: * News for Version 4.3:: * News for Version 4.2:: * News for Version 4.1:: * News for Version 4.0:: * Future:: * Credits:: @end menu @node News for Version 4.5 @unnumberedsec News for Version 4.5 @cindex news Proof-General is now distributed under the GPLv3+ license. This release contains several bugfixes and many new features (see the CHANGES file or the Git changelog for more details). The support of the following systems have been added: EasyCrypt, qrhl-tool. The old code for the support of the following systems have been removed: Twelf, CCC, Lego, Hol-Light, ACL2, Plastic, Lambda-Clam, Isabelle, HOL98. @node News for Version 4.4 @unnumberedsec News for Version 4.4 @cindex news Proof General 4.4 is the first release since PG has moved to @uref{https://github.com/ProofGeneral/PG, GitHub}. This release contains several bugfixes and improvements (see the Git ChangeLog for more details) and supports both Coq 8.4 and Coq 8.5. @node News for Version 4.3 @unnumberedsec News for Version 4.3 @cindex news In Proof General version 4.3, the multiple file handling for Coq has been improved. It now supports asynchronous and parallel compilation of required modules. The proof tree display now supports the newest features of Coq 8.4. Proof General version 4.3 is compatible with Prooftree version 0.11 (or better). @node News for Version 4.2 @unnumberedsec News for Version 4.2 @cindex news Proof General version 4.2 adds the usual round of compatibility fixes, to support newer versions of Emacs and Coq. It also contains some updates to support HOL Light in a primitive fashion. It also contains a new mechanism to display proof trees, provided by Hendrik Tews and using a bespoke rendering application named @uref{http://askra.de/software/prooftree/, Prooftree}. @node News for Version 4.1 @unnumberedsec News for Version 4.1 @cindex news Proof General version 4.1 adds some compatibility fixes to Proof General 4.0, specifically for Coq version 8.3 and Isabelle 2011. It also contains a new implementation of multiple file handling for Coq provided by Hendrik Tews. @node News for Version 4.0 @unnumberedsec News for Version 4.0 @cindex news Proof General version 4.0 is a major overhaul of Proof General. The main changes are: @itemize @bullet @item support for GNU Emacs only, @b{you cannot use XEmacs any more}; @item a new @b{Unicode Tokens} mode, which now replaces X-Symbol, @pxref{Unicode symbols and special layout support}; @item to allow ``document centred'' working, annotating scripts with prover output and automatically sending commands to the prover, @pxref{Document centred working}; @item support for latest versions of provers (Isabelle2009-2 and Coq 8.2); @item numerous smaller enhancements and efficiency improvements. @end itemize See the @file{CHANGES} file in the distribution for more complete details of changes, and the appendix @ref{History of Proof General} for old news. @node Future @unnumberedsec Future @cindex Proof General Kit @cindex Future The aim of the Proof General project is to provide powerful environments and tools for interactive proof. Proof General has been Emacs based so far and uses heavy per-prover customisation. The @b{Proof General Kit} project proposes that proof assistants use a @i{standard} XML-based protocol for interactive proof, dubbed @b{PGIP}. PGIP will enable middleware for interactive proof tools and interface components. Rather than configuring Proof General for your proof assistant, you will need to configure your proof assistant to understand PGIP. There is a similarity however; the design of PGIP was based heavily on the Emacs Proof General framework. At the time of writing, the Proof General Kit software is in a prototype stage and the PGIP protocol is still being refined. We have a prototype Proof General plugin for the Eclipse IDE and a prototype version of a PGIP-enabled Isabelle. There is also a middleware component for co-ordinating proof written in Haskell, the @i{Proof General Broker}. Further collaborations are sought for more developments, especially the PGIP enabling of other provers. For more details, see @uref{http://proofgeneral.inf.ed.ac.uk/kit, the Proof General Kit webpage}. Help us to help you organize your proofs! @node Credits @unnumberedsec Credits @cindex maintenance The original developers of the basis of Proof General were: @itemize @bullet @item @b{David Aspinall}, @item @b{Healfdene Goguen}, @item @b{Thomas Kleymann}, and @item @b{Dilip Sequeira}. @end itemize LEGO Proof General (the successor of @code{lego-mode}) was written by Thomas Kleymann and Dilip Sequeira. It is no longer maintained. @c @c It is presently maintained by David Aspinall and @c Paul Callaghan. @c Coq Proof General was written by Healfdene Goguen, with later contributions from Patrick Loiseleur. It is now maintained by Pierre Courtieu. @c Isabelle Proof General was written and is being maintained by David Aspinall. It has benefited greatly from tweaks and suggestions by Markus Wenzel, who wrote the first support for Isar and added Proof General support inside Isabelle. David von Oheimb supplied the original patches for X-Symbol support, which improved Proof General significantly. Christoph Wedler, the author of X-Symbol, provided much useful support in adapting his package for PG. The generic base for Proof General was developed by Kleymann, Sequeira, Goguen and Aspinall. It follows some of the ideas used in Project @uref{http://www.inria.fr/croap/,CROAP}. The project to implement a proof mode for LEGO was initiated in 1994 and coordinated until October 1998 by Thomas Kleymann, becoming generic along the way. In October 1998, the project became Proof General and has been managed by David Aspinall since then. This manual was written by David Aspinall and Thomas Kleymann, with words borrowed from user documentation of LEGO mode, prepared by Dilip Sequeira. Healfdene Goguen wrote some text for Coq Proof General. Since Proof General 2.0, this manual has been maintained by David Aspinall, with contributions from Pierre Courtieu, Markus Wenzel and Hendrik Tews. The Proof General project has benefited from (indirect) funding by EPSRC (@i{Applications of a Type Theory Based Proof Assistant} in the late 1990s and @i{The Integration and Interaction of Multiple Mathematical Reasoning Processes}, EP/E005713/1 (RA0084) in 2006-8), the EC (the Co-ordination Action @i{Types} and previous related projects), and the support of the LFCS. Version 3.1 was prepared whilst David Aspinall was visiting ETL, Japan, supported by the British Council. For Proof General 3.7, Graham Dutton helped with web pages and infrastructure; since then the the computing support team at the School of Informatics have given help. For testing and feedback for older versions of Proof General, thanks go to Rod Burstall, Martin Hofmann, and James McKinna, and several on the longer list below. For the Proof General 4.0 release, special thanks go to Stefan Monnier for patches and suggestions, to Makarius for many bug reports and help with Isabelle support and to Pierre Courtieu for providing new features for Coq support. Between Proof General 4.3 and 4.4 releases, the PG sources have been migrated from CVS to to GitHub; special thanks go to Clement Pit--Claudel for help in this migration. Proof General 4.4's new icons were contributed by Yoshihiro Imai (@uref{http://proofcafe.org/wiki/Generaltan}) under CC-BY-SA 3.0 (@uref{https://creativecommons.org/licenses/by-sa/3.0/}) @c FIXME: watch contributors here! During the development of Proof General 3.x and 4.x releases, many people helped provide testing and other feedback, including the Proof General maintainers, Paul Callaghan, Pierre Courtieu, and Markus Wenzel, Stefan Berghofer, Gerwin Klein, and other folk who tested pre-releases or sent bug reports and patches, including Cuihtlauac Alvarado, Esben Andreasen, Lennart Beringer, Pascal Brisset, James Brotherston, Martin Buechi, Pierre Casteran, Lucas Dixon, Erik Martin-Dorel, Matt Fairtlough, Ivan Filippenko, Georges Gonthier, Robin Green, Florian Haftmann, Kim Hyung Ho, Mark A. Hillebrand, Greg O'Keefe, Alex Krauss, Peter Lammich, Pierre Lescanne, John Longley, Erik Martin-Dorel, Assia Mahboubi, Adam Megacz, Stefan Monnier, Tobias Nipkow, Clement Pit--Claudel, Leonor Prensa Nieto, David von Oheimb, Lawrence Paulson, Paul Roziere, Randy Pollack, Robert R. Schneck, Norbert Schirmer, Sebastian Skalberg, Mike Squire, Hendrik Tews, Norbert Voelker, Tjark Weber, Mitsuharu Yamamoto. Thanks to all of you (and apologies to anyone missed)! @c ================================================================= @c @c CHAPTER: Introduction @c @node Introducing Proof General @chapter Introducing Proof General @cindex proof assistant @cindex Proof General @c would like the logo on the title page really but @c it doesn't seem to work there for html. @html [ Proof General logo ] @end html @dfn{Proof General} is a generic Emacs interface for interactive proof assistants,@footnote{A @dfn{proof assistant} is a computerized helper for developing mathematical proofs. For short, we sometimes call it a @dfn{prover}, although we always have in mind an interactive system rather than a fully automated theorem prover.} developed at the LFCS in the University of Edinburgh. You do not have to be an Emacs militant to use Proof General! The interface is designed to be very easy to use. You develop your proof script@footnote{A @dfn{proof script} is a sequence of commands which constructs a proof, usually stored in a file.} in-place rather than line-by-line and later reassembling the pieces. Proof General keeps track of which proof steps have been processed by the prover, and prevents you editing them accidentally. You can undo steps as usual. The aim of Proof General is to provide a powerful and configurable interface for numerous interactive proof assistants. We target Proof General mainly at intermediate or expert users, so that the interface should be useful for large proof developments. Please help us! Send us comments, suggestions, or (the best) patches to improve support for your chosen proof assistant. Contact us at @uref{https://github.com/ProofGeneral/PG/issues}. If your chosen proof assistant isn't supported, read the accompanying @i{Adapting Proof General} manual to find out how to configure PG for a new prover. @menu * Installing Proof General:: * Quick start guide:: * Features of Proof General:: * Supported proof assistants:: * Prerequisites for this manual:: * Organization of this manual:: @end menu @node Installing Proof General @section Installing Proof General If Proof General has not already been installed for you, you should unpack it and insert the line: @lisp (load "@var{proof-general-home}/generic/proof-site.el") @end lisp into your @file{~/.emacs} file, where @var{proof-general-home} is the top-level directory that was created when Proof General was unpacked. For much more information, @xref{Obtaining and Installing}. @node Quick start guide @section Quick start guide Once Proof General is correctly installed, the corresponding Proof General mode will be invoked automatically when you visit a proof script file for your proof assistant, for example: @multitable @columnfractions .35 .3 .35 @item @b{Prover} @tab @b{Extensions} @tab @b{Mode} @item Coq @tab @file{.v} @tab @code{coq-mode} @item Phox @tab @file{.phx} @tab @code{phox-mode} @item PG-Shell @tab @file{.pgsh} @tab @code{pgshell-mode} @item EasyCrypt @tab @file{.ec} @tab @code{easycrypt-mode} @end multitable (the exact list of Proof Assistants supported may vary according to the version of Proof General and its local configuration). You can also invoke the mode command directly, e.g., type @kbd{M-x coq-mode}, to turn a buffer into a Coq script buffer. You'll find commands to process the proof script are available from the toolbar, menus, and keyboard. Type @kbd{C-h m} to get a list of the keyboard shortcuts for the current mode. The commands available should be easy to understand, but the rest of this manual describes them in some detail. The proof assistant itself is started automatically inside Emacs as an "inferior" process when you ask for some of the proof script to be processed. You can start the proof assistant manually with the menu command "Start proof assistant". To follow an example use of Proof General on a Isabelle proof, @pxref{Walkthrough example in Isabelle}. If you know the syntax for proof scripts in another theorem prover, you can easily adapt the details given there. @node Features of Proof General @section Features of Proof General @cindex Features @cindex Why use Proof General? Why would you want to use Proof General? @c FIXME: would like to keep this synched with web page, really. @c but web page needs extra markup. Proof General is designed to be useful for novices and expert users alike. It will be useful to you if you use a proof assistant, and you'd like an interface with the following features: simplified interaction, script management, multiple file scripting, a script editing mode, proof by pointing, proof-tree visualization, toolbar and menus, syntax highlighting, real symbols, functions menu, tags, and finally, adaptability. Here is an outline of some of these features. Look in the contents page or index of this manual to find out about the others! @itemize @bullet @item @i{Simplified interaction}@* Proof General is designed for proof assistants which have a command-line shell interpreter. When using Proof General, the proof assistant's shell is hidden from the user. Communication takes place via three buffers (Emacs text widgets). Communication takes place via three buffers. The @dfn{script buffer} holds input, the commands to construct a proof. The @dfn{goals buffer} displays the current list of subgoals to be solved. The @dfn{response buffer} displays other output from the proof assistant. By default, only two of these three buffers are displayed. This means that the user normally only sees the output from the most recent interaction, rather than a screen full of output from the proof assistant. Proof General does not commandeer the proof assistant shell: the user still has complete access to it if necessary. For more details, @pxref{Summary of Proof General buffers} and @pxref{Display customization}. @item @i{Script management}@* Proof General colours proof script regions blue when they have been processed by the prover, and colours regions red when the prover is currently processing them. The appearance of Emacs buffers always matches the proof assistant's state. Coloured parts of the buffer cannot be edited. Proof General has functions for @emph{asserting} or @emph{retracting} parts of a proof script, which alters the coloured regions. For more details, @pxref{Basic Script Management}, @ref{Script processing commands}, and @ref{Advanced Script Management and Editing}. @item @i{Script editing mode}@* Proof General provides useful facilities for editing proof scripts, including syntax hilighting and a menu to jump to particular goals, definitions, or declarations. Special editing functions send lines of proof script to the proof assistant, or undo previous proof steps. For more details, @pxref{Script editing commands}, and @ref{Script processing commands}. @item @i{Proof-tree visualization}@* In cooperation with the external program Prooftree (available from the @uref{http://askra.de/software/prooftree/, Prooftree website}), Proof General can display proof trees graphically and provide visual information about the proof status of different branches in a proof. The proof-tree display provides additional means for inspecting the proof tree and thus helps against loosing track in proofs. The graphical proof-tree visualization is currently only supported for Coq. For more details, @pxref{Graphical Proof-Tree Visualization}. @item @i{Toolbar and menus}@* A script buffer has a toolbar with navigation buttons for processing parts of the proof script. A menu provides further functions for operations in the proof assistant, as well as customization of Proof General. For more details, @pxref{Toolbar commands}, @ref{Proof assistant commands}, and @ref{Customizing Proof General}. @item @i{Proof by pointing}@* Proof General has support for proof-by-pointing and similar features. Proof by pointing allows you to click on a subterm of a goal to be proved, and automatically apply an appropriate proof rule or tactic. Proof by pointing is specific to the proof assistant (and logic) in use; therefore it is configured mainly on the proof assistant side. If you would like to see proof by pointing support for Proof General in a particular proof assistant, petition the developers of the proof assistant to provide it. @c Proof General expects to parse @c term-structure annotations on the output syntax of the prover. @c It uses these to construct a message to the prover indicating @c where the user has clicked, and the proof assistant can @c response with a suggested tactic. @end itemize @node Supported proof assistants @section Supported proof assistants Proof General comes ready-customized for several proof assistants, including these: @c FLAG VERSIONS HERE @itemize @bullet @item @b{Coq Proof General} for Coq Version 8.2@* @xref{Coq Proof General}, for more details. @c @item @c @b{PhoX Proof General} for PhoX 0.8X@* @c @xref{PhoX Proof General}, for more details. @item @b{EasyCrypt Proof General} for EasyCrypt@* @xref{EasyCrypt Proof General}, for mode details. @item @b{Shell Proof General} for shell scripts (not really a proof assistant!)@* @xref{Shell Proof General}, for more details. @end itemize Proof General is designed to be generic, so if you know how to write regular expressions, you can make: @itemize @bullet @item @b{Your Proof General} for your favourite proof assistant.@* For more details of how to make Proof General work with another proof assistant, see the accompanying manual @i{Adapting Proof General}. @end itemize The exact list of Proof Assistants supported may vary according to the version of Proof General you have and its local configuration; only the standard instances documented in this manual are listed above. Note that there is some variation between the features supported by different instances of Proof General. The main variation is proof by pointing, which has been supported only in LEGO so far. For advanced features like this, some extensions to the output routines of the proof assistant are required, typically. If you like Proof General, @b{please help us by asking the implementors of your favourite proof assistant to support Proof General} as much as possible. @node Prerequisites for this manual @section Prerequisites for this manual @cindex Meta @cindex Alt @cindex key sequences This manual assumes that you understand a little about using Emacs, for example, switching between buffers using @kbd{C-x b} and understanding that a key sequence like @kbd{C-x b} means "control with x, followed by b". A key sequence like @kbd{M-z} means "meta with z". (@key{Meta} may be labelled @key{Alt} on your keyboard). The manual also assumes you have a basic understanding of your proof assistant and the language and files it uses for proof scripts. But even without this, Proof General is not useless: you can use the interface to @emph{replay} proof scripts for any proof assistant without knowing how to start it up or issue commands, etc. This is the beauty of a common interface mechanism. To get more from Proof General and adapt it to your liking, it helps to know a little bit about how Emacs lisp packages can be customized via the Customization mechanism. It's really easy to use. For details, @pxref{How to customize}. @inforef{Customization, ,emacs}, for documentation in Emacs. To get the absolute most from Proof General, to improve it or to adapt it for new provers, you'll need to know a little bit of Emacs lisp. Emacs is self-documenting, so you can begin from @kbd{C-h} and find out everything! Here are some useful commands: @table @asis @item @kbd{C-h i} @code{info} @item @kbd{C-h m} @code{describe-mode} @item @kbd{C-h b} @code{describe-bindings} @item @kbd{C-h f} @code{describe-function} @item @kbd{C-h v} @code{describe-variable} @end table @node Organization of this manual @section Organization of this manual This manual covers the user-level view and customization of Proof General. The accompanying @i{Adapting Proof General} manual considers adapting Proof General to new proof assistants, and documents some of the internals of Proof General. Three appendices of this manual contain some details about obtaining and installing Proof General and some known bugs. The contents of these final chapters is also covered in the files @file{INSTALL} and @file{BUGS} contained in the distribution. Refer to those files for the latest information. The manual concludes with some references and indexes. See the table of contents for full details. @c ================================================================= @c @c CHAPTER: Basic Script Management @c @node Basic Script Management @chapter Basic Script Management This chapter is an introduction to using the script management facilities of Proof General. We begin with a quick walkthrough example, then describe the concepts and functions in more detail. @menu * Walkthrough example in Isabelle:: * Proof scripts:: * Script buffers:: * Summary of Proof General buffers:: * Script editing commands:: * Script processing commands:: * Proof assistant commands:: * Toolbar commands:: * Interrupting during trace output:: @end menu @c FIXME: Rewrite this to use Coq since Isabelle support was removed. @node Walkthrough example in Isabelle @section Walkthrough example in Isabelle Here's a short example in Isabelle to see how script management is used. The file you are asked to type below is included in the distribution as @file{isar/Example.thy}. If you're not using Isabelle, substitute some lines from a simple proof for your proof assistant, or consult the example file supplied with Proof General for your prover, called something like @file{foo/example.foo} for a proof assistant Foo. This walkthrough is keyboard based, but you could easily use the toolbar and menu functions instead. The best way to learn Emacs key bindings is by using the menus. You'll find the keys named below listed on the menus. @itemize @bullet @item First, start Emacs with Proof General loaded. According to how you have installed Proof General, this may be by typing @code{proofgeneral} in a terminal, selecting it from a menu, or simply by starting Emacs itself. @item Next, find a new file by @kbd{C-x C-f} and typing as the filename @file{Walkthrough.thy}. This should load Isabelle Proof General and the toolbar and Proof General menus will appear. You should have an empty buffer displayed. @end itemize The notation @kbd{C-x C-f} means control key with `x' followed by control key with `f'. This is a standard notation for Emacs key bindings, used throughout this manual. This function also appears on the @code{File} menu of Emacs. The remaining commands used will be on the @code{Proof-General} menu or toolbar. If you're not using Isabelle, you must choose a different file extension, appropriately for your proof assistant. If you don't know what to use, see the previous chapter for the list of supported assistants and file extensions. @itemize @bullet @item Turn on @dfn{electric terminator} by typing @kbd{C-c ;} and enter: @lisp theory Walkthrough imports Main begin; @end lisp This first command begins the definition of a new theory inside Isabelle, which extends the theory @code{Main}. (We're assuming that you have Isabelle/HOL available, which declares the @code{Main} theory. You should be able to see the list of installed logics in Isabelle on the @code{Logics} menu). @end itemize Electric terminator sends commands to the proof assistant as you type them. At the moment you type the semicolon, the @code{theory} command will be sent to Isabelle behind the scenes. First, there is a short delay while Isabelle is launched; you may see a welcome message. Then, you may notice that the command briefly is given an orange/pink background (or shown in inverse video if you don't have a colour display), before you see a window containing text like this: @lisp theory Walkthrough @end lisp which reflects the command just executed. @c = @c @{ProtoPure, CPure, HOL, Set, Typedef, Fun, Product_Type, Lfp, Gfp, @c Sum_Type, Relation, Record, Inductive, Transitive_Closure, @c Wellfounded_Recursion, Ring_and_Field, Nat, NatArith, Divides, Power, @c Finite_Set, Equiv, IntDef, Datatype_Universe, Datatype, Numeral, Bin, @c IntArith, Wellfounded_Relations, Recdef, IntDiv, NatBin, NatSimprocs, @c SetInterval, Presburger, Relation_Power, Parity, PreList, List, Map, @c Hilbert_Choice, Infinite_Set, Extraction, Refute, Main, #@} @c (Which gives you some idea of the theories that go to build up @code{Main}!). @c FIXME: explain window layouts a bit In this case of this first command, it is hard to see the orange/pink stage because the command is processed very quickly on modern machines. But in general, processing commands can take an arbitrary amount of time (or not terminate at all). For this reason, Proof General maintains a queue of commands which are sent one-by-one from the proof script. As Isabelle successfully processes commands in the queue, they will turn from the orange/pink colour into blue. The blue regions indicate text that has been read by the prover and should not be edited, to avoid confusion between what the prover has processed and what you are looking at. To enforce this (and avoid potentially expensive reprocessing) the blue region can be made read-only. This is controlled by the menu item: @lisp Proof-General -> Quick Options -> Read Only @end lisp The first option `Strict Read Only' was formerly the default for Proof General, and causes the blue region to be @i{locked}. Because of this, the term @dfn{locked region} term is used in Proof General documentation to mean the blue portion of the text which has been processed, although it is no longer locked by default. The current default is `Undo on Edit' which causes the prover to undo back to any user edits. So if you change a processed piece of text you will need to re-process it. The final option, `Freely Edit', allows you to freely edit the buffer without causing the prover to reprocess it. This can quickly lead to confusion and a loss of synchronization between what you are reading and what the prover has processed, so it is best used sparingly. Electric terminator mode is popular, but not enabled by default because of the principle of least surprise. Moreover, in Isabelle, the semicolon terminators are optional so proof scripts are usually written without them to avoid clutter. You'll notice that although you typed a semi-colon it was not included in the buffer! The electric terminator tries to be smart about comments and strings but sometimes it may be confused (e.g., adding a semi-colon inside an already written comment), or you may need to type several terminator commands together. In this case you can use the standard Emacs @b{quote next character}, typing @kbd{C-q ;} to quote the semi-colon. Alternatively you can use a prefix argument, as in @kbd{M-3 ;} to type three semi-colons. Without using electric terminator, you can trigger processing the text up to the current position of the point with the key @kbd{C-c C-RET}, or just up to the next command with @kbd{C-c C-n}. We show the rest of the example in Isabelle with semi-colons, but these will not appear in the final text. Coq, on the other hand, requires a full-stop terminator at the end of each line. If you want to enable electric terminator, use the menu item: @code{Proof-General -> Quick Options -> Processing -> Electric Terminator} If you want to keep electric terminator enabled all the time, you can customize Proof General to do so, @xref{Customizing Proof General}. For the common options, customization is easy: just use the menu item @code{Proof General -> Quick Options} to make your choices, and @code{Proof-General -> Quick Options -> Save Options} to save your choices. @itemize @bullet @item Next type on a new line: @lisp theorem my_theorem: "A & B --> B & A"; @end lisp @end itemize The goal we have set ourselves to prove should be displayed in the @i{goals buffer}. @c FIXME explain again @itemize @bullet @item Now type: @lisp proof assume "A & C"; @end lisp @end itemize This will update the goals buffer. But whoops! That was the wrong command, we typed @code{C} instead of @code{B}. @itemize @bullet @item Press @kbd{C-c C-BS} to pretend that didn't happen. @end itemize Note: @kbd{BS} means the backspace key. This key press sends an undo command to Isabelle, and deletes the @code{assume} command from the proof script. If you just want to undo without deleting, you can type @kbd{C-c C-u} instead, or use the left-arrow toolbar navigation button. @itemize @bullet @item Instead, let's try: @lisp assume "A & B"; @end lisp Which is better. @item From this assumption we can get @code{B} and @code{A} by the trivial step @code{..} which splits the assumption using an elimination step: @lisp then obtain B and A ..; @end lisp @item Finally, we establish the goal by the trivial step @code{..} again, which triggers an introduction rule: @lisp then show "B & A" ..; @end lisp @end itemize After this proof step, the message from Isabelle indicates that the proof has succeeded, so we can conclude the proof with the @code{qed} command. @itemize @bullet @item Finally, type: @lisp qed; @end lisp @end itemize This last command closes the proof and saves the proved theorem. Moving the mouse pointer over the qed command now reveals that the entire proof has been aggregated into a single segment (if you did this before, you would see highlighting of each command separately). @c This is no longer true! @c This reflects the fact that Isabelle has thrown away the history of the @c proof, so if we want to undo now, the whole proof must be retracted. @itemize @bullet @item Suppose we decide to call the theorem something more sensible. Move the cursor up into the locked region, somewhere between @samp{theorem} and @samp{qed}, enter @kbd{C-c C-RET}. @end itemize You see that the locked segment for the whole proof is now unlocked (and uncoloured): it is transferred back into the editing region. The command @kbd{C-c C-RET} moves the end of the locked region to the cursor position, or as near as possible above or below it, sending undoing commands or proof commands as necessary. In this case, the locked region will always be moved back to the end of the @code{theory} line, since that is the closest possible position to the cursor that appears before it. If you simply want to @i{retract} the whole file in one go, you can use the key @kbd{C-c C-r} (which corresponds to the up arrow on the toolbar), which will automatically move the cursor to the top of the file. @itemize @bullet @item Now improve the goal name, for example: @lisp theorem and_commutes: "A & B --> B & A" @end lisp You can swiftly replay the rest of the buffer now with @kbd{C-c C-b} (or the down arrow on the toolbar). @item At the end of the buffer, you may insert the command @lisp end @end lisp to complete the theory. @end itemize Notice that if you right-click on one of the highlighted regions in the blue area you will see a context menu for the region. This includes a ``show/hide'' option for @i{folding} a proof, as well as some editing commands for copying the region or rearranging its order in the processed text: ``move up/move down''. (These latter commands occasionally help you reorder text without needing to reprove it, although they risk breaking the proof!) @c da: no longer true with Isabelle2007 @c Note that once a theory is completed in Isabelle, you cannot undo into @c it, again because Isabelle discards the history of the theory's @c creation. Just like completed proofs, there is no option other than @c undoing the whole theory. To prevent you doing this inadvertently, @c however (maybe undoing many proofs which are time-consuming to replay), @c the @kbd{C-c C-u} or @kbd{C-c C-RET} commands will generate an error @c message, typically: @c @lisp @c *** Cannot undo "end" @c *** At command "cannot_undo". @c @end lisp @c If you really want to retract the theory for editing once more, you can @c use the key @kbd{C-c C-r} (which corresponds to the up arrow on the @c toolbar). Finally, once you are happy with your theory, you should save the file with @kbd{C-x C-s} before moving on to edit another file or exiting Emacs. If you forget to do this, Proof General or Emacs will surely prompt you sooner or later! @node Proof scripts @section Proof scripts @cindex proof script @cindex scripting A @dfn{proof script} is a sequence of commands which constructs definitions, declarations, theories, and proofs in a proof assistant. Proof General is designed to work with text-based @i{interactive} proof assistants, where the mode of working is usually a dialogue between the human and the proof assistant. Primitive interfaces for proof assistants simply present a @dfn{shell} (command interpreter) view of this dialogue: the human repeatedly types commands to the shell until the proof is completed. The system responds at each step, perhaps with a new list of subgoals to be solved, or perhaps with a failure report. Proof General manages the dialogue to show the human only the information which is relevant at each step. Often we want to keep a record of the proof commands used to prove a theorem, to build up a library of proved results. An easy way to store a proof is to keep a text file which contains a proof script; proof assistants usually provide facilities to read a proof script from a file instead of the terminal. Using the file, we can @dfn{replay} the proof script to prove the theorem again. @c Re-playing a proof script is a non-interactive procedure, @c since it is supposed to succeed. Using only a primitive shell interface, it can be tedious to construct proof scripts with cut-and-paste. Proof General helps out by issuing commands directly from a proof script file, while it is being written and edited. Proof General can also be used conveniently to replay a proof step-by-step, to see the progress at each stage. @c developing them in proof script files. @dfn{Scripting} is the process of building up a proof script file or replaying a proof. When scripting, Proof General sends proof commands to the proof assistant one at a time, and prevents you from editing commands which have been successfully completed by the proof assistant, to keep synchronization. Regions of the proof script are analysed based on their syntax and the behaviour of the proof assistant after each proof command. @node Script buffers @section Script buffers @cindex script buffer @cindex proof script mode A @dfn{script buffer} is a buffer displaying a proof script. Its Emacs mode is particular to the proof assistant you are using (but it inherits from @dfn{proof-mode}). A script buffer is divided into three regions: @emph{locked}, @emph{queue} and @emph{editing}. The proof commands in the script buffer can include a number of @emph{Goal-save sequences}. @menu * Locked queue and editing regions:: * Goal-save sequences:: * Active scripting buffer:: @end menu @node Locked queue and editing regions @subsection Locked, queue, and editing regions @cindex Locked region @cindex Queue region @cindex Editing region @cindex blue text @cindex pink text The three regions that a script buffer is divided into are: @c @itemize @bullet @item The @emph{locked} region, which appears in blue (underlined on monochrome displays) and contains commands which have been sent to the proof process and verified. The commands in the locked region cannot be edited. @item The @emph{queue} region, which appears in pink (inverse video) and contains commands waiting to be sent to the proof process. Like those in the locked region, these commands can't be edited. @item The @emph{editing} region, which contains the commands the user is working on, and can be edited as normal Emacs text. @end itemize These three regions appear in the buffer in the order above; that is, the locked region is always at the start of the buffer, and the editing region always at the end. The queue region only exists if there is input waiting to be processed by the proof process. Proof General has two fundamental operations which transfer commands between these regions: @emph{assertion} (or processing) and @emph{retraction} (or undoing). @cindex Assertion @strong{Assertion} causes commands from the editing region to be transferred to the queue region and sent one by one to the proof process. If the command is accepted, it is transferred to the locked region, but if an error occurs it is signalled to the user, and the offending command is transferred back to the editing region together with any remaining commands in the queue. Assertion corresponds to processing proof commands, and makes the locked region grow. @cindex Retraction @strong{Retraction} causes commands to be transferred from the locked region to the editing region (again via the queue region) and the appropriate 'undo' commands to be sent to the proof process. Retraction corresponds to undoing commands, and makes the locked region shrink. For details of the commands available for doing assertion and retraction, @xref{Script processing commands}. @node Goal-save sequences @subsection Goal-save sequences @cindex goal @cindex save @cindex goal-save sequences A proof script contains a sequence of commands used to prove one or more theorems. As commands in a proof script are transferred to the locked region, they are aggregated into segments which constitute the smallest units which can be undone. Typically a segment consists of a declaration or definition, or all the text from a @dfn{goal} command to the corresponding @dfn{save} (e.g. @code{qed}) command, or the individual commands in the proof of an unfinished goal. As the mouse moves over the the region, the segment containing the pointer will be highlighted. Proof General therefore assumes that the proof script has a series of proofs which look something like this: @lisp goal @var{mythm} is @var{G} @dots{} save theorem @var{mythm} @end lisp interspersed with comments, definitions, and the like. Of course, the exact syntax and terminology will depend on the proof assistant you use. The name @var{mythm} can appear in a menu for the proof script to help quickly find a proof (@pxref{Imenu and Speedbar}). @c Proof General recognizes the goal-save sequences in proof scripts. @c once a goal-save region has been fully processed by the proof assistant, @c it is treated as atomic when undoing proof steps. This reflects the @c fact that most proof assistants discard the history of a proof once a it @c is completed or once a new proof is begun. @node Active scripting buffer @subsection Active scripting buffer @cindex active scripting buffer You can edit as many script buffers as you want simultaneously, but only one buffer at a time can be used to process a proof script incrementally: this is the @dfn{active scripting buffer}. The active scripting buffer has a special indicator: the word @code{Scripting} appears in its mode line at the bottom of the screen. This is coloured to indicate the status: if it has a pink or blue background, the prover is processing the text (busy when pink). If it is in green, the buffer is completely processed. When you use a scripting command, it will automatically turn a buffer into the active scripting mode. You can also do this by hand, via the menu command 'Toggle Scripting' or the key @kbd{C-c C-s}. @table @asis @item @kbd{C-c C-s} @code{proof-toggle-active-scripting} @end table When active scripting mode is turned on, several things may happen to get ready for scripting (exactly what happens depends on which proof assistant you are using and some user settings). First, the proof assistant is started if it is not already running. Second, a command is sent to the proof assistant to change directory to the directory of the current buffer. If the current buffer corresponds to a file, this is the directory the file lives in. This is in case any scripting commands refer to files in the same directory as the script. The third thing that may happen is that you are prompted to save some unsaved buffers. This is in case any scripting commands may read in files which you are editing. Finally, some proof assistants may automatically read in files which the current file depends on implicitly. In Isabelle, for example, there is an implicit dependency between a @code{.ML} script file and a @code{.thy} theory file which defines its theory. If you have a partly processed scripting buffer and use @kbd{C-c C-s}, or you attempt to use script processing in a new buffer, Proof General will ask you if you want to retract what has been proved so far, @code{Scripting incomplete in buffer myproof.v, retract?} or if you want to process the remainder of the active buffer, @code{Completely process buffer myproof.v instead?} before you can start scripting in a new buffer. If you refuse to do either, Proof General will give an error message: @code{Cannot have more than one active scripting buffer!}. To turn off active scripting, the buffer must be completely processed (all blue), or completely unprocessed. There are two reasons for this. First, it would certainly be confusing if it were possible to split parts of a proof arbitrarily between different buffers; the dependency between the commands would be lost and it would be tricky to replay the proof.@footnote{Some proof assistants provide some level of support for switching between multiple concurrent proofs, but Proof General does not use this. Generally the exact context for such proofs is hard to define to easily split them into multiple files.} Second, we want to interface with file management in the proof assistant. Proof General assumes that a proof assistant may have a notion of which files have been processed, but that it will only record files that have been @i{completely} processed. For more explanation of the handling of multiple files, @xref{Switching between proof scripts}. @c TEXI DOCSTRING MAGIC: proof-toggle-active-scripting @deffn Command proof-toggle-active-scripting &optional arg Toggle active scripting mode in the current buffer.@* With @var{arg}, turn on scripting iff @var{arg} is positive. @end deffn @node Summary of Proof General buffers @section Summary of Proof General buffers @cindex shell buffer @cindex goals buffer @cindex response buffer @cindex proof by pointing Proof General manages several kinds of buffers in Emacs. Here is a summary of the different kinds of buffers you will use when developing proofs. @itemize @bullet @item The @dfn{proof shell buffer} is an Emacs shell buffer used to run your proof assistant. Usually it is hidden from view (but @pxref{Escaping script management}). Communication with the proof shell takes place via two or three intermediate buffers. @item A @dfn{script buffer}, as we have explained, is a buffer for editing a proof script. The @dfn{active scripting buffer} is the script buffer which is currently being used to send commands to the proof shell. @item The @dfn{goals buffer} displays the list of subgoals to be solved for a proof in progress. During a proof it is usually displayed together with the script buffer. The goals buffer has facility for @dfn{proof-by-pointing}. @item The @dfn{response buffer} displays other output from the proof assistant, for example error messages or informative messages. The response buffer is displayed whenever Proof General puts a new message in it. @item The @dfn{trace buffer} is a special version of the response buffer. It may be used to display unusual debugging output from the prover, for example, tracing proof tactics or rewriting procedures. This buffer is also displayed whenever Proof General puts a new message in it (although it may be quickly replaced with the response or goals buffer in two-buffer mode). @end itemize Normally Proof General will automatically reveal and hide the goals and response buffers as necessary during scripting. However there are ways to customize the way the buffers are displayed, for example, to prevent auxiliary buffers being displayed at all (@pxref{Display customization}). The menu @code{Proof General -> Buffers} provides a convenient way to display or switch to a Proof General buffer: the active scripting buffer; the goal or response buffer; the tracing buffer; or the shell buffer. Another command on this menu, @code{Clear Responses}, clears the response and tracing buffer. @node Script editing commands @section Script editing commands Proof General provides a few functions for editing proof scripts. The generic functions mainly consist of commands to navigate within the script. Specific proof assistant code may add more to these basics. @findex indent-for-tab-command @vindex proof-script-indent Indentation is controlled by the user option @code{proof-script-indent} (@pxref{User options}). When indentation is enabled, Proof General will indent lines of proof script with the usual Emacs functions, particularly @kbd{TAB}, @code{indent-for-tab-command}. @c FIXME: remove when indentation is fixed. Unfortunately, indentation in Proof General @value{version} is somewhat slow. Therefore with large proof scripts, we recommend @code{proof-script-indent} is turned off. Here are the commands for moving around in a proof script, with their default key-bindings: @kindex C-c C-a @kindex C-c C-e @kindex C-c C-. @table @kbd @item C-c C-a @code{proof-goto-command-start} @item C-c C-e @code{proof-goto-command-end} @item C-c C-. @code{proof-goto-end-of-locked} @end table @c TEXI DOCSTRING MAGIC: proof-goto-command-start @deffn Command proof-goto-command-start Move point to start of current (or final) command of the script. @end deffn @c TEXI DOCSTRING MAGIC: proof-goto-command-end @deffn Command proof-goto-command-end Set point to end of command at point. @end deffn @vindex proof-terminal-string The variable @code{proof-terminal-string} is a prover-specific string to terminate proof commands. LEGO and Isabelle used a semicolon, @samp{;}. Coq employs a full-stop @samp{.}. @c TEXI DOCSTRING MAGIC: proof-goto-end-of-locked @deffn Command proof-goto-end-of-locked &optional switch Jump to the end of the locked region, maybe switching to script buffer.@* If called interactively or @var{switch} is non-nil, switch to script buffer. If called interactively, a mark is set at the current location with @samp{@code{push-mark}} @end deffn @c PG4: this is not available at the moment @c @c During the course of a large proof, it may be useful to copy previous @c commands. As you move the mouse over previous portions of the script, @c you'll notice that each proof command is highlighted individually. @c (Once a goal...save sequence is ``closed'', the whole sequence is @c highlighted). There is a useful mouse binding for copying the @c highlighted command under the mouse: @c @kindex C-button1 @c @table @kbd @c @item C-button1 @c @code{proof-mouse-track-insert} @c @end table @c @c DOCSTRING MAGIC: proof-mouse-track-insert @c @deffn Command proof-mouse-track-insert event @c Copy highlighted command under mouse @var{event} to point. Ignore comments.@* @c If there is no command under the mouse, behaves like mouse-track-insert. @c @end deffn @c Read the documentation in Emacs to find out about the normal behaviour @c of @code{proof-mouse-track-insert}, if you don't already know what it @c does. @node Script processing commands @section Script processing commands @kindex C-c C-n @kindex C-c C-u @kindex C-c C-BS @kindex C-c C-b @kindex C-c C-r @kindex C-c C-RET @cindex prefix argument Here are the commands for asserting and retracting portions of the proof script, together with their default key-bindings. Sometimes assertion and retraction commands can only be issued when the queue is empty. You will get an error message @code{Proof Process Busy!} if you try to assert or retract when the queue is being processed.@footnote{In fact, this is an unnecessary restriction imposed by the original design of Proof General. There is nothing to stop future versions of Proof General allowing the queue region to be extended or shrunk, whilst the prover is processing it. Proof General 3.0 already relaxes the original design, by allowing successive assertion commands without complaining.} @table @kbd @item C-c C-n @code{proof-assert-next-command-interactive} @item C-c C-u @code{proof-undo-last-successful-command} @item C-c C-BS @code{proof-undo-and-delete-successful-command} @item C-c C-RET @code{proof-goto-point} @item C-c C-b @code{proof-process-buffer} @item C-c C-r @code{proof-retract-buffer} @item C-c @var{terminator-character} @code{proof-electric-terminator-toggle} @end table The last command, @code{proof-electric-terminator-toggle}, is triggered using the character which terminates proof commands for your proof assistant's script language. LEGO and Isabelle used @kbd{C-c ;}, for Coq, use @kbd{C-c .}. This not really a script processing command. Instead, if enabled, it causes subsequent key presses of @kbd{;} or @kbd{.} to automatically activate @code{proof-assert-next-command-interactive} for convenience. Rather than use a file command inside the proof assistant to read a proof script, a good reason to use @kbd{C-c C-b} (@code{proof-process-buffer}) is that with a faulty proof script (e.g., a script you are adapting to prove a different theorem), Proof General will stop exactly where the proof script fails, showing you the error message and the last processed command. So you can easily continue development from exactly the right place in the script. In normal development, one often jumps into the middle or to the end of some file, because this is the point, where a lemma must be added or a definition must be fixed. Before starting the real work, one needs to assert the file up to that point, usually with @kbd{C-c C-RET} (@code{proof-goto-point}). Even for medium sized files, asserting a big portion can take several seconds. There are different ways to speed this process up. @itemize @bullet @item One can split the development into smaller files. This works quite well with Coq, automatic background compilation, @ref{Automatic Compilation in Detail}, and the fast compilation options, @ref{Quick and inconsistent compilation}. @item One can configure @code{proof-omit-proofs-option} to @code{t} to omit complete opaque proofs when larger chunks are asserted. A proof is opaque, if its proof script or proof term cannot influence the following code. In Coq, opaque proofs are finished with @code{Qed}, non-opaque ones with @code{Defined}. When this omit proofs feature is configured, complete opaque proofs are silently replace with a suitable cheating command (@code{Admitted} for Coq) before sending the proof to the proof assistant. For files with big proofs this can bring down the processing time to 10% with the obvious disadvantage that errors in the omitted proofs go unnoticed. For checking the proofs occasionally, a prefix argument for @code{proof-goto-point} and @code{proof-process-buffer} causes these commands to disregard the setting of @code{proof-omit-proofs-option}. Currently, the omit proofs feature is only supported for Coq. @item An often used poor man's solution is to collect all new material at the end of one file, regardless where the material really belongs. When the final theorem has been proved, one cleans up the mess and moves all stuff where it really belongs. @end itemize Here is the full set of script processing commands. @c TEXI DOCSTRING MAGIC: proof-assert-next-command-interactive @deffn Command proof-assert-next-command-interactive Process until the end of the next unprocessed command after point.@* If inside a comment, just process until the start of the comment. @end deffn @c TEXI DOCSTRING MAGIC: proof-undo-last-successful-command @deffn Command proof-undo-last-successful-command Undo last successful command at end of locked region. @end deffn @c TEXI DOCSTRING MAGIC: proof-undo-and-delete-last-successful-command @deffn Command proof-undo-and-delete-last-successful-command Undo and delete last successful command at end of locked region.@* Useful if you typed completely the wrong command. Also handy for proof by pointing, in case the last proof-by-pointing command took the proof in a direction you don't like. Notice that the deleted command is put into the Emacs kill ring, so you can use the usual @samp{yank} and similar commands to retrieve the deleted text. @end deffn @c TEXI DOCSTRING MAGIC: proof-goto-point @deffn Command proof-goto-point &optional raw Assert or retract to the command at current position.@* Calls @samp{@code{proof-assert-until-point}} or @samp{@code{proof-retract-until-point}} as appropriate. With prefix argument @var{raw} the omit proofs feature (@samp{@code{proof-omit-proofs-option}}) is temporaily disabled to check all proofs in the asserted region. @end deffn @c TEXI DOCSTRING MAGIC: proof-process-buffer @deffn Command proof-process-buffer &optional raw Process the current (or script) buffer, and maybe move point to the end.@* With prefix argument @var{raw} the omit proofs feature (@samp{@code{proof-omit-proofs-option}}) is temporaily disabled to check all proofs in the asserted region. @end deffn @c TEXI DOCSTRING MAGIC: proof-retract-buffer @deffn Command proof-retract-buffer &optional called-interactively Retract the current buffer, and maybe move point to the start.@* Point is only moved according to @samp{@code{proof-follow-mode}}, if @var{called-interactively} is non-nil, which is the case for all interactive calls. @end deffn @c TEXI DOCSTRING MAGIC: proof-electric-terminator-toggle @deffn Command proof-electric-terminator-toggle &optional arg Toggle @samp{@code{proof-electric-terminator-enable}}. With @var{arg}, turn on iff ARG>0.@* This function simply uses @code{customize-set-variable} to set the variable. @end deffn @c TEXI DOCSTRING MAGIC: proof-assert-until-point-interactive @deffn Command proof-assert-until-point-interactive Process the region from the end of the locked-region until point.@* If inside a comment, just process until the start of the comment. @end deffn @c TEXI DOCSTRING MAGIC: proof-retract-until-point-interactive @deffn Command proof-retract-until-point-interactive &optional delete-region Tell the proof process to retract until point.@* If invoked outside a locked region, undo the last successfully processed command. If called with a prefix argument (@var{delete-region} non-nil), also delete the retracted region from the proof-script. @end deffn As experienced Emacs users will know, a @i{prefix argument} is a numeric argument supplied by some key sequence typed before a command key sequence. You can supply a specific number by typing @key{Meta} with the digits, or a ``universal'' prefix of @kbd{C-u}. See @inforef{Arguments, ,emacs} for more details. Several Proof General commands, like @code{proof-retract-until-point-interactive}, may accept a @i{prefix argument} to adjust their behaviour somehow. @node Proof assistant commands @section Proof assistant commands @kindex C-c C-p @kindex C-c C-h @kindex C-c C-c @kindex C-c C-v @kindex C-c C-f @kindex C-c C-t There are several commands for interacting with the proof assistant and Proof General, which do not involve the proof script. Here are the key-bindings and functions. @table @kbd @item C-c C-l @code{proof-display-some-buffers} @item C-c C-p @code{proof-prf} @item C-c C-t @code{proof-ctxt} @item C-c C-h @code{proof-help} @item C-c C-i @code{proof-query-identifier} @item C-c C-f @code{proof-find-theorems} @item C-c C-w @code{pg-response-clear-displays} @item C-c C-c @code{proof-interrupt-process} @item C-c C-v @code{proof-minibuffer-cmd} @item C-c C-s @code{proof-shell-start} @item C-c C-x @code{proof-shell-exit} @end table @c TEXI DOCSTRING MAGIC: proof-display-some-buffers @deffn Command proof-display-some-buffers Display the response, trace, goals, or shell buffer, rotating.@* A fixed number of repetitions of this command switches back to the same buffer. Also move point to the end of the response buffer if it's selected. If in three window or multiple frame mode, display two buffers. The idea of this function is to change the window->buffer mapping without adjusting window layout. @end deffn @c TEXI DOCSTRING MAGIC: proof-prf @deffn Command proof-prf Show the current proof state.@* Issues a command to the assistant based on @code{proof-showproof-command}. @end deffn @c TEXI DOCSTRING MAGIC: proof-ctxt @deffn Command proof-ctxt Show the current context.@* Issues a command to the assistant based on @code{proof-context-command}. @end deffn @c TEXI DOCSTRING MAGIC: proof-help @deffn Command proof-help Show a help or information message from the proof assistant.@* Typically, a list of syntax of commands available. Issues a command to the assistant based on @code{proof-info-command}. @end deffn @c TEXI DOCSTRING MAGIC: proof-query-identifier @deffn Command proof-query-identifier string Query the prover about the identifier @var{string}.@* If called interactively, @var{string} defaults to the current word near point. @end deffn @c TEXI DOCSTRING MAGIC: proof-find-theorems @deffn Command proof-find-theorems arg Search for items containing given constants.@* Issues a command based on @var{arg} to the assistant, using @code{proof-find-theorems-command}. The user is prompted for an argument. @end deffn @c TEXI DOCSTRING MAGIC: pg-response-clear-displays @deffn Command pg-response-clear-displays Clear Proof General response and tracing buffers.@* You can use this command to clear the output from these buffers when it becomes overly long. Particularly useful when @samp{@code{proof-tidy-response}} is set to nil, so responses are not cleared automatically. @end deffn @c TEXI DOCSTRING MAGIC: proof-interrupt-process @deffn Command proof-interrupt-process Interrupt the proof assistant. Warning! This may confuse Proof General. This sends an interrupt signal to the proof assistant, if Proof General thinks it is busy. This command is risky because we don't know whether the last command succeeded or not. The assumption is that it didn't, which should be true most of the time, and all of the time if the proof assistant has a careful handling of interrupt signals. Some provers may ignore (and lose) interrupt signals, or fail to indicate that they have been acted upon yet stop in the middle of output. In the first case, PG will terminate the queue of commands at the first available point. In the second case, you may need to press enter inside the prover command buffer (e.g., with Isabelle@var{2009} press RET inside @strong{isabelle}). @end deffn @c TEXI DOCSTRING MAGIC: proof-minibuffer-cmd @deffn Command proof-minibuffer-cmd cmd Send @var{cmd} to proof assistant. Interactively, read from minibuffer.@* The command isn't added to the locked region. If a prefix arg is given and there is a selected region, that is pasted into the command. This is handy for copying terms, etc from the script. If @samp{@code{proof-strict-state-preserving}} is set, and @samp{@code{proof-state-preserving-p}} is configured, then the latter is used as a check that the command will be safe to execute, in other words, that it won't ruin synchronization. If when applied to the command it returns false, then an error message is given. @var{warning}: this command risks spoiling synchronization if the test @samp{@code{proof-state-preserving-p}} is not configured, if it is only an approximate test, or if @samp{@code{proof-strict-state-preserving}} is off (nil). @end deffn As if the last two commands weren't risky enough, there's also a command which explicitly adjusts the end of the locked region, to be used in extreme circumstances only. @xref{Escaping script management}. There are a few commands for starting, stopping, and restarting the proof assistant process. The first two have key bindings but restart does not. As with any Emacs command, you can invoke these with @kbd{M-x} followed by the command name. @c TEXI DOCSTRING MAGIC: proof-shell-start @deffn Command proof-shell-start Initialise a shell-like buffer for a proof assistant.@* Does nothing if proof assistant is already running. Also generates goal and response buffers. If @samp{@code{proof-prog-name-ask}} is set, query the user for the process command. @end deffn @c TEXI DOCSTRING MAGIC: proof-shell-exit @deffn Command proof-shell-exit &optional dont-ask Query the user and exit the proof process. This simply kills the @samp{@code{proof-shell-buffer}} relying on the hook function @samp{@code{proof-shell-kill-function}} to do the hard work. If optional argument @var{dont-ask} is non-nil, the proof process is terminated without confirmation. The kill function uses @samp{-quit-timeout} as a timeout to wait after sending @samp{@code{proof-shell-quit-cmd}} before rudely killing the process. This function should not be called if @samp{@code{proof-shell-exit-in-progress}} is t, because a recursive call of @samp{@code{proof-shell-kill-function}} will give strange errors. @end deffn @c TEXI DOCSTRING MAGIC: proof-shell-restart @deffn Command proof-shell-restart Clear script buffers and send @samp{@code{proof-shell-restart-cmd}}.@* All locked regions are cleared and the active scripting buffer deactivated. If the proof shell is busy, an interrupt is sent with @samp{@code{proof-interrupt-process}} and we wait until the process is ready. The restart command should re-synchronize Proof General with the proof assistant, without actually exiting and restarting the proof assistant process. It is up to the proof assistant how much context is cleared: for example, theories already loaded may be "cached" in some way, so that loading them the next time round only performs a re-linking operation, not full re-processing. (One way of caching is via object files, used by Coq). @end deffn @node Toolbar commands @section Toolbar commands The toolbar provides a selection of functions for asserting and retracting portions of the script, issuing non-scripting commands to inspect the prover's state, and inserting "goal" and "save" type commands. The latter functions are not available on keys, but are available from the from the menu, or via @kbd{M-x}, as well as the toolbar. @c TEXI DOCSTRING MAGIC: proof-issue-goal @deffn Command proof-issue-goal arg Write a goal command in the script, prompting for the goal.@* Issues a command based on @var{arg} to the assistant, using @code{proof-goal-command}. The user is prompted for an argument. @end deffn @c TEXI DOCSTRING MAGIC: proof-issue-save @deffn Command proof-issue-save arg Write a save/qed command in the script, prompting for the theorem name.@* Issues a command based on @var{arg} to the assistant, using @code{proof-save-command}. The user is prompted for an argument. @end deffn @node Interrupting during trace output @section Interrupting during trace output If your prover generates output which is recognized as tracing output in Proof General, you may need to know about a special provision for interrupting the prover process. @c % If the trace output is voluminous, perhaps looping, it may be difficult to interrupt with the ordinary @kbd{C-c C-c} (@code{proof-interrupt-process}) or the corresponding button/menu. In this case, you should try Emacs's @b{quit key}, @kbd{C-g}. This will cause a quit in any current editing commands, as usual, but during tracing output it will also send an interrupt signal to the prover. Hopefully this will stop the tracing output, and Emacs should catch up after a short delay. Here's an explanation of the reason for this special provision. When large volumes of output from the prover arrive quickly in Emacs, as typically is the case during tracing (especially tracing looping tactics!), Emacs may hog the CPU and spend all its time updating the display with the trace output. This is especially the case when features like output fontification and token display are active. If this happens, ordinary user input in Emacs is not processed, and it becomes difficult to do normal editing. The root of the problem is that Emacs runs in a single thread, and pending process output is dealt with before pending user input. Whether or not you see this problem depends partly on the processing power of your machine (or CPU available to Emacs when the prover is running). One way to test is to start an Emacs shell with @kbd{M-x shell} and type a command such as @code{yes} which produces output indefinitely. Now see if you can interrupt the process! (Warning --- on slower machines especially, this can cause lockups, so use a fresh Emacs.) @c ================================================================= @c @c CHAPTER: Advanced Script Management @c @node Advanced Script Management and Editing @chapter Advanced Script Management and Editing @cindex Multiple Files If you are working with large proof developments, you may want to know about the advanced script management and editing features of Proof General covered in this chapter. @menu * Document centred working:: * Automatic processing:: * Visibility of completed proofs:: * Switching between proof scripts:: * View of processed files :: * Retracting across files:: * Asserting across files:: * Automatic multiple file handling:: * Escaping script management:: * Editing features:: @end menu @node Document centred working @section Document centred working @cindex annotation Proof scripts can be annotated with the output produced by the prover while they are checked. By hovering the mouse on the completed regions you can see any output that was produced when they were checked. Depending on the proof language (it works well with declarative languages), this may enable a ``document centred'' way of working, where you may not need to keep a separate window open for displaying prover output. This way of working is controlled by several settings. To help configure things appropriately for document-centred working, there are two short-cut commands: @lisp Proof-General -> Quick Options -> Display -> Document Centred Proof-General -> Quick Options -> Display -> Default @end lisp which change settings appropriately between a document centred mode and the original classic Proof General behaviour and appearance. The first command also engages automatic processing of the whole buffer, explained in the following section further below. The behaviour can be fine-tuned with the individual settings. Starting with the classic settings, first, you may select @lisp Proof-General -> Quick Options -> Processing -> Full Annotations @end lisp to ensure that the details are recorded in the script. This is not the default because it can cause long sequences of commands to execute more slowly as the output is collected from the prover eagerly when the commands are executed, and printing can be be slow for large and complex expressions. It also increases the space requirements for Emacs buffers. However, when interactively developing smaller files, it is very useful. Next, you may @i{de}select @lisp Proof-General -> Quick Options -> Display -> Auto Raise @end lisp which will prevent the prover output being eagerly displayed. You can still manually arrange your Emacs windows and frames to ensure the output buffers are present if you want. You may like to @i{de}select @lisp Proof General -> Quick Options -> Display -> Colour Locked @end lisp to prevent highlighting of the locked region. This text which has been checked and that which has not is less obvious, but you can see the position of the next command to be processed with the marker. If you have no colouring on the locked region, it can be hard to see where processing has got to. Look for the ``overlay marker'', a triangle in the left-hand fringe of the display, to see which line processing has stopped at. If it has stopped on a region with an error, you might want to see that. You can select @lisp Proof-General -> Quick Options -> Display -> Sticky Errors @end lisp to add a highlight for regions which did not successfully process on the last attempt. Whenever the region is edited, the highlight is removed. Finally, you may want to ensure that @lisp Proof-General -> Quick Options -> Read Only -> Undo On Edit @end lisp is selected. Undo on edit is a setting for the @code{proof-strict-read-only} variable. This allows you to freely edit the processed region, but first it automatically retracts back to the point of the edit. Comments can be edited freely without retraction. The configuration variables controlled by the above menu items can be customized as Emacs variables. The two settings which control interaction with the prover are @code{proof-full-annotation} and @code{proof-strict-read-only}. Note that you can also record the history of output from the prover @i{without} adding mouse hovers to the script. This is controlled by @code{proof-output-tooltips} which is also on the Display menu in Quick Options. @xref{Display customization}, for more information about customizing display options. @c TEXI DOCSTRING MAGIC: proof-full-annotation @defopt proof-full-annotation Non-nil causes Proof General to record output for all proof commands.@* Proof output is recorded as it occurs interactively; normally if many steps are taken at once, this output is suppressed. If this setting is used to enable it, the proof script can be annotated with full details. See also @samp{@code{proof-output-tooltips}} to enable automatic display of output on mouse hovers. The default value is @code{nil}. @end defopt @c TEXI DOCSTRING MAGIC: proof-strict-read-only @defopt proof-strict-read-only Whether Proof General is strict about the read-only region in buffers.@* If non-nil, an error is given when an attempt is made to edit the read-only region, except for the special value @code{'retract} which means undo first. If nil, Proof General is more relaxed (but may give you a reprimand!). The default value is @code{retract}. @end defopt @node Automatic processing @section Automatic processing @cindex Automatic processing @cindex autosend @vindex proof-autosend-enable If you like making your hair stand on end, the electric terminator mode is probably not enough. Proof General has another feature that will automatically send text to the prover, while you aren't looking. Enabling @lisp Proof-General -> Quick Options -> Processing -> Process Automatically @end lisp Causes Proof General to start processing text when Emacs is idle for a while. You can choose either to send just the next command beyond the point, or the whole buffer. See @lisp Proof-General -> Quick Options -> Processing -> Automatic Processing Mode @end lisp for the choices. The text will be sent in a fast loop that processes more quickly than @kbd{C-c C-b} (i.e., @code{proof-process-buffer}, the down toolbar button), but ignores user input and doesn't update the display. But the feature tries to be non-intrusive to the user: if you start to type something or use the mouse, the fast loop will be interrupted and revert to a slower interactive loop with display updates. In the check next command mode, the successfully checked region will briefly flash up as green to indicate it is okay. You can use @kbd{C-c C-.} (@code{proof-goto-end-of-locked}) to find out where processing got to, as usual. Text is only sent if the last interactive command processed some text (i.e., wasn't an undo step backwards into the buffer) and processing didn't stop with an error. To start automatic processing again after an error, simply hit @kbd{C-c C-n} after editing the buffer. To turn the automatic processing on or off from the keyboard, you can use the key binding: @table @kbd @item C-c > @code{proof-autosend-toggle} @end table @c TEXI DOCSTRING MAGIC: proof-autosend-toggle @deffn Command proof-autosend-toggle &optional arg Toggle @samp{@code{proof-autosend-enable}}. With @var{arg}, turn on iff ARG>0.@* This function simply uses @code{customize-set-variable} to set the variable. @end deffn @node Visibility of completed proofs @section Visibility of completed proofs @cindex Visibility of proofs Large developments may consist of large files with many proofs. To help see what has been proved without the detail of the proof itself, Proof General can hide portions of the proof script. Two different kinds of thing can be hidden: comments and (what Proof General designates as) the body of proofs. You can toggle the visibility of a proof script portion by using the context sensitive menu triggered by @b{clicking the right mouse button on a completed proof}, or the key @kbd{C-c v}, which runs @code{pg-toggle-visibility}. You can also select the ``disappearing proofs'' mode from the menu, @lisp Proof-General -> Quick Options -> Display -> Disappearing Proofs @end lisp This automatically hides each the body of each proof portion as it is completed by the proof assistant. Two further menu commands in the main Proof-General menu, @emph{Show all} and @emph{Hide all} apply to all the completed portions in the buffer. Notice that by design, this feature only applies to completed proofs, @emph{after} they have been processed by the proof assistant. When files are first visited in Proof General, no information is stored about proof boundaries. The relevant elisp functions and settings are mentioned below. @c TEXI DOCSTRING MAGIC: pg-toggle-visibility @deffn Command pg-toggle-visibility Toggle visibility of region under point. @end deffn @c TEXI DOCSTRING MAGIC: pg-show-all-proofs @deffn Command pg-show-all-proofs Display all completed proofs in the buffer. @end deffn @c TEXI DOCSTRING MAGIC: pg-hide-all-proofs @deffn Command pg-hide-all-proofs Hide all completed proofs in the buffer. @end deffn @c TEXI DOCSTRING MAGIC: proof-disappearing-proofs @defopt proof-disappearing-proofs Non-nil causes Proof General to hide proofs as they are completed. The default value is @code{nil}. @end defopt @node Switching between proof scripts @section Switching between proof scripts @cindex Switching between proof scripts Basic modularity in large proof developments can be achieved by splitting proof scripts across various files. Let's assume that you are in the middle of a proof development. You are working on a soundness proof of Hoare Logic in a file called@footnote{The suffix may depend of the specific proof assistant you are using e.g, Coq's proof script files have to end with @file{.v}.} @file{HSound.v}. It depends on a number of other files which develop underlying concepts e.g. syntax and semantics of expressions, assertions, imperative programs. You notice that the current lemma is too difficult to prove because you have forgotten to prove some more basic properties about determinism of the programming language. Or perhaps a previous definition is too cumbersome or even wrong. At this stage, you would like to visit the appropriate file, say @file{sos.v} and retract to where changes are required. Then, using script management, you want to develop some more basic theory in @file{sos.v}. Once this task has been completed (possibly involving retraction across even earlier files) and the new development has been asserted, you want to switch back to @file{HSound.v} and replay to the point you got stuck previously. Some hours (or days) later you have completed the soundness proof and are ready to tackle new challenges. Perhaps, you want to prove a property that builds on soundness or you want to prove an orthogonal property such as completeness. Proof General lets you do all of this while maintaining the consistency between proof script buffers and the state of the proof assistant. However, you cannot have more than one buffer where only a fraction of the proof script contains a locked region. Before you can employ script management in another proof script buffer, you must either fully assert or retract the current script buffer. @node View of processed files @section View of processed files Proof General tries to be aware of all files that the proof assistant has processed or is currently processing. In the best case, it relies on the proof assistant explicitly telling it whenever it processes a new file which corresponds@footnote{For example, LEGO generated additional compiled (optimised) proof script files for efficiency.} to a file containing a proof script. If the current proof script buffer depends on background material from other files, proof assistants typically process these files automatically. If you visit such a file, the whole file is locked as having been processed in a single step. From the user's point of view, you can only retract but not assert in this buffer. Furthermore, retraction is only possible to the @emph{beginning} of the buffer. @c This isn't strictly true, is it? We lock off buffers atomically, @c but spans in them to start with stay there. (Only meaningful @c for reading currently active scripting file) Unlike a script buffer that has been processed step-by-step via Proof General, automatically loaded script buffers do not pass through a ``red'' phase to indicate that they are currently being processed. This is a limitation of the present implementation. Proof General locks a buffer as soon as it sees the appropriate message from the proof assistant. Different proof assistants may use different messages: either @emph{early locking} when processing a file begins (e.g. LEGO) or @emph{late locking} when processing a file ends (e.g. Isabelle). With @emph{early locking}, you may find that a script which has only been partly processed (due to an error or interrupt, for example), is wrongly completely locked by Proof General. Visit the file and retract back to the start to fix this. With @emph{late locking}, there is the chance that you can break synchronization by editing a file as it is being read by the proof assistant, and saving it before processing finishes. In fact, there is a general problem of editing files which may be processed by the proof assistant automatically. Synchronization can be broken whenever you have unsaved changes in a proof script buffer and the proof assistant processes the corresponding file. (Of course, this problem is familiar from program development using separate editors and compilers). The good news is that Proof General can detect the problem and flashes up a warning in the response buffer. You can then visit the modified buffer, save it and retract to the beginning. Then you are back on track. @node Retracting across files @section Retracting across files @cindex Retraction Make sure that the current script buffer has either been completely asserted or retracted (Proof General enforces this). Then you can retract proof scripts in a different file. Simply visit a file that has been processed earlier and retract in it, using the retraction commands from @pxref{Script processing commands}. Apart from removing parts of the locked region in this buffer, all files which depend on it will be retracted (and thus unlocked) automatically. Proof General reminds you that now is a good time to save any unmodified buffers. @node Asserting across files @section Asserting across files @cindex Assertion Make sure that the current script buffer has either been completely asserted or retracted. Then you can assert proof scripts in a different file. Simply visit a file that contains no locked region and assert some command with the usual assertion commands, @pxref{Script processing commands}. Proof General reminds you that now is a good time to save any unmodified buffers. This is particularly useful as assertion may cause the proof assistant to automatically process other files. @node Automatic multiple file handling @section Automatic multiple file handling To make it easier to adapt Proof General for a proof assistant, there is another possibility for multiple file support --- that it is provided automatically by Proof General and not integrated with the file-management system of the proof assistant. In this case, Proof General assumes that the only files processed are the ones it has sent to the proof assistant itself. Moreover, it (conservatively) assumes that there is a linear dependency between files in the order they were processed. If you only have automatic multiple file handling, you'll find that any files loaded directly by the proof assistant are @emph{not} locked when you visit them in Proof General. Moreover, if you retract a file it may retract more than is strictly necessary (because it assumes a linear dependency). For further technical details of the ways multiple file scripting is configured, see @i{Handling multiple files} in the @i{Adapting Proof General} manual. @node Escaping script management @section Escaping script management @cindex Shell Occasionally you may want to review the dialogue of the entire session with the proof assistant, or check that it hasn't done something unexpected. Experienced users may also want to directly communicate with the proof assistant rather than sending commands via the minibuffer, @pxref{Proof assistant commands}. Although the proof shell is usually hidden from view, it is run in a buffer which you can use to interact with the prover if necessary. You can switch to it using the menu: @lisp Proof-General -> Buffers -> Shell @end lisp @b{Warning:} you can probably cause confusion by typing in the shell buffer! Proof General may lose track of the state of the proof assistant. Output from the assistant is only fully monitored when Proof General is in control of the shell. When in control, Proof General watches the output from the proof assistant to guess when a file is loaded or when a proof step is taken or undone. What happens when you type in the shell buffer directly depends on how complete the communication is between Proof General and the prover (which depends on the particular instantiation of Proof General). If synchronization is lost, you have two options to resynchronize. If you are lucky, it might suffice to use the key: @table @kbd @item C-c C-z @code{proof-frob-locked-end} @end table This command is disabled by default, to protect novices using it accidently. If @code{proof-frob-locked-end} does not work, you will need to restart script management altogether (@pxref{Proof assistant commands}). @c TEXI DOCSTRING MAGIC: proof-frob-locked-end @deffn Command proof-frob-locked-end Move the end of the locked region backwards to regain synchronization.@* Only for use by consenting adults. This command can be used to repair synchronization in case something goes wrong and you want to tell Proof General that the proof assistant has processed less of your script than Proof General thinks. You should only use it to move the locked region to the end of a proof command. @end deffn @node Editing features @section Editing features @cindex Input ring To make editing proof scripts more productive, Proof General provides some additional editing commands. One facility is the @i{input ring} of previously processed commands. This allows a convenient way of repeating an earlier command or a small edit of it. The feature is reminiscent of history mechanisms provided in shell terminals (and the implementation is borrowed from the Emacs Comint package). The input ring only contains commands which have been successfully processed (coloured blue). Duplicated commands are only entered once. @c this is disabled for now, it's not robust @c When commands are undone, they are removed from the ring. The size of the ring is set by the variable @code{pg-input-ring-size}. @kindex M-p @kindex M-n @table @kbd @item M-p @code{pg-previous-matching-input-from-input} @item M-n @code{pg-next-matching-input-from-input} @end table @c TEXI DOCSTRING MAGIC: pg-previous-input @deffn Command pg-previous-input arg Cycle backwards through input history, saving input.@* If called interactively, @var{arg} is given by the prefix argument. @end deffn @c TEXI DOCSTRING MAGIC: pg-next-input @deffn Command pg-next-input arg Cycle forwards through input history.@* If called interactively, @var{arg} is given by the prefix argument. @end deffn @c TEXI DOCSTRING MAGIC: pg-previous-matching-input @deffn Command pg-previous-matching-input regexp n Search backwards through input history for match for @var{regexp}.@* (Previous history elements are earlier commands.) With prefix argument @var{n}, search for Nth previous match. If @var{n} is negative, find the next or Nth next match. @end deffn @c TEXI DOCSTRING MAGIC: pg-next-matching-input @deffn Command pg-next-matching-input regexp n Search forwards through input history for match for @var{regexp}.@* (Later history elements are more recent commands.) With prefix argument @var{n}, search for Nth following match. If @var{n} is negative, find the previous or Nth previous match. @end deffn @c TEXI DOCSTRING MAGIC: pg-previous-matching-input-from-input @deffn Command pg-previous-matching-input-from-input n Search backwards through input history for match for current input.@* (Previous history elements are earlier commands.) With prefix argument @var{n}, search for Nth previous match. If @var{n} is negative, search forwards for the -Nth following match. @end deffn @c TEXI DOCSTRING MAGIC: pg-next-matching-input-from-input @deffn Command pg-next-matching-input-from-input n Search forwards through input history for match for current input.@* (Following history elements are more recent commands.) With prefix argument @var{n}, search for Nth following match. If @var{n} is negative, search backwards for the -Nth previous match. @end deffn @c ================================================================= @c @c CHAPTER: Unicode Tokens @c @node Unicode symbols and special layout support @chapter Unicode symbols and special layout support @cindex symbols @cindex X-Symbols @cindex Greek letters @cindex logical symbols @cindex mathematical symbols @cindex subscripts @cindex superscripts @cindex Maths Menu @cindex Tokens Mode Proof General inherits support for displaying Unicode (and any other) fonts from the underlying Emacs program. If you are lucky, your system will be able to use or synthesise a font that provides a rich set of mathematical symbols. To store symbols directly in files you need to use a particular coding, for example UTF-8. Newer Emacs versions can handle a multitude of different coding systems and will try to automatically detect an appropriate one; consult the Emacs documentation for more details. Of course, the prover that you are using will need to understand the same encodings and symbol meanings. Alternatively, you can use the @b{Unicode Tokens} mode provided in Proof General to display mathematical symbols in place of sequences of other characters (usually plain ASCII). This can provide better compatibility, portability, and flexibility. Even if you use real Unicode characters as prover input, the Unicode Tokens mode can provide some helpful facilities for input shorthands and giving special layout. @menu * Maths menu:: * Unicode Tokens mode:: * Configuring tokens symbols and shortcuts:: * Special layout:: * Moving between Unicode and tokens:: * Finding available tokens shortcuts and symbols:: * Selecting suitable fonts:: @end menu @node Maths menu @section Maths menu The @b{Maths Menu} minor mode (adapted from a menu by Dave Love) simply adds a menu @code{Maths} to the main menubar for inserting common mathematical symbols. You can enable or disable it via the menu @example Proof-General -> Quick Options -> Minor Modes -> Unicode Maths Menu @end example (@code{proof-maths-menu-toggle}). Whether or not the symbols display well the menus depends on the font used to display the menus (which depends on the Emacs version, toolkit and platform). Ordinarily, the symbols inserted into the text will be Unicode characters which will be saved in the file using the encoding selected by standard Emacs mechanisms. @node Unicode Tokens mode @section Unicode Tokens mode The @b{Unicode Tokens} minor mode has been written specially for Proof General (with thanks to Stefan Monnier for providing inspiration and a starting point). It supports the display of symbols when the underlying text of the file and buffer actually contains something else, typically, plain ASCII text. It provides backward compatibility with the older X-Symbol mode. Unicode Tokens can be enabled or disabled using the menu: @example Proof-General -> Quick Options -> Display -> Unicode Tokens @end example The mode to allows ASCII tokens (i.e., sequences of plain ASCII characters) to be displayed as Unicode character compositions, perhaps with additional text properties. The additional text properties allow the use of tokens to cause font changes (bold, italic), text size changes, and sub-script/super-script. For example, the ASCII sequences @code{/\} or @code{\} could be displayed as a conjunction symbol. @comment %% fixme The sequence @code{x __ y} might be written to display @code{y} as subscript. This allows a file to be stored in perfectly portable plain ASCII encoding, but be displayed and edited with real symbols and appealing layout. Of course, the proof assistant needs to understand the underlying tokens in each case. Technically, the mechanism is based on Emacs Font Lock facility, using the @code{composition} text property to display ASCII character sequence tokens as something else. This means that the underlying buffer text is @i{not} altered. This is a major advantage over the older X-Symbol (and the experimental version of Unicode Tokens in PG 3.7.1), which had the annoying risk of saving your buffer text in a corrupted format. This can never happen with the new mode. When the Unicode Tokens mode is enabled, Maths Menu is automatically modified to insert tokenised versions of the Unicode characters (whenever a reverse mapping can be found). This means that you can still use the Maths Menu to conveniently input symbols. You can easily add custom key bindings for particular symbols you need to enter often (@pxref{Adding your own keybindings} for examples). The Unicode Tokens mode also allows short-cut sequences of ordinary characters to quickly type tokens (similarly to the facility provided by X-Symbol). These, along with the token settings themselves, are configured on a per-prover basis. @node Configuring tokens symbols and shortcuts @section Configuring tokens symbols and shortcuts To edit the strings used to display tokens, or the collection of short-cuts, you can edit the file @code{@i{PA}-unicode-tokens.el}, or customize the main variables it contains, for example @code{@i{PA}-token-name-alist} and @code{@i{PA}-shortcut-alist}. @c FIXME: Isabelle support was removed. E.g., for Isabelle @example M-x customize-variable isar-token-name-alist RET @end example provides an interface to the tokens, and @example M-x customize-variable isar-shortcut-alist @end example an interface to the shortcuts. Where possible, it is better to use the more fine grained way is available to do this, which edits the separate tables which are combine to form the big list of tokens. This is available via the menus, e.g., in Isabelle, use @example Tokens -> Customize -> Extended Symbols @end example to customize the symbols used for the ``extended'' (non standard) symbol list. @node Special layout @section Special layout The Unicode Tokens mode supports both @i{symbol tokens} used to display character sequences in different ways and @i{control tokens} used to control the layout of the text in various ways, such as superscript, subscript, large, small, bold, italic, etc. (The size and position layout is managed using Emacs's @code{display} text property) As well as displaying token sequences as special symbols, symbol tokens themselves can define layout options as well; for example you might define a token @code{\} to display a large circled-plus glyph. If you try the customization mentioned in the section above you will see the options available when defining symbols. These options are fixed layout schemes which also make layout tokens easy to configure for provers. The layout possibilities include the ones shown in the table below. There are two ways of configuring control tokens for layout: @i{character controls} and @i{region controls}. The character controls apply to the next ``character'', although this is a prover-specific notion and might actually mean the next word or identifier. An example might be writing @code{BOLDCHAR x} to make a bold @b{x}. Similarly the region controls apply to a delineated region of text, for example, writing @code{BEGINBOLD this is bold ENDBOLD} could cause the enclosed text @b{this is bold} to be displayed in a bold font. The control tokens that have been configured populate the Tokens menu, so, for example, you may be able to select a region of text and then use the menu item: @example Tokens -> Format Region -> Bold @end example to cause the bold region tokens to be inserted around the selected text, which should cause the buffer presentation to show the text in a bold format (hiding the tokens). Here is the table of layout controls available. What you actually can use will depend on the configuration for the underlying prover. @table @code @item sub lower the text (subscript) @item sup raise the text (superscript) @item bold make the text be in the bold weight of the current font @item italic make the text be in the italic variant of the current font @item big make the text be in a bigger size of the current font @item small make the text be in a smaller size of the current font @item underline underline the text @item overline overline the text @item script display the text in a ``script'' font @item frakt display the text in a ``fraktur'' font @item serif display the text in a serif font @item sans display the text in a sans serif font @item keyword display the text in the keyword face (@code{font-lock-keyword-face}) @item function display the text in the function name face (@code{font-lock-function-name-face}) @item type display the text in the type name face (@code{font-lock-type-face}) @item preprocessor display the text in the preprocessor face (@code{font-lock-preprocessor-face}) @item doc display the text in the documentation face (@code{font-lock-doc-face}) @item builtin display the text in the builtin face (@code{font-lock-builtin-face}) @end table Notice that the fonts can be set conveniently by the menu commands @example Tokens -> Set Fonts -> Script @end example etc. @xref{Selecting suitable fonts}, for more. The symbols used to select the various font-lock faces (see @code{M-x list-faces-display} to show them) allow you to define custom colouring of text for proof assistant input and output, exploiting rich underlying syntax mechanisms of the prover. @c note: see unicode-tokens-fontsymb-properties @c TEXI DOCSTRING MAGIC: unicode-tokens-serif-font-face @deffn Face unicode-tokens-serif-font-face Serif (roman) font face. @end deffn @c TEXI DOCSTRING MAGIC: unicode-tokens-sans-font-face @deffn Face unicode-tokens-sans-font-face Sans serif font face. @end deffn @c TEXI DOCSTRING MAGIC: unicode-tokens-fraktur-font-face @deffn Face unicode-tokens-fraktur-font-face Fraktur font face. @end deffn @c TEXI DOCSTRING MAGIC: unicode-tokens-script-font-face @deffn Face unicode-tokens-script-font-face Script font face. @end deffn @node Moving between Unicode and tokens @section Moving between Unicode and tokens If you want to share text between applications (e.g., email some text from an Isabelle theory file which heavily uses symbols), it is useful to convert to and from Unicode with cut-and-paste operations. The default buffer cut and paste functions will copy the underlying text, which contains the tokens (ASCII format). To copy and convert or paste then convert back, use these commands: @example Tokens -> Copy as unicode Tokens -> Paste from unicode @end example Both of these are necessarily approximate. The buffer presentation may use additional controls (for super/subscript layout or bold fonts, etc), which cannot be converted. Pasting relies on being able to identify a unique token mapped from a single Unicode character; the token table may not include such an entry, or may be ambiguous. @c TEXI DOCSTRING MAGIC: unicode-tokens-copy @deffn Command unicode-tokens-copy beg end Copy presentation of region between @var{beg} and @var{end}.@* This is an approximation; it makes assumptions about the behaviour of symbol compositions, and will lose layout information. @end deffn @c TEXI DOCSTRING MAGIC: unicode-tokens-paste @deffn Command unicode-tokens-paste Paste text from clipboard, converting Unicode to tokens where possible. @end deffn If you are using a mixture of ``real'' Unicode and tokens like this you may want to be careful to check the buffer contents: the command @code{unicode-tokens-highlight-unicode} helps you to manage this. It is available on the Tokens menu as @example Tokens -> Highlight Real Unicode Chars @end example Alternative ways to check are to toggle the display of tokens using @example Tokens -> Reveal Symbol Tokens @end example (the similar entry for @code{Control Tokens} displays tokens being used to control layout). Or simply toggle the tokens mode, which will leave the true Unicode tokens untouched. @c TEXI DOCSTRING MAGIC: unicode-tokens-highlight-unicode @defvar unicode-tokens-highlight-unicode Non-nil to highlight Unicode characters. @end defvar @node Finding available tokens shortcuts and symbols @section Finding available tokens shortcuts and symbols Two commands (both on the Tokens menu) allow you to see the tokens and shortcuts available: @example Tokens -> List Tokens Tokens -> List Shortcuts @end example Additionally, you can view the complete Unicode character set available in the default Emacs font, with @example Tokens -> List Unicode Characters @end example (this uses a list adapted from Norman Walsh's @code{unichars.el}). Note that the Unicode Tokens modes displays symbols defined by symbol tokens in a special font. @c TEXI DOCSTRING MAGIC: unicode-tokens-list-tokens @deffn Command unicode-tokens-list-tokens Show a buffer of all tokens. @end deffn @c TEXI DOCSTRING MAGIC: unicode-tokens-list-shortcuts @deffn Command unicode-tokens-list-shortcuts Show a buffer of all the shortcuts available. @end deffn @c TEXI DOCSTRING MAGIC: unicode-tokens-list-unicode-chars @deffn Command unicode-tokens-list-unicode-chars Insert each Unicode character into a buffer.@* Lets you see which characters are available for literal display in your Emacs font. @end deffn @node Selecting suitable fonts @section Selecting suitable fonts The precise set of symbol glyphs that are available to you will depend in complicated ways on your operating system, Emacs version, configuration options used when Emacs was compiled, installed font sets, and (even) command line options used to start Emacs. So it is hard to give comprehensive and accurate advice in this manual. In general, things work @i{much} better with Emacs 23 than earlier versions. To improve flexibility, Unicode Tokens mode allows you to select another font to display symbols from the default font that is used to display text in the buffer. This is the font that is configured by the menu @example Tokens -> Set Fonts -> Symbol @end example its customization name is @code{unicode-tokens-symbol-font-face}, but notice that only the font family aspect of the face is used. Similarly, other fonts can be configured for controling different font families (script, fraktur, etc). For symbols, good results are possible by using a proportional font for displaying symbols that has many symbol glyphs, for example the main font StixGeneral font from the Stix Fonts project (@uref{http://www.stixfonts.org/}). At the time of writing you can obtain a beta version of these fonts in TTF format from @uref{http://olegueret.googlepages.com/stixfonts-ttf}. On recent Linux distributions and with an Emacs 23 build that uses Xft, simply copy these @code{ttf} files into the @code{.fonts} directory inside your home directory to make them available. Another font I like is @b{DejaVu Sans Mono}. It covers all of the standard Isabelle symbols. Some of the symbols are currently not perfect; however this font is an open source effort so users can contribute or suggest improvements. See @uref{http://dejavu-fonts.org}. If you are stuck with Emacs 22, you need to use the @i{fontset} mechanism which configures sets of fonts to use for display. The default font sets may not include enough symbols (typical symptom: symbols display as empty boxes). To address this, the menu command @example Tokens -> Set Fonts -> Make Fontsets @end example constructs a number of fontsets at particular point sizes, based on several widely available fonts. See @code{pg-fontsets.el} for the code. After running this command, you can select from additional fontsets from the menus for changing fonts. For further suggestions, please search (and contribute!) to the Proof General wiki at @uref{http://proofgeneral.inf.ed.ac.uk/wiki}. @c TEXI DOCSTRING MAGIC: unicode-tokens-symbol-font-face @deffn Face unicode-tokens-symbol-font-face The default font used for symbols. Only :family and :slant attributes are used. @end deffn @c TEXI DOCSTRING MAGIC: unicode-tokens-font-family-alternatives @defvar unicode-tokens-font-family-alternatives Not documented. @end defvar @c ================================================================= @c @c CHAPTER: Support for other Packages @c @node Support for other Packages @chapter Support for other Packages Proof General makes some configuration for other Emacs packages which provide various useful facilities that can make your editing more effective. Sometimes this configuration is purely at the proof assistant specific level (and so not necessarily available), and sometimes it is made using Proof General settings. When adding support for a new proof assistant, we suggest that these other packages are supported, as a convention. The packages currently supported include @code{font-lock}, @code{imenu} and @code{speedbar}, @code{outline-mode}, @code{completion}, and @code{etags}. @menu * Syntax highlighting:: * Imenu and Speedbar:: * Support for outline mode:: * Support for completion:: * Support for tags:: @end menu @node Syntax highlighting @section Syntax highlighting @vindex coq-mode-hooks @cindex font lock @cindex colour @c Proof General specifics Proof script buffers are decorated (or @i{fontified}) with colours, bold and italic fonts, etc, according to the syntax of the proof language and the settings for @code{font-lock-keywords} made by the proof assistant specific portion of Proof General. Moreover, Proof General usually decorates the output from the proof assistant, also using @code{font-lock}. To automatically switch on fontification in Emacs, you may need to engage @code{M-x global-font-lock-mode}. By the way, the choice of colour, font, etc, for each kind of markup is fully customizable in Proof General. Each @emph{face} (Emacs terminology) is controlled by its own customization setting. You can display a list of all of them using the customize menu: @lisp Proof General -> Advanced -> Customize -> Faces -> Proof Faces. @end lisp @node Imenu and Speedbar @section Imenu and Speedbar @vindex proof-goal-with-hole-regexp @vindex proof-goal-with-hole-result @c FIXME: should be see alsos. @cindex Speedbar @cindex Imenu @cindex index menu The Emacs package @code{imenu} (Index Menu) provides a menu built from the names of entities (e.g., theorems, definitions, etc) declared in a buffer. This allows easy navigation within the file. Proof General configures both packages automatically so that you can quickly jump to particular proofs in a script buffer. (Developers note: the automatic configuration is done with the settings @code{proof-goal-with-hole-regexp} and @code{proof-save-with-hole-regexp}. Better configuration may be made manually with several other settings, see the @i{Adapting Proof General} manual for further details). To use Imenu, select the option @lisp Proof-General -> Quick Options -> Minor Modes -> Index Menu @end lisp This adds an "Index" menu to the main menu bar for proof script buffers. You can also use @kbd{M-x imenu} for keyboard-driven completion of tags built from names in the buffer. Speedbar displays a file tree in a separate window on the display, allowing quick navigation. Middle/double-clicking or pressing @kbd{+} on a file icon opens up to display tags (definitions, theorems, etc) within the file. Middle/double-clicking on a file or tag jumps to that file or tag. To use Speedbar, use @lisp Proof-General -> Quick Options -> Minor Modes -> Speedbar @end lisp If you prefer the old fashioned way, `M-x speedbar' does the same job. For more information about Speedbar, see @uref{http://cedet.sourceforge.net/speedbar.shtml}. @node Support for outline mode @section Support for outline mode @cindex outline mode Proof General configures Emacs variables (@code{outline-regexp} and @code{outline-heading-end-regexp}) so that outline minor mode can be used on proof script files. The headings taken for outlining are the "goal" statements at the start of goal-save sequences, @pxref{Goal-save sequences}. If you want to use @code{outline} to hide parts of the proof script in the @emph{locked} region, you need to disable @code{proof-strict-read-only}. Use @kbd{M-x outline-minor-mode} to turn on outline minor mode. Functions for navigating, hiding, and revealing the proof script are available in menus. @c 3.5: this remark taken from BUGS Please note that outline-mode may not work well in processed proof script files, because of read-only restrictions of the protected region. This is an inherent problem with outline because it works by modifying the buffer. If you want to use outline with processed scripts, you can turn off the @code{Strict Read Only} option. See @inforef{Outline Mode, ,emacs} for more information about outline mode. @node Support for completion @section Support for completion @cindex completion You might find the @emph{completion} facility of Emacs useful when you're using Proof General. The key @kbd{C-RET} is defined to invoke the @code{complete} command. Pressing @kbd{C-RET} cycles through completions displaying hints in the minibuffer. Completions are filled in according to what has been recently typed, from a database of symbols. The database is automatically saved at the end of a session. Proof General has the additional facility for setting a completion table for each supported proof assistant, which gets loaded into the completion database automatically. Ideally the completion table would be set from the running process according to the identifiers available are within the particular context of a script file. But until this is available, this table may be set to contain a number of standard identifiers available for your proof assistant. The setting @code{@emph{PA}-completion-table} holds the list of identifiers for a proof assistant. The function @code{proof-add-completions} adds these into the completion database. @c TEXI DOCSTRING MAGIC: PA-completion-table @defvar PA-completion-table List of identifiers to use for completion for this proof assistant.@* Completion is activated with M-x complete. If this table is empty or needs adjusting, please make changes using @samp{@code{customize-variable}} and post suggestions at https://github.com/ProofGeneral/PG/issues @end defvar The completion facility uses a library @file{completion.el} which usually ships with Emacs, and supplies the @code{complete} function. @c FIXME: edited from default. @c NOT DOCSTRING MAGIC: complete @deffn Command complete Fill out a completion of the word before point. @* Point is left at end. Consecutive calls rotate through all possibilities. Prefix args: @table @kbd @item C-u leave point at the beginning of the completion, not the end. @item a number rotate through the possible completions by that amount @item 0 same as -1 (insert previous completion) @end table See the comments at the top of @samp{completion.el} for more info. @end deffn @node Support for tags @section Support for tags @cindex tags An Emacs "tags table" is a description of how a multi-file system is broken up into files. It lists the names of the component files and the names and positions of the functions (or other named subunits) in each file. Grouping the related files makes it possible to search or replace through all the files with one command. Recording the function names and positions makes possible the @kbd{M-.} command which finds the definition of a function by looking up which of the files it is in. Some instantiations of Proof General (currently Coq) are supplied with external programs (@file{coqtags}) for making tags tables. For example, invoking @samp{coqtags *.v} produces a file @file{TAGS} for all files @samp{*.v} in the current directory. Invoking @samp{coqtags `find . -name \*.v`} produces a file @file{TAGS} for all files ending in @samp{.v} in the current directory structure. Once a tag table has been made for your proof developments, you can use the Emacs tags mechanisms to find tags, and complete symbols from tags table. One useful key-binding you might want to make is to set the usual tags completion key @kbd{M-tab} to run @code{tag-complete-symbol} to use completion from names in the tag table. To set this binding in Proof General script buffers, put this code in your @file{.emacs} file: @lisp (add-hook 'proof-mode-hook (lambda () (local-set-key '(meta tab) 'tag-complete-symbol))) @end lisp Since this key-binding interferes with a default binding that users may already have customized (or may be taken by the window manager), Proof General doesn't do this automatically. Apart from completion, there are several other operations on tags. One common one is replacing identifiers across all files using @code{tags-query-replace}. For more information on how to use tags, @inforef{Tags, ,emacs}. To use tags for completion at the same time as the completion mechanism mentioned already, you can use the command @kbd{M-x add-completions-from-tags-table}. @c TEXI DOCSTRING MAGIC: add-completions-from-tags-table @deffn Command add-completions-from-tags-table Add completions from the current tags table. @end deffn @c ================================================================= @c @c CHAPTER: Proof by Pointing @c @node Subterm Activation and Proof by Pointing @chapter Subterm Activation and Proof by Pointing This chapter describes what you can do from inside the goals buffer, providing support for these features exists for your proof assistant. As of Proof General 4.4, this support has existed only for LEGO and proof-by-pointing functionality has been temporarily removed from the interface. If you would like to see subterm activation support for Proof General in another proof assistant, please petition the developers of that proof assistant to provide it! @menu * Goals buffer commands:: @end menu @node Goals buffer commands @section Goals buffer commands When you are developing a proof, the input focus (Emacs cursor) is usually on the script buffer. Therefore Proof General binds some mouse buttons for commands in the goals buffer, to avoid the need to move the cursor between buffers. The mouse bindings are these: @table @kbd @item mouse-1 @code{pg-goals-button-action} @item C-mouse-3 @code{proof-undo-and-delete-last-successful-command} @c @item mouse-3 @c @code{pg-goals-yank-subterm} @item C-S-mouse-1 @code{pg-identifier-under-mouse-query} @end table Where @kbd{mouse-1} indicates the left mouse button, and @kbd{mouse-3} indicates the right hand mouse button. The functions available provide a way to construct commands automatically (@code{pg-goals-button-action}) and to inspect identifiers (@code{pg-identifier-under-mouse-query}) as the Info toolbar button does. Proof-by-pointing is a cute idea. It lets you automatically construct parts of a proof by clicking. You can ask the proof assistant to try to do a step in the proof, based on where you click. If you don't like the command which was inserted into the script, you can comment use the control key with the right button to undo the step and delete it from your script (@code{proof-undo-and-delete-last-successful-command}). Proof-by-pointing may construct several commands in one go. These are sent back to the proof assistant altogether and appear as a single step in the proof script. However, if the proof is later replayed (without using PBP), the proof-by-pointing constructions will be considered as separate proof commands, as usual. The main function for proof-by-pointing is @code{pg-goals-button-action}. @c TEXI FIXME DOCSTRING MAGIC: pg-goals-button-action @deffn Command pg-goals-button-action event Construct a proof-by-pointing command based on the mouse-click @var{event}.@* This function should be bound to a mouse button in the Proof General goals buffer. The @var{event} is used to find the smallest subterm around a point. A position code for the subterm is sent to the proof assistant, to ask it to construct an appropriate proof command. The command which is constructed will be inserted at the end of the locked region in the proof script buffer, and immediately sent back to the proof assistant. If it succeeds, the locked region will be extended to cover the proof-by-pointing command, just as for any proof command the user types by hand. @end deffn Proof-by-pointing uses markup describing the term structure of the concrete syntax output by the proof assistant. This markup is useful in itself: it allows you to explore the structure of a term using the mouse (the smallest subexpression that the mouse is over is highlighted), and easily copy subterms from the output to a proof script. @c The right-hand mouse button provides this convenient way to copy @c subterms from the goals buffer, using the function @c @code{pg-goals-yank-subterm}. @c TEXI FIXME DOCSTRING MAGIC: pg-goals-yank-subterm @c @deffn Command pg-goals-yank-subterm event @c Copy the subterm indicated by the mouse-click @var{event}.@* @c This function should be bound to a mouse button in the Proof General @c goals buffer. @c The @var{event} is used to find the smallest subterm around a point. The @c subterm is copied to the @samp{@code{kill-ring}}, and immediately yanked (copied) @c into the current buffer at the current cursor position. @c In case the current buffer is the goals buffer itself, the yank @c is not performed. Then the subterm can be retrieved later by an @c explicit yank. @c @end deffn @c TEXI DOCSTRING MAGIC: pg-identifier-under-mouse-query @deffn Command pg-identifier-under-mouse-query event Query the prover about the identifier near mouse click @var{event}. @end deffn @c Proof General expects to parse @c term-structure annotations on the output syntax of the prover. @c It uses these to construct a message to the prover indicating @c where the user has clicked, and the proof assistant can @c response with a suggested tactic. @c ================================================================= @c @c CHAPTER @c @node Graphical Proof-Tree Visualization @chapter Graphical Proof-Tree Visualization @cindex proof-tree visualization Since version 4.2, Proof General supports proof-tree visualization on graphical desktops via the additional program Prooftree. Currently, proof-tree visualization is only supported for the Coq proof assistant. This version of Proof General requires Prooftree version 0.11. Check the @uref{http://askra.de/software/prooftree/, Prooftree website}, to see if some later versions are also compatible. (Because of the communication protocol, Proof General is always only compatible with certain versions of Prooftree.) For installation instructions and more detailed information about Prooftree, please refer to the @uref{http://askra.de/software/prooftree/, Prooftree website} and the @uref{http://askra.de/software/prooftree/prooftree.man.html, Prooftree man page}. For information about how to support proof-tree visualization for a different proof assistant, see Section @i{Configuring Proof-Tree Visualization} in the @i{Adapting Proof General} manual. @menu * Starting and Stopping Proof-Tree Visualization:: * Features of Prooftree:: * Prooftree Customization:: @end menu @node Starting and Stopping Proof-Tree Visualization @section Starting and Stopping Proof-Tree Visualization When proof-tree visualization is supported (currently only for the Coq proof assistant), you can start the visualization via the proof-tree button in the tool-bar, via the menu @lisp Proof-General -> Start/Stop Prooftree @end lisp or via the keyboard shortcut @kbd{C-c C-d}, all of which invoke @code{proof-tree-external-display-toggle}. If you are inside a proof, the graphical display is started immediately for your current proof. Otherwise the display starts as soon as you start the next proof. Starting the proof-tree display in the middle of a proof involves an automatic reexecution of your current proof script in the locked region, which should be almost unnoticeable, except for the time it takes. The proof-tree display stops at the end of the proof or when you invoke @code{proof-tree-external-display-toggle} by one of the three indicated means again. Alternatively you can also close the proof-tree window. Proof General launches only one instance of Prooftree, which can manage an arbitrary amount of proof-tree windows. @node Features of Prooftree @section Features of Prooftree The proof-tree window provides visual information about the status of the different branches in your proof (by coloring completely proved branches in green, for example) and means for inspecting previous proof states without the need to retract parts of your proof script. Currently, Prooftree provides the following features: @itemize @bullet @item Navigation in the proof tree and display of all previous proof states and proof commands. @item Display branches of the proof in different colors according to their proof state, distinguishing branches with open, partially or fully instantiated existential variables as well as branches that have been finished by a cheating command such as @code{admit}. @item Display the status of existential variables and their dependencies. @item Mark proof commands that introduce or instantiate a given existential variable. @item Snapshots of proof trees for reference when you retract your proof to try a different approach. @item Trigger a retract (undo) operation with a selected sequent as target. @item Insert proof scripts from the proof tree in the current buffer. @end itemize For a more elaborated description please consult the help dialog of Prooftree or the @uref{http://askra.de/software/prooftree/prooftree.man.html, Prooftree man page}. @node Prooftree Customization @section Prooftree Customization The location of the Prooftree program and command line arguments can be configured in the customization group @code{proof-tree}. You can visit this customization group inside a running instance of Proof General by typing @code{M-x customize-group proof-tree }. The graphical aspects of the proof-tree rendering, fonts and colors can be changed inside Prooftree by invoking the @code{Configuration} item of the main menu. Prover specific parts such as the regular expressions for recognizing subgoals, existential variables and navigation and cheating commands are in the customization group @code{proof-tree-internals}. Under normal circumstances there should be no need to change one of these internal settings. @c ================================================================= @c @c CHAPTER @c @node Customizing Proof General @chapter Customizing Proof General @cindex Customization There are two ways of customizing Proof General: it can be customized for a user's preferences using a particular proof assistant, or it can be customized by a developer to add support for a new proof assistant. The latter kind of customization we call instantiation, or @emph{adapting}. See the @i{Adapting Proof General} manual for how to do this. Here we cover the user-level customization for Proof General. There are two kinds of user-level settings in Proof General: @itemize @bullet @item Settings that apply @emph{globally} to all proof assistants. @item those that can be adjusted for each proof assistant @emph{individually}. @end itemize The first sort have names beginning with @code{proof-}. The second sort have names which begin with a symbol corresponding to the proof assistant: for example, @code{isa-}, @code{coq-}, etc. The symbol is the root of the mode name. @xref{Quick start guide}, for a table of the supported modes. To stand for an arbitrary proof assistant, we write @code{@emph{PA}-} for these names. In this chapter we only consider the generic settings: ones which apply to all proof assistants (globally or individually). The support for a particular proof assistant may provide extra individual customization settings not available in other proof assistants. See the chapters covering each assistant for details of those settings. @menu * Basic options:: * How to customize:: * Display customization:: * User options:: * Changing faces:: * Tweaking configuration settings:: @end menu @node Basic options @section Basic options Proof General has some common options which you can toggle directly from the menu: @lisp Proof-General -> Quick Options @end lisp The effect of changing one of these options will be seen immediately (or in the next proof step). The window-control options on this menu are described shortly. @xref{Display customization}. To save the current settings for these options (only), use the Save Options command in the submenu: @lisp Proof-General -> Quick Options -> Save Options @end lisp or @code{M-x customize-save-customized}. The options on this sub-menu are also available in the complete user customization options group for Proof General. For this you need to know a little bit about how to customize in Emacs. @node How to customize @section How to customize @cindex Using Customize @cindex Emacs customization library Proof General uses the Emacs customization library to provide a friendly interface. You can access all the customization settings for Proof General via the menu: @lisp Proof-General -> Advanced -> Customize @end lisp Using the customize facility is straightforward. You can select the setting to customize via the menus, or with @code{M-x customize-variable}. When you have selected a setting, you are shown a buffer with its current value, and facility to edit it. Once you have edited it, you can use the special buttons @var{set}, @var{save} and @var{done}. You must use one of @var{set} or @var{save} to get any effect. The @var{save} button stores the setting in your @file{.emacs} file. The command @kbd{M-x customize-save-customized} or Emacs menubar item @code{Options -> Save Options} saves all settings you have edited. A technical note. In the customize menus, the variable names mentioned later in this chapter may be abbreviated --- the "@code{proof}-" or similar prefixes are omitted. Also, some of the option settings may have more descriptive names (for example, @var{on} and @var{off}) than the low-level lisp values (non-@code{nil}, @code{nil}) which are mentioned in this chapter. These features make customize rather more friendly than raw lisp. You can also access the customize settings for Proof General from other (non-script) buffers. Use the menu: @lisp Options -> Customize Emacs -> Top-level Customization Group @end lisp and select the @code{External} and then @code{Proof-General} groups. The complete set of customization settings will only be available after Proof General has been fully loaded. Proof General is fully loaded when you visit a script file for the first time, or if you type @kbd{M-x load-library RET proof RET}. For more help with customize, see @inforef{Customization, ,emacs}. @node Display customization @section Display customization @cindex display customization @cindex multiple windows @cindex buffer display customization @cindex frames @cindex multiple frames @cindex three-buffer interaction @cindex auto raise By default, Proof General displays two buffers during scripting, in a split window on the display. One buffer is the script buffer. The other buffer is either the goals buffer (@code{*goals*}) or the response buffer (@code{*response*}). Proof General raises and switches between these last two automatically. Proof General allows several ways to customize this default display model, by splitting the Emacs frames in different ways and maximising the amount of information shown, or by using multiple frames. The customization options are explained below; they are also available on the menu: @lisp Proof-General -> Quick Options -> Display @end lisp and you can save your preferred default. If your screen is large enough, you may prefer to display all three of the interaction buffers at once. This is useful, for example, to see output from the @code{proof-find-theorems} command at the same time as the subgoal list. Set the user option @code{proof-three-window-enable} to make Proof General keep both the goals and response buffer displayed. If you prefer to switch windows and buffers manually when you want to see the prover output, you can customize the user option @code{proof-auto-raise-buffers} to prevent the automatic behaviour. You can browse interaction output by hovering the mouse over the command regions in the proof script. @c TEXI DOCSTRING MAGIC: proof-auto-raise-buffers @defopt proof-auto-raise-buffers If non-nil, automatically raise buffers to display latest output.@* If this is not set, buffers and windows will not be managed by Proof General. The default value is @code{t}. @end defopt @c TEXI DOCSTRING MAGIC: proof-three-window-enable @defopt proof-three-window-enable Whether response and goals buffers have dedicated windows.@* If non-nil, Emacs windows displaying messages from the prover will not be switchable to display other windows. This option can help manage your display. Setting this option triggers a three-buffer mode of interaction where the goals buffer and response buffer are both displayed, rather than the two-buffer mode where they are switched between. It also prevents Emacs automatically resizing windows between proof steps. If you use several frames (the same Emacs in several windows on the screen), you can force a frame to stick to showing the goals or response buffer. The default value is @code{t}. @end defopt Sometimes during script management, there is no response from the proof assistant to some command. In this case you might like the empty response window to be hidden so you have more room to see the proof script. The setting @code{proof-delete-empty-windows} helps you do this. @c TEXI DOCSTRING MAGIC: proof-delete-empty-windows @defopt proof-delete-empty-windows If non-nil, automatically remove windows when they are cleaned.@* For example, at the end of a proof the goals buffer window will be cleared; if this flag is set it will automatically be removed. If you want to fix the sizes of your windows you may want to set this variable to @code{'nil'} to avoid windows being deleted automatically. If you use multiple frames, only the windows in the currently selected frame will be automatically deleted. The default value is @code{nil}. @end defopt This option only has an effect when you have set @code{proof-three-window-mode}. If you are working on a machine with a window system, you can use Emacs to manage several @i{frames} on the display, to keep the goals buffer displayed in a fixed place on your screen and in a certain font, for example. A convenient way to do this is via the user option @c TEXI DOCSTRING MAGIC: proof-multiple-frames-enable @defopt proof-multiple-frames-enable Whether response and goals buffers have separate frames.@* If non-nil, Emacs will make separate frames (screen windows) for the goals and response buffers, by altering the Emacs variable @samp{@code{special-display-regexps}}. The default value is @code{nil}. @end defopt Multiple frames work best when @code{proof-delete-empty-windows} is off and @code{proof-three-window-mode} is on. Finally, there are two commands available which help to switch between buffers or refresh the window layout. These are on the menu: @lisp Proof-General -> Buffers @end lisp @c TEXI DOCSTRING MAGIC: proof-display-some-buffers @deffn Command proof-display-some-buffers Display the response, trace, goals, or shell buffer, rotating.@* A fixed number of repetitions of this command switches back to the same buffer. Also move point to the end of the response buffer if it's selected. If in three window or multiple frame mode, display two buffers. The idea of this function is to change the window->buffer mapping without adjusting window layout. @end deffn @c TEXI DOCSTRING MAGIC: proof-layout-windows @deffn Command proof-layout-windows Refresh the display of windows according to current display mode. For multiple frame mode, this function obeys the setting of @samp{@code{pg-response-eagerly-raise}}, which see. For single frame mode: - In two panes mode, this uses a canonical layout made by splitting Emacs windows in equal proportions. The splitting is vertical if Emacs width is smaller than @samp{@code{split-width-threshold}} and horizontal otherwise. You can then adjust the proportions by dragging the separating bars. - In three pane mode, there are three display modes, depending @lisp where the three useful buffers are displayed: scripting buffer, goals buffer and response buffer. Here are the three modes: - vertical: the 3 buffers are displayed in one column. - hybrid: 2 columns mode, left column displays scripting buffer and right column displays the 2 others. - horizontal: 3 columns mode, one for each buffer (script, goals, response). By default, the display mode is automatically chosen by considering the current Emacs frame width: if it is smaller than @samp{@code{split-width-threshold}} then vertical mode is chosen, otherwise if it is smaller than 1.5 * @samp{@code{split-width-threshold}} then hybrid mode is chosen, finally if the frame is larger than 1.5 * @samp{@code{split-width-threshold}} then the horizontal mode is chosen. You can change the value of @samp{@code{split-width-threshold}} at your will. If you want to force one of the layouts, you can set variable @samp{@code{proof-three-window-mode-policy}} to @code{'vertical}, @code{'horizontal} or @code{'hybrid}. The default value is @code{'smart} which sets the automatic behaviour described above. @end lisp @end deffn @c TEXI DOCSTRING MAGIC: proof-shrink-windows-tofit @defopt proof-shrink-windows-tofit If non-nil, automatically shrink output windows to fit contents.@* In single-frame mode, this option will reduce the size of the goals and response windows to fit their contents. The default value is @code{nil}. @end defopt @c TEXI DOCSTRING MAGIC: proof-colour-locked @defopt proof-colour-locked If non-nil, colour the locked region with @samp{@code{proof-locked-face}}.@* If this is not set, buffers will have no special face set on locked regions. The default value is @code{t}. @end defopt @c TEXI DOCSTRING MAGIC: proof-output-tooltips @defopt proof-output-tooltips Non-nil causes Proof General to add tooltips for prover output.@* Hovers will be added when this option is non-nil. Prover outputs can be displayed when the mouse hovers over the region that produced it and output is available (see @samp{@code{proof-full-annotation}}). If output is not available, the type of the output region is displayed. Changes of this option will not be reflected in already-processed regions of the script. The default value is @code{nil}. @end defopt @node User options @section User options @c Index entries for each option 'concept' @cindex User options @cindex Strict read-only @cindex Undo in read-only region @cindex Query program name @cindex Dedicated windows @cindex Remote host @cindex Toolbar follow mode @cindex Toolbar disabling @cindex Toolbar button enablers @cindex Proof script indentation @cindex Indentation @cindex Remote shell @cindex Running proof assistant remotely @cindex Input ring @c @cindex formatting proof script Here is a list of the important user options for Proof General, apart from the display options mentioned above. User options can be set via the customization system already mentioned, via the old-fashioned @code{M-x edit-options} mechanism, or simply by adding @code{setq}'s to your @file{.emacs} file. The first approach is strongly recommended. Unless mentioned, all of these settings can be changed dynamically, without needing to restart Emacs to see the effect. But you must use customize to be sure that Proof General reconfigures itself properly. @c TEXI DOCSTRING MAGIC: proof-splash-enable @defopt proof-splash-enable If non-nil, display a splash screen when Proof General is loaded. The default value is @code{t}. @end defopt @c TEXI DOCSTRING MAGIC: proof-electric-terminator-enable @defopt proof-electric-terminator-enable If non-nil, use electric terminator mode.@* If electric terminator mode is enabled, pressing a terminator will automatically issue @samp{proof-assert-next-command} for convenience, to send the command straight to the proof process. If the command you want to send already has a terminator character, you don't need to delete the terminator character first. Just press the terminator somewhere nearby. Electric! The default value is @code{nil}. @end defopt @c TEXI DOCSTRING MAGIC: proof-next-command-insert-space @defopt proof-next-command-insert-space If non-nil, PG will use heuristics to insert newlines or spaces in scripts.@* In particular, if electric terminator is switched on, spaces or newlines will be inserted as the user types commands to the prover. The default value is @code{t}. @end defopt @c TEXI DOCSTRING MAGIC: proof-toolbar-enable @defopt proof-toolbar-enable If non-nil, display Proof General toolbar for script buffers. The default value is @code{t}. @end defopt @c TEXI DOCSTRING MAGIC: proof-query-file-save-when-activating-scripting @defopt proof-query-file-save-when-activating-scripting If non-nil, query user to save files when activating scripting. Often, activating scripting or executing the first scripting command of a proof script will cause the proof assistant to load some files needed by the current proof script. If this option is non-nil, the user will be prompted to save some unsaved buffers in case any of them corresponds to a file which may be loaded by the proof assistant. You can turn this option off if the save queries are annoying, but be warned that with some proof assistants this may risk processing files which are out of date with respect to the loaded buffers! The default value is @code{t}. @end defopt @c TEXI DOCSTRING MAGIC: PA-script-indent @defopt PA-script-indent If non-nil, enable indentation code for proof scripts. The default value is @code{t}. @end defopt @c TEXI DOCSTRING MAGIC: PA-one-command-per-line @defopt PA-one-command-per-line If non-nil, format for newlines after each command in a script. The default value is @code{t}. @end defopt @c TEXI DOCSTRING MAGIC: proof-omit-proofs-option @defvar proof-omit-proofs-option Set to t to omit complete opaque proofs for speed reasons.@* When t, complete opaque proofs in the asserted region are not sent to the proof assistant (and thus not checked). For files with big proofs this can drastically reduce the processing time for the asserted region at the cost of not checking the proofs. For partial and non-opaque proofs in the asserted region all proof commands are sent to the proof assistant. Using a prefix argument for @samp{@code{proof-goto-point}} (M-x @code{proof-goto-point}) or @samp{@code{proof-process-buffer}} (M-x @code{proof-process-buffer}) temporarily disables omitting proofs. @end defvar @c TEXI DOCSTRING MAGIC: proof-prog-name-ask @defopt proof-prog-name-ask If non-nil, query user which program to run for the inferior process. The default value is @code{nil}. @end defopt @c TEXI DOCSTRING MAGIC: PA-prog-args @defvar PA-prog-args Arguments to be passed to @samp{@code{proof-prog-name}} to run the proof assistant.@* If non-nil, will be treated as a list of arguments for @samp{@code{proof-prog-name}}. Otherwise @samp{@code{proof-prog-name}} will be split on spaces to form arguments. Remark: Arguments are interpreted strictly: each one must contain only one word, with no space (unless it is the same word). For example if the arguments are -x foo -y bar, then the list should be '("-x" "foo" "-y" "bar"), notice that '("-x foo" "-y bar") is @strong{wrong}. @end defvar @c TEXI DOCSTRING MAGIC: PA-prog-env @defvar PA-prog-env Modifications to @samp{@code{process-environment}} made before running @samp{@code{proof-prog-name}}.@* Each element should be a string of the form ENVVARNAME=@var{value}. They will be added to the environment before launching the prover (but not pervasively). For example for coq on Windows you might need something like: (setq @code{coq-prog-env} '("HOME=C:\Program Files\Coq\")) @end defvar @c TEXI DOCSTRING MAGIC: proof-prog-name-guess @defopt proof-prog-name-guess If non-nil, use @samp{@code{proof-guess-command-line}} to guess @samp{@code{proof-prog-name}}.@* This option is compatible with @samp{@code{proof-prog-name-ask}}. No effect if @samp{@code{proof-guess-command-line}} is nil. The default value is @code{nil}. @end defopt @c TEXI DOCSTRING MAGIC: proof-tidy-response @defopt proof-tidy-response Non-nil indicates that the response buffer should be cleared often.@* The response buffer can be set either to accumulate output, or to clear frequently. With this variable non-nil, the response buffer is kept tidy by clearing it often, typically between successive commands (just like the goals buffer). Otherwise the response buffer will accumulate output from the prover. The default value is @code{t}. @end defopt @c TEXI DOCSTRING MAGIC: proof-keep-response-history @defopt proof-keep-response-history Whether to keep a browsable history of responses.@* With this feature enabled, the buffers used for prover responses will have a history that can be browsed without processing/undoing in the prover. (Changes to this variable take effect after restarting the prover). The default value is @code{nil}. @end defopt @c TEXI DOCSTRING MAGIC: pg-input-ring-size @defopt pg-input-ring-size Size of history ring of previous successfully processed commands. The default value is @code{32}. @end defopt @c TEXI DOCSTRING MAGIC: proof-general-debug @defopt proof-general-debug Non-nil to run Proof General in debug mode.@* This changes some behaviour (e.g. markup stripping) and displays debugging messages in the response buffer. To avoid erasing messages shortly after they're printed, set @samp{@code{proof-tidy-response}} to nil. This is only useful for PG developers. The default value is @code{nil}. @end defopt @c ******* NON-BOOLEANS ******* @c TEXI DOCSTRING MAGIC: proof-follow-mode @defopt proof-follow-mode Choice of how point moves with script processing commands.@* One of the symbols: @code{'locked}, @code{'follow}, @code{'followdown}, @code{'ignore}. If @code{'locked}, point sticks to the end of the locked region. If @code{'follow}, point moves just when needed to display the locked region end. If @code{'followdown}, point if necessary to stay in writeable region If @code{'ignore}, point is never moved after movement commands or on errors. If you choose @code{'ignore}, you can find the end of the locked using M-x @code{proof-goto-end-of-locked} The default value is @code{locked}. @end defopt @c TEXI DOCSTRING MAGIC: proof-auto-action-when-deactivating-scripting @defopt proof-auto-action-when-deactivating-scripting If @code{'retract} or @code{'process}, do that when deactivating scripting. With this option set to @code{'retract} or @code{'process}, when scripting is turned off in a partly processed buffer, the buffer will be retracted or processed automatically. With this option unset (nil), the user is questioned instead. Proof General insists that only one script buffer can be partly processed: all others have to be completely processed or completely unprocessed. This is to make sure that handling of multiple files makes sense within the proof assistant. NB: A buffer is completely processed when all non-whitespace is locked (coloured blue); a buffer is completely unprocessed when there is no locked region. For some proof assistants (such as Coq) fully processed buffers make no sense. Setting this option to @code{'process} has then the same effect as leaving it unset (nil). (This behaviour is controlled by @samp{@code{proof-no-fully-processed-buffer}}.) The default value is @code{nil}. @end defopt @c TEXI DOCSTRING MAGIC: proof-rsh-command @defopt proof-rsh-command Shell command prefix to run a command on a remote host.@* For example, @lisp ssh bigjobs @end lisp Would cause Proof General to issue the command @samp{ssh bigjobs coqtop} to start Coq remotely on our large compute server called @samp{bigjobs}. The protocol used should be configured so that no user interaction (passwords, or whatever) is required to get going. For proper behaviour with interrupts, the program should also communicate signals to the remote host. The default value is @code{nil}. @end defopt @node Changing faces @section Changing faces The numerous fonts and colours that Proof General uses are configurable. If you alter faces through the customize menus (or the command @kbd{M-x customize-face}), only the particular kind of display in use (colour window system, monochrome window system, console, @dots{}) will be affected. This means you can keep separate default settings for each different display environment where you use Proof General. As well as the faces listed below, Proof General may use the regular @code{font-lock-} faces (eg @code{font-lock-keyword-face}, @code{font-lock-variable-name-face}, etc) for fontifying the proof script or proof assistant output. These can be altered to your taste just as easily, but note that changes will affect all other modes which use them! @menu * Script buffer faces:: * Goals and response faces:: @end menu @node Script buffer faces @subsection Script buffer faces @c TEXI DOCSTRING MAGIC: proof-queue-face @deffn Face proof-queue-face Face for commands in proof script waiting to be processed. @end deffn @c TEXI DOCSTRING MAGIC: proof-locked-face @deffn Face proof-locked-face Face for locked region of proof script (processed commands). @end deffn @c TEXI DOCSTRING MAGIC: proof-script-sticky-error-face @deffn Face proof-script-sticky-error-face Proof General face for marking an error in the proof script. @end deffn @c TEXI DOCSTRING MAGIC: proof-script-highlight-error-face @deffn Face proof-script-highlight-error-face Proof General face for highlighting an error in the proof script. @end deffn @c TEXI DOCSTRING MAGIC: proof-mouse-highlight-face @deffn Face proof-mouse-highlight-face General mouse highlighting face used in script buffer. @end deffn @c TEXI DOCSTRING MAGIC: proof-highlight-dependent-face @deffn Face proof-highlight-dependent-face Face for showing (backwards) dependent parts. @end deffn @c TEXI DOCSTRING MAGIC: proof-highlight-dependency-face @deffn Face proof-highlight-dependency-face Face for showing (forwards) dependencies. @end deffn @c TEXI DOCSTRING MAGIC: proof-declaration-name-face @deffn Face proof-declaration-name-face Face for declaration names in proof scripts.@* Exactly what uses this face depends on the proof assistant. @end deffn @c TEXI DOCSTRING MAGIC: proof-tacticals-name-face @deffn Face proof-tacticals-name-face Face for names of tacticals in proof scripts.@* Exactly what uses this face depends on the proof assistant. @end deffn @node Goals and response faces @subsection Goals and response faces @c TEXI DOCSTRING MAGIC: proof-error-face @deffn Face proof-error-face Face for error messages from proof assistant. @end deffn @c TEXI DOCSTRING MAGIC: proof-warning-face @deffn Face proof-warning-face Face for warning messages.@* Warning messages can come from proof assistant or from Proof General itself. @end deffn @c TEXI DOCSTRING MAGIC: proof-debug-message-face @deffn Face proof-debug-message-face Face for debugging messages from Proof General. @end deffn @c TEXI DOCSTRING MAGIC: proof-boring-face @deffn Face proof-boring-face Face for boring text in proof assistant output. @end deffn @c TEXI DOCSTRING MAGIC: proof-active-area-face @deffn Face proof-active-area-face Face for showing active areas (clickable regions), outside of subterm markup. @end deffn @c TEXI DOCSTRING MAGIC: proof-eager-annotation-face @deffn Face proof-eager-annotation-face Face for important messages from proof assistant. @end deffn @c Maybe this detail of explanation belongs in the internals, @c with just a hint here. The slightly bizarre name of the last face comes from the idea that while large amounts of output are being sent from the prover, some messages should be displayed to the user while the bulk of the output is hidden. The messages which are displayed may have a special annotation to help Proof General recognize them, and this is an "eager" annotation in the sense that it should be processed as soon as it is observed by Proof General. @node Tweaking configuration settings @section Tweaking configuration settings This section is a note for advanced users. Configuration settings are the per-prover customizations of Proof General. These are not intended to be adjusted by the user. But occasionally you may like to test changes to these settings to improve the way Proof General works. You may want to do this when a proof assistant has a flexible proof script language in which one can define new tactics or even operations, and you want Proof General to recognize some of these which the default settings don't mention. So please feel free to try adjusting the configuration settings and report to us if you find better default values than the ones we have provided. The configuration settings appear in the customization group @code{prover-config}, or via the menu @lisp Proof-General -> Internals -> Prover Config @end lisp One basic example of a setting you may like to tweak is: @c TEXI DOCSTRING MAGIC: proof-assistant-home-page @defvar proof-assistant-home-page Web address for information on proof assistant.@* Used for Proof General's help menu. @end defvar Most of the others are more complicated. For more details of the settings, see @i{Adapting Proof General} for full details. To browse the settings, you can look through the customization groups @code{prover-config}, @code{proof-script} and @code{proof-shell}. The group @code{proof-script} contains the configuration variables for scripting, and the group @code{proof-shell} contains those for interacting with the proof assistant. Unfortunately, although you can use the customization mechanism to set and save these variables, saving them may have no practical effect because the default settings are mostly hard-wired into the proof assistant code. Ones we expect may need changing appear as proof assistant specific configurations. For example, @code{proof-assistant-home-page} is set in the Coq code from the value of the customization setting @code{coq-www-home-page}. At present there is no easy way to save changes to other configuration variables across sessions, other than by editing the source code. (In future versions of Proof General, we plan to make all configuration settings editable in Customize, by shadowing the settings as prover specific ones using the @code{@emph{PA}-} mechanism). @c Please contact us if this proves to be a problem for any variable. @c ================================================================= @c @c CHAPTER @c @node Hints and Tips @chapter Hints and Tips Apart from the packages officially supported in Proof General, many other features of Emacs are useful when using Proof General, even though they need no specific configuration for Proof General. It is worth taking a bit of time to explore the Emacs manual to find out about them. Here we provide some hints and tips for a couple of Emacs features which users have found valuable with Proof General. Further contributions to this chapter are welcomed! @menu * Adding your own keybindings:: * Using file variables:: * Using abbreviations:: @end menu @node Adding your own keybindings @section Adding your own keybindings @cindex keybindings Proof General follows Emacs convention for file modes in using @key{C-c} prefix key-bindings for its own functions, which is why some of the default keyboard short-cuts are quite lengthy. Some users may prefer to add additional key-bindings for shorter sequences. This can be done interactively with the command @code{M-x local-set-key}, or for longevity, by adding code like this to your @file{.emacs} file: @lisp (eval-after-load "proof-script" '(progn (define-key proof-mode-map [(control n)] 'proof-assert-next-command-interactive) (define-key proof-mode-map [(control b)] 'proof-undo-last-successful-command) )) @end lisp This lisp fragment adds bindings for every buffer in proof script mode (the Emacs keymap is called @code{proof-mode-map}). To just affect one prover, use a keymap name like @code{coq-mode-map} and evaluate after the library @code{coq} has been loaded. To find the names of the functions you may want to bind, look in this manual, or query current bindings interactively with @kbd{C-h k}. This command (@code{describe-key}) works for menu operations as well; also use it to discover the current key-bindings which you're losing by declarations such as those above. By default, @kbd{C-n} is @code{next-line} and @kbd{C-b} is @code{backward-char-command}; neither are really needed if you have working cursor keys. If your keyboard has a @i{super} modifier (on my PC keyboard it has a Windows symbol and is next to the control key), you can freely bind keys on that modifier globally (since none are used by default). Use lisp like this: @lisp (global-set-key [?\s-l] 'maths-menu-insert-lambda) (global-set-key [?\s-l] 'maths-menu-insert-lambda) (global-set-key [?\s-l] 'maths-menu-insert-lambda) (global-set-key [?\s-L] 'maths-menu-insert-Lambda) (global-set-key [?\s-D] 'maths-menu-insert-Delta) (global-set-key [?\s-a] 'maths-menu-insert-for-all) (global-set-key [?\s-e] 'maths-menu-insert-there-exists) (global-set-key [?\s-t] 'maths-menu-insert-down-tack) (global-set-key [?\s-b] 'maths-menu-insert-up-tack) (global-set-key [?\s-\#] 'maths-menu-insert-music-sharp-sign) (global-set-key [?\s-\.] 'maths-menu-insert-horizontal-ellipsis) (global-set-key [?\s-3] 'proof-three-window-toggle) @end lisp This defines a bunch of short-cuts for inserting symbols taken from the Maths Menu, @pxref{Unicode symbols and special layout support} and a short-cut for enabling three window mode, @pxref{Display customization}. @node Using file variables @section Using file variables @cindex file variables A very convenient way to customize file-specific variables is to use File Variables (@inforef{File Variables, ,emacs}). This feature of Emacs permits to specify values for certain Emacs variables when a file is loaded. File variables and their values are written as a list at the end of the file. @b{Remark 1:} The examples in the following are for Coq but the trick is applicable to other provers. @b{Remark 2:} For Coq specifically, there is a recommended other way of configuring Coq command-line options: project files (@ref{Using the Coq project file}). However file variables are useful to set a specific @code{coqtop} executable, or for defining file-specific command-line options. Actually, since project files are intended to be included in the distribution of a library (and included in its repository), the file variables can be used to set non versioned options like @code{coq-prog-name}. @b{Remark 3:} For obvious security reasons, when emacs reads file variables, it asks for permission to the user before applying the assignment. You should read carefully the content of the variable before accepting. You can hit @code{!} to accept definitely the exact values at hand. Let us take a concrete example: suppose the makefile for @file{foo.v} is located in directory @file{.../dir/}, you need the right compile command in the @code{compile-command} emacs variable. Moreover suppose that you want @code{coqtop} to be found in a non standard directory. To put these values in file variables, here is what you should put at the end of @file{foo.v}: @lisp (* *** Local Variables: *** *** coq-prog-name: "../../coqsrc/bin/coqtop" *** *** compile-command: "make -C .. -k bar/foo.vo" *** *** End:*** *) @end lisp And then the right call to make will be done if you use the @kbd{M-x compile} command, and the correct @code{coqtop} will be called by ProofGeneral. Note that the lines are commented in order to be ignored by the proof assistant. It is possible to use this mechanism for all variables, @inforef{File Variables, ,emacs}. @emph{NOTE:} @code{coq-prog-name} should contain only the @code{coqtop} executable, @emph{not the options}. One can also specify file variables on a per directory basis, @inforef{Directory Variables, ,emacs}. You can achieve almost the same as above for all the files of a directory by storing @lisp ((coq-mode . ((coq-prog-name . "/home/xxx/yyy/coqsrc/bin/coqtop") (compile-command . "make -C .. -k")))) @end lisp into the file @code{.dir-locals.el} in one of the parent directories. The value in this file must be an alist that maps mode names to alists, where these latter alists map variables to values. You can aso put arbitrary code in this file @inforef{Directory Variables, ,emacs}. @emph{Note:} if you add such content to the @code{.dir-locals.el} file you should restart Emacs or revert your buffer. @node Using abbreviations @section Using abbreviations A very useful package of Emacs supports automatic expansions of abbreviations as you type, @inforef{Abbrevs, ,emacs}. For example, the proof assistant Coq has many command strings that are long, such as ``reflexivity,'' ``Inductive,'' ``Definition'' and ``Discriminate.'' Here is a part of the Coq Proof General abbreviations: @lisp "abs" "absurd " "ap" "apply " "as" "assumption" @end lisp The above list was taken from the file that Emacs saves between sessions. The easiest way to configure abbreviations is as you write, by using the key presses @kbd{C-x a g} (@code{add-global-abbrev}) or @kbd{C-x a i g} (@code{inverse-add-global-abbrev}). To enable automatic expansion of abbreviations (which can be annoying), the @code{Abbrev} minor mode, type @kbd{M-x abbrev-mode RET}. When you are not in Abbrev mode you can expand an abbreviation by pressing @kbd{C-x '} (@code{expand-abbrev}). See the Emacs manual for more details. @c ================================================================= @c @c CHAPTER: Coq Proof General @c @node Coq Proof General @chapter Coq Proof General @macro coqrefman {sectionurl,txt} @uref{https://coq.inria.fr/distrib/current/refman/\sectionurl\,\txt\} @end macro Coq Proof General is an instantiation of Proof General for the Coq proof assistant. It supports most of the generic features of Proof General. @menu * Coq-specific commands:: * Using the Coq project file:: * Proof using annotations:: * Multiple File Support:: * Omitting proofs for speed:: * Editing multiple proofs:: * User-loaded tactics:: * Indentation tweaking:: * Holes feature:: * Proof-Tree Visualization:: * Showing Proof Diffs:: * Opam-switch-mode support:: @end menu @node Coq-specific commands @section Coq-specific commands @kindex C-c C-a C-i @kindex C-c C-a C-a @kindex C-c C-a C-b @kindex C-c C-a C-s @kindex C-c C-a C-) @kindex C-c C-a C-p @kindex C-c C-a C-c @kindex C-c C-a C-o Coq Proof General supplies the following key-bindings: @table @kbd @item C-c C-a C-i Inserts ``intros '' and also introduces the name of the hypothesis proposed by coq on the current goal. @item C-c C-a C-s Show the goal (enter for the current goal, i for the ith goal). Add the prefix C-u to see the answer with all pretty printing options temporarily disable (Set Printing All). @item C-c C-a C-c Prompts for ``Check '' query arguments, the default input name is built from the identifier under the cursor. Add the prefix C-u to see the answer with all pretty printing options temporarily disable (Set Printing All). @item C-c C-a C-p The same for a ``Print '' query. @item C-c C-a C-b The same for a ``About '' query. @item C-c C-a C-a The same for a ``Search '' query (no C-u prefix). @item C-c C-a C-o The same for a Search ``SearchIsos'' (no C-u prefix). @item C-c C-a C-) Inserts ``End .'' (this should work well with nested sections). @end table @node Using the Coq project file @section Using the Coq project file The Coq project file is the recommended way to configure the Coq load path and the mapping of logical module names to physical file path (-R,-Q,-I options). The project file is typically named @code{_CoqProject} and must be located at the directory root of your Coq project. Proof General searches for the Coq project file starting at the current directory and walking the directory structure upwards. The Coq project file contains the common options (especially @code{-R}) and a list of the files of the project, see the Coq reference manual, Section @coqrefman{practical-tools/utilities.html#building-a-coq-project, ``Building a Coq project''}. @c @uref{https://coq.inria.fr/distrib/current/refman/practical-tools/utilities.html#building-a-coq-project, @c ``Building a Coq project''}. The Coq project file should contain something like: @verbatim -R foo bar -I foo2 -arg -foo3 file.v bar/other_file.v ... @end verbatim Proof General only extracts the common options from the Coq project file and uses them for @code{coqtop} background processes as well as for @code{coqdep} and @code{coqc} when you use the auto compilation feature, @ref{Automatic Compilation in Detail}. For the example above, Proof General will start @code{coqtop -emacs -foo3 -R foo bar -I foo2} (remark: @code{-emacs} is always added to the options). @emph{NOTE:} @code{-arg} must be followed by one and only one option to pass to coqtop/coqc, use several @code{-arg} to issue several options. One per line (limitation of Proof General). For backward compatibility, one can also configure the load path with the option @code{coq-load-path}, but this is not compatible with @code{CoqIde} or @code{coq_makefile}. @emph{NOTE:} the Coq project file cannot define which version of @code{coqtop} is launched. You need either to launch emacs with the right executable in the path or use @inforef{File Variables, ,emacs} or @inforef{Directory Variables, ,emacs}. See @ref{Using file variables} below. @menu * Changing the name of the coq project file:: * Disabling the coq project file mechanism:: @end menu @node Changing the name of the coq project file @subsection Changing the name of the coq project file To change the name of the Coq project file, configure @code{coq-project-filename} (select menu @code{Proof-General -> Advanced -> Customize -> Coq} and scroll down to ``Coq Project Filename''). Customizing @code{coq-project-filename} this way will change the Coq project file name permanently and globally. If you only want to change the name of the Coq project file for one project you can set the option as local file variable, @ref{Using file variables}. This can be done either directly in every file or once for all files of a directory tree with a @code{.dir-local.el} file, @inforef{Directory Variables, ,emacs}. The file @code{.dir-local.el} should then contain @lisp ((coq-mode . ((coq-project-filename . "myprojectfile")))) @end lisp Note that variables set in @code{.dir-local.el} are automatically made buffer local (such that files in different directories can have their independent setting of @code{coq-project-filename}). If you make complex customizations using @code{eval} in @code{.dir-local.el}, you might want to add appropriate calls to @code{make-local-variable}. Documentation of the user option @code{coq-project-filename}: @c TEXI DOCSTRING MAGIC: coq-project-filename @defvar coq-project-filename The name of coq project file.@* The coq project file of a coq development (cf. Coq documentation on "makefile generation") should contain the arguments given to coq_makefile. In particular it contains the -I and -R options (preferably one per line). If @samp{coq-use-coqproject} is t (default) the content of this file will be used by Proof General to infer the @samp{@code{coq-load-path}} and the @samp{@code{coq-prog-args}} variables that set the coqtop invocation by Proof General. This is now the recommended way of configuring the coqtop invocation. Local file variables may still be used to override the coq project file's configuration. .dir-locals.el files also work and override project file settings. @end defvar @node Disabling the coq project file mechanism @subsection Disabling the coq project file mechanism To disable the Coq project file feature in Proof General, set @code{coq-use-project-file} to nil (select menu @code{Proof-General -> Advanced -> Customize -> Coq} and scroll down to ``Coq Use Project File''). @c TEXI DOCSTRING MAGIC: coq-use-project-file @defvar coq-use-project-file If t, when opening a Coq file read the dominating _CoqProject.@* If t, when a Coq file is opened, Proof General will look for a project file (see @samp{@code{coq-project-filename}}) somewhere in the current directory or its parent directories. If there is one, its contents are read and used to determine the arguments that must be given to coqtop. In particular it sets the load path (including the -R lib options) (see @samp{@code{coq-load-path}}). @end defvar You can also use the .dir-locals.el as above to configure this setting on a per project basis. @node Proof using annotations @section Proof using annotations In order to process files asynchronously and pre-compile files (.vos and .vok files), it is advised (inside sections) to list the section variables (and hypothesis) on which each lemma depends on. This must be done at the beginning of a proof with this syntax: @verbatim Lemma foo: ... . Proof using x y H1 H2. @end verbatim If the annotation is missing, then at Qed time (i.e. later in the script) coq complains with a warning and a suggestion of a correct annotation that should be added. ProofGeneral intercepts this suggestion and stores relevant information. Then depending on user preference it can either @itemize @bullet @item insert immediately the ``using...'' annotation after ``Proof'', without replaying the proof. @item highlight the place where the annotation should be inserted and allow the user to perform the insertion later either via right click menu on the proof or by @code{M-x coq-insert-suggested-dependency} (it won't replay the proof) @item ask the user each time which of the two solutions above he wants @item ignore completely the suggestion. @end itemize This can be configured either via Coq menu or by setting variable @code{coq-accept-proof-using-suggestion} to one of the following values: @code{'always}, @code{'highlight}, @code{'ask} or @code{'never}. @node Multiple File Support @section Multiple File Support Since version 4.1 Coq Proof General has multiple file support. It consists of the following points: @table @asis @item Restarting @code{coqtop} when changing the active scripting buffer Different buffers may require different load path' or different sets of @code{-I} options. Because Coq cannot undo changes in the load path, Proof General is forced to restart @code{coqtop} when the active scripting buffer changes. @item Locking ancestors Locking those buffers on which the current active scripting buffer depends. This is controlled by the user option @code{coq-lock-ancestors}, @ref{Customizing Coq Multiple File Support} and @ref{Locking Ancestors}. @item (Re-)Compilation Before a @code{Require} command is processed it may be necessary to save some buffers and compile some files. When automatic (re-)compilation is enabled (it's off by default), one can freely work in different buffers within one Proof General session. Proof General will compile the necessary files whenever a @code{Require} command is processed. The compilation feature does currently not support ML modules. @end table There are actually two implementations of the Recompilation feature. @table @asis @item Parallel asynchronous compilation (stable, default) With parallel compilation, coqdep and coqc are launched in the background and Proof General stays responsive during compilation. Up to `coq-max-background-compilation-jobs' coqdep and coqc processes may run in parallel. Compiled interfaces (@code{-vos} for Coq 8.11 or newer) and quick compilation (@code{-quick}/@code{-vio} for Coq 8.5 or newer) is supported with various modes, @ref{Quick and inconsistent compilation}. @item Synchronous single threaded compilation (obsolete) With synchronous compilation, coqdep and coqc are called synchronously for each Require command. Proof General is locked until the compilation finishes. Neither quick nor vos compilation is supported with synchronously compilation. @end table To enable the automatic compilation feature, you have to follow these points: @itemize @bullet @item Set the option @code{coq-compile-before-require} (menu @code{Coq -> Auto Compilation -> Compile Before Require}) to enable compilation before processing @code{Require} commands. By default, this enables parallel asynchronous compilation. @item Nonstandard load path elements @emph{must} be configured via a Coq project file (this is the recommended option), @ref{Using the Coq project file} or via option @code{coq-load-path}. @code{-I} or @code{-R} options in @code{coq-prog-name} or @code{coq-prog-args} must be deleted. @item Configure @code{coq-max-background-compilation-jobs} if you want to limit the number of parallel background jobs and set @code{coq-compile-keep-going} (menu @code{Coq -> Auto Compilation -> Keep going}) to let compilation continue after the first error. @end itemize To abort parallel background compilation, use @code{C-c C-c} (@code{proof-interrupt-process}), the tool bar interrupt icon, the menu entry @code{Abort Background Compilation} (menu @code{Coq -> Auto Compilation}) or kill the Coq toplevel via @code{C-c C-x} (@code{proof-shell-exit}). To abort synchronous single threaded compilation, simply hit @code{C-g}. @menu * Automatic Compilation in Detail:: * Locking Ancestors:: * Quick and inconsistent compilation:: * Customizing Coq Multiple File Support:: * Current Limitations:: @end menu @node Automatic Compilation in Detail @subsection Automatic Compilation in Detail When @code{coq-compile-before-require} is enabled, Proof General looks for @code{Require} commands in text that gets asserted (i.e., in text that is moved from the editing region to the queue region, @ref{Locked queue and editing regions}). If Proof General finds a @code{Require} command, it checks the dependencies and (re-)compiles files as necessary. The Require command and the following text is only sent to Coq after the compilation has finished. @code{Declare ML Module} commands are currently not recognized and dependencies on ML Modules reported by @code{coqdep} are ignored. Proof General uses @code{coqdep} to determine which libraries a @code{Require} command will load and which files must be up-to-date. Because Proof General cannot know whether files are updated outside of Emacs, it checks for every @code{Require} command the complete dependency tree and recompiles files as necessary. Output from the compilation is only shown in case of errors. It then appears in the buffer @code{*coq-compile-response*}. One can use @code{C-x `} (bound to @code{next-error}, @inforef{Compilation Mode,,emacs}) to jump to error locations. Sometimes the compilation commands do not produce error messages with location information, then @code{C-x `} does only work in a limited way. Proof General supports both vos and quick/vio compilation to speed up compilation of required modules at the price of consistency. Because quick/vio compilation does not seem to have a benefit with vos compilation present, the former is only supported for Coq before 8.11. Both can be configured via the settings @code{coq-compile-vos} and @code{coq-compile-quick} and via menu entries in @code{Coq -> Auto Compilation}, @ref{Quick and inconsistent compilation}. Similar to @code{make -k}, background compilation can be configured to continue as far as possible after the first error, see option @code{coq-compile-keep-going} (menu @code{Coq -> Auto Compilation -> Keep going}). The keep-going option applies to errors from @code{coqdep} and @code{coqc}. However, when starting @code{coqc} or @code{coqdep} fails), the compilation is immediately aborted. When a @code{Require} command causes a compilation of some files, one may wish to save some buffers to disk beforehand. The option @code{coq-compile-auto-save} controls how and which files are saved. There are two orthogonal choices: One may wish to save all or only the Coq source files, and, one may or may not want to confirm the saving of each file. With `coq-compile-parallel-in-background' (menu @code{Coq -> Settings -> Compile Parallel In Background}) you can choose between two implementations of internal compilation. @table @asis @item Synchronous single threaded compilation This is the old, now outdated version supported since Proof General 4.1. This method starts coqdep and coqc processes one after each other in synchronous subprocesses. Your Emacs session will be locked until compilation finishes. Use @code{C-g} to interrupt compilation. This method supports compilation via an external command (such as @code{make}), see option @code{coq-compile-command} in @ref{Customizing Coq Multiple File Support} below. Synchronous compilation does neither support quick/vio nor vos compilation. @item Parallel asynchronous compilation This is the newer, recommended and default version added in Proof General version 4.3. It runs up to @code{coq-max-background-compilation-jobs} coqdep and coqc jobs in parallel in asynchronous subprocesses (or uses all your CPU cores if @code{coq-max-background-compilation-jobs} equals @code{'all-cpus}). Your Emacs will stay responsive during compilation. To abort the background compilation process, use @code{C-c C-c} (@code{proof-interrupt-process}), the tool bar interrupt icon, the menu entry @code{Abort Background Compilation} (menu @code{Coq -> Auto Compilation}) or kill the Coq toplevel via @code{C-c C-x} (@code{proof-shell-exit}). For the usual case, you have at most `coq-max-background-compilation-jobs' parallel processes @emph{including} your Proof General process. The usual case applies, when the Require commands are the first commands in the file. If you have other commands between two Require commands or before the first Require, then you may see Proof General and Coq running in addition to `coq-max-background-compilation-jobs' compilation jobs. Parallel asynchronous compilation supports both vos and quick/vio compilation, but exclusively, depending on the Coq version, @ref{Quick and inconsistent compilation}. @end table @node Locking Ancestors @subsection Locking Ancestors Locking ancestor files works as a side effect of dependency checking. This means that ancestor locking does only work when Proof General performs dependency checking and compilation itself. If an external command is used, Proof General does not see all dependencies and can therefore only lock direct ancestors. In the default setting, when you want to edit a locked ancestor, you are forced to completely retract the current scripting buffer. You can simplify this by setting @code{proof-strict-read-only} to @code{'retract} (menu @code{Proof-General -> Quick Options -> Read Only -> Undo On Edit}). Then typing in some ancestor will immediately retract your current scripting buffer and unlock that ancestor. You have two choices, if you don't like ancestor locking in its default way. You can either switch ancestor locking completely off via menu @code{Coq -> Auto Compilation -> Lock Ancestors} or @code{coq-lock-ancestors} (@ref{Customizing Coq Multiple File Support}). Alternatively, you can generally permit editing in locked sections with selecting @code{Proof-General} -> @code{Quick Options} -> @code{Read Only} -> @code{Freely Edit} (which will set the option @code{proof-strict-read-only} to @code{nil}). [The right behaviour for Coq, namely to retract the current scripting buffer only up to the appropriate @code{Require} command, would be quite difficult to implement in the current Proof General infrastructure. Further, it has only dubious benefit, as Require commands are usually on the top of each file.] @node Quick and inconsistent compilation @subsection Quick and inconsistent compilation Coq now supports two different modes for speeding up compilation at the price of consistency. Since Coq 8.11, @code{-vos} compiles interfaces into @code{.vos} files and since Coq 8.5 @code{-quick}/@code{-vio} produces @code{.vio} files. Proof General supports both modes with parallel asynchronous compilation, but exclusively, depending on the detected Coq version. For Coq 8.11 or newer only @code{-vos} can be used. There are a number of different compilation options supported, see below. For Coq 8.11 or newer (decided by the automatic Coq version detection of Proof General or by the setting @code{coq-pinned-version}) required modules are either compiled to @code{.vo} or @code{.vos} files, depending on the setting @code{coq-compile-vos}, which can also be set on menu @code{Coq -> Auto Compilation -> vos compilation}. There are four choices: @table @asis @item @code{vos-and-vok} First compile using @code{-vos}, skipping proofs. When compilation finished, run @code{coqc -vok} in a second stage to check proofs on all files that require it. Some universe constraints might be missed, rendering this method possibly inconsistent. @item @code{vos} Only compile using @code{-vos}, skipping proofs. No @code{coqc -vok} run to check proofs. Obviously inconsistent. @item @code{ensure-vo} Compile without @code{-vos} to @code{.vo} files, checking all proofs and universe constraints. Only consistent choice. @item unset (@code{nil}) Compile with @code{-vos} if @code{coq-compile-quick} (see below) equals @code{quick-no-vio2vo}. Otherwise compile without @code{-vos} to @code{.vo}. This value provides an upgrade path for users that configured @code{coq-compile-quick} in the past. @end table For @code{vos-and-vok} the second @code{-vok} stage runs asynchronously @code{coq-compile-second-stage-delay} seconds after the last @code{Require} command has been processed. Errors might pop up later and interrupt your normal interaction with Coq. Because the second stage is not time critical, it runs on @code{coq-max-background-second-stage-percentage} per cent of the cores configured for the first stage. When @code{coq-compile-keep-going} is configured and an error occurs, the second @code{-vok} stage is run on those dependencies not affected by the error. For Coq version 8.5 until before 8.11, Proof General supports quick or vio compilation with parallel asynchronous compilation. There are 4 modes that can be configured with @code{coq-compile-quick} or by selecting one of the radio buttons in the @code{Coq -> Auto Compilation -> Quick compilation} menu. For Coq before 8.11 @code{coq-compile-vos} is ignored. Value @code{no-quick} was provided for the transition, for those that have not switched there development to @code{Proof using}. Use @code{quick-no-vio2vo}, if you want quick recompilation without producing .vo files. Option @code{quick-and-vio2vo} recompiles with @code{-quick}/@code{-vio} as @code{quick-no-vio2vo} does, but schedules a second vio2vo stage for missing @code{.vo} files. Finally, use @code{ensure-vo} for only importing @code{.vo} files with complete universe checks. Note that with all of @code{no-quick}, @code{quick-no-vio2vo} and @code{quick-and-vio2vo} your development might be unsound because proofs might have been skipped and universe constraints are not fully present in @code{.vio} files. There are a few peculiarities of quick compilation in Coq 8.5 and possibly also in other versions. @itemize @item Quick compilation runs noticeably slower when section variables are not declared via @code{Proof using}. @item Even when section variables are declared, quick compilation runs slower on very small files, probably because of the comparatively big size of the @code{.vio} files. You can speed up quick compilation noticeably by running on a RAM disk. @item If both, the @code{.vo} and the @code{.vio} files are present, Coq loads the more recent one, regardless of whether @code{-quick}, and emits a warning when the @code{.vio} is more recent than the @code{.vo}. @item Under some circumstances, files compiled when only the @code{.vio} file of some library was present are not compatible with (other) files compiled when also the @code{.vo} file of that library was present, see Coq issue #5223 for details. As a rule of thumb one should run vio2vo compilation only before or after library loading. @item Apart from the previous point, Coq works fine when libraries are present as a mixture of @code{.vio} and @code{.vo} files. While @code{make} insists on building all prerequisites as either @code{.vio} or @code{.vo} files, Proof General just checks whether an up-to-date compiled library file is present. @item To ensure soundness, all library dependencies must be compiled as @code{.vo} files and loaded into one Coq instance. @end itemize Detailed description of the 4 possible settings of @code{coq-compile-quick}: @table @code @item no-quick Compile outdated prerequisites without @code{-quick}, producing @code{.vo} files, but don't compile prerequisites for which an up-to-date @code{.vio} file exists. Delete or overwrite outdated @code{.vo} files. @item quick-no-vio2vo Compile outdated prerequisites with @code{-quick}, producing @code{.vio} files, but don't compile prerequisites for which an up-to-date @code{.vo} file exists. Delete or overwrite outdated @code{.vio} files. @item quick-and-vio2vo Same as @code{quick-no-vio2vo}, but start a second vio2vo stage for missing @code{.vo} files. Everything described previously for the second @code{-vok} stage applies here as well. @emph{Warning}: This mode does only work when you process require commands in batches. Slowly single-stepping through require's might lead to inconsistency errors when loading some libraries, see Coq issue #5223. To mitigate this risk, vio2vo compilation only starts after a certain delay after the last require command of the current queue region has been processed. This is controlled by @code{coq-compile-second-stage-delay}, @ref{Customizing Coq Multiple File Support}. @item ensure-vo Ensure that all library dependencies are present as @code{.vo} files and delete outdated @code{.vio} files or @code{.vio} files that are more recent than the corresponding @code{.vo} file. This setting is the only one that ensures soundness. @end table The options @code{no-quick} and @code{ensure-vo} are compatible with Coq 8.4 or older. When Proof General detects such an older Coq version, it changes the quick compilation mode automatically. For this to work, the option @code{coq-compile-quick} must only be set via the customization system or via the menu. @node Customizing Coq Multiple File Support @subsection Customizing Coq Multiple File Support The customization settings for multiple file support of Coq Proof General are in a separate customization group, the @code{coq-auto-compile} group. To view all options in this group do @code{M-x customize-group coq-auto-compile} or select menu entry @code{Proof-General -> Advanced -> Customize -> Coq -> Coq Auto Compile -> Coq Auto Compile}. @c TEXI DOCSTRING MAGIC: coq-compile-before-require @defvar coq-compile-before-require If non-nil, check dependencies of required modules and compile if necessary.@* If non-nil ProofGeneral intercepts "Require" commands and checks if the required library module and its dependencies are up-to-date. If not, they are compiled from the sources before the "Require" command is processed. This option can be set/reset via menu @samp{Coq -> Auto Compilation -> Compile Before Require}. @end defvar @c TEXI DOCSTRING MAGIC: coq-compile-auto-save @defvar coq-compile-auto-save Buffers to save before checking dependencies for compilation.@* There are two orthogonal choices: Firstly one can save all or only the coq buffers, where coq buffers means all buffers in coq mode except the current buffer. Secondly, Emacs can ask about each such buffer or save all of them unconditionally. This makes four permitted values: @code{'ask-coq} to confirm saving all modified Coq buffers, @code{'ask-all} to confirm saving all modified buffers, @code{'save-coq} to save all modified Coq buffers without confirmation and @code{'save-all} to save all modified buffers without confirmation. This option can be set via menu @samp{Coq -> Auto Compilation -> Auto Save}. @end defvar The following options configure parallel compilation. @c TEXI DOCSTRING MAGIC: coq-compile-parallel-in-background @defvar coq-compile-parallel-in-background Choose the internal compilation method.@* When Proof General compiles itself, you have the choice between two implementations. If this setting is nil, then Proof General uses the old implementation and compiles everything sequentially with synchronous job. With this old method Proof General is locked during compilation. If this setting is t, then the new method is used and compilation jobs are dispatched in parallel in the background. The maximal number of parallel compilation jobs is set with @samp{@code{coq-max-background-compilation-jobs}}. This option can be set/reset via menu @samp{Coq -> Auto Compilation -> Compile Parallel In Background}. @end defvar The options @code{coq-compile-vos} and @code{coq-compile-quick} are described in detail above, @ref{Quick and inconsistent compilation}. @c TEXI DOCSTRING MAGIC: coq-compile-keep-going @defvar coq-compile-keep-going Continue compilation after the first error as far as possible.@* Similar to @samp{`make -k}', with this option enabled, the background compilation continues after the first error as far as possible. With this option disabled, background compilation is immediately stopped after the first error. This option can be set/reset via menu @samp{Coq -> Auto Compilation -> Keep going}. @end defvar @c TEXI DOCSTRING MAGIC: coq-max-background-compilation-jobs @defvar coq-max-background-compilation-jobs Maximal number of parallel jobs, if parallel compilation is enabled.@* Use the number of available CPU cores if this is set to @code{'all-cpus}. This variable is the user setting. The value that is really used is @samp{@code{coq--internal-max-jobs}}. Use @samp{@code{coq-max-jobs-setter}} or the customization system to change this variable. Otherwise your change will have no effect, because @samp{@code{coq--internal-max-jobs}} is not adapted. @end defvar @c TEXI DOCSTRING MAGIC: coq-max-background-second-stage-percentage @defvar coq-max-background-second-stage-percentage Percentage of @samp{@code{coq-max-background-compilation-jobs}} for the second stage.@* This setting configures the maximal number of @samp{`-vok}' or vio2vo background jobs running in a second stage as percentage of @samp{@code{coq-max-background-compilation-jobs}}. For backward compatibility, if this option is not customized, it is initialized from the now deprecated option @samp{@code{coq-max-background-vio2vo-percentage}}. @end defvar @c TEXI DOCSTRING MAGIC: coq-compile-second-stage-delay @defvar coq-compile-second-stage-delay Delay in seconds before starting the second stage compilation.@* The delay is applied to both @samp{`-vok}' and vio2vo second stages. For Coq < 8.11 and vio2vo delay helps to avoid running into a library inconsistency with @code{'quick-and-vio2vo}, see Coq issue #@var{5223}. For backward compatibility, if this option is not customized, it is initialized from the now deprecated option @samp{@code{coq-compile-vio2vo-delay}}. @end defvar Locking ancestors can be disabled with the following option. @c TEXI DOCSTRING MAGIC: coq-lock-ancestors @defvar coq-lock-ancestors If non-nil, lock ancestor module files.@* If external compilation is used (via @samp{@code{coq-compile-command}}) then only the direct ancestors are locked. Otherwise all ancestors are locked when the "Require" command is processed. This option can be set via menu @samp{Coq -> Auto Compilation -> Lock Ancestors}. @end defvar The sequential compilation setting supports an external compilation command (which could be a parallel running @code{make}). For this set @code{coq-compile-parallel-in-background} to @code{nil} and configure the compilation command in @code{coq-compile-command}. @c TEXI DOCSTRING MAGIC: coq-compile-command @defvar coq-compile-command External compilation command. If empty ProofGeneral compiles itself.@* If unset (the empty string) ProofGeneral computes the dependencies of required modules with coqdep and compiles as necessary. This internal dependency checking does currently not handle ML modules. If a non-empty string, the denoted command is called to do the dependency checking and compilation. Before executing this command the following keys are substituted as follows: @lisp %p the (physical) directory containing the source of the required module %o the Coq object file in the physical directory that will be loaded %s the Coq source file in the physical directory whose object will be loaded %q the qualified id of the "Require" command %r the source file containing the "Require" @end lisp For instance, "make -C %p %o" expands to "make -C bar foo.vo" when module "foo" from directory "bar" is required. After the substitution the command can be changed in the minibuffer if @samp{@code{coq-confirm-external-compilation}} is t. @end defvar @c TEXI DOCSTRING MAGIC: coq-confirm-external-compilation @defvar coq-confirm-external-compilation If set let user change and confirm the compilation command.@* Otherwise start the external compilation without confirmation. This option can be set/reset via menu @samp{Coq -> Auto Compilation -> Confirm External Compilation}. @end defvar The preferred way to configure the load path and the mapping of logical library names to physical file path is the Coq project file, @ref{Using the Coq project file}. Alternatively one can configure these things with the following options. @c TEXI DOCSTRING MAGIC: coq-load-path @defvar coq-load-path Non-standard coq library load path.@* This list specifies the LoadPath extension for coqdep, coqc and coqtop. Usually, the elements of this list are strings (for "-I") or lists of two strings (for "-R" dir path and "-Q" dir path). The possible forms of elements of this list correspond to the 4 forms of include options (@samp{-I} @samp{-Q} and @samp{-R}). An element can be @lisp - A list of the form @samp{(}ocamlimport dir)', specifying (in 8.5) a directory to be added to ocaml path (@samp{-I}). - A list of the form @samp{(}rec dir path)' (where dir and path are strings) specifying a directory to be recursively mapped to the logical path @samp{path} (@samp{-R dir path}). - A list of the form @samp{(}recnoimport dir path)' (where dir and path are strings) specifying a directory to be recursively mapped to the logical path @samp{path} (@samp{-Q dir path}), but not imported (modules accessible for import with qualified names only). Note that -Q dir "" has a special, nonrecursive meaning. - A list of the form (8.4 only) @samp{(}nonrec dir path)', specifying a directory to be mapped to the logical path @code{'path'} ('-I dir -as path'). @end lisp For convenience the symbol @samp{rec} can be omitted and entries of the form @samp{(dir path)} are interpreted as @samp{(rec dir path)}. A plain string maps to -Q ... "" in 8.5, and -I ... in 8.4. Under normal circumstances this list does not need to contain the coq standard library or "." for the current directory (see @samp{@code{coq-load-path-include-current}}). @var{warning}: if you use coq <= 8.4, the meaning of these options is not the same (-I is for coq path). @end defvar @c TEXI DOCSTRING MAGIC: coq-load-path-include-current @defvar coq-load-path-include-current If t, let coqdep search the current directory too.@* Should be t for normal users. If t, pass -Q dir "" to coqdep when processing files in directory "dir" in addition to any entries in @samp{@code{coq-load-path}}. This setting is only relevant with Coq < 8.5. @end defvar During library dependency checking Proof General does not dive into the Coq standard library or into libraries that are installed as user contributions. This stems from @code{coqdep}, which does not output dependencies to these directories. The internal dependency check can also ignore additional libraries. @c TEXI DOCSTRING MAGIC: coq-compile-ignored-directories @defvar coq-compile-ignored-directories Directories in which ProofGeneral should not compile modules.@* List of regular expressions for directories in which ProofGeneral should not compile modules. If a library file name matches one of the regular expressions in this list then ProofGeneral does neither compile this file nor check its dependencies for compilation. It makes sense to include non-standard coq library directories here if they are not changed and if they are so big that dependency checking takes noticeable time. The regular expressions in here are always matched against the .vo file name, regardless whether @samp{`-quick}' would be used to compile the file or not. @end defvar @node Current Limitations @subsection Current Limitations @itemize @item No support for @code{Declare ML Module} commands and files depending on an ML module. @item When a compiled library has the same time stamp as the source file, it is considered outdated. Some old file systems (for instance ext3) or Emacs before version 24.3 support only time stamps with one second granularity. On such configurations Proof General will perform some unnecessary compilations. @end itemize @node Omitting proofs for speed @section Omitting proofs for speed To speed up asserting larger chunks, Proof General can omit complete opaque proofs by silently replacing the whole proof script with @code{Admitted}, @ref{Script processing commands}. This works when @itemize @item proofs are not nested @item opaque and non-opaque proofs start with @code{Proof.} or @code{Proof using} @item opaque proofs end with @code{Qed} or @code{Admitted} @item non-opaque proofs or definition end with @code{Defined} @end itemize Aborted proofs can be present if they start with a variant of @code{Proof} and end with @code{Abort}. They are handled like non-opaque proofs (i.e., not omitted). To enable omitting proofs, configure @code{proof-omit-proofs-option} or select @code{Proof-General -> Quick Options -> Processing -> Omit Proofs}. With a prefix argument, both @code{proof-goto-point} and @code{proof-process-buffer} will temporarily disable the omit proofs feature and send the full proof script to Coq. If a nested proof is detected while searching for opaque proofs to omit, a warning is displayed and the complete remainder of the asserted region is sent unmodified to Coq. If the proof script relies on sections, it is highly recommended to use a @code{Proof using} annotation for all lemmas contained in a Section, otherwise @code{Coq} will compute a wrong type for these lemmas when this omitting-proofs feature is enabled. To automate this, we recall that ProofGeneral provides a dedicated feature to generate these @code{Proof using} annotations (a defective form being e.g. @code{Proof using Type} if no section hypothesis is used), see the menu command @code{Coq > "Proof using" mode} and @ref{Proof using annotations} for details. @node Editing multiple proofs @section Editing multiple proofs Coq allows the user to enter top-level commands while editing a proof script. For example, if the user realizes that the current proof will fail without an additional axiom, he or she can add that axiom to the system while in the middle of the proof. Similarly, the user can nest lemmas, beginning a new lemma while in the middle of an earlier one, and as the lemmas are proved or their proofs aborted they are popped off a stack. Coq Proof General supports this feature of Coq. Top-level commands entered while in a proof are well backtracked. If new lemmas are started, Coq Proof General lets the user work on the proof of the new lemma, and when the lemma is finished it falls back to the previous one. This is supported to any nesting depth that Coq allows. Warning! Using Coq commands for navigating inside the different proofs (@code{Resume} and especially @code{Suspend}) are not supported, backtracking will break synchronization. @b{Special note:} The old feature that moved nested proofs outside the current proof is disabled. @node User-loaded tactics @section User-loaded tactics Another feature that Coq allows is the extension of the grammar of the proof assistant by new tactic commands. This feature interacts with the proof script management of Proof General, because Proof General needs to know when a tactic is called that alters the proof state. When the user tries to retract across an extended tactic in a script, the algorithm for calculating how far to undo has a default behavior that is not always accurate in proof mode: do "@code{Undo}". Coq Proof General does not currently support dynamic tactic extension in Coq: this is desirable but requires assistance from the Coq core. Instead we provide a way to add tactic and command names in the @file{.emacs} file. Four Configurable variables allows to register personal new tactics and commands into four categories: @itemize @bullet @item @emph{state changing commands}, which need "@code{Back}" to be backtracked; @item @emph{state changing tactics}, which need "@code{Undo}" to be backtracked; @item @emph{state preserving commands}, which do not need to be backtracked; @item @emph{state preserving tactics}, which do not need to be backtracked; @end itemize We give an example of existing commands that fit each category. @itemize @bullet @item @code{coq-user-state-preserving-commands}: example: "@code{Print}" @item @code{coq-user-state-changing-commands}: example: "@code{Require}" @item @code{coq-user-state-changing-tactics}: example: "@code{Intro}" @item @code{coq-user-state-preserving-tactics}: example: "@code{Idtac}" @end itemize This variables are regexp string lists. See their documentations in emacs (@code{C-h v coq-user...}) for details on how to set them in your @file{.emacs} file. Here is a simple example: @lisp (setq coq-user-state-changing-commands '("MyHint" "MyRequire")) (setq coq-user-state-preserving-commands '("Show\\s-+Mydata")) @end lisp The regexp character sequence @code{\\s-+} means "one or more whitespaces". See the Emacs documentation of @code{regexp-quote} for the syntax and semantics. WARNING: you need to restart Emacs to make the changes to these variables effective. In case of losing synchronization, the user can use @kbd{C-c C-z} to move the locked region to the proper position, (@code{proof-frob-locked-end}, @pxref{Escaping script management}) or @kbd{C-c C-v} to re-issue an erroneously back-tracked tactic without recording it in the script. @node Indentation tweaking @section Indentation tweaking Indentation of Coq script is provided by Proof General, but it may behave badly especially if you use syntax extensions. You can sometimes fix this problem by telling PG that some token should be considered as identical to other ones by the indentation mechanism. Use the two variables @code{coq-smie-user-tokens} and @code{coq-smie-monadic-tokens}. This variables contains associations between user tokens and the existing pg tokens they should be equated too. @itemize @bullet @item @code{coq-smie-user-tokens} this is where users should put ther own tokens. For instance: @lisp (setq coq-smie-user-tokens '((\"xor\" . \"or\") (\"ifb\" . \"if\"))) @end lisp to have token \"xor\" and \"ifb\" be considered as having @item @code{coq-smie-monadic-tokens} is specific to monadic operators: it contains usual monadic notations by default (but you can redefine it if needed). Specific tokens are defined for the two usual monadic forms: @verbatim "let monadic" E "<- monadic" E "in monadic" E E "<- monadic" E ";; monadic" E @end verbatim The default value of @code{coq-smie-monadic-tokens} gives the following concrete syntax to these tokens: @lisp ((";;" . ";; monadic") ("do" . "let monadic") ("<-" . "<- monadic") (";" . "in monadic")) @end lisp thus allowing for the following: @verbatim do x <- foo; do y <- bar; ... @end verbatim and @verbatim x <- foo;; y <- bar;; ... @end verbatim @end itemize @emph{NOTE:} This feature is experimental. @emph{NOTE:} the ``pg tokens'' are actually the ones PG generates internally by exploring the file around the indentation point. Consequently this refers to internals of PoofGeneral. Contact the Proof General team if you need help. @node Holes feature @section Holes feature @emph{Holes} are an experimental feature for complex expression editing by filling in templates. It is inspired from other tools, like Pcoq (@uref{http://www-sop.inria.fr/lemme/pcoq/index.html}). The principle is simple, holes are pieces of text that can be "filled" by various means. The Coq command insertion menu system makes use of the holes system. Almost all holes operations are available in the Holes menu. @b{Notes:} Holes make use of the Emacs abbreviation mechanism, it will work without problem if you don't have an abbrev table defined for Coq in your config files. Use @code{C-h v abbrev-file-name} to see the name of the abbreviation file. If you already have such a table it won't be automatically overwritten (so that you keep your own abbreviations). But you must read the abbrev file given in the Proof General sources to be able to use the command insertion menus. You can do the following to merge your abbreviations with ProofGeneral's abbreviations: @code{M-x read-abbrev-file}, then select the file named @code{coq-abbrev.el} in the @code{ProofGeneral/coq} directory. At Emacs exit you will be asked if you want to save abbrevs; answer yes. @node Proof-Tree Visualization @section Proof-Tree Visualization Starting with Proof General version 4.2 and Coq version 8.4, Coq Proof General has full support for proof-tree visualization, @pxref{Graphical Proof-Tree Visualization}. To find out which versions of Prooftree are compatible with this version of Proof General, @pxref{Graphical Proof-Tree Visualization} or the @uref{http://askra.de/software/prooftree/, Prooftree website}. For the visualization to work properly, proofs must be started with @code{Proof}, which is encouraged practice anyway (see Coq Bug #2776). Without @code{Proof} you lose the initial proof goal, possibly having two or more initial goals in the display. To support @code{Grab Existential Variables} Prooftree can actually display several graphically independent proof trees in several layers. @node Showing Proof Diffs @section Showing Proof Diffs Coq 8.10 supports automatically highlighting the differences between successive proof steps in Proof General. The feature is described in the Coq Documentation, section @coqrefman{proofs/writing-proofs/proof-mode.html#showing-differences-between-proof-steps, Showing differences between proof steps}. The Coq proof diff does more than a basic "diff" operation. For example: @itemize @bullet @item diffs are computed on a per-token basis (as determined by the Coq lexer) rather than on a per-character basis, probably a better match for how people understand the output. (For example, a token-based diff between "abc" and "axc" will highlight all of "abc" and "axc" as a difference, while a character-based diff would indicate that "a" and "c" are in common and that only the "b"/"x" is a difference.) @item diffs ignore the order of hypotheses @item tactics that only change the proof view are handled specially, for example "swap" after a "split" will show the diffs between before "split" and after "swap", which is more useful @item some error messages have been instrumented to show diffs where it is helpful @end itemize To enable or disable diffs, set @code{coq-diffs} (select menu @code{Coq -> Diffs}) to "on", "off" or "removed". "on" highlights added tokens with the background color from @code{diff-refine-added}. "removed" highlights removed tokens with the background color from @code{diff-refine-removed}. With the "removed" setting, lines that have both added and removed text may be shown twice, as "before" and "after" lines. To preserve the settings for the next time you start Proof General, select @code{Coq -> Settings -> Save Settings}. The colors used to highlight diffs are configurable in the @code{Proof-General -> Advanced -> Customize -> Proof Faces} menu. The 4 @code{Coq Diffs ...} faces control the highlights. Lines that have added or removed tokens are shown with the entire line highlighted with a @code{Coq Diffs ... Bg} face. The added or removed tokens themselves are highlighted with non-@code{Bg} faces. @node Opam-switch-mode support @section Opam-switch-mode support Coq can be installed using @code{opam} (the OCaml package manager), which makes it easy to manage several different switches, having each a different version of Coq. Instead of running a command like @code{opam switch ...} in a terminal and restarting emacs to benefit from a different switch, one can: @itemize @bullet @item @b{Install} the @uref{https://github.com/ProofGeneral/opam-switch-mode, opam-switch-mode} and use the dedicated mode bar menu @code{OPSW} it provides. @item @b{Configure} Proof General using the customization option @code{coq-kill-coq-on-opam-switch}, so that the Coq background process is killed when changing the opam switch through @code{opam-switch-mode}. @end itemize @c TEXI DOCSTRING MAGIC: coq-kill-coq-on-opam-switch @defvar coq-kill-coq-on-opam-switch If t kill coq when the opam switch changes (requires @samp{opam-switch-mode}).@* When @samp{opam-switch-mode} is loaded and the user changes the opam switch through @samp{opam-switch-mode} then this option controls whether the coq background process (the proof shell) is killed such that the next assert command starts a new proof shell, probably using a different coq version from a different opam switch. See https://github.com/ProofGeneral/opam-switch-mode for @samp{opam-switch-mode} @end defvar @c ================================================================= @c @c CHAPTER: EasyCrypt Proof General @c @node EasyCrypt Proof General @chapter EasyCrypt Proof General @cindex EasyCrypt Proof General @menu * EasyCrypt specific commands:: * EasyCrypt weak-check mode:: * EasyCrypt customizations:: @end menu EasyCrypt Proof General is an instantiation of Proof General for the EasyCrypt proof assistant. @node EasyCrypt specific commands @section EasyCrypt specific commands @kindex C-c C-a C-p @kindex C-c C-a C-c EasyCrypt Proof General supplies the following key-bindings: @table @kbd @item C-c C-a C-p Prompts for ``print'' query arguments. @item C-c C-a C-c The same for a ``check'' query. @end table @node EasyCrypt weak-check mode @section EasyCrypt weak-check mode The EasyCrypt menu contains a @code{Weak-check mode} toggle menu, which allows you to enable or disable the EasyCrypt Weak-Check mode. When enabled, all @code{smt} calls are ignored and assumed to succeed. @node EasyCrypt customizations @section EasyCrypt customizations Here are some of the other user options specific to EasyCrypt. You can set these as usual with the customization mechanism. @c TEXI DOCSTRING MAGIC: easycrypt-prog-name @defopt easycrypt-prog-name Name of program to run EasyCrypt. The default value is @code{"easycrypt"}. @end defopt @c TEXI DOCSTRING MAGIC: easycrypt-load-path @defvar easycrypt-load-path Non-standard EasyCrypt library load path.@* This list specifies the include path for EasyCrypt. The elements of this list are strings. @end defvar @c TEXI DOCSTRING MAGIC: easycrypt-web-page @defvar easycrypt-web-page URL of web page for EasyCrypt. @end defvar @c ================================================================= @c @c CHAPTER: Shell Proof General @c @node Shell Proof General @chapter Shell Proof General @cindex Shell Proof General This instance of Proof General is not really for proof assistants at all, but simply provided as a handy way to use a degenerate form of script management with other tools. Suppose you have a software tool of some kind with a command line interface, and you want to demonstrate several example uses of it, perhaps at a conference. But the command lines for your tool may be quite complicated, so you do not want to type them in live. Instead, you just want to cut and paste from a pre-recorded list. But watching somebody cut and paste commands into a window is almost as tedious as watching them type those commands! Shell Proof General comes to the rescue. Simply record your commands in a file with the extension @code{.pgsh}, and load up Proof General. Now use the toolbar to send each line of the file to your tool, and have the output displayed clearly in another window. Much easier and more pleasant for your audience to watch! If you wish, you may adjust the value of @code{proof-prog-name} in @file{pgshell.el} to launch your program rather than the shell interpreter. We welcome feedback and suggestions concerning this subsidiary provision in Proof General. Please recommend it to your colleagues (e.g., the model checking crew). @c ================================================================= @c @c APPENDIX: Obtaining and Installing @c @c @node Obtaining and Installing @appendix Obtaining and Installing Proof General has its own @uref{https://proofgeneral.github.io,home page} hosted at GitHub. Visit this page for the latest news! @menu * Obtaining Proof General:: * Installing Proof General from sources:: * Setting the names of binaries:: * Notes for syssies:: @end menu @node Obtaining Proof General @section Obtaining Proof General You can obtain Proof General from the URL @example @uref{https://github.com/ProofGeneral/PG}. @end example The distribution is available in the master branch of the repository. Tagged versions of the sources may be redistributed by third party packagers in other forms. The sources includes the generic elisp code, and code for Coq, EasyCrypt, and other provers. Also included are installation instructions (reproduced in brief below) and this documentation. @node Installing Proof General from sources @section Installing Proof General from sources Remove old versions of Proof General, then download and install the new release from GitHub: @example $ git clone https://github.com/ProofGeneral/PG ~/.emacs.d/lisp/PG $ cd ~/.emacs.d/lisp/PG $ make @end example Then add the following to your @file{.emacs}: @lisp ;; Open .v files with Proof General's Coq mode (load "~/.emacs.d/lisp/PG/generic/proof-site") @end lisp If Proof General complains about a version mismatch, make sure that the shell's @code{emacs} is indeed your usual Emacs. If not, run the Makefile again with an explicit path to Emacs. On macOS in particular you'll probably need something like @example make clean; make EMACS=/Applications/Emacs.app/Contents/MacOS/Emacs @end example @node Setting the names of binaries @section Setting the names of binaries The @code{load} command you have added will load @file{proof-site} which sets the Emacs load path for Proof General and add auto-loads and modes for the supported assistants. The default names for proof assistant binaries may work on your system. If not, you will need to set the appropriate variables. The easiest way to do this (and most other customization of Proof General) is via the Customize mechanism, see the menu item: @example Proof-General -> Advanced -> Customize -> @var{Name of Assistant} -> Prog Name @end example The Proof-General menu is available from script buffers after Proof General is loaded. To load it manually, type @lisp M-x load-library RET proof RET @end lisp If you do not want to use customize, simply add a line like this: @lisp (setq coq-prog-name "/usr/bin/coqtop") @end lisp to your @file{.emacs} file. For more advice on how to customize the @code{coq-prog-name} variable, @pxref{Using file variables}, Remark 2. @node Notes for syssies @section Notes for syssies Here are some more notes for installing Proof General in more complex ways. Only attempt things in this section if you really understand what you're doing! @unnumberedsubsec Byte compilation Compilation of the Emacs lisp files improves efficiency but can sometimes cause compatibility problems, especially if you use more than one version of Emacs with the same @code{.elc} files. If you discover problems using the byte-compiled @code{.elc} files which aren't present using the source @code{.el} files, please report them to us. You can compile Proof General by typing @code{make} in the directory where you installed it. It may be necessary to do this if you use a different version of Emacs. @unnumberedsubsec Site-wide installation If you are installing Proof General site-wide, you can put the components in the standard directories of the filesystem if you prefer, providing the variables in @file{proof-site.el} are adjusted accordingly (see @i{Proof General site configuration} in @i{Adapting Proof General} for more details). Make sure that the @file{generic/} and assistant-specific elisp files are kept in subdirectories (@file{coq/}, @file{phox/}, @file{easycrypt/}, ...) of @code{proof-home-directory} so that the autoload directory calculations are correct. To prevent every user needing to edit their own @file{.emacs} files, you can put the @code{load-file} command to load @file{proof-site.el} into @file{site-start.el} or similar. Consult the Emacs documentation for more details if you don't know where to find this file. @unnumberedsubsec Removing support for unwanted provers You cannot run more than one instance of Proof General at a time: so if you're using Coq, visiting an @file{.ec} file will not load EasyCrypt Proof General, and the buffer remains in fundamental mode. If there are some assistants supported that you never want to use, you can adjust the variable @code{proof-assistants} in @file{proof-site.el} to remove the extra autoloads. This is advisable in case the extensions clash with other Emacs modes, for example @c @code{sml-mode} for @file{.ML} files, or Verilog mode for @file{.v} files clashes with Coq mode. See @i{Proof General site configuration} in @i{Adapting Proof General}, for more details of how to adjust the @code{proof-assistants} setting. Instead of altering @code{proof-assistants}, a simple way to disable support for some prover is to delete the relevant directories from the PG installation. For example, to remove support for Coq, delete the @file{coq} directory in the Proof General home directory. @c Via the Customize mechanism, see the menu: @c @example @c Options -> Customize -> Emacs -> External -> Proof General @c @end example @c or, after loading Proof General, in a proof script buffer @c @example @c Proof-General -> Customize @c @end example @c ================================================================= @c @c APPENDIX: Reporting Bugs @c @c @node Bugs and Enhancements @appendix Bugs and Enhancements For an up-to-date description of bugs and other issues, please consult the bugs file included in the distribution: @uref{http://proofgeneral.inf.ed.ac.uk/releases/ProofGeneral-latest/BUGS,@file{BUGS}}. If you discover a problem which isn't mentioned in @file{BUGS}, please use the search facility on our Trac tracking system at @uref{http://proofgeneral.inf.ed.ac.uk/trac}. If you cannot find the problem mentioned, please add a ticket, giving a careful description of how to repeat your problem, and saying @b{exactly} which versions of all Emacs and theorem prover you are using. @sp 1 If you have some suggested enhancements to request or contribute, please also use the tracking system at @uref{http://proofgeneral.inf.ed.ac.uk/trac} for this. @node References @unnumbered References A short overview of the Proof General system is described in the note: @itemize @bullet @item @b{[Asp00]} David Aspinall. @i{Proof General: A Generic Tool for Proof Development}. Tools and Algorithms for the Construction and Analysis of Systems, Proc TACAS 2000. LNCS 1785. @end itemize Script management as used in Proof General is described in the paper: @itemize @bullet @item @b{[BT98]} Yves Bertot and Laurent Théry. @i{A generic approach to building user interfaces for theorem provers}. Journal of Symbolic Computation, 25(7), pp. 161-194, February 1998. @end itemize Proof General has support for proof by pointing, as described in the document: @itemize @bullet @item @b{[BKS97]} Yves Bertot, Thomas Kleymann-Schreiber and Dilip Sequeira. @i{Implementing Proof by Pointing without a Structure Editor}. LFCS Technical Report ECS-LFCS-97-368. Also published as Rapport de recherche de l'INRIA Sophia Antipolis RR-3286 @end itemize @c @c @c APPENDIX: History @c @c @node History of Proof General @unnumbered History of Proof General @cindex history It all started some time in 1994. There was no Emacs interface for LEGO. Back then, Emacs militants worked directly with the Emacs shell to interact with the LEGO system. David Aspinall convinced Thomas Kleymann that programming in Emacs Lisp wasn't so difficult after all. In fact, Aspinall had already implemented an Emacs interface for Isabelle with bells and whistles, called @uref{http://homepages.inf.ed.ac.uk/da/Isamode,Isamode}. Soon after, the package @code{lego-mode} was born. Users were able to develop proof scripts in one buffer. Support was provided to automatically send parts of the script to the proof process. The last official version with the name @code{lego-mode} (1.9) was released in May 1995. @cindex proof by pointing @cindex CtCoq @cindex Centaur The interface project really took off the ground in November 1996. Yves Bertot had been working on a sophisticated user interface for the Coq system (CtCoq) based on the generic environment Centaur. He visited the Edinburgh LEGO group for a week to transfer proof-by-pointing technology. Even though proof-by-pointing is an inherently structure-conscious algorithm, within a week, Yves Bertot, Dilip Sequeira and Thomas Kleymann managed to implement a first prototype of proof-by-pointing in the Emacs interface for LEGO [BKS97]. @cindex structure editor @cindex script management Perhaps we could reuse even more of the CtCoq system. It being a structure editor did no longer seem to be such an obstacle. Moreover, to conveniently use proof-by-pointing in actual developments, one would need better support for script management. @cindex generic In 1997, Dilip Sequeira implemented script management in our Emacs interface for LEGO following the recipe in [BT98]. Inspired by the project CROAP, the implementation made some effort to be generic. A working prototype was demonstrated at UITP'97. In October 1997, Healfdene Goguen ported @code{lego-mode} to Coq. Part of the generic code in the @code{lego} package was outsourced (and made more generic) in a new package called @code{proof}. Dilip Sequeira provided some LEGO-specific support for handling multiple files and wrote a few manual pages. The system was reasonably robust and we shipped out the package to friends. In June 1998, David Aspinall reentered the picture by providing an instantiation for Isabelle. Actually, our previous version wasn't quite as generic as we had hoped. Whereas LEGO and Coq are similar systems in many ways, Isabelle was really a different beast. Fierce re-engineering and various usability improvements were provided by Aspinall and Kleymann to make it easier to instantiate to new proof systems. The major technical improvement was a truly generic extension of script management to work across multiple files. It was time to come up with a better name than just @code{proof} mode. David Aspinall suggested @emph{Proof General} and set about reorganizing the file structure to disentangle the Proof General project from LEGO at last. He cooked up some images and bolted on a toolbar, so a naive user can replay proofs without knowing a proof assistant language or even Emacs hot-keys. He also designed some web pages, and wrote most of this manual. Despite views of some detractors, we demonstrated that an interface both friendly and powerful can be built on top of Emacs. Proof General 2.0 was the first official release of the improved program, made in December 1998. Version 2.1 was released in August 1999. It was used at the Types Summer School held in Giens, France in September 1999 (see @uref{http://www-sop.inria.fr/types-project/types-sum-school.html}). About 50 students learning Coq, Isabelle, and LEGO used Proof General for all three systems. This experience provided invaluable feedback and encouragement to make the improvements that went into Proof General 3.0. @menu * Old News for 3.0:: * Old News for 3.1:: * Old News for 3.2:: * Old News for 3.3:: * Old News for 3.4:: * Old News for 3.5:: * Old News for 3.6:: * Old News for 3.7:: @end menu @node Old News for 3.0 @unnumberedsec Old News for 3.0 Proof General 3.0 (released November 1999) has many improvements over 2.x releases. First, there are usability improvements. The toolbar was somewhat impoverished before. It now has twice as many buttons, and includes all of the useful functions used during proof which were previously hidden on the menu, or even only available as key-presses. Key-bindings have been re-organized, users of previous versions may notice. The menu has been redesigned and coordinated with the toolbar, and now gives easy access to more of the features of Proof General. Previously several features were only likely to be discovered by those keen enough to read this manual! Second, there are improvements, extensions, and bug fixes in the generic basis. Proofs which are unfinished and not explicitly closed by a ``save'' type command are supported by the core, if they are allowed by the prover. The design of switching the active scripting buffer has been streamlined. The management of the queue of commands waiting to be sent to the shell has been improved, so there are fewer unnecessary "Proof Process Busy!" messages. The support for scripting with multiple files was improved so that it behaves reliably with Isabelle99; file reading messages can be communicated in both directions now. The proof shell filter has been optimized to give hungry proof assistants a better share of CPU cycles. Proof-by-pointing has been resurrected; even though LEGO's implementation is incomplete, it seems worth maintaining the code in Proof General so that the implementors of other proof assistants are encouraged to provide support. For one example, we can certainly hope for support in Coq, since the CtCoq proof-by-pointing code has been moved into the Coq kernel lately. We need a volunteer from the Coq community to help to do this. An important new feature in Proof General 3.0 is support for @uref{http://x-symbol.sourceforge.net/,X-Symbol}, which means that real logical symbols, Greek letters, etc can be displayed during proof development, instead of their ASCII approximations. This makes Proof General a more serious competitor to native graphical user interfaces. Finally, Proof General has become much easier to adapt to new provers --- it fails gracefully (or not at all!) when particular configuration variables are unset, and provides more default settings which work out-of-the-box. An example configuration for Isabelle is provided, which uses just 25 or so simple settings. This manual has been updated and extended for Proof General 3.0. Amongst other improvements, it has a better description of how to add support for a new prover. See the @code{CHANGES} file in the distribution for more information about the latest improvements in Proof General. Developers should check the @code{ChangeLog} in the developer's release for detailed comments on internal changes. Most of the work for Proof General 3.0 has been done by David Aspinall. Markus Wenzel helped with Isabelle support, and provided invaluable feedback and testing, especially for the improvements to multiple file handling. Pierre Courtieu took responsibility from Patrick Loiseleur for Coq support, although improvements in both Coq and LEGO instances for this release were made by David Aspinall. Markus Wenzel provided support for his Isar language, a new proof language for Isabelle. David von Oheimb helped to develop the generic version of his X-Symbol addition which he originally provided for Isabelle. A new instantiation of Proof General is being worked on for @emph{Plastic}, a proof assistant being developed at the University of Durham. @node Old News for 3.1 @unnumberedsec Old News for 3.1 @cindex news Proof General 3.1 (released March 2000) is a bug-fix improvement over version 3.0. There are some minor cosmetic improvements, but large changes have been held back to ensure stability. This release solves a few minor problems which came to light since the final testing stages for 3.0. It also solves some compatibility problems, so now it works with various versions of Emacs which we hadn't tested with before (non-mule GNU Emacs, certain Japanese Emacs versions). We're also pleased to announce HOL Proof General, a new instance of Proof General for HOL98. This is supplied as a "technology demonstration" for HOL users in the hope that somebody from the HOL community will volunteer to adopt it and become a maintainer and developer. (Otherwise, work on HOL Proof General will not continue). Apart from that there are a few other small improvements. Check the CHANGES file in the distribution for full details. The HOL98 support and much of the work on Proof General 3.1 was undertaken by David Aspinall while he was visiting ETL, Osaka, Japan, supported by the British Council and ETL. @node Old News for 3.2 @unnumberedsec Old News for 3.2 @cindex news Proof General 3.2 introduced several new features and some bug fixes. One noticeable new feature is the addition of a prover-specific menu for each of the supported provers. This menu has a ``favourites'' feature that you can use to easily define new functions. Please contribute other useful functions (or suggestions) for things you would like to appear on these menus. Because of the new menus and to make room for more commands, we have made a new key map for prover specific functions. These now all begin with @kbd{C-c C-a}. This has changed a few key bindings slightly. Another new feature is the addition of prover-specific completion tables, to encourage the use of Emacs's completion facility, using @kbd{C-RET}. @xref{Support for completion}, for full details. A less obvious new feature is support for turning the proof assistant output on and off internally, to improve efficiency when processing large scripts. This means that more of your CPU cycles can be spent on proving theorems. Adapting for new proof assistants continues to be made more flexible, and easier in several places. This has been motivated by adding experimental support for some new systems. One new system which had good support added in a very short space of time is @b{PhoX} (see @uref{http://www.lama.univ-savoie.fr/~RAFFALLI/af2.html, the PhoX home page} for more information). PhoX joins the rank of officially supported Proof General instances, thanks to its developer Christophe Raffalli. Breaking the manual into two pieces was overdue: now all details on adapting Proof General, and notes on its internals, are in the @i{Adapting Proof General} manual. You should find a copy of that second manual close to wherever you found this one; consult the Proof General home page if in doubt. The internal code of Proof General has been significantly overhauled for this version, which should make it more robust and readable. The generic code has an improved file structure, and there is support for automatic generation of autoload functions. There is also a new mechanism for defining prover-specific customization and instantiation settings which fits better with the customize library. These settings are named in the form @code{@i{PA}-setting-name} in the documentation; you replace @i{PA} by the symbol for the proof assistant you are interested in. @xref{Customizing Proof General}, for details. Finally, important bug fixes include the robustification against @code{write-file} (@kbd{C-x C-w}), @code{revert-buffer}, and friends. These are rather devious functions to use during script management, but Proof General now tries to do the right thing if you're deviant enough to try them out! Work on this release was undertaken by David Aspinall between May-September 2000, and includes contributions from Markus Wenzel, Pierre Courtieu, and Christophe Raffalli. Markus added some Isar documentation to this manual. @node Old News for 3.3 @unnumberedsec Old News for 3.3 Proof General 3.3 includes a few feature additions, but mainly the focus has been on compatibility improvements for new versions of provers (in particular, Coq 7), and new versions of emacs (in particular, XEmacs 21.4). One new feature is control over visibility of completed proofs, @xref{Visibility of completed proofs}. Another new feature is the tracking of theorem dependencies inside Isabelle. A context-sensitive menu (right-button on proof scripts) provides facility for browsing the ancestors and child theorems of a theorem, and highlighting them. The idea of this feature is that it can help you untangle and rearrange big proof scripts, by seeing which parts are interdependent. The implementation is provisional and not documented yet in the body of this manual. It only works for the "classic" version of Isabelle99-2. @node Old News for 3.4 @unnumberedsec Old News for 3.4 Proof General 3.4 adds improvements and also compatibility fixes for new versions of Emacs, in particular, for GNU Emacs 21, which adds the remaining pretty features that have only been available to XEmacs users until now (the toolbar and X-Symbol support). One major improvement has been to provide better support for synchronization with Coq proof scripts; now Coq Proof General should be able to retract and replay most Coq proof scripts reliably. Credit is due to Pierre Courtieu, who also updated the documentation in this manual. As of version 3.4, Proof General is distributed under the GNU General Public License (GPL). Compared with the previous more restrictive license, this means the program can now be redistributed by third parties, and used in any context without applying for a special license. Despite these legal changes, we would still appreciate if you send us back any useful improvements you make to Proof General. @node Old News for 3.5 @unnumberedsec Old News for 3.5 @node Old News for 3.6 @unnumberedsec Old News for 3.6 There was no 3.6 release of Proof General. @node Old News for 3.7 @unnumberedsec Old News for 3.7 Proof General version 3.7.1 is an updated and enhanced version of Proof General 3.7. See @file{CHANGES} for more details. Proof General version 3.7 collects together a cumulative set of improvements to Proof General 3.5. There are compatibility fixes for newer Emacs versions, and particularly for GNU Emacs: credit is due to Stefan Monnier for an intense period of debugging and patching. The options menu has been simplified and extended, and the display management is improved and repaired for Emacs API changes. There are some other usability improvements, some after feedback from use at TYPES Summer Schools. Many new features have been added to enhance Coq mode (thanks to Pierre Courtieu) and several improvements made for Isabelle (thanks to Makarius Wenzel, Stefan Berghofer and Tjark Weber). Support has been added for the useful Emacs packages Speedbar @c @uref{http://cedet.sourceforge.net/speedbar.shtml,Speedbar} and Index Menu, both usually distributed with Emacs. A compatible version of the Emacs package Math-Menu (for Unicode symbols) is bundled with Proof General. An experimental Unicode Tokens package has been added which will replace X-Symbol. See the @file{CHANGES} file in the distribution for more complete details of changes since version 3.5, and the appendix @ref{History of Proof General} for old news. @node Function Index @unnumbered Function and Command Index @printindex fn @node Variable Index @unnumbered Variable and User Option Index @printindex vr @node Keystroke Index @unnumbered Keystroke Index @printindex ky @node Concept Index @unnumbered Concept Index @printindex cp @page @contents @bye PG-4.5/doc/README.documentation000066400000000000000000000023211426357011200161640ustar00rootroot00000000000000Proof General Documentation =========================== The distribution may include pre-built documentation for your convenience. Otherwise you will need to run make info make dvi make pdf make html according to what format you'd like. Everything is generated from the master Texinfo files ProofGeneral.texi and PG-adapting.texi, so you'll need the proper tools for conversion. Check Makefile.doc for details. Front Image for Manual ---------------------- If you want a front image on the printed dvi/gs manuals, you need to have the ProofGeneral.eps file in this directory. You can download a compressed version from http://proofgeneral.inf.ed.ac.uk/ProofGeneralPortrait.eps.gz This file is not included with the distribution because it is rather large (1.6M). Instead of downloading, you may be able to generate an alternative eps from the included ProofGeneral-image.jpg file using an image manipulation program such as gimp or Imagemagick. This will give you a slightly different (and degraded) image compared to the distributed one mentioned above. Running "made dvi" will adjust the Texinfo file to make the front page blank if there is no ProofGeneral.eps file available. David Aspinall. August 2000. PG-4.5/doc/dir000066400000000000000000000012631426357011200131410ustar00rootroot00000000000000This is the file .../info/dir, which contains the topmost node of the Info hierarchy. The first time you invoke Info you start off looking at that node, which is (dir)Top.  File: dir Node: Top This is the top of the INFO tree This (the Directory node) gives a menu of major topics. Typing "q" exits, "?" lists all Info commands, "d" returns here, "h" gives a primer for first-timers, "mEmacs" visits the Emacs topic, etc. In Emacs, you can click mouse button 2 on a menu item or cross reference to select it. * Menu: Theorem proving * ProofGeneral: (ProofGeneral). Organize your proofs with Emacs! * Adapting PG: (PG-adapting). Adapt Proof General to new provers PG-4.5/doc/docstring-magic.el000066400000000000000000000070751426357011200160430ustar00rootroot00000000000000;;; doc/docstring-magic.el --- hack for using texi-docstring-magic. ;; This file is part of Proof General. ;; Portions © Copyright 1994-2012 David Aspinall and University of Edinburgh ;; Portions © Copyright 2003-2018 Free Software Foundation, Inc. ;; Portions © Copyright 2001-2017 Pierre Courtieu ;; Portions © Copyright 2010, 2016 Erik Martin-Dorel ;; Portions © Copyright 2011-2013, 2016-2017 Hendrik Tews ;; Portions © Copyright 2015-2017 Clément Pit-Claudel ;; Author: David Aspinall ;; Maintainer: Proof General maintainer ;;; Commentary: ;; ;; Ensure that non-compiled versions of everything are loaded. ;; ;;; Code: (setq load-path (append '("../generic/") load-path)) (load "proof-site.el") (require 'proof-autoloads) (require 'proof-utils) ;; Prevent loading some files normally loaded in compilation ;; NB: Loading several prover files at once is a bit of a problem ;; with new config mechanism. ;; Could abstract more code in proof-site.el to avoid duplication here. (let ((assistants (mapcar (function car) proof-assistant-table))) ; assume not customized (while assistants (let* ((assistant (car assistants)) ; compiler bogus warning here (nameregexp (or (cdr-safe (assoc assistant proof-assistant-table)) (error "Symbol %s is not in proof-assistant-table (in docstring-magic)" (symbol-name assistant)))) (assistant-name (car nameregexp)) (sname (symbol-name assistant)) (elisp-file sname)) (setq proof-assistant-symbol nil) ;; proof-ready-for-assistant below loads pg-custom by require. ;; pg-custom must be loaded for each proof assistant again, ;; because it defines a lot with defpgcustom, which defines ;; assistent specific variables by using assistant-symbol ;; (called assistant here). Therefore, delete pg-custom from the ;; featue list here, such that it is also loaded for the second ;; proof assistant. Otherwise (proof-ass keymap) would fail ;; because the symbol is not defined for the second proof ;; assistant. And (proof-ass keymap) is put into ;; proof-ready-for-assistant-hook by ;; proof-eval-when-ready-for-assistant, when proof-script is ;; loaded as autoload for proof-ready-for-assistant, because ;; then proof-assistant is not yet set. (setq features (delete 'pg-custom features)) (proof-ready-for-assistant assistant assistant-name) ;; Must load proof-config each time to define proof assistant ;; specific variables (setq features (delete 'pg-custom features)) (load-library elisp-file) (setq assistants (cdr assistants))))) ;; Now a fake proof assistant to document the automatically ;; specific variables (setq proof-assistant-symbol nil) ;; ensure again, pg-custom is loaded inside proof-ready-for-assistant, ;; see above (setq features (delete 'pg-custom features)) (proof-ready-for-assistant 'PA "PROOF ASSISTANT") (setq features (delete 'pg-custom features)) (load "pg-custom.el") ;; These next few are autoloaded usually (load "proof-menu.el") (load "proof-toolbar.el") (load "proof-script.el") (load "proof-shell.el") (load "pg-user.el") (load "pg-goals.el") (load "pg-response.el") (load "unicode-tokens.el") (load "proof-splash.el") ;; A couple of comint symbols are mentioned in the docs (require 'comint) ;; Also completion (require 'completion) ;; Set some symbols to make markup happen (setq sml-mode 'markup-hack) (setq func-menu 'markup-hack) (load "texi-docstring-magic.el") (provide 'docstring-magic) ;;; docstring-magic.el ends here PG-4.5/doc/proofgen.css000066400000000000000000000050541426357011200147730ustar00rootroot00000000000000/* Style sheet for the Proof General web pages. * David Aspinall, June 1999. * proofgen.css,v 4.0 2000/03/13 07:36:57 da Exp */ body{ font-family: Verdana, Arial, sans-serif; background: #2D1D03; /* background brown */ background-attachment: fixed; color: #FFFFFF; } p{ max-width: 1024px; font-family: Verdana, Arial, sans-serif; color: #FFFFFF; } pre{ color: #FFFFFF; } h1{ color: #FFFFFF; font-size: large; font-weight: bold; } h2{ font-size: medium; font-weight: bold; color: #FFFFD0; padding: 2px 4px 4px 8px; background: #5D2D13; } h3{ font-size: medium; padding: 2px 2px 2px 8px; margin-right: 50%; background: #4D1D23; color: #FFFFD0; } h4{ font-size: medium; color: #FFD0D0; padding: 2px 2px 2px 8px; } blockquote,form,input,select{ color: #FFFFFF; } address{ font-size: small; color: #FFFFFF; } select { font-size: 100%; background: #2D1D03; color: #FFFFFF; } textarea,input { font-size: 100%; background: #4D2D23; color: #FFFFFF; } input[type=submit],input[type=reset],input[type=Submit] { font-size: 80%; padding-top: 0px; padding-bottom: 0px; background: #401010; } #button:active{ background: #402020; } dl,ul,dir,li{ color: #FFFFFF; max-width: 1024px; } dt{ font-style: italic; padding: 2px 2px 2px 8px; margin-left: 20px; margin-right: 20px; background: #4D1D23; } table{ font-family: Verdana, Arial, sans-serif; color: #FFFFFF; } table.menubar{ font-family: Verdana, Arial, sans-serif; font-size: smaller; color: #FFFFFF; } td,tr{ color: #FFFFFF; } a:link,a:visited{ font-family: Verdana, Arial, sans-serif; text-decoration: none; color: #E0D020; } a:active,a:hover{ font-family: Verdana, Arial, sans-serif; text-decoration: underline; color: #E8D830; } pre{ background: #2D1D03; } /* Specifics */ p.nb{ font-size: smaller; font-style: italic; } /* These bits for Mailman pages for mailing lists */ TD.head1old { font-family: Verdana, Arial, sans-serif; text-align: center; color: #FFFFFF; font-weight: bold; font-size: 110%; } td.head1{ font-family: Verdana, Arial, sans-serif; font-weight: bold; font-size: 110%; text-align: center; color: #FFFFFF; } td.head2{ font-family: Verdana, Arial, sans-serif; font-size: 100%; font-weight: bold; color: #FFFFD0; padding: 2px 4px 4px 4px; background: #7D4D33; } td.head3{ font-family: Verdana, Arial, sans-serif; padding: 2px 2px 2px 2px; margin-right: 10%; background: #6D3D43; font-size: 80%; color: #FFFFD0; } td.head4{ font-family: Verdana, Arial, sans-serif; font-size: 100%; font-weight: bold; color: #FFD0D0; } PG-4.5/doc/proofgeneral.1000066400000000000000000000027051426357011200152070ustar00rootroot00000000000000.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.35. .TH PROOFGENERAL "1" "August 2005" "proofgeneral ()" "User Commands" .SH NAME proofgeneral \- manual page for proofgeneral () .SH SYNOPSIS .B proofgeneral [\fIOPTION\fR] [\fIFILE\fR]... .SH DESCRIPTION Launches Emacs Proof General, editing the proof script FILE. .SH OPTIONS .TP \fB\-\-emacs\fR startup Proof General with emacs (GNU Emacs) .TP \fB\-\-xemacs\fR startup Proof General with xemacs (XEmacs) .TP \fB\-\-emacsbin\fR startup Proof General with emacs binary .TP \fB\-h\fR, \fB\-\-help\fR show this help and exit .TP \fB\-v\fR, \fB\-\-version\fR output version information and exit .PP Unrecognized options are passed to Emacs, along with file names. .SH EXAMPLES .TP proofgeneral Example.ec Load Proof General editing EasyCrypt file Example.ec .TP proofgeneral example.v Load Proof General editing Coq file Example.v .PP For documentation and latest versions, visit http://proofgeneral.inf.ed.ac.uk. .SH "REPORTING BUGS" Report bugs to . .PP David Aspinall. .SH COPYRIGHT Copyright \(co 1998-2005 LFCS, University of Edinburgh, UK. .br This is free software; see the source for copying conditions. .SH "SEE ALSO" The full documentation for .B proofgeneral is maintained as a Texinfo manual. If the .B info and .B proofgeneral programs are properly installed at your site, the command .IP .B info proofgeneral .PP should give you access to the complete manual. PG-4.5/easycrypt/000077500000000000000000000000001426357011200137145ustar00rootroot00000000000000PG-4.5/easycrypt/easycrypt-abbrev.el000066400000000000000000000016201426357011200175170ustar00rootroot00000000000000;;; easycrypt-abbrev.el --- Abbrev table and menus for EasyCrypt mode ;; -------------------------------------------------------------------- ;; Copyright (c) - 2012--2016 - IMDEA Software Institute ;; Copyright (c) - 2012--2016 - Inria ;; ;; Distributed under the terms of the GPL-v3 license ;; -------------------------------------------------------------------- ;;; Commentary: ;; (require 'proof) (require 'easycrypt-syntax) ;;; Code: (defpgdefault menu-entries '( ["Use Three Panes" proof-three-window-toggle :style toggle :active (not proof-multiple-frames-enable) :selected proof-three-window-enable :help "Use three panes"] ["Weak-check mode" easycrypt-proof-weak-mode-toggle :style toggle :selected easycrypt-proof-weak-mode :help "Toggles EasyCrypt check mode."] )) (provide 'easycrypt-abbrev) ;;; easycrypt-abbrev.el ends here PG-4.5/easycrypt/easycrypt-hooks.el000066400000000000000000000053521426357011200174070ustar00rootroot00000000000000;;; easycrypt-hooks.el --- Auxiliary functions for EasyCrypt mode ;; -------------------------------------------------------------------- ;; Copyright (c) - 2012--2016 - IMDEA Software Institute ;; Copyright (c) - 2012--2016 - Inria ;; ;; Distributed under the terms of the GPL-v3 license ;; -------------------------------------------------------------------- ;;; Commentary: ;; (require 'span) (require 'proof) ;;; Code: (defvar easycrypt-last-but-one-statenum 0) (defvar easycrypt-proof-weak-mode nil) ;; Proof mode (defun easycrypt-proof-weak-mode-toggle () "Toggle EasyCrypt check mode." (interactive) (cond (easycrypt-proof-weak-mode (proof-shell-invisible-cmd-get-result "pragma Proofs:check")) (t (proof-shell-invisible-cmd-get-result "pragma Proofs:weak"))) (if (eq 'error proof-shell-last-output-kind) (message "Failed to set proof mode"))) ;; Function for set or get the information in the span (defsubst easycrypt-get-span-statenum (span) "Return the state number of the SPAN." (span-property span 'statenum)) (defsubst easycrypt-set-span-statenum (span val) "Set the state number of the SPAN to VAL." (span-set-property span 'statenum val)) (defsubst proof-last-locked-span () (with-current-buffer proof-script-buffer (span-at (- (proof-unprocessed-begin) 1) 'type))) (defun easycrypt-last-prompt-info (s) "Extract the information from prompt." (let ((lastprompt (or s (error "No prompt")))) (when (string-match "\\[\\([0-9]+\\)|\\(\\sw+\\)\\]" lastprompt) (list (string-to-number (match-string 1 lastprompt)) (if (equal (match-string 2 lastprompt) "weakcheck") t nil))))) (defun easycrypt-last-prompt-info-safe () "Take from `proof-shell-last-prompt' the last information in the prompt." (easycrypt-last-prompt-info proof-shell-last-prompt)) (defun easycrypt-set-state-infos () "Set information necessary for backtracking." (if proof-shell-last-prompt ;; infos = prompt infos of the very last prompt ;; sp = last locked span, which we want to fill with prompt infos (let ((sp (if proof-script-buffer (proof-last-locked-span))) (infos (or (easycrypt-last-prompt-info-safe) '(0 nil)))) (unless (or (not sp) (easycrypt-get-span-statenum sp)) (easycrypt-set-span-statenum sp easycrypt-last-but-one-statenum)) (setq easycrypt-last-but-one-statenum (car infos)) (setq easycrypt-proof-weak-mode (car (cdr infos))) ))) (add-hook 'proof-state-change-pre-hook 'easycrypt-set-state-infos) (defun easycrypt-find-and-forget (span) (let ((span-staten (easycrypt-get-span-statenum span))) (list (format "undo %s." (int-to-string span-staten))))) (provide 'easycrypt-hooks) ;;; easycrypt-hooks.el ends here PG-4.5/easycrypt/easycrypt-keywords.el000066400000000000000000000043641426357011200201350ustar00rootroot00000000000000;;; easycrypt-keywords.el --- Definition of keywords for EasyCrypt mode ;; -------------------------------------------------------------------- ;; Copyright (c) - 2012--2016 - IMDEA Software Institute ;; Copyright (c) - 2012--2016 - Inria ;; ;; Distributed under the terms of the GPL-v3 license ;; -------------------------------------------------------------------- ;;; Commentary: ;; ;; Generated on Tue Feb 21 23:37:34 2017 ;; ;;; Code: (defvar easycrypt-bytac-keywords '( "exact" "assumption" "smt" "by" "reflexivity" "done" )) (defvar easycrypt-dangerous-keywords '( "admit" "admitted" )) (defvar easycrypt-global-keywords '( "axiom" "axiomatized" "lemma" "realize" "proof" "qed" "abort" "goal" "end" "import" "export" "include" "local" "declare" "hint" "nosmt" "module" "of" "const" "op" "pred" "inductive" "notation" "abbrev" "require" "theory" "abstract" "section" "type" "class" "instance" "print" "search" "as" "Pr" "clone" "with" "rename" "prover" "timeout" "why3" "dump" "remove" "Top" "Self" )) (defvar easycrypt-internal-keywords '( "time" "undo" "debug" "pragma" )) (defvar easycrypt-prog-keywords '( "forall" "exists" "fun" "glob" "let" "in" "var" "proc" "if" "then" "else" "elif" "while" "assert" "return" "res" "equiv" "hoare" "phoare" "islossless" "async" )) (defvar easycrypt-tactic-keywords '( "beta" "iota" "zeta" "eta" "logic" "delta" "simplify" "congr" "change" "split" "left" "right" "case" "pose" "cut" "have" "suff" "elim" "clear" "apply" "rewrite" "rwnormal" "subst" "progress" "trivial" "auto" "idtac" "move" "modpath" "field" "fieldeq" "ring" "ringeq" "algebra" "transitivity" "symmetry" "seq" "wp" "sp" "sim" "skip" "call" "rcondt" "rcondf" "swap" "cfold" "rnd" "pr_bounded" "bypr" "byphoare" "byequiv" "fel" "conseq" "exfalso" "inline" "alias" "fission" "fusion" "unroll" "splitwhile" "kill" "eager" )) (defvar easycrypt-tactical-keywords '( "try" "first" "last" "do" "strict" "expect" )) (provide 'easycrypt-keywords) ;;; easycrypt-keywords.el ends here PG-4.5/easycrypt/easycrypt-syntax.el000066400000000000000000000151641426357011200176140ustar00rootroot00000000000000;;; easycrypt-syntax.el --- Syntax definitions for EasyCrypt mode ;; -------------------------------------------------------------------- ;; Copyright (c) - 2012--2016 - IMDEA Software Institute ;; Copyright (c) - 2012--2016 - Inria ;; ;; Distributed under the terms of the GPL-v3 license ;; -------------------------------------------------------------------- ;;; Commentary: ;; (require 'proof-syntax) (require 'easycrypt-keywords) (require 'easycrypt-hooks) ;;; Code: (defconst easycrypt-id "[A-Za-z_]+") (defconst easycrypt-terminal-string ".") (defconst easycrypt-command-end-regexp "[^\\.]\\.\\(\\s \\|\n\\|$\\)") (defconst easycrypt-keywords-proof-goal '("lemma" "equiv" "hoare" "realize")) (defconst easycrypt-keywords-proof-save '("save" "qed")) (defconst easycrypt-non-undoables-regexp "^pragma\\b") (defconst easycrypt-keywords-code-open '("{")) (defconst easycrypt-keywords-code-close '("}")) (defconst easycrypt-keywords-code-end '(";")) (defvar easycrypt-other-symbols "\\(\\.\\.\\|\\[\\]\\)") (defvar easycrypt-operator-char-1 "=\\|<\\|>\\|~") (defvar easycrypt-operator-char-2 "\\+\\|\\-") (defvar easycrypt-operator-char-3 "\\*\\|/\\|%") (defvar easycrypt-operator-char-4 "!\\|\\$\\|&\\|\\?\\|@\\|\\^\\|:\\||\\|#") (defvar easycrypt-operator-char-1234 (concat "\\(" easycrypt-operator-char-1 "\\|" easycrypt-operator-char-2 "\\|" easycrypt-operator-char-3 "\\|" easycrypt-operator-char-4 "\\)")) (defconst easycrypt-proof-save-regexp (concat "^\\(" (proof-ids-to-regexp easycrypt-keywords-proof-save) "\\)\\b")) (defconst easycrypt-goal-command-regexp (concat "^\\(?:local\\s-+\\)?\\(?:" (proof-ids-to-regexp easycrypt-keywords-proof-goal) "\\)" "\\s-+\\(?:nosmt\\s-+\\)?\\(\\sw+\\)")) (defun easycrypt-save-command-p (span str) "Decide whether argument is a [save|qed] command or not." (let ((txt (or (span-property span 'cmd) ""))) (proof-string-match-safe easycrypt-proof-save-regexp txt))) (defun easycrypt-goal-command-p (span) "Is SPAN a goal start?" (let ((txt (or (span-property span 'cmd) ""))) (proof-string-match-safe easycrypt-goal-command-regexp txt))) (defun easycrypt-init-output-syntax-table () "Set appropriate values for syntax table for EasyCrypt output." (modify-syntax-entry ?, " ") (modify-syntax-entry ?\' "_") (modify-syntax-entry ?_ "_") ;; For comments (modify-syntax-entry ?\* ". 23") ;; For blocks (modify-syntax-entry ?\( "()1") (modify-syntax-entry ?\) ")(4") (modify-syntax-entry ?\{ "(}") (modify-syntax-entry ?\} "){") (modify-syntax-entry ?\[ "(]") (modify-syntax-entry ?\] ")[")) ;; ----- regular expressions (defvar easycrypt-error-regexp "^\\[error-[0-9]+-[0-9]+\\]\\|^anomaly" "A regexp indicating that the EasyCrypt process has identified an error.") (defvar easycrypt-shell-proof-completed-regexp "No more goals" "*Regular expression indicating that the proof has been completed.") (defconst easycrypt-any-command-regexp ;; allow terminator to be considered as command start: ;; FIXME: really needs change in generic function to take account of this, ;; since the end character of a command is not the start (concat "\\(\\s(\\|\\s)\\|\\sw\\|\\s \\|\\s_\\)*=" ;match assignments "\\|;;\\|;\\|" (proof-ids-to-regexp easycrypt-global-keywords)) "Regexp matching any EasyCrypt command start or the terminator character.") (defconst easycrypt-keywords-indent-open (append (append '("local") easycrypt-keywords-proof-goal) easycrypt-keywords-code-open)) (defconst easycrypt-keywords-indent-close (append easycrypt-keywords-proof-save easycrypt-keywords-code-close)) (defconst easycrypt-keywords-indent-enclose (append easycrypt-keywords-code-open easycrypt-keywords-code-close easycrypt-keywords-code-end easycrypt-keywords-proof-goal easycrypt-keywords-proof-save)) ; Regular expression for indentation (defconst easycrypt-indent-any-regexp (proof-regexp-alt easycrypt-any-command-regexp "\\s(" "\\s)")) (defconst easycrypt-indent-enclose-regexp (proof-regexp-alt (proof-ids-to-regexp easycrypt-keywords-indent-enclose) "\\s)")) (defconst easycrypt-indent-open-regexp (proof-regexp-alt (proof-ids-to-regexp easycrypt-keywords-indent-open) "\\s(")) (defconst easycrypt-indent-close-regexp (proof-regexp-alt (proof-ids-to-regexp easycrypt-keywords-indent-close) "\\s)")) (defface easycrypt-tactics-closing-face (proof-face-specs (:foreground "red") (:foreground "red") ()) "Face for names of closing tactics in proof scripts." :group 'proof-faces) (defface easycrypt-tactics-dangerous-face (proof-face-specs (:background "red") (:background "red") ()) "Face for names of dangerous tactics in proof scripts." :group 'proof-faces) (defface easycrypt-tactics-tacticals-face (proof-face-specs (:foreground "dark green") (:foreground "dark green") ()) "Face for names of tacticals in proof scripts." :group 'proof-faces) (defconst easycrypt-tactics-closing-face 'easycrypt-tactics-closing-face) (defconst easycrypt-tactics-dangerous-face 'easycrypt-tactics-dangerous-face) (defconst easycrypt-tactics-tacticals-face 'easycrypt-tactics-tacticals-face) (defvar easycrypt-font-lock-keywords (list (cons (proof-ids-to-regexp easycrypt-global-keywords) 'font-lock-keyword-face) (cons (proof-ids-to-regexp easycrypt-tactic-keywords) 'proof-tactics-name-face) (cons (proof-ids-to-regexp easycrypt-tactical-keywords) 'easycrypt-tactics-tacticals-face) (cons (proof-ids-to-regexp easycrypt-bytac-keywords) 'easycrypt-tactics-closing-face) (cons (proof-ids-to-regexp easycrypt-dangerous-keywords) 'easycrypt-tactics-dangerous-face) (cons (proof-ids-to-regexp easycrypt-prog-keywords) 'font-lock-keyword-face) (cons (concat easycrypt-operator-char-1234 "+") 'font-lock-type-face) (cons easycrypt-other-symbols 'font-lock-type-face))) (defun easycrypt-init-syntax-table () "Set appropriate values for syntax table in current buffer." (modify-syntax-entry ?\$ ".") (modify-syntax-entry ?\/ ".") (modify-syntax-entry ?\\ ".") (modify-syntax-entry ?+ ".") (modify-syntax-entry ?- ".") (modify-syntax-entry ?= ".") (modify-syntax-entry ?% ".") (modify-syntax-entry ?< ".") (modify-syntax-entry ?> ".") (modify-syntax-entry ?\& ".") (modify-syntax-entry ?_ "_") (modify-syntax-entry ?\' "_") (modify-syntax-entry ?\| ".") (modify-syntax-entry ?\. ".") (modify-syntax-entry ?\* ". 23n") (modify-syntax-entry ?\( "()1") (modify-syntax-entry ?\) ")(4")) (provide 'easycrypt-syntax) ;;; easycrypt-syntax.el ends here PG-4.5/easycrypt/easycrypt.el000066400000000000000000000236341426357011200162710ustar00rootroot00000000000000;;; easycrypt.el --- Major mode for EasyCrypt ;; -------------------------------------------------------------------- ;; Copyright (c) - 2012--2016 - IMDEA Software Institute ;; Copyright (c) - 2012--2016 - Inria ;; ;; Distributed under the terms of the GPL-v3 license ;; -------------------------------------------------------------------- ;;; Commentary: ;; (require 'cl-lib) ;cl-every (require 'proof) (require 'easycrypt-syntax) (require 'easycrypt-hooks) (require 'easycrypt-abbrev) ;;; Code: (add-to-list 'hs-special-modes-alist '(easycrypt-mode "{" "}" "/[*/]" nil nil)) ;; -------------------------------------------------------------------- (defun easycrypt-load-path-safep (path) (and (listp path) (cl-every #'stringp path))) ;; -------------------------------------------------------------------- (defcustom easycrypt-prog-name "easycrypt" "*Name of program to run EasyCrypt." :type 'file :group 'easycrypt) (defcustom easycrypt-load-path nil "Non-standard EasyCrypt library load path. This list specifies the include path for EasyCrypt. The elements of this list are strings." :type '(repeat (string :tag "simple directory (-I)")) :safe 'easycrypt-load-path-safep :group 'easycrypt) (defcustom easycrypt-web-page "http://www.easycrypt.info/" "URL of web page for EasyCrypt." :type 'string :group 'easycrypt-config) ;; -------------------------------------------------------------------- (defun easycrypt-option-of-load-path-entry (entry) (list "-I" (expand-file-name entry))) ;; -------------------------------------------------------------------- (defun easycrypt-include-options () (let ((result nil)) (when easycrypt-load-path (dolist (entry easycrypt-load-path) (setq result (append result (easycrypt-option-of-load-path-entry entry))))) result)) ;; -------------------------------------------------------------------- (defun easycrypt-build-prog-args () (delete "-emacs" easycrypt-prog-args) (push "-emacs" easycrypt-prog-args)) (easycrypt-build-prog-args) ;; -------------------------------------------------------------------- (defun easycrypt-prog-args () (append easycrypt-prog-args (easycrypt-include-options))) ;; -------------------------------------------------------------------- ;; Generic mode (defun easycrypt-config () "Configure Proof General scripting for EasyCrypt." (easycrypt-init-output-syntax-table) (setq proof-terminal-string easycrypt-terminal-string) (setq proof-script-command-end-regexp easycrypt-command-end-regexp) (setq proof-script-comment-start "(*" proof-script-comment-end "*)") ;; For undo (setq proof-find-and-forget-fn 'easycrypt-find-and-forget proof-completed-proof-behaviour nil proof-non-undoables-regexp easycrypt-non-undoables-regexp proof-shell-restart-cmd "pragma restart. ") (set (make-local-variable 'comment-quote-nested) nil) ;; For func-menu and finding goal...save regions (setq proof-save-command-regexp easycrypt-proof-save-regexp proof-really-save-command-p 'easycrypt-save-command-p proof-save-with-hole-regexp nil proof-goal-command-p 'easycrypt-goal-command-p proof-goal-with-hole-regexp easycrypt-goal-command-regexp proof-goal-with-hole-result 1) (setq proof-goal-command "lemma %s: ." proof-save-command "qed.") (setq proof-prog-name easycrypt-prog-name proof-assistant-home-page easycrypt-web-page) ; Options (setq proof-three-window-enable t proof-three-window-mode-policy (quote hybrid) proof-auto-multiple-files t) ; Setting indents (set (make-local-variable 'indent-tabs-mode) nil) (setq proof-indent-enclose-offset (- proof-indent) proof-indent-open-offset 0 proof-indent-close-offset 0 proof-indent-any-regexp easycrypt-indent-any-regexp proof-indent-enclose-regexp easycrypt-indent-enclose-regexp proof-indent-open-regexp easycrypt-indent-open-regexp proof-indent-close-regexp easycrypt-indent-close-regexp) ; Silent/verbose mode for batch processing (setq proof-shell-start-silent-cmd "pragma silent. " proof-shell-stop-silent-cmd "pragma verbose. ") ; Ask for the current goal (setq proof-showproof-command "pragma noop. ") (easycrypt-init-syntax-table) ;; we can cope with nested comments (set (make-local-variable 'comment-quote-nested) nil) (setq proof-script-font-lock-keywords easycrypt-font-lock-keywords)) (defun easycrypt-shell-config () "Configure Proof General shell for EasyCrypt." (easycrypt-init-output-syntax-table) (setq proof-shell-auto-terminate-commands easycrypt-terminal-string) (setq proof-shell-eager-annotation-start (concat "\\(?:^\\[W\\] *\\)\\|\\(?:" easycrypt-shell-proof-completed-regexp "\\)")) (setq proof-shell-strip-crs-from-input nil) (setq proof-shell-annotated-prompt-regexp "^\\[[0-9]+|\\sw+\\]>") (setq proof-shell-clear-goals-regexp easycrypt-shell-proof-completed-regexp) (setq proof-shell-proof-completed-regexp easycrypt-shell-proof-completed-regexp) (setq proof-shell-error-regexp easycrypt-error-regexp) (setq proof-shell-truncate-before-error nil) (setq proof-shell-start-goals-regexp "^Current") (setq proof-shell-end-goals-regexp nil) ; up to next prompt (setq proof-shell-font-lock-keywords easycrypt-font-lock-keywords)) ;; -------------------------------------------------------------------- ;; Derived modes (define-derived-mode easycrypt-mode proof-mode "EasyCrypt script" nil (easycrypt-config) (proof-config-done)) (define-derived-mode easycrypt-shell-mode proof-shell-mode "EasyCrypt shell" nil (easycrypt-shell-config) (proof-shell-config-done)) (define-derived-mode easycrypt-response-mode proof-response-mode "EasyCrypt response" nil (easycrypt-init-output-syntax-table) (setq proof-response-font-lock-keywords easycrypt-font-lock-keywords) (proof-response-config-done)) (define-derived-mode easycrypt-goals-mode proof-goals-mode "EasyCrypt goals" nil (easycrypt-init-output-syntax-table) (setq proof-goals-font-lock-keywords easycrypt-font-lock-keywords) (proof-goals-config-done)) (defun easycrypt-get-last-error-location () "Remove [error] in the error message and extract the position and length of the error." (proof-with-current-buffer-if-exists proof-response-buffer (goto-char (point-max)) (when (re-search-backward "\\[error-\\([0-9]+\\)-\\([0-9]+\\)\\]" nil t) (let* ((inhibit-read-only t) (pos1 (string-to-number (match-string 1))) (pos2 (string-to-number (match-string 2))) (len (- pos2 pos1))) (delete-region (match-beginning 0) (match-end 0)) (list pos1 len))))) (defun easycrypt-advance-until-command () (while (proof-looking-at "\\s-") (forward-char 1))) (defun easycrypt-highlight-error () "Use ‘easycrypt-get-last-error-location’ to know the position of the error and then highlight in the script buffer." (proof-with-current-buffer-if-exists proof-script-buffer (let ((mtch (easycrypt-get-last-error-location))) (when mtch (let ((pos (car mtch)) (lgth (cadr mtch))) (if (eq (proof-unprocessed-begin) (point-min)) (goto-char (proof-unprocessed-begin)) (goto-char (+ (proof-unprocessed-begin) 1))) (easycrypt-advance-until-command) (goto-char (+ (point) pos)) (span-make-self-removing-span (point) (+ (point) lgth) 'face 'proof-script-highlight-error-face)))))) (defun easycrypt-highlight-error-hook () (easycrypt-highlight-error)) (defun easycrypt-redisplay-hook () (easycrypt-redisplay)) (add-hook 'proof-shell-handle-error-or-interrupt-hook 'easycrypt-highlight-error-hook t) ;; -------------------------------------------------------------------- ;; Check mode related commands (defun easycrypt-cmode-check () "Set EasyCrypt in check mode." (interactive) (proof-shell-invisible-command "pragma Proofs:check.")) (defun easycrypt-cmode-weak-check () "Set EasyCrypt in weak-check mode." (interactive) (proof-shell-invisible-command "pragma Proofs:weak.")) ;; -------------------------------------------------------------------- (defun easycrypt-ask-do (do) (let* ((cmd)) (setq cmd (read-string (format "Term for `%s': " do))) (proof-shell-ready-prover) (proof-shell-invisible-command (format " %s %s . " do cmd)))) ;; -------------------------------------------------------------------- (defun easycrypt-Print () "Ask for a term and print its type." (interactive) (easycrypt-ask-do "print")) ;; -------------------------------------------------------------------- (defun easycrypt-Check () (easycrypt-Print)) ;; -------------------------------------------------------------------- ;; Key bindings (define-key easycrypt-keymap "\C-p" 'easycrypt-Print) (define-key easycrypt-goals-mode-map "\C-c\C-a\C-p" 'easycrypt-Print) (define-key easycrypt-response-mode-map "\C-c\C-a\C-p" 'easycrypt-Print) (define-key easycrypt-keymap "\C-c" 'easycrypt-Check) (define-key easycrypt-goals-mode-map "\C-c\C-a\C-c" 'easycrypt-Check) (define-key easycrypt-response-mode-map "\C-c\C-a\C-c" 'easycrypt-Check) ;; -------------------------------------------------------------------- ;; 3-window pane layout hack (add-hook 'proof-activate-scripting-hook '(lambda () (when proof-three-window-enable (proof-layout-windows)))) ;; -------------------------------------------------------------------- (provide 'easycrypt) ;;; easycrypt.el ends here PG-4.5/etc/000077500000000000000000000000001426357011200124445ustar00rootroot00000000000000PG-4.5/etc/Dockerfile000066400000000000000000000013421426357011200144360ustar00rootroot00000000000000FROM dockerfile/ubuntu:latest MAINTAINER David Aspinall RUN apt-get update # Install Emacs and Proof General RUN \ apt-get install -y emacs && \ cd /tmp && \ wget http://proofgeneral.inf.ed.ac.uk/releases/ProofGeneral-latest.tgz && \ tar -xpzf ProofGeneral-latest.tgz && \ cd ProofGeneral && \ make clean; make install && \ rm -rf /tmp/ProofGeneral* # Get some theorem provers... RUN \ apt-get install -y coq RUN \ cd /tmp && \ wget http://isabelle.in.tum.de/dist/Isabelle2014_linux.tar.gz && \ cd /usr/local && tar -xpzf Isabelle_2014_linux.tar.gz # Cleanup RUN rm -rf /var/lib/apt/lists* # Define working directory. WORKDIR /proofgeneral # Define default command. CMD ["proofgeneral"] PG-4.5/etc/ProofGeneral.desktop000066400000000000000000000002621426357011200164220ustar00rootroot00000000000000[Desktop Entry] Value=1.0 Type=Application Name=Proof General Comment=Interface to Proof Assistants Icon=pgicon.png Exec=proofgeneral Terminal=false Categories=Development;Math; PG-4.5/etc/ProofGeneral.menu000066400000000000000000000003271426357011200157170ustar00rootroot00000000000000?package(ProofGeneral):\ needs=X11\ section="Applications/Sciences/Computer science"\ title="Proof General"\ longtitle="Interface to Proof Assistants"\ command="/usr/bin/proofgeneral"\ icon="pgicon.png" PG-4.5/etc/ProofGeneral.spec000066400000000000000000000052021426357011200157020ustar00rootroot00000000000000Summary: Proof General, Emacs interface for Proof Assistants Name: ProofGeneral Version: 4.5 Release: 1 Group: Text Editors/Integrated Development Environments (IDE) License: GPLv3+ Url: http://proofgeneral.inf.ed.ac.uk/ Packager: David Aspinall Source: http://proofgeneral.inf.ed.ac.uk/ProofGeneral-%{version}.tgz BuildRoot: /tmp/ProofGeneral-root BuildRequires: emacs PreReq: /sbin/install-info Prefixes: /usr/share/emacs /usr/bin /usr/share/info BuildArchitectures: noarch %description Proof General is a generic Emacs interface for proof assistants, suitable for use by pacifists and Emacs militants alike. It is supplied ready-customized for EasyCrypt, Coq, and PhoX. You can adapt Proof General to other proof assistants if you know a little bit of Emacs Lisp. To use Proof General, use the command `proofgeneral', which launches Emacs with Proof General loaded. %changelog * Fri May 4 2001 David Aspinall - Changelog in CVS now; official spec file developed with source. %prep %setup %build [ -n "${RPM_BUILD_ROOT}" ] && rm -rf ${RPM_BUILD_ROOT} %install mkdir -p ${RPM_BUILD_ROOT}/usr/share/emacs/ProofGeneral # Clean out any .elc's that were in the tar file, and # rebuild for the required emacs version. make distclean # Build packages and install make install PREFIX=${RPM_BUILD_ROOT}/usr EMACS=emacs DEST_PREFIX=/usr # Install docs too make install-doc PREFIX=${RPM_BUILD_ROOT}/usr DEST_PREFIX=/usr DOCDIR=${RPM_BUILD_ROOT}%{_docdir} rm -f ${RPM_BUILD_ROOT}/usr/share/info/dir gzip ${RPM_BUILD_ROOT}/usr/share/info/* # Rename READMEs in subdirs to avoid clashes for f in */README; do mv $f $f.`dirname $f`; done %clean if [ "X" != "${RPM_BUILD_ROOT}X" ]; then rm -rf $RPM_BUILD_ROOT fi %post /sbin/install-info /usr/share/info/ProofGeneral.info* /usr/share/info/dir /sbin/install-info /usr/share/info/PG-adapting.info* /usr/share/info/dir if [ -x /usr/bin/gtk-update-icon-cache ]; then gtk-update-icon-cache -q /usr/share/icons/hicolor fi %preun /sbin/install-info --delete /usr/share/info/ProofGeneral.info* /usr/share/info/dir /sbin/install-info --delete /usr/share/info/PG-adapting.info* /usr/share/info/dir %postun if [ -x /usr/bin/gtk-update-icon-cache ]; then gtk-update-icon-cache -q /usr/share/icons/hicolor fi %files %defattr(-,root,root) %{_bindir}/* %doc %{_datadir}/man/man1/* %doc %{_datadir}/info/*.info* %doc %{_datadir}/doc/* %{_datadir}/pixmaps/proofgeneral.png %{_datadir}/icons/hicolor/*/proofgeneral.png %{_datadir}/ProofGeneral/* %{_datadir}/mime-info/proofgeneral.* %{_datadir}/applications/proofgeneral.desktop %{_datadir}/application-registry/proofgeneral.applications PG-4.5/etc/README000066400000000000000000000016601426357011200133270ustar00rootroot00000000000000Files in the PG/etc directory ============================= Files in this directory are auxiliary documentation and test files, not needed for a running Proof General installation. README this file ProofGeneral.spec Sample specfile for building the Proof General RPM. Use "rpm -tb" to build from tarball. ProofGeneral.menu Menu file for some Linux versions. Install in /usr/lib/menu. ProofGeneral.desktop Menu file for some Linux versions. Install in /etc/X11/applnk/Applications/ demoisa Isabelle Demo PG coq Coq .. others, similarly cvs-tips.txt Notes on cvs with PG project development-tips.txt Notes on development profiling.txt profiling proviola/ See README therein. testsuite/ Test suites (replaced by generic/pg-autotest) trac/ Test cases for reported bugs to check regression (manually) PG-4.5/etc/coq/000077500000000000000000000000001426357011200132265ustar00rootroot00000000000000PG-4.5/etc/coq/UndoFail.v000066400000000000000000000017271426357011200151250ustar00rootroot00000000000000(* Default undo depth is 100 in Coq 8.1. See trac #204 *) Lemma Foo : True. idtac. idtac. idtac. idtac. idtac. idtac. idtac. idtac. idtac. idtac. idtac. idtac. idtac. idtac. idtac. idtac. idtac. idtac. idtac. idtac. idtac. idtac. idtac. idtac. idtac. idtac. idtac. idtac. idtac. idtac. idtac. idtac. idtac. idtac. idtac. idtac. idtac. idtac. idtac. idtac. idtac. idtac. idtac. idtac. idtac. idtac. idtac. idtac. idtac. idtac. idtac. idtac. idtac. idtac. idtac. idtac. idtac. idtac. idtac. idtac. idtac. idtac. idtac. idtac. idtac. idtac. idtac. idtac. idtac. idtac. idtac. idtac. idtac. idtac. idtac. idtac. idtac. idtac. idtac. idtac. idtac. idtac. idtac. idtac. idtac. idtac. idtac. idtac. idtac. idtac. idtac. idtac. idtac. idtac. idtac. idtac. idtac. idtac. idtac. idtac. idtac. idtac. idtac. idtac. idtac. idtac. idtac. idtac. idtac. assert (NI : ~False). intros IX; auto. (* Process the script until here, then undo back 3 or 4 lines. Notice that NI doesn't disappear. *)PG-4.5/etc/coq/bug-114.v000066400000000000000000000003461426357011200145000ustar00rootroot00000000000000(* Trac #114: identifiers starting with "fun" are wrongly coloured *) forall (funA B: Prop) (* funA should be all magenta *) fun (forallA B: Prop) (* forallA should be all magenta *) (* Fixed in coq-syntax.el, 8.41 *) PG-4.5/etc/coq/bug-447.v000066400000000000000000000107571426357011200145200ustar00rootroot00000000000000Ltac bar k := k tt. (* The next tactic definition seems to get stuck when processing in PG. It works fine typed into coqtop and also works if a couple of the match lines are removed. It does seem to be something to do with the line length, as if the lines are commented out the same problem happens. See http://proofgeneral.inf.ed.ac.uk/trac/ticket/447 *) Ltac foo x := bar ltac:(fun a => bar ltac:(fun b => bar ltac:(fun c => bar ltac:(fun d => bar ltac:(fun e => bar ltac:(fun f => bar ltac:(fun g => bar ltac:(fun h => let x := match tt with | tt => constr:(1) end in let x := match tt with | tt => constr:(1) end in let x := match tt with | tt => constr:(1) end in let x := match tt with | tt => constr:(1) end in let x := match tt with | tt => constr:(1) end in let x := match tt with | tt => constr:(1) end in let x := match tt with | tt => constr:(1) end in let x := match tt with | tt => constr:(1) end in let x := match tt with | tt => constr:(1) end in let x := match tt with | tt => constr:(1) end in let x := match tt with | tt => constr:(1) end in let x := match tt with | tt => constr:(1) end in let x := match tt with | tt => constr:(1) end in let x := match tt with | tt => constr:(1) end in let x := match tt with | tt => constr:(1) end in let x := match tt with | tt => constr:(1) end in let x := match tt with | tt => constr:(1) end in let x := match tt with | tt => constr:(1) end in let x := match tt with | tt => constr:(1) end in let x := match tt with | tt => constr:(1) end in let x := match tt with | tt => constr:(1) end in let x := match tt with | tt => constr:(1) end in let x := match tt with | tt => constr:(1) end in let x := match tt with | tt => constr:(1) end in let x := match tt with | tt => constr:(1) end in let x := match tt with | tt => constr:(1) end in let x := match tt with | tt => constr:(1) end in let x := match tt with | tt => constr:(1) end in let x := match tt with | tt => constr:(1) end in let x := match tt with | tt => constr:(1) end in let x := match tt with | tt => constr:(1) end in let x := match tt with | tt => constr:(1) end in let x := match tt with | tt => constr:(1) end in let x := match tt with | tt => constr:(1) end in let x := match tt with | tt => constr:(1) end in let x := match tt with | tt => constr:(1) end in let x := match tt with | tt => constr:(1) end in let x := match tt with | tt => constr:(1) end in let x := match tt with | tt => constr:(1) end in let x := match tt with | tt => constr:(1) end in let x := match tt with | tt => constr:(1) end in let x := match tt with | tt => constr:(1) end in let x := match tt with | tt => constr:(1) end in let x := match tt with | tt => constr:(1) end in let x := match tt with | tt => constr:(1) end in let x := match tt with | tt => constr:(1) end in let x := match tt with | tt => constr:(1) end in let x := match tt with | tt => constr:(1) end in let x := match tt with | tt => constr:(1) end in let x := match tt with | tt => constr:(1) end in let x := match tt with | tt => constr:(1) end in let x := match tt with | tt => constr:(1) end in let x := match tt with | tt => constr:(1) end in let x := match tt with | tt => constr:(1) end in let x := match tt with | tt => constr:(1) end in let x := match tt with | tt => constr:(1) end in let x := match tt with | tt => constr:(1) end in let x := match tt with | tt => constr:(1) end in let x := match tt with | tt => constr:(1) end in let x := match tt with | tt => constr:(1) end in let x := match tt with | tt => constr:(1) end in let x := match tt with | tt => constr:(1) end in let x := match tt with | tt => constr:(1) end in let x := match tt with | tt => constr:(1) end in let x := match tt with | tt => constr:(1) end in let x := match tt with | tt => constr:(1) end in let x := match tt with | tt => constr:(1) end in let x := match tt with | tt => constr:(1) end in let x := match tt with | tt => constr:(1) end in let x := match tt with | tt => constr:(1) end in let x := match tt with | tt => constr:(1) end in let x := match tt with | tt => constr:(1) end in let x := match tt with | tt => constr:(1) end in let x := match tt with | tt => constr:(1) end in let x := match tt with | tt => constr:(1) end in let x := match tt with | tt => constr:(1) end in let x := match tt with | tt => constr:(1) end in let x := match tt with | tt => constr:(1) end in idtac)))))))). Ltac wim x := foo x. PG-4.5/etc/coq/highlighterror.v000066400000000000000000000003771426357011200164450ustar00rootroot00000000000000(* Test of error highlighting The error should highlight the last γ₁₂ variable occurrence, the whole of it, and only it (not the final dot nor the preceding space). *) Require Import Utf8. Lemma α₁: ∀ x:nat, ∀ γ₁₂: bool, x = γ₁₂. PG-4.5/etc/coq/indent.v000066400000000000000000000034771426357011200147110ustar00rootroot00000000000000(* Pierre: could you add some real test cases to this file, please? e.g. a file that can be processed, and indented how you want --- so TAB makes no difference to indentation (bad examples in comments) *) (* First problem: matching compound reserved words *) Syntactic Definition foo := bar. (* Neither of these are good enough: the backwards search simply finds "Definition" first *) (* (re-search-backward "\\(\\\\s-+\\)?Definition") *) (* (posix-search-backward "\\(\\\\s-+\\)?Definition") *) (* I suppose Java has this issue too, so the syntax designers of Coq are not really to blame... However, if you take a look at the Emacs code used for calculating Java indentation you will get a shock!! Proof General's is much simpler. I sugest introducing another function (and regexp) proof-within-compound-reserved-word which we can use as a guard for repeating the regexp search backwards, as an extra condition in proof-indent-goto-prev (similarly to proof-looking-at-syntactic-context which resumes the search in case we landed in a string or comment). Pierre, do you want to try that? - da *) (* Second problem: hanging indentation of cases *) (* Desirable indent (Pierre: not quite what you said: you had different indent between Cases and next line in nested case) Definition f := Cases i with x => Cases x with z => # | # => # | # => # end end *) (* currently: *) Definition f := Cases i with x => Cases x with z => # | a => b | # => # end end (* Nasty example from Trac http://proofgeneral.inf.ed.ac.uk/trac/ticket/173 *) Theorem p : forall (P : Prop), P -> P. Proof. try (simpl in *). intros P H. apply H. (* da: shouldn't we outdent again here? *) Qed. PG-4.5/etc/coq/lostmessages.v000066400000000000000000000005101426357011200161220ustar00rootroot00000000000000(* These are some examples which generate goals and errors at the same moment. May be broken in development version of Coq. See http://proofgeneral.inf.ed.ac.uk/trac/ticket/141 *) Require Import Setoid. Goal False. setoid_replace False with True. Goal True /\ True -> True. intro H. destruct H as [H1 H2 H3]. PG-4.5/etc/coq/multiple-plain/000077500000000000000000000000001426357011200161625ustar00rootroot00000000000000PG-4.5/etc/coq/multiple-plain/README000066400000000000000000000001661426357011200170450ustar00rootroot00000000000000Plain tests for multiple file handling, without using require. Test: process a.v process b.v undo a.v, redo a.v PG-4.5/etc/coq/multiple-plain/a.v000066400000000000000000000002671426357011200165760ustar00rootroot00000000000000(* Simple tests for multiple file handling *) Goal forall (A B:Prop),(A /\ B) -> (B /\ A). intros A B H. elim H. intros. split. assumption. assumption. Save and_comms_a. PG-4.5/etc/coq/multiple-plain/b.v000066400000000000000000000002671426357011200165770ustar00rootroot00000000000000(* Simple tests for multiple file handling *) Goal forall (A B:Prop),(A /\ B) -> (B /\ A). intros A B H. elim H. intros. split. assumption. assumption. Save and_comms_b. PG-4.5/etc/coq/multiple-plain/c.v000066400000000000000000000002671426357011200166000ustar00rootroot00000000000000(* Simple tests for multiple file handling *) Goal forall (A B:Prop),(A /\ B) -> (B /\ A). intros A B H. elim H. intros. split. assumption. assumption. Save and_comms_c. PG-4.5/etc/coq/multiple/000077500000000000000000000000001426357011200150615ustar00rootroot00000000000000PG-4.5/etc/coq/multiple/.cvsignore000066400000000000000000000000051426357011200170540ustar00rootroot00000000000000*.vo PG-4.5/etc/coq/multiple/Makefile000066400000000000000000000101271426357011200165220ustar00rootroot00000000000000############################################################################## ## The Calculus of Inductive Constructions ## ## ## ## Projet Coq ## ## ## ## INRIA ENS-CNRS ## ## Rocquencourt Lyon ## ## ## ## Coq V7 ## ## ## ## ## ############################################################################## # WARNING # # This Makefile has been automagically generated by coq_makefile # Edit at your own risks ! # # END OF WARNING # # This Makefile was generated by the command line : # coq_makefile a.v b1.v b2.v b.v c.v d.v # ########################## # # # Variables definitions. # # # ########################## CAMLP4LIB=`camlp4 -where` COQSRC=-I $(COQTOP)/kernel -I $(COQTOP)/lib \ -I $(COQTOP)/library -I $(COQTOP)/parsing \ -I $(COQTOP)/pretyping -I $(COQTOP)/interp \ -I $(COQTOP)/proofs -I $(COQTOP)/syntax -I $(COQTOP)/tactics \ -I $(COQTOP)/toplevel -I $(COQTOP)/contrib/correctness \ -I $(COQTOP)/contrib/extraction -I $(COQTOP)/contrib/field \ -I $(COQTOP)/contrib/fourier -I $(COQTOP)/contrib/graphs \ -I $(COQTOP)/contrib/interface -I $(COQTOP)/contrib/jprover \ -I $(COQTOP)/contrib/omega -I $(COQTOP)/contrib/romega \ -I $(COQTOP)/contrib/ring -I $(COQTOP)/contrib/xml \ -I $(CAMLP4LIB) ZFLAGS=$(OCAMLLIBS) $(COQSRC) OPT= COQFLAGS=-q $(OPT) $(COQLIBS) $(OTHERFLAGS) $(COQ_XML) COQC=$(COQBIN)coqc GALLINA=gallina COQDOC=coqdoc CAMLC=ocamlc -c CAMLOPTC=ocamlopt -c CAMLLINK=ocamlc CAMLOPTLINK=ocamlopt COQDEP=$(COQBIN)coqdep -c GRAMMARS=grammar.cma CAMLP4EXTEND=pa_extend.cmo pa_ifdef.cmo q_MLast.cmo PP=-pp "camlp4o -I . -I $(COQTOP)/parsing $(CAMLP4EXTEND) $(GRAMMARS) -impl" ######################### # # # Libraries definition. # # # ######################### OCAMLLIBS=-I . COQLIBS=-I . ################################### # # # Definition of the "all" target. # # # ################################### VFILES=a.v\ b1.v\ b2.v\ b.v\ c.v\ d.v VOFILES=$(VFILES:.v=.vo) VIFILES=$(VFILES:.v=.vi) GFILES=$(VFILES:.v=.g) HTMLFILES=$(VFILES:.v=.html) GHTMLFILES=$(VFILES:.v=.g.html) all: a.vo\ b1.vo\ b2.vo\ b.vo\ c.vo\ d.vo spec: $(VIFILES) gallina: $(GFILES) html: $(HTMLFILES) gallinahtml: $(GHTMLFILES) all.ps: $(VFILES) $(COQDOC) -ps -o $@ `$(COQDEP) -sort -suffix .v $(VFILES)` all-gal.ps: $(VFILES) $(COQDOC) -ps -g -o $@ `$(COQDEP) -sort -suffix .v $(VFILES)` #################### # # # Special targets. # # # #################### .PHONY: all opt byte archclean clean install depend html .SUFFIXES: .v .vo .vi .g .html .tex .g.tex .g.html .v.vo: $(COQC) $(COQDEBUG) $(COQFLAGS) $* .v.vi: $(COQC) -i $(COQDEBUG) $(COQFLAGS) $* .v.g: $(GALLINA) $< .v.tex: $(COQDOC) -latex $< -o $@ .v.html: $(COQDOC) -html $< -o $@ .v.g.tex: $(COQDOC) -latex -g $< -o $@ .v.g.html: $(COQDOC) -html -g $< -o $@ byte: $(MAKE) all "OPT=" opt: $(MAKE) all "OPT=-opt" include .depend .depend depend: rm -f .depend $(COQDEP) -i $(COQLIBS) *.v *.ml *.mli >.depend $(COQDEP) $(COQLIBS) -suffix .html *.v >>.depend install: mkdir -p `$(COQC) -where`/user-contrib cp -f *.vo `$(COQC) -where`/user-contrib clean: rm -f *.cmo *.cmi *.cmx *.o *.vo *.vi *.g *~ rm -f all.ps all-gal.ps $(HTMLFILES) $(GHTMLFILES) archclean: rm -f *.cmx *.o html: # WARNING # # This Makefile has been automagically generated by coq_makefile # Edit at your own risks ! # # END OF WARNING PG-4.5/etc/coq/multiple/README000066400000000000000000000010541426357011200157410ustar00rootroot00000000000000Multiple files in PG 3.5 / Coq 8.0 The option "auto-compile-vos" has been fixed up somewhat for this release. Please report any problems to David Aspinall (da@inf.ed.ac.uk) Strategy is: - When scripting is turned *off* in a buffer, you will be asked if you want to save it, and then either M-x compile is run (if PG sees a Makefile in the same directory), or coqc on just the buffer is run. (You can customize this behaviour by setting compile-command and/or coq-compile-file-command). [ Desirable improvement: query user to save any dependent files ] PG-4.5/etc/coq/multiple/a.v000066400000000000000000000002671426357011200154750ustar00rootroot00000000000000(* Simple tests for multiple file handling *) Goal forall (A B:Prop),(A /\ B) -> (B /\ A). intros A B H. elim H. intros. split. assumption. assumption. Save and_comms_a. PG-4.5/etc/coq/multiple/b.v000066400000000000000000000003041426357011200154660ustar00rootroot00000000000000(* Simple tests for multiple file handling *) Require b1. Goal forall (A B:Prop),(A /\ B) -> (B /\ A). intros A B H. elim H. intros. split. assumption. assumption. Save and_comms_b. PG-4.5/etc/coq/multiple/b1.v000066400000000000000000000000401426357011200155440ustar00rootroot00000000000000Require b2. Parameter b1:Set. PG-4.5/etc/coq/multiple/b2.v000066400000000000000000000000541426357011200155520ustar00rootroot00000000000000(* b2 -> b1 -> b -> c *) Parameter b2:Set. PG-4.5/etc/coq/multiple/c.v000066400000000000000000000003551426357011200154750ustar00rootroot00000000000000(* Simple tests for multiple file handling *) Require d. (* d requires a *) Require a. Require b. Goal forall (A B:Prop),(A /\ B) -> (B /\ A). intros A B H. elim H. intros. split. assumption. assumption. Save and_comms_c. PG-4.5/etc/coq/multiple/d.v000066400000000000000000000000371426357011200154730ustar00rootroot00000000000000Require a. Parameter d:Set. PG-4.5/etc/coq/naming.v000066400000000000000000000021421426357011200146650ustar00rootroot00000000000000(* Coq theorems, etc can be named at the top .... *) Theorem and_comms: forall (A B:Prop),(A /\ B) -> (B /\ A). intros A B H. induction H. apply conj. assumption. assumption. Qed. (* at the bottom... *) Goal forall (A B:Prop),(A /\ B) -> (B /\ A). intros A B H. induction H. apply conj. assumption. assumption. Save and_comms2. (* or not at all! *) (* Coq calls this "Unamed_thm", so must forget it like any other *) (* test: do, undo, then check shell buffer to see "Reset Unnamed_thm" *) Goal forall (A B:Prop),(A /\ B) -> (B /\ A). intros A B H. induction H. apply conj. assumption. assumption. Save. (* Odd side effect: two unnamed theorems in a row are not possible! Latest: with Coq 8.2, we get Unamed_thm0, Unamed_thm1, ... *) Goal forall (A B:Prop),(A /\ B) -> (B /\ A). intros A B H. induction H. apply conj. assumption. assumption. Save. (* TESTING: notice output window behaviour here with different settings: exact output displayed also depends on how many steps are issued at once. *) Goal forall (A B:Prop),(A /\ B) -> (B /\ A). tauto. Save. PG-4.5/etc/coq/nested.v000066400000000000000000000063711426357011200147060ustar00rootroot00000000000000(* Testing nested Proofs, and backtrack mechanism in general. BUGS: - Nested sections... ======= Below here fixed - Retract 7a -> 6 needs to do 3 sorts of undo commands! Abort, Undo, Back. Algorithm is to use current search-forwards from target span mechanism, which has to cover the whole range of undo to count all the Backs. However, only the initial Undo's which appear before an Abort need to be counted. (See coq-find-and-forget). - Undo of "Require Omega" in proof uses Undo instead of Back. [ coq-count-undos needs fixing to use Back as well as Undo ? ] - once point 12 is reached, sould have one block from 3 to 12. With the goalsave test : OK but the reset command is wrong. - From point 5, retract to point 1: "Abort. Back 5." Argl Wrong, tactics and line 3 are counted for Back!! This comes from my modification of coq-find-and-forget function. - point 7 is not well backtracked, but this can be solved easily in coq.el. *) Require Logic. (* 1 This needs "Back 1" to be retracted *) Require List. (* 2 This needs "Back 1" to be retracted *) Section Apple. (* 2a. *) Fixpoint f [n:nat] : nat := Cases n of O => O | (S m)=> (f m) end. (* 2b. Retraction to 2a from here uses "Reset". Retraction to 2a from inside proof uses "Abort. Back." *) Lemma t1: (n: nat ) {n=O} + {(EX y | n = (S y))}. (* 3 This needs "Restart" to be retracted if inside the proof, and "Reset t1. Back 4." if outside (after point 12). 3 because of the Require and the two lemmas inside the proof. If only "Reset t1", like with the current version of PG, then t2 and t3 are still in the environment. Try this with the current version and with my patch *) (* da: Back command seems much better behaved than "Reset", which always clears proof state, I think. Should PG always use Back? *) Intros. (* 4 This needs "Undo" to be retracted *) Case n. (* 5 "Undo" *) EAuto. (* 6 "Undo" *) Definition foo:=O. (* 6.5 between 6 and 7 *) Require Omega. (* 7 This needs "Back 1" to be retracted. *) Lemma t2 : O=O. (* 7a. -> 6: "Abort. Back 1. Undo 1." *) Auto. Print f. (* a non-undoable "tactic" *) Lemma t4 : O=O. Auto. (* 7b. -> 6: "Abort. [Undo.] Abort. Back 1. Undo 1." *) (* 7b. -> 2: "Abort. Abort. Abort. Back 1." This is a useful test case because PG splits undo calculation into phases: outwith top-level proof and within top-level proof. *) Save. Save. (* 8 "Back 1" or "Reset t2". *) Proof. (* another non-undoable... *) Intros. (* 9 "Undo": example of retraction 9->6: Undo 2. Back 3. *) Fixpoint g [n:nat] : nat := Cases n of O => O | (S m)=> (g m) end. (*7*) Lemma t3 : O=O. Auto. Save. (* 10 "Back 1" or "Reset t3" *) EAuto. (* 11 "Undo" *) Save. (* 12 *) End Apple. Section Banana. Lemma Coq: O=O. Auto. Save. (* silly example to show that testing prompt in coq-proof-mode-p to determine if we're in proof mode is not good enough. Hopefully nobody calls their theorems "Coq".*) End Banana. (* Nested sections? Oh no, this is too horrible to even think about. *) Section Cranberry. Section Damson. Lemma CoqIsStrange: O=O. Auto. Save. End Damson. End Cranberry. PG-4.5/etc/coq/parsing.v000066400000000000000000000003521426357011200150600ustar00rootroot00000000000000(* Here's a test of a (* nested comment: Since Coq has them, PG ought to be able to deal with them. They work fine in GNU Emacs, but problematical in XEmacs. *) *) Require Logic. (* Comment at the end here. *) PG-4.5/etc/coq/parsingcheck-410.v000066400000000000000000000002071426357011200163570ustar00rootroot00000000000000Require Export Coq.Lists.List. Notation "[ ]" := nil : list_scope. Notation "[ a ; .. ; b ]" := (a :: .. (b :: []) ..) : list_scope. PG-4.5/etc/coq/parsingdot.v000066400000000000000000000034261426357011200155740ustar00rootroot00000000000000(* From: Pierre Courtieu To: David Aspinall Subject: little annoying bug - don't know how to solve it clean Date: Tue, 4 Feb 2003 21:06:55 +0100 Hi David, I am trying to remove a little bug of coq/pg. It happens when the user types by mistake two dots, instead of one. It happens quite often and it should be refused (i.e. not sent to Coq) by pg. Example *) Goal (A,B:Prop)(A /\ B) -> (B /\ A). Intros x y z.. (* Test 1: (setq proof-script-command-end-regexp "[.][\\. \t\n\r]" ) *) (* Test 2: (setq proof-script-command-end-regexp "[.]\\([\\. \t\n\r]\\)") *) (* What happens now is that "Intros x y z.." is sent to Coq, Coq reads the first part of the command "Intros x y z.", executes it, and then throws an error because of the second part "." is not correct. So pg stays before "Intros x y z..", which is incorrect since "Intros x y z." has been acceted by Coq. Remember that the current config of Coq is the following: (setq proof-script-command-end-regexp "[.]\\([ \t\n\r]\\)" ) this is due to the fact that foo.bar is a valid identifier (Module/Section). Problem is that: - I cannot use "[.]\\([^a-Z.]\\)" because if we have: Intros x y z.. Auto. then the command sent to Coq would be "Intros x y z.. Auto.", which is worse. - I cannot use "[.]" because it would cut qualified names ("foo.bar"). Actually what I would like to use is a proof-not-allowed-command-end variable, or more generally a hook for the function proof-script-parse-function. I have defined (not commited) a coq-script-parse-function below to do the check by hand, it is a copy of proof-script-generic-parse-cmdend, with a check for ".." at the end (error if yes). The behavior we want is really an error here: It must not be sent to coq at all! *)PG-4.5/etc/coq/queryreplace.v000066400000000000000000000026471426357011200161270ustar00rootroot00000000000000(* STATUS: Solved. This was caused by the anyway faulty proof-zap-commas-region failing to save the match data. See comments in proof-syntax.el about that function. *) (* From: Cuihtlauac ALVARADO To: David Aspinall Subject: broken query-replace Date: 09 Jul 2002 11:09:03 +0200 BTW, there's something stange I've forgot to post. In FSF-emacs PG & global-font-lock-mode does not play well together. Add (global-font-lock-mode t) in your .emacs an then try to query-replace "dom" by "foo" in *) Record t : Type := make { dom : Set; null : dom; inv : dom->dom; op : dom->dom->dom; null_l : (x:dom)x=(op null x); null_r : (x:dom)x=(op x null); inv_l : (x:dom)null=(op (inv x) x); inv_r : (x:dom)null=(op x (inv x)); assoc : (x,y,z:dom)(op x (op y z))=(op (op x y) z); inv_null : null=(inv null); inv_inv : (x:dom)x=(inv (inv x)); assoc_inv_l : (x,y:dom)y=(op (inv x) (op x y)); assoc_inv_r : (x,y:dom)y=(op x (op (inv x) y)); inv_op : (x,y:dom)(op (inv y) (inv x))=(inv (op x y)) }. (* assoc, assoc_inv_l, assoc_inv_r and inv_op occurences of "dom" are replaced by "fooom" instead of "dom", quite strange is'n it ? Query-replacing "dom" by "bar" leads to "barom", which make me thinks only the first letter of the pattern is replaced... I've seen this strange behaviour for a while, it was present in earlier versions of PG & emacs. *) PG-4.5/etc/coq/xemacs21528.v000066400000000000000000000006621426357011200153030ustar00rootroot00000000000000(* There are regexp problems with XEmacs 21.5.28 which break this example. 9.12.07: It turned out that the default syntax table wasn't merged properly with the default, suspect bugs in derived.el. Patched in `proof-script.el' for now. *) Module Type T. Parameter p1 : nat. Parameter p2 : nat. Parameter p3 : nat. Parameter p4 : nat. Parameter p5 : nat. Parameter p6 : nat. Parameter p7 : nat. Parameter p8 : nat. End T. PG-4.5/etc/coq/xsymboltest.v000066400000000000000000000022601426357011200160120ustar00rootroot00000000000000(* Grammar for symbols: a symbol is encoded only if - preceded by _ or some space or some symbol **and** - followed by _ or some space or some symbol Grammar for sub/superscript: - a double _ introduces a subscript that ends at the first space - a double ^ introduces a superscript that ends at the first space - a _ followed by { introduces a subscript expression that ends at the first } - a ^ followed by { introduces a superscript expression that ends at the first } *) foo_alpha_1_beta_3 (* this should appear like foo_a_1_B_3 where a and B are greek *) delta__1 delta^^1 (* greek delta with a sub 1 and the same with super 1 *) x_{a+b} x^{a+b} (* x with a+b subscripted and then superscripted *) philosophi (* no greek letter should appear on this line *) aalpha alphaa (* no greek letter *) _alpha (* _a where a is greek *) alpha_ (* a_ where a is greek *) Fixpoint toto (x:nat) {struct x} : nat := (* nat should appear as |N *) match x with | O => O (* double arrow here *) | S y => toto y (* double arrow here *) end. Lemma titi : forall x:nat,x=x. (* symbolique for-all and nat *) PG-4.5/etc/cvs-tips.txt000066400000000000000000000056331426357011200147640ustar00rootroot00000000000000Using CVS to access Proof General repository ============================================ Here are some notes on how to access the PG repository remotely using CVS, using pserver access to cvs.inf.ed.ac.uk 0. If you want write access to the Proof General repository, fill in the web form here to apply for an account: http://www.informatics.ed.ac.uk/systems/cvs/new/ The request will be processed manually and confirmed with the Proof General maintainer (David Aspinall), so you should discuss with him before applying. 1. Login to the CVS server: cvs -d :pserver:@cvs.inf.ed.ac.uk:/disk/cvs/proofgen login Replace with your username, or with "anon" for anonymous access. 2. Checkout the repository: cvs -d :pserver:@cvs.inf.ed.ac.uk:/disk/cvs/proofgen checkout ProofGeneral Inside the ProofGeneral directory, to retrieve the latest updates, do: cvs update To commit some changes to file , do: cvs commit -m"" See "man cvs" for (much) more. ----------------------------------------------------------------- Making a branch to patch a previous release: ============================================ cvs checkout -r Release-3-1-3 ProofGeneral cd ProofGeneral cvs tag -b Release-3-1-branch # Drop this repo, has sticky tag for 3-1-3. cd .. ; cvs release -d ProofGeneral # Get new one cvs checkout -r Release-3-1-branch ProofGeneral cd ProofGeneral patch ... blah ... cvs commit ... blah .. Then make release as ~proofgen: mkdir oldbranch cd oldbranch cvs checkout -r Release-3-1-branch ProofGeneral make devel.releaseall VERSION=3.1 FULLVERSION=3.1.99 NB: See warning in Makefile.devel about this (it will downgrade web pages). Then perhaps merge in branch changes into main stream: cd projects/proofgen/ProofGeneral cvs update -jRelease-3-1-branch NB: this merging will always create conficts with $Id$ tags in source. (Is there a way to avoid this?) Overriding the CVS/Root setting temporarily: ============================================ Use cvs -d $CVSROOT NB: This doesn't alter CVS/Root, but uses NEWROOT in preference. ($CVSROOT does not overide CVS/Root at all). Useful command: alias cvs='cvs -d $CVSROOT' to force this behaviour. Moving to a new branch ====================== This only works on a clean repository (no spurious files): find * -path '*/CVS' -prune -o -path 'CVS' -prune -o -print | tr '\n' '\0' | xargs -0 cvs commit -m"Updating branch" -f -r 4.0 (The tr is needed because of some nasty filenames, e.g. etc/isa/\backslashname) Updating base revision number ============================= Starting with a new base revision number is handy to easily see changes since last release. cvs commit -f -R -r 12.0 -m"Update base revision number for 4.2 development cycle" . cvs up -A Need second update to remove automatically added sticky tag. PG-4.5/etc/demoisa/000077500000000000000000000000001426357011200140655ustar00rootroot00000000000000PG-4.5/etc/demoisa/A.ML000066400000000000000000000000021426357011200144670ustar00rootroot000000000000001;PG-4.5/etc/demoisa/B.ML000066400000000000000000000000021426357011200144700ustar00rootroot000000000000002;PG-4.5/etc/demoisa/C.ML000066400000000000000000000000021426357011200144710ustar00rootroot000000000000003;PG-4.5/etc/demoisa/D.ML000066400000000000000000000000021426357011200144720ustar00rootroot000000000000004;PG-4.5/etc/demoisa/README000066400000000000000000000003471426357011200147510ustar00rootroot00000000000000This is a test for automatic multiple file handling. Assert each of A.ML, B.ML, C.ML, D.ML in turn. Then retract B.ML. D.ML and C.ML should be automatically retracted. Set proof-tidy-response=nil to track what happens. - da. PG-4.5/etc/desktop/000077500000000000000000000000001426357011200141155ustar00rootroot00000000000000PG-4.5/etc/desktop/README000066400000000000000000000006011426357011200147720ustar00rootroot00000000000000You can install files in this directory to add desktop integration for Proof General. This is presently done in the RPM file. See http://standards.freedesktop.org/desktop-entry-spec/ Please add i18n alternatives and other improvements if you'd like to see them on your desktop, and send them back to me. - da --- Notes: application-registry/ } for GNOME mime-info/ } PG-4.5/etc/desktop/application-registry/000077500000000000000000000000001426357011200202665ustar00rootroot00000000000000PG-4.5/etc/desktop/application-registry/proofgeneral.applications000066400000000000000000000002511426357011200253570ustar00rootroot00000000000000proofgeneral command=proofgeneral name=Proof General can_open_multiple_files=true expects_uris=false requires_terminal=false mime_types=application/x-proofgeneral PG-4.5/etc/desktop/icons/000077500000000000000000000000001426357011200152305ustar00rootroot00000000000000PG-4.5/etc/desktop/icons/128x128/000077500000000000000000000000001426357011200161655ustar00rootroot00000000000000PG-4.5/etc/desktop/icons/128x128/proofgeneral.png000066400000000000000000000334451426357011200213670ustar00rootroot00000000000000PNG  IHDR>abKGD pHYs55 !CwtIME .C ̩ IDATxw\u\:ht# IJV-[N;x֎؞cggwvYgfe$ےEeJ3ȡ:^?H-dS8n?&\krMɏz9\k꿼 jTU5 āGI $0LH)BDAE,]^k R8nu_ߙZRK=߀RZdUsۺբ|h$BS %HPt3eaL C]F#J@WWאeyLBhJ;Xm+ES0S&f0:oq89X<0Mc"Bfcr5A(\tEM4 n˻_ UF1uPUעcۣݱAm.Bє6LPM Ұ:"eӮ4o6uSq]7dߧ7frzLGIˆD{c1;h"wR:Dћ3Ԇh ?r`e,S Ti L6ɫ @hJ$ŕ_H,hOL"X_OD㳎 _-ak#8xtE͍fͻ{ja/FVE7E:"4F }N3\2gfM9ҮiA^!1vtt{E4MC }'o]mbPϯR7Bĺɫ-uуH);A:G4MQت!*\= ؜#tŸNT"EH[^ӣGMvr ʠk>nV;< Z@ZWEơY:gԢ:^t]C~ꋮ4?3|{7/.}k>CiNazEkDL.Dt* &"CmbdTs?nDۯE츃6,3G!4,S0A<MqFwL=垨+z]ahe@zogB0;;KV4MY}i} PW~ApF<+iݫf\mF?󮝬i0;;CXIJ,j5<#͢gS֘j8WE` l)։Vu@4يݱ9B/|=2aG__tu)DQ/@U. w*fA1Wujxs5Яf< 4 UUQH$ :;;PɸKPl.AdFr=W(pyrv*7(AۜmE/Ng+p]MgНufIeŃKԧk*-7Xn庬E\jB{.{"haaa>H<И#SUS{KP5bk"S(u` S`uDXF Ix ?]C!BUbV&i`uXڱOekikU_><:::$lͶI|?X6˝93vH ؔ%)K?!T+iUZDօ IΛ/k033SboOvaT9w.bvAƟjyE\ן;iqCU]J[$SHRR+S߽Jʼn72]h"CI7A|Eb.]gIVzzzH$((uJ|Et]'3||o:NAZ q-+8^ lS]HXl좍oqA셦Ԃ=t ˍ6ʍfm[HfUZG*b뺴Z-,H$DH$tww4_Gz5|En̲'Aש|Oݺp4h@6+E5"mZ% Es [sqiuw>9 jSiuZi#rr;x7΍rwK{'ʄ\աh*'My/,4αc#|[h]7T t%#h`d )۬Msu& UCSum݃jcEUp6^CB._4gz2xmR@xBG u-F@4܍i0RDҮ(ԙ3 CZ-b!|j#ғ:UEuE7"35\gͷ݀ vٹ]U}bٱlgbr 0V[ Bu7fVU/;" 3 HkS'&1OU8=66#a V2qZj|L'/-VF !Sl5Rv|wuRReԑ6&ԭ!(!= ":.6z;p *"y^RR ӹeMM(au.N_b|jjt-^uZ.Z#$@ף -nԒ8{JBex{6wV(h]E=9.b.;:x>FjRVʉE=8GhQoO P@!b,7};PW!{uܰOݶ}z|K( \OJ@u$zA)'[Hڽ[@SPLPMUoo9>ze^|ܺ6G:j0[Y:m LM] TFh]WZ_&JJ*Mc5/Gض*@t%#tIL4MrEAQL( (B *"q=zåZoQ(7Y(ؔf؉ Z@ꨆ]?`x|bEQ]B 4etk EafB4EeE:C cc%0C)!ӗ&1qZJcxEn\dNVjHZ\jjuCGJ:R"b\M|ȱqv! jڧLq{V>;UU4d2I" DkU:slY>j5VriMM1(Fb1tDQ7MH3!I¶1VU%<&cPdUx@KQ EW;|{EoS?x!\y@Px2 5;;{(Bƍ]mkL"5<§>AvnـieX똆S//wZRNY+Okժ< 6.PC4T]GTU[r(K)7B4@3 \MC5 nر-ݤQQX\dv!V E4*U|9*|߉b<.MIZa#a빹L`1c'moJ-[1iXL$/~vWm:W!(-el۸qꆁO&r zew!⿞֯7t 誢dCOVCcc sϝMEEO{$q~W%,@Qs~o~W%/h4:@Ap18(1 RBQ ~-Xt[+_F >oNt;˝:Œr}?oQ䥃qsw!-N09^^<|q\@<7s}]]KЬ+3XɎRN%9rǟ}.R2r9{9"8 -iqzf#x=4lL2y7_*޽,V*~׆R uwё|˸X. (\.@Q띅Ð#lݲd&f2r-|yze;l[FFx_i3<5- \3_G05?LV::عi|ǰ7>HSU4ݠZ"T ZWVqUXl6'޹}==g<4'etvh2O|CC9b}UC.3e>y;?222?Gʁ؎=R( ss=zv7o݂ePu@VjB\Ƶ1L}a|rxQf3=}'vo[vl;?lxgygYy'_qZ>Lф7za\ 3lvzl޴~$l݊aR7΄.h.5M{bj6/d(POCZ}QNKHEAY*߷:yj/m5ֱy:l_7h|͢Ð?za€Ƒ1ܴ֯%'0l'oQc)ONFѧ/k>tVuӂp}1_(NQZ= S+S8bYtuӳE!ȩS)Z =GPן"r,|ްZc1p\?:R5C.Lͣ{)r~@rN6=)3%QCv 8+\ȨoƳ\E/ mWBIvW(N0'M"h";r,lc6[=rJo}h(| óuE.\QnB\>O$SBΧtSꆺC<8kX,*+N@wW'P!\Q+}U #ssgXx4J2ůxWΰ}Mضf }Fo͛T*M:ZoT7YGiTlG[yѿjK7?SlY`{JDDCZEY3ިڨx \B0 E j6GFw׍7HĵmꎃN@(ʧ>2o"zww053$ V@SUM8s*>u-= }!s"*9iaE<ϋ_XrO;Qt"PHZy>y=h^eՊ>jΦk/K%r60UD\G66DLɻhVm KdҬՈˠ$ypbމFF=3Xqd+h[ +zټa%Ϣ$ i MqZ-MU9%գGCFN#J}mżjVu}U"--W9Jvkt@錠BSږT@xgn6Ϧez6̗u|?6}.x-0;?w]/PB8D;5+x  O&YxÏy (R21;Ǔ/8fsJꥰHdrXܖI&7<RrMxW86֯E BFO=ľeY,?~GzuC|_sc0A: y^*_2|p Nv`TiyITf5de3eRny;tl6.`{%stg6V1tu;;[Icg7rS3s<9>z)%kWcﻏ5\B#}u(9||Te:16^JZ#ym=xնi͚7/WGgoBn/;;;{0mۿ17==^t\<#GHvwuzNVJ%1t nr>%HyԪU"3gxlC.c\2|\W^!rΦoG8:=CO:DRpRReY]XXh}x7;_<44+''! ,ܲv*ffWD,@ah*z{eɦScQ,QCU=pFAZRR֨TT t/35Ce:[14gP78:3Îdg `Bju{<297u)7&EWUaȇ^\&P6xW0+iJو%0ѕɠ_TBsNrIRj IR2<;GsُdR 2$dT2N*(۟~ɅYzb V%3\OŠ $Nn"f vfO)ܷVcjVttyɞ{Xϒ&HdKM9BfB $9j^͉BQuNtM&Y+*-;6=yߞ/ؗ˦i_^\\<#mΒ!+ ?%oߴI߲rj෧{) ARw&rl!o/- an3i%I_+;td2̗w}~̈&(-TZA`/xU0ыKS 刦R+ҝɤ֑L 4qRöPt]Brח% 6ꊲҴ5tUaۮ7Sw(JByw'6MWi.LYY??pq~7W~tuu-zο/旎%ab,8VBJIqvc33LQI)|_ ! )eU1/ !N(r0].7ZL?U3]EQUϚ҉_L ϒNS^PZ\lo~c${9{ᇙ {5,X2ʊ}4MjufO, Ðd6I#SMj7555 <ʩpy#x+hxzYVkZZVkm\.Vo6>k7x*-zA/Kj#mI9_!uf( V";xXB% C.躾J[hUS=,3sLwuSs<KmFoU#<d{3,.bZR.TS m+DDcF.38yrMd0L0=2=\F\J<SM~'IfQuA%3o Jc7 $. s:-s ;{x:d˅*OhTdڝٞ XT}Ρ.s tPXXdvztWdgr̳{BZ(O4.tvvvj3l !笘E&JRb>+Wrmqx(n2ԿݞklY,..rwPv =_Ť/4cJl7[PR4PUZ"C|D׊4"+fiD}D$F9Uh yF5\0[k1HJ:."7;e]zkKl}ՃCtd^1Ʀy6:?I3-ΐ&B 嶮j";QT?4B2s=&McLyK Xǿ_> X{FiHbb&Q4V}3'PR+PTEz Kח񮏥ј !ӕ&AqJuZ<MD&BzģY*s{yZ)6}U&gN2k9.IUQ'""ik1vWJZMUSvku+N]vg=1m A6ft Njj^s-tCVkJfS8x#JNI[ PTeWT5lY3~|]?Xhb2' gvr}Ǩ.Յ׹y+faE[g"ng*KPXw}Je**v%~Ȫ?vW/15x4Wr A gHtcfSȍ{vε<#C LâQh5#^u މB.RT.~nju |EUqזɥ1 0cD|s}|oaDQ2tC;ԏX"ApbPBR7vRYvs y4M1Vz_WQ%X$9oIĩJpt-..VU d$]lzSظ\EQLDQzHw*cht.$?::}]vq ;شi#;)P(8>>^pEeM? :֯u:Wt4JL@],]Z}ʕ4{;"Xkx|ĩU+w+;So!a>jB̅~8LAM^BX,OnRDpuյ>RM,˯WyW6왙˧jԴV0+23a *(u]ߧ(ʈ)j?*xk !:|߫(#4muRXlp5&lwV8IENDB`PG-4.5/etc/desktop/icons/16x16/000077500000000000000000000000001426357011200160155ustar00rootroot00000000000000PG-4.5/etc/desktop/icons/16x16/proofgeneral.png000066400000000000000000000017741426357011200212170ustar00rootroot00000000000000PNG  IHDR(-SgAMA asRGB cHRMz&u0`:pQ<PLTE4@ E"!G#!G#C!0 D"&W)(\+(]+)^,)^,(]+%S'E!6#O&%U(=#O&%S'.B /[,!G#&C_0#N&!" *-&E!%&&q]]mhZ({zzyiigf!E88nZX|bZZXtPOhJI:--?4.;D4BP;@=3;*,6F25F1bm\+<(7I4LZEO^I+9((9']`Q|p8J45F2#(!)`--c/2e1*a-)^,-b.wIUGo6&]+)`,PU_}=@m42b.)]+*`-Qd5Y_3?V/Sj8Rr9@k2(_+**'('',)(0-*A?4\^GE^<+U+$T'yv}~w˱Suaؿutgejbk`QVOqtcchXdNtRNS?VdePGփ+JYʈ%ޅc^Y CYG1j{W7bKGDH pHYs55 !CwIDATc```dbfaecd.n^>~A!a@ AăCB#B`)Ȩظ@>\BbRrJjZ`zHgȾNS춟 Ec٩[!E%Y]﹏7g!Vc^c4}%D[](XDeZR/q%-slK m $B8iZRKQFހAR'k#B3@ (ZCE z< TWT+T^vI} tFѕ˓%<7Fa6㸹\O͚00EW"D!{Mt ¤7oK!A%ά42XրF4끛[ UODF}esjZ#/@ qcY Bal|p8͈mB @q-[b#=-NÅU\\2 NG@(|dFDpA3m.'7vW9TAEXPuhJt4;bl>!a4OPH>aABȵי( APg|u Puq@"@a$m&SH)!%@?ڎuOnn%.a PBxɤK$fJ!_)#?{+t`&0" $SinܟG`ķX]]2Lp=/<ɉgQC4>w EB"J#Ģ108<??X@HW( pܼ9pk|!Ls\mի:#Z4]w)1&_P"+1ߪa8|š!BTk?\ps8v/ٮ,'G? a{& ITh\v>׶zL(^;y$ѵNBB@ë8뮝˵,D`bL&6\fJƒ}{p`b/cö;&t]G0#B \\FuigfA @<ϧRϯ4Jenmrn磊")gv1;7cBA;p0s:62@J̗+rRcl1q!-W0گm02(ʉSx_qaTƠ0j{tX>IET=% Vi^ߖ @QRRX4Vˎx4H30z %tEXtdate:create2016-05-24T22:13:21-04:00 9%tEXtdate:modify2016-05-24T22:13:21-04:00QIENDB`PG-4.5/etc/desktop/icons/48x48/000077500000000000000000000000001426357011200160275ustar00rootroot00000000000000PG-4.5/etc/desktop/icons/48x48/proofgeneral.png000066400000000000000000000071421426357011200212240ustar00rootroot00000000000000PNG  IHDR00WgAMA asRGB cHRMz&u0`:pQ<bKGDC pHYs55 !Cw WIDAThՙYy>ÕH.4)HK)-Y Apbyo b @:_ $ QDvbҲlQQ\"܋ܝ}_/@͂5id]FʘS!2)!>ҁ ZǗvt"Vrt_@R:#Kv~ZQaHS B t+mzEǺ_ oDI#~m_dds]-3m~i})M Aփzz|7ƦO_sJ)^f12ΈU>gdmc&_Ld?/,y!e`em#VzV8L[hanrO9-m˝Ԡ6RHS 0Wwl,KZ-&_Jio&(v&krO~O+W}ݻ<&%l>gO>g>!̌%r>Dn4>!>4&/ t; <ԣ iU%@:t: #֠5R">(l$I027fYi7E1cg>EHy#+Z#q|eTwz?9nj}[V*ssN96Qv]}Fw)139x( 6UWCz硩g'FtGdzjMI=Rd˲Z:2$aH~<}a׏?8MwdNLޱѧ{NŰ,#]WoW,&Nb:m<80x׹rSFzA\ۦF̯hD oc絶Nq//-}kn}G0F.$Z_?uZ9sJGvxRv$WE0bvuZEIJ˳jSss/7} ?m۱hR97^.-ƵRbYmU?src`>/"_Gg\kc9qByvk4~P̤+Zlc}}N1l;FOW#F֏bJq+kb;bA$Odo_[#~ T2NP?ΥBuP[!17# , !ɗsdi!6 ,3()8_1P᳃Nnvq\\g~H%(;k("Q\Y!Hz5ri|֚nΖ_@*<& )dKy8&[NQȺktG%=4$V$R_:@PtcIG1qf\ܔa%[$Dge.x~K]LxwNw3=7?ύXAg^ǿS(_I2S+e>yL K-eH%(:}Y+K~L)Rڡh`e5DAD%Qyޫ^hmHv`>AP^+'O8h}= Qѩ^l6ngse jeF|@c%tEXtdate:create2016-05-24T22:13:21-04:00 9%tEXtdate:modify2016-05-24T22:13:21-04:00QIENDB`PG-4.5/etc/desktop/icons/64x64/000077500000000000000000000000001426357011200160235ustar00rootroot00000000000000PG-4.5/etc/desktop/icons/64x64/proofgeneral.png000066400000000000000000000116651426357011200212250ustar00rootroot00000000000000PNG  IHDR@@iqbKGD pHYs55 !CwtIME .. DBIDATxǙ?}t=!9(JDIIlY:Bf ME A.dl:+YeKQL4gH鹺{z}T^ E2k")`0}~>OU/oK###fqQUj&INSt@A֟ !tHTUaYVkmm}ry8LýZ8bb(bH1Ԋb(yESB * 3JD&ix7u4M8PT lfQ=h,UQt)!UD9a;lo~Z^T55nv}gIJFx-h;lEF]}v?*Ywr 6?U @(PQM =gUad̃J (.oz~O3M?IT]E1TY,dwm}WT I)IL}Li_?6M{nPpbAf1uJU]ۅ=ɿt˽^on)=~j~A+>JWR{{hhb'Ӛ6G+uepln6) F`2Qʲrh=]zV'M'^ ̮0t+*?2SjN8)Yrfv$JR"Ď](*BNaw f2 Q7qĿeDA%MrXB&nx-BG߿]{[8N${f͊YwCΗUבRyN.3*؍؉@~C34b/;[qZ,E%+"Rcth]4 FGGiq|*9{sM**-DT IY݁Y^]`)UpBiS.ZtU(C6QTPUv&_v6ϗrhȅm0Qɲ(-*F ZFs"`t_]Hbi8'qQ\}Si*aisWZz~[˱VEJscajNRFF^`ӏG0 ]B R}Z-4U?X2" nȚ/6L +2僅6c 'QBy`aj*+9v# SPb4Sed*P6w@FӔ)e㔚mZwBIO"2 S$$!gu$! 'ˆ2X(>]/n[7Rn-(XIʹ+m.#)@I5Hҏ$A^QUt]4ARPczJnh*.2\X7; pta&(:%Qsf=.XJ >%2UUL^!1RVwQ0P uBRQ(eʯ[ a\w51QCYG5kq' SId"TlL&쬭]v?0f~C}pk5o.sk1jFCӺm4I]ll6[▃e44MKdUUTUUIi Elbё:ijB}sJ=#DFA3{-p;^%w-->00pprr/K4O \#H*  5|P)i7xad+  ȥ_Wv`d||D63l'1MlT&xgLM{>?رd\FApƩfy2G>(,BxC}t{=6Z-VMV[󭅥vt; }@^?=55uvxz=sGo.'y|gϻ((Ӕ~|ub=iPUCCT8,%ixe;m7̀﫪*QqqtPBGYwz,q衇h7ҋ/7_<6+Dޜ4_)IM Pٶ}osH$)zin޲? \BK֗lLVP79wccYh:4ҹTUHOrAWYgTbf4ӓL75VWV36|[3qNϊ,GF]qdf0cnvlSz=$ASU|/?y-Mf^zFw;O~5T^%GT % :\DJ|Ͽxymh;MǮ5(B4[۔JeJ277ǥ2%Sp?k_y3틿^\M>GFƯoUBNw:Daȧȕ^サpzˎ!;0yr>Ñ( gVx(Lf ຣIr]mu..vzs8Py~9 @!A\g׻&RMoth&S!mϬw)%2M/&X4ˍ֦spj*?Q66"ymgt/O38g5 u_KS\3KkklVs]@Ï~XƓ#{8 (|r#޻d,$Y׸( !N+v6V_8zLP`nnS+yvx3W:^s_#YD7;N<@zMV$͐;1(R! [^~{au$qD/n6qŷ^=u#҂PZrMN$ Iۡ8XeVqU/YVs^nwC}wzl[+}PsB((Vʙ>BMs\^Zb4)X&q:ӓVP8fc\^e`#{ ́rqf6d{s'eP!KW(|~P."gȧ믾;afj/]HJŝ@, q:"ejZ_=#˕z'g)wU KG/rP=ɓ'x쑇QU:$Mh( ,>u6&iJ4Mf2{+?"T5 FJZ+"ꛛr{wglac0n3<&M J$Bmb!T*bY4U$$^fkg>&HL)(gdM'hRf38xfq0>B}{n'vۙﵷ;O|L%cżٷwȿ$G( ~! o6|5Zs"#̈́'&A>shC Ӕkk}z|u?z]FpqqBrǧsG&t/\hIUjf8ž^FI{{Kd8B&RXl4`PYs&T-V}mWz498'2 pg-vars -> proof-site -> pg-vars [To Be Continued] Some Emacs Resources ==================== Emacs Wiki: http://www.emacswiki.org Mailing list archives: http://mail.gnu.org/archive/html/emacs-devel/ PG-4.5/etc/emacsbugs/000077500000000000000000000000001426357011200144155ustar00rootroot00000000000000PG-4.5/etc/emacsbugs/compose-char.txt000066400000000000000000000701301426357011200175370ustar00rootroot00000000000000From: David Aspinall To: bug-gnu-emacs@gnu.org Subject: 23.3; Repeatable segmentation fault, all platforms, in character composition code Date: Mon, 06 Jun 2011 14:34:51 +0100 --text follows this line-- There is a segfault which arises reproducibly when compose-character is used near the end of a buffer. I'm afraid I don't have a raw test case but here is a recipe to reproduce it that loads the Emacs application Proof General: wget http://proofgeneral.inf.ed.ac.uk/releases/ProofGeneral-4.0.tgz tar -xpzf ProofGeneral-4.0.tgz (cd ProofGeneral; make clean) emacs -q -l ProofGeneral/generic/proof-site.el C-x C-f Test.thy Then type \ and Emacs segfaults. If instead you type M-x 1 0 SPACE C-a \ it behaves as expected: looks like the code is running off the end of the buffer. Downstream issue is here: http://proofgeneral.inf.ed.ac.uk/trac/ticket/338 It contains a backtrace from Emacs running on Mac OS X, copied below. - David Subject: [isabelle] Emacs/Isabelle crash From: David Brumley Date: Mon, 25 Apr 2011 11:19:32 -0400 To: cl-isabelle-users@lists.cam.ac.uk Hi, I downloaded isabelle today for OS X from the main website (Isabelle2011.dmg). I'm working through the tutorial at http://isabelle.in.tum.de/doc/tutorial.pdf. On page 20, I go to enter in the type declaration given, using \ for the negation in the "value" method (per appendix A.1). Emacs reliably crashes every time I do this. Crash report below. What would be the best course of action to move forward? Install carbon emacs 22.x? Use some other symbol entry for negation (what would I use?) Thanks, David Process: Emacs [62639] Path: /Applications/Isabelle2011.app/Contents/Resources/Emacs.app/Contents/MacOS/Emacs Identifier: org.gnu.Emacs Version: Version 23.2 (9.0) Code Type: X86-64 (Native) Parent Process: bash [62631] Date/Time: 2011-04-25 11:16:16.359 -0400 OS Version: Mac OS X 10.6.7 (10J869) Report Version: 6 Interval Since Last Report: 2506101 sec Crashes Since Last Report: 11 Per-App Interval Since Last Report: 3565 sec Per-App Crashes Since Last Report: 3 Anonymous UUID: 6B212705-6B54-44EC-8BE3-2EEC5563842D Exception Type: EXC_CRASH (SIGABRT) Exception Codes: 0x0000000000000000, 0x0000000000000000 Crashed Thread: 0 Dispatch queue: com.apple.main-thread Application Specific Information: abort() called Thread 0 Crashed: Dispatch queue: com.apple.main-thread 0 libSystem.B.dylib 0x00007fff8020a5d6 __kill + 10 1 libSystem.B.dylib 0x00007fff802aacd6 abort + 83 2 org.gnu.Emacs 0x000000010016e44c ns_term_shutdown + 44 3 org.gnu.Emacs 0x0000000100090274 fatal_error_signal + 340 4 libSystem.B.dylib 0x00007fff8021c66a _sigtramp + 26 5 libSystem.B.dylib 0x00007fff8020a5d6 __kill + 10 6 libSystem.B.dylib 0x00007fff802aacd6 abort + 83 7 org.gnu.Emacs 0x00000001000bdd95 buf_charpos_to_bytepos + 389 8 org.gnu.Emacs 0x0000000100160a7b composition_update_it + 539 9 org.gnu.Emacs 0x000000010002eca3 next_element_from_composition + 131 10 org.gnu.Emacs 0x000000010002f0b6 next_element_from_buffer + 182 11 org.gnu.Emacs 0x000000010002f235 next_element_from_buffer + 565 12 org.gnu.Emacs 0x000000010002bc90 get_next_display_element + 64 13 org.gnu.Emacs 0x0000000100032aba display_line + 474 14 org.gnu.Emacs 0x000000010003d313 try_window + 163 15 org.gnu.Emacs 0x000000010003f009 redisplay_window + 6713 16 org.gnu.Emacs 0x0000000100040847 redisplay_window_0 + 39 17 org.gnu.Emacs 0x00000001001075ae internal_condition_case_1 + 334 18 org.gnu.Emacs 0x0000000100029a9d redisplay_windows + 93 19 org.gnu.Emacs 0x000000010004148c redisplay_internal + 3116 20 org.gnu.Emacs 0x000000010009e8be read_char + 2350 21 org.gnu.Emacs 0x00000001000a104f read_key_sequence + 1215 22 org.gnu.Emacs 0x00000001000a31f9 Fread_key_sequence + 313 23 org.gnu.Emacs 0x0000000100109256 Ffuncall + 1126 24 org.gnu.Emacs 0x0000000100145aae Fbyte_code + 6814 25 org.gnu.Emacs 0x0000000100108bfc funcall_lambda + 588 26 org.gnu.Emacs 0x0000000100109042 Ffuncall + 594 27 org.gnu.Emacs 0x0000000100145aae Fbyte_code + 6814 28 org.gnu.Emacs 0x0000000100108bfc funcall_lambda + 588 29 org.gnu.Emacs 0x0000000100109042 Ffuncall + 594 30 org.gnu.Emacs 0x000000010010a78e call1 + 30 31 org.gnu.Emacs 0x000000010009e44f read_char + 1215 32 org.gnu.Emacs 0x00000001000a104f read_key_sequence + 1215 33 org.gnu.Emacs 0x00000001000a35cb command_loop_1 + 587 34 org.gnu.Emacs 0x0000000100107717 internal_condition_case + 327 35 org.gnu.Emacs 0x000000010009a9a7 command_loop_2 + 55 36 org.gnu.Emacs 0x0000000100107820 internal_catch + 224 37 org.gnu.Emacs 0x000000010009b436 command_loop + 182 38 org.gnu.Emacs 0x000000010009b89f recursive_edit_1 + 159 39 org.gnu.Emacs 0x000000010009ba3f Frecursive_edit + 287 40 org.gnu.Emacs 0x000000010009102c main + 3452 41 org.gnu.Emacs 0x0000000100002034 start + 52 Thread 1: Dispatch queue: com.apple.libdispatch-manager 0 libSystem.B.dylib 0x00007fff801d512a kevent + 10 1 libSystem.B.dylib 0x00007fff801d6ffd _dispatch_mgr_invoke + 154 2 libSystem.B.dylib 0x00007fff801d6cd4 _dispatch_queue_invoke + 185 3 libSystem.B.dylib 0x00007fff801d67fe _dispatch_worker_thread2 + 252 4 libSystem.B.dylib 0x00007fff801d6128 _pthread_wqthread + 353 5 libSystem.B.dylib 0x00007fff801d5fc5 start_wqthread + 13 Thread 0 crashed with X86 Thread State (64-bit): rax: 0x0000000000000000 rbx: 0x0000000000000006 rcx: 0x00007fff5fbf3fe8 rdx: 0x0000000000000000 rdi: 0x000000000000f4af rsi: 0x0000000000000006 rbp: 0x00007fff5fbf4000 rsp: 0x00007fff5fbf3fe8 r8: 0x0000000000000001 r9: 0x0000000119ba57a0 r10: 0x00007fff80206616 r11: 0x0000000000000206 r12: 0x0000000000000006 r13: 0x0000000100534d48 r14: 0x0000000000000200 r15: 0x00000000000000ac rip: 0x00007fff8020a5d6 rfl: 0x0000000000000206 cr2: 0x0000000102a35fff Binary Images: 0x100000000 - 0x1001d9fff +org.gnu.Emacs Version 23.2 (9.0) <7D762A3A-B020-669B-93E9-CD4525AAB2E1> /Applications/Isabelle2011.app/Contents/Resources/Emacs.app/Contents/MacOS/Emacs 0x1013aa000 - 0x1013aeff7 libFontRegistryUI.dylib ??? (???) <89E50DF0-2A72-B443-28AE-5F27EC7E22C7> /System/Library/Frameworks/ApplicationServices.framework/Frameworks/ATS.framework/Resources/libFontRegistryUI.dylib 0x7fff5fc00000 - 0x7fff5fc3bdef dyld 132.1 (???) <486E6C61-1197-CC7C-2197-82CE505102D7> /usr/lib/dyld 0x7fff800d1000 - 0x7fff801b7fef com.apple.DesktopServices 1.5.10 (1.5.10) /System/Library/PrivateFrameworks/DesktopServicesPriv.framework/Versions/A/DesktopServicesPriv 0x7fff801b8000 - 0x7fff801bafff libRadiance.dylib ??? (???) <73257486-8E94-E758-1A5A-5B521F27EE12> /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ImageIO.framework/Versions/A/Resources/libRadiance.dylib 0x7fff801bb000 - 0x7fff8037cfff libSystem.B.dylib 125.2.10 (compatibility 1.0.0) <9BAEB2F2-B485-6349-E1AB-637FE12EE770> /usr/lib/libSystem.B.dylib 0x7fff803c1000 - 0x7fff804d8fef libxml2.2.dylib 10.3.0 (compatibility 10.0.0) <1B27AFDD-DF87-2009-170E-C129E1572E8B> /usr/lib/libxml2.2.dylib 0x7fff80582000 - 0x7fff80740fff libicucore.A.dylib 40.0.0 (compatibility 1.0.0) <2C6ECACF-CD56-1714-6F63-CB6F5EE7A1E2> /usr/lib/libicucore.A.dylib 0x7fff80741000 - 0x7fff80750fff com.apple.opengl 1.6.12 (1.6.12) <29482652-1E44-1C47-428F-1209AA65336D> /System/Library/Frameworks/OpenGL.framework/Versions/A/OpenGL 0x7fff80751000 - 0x7fff80909fef com.apple.ImageIO.framework 3.0.4 (3.0.4) /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ImageIO.framework/Versions/A/ImageIO 0x7fff8090a000 - 0x7fff80917fe7 libCSync.A.dylib 545.0.0 (compatibility 64.0.0) <45B5B514-7CEB-38A9-F34A-1D96F010EC42> /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/CoreGraphics.framework/Versions/A/Resources/libCSync.A.dylib 0x7fff80918000 - 0x7fff8091dfff libGIF.dylib ??? (???) <1B9DCB7F-CD1D-B23F-8AC6-5292B94A4D0E> /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ImageIO.framework/Versions/A/Resources/libGIF.dylib 0x7fff8091e000 - 0x7fff80cbbfe7 com.apple.QuartzCore 1.6.3 (227.36) <6FD8E129-135E-2F89-E9F0-A3CD0C6FCEF1> /System/Library/Frameworks/QuartzCore.framework/Versions/A/QuartzCore 0x7fff80e1d000 - 0x7fff80ed3fff libobjc.A.dylib 227.0.0 (compatibility 1.0.0) <99CB3A0F-64CF-1D16-70CD-8AED2EF06C30> /usr/lib/libobjc.A.dylib 0x7fff80fed000 - 0x7fff81018ff7 libxslt.1.dylib 3.24.0 (compatibility 3.0.0) <87A0B228-B24A-C426-C3FB-B40D7258DD49> /usr/lib/libxslt.1.dylib 0x7fff8108e000 - 0x7fff81095fff com.apple.OpenDirectory 10.6 (10.6) <4200CFB0-DBA1-62B8-7C7C-91446D89551F> /System/Library/Frameworks/OpenDirectory.framework/Versions/A/OpenDirectory 0x7fff81096000 - 0x7fff81130ff7 com.apple.ApplicationServices.ATS 4.4 (???) <55B528A6-0C88-6CB8-152B-A34A440FACFE> /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ATS.framework/Versions/A/ATS 0x7fff81131000 - 0x7fff811b6ff7 com.apple.print.framework.PrintCore 6.3 (312.7) /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/PrintCore.framework/Versions/A/PrintCore 0x7fff81210000 - 0x7fff81214ff7 libCGXType.A.dylib 545.0.0 (compatibility 64.0.0) <49E6AF5D-AF9B-67CF-A6B8-C79F6BA8A627> /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/CoreGraphics.framework/Versions/A/Resources/libCGXType.A.dylib 0x7fff81215000 - 0x7fff8132efef libGLProgrammability.dylib ??? (???) /System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGLProgrammability.dylib 0x7fff81348000 - 0x7fff8136dff7 com.apple.CoreVideo 1.6.2 (45.6) /System/Library/Frameworks/CoreVideo.framework/Versions/A/CoreVideo 0x7fff81873000 - 0x7fff81884ff7 libz.1.dylib 1.2.3 (compatibility 1.0.0) <97019C74-161A-3488-41EC-A6CA8738418C> /usr/lib/libz.1.dylib 0x7fff8197e000 - 0x7fff81984ff7 com.apple.CommerceCore 1.0 (9) <4C66D962-91B5-F25C-A6FF-DFD5F924A0DD> /System/Library/PrivateFrameworks/CommerceKit.framework/Versions/A/Frameworks/CommerceCore.framework/Versions/A/CommerceCore 0x7fff81a03000 - 0x7fff81a17ff7 com.apple.speech.synthesis.framework 3.10.35 (3.10.35) <621B7415-A0B9-07A7-F313-36BEEDD7B132> /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/SpeechSynthesis.framework/Versions/A/SpeechSynthesis 0x7fff81a18000 - 0x7fff81a5bff7 libRIP.A.dylib 545.0.0 (compatibility 64.0.0) <2C596A24-8B86-79D6-1A8E-5E8FFB6A1558> /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/CoreGraphics.framework/Versions/A/Resources/libRIP.A.dylib 0x7fff81a5c000 - 0x7fff81a6aff7 libkxld.dylib ??? (???) <27713C39-0E51-8F5A-877B-C5539C96A520> /usr/lib/system/libkxld.dylib 0x7fff81aa9000 - 0x7fff81b09fe7 com.apple.framework.IOKit 2.0 (???) /System/Library/Frameworks/IOKit.framework/Versions/A/IOKit 0x7fff81b0a000 - 0x7fff81baafff com.apple.LaunchServices 362.2 (362.2) /System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/LaunchServices.framework/Versions/A/LaunchServices 0x7fff81bab000 - 0x7fff81bb1ff7 com.apple.DiskArbitration 2.3 (2.3) <857F6E43-1EF4-7D53-351B-10DE0A8F992A> /System/Library/Frameworks/DiskArbitration.framework/Versions/A/DiskArbitration 0x7fff81bb6000 - 0x7fff81bd9fff com.apple.opencl 12.3.6 (12.3.6) <42FA5783-EB80-1168-4015-B8C68F55842F> /System/Library/Frameworks/OpenCL.framework/Versions/A/OpenCL 0x7fff81c22000 - 0x7fff81c9ffef libstdc++.6.dylib 7.9.0 (compatibility 7.0.0) <35ECA411-2C08-FD7D-11B1-1B7A04921A5C> /usr/lib/libstdc++.6.dylib 0x7fff81da7000 - 0x7fff81dd8fff libGLImage.dylib ??? (???) <6925991A-9B1B-B9FA-645A-807F9BCC3DE7> /System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGLImage.dylib 0x7fff81dd9000 - 0x7fff81e01fff com.apple.DictionaryServices 1.1.2 (1.1.2) /System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/DictionaryServices.framework/Versions/A/DictionaryServices 0x7fff81e02000 - 0x7fff81e51fef libTIFF.dylib ??? (???) /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ImageIO.framework/Versions/A/Resources/libTIFF.dylib 0x7fff81e60000 - 0x7fff81e60ff7 com.apple.vecLib 3.6 (vecLib 3.6) <96FB6BAD-5568-C4E0-6FA7-02791A58B584> /System/Library/Frameworks/vecLib.framework/Versions/A/vecLib 0x7fff81e61000 - 0x7fff81eb0ff7 com.apple.DirectoryService.PasswordServerFramework 6.1 (6.1) <01B370FB-D524-F660-3826-E85B7F0D85CD> /System/Library/PrivateFrameworks/PasswordServer.framework/Versions/A/PasswordServer 0x7fff81eec000 - 0x7fff81f6bfe7 com.apple.audio.CoreAudio 3.2.6 (3.2.6) <6D8AD3F7-409D-512C-C5BE-66C64D1B8F3E> /System/Library/Frameworks/CoreAudio.framework/Versions/A/CoreAudio 0x7fff81f70000 - 0x7fff8202dfff com.apple.CoreServices.OSServices 359 (359) <8F509D8D-4C94-9A1C-3A87-5B775D9F6075> /System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/OSServices.framework/Versions/A/OSServices 0x7fff822d2000 - 0x7fff82387fe7 com.apple.ink.framework 1.3.3 (107) <8C36373C-5473-3A6A-4972-BC29D504250F> /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/Ink.framework/Versions/A/Ink 0x7fff823be000 - 0x7fff82406ff7 libvDSP.dylib 268.0.1 (compatibility 1.0.0) <98FC4457-F405-0262-00F7-56119CA107B6> /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libvDSP.dylib 0x7fff82407000 - 0x7fff8244eff7 com.apple.coreui 2 (114) <923E33CC-83FC-7D35-5603-FB8F348EE34B> /System/Library/PrivateFrameworks/CoreUI.framework/Versions/A/CoreUI 0x7fff8244f000 - 0x7fff82e45fff com.apple.AppKit 6.6.7 (1038.35) <9F4DF818-9DB9-98DA-490C-EF29EA757A97> /System/Library/Frameworks/AppKit.framework/Versions/C/AppKit 0x7fff82e46000 - 0x7fff830c9fe7 com.apple.Foundation 6.6.6 (751.53) <476E617B-B59B-53DE-991D-98C1993BCBCE> /System/Library/Frameworks/Foundation.framework/Versions/C/Foundation 0x7fff831b3000 - 0x7fff831d0ff7 libPng.dylib ??? (???) <0C232C1E-49C8-F7A9-9634-DF2BDA1AB722> /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ImageIO.framework/Versions/A/Resources/libPng.dylib 0x7fff834b2000 - 0x7fff83542fff com.apple.SearchKit 1.3.0 (1.3.0) <4175DC31-1506-228A-08FD-C704AC9DF642> /System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/SearchKit.framework/Versions/A/SearchKit 0x7fff8358e000 - 0x7fff835c7fef libcups.2.dylib 2.8.0 (compatibility 2.0.0) /usr/lib/libcups.2.dylib 0x7fff835c8000 - 0x7fff835c8ff7 com.apple.CoreServices 44 (44) /System/Library/Frameworks/CoreServices.framework/Versions/A/CoreServices 0x7fff835c9000 - 0x7fff83613ff7 com.apple.Metadata 10.6.3 (507.15) <5170FCE0-ED6C-2E3E-AB28-1DDE3F628FC5> /System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/Metadata.framework/Versions/A/Metadata 0x7fff83614000 - 0x7fff836d5fef com.apple.ColorSync 4.6.6 (4.6.6) /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ColorSync.framework/Versions/A/ColorSync 0x7fff836d6000 - 0x7fff83797fff libFontParser.dylib ??? (???) <244BCE74-7EEE-C9DE-9779-F3AEF5869BE6> /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ATS.framework/Versions/A/Resources/libFontParser.dylib 0x7fff837ac000 - 0x7fff837b1fff libGFXShared.dylib ??? (???) <878C429B-44D4-875C-1A35-4FD8C6152695> /System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGFXShared.dylib 0x7fff837f7000 - 0x7fff83818fff libresolv.9.dylib 41.0.0 (compatibility 1.0.0) <9F322F47-0584-CB7D-5B73-9EBD670851CD> /usr/lib/libresolv.9.dylib 0x7fff83819000 - 0x7fff8385afef com.apple.QD 3.36 (???) <5DC41E81-32C9-65B2-5528-B33E934D5BB4> /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/QD.framework/Versions/A/QD 0x7fff8385d000 - 0x7fff83992ff7 com.apple.audio.toolbox.AudioToolbox 1.6.6 (1.6.6) /System/Library/Frameworks/AudioToolbox.framework/Versions/A/AudioToolbox 0x7fff83a27000 - 0x7fff83a40fff com.apple.CFOpenDirectory 10.6 (10.6) /System/Library/Frameworks/OpenDirectory.framework/Versions/A/Frameworks/CFOpenDirectory.framework/Versions/A/CFOpenDirectory 0x7fff83aae000 - 0x7fff83aeffff com.apple.SystemConfiguration 1.10.5 (1.10.2) /System/Library/Frameworks/SystemConfiguration.framework/Versions/A/SystemConfiguration 0x7fff84065000 - 0x7fff8407bfe7 com.apple.MultitouchSupport.framework 207.10 (207.10) <458F0259-6EDC-16BA-E6AA-1CEED002D188> /System/Library/PrivateFrameworks/MultitouchSupport.framework/Versions/A/MultitouchSupport 0x7fff8407c000 - 0x7fff84091ff7 com.apple.LangAnalysis 1.6.6 (1.6.6) <1AE1FE8F-2204-4410-C94E-0E93B003BEDA> /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/LangAnalysis.framework/Versions/A/LangAnalysis 0x7fff84092000 - 0x7fff841b3fe7 libcrypto.0.9.8.dylib 0.9.8 (compatibility 0.9.8) <48AEAFE1-21F4-B3C8-4199-35AD5E8D0613> /usr/lib/libcrypto.0.9.8.dylib 0x7fff84521000 - 0x7fff84547fe7 libJPEG.dylib ??? (???) /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ImageIO.framework/Versions/A/Resources/libJPEG.dylib 0x7fff84548000 - 0x7fff84548ff7 com.apple.Accelerate 1.6 (Accelerate 1.6) <15DF8B4A-96B2-CB4E-368D-DEC7DF6B62BB> /System/Library/Frameworks/Accelerate.framework/Versions/A/Accelerate 0x7fff84549000 - 0x7fff8454fff7 IOSurface ??? (???) /System/Library/Frameworks/IOSurface.framework/Versions/A/IOSurface 0x7fff84550000 - 0x7fff84734ff7 libType1Scaler.dylib ??? (???) <2C7624EC-01D5-5E9E-3FB8-8ADA460ED6DE> /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ATS.framework/Versions/A/Resources/libType1Scaler.dylib 0x7fff84735000 - 0x7fff84f3ffe7 libBLAS.dylib 219.0.0 (compatibility 1.0.0) /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libBLAS.dylib 0x7fff84f40000 - 0x7fff84f41ff7 com.apple.audio.units.AudioUnit 1.6.6 (1.6.6) /System/Library/Frameworks/AudioUnit.framework/Versions/A/AudioUnit 0x7fff84fa5000 - 0x7fff84fa5ff7 com.apple.Accelerate.vecLib 3.6 (vecLib 3.6) <4CCE5D69-F1B3-8FD3-1483-E0271DB2CCF3> /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/vecLib 0x7fff84fd0000 - 0x7fff8500ffef libncurses.5.4.dylib 5.4.0 (compatibility 5.4.0) <9D53BE03-6D81-D0CB-F657-4E842E69A66A> /usr/lib/libncurses.5.4.dylib 0x7fff85010000 - 0x7fff85344fff com.apple.CoreServices.CarbonCore 861.34 (861.34) /System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/CarbonCore.framework/Versions/A/CarbonCore 0x7fff85345000 - 0x7fff853affe7 libvMisc.dylib 268.0.1 (compatibility 1.0.0) /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libvMisc.dylib 0x7fff853ba000 - 0x7fff853d0fef libbsm.0.dylib ??? (???) <42D3023A-A1F7-4121-6417-FCC6B51B3E90> /usr/lib/libbsm.0.dylib 0x7fff853d1000 - 0x7fff85404fff libTrueTypeScaler.dylib ??? (???) <632BAC10-4C24-D1F2-3943-DF5F2326318B> /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ATS.framework/Versions/A/Resources/libTrueTypeScaler.dylib 0x7fff85421000 - 0x7fff854d1fff edu.mit.Kerberos 6.5.11 (6.5.11) <085D80F5-C9DC-E252-C21B-03295E660C91> /System/Library/Frameworks/Kerberos.framework/Versions/A/Kerberos 0x7fff856c3000 - 0x7fff856d7fff libGL.dylib ??? (???) <0FA671EB-6FA0-BA97-C00A-C42247C22B26> /System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGL.dylib 0x7fff8571f000 - 0x7fff857f1fe7 com.apple.CFNetwork 454.11.12 (454.11.12) /System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/CFNetwork.framework/Versions/A/CFNetwork 0x7fff857f2000 - 0x7fff858abfff libsqlite3.dylib 9.6.0 (compatibility 9.0.0) <2C5ED312-E646-9ADE-73A9-6199A2A43150> /usr/lib/libsqlite3.dylib 0x7fff858ac000 - 0x7fff858bbfff com.apple.NetFS 3.2.2 (3.2.2) <7CCBD70E-BF31-A7A7-DB98-230687773145> /System/Library/Frameworks/NetFS.framework/Versions/A/NetFS 0x7fff858bc000 - 0x7fff858bdff7 com.apple.TrustEvaluationAgent 1.1 (1) <5952A9FA-BC2B-16EF-91A7-43902A5C07B6> /System/Library/PrivateFrameworks/TrustEvaluationAgent.framework/Versions/A/TrustEvaluationAgent 0x7fff858ca000 - 0x7fff85a08fff com.apple.CoreData 102.1 (251) <9DFE798D-AA52-6A9A-924A-DA73CB94D81A> /System/Library/Frameworks/CoreData.framework/Versions/A/CoreData 0x7fff85a2c000 - 0x7fff85d2afff com.apple.HIToolbox 1.6.5 (???) /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/HIToolbox.framework/Versions/A/HIToolbox 0x7fff85dc5000 - 0x7fff85e0efef libGLU.dylib ??? (???) <0FCD57C5-D7AA-F2DD-D2EC-C1C8B931F65C> /System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGLU.dylib 0x7fff85e55000 - 0x7fff85ed3ff7 com.apple.CoreText 3.151.8 (???) <5DCD6BD9-63FB-767E-5993-5AEBE890145B> /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/CoreText.framework/Versions/A/CoreText 0x7fff85ed4000 - 0x7fff85ed5fff liblangid.dylib ??? (???) /usr/lib/liblangid.dylib 0x7fff85ed6000 - 0x7fff85fa1fff ColorSyncDeprecated.dylib 4.6.0 (compatibility 1.0.0) /System/Library/Frameworks/ApplicationServices.framework/Frameworks/ColorSync.framework/Versions/A/Resources/ColorSyncDeprecated.dylib 0x7fff85fae000 - 0x7fff8608bfff com.apple.vImage 4.1 (4.1) /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vImage.framework/Versions/A/vImage 0x7fff86d97000 - 0x7fff871dafef libLAPACK.dylib 219.0.0 (compatibility 1.0.0) <0CC61C98-FF51-67B3-F3D8-C5E430C201A9> /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libLAPACK.dylib 0x7fff871db000 - 0x7fff87216fff com.apple.AE 496.4 (496.4) <55AAD5CA-7160-7899-1C68-562ED8160DF7> /System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/AE.framework/Versions/A/AE 0x7fff8728c000 - 0x7fff872d8fff libauto.dylib ??? (???) /usr/lib/libauto.dylib 0x7fff87544000 - 0x7fff8796ffef com.apple.RawCamera.bundle 3.6.4 (561) /System/Library/CoreServices/RawCamera.bundle/Contents/MacOS/RawCamera 0x7fff87970000 - 0x7fff879fcfef SecurityFoundation ??? (???) /System/Library/Frameworks/SecurityFoundation.framework/Versions/A/SecurityFoundation 0x7fff879fd000 - 0x7fff87a3aff7 libFontRegistry.dylib ??? (???) <8C69F685-3507-1B8F-51AD-6183D5E88979> /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ATS.framework/Versions/A/Resources/libFontRegistry.dylib 0x7fff87a3b000 - 0x7fff87a41fff libCGXCoreImage.A.dylib 545.0.0 (compatibility 64.0.0) /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/CoreGraphics.framework/Versions/A/Resources/libCGXCoreImage.A.dylib 0x7fff87ac6000 - 0x7fff87ad8fe7 libsasl2.2.dylib 3.15.0 (compatibility 3.0.0) <76B83C8D-8EFE-4467-0F75-275648AFED97> /usr/lib/libsasl2.2.dylib 0x7fff87ad9000 - 0x7fff87b2bff7 com.apple.HIServices 1.8.2 (???) <7C91D07D-FA20-0882-632F-0CAE4FAC2B79> /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/HIServices.framework/Versions/A/HIServices 0x7fff87d2b000 - 0x7fff87ea2fe7 com.apple.CoreFoundation 6.6.4 (550.42) <770C572A-CF70-168F-F43C-242B9114FCB5> /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation 0x7fff87ee0000 - 0x7fff88168fef com.apple.security 6.1.2 (55002) <015C9A08-3D07-9462-8E91-DB1924349621> /System/Library/Frameworks/Security.framework/Versions/A/Security 0x7fff88169000 - 0x7fff881beff7 com.apple.framework.familycontrols 2.0.2 (2020) /System/Library/PrivateFrameworks/FamilyControls.framework/Versions/A/FamilyControls 0x7fff881bf000 - 0x7fff881caff7 com.apple.speech.recognition.framework 3.11.1 (3.11.1) <3D65E89B-FFC6-4AAF-D5CC-104F967C8131> /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/SpeechRecognition.framework/Versions/A/SpeechRecognition 0x7fff8827d000 - 0x7fff88281ff7 libmathCommon.A.dylib 315.0.0 (compatibility 1.0.0) <95718673-FEEE-B6ED-B127-BCDBDB60D4E5> /usr/lib/system/libmathCommon.A.dylib 0x7fff88282000 - 0x7fff88285ff7 libCoreVMClient.dylib ??? (???) <00C97B96-8D3B-45EB-F503-DB49712DC42D> /System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libCoreVMClient.dylib 0x7fff882a7000 - 0x7fff882c7ff7 com.apple.DirectoryService.Framework 3.6 (621.11) /System/Library/Frameworks/DirectoryService.framework/Versions/A/DirectoryService 0x7fff8862c000 - 0x7fff88d2906f com.apple.CoreGraphics 1.545.0 (???) /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/CoreGraphics.framework/Versions/A/CoreGraphics 0x7fff88e7a000 - 0x7fff88e7aff7 com.apple.ApplicationServices 38 (38) <10A0B9E9-4988-03D4-FC56-DDE231A02C63> /System/Library/Frameworks/ApplicationServices.framework/Versions/A/ApplicationServices 0x7fffffe00000 - 0x7fffffe01fff libSystem.B.dylib ??? (???) <9BAEB2F2-B485-6349-E1AB-637FE12EE770> /usr/lib/libSystem.B.dylib Model: MacPro4,1, BootROM MP41.0081.B07, 4 processors, Quad-Core Intel Xeon, 2.93 GHz, 6 GB, SMC 1.39f5 Graphics: ATI Radeon HD 4870, ATI Radeon HD 4870, PCIe, 512 MB Memory Module: global_name AirPort: spairport_wireless_card_type_airport_extreme (0x14E4, 0x8E), Broadcom BCM43xx 1.0 (5.10.131.36.9) Bluetooth: Version 2.4.0f1, 2 service, 19 devices, 1 incoming serial ports Network Service: Ethernet 1, Ethernet, en0 PCI Card: ATI Radeon HD 4870, Display, Slot-1 Serial ATA Device: HL-DT-ST DVD-RW GH41N Serial ATA Device: Hitachi HDE721010SLA330, 931.51 GB Serial ATA Device: Hitachi HDE721010SLA330, 931.51 GB USB Device: FreeAgent, 0x0bc2, 0x3008, 0xfd300000 USB Device: Hub, 0x0424 (SMSC), 0x2514, 0xfd100000 USB Device: Hub, 0x0424 (SMSC), 0x2602, 0xfd110000 USB Device: Flash, 0x0424 (SMSC), 0x2228, 0xfd111000 USB Device: BRCM2046 Hub, 0x0a5c (Broadcom Corp.), 0x4500, 0x5a100000 USB Device: Bluetooth USB Host Controller, 0x05ac (Apple Inc.), 0x8215, 0x5a110000 FireWire Device: built-in_hub, Up to 800 Mb/sec PG-4.5/etc/emacsbugs/visiblity-attempt.el000066400000000000000000000021031426357011200204250ustar00rootroot00000000000000;;; visiblity-attempt.el --- Test area for invisibility ;; This file is part of Proof General. ;; Portions © Copyright 1994-2012 David Aspinall and University of Edinburgh ;; Portions © Copyright 2003, 2012, 2014 Free Software Foundation, Inc. ;; Portions © Copyright 2001-2017 Pierre Courtieu ;; Portions © Copyright 2010, 2016 Erik Martin-Dorel ;; Portions © Copyright 2011-2013, 2016-2017 Hendrik Tews ;; Portions © Copyright 2015-2017 Clément Pit-Claudel ;;; Commentary: ;; ;; Test area for invisibility ;; ;;; Code: (defvar vis nil) (overlay-put (make-overlay 18 22) 'invisible 'smaller) (overlay-put (make-overlay 9 43) 'invisible 'larger) (defun toggle-invis () (interactive) (if vis (add-to-invisibility-spec '(larger . t)) (remove-from-invisibility-spec '(larger . t))) (setq vis (not vis))) ;; In this buffer: ;; M-x eval-buffer RET ;; M-x toggle-invis ;; The smaller area remains visible, although there is a surrounding ;; overlay which has an invisibility spec which should cover the ;; revealed characters. Arguably a bug. PG-4.5/etc/profiling.txt000066400000000000000000000006521426357011200152010ustar00rootroot00000000000000Notes on Profiling Proof General in Emacs ----------------------------------------- Run make profile. to run scripted profiling tests in /-profiling.el Interactive use of Elisp profiler: M-x elp-instrument-package RET proof RET M-x elp-instrument-package RET pg RET < do something now > M-x elp-results To display results. Canonical settings: M-x profile-pg (in lib/pg-dev). PG-4.5/etc/proofgeneral-domain.txt000066400000000000000000000013561426357011200171420ustar00rootroot00000000000000 Notes about proofgeneral.org [obsolete!] ----------------------------------------- Hosted by freeparking.co.uk. Sign up 20th Sep 2000, 2 years for 29.95 mail.proofgeneral.org is freeparking's mail handler www.proofgeneral.org is zermelo.dcs.ed.ac.uk DNS zone: proofgeneral.org A 129.215.96.75 Email aliases: -------------- support proofgen@informatics.ed.ac.uk feedback proofgen@informatics.ed.ac.uk bugs proofgen@informatics.ed.ac.uk eeproof proofgen@informatics.ed.ac.uk da David.Aspinall@ed.ac.uk users proofgeneral@informatics.ed.ac.uk http://lists.inf.ed.ac.uk/mailman/listinfo/proofgeneral devel proofgeneral-devel@informatics.ed.ac.uk http://lists.inf.ed.ac.uk/mailman/listinfo/proofgeneral-devel PG-4.5/etc/proviola/000077500000000000000000000000001426357011200142775ustar00rootroot00000000000000PG-4.5/etc/proviola/README000066400000000000000000000006611426357011200151620ustar00rootroot00000000000000Experimental work-in-progress on "Movie" output from annotated Proof General buffers. The XSL files here are due to Carst Tankink, copied from the Proviola project. See http://mws.cs.ru.nl/proviola and these papers: Carst Tankink, Herman Geuvers, James McKinna, Freek Wiedijk Proviola: a Tool for Proof Re-animation MKM 2010. Carst Tankink, Herman Geuvers and James McKinna. Narrating Formal Proof (Work in Progress) UITP 2010. PG-4.5/etc/proviola/movie-pp.rnc000066400000000000000000000006601426357011200165410ustar00rootroot00000000000000default namespace = "" start = element movie { element film { element frame { attribute frameNumber { xsd:integer }, element command { text }, element response { text }, element command-pp { part+ }, element response-pp { part* } }+ } } part = element part { attribute class { classname }, text } classname = "plain" | "comment" | "obligation" | "label" PG-4.5/etc/proviola/movie.rnc000066400000000000000000000003301426357011200161160ustar00rootroot00000000000000default namespace = "" start = element movie { element film { element frame { attribute frameNumber { xsd:integer }, element command { text }, element response { text } } }+ } PG-4.5/etc/proviola/proviola-pp.xsl000066400000000000000000000060331426357011200173010ustar00rootroot00000000000000
    
      
        
        mouseover(
          
        )
        
        
        
          
          
            
          
          
          
        
          
      
    
    
        
        
        
        
      
PG-4.5/etc/proviola/proviola-spp.xsl000066400000000000000000000070231426357011200174640ustar00rootroot00000000000000
    
      
        
        mouseover(
          
        )
        
        
          
	    
          
          
	
      
    
    
        
        
      
PG-4.5/etc/proviola/proviola.xsl000066400000000000000000000064551426357011200166740ustar00rootroot00000000000000
    
      
        
        mouseover(
          
        )
        
        
      
    
    
        
        
      
PG-4.5/etc/testsuite/000077500000000000000000000000001426357011200144755ustar00rootroot00000000000000PG-4.5/etc/testsuite/pg-pgip-test.el000066400000000000000000000016221426357011200173400ustar00rootroot00000000000000;;; Tests for pg-pgip.el ;; This file is part of Proof General. ;; Portions © Copyright 1994-2012 David Aspinall and University of Edinburgh ;; Portions © Copyright 2003, 2012, 2014 Free Software Foundation, Inc. ;; Portions © Copyright 2001-2017 Pierre Courtieu ;; Portions © Copyright 2010, 2016 Erik Martin-Dorel ;; Portions © Copyright 2011-2013, 2016-2017 Hendrik Tews ;; Portions © Copyright 2015-2017 Clément Pit-Claudel ;;; Commentary: ;; ;;; Code: (pg-clear-test-suite "pg-pgip") (pg-set-test-suite "pg-pgip") (pg-test-eval (pg-pgip-interpret-value "true" 'boolean) t) (pg-test-eval (pg-pgip-interpret-value "false" 'boolean) nil) (pg-test-eval (pg-pgip-interpret-value "27" 'integer) 27) (pg-test-eval (pg-pgip-interpret-value "true" (list 'choice 'boolean 'integer)) t) (pg-test-eval (pg-pgip-interpret-value "27" (list 'choice 'boolean 'integer)) 27) ;; End of `pg-pgip-test.el' PG-4.5/etc/testsuite/pg-test.el000066400000000000000000000071631426357011200164110ustar00rootroot00000000000000;;; pg-test.el --- Simple test framework for Proof General. ;; This file is part of Proof General. ;; Portions © Copyright 1994-2012 David Aspinall and University of Edinburgh ;; Portions © Copyright 2003-2018 Free Software Foundation, Inc. ;; Portions © Copyright 2001-2017 Pierre Courtieu ;; Portions © Copyright 2010, 2016 Erik Martin-Dorel ;; Portions © Copyright 2011-2013, 2016-2017 Hendrik Tews ;; Portions © Copyright 2015-2017 Clément Pit-Claudel ;;; Commentary: ;; ;;; Code: (eval-when-compile (require 'cl-lib)) (defconst pg-test-buffer "** PG test output **") (defvar pg-test-total-success-count 0) (defvar pg-test-total-fail-count 0) (defvar pg-test-suite-success-count 0) (defvar pg-test-suite-fail-count 0) ;; A test suite is a list of tests. (defvar pg-test-suite-table nil) (defvar pg-current-test-suite nil) (defun pg-set-test-suite (name) (setq pg-current-test-suite name) (unless (assoc name pg-test-suite-table) (setq pg-test-suite-table ;; Add an empty subtable (cons (cons name nil) pg-test-suite-table)))) (defun pg-clear-test-suite (name) (setq pg-test-suite-table (remassoc name pg-test-suite-table))) (defmacro pg-test-eval (expr result) "Add test (equal (eval EXPR) RESULT) to current test suite." (let* ((suite (assoc pg-current-test-suite pg-test-suite-table)) (testnum (length suite)) (name (concat pg-current-test-suite "." (int-to-string testnum)))) (setcdr suite (cons (list name 'eval expr result) (cdr suite))) ;; Result is number of this test in suite testnum)) (defun pg-execute-test (test) (let ((name (car test)) (type (cadr test))) (cond ((eq type 'eval) (let ((expr (nth 2 test)) (goodresult (nth 3 test)) result errorresult exn) (condition-case exn (setq result (eval expr)) ;; FIXME: add negative tests here, that exns _are_ raised. (t (setq errorresult (format " %s failed: error signalled: %s %s\n" name (car exn) (cdr exn))))) (or errorresult (unless (equal goodresult result) (setq errorresult (format " %s failed: exprected result %s, got %s\n" name goodresult result)))) (if errorresult (cl-incf pg-test-suite-fail-count) (cl-incf pg-test-suite-success-count) (setq errorresult (format " %s succeeded.\n" name))) ;; Return string errorresult)) ;; No other types at the moment (t (error "Eek! unrecognized test type.")) ))) (defun pg-execute-test-suite (name) (interactive (list (completing-read "Run test suite: " pg-test-suite-table))) (setq pg-test-suite-success-count 0) (setq pg-test-suite-fail-count 0) (save-excursion (set-buffer (get-buffer-create pg-test-buffer)) (insert "=================================================================\n") (insert "TEST SUITE: " name "\n") (insert "=================================================================\n") (apply 'insert (mapcar 'pg-execute-test (reverse (cdr-safe (assoc name pg-test-suite-table))))) (insert (format "\nTotal successful tests: %s, failed tests: %s\n\n" pg-test-suite-success-count pg-test-suite-fail-count))) (setq pg-test-total-success-count (+ pg-test-suite-success-count pg-test-total-success-count)) (setq pg-test-total-fail-count (+ pg-test-suite-fail-count pg-test-total-fail-count))) (defun pg-execute-all-tests () (interactive) (pop-to-buffer (get-buffer-create pg-test-buffer)) (erase-buffer) (sit-for 0) (setq pg-test-total-success-count 0) (setq pg-test-total-fail-count 0) (mapcar 'pg-execute-test-suite (mapcar 'car pg-test-suite-table))) ;; End of `pg-test.el' PG-4.5/etc/trac/000077500000000000000000000000001426357011200133755ustar00rootroot00000000000000PG-4.5/etc/trac/README000066400000000000000000000000721426357011200142540ustar00rootroot00000000000000Small tests for regressions. Indexed by trac bug number. PG-4.5/etc/trac/Trac140.v000066400000000000000000000011161426357011200147010ustar00rootroot00000000000000(* Follow example shows bad behaviour in low-level regexp matching for output font locking. See http://proofgeneral.inf.ed.ac.uk/trac/ticket/140. *) (* Note: the bad behaviour seems to be triggered when the pretty-printed output starts to print parameters on a separate line and then gets successively worse. p5 does this for me *) Module Type T. Parameter p1 : nat. Parameter p2 : nat. Parameter p3 : nat. Parameter p4 : nat. Parameter p5 : nat. (* Parameter p6 : nat. Parameter p7 : nat. Parameter p8 : nat. Parameter p9 : nat. *) End T. Time Print Module Type T. PG-4.5/etc/trac/Trac345.thy000066400000000000000000000001711426357011200152470ustar00rootroot00000000000000theory Trac345 imports Main begin (* "a comment" *) -- a comment (* "another comment that PG does not get to" *) end PG-4.5/etc/trac/trac-200.thy000066400000000000000000000004241426357011200153530ustar00rootroot00000000000000(* See trac #200 *) theory Trac200 imports Main begin (* Test simulating sledgehammer asynchronous output *) ML {* Thread.fork (fn () => (OS.Process.sleep (Time.fromSeconds 3); priority "urgent message"), []) *} (* Want to preserve correct term output *) term "x" end PG-4.5/etc/trac/trac-206.thy000066400000000000000000000005531426357011200153640ustar00rootroot00000000000000(* see trac #206 *) theory Trac206 imports Main begin (* The special markup (for terms etc.) is not processed in minibuffer messages. For example: *) ML_command {* warning (Syntax.string_of_typ @{context} @{typ 'a}) *} term "\ x. x" (* Here the decoration for 'a shows up as funny control characters, instead of proper font-lock colouring. *) end PG-4.5/etc/trac/trac-296.v000066400000000000000000000002631426357011200150340ustar00rootroot00000000000000(* PG accepts this as valid though it isn't; see http://proofgeneral.inf.ed.ac.uk/trac/ticket/296 *) Check nat.&!&*\:,.:<*&!)@)$. (* How should this one parse? *) Check 0.99. PG-4.5/etc/trac/trac-307.thy000066400000000000000000000004021426357011200153570ustar00rootroot00000000000000 theory trac307 imports Main begin lemma foo: "Suc x = Suc x" .. (* 2. Go to the simp-command that does not terminate 3. Perform the following actions: Undo, Interrupt, Undo, Next Sync is lost. *) lemma "P (Suc x)" apply (simp add: foo) end PG-4.5/etc/trac/trac-345.thy000066400000000000000000000001501426357011200153610ustar00rootroot00000000000000theory Scratch imports Main begin -- "a comment" ; -- "another comment that PG does not get to" end PG-4.5/etc/trac/trac-346.v000066400000000000000000000002631426357011200150300ustar00rootroot00000000000000Open Scope ... (* is not colorized at all, *) Reserved Notation ... (* has only "Notation" colorized, *) Set Implicit Arguments. (* has only "Set" colorized, in a wrong way. *) PG-4.5/etc/trac/trac109.v000066400000000000000000000001221426357011200147420ustar00rootroot00000000000000(* http://proofgeneral.inf.ed.ac.uk/trac/ticket/109 *) Goal True. idtac "Hello!". PG-4.5/generic/000077500000000000000000000000001426357011200133055ustar00rootroot00000000000000PG-4.5/generic/README000066400000000000000000000006111426357011200141630ustar00rootroot00000000000000Proof General The code in this directory implements the generic basis of Proof General. It was written by Thomas Kleymann, Dilip Sequeira, Healfdene Goguen, David Aspinall, and Markus Wenzel. Several other people helped with contributions and modifications, see individual credits in the code or summary in the Proof General manual. Contributions to the generic basis are welcome! $Id$ PG-4.5/generic/pg-assoc.el000066400000000000000000000047431426357011200153530ustar00rootroot00000000000000;;; pg-assoc.el --- Functions for associated buffers ;; This file is part of Proof General. ;; Portions © Copyright 1994-2012 David Aspinall and University of Edinburgh ;; Portions © Copyright 2003-2018 Free Software Foundation, Inc. ;; Portions © Copyright 2001-2017 Pierre Courtieu ;; Portions © Copyright 2010, 2016 Erik Martin-Dorel ;; Portions © Copyright 2011-2013, 2016-2017 Hendrik Tews ;; Portions © Copyright 2015-2017 Clément Pit-Claudel ;; Authors: David Aspinall, Yves Bertot, Healfdene Goguen, ;; Thomas Kleymann and Dilip Sequeira ;; SPDX-License-Identifier: GPL-3.0-or-later ;;; Commentary: ;; ;; Defines an empty mode inherited by modes of the associated buffers. ;; ;;; Code: (require 'cl-lib) ;cl-remove-if-not (require 'proof-utils) (define-derived-mode proof-universal-keys-only-mode fundamental-mode proof-general-name "Universal keymaps only" ;; Doesn't seem to supress TAB, RET (suppress-keymap proof-universal-keys-only-mode-map 'all) (proof-define-keys proof-universal-keys-only-mode-map proof-universal-keys)) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Return a list of associated buffers ;; ;;;###autoload (defun proof-associated-buffers () "Return a list of the associated buffers. Some may be dead/nil." (list proof-goals-buffer proof-response-buffer proof-trace-buffer proof-thms-buffer)) ;;;###autoload (defun proof-associated-windows (&optional all-frames) "Return a list of the associated buffers windows. Dead or nil buffers are not represented in the list. Optional argument ALL-FRAMES has the same meaning than for `get-buffer-window'." (let ((bufs (proof-associated-buffers)) buf wins) (while bufs (setq buf (car bufs)) (if (and buf (get-buffer-window-list buf nil all-frames)) (setq wins (append (get-buffer-window-list buf nil all-frames) wins))) (setq bufs (cdr bufs))) wins)) (defun proof-associated-buffer-p (b) (member b (proof-associated-buffers))) (defun proof-filter-associated-windows (lw) "Remove windows of LW not displaying at least one associated buffer." (cl-remove-if-not (lambda (w) (proof-associated-buffer-p (window-buffer w))) lw)) ;;;###autoload (defun proof-associated-frames () "Return the list of frames displaying at least one associated buffer." (cl-remove-if-not (lambda (f) (proof-filter-associated-windows (window-list f))) (frame-list))) (provide 'pg-assoc) ;;; pg-assoc.el ends here PG-4.5/generic/pg-autotest.el000066400000000000000000000221361426357011200161070ustar00rootroot00000000000000;;; pg-autotest.el --- Simple testing framework for Proof General ;; This file is part of Proof General. ;; Portions © Copyright 1994-2012 David Aspinall and University of Edinburgh ;; Portions © Copyright 2003-2018 Free Software Foundation, Inc. ;; Portions © Copyright 2001-2017 Pierre Courtieu ;; Portions © Copyright 2010, 2016 Erik Martin-Dorel ;; Portions © Copyright 2011-2013, 2016-2017 Hendrik Tews ;; Portions © Copyright 2015-2017 Clément Pit-Claudel ;; Authors: David Aspinall ;; SPDX-License-Identifier: GPL-3.0-or-later ;;; Commentary: ;; ;; Support for running a series of scripted UI tests. ;; ;; TODO: ;; -- fix failure handling for scriptfile ;; -- add macros for defining test suites ;; -- add more precise functional tests to check results ;; -- add negative tests ;;; Code: (eval-when-compile (require 'cl-lib)) (require 'proof-splash) (setq proof-splash-enable nil) ; prevent splash when testing (require 'proof) (require 'proof-shell) (require 'proof-utils) ;;; Code: (defvar pg-autotest-success t "Flag indicating overall successful state of tests.") (defvar pg-autotest-log t "Value for 'standard-output' during tests.") ;;; Some utilities (defun pg-autotest-find-file (file) "Find FILE (relative to `proof-home-directory')." (let* ((name (expand-file-name file proof-home-directory))) (if (file-exists-p name) (find-file name) (error (format "autotest: requested file %s does not exist" name))))) (defun pg-autotest-find-file-restart (file) "Find FILE and make ready to script there." ;; Ensure scripting off; if completely full, will register, otherwise retract (proof-deactivate-scripting-auto) (pg-autotest-find-file file) (goto-char (point-min)) (unless (proof-locked-region-empty-p) ;; Should retract and unregister if was completely full (proof-goto-point)) (proof-shell-wait) (pg-autotest-test-assert-unprocessed file)) ;;; Invoke a test (defmacro pg-autotest-apply (fn &rest args) `(let ((scaffoldfn (intern (concat "pg-autotest-" (symbol-name (quote ,fn)))))) (if (fboundp scaffoldfn) (apply scaffoldfn (list ,@args)) (pg-autotest-message "TEST: %s" (prin1-to-string (cons (quote ,fn) (quote ,args)))) (apply (intern (concat "pg-autotest-test-" (symbol-name (quote ,fn)))) (list ,@args))))) (defmacro pg-autotest (fn &rest args) `(if debug-on-error (pg-autotest-apply ,fn ,@args) (unwind-protect (progn (setq standard-output pg-autotest-log) (condition-case err (pg-autotest-apply ,fn ,@args) (error (progn (setq pg-autotest-success nil) (pg-autotest-message "ERROR %s: %s" (quote ,fn) (prin1-to-string err)))))) (setq standard-output t)))) ;;; Test output and timing (defun pg-autotest-log (file) (save-excursion (find-file file) (setq buffer-save-without-query t) (erase-buffer) (setq pg-autotest-log (current-buffer)) (pg-autotest-message (concat "Tests started " (format-time-string "%D %H:%M"))))) (defun pg-autotest-message (msg &rest args) "Give message MSG (formatted using ARGS) in log file output and on display." (let ((fmsg (if args (apply 'format msg args) msg))) (proof-with-current-buffer-if-exists pg-autotest-log (insert fmsg "\n")) (message "%s" fmsg) (redisplay t))) (defun pg-autotest-remark (msg) (pg-autotest-message "\n\nREMARK: %s\n" msg)) (defun pg-autotest-timestart (&optional clockname) "Make a note of current time, named 'local or CLOCKNAME." (put 'pg-autotest-time (or clockname 'local) (current-time))) (defun pg-autotest-timetaken (&optional clockname) "Report time since (startclock CLOCKNAME)." (let* ((timestart (get 'pg-autotest-time (or clockname 'local))) (timetaken (time-subtract (current-time) timestart))) (pg-autotest-message "TIME: %f (%s)" (float-time timetaken) (if clockname (symbol-name clockname) "this test")))) ;;; Start up and exit (defun pg-autotest-start (&optional debug) "Start a session of tests. DEBUG indicates to capture debug output." (when debug (setq debug-on-error t) ; enable in case a test goes wrong (setq proof-general-debug t) ; debug messages from PG (defadvice proof-debug (before proof-debug-to-log (msg &rest args)) "Output the debug message to the test log." (apply 'pg-autotest-message msg args)) (ad-activate 'proof-debug))) (defun pg-autotest-exit () "Exit Emacs returning Unix success 0 if all tests succeeded." (pg-autotest-message (concat "\nTests completed " (format-time-string "%D %H:%M"))) (proof-with-current-buffer-if-exists pg-autotest-log (goto-char (point-max)) (insert "\n\nContents of *Messages*:\n\n") (with-current-buffer (get-buffer "*Messages*") (append-to-buffer pg-autotest-log (point-min) (point-max))) (goto-char (point-max)) (when (get-buffer "*PG Debug*") (insert "\n\nContents of *PG Debug*:\n\n") (proof-with-current-buffer-if-exists (get-buffer "*PG Debug*")) (append-to-buffer pg-autotest-log (point-min) (point-max))) (save-buffer 0)) (kill-emacs (if pg-autotest-success 0 1))) ;;; The test script functions proper (defun pg-autotest-test-process-wholefile (file) "Load FILE and script in one go. An error is signalled if scripting doesn't completely the whole buffer." (pg-autotest-find-file-restart file) (proof-process-buffer) (proof-shell-wait) (pg-autotest-test-assert-processed file)) (defun pg-autotest-test-script-wholefile (file) "Process FILE line-by-line, using `proof-shell-wait'. An error is signalled if scripting doesn't complete." (pg-autotest-find-file-restart file) (save-excursion (let ((making-progress t) last-locked-end) (while making-progress (setq last-locked-end (proof-unprocessed-begin)) (goto-char last-locked-end) (save-current-buffer (condition-case err (proof-assert-next-command-interactive) (error (let ((msg (car-safe (cdr-safe err)))) (unless (string-equal msg ;; normal user error message at end of buffer "At end of the locked region, nothing to do to!") (pg-autotest-message "proof-assert-next-command-interactive hit an error: %s" msg))))) (proof-shell-wait)) (goto-char (proof-queue-or-locked-end)) (setq making-progress (> (point) last-locked-end))))) (pg-autotest-test-assert-processed file)) (defun pg-autotest-test-script-randomjumps (file jumps) "Load FILE and process in it by jumping around randomly JUMPS times. This should be robust against synchronization errors; we test this by completely processing the buffer as the last step." ;; TODO: Additionally some edits are made but undone. (pg-autotest-find-file-restart file) (while (> jumps 0) (let* ((random-point (random (point-max))) (random-edit nil) ; (< 20 (random 100))) (random-thing (random 10))) (cond ((and (eq random-thing 0) (not (proof-locked-region-full-p))) (pg-autotest-message " random jump: processing whole buffer") (proof-process-buffer) (proof-shell-wait) (cl-decf jumps)) ((and (eq random-thing 1) (not (proof-locked-region-empty-p))) (pg-autotest-message " random jump: retracting whole buffer") (proof-retract-buffer) (proof-shell-wait) (cl-decf jumps)) (t (pg-autotest-message " random jump: going to point: %d" random-point)) (goto-char random-point) (unless (if (>= (point) (proof-unprocessed-begin)) (proof-only-whitespace-to-locked-region-p)) (proof-goto-point) (if (eq random-thing 2) (progn ;; interrupt after 2 secs (sit-for 1) (sit-for 1) (when proof-shell-busy (pg-autotest-message " random jump: interrupting prover") (proof-interrupt-process))) (proof-shell-wait)) (cl-decf jumps))))) (unless (proof-locked-region-full-p) (proof-process-buffer) (proof-shell-wait)) (pg-autotest-test-assert-processed file)) (defun pg-autotest-test-retract-file (file) (save-excursion (pg-autotest-find-file file) (proof-retract-buffer) (sit-for 1))) (defun pg-autotest-test-assert-processed (file) "Check that FILE has been fully processed." (save-excursion ;; TODO: also check on included files list (pg-autotest-find-file file) (pg-autotest-test-assert-full))) (defun pg-autotest-test-assert-full () "Check that current buffer has been fully processed." (proof-shell-wait) (unless (proof-locked-region-full-p) (error (format "Locked region in buffer `%s' is not full" (buffer-name))))) (defun pg-autotest-test-assert-unprocessed (file) "Check that FILE has been fully unprocessed." (save-excursion (pg-autotest-find-file file) (unless (proof-locked-region-empty-p) (error (format "Locked region in file `%s' is not empty" file))))) (defun pg-autotest-test-eval (body) "Evaluate given expression for side effect." (eval body)) (defun pg-autotest-test-quit-prover () "Exit prover process." (if (buffer-live-p proof-shell-buffer) (let ((kill-buffer-query-functions nil)) (kill-buffer proof-shell-buffer)) (error "No proof shell buffer to kill"))) (provide 'pg-autotest) ;;; pg-autotest.el ends here PG-4.5/generic/pg-custom.el000066400000000000000000000200071426357011200155440ustar00rootroot00000000000000;;; pg-custom.el --- Proof General per-prover settings ;; This file is part of Proof General. ;; Portions © Copyright 1994-2012 David Aspinall and University of Edinburgh ;; Portions © Copyright 2003, 2012, 2014, 2021 Free Software Foundation, Inc. ;; Portions © Copyright 2001-2017 Pierre Courtieu ;; Portions © Copyright 2010, 2016 Erik Martin-Dorel ;; Portions © Copyright 2011-2013, 2016-2017 Hendrik Tews ;; Portions © Copyright 2015-2017 Clément Pit-Claudel ;; Author: David Aspinall and others ;; SPDX-License-Identifier: GPL-3.0-or-later ;;; Commentary: ;; ;; Prover specific settings and user options. ;; ;; The settings defined here automatically use the current proof ;; assistant symbol as a prefix, i.e. coq-favourites, ;; or whatever will be defined on evaluation. ;; ;; This file is loaded only by mode stubs defined in `proof-site.el', ;; immediately after `proof-assistant' and similar settings have been ;; configured. ;; ;; WARNING: loading this file without these variables being set will ;; give errors, because defpgcustom calls are expanded to top-level ;; forms that refer to `proof-assistant', which is only properly set ;; when the mode for a proof assistant is started (see mode stub). ;; ;; See also: ;; ;; proof-useropts.el ;; pg-vars.el ;;; Code: (require 'pg-pamacs) ; defpgcustom (require 'pg-vars) ; for proof-next-command-on-new-line (require 'proof-config) ; for proof-toolbar-entries-default (defpgcustom script-indent t "*If non-nil, enable indentation code for proof scripts." :type 'boolean :group 'proof-user-options) (defconst proof-toolbar-entries-default `((state "Display Proof State" "Display the current proof state" t proof-showproof-command) (context "Display Context" "Display the current context" t proof-context-command) (goal "Start a New Proof" "Start a new proof" t nil) (retract "Retract Buffer" "Retract (undo) whole buffer" t t) (undo "Undo Step" "Undo the previous proof command" t t) (delete "Delete Step" "Delete the last proof command" nil t) (next "Next Step" "Process the next proof command" t t) (use "Use Buffer" "Process whole buffer" t t) (goto "Goto Point" "Process or undo to the cursor position" t t) (qed "Finish Proof" "Close/save proved theorem" t nil) (home "Goto Locked End" "Goto end of the last command processed" t t) (find "Find Theorems" "Find theorems" t proof-find-theorems-command) (info "Identifier Info" "Information about identifier" t proof-query-identifier-command) (command "Issue Command" "Issue a non-scripting command" t t) (prooftree "Start/Stop Prooftree" "Start/Stop external proof-tree display" t proof-tree-configured) (interrupt "Interrupt Prover" "Interrupt the proof assistant" t t) (restart "Restart Scripting" "Restart scripting (clear all locked regions)" t t) (visibility "Toggle Visibility" "Show or hide hidden proofs" nil t) (help nil "Proof General manual" t t)) "Example value for proof-toolbar-entries. Also used to define scripting menu. This gives a bare toolbar that works for any prover, providing the appropriate configuration variables are set. To add/remove prover specific buttons, adjust the `-toolbar-entries' variable, and follow the pattern in `proof-toolbar.el' for defining functions, images.") (defpgcustom toolbar-entries proof-toolbar-entries-default "List of entries for Proof General toolbar and Scripting menu. Format of each entry is (TOKEN MENUNAME TOOLTIP TOOLBAR-P [VISIBLE-P]). For each TOKEN, we expect an icon with base filename TOKEN, a function proof-toolbar-, and (optionally) a dynamic enabler proof-toolbar--enable-p. If VISIBLE-P is absent, or evaluates to non-nil, the item will appear on the toolbar or menu. If it evaluates to nil, the item is not shown. If MENUNAME is nil, item will not appear on the scripting menu. If TOOLBAR-P is nil, item will not appear on the toolbar. The default value is `proof-toolbar-entries-default' which contains the standard Proof General buttons.") (defpgcustom prog-args nil "Arguments to be passed to `proof-prog-name' to run the proof assistant. If non-nil, will be treated as a list of arguments for `proof-prog-name'. Otherwise `proof-prog-name' will be split on spaces to form arguments. Remark: Arguments are interpreted strictly: each one must contain only one word, with no space (unless it is the same word). For example if the arguments are -x foo -y bar, then the list should be '(\"-x\" \"foo\" \"-y\" \"bar\"), notice that '(\"-x foo\" \"-y bar\") is *wrong*." :type '(repeat string) :group 'proof-shell) (defpgcustom prog-env nil "Modifications to `process-environment' made before running `proof-prog-name'. Each element should be a string of the form ENVVARNAME=VALUE. They will be added to the environment before launching the prover (but not pervasively). For example for coq on Windows you might need something like: \(setq coq-prog-env '(\"HOME=C:\\Program Files\\Coq\\\"))" :type '(repeat string) :group 'proof-shell) (defpgcustom quit-timeout (cond ;; ((eq proof-assistant-symbol 'isar) 45) (t 5)) "The number of seconds to wait after sending `proof-shell-quit-cmd'. After this timeout, the proof shell will be killed off more rudely. If your proof assistant takes a long time to clean up (for example writing persistent databases out or the like), you may need to bump up this value." :type 'number :group 'proof-shell) (defpgcustom favourites nil "*Favourite commands for this proof assistant. A list of lists of the form (COMMAND INSCRIPT MENUNAME KEY), arguments for `proof-add-favourite', which see.") (defpgcustom menu-entries nil "Extra entries for proof assistant specific menu. A list of menu items [NAME CALLBACK ENABLER ...]. See the documentation of `easy-menu-define' for more details." :type 'sexp :group 'prover-config) (defpgcustom help-menu-entries nil "Extra entries for help submenu for proof assistant specific help menu. A list of menu items [NAME CALLBACK ENABLER ...]. See the documentation of `easy-menu-define' for more details." :type 'sexp :group 'prover-config) (defpgcustom keymap (make-keymap (concat proof-assistant " keymap")) "Proof assistant specific keymap, used under prefix C-c a." :type 'sexp :group 'prover-config) (defpgcustom completion-table nil "List of identifiers to use for completion for this proof assistant. Completion is activated with \\[complete]. If this table is empty or needs adjusting, please make changes using `customize-variable' and post suggestions at https://github.com/ProofGeneral/PG/issues" :type '(repeat string) :group 'prover-config) ;; TODO: not used yet. (defpgcustom tags-program nil "Program to run to generate TAGS table for proof assistant. Currently this setting is UNIMPLEMENTED, changes have no effect." :type 'file :group 'prover-config) ;; TODO: not used yet. Want to move specific enabling of holes modes ;; to generic code (coq.el enables it in script and shell). ;; See http://proofgeneral.inf.ed.ac.uk/trac/ticket/211 (defpgcustom use-holes (eq proof-assistant-symbol 'coq) "Whether or not to use the holes (editing template) mechanism. Enabled by default for Coq. Currently this setting is UNIMPLEMENTED, changes have no effect." :type 'boolean :group 'prover-config) (defpgcustom one-command-per-line (cond ;; ((eq proof-assistant-symbol 'isar) nil) (t t)) "*If non-nil, format for newlines after each command in a script." :type 'boolean :group 'proof-user-options) ;; Contributed modes (defpgcustom maths-menu-enable nil "*Non-nil for Unicode maths menu in Proof General for this assistant." :type 'boolean :set 'proof-set-value :group 'proof-user-options) (defpgcustom unicode-tokens-enable nil ;; (eq proof-assistant-symbol 'isar) "*Non-nil for using Unicode token input mode in Proof General." :type 'boolean :set 'proof-set-value :group 'proof-user-options) (provide 'pg-custom) ;;; pg-custom.el ends here PG-4.5/generic/pg-goals.el000077500000000000000000000112031426357011200153400ustar00rootroot00000000000000;;; pg-goals.el --- Proof General goals buffer mode. ;; This file is part of Proof General. ;; Portions © Copyright 1994-2012 David Aspinall and University of Edinburgh ;; Portions © Copyright 2003-2019 Free Software Foundation, Inc. ;; Portions © Copyright 2001-2017 Pierre Courtieu ;; Portions © Copyright 2010, 2016 Erik Martin-Dorel ;; Portions © Copyright 2011-2013, 2016-2017 Hendrik Tews ;; Portions © Copyright 2015-2017 Clément Pit-Claudel ;; Authors: David Aspinall, Yves Bertot, Healfdene Goguen, ;; Thomas Kleymann and Dilip Sequeira ;; SPDX-License-Identifier: GPL-3.0-or-later ;;; Commentary: ;;; Code: (eval-when-compile (require 'easymenu) ; easy-menu-add, etc (require 'span)) ; span-* (require 'proof-script) ;For proof-insert-sendback-command (defvar proof-goals-mode-menu) ; defined by macro below (defvar proof-assistant-menu) ; defined by macro in proof-menu (require 'pg-assoc) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Goals buffer mode ;; ;;;###autload (define-derived-mode proof-goals-mode proof-universal-keys-only-mode proof-general-name "Mode for goals display. May enable proof-by-pointing or similar features. \\{proof-goals-mode-map}" (setq proof-buffer-type 'goals) (add-hook 'kill-buffer-hook 'pg-save-from-death nil t) (easy-menu-add proof-goals-mode-menu proof-goals-mode-map) (easy-menu-add proof-assistant-menu proof-goals-mode-map) (proof-toolbar-setup) (buffer-disable-undo) (if proof-keep-response-history (bufhist-mode)) ; history for contents (set-buffer-modified-p nil) (setq cursor-in-non-selected-windows nil)) ;; ;; Menu for goals buffer ;; (proof-eval-when-ready-for-assistant ; proof-aux-menu depends on (easy-menu-define proof-goals-mode-menu proof-goals-mode-map "Menu for Proof General goals buffer." (proof-aux-menu))) ;; ;; Keys for goals buffer ;; (define-key proof-goals-mode-map [q] 'bury-buffer) ;; TODO: use standard Emacs button behaviour here (cf Info mode) (define-key proof-goals-mode-map [mouse-1] 'pg-goals-button-action) (define-key proof-goals-mode-map [C-M-mouse-3] 'proof-undo-and-delete-last-successful-command) ;; ;; The completion of init ;; ;;;###autoload (defun proof-goals-config-done () "Initialise the goals buffer after the child has been configured." (setq font-lock-defaults '(proof-goals-font-lock-keywords))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Goals buffer processing ;; (defun pg-goals-display (string keepresponse) "Display STRING in the `proof-goals-buffer', properly marked up. Converts term substructure markup into mouse-highlighted extents. The response buffer may be cleared to avoid confusing the user with output associated with a previous goals message. This function tries to do that by calling `pg-response-maybe-erase'. If KEEPRESPONSE is non-nil, we assume that a response message corresponding to this goals message has already been displayed before this goals message (see `proof-shell-handle-delayed-output'), so the response buffer should not be cleared." ;; Response buffer may be out of date. It may contain (error) ;; messages relating to earlier proof states ;; Erase the response buffer if need be, maybe removing the ;; window. Indicate it should be erased before the next output. (pg-response-maybe-erase t t nil keepresponse) ;; Erase the goals buffer and add in the new string (with-current-buffer proof-goals-buffer (setq buffer-read-only nil) (unless (eq 0 (buffer-size)) (bufhist-checkpoint-and-erase)) ;; Only display if string is non-empty. (unless (string-equal string "") (funcall pg-insert-text-function string)) (setq buffer-read-only t) (set-buffer-modified-p nil) ;; Keep point at the start of the buffer. (proof-display-and-keep-buffer proof-goals-buffer (point-min)))) ;; ;; Actions in the goals buffer ;; (defun pg-goals-button-action (event) "Construct a command based on the mouse-click EVENT." (interactive "e") (let* ((posn (event-start event)) (pos (posn-point posn)) (buf (window-buffer (posn-window posn))) (props (text-properties-at pos buf)) (sendback (plist-get props 'sendback))) (cond (sendback (with-current-buffer buf (let* ((cmdstart (previous-single-property-change pos 'sendback nil (point-min))) (cmdend (next-single-property-change pos 'sendback nil (point-max))) (cmd (buffer-substring-no-properties cmdstart cmdend))) (proof-insert-sendback-command cmd))))))) (provide 'pg-goals) ;;; pg-goals.el ends here PG-4.5/generic/pg-movie.el000066400000000000000000000102561426357011200153560ustar00rootroot00000000000000;;; pg-movie.el --- Export a processed script buffer for external replay ;; This file is part of Proof General. ;; Portions © Copyright 1994-2012 David Aspinall and University of Edinburgh ;; Portions © Copyright 2003-2018 Free Software Foundation, Inc. ;; Portions © Copyright 2001-2017 Pierre Courtieu ;; Portions © Copyright 2010, 2016 Erik Martin-Dorel ;; Portions © Copyright 2011-2013, 2016-2017 Hendrik Tews ;; Portions © Copyright 2015-2017 Clément Pit-Claudel ;; Author: David Aspinall and others ;; SPDX-License-Identifier: GPL-3.0-or-later ;;; Commentary: ;; ;; Given a processed proof script, write out an XML file that ;; contains the buffer contents and the contents of prover ;; output attached to spans. ;; ;; See etc/proviola and http://mws.cs.ru.nl/proviola/ ;; ;; Much more could be done to dump the prettified output from the ;; prover, but this is probably not the right way of doing things in ;; general (one would rather have prover-integrated batch tools). ;; ;; It does give quick and easy results for provers already supported by ;; Proof General though! ;; ;;; Code: (eval-when-compile (require 'cl-lib)) (eval-when-compile (require 'span) (require 'unicode-tokens)) (require 'pg-xml) (defconst pg-movie-xml-header "") (defconst pg-movie-stylesheet "") (defun pg-movie-stylesheet-location () (expand-file-name "etc/proviola/proviola-spp.xsl" proof-home-directory)) (defvar pg-movie-frame 0 "Frame counter for movie.") (defun pg-movie-of-span (span) "Render annotated SPAN in XML." (let* ((tokens (proof-ass unicode-tokens-enable)) (cmd (buffer-substring-no-properties (span-start span) (span-end span))) (tcmd (if tokens ;; no subscripts of course (unicode-tokens-encode-str cmd) cmd)) (helpspan (span-property span 'pg-helpspan)) (resp (when helpspan (span-property helpspan 'response))) (tresp (if resp (if tokens (unicode-tokens-encode-str resp) resp) "")) (type (span-property span 'type)) (class (cond ((eq type 'comment) "comment") ((eq type 'proof) "lemma") ((eq type 'goalsave) "lemma") (t "command"))) (label (span-property span 'rawname)) (frameid (int-to-string pg-movie-frame))) (cl-incf pg-movie-frame) (pg-xml-node frame (list (pg-xml-attr frameNumber frameid)) (list (pg-xml-node command (append (list (pg-xml-attr class class)) (if label (list (pg-xml-attr label label)))) (list tcmd)) (pg-xml-node response nil (list tresp)))))) (defun pg-movie-of-region (start end) (list (pg-xml-node movie nil (list (pg-xml-node film nil (span-mapcar-spans-inorder 'pg-movie-of-span start end 'type)))))) ;;;###autoload (defun pg-movie-export (&optional force) "Export the movie file from the current script buffer. If FORCE, overwrite existing file without asking." (interactive "DP") (setq pg-movie-frame 0) (let ((movie (pg-movie-of-region (point-min) (point-max))) (movie-file-name (concat (file-name-sans-extension (buffer-file-name)) ".xml"))) (with-current-buffer (get-buffer-create "*pg-movie*") (erase-buffer) (insert pg-movie-xml-header "\n") (insert pg-movie-stylesheet "\n") (xml-print movie) (write-file movie-file-name (not force))))) ;;;###autoload (defun pg-movie-export-from (script &optional force) "Export the movie file that results from processing SCRIPT." (interactive "fFile: P") (let ((proof-full-annotation t) ; dynamic (proof-fast-process-buffer t)) (find-file script) (proof-process-buffer) (pg-movie-export force))) ;;;###autoload (defun pg-movie-export-directory (dir extn) "Export movie files from directory DIR with extension EXTN. Existing XML files are overwritten." (interactive "DDirectory: sFile extension: ") (let ((files (directory-files dir t (concat "\\." extn "$")))) (dolist (f files) (pg-movie-export-from f 'force)) (copy-file (pg-movie-stylesheet-location) dir 'overwrite))) (provide 'pg-movie) ;;; pg-movie.el ends here PG-4.5/generic/pg-pamacs.el000066400000000000000000000240561426357011200155060ustar00rootroot00000000000000;;; pg-pamacs.el --- Macros for per-proof assistant configuration -*- lexical-binding: t; -*- ;; This file is part of Proof General. ;; Portions © Copyright 1994-2012 David Aspinall and University of Edinburgh ;; Portions © Copyright 2003-2021 Free Software Foundation, Inc. ;; Portions © Copyright 2001-2017 Pierre Courtieu ;; Portions © Copyright 2010, 2016 Erik Martin-Dorel ;; Portions © Copyright 2011-2013, 2016-2017 Hendrik Tews ;; Portions © Copyright 2015-2017 Clément Pit-Claudel ;; Author: David Aspinall ;; Keywords: internal ;;; Commentary: ;; ;; Macros for defining per-assistant customization settings. ;; ;; This mechanism is an improved way to handle per-assistant settings. ;; Instead of declaring a variable "proof-assistant-web-page" and ;; duplicating it in the prover specific code to make the generic ;; setting, we automatically declare "isabelle-web-page", ;; "coq-web-page", etc, using these macros. ;; ;; The advantage of this is that people's save settings will work ;; properly, and that it will become more possible to use more than ;; one instance of PG at a time. The disadvantage is that it is more ;; complicated, and less "object-oriented" than the previous approach. ;; ;; There are two mechanisms for accessing generic vars: ;; ;; (proof-ass name) or (proof-assistant-name) ;; ;;; Code: (require 'proof-site) ; proof-assitant-symbol (require 'proof-compat) ; pg-custom-undeclare-variable (require 'proof-autoloads) ; proof-debug (defmacro deflocal (var value &optional doc) "Define a buffer local variable VAR with default value VALUE and docstring DOC." `(progn (defvar ,var nil ,doc) (make-variable-buffer-local (quote ,var)) (setq-default ,var ,value))) (deflocal proof-buffer-type nil "Symbol for the type of this buffer: 'script, 'shell, 'goals, or 'response.") ;; ;; Main macros ;; (defmacro proof-ass-sym (sym) "Return the symbol for SYM for the current prover. SYM not evaluated. This macro should only be called once a specific prover is known." `(intern (concat (symbol-name proof-assistant-symbol) "-" (symbol-name ',sym)))) (defmacro proof-ass-symv (sym) "Return the symbol for SYM for the current prover. SYM evaluated. This macro should only be invoked once a specific prover is engaged." `(intern (concat (symbol-name proof-assistant-symbol) "-" (symbol-name ,sym)))) (defmacro proof-ass (sym) "Return the value for SYM for the current prover. This macro should only be invoked once a specific prover is engaged." `(symbol-value (intern (concat (symbol-name proof-assistant-symbol) "-" (symbol-name ',sym))))) (defun proof-ass-differs-from-default (sym) "Return non-nil if SYM for current prover differs from its customize standard value." (let ((pasym (proof-ass-symv sym))) (not (equal (eval (car (get pasym 'standard-value)) t) (symbol-value pasym))))) (defun proof-defpgcustom-fn (sym args) "Define a new customization variable -SYM for current proof assistant. Helper for macro `defpgcustom'." (let ((specific-var (proof-ass-symv sym)) (generic-var (intern (concat "proof-assistant-" (symbol-name sym)))) ;; (newargs (if (member :group args) ;; args ;; (append (list :group ;; proof-assistant-internals-cusgrp) ;; args))) ) (eval `(defcustom ,specific-var ,@args) t) ;; For functions, we could simply use defalias. Unfortunately there ;; is nothing similar for values, so we define a new set/get function. (eval `(defun ,generic-var (&optional newval) ,(concat "Set or get value of " (symbol-name sym) " for current proof assistant. If NEWVAL is present, set the variable, otherwise return its current value.") (if newval (setq ,specific-var newval) ,specific-var)) t))) (defun undefpgcustom (sym) (let ((specific-var (proof-ass-symv sym)) (generic-var (intern (concat "proof-assistant-" (symbol-name sym))))) (pg-custom-undeclare-variable specific-var) (fmakunbound generic-var))) (defmacro defpgcustom (sym &rest args) "Define a new customization variable -SYM for the current proof assistant. This is intended for defining settings which are useful for any prover, but which the user may require different values of across provers. The function proof-assistant- is also defined, which can be used in the generic portion of Proof General to access the value for the current prover. Arguments ARGS are as for `defcustom', which see. If a :group argument is not supplied, the setting will be added to the internal settings for the current prover (named -config)." `(proof-defpgcustom-fn (quote ,sym) (quote ,args))) (defun proof-defpgdefault-fn (sym value) "Helper for `defpgdefault', which see. SYM and VALUE are evaluated." ;; NB: we need this because nothing in customize library seems to do ;; the right thing. (let ((symbol (proof-ass-symv sym))) (set-default symbol (cond ;; Use saved value if it's set ((get symbol 'saved-value) (car (get symbol 'saved-value))) ;; Otherwise override old default with new one (t value))))) (defmacro defpgdefault (sym value) "Set default for the proof assistant specific variable -SYM to VALUE. This should be used in prover-specific code to alter the default values for prover specific settings. Usage: (defpgdefault SYM VALUE)" `(proof-defpgdefault-fn (quote ,sym) ,value)) ;; ;; Make a function named for the current proof assistant. ;; (defmacro defpgfun (name arglist &rest args) "Define function -SYM as for defun." `(defun ,(proof-ass-symv name) ,arglist ,@args)) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Prover-assistant specific customizations ;; which are recorded in `proof-assistant-settings' ;; ;;; autoload for compiled version: used in macro proof-defpacustom ;;;###autoload (defun proof-defpacustom-fn (name val args) "As for macro `defpacustom' but evaluating arguments." (unless (and proof-assistant (not (string= proof-assistant ""))) (error "No proof assistant defined")) (let (newargs setting evalform type descr) (while args (cond ((eq (car args) :setting) (setq setting (cadr args)) (setq args (cdr args))) ((eq (car args) :eval) (setq evalform (cadr args)) (setq args (cdr args))) ((eq (car args) :pgipcmd) ;; Construct a function which yields a PGIP string (setq setting `(lambda (x) (pg-pgip-string-of-command (proof-assistant-format ,(cadr args) x)))) (setq args (cdr args))) ((eq (car args) :pggroup) ;; use the group as a prefix to the name, and set a pggroup property on it (setq name (intern (concat (downcase (cadr args)) ":" (symbol-name name)))) (put name 'pggroup (cadr args)) (setq args (cdr args))) ((eq (car args) :pgdynamic) (put name 'pgdynamic (cadr args)) (setq args (cdr args))) ((eq (car args) :type) (setq type (cadr args)) (if (eq (eval type t) 'float) (setq type (quote 'number))) ; widget type for defcustom (setq args (cdr args)) (setq newargs (cons type (cons :type newargs)))) (t ; first element, description (setq newargs (cons (car args) newargs)))) (setq args (cdr args))) (setq newargs (reverse newargs)) (setq descr (car-safe newargs)) (unless (and type (memq (eval type t) '(boolean integer number string))) (error "Macro defpacustom: missing :type keyword or wrong :type value")) ;; Error in case a defpacustom is repeated. (when (assq name proof-assistant-settings) (error "Macro defpacustom: Proof assistant setting %s re-defined!" name)) (eval `(defpgcustom ,name ,val ,@newargs :set #'proof-set-value :group (quote ,proof-assistant-cusgrp)) t) (cond (evalform (eval `(defpgfun ,name () ,evalform) t)) (setting (eval `(defpgfun ,name () (proof-assistant-invisible-command-ifposs (proof-assistant-settings-cmd (quote ,name)))) t))) (push (list name setting (eval type t) descr) proof-assistant-settings))) ;;;###autoload (defmacro defpacustom (name val &rest args) "Define a setting NAME for the current proof assistant, default VAL. Mainly intended for configuring settings of running provers, which can be changed by sending commands. In this case, NAME stands for the internal setting, flag, etc, for the proof assistant, and a :setting and :type value should be provided. The :type of NAME should be one of 'integer, 'float, 'boolean, 'string. Other types are not supported (see `proof-menu-entry-for-setting'). They will yield an error when constructing the proof assistant menu. The function `proof-assistant-format' is used to format VAL. This macro invokes the standard Emacs `defcustom' macro, so this also defines a customizable setting inside Emacs. The customization variable is automatically put into the group named after the prover. If NAME corresponds instead to a PG internal setting, then a form :eval to evaluate can be provided instead. Additional properties in the ARGS prop list may include: pggroup string A grouping name for the setting, in case there are many. For example, \"Timing\", \"Tracing\", etc. Used to generate sub-menus in the UI. pgipgcmd string Alternative to :setting. Send a PGIP formatted command based on given string. pgdynamic flag If flag is non-nil, this setting is a dynamic one that is particular to the running instance of the prover. Automatically set by preferences configured from PGIP askprefs message. This macro also extends the `proof-assistant-settings' list." `(proof-defpacustom-fn (quote ,name) (quote ,val) (quote ,args))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Evaluation once proof assistant is known ;; (defmacro proof-eval-when-ready-for-assistant (&rest body) "Evaluate BODY once the proof assistant is determined (possibly now)." `(if (and (boundp 'proof-assistant-symbol) proof-assistant-symbol) (progn ,@body) (add-hook 'proof-ready-for-assistant-hook (lambda () ,@body)))) (provide 'pg-pamacs) ;;; pg-pamacs.el ends here PG-4.5/generic/pg-pbrpm.el000066400000000000000000000536641426357011200153710ustar00rootroot00000000000000;; pg-pbrpm.el --- Proof General - Proof By Rules Pop-up Menu - mode. -*- lexical-binding: t; -*- ;; ;; Copyright (C) 2004 - Universite de Savoie, France. ;; Authors: Jean-Roch SOTTY, Christophe Raffalli ;; SPDX-License-Identifier: GPL-3.0-or-later ;; ;; $Id$ ;; ;;; Commentary: ;; ;; Analyse the goal buffer to produce a popup menu. ;; ;; NB: this code is currently XEmacs specific ;; (uses make-gui-button, insert-gui-button, make-dialog-frame) ;; ;; da: can you simply use ;; make-button/make-text-button and something like ;; ;; (make-frame '((minibuffer . nil) (menu-bar-lines . 0) (tool-bar-lines . nil))) (declare-function proof-pbrpm-generate-menu "nofile") (declare-function insert-gui-button "nofile") (declare-function make-gui-button "nofile") (declare-function make-dialog-frame "nofile") (declare-function event-point "nofile") (declare-function event-buffer "nofile") (declare-function default-mouse-track-return-dragged-selection "nofile") (declare-function default-mouse-track-drag-hook "nofile") (declare-function mouse-track "nofile") ;; ;;; Code: (require 'span) (eval-when-compile (require 'cl-lib)) (eval-when-compile (require 'proof-utils)) (require 'proof-script) ;For proof-insert-pbp-command (require 'proof) ;;; ;;; Configuration ;;; (defvar pg-pbrpm-use-buffer-menu t "If t, pbrpm will use a menu displayed in a dialog frame instead of a popup menu.") (defvar pg-pbrpm-start-goal-regexp nil "Regexp to match start of goals. Used to produce a table of goal descriptions in `pg-pbrpm-analyse-goal-buffer'.") (defvar pg-pbrpm-start-goal-regexp-par-num nil "Match number for `pg-pbrpm-start-goal-regexp' to extract goal number.") (defvar pg-pbrpm-end-goal-regexp nil "Regexp to match end of goal. Used to produce a table of goal descriptions in `pg-pbrpm-analyse-goal-buffer'.") (defvar pg-pbrpm-start-hyp-regexp nil "Regexp to match start of hypothesis. Used to produce a table of goal descriptions in `pg-pbrpm-analyse-goal-buffer'.") (defvar pg-pbrpm-start-hyp-regexp-par-num nil "Match number for `pg-pbrpm-start-hyp-regexp' to extract hypothesis number. Used to produce a table of goal descriptions in `pg-pbrpm-analyse-goal-buffer'.") (defvar pg-pbrpm-start-concl-regexp nil "Regexp to match start of conclusions. Used to produce a table of goal descriptions in `pg-pbrpm-analyse-goal-buffer'.") (defvar pg-pbrpm-auto-select-regexp nil "Regexp used to select regions of text around point. Matches the region to be returned.") ;;; ;;; Local variables ;;; (defvar pg-pbrpm-buffer-menu nil) (defvar pg-pbrpm-spans nil) (defvar pg-pbrpm-goal-description nil) (defvar pg-pbrpm-windows-dialog-bug nil) (defvar pbrpm-menu-desc nil) (defun pg-pbrpm-erase-buffer-menu () (with-current-buffer pg-pbrpm-buffer-menu (mapc 'span-delete pg-pbrpm-spans) (setq pg-pbrpm-spans nil) (erase-buffer))) (defun pg-pbrpm-menu-change-hook (start end len) (save-excursion (let ((span (span-at (- start 1) 'editable))) (if (not span) (setq span (span-at start 'editable))) (if span (let ((len (- (span-end span) (span-start span)))) (mapc (lambda (sp) (let* ((p1 (span-start sp)) (p2 (span-end sp)) (proof--inhibit-retract-on-change t)) (goto-char p1) (insert (span-string span)) (delete-region (+ p1 len) (+ p2 len)))) (span-property span 'occurrences))))))) (defun pg-pbrpm-create-reset-buffer-menu () "Create if necessary and erase all text in the buffer menu." (if (or (not pg-pbrpm-buffer-menu) (not (buffer-live-p pg-pbrpm-buffer-menu))) (progn (setq pg-pbrpm-buffer-menu (generate-new-buffer (generate-new-buffer-name "*proof-menu*"))) (set-buffer pg-pbrpm-buffer-menu) ; needs to be fixed here, the mode could be some other prover ; (phox-mode) ; da: proof-mode-for-script should do it ; cr: proof-mode-for-script is not defined in 3.7 ; (if (functionp 'proof-mode-for-script) ; (funcall 'proof-mode-for-shell) (funcall 'proof-mode)) ; da: it's the name of a function, not fn itself. See pg-vars (funcall proof-mode-for-script) (add-hook 'after-change-functions #'pg-pbrpm-menu-change-hook nil t) (pg-pbrpm-erase-buffer-menu))) (set-buffer pg-pbrpm-buffer-menu)) (defun pg-pbrpm-analyse-goal-buffer () "Analyse the goal buffer and produce a table to find goals and hypothesis. It stores, in the variable ‘pg-pbrpm-goal-description’, a list with shape (start-goal end-goal goal-name start-concl hyps ...) with 5 elements per goal: start-goal: the position of the first char of the goal end-goal: the position of the last char of the goal goal-name: the goal name (or number) start-concl: the position of first char of the conclusion of the goal hyps: the list of hypothesis with the shape: (start-hyp start-hyp-text end-hyp hyp-name ...) with 4 elements per hypothesis: start-hyp: the position of the first char of the hyp (including its name) start-hyp-text: the position of the first char of the hyp formula (no name) end-hyp: the position of the last char of the hypothesis hyp-name: then name of the hypothesis." (with-current-buffer proof-goals-buffer (save-excursion (goto-char 0) (let ((goals nil)) (progn (while (search-forward-regexp pg-pbrpm-start-goal-regexp nil t) (let ((hyps nil) (start-goal (match-end 0)) (goal-num (match-string pg-pbrpm-start-goal-regexp-par-num)) (end-goal (search-forward-regexp pg-pbrpm-end-goal-regexp nil t))) (goto-char start-goal) (while (search-forward-regexp pg-pbrpm-start-hyp-regexp end-goal t) (let ((start-hyp (match-beginning 0)) (start-hyp-text (match-end 0)) (hyp-name (match-string pg-pbrpm-start-hyp-regexp-par-num)) (end-hyp (- (if (search-forward-regexp pg-pbrpm-start-hyp-regexp end-goal t) (match-beginning 0) (search-forward-regexp pg-pbrpm-start-concl-regexp end-goal t) (match-beginning 0)) 1))) (goto-char start-hyp-text) (setq hyps (append (list start-hyp start-hyp-text end-hyp hyp-name) hyps)))) (setq goals (append (list start-goal end-goal goal-num (search-forward-regexp pg-pbrpm-start-concl-regexp nil t) hyps) goals)))) (setq pg-pbrpm-goal-description goals)))))) (add-hook 'proof-shell-handle-delayed-output-hook 'pg-pbrpm-analyse-goal-buffer) ;;--------------------------------------------------------------------------;; ;; the Rules Popup Menu functions ;;--------------------------------------------------------------------------;; (defun pg-pbrpm-button-action (event) "This function is bound to a CTRL-RightClick in the Proof General goals buffer." (interactive "e") (save-excursion (pg-pbrpm-build-menu event (point-marker) (mark-marker)) ) ) (defun pg-pbrpm-exists (f l0) (if (null l0) nil (or (funcall f (car l0)) (pg-pbrpm-exists f (cdr l0))))) (defun pg-pbrpm-eliminate-id (acc l) (if (null l) (reverse acc) (if (pg-pbrpm-exists (lambda (x) (string= (car x) (car (car l)))) acc) (pg-pbrpm-eliminate-id acc (cdr l)) (pg-pbrpm-eliminate-id (cons (car l) acc) (cdr l))))) (defun pg-pbrpm-build-menu (event start end) "Build a Proof By Rules pop-up menu. Depends on the state of the proof, the event and a selected region (between the start and end markers). The prover command is processed via pg-pbrpm-run-command." ;; first, run the prover specific (name, rule)'s list generator (let ((click-info (pg-pbrpm-process-click event start end))) ; retrieve click informations (if click-info (let ((pbrpm-list (pg-pbrpm-eliminate-id nil (mapcar 'cdr (sort (proof-pbrpm-generate-menu click-info (pg-pbrpm-process-regions-list)) (lambda (l1 l2) (< (car l1) (car l2))))))) (count 0)) ;; retrieve selected region informations ;; then make that list a menu description (if pbrpm-list (if (not pg-pbrpm-use-buffer-menu) (progn (setq pbrpm-menu-desc '("PBRPM-menu")) (while pbrpm-list (let* ((pbrpm-list-car (pop pbrpm-list)) (description (pop pbrpm-list-car)) (command (concat "(*" description "*)\n" (pop pbrpm-list-car)))) (setq pbrpm-menu-desc (append pbrpm-menu-desc (list (vector description (list 'pg-pbrpm-run-command (list command nil nil)))))))) ;; finally display the pop-up-menu (popup-menu pbrpm-menu-desc)) (pg-pbrpm-create-reset-buffer-menu) (while pbrpm-list (let* ((pbrpm-list-car (pop pbrpm-list)) (description (pop pbrpm-list-car)) (command (pop pbrpm-list-car)) (act (pop pbrpm-list-car)) (pos (point))) (setq count (+ 1 count)) (insert " ") (insert description) (insert " ") ; hack for renaming of last name (let ((spans (pg-pbrpm-setup-span pos (point)))) (insert-gui-button (make-gui-button (concat (int-to-string count) ")") 'pg-pbrpm-run-command (list command act spans)) pos)) (insert "\n"))) (insert-gui-button (make-gui-button "Cancel" (lambda (n) (pg-pbrpm-erase-buffer-menu) (delete-frame)) nil)) ;; needs to be fixed for other prover than phox ;; da: I've removed code here, we should simply keep this ;; buffer with font lock on. (mapc 'span-read-only pg-pbrpm-spans) (make-dialog-frame '(width 80 height 30))) (beep)))))) (defun pg-pbrpm-setup-span (start end) "Set up the span in the menu buffer." (save-excursion (let ((rank 0) (spans nil) (allspan (span-make start end))) (while (< start end) (goto-char start) (let ((pos (search-forward "\\[" end 0)) (goalnum 0)) (if pos (progn (delete-char -2) (setq end (- end 2)) (setq pos (- pos 2)))) ; (message "make l span %d %d" start (if pos pos end)) (let ((span (span-make start (if pos pos end)))) (span-set-property span 'pglock t) (setq pg-pbrpm-spans (cons span pg-pbrpm-spans))) (if pos (progn (search-forward "\\]" end) (delete-char -2) (setq end (- end 2)) (setq start (point)) (save-excursion (goto-char pos) (if (search-forward-regexp "\\\\|\\([0-9]\\)" start t) (progn (setq goalnum (string-to-number (match-string 1))) (let ((len (- (match-end 0) (match-beginning 0)))) (setq end (- end len)) (setq start (- start len))) (delete-region (match-beginning 0) (match-end 0))))) (let* ((span (span-make pos start)) (str (concat "\\{" (span-string span) (if (= goalnum 0) "" (concat "\\|" (int-to-string goalnum))) "\\}")) (len (- start pos)) (occurrences nil)) (save-excursion (goto-char pos) (while (search-forward str end t) (setq end (+ (- end (- (match-end 0) (match-beginning 0))) len)) (delete-region (match-beginning 0) (match-end 0)) (insert (span-string span)) ; (message "span o %d %d" (match-beginning 0) (+ (match-beginning 0) len)) (setq occurrences (cons (span-make (match-beginning 0) (+ (match-beginning 0) len)) occurrences)))) ; (message "make w span %d %d %s %d" pos start (span-string span) goalnum) (setq spans (cons span spans)) (setq rank (+ rank 1)) (span-set-property span 'editable t) (span-set-property span 'rank rank) (span-set-property span 'goalnum goalnum) (span-set-property span 'occurrences occurrences) (span-set-property span 'original-text (span-string span)) (span-set-property span 'face 'pg-pbrpm-menu-input-face))) (setq start (if pos pos end))))) (cons allspan (sort (reverse spans) (lambda (sp1 sp2) (< (span-property sp1 'goalnum) (span-property sp1 'goalnum)))))))) (defun pg-pbrpm-run-command (args) "Insert command into the proof queue and then run it. \(adapted from ‘proof-insert-pbp-command’)" (let* ((command (pop args)) (act (pop args)) (spans (pop args)) (allspan (pop spans))) (if act (setq command (apply act command spans nil))) (if allspan (setq command (concat "(* " (span-string allspan) " *)\n" command "."))) ; delete buffer (and its span) after applying "act" (pg-pbrpm-erase-regions-list) (if pg-pbrpm-use-buffer-menu (progn (pg-pbrpm-erase-buffer-menu) (delete-frame))) ;; da: why not just this? (pop-to-buffer proof-script-buffer) (let ((proof-next-command-on-new-line t)) (proof-insert-pbp-command command)))) ;; (let (span) ;; (pop-to-buffer proof-script-buffer) ;; (proof-goto-end-of-locked) ;; (proof-activate-scripting nil 'advancing) ;; (insert (concat "\n" command)) ;; (setq span (span-make (proof-unprocessed-begin) (point))) ;; ; TODO : define the following properties for PBRPM, I don't understand their use ... ;; (span-set-property span 'type 'pbp) ;; (span-set-property span 'cmd command) ;; (proof-start-queue (proof-unprocessed-begin) (point) ;; (list (list span (list command) ;; 'proof-done-advancing)))))) ;;--------------------------------------------------------------------------;; ;; Click Informations extractors ;;--------------------------------------------------------------------------;; (defun pg-pbrpm-get-pos-info (pos) "Get position information for POS. Returns (n . s) where n is the goal name s if either the hypothesis name, \"none\" (for the conclusion), or \"whole\" in strange cases." (let ((l pg-pbrpm-goal-description) (found nil) start-goal end-goal goal-name start-concl hyps the-goal-name the-click-info start-hyp end-hyp start-hyp-text hyp-name) (while (and pos l (not found)) (setq start-goal (car l)) (setq end-goal (cadr l)) (setq goal-name (cl-caddr l)) (setq start-concl (cl-cadddr l)) (setq hyps (car (cl-cddddr l))) (setq l (cdr (cl-cddddr l))) (if (and (<= start-goal pos) (<= pos end-goal)) (progn (setq found t) (setq the-goal-name goal-name)))) (if found (progn (if (<= start-concl pos) (setq the-click-info "none") (setq found nil) (while (and hyps (not found)) (setq start-hyp (car hyps)) (setq start-hyp-text (cadr hyps)) (setq end-hyp (cl-caddr hyps)) (setq hyp-name (cl-cadddr hyps)) (setq hyps (cl-cddddr hyps)) (if (and (<= start-hyp pos) (<= pos end-hyp)) (progn (setq found t) (setq the-click-info hyp-name)))) (if (not found) (setq the-click-info "whole"))) (cons the-goal-name the-click-info))))) (defun pg-pbrpm-get-region-info (start end) "Get position info for a region, if region is within a single position. See `pg-pbrpm-get-pos-info'." (let ((r1 (pg-pbrpm-get-pos-info start)) (r2 (pg-pbrpm-get-pos-info end))) ;; da: this said start, surely wrong? (if (and r1 r2 (string-equal (car r1) (car r2))) (if (string-equal (cdr r1) (cdr r2)) r1 (cons (car r1) "whole")) nil))) (defun pg-pbrpm-auto-select-around-point () "Extract some text arround point, according to `pg-pbrpm-auto-select-regexp'. If no match found, return the empty string." (save-excursion (let ((pos (point))) (beginning-of-line) (cl-block 'loop (while (< (point) pos) (unless (search-forward-regexp pg-pbrpm-auto-select-regexp nil t) (cl-return-from 'loop "")) (if (and (<= (match-beginning 0) pos) (<= pos (match-end 0))) (cl-return-from 'loop (match-string 0)))) (cl-return-from 'loop ""))))) (defun pg-pbrpm-translate-position (buffer pos) "If BUFFER is goals-buffer, return POS, otherwise the point in the goal buffer." (if (eq proof-goals-buffer buffer) pos (with-current-buffer proof-goals-buffer (point)))) (defun pg-pbrpm-process-click (event start end) "Return the list of infos about the click needed to call ‘generate-menu’. EVENT is an event." (save-excursion (save-window-excursion (mouse-set-point event) (let* ((pos (event-point event)) (buffer (event-buffer event)) (r (pg-pbrpm-get-pos-info (pg-pbrpm-translate-position buffer pos)))) (if r (list (string-to-number (car r)) ; should not be an int for other prover (if (eq proof-goals-buffer buffer) (cdr r) (pg-pbrpm-auto-select-around-point)) (if (and start end (eq proof-goals-buffer buffer) (<= (marker-position start) pos) (<= pos (marker-position end))) (pg-pbrpm-region-expression buffer (marker-position start) (marker-position end)) (pg-pbrpm-auto-select-around-point)))))))) ;;--------------------------------------------------------------------------;; ;; Selected Region informations extractors ;;--------------------------------------------------------------------------;; (defvar pg-pbrpm-remember-region-selected-region nil) (defvar pg-pbrpm-regions-list nil) (defun pg-pbrpm-erase-regions-list () (mapc (lambda (span) (span-delete span)) pg-pbrpm-regions-list) (setq pg-pbrpm-regions-list nil) nil) (add-hook 'mouse-track-drag-up-hook (lambda (event count) (if (not (member 'control (event-modifiers event))) (pg-pbrpm-erase-regions-list)))) (defun pg-pbrpm-filter-regions-list () (let ((l pg-pbrpm-regions-list)) (setq pg-pbrpm-regions-list nil) (mapc (lambda (span) (if (span-live-p span) (setq pg-pbrpm-regions-list (cons span pg-pbrpm-regions-list)) (span-delete span))) l))) (defface pg-pbrpm-multiple-selection-face (proof-face-specs (:background "orange") (:background "darkorange") (:italic t)) "*Face for showing (multiple) selection." :group 'proof-faces) (defface pg-pbrpm-menu-input-face (proof-face-specs (:background "Gray80") (:background "Gray65") (:italic t)) "*Face for showing (multiple) selection." :group 'proof-faces) (defun pg-pbrpm-do-remember-region (start end) (pg-pbrpm-filter-regions-list) (if (and start end (not (eq start end))) ; if a region is selected (let ((span (span-make start end)) (found nil)) (setq pg-pbrpm-regions-list (reverse (mapcar (lambda (oldspan) (let ((oldstart (span-start oldspan)) (oldend (span-end oldspan))) (if (and (eq (current-buffer) (span-buffer oldspan)) (or (and (<= start oldstart) (<= oldstart end)) (and (<= start oldend) (<= oldend end)))) (progn (setq found t) (span-delete oldspan) span) oldspan))) pg-pbrpm-regions-list))) (if (not found) (setq pg-pbrpm-regions-list (cons span pg-pbrpm-regions-list))) (span-set-property span 'face 'pg-pbrpm-multiple-selection-face)))) ; the follwing are adapted from mouse-track-insert from mouse.el (defun pg-pbrpm-remember-region-drag-up-hook (event click-count) (setq pg-pbrpm-remember-region-selected-region (default-mouse-track-return-dragged-selection event))) (defun pg-pbrpm-remember-region-click-hook (event click-count) (default-mouse-track-drag-hook event click-count nil) (pg-pbrpm-remember-region-drag-up-hook event click-count) t) (defun pg-pbrpm-remember-region (event &optional delete) "Allow multiple selection as a list of span stored in ???. The current (standard) selection in the same buffer is also stored." (interactive "*e") (setq pg-pbrpm-remember-region-selected-region nil) (let ((mouse-track-drag-up-hook 'pg-pbrpm-remember-region-drag-up-hook) (mouse-track-click-hook 'pg-pbrpm-remember-region-click-hook) (start (point)) (end (mark))) (if (and start end) (pg-pbrpm-do-remember-region start end)) (mouse-track event) (if (consp pg-pbrpm-remember-region-selected-region) (let ((pair pg-pbrpm-remember-region-selected-region)) (pg-pbrpm-do-remember-region (car pair) (cdr pair)))))) (defun pg-pbrpm-process-region (span) "Return the list of infos on the selected region needed to call ‘generate-menu’. SPAN is a span covering the selected region." (let ((start (span-start span)) (end (span-end span)) (buffer (span-buffer span)) r) (if (and start end) ; if a region is selected (if (eq proof-goals-buffer buffer) (progn (setq r (pg-pbrpm-get-region-info start end)) (if r (list (string-to-number (car r)) ; should not be an int for other prover (cdr r) (pg-pbrpm-region-expression buffer start end)) (list 0 "none" (pg-pbrpm-region-expression buffer start end)))) (list 0 "none" (pg-pbrpm-region-expression buffer start end)))))) (defun pg-pbrpm-process-regions-list () (pg-pbrpm-do-remember-region (point-marker) (mark-marker)) (mapcar (lambda (span) (pg-pbrpm-process-region span)) pg-pbrpm-regions-list)) (defun pg-pbrpm-region-expression (buffer start end) "Valid parenthesis'd expression." ;; an expression is valid if it has as many left paren' as right paren' (with-current-buffer buffer (buffer-substring start end))) ; (let ; ((pbrpm-left-pars 0) ; (pbrpm-right-pars 0) ; (pos start)) ; (while (< pos end) ; (if (proof-pbrpm-left-paren-p (char-after pos)) ; (setq pbrpm-left-pars (+ pbrpm-left-pars 1))) ; (if (proof-pbrpm-right-paren-p (char-after pos)) ; (setq pbrpm-right-pars (+ pbrpm-right-pars 1))) ; (setq pos (+ pos 1))) ; (if (= pbrpm-left-pars pbrpm-right-pars) ; (buffer-substring start end buffer) ; (progn ; nil ; TODO : define how to manage this error case ; ;we could call (pg-pbrpm-dialog "Selected region is not valid), then what about the state of the process ? ; )))) ;;--------------------------------------------------------------------------;; (eval-after-load "pg-goals" '(progn (define-key proof-goals-mode-map [(button3)] 'pg-pbrpm-button-action) (define-key proof-goals-mode-map [(control button3)] 'pg-goals-yank-subterm) (define-key proof-goals-mode-map [(control button1)] 'pg-pbrpm-remember-region) (define-key proof-mode-map [(button3)] 'pg-pbrpm-button-action) (define-key proof-mode-map [(control button3)] 'pg-goals-yank-subterm) (define-key proof-mode-map [(control button1)] 'pg-pbrpm-remember-region))) (eval-after-load "proof-script" '(progn (define-key pg-span-context-menu-keymap [(button3)] 'pg-pbrpm-button-action) (define-key pg-span-context-menu-keymap [(control button3)] 'pg-span-context-menu))) (provide 'pg-pbrpm) ;;; pg-pbrpm ends here PG-4.5/generic/pg-pgip.el000066400000000000000000000560011426357011200151740ustar00rootroot00000000000000;;; pg-pgip.el --- PGIP manipulation for Proof General ;; This file is part of Proof General. ;; Portions © Copyright 1994-2012 David Aspinall and University of Edinburgh ;; Portions © Copyright 2003-2018 Free Software Foundation, Inc. ;; Portions © Copyright 2001-2017 Pierre Courtieu ;; Portions © Copyright 2010, 2016 Erik Martin-Dorel ;; Portions © Copyright 2011-2013, 2016-2017 Hendrik Tews ;; Portions © Copyright 2015-2017 Clément Pit-Claudel ;; Author: David Aspinall ;; SPDX-License-Identifier: GPL-3.0-or-later ;;; Commentary: ;; ;; STATUS: Experimental ;; ;; Proof General Kit uses PGIP, an XML-message protocol ;; for interactive proof. This file contains functions ;; to process PGIP commands sent from the proof assistant ;; and to construct PGIP commands to send out. ;; ;; TESTING NOTES: turn on `proof-general-debug' for ;; useful tracing messages: (setq proof-general-debug t). ;; ;; TODO NEXT: ;; -- completion command for completion tables ;; -- parsescript input/outputs ;; -- guiconfig, some parts of ;; -- support fully native PGIP mode ;; ;;; Code: (require 'cl-lib) ; incf (require 'pg-xml) ; (declare-function pg-response-warning "pg-response") (declare-function pg-response-message "pg-response") (require 'proof-script) (defalias 'pg-pgip-debug 'proof-debug) (defalias 'pg-pgip-error 'error) (defalias 'pg-pgip-warning 'pg-internal-warning) (defconst pg-pgip-version-supported "2.0" "Version of PGIP supported by this library.") ;;;###autoload (defun pg-pgip-process-packet (pgips) "Process the command packet PGIP, which is parsed XML according to pg-xml-parse-*. The list PGIPS may contain one or more PGIP packets, whose contents are processed." ;; PGIP processing is split into two steps: ;; (1) process each command, altering internal data structures ;; (2) post-process for each command type, affecting external interface (menus, etc). (mapc #'pg-pgip-post-process (cl-reduce #'cl-union (mapcar #'pg-pgip-process-pgip pgips)))) ;; TODO: use id's and sequence numbers to reconstruct streams of messages. (defvar pg-pgip-last-seen-id nil) (defvar pg-pgip-last-seen-seq nil) (defun pg-pgip-process-pgip (pgip) "Process the commands in the PGIP XML-node PGIP." ;; NB: appearances of 'notreallyoptional below should be removed, ;; but they are needed for compatibility with Isabelle at the moment, ;; whose PGIP follows an older schema. (let* ((name (xml-node-name pgip)) (tag (pg-xml-get-attr 'tag pgip 'optional)) (id (pg-xml-get-attr 'id pgip 'optional)) (class (pg-xml-get-attr 'messageclass pgip 'notreallyoptional)) (refseq (pg-xml-get-attr 'refseq pgip 'optional)) (refid (pg-xml-get-attr 'refid pgip 'optional)) (seq (pg-xml-get-attr 'seq pgip 'notreallyoptional))) (setq pg-pgip-last-seen-id id) (setq pg-pgip-last-seen-seq seq) (if (eq name 'pgip) ;; NB: schema currently allows only one message here (mapcar #'pg-pgip-process-msg (xml-node-children pgip)) (pg-internal-warning "pg-pgip-process-pgip: expected PGIP element, got %s" name)))) (defun pg-pgip-process-msg (pgipmsg) "Process the PGIP message in the XML node PGIPMSG. Return a symbol representing the PGIP command processed, or nil." (let* ((name (xml-node-name pgipmsg)) (fname (intern (concat "pg-pgip-process-" (symbol-name name))))) (if (fboundp fname) (progn (pg-pgip-debug "Processing PGIP message seq %s, type %s" (or (pg-xml-get-attr 'seq pgipmsg 'notreallyoptional) "") name) (funcall fname pgipmsg) name) (pg-internal-warning "!!! unrecognized/unimplemented PGIP message element `%s'" name) nil))) (defvar pg-pgip-post-process-functions '((hasprefs . proof-assistant-menu-update) (oldhaspref . proof-assistant-menu-update) ;; NB: Isabelle compatibility (menuadd . proof-assistant-menu-update) (menudel . proof-assistant-menu-update) (idtable . pg-pgip-update-idtables) ;; TODO: not yet implemented (addid . pg-pgip-update-idtables) (delid . pg-pgip-update-idtables)) "Table of functions to call after processing PGIP commands.") (defun pg-pgip-post-process (cmdname) "Perform post-processing for a PGIP command type CMDNAME (a symbol)." (let ((ppfn (cdr-safe (assoc cmdname pg-pgip-post-process-functions)))) (if (fboundp ppfn) (progn (pg-pgip-debug "Post-processing for PGIP message type `%s' with function `%s'" cmdname ppfn) (funcall ppfn)) (pg-pgip-debug "[No post-processing defined for PGIP message type `%s']" cmdname)))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Message processing: fromprovermsg/kitconfig ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (defun pg-pgip-process-askpgip (node) (pg-pgip-debug "Received message with version `%s'" (pg-xml-get-attr 'version node 'notreallyoptional)) ;; TODO: send a uses PGIP message back? ) (defun pg-pgip-process-usespgip (node) (let ((version (pg-pgip-get-version node))) (pg-pgip-debug "Received message with version `%s'" version))) (defun pg-pgip-process-usespgml (node) (let ((version (pg-pgip-get-version node))) (pg-pgip-debug "Received message with version `%s'" version))) (defun pg-pgip-process-pgmlconfig (node) ;; symconfig specify an ascii alternative string for a named symbol; ;; we process it by storing a property 'pgml-alt on the elisp symbol. (let ((pgmlconfigures (xml-get-children node 'symconfig))) (dolist (config pgmlconfigures) (cond ((and (not (stringp config)) (eq (xml-node-name config) "symconfig")) (let ((symname (pg-pgip-get-symname node)) (asciialt (pg-xml-get-attr 'alt node t))) (put (intern symname) 'pgml-alt asciialt))) (t (pg-pgip-warning "Unexpected child of node: %s" config)))))) (defun pg-pgip-process-proverinfo (node) (let* ((name (pg-pgip-get-name node)) (descr (pg-pgip-get-descr node t "")) (version (pg-pgip-get-version node t "")) (url (pg-pgip-get-url node t)) (welcomeelt (pg-xml-get-child 'welcomemsg node)) (welcomemsg (if welcomeelt (pg-xml-get-text-content welcomeelt))) (icon (xml-get-children node 'icon)) (helpdocs (xml-get-children node 'helpdocs))) ;; TODO: enter the data into a table of provers (see proof-site.el). ;; Seems little point doing this while we have the single-prover limitation. )) ;; ;; Preferences ;; (defun pg-pgip-process-hasprefs (node) (let* ((prefcat (pg-pgip-get-prefcat node)) (hasprefnodes (xml-get-children node 'haspref))) (dolist (node hasprefnodes) (let* ((name (pg-pgip-get-name node)) (descr (pg-pgip-get-descr node 'optional)) (pgiptype (pg-pgip-get-pgiptype (pg-xml-child-elt node))) (default (pg-pgip-get-default node 'optional)) (defaultlsp (if default (pg-pgip-interpret-value default pgiptype) (pg-pgip-default-for pgiptype))) (icon (pg-pgip-get-icon node 'optional))) ;; TODO; ignored (pg-pgip-haspref name pgiptype prefcat descr defaultlsp))))) (defun pg-pgip-haspref (name type prefcat descr default) "Call `defpacustom' with values from a element." (let* ((subst (pg-pgip-subst-for type)) ;; FIXME: this substitution mechanism is not really good enough, we ;; want to escape XML characters, etc. Should be possible: turn this ;; into a function. (pgipcmd (concat "" subst "")) (symname (intern name))) (pg-pgip-debug "haspref calling defpacustom: name:%s default:%s type:%s pgipcmd:%s" symname default type pgipcmd) (eval `(defpacustom ,symname ,default ,descr :type (quote ,type) :pggroup ,prefcat :pgipcmd ,pgipcmd :pgdynamic t)))) (defun pg-pgip-process-prefval (node) ;; ;; value ;; ;; Proof assistant advises that preference n has been updated. ;; ;; Protocol is that sent on a PGIP channel is assumed to ;; succeed, so is not required to be acknowledged with a ;; message from prover. But no harm will result if it is --- and that ;; might be appropriate if some canonicalisation occurs. ; in progress [FIXME: Isabelle can send this as reply to getpref now] ;(defun pg-pgip-prefval (attrs value) ; "Process a element, by setting interface's copy of preference." ; (let* ; ((name (pg-xml-get-attr 'haspref 'name attrs t)) ; (type ( ) ;; ;; guiconfig ;; (defun pg-pgip-process-guiconfig (node) ) ;; ;; Identifiers: managing obarrays of symbols used for completion ;; (defvar proof-assistant-idtables nil "List of idtables (objtype symbols) for currently running proof assistant.") (defun pg-pgip-process-ids (node) "Manipulate identifier tables, according to setids/addids/delids in NODE." (let ((idtables (pg-xml-child-elts node)) (opn (xml-node-name node))) (dolist (idtable idtables) (let* ((context (pg-xml-get-attr 'context idtable 'optional)) (objtype (intern (pg-pgip-get-objtype idtable))) (idents (mapcar #'pg-xml-get-text-content (xml-get-children idtable 'identifier))) (obarray (or (and (not (eq opn 'setids)) (get objtype 'pgsymbols)) ;; new empty obarray for setids or if unset (put objtype 'pg-symbols (make-vector 31 0))))) (setq proof-assistant-idtables (if (and (null idents) (eq opn 'setids)) (delete objtype proof-assistant-idtables) (cl-adjoin objtype proof-assistant-idtables))) (cond ((or (eq opn 'setids) (eq opn 'addids)) (mapc (lambda (i) (intern i obarray)) idents)) ((eq opn 'delids) (mapc (lambda (i) (unintern i obarray)) idents)) (t (pg-pgip-error "Pg-pgip-process-ids: called on wrong node %s" (xml-node-name node)))))))) (defun pg-complete-idtable-symbol () (interactive) ;; TODO: complete based on blah ) (defalias 'pg-pgip-process-setids 'pg-pgip-process-ids) (defalias 'pg-pgip-process-addids 'pg-pgip-process-ids) (defalias 'pg-pgip-process-delids 'pg-pgip-process-ids) (defun pg-pgip-process-idvalue (node) (let ((name (pg-pgip-get-name node)) (objtype (pg-pgip-get-objtype node)) (text (pg-pgip-get-displaytext node))) ;; TODO: display and cache the value in a dedicated buffer ;; FIXME: should idvalue have a context? (pg-response-message text))) ;; ;; Menu configuration [TODO] ;; (defun pg-pgip-process-menuadd (node) ) (defun pg-pgip-process-menudel (node) ) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Message processing: fromprovermsg/proveroutput ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (defun pg-pgip-process-ready (node) ) (defun pg-pgip-process-cleardisplay (node) (let ((area (pg-pgip-get-area node))) (cond ((equal area "message") (pg-response-maybe-erase nil t t)) ((equal area "display") (proof-clean-buffer proof-goals-buffer)) ((equal area "all") (pg-response-maybe-erase nil t t) (proof-clean-buffer proof-goals-buffer) ;; TODO: could also erase trace here. ;; [PGIP: Should trace have a separate cat?] )))) (defun pg-pgip-process-proofstate (node) ;(let ((pgml (pg-xml-child ) ) (defun pg-pgip-process-normalresponse (node) (let ((text (pg-pgip-get-displaytext node))) (pg-response-message text))) (defun pg-pgip-process-errorresponse (node) (let ((text (pg-pgip-get-displaytext node))) (pg-response-warning text))) (defun pg-pgip-process-scriptinsert (node) (let ((text (pg-pgip-get-displaytext node))) (proof-insert-pbp-command text))) (defun pg-pgip-process-metainforesponse (node) ) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Message processing: fromprovermsg/fileinfomsg ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (defun pg-pgip-file-of-url (urlstr) (save-match-data (if (string-match "^file:///\\(.*\\)$" urlstr) (match-string 1 urlstr)))) (defun pg-pgip-process-informfileloaded (node) (let* ((thyname (pg-pgip-get-thyname node)) (url (pg-pgip-get-url node)) (filename (pg-pgip-file-of-url url))) (proof-register-possibly-new-processed-file filename))) (defun pg-pgip-process-informfileretracted (node) (let* ((thyname (pg-pgip-get-thyname node)) (url (pg-pgip-get-url node)) (filename (pg-pgip-file-of-url url))) ;(proof-unregister-possibly-processed-file filename))) ;; unimplemented! )) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Message processing: todisplaymsg/brokermsg ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (defun pg-pgip-process-brokerstatus (node) ) (defun pg-pgip-process-proveravailmsg (node) ) (defun pg-pgip-process-newprovermsg (node) ) (defun pg-pgip-process-proverstatusmsg (node) ) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Message processing: todisplaymsg/dispmsg/dispfilemsg ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (defvar pg-pgip-srcids nil "Association list of srcrds to (buffer file) lists") ;; FIXME: right action? (defun pg-pgip-process-newfile (node) "Process message from broker by displaying file. Also sets local proverid and srcid variables for buffer." (let* ((srcid (pg-pgip-get-srcid node)) (proverid (pg-pgip-get-proverid node)) (url (pg-pgip-get-url node)) (file (pg-pgip-file-of-url url))) (find-file file) (let ((buffer (get-file-buffer file))) (with-current-buffer buffer (make-local-variable 'proverid) (setq proverid proverid)) (set pg-pgip-srcids (cl-acons srcid (list buffer file) pg-pgip-srcids))))) ;; FIXME: right action? (defun pg-pgip-process-filestatus (node) "Process flag by adjusting buffer's modified flag." (let* ((srcid (pg-pgip-get-srcid node)) (filestat (pg-xml-get-attr 'filestat node)) (buffer (car-safe (cdr-safe (assoc srcid pg-pgip-srcids))))) (proof-with-current-buffer-if-exists buffer (cond ((equal filestat "changed") (set-buffer-modified-p t)) ((equal filestat "saved") (set-buffer-modified-p nil)))))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Message processing: todisplaymsg/dispmsg/dispobjmsg ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (defun pg-pgip-process-newobj (node) ) (defun pg-pgip-process-delobj (node) ) (defun pg-pgip-process-objectstatus (node) ) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Message processing: parsescript [incomplete] ;; ;; NB: pgip.rnc v 2.18 only has parsescript sent to prover, ;; so if we get here we have a invalid document. ;; ;; Provide parsing functionality for other interfaces (sacrilege!) ;; (defun pg-pgip-process-parsescript (node) ;; Text ought to be cdata or something. We'll stick it into a buffer ;; and run the proof-script code on it. (save-excursion (let* ((text (pg-xml-get-text-content node)) (buf (get-buffer-create " *pgip-parsescript*"))) (delete-region (point-min) (point-max)) ; wipe previous contents (insert text) (let ((semis (proof-segment-up-to (point)))) ;; semis is now a list of (type, string, int) tuples (in reverse order). ;; we'll turn it into XML and send it back to the prover ;; FIXME: todo: make parseresult element according to types, ;; properscriptcmd = properproofcmd | properfilecmd | bindid )))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; PGIP types and values <-> Elisp types and values ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (defun pg-pgip-get-pgiptype (node) "Return internal (custom format) representation for element in NODE." (let ((tyname (and node (xml-node-name node)))) (cond ((eq tyname 'pgipbool) 'boolean) ((eq tyname 'pgipint) 'integer) ;; TODO: implement range limits ((eq tyname 'pgipfloat) 'float) ;; TODO: implement range limits ((eq tyname 'pgipstring) 'string) ((eq tyname 'pgipconst) (let ((name (pg-pgip-get-name node 'optional)) (val (pg-pgip-get-value node))) (if name (list 'const :tag name val) (list 'const val)))) ((eq tyname 'pgipchoice) (let* ((choicesnodes (pg-xml-child-elts node)) (choices (mapcar #'pg-pgip-get-pgiptype choicesnodes))) (list 'choice choices))) (t (pg-pgip-warning "pg-pgip-get-pgiptype: unrecognized/missing typename \"%s\"" tyname))))) (defun pg-pgip-default-for (type) "Synthesize a default value for type TYPE." (cond ((eq type 'boolean) nil) ((eq type 'integer) 0) ((eq type 'string) "") ((eq (car-safe type) 'const) (car (last type))) ((eq (car-safe type) 'choice) (pg-pgip-default-for (car-safe (cdr-safe type)))) (t (pg-pgip-error "pg-pgip-default-for: unrecognized type passed in")))) (defun pg-pgip-subst-for (type) "Return a substitution string for type TYPE." (cond ((eq type 'boolean) "%b") ((eq type 'integer) "%i") ((eq type 'float) "%f") (t "%s"))) ;; Converting PGIP representations to elisp representations. This is ;; the inverse of proof-assistant-format translations in ;; proof-menu.el, although we fix PGIP value syntax. (defun pg-pgip-interpret-value (value type) "Interpret the PGIP value VALUE at (lisp-representation for) TYPE." (cond ((eq type 'boolean) (cond ((or (string-equal value "true") (string-equal value "1")) t) ((or (string-equal value "false") (string-equal value "0")) nil) (t (progn (pg-pgip-warning "pg-pgip-interpret-value: received non-bool value %s" value) nil)))) ((eq type 'integer) (string-to-number value)) ((eq type 'float) (string-to-number value)) ((eq type 'string) value) ((eq (car-safe type) 'const) value) ((eq (car-safe type) 'choice) (pg-pgip-interpret-choice (cdr type) value)) (t (pg-pgip-error "pg-pgip-interpret-value: unkown type %s" type)))) (defun pg-pgip-interpret-choice (choices value) ;; Untagged union types: test for value in each type in turn. (let (res) (while (and choices (not res)) (let ((type (car choices))) (cond ((and (eq (car-safe type) 'const) (string-equal value (cadr type))) (setq res (pg-pgip-interpret-value value 'const))) ((and (eq type 'integer) (string-match "[+-]?[0-9]+$" value)) (setq res (pg-pgip-interpret-value value 'integer))) ((and (eq type 'boolean) (or (string-equal value "true") (string-equal value "false") (string-equal value "0") (string-equal value "1"))) (setq res (pg-pgip-interpret-value value 'boolean))) ((eq type 'string) (setq res (pg-pgip-interpret-value value 'string))))) (setq choices (cdr choices))) (or res (pg-pgip-error "pg-pgip-interpret-choice: mismatching value %s for choices %s" value choices)))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Sending PGIP commands to prover ;; (defun pg-pgip-string-of-command (pgip &optional refseq refid otherclass) "Convert XML node PGIP or string into a command string to send to the prover. This wraps the node in a packet with appropriate attributes. See `pg-pgip-assemble-packet' " (let ((wrappedpgip (pg-xml-string-of (list (pg-pgip-assemble-packet (list pgip) refseq refid otherclass))))) (cond ((stringp proof-shell-issue-pgip-cmd) (format proof-shell-issue-pgip-cmd wrappedpgip)) ((functionp proof-shell-issue-pgip-cmd) (funcall proof-shell-issue-pgip-cmd wrappedpgip)) (t ;; FIXME: Empty setting: might be better to send a comment (pg-pgip-warning "pg-prover-interpret-pgip-command: `proof-shell-issue-pgip' is unset!") "")))) (defconst pg-pgip-id ;; Identifier based on hostname, user, time, and (FIXME: possible?) ppid (concat (getenv "HOSTNAME") "/" (getenv "USER") "/" (let ((tm (if (fboundp 'time-convert) (time-convert nil 'list) (current-time)))) (format "%d.%d" (car tm) (cadr tm)))) "PGIP Identifier for this Emacs Proof General component.") (defvar pg-pgip-refseq nil "The sequence number of the received message this reply refers to") (defvar pg-pgip-refid nil "The identity of the component this message is being sent to") (defvar pg-pgip-seq 0 "Sequence number of messages sent out.") (defun pg-pgip-assemble-packet (body &optional refseq refid otherclass) "Construct a PGIP node with body list BODY. REFSEQ and REFID are used for the corresponding attributes, if present. By default, the class of the message is \"pa\" (destined for prover). OTHERCLASS overrides this." (let* ((tag (pg-xml-attr tag (concat "EmacsPG/" proof-general-short-version "/" proof-assistant))) (id (pg-xml-attr id pg-pgip-id)) (class (pg-xml-attr class (or otherclass "pa"))) (seq (pg-xml-attr seq (int-to-string (cl-incf pg-pgip-seq)))) (refseq (if refseq (list (pg-xml-attr refseq refseq)))) (refid (if refid (list (pg-xml-attr refid refid)))) (pgip_attrs (append (list tag id class seq) refseq refid))) (pg-xml-node pgip pgip_attrs body))) (defun pg-pgip-issue (pgip &optional block refseq refid otherclass) "Issue a PGIP command via `proof-shell-issue-pgip-cmd' and `proof-shell-invisible-command'. This expects a single XML node/string in PGIP, which will have a PGIP header attached. If BLOCK is non-nil, we wait for the response from the prover. For remaining optional args, see doc of `pgip-assemble-packet'." (proof-shell-invisible-command (pg-pgip-string-of-command pgip refseq refid otherclass) block)) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Functions to send particular commands ;; ;;;###autoload (defun pg-pgip-maybe-askpgip () "Send an message to the prover if PGIP is supported." (if proof-shell-issue-pgip-cmd (pg-pgip-issue "" 'block))) ;;;###autoload (defun pg-pgip-askprefs () "Send an message to the prover." (pg-pgip-issue "" 'block)) (defun pg-pgip-askids (&optional objtype thyname) "Send an message to the prover." (pg-pgip-issue (pg-xml-node askids (append (if thyname (list (pg-xml-attr 'thyname objtype))) (if objtype (list (pg-xml-attr 'objtype objtype)))) nil) 'block)) (defun pg-pgip-reset () "Reset state of the PGIP module" (setq pg-pgip-refseq nil pg-pgip-refid nil pg-pgip-last-seen-id nil pg-pgip-last-seen-seq nil pg-pgip-seq 0 proof-assistant-settings nil ;; optional proof-assistant-idtables nil)) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Standalone PGIP processing -- Emacs in batch mode, yuk! ;; ;; TODO: output PGIP on stdout, read in on stdin. ;; standard-input ;; standard-output ;; (defun pg-pgip-filter () ;; (let (instuff outstuff) ;; (while (setq (read-char standard-input)) ;; reads lisp!!! ;; ))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Constants for export ;; (defconst pg-pgip-start-element-regexp "") (provide 'pg-pgip) ;;; pg-pgip.el ends here PG-4.5/generic/pg-response.el000066400000000000000000000523421426357011200160770ustar00rootroot00000000000000;;; pg-response.el --- Proof General response buffer mode. ;; This file is part of Proof General. ;; Portions © Copyright 1994-2012 David Aspinall and University of Edinburgh ;; Portions © Copyright 2003-2021 Free Software Foundation, Inc. ;; Portions © Copyright 2001-2017 Pierre Courtieu ;; Portions © Copyright 2010, 2016 Erik Martin-Dorel ;; Portions © Copyright 2011-2013, 2016-2017 Hendrik Tews ;; Portions © Copyright 2015-2017 Clément Pit-Claudel ;; Authors: David Aspinall, Healfdene Goguen, ;; Thomas Kleymann and Dilip Sequeira ;; SPDX-License-Identifier: GPL-3.0-or-later ;;; Commentary: ;; ;; This mode is used for the response buffer proper, and ;; also the trace and theorems buffer. A sub-module of proof-shell. ;; ;;; Code: (eval-when-compile (require 'easymenu) ; easy-menu-add (require 'proof-utils)) ; deflocal, proof-eval-when-ready-for-assistant (defvar proof-response-mode-menu) (defvar proof-assistant-menu) (require 'pg-assoc) (require 'span) (defvar pg-insert-text-function #'insert "hook for coq diffs highlighting routine") ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Local variables ;; (deflocal pg-response-eagerly-raise t "Non-nil if this buffer will be eagerly raised/displayed on startup.") ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Response buffer mode ;; ;;;###autoload (define-derived-mode proof-response-mode proof-universal-keys-only-mode "PGResp" "Responses from Proof Assistant" (setq proof-buffer-type 'response) (add-hook 'kill-buffer-hook 'pg-save-from-death nil t) (easy-menu-add proof-response-mode-menu proof-response-mode-map) (easy-menu-add proof-assistant-menu proof-response-mode-map) (proof-toolbar-setup) (setq pg-response-next-error nil) (buffer-disable-undo) (if proof-keep-response-history (bufhist-mode)) ; history for contents (set-buffer-modified-p nil) (setq buffer-read-only t) (setq cursor-in-non-selected-windows nil)) ;; ;; Menu for response buffer ;; (proof-eval-when-ready-for-assistant ; proof-aux-menu depends on (easy-menu-define proof-response-mode-menu proof-response-mode-map "Menu for Proof General response buffer." (proof-aux-menu))) ;; ;; Keys for response buffer ;; ;; TODO: use standard Emacs button behaviour here (cf Info mode) (define-key proof-response-mode-map [mouse-1] 'pg-goals-button-action) (define-key proof-response-mode-map [q] 'bury-buffer) (define-key proof-response-mode-map [c] 'pg-response-clear-displays) ;;;###autoload (defun proof-response-config-done () "Complete initialisation of a response-mode derived buffer." (setq font-lock-defaults '(proof-response-font-lock-keywords))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Window configuration ;; -- multiple frames for goals and response buffers, ;; -- three window mode ;; (defvar pg-response-special-display-regexp nil "Regexp for ‘display-buffer-alist’ for multiple frame use. Internal variable, setting this will have no effect!") (defconst proof-multiframe-parameters '((minibuffer . nil) (modeline . nil) ; ignored? (unsplittable . t) (menu-bar-lines . 0) (tool-bar-lines . nil) (proofgeneral . t)) ;; indicates generated for/by PG "List of GNU Emacs frame parameters for secondary frames.") (defun proof-multiple-frames-enable () (let ((display-buffer-entry (cons pg-response-special-display-regexp `((display-buffer-reuse-window display-buffer-pop-up-frame) . ((reusable-frames . t) (pop-up-frame-parameters . ,proof-multiframe-parameters)))))) (if proof-multiple-frames-enable (add-to-list 'display-buffer-alist display-buffer-entry) ;(add-to-list 'display-buffer-alist (proof-buffer-dislay)) (setq display-buffer-alist (delete display-buffer-entry display-buffer-alist)))) (proof-layout-windows)) (defun proof-three-window-enable () (proof-layout-windows)) (defun proof-guess-3win-display-policy (&optional policy) "Return the 3 windows mode layout policy from user choice POLICY. If POLICY is ’smart then guess the good policy from the current frame geometry, otherwise follow POLICY. See ‘proof-layout-windows’ for more details about POLICY." (if (eq policy 'smart) (cond ((>= (frame-width) (* 1.5 split-width-threshold)) 'horizontal) ((>= (frame-width) split-width-threshold) 'hybrid) (t 'vertical)) policy)) (defun proof-select-three-b (b1 b2 b3 &optional policy) "Put the three buffers B1, B2, and B3 into three windows. Following POLICY, which can be 'smart, 'horizontal, 'vertical, or 'hybrid. See ‘proof-layout-windows’ for more details about POLICY." (interactive "bBuffer1:\nbBuffer2:\nbBuffer3:") (delete-other-windows) (switch-to-buffer b1) (let ((pol (proof-guess-3win-display-policy policy))) (save-selected-window (cond ((eq pol 'hybrid) (split-window-horizontally) (other-window 1) (switch-to-buffer b2) (proof-safe-split-window-vertically) ; enlarge vertically if necessary (set-window-dedicated-p (selected-window) proof-three-window-enable) (other-window 1) (switch-to-buffer b3) (set-window-dedicated-p (selected-window) proof-three-window-enable)) ((eq pol 'vertical) (split-window-vertically) (other-window 1) (switch-to-buffer b2) (proof-safe-split-window-vertically) ; enlarge vertically if necessary (set-window-dedicated-p (selected-window) proof-three-window-enable) (other-window 1) (switch-to-buffer b3) (set-window-dedicated-p (selected-window) proof-three-window-enable)) ((eq pol 'horizontal) (split-window-horizontally) ; horizontally again (other-window 1) (switch-to-buffer b2) (enlarge-window (/ (frame-width) 6) t) ; take 2/3 of width before splitting again (split-window-horizontally) ; horizontally again (set-window-dedicated-p (selected-window) proof-three-window-enable) (other-window 1) (switch-to-buffer b3) (set-window-dedicated-p (selected-window) proof-three-window-enable)))))) (defun proof-display-three-b (&optional policy) "Layout three buffers in a single frame. Only do this if buffers exist. In this case, call ‘proof-select-three-b’ with argument POLICY." (interactive) (when (and (buffer-live-p proof-goals-buffer) (buffer-live-p proof-response-buffer)) (save-excursion (proof-select-three-b proof-script-buffer proof-goals-buffer proof-response-buffer policy)))) ;; this is a canidate for replacing proof-delete-other-frames below, less brutal. ;; For the moment we experiment this locall on coq mode. (defun proof-delete-all-associated-windows () "Delete windows (and maybe frames) showing associated buffers. Delete a frame if it displays only associated buffers, unless it is the only frame (try to bury buffers then)." (mapc (lambda (w) ;; try to delete window, or frame, or only bury buffer (if (not (frame-root-window-p w)) (delete-window w) (if (< 1 (length (frame-list))) (delete-frame (window-frame w)) (window--display-buffer (other-buffer) w 'window)))) (proof-associated-windows t))) (defvar pg-frame-configuration nil "Variable storing last used frame configuration.") ;; FIXME: would be nice to try storing this persistently. (defun pg-cache-frame-configuration () "Cache the current frame configuration, between prover restarts." (setq pg-frame-configuration (current-frame-configuration))) (defun proof-layout-windows () "Refresh the display of windows according to current display mode. For multiple frame mode, this function obeys the setting of `pg-response-eagerly-raise', which see. For single frame mode: - In two panes mode, this uses a canonical layout made by splitting Emacs windows in equal proportions. The splitting is vertical if Emacs width is smaller than `split-width-threshold' and horizontal otherwise. You can then adjust the proportions by dragging the separating bars. - In three pane mode, there are three display modes, depending where the three useful buffers are displayed: scripting buffer, goals buffer and response buffer. Here are the three modes: - vertical: the 3 buffers are displayed in one column. - hybrid: 2 columns mode, left column displays scripting buffer and right column displays the 2 others. - horizontal: 3 columns mode, one for each buffer (script, goals, response). By default, the display mode is automatically chosen by considering the current Emacs frame width: if it is smaller than `split-width-threshold' then vertical mode is chosen, otherwise if it is smaller than 1.5 * `split-width-threshold' then hybrid mode is chosen, finally if the frame is larger than 1.5 * `split-width-threshold' then the horizontal mode is chosen. You can change the value of `split-width-threshold' at your will. If you want to force one of the layouts, you can set variable `proof-three-window-mode-policy' to 'vertical, 'horizontal or 'hybrid. The default value is 'smart which sets the automatic behaviour described above." (interactive) (cond (proof-multiple-frames-enable ;; If we are coming from single frame mode, delete associated ;; windows (and only them). (delete-other-windows) ;; hope we're on the right frame/window (if proof-script-buffer (switch-to-buffer proof-script-buffer)) (proof-map-buffers (proof-associated-buffers) (if pg-response-eagerly-raise (proof-display-and-keep-buffer (current-buffer) nil 'force))) ;; Restore an existing frame configuration (seems buggy, typical) (if pg-frame-configuration (set-frame-configuration pg-frame-configuration 'nodelete))) (proof-three-window-enable ; single frame ;; If we are coming from multiple frame mode, delete associated ;; frames (and only them). (proof-delete-all-associated-windows) (set-window-dedicated-p (selected-window) nil) (proof-display-three-b proof-three-window-mode-policy)) ;; Two window mode. ;; Show the response buffer as first in preference order. (t ;; If we are coming from multiple frame mode, delete associated ;; frames (and only them). (proof-delete-all-associated-windows) (set-window-dedicated-p (selected-window) nil) (if (buffer-live-p proof-response-buffer) (proof-display-and-keep-buffer proof-response-buffer nil 'force)))) (pg-hint (pg-response-buffers-hint))) (defun proof-delete-other-frames () "Delete frames showing associated buffers." (save-selected-window ;; FIXME: this is a bit too brutal. If there is no ;; frame for the associated buffer, we may delete ;; the main frame!! (let ((mainframe (window-frame (if proof-script-buffer (proof-get-window-for-buffer proof-script-buffer) ;; We may lose with just selected window (selected-window))))) (proof-map-buffers (proof-associated-buffers) (let* ((win ;; NB: g-w-f-b will re-display in new frame if ;; the buffer isn't selected/visible. This causes ;; new frame to flash up and be deleted if already ;; deleted! ;; (proof-get-window-for-buffer (current-buffer)) ;; This next choice is probably better: (get-buffer-window (current-buffer) 'visible)) (fm (and win (window-frame win)))) (unless (equal mainframe fm) (if fm (delete-frame fm)))))))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Displaying in the response buffer ;; ;; Flag and function to keep response buffer tidy. (defvar pg-response-erase-flag nil "Non-nil means the response buffer should be cleared before next message.") ;;;###autoload (defun pg-response-maybe-erase (&optional erase-next-time clean-windows force keep) "Erase the response buffer, according to confusing flag combinations. Mainly, we look at `pg-response-erase-flag' and clear the response buffer if this is non-nil, but NOT the special symbol 'invisible. ERASE-NEXT-TIME is the new value for the flag. FORCE overrides the flag to force cleaning. KEEP overrides the flag to prevent cleaning. FORCE takes precedent over KEEP. If CLEAN-WINDOWS is set, use `proof-clean-buffer' to do the erasing, otherwise we use `bufhist-checkpoint-and-erase' to record an undo history entry for the current buffer contents. If the user option `proof-tidy-response' is nil, the buffer will never be cleared unless FORCE is set. No effect if there is no response buffer currently. Returns non-nil if response buffer was cleared." (when (buffer-live-p proof-response-buffer) (let ((doit (or (and proof-tidy-response (not keep) (not (eq pg-response-erase-flag 'invisible)) pg-response-erase-flag) force))) (if doit (if clean-windows (proof-clean-buffer proof-response-buffer) (with-current-buffer proof-response-buffer (let ((inhibit-read-only t)) (setq pg-response-next-error nil) ; all error msgs lost! (if (> (buffer-size) 0) (bufhist-checkpoint-and-erase)) (set-buffer-modified-p nil))))) (setq pg-response-erase-flag erase-next-time) doit))) (defun pg-response-display (str) "Show STR as a response in the response buffer." (pg-response-maybe-erase t nil) (pg-response-display-with-face str) ;; NB: this displays an empty buffer sometimes when it's not ;; so useful. It _is_ useful if the user has requested to ;; see the proof state and there is none ;; (Isabelle/Isar displayed nothing: might be better if it did). (proof-display-and-keep-buffer proof-response-buffer)) ;; ;; Images for the response buffer ;; ;(defimage pg-response-error-image ; ((:type xpm :file "/home/da/PG/images/epg-interrupt.xpm"))) ;(defimage pg-response-warning-image ; ((:type xpm :file "/home/da/PG/images/epg-abort.xpm"))) ;; TODO: this function should be combined with ;; pg-response-maybe-erase-buffer. ;;;###autoload (defun pg-response-display-with-face (str &optional face) "Display STR with FACE in response buffer." (cond ((member str '("" "\n"))) ; Quick exit, no display. (t (with-current-buffer proof-response-buffer (setq buffer-read-only nil) ;; da: I've moved newline before the string itself, to match ;; the other cases when messages are inserted and to cope ;; with warnings after delayed output (non newline terminated). (goto-char (point-max)) ;; insert a newline before the new message unless the ;; buffer is empty or proof-script-insert-newlines is nil (unless (or (not proof-script-insert-newlines) (bobp)) ;FIXME: Why not `bolp'? (newline)) (let ((start (point))) (if face (insert str) (funcall pg-insert-text-function str)) (unless (bolp) (newline)) (when face ;; FIXME: Why not (put-text-property start (point) 'face face)? (overlay-put (span-make start (point)) 'face face)) (setq buffer-read-only t) (set-buffer-modified-p nil)))))) (defun pg-response-clear-displays () "Clear Proof General response and tracing buffers. You can use this command to clear the output from these buffers when it becomes overly long. Particularly useful when `proof-tidy-response' is set to nil, so responses are not cleared automatically." (interactive) (proof-with-current-buffer-if-exists proof-response-buffer (if (> (buffer-size) 0) (let ((inhibit-read-only t)) (bufhist-checkpoint-and-erase) (set-buffer-modified-p nil)))) (proof-with-current-buffer-if-exists proof-trace-buffer (let ((inhibit-read-only t)) (erase-buffer) (set-buffer-modified-p nil))) (message "Response buffers cleared.")) ;;;###autoload (defun pg-response-message (&rest args) "Issue the message ARGS in the response buffer and display it." (pg-response-display-with-face (apply 'concat args)) (proof-display-and-keep-buffer proof-response-buffer)) ;;;####autoload (defun pg-response-warning (&rest args) "Issue the warning ARGS in the response buffer and display it. The warning is coloured with `proof-warning-face'." (pg-response-display-with-face (apply 'concat args) 'proof-warning-face) (proof-display-and-keep-buffer proof-response-buffer)) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Next error function. ;; ;;;###autoload (defun proof-next-error (&optional argp) "Jump to location of next error reported in the response buffer. A prefix arg specifies how many error messages to move; negative means move back to previous error messages. Optional argument ARGP means reparse the error message buffer and start at the first error." (interactive "P") (if (and pg-next-error-regexp (or (buffer-live-p proof-response-buffer) (error "Next error: no response buffer to parse!"))) (let ((wanted-error (or (and (not (consp argp)) (+ (prefix-numeric-value argp) (or pg-response-next-error 0))) (and (consp argp) 1) (or pg-response-next-error 1))) line column file errpos) (set-buffer proof-response-buffer) (goto-char (point-min)) (if (re-search-forward pg-next-error-regexp nil t wanted-error) (progn (setq errpos (save-excursion (goto-char (match-beginning 0)) (beginning-of-line) (point))) (setq line (match-string 2)) ; may be unset (if line (setq line (string-to-number line))) (setq column (match-string 3)) ; may be unset (if column (setq column (string-to-number column))) (setq pg-response-next-error wanted-error) (if (and pg-next-error-filename-regexp ;; Look for the most recently mentioned filename (re-search-backward pg-next-error-filename-regexp nil t)) (setq file (if (file-exists-p (match-string 2)) (match-string 2) ;; May need post-processing to extract filename (if pg-next-error-extract-filename (format pg-next-error-extract-filename (match-string 2)))))) ;; Now find the other buffer we need to display (let* ((errbuf (if file (find-file-noselect file) (or proof-script-buffer ;; Could make guesses, e.g. last active script (error "Next error: can't guess file for error message")))) (pop-up-windows t) (rebufwindow (or (get-buffer-window proof-response-buffer 'visible) ;; Pop up a window. (display-buffer proof-response-buffer (and proof-multiple-frames-enable (cons nil proof-multiframe-parameters)))))) ;; Make sure the response buffer stays where it is, ;; and make sure source buffer is visible (select-window rebufwindow) (pop-to-buffer errbuf) ;; Display the error message in the response buffer (set-window-point rebufwindow errpos) (set-window-start rebufwindow errpos) ;; Find the error location in the error buffer (set-buffer errbuf) ;; FIXME: no handling of selective display here (with-no-warnings ; "interactive only" (goto-line line)) (if (and column (> column 1)) (move-to-column (1- column))))) (setq pg-response-next-error nil) (error "Next error: couldn't find a next error"))))) ;;;###autoload (defun pg-response-has-error-location () "Return non-nil if the response buffer has an error location. See `pg-next-error-regexp'." (if pg-next-error-regexp (proof-with-current-buffer-if-exists proof-response-buffer (save-excursion (goto-char (point-min)) (re-search-forward pg-next-error-regexp nil t))))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Tracing buffers ;; (defcustom proof-trace-buffer-max-lines 10000 "The maximum size in lines for Proof General *trace* buffers. A value of 0 stands for unbounded." :type 'integer :group 'proof-shell) ;; An analogue of pg-response-display-with-face (defun proof-trace-buffer-display (start end) "Copy region START END from current buffer to end of the trace buffer." (let ((cbuf (current-buffer))) (with-current-buffer proof-trace-buffer (save-excursion (goto-char (point-max)) (let ((inhibit-read-only t)) (insert ?\n) (insert-buffer-substring cbuf start end) (unless (bolp) (insert ?\n))))))) (defun proof-trace-buffer-finish () "Call to complete a batch of tracing output. The buffer is truncated if its size is greater than `proof-trace-buffer-max-lines'." (if (> proof-trace-buffer-max-lines 0) (proof-with-current-buffer-if-exists proof-trace-buffer (save-excursion (goto-char (point-max)) (forward-line (- proof-trace-buffer-max-lines)) (let ((inhibit-read-only t)) (delete-region (point-min) (point))))))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Theorems buffer ;; ;; [ INCOMPLETE ] ;; ;; Revives an old idea from Isamode: a buffer displaying a bunch ;; of theorem names. ;; ;; (defun pg-thms-buffer-clear () "Clear the theorems buffer." (with-current-buffer proof-thms-buffer (let (start str) (goto-char (point-max)) (newline) (setq start (point)) ;FIXME: Unused! (insert str) ;FIXME: `str' is nil!!! (unless (bolp) (newline)) (set-buffer-modified-p nil)))) (provide 'pg-response) ;;; pg-response.el ends here PG-4.5/generic/pg-user.el000066400000000000000000001421071426357011200152160ustar00rootroot00000000000000;;; pg-user.el --- User level commands for Proof General -*- lexical-binding:t -*- ;; This file is part of Proof General. ;; Portions © Copyright 1994-2012 David Aspinall and University of Edinburgh ;; Portions © Copyright 2003-2019 Free Software Foundation, Inc. ;; Portions © Copyright 2001-2017 Pierre Courtieu ;; Portions © Copyright 2010, 2016 Erik Martin-Dorel ;; Portions © Copyright 2011-2013, 2016-2017 Hendrik Tews ;; Portions © Copyright 2015-2017 Clément Pit-Claudel ;; Author: David Aspinall and others ;; SPDX-License-Identifier: GPL-3.0-or-later ;;; Commentary: ;; ;; This file defines some user-level commands. Most of them ;; are script-based operations. Exported user-level commands ;; are defined here as autoloads to avoid circular requires. ;;; Code: (require 'span) (require 'scomint) (require 'proof-script) ; we build on proof-script (eval-when-compile (require 'cl-lib)) ;cl-decf (defvar which-func-modes) ; Defined by which-func. (declare-function proof-segment-up-to "proof-script") (declare-function proof-interrupt-process "proof-shell") ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Utilities: moving point in proof script buffer ;; ;; First: two commands for moving forwards in proof scripts. Moving ;; forward for a "new" command may insert spaces or new lines. Moving ;; forward for the "next" command does not. ;;;###autoload (defun proof-script-new-command-advance () "Move point to a nice position for a new command, possibly inserting spaces. Assumes that point is at the end of a command. No effect if `proof-next-command-insert-space' is nil." (interactive) (when proof-next-command-insert-space (let (sps) (if (and (proof-next-command-new-line) (setq sps (skip-chars-forward " \t")) ;; don't break existing lines (eolp)) (progn (newline) (unless proof-next-command-on-new-line (indent-relative)))) (unless (proof-next-command-new-line) ;; Multiple commands per line: skip spaces at point, and insert ;; the 1/0 number of spaces that were skipped in front of point ;; (at least one). This has the pleasing effect that the spacing ;; policy of the current line is copied: e.g. ; ;; ; Tab columns don't work properly, however. (let ((newspace (max (or sps 1) (skip-chars-forward " \t"))) (p (point))) (insert-char ?\040 newspace) (goto-char p)))))) (defun proof-maybe-follow-locked-end (&optional pos) "Move point according to `proof-follow-mode'. If optional POS is set, use that position, else `proof-queue-or-locked-end'. Assumes script buffer is current." (unless (or proof-autosend-running (eq proof-follow-mode 'ignore)) (let ((dest (or pos (proof-queue-or-locked-end)))) (cond ((eq proof-follow-mode 'locked) (goto-char dest) (or pos (proof-script-next-command-advance))) ((eq proof-follow-mode 'follow) (unless (pos-visible-in-window-p dest) (let ((win (get-buffer-window (current-buffer) t))) (if win (set-window-point win dest))))) ((and (eq proof-follow-mode 'followdown) (> dest (point))) (goto-char dest)))))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Further movement commands ;; (defun proof-goto-command-start () "Move point to start of current (or final) command of the script." (interactive) (let* ((cmd (span-at (point) 'type)) (start (if cmd (span-start cmd)))) (if start (progn ;; BUG: only works for unclosed proofs. (goto-char start)) (let ((semis (nth 1 (proof-segment-up-to (point) t)))) (if (eq 'unclosed-comment (car-safe semis)) (setq semis (cdr-safe semis))) (if (nth 2 semis) ; fetch end point of previous command (goto-char (nth 2 semis)) ;; no previous command: just next to end of locked (goto-char (proof-unprocessed-begin))))) ;; Oddities of this function: if we're beyond the last proof ;; command, it jumps back to the last command. Could alter this ;; by spotting that command end of last of semis is before ;; point. Also, behaviour with comments is different depending ;; on whether locked or not. (skip-chars-forward " \t\n"))) (defun proof-goto-command-end () "Set point to end of command at point." (interactive) (let ((cmd (span-at (point) 'type))) (if cmd (goto-char (span-end cmd)) (let ((semis (save-excursion (proof-segment-up-to-using-cache (point))))) (if semis (progn (goto-char (nth 2 (car semis))) (skip-chars-backward " \t\n") (unless (eq (point) (point-min)) (backward-char)))))))) (defun proof-forward-command (&optional num) "Move forward to the start of the next proof region. If called interactively, NUM is given by the prefix argument." (interactive "p") (skip-chars-forward " \t\n") (let* ((span (or (span-at (point) 'type) (and (skip-chars-backward " \t\n") (> (point) (point-min)) (span-at (1- (point)) 'type)))) (nextspan (and span (pg-numth-span-higher-or-lower (pg-control-span-of span) num 'noerr)))) (cond ((and nextspan (> num 0)) (goto-char (span-start nextspan)) (skip-chars-forward " \t\n")) ((and nextspan (< num 0)) (goto-char (span-end nextspan))) ((and span (> num 0)) (goto-char (span-end span))) ((and span (< num 0)) (goto-char (span-start span)))))) (defun proof-backward-command (&optional num) (interactive "p") (proof-forward-command (- num))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Processing commands ;; ;;;###autoload (defun proof-goto-point (&optional raw) "Assert or retract to the command at current position. Calls `proof-assert-until-point' or `proof-retract-until-point' as appropriate. With prefix argument RAW the omit proofs feature (`proof-omit-proofs-option') is temporaily disabled to check all proofs in the asserted region." (interactive "P") (let ((proof-omit-proofs-option proof-omit-proofs-option)) (when raw (setq proof-omit-proofs-option nil)) (save-excursion (if (> (proof-queue-or-locked-end) (point)) (proof-retract-until-point) (if (proof-only-whitespace-to-locked-region-p) (progn (skip-chars-forward " \t\n") (forward-char 1))) (proof-assert-until-point))))) (defun proof-assert-next-command-interactive () "Process until the end of the next unprocessed command after point. If inside a comment, just process until the start of the comment." (interactive) (proof-with-script-buffer ; for toolbar/other buffers (save-excursion (goto-char (proof-queue-or-locked-end)) (skip-chars-forward " \t\n") (proof-assert-until-point)) (proof-maybe-follow-locked-end))) ;; NB: "interactive" variant merely for a simple docstring. (defun proof-assert-until-point-interactive () "Process the region from the end of the locked-region until point. If inside a comment, just process until the start of the comment." (interactive) (proof-assert-until-point)) ;;;###autoload (defun proof-process-buffer (&optional raw) "Process the current (or script) buffer, and maybe move point to the end. With prefix argument RAW the omit proofs feature (`proof-omit-proofs-option') is temporaily disabled to check all proofs in the asserted region." (interactive "P") (let ((proof-omit-proofs-option proof-omit-proofs-option)) (when raw (setq proof-omit-proofs-option nil)) (proof-with-script-buffer (save-excursion (goto-char (point-max)) (proof-assert-until-point-interactive)) (proof-maybe-follow-locked-end)) (when proof-fast-process-buffer (message "Processing buffer...") (proof-shell-wait) (message "Processing buffer...done")))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Undoing commands ;; (defun proof-undo-last-successful-command () "Undo last successful command at end of locked region." (interactive) (proof-undo-last-successful-command-1)) (defun proof-undo-and-delete-last-successful-command () "Undo and delete last successful command at end of locked region. Useful if you typed completely the wrong command. Also handy for proof by pointing, in case the last proof-by-pointing command took the proof in a direction you don't like. Notice that the deleted command is put into the Emacs kill ring, so you can use the usual `yank' and similar commands to retrieve the deleted text." (interactive) (proof-undo-last-successful-command-1 'kill-region)) (defun proof-undo-last-successful-command-1 (&optional undo-action) "Undo last successful command at end of locked region. If optional UNDO-ACTION is non-nil, that function is called on the text region in the proof script after undoing." (interactive "P") (proof-with-script-buffer (let (lastspan) (save-excursion (unless (proof-locked-region-empty-p) (if (setq lastspan (span-at-before (proof-unprocessed-begin) 'type)) (progn (goto-char (span-start lastspan)) (proof-retract-until-point undo-action)) (error "Nothing to undo!")))) (if lastspan (proof-maybe-follow-locked-end (span-start lastspan)))))) (defun proof-retract-buffer (&optional called-interactively) "Retract the current buffer, and maybe move point to the start. Point is only moved according to `proof-follow-mode', if CALLED-INTERACTIVELY is non-nil, which is the case for all interactive calls." ;; The numeric prefix argument "p" is never nil, ;; see Section "Distinguish Interactive Calls" in the Elisp manual. (interactive "p") (proof-with-script-buffer (save-excursion (goto-char (point-min)) (proof-retract-until-point-interactive)) (if called-interactively (proof-maybe-follow-locked-end (point-min))))) (defun proof-retract-current-goal () "Retract the current proof, and move point to its start." (interactive) (let ((span (proof-last-goal-or-goalsave))) (save-excursion (if (and span (not (eq (span-property span 'type) 'goalsave)) (< (span-end span) (proof-unprocessed-begin))) (progn (goto-char (span-start span)) (proof-retract-until-point-interactive)) (error "Not proving"))) (if span (proof-maybe-follow-locked-end (span-start span))))) ;; ;; Mouse functions ;; (defun proof-mouse-goto-point (event) "Call `proof-goto-point' on the click position EVENT." (interactive "e") (proof-with-script-buffer (mouse-set-point event) (proof-goto-point) (proof-maybe-follow-locked-end))) ;; ;; Minibuffer non-scripting command ;; (defvar proof-minibuffer-history nil "History of proof commands read from the minibuffer.") (defun proof-minibuffer-cmd (cmd) "Send CMD to proof assistant. Interactively, read from minibuffer. The command isn't added to the locked region. If a prefix arg is given and there is a selected region, that is pasted into the command. This is handy for copying terms, etc from the script. If `proof-strict-state-preserving' is set, and `proof-state-preserving-p' is configured, then the latter is used as a check that the command will be safe to execute, in other words, that it won't ruin synchronization. If when applied to the command it returns false, then an error message is given. WARNING: this command risks spoiling synchronization if the test `proof-state-preserving-p' is not configured, if it is only an approximate test, or if `proof-strict-state-preserving' is off (nil)." (interactive (list (read-string "Command: " (if (and current-prefix-arg (region-active-p)) (replace-regexp-in-string "[ \t\n]+" " " (buffer-substring (region-beginning) (region-end)))) 'proof-minibuffer-history))) (if (and proof-strict-state-preserving proof-state-preserving-p (not (funcall proof-state-preserving-p cmd))) (error "Command is not state preserving, I won't execute it!")) (proof-shell-invisible-command cmd)) ;; ;; Frobbing locked end ;; ;; In fact, it's so risky, we'll disable it by default (put 'proof-frob-locked-end 'disabled t) (defun proof-frob-locked-end () "Move the end of the locked region backwards to regain synchronization. Only for use by consenting adults. This command can be used to repair synchronization in case something goes wrong and you want to tell Proof General that the proof assistant has processed less of your script than Proof General thinks. You should only use it to move the locked region to the end of a proof command." (interactive) (cond (proof-shell-busy (error "You can't use this command while %s is busy!" proof-assistant)) ((not (eq (current-buffer) proof-script-buffer)) (error "Must be in the active scripting buffer")) (t (proof-set-locked-end (point)) (span-delete-spans (proof-unprocessed-begin) (point-max) 'type)))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; ;;; Non-scripting proof assistant commands. ;;; ;; These are based on defcustom'd settings so that users may ;; re-configure the system to their liking. ;; ;; Helper macros and functions ;; ;; See put expression at end to give this indentation like while form (defmacro proof-if-setting-configured (var &rest body) "Give error if a configuration setting VAR is unset, otherwise eval BODY." `(if ,var (progn ,@body) (error "Proof General not configured for this: set %s" ,(symbol-name var)))) ;;;###autoload (defmacro proof-define-assistant-command (fn doc cmdvar &optional body) "Define FN (docstring DOC): check if CMDVAR is set, then send BODY to prover. BODY defaults to CMDVAR, a variable." `(defun ,fn () ,(concat doc (concat "\nIssues a command to the assistant based on " (symbol-name cmdvar) ".") "") (interactive) (proof-if-setting-configured ,cmdvar (proof-shell-invisible-command ,(or body cmdvar))))) ;;;###autoload (defmacro proof-define-assistant-command-witharg (fn doc cmdvar prompt &rest body) "Define FN (arg) with DOC: check CMDVAR is set, PROMPT a string and eval BODY. The BODY can contain occurrences of arg. CMDVAR is a variable holding a function or string. Automatically has history." `(progn (defvar ,(intern (concat (symbol-name fn) "-history")) nil ,(concat "History of arguments for " (symbol-name fn) ".")) (defun ,fn (arg) ,(concat doc "\nIssues a command based on ARG to the assistant, using " (symbol-name cmdvar) ".\n" "The user is prompted for an argument.") (interactive (proof-if-setting-configured ,cmdvar (if (stringp ,cmdvar) (list (format ,cmdvar (read-string ,(concat prompt ": ") "" ,(intern (concat (symbol-name fn) "-history"))))) (funcall ,cmdvar)))) ,@body))) (defun proof-issue-new-command (cmd) "Insert CMD into the script buffer and issue it to the proof assistant. If point is in the locked region, move to the end of it first. Start up the proof assistant if necessary." (proof-with-script-buffer (if (proof-shell-live-buffer) (if (proof-in-locked-region-p) (proof-goto-end-of-locked t))) (proof-script-new-command-advance) (insert cmd) (proof-assert-until-point-interactive) (proof-script-new-command-advance))) ;; ;; Commands which do not require a prompt and send an invisible ;; command. ;; (proof-define-assistant-command proof-prf "Show the current proof state." proof-showproof-command (progn (pg-goals-buffers-hint) proof-showproof-command)) (proof-define-assistant-command proof-ctxt "Show the current context." proof-context-command) (proof-define-assistant-command proof-help "Show a help or information message from the proof assistant. Typically, a list of syntax of commands available." proof-info-command) (proof-define-assistant-command proof-cd "Change directory to the default directory for the current buffer." proof-shell-cd-cmd (proof-format-filename proof-shell-cd-cmd default-directory)) (defun proof-cd-sync () "If `proof-shell-cd-cmd' is set, do `proof-cd' and wait for prover ready. This is intended as a value for `proof-activate-scripting-hook'" ;; The hook is set in proof-mode before proof-shell-cd-cmd may be set, ;; so we explicitly test it here. (when proof-shell-cd-cmd (proof-cd) (proof-shell-wait))) ;; ;; Commands which require an argument, and maybe affect the script. ;; (proof-define-assistant-command-witharg proof-find-theorems "Search for items containing given constants." proof-find-theorems-command "Find theorems containing" (proof-shell-invisible-command arg)) (proof-define-assistant-command-witharg proof-issue-goal "Write a goal command in the script, prompting for the goal." proof-goal-command "Goal" ; Goals always start at a new line (let ((proof-next-command-on-new-line t)) (proof-issue-new-command arg))) (proof-define-assistant-command-witharg proof-issue-save "Write a save/qed command in the script, prompting for the theorem name." proof-save-command "Save as" ; Saves always start at a new line (let ((proof-next-command-on-new-line t)) (proof-issue-new-command arg))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Electric terminator mode ;; ;; Register proof-electric-terminator as a minor mode. (or (assq 'proof-electric-terminator-enable minor-mode-alist) (setq minor-mode-alist (append minor-mode-alist (list '(proof-electric-terminator-enable (:eval (if (eq major-mode proof-mode-for-script) proof-terminal-string))))))) ;;;###autoload (defun proof-electric-terminator-enable (&optional arg) "Ensure modeline update to display new value for electric terminator. This a function is called by the custom-set property 'proof-set-value. It can also be used as a minor mode function: with ARG, turn on iff ARG>0" (unless (null arg) (setq proof-electric-terminator-enable (> (prefix-numeric-value arg) 0))) (force-mode-line-update)) (proof-deftoggle proof-electric-terminator-enable proof-electric-terminator-toggle) (defun proof-electric-terminator (&optional count) "Insert terminator char, maybe sending the command to the assistant. If we are inside a comment or string, insert the terminator. Otherwise, if the variable `proof-electric-terminator-enable' is non-nil, the command will be sent to the assistant. To side-step the electric action and possibly insert multiple characters, pass a non-nil COUNT arg, e.g. a numeric prefix such as M-3 ." (interactive "P") (if (and (not count) proof-electric-terminator-enable (not (proof-inside-comment (point))) (not (proof-inside-string (point)))) (proof-assert-electric-terminator) (self-insert-command (prefix-numeric-value count)))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Completion based on -completion-table ;; ;; Requires completion.el package. Completion is usually a hand-wavy ;; thing, so we don't attempt to maintain a precise completion table. ;; (defun proof-add-completions () "Add completions from -completion-table to completion database. Uses `add-completion' with a negative number of uses and ancient last use time, to discourage saving these into the users database." (interactive) (require 'completion) (defvar completion-min-length) (declare-function add-completion "completion" (string &optional num-uses last-use-time)) (when (> (length proof-assistant) 0) (mapcar (lambda (cmpl) ;; completion gives error; trapping is tricky so test again (if (>= (length cmpl) completion-min-length) (add-completion cmpl -1000 0))) (proof-ass completion-table)))) ;; NB: completion table is expected to be set when proof-script ;; is loaded! Call `proof-script-add-completions' to update. (eval-after-load "completion" '(proof-add-completions)) (defun proof-script-complete (&optional arg) "Like `complete' but case-fold-search set to `proof-case-fold-search'." (interactive "*p") ;; completion not autoloaded in GNU Emacs ;; FIXME: It's probably because we shouldn't use it ;-) (require 'completion) (declare-function complete "completion" (&optional arg)) (let ((case-fold-search proof-case-fold-search)) (complete arg))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Span manipulation ;; (defun pg-copy-span-contents (span) "Copy contents of SPAN to kill ring, sans surrounding whitespace." (copy-region-as-kill (save-excursion (goto-char (span-start span)) (skip-chars-forward " \t\n") (point)) (save-excursion (goto-char (span-end span)) (skip-chars-backward " \t\n") (point))) (if (fboundp 'own-clipboard) ;; XEmacs function (own-clipboard (car kill-ring)))) (defun pg-numth-span-higher-or-lower (span num &optional noerr) "Find NUM'th span after/before SPAN. NUM is positive for after." (unless (and span (<= (span-end span) (proof-unprocessed-begin))) (if noerr nil (error "No processed region under point"))) (let ((downflag (> num 0)) (num (abs num)) nextspan) (while (and (> num 0) (setq nextspan (if downflag (next-span span 'type) (prev-span span 'type))) (if downflag ;; If moving down, check we don't go beyond ;; end of processed region (<= (span-end span) (proof-unprocessed-begin)) t)) (setq num (1- num)) (setq span nextspan)) (if (= num 0) span (if noerr nil (error "No region to move past"))))) (defun pg-control-span-of (span) "Return the controlling span of SPAN, or SPAN itself." (or (span-property span 'controlspan) span)) ;; Really a drag-and-drop interface for this would be nice. (defun pg-move-span-contents (span num) "Move SPAN up/downwards in the buffer, past NUM spans. If NUM is negative, move upwards. Return new span." (save-excursion (let ((downflag (> num 0)) nextspan) ;; Always move a control span instead; it contains ;; children span which move together with it. (setq span (pg-control-span-of span)) (setq nextspan (pg-numth-span-higher-or-lower span num)) ;; We're going to move the span to before/after nextspan. ;; First make sure inserting there doesn't extend the span. (if downflag (span-set-property nextspan 'end-open t) (span-set-property nextspan 'start-open t)) ;; When we delete the span, we want to duplicate it ;; to recreate in the new position. (span-set-property span 'duplicable 't) ;; TODO: this is faulty: moving span up gives children ;; list with single nil element. Hence liveness test (mapc (lambda (s) (if (span-live-p s) (span-set-property s 'duplicable 't))) (span-property span 'children)) (let* ((start (span-start span)) (end (span-end span)) (contents (buffer-substring start end)) ;; Locked end may move up when we delete ;; region: we'll make sure to reset it ;; again later, it shouldn't change. ;; NB: (rely on singlethreadedness here, so ;; lockedend doesn't move while in this code). (lockedend (span-end proof-locked-span))) (let ((inhibit-read-only t)) ;; TODO: undo behaviour isn't quite right yet. (undo-boundary) (delete-region start end) (let ((insertpos (if downflag (span-end nextspan) (span-start nextspan)))) (goto-char insertpos) ;; Let XEmacs duplicate extents as needed, then repair ;; their associations (insert contents) (let ((new-span (span-at insertpos 'type)));should be one we deleted. (span-set-property new-span 'children (pg-fixup-children-spans new-span insertpos (point))) (span-set-end proof-locked-span lockedend) (undo-boundary) new-span))))))) (defun pg-fixup-children-spans (new-parent start end) (append (span-mapcar-spans (lambda (span) (if (span-property span 'controlspan) (progn (span-set-property span 'controlspan new-parent) (list span)))) start end 'type))) (defun pg-move-region-down (&optional num) "Move the region under point downwards in the buffer, past NUM spans." (interactive "p") (let ((span (span-at (point) 'type))) (and span (goto-char (span-start (pg-move-span-contents span num))) (skip-chars-forward " \t\n")))) (defun pg-move-region-up (&optional num) "Move the region under point upwards in the buffer, past NUM spans." (interactive "p") (pg-move-region-down (- num))) ;; No key-binding is defined for these two functions: (defun pg-show-all-proofs () "Display all completed proofs in the buffer." (interactive) (pg-show-all-portions 'proof)) (defun pg-hide-all-proofs () "Hide all completed proofs in the buffer." (interactive) (pg-show-all-portions 'proof 'hide)) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Context menus inside spans ;; (defun pg-pos-for-event (event) "Return position corresponding to position of a mouse click EVENT." (with-current-buffer (window-buffer (posn-window (event-start event))) (posn-point (event-start event)))) (defun pg-span-for-event (event) "Return span corresponding to position of a mouse click EVENT." (span-at (pg-pos-for-event event) 'type)) (defun pg-span-context-menu (event) "Display a context sensitive menu for proof script, around EVENT." (interactive "e") (let* ((span (pg-span-for-event event)) cspan) (when span ;; Find controlling span (while (setq cspan (span-property span 'controlspan)) (setq span cspan)) (let* ((idiom (and span (span-property span 'idiom))) (id (and span (span-property span 'id)))) (popup-menu (pg-create-in-span-context-menu span idiom (if id (symbol-name id)))))))) (defun pg-toggle-visibility () "Toggle visibility of region under point." (interactive) (let* ((span (span-at (point) 'type)) (idiom (and span (span-property span 'idiom))) (id (and span (span-property span 'id)))) (and idiom id (pg-toggle-element-visibility idiom (symbol-name id))))) (defun pg-create-in-span-context-menu (span idiom name) "Create the dynamic context-sensitive menu for a span." (append (list (pg-span-name span)) (list (vector "Show/hide" (if idiom (list 'pg-toggle-element-visibility `(quote ,idiom) name)) (not (not idiom)))) (list (vector "Copy" (list 'pg-copy-span-contents span) t)) (list (vector "Undo" (list 'pg-span-undo span) t)) ;; PG 4.1: these commands are neither very useful nor reliable ;; (list (vector ;; "Move up" (list 'pg-move-span-contents span -1) ;; (pg-numth-span-higher-or-lower (pg-control-span-of span) -1 'noerr))) ;; (list (vector ;; "Move down" (list 'pg-move-span-contents span 1) ;; (pg-numth-span-higher-or-lower (pg-control-span-of span) 1 'noerr))) (if proof-script-span-context-menu-extensions (funcall proof-script-span-context-menu-extensions span idiom name)) (if proof-shell-theorem-dependency-list-regexp (proof-dependency-in-span-context-menu span)))) (defun pg-span-undo (span) "Undo to the start of the given SPAN." (interactive) (goto-char (span-start span)) (proof-retract-until-point)) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Message buffer hints ;; (defun pg-goals-buffers-hint () (pg-hint "Use \\\\[proof-display-some-buffers] to rotate output buffers; \\\\[pg-response-clear-displays] to clear response & trace.")) ;;;###autoload (defun pg-slow-fontify-tracing-hint () (pg-hint "Large tracing output; refreshing intermittently. Use \\\\[pg-response-clear-displays] to clear trace.")) ;;;###autoload (defun pg-response-buffers-hint (&optional nextbuf) (unless (not (buffer-live-p proof-goals-buffer)) (pg-hint (format "\\[proof-prf] for goals;%s \\[proof-layout-windows] refreshes" (if (or proof-three-window-enable proof-multiple-frames-enable) "" (format " \\[proof-display-some-buffers] rotates output%s;" (if nextbuf (concat " (next:" nextbuf ")") ""))))))) ;;;###autoload (defun pg-jump-to-end-hint () (pg-hint "Use \\[proof-goto-end-of-locked] to jump to end of processed region")) ;;;###autoload (defun pg-processing-complete-hint () "Display hint for showing end of locked region or processing complete." (if (buffer-live-p proof-script-buffer) (let ((win (get-buffer-window proof-script-buffer))) (unless ;; end of locked already displayed (and win (pos-visible-in-window-p (proof-unprocessed-begin))) (with-current-buffer proof-script-buffer (cond ((proof-locked-region-empty-p)) ;; nothing if empty ((proof-locked-region-full-p) (pg-hint (concat "Processing complete in " (buffer-name proof-script-buffer)))) ((not proof-autosend-running) ;; partly complete: hint about displaying the locked end (pg-jump-to-end-hint)))))))) ;;;###autoload (defun pg-next-error-hint () "Display hint for locating error." (pg-hint "Use \\[proof-next-error] to go to next error location.")) ;;;###autoload (defun pg-hint (hintmsg) "Display a hint HINTMSG in the minibuffer, if `pg-show-hints' is non-nil. The function `substitute-command-keys' is called on the argument." (if pg-show-hints (message (substitute-command-keys hintmsg)))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Symbol near point/identifier under mouse query ;; (defun pg-identifier-under-mouse-query (event) "Query the prover about the identifier near mouse click EVENT." (interactive "e") (if proof-query-identifier-command (save-selected-window (save-excursion (mouse-set-point event) (pg-identifier-near-point-query))))) ;;;###autoload (defun pg-identifier-near-point-query () "Query the prover about the identifier near point. If the result is successful, we add a span to the buffer which has a popup with the information in it." (interactive) (let* ((stend (if (region-active-p) (cons (region-beginning) (region-end)) (pg-current-word-pos))) (start (car-safe stend)) (end (cdr-safe stend)) (identifier (if start (buffer-substring-no-properties start end))) (ctxt (if start (save-excursion (goto-char start) (proof-buffer-syntactic-context))))) (if start (pg-identifier-query identifier ctxt ;; the callback (lambda (_) (save-excursion (let ((idspan (span-make start end))) ;; (span-set-property idspan 'priority 90) ; highest (span-set-property idspan 'help-echo (pg-last-output-displayform))))))))) (defvar proof-query-identifier-history nil "History for `proof-query-identifier'.") (defun proof-query-identifier (string) "Query the prover about the identifier STRING. If called interactively, STRING defaults to the current word near point." (interactive (list (completing-read "Query identifier: " nil nil nil (current-word) 'proof-query-identifier-history))) (if string (pg-identifier-query string))) (defun pg-identifier-query (identifier &optional ctxt callback) "Query the proof assisstant about the given IDENTIFIER. This uses `proof-query-identifier-command'. Parameter CTXT allows to give a context for the identifier (which allows for multiple name spaces). If CALLBACK is set, we invoke that when the command completes." (unless (or (null identifier) (string-equal identifier "")) ;; or whitespace? (proof-shell-invisible-command (cond ((stringp proof-query-identifier-command) ;; simple customization (format proof-query-identifier-command identifier)) (t ;; buffer-syntactic context dependent, as an alist ;; (handy for Isabelle: not a true replacement for parsing) (format (nth 1 (assq ctxt proof-query-identifier-command)) identifier))) nil ; no wait callback))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Imenu and Speedbar ;; (declare-function speedbar-add-supported-extension "speedbar") (eval-after-load "speedbar" '(and proof-assistant-symbol ;; *should* be set by now (speedbar-add-supported-extension (nth 2 (assoc proof-assistant-symbol proof-assistant-table))))) ;;;###autoload (defun proof-imenu-enable () "Add or remove index menu." ;; NB: next two a bit interferring, but we suppose use-case is PG. (which-function-mode (if proof-imenu-enable 1 0)) (when (listp which-func-modes) ;; FIXME: It's not PG's business to decide whether to use ;; which-function-mode. (add-to-list 'which-func-modes proof-mode-for-script)) (if proof-imenu-enable (imenu-add-to-menubar "Index") (progn (when (listp which-func-modes) (setq which-func-modes (remove proof-mode-for-script which-func-modes))) (let ((oldkeymap (keymap-parent (current-local-map)))) (if ;; sanity checks in case someone else set local keymap (and oldkeymap (lookup-key (current-local-map) [menu-bar index]) (not (lookup-key oldkeymap [menu-bar index]))) (use-local-map oldkeymap))) (remove-hook 'menu-bar-update-hook 'imenu-update-menubar)))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Command history ;; ;; This implements a history ring for commands in the locked region. ;; Inspired by (and code heavily copied from) comint. ;; ;; The current behaviour is not ideal: we only extend the input ring as ;; we process (so history does not browse pink text while the ;; prover is busy). Moreover, instead of using a history, we might ;; simply parse commands backwards (or forwards) in the buffer. ;; (i.e, more like the copying behaviour implemented in Bibtex mode). ;; (defvar pg-input-ring nil "Ring of previous inputs.") (defvar pg-input-ring-index nil "Position of last matched command.") (defvar pg-stored-incomplete-input nil "Stored incomplete input: string between point and locked.") (defun pg-previous-input (arg) "Cycle backwards through input history, saving input. If called interactively, ARG is given by the prefix argument." (interactive "*p") (if (and pg-input-ring-index (or ; leaving the "end" of the ring (and (< arg 0) ; going down (eq pg-input-ring-index 0)) (and (> arg 0) ; going up (eq pg-input-ring-index (1- (ring-length pg-input-ring))))) pg-stored-incomplete-input) (pg-restore-input) (pg-previous-matching-input "." arg))) (defun pg-next-input (arg) "Cycle forwards through input history. If called interactively, ARG is given by the prefix argument." (interactive "*p") (pg-previous-input (- arg))) (defun pg-delete-input () (let* ((unproc (proof-unprocessed-begin)) (start (save-excursion (goto-char unproc) (skip-chars-forward " \t\n") (point))) (end (point-at-eol))) (cond ((< start end) (delete-region start end)) ((< start (point-at-eol)) (delete-region start (point-at-eol)))))) (defun pg-get-old-input () "Return text between end of locked region and point, up to EOL. If there is no text, return the empty string." (let* ((unproc (proof-unprocessed-begin)) (start (save-excursion (goto-char unproc) (skip-chars-forward " \t\n") (point))) (end (point-at-eol))) (if (< start end) (buffer-substring-no-properties start end) nil))) (defun pg-restore-input () "Restore unfinished input." (interactive) (when pg-input-ring-index (pg-delete-input) (when (> (length pg-stored-incomplete-input) 0) (insert pg-stored-incomplete-input) (message "Input restored")) (setq pg-input-ring-index nil))) (defun pg-search-start (arg) "Index to start a directional search, starting at `pg-input-ring-index'." (if pg-input-ring-index ;; If a search is running, offset by 1 in direction of arg (mod (+ pg-input-ring-index (if (> arg 0) 1 -1)) (ring-length pg-input-ring)) ;; For a new search, start from beginning or end, as appropriate (if (>= arg 0) 0 ; First elt for forward search (1- (ring-length pg-input-ring))))) ; Last elt for backward search (defun pg-regexp-arg (prompt) "Return list of regexp and prefix arg using PROMPT." (let* (;; Don't clobber this. (last-command last-command) (regexp (read-from-minibuffer prompt nil nil nil 'minibuffer-history-search-history))) (list (if (string-equal regexp "") (setcar minibuffer-history-search-history (nth 1 minibuffer-history-search-history)) regexp) (prefix-numeric-value current-prefix-arg)))) (defun pg-search-arg (arg) ;; First make sure there is a ring and that we are after the process mark (cond ((not (>= (point) (proof-unprocessed-begin))) (error "Not in unlocked region")) ((or (null pg-input-ring) (ring-empty-p pg-input-ring)) (error "Empty input ring")) ((zerop arg) ;; arg of zero resets search from beginning, and uses arg of 1 (setq pg-input-ring-index nil) 1) (t arg))) (defun pg-previous-matching-input-string-position (regexp arg &optional start) "Return the index matching REGEXP ARG places along the input ring. Moves relative to START, or `pg-input-ring-index'." (if (or (not (ring-p pg-input-ring)) (ring-empty-p pg-input-ring)) (error "No history")) (let* ((len (ring-length pg-input-ring)) (motion (if (> arg 0) 1 -1)) (n (mod (- (or start (pg-search-start arg)) motion) len)) (tried-each-ring-item nil) (prev nil)) ;; Do the whole search as many times as the argument says. (while (and (/= arg 0) (not tried-each-ring-item)) ;; Step once. (setq prev n n (mod (+ n motion) len)) ;; If we haven't reached a match, step some more. (while (and (< n len) (not tried-each-ring-item) (not (string-match regexp (ring-ref pg-input-ring n)))) (setq n (mod (+ n motion) len) ;; If we have gone all the way around in this search. tried-each-ring-item (= n prev))) (setq arg (if (> arg 0) (1- arg) (1+ arg)))) ;; Now that we know which ring element to use, if we found it, return that. (if (string-match regexp (ring-ref pg-input-ring n)) n))) (defun pg-previous-matching-input (regexp n) "Search backwards through input history for match for REGEXP. \(Previous history elements are earlier commands.) With prefix argument N, search for Nth previous match. If N is negative, find the next or Nth next match." (interactive (pg-regexp-arg "Previous input matching (regexp): ")) (setq n (pg-search-arg n)) (let ((pos (pg-previous-matching-input-string-position regexp n))) ;; Has a match been found? (if (null pos) (error "Match not found for regexp %s" regexp) ;; If leaving the edit line, save partial input (if (null pg-input-ring-index) ;not yet on ring (setq pg-stored-incomplete-input (pg-get-old-input))) (setq pg-input-ring-index pos) (message "History item: %d" (1+ pos)) (pg-delete-input) (insert (ring-ref pg-input-ring pos))))) (defun pg-next-matching-input (regexp n) "Search forwards through input history for match for REGEXP. \(Later history elements are more recent commands.) With prefix argument N, search for Nth following match. If N is negative, find the previous or Nth previous match." (interactive (pg-regexp-arg "Next input matching (regexp): ")) (pg-previous-matching-input regexp (- n))) (defvar pg-matching-input-from-input-string "" "Input previously used to match input history.") ;;;###autoload (defun pg-previous-matching-input-from-input (n) "Search backwards through input history for match for current input. \(Previous history elements are earlier commands.) With prefix argument N, search for Nth previous match. If N is negative, search forwards for the -Nth following match." (interactive "p") (if (not (memq last-command '(pg-previous-matching-input-from-input pg-next-matching-input-from-input))) ;; Starting a new search (setq pg-matching-input-from-input-string (pg-get-old-input) pg-input-ring-index nil)) (if pg-matching-input-from-input-string (pg-previous-matching-input (concat "^" (regexp-quote pg-matching-input-from-input-string)) n) (pg-previous-matching-input "." n))) ;;;###autoload (defun pg-next-matching-input-from-input (n) "Search forwards through input history for match for current input. \(Following history elements are more recent commands.) With prefix argument N, search for Nth following match. If N is negative, search backwards for the -Nth previous match." (interactive "p") (pg-previous-matching-input-from-input (- n))) ;;;###autoload (defun pg-add-to-input-history (cmd) "Maybe add CMD to the input history. CMD is only added to the input history if it is not a duplicate of the last item added." (when (or (not (ring-p pg-input-ring)) (ring-empty-p pg-input-ring) (not (string-equal (ring-ref pg-input-ring 0) cmd))) (unless (ring-p pg-input-ring) (setq pg-input-ring (make-ring pg-input-ring-size))) (ring-insert pg-input-ring cmd))) ;;;###autoload (defun pg-remove-from-input-history (cmd) "Maybe remove CMD from the end of the input history. This is called when the command is undone. It's only removed if it matches the last item in the ring." (if (and (ring-p pg-input-ring) (not (ring-empty-p pg-input-ring)) (string-equal (ring-ref pg-input-ring 0) cmd)) (ring-remove pg-input-ring 0))) ;;;###autoload (defun pg-clear-input-ring () (setq pg-input-ring nil)) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Protected undo (added in PG 4.0) ;; ;; From a suggestion of Stefan Monnier as an improvement over the ;; previous use of `undo-make-selective-list' to hack ;; `buffer-undo-list' in `proof-set-queue-endpoints'. ;; ;; Improved version due to Erik Martin-Dorel. Uses auxiliary ;; functions `pg-protected-undo-1' and `next-undo-elt' ;; (define-key proof-mode-map [remap undo] 'pg-protected-undo) (define-key proof-mode-map [remap advertised-undo] 'pg-protected-undo) (defun pg-protected-undo (&optional arg) "As `undo' but avoids breaking the locked region. A numeric ARG serves as a repeat count. If called interactively, ARG is given by the prefix argument. If ARG is omitted, nil, or not numeric, it takes the value 1. It performs each of the desired undos checking that these operations will not affect the locked region, obeying `proof-strict-read-only' if required. If strict read only behaviour is enforced, the user is queried whether to retract before the undo is allowed. If automatic retraction is enabled, the retract and undo will go ahead without querying the user. Moreover, undo/redo is always allowed in comments located in \ the locked region." (interactive "*P") (if (or (not proof-locked-span) (equal (proof-queue-or-locked-end) (point-min))) (undo arg) (let ((repeat ; Allow the user to perform successive undos at once (if (numberp arg) (prefix-numeric-value arg) ; arg is a raw prefix argument 1)) (newarg ; Allow the user to limit the undo to the current region (and ;; this Boolean expression is necessary to match ;; the behavior of GNU Emacs (23.2) undo function (or (region-active-p) (and arg (not (numberp arg)))) (> (region-end) (region-beginning))))) (while (> repeat 0) (pg-protected-undo-1 newarg) ; do some safe undos step by step (setq last-command 'undo) ; need for this assignment meanwhile (cl-decf repeat))))) (defun pg-protected-undo-1 (arg) "This function is intended to be called by `pg-protected-undo'. The flag ARG is passed to functions `undo' and `next-undo-elt'. It should be a non-numeric value saying whether an undo-in-region behavior is expected." ;; Note that if ARG is non-nil, (> (region-end) (region-beginning)) must hold, ;; at least for the first call from the loop of `pg-protected-undo'. (setq arg (and arg (not (numberp arg)))) ; ensure arg is boolean (if (or (not proof-locked-span) (equal (proof-queue-or-locked-end) (point-min))) ; required test (undo arg) (let* ((next (next-undo-elt arg)) (delta (undo-delta next)) ; can be '(0 . 0) if next is nil (beg (car delta)) (end (max beg (- beg (cdr delta))))) ; Key computation (when (and next (> beg 0) ; the "next undo elt" exists (> (proof-queue-or-locked-end) beg) proof-strict-read-only ; edit freely doesn't retract (not (and ; neither does edit in comments (proof-inside-comment beg) (proof-inside-comment end)))) (if (or (eq proof-strict-read-only 'retract) (y-or-n-p "Next undo will modify read-only region, retract? ")) (proof-retract-before-change beg end) (when (eq last-command 'undo) (setq this-command 'undo)) ;; now we can stop the function without breaking possible undo chains (error "Cannot undo without retracting to the appropriate position"))) (undo arg)))) (defun next-undo-elt (arg) "Return the undo element that will be processed on next undo/redo. Assume the undo-in-region behavior will apply if ARG is non-nil." (let ((undo-list (if arg ; handle "undo in region" (undo-make-selective-list (region-beginning) (region-end)) ; can be '(nil) buffer-undo-list))) ; can be nil (if (or (null undo-list) (equal undo-list (list nil))) nil ; there is clearly no undo elt (while (and undo-list ; to ensure it will terminate (let ((elt (car undo-list))) (not (and (consp elt) (or (stringp (car elt)) (integerp (car elt))))))) (setq undo-list (cdr undo-list))) ; get the last undo record (if (and (eq last-command 'undo) (or (eq pending-undo-list t) (gethash undo-list undo-equiv-table))) ;; then we are within a run of consecutive undo commands (if (eq pending-undo-list t) nil (car pending-undo-list)) (car undo-list))))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Automatic processing of buffer ahead of point ;; ;; Added in PG 4.0 ;; (defvar proof-autosend-timer nil "Timer used by autosend.") (deflocal proof-autosend-modified-tick nil "Records 'buffer-chars-modified-tick' since last autosend.") ;;;###autoload (defun proof-autosend-enable (&optional nomsg) "Enable or disable autosend behaviour." (if proof-autosend-timer (cancel-timer proof-autosend-timer)) (when proof-autosend-enable (setq proof-autosend-timer (run-with-idle-timer proof-autosend-delay t 'proof-autosend-loop)) (setq proof-autosend-modified-tick nil) (unless nomsg (message "Automatic sending turned on."))) (when (not proof-autosend-enable) (setq proof-autosend-timer nil) (unless nomsg (message "Automatic sending turned off.")))) (defun proof-autosend-delay () "Adjust autosend timer when variable `proof-autosend-delay' changes." (proof-autosend-enable t)) (defun proof-autosend-loop () (proof-with-current-buffer-if-exists proof-script-buffer (unless (or (proof-locked-region-full-p) proof-shell-busy ;; TODO: re-engage autosend after C-c C-n even if not modified. (eq (buffer-chars-modified-tick) proof-autosend-modified-tick) (and proof-autosend-all (eq proof-shell-last-queuemode 'retracting))) (let ((proof-autosend-running t)) (setq proof-autosend-modified-tick (buffer-chars-modified-tick)) (if proof-autosend-all (proof-autosend-loop-all) (proof-autosend-loop-next)))))) (defun proof-autosend-loop-all () "Send commands from the script until an error, complete, or input appears." (message "Sending commands to prover...") (unwind-protect (progn (save-excursion (goto-char (point-max)) (proof-assert-until-point (if proof-multiple-frames-enable 'no-minibuffer-messages ; nb: not API '(no-response-display no-error-display no-goals-display)))) (proof-shell-wait t) ; interruptible (cond ((eq proof-shell-last-output-kind 'error) (message "Sending commands to prover...error")) ((and (input-pending-p) proof-shell-busy) (proof-interrupt-process) (message "Sending commands to prover...interrupted") (proof-shell-wait)) (t (message "Sending commands to prover...done")))))) (defun proof-autosend-loop-next () "Send the next command from the script and indicate its success/otherwise." (unwind-protect (let ((qol (proof-queue-or-locked-end))) (save-excursion ;(goto-char qol) ;(skip-chars-forward " \t\n") (message "Trying next commands in prover...") (proof-assert-until-point (if proof-multiple-frames-enable 'no-minibuffer-messages ; nb: not API '(no-response-display no-error-display no-goals-display)))) (let ((proof-sticky-errors t)) (proof-shell-wait t)) ; interruptible (cond ((eq proof-shell-last-output-kind 'error) (message "Trying next commands in prover...error")) ((and (input-pending-p) proof-shell-busy) (proof-interrupt-process) (message "Trying next commands in prover...interrupted") (proof-shell-wait)) (t (message "Trying next commands in prover...OK"))) ;; success: now undo in prover, highlight undone spans if OK (unless (eq qol (proof-queue-or-locked-end)) ; no progress (save-excursion (goto-char qol) (proof-retract-until-point (lambda (beg end) (span-make-self-removing-span (save-excursion (goto-char beg) (skip-chars-forward " \t\n") (point)) end 'face 'highlight)) '(no-response-display no-error-display no-goals-display))))))) (provide 'pg-user) ;;; pg-user.el ends here PG-4.5/generic/pg-vars.el000066400000000000000000000257761426357011200152270ustar00rootroot00000000000000;;; pg-vars.el --- Proof General global variables ;; This file is part of Proof General. ;; Portions © Copyright 1994-2012 David Aspinall and University of Edinburgh ;; Portions © Copyright 2003, 2012, 2014 Free Software Foundation, Inc. ;; Portions © Copyright 2001-2017 Pierre Courtieu ;; Portions © Copyright 2010, 2016 Erik Martin-Dorel ;; Portions © Copyright 2011-2013, 2016-2017 Hendrik Tews ;; Portions © Copyright 2015-2017 Clément Pit-Claudel ;; Author: David Aspinall and others ;; SPDX-License-Identifier: GPL-3.0-or-later ;;; Commentary: ;; ;; Global variables used in several files. ;; ;; ;;; Code: ;;; ;;; Early variables ;;; (defvar proof-assistant-cusgrp nil "Symbol for the customization group of user options for the proof assistant. Do not change this variable! It is set automatically by the mode stub defined in proof-site, from the name given in ‘proof-assistant-table’.") (defvar proof-assistant-internals-cusgrp nil "Symbol for the customization group of PG internal settings. Do not change this variable! It is set automatically by the mode stub defined in proof-site, from the name given in ‘proof-assistant-table’.") (defvar proof-assistant "" "Name of the proof assistant Proof General is using. Do not change this variable! It is set automatically by the mode stub defined in proof-site, from names given in `proof-assistant-table'.") (defvar proof-assistant-symbol nil "Symbol for the proof assistant Proof General is using. Used for automatic configuration based on standard variable names. Settings will be found by looking for names beginning with this symbol as a prefix. Non-nil indicates PG has been initialised for an assistant. If this is nil, the hook functions in `proof-ready-for-assistant-hook' are yet to be run. Do not change this variable! It is set automatically by the mode stub defined in proof-site, from the symbols given in `proof-assistant-table'.") (defvar proof-mode-for-shell nil "Mode function for proof shell buffers. Do not change this variable! It is set automatically by the mode stub defined in proof-site to -shell-mode.") (defvar proof-mode-for-response nil "Mode function for proof response buffer (and trace buffer, if used). Do not change this variable! It is set automatically by the mode stub defined in proof-site to -response-mode.") (defvar proof-mode-for-goals nil "Mode for proof state display buffers. Do not change this variable! It is set automatically by the mode stub defined in proof-site to -goals-mode.") (defvar proof-mode-for-script nil "Mode for proof script buffers. Do not change this variable! It is set automatically by the mode stub defined in proof-site to -mode.") (defvar proof-ready-for-assistant-hook nil "Hook functions to run after PG is configured for a proof assistant. These functions allow late initialisation, once the choice of prover has been set.") ;;; ;;; Later variables ;;; (could be separated to cut down Emacs env pollution) ;;; (defvar proof-shell-busy nil "A lock indicating that the proof shell is processing. The lock notes that we are processing a queue of commands being sent to the prover, and indicates whether the commands correspond to script management from a buffer (rather than being ad-hoc query commands to the prover). When processing commands from a buffer for script management, this will be set to the queue mode 'advancing or 'retracting to indicate the direction of movement. When this is non-nil, `proof-shell-ready-prover' will give an error if called with a different requested queue mode. See also functions `proof-activate-scripting' and `proof-shell-available-p'.") (defvar proof-shell-last-queuemode nil "Flag indicating last direction of proof queue. This is actually the last non-nil value of `proof-shell-busy'.") (defvar proof-included-files-list nil "List of files currently included in proof process. This list contains files in canonical truename format \(see `file-truename'). Whenever a new file is being processed, it gets added to this list via the `proof-shell-process-file' configuration settings. When the prover retracts a file, this list is resynchronised via the `proof-shell-retract-files-regexp' and `proof-shell-compute-new-files-list' configuration settings. Only files which have been *fully* processed should be included here. Proof General itself will automatically add the filenames of a script buffer which has been completely read when scripting is deactivated. It will automatically remove the filename of a script buffer which is completely unread when scripting is deactivated. NB: Currently there is no generic provision for removing files which are only partly read-in due to an error, so ideally the proof assistant should only output a processed message when a file has been successfully read.") (defvar proof-script-buffer nil "The currently active scripting buffer or nil if none.") (defvar proof-previous-script-buffer nil "Previous value of `proof-script-buffer', recorded when scripting turned off. This can be used to help multiple file handling.") (defvar proof-shell-buffer nil "Process buffer where the proof assistant is run.") (defvar proof-goals-buffer nil "The goals buffer.") (defvar proof-response-buffer nil "The response buffer.") (defvar proof-trace-buffer nil "A tracing buffer for storing tracing output from the proof shell. See `proof-shell-trace-output-regexp' for details.") (defvar proof-thms-buffer nil "A buffer for displaying a list of theorems from the proof assistant. See `proof-shell-thm-display-regexp' for details.") (defvar proof-shell-error-or-interrupt-seen nil "Flag indicating that an error or interrupt has just occurred. Set to 'error or 'interrupt if one was observed from the proof assistant during the last group of commands.") (defvar pg-response-next-error nil "Error counter in response buffer to count for next error message.") (defvar proof-shell-proof-completed nil "Flag indicating that a completed proof has just been observed. If non-nil, the value counts the commands from the last command of the proof (starting from 1).") ;; ;; Internal variables ;; -- usually local to a couple of modules and perhaps inspected ;; by prover modes ;; -- here to avoid compiler warnings and minimise requires. ;; (defvar proof-shell-silent nil "A flag, non-nil if PG thinks the prover is silent.") (defvar proof-shell-last-prompt "" "A raw record of the last prompt seen from the proof system. This is the string matched by `proof-shell-annotated-prompt-regexp'.") (defvar proof-shell-last-output "" "A record of the last string seen from the proof system. This is raw string, for internal use only.") (defvar proof-shell-last-output-kind nil "A symbol denoting the type of the last output string from the proof system. Specifically: 'interrupt An interrupt message 'error An error message 'loopback A command sent from the PA to be inserted into the script 'response A response message 'goals A goals (proof state) display 'systemspecific Something specific to a particular system, -- see `proof-shell-handle-output-system-specific' The output corresponding to this will be in `proof-shell-last-output'. See also `proof-shell-proof-completed' for further information about the proof process output, when ends of proofs are spotted. This variable can be used for instance specific functions which want to examine `proof-shell-last-output'.") (defvar proof-assistant-settings nil "Settings kept in Proof General for current proof assistant. A list of lists (SYMBOL SETTING TYPE DESCR) where SETTING is a string value to send to the proof assistant using the value of SYMBOL and and the function `proof-assistant-format'. The TYPE item determines the form of the menu entry for the setting (this is an Emacs widget type) and the DESCR description string is used as a help tooltip in the settings menu. As TYPE's only the simple types boolean, integer, number and string are supported (see `proof-menu-entry-for-setting'). Other types will yield an error when constructing the proof assistant menu from this list. Customizations defined with `defpacustom' are automatically added to this list.") (defvar proof-assistant-additional-settings nil "Additional proof assistant specific customizations (as list of symbols). This variable should hold those proof assistant specific customizations that are not included in `proof-assistant-settings' but which should be saved/restored with the save and reset settings menu entry in the proof assistant menu. Customization variables are missing in `proof-assistant-settings' when they have a type not supported by `defpacusom'.") (defvar pg-tracing-slow-mode nil "Non-nil for slow refresh mode for tracing output.") (defvar proof-nesting-depth 0 "Current depth of a nested proof. Zero means outside a proof, 1 means inside a top-level proof, etc. This variable is maintained in `proof-done-advancing'; it is zeroed in `proof-shell-clear-state'.") (defvar proof-last-theorem-dependencies nil "Contains the dependencies of the last theorem. A list of strings. Set in `proof-shell-process-urgent-message'.") (defvar proof-autosend-running nil "Flag indicating we are sending commands to the prover automatically. Used in `proof-autosend-loop' and inspected in other places to inhibit user interaction.") (defvar proof-next-command-on-new-line nil "Indicate that `proof-script-new-command-advance' should make a newline. Internal variable dynamically bound.") ;; ;; Not variables at all: global constants (were in proof-config) ;; (defcustom proof-general-name "Proof-General" "Proof General name used internally and in menu titles." :type 'string :group 'proof-general-internals) (defcustom proof-general-home-page "https://proofgeneral.github.io" "*Web address for Proof General." :type 'string :group 'proof-general-internals) (defcustom proof-unnamed-theorem-name "Unnamed_thm" "A name for theorems which are unnamed. Used internally by Proof General." :type 'string :group 'proof-general-internals) (defcustom proof-universal-keys '(([(control c) ?`] . proof-next-error) ([(control c) (control c)] . proof-interrupt-process) ([(control c) (control n)] . proof-assert-next-command-interactive) ([(control c) (control u)] . proof-undo-last-successful-command) ([(control c) (control p)] . proof-prf) ([(control c) (control l)] . proof-layout-windows) ([(control c) (control x)] . proof-shell-exit) ([(control c) (control v)] . proof-minibuffer-cmd) ([(control c) (control w)] . pg-response-clear-displays) ([(control c) (control ?.)] . proof-goto-end-of-locked) ([(control c) (control f)] . proof-find-theorems) ([(control c) (control o)] . proof-display-some-buffers) ([(control shift mouse-1)] . pg-identifier-under-mouse-query)) "List of key bindings made for all proof general buffers. Elements of the list are tuples `(k . f)' where `k' is a key binding (vector) and `f' the designated function." :type 'sexp :group 'proof-general-internals) (provide 'pg-vars) ;;; pg-vars.el ends here PG-4.5/generic/pg-xml.el000066400000000000000000000173051426357011200150410ustar00rootroot00000000000000;;; pg-xml.el --- XML functions for Proof General -*- lexical-binding:t -*- ;; This file is part of Proof General. ;; Portions © Copyright 1994-2012 David Aspinall and University of Edinburgh ;; Portions © Copyright 2003-2018 Free Software Foundation, Inc. ;; Portions © Copyright 2001-2017 Pierre Courtieu ;; Portions © Copyright 2010, 2016 Erik Martin-Dorel ;; Portions © Copyright 2011-2013, 2016-2017 Hendrik Tews ;; Portions © Copyright 2015-2017 Clément Pit-Claudel ;; Author: David Aspinall ;; SPDX-License-Identifier: GPL-3.0-or-later ;;; Commentary: ;; ;; XML functions for Proof General. ;; ;;; Code: (require 'cl-lib) ;cl-mapcan (require 'xml) (require 'proof-utils) ;; for pg-internal-warning (defalias 'pg-xml-error 'error) ;; ;; Elisp format of XML trees (see xml.el) ;; ;; xml-list ::= (node node ...) ;; node ::= (qname attribute-list . child_node_list) ;; child_node_list ::= child_node child_node ... ;; child_node ::= node | string ;; qname ::= (:namespace-uri . "name") | "name" ;; attribute_list ::= ((qname . "value") (qname . "value") ...) ;; | nil ;; string ::= "..." ;; ;; NB [da]: without namespace aware parsing, qnames are symbols. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Parsing function: pg-xml-parse-buffer ;; ;;;###autoload (defun pg-xml-parse-string (arg) "Parse string in ARG, same as pg-xml-parse-buffer." (let ((tempbuffer (get-buffer-create " *xml-parse*"))) (with-current-buffer tempbuffer (delete-region (point-min) (point-max)) (insert arg) (pg-xml-parse-buffer (current-buffer) 'nomessage)))) (defun pg-xml-parse-buffer (&optional buffer nomsg start end) "Parse an XML documment in BUFFER (defaulting to current buffer). Display progress message unless NOMSG is non-nil. Parsing according to `xml-parse-file' of xml.el. Optional START and END bound the parse." (unless nomsg (message "Parsing %s..." (buffer-name buffer))) (let ((xml (xml-parse-region (or start (point-min)) (or end (point-max)) (or buffer (current-buffer)) nil))) (unless nomsg (message "Parsing %s...done" (buffer-name buffer))) xml)) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Helper functions for parsing ;; (defun pg-xml-get-attr (attribute node &optional optional defaultval) (let ((val (cdr (assoc attribute (xml-node-attributes node))))) (or val (if optional defaultval (pg-xml-error "Function pg-xml-get-attr: Didn't find required %s attribute in %s element" attribute (xml-node-name node)))))) (defun pg-xml-child-elts (node) "Return list of *element* children of NODE (ignoring strings)." (let ((children (xml-node-children node))) (cl-mapcan (lambda (x) (if (listp x) (list x))) children))) (defun pg-xml-child-elt (node) "Return unique element child of NODE." (let ((children (pg-xml-child-elts node))) (if (= (length children) 1) (car children) (pg-internal-warning "pg-xml-child-elt: expected single element child of %s" (xml-node-name node))))) (defun pg-xml-get-child (child node) "Return single element CHILD of NODE, give error if more than one." (let ((children (xml-get-children node child))) (if (> (length children) 1) (progn (pg-internal-warning "pg-xml-get-child: got more than one %s child of %s node, ignoring rest" child (xml-node-name node)) (car children)) children))) (defun pg-xml-get-text-content (node) "Return the concatenation of all the text children of node NODE." (mapconcat (lambda (x) (if (stringp x) x "")) (xml-node-children node) "")) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Producing functions: constructing an XML tree in xml.el format ;; and converting to a string (defmacro pg-xml-attr (name val) `(cons (quote ,name) ,val)) (defmacro pg-xml-node (name atts children) `(cons (quote ,name) (cons ,atts ,children))) (defconst pg-xml-header "\n") (defun pg-xml-string-of (xmls) "Convert the XML trees in XMLS into a string (without additional indentation)." (let* (strs (insertfn (lambda (&rest args) (push (mapconcat #'identity args "") strs)))) (dolist (xml xmls) (pg-xml-output-internal xml nil insertfn)) (mapconcat #'identity (reverse strs) ""))) ;; based on xml-debug-print from xml.el (defun pg-xml-output-internal (xml indent-string outputfn) "Output the XML tree. Use indentation INDENT-STRING (or none if nil). Cal OUTPUTFN, which should accept a list of args." (let ((tree xml) attlist) (funcall outputfn (or indent-string "") "<" (symbol-name (xml-node-name tree))) ;; output the attribute list (setq attlist (xml-node-attributes tree)) (while attlist (funcall outputfn " ") (funcall outputfn (symbol-name (caar attlist)) "=\"" (cdar attlist) "\"") (setq attlist (cdr attlist))) (setq tree (xml-node-children tree)) (if tree (progn (funcall outputfn ">") ;; output the children (dolist (node tree) (cond ((listp node) (if indent-string (funcall outputfn "\n")) (pg-xml-output-internal node (if indent-string (concat indent-string " ")) outputfn)) ((stringp node) (funcall outputfn node)) (t (error "Function pg-xml-output-internal: Invalid XML tree")))) (funcall outputfn (if indent-string (concat "\n" indent-string) "") "")) (funcall outputfn "/>")))) (defun pg-xml-cdata (str) (concat " child of NODE, or nil if none." (pg-xml-get-child 'icon node)) (defsubst pg-pgip-get-name (node &optional optional defaultval) (pg-xml-get-attr 'name node optional defaultval)) (defsubst pg-pgip-get-version (node &optional optional defaultval) (pg-xml-get-attr 'version node optional defaultval)) (defsubst pg-pgip-get-descr (node &optional optional defaultval) (pg-xml-get-attr 'descr node optional defaultval)) (defsubst pg-pgip-get-thmname (node &optional optional defaultval) (pg-xml-get-attr 'thmname node optional defaultval)) (defsubst pg-pgip-get-thyname (node &optional optional defaultval) (pg-xml-get-attr 'thmname node optional defaultval)) (defsubst pg-pgip-get-url (node &optional optional defaultval) (pg-xml-get-attr 'url node optional defaultval)) (defsubst pg-pgip-get-srcid (node &optional optional defaultval) (pg-xml-get-attr 'srcid node optional defaultval)) (defsubst pg-pgip-get-proverid (node &optional optional defaultval) (pg-xml-get-attr 'proverid node optional defaultval)) (defsubst pg-pgip-get-symname (node &optional optional defaultval) (pg-xml-get-attr 'name node optional defaultval)) (defsubst pg-pgip-get-prefcat (node &optional optional defaultval) (pg-xml-get-attr 'prefcategory node optional defaultval)) (defsubst pg-pgip-get-default (node &optional optional defaultval) (pg-xml-get-attr 'default node optional defaultval)) (defsubst pg-pgip-get-objtype (node &optional optional defaultval) (pg-xml-get-attr 'objtype node optional defaultval)) (defsubst pg-pgip-get-value (node) (pg-xml-get-text-content node)) (defalias 'pg-pgip-get-displaytext 'pg-pgip-get-pgmltext) (defun pg-pgip-get-pgmltext (node) ;; TODO: fetch text or markup XML with text properties (pg-xml-get-text-content node)) (provide 'pg-xml) ;;; pg-xml.el ends here PG-4.5/generic/proof-autoloads.el000066400000000000000000001253231426357011200167530ustar00rootroot00000000000000;;; proof-autoloads.el --- automatically extracted autoloads ;; This file is part of Proof General. ;; Portions © Copyright 1994-2012 David Aspinall and University of Edinburgh ;; Portions © Copyright 2003-2018 Free Software Foundation, Inc. ;; Portions © Copyright 2001-2017 Pierre Courtieu ;; Portions © Copyright 2010, 2016 Erik Martin-Dorel ;; Portions © Copyright 2011-2013, 2016-2017 Hendrik Tews ;; Portions © Copyright 2015-2017 Clément Pit-Claudel ;;; Commentary: ;; ;;; Code: (provide 'proof-autoloads) ;;;### (autoloads nil "../coq/coq" "../coq/coq.el" (0 0 0 0)) ;;; Generated autoloads from ../coq/coq.el (autoload 'coq-pg-setup "../coq/coq" nil nil nil) (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "../coq/coq" '("auto-adapt-printing-width" "build-list-id-from-string" "coq-" "count-not-intersection" "hide-additional-subgoals" "is-not-split-vertic" "last-coq-error-location" "mod" "notation-print-kinds-table" "printing-depth" "proof-" "reqkinds-kinds-table" "time-commands"))) ;;;*** ;;;### (autoloads nil "../coq/coq-abbrev" "../coq/coq-abbrev.el" ;;;;;; (0 0 0 0)) ;;; Generated autoloads from ../coq/coq-abbrev.el (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "../coq/coq-abbrev" '("coq-" "holes-show-doc"))) ;;;*** ;;;### (autoloads nil "../coq/coq-autotest" "../coq/coq-autotest.el" ;;;;;; (0 0 0 0)) ;;; Generated autoloads from ../coq/coq-autotest.el (autoload 'coq-autotest "../coq/coq-autotest" nil t nil) ;;;*** ;;;### (autoloads nil "../coq/coq-compile-common" "../coq/coq-compile-common.el" ;;;;;; (0 0 0 0)) ;;; Generated autoloads from ../coq/coq-compile-common.el (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "../coq/coq-compile-common" '("coq-" "number-of-cpus" "time-less-or-equal"))) ;;;*** ;;;### (autoloads nil "../coq/coq-db" "../coq/coq-db.el" (0 0 0 0)) ;;; Generated autoloads from ../coq/coq-db.el (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "../coq/coq-db" '("coq-" "filter-state-" "max-length-db"))) ;;;*** ;;;### (autoloads nil "../coq/coq-diffs" "../coq/coq-diffs.el" (0 ;;;;;; 0 0 0)) ;;; Generated autoloads from ../coq/coq-diffs.el (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "../coq/coq-diffs" '("coq-"))) ;;;*** ;;;### (autoloads nil "../coq/coq-indent" "../coq/coq-indent.el" ;;;;;; (0 0 0 0)) ;;; Generated autoloads from ../coq/coq-indent.el (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "../coq/coq-indent" '("coq-"))) ;;;*** ;;;### (autoloads nil "../coq/coq-local-vars" "../coq/coq-local-vars.el" ;;;;;; (0 0 0 0)) ;;; Generated autoloads from ../coq/coq-local-vars.el (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "../coq/coq-local-vars" '("coq-"))) ;;;*** ;;;### (autoloads nil "../coq/coq-mode" "../coq/coq-mode.el" (0 0 ;;;;;; 0 0)) ;;; Generated autoloads from ../coq/coq-mode.el (add-to-list 'auto-mode-alist '("\\.v\\'" . coq-mode)) (autoload 'coq-mode "../coq/coq-mode" "\ Major mode for Coq scripts. \\{coq-mode-map} \(fn)" t nil) (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "../coq/coq-mode" '("coq-" "get-coq-library-directory"))) ;;;*** ;;;### (autoloads nil "../coq/coq-par-compile" "../coq/coq-par-compile.el" ;;;;;; (0 0 0 0)) ;;; Generated autoloads from ../coq/coq-par-compile.el (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "../coq/coq-par-compile" '("coq-" "split-list-at-predicate"))) ;;;*** ;;;### (autoloads nil "../coq/coq-seq-compile" "../coq/coq-seq-compile.el" ;;;;;; (0 0 0 0)) ;;; Generated autoloads from ../coq/coq-seq-compile.el (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "../coq/coq-seq-compile" '("coq-seq-"))) ;;;*** ;;;### (autoloads nil "../coq/coq-smie" "../coq/coq-smie.el" (0 0 ;;;;;; 0 0)) ;;; Generated autoloads from ../coq/coq-smie.el (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "../coq/coq-smie" '("coq-"))) ;;;*** ;;;### (autoloads nil "../coq/coq-syntax" "../coq/coq-syntax.el" ;;;;;; (0 0 0 0)) ;;; Generated autoloads from ../coq/coq-syntax.el (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "../coq/coq-syntax" '("coq-" "develock-coq-font-lock-keywords"))) ;;;*** ;;;### (autoloads nil "../coq/coq-system" "../coq/coq-system.el" ;;;;;; (0 0 0 0)) ;;; Generated autoloads from ../coq/coq-system.el (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "../coq/coq-system" '("coq-"))) ;;;*** ;;;### (autoloads nil "../coq/coq-unicode-tokens" "../coq/coq-unicode-tokens.el" ;;;;;; (0 0 0 0)) ;;; Generated autoloads from ../coq/coq-unicode-tokens.el (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "../coq/coq-unicode-tokens" '("coq-"))) ;;;*** ;;;### (autoloads nil "../lib/bufhist" "../lib/bufhist.el" (0 0 0 ;;;;;; 0)) ;;; Generated autoloads from ../lib/bufhist.el (autoload 'bufhist-mode "../lib/bufhist" "\ Minor mode retaining an in-memory history of the buffer contents. If called interactively, enable Bufhist mode if ARG is positive, and disable it if ARG is zero or negative. If called from Lisp, also enable the mode if ARG is omitted or nil, and toggle it if ARG is `toggle'; disable the mode otherwise. Commands:\\ \\[bufhist-prev] bufhist-prev go back in history \\[bufhist-next] bufhist-next go forward in history \\[bufhist-first] bufhist-first go to first item in history \\[bufhist-last] bufhist-last go to last (current) item in history. \\[bufhist-clear] bufhist-clear clear history. \\[bufhist-delete] bufhist-clear delete current item from history. \(fn &optional ARG)" t nil) (autoload 'bufhist-init "../lib/bufhist" "\ Initialise a ring history for the current buffer. The history will be read-only unless READWRITE is non-nil. For read-only histories, edits to the buffer switch to the latest version. If RINGSIZE is omitted or nil, the size defaults to ‘bufhist-ring-size’. \(fn &optional READWRITE RINGSIZE)" t nil) (autoload 'bufhist-exit "../lib/bufhist" "\ Stop keeping ring history for current buffer." t nil) (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "../lib/bufhist" '("bufhist-"))) ;;;*** ;;;### (autoloads nil "../lib/holes" "../lib/holes.el" (0 0 0 0)) ;;; Generated autoloads from ../lib/holes.el (autoload 'holes-set-make-active-hole "../lib/holes" "\ Make a new hole between START and END or at point, and make it active. \(fn &optional START END)" t nil) (autoload 'holes-mode "../lib/holes" "\ Toggle Holes minor mode. With arg, turn Outline minor mode on if arg is positive, off otherwise. The mode `holes-mode' is meant to help program editing. It is useful to build complicated expressions by copy pasting several peices of text from different parts of a buffer (or even from different buffers). HOLES A hole is a piece of (highlighted) text that may be replaced by another part of text later. There is no information stored on the file for holes, so you can save and modify files containing holes with no harm... You can even insert or delete characters inside holes like any other characters. USE At any time only one particular hole, called \"active\", can be \"filled\". Holes can be in several buffers but there is always one or zero active hole globally. It is highlighted with a different color. Functions described below have default shortcuts when `holes-mode' is on that you can customize. TO DEFINE A HOLE, two methods: o Select a region with keyboard or mouse, then use \\[holes-set-make-active-hole]. If the selected region is empty, then a hole containing # is created at point. o Select text with mouse while pressing ctrl and meta (`C-M-select'). If the selected region is empty (i.e. if you just click while pressing ctrl+meta), then a hole containing # is created. TO ACTIVATE A HOLE, click on it with the button 1 of your mouse. The previous active hole will be deactivated. TO FORGET A HOLE without deleting its text, click on it with the button 2 (middle) of your mouse. TO DESTROY A HOLE and delete its text, click on it with the button 3 of your mouse. TO FILL A HOLE with a text selection, first make sure it is active, then two methods: o Select text with keyboard or mouse and hit \\[holes-replace-update-active-hole] o Select text with mouse while pressing ctrl, meta and shift (`C-M-S-select'). This is a generalization of the `mouse-track-insert' feature of XEmacs. This method allows you to fill different holes faster than with the usual copy-paste method. After replacement the next hole is automatically made active so you can fill it immediately by hitting again \\[holes-replace-update-active-hole] or `C-M-S-select'. TO JUMP TO THE ACTIVE HOLE, just hit \\[holes-set-point-next-hole-destroy]. You must be in the buffer containing the active hole. the point will move to the active hole, and the active hole will be destroyed so you can type something to put at its place. The following hole is automatically made active, so you can hit \\[holes-set-point-next-hole-destroy] again. It is useful in combination with abbreviations. For example in `coq-mode' \"fix\" is an abbreviation for Fixpoint # (# : #) {struct #} : # := #, where each # is a hole. Then hitting \\[holes-set-point-next-hole-destroy] goes from one hole to the following and you can fill-in each hole very quickly. COMBINING HOLES AND SKELETONS `holes' minor mode is made to work with minor mode `skeleton' minor mode. KNOWN BUGS o Don't try to make overlapping holes, it doesn't work. (what would it mean anyway?) o Cutting or pasting a hole will not produce new holes, and undoing on holes cannot make holes re-appear. \(fn &optional ARG)" t nil) (autoload 'holes-abbrev-complete "../lib/holes" "\ Complete abbrev by putting holes and indenting. Moves point at beginning of expanded text. Put this function as call-back for your abbrevs, and just expanded \"#\" and \"@{..}\" will become holes." nil nil) (autoload 'holes-insert-and-expand "../lib/holes" "\ Insert S, expand it and replace #s and @{]s by holes. \(fn S)" nil nil) (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "../lib/holes" '("hole"))) ;;;*** ;;;### (autoloads nil "../lib/local-vars-list" "../lib/local-vars-list.el" ;;;;;; (0 0 0 0)) ;;; Generated autoloads from ../lib/local-vars-list.el (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "../lib/local-vars-list" '("local-vars-list-"))) ;;;*** ;;;### (autoloads nil "../lib/maths-menu" "../lib/maths-menu.el" ;;;;;; (0 0 0 0)) ;;; Generated autoloads from ../lib/maths-menu.el (autoload 'maths-menu-mode "../lib/maths-menu" "\ Install a menu for entering mathematical characters. Uses window system menus only when they can display multilingual text. Otherwise the menu-bar item activates the text-mode menu system. This mode is only useful with a font which can display the maths repertoire. If called interactively, enable Maths-Menu mode if ARG is positive, and disable it if ARG is zero or negative. If called from Lisp, also enable the mode if ARG is omitted or nil, and toggle it if ARG is `toggle'; disable the mode otherwise. \(fn &optional ARG)" t nil) (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "../lib/maths-menu" '("maths-menu-"))) ;;;*** ;;;### (autoloads nil "../lib/pg-fontsets" "../lib/pg-fontsets.el" ;;;;;; (0 0 0 0)) ;;; Generated autoloads from ../lib/pg-fontsets.el (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "../lib/pg-fontsets" '("pg-fontsets-"))) ;;;*** ;;;### (autoloads nil "../lib/proof-compat" "../lib/proof-compat.el" ;;;;;; (0 0 0 0)) ;;; Generated autoloads from ../lib/proof-compat.el (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "../lib/proof-compat" '("pg-custom-undeclare-variable"))) ;;;*** ;;;### (autoloads nil "../lib/span" "../lib/span.el" (0 0 0 0)) ;;; Generated autoloads from ../lib/span.el (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "../lib/span" '("fold-spans" "next-span" "prev-span" "set-span-" "span"))) ;;;*** ;;;### (autoloads nil "../qrhl/qrhl" "../qrhl/qrhl.el" (0 0 0 0)) ;;; Generated autoloads from ../qrhl/qrhl.el (let ((loads (get 'qrhl 'custom-loads))) (if (member '"../qrhl/qrhl" loads) nil (put 'qrhl 'custom-loads (cons '"../qrhl/qrhl" loads)))) (defvar qrhl-input-method "qrhl" "\ Input method to use when editing qRHL proof scripts") (custom-autoload 'qrhl-input-method "../qrhl/qrhl" t) (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "../qrhl/qrhl" '("qrhl-"))) ;;;*** ;;;### (autoloads nil "pg-assoc" "pg-assoc.el" (0 0 0 0)) ;;; Generated autoloads from pg-assoc.el (autoload 'proof-associated-buffers "pg-assoc" "\ Return a list of the associated buffers. Some may be dead/nil." nil nil) (autoload 'proof-associated-windows "pg-assoc" "\ Return a list of the associated buffers windows. Dead or nil buffers are not represented in the list. Optional argument ALL-FRAMES has the same meaning than for `get-buffer-window'. \(fn &optional ALL-FRAMES)" nil nil) (autoload 'proof-associated-frames "pg-assoc" "\ Return the list of frames displaying at least one associated buffer." nil nil) (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "pg-assoc" '("proof-"))) ;;;*** ;;;### (autoloads nil "../lib/pg-dev" "../lib/pg-dev.el" (0 0 0 0)) ;;; Generated autoloads from ../lib/pg-dev.el (autoload 'profile-pg "../lib/pg-dev" "\ Configure Proof General for profiling. Use \\[elp-results] to see results." t nil) (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "../lib/pg-dev" '("elp-pack-number" "pg-" "unload-pg"))) ;;;*** ;;;### (autoloads nil "pg-autotest" "pg-autotest.el" (0 0 0 0)) ;;; Generated autoloads from pg-autotest.el (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "pg-autotest" '("pg-autotest"))) ;;;*** ;;;### (autoloads nil "pg-custom" "pg-custom.el" (0 0 0 0)) ;;; Generated autoloads from pg-custom.el (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "pg-custom" '("completion-table" "favourites" "help-menu-entries" "keymap" "maths-menu-enable" "menu-entries" "one-command-per-line" "pro" "quit-timeout" "script-indent" "tags-program" "toolbar-entries" "unicode-tokens-enable" "use-holes"))) ;;;*** ;;;### (autoloads nil "pg-goals" "pg-goals.el" (0 0 0 0)) ;;; Generated autoloads from pg-goals.el (autoload 'proof-goals-config-done "pg-goals" "\ Initialise the goals buffer after the child has been configured." nil nil) (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "pg-goals" '("pg-goals-" "proof-goals-mode"))) ;;;*** ;;;### (autoloads nil "pg-movie" "pg-movie.el" (0 0 0 0)) ;;; Generated autoloads from pg-movie.el (autoload 'pg-movie-export "pg-movie" "\ Export the movie file from the current script buffer. If FORCE, overwrite existing file without asking. \(fn &optional FORCE)" t nil) (autoload 'pg-movie-export-from "pg-movie" "\ Export the movie file that results from processing SCRIPT. \(fn SCRIPT &optional FORCE)" t nil) (autoload 'pg-movie-export-directory "pg-movie" "\ Export movie files from directory DIR with extension EXTN. Existing XML files are overwritten. \(fn DIR EXTN)" t nil) (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "pg-movie" '("pg-movie-"))) ;;;*** ;;;### (autoloads nil "pg-pamacs" "pg-pamacs.el" (0 0 0 0)) ;;; Generated autoloads from pg-pamacs.el (autoload 'proof-defpacustom-fn "pg-pamacs" "\ As for macro `defpacustom' but evaluating arguments. \(fn NAME VAL ARGS)" nil nil) (autoload 'defpacustom "pg-pamacs" "\ Define a setting NAME for the current proof assistant, default VAL. Mainly intended for configuring settings of running provers, which can be changed by sending commands. In this case, NAME stands for the internal setting, flag, etc, for the proof assistant, and a :setting and :type value should be provided. The :type of NAME should be one of 'integer, 'float, 'boolean, 'string. Other types are not supported (see `proof-menu-entry-for-setting'). They will yield an error when constructing the proof assistant menu. The function `proof-assistant-format' is used to format VAL. This macro invokes the standard Emacs `defcustom' macro, so this also defines a customizable setting inside Emacs. The customization variable is automatically put into the group named after the prover. If NAME corresponds instead to a PG internal setting, then a form :eval to evaluate can be provided instead. Additional properties in the ARGS prop list may include: pggroup string A grouping name for the setting, in case there are many. For example, \"Timing\", \"Tracing\", etc. Used to generate sub-menus in the UI. pgipgcmd string Alternative to :setting. Send a PGIP formatted command based on given string. pgdynamic flag If flag is non-nil, this setting is a dynamic one that is particular to the running instance of the prover. Automatically set by preferences configured from PGIP askprefs message. This macro also extends the `proof-assistant-settings' list. \(fn NAME VAL &rest ARGS)" nil t) (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "pg-pamacs" '("deflocal" "defpg" "proof-" "undefpgcustom"))) ;;;*** ;;;### (autoloads nil "pg-pbrpm" "pg-pbrpm.el" (0 0 0 0)) ;;; Generated autoloads from pg-pbrpm.el (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "pg-pbrpm" '("pbrpm-menu-desc" "pg-pbrpm-"))) ;;;*** ;;;### (autoloads nil "pg-pgip" "pg-pgip.el" (0 0 0 0)) ;;; Generated autoloads from pg-pgip.el (autoload 'pg-pgip-process-packet "pg-pgip" "\ Process the command packet PGIP, which is parsed XML according to pg-xml-parse-*. The list PGIPS may contain one or more PGIP packets, whose contents are processed. \(fn PGIPS)" nil nil) (autoload 'pg-pgip-maybe-askpgip "pg-pgip" "\ Send an message to the prover if PGIP is supported." nil nil) (autoload 'pg-pgip-askprefs "pg-pgip" "\ Send an message to the prover." nil nil) (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "pg-pgip" '("pg-" "proof-assistant-idtables"))) ;;;*** ;;;### (autoloads nil "pg-response" "pg-response.el" (0 0 0 0)) ;;; Generated autoloads from pg-response.el (autoload 'proof-response-mode "pg-response" "\ Responses from Proof Assistant \(fn)" t nil) (autoload 'proof-response-config-done "pg-response" "\ Complete initialisation of a response-mode derived buffer." nil nil) (autoload 'pg-response-maybe-erase "pg-response" "\ Erase the response buffer, according to confusing flag combinations. Mainly, we look at `pg-response-erase-flag' and clear the response buffer if this is non-nil, but NOT the special symbol 'invisible. ERASE-NEXT-TIME is the new value for the flag. FORCE overrides the flag to force cleaning. KEEP overrides the flag to prevent cleaning. FORCE takes precedent over KEEP. If CLEAN-WINDOWS is set, use `proof-clean-buffer' to do the erasing, otherwise we use `bufhist-checkpoint-and-erase' to record an undo history entry for the current buffer contents. If the user option `proof-tidy-response' is nil, the buffer will never be cleared unless FORCE is set. No effect if there is no response buffer currently. Returns non-nil if response buffer was cleared. \(fn &optional ERASE-NEXT-TIME CLEAN-WINDOWS FORCE KEEP)" nil nil) (autoload 'pg-response-display-with-face "pg-response" "\ Display STR with FACE in response buffer. \(fn STR &optional FACE)" nil nil) (autoload 'pg-response-message "pg-response" "\ Issue the message ARGS in the response buffer and display it. \(fn &rest ARGS)" nil nil) (autoload 'proof-next-error "pg-response" "\ Jump to location of next error reported in the response buffer. A prefix arg specifies how many error messages to move; negative means move back to previous error messages. Optional argument ARGP means reparse the error message buffer and start at the first error. \(fn &optional ARGP)" t nil) (autoload 'pg-response-has-error-location "pg-response" "\ Return non-nil if the response buffer has an error location. See `pg-next-error-regexp'." nil nil) (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "pg-response" '("pg-" "proof-"))) ;;;*** ;;;### (autoloads nil "pg-user" "pg-user.el" (0 0 0 0)) ;;; Generated autoloads from pg-user.el (autoload 'proof-script-new-command-advance "pg-user" "\ Move point to a nice position for a new command, possibly inserting spaces. Assumes that point is at the end of a command. No effect if `proof-next-command-insert-space' is nil." t nil) (autoload 'proof-goto-point "pg-user" "\ Assert or retract to the command at current position. Calls `proof-assert-until-point' or `proof-retract-until-point' as appropriate. With prefix argument RAW the omit proofs feature \(`proof-omit-proofs-option') is temporaily disabled to check all proofs in the asserted region. \(fn &optional RAW)" t nil) (autoload 'proof-process-buffer "pg-user" "\ Process the current (or script) buffer, and maybe move point to the end. With prefix argument RAW the omit proofs feature (`proof-omit-proofs-option') is temporaily disabled to check all proofs in the asserted region. \(fn &optional RAW)" t nil) (autoload 'proof-define-assistant-command "pg-user" "\ Define FN (docstring DOC): check if CMDVAR is set, then send BODY to prover. BODY defaults to CMDVAR, a variable. \(fn FN DOC CMDVAR &optional BODY)" nil t) (autoload 'proof-define-assistant-command-witharg "pg-user" "\ Define FN (arg) with DOC: check CMDVAR is set, PROMPT a string and eval BODY. The BODY can contain occurrences of arg. CMDVAR is a variable holding a function or string. Automatically has history. \(fn FN DOC CMDVAR PROMPT &rest BODY)" nil t) (autoload 'proof-electric-terminator-enable "pg-user" "\ Ensure modeline update to display new value for electric terminator. This a function is called by the custom-set property 'proof-set-value. It can also be used as a minor mode function: with ARG, turn on iff ARG>0 \(fn &optional ARG)" nil nil) (autoload 'pg-slow-fontify-tracing-hint "pg-user" nil nil nil) (autoload 'pg-response-buffers-hint "pg-user" "\ \(fn &optional NEXTBUF)" nil nil) (autoload 'pg-jump-to-end-hint "pg-user" nil nil nil) (autoload 'pg-processing-complete-hint "pg-user" "\ Display hint for showing end of locked region or processing complete." nil nil) (autoload 'pg-next-error-hint "pg-user" "\ Display hint for locating error." nil nil) (autoload 'pg-hint "pg-user" "\ Display a hint HINTMSG in the minibuffer, if `pg-show-hints' is non-nil. The function `substitute-command-keys' is called on the argument. \(fn HINTMSG)" nil nil) (autoload 'pg-identifier-near-point-query "pg-user" "\ Query the prover about the identifier near point. If the result is successful, we add a span to the buffer which has a popup with the information in it." t nil) (autoload 'proof-imenu-enable "pg-user" "\ Add or remove index menu." nil nil) (autoload 'pg-previous-matching-input-from-input "pg-user" "\ Search backwards through input history for match for current input. \(Previous history elements are earlier commands.) With prefix argument N, search for Nth previous match. If N is negative, search forwards for the -Nth following match. \(fn N)" t nil) (autoload 'pg-next-matching-input-from-input "pg-user" "\ Search forwards through input history for match for current input. \(Following history elements are more recent commands.) With prefix argument N, search for Nth following match. If N is negative, search backwards for the -Nth previous match. \(fn N)" t nil) (autoload 'pg-add-to-input-history "pg-user" "\ Maybe add CMD to the input history. CMD is only added to the input history if it is not a duplicate of the last item added. \(fn CMD)" nil nil) (autoload 'pg-remove-from-input-history "pg-user" "\ Maybe remove CMD from the end of the input history. This is called when the command is undone. It's only removed if it matches the last item in the ring. \(fn CMD)" nil nil) (autoload 'pg-clear-input-ring "pg-user" nil nil nil) (autoload 'proof-autosend-enable "pg-user" "\ Enable or disable autosend behaviour. \(fn &optional NOMSG)" nil nil) (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "pg-user" '("next-undo-elt" "pg-" "proof-"))) ;;;*** ;;;### (autoloads nil "pg-vars" "pg-vars.el" (0 0 0 0)) ;;; Generated autoloads from pg-vars.el (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "pg-vars" '("pg-" "proof-"))) ;;;*** ;;;### (autoloads nil "pg-xml" "pg-xml.el" (0 0 0 0)) ;;; Generated autoloads from pg-xml.el (autoload 'pg-xml-parse-string "pg-xml" "\ Parse string in ARG, same as pg-xml-parse-buffer. \(fn ARG)" nil nil) (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "pg-xml" '("pg-"))) ;;;*** ;;;### (autoloads nil "proof-auxmodes" "proof-auxmodes.el" (0 0 0 ;;;;;; 0)) ;;; Generated autoloads from proof-auxmodes.el (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "proof-auxmodes" '("proof-"))) ;;;*** ;;;### (autoloads nil "proof-config" "proof-config.el" (0 0 0 0)) ;;; Generated autoloads from proof-config.el (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "proof-config" '("pbp-" "pg-" "proof-"))) ;;;*** ;;;### (autoloads nil "proof-depends" "proof-depends.el" (0 0 0 0)) ;;; Generated autoloads from proof-depends.el (autoload 'proof-depends-process-dependencies "proof-depends" "\ Process dependencies reported by prover, for NAME in span GSPAN. Called from `proof-done-advancing' when a save is processed and `proof-last-theorem-dependencies' is set. \(fn NAME GSPAN)" nil nil) (autoload 'proof-dependency-in-span-context-menu "proof-depends" "\ Make some menu entries showing proof dependencies of SPAN. Use `proof-dependency-menu-system-specific' to build system specific entries. \(fn SPAN)" nil nil) (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "proof-depends" '("pg-" "proof-"))) ;;;*** ;;;### (autoloads nil "proof-easy-config" "proof-easy-config.el" ;;;;;; (0 0 0 0)) ;;; Generated autoloads from proof-easy-config.el (autoload 'proof-easy-config "proof-easy-config" "\ Configure Proof General for a given proof assistant. The symbol SYM and string name NAME must match those given in the `proof-assistant-table', which see. Additional arguments are taken into account as a setq BODY. \(fn SYM NAME &rest BODY)" nil t) (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "proof-easy-config" '("proof-easy-config-"))) ;;;*** ;;;### (autoloads nil "proof-faces" "proof-faces.el" (0 0 0 0)) ;;; Generated autoloads from proof-faces.el (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "proof-faces" '("pg-defface-window-systems" "proof-"))) ;;;*** ;;;### (autoloads nil "proof-indent" "proof-indent.el" (0 0 0 0)) ;;; Generated autoloads from proof-indent.el (autoload 'proof-indent-line "proof-indent" "\ Indent current line of proof script, if indentation enabled." t nil) (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "proof-indent" '("proof-indent-"))) ;;;*** ;;;### (autoloads nil "proof-maths-menu" "proof-maths-menu.el" (0 ;;;;;; 0 0 0)) ;;; Generated autoloads from proof-maths-menu.el (autoload 'proof-maths-menu-set-global "proof-maths-menu" "\ Set global status of maths-menu mode for PG buffers to be FLAG. Turn on/off menu in all script buffers and ensure new buffers follow suit. \(fn FLAG)" nil nil) (autoload 'proof-maths-menu-enable "proof-maths-menu" "\ Turn on or off maths-menu mode in Proof General script buffer. This invokes `maths-menu-mode' to toggle the setting for the current buffer, and then sets PG's option for default to match. Also we arrange to have maths menu mode turn itself on automatically in future if we have just activated it for this buffer." t nil) ;;;*** ;;;### (autoloads nil "proof-menu" "proof-menu.el" (0 0 0 0)) ;;; Generated autoloads from proof-menu.el (autoload 'proof-menu-define-keys "proof-menu" "\ Prover specific keymap under C-c C-a. \(fn MAP)" nil nil) (autoload 'proof-menu-define-main "proof-menu" nil nil nil) (autoload 'proof-menu-define-specific "proof-menu" nil nil nil) (autoload 'proof-aux-menu "proof-menu" "\ Construct and return PG auxiliary menu used in non-scripting buffers." nil nil) (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "proof-menu" '("proof-"))) ;;;*** ;;;### (autoloads nil "proof-script" "proof-script.el" (0 0 0 0)) ;;; Generated autoloads from proof-script.el (autoload 'proof-ready-for-assistant "proof-script" "\ Configure PG for symbol ASSISTANTSYM, name ASSISTANT-NAME. If ASSISTANT-NAME is omitted, look up in `proof-assistant-table'. \(fn ASSISTANTSYM &optional ASSISTANT-NAME)" nil nil) (autoload 'proof-colour-locked "proof-script" "\ Alter the colour of all locked regions according to variable `proof-colour-locked'." t nil) (autoload 'proof-unprocessed-begin "proof-script" "\ Return end of locked region in current buffer or (point-min) otherwise. The position is actually one beyond the last locked character." nil nil) (autoload 'proof-locked-region-full-p "proof-script" "\ Non-nil if the locked region covers all the buffer's non-whitespace. Works on any buffer." nil nil) (autoload 'proof-locked-region-empty-p "proof-script" "\ Non-nil if the locked region is empty. Works on any buffer." nil nil) (autoload 'proof-register-possibly-new-processed-file "proof-script" "\ Register a possibly new FILE as having been processed by the prover. If INFORMPROVER is non-nil, the proof assistant will be told about this, to co-ordinate with its internal file-management. (Otherwise we assume that it is a message from the proof assistant which triggers this call). In this case, the user will be queried to save some buffers, unless NOQUESTIONS is non-nil. No action is taken if the file is already registered. A warning message is issued if the register request came from the proof assistant and Emacs has a modified buffer visiting the file. \(fn FILE &optional INFORMPROVER NOQUESTIONS)" nil nil) (autoload 'proof-mode "proof-script" "\ Proof General major mode class for proof scripts. \\{proof-mode-map} \(fn)" t nil) (autoload 'proof-config-done "proof-script" "\ Finish setup of Proof General scripting mode. Call this function in the derived mode for the proof assistant to finish setup which depends on specific proof assistant configuration." nil nil) (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "proof-script" '("pg-" "proof-"))) ;;;*** ;;;### (autoloads nil "proof-shell" "proof-shell.el" (0 0 0 0)) ;;; Generated autoloads from proof-shell.el (autoload 'proof-shell-ready-prover "proof-shell" "\ Make sure the proof assistant is ready for a command. If QUEUEMODE is set, succeed if the proof shell is busy but has mode QUEUEMODE, which is a symbol or list of symbols. Otherwise, if the shell is busy, give an error. No change to current buffer or point. \(fn &optional QUEUEMODE)" nil nil) (autoload 'proof-shell-live-buffer "proof-shell" "\ Return non-nil if ‘proof-shell-buffer’ is live." nil nil) (autoload 'proof-shell-available-p "proof-shell" "\ Return non-nil if there is a proof shell active and available. No error messages. Useful as menu or toolbar enabler." nil nil) (autoload 'proof-shell-insert "proof-shell" "\ Insert STRINGS at the end of the proof shell, call `scomint-send-input'. STRINGS is a list of strings (which will be concatenated), or a single string. The ACTION argument is a symbol which is typically the name of a callback for when each string has been processed. This calls `proof-shell-insert-hook'. The arguments ACTION and SCRIPTSPAN may be examined by the hook to determine how to modify the string variable (exploiting dynamic scoping) which will be the command actually sent to the shell. Note that the hook is not called for the empty (null) string or a carriage return. We strip the string of carriage returns before inserting it and updating `proof-marker' to point to the end of the newly inserted text. Do not use this function directly, or output will be lost. It is only used in `proof-add-to-queue' when we start processing a queue, and in `proof-shell-exec-loop', to process the next item. \(fn STRINGS ACTION &optional SCRIPTSPAN)" nil nil) (autoload 'proof-start-queue "proof-shell" "\ Begin processing a queue of commands. If START is non-nil, START and END are buffer positions in the active scripting buffer for the queue region. This function calls ‘proof-add-to-queue’ with args QUEUEITEMS and QUEUEMODE. \(fn START END QUEUEITEMS &optional QUEUEMODE)" nil nil) (autoload 'proof-extend-queue "proof-shell" "\ Extend the current queue with QUEUEITEMS, queue end END. To make sense, the commands should correspond to processing actions for processing a region from (buffer-queue-or-locked-end) to END. The queue mode is set to 'advancing \(fn END QUEUEITEMS)" nil nil) (autoload 'proof-shell-wait "proof-shell" "\ Busy wait for `proof-shell-busy' to become nil, reading from prover. Needed between sequences of commands to maintain synchronization, because Proof General does not allow for the action list to be extended in some cases. Also is considerably faster than leaving the Emacs top-level command loop to read from the prover. Called by `proof-shell-invisible-command' and `proof-process-buffer' when setting `proof-fast-process-buffer' is enabled. If INTERRUPT-ON-INPUT is non-nil, return if input is received. If TIMEOUTSECS is a number, time out after that many seconds. \(fn &optional INTERRUPT-ON-INPUT TIMEOUTSECS)" nil nil) (autoload 'proof-shell-invisible-command "proof-shell" "\ Send CMD to the proof process. The CMD is `invisible' in the sense that it is not recorded in buffer. CMD may be a string or a string-yielding expression. Automatically add `proof-terminal-string' if necessary, examining `proof-shell-no-auto-terminate-commands'. By default, let the command be processed asynchronously. But if optional WAIT command is non-nil, wait for processing to finish before and after sending the command. In case CMD is (or yields) nil, do nothing. INVISIBLECALLBACK will be invoked after the command has finished, if it is set. It should probably run the hook variables `proof-state-change-hook'. FLAGS are additional flags to put onto the `proof-action-list'. The flag 'invisible is always added to FLAGS. \(fn CMD &optional WAIT INVISIBLECALLBACK &rest FLAGS)" nil nil) (autoload 'proof-shell-invisible-cmd-get-result "proof-shell" "\ Execute CMD and return result as a string. This expects CMD to result in some theorem prover output. Ordinary output (and error handling) is disabled, and the result \(contents of `proof-shell-last-output') is returned as a string. \(fn CMD)" nil nil) (autoload 'proof-shell-invisible-command-invisible-result "proof-shell" "\ Execute CMD for side effect in the theorem prover, waiting before and after. Error messages are displayed as usual. \(fn CMD)" nil nil) (autoload 'proof-shell-mode "proof-shell" "\ Proof General shell mode class for proof assistant processes \(fn)" t nil) (autoload 'proof-shell-config-done "proof-shell" "\ Initialise the specific prover after the child has been configured. Every derived shell mode should call this function at the end of processing." nil nil) (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "proof-shell" '("pg-" "proof-"))) ;;;*** ;;;### (autoloads nil "proof-site" "proof-site.el" (0 0 0 0)) ;;; Generated autoloads from proof-site.el (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "proof-site" '("proof"))) ;;;*** ;;;### (autoloads nil "proof-splash" "proof-splash.el" (0 0 0 0)) ;;; Generated autoloads from proof-splash.el (autoload 'proof-splash-display-screen "proof-splash" "\ Save window config and display Proof General splash screen. If TIMEOUT is non-nil, time out outside this function, definitely by end of configuring proof mode. Otherwise, make a key binding to remove this buffer. \(fn &optional TIMEOUT)" t nil) (autoload 'proof-splash-message "proof-splash" "\ Make sure the user gets welcomed one way or another." t nil) (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "proof-splash" '("pg-about" "proof-"))) ;;;*** ;;;### (autoloads nil "proof-syntax" "proof-syntax.el" (0 0 0 0)) ;;; Generated autoloads from proof-syntax.el (autoload 'proof-replace-regexp-in-string "proof-syntax" "\ Like ‘replace-regexp-in-string’, but set ‘case-fold-search’ to ‘proof-case-fold-search’. \(fn REGEXP REP STRING)" nil nil) (autoload 'proof-format "proof-syntax" "\ Format a string by matching regexps in ALIST against STRING. ALIST contains (REGEXP . REPLACEMENT) pairs where REPLACEMENT may be a string or sexp evaluated to get a string. \(fn ALIST STRING)" nil nil) (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "proof-syntax" '("proof-"))) ;;;*** ;;;### (autoloads nil "proof-toolbar" "proof-toolbar.el" (0 0 0 0)) ;;; Generated autoloads from proof-toolbar.el (autoload 'proof-toolbar-setup "proof-toolbar" "\ Initialize Proof General toolbar and enable it for all PG buffers. If `proof-toolbar-enable' is nil, change the buffer toolbars back the default toolbar." t nil) (autoload 'proof-toolbar-toggle "proof-toolbar") (autoload 'proof-toolbar-scripting-menu "proof-toolbar" "\ Menu made from the Proof General toolbar commands." nil nil) (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "proof-toolbar" '("proof-toolbar-"))) ;;;*** ;;;### (autoloads nil "proof-tree" "proof-tree.el" (0 0 0 0)) ;;; Generated autoloads from proof-tree.el (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "proof-tree" '("proof-tree-"))) ;;;*** ;;;### (autoloads nil "proof-unicode-tokens" "proof-unicode-tokens.el" ;;;;;; (0 0 0 0)) ;;; Generated autoloads from proof-unicode-tokens.el (autoload 'proof-unicode-tokens-mode-if-enabled "proof-unicode-tokens" "\ Turn on or off the Unicode Tokens minor mode in this buffer." nil nil) (autoload 'proof-unicode-tokens-set-global "proof-unicode-tokens" "\ Set global status of unicode tokens mode for PG buffers to be FLAG. Turn on/off menu in all script buffers and ensure new buffers follow suit. \(fn FLAG)" nil nil) (autoload 'proof-unicode-tokens-enable "proof-unicode-tokens" "\ Turn on or off Unicode tokens mode in Proof General script buffer. This invokes `unicode-tokens-mode' to toggle the setting for the current buffer, and then sets PG's option for default to match. Also we arrange to have unicode tokens mode turn itself on automatically in future if we have just activated it for this buffer. Note: this function is called when the customize setting for the prover is changed." t nil) (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "proof-unicode-tokens" '("proof-unicode-tokens-"))) ;;;*** ;;;### (autoloads nil "proof-useropts" "proof-useropts.el" (0 0 0 ;;;;;; 0)) ;;; Generated autoloads from proof-useropts.el (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "proof-useropts" '("pg-" "proof-"))) ;;;*** ;;;### (autoloads nil "proof-utils" "proof-utils.el" (0 0 0 0)) ;;; Generated autoloads from proof-utils.el (autoload 'proof-upgrade-elpa-packages "proof-utils" "\ Upgrade all ELPA packages (using package.el)." t nil) (autoload 'proof-debug "proof-utils" "\ Issue the debugging message (format MSG ARGS) in the *PG Debug* buffer. If flag `proof-general-debug' is nil, do nothing. \(fn MSG &rest ARGS)" nil nil) (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "proof-utils" '("pg-" "proof-"))) ;;;*** ;;;### (autoloads nil "../lib/scomint" "../lib/scomint.el" (0 0 0 ;;;;;; 0)) ;;; Generated autoloads from ../lib/scomint.el (autoload 'scomint-make-in-buffer "../lib/scomint" "\ Make a Comint process NAME in BUFFER, running PROGRAM. If BUFFER is nil, it defaults to NAME surrounded by `*'s. PROGRAM should be either a string denoting an executable program to create via `start-file-process', or a cons pair of the form (HOST . SERVICE) denoting a TCP connection to be opened via `open-network-stream'. If there is already a running process in that buffer, it is not restarted. Optional fourth arg STARTFILE is the name of a file to send the contents of to the process. If PROGRAM is a string, the remaining SWITCHES are arguments to PROGRAM. \(fn NAME BUFFER PROGRAM &optional STARTFILE &rest SWITCHES)" nil nil) (autoload 'scomint-make "../lib/scomint" "\ Make a Comint process NAME in a buffer, running PROGRAM. The name of the buffer is made by surrounding NAME with `*'s. PROGRAM should be either a string denoting an executable program to create via `start-file-process', or a cons pair of the form (HOST . SERVICE) denoting a TCP connection to be opened via `open-network-stream'. If there is already a running process in that buffer, it is not restarted. Optional third arg STARTFILE is the name of a file to send the contents of the process to. If PROGRAM is a string, the remaining SWITCHES are arguments to PROGRAM. \(fn NAME PROGRAM &optional STARTFILE &rest SWITCHES)" nil nil) (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "../lib/scomint" '("scomint-"))) ;;;*** ;;;### (autoloads nil "../lib/texi-docstring-magic" "../lib/texi-docstring-magic.el" ;;;;;; (0 0 0 0)) ;;; Generated autoloads from ../lib/texi-docstring-magic.el (autoload 'texi-docstring-magic "../lib/texi-docstring-magic" "\ Update all texi docstring magic annotations in buffer. With prefix arg, no errors on unknown symbols. (This results in @def .. @end being deleted if not known). \(fn &optional NOERROR)" t nil) (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "../lib/texi-docstring-magic" '("texi-docstring-"))) ;;;*** ;;;### (autoloads nil "../lib/unicode-chars" "../lib/unicode-chars.el" ;;;;;; (0 0 0 0)) ;;; Generated autoloads from ../lib/unicode-chars.el (autoload 'unicode-chars-list-chars "../lib/unicode-chars" "\ Insert each Unicode character into a buffer. Lets you see which characters are available for literal display in your Emacs font." t nil) (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "../lib/unicode-chars" '("unicode-chars-alist"))) ;;;*** ;;;### (autoloads nil "../lib/unicode-tokens" "../lib/unicode-tokens.el" ;;;;;; (0 0 0 0)) ;;; Generated autoloads from ../lib/unicode-tokens.el (autoload 'unicode-tokens-encode-str "../lib/unicode-tokens" "\ Return a unicode encoded version presentation of STR. \(fn STR)" nil nil) (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "../lib/unicode-tokens" '("unicode-tokens-"))) ;;;*** ;;;### (autoloads nil nil ("../qrhl/qrhl-input.el" "proof.el") (0 ;;;;;; 0 0 0)) ;;;*** ;; Local Variables: ;; version-control: never ;; no-update-autoloads: t ;; End: ;;; proof-autoloads.el ends here PG-4.5/generic/proof-auxmodes.el000066400000000000000000000034161426357011200166030ustar00rootroot00000000000000;;; proof-auxmodes.el --- Arrange for auxiliary modes to be loaded when required ;; This file is part of Proof General. ;; Portions © Copyright 1994-2012 David Aspinall and University of Edinburgh ;; Portions © Copyright 2003, 2012, 2014 Free Software Foundation, Inc. ;; Portions © Copyright 2001-2017 Pierre Courtieu ;; Portions © Copyright 2010, 2016 Erik Martin-Dorel ;; Portions © Copyright 2011-2013, 2016-2017 Hendrik Tews ;; Portions © Copyright 2015-2017 Clément Pit-Claudel ;; Author: David Aspinall ;; SPDX-License-Identifier: GPL-3.0-or-later ;;; Commentary: ;; ;; Startup code from auxiliary modes are collected here, allowing late ;; loading of their main defining files and the possibility to disable them. ;; ;;; Code: (require 'proof-utils) ; proof-ass, proof-eval... ;; ;; Maths menu ;; (defun proof-maths-menu-support-available () "A test to see whether maths-menu support is available. The test loads optional prover-specific config in -maths-menu.el" (or (proof-try-require (proof-ass-sym maths-menu)) t)) (proof-eval-when-ready-for-assistant (if (and (proof-ass maths-menu-enable) (proof-maths-menu-support-available)) (proof-maths-menu-set-global t))) ;; ;; Unicode tokens ;; (defun proof-unicode-tokens-support-available () "A test to see whether unicode tokens support is available." ;; Requires prover-specific config in -unicode-tokens.el ;; Loaded before unicode-tokens.el to allow load-time config there (proof-try-require (proof-ass-sym unicode-tokens))) (proof-eval-when-ready-for-assistant (if (and (proof-ass unicode-tokens-enable) (proof-unicode-tokens-support-available)) (proof-unicode-tokens-set-global t))) (provide 'proof-auxmodes) ;;; proof-auxmodes.el ends here PG-4.5/generic/proof-config.el000066400000000000000000002252341426357011200162270ustar00rootroot00000000000000;;; proof-config.el --- Proof General configuration for proof assistant ;; This file is part of Proof General. ;; Portions © Copyright 1994-2012 David Aspinall and University of Edinburgh ;; Portions © Copyright 2003-2021 Free Software Foundation, Inc. ;; Portions © Copyright 2001-2017 Pierre Courtieu ;; Portions © Copyright 2010, 2016 Erik Martin-Dorel ;; Portions © Copyright 2011-2013, 2016-2017 Hendrik Tews ;; Portions © Copyright 2015-2017 Clément Pit-Claudel ;; Author: David Aspinall and others ;; SPDX-License-Identifier: GPL-3.0-or-later ;;; Commentary: ;; ;; This file declares all prover-specific configuration variables for ;; Proof General. The variables are used variously by the proof ;; script mode and the proof shell mode, menus, and toolbar. ;; ;; To customize Proof General for a new proof assistant, you ;; should read this file carefully! ;; ;; 1. Menus, user-level commands, toolbar ;; 2. Script mode configuration ;; 3. Shell mode configuration ;; 3a. commands ;; 3b. regexps ;; 3c. tokens ;; 3d. hooks and others ;; 4. Goals buffer configuration ;; ;; The remaining variables in should be set for each proof assistant. ;; You don't need to set every variable for basic functionality; ;; consult the manual for details of which ones are important. ;; ;; Customization groups and structure (sections in brackets) ;; ;; proof-general : Overall group ;; proof-user-options : User options for Proof General ;; (see proof-useropts.el) ;; : User options for proof assistant ;; (see pg-custom.el) ;; -internals : Internal settings for proof assistant ;; (see pg-custom.el) ;; ;; proof-general-internals : Internal settings of Proof General ;; prover-config : Configuration for proof assistant (1) ;; proof-script : settings for proof script mode (2) ;; proof-shell : settings for proof shell mode (3) ;; proof-goals : settings for goals buffer (4) ;; -config : Specific internal settings for a prover ;; ;; ====================================================================== ;; ;; Developer notes: ;; ;; i. When adding a new configuration variable, please ;; (a) put it in the right customize group, and ;; (b) add a magical comment in ProofGeneral.texi/PG-adapting.texi ;; ;; ii. Presently the customize library seems a bit picky over the ;; :type property and some correct but complex types don't work: ;; If the type is ill-formed, editing the whole group will be ;; broken. Check after updates, by killing all customize buffers ;; and invoking customize-group ;; ;; ;; See also: ;; ;; pg-custom.el ;; pg-vars.el ;;; Code: (require 'proof-useropts) ; user options (require 'proof-faces) ; user options: faces (eval-when-compile (require 'custom)) ;; ;; Prelude ;; (defgroup prover-config nil "Configuration of Proof General for the prover in use." :group 'proof-general-internals :prefix "proof-") ;; The variables in the "prover-config" (NB: not "proof config"!!) ;; customize group are those which are intended to be set by the ;; prover specific elisp, i.e. constants set on a per-prover basis. ;; Putting these in a customize group is useful for documenting this ;; type of variable, and for developing a new instantiation of Proof ;; General. But it is *not* useful for final user-level ;; customization! The reason is that saving these customizations ;; across a session is not liable to work, because the prover specific ;; elisp usually overrides with a series of setq's in ;; -mode-config type functions. This is why prover-config ;; appears under the proof-general-internal group. (defcustom proof-guess-command-line nil "Function to guess command line for proof assistant, given a filename. The function could take a filename as argument, run `make -n' to see how to compile the file non-interactively, then translate the result into an interactive invocation of the proof assistant with the same command line options. For an example, see coq/coq.el." :type 'function :group 'prover-config) ;; ;; 1. Configuration for menus, user-level commands, toolbar, etc. ;; (defcustom proof-assistant-home-page "" "Web address for information on proof assistant. Used for Proof General's help menu." :type 'string :group 'prover-config) (defcustom proof-context-command nil "Command to display the context in proof assistant." :type 'string :group 'prover-config) (defcustom proof-info-command nil "Command to ask for help or information in the proof assistant. String or fn. If a string, the command to use. If a function, it should return the command string to insert." :type '(choice string function) :group 'prover-config) (defcustom proof-showproof-command nil "Command to display proof state in proof assistant." :type 'string :group 'prover-config) (defcustom proof-goal-command nil "Command to set a goal in the proof assistant. String or fn. If a string, the format character `%s' will be replaced by the goal string. If a function, it should return the command string to insert." :type '(choice string function) :group 'prover-config) (defcustom proof-save-command nil "Command to save a proved theorem in the proof assistant. String or fn. If a string, the format character `%s' will be replaced by the theorem name. If a function, it should return the command string to insert." :type '(choice string function) :group 'prover-config) (defcustom proof-find-theorems-command nil "Command to search for a theorem containing a given term. String or fn. If a string, the format character `%s' will be replaced by the term. If a function, it should return the command string to send." :type '(choice string function) :group 'prover-config) (defcustom proof-query-identifier-command nil "Command sent to the prover to query about a given identifier (or string). This is typically a command used to print a theorem, constant, or whatever. Inside the command the string %s is replaced by the given identifier or string. Value should be a string for a single command, or maybe an association list between values for `proof-buffer-syntactic-context' and strings, which allows different prover commands to be sent based on the syntactic context of the string. If value is an alist, must include a default value for no context (nil)." :type '(or string (list (cons (choice 'nil 'string 'comment) string))) :group 'proof-shell) (defcustom proof-assistant-true-value "true" "String for true values in proof assistant, used for setting flags. Default is the string \"true\"." :type 'string :group 'prover-config) (defcustom proof-assistant-false-value "false" "String for false values in proof assistant, used for setting flags. Default is the string \"false\"." :type 'string :group 'prover-config) (defcustom proof-assistant-format-int-fn 'int-to-string "Function for converting integer values to ints in proof assistant. Used for configuring settings in proof assistant. Default is `int-to-string'." :type 'function :group 'prover-config) (defcustom proof-assistant-format-float-fn 'number-to-string "Function for converting float values to ints in proof assistant. Used for configuring settings in proof assistant. Default is `number-to-string'." :type 'function :group 'prover-config) (defcustom proof-assistant-format-string-fn (lambda (value) value) "Function for converting string values to strings in proof assistant. Used for configuring settings in proof assistant. Default is the identity function." :type 'string :group 'prover-config) (defcustom proof-assistant-setting-format nil "Function for formatting setting strings for proof assistant. Setting strings are calculated by replacing a format character %b, %i, %f, %s, or %l in the :setting string in for each variable defined with `defpacustom', using the current value of that variable. This function is applied as a final step to do any extra markup, or conversion, etc. (No changes are done if nil)." :type '(choice string (const nil)) :group 'prover-config) (defcustom proof-tree-configured nil "Whether external proof-tree display is configured. This boolean enables the proof-tree menu entry and the function that starts external proof-tree display." :type 'boolean :group 'proof-tree-internals) ;; ;; 2. Configuration for proof script mode ;; ;; ;; The following variables should be set before proof-config-done ;; is called. These configure the mode for the script buffer, ;; including highlighting, etc. ;; (defgroup proof-script nil "Proof General configuration of scripting buffer mode." :group 'prover-config :prefix "proof-") (defcustom proof-terminal-string nil "String that terminates commands sent to prover; nil if none. To configure command recognition properly, you must set at least one of these: `proof-script-sexp-commands', `proof-script-command-end-regexp', `proof-script-command-start-regexp', `proof-terminal-string', or `proof-script-parse-function'." :type 'character :group 'prover-config) (defcustom proof-electric-terminator-noterminator nil "If non-nil, electric terminator does not actually insert a terminator." :type 'boolean :group 'prover-config) (defcustom proof-script-sexp-commands nil "Non-nil if script has Lisp-like syntax: commands are top-level sexps. You should set this variable in script mode configuration. To configure command recognition properly, you must set at least one of these: `proof-script-sexp-commands', `proof-script-command-end-regexp', `proof-script-command-start-regexp', `proof-terminal-string', or `proof-script-parse-function'." :type 'boolean :group 'prover-config) (defcustom proof-script-command-end-regexp nil "Regular expression which matches end of commands in proof script. You should set this variable in script mode configuration. The end of the command is considered to be the end of the match of this regexp. The regexp may include a nested group, which can be used to recognize the start of the following command \(or white space). If there is a nested group, the end of the command is considered to be the start of the nested group, i.e. (match-beginning 1), rather than (match-end 0). To configure command recognition properly, you must set at least one of these: `proof-script-sexp-commands', `proof-script-command-end-regexp', `proof-script-command-start-regexp', `proof-terminal-string', or `proof-script-parse-function'." :type 'string :group 'prover-config) (defcustom proof-script-command-start-regexp nil "Regular expression which matches start of commands in proof script. You should set this variable in script mode configuration. To configure command recognition properly, you must set at least one of these: `proof-script-sexp-commands', `proof-script-command-end-regexp', `proof-script-command-start-regexp', `proof-terminal-string', or `proof-script-parse-function'." :type 'string :group 'prover-config) (defcustom proof-script-integral-proofs nil "Whether the complete text after a goal confines the actual proof. In structured proof languages like Isabelle/Isar a theorem is established by a goal statement (with full information about the result, including name and statement), followed by a self-contained piece of text for the proof. The latter should be treated as an integral entity for purposes of hiding proof bodies etc. This variable is better set to nil for tactical provers (like Coq) where important information about the result is spread over the initial ``goal'' and the final ``save'' command." :type 'boolean :group 'prover-config) (defcustom proof-script-fly-past-comments nil "*If non-nil, fly past successive comments, coalescing into single spans." :type 'boolean :group 'proof-user-options) (defcustom proof-script-parse-function nil "A function which parses a portion of the proof script. It is called with the proof script as the current buffer, and point the position where the parse should begin. It should move point to the exact end of the next \"segment\", and return a symbol indicating what has been parsed: 'comment for a comment 'cmd for a proof script command nil if there is no complete next segment in the buffer If this is left unset, it will be configured automatically to a generic function according to which of `proof-terminal-string' and its friends are set." :type 'string :group 'prover-config) (defcustom proof-script-comment-start "" "String which starts a comment in the proof assistant command language. The script buffer's `comment-start' is set to this string plus a space. Moreover, comments are usually ignored during script management, and not sent to the proof process. You should set this variable for reliable working of Proof General, as well as `proof-script-comment-end'." :type 'string :group 'proof-script) (defcustom proof-script-comment-start-regexp nil "Regexp which matches a comment start in the proof command language. The default value for this is set as (regexp-quote `proof-script-comment-start') but you can set this variable to something else more precise if necessary." :type 'string :group 'proof-script) (defcustom proof-script-comment-end "" "String which ends a comment in the proof assistant command language. Should be an empty string if comments are terminated by `end-of-line' The script buffer's `comment-end' is set to a space plus this string, if it is non-empty. See also `proof-script-comment-start'. You should set this variable for reliable working of Proof General." :type 'string :group 'proof-script) (defcustom proof-script-comment-end-regexp nil "Regexp which matches a comment end in the proof command language. The default value for this is set as (regexp-quote `proof-script-comment-end') but you can set this variable to something else more precise if necessary." :type 'string :group 'proof-script) (defcustom proof-string-start-regexp "\"" "Matches the start of a quoted string in the proof assistant command language." :type 'string :group 'proof-script) (defcustom proof-string-end-regexp "\"" "Matches the end of a quoted string in the proof assistant command language." :type 'string :group 'proof-script) (defcustom proof-case-fold-search nil "Value for `case-fold-search' when recognizing portions of proof scripts. Also used for completion, via `proof-script-complete'. The default value is nil. If your prover has a case *insensitive* input syntax, `proof-case-fold-search' should be set to t instead. NB: This setting is not used for matching output from the prover." :type 'boolean :group 'proof-script) (defcustom proof-save-command-regexp nil "Matches a save command." :type 'regexp :group 'proof-script) (defcustom proof-show-proof-diffs-regexp nil "Matches all \"Show Proof\" forms (specific to the Coq prover)." :type 'regexp :group 'proof-script) (defcustom proof-save-with-hole-regexp nil "Regexp which matches a command to save a named theorem. The name of the theorem is built from the variable `proof-save-with-hole-result' using the same convention as `query-replace-regexp'. Used for setting names of goal..save and proof regions. It's safe to leave this setting as nil." :type 'regexp :group 'proof-script) (defcustom proof-save-with-hole-result 2 "How to get theorem name after ‘proof-save-with-hole-regexp’ match. String or Int. If an int N, use ‘match-string’ to get the value of the Nth parenthesis matched. If a string, use ‘replace-match’. In this case, ‘proof-save-with-hole-regexp’ should match the entire command." :type '(choice string integer) :group 'proof-script) ;; FIXME: unify uses so that proof-anchor-regexp works sensibly (defcustom proof-goal-command-regexp nil "Matches a goal command in the proof script. This is used to make the default value for `proof-goal-command-p', used as an important part of script management to find the start of an atomic undo block." :type 'regexp :group 'proof-script) (defcustom proof-goal-with-hole-regexp nil "Regexp which matches a command used to issue and name a goal. The name of the theorem is built from the variable `proof-goal-with-hole-result' using the same convention as for `query-replace-regexp'. Used for setting names of goal..save regions and for default configuration of other modes (function menu, imenu). It's safe to leave this setting as nil." :type 'regexp :group 'proof-script) (defcustom proof-goal-with-hole-result 2 "How to get theorem name after `proof-goal-with-hole-regexp' match. String or Int. If an int N, use `match-string' to get the value of the Nth parenthesis matched. If a string, use `replace-match'. In this case, `proof-goal-with-hole-regexp' should match the entire command." :type '(choice string integer) :group 'proof-script) (defcustom proof-non-undoables-regexp nil "Regular expression matching commands which are *not* undoable. These are commands which should not appear in proof scripts, for example, undo commands themselves (if the proof assistant cannot \"redo\" an \"undo\"). Used in default functions `proof-generic-state-preserving-p' and `proof-generic-count-undos'. If you don't use those, may be left as nil." :type '(choice (const nil) regexp) :group 'proof-script) (defcustom proof-nested-undo-regexp nil "Regexp for commands that must be counted in nested goal-save regions. Used for provers which allow nested atomic goal-saves, but with some nested history that must be undone specially. At the moment, the behaviour is that a goal-save span has a 'nestedundos property which is set to the number of commands within it which match this regexp. The idea is that the prover-specific code can create a customized undo command to retract the goal-save region, based on the 'nestedundos setting. Coq uses this to forget declarations, since declarations in Coq reside in a separate context with its own (flat) history." :type '(choice (const nil) regexp) :group 'proof-script) (defcustom proof-ignore-for-undo-count nil "Matcher for script commands to be ignored in undo count. May be left as nil, in which case it will be set to `proof-non-undoables-regexp'. Used in default function `proof-generic-count-undos'." :type '(choice (const nil) regexp function) :group 'proof-script) (defcustom proof-script-imenu-generic-expression nil "Regular expressions to help find definitions and proofs in a script. Value for `imenu-generic-expression', see documentation of Imenu and that variable for details." :type 'sexp :group 'proof-script) ;; FIXME da: unify this with proof-save-command-regexp, to allow fn or regexp (defcustom proof-goal-command-p 'proof-generic-goal-command-p "A function to test: is this really a goal command span? This is added as a more refined addition to `proof-goal-command-regexp', to solve the problem that Coq and some other provers can have goals which look like definitions, etc. (In the future we may generalize `proof-goal-command-regexp' instead)." :type 'function :group 'proof-script) ;; FIXME da: unify this with proof-save-command-regexp, to allow fn or regexp (defcustom proof-really-save-command-p (lambda (span cmd) t) "Is this really a save command? This is a more refined addition to `proof-save-command-regexp'. It should be a function taking a span and command as argument, and can be used to track nested proofs." :type 'function :group 'proof-script) (defcustom proof-completed-proof-behaviour nil "Indicates how Proof General treats commands beyond the end of a proof. Normally goal...save regions are \"closed\", i.e. made atomic for undo. But once a proof has been completed, there may be a delay before the \"save\" command appears --- or it may not appear at all. Unless nested proofs are supported, this can spoil the undo-behaviour in script management since once a new goal arrives the old undo history may be lost in the prover. So we allow Proof General to close off the goal..[save] region in more flexible ways. The possibilities are: nil - nothing special; close only when a save arrives 'closeany - close as soon as the next command arrives, save or not 'closegoal - close when the next \"goal\" command arrives 'extend - keep extending the closed region until a save or goal. If your proof assistant allows nested goals, it will be wrong to close off the portion of proof so far, so this variable should be set to nil. NB: 'extend behaviour is not currently compatible with appearance of save commands, so don't use that if your prover has save commands." :type '(choice (const :tag "Close on save only" nil) (const :tag "Close next command" closeany) (const :tag "Close next goal" closegoal) (const :tag "Extend" ignore)) :group 'proof-script) (defcustom proof-count-undos-fn 'proof-generic-count-undos "Function to calculate a list of commands to undo to reach a target span. The function takes a span as an argument, and should return a string which is the command to undo to the target span. The target is guaranteed to be within the current (open) proof. This is an important function for script management. The default setting `proof-generic-count-undos' is based on the settings `proof-non-undoables-regexp' and `proof-non-undoables-regexp'." :type 'function :group 'proof-script) (defcustom proof-find-and-forget-fn 'proof-generic-find-and-forget "Function to return list of commands to forget to before its argument span. This setting is used to for retraction (undoing) in proof scripts. It should undo the effect of all settings between its target span up to (proof-unprocessed-begin). This may involve forgetting a number of definitions, declarations, or whatever. If return value is nil, it means there is nothing to do. This is an important function for script management. Study one of the existing instantiations for examples of how to write it, or leave it set to the default function `proof-generic-find-and-forget' \(which see)." :type 'function :group 'proof-script) (defcustom proof-forget-id-command nil "Command to forget back to a given named span. A string; `%s' will be replaced by the name of the span. This is only used in the implementation of `proof-generic-find-and-forget', you only need to set if you use that function (by not customizing `proof-find-and-forget-fn'." :type 'string :group 'proof-script) (defcustom pg-topterm-goalhyplit-fn nil "Function to return cons if point is at a goal/hypothesis/literal. This is used to parse the proofstate output to mark it up for proof-by-pointing or literal command insertion. It should return a cons or nil. First element of the cons is a symbol, 'goal', 'hyp' or 'lit'. The second element is a string: the goal, hypothesis, or literal command itself. If you leave this variable unset, no proof-by-pointing markup will be attempted." :type '(choice function (const nil)) :group 'proof-script) (defcustom proof-kill-goal-command nil "Command to kill the currently open goal. If this is set to nil, PG will expect `proof-find-and-forget-fn' to do all the work of retracting to an arbitrary point in a file. Otherwise, the generic split-phase mechanism will be used: 1. If inside an unclosed proof, use `proof-count-undos'. 2. If retracting to before an unclosed proof, use `proof-kill-goal-command', followed by `proof-find-and-forget-fn' if necessary." :type 'string :group 'proof-script) (defcustom proof-undo-n-times-cmd nil "Command to undo n steps of the currently open goal. String or function. If this is set to a string, `%s' will be replaced by the number of undo steps to issue. If this is set to a function, it should return a list of the appropriate commands (given the number of undo steps). This setting is used for the default `proof-generic-count-undos'. If you set `proof-count-undos-fn' to some other function, there is no need to set this variable." :type '(or string function) :group 'proof-script) (defcustom proof-nested-goals-history-p nil "Whether the prover supports recovery of history for nested proofs. If it does (non-nil), Proof General will retain history inside nested proofs. If it does not, Proof General will amalgamate nested proofs into single steps within the outer proof." :type 'boolean :group 'proof-script) (defcustom proof-arbitrary-undo-positions nil "Non-nil if Proof General may undo to arbitrary positions. The classic behaviour of Proof General is to undo completed proofs in one step: this design arose because older provers discarded nested history once proofs were complete. The proof script engine amalgamates spans for a complete proof (into a single 'goalsave) to give this effect. Newer designs keep more state, and may support arbitrary undo with a file being processed. If this flag is non-nil, amalgamation will not happen." :type 'boolean :group 'proof-script) (defcustom proof-state-preserving-p 'proof-generic-state-preserving-p "A predicate, non-nil if its argument (a command) preserves the proof state. This is a safety-test used by `proof-minibuffer-cmd' to filter out scripting commands which should be entered directly into the script itself. The default setting for this function, `proof-generic-state-preserving-p' tests by negating the match on `proof-non-undoables-regexp'." :type 'function :group 'proof-script) (defcustom proof-activate-scripting-hook nil "Hook run when a buffer is switched into scripting mode. The current buffer will be the newly active scripting buffer. This hook may be useful for synchronizing with the proof assistant, for example, to switch to a new theory \(in case that isn't already done by commands in the proof script). When functions in this hook are called, the variable `activated-interactively' will be non-nil if `proof-activate-scripting' was called interactively \(rather than as a side-effect of some other action). If a hook function sends commands to the proof process, it should wait for them to complete (so the queue is cleared for scripting commands), unless activated-interactively is set." :type '(repeat function) :group 'proof-script) (defcustom proof-deactivate-scripting-hook nil "Hook run when a buffer is switched out of scripting mode. The current buffer will be the recently scripting buffer. This hook may be useful for synchronizing with the proof assistant, for example, to compile a completed file." :type '(repeat function) :group 'proof-script) (defcustom proof-no-fully-processed-buffer nil "Set to t if buffers should always retract before scripting elsewhere. Leave at nil if fully processed buffers make sense for the current proof assistant. If nil the user can choose to fully assert a buffer when starting scripting in a different buffer. If t there is only the choice to fully retract the active buffer before starting scripting in a different buffer. This last behavior is needed for Coq." :type 'boolean :group 'proof-script) (defcustom proof-omit-proofs-configured nil "t if the omit proofs feature has been configured by the proof assitant. See also `proof-omit-proofs-option' or the Proof General manual for a description of the feature. This option can only be set, if all of `proof-script-proof-start-regexp', `proof-script-proof-end-regexp', `proof-script-definition-end-regexp' and `proof-script-proof-admit-command' have been configured. The omit proofs feature skips over opaque proofs in the source code, admitting the theorems, to speed up processing. If `proof-omit-proofs-option' is set by the user, all proof commands in the source following a match of `proof-script-proof-start-regexp' up to and including the next match of `proof-script-proof-end-regexp', are omitted (not send to the proof assistant) and replaced by `proof-script-proof-admit-command'. If a match for `proof-script-definition-end-regexp' is found while searching forward for the proof end, the current proof (up to and including the match of `proof-script-definition-end-regexp') is considered to be not opaque and not omitted, thus all these proof commands _are_ sent to the proof assistant. The feature does not work for nested proofs. If a match for `proof-script-proof-start-regexp' is found before the next match for `proof-script-proof-end-regexp' or `proof-script-definition-end-regexp', the search for opaque proofs immediately stops and all commands following the previous match of `proof-script-proof-start-regexp' are sent verbatim to the proof assistant. All the regular expressions for this feature are matched against the commands inside proof action items, that is as strings, without surrounding space." :type 'boolean :group 'proof-script) ;; proof-omit-proofs-option is in proof-useropts as user option (defcustom proof-script-proof-start-regexp nil "Regular expression for the start of a proof for the omit proofs feature. See `proof-omit-proofs-configured'." :type 'regexp :group 'proof-script) (defcustom proof-script-proof-end-regexp nil "Regular expression for the end of an opaque proof for the omit proofs feature. See `proof-omit-proofs-configured'." :type 'regexp :group 'proof-script) (defcustom proof-script-definition-end-regexp nil "Regexp for the end of a non-opaque proof for the omit proofs feature. See `proof-omit-proofs-configured'." :type 'regexp :group 'proof-script) (defcustom proof-script-proof-admit-command nil "Proof command to be inserted instead of omitted proofs." :type 'string :group 'proof-script) ;; ;; Proof script indentation ;; (defcustom proof-indent 2 "Amount of proof script indentation." :type 'number :group 'proof-script) (defcustom proof-indent-hang nil "Enable 'hanging' indentation for proof script." :type 'boolean :group 'proof-script) (defcustom proof-indent-enclose-offset 1 "Extra offset for enclosing indentation syntax elements." :type 'number :group 'proof-script) (defcustom proof-indent-open-offset 1 "Extra offset for opening indentation syntax elements." :type 'number :group 'proof-script) (defcustom proof-indent-close-offset 1 "Extra offset for closing indentation syntax elements." :type 'number :group 'proof-script) (defcustom proof-indent-any-regexp "\\s(\\|\\s)" "Regexp for *any* syntax element guiding proof script indentation." :type 'string :group 'proof-script) (defcustom proof-indent-inner-regexp nil "Regexp for text within syntax elements of proof script indentation." :type 'string :group 'proof-script) (defcustom proof-indent-enclose-regexp nil "Regexp for enclosing syntax elements of proof script indentation." :type 'string :group 'proof-script) (defcustom proof-indent-open-regexp "\\s(" "Regexp for opening syntax elements of proof script indentation." :type 'string :group 'proof-script) (defcustom proof-indent-close-regexp "\\s)" "Regexp for closing syntax elements of proof script indentation." :type 'string :group 'proof-script) (defcustom proof-script-insert-newlines t "If non-nil, insert a newline between each message in response buffer." :type 'boolean :group 'proof-script) (defcustom proof-script-color-error-messages t "If non-nil, error messages will be globally colored with corresponding face. If prover mode has a better coloring mechanism for errors, set this to nil." :type 'boolean :group 'proof-script) (defcustom proof-script-font-lock-keywords nil "Value of `font-lock-keywords' used to fontify proof scripts. The proof script mode should set this before calling `proof-config-done'. Used also by `proof-easy-config' mechanism. See also `proof-goals-font-lock-keywords' and `proof-response-font-lock-keywords'." :type 'sexp :group 'proof-script) (defcustom proof-script-syntax-table-entries nil "List of syntax table entries for proof script mode. A flat list of the form (CHAR SYNCODE CHAR SYNCODE ...) See doc of `modify-syntax-entry' for details of characters and syntax codes. At present this is used only by the `proof-easy-config' macro." :type 'sexp :group 'proof-script) ;; ;; Proof script context menu customization ;; (defcustom proof-script-span-context-menu-extensions nil "Extensions for the in-span context sensitive menu. This should be a function which accepts three arguments: SPAN IDIOM NAME. See pg-user.el: `pg-create-in-span-context-menu' for more hints." :type 'function :group 'proof-script) ;; ;; 3. Configuration for proof shell ;; ;; The variables in this section concern the proof shell mode. ;; The first group of variables are hooks invoked at various points. ;; The second group of variables are concerned with matching the output ;; from the proof assistant. ;; ;; Variables here are put into the customize group 'proof-shell'. ;; ;; These should be set in the shell mode configuration, again, ;; before proof-shell-config-done is called. ;; (defgroup proof-shell nil "Settings for output from the proof assistant in the proof shell." :group 'prover-config :prefix "proof-shell-") ;; ;; 3a. commands ;; (defcustom proof-prog-name nil "System command to run the proof assistant in the proof shell. May contain arguments separated by spaces, but see also the prover specific settings `-prog-args' and `-prog-env'. Remark: if `-prog-args' is non-nil, then `proof-prog-name' is considered strictly: it must contain *only* the program name with no option, spaces are interpreted literally as part of the program name." :type 'string :group 'proof-shell) (defcustom proof-shell-auto-terminate-commands t "Non-nil if Proof General should try to add terminator to every command. If non-nil, whenever a command is sent to the prover using `proof-shell-invisible-command', Proof General will check to see if it ends with `proof-terminal-string', and add it if not. If `proof-terminal-string' is nil, this has no effect." :type 'boolean :group 'proof-shell) (defcustom proof-shell-pre-sync-init-cmd nil "The command for configuring the proof process to gain synchronization. This command is sent before Proof General's synchronization mechanism is engaged, to allow customization inside the process to help gain syncrhonization (e.g. engaging special markup). It is better to configure the proof assistant for this purpose via command line options if possible, in which case this variable does not need to be set. See also `proof-shell-init-cmd'." :type '(choice string (const nil)) :group 'proof-shell) (defcustom proof-shell-init-cmd nil "The command(s) for initially configuring the proof process. This command is sent to the process as soon as synchronization is gained \(when an annotated prompt is first recognized). It can be used to configure the proof assistant in some way, or print a welcome message \(since output before the first prompt is discarded). See also `proof-shell-pre-sync-init-cmd'." :type '(choice (list string) string (const nil)) :group 'proof-shell) ;; TODO: remove proof-shell-init-cmd in favour of this hook (defcustom proof-shell-init-hook nil "Hooks run when the proof process has started up." :type '(list function) :group 'proof-shell) (defcustom proof-shell-restart-cmd "" "A command for re-initialising the proof process." :type '(choice string (const nil)) :group 'proof-shell) (defcustom proof-shell-quit-cmd nil "A command to quit the proof process. If nil, send EOF instead." :type '(choice string (const nil)) :group 'proof-shell) (defcustom proof-shell-cd-cmd nil "Command to the proof assistant to change the working directory. The format character `%s' is replaced with the directory, and the escape sequences in `proof-shell-filename-escapes' are applied to the filename. This setting is used to define the function `proof-cd' which changes to the value of (default-directory) for script buffers. For files, the value of (default-directory) is simply the directory the file resides in. NB: By default, `proof-cd' is called from `proof-activate-scripting-hook', so that the prover switches to the directory of a proof script every time scripting begins." :type 'string :group 'proof-shell) (defcustom proof-shell-start-silent-cmd nil "Command to turn prover goals output off when sending many script commands. If non-nil, Proof General will automatically issue this command to help speed up processing of long proof scripts. See also `proof-shell-stop-silent-cmd'. NB: terminator not added to command." :type '(choice string (const nil)) :group 'proof-shell) (defcustom proof-shell-stop-silent-cmd nil "Command to turn prover output on. If non-nil, Proof General will automatically issue this command to help speed up processing of long proof scripts. See also `proof-shell-start-silent-cmd'. NB: Terminator not added to command." :type '(choice string (const nil)) :group 'proof-shell) (defcustom proof-shell-silent-threshold 2 "Number of waiting commands in the proof queue needed to trigger silent mode. Default is 2, but you can raise this in case switching silent mode on or off is particularly expensive (or make it ridiculously large to disable silent mode altogether)." :type 'integer :group 'proof-shell) (defcustom proof-shell-inform-file-processed-cmd nil "Command to the proof assistant to tell it that a file has been processed. The format character `%s' is replaced by a complete filename for a script file which has been fully processed interactively with Proof General. See `proof-format-filename' for other possibilities to process the filename. This setting used to interface with the proof assistant's internal management of multiple files, so the proof assistant is kept aware of which files have been processed. Specifically, when scripting is deactivated in a completed buffer, it is added to Proof General's list of processed files, and the prover is told about it by issuing this command. If this is set to nil, no command is issued. See also: `proof-shell-inform-file-retracted-cmd', `proof-shell-process-file', `proof-shell-compute-new-files-list'." :type '(choice string (const nil)) :group 'proof-shell) (defcustom proof-shell-inform-file-retracted-cmd nil "Command to the proof assistant to tell it that a file has been retracted. The format character `%s' is replaced by a complete filename for a script file which Proof General wants the prover to consider as not completely processed. See `proof-format-filename' for other possibilities to process the filename. This is used to interface with the proof assistant's internal management of multiple files, so the proof assistant is kept aware of which files have been processed. Specifically, when scripting is activated, the file is removed from Proof General's list of processed files, and the prover is told about it by issuing this command. The action may cause the prover in turn to suggest to Proof General that files depending on this one are also unlocked. If this is set to nil, no command is issued. It is also possible to set this value to a function which will be invoked on the name of the retracted file, and should remove the ancestor files from `proof-included-files-list' by some other calculation. See also: `proof-shell-inform-file-processed-cmd', `proof-shell-process-file', `proof-shell-compute-new-files-list'." :type '(choice string (const nil)) ;; FIXME: or function :group 'proof-shell) (defcustom proof-auto-multiple-files nil "Whether to use automatic multiple file management. If non-nil, Proof General will automatically retract a script file whenever another one is retracted which it depends on. It assumes a simple linear dependency between files in the order which they were processed. If your proof assistant has no management of file dependencies, or one which depends on a simple linear context, you may be able to use this setting to good effect. If the proof assistant has more complex file dependencies then you should configure it to communicate with Proof General about the dependencies rather than using this setting." :type 'boolean :group 'proof-shell) ;; not really proof-shell (defcustom proof-cannot-reopen-processed-files nil "Non-nil if the prover allows re-opening of already processed files. If the user has used Proof General to process a file incrementally, then PG will retain the spans recording undo history in the buffer corresponding to that file (provided it remains visited in Emacs). If the prover allows, it will be possible to undo to a position within this file. If the prover does *not* allow this, this variable should be set non-nil, so that when a completed file is activated for scripting (to do undo operations), the whole history is discarded." :type 'boolean :group 'proof-shell) ;; not really proof shell ;; (defcustom proof-shell-adjust-line-width-cmd nil ;; ;; 3b. Regexp variables for matching output from proof process. ;; (defcustom proof-shell-annotated-prompt-regexp nil "Regexp matching a (possibly annotated) prompt pattern. THIS IS THE MOST IMPORTANT SETTING TO CONFIGURE!! Output is grabbed between pairs of lines matching this regexp, and the appearance of this regexp is used by Proof General to recognize when the prover has finished processing a command. To help speed up matching you may be able to annotate the proof assistant prompt with a special character not appearing in ordinary output, which should appear in this regexp." :type 'regexp :group 'proof-shell) (defcustom proof-shell-error-regexp nil "Regexp matching an error report from the proof assistant. We assume that an error message corresponds to a failure in the last proof command executed. So don't match mere warning messages with this regexp. Moreover, an error message should *not* be matched as an eager annotation (see `proof-shell-eager-annotation-start') otherwise it will be lost. Error messages are considered to begin from `proof-shell-error-regexp' and continue until the next prompt. The variable `proof-shell-truncate-before-error' controls whether text before the error message is displayed. The engine matches interrupts before errors, see `proof-shell-interrupt-regexp'. It is safe to leave this variable unset (as nil)." :type '(choice (const nil) regexp) :group 'proof-shell) (defcustom proof-shell-truncate-before-error t "Non-nil means truncate output that appears before error messages. If nil, the whole output that the prover generated before the last error message will be shown. NB: the default setting for this is t to be compatible with behaviour in Proof General before version 3.4. The more obvious setting for new instances is probably nil. Interrupt messages are treated in the same way. See `proof-shell-error-regexp' and `proof-shell-interrupt-regexp'." :type 'boolean :group 'proof-shell) (defcustom pg-next-error-regexp nil "Regular expression which matches an error message, perhaps with line/column. Used by `proof-next-error' to jump to line numbers causing errors during some batch processing of the proof assistant. \(During \"manual\" script processing, script usually automatically jumps to the end of the locked region) Match number 2 should be the line number, if present. Match number 3 should be the column number, if present. The filename may be matched by `pg-next-error-filename-regexp', which is assumed to precede pg-next-error-regexp." :type 'string :group 'proof-shell) (defcustom pg-next-error-filename-regexp nil "Used to locate a filename that an error message refers to. Used by `proof-next-error' to jump to locations causing errors during some batch processing of the proof assistant. \(During \"manual\" script processing, the script usually automatically jumps to the end of the locked region). Match number 2 should be the file name, if present. Errors must first be matched by `pg-next-error-regexp' \(whether they contain a line number or not). The response buffer is then searched *backwards* for a regexp matching this variable, `pg-next-error-filename-regexp'. (So if the filename appears after the line number, make the first regexp match the whole line). Finally `pg-next-error-extract-filename' may be used to extract the filename from This regexp should be set to match messages also matched by `proof-shell-error-message-line-number-regexp'. Match number 1 should be the filename." :type 'string :group 'proof-shell) ;; FIXME: generalize this to string-or-function scheme (defcustom pg-next-error-extract-filename nil "A string used to extract filename from error message. %s replaced. NB: this is only used if the match itself does not already correspond to a filename." :type 'string :group 'proof-shell) (defcustom proof-shell-interrupt-regexp nil "Regexp matching output indicating the assistant was interrupted. We assume that an interrupt message corresponds to a failure in the last proof command executed. So don't match mere warning messages with this regexp. Moreover, an interrupt message should not be matched as an eager annotation (see `proof-shell-eager-annotation-start') otherwise it will be lost. The engine matches interrupts before errors, see `proof-shell-error-regexp'. It is safe to leave this variable unset (as nil)." :type '(choice (const nil) regexp) :group 'proof-shell) (defcustom proof-shell-proof-completed-regexp nil "Regexp matching output indicating a finished proof. When output which matches this regexp is seen, we clear the goals buffer in case this is not also marked up as a `goals' type of message. We also enable the QED function (save a proof) and we may automatically close off the proof region if another goal appears before a save command, depending on whether the prover supports nested proofs or not." :type '(choice (const nil) regexp) :group 'proof-shell) (defcustom proof-shell-clear-response-regexp nil "Regexp matching output telling Proof General to clear the response buffer. More precisely, this should match a string which is bounded by matches on `proof-shell-eager-annotation-start' and `proof-shell-eager-annotation-end'. This feature is useful to give the prover more control over what output is shown to the user. Set to nil to disable." :type '(choice (const nil) regexp) :group 'proof-shell) (defcustom proof-shell-clear-goals-regexp nil "Regexp matching output telling Proof General to clear the goals buffer. More precisely, this should match a string which is bounded by matches on `proof-shell-eager-annotation-start' and `proof-shell-eager-annotation-end'. This feature is useful to give the prover more control over what output is shown to the user. Set to nil to disable." :type '(choice (const nil) regexp) :group 'proof-shell) (defcustom proof-shell-start-goals-regexp nil "Regexp matching the start of the proof state output. This is an important setting. Output between `proof-shell-start-goals-regexp' and `proof-shell-end-goals-regexp' will be pasted into the goals buffer and possibly analysed further for proof-by-pointing markup. If it is left as nil, the goals buffer will not be used. The goals display starts at the beginning of the match on this regexp, unless it has a match group, in which case it starts at (match-end 1)." :type '(choice (const nil) regexp) :group 'proof-shell) (defcustom proof-shell-end-goals-regexp nil "Regexp matching the end of the proof state output, or nil. This allows a shorter form of the proof state output to be displayed, in case several messages are combined in a command output. The portion treated as the goals output will be that between the match on `proof-shell-start-goals-regexp' (which see) and the start of the match on `proof-shell-end-goals-regexp'. If nil, use the whole of the output from the match on `proof-shell-start-goals-regexp' up to the next prompt." :type '(choice (const nil) regexp) :group 'proof-shell) (defcustom proof-shell-empty-action-list-command nil "A function returning a list of commands (strings). These commands are sent to the prover when the last command in the queue has been performed. Typically to ask for some informational display (goals, etc.) The function takes as argument the last command in the queue. NOTE 1: The commands will be tagged invisible, i.e., not related to a place in the buffer. NOTE 2: The commands should NOT have any effect on the state of the prover. Otherwise running the script outside pg would be inconsistent." :type 'function :group 'proof-shell) (defcustom proof-shell-eager-annotation-start nil "Eager annotation field start. A regular expression or nil. An \"eager annotation indicates\" to Proof General that some following output should be displayed (or processed) immediately and not accumulated for parsing later. Note that this affects processing of output which is ordinarily accumulated: output which appears before the eager annotation start will be discarded. The start/end annotations can be used to hilight the output, but are stripped from display of the message in the minibuffer. It is useful to recognize (starts of) warnings or file-reading messages with this regexp. You must also recognize any special messages from the prover to PG with this regexp (e.g. `proof-shell-clear-goals-regexp', `proof-shell-retract-files-regexp', etc.) See also `proof-shell-eager-annotation-start-length', `proof-shell-eager-annotation-end'. Set to nil to disable this feature." :type '(choice regexp (const :tag "Disabled" nil)) :group 'proof-shell) (defcustom proof-shell-eager-annotation-start-length 10 "Maximum length of an eager annotation start. Must be set to the maximum length of the text that may match `proof-shell-eager-annotation-start' (at least 1). If this value is too low, eager annotations may be lost! This value is used internally by Proof General to optimize the process filter to avoid unnecessary searching." :type 'integer :group 'proof-shell) (defcustom proof-shell-eager-annotation-end "\n" "Eager annotation field end. A regular expression or nil. An eager annotation indicates to Emacs that some following output should be displayed or processed immediately. See also `proof-shell-eager-annotation-start'. It is nice to recognize (ends of) warnings or file-reading messages with this regexp. You must also recognize (ends of) any special messages from the prover to PG with this regexp (e.g. `proof-shell-clear-goals-regexp', `proof-shell-retract-files-regexp', etc.) The default value is \"\\n\" to match up to the end of the line." :type '(choice regexp (const :tag "Unset" nil)) :group 'proof-shell) (defcustom proof-shell-strip-output-markup 'identity "A function which strips markup from the process output. This should remove any markup which is made invisible by font-lock when displayed in the output buffer. This is used in `pg-insert-last-output-as-comment' to insert output into the proof script, and for cut and paste operations." :type 'function :group 'proof-shell) (defcustom proof-shell-assumption-regexp nil "A regular expression matching the name of assumptions. At the moment, this setting is not used in the generic Proof General. Future use may provide a generic implementation for `pg-topterm-goalhyplit-fn', used to help parse the goals buffer to annotate it for proof by pointing." :type '(choice regexp (const :tag "Unset" nil)) :group 'proof-shell) (defcustom proof-shell-process-file nil "A pair (REGEXP . FUNCTION) to match a processed file name. If REGEXP matches output, then the function FUNCTION is invoked. It must return the name of a script file (with complete path) that the system has successfully processed. In practice, FUNCTION is likely to inspect the match data. If it returns the empty string, the file name of the scripting buffer is used instead. If it returns nil, no action is taken. More precisely, REGEXP should match a string which is bounded by matches on `proof-shell-eager-annotation-start' and `proof-shell-eager-annotation-end'. Care has to be taken in case the prover only reports on compiled versions of files it is processing. In this case, FUNCTION needs to reconstruct the corresponding script file name. The new (true) file name is added to the front of `proof-included-files-list'." :type '(choice (cons regexp function) (const nil)) :group 'proof-shell) ;; FIXME da: why not amalgamate the next two into a single ;; variable as above? Maybe because removing one ;; (defcustom proof-shell-retract-files-regexp nil "Matches a message that the prover has retracted a file. More precisely, this should match a string which is bounded by matches on `proof-shell-eager-annotation-start' and `proof-shell-eager-annotation-end'. At this stage, Proof General's view of the processed files is out of date and needs to be updated with the help of the function `proof-shell-compute-new-files-list'." :type '(choice regexp (const nil)) :group 'proof-shell) (defcustom proof-shell-compute-new-files-list nil "Function to update `proof-included-files list'. It needs to return an up-to-date list of all processed files. The result will be stored in `proof-included-files-list'. This function is called when `proof-shell-retract-files-regexp' has been matched in the prover output. In practice, this function is likely to inspect the previous (global) variable `proof-included-files-list' and the match data triggered by `proof-shell-retract-files-regexp'." :type '(choice function (const nil)) :group 'proof-shell) (defcustom pg-special-char-regexp "[\200-\377]" "Regexp matching any \"special\" character sequence." :type 'string :group 'proof-shell) (defcustom proof-shell-match-pgip-cmd nil "Regexp used to match PGIP command from proof assistant. More precisely, this should match a string which is bounded by matches on `proof-shell-eager-annotation-start' and `proof-shell-eager-annotation-end'. The matching string will be parsed as XML and then processed by `pg-pgip-process-cmd'." :type '(choice (const nil) regexp) :group 'proof-shell) ;; FIXME: next one needs changing to be a function, or have function ;; built from it. (defcustom proof-shell-issue-pgip-cmd nil "Command sent to prover to process PGIP command in %s placeholder." :type '(choice (const nil) string) :group 'proof-shell) (defcustom proof-use-pgip-askprefs nil "Whether to use the PGIP command to configure prover settings." :type 'boolean :group 'proof-shell) ;; FIXME FIXME: this next one not yet used. It's hard to interleave ;; commands with the ordinary queue anyway: the prover should ;; automatically output this information if it is enabled. (defcustom proof-shell-query-dependencies-cmd nil "Command to query the prover for dependencies of given theorem name. %s is replaced by the name of the theorem. This command will be sent when a proof is completed." :type 'string :group 'proof-shell) (defcustom proof-shell-theorem-dependency-list-regexp nil "Matches output telling Proof General about dependencies. This is to allow navigation and display of dependency information. The output from the prover should be a message with the form DEPENDENCIES OF X Y Z ARE A B C with X Y Z, A B C separated by whitespace or somehow else (see `proof-shell-theorem-dependency-list-split'. This variable should be set to a regexp to match the overall message (which should be an urgent message), with two sub-matches for X Y Z and A B C. This is an experimental feature, currently work-in-progress." :type '(choice (const nil) regexp) :group 'proof-shell) (defcustom proof-shell-theorem-dependency-list-split nil "Splits strings which match `proof-shell-theorem-dependency-list-regexp'. Used as an argument to `split-string'; nil defaults to whitespace. \(This setting is necessary for provers which allow whitespace in the names of theorems/definitions/constants)." :type '(choice (const nil) regexp) :group 'proof-shell) (defcustom proof-shell-show-dependency-cmd nil "Command sent to the prover to display a dependency. This is typically a command used to print a theorem, constant, or whatever. A string with %s replaced by the dependency name." :type 'string :group 'proof-shell) ;; A feature that could be added to support Isabelle's tracing of ;; tactics. Seems to be little used, so probably not worth adding. ;(defcustom proof-shell-interactive-input-regexp nil ; "Matches special interactive input request prompt from the prover. ;A line which matches this regexp but would otherwise be treated ;as an ordinary response is instead treated as a prompt for ;input to be displayed in the minibuffer. The line which is ;input is delivered directly to the proof assistant. ;This can be used if the proof assistant requires return key ;presses to continue, or similar." ; :type 'string ; :group 'proof-shell) (defcustom proof-shell-trace-output-regexp nil "Matches tracing output which should be displayed in trace buffer. Each line which matches this regexp but would otherwise be treated as an ordinary response, is sent to the trace buffer instead of the response buffer. This is intended for unusual debugging output from the prover, rather than ordinary output from final proofs. This should match a string which is bounded by matches on `proof-shell-eager-annotation-start' and `proof-shell-eager-annotation-end'. Set to nil to disable." :type '(choice (const nil) regexp) :group 'proof-shell) (defcustom proof-shell-thms-output-regexp nil "Matches theorem display which should be displayed in theorem buffer. Each line which matches this regexp but would otherwise be treated as an ordinary response, is sent to the theorem buffer as well as the response buffer." :type '(choice (const nil) regexp) :group 'proof-shell) (defcustom proof-shell-interactive-prompt-regexp nil "Matches output from the prover which indicates an interactive prompt. If we match this, we suppose that the prover has switched to an interactive diagnostic mode which requires direct interaction with the shell rather than via script management. In this case, the shell buffer will be displayed and the user left to their own devices. Note: this should match a string which is bounded by matches on `proof-shell-eager-annotation-start' and `proof-shell-eager-annotation-end'." :type '(choice (const nil) regexp) :group 'proof-shell) (defcustom proof-shell-last-cmd-left-goals-p (lambda () nil) "A function to test: are we currently inside a proof? This function takes no argument and should use `proof-shell-last-prompt' and `proof-shell-last-output' to determine whether the last command ended up inside a proof (either by remaining inside one or opening a new one), or outside of any proof. " :type 'function :group 'proof-script) ;; ;; 3c. tokens mode: turning on/off tokens output ;; (defcustom proof-tokens-activate-command nil "Command to activate token input/output for prover. If non-nil, this command is sent to the proof assistant when Unicode Tokens support is activated." :type 'string :group 'prover-config) (defcustom proof-tokens-deactivate-command nil "Command to deactivate token input/output for prover. If non-nil, this command is sent to the proof assistant when Unicode Tokens support is deactivated." :type 'string :group 'proof-config) (defcustom proof-tokens-extra-modes nil "List of additional mode names to use with Proof General tokens. These modes will have Tokens enabled for the proof assistant token language, in addition to the four modes for Proof General (script, shell, response, pbp). Set this variable if you want additional modes to also display tokens (for example, editing documentation or source code files)." :type '(repeat symbol) :group 'proof-config) ;; ;; 3d. hooks and other miscellaneous customizations ;; (defcustom proof-shell-unicode t "Whether communication between PG and prover is 8bit clean. If non-nil, no special non-ASCII characters must be used in markup. If so, the process coding system will be set to UTF-8. With old systems that may use unsafe unicode prefix sequences \(i.e., lead to hanging in C-libraries), this should be set to nil." :type 'boolean :group 'proof-shell) (defcustom proof-shell-filename-escapes nil "A list of escapes that are applied to %s for filenames. A list of cons cells, car of which is string to be replaced by the cdr. For example, when directories are sent to Isabelle, HOL, and Coq, they appear inside ML strings and the backslash character and quote characters must be escaped. The setting '((\"\\\\\\\\\" . \"\\\\\\\\\") (\"\\\"\" . \"\\\\\\\"\")) achieves this. This setting is used inside the function `proof-format-filename'." :type '(list (cons string string)) :group 'proof-shell) (defcustom proof-shell-process-connection-type (if (>= emacs-major-version 24) nil t) "The value of `process-connection-type' for the proof shell. Set non-nil for ptys, nil for pipes. NOTE: In Emacs >= 24 (checked for 24 and 25.0.50.1), t is not a good choice: input is cut after 4095 chars, which hangs pg." :type 'boolean :group 'proof-shell) (defcustom proof-shell-strip-crs-from-input t "If non-nil, replace carriage returns in every input with spaces. This is enabled by default: it is appropriate for many systems based on human input, because several CR's can result in several prompts, which may mess up the display (or even worse, the synchronization). If the prover can be set to output only one prompt for every chunk of input, then newlines can be retained in the input." :type 'boolean :group 'proof-shell) (defcustom proof-shell-strip-crs-from-output (eq system-type 'cygwin32) ;; Cygwin32 probs with Isabelle noted by Norbert Voelker "If non-nil, remove carriage returns (^M) at the end of lines from output. This is enabled for cygwin32 systems by default. You should turn it off if you don't need it (slight speed penalty)." :type 'boolean :group 'proof-shell) (defcustom proof-shell-extend-queue-hook nil "Hooks run by ‘proof-extend-queue’ before extending `proof-action-list'. Can be used to run additional actions before items are added to the queue \(such as compiling required modules for Coq) or to modify the items that are going to be added to `proof-action-list'. The items that are about to be added are bound to `queueitems'." :type '(repeat function) :group 'proof-shell) (defcustom proof-shell-insert-hook nil "Hook run by `proof-shell-insert' before inserting a command. Can be used to configure the proof assistant to the interface in various ways -- for example, to observe or alter the commands sent to the prover, or to sneak in extra commands to configure the prover. This hook is called inside a `save-excursion' with the `proof-shell-buffer' current, just before inserting and sending the text in the variable `string'. The hook can massage `string' or insert additional text directly into the `proof-shell-buffer'. Before sending `string', it will be stripped of carriage returns. Additionally, the hook can examine the variable `action'. It will be a symbol, set to the callback command which is executed in the proof shell filter once `string' has been processed. The `action' variable suggests what class of command is about to be inserted, the first two are normally the ones of interest: 'proof-done-advancing A \"forward\" scripting command 'proof-done-retracting A \"backward\" scripting command 'proof-done-invisible A non-scripting command 'proof-shell-set-silent Indicates prover output has been surpressed 'proof-shell-clear-silent Indicates prover output has been restored 'init-cmd Early initialization command sent to prover Caveats: You should be very careful about setting this hook. Proof General relies on a careful synchronization with the process between inputs and outputs. It expects to see a prompt for each input it sends from the queue. If you add extra input here and it causes more prompts than expected, things will break! Extending the variable `string' may be safer than inserting text directly, since it is stripped of carriage returns before being sent. Example uses: Lego used this hook for setting the pretty printer width if the window width has changed; Plastic used it to remove literate-style markup from `string'. See also `proof-script-preprocess' which can munge text when it is added to the queue of commands." ;; FIXME: The docstring suggests this is used by the backend code (e.g. LEGO ;; support) rather than by the end user, so maybe it shouldn't be ;; a `defcustom'? :type '(repeat function) :group 'proof-shell) (defcustom proof-assert-command-hook nil "Hooks run before asserting a command (or a set of commands). Can be used to insert commands before any (set of) input sent by the user. It is run by `proof-assert-until-point'. WARNING: don't call `proof-assert-until-point' in this hook, you would loop forever. Example of use: Insert a command to adapt printing width. Note that `proof-shell-insert-hook' (which see) may be use instead if no more prompt will be displayed." :type '(repeat function) :group 'proof-shell) (defcustom proof-retract-command-hook nil "Hooks run before retracting a command (or a set of commands). Can be used to insert commands. It is run by `proof-retract-until-point'. WARNING: don't call `proof-retract-until-point' in this hook, you would loop forever. Example of use: Insert a command to adapt printing width. Note that `proof-shell-insert-hook' (which see) may be use instead if no more prompt will be displayed." :type '(repeat function) :group 'proof-shell) (defcustom proof-script-preprocess nil "Function to pre-process (SPAN STRING) taken from proof script." :type 'function :group 'proof-shell) (defcustom proof-shell-handle-delayed-output-hook '(proof-pbp-focus-on-first-goal) "Hooks run after new output has been displayed in goals or response buffer." :type '(repeat function) :group 'proof-shell) (defcustom proof-shell-handle-error-or-interrupt-hook '(proof-goto-end-of-locked-on-error-if-pos-not-visible-in-window) "Run after an error or interrupt has been reported in the response buffer. Hook functions may inspect `proof-shell-last-output-kind' to determine whether the cause was an error or interrupt. Possible values for this hook include: `proof-goto-end-of-locked-on-error-if-pos-not-visible-in-window' `proof-goto-end-of-locked-if-pos-not-visible-in-window' which move the cursor in the scripting buffer on an error or error/interrupt. Remark: This hook is called from shell buffer. If you want to do something in scripting buffer, `save-excursion' and/or `set-buffer'." :type '(repeat function) :group 'proof-shell) (defcustom proof-shell-signal-interrupt-hook nil "Run when the user tries to interrupt the prover. This hook is run inside `proof-interrupt-process' when the user tries to interrupt the proof process. It is therefore run earlier than `proof-shell-handle-error-or-interrupt-hook', which runs when the interrupt is acknowledged inside `proof-shell-exec-loop'. This hook also runs when the proof assistent is killed. Hook functions should set the dynamic variable `prover-was-busy' to t if there might have been a reason to interrupt. Otherwise the generic interrupt handler might issue a prover-not-busy error." :type '(repeat function) :group 'proof-shell) (defcustom proof-shell-pre-interrupt-hook nil "Run immediately after `comint-interrupt-subjob' is called. This hook is added to allow customization for systems that query the user before returning to the top level." :type '(repeat function) :group 'proof-shell) (defcustom proof-shell-handle-output-system-specific nil "Set this variable to handle system specific output. Errors and interrupts are recognised in the function `proof-shell-handle-immediate-output'. Later output is handled by `proof-shell-handle-delayed-output', which displays messages to the user in *goals* and *response* buffers. This hook can run between the two stages to take some effect. It should be a function which is passed (cmd string) as arguments, where `cmd' is a string containing the currently processed command and `string' is the response from the proof system. If action is taken and goals/response display should be prevented, the function should update the variable `proof-shell-last-output-kind' to some non-nil symbol. The symbol will be compared against standard ones, see documentation of `proof-shell-last-output-kind'. A suggested canonical non-standard symbol is 'systemspecific." :type '(repeat function) :group 'proof-shell) (defcustom proof-state-change-pre-hook nil "This hook is called when a scripting state change may have occurred. Specifically, this hook is called after a region has been asserted or retracted, or after a command has been sent to the prover with `proof-shell-invisible-command'. It is run *before* the generic processing of the command span is done (see function `prof-done-advancing'). See `proof-state-change-hook' to insert actions after it." :type '(repeat function) :group 'proof-shell) (defcustom proof-state-change-hook nil "This hook is called when a scripting state change may have occurred. Specifically, this hook is called after a region has been asserted or retracted, or after a command has been sent to the prover with `proof-shell-invisible-command'. It is run *after* the generic processing of the command span is done (see function `prof-done-advancing'). See `proof-state-change-pre-hook' to insert actions before it. This hook may be used to refresh the toolbar." :type '(repeat function) :group 'proof-shell) ;;;;;; (defcustom proof-dependencies-system-specific nil "Set this variable to handle system specific dependency output. This must be a function with 1 parameter: the goalsave span of the theorem being saved." :type '(repeat function) :group 'proof-shell) (defcustom proof-dependency-menu-system-specific nil "Hook for system specific menu items for dependency menu. This must be a function taking one argument: the span one which the secific menu must be added. It must return a lit with the same type as `proof-dependency-in-span-context-menu' returns." :type '(repeat function) :group 'proof-shell) ;;;;; (defcustom proof-shell-syntax-table-entries nil "List of syntax table entries for proof script mode. A flat list of the form (CHAR SYNCODE CHAR SYNCODE ...) See doc of `modify-syntax-entry' for details of characters and syntax codes. At present this is used only by the `proof-easy-config' macro." :type 'sexp :group 'proof-shell) ;; ;; 4. Goals buffer ;; (defgroup proof-goals nil "Settings for configuring the goals buffer." :group 'prover-config :prefix "pg-goals-") (defcustom pg-subterm-first-special-char nil "First special character. Codes above this character can have special meaning to Proof General, and are stripped from the prover's output strings. Leave unset if no special characters are being used." :type '(choice character (const nil)) :group 'proof-goals) (defcustom pg-subterm-anns-use-stack nil ;; FIXME: The docstring suggest we should use t!? "Choice of syntax tree encoding for terms. If nil, prover is expected to make no optimisations. If non-nil, the pretty printer of the prover only reports local changes. For Coq 6.2, use t." :type 'boolean :group 'proof-goals) (defcustom pg-goals-change-goal nil "Command to change to the goal `%s'." :type 'string :group 'proof-goals) (defcustom pbp-goal-command nil "Command sent when `pg-goals-button-action' is requested on a goal." :type '(choice (const nil) string) :group 'proof-goals) (defcustom pbp-hyp-command nil "Command sent when `pg-goals-button-action' is requested on an assumption." :type '(choice (const nil) string) :group 'proof-goals) (defcustom pg-subterm-help-cmd nil "Command to display mouse help about a subterm. This command is sent to the proof assistant, replacing %s by the subterm that the mouse is over." :type '(choice (const nil) string) :group 'proof-goals) (defcustom pg-goals-error-regexp nil "Regexp indicating that the proof process has identified an error." :type '(choice (const nil) regexp) :group 'proof-goals) (defcustom proof-shell-result-start nil "Regexp matching start of an output from the prover after pbp commands. In particular, after a `pbp-goal-command' or a `pbp-hyp-command'." :type '(choice (const nil) regexp) :group 'proof-goals) (defcustom proof-shell-result-end "" "Regexp matching end of output from the prover after pbp commands. In particular, after a `pbp-goal-command' or a `pbp-hyp-command'." :type 'regexp :group 'proof-goals) (defcustom pg-subterm-start-char nil "Opening special character for subterm markup. Subsequent special characters with values *below* `pg-subterm-first-special-char' are assumed to be subterm position indicators. Annotations should be finished with `pg-subterm-sep-char'; the end of the concrete syntax is indicated by `pg-subterm-end-char'. If `pg-subterm-start-char' is nil, subterm markup is disabled." :type '(choice character (const nil)) :group 'proof-goals) (defcustom pg-subterm-sep-char nil "Finishing special for a subterm markup. See doc of `pg-subterm-start-char'." :type '(choice character (const nil)) :group 'proof-goals) (defcustom pg-subterm-end-char nil "Closing special character for subterm markup. See `pg-subterm-start-char'." :type 'character :group 'proof-goals) (defcustom pg-topterm-regexp nil "Annotation regexp that indicates the beginning of a \"top\" element. A \"top\" element may be a sub-goal to be proved or a named hypothesis, for example. It could also be a literal command to insert and send back to the prover. The function `pg-topterm-goalhyplit-fn' examines text following this special character, to determine what kind of top element it is. This setting is also used to see if proof-by-pointing features are configured. If it is unset, some of the code for parsing the prover output is disabled." :type 'character :group 'proof-goals) (defcustom proof-goals-font-lock-keywords nil "Value of `font-lock-keywords' used to fontify the goals output. The goals shell mode should set this before calling `proof-goals-config-done'. Used also by `proof-easy-config' mechanism. See also `proof-script-font-lock-keywords' and `proof-response-font-lock-keywords'." :type 'sexp :group 'proof-goals) (defcustom proof-response-font-lock-keywords nil "Value of `font-lock-keywords' used to fontify the response output. The response mode should set this before calling `proof-response-config-done'. Used also by `proof-easy-config' mechanism. See also `proof-script-font-lock-keywords' and `proof-goals-font-lock-keywords'." :type 'sexp :group 'proof-goals) (defcustom proof-shell-font-lock-keywords nil "Value of `font-lock-keywords' used to fontify the shell buiffer. The shell mode should may this before calling `proof-response-config-done'. Note that by default, font lock is turned *off* in shell buffers to improve performance. If you need to understand some output it may help to turn it on temporarily. See also `proof-script-font-lock-keywords', `proof-goals-font-lock-keywords' and `proof-response-font-lock-keywords'." :type 'sexp :group 'proof-goals) (defcustom pg-before-fontify-output-hook nil "This hook is called before fontifying a region in an output buffer. A function on this hook can alter the region of the buffer within the current restriction, and must return the final value of (point-max). \[This hook is presently only used by phox-sym-lock]." :type '(repeat function) :group 'proof-goals) (defcustom pg-after-fontify-output-hook nil "This hook is called before fonfitying a region in an output buffer. \[This hook is presently only used by Isabelle]." :type '(repeat function) :group 'proof-goals) (provide 'proof-config) ;;; proof-config.el ends here PG-4.5/generic/proof-depends.el000066400000000000000000000247421426357011200164050ustar00rootroot00000000000000;;; proof-depends.el --- Theorem-theorem and theorem-definition dependencies -*- lexical-binding:t -*- ;; This file is part of Proof General. ;; Portions © Copyright 1994-2012 David Aspinall and University of Edinburgh ;; Portions © Copyright 2003-2021 Free Software Foundation, Inc. ;; Portions © Copyright 2001-2017 Pierre Courtieu ;; Portions © Copyright 2010, 2016 Erik Martin-Dorel ;; Portions © Copyright 2011-2013, 2016-2017 Hendrik Tews ;; Portions © Copyright 2015-2017 Clément Pit-Claudel ;; Authors: David Aspinall ;; Earlier version by Fiona McNeil. ;; SPDX-License-Identifier: GPL-3.0-or-later ;;; Commentary: ;; ;; Status: Experimental code ;; ;; Based on Fiona McNeill's MSc project on analysing dependencies ;; within proofs. Code rewritten by David Aspinall. ;; ;;; Code: (require 'cl-lib) (require 'span) (require 'pg-vars) (require 'proof-script) ;For pg-set-span-helphighlights (require 'proof-config) (require 'proof-autoloads) (defvar proof-thm-names-of-files nil "A list of file and theorems contained within. A list of lists; the first element of each list is a file-name, the second element a list of all the thm names in that file. i.e.: ((file-name-1 (thm1 thm2 thm3)) (file-name-2 (thm1 thm2 thm3)))") (defvar proof-def-names-of-files nil "A list of files and defs contained within. A list of lists; the first element of each list is a file-name, the second element a list of all the def names in that file. i.e.: ((file-name-1 (def1 def2 def3)) (file-name-2 (def1 def2 def3)))") ;; Utility functions (defun proof-depends-module-name-for-buffer () "Return a module name for the current buffer. This is a name that the prover prefixes all item names with. For example, in isabelle, a file Stuff.ML contains theorems with fully qualified names of the form Stuff.theorem1, etc. For other provers, this function may need modifying." (if buffer-file-name (file-name-nondirectory (file-name-sans-extension buffer-file-name)) "")) (defun proof-depends-module-of (name) "Return a pair of a module name and base name for given item NAME. Assumes module name is given by dotted prefix." (let ((dot (string-match "\\." name))) (if dot (cons (substring name 0 dot) (substring name (+ dot 1))) (cons "" name)))) (defun proof-depends-names-in-same-file (names) "Return subset of list NAMES which are guessed to occur in same file. This is done using `proof-depends-module-name-for-buffer' and `proof-depends-module-of'." (let ((filemod (proof-depends-module-name-for-buffer)) samefile) (while names (let ((splitname (proof-depends-module-of (car names)))) (if (equal filemod (car splitname)) (setq samefile (cons (cdr splitname) samefile)))) (setq names (cdr names))) ;; NB: reversed order samefile)) ;; ;; proof-depends-process-dependencies: the main entry point. ;; ;;;###autoload (defun proof-depends-process-dependencies (name gspan) "Process dependencies reported by prover, for NAME in span GSPAN. Called from `proof-done-advancing' when a save is processed and `proof-last-theorem-dependencies' is set." (span-set-property gspan 'dependencies ;; Ancestors of NAME are in the second component. ;; FIXME: for now we ignore the first component: ;; NAME may not be enough [e.g. Isar allowed proof regions ;; with multiple names, which are reported in dep'c'y ;; output]. (cdr proof-last-theorem-dependencies)) (let* ((samefilenames (proof-depends-names-in-same-file (cdr proof-last-theorem-dependencies))) ;; Find goalsave spans earlier in this file which this ;; one depends on; update their list of dependents, ;; and return resulting list paired up with names. (depspans (apply #'append (span-mapcar-spans (lambda (depspan) (let ((dname (span-property depspan 'name))) (if (and (eq (span-property depspan 'type) 'goalsave) (member dname samefilenames)) (let ((forwarddeps (span-property depspan 'dependents))) (span-set-property depspan 'dependents (cons (list name gspan) forwarddeps)) ;; return list of args for menu fun: name and span (list (list dname depspan)))))) (point-min) (span-start gspan) 'type)))) (span-set-property gspan 'dependencies-within-file depspans) (setq proof-last-theorem-dependencies nil) (funcall proof-dependencies-system-specific gspan))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Menu Functions ;; ;; The following functions set up the menus which are the key way in ;; which the dependency information is used. ;;;###autoload (defun proof-dependency-in-span-context-menu (span) "Make some menu entries showing proof dependencies of SPAN. Use `proof-dependency-menu-system-specific' to build system specific entries." ;; FIXME: might only activate this for dependency-relevant spans. (let ((defmenu (list "-------------" (proof-dep-make-submenu "Local Dependency..." #'car #'proof-goto-dependency (span-property span 'dependencies-within-file)) (proof-make-highlight-depts-menu "Highlight Dependencies" 'proof-highlight-depcs span 'dependencies-within-file) (proof-dep-make-submenu "Local Dependents..." #'car #'proof-goto-dependency (span-property span 'dependents)) (proof-make-highlight-depts-menu "Highlight Dependents" 'proof-highlight-depts span 'dependents) ["Unhighlight all" proof-dep-unhighlight t] "-------------" (proof-dep-alldeps-menu span)))) (if (not proof-dependency-menu-system-specific) defmenu (append (funcall proof-dependency-menu-system-specific span) defmenu)))) (defun proof-dep-alldeps-menu (span) (or (span-property span 'dependencies-menu) ;; cached value (span-set-property span 'dependencies-menu (proof-dep-make-alldeps-menu (span-property span 'dependencies))))) (defun proof-dep-make-alldeps-menu (deps) (let ((menuname "All Dependencies...") (showdep 'proof-show-dependency)) (if deps (let ((nestedtop (proof-dep-split-deps deps))) (cons menuname (append (mapcar (lambda (l) (vector l (list showdep l) t)) (cdr nestedtop)) (mapcar (lambda (sm) (proof-dep-make-submenu (car sm) #'car #'proof-show-dependency (mapcar #'list (cdr sm)))) (car nestedtop))))) (vector menuname nil nil)))) (defun proof-dep-split-deps (deps) "Split dependencies DEPS into named nested lists according to dotted prefixes." ;; NB: could handle deeper nesting here, but just do one level for now. (let (nested toplevel) ;; Add each name into a nested list or toplevel list (dolist (name deps) (let* ((period (string-match "\\." name)) (ns (and period (substring name 0 period))) (subitems (and ns (assoc ns nested)))) (cond ((and ns subitems) (setcdr subitems (cl-adjoin name (cdr subitems)))) (ns (push (cons ns (list name)) nested)) (t (setq toplevel (cl-adjoin name toplevel)))))) (cons nested toplevel))) (defun proof-dep-make-submenu (name namefn appfn list) "Make menu items for a submenu NAME, using APPFN applied to each elt in LIST. If LIST is empty, return a disabled menu item with NAME. NAMEFN is applied to each element of LIST to make the names." (if list (cons name (mapcar (lambda (l) (vector (funcall namefn l) (cons appfn l) t)) list)) (vector name nil nil))) (defun proof-make-highlight-depts-menu (name fn span prop) "Return a menu item that for highlighting dependents/depencies of SPAN." (let ((deps (span-property span prop))) (vector name `(,fn ,(span-property span 'name) (quote ,deps)) (not (not deps))))) ;; ;; Functions triggered by menus ;; (defun proof-goto-dependency (_name span) "Go to the start of SPAN." ;; FIXME(EMD): seems buggy as NAME is not used ;; FIXME: check buffer is right one. Later we'll allow switching buffer ;; here and jumping to different files. (goto-char (span-start span)) (skip-chars-forward " \t\n")) (defun proof-show-dependency (thm) "Show dependency THM using `proof-show-dependency-cmd'. This is simply to display the dependency somehow." (if proof-shell-show-dependency-cmd ;; robustness (proof-shell-invisible-command (format proof-shell-show-dependency-cmd thm)))) (defconst pg-dep-span-priority 500) (defconst pg-ordinary-span-priority 100) (defun proof-highlight-depcs (name nmspans) (let ((helpmsg (concat "This item is a dependency (ancestor) of " name))) (while nmspans (let ((span (cl-cadar nmspans))) (proof-depends-save-old-face span) (span-set-property span 'face 'proof-highlight-dependency-face) ;; (span-set-property span 'priority pg-dep-span-priority) (span-set-property span 'mouse-highlight nil) (span-set-property span 'help-echo helpmsg)) (setq nmspans (cdr nmspans))))) (defun proof-highlight-depts (name nmspans) (let ((helpmsg (concat "This item depends on (is a child of) " name))) (while nmspans (let ((span (cl-cadar nmspans))) (proof-depends-save-old-face span) (span-set-property span 'face 'proof-highlight-dependent-face) ;; (span-set-property span 'priority pg-dep-span-priority) (span-set-property span 'mouse-highlight nil) (span-set-property span 'help-echo helpmsg) (span-set-property span 'balloon-help helpmsg)) (setq nmspans (cdr nmspans))))) (defun proof-depends-save-old-face (span) (unless (span-property span 'depends-old-face) (span-set-property span 'depends-old-face (span-property span 'face)))) (defun proof-depends-restore-old-face (span) (when (span-property span 'depends-old-face) (span-set-property span 'face (span-property span 'depends-old-face)) (span-set-property span 'depends-old-face nil))) (defun proof-dep-unhighlight () "Remove additional highlighting on all spans in file to their default." (interactive) (save-excursion (let ((span (span-at (point-min) 'type))) ;; FIXME: covers too many spans! (while span (pg-set-span-helphighlights span 'nohighlight) (proof-depends-restore-old-face span) ;; (span-set-property span 'priority pg-ordinary-span-priority) (setq span (next-span span 'type)))))) (provide 'proof-depends) ;; proof-depends.el ends here (provide 'proof-depends) ;;; proof-depends.el ends here PG-4.5/generic/proof-easy-config.el000066400000000000000000000105151426357011200171600ustar00rootroot00000000000000;;; proof-easy-config.el --- Easy configuration for Proof General ;; This file is part of Proof General. ;; Portions © Copyright 1994-2012 David Aspinall and University of Edinburgh ;; Portions © Copyright 2003, 2012, 2014 Free Software Foundation, Inc. ;; Portions © Copyright 2001-2017 Pierre Courtieu ;; Portions © Copyright 2010, 2016 Erik Martin-Dorel ;; Portions © Copyright 2011-2013, 2016-2017 Hendrik Tews ;; Portions © Copyright 2015-2017 Clément Pit-Claudel ;; Author: David Aspinall ;; SPDX-License-Identifier: GPL-3.0-or-later ;;; Commentary: ;; ;; Future versions might copy settings instead; consider how best to ;; interface with customization mechanism so a new prover can be ;; configured by editing inside custom buffers. ;; ;;; Code: (require 'proof-site) ; proof-assistant, proof-assistant-symbol (require 'proof-auxmodes) ; make sure extra modes available (defconst proof-easy-config-derived-modes-table '(("" "script" proof-mode (proof-config-done)) ("shell" "shell" proof-shell-mode (proof-shell-config-done)) ("response" "response" proof-response-mode (proof-response-config-done)) ("goals" "goals" proof-goals-mode (proof-goals-config-done))) "A list of (PREFIXSYM SUFFIXNAME PARENT MODEBODY) for derived modes.") (defun proof-easy-config-define-derived-modes () (dolist (modedef proof-easy-config-derived-modes-table) (let* ((prefixsym (nth 0 modedef)) (suffixnm (nth 1 modedef)) (parent (nth 2 modedef)) (body (nthcdr 3 modedef)) (modert (concat (symbol-name proof-assistant-symbol) "-" prefixsym)) (hyphen (if (string-equal prefixsym "") "" "-")) (mode (intern (concat modert hyphen "mode"))) (modename (concat proof-assistant " " suffixnm)) ;; FIXME: declare these variables in proof-config: ;; proof-{goals,response,trace}-syntax-table-entries ;; FIXME: in future versions, use these settings in *-config-done ;; to simplify elisp code elsewhere. ;; FIXME: add imenu-generic-expression too ;; (modsyn (intern (concat "proof-" suffixnm "-syntax-table-entries"))) (fullbody (append (if (and (boundp modsyn) (eval modsyn)) (list `(let ((syn ,modsyn)) (while syn (modify-syntax-entry (car syn) (cadr syn)) (setq syn (cddr syn)))))) body))) (eval `(define-derived-mode ,mode ,parent ,modename nil ,@fullbody))))) (defun proof-easy-config-check-setup (sym name) "Perform a number of simple checks. The proof assistant is denoted by symbol SYM and string NAME." (let ((msg "")) ;; At the moment we just check that the symbol/name used ;; in the macro matches that in `proof-assistant-table' ;; and have the right type. (unless (symbolp sym) (error "Macro proof-easy-config: first argument (%s) should be a symbol" sym)) (unless (stringp name) (error "Macro proof-easy-config: second argument (%s) should be a string" name)) (cond ((or (and (boundp 'proof-assistant) proof-assistant (not (equal proof-assistant "")) (not (equal proof-assistant name)) (setq msg (format "\nproof-assistant name: \"%s\" doesn't match expected \"%s\"" proof-assistant name))) (and (boundp 'proof-assistant-symbol) proof-assistant-symbol (not (eq proof-assistant-symbol sym)) (setq msg (format "\nproof-assistant symbol: '%s doesn't match expected '%s" proof-assistant-symbol sym)))) (error "Macro proof-easy-config: PG already in use or name/symbol mismatch %s" msg)) (t ;; Setting these here is nice for testing: no need to get ;; proof-assistant-table right first. (customize-set-variable 'proof-assistant name) (customize-set-variable 'proof-assistant-symbol sym))))) ;;;###autoload (defmacro proof-easy-config (sym name &rest body) "Configure Proof General for a given proof assistant. The symbol SYM and string name NAME must match those given in the `proof-assistant-table', which see. Additional arguments are taken into account as a setq BODY." `(progn (proof-easy-config-check-setup ,sym ,name) (setq ,@body) (proof-easy-config-define-derived-modes))) ;; (provide 'proof-easy-config) (provide 'proof-easy-config) ;;; proof-easy-config.el ends here PG-4.5/generic/proof-faces.el000066400000000000000000000212471426357011200160410ustar00rootroot00000000000000;;; proof-faces.el --- Faces for Proof General ;; This file is part of Proof General. ;; Portions © Copyright 1994-2012 David Aspinall and University of Edinburgh ;; Portions © Copyright 2003, 2012, 2014 Free Software Foundation, Inc. ;; Portions © Copyright 2001-2017 Pierre Courtieu ;; Portions © Copyright 2010, 2016 Erik Martin-Dorel ;; Portions © Copyright 2011-2013, 2016-2017 Hendrik Tews ;; Portions © Copyright 2015-2017 Clément Pit-Claudel ;; Author: David Aspinall and others ;; SPDX-License-Identifier: GPL-3.0-or-later ;;; Commentary: ;; ;; In an ideal world, faces should work sensibly: ;; ;; a) with default colours ;; b) with -rv ;; c) on console ;; d) on different Emacsen/architectures (win32, mac, etc) ;; ;; But it's difficult to keep track of all that! ;; Please report any bad/failing colour ;; combinations (with suggested improvements) at ;; https://github.com/ProofGeneral/PG/issues ;; ;; Some of these faces aren't used by default in Proof General, ;; but you can use them in font lock patterns for specific ;; script languages. ;;; Code: (defgroup proof-faces nil "Faces used by Proof General." :group 'proof-general :prefix "proof-") ;; TODO: get rid of this list. Does 'default work widely enough ;; by now? (defconst pg-defface-window-systems '(x ;; bog standard mswindows ;; Windows w32 ;; Windows gtk ;; gtk emacs (obsolete?) mac ;; used by Aquamacs carbon ;; used by Carbon XEmacs ns ;; NeXTstep Emacs (Emacs.app) x-toolkit) ;; possible catch all (but probably not) "A list of possible values for variable `window-system'. If you are on a window system and your value of variable `window-system' is not listed here, you may not get the correct syntax colouring behaviour.") (defmacro proof-face-specs (bl bd ow) "Return a spec for `defface' with BL for light bg, BD for dark, OW o/w." `(append (apply 'append (mapcar (lambda (ty) (list (list (list (list 'type ty) '(class color) (list 'background 'light)) (quote ,bl)) (list (list (list 'type ty) '(class color) (list 'background 'dark)) (quote ,bd)))) pg-defface-window-systems)) (list (list t (quote ,ow))))) (defface proof-queue-face (proof-face-specs (:background "mistyrose" :extend t) ;; was "darksalmon" in PG 3.4,3.5 (:background "mediumorchid" :extend t) (:foreground "white" :background "black" :extend t)) "*Face for commands in proof script waiting to be processed." :group 'proof-faces) (defface proof-locked-face (proof-face-specs ;; This colour is quite subjective and may be best chosen according ;; to the type of display you have. (:background "#eaf8ff" :extend t) (:background "darkslateblue" :extend t) (:underline t :extend t)) "*Face for locked region of proof script (processed commands)." :group 'proof-faces) (defface proof-declaration-name-face (proof-face-specs (:foreground "chocolate" :bold t) (:foreground "orange" :bold t) (:italic t :bold t)) "*Face for declaration names in proof scripts. Exactly what uses this face depends on the proof assistant." :group 'proof-faces) (defface proof-tacticals-name-face (proof-face-specs (:foreground "MediumOrchid3") (:foreground "orchid") (bold t)) "*Face for names of tacticals in proof scripts. Exactly what uses this face depends on the proof assistant." :group 'proof-faces) (defface proof-tactics-name-face (proof-face-specs (:foreground "darkblue") (:foreground "mediumpurple") (:underline t)) "*Face for names of tactics in proof scripts. Exactly what uses this face depends on the proof assistant." :group 'proof-faces) (defface proof-error-face (proof-face-specs (:background "rosybrown1") ; a drab version of misty rose (:background "brown") (:bold t)) "*Face for error messages from proof assistant." :group 'proof-faces) (defface proof-warning-face (proof-face-specs (:background "lemon chiffon") (:background "orange2") (:italic t)) "*Face for warning messages. Warning messages can come from proof assistant or from Proof General itself." :group 'proof-faces) (defface proof-eager-annotation-face (proof-face-specs (:background "palegoldenrod") (:background "darkgoldenrod") (:italic t)) "*Face for important messages from proof assistant." :group 'proof-faces) (defface proof-debug-message-face (proof-face-specs (:foreground "Gray65") (:background "Gray30") (:italic t)) "*Face for debugging messages from Proof General." :group 'proof-faces) (defface proof-boring-face (proof-face-specs (:foreground "Gray75") (:background "Gray30") (:italic t)) "*Face for boring text in proof assistant output." :group 'proof-faces) (defface proof-mouse-highlight-face (proof-face-specs (:background "lightblue") (:background "darkslateblue") (:italic t)) "*General mouse highlighting face used in script buffer." :group 'proof-faces) (defface proof-command-mouse-highlight-face (proof-face-specs (:background "gold1") (:background "gold4") (:italic t)) "*Mouse highlighting face for atomic regions (usually commands) in script buffer." :group 'proof-faces) (defface proof-region-mouse-highlight-face (proof-face-specs (:background "yellow2") (:background "yellow3") (:italic t)) "*Mouse highlighting face for compound regions (usually proofs) in script buffer." :group 'proof-faces) (defface proof-highlight-dependent-face (proof-face-specs (:background "orange") (:background "darkorange") (:italic t)) "*Face for showing (backwards) dependent parts." :group 'proof-faces) (defface proof-highlight-dependency-face (proof-face-specs (:background "khaki") (:background "peru") (:italic t)) "*Face for showing (forwards) dependencies." :group 'proof-faces) (defface proof-active-area-face (proof-face-specs (:background "lightyellow" :box (:line-width 2 :color "grey75" :style released-button)) (:background "darkyellow" :underline t) (:underline t)) "*Face for showing active areas (clickable regions), outside of subterm markup." :group 'proof-faces) (defface proof-script-sticky-error-face (proof-face-specs (:background "indianred1") (:background "indianred3") (:underline t)) "Proof General face for marking an error in the proof script. " :group 'proof-faces) (defface proof-script-highlight-error-face (proof-face-specs (:background "indianred1" :bold t) (:background "indianred3" :bold t) (:underline t :bold t)) "Proof General face for highlighting an error in the proof script. " :group 'proof-faces) (defface proof-omitted-proof-face (proof-face-specs (:background "#EAEFFF" :extend t) (:background "#9C4A90" :extend t) (:foreground "white" :background "black" :extend t)) "*Face for background of omitted proofs" :group 'proof-faces) ;;; Compatibility: these are required for use in GNU Emacs/font-lock-keywords (defconst proof-face-compat-doc "Evaluates to a face name, for compatibility.") (defconst proof-queue-face 'proof-queue-face proof-face-compat-doc) (defconst proof-locked-face 'proof-locked-face proof-face-compat-doc) (defconst proof-declaration-name-face 'proof-declaration-name-face proof-face-compat-doc) (defconst proof-tacticals-name-face 'proof-tacticals-name-face proof-face-compat-doc) (defconst proof-tactics-name-face 'proof-tactics-name-face proof-face-compat-doc) (defconst proof-error-face 'proof-error-face proof-face-compat-doc) (defconst proof-script-sticky-error-face 'proof-script-sticky-error-face proof-face-compat-doc) (defconst proof-script-highlight-error-face 'proof-script-highlight-error-face proof-face-compat-doc) (defconst proof-warning-face 'proof-warning-face proof-face-compat-doc) (defconst proof-eager-annotation-face 'proof-eager-annotation-face proof-face-compat-doc) (defconst proof-debug-message-face 'proof-debug-message-face proof-face-compat-doc) (defconst proof-boring-face 'proof-boring-face proof-face-compat-doc) (defconst proof-mouse-highlight-face 'proof-mouse-highlight-face proof-face-compat-doc) (defconst proof-command-mouse-highlight-face 'proof-command-mouse-highlight-face proof-face-compat-doc) (defconst proof-region-mouse-highlight-face 'proof-region-mouse-highlight-face proof-face-compat-doc) (defconst proof-highlight-dependent-face 'proof-highlight-dependent-face proof-face-compat-doc) (defconst proof-highlight-dependency-face 'proof-highlight-dependency-face proof-face-compat-doc) (defconst proof-active-area-face 'proof-active-area-face proof-face-compat-doc) (defconst proof-script-error-face 'proof-script-errror-face-compat-doc) (provide 'proof-faces) ;;; proof-faces.el ends here PG-4.5/generic/proof-indent.el000066400000000000000000000071031426357011200162340ustar00rootroot00000000000000;;; proof-indent.el --- Generic indentation for proof assistants ;; This file is part of Proof General. ;; Portions © Copyright 1994-2012 David Aspinall and University of Edinburgh ;; Portions © Copyright 2003, 2012, 2014 Free Software Foundation, Inc. ;; Portions © Copyright 2001-2017 Pierre Courtieu ;; Portions © Copyright 2010, 2016 Erik Martin-Dorel ;; Portions © Copyright 2011-2013, 2016-2017 Hendrik Tews ;; Portions © Copyright 2015-2017 Clément Pit-Claudel ;; Authors: Markus Wenzel, David Aspinall ;; SPDX-License-Identifier: GPL-3.0-or-later ;;; Commentary: ;; ;;; Code: (require 'proof-config) ; config variables (require 'proof-utils) ; proof-ass (require 'proof-syntax) ; p-looking-at-safe, p-re-search (require 'proof-autoloads) ; p-locked-end (defun proof-indent-indent () "Determine indentation caused by syntax element at current point." (cond ((proof-looking-at-safe proof-indent-open-regexp) proof-indent) ((proof-looking-at-safe proof-indent-close-regexp) (- proof-indent)) (t 0))) (defun proof-indent-offset () "Determine offset of syntax element at current point." (cond ((proof-looking-at-syntactic-context) proof-indent) ((proof-looking-at-safe proof-indent-inner-regexp) proof-indent) ((proof-looking-at-safe proof-indent-enclose-regexp) proof-indent-enclose-offset) ((proof-looking-at-safe proof-indent-open-regexp) proof-indent-open-offset) ((proof-looking-at-safe proof-indent-close-regexp) proof-indent-close-offset) ((proof-looking-at-safe proof-indent-any-regexp) 0) ((proof-looking-at-safe "\\s-*$") 0) (t proof-indent))) (defun proof-indent-inner-p () "Check if current point is between actual indentation elements." (or (proof-looking-at-syntactic-context) (proof-looking-at-safe proof-indent-inner-regexp) (not (or (proof-looking-at-safe proof-indent-any-regexp) (proof-looking-at-safe "\\s-*$"))))) (defun proof-indent-goto-prev () ; Note: may change point, even in case of failure! "Goto to previous syntax element for script indentation, ignoring string/comment contexts." (and (proof-re-search-backward proof-indent-any-regexp nil t) (or (not (proof-looking-at-syntactic-context)) (proof-indent-goto-prev)))) (defun proof-indent-calculate (indent inner) ; Note: may change point! "Calculate indentation level at point. INDENT is current indentation level, INNER a flag for inner indentation." (let* ((current (point)) (found-prev (proof-indent-goto-prev))) (if (not found-prev) (goto-char current)) ; recover position (cond ((and found-prev (or proof-indent-hang (= (current-indentation) (current-column)))) (+ indent (current-column) (if (and inner (not (proof-indent-inner-p))) 0 (proof-indent-indent)) (- (proof-indent-offset)))) ((not found-prev) 0) ;FIXME mmw: improve this case!? (t (proof-indent-calculate (+ indent (if inner 0 (proof-indent-indent))) inner))))) ;;;###autoload (defun proof-indent-line () "Indent current line of proof script, if indentation enabled." (interactive) (unless (not (proof-ass script-indent)) (if (< (point) (proof-unprocessed-begin)) (if (< (current-column) (current-indentation)) (skip-chars-forward "\t ")) (save-excursion (indent-line-to (max 0 (save-excursion (back-to-indentation) (proof-indent-calculate (proof-indent-offset) (proof-indent-inner-p)))))) (if (< (current-column) (current-indentation)) (back-to-indentation))))) (provide 'proof-indent) ;;; proof-indent.el ends here PG-4.5/generic/proof-maths-menu.el000066400000000000000000000041511426357011200170310ustar00rootroot00000000000000;;; proof-maths-menu.el --- Support for maths menu mode package ;; This file is part of Proof General. ;; Portions © Copyright 1994-2012 David Aspinall and University of Edinburgh ;; Portions © Copyright 2003-2018 Free Software Foundation, Inc. ;; Portions © Copyright 2001-2017 Pierre Courtieu ;; Portions © Copyright 2010, 2016 Erik Martin-Dorel ;; Portions © Copyright 2011-2013, 2016-2017 Hendrik Tews ;; Portions © Copyright 2015-2017 Clément Pit-Claudel ;; Author: David Aspinall ;; SPDX-License-Identifier: GPL-3.0-or-later ;;; Commentary: ;; ;; With thanks to Dave Love for the original maths menu code, ;; provided at http://www.loveshack.ukfsn.org/emacs/ ;; ;; Note: maths menu is bundled with Proof General in lib/, and PG will select ;; it's own version before any other version on the Emacs load path. ;; If you want to override this, simply load your version before ;; starting Emacs, with (require 'maths-menu). ;; ;;; Code: (eval-when-compile (require 'proof-auxmodes) ; loaded by proof.el (require 'maths-menu)) ; loaded dynamically in proof-auxmodes ;;;###autoload (defun proof-maths-menu-set-global (flag) "Set global status of maths-menu mode for PG buffers to be FLAG. Turn on/off menu in all script buffers and ensure new buffers follow suit." (let ((hook (proof-ass-sym mode-hook))) (if flag (add-hook hook 'maths-menu-mode) (remove-hook hook 'maths-menu-mode)) (proof-map-buffers (proof-buffers-in-mode proof-mode-for-script) (maths-menu-mode (if flag 1 0))))) ;;;###autoload (defun proof-maths-menu-enable () "Turn on or off maths-menu mode in Proof General script buffer. This invokes `maths-menu-mode' to toggle the setting for the current buffer, and then sets PG's option for default to match. Also we arrange to have maths menu mode turn itself on automatically in future if we have just activated it for this buffer." (interactive) (require 'maths-menu) (if (proof-maths-menu-support-available) (proof-maths-menu-set-global (not maths-menu-mode)))) (provide 'proof-maths-menu) ;;; proof-maths-menu.el ends here PG-4.5/generic/proof-menu.el000066400000000000000000001134741426357011200157300ustar00rootroot00000000000000;;; proof-menu.el --- Menus, keymaps, misc commands for Proof General ;; This file is part of Proof General. ;; Portions © Copyright 1994-2012 David Aspinall and University of Edinburgh ;; Portions © Copyright 2003-2018 Free Software Foundation, Inc. ;; Portions © Copyright 2001-2017 Pierre Courtieu ;; Portions © Copyright 2010, 2016, 2021 Erik Martin-Dorel ;; Portions © Copyright 2011-2013, 2016-2017 Hendrik Tews ;; Portions © Copyright 2015-2017 Clément Pit-Claudel ;; Authors: David Aspinall ;; SPDX-License-Identifier: GPL-3.0-or-later ;;; Commentary: ;; ;;; Code: (require 'cl-lib) ; cl-mapcan, ... (defvar proof-assistant-menu) ; defined by macro in proof-menu-define-specific (defvar proof-mode-map) (require 'proof-utils) ; proof-deftoggle, proof-eval-when-ready-for-assistant (require 'proof-useropts) (require 'proof-config) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; ;;; Miscellaneous commands ;;; (defvar proof-display-some-buffers-count 0) (defun proof-display-some-buffers () "Display the response, trace, goals, or shell buffer, rotating. A fixed number of repetitions of this command switches back to the same buffer. Also move point to the end of the response buffer if it's selected. If in three window or multiple frame mode, display two buffers. The idea of this function is to change the window->buffer mapping without adjusting window layout." (interactive) ;; Idea: a humane toggle, which allows habituation. ;; E.g. two taps of C-c C-l always shows the goals buffer, three the ;; trace buffer, etc. (Makes less sense from the menu, though, ;; where it seems more natural just to rotate from last position) (cond ((and (called-interactively-p 'any) (eq last-command 'proof-display-some-buffers)) (cl-incf proof-display-some-buffers-count)) (t (setq proof-display-some-buffers-count 0))) (let* ((assocbufs (cl-remove-if-not #'buffer-live-p (list proof-response-buffer proof-thms-buffer proof-trace-buffer proof-goals-buffer ))) ;proof-shell-buffer (numassoc (length assocbufs))) ;; If there's no live other buffers, we don't do anything. (unless (zerop numassoc) (let ((selectedbuf (nth (mod proof-display-some-buffers-count numassoc) assocbufs)) (nextbuf (nth (mod (1+ proof-display-some-buffers-count) numassoc) assocbufs))) (cond ((or proof-three-window-enable proof-multiple-frames-enable) ;; Display two buffers: next in rotation and goals/response ;; FIXME: this doesn't work as well as it might. (proof-switch-to-buffer selectedbuf 'noselect) (proof-switch-to-buffer (if (eq selectedbuf proof-goals-buffer) proof-response-buffer proof-goals-buffer) 'noselect)) (selectedbuf (proof-switch-to-buffer selectedbuf 'noselect))) (if (eq selectedbuf proof-response-buffer) (set-window-point (get-buffer-window proof-response-buffer t) (point-max))) (pg-response-buffers-hint (buffer-name nextbuf)))))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; ;;; Key bindings ;;; ;;;###autoload (defun proof-menu-define-keys (map) "Prover specific keymap under C-c C-a." ;; M-a and M-e are usually {forward,backward}-sentence. ;; Some modes also override these with similar commands (define-key map [(meta a)] 'proof-backward-command) (define-key map [(meta e)] 'proof-forward-command) (define-key map [(meta up)] 'proof-backward-command) (define-key map [(meta down)] 'proof-forward-command) (define-key map [(control meta a)] 'proof-goto-command-start) (define-key map [(control meta e)] 'proof-goto-command-end) (define-key map [(control c) (control b)] 'proof-process-buffer) ;; C-c C-c is proof-interrupt-process in universal-keys (define-key map [(control c) (control d)] 'proof-tree-external-display-toggle) ;; C-c C-f is proof-find-theorems in universal-keys (define-key map [(control c) (control H)] 'proof-help) ;; C-c C-l is proof-layout-windows in universal-keys ;; C-c C-n is proof-assert-next-command-interactive in universal-keys ;; C-c C-o is proof-display-some-buffers in universal-keys (define-key map [(control c) (control p)] 'proof-prf) (define-key map [(control c) (control r)] 'proof-retract-buffer) (define-key map [(control c) (control s)] 'proof-toggle-active-scripting) (define-key map [(control c) (control t)] 'proof-ctxt) (define-key map [(control c) (control i)] 'proof-query-identifier) ;; C-c C-u is proof-undo-last-successful-command in universal-keys ;; C-c C-w is pg-response-clear-displays in universal-keys (define-key map [(control c) (control z)] 'proof-frob-locked-end) (define-key map [(control c) (control backspace)] 'proof-undo-and-delete-last-successful-command) ;; C-c C-v is proof-minibuffer-cmd in universal-keys ;; C-c C-. is proof-goto-end-of-locked in universal-keys (define-key map [(control c) (control return)] 'proof-goto-point) (define-key map [(control c) (control m)] 'proof-goto-point) ; fallback for tty (define-key map [(control c) ?v] 'pg-toggle-visibility) (define-key map [(control meta mouse-3)] 'proof-mouse-goto-point) ;; NB: next binding overwrites comint-find-source-code. (define-key map [(meta p)] 'pg-previous-matching-input-from-input) (define-key map [(meta n)] 'pg-next-matching-input-from-input) ;; Standard binding for completion (define-key map [(control return)] 'proof-script-complete) (define-key map [(control c) (control ?\;)] 'pg-insert-last-output-as-comment) ;; (define-key map [(control meta up)] 'pg-move-region-up) (define-key map [(control meta down)] 'pg-move-region-down) ;; (define-key map [(control c) ?b] 'proof-toolbar-toggle) (define-key map [(control c) ?>] 'proof-autosend-toggle) ;; Add the universal keys bound in all PG buffers. ;; NB: C-c ` is next-error in universal-keys (proof-define-keys map proof-universal-keys)) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; ;;; Functions to define the menus ;;; ;; The main Proof-General generic menu ;;;###autoload (defun proof-menu-define-main () (easy-menu-define proof-mode-menu proof-mode-map "The main Proof General menu" (proof-main-menu))) ;; The proof assistant specific menu (defvar proof-menu-favourites nil "The Proof General favourites menu for the current proof assistant.") (defvar proof-menu-settings nil "Settings submenu for Proof General.") ;;;###autoload (defun proof-menu-define-specific () (easy-menu-do-define 'proof-assistant-menu proof-mode-map (concat "The menu for " proof-assistant) (cons proof-assistant (append (proof-ass menu-entries) '("----") (or proof-menu-favourites (proof-menu-define-favourites-menu)) (or proof-menu-settings (proof-menu-define-settings-menu)) '("----") (list (vector (concat "Start " proof-assistant) 'proof-shell-start ':active '(not (proof-shell-live-buffer))) (vector (concat "Exit " proof-assistant) 'proof-shell-exit ':active '(proof-shell-live-buffer)) ;; TODO: doc -set-command here (vector (concat "Set " proof-assistant " Command") (proof-ass-sym set-command) ':visible '(fboundp (proof-ass-sym set-command)))) '("----") (list (cons "Help" (append (list (vector (concat proof-assistant " Information") 'proof-help :visible proof-info-command) (vector (concat proof-assistant " Web Page") '(browse-url proof-assistant-home-page) :visible proof-assistant-home-page)) (proof-ass help-menu-entries)))))))) (defun proof-assistant-menu-update () "Update proof assistant menu in scripting buffers." (proof-map-buffers (proof-buffers-in-mode proof-mode-for-script) (easy-menu-remove proof-assistant-menu) (proof-menu-define-settings-menu) (proof-menu-define-specific) (easy-menu-add proof-assistant-menu (proof-ass mode-map)))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Contents of sub menus ;; (defvar proof-help-menu '("Help" ["About PG" proof-splash-display-screen t] ["Info" (info "ProofGeneral") t] ["Homepage" (browse-url proof-general-home-page) t] ["Send Bug Report" proof-submit-bug-report t]) "Proof General help menu.") (defvar proof-show-hide-menu '(("Show All" ["Proofs" (pg-show-all-portions 'proof) t] ["Commands" (pg-show-all-portions 'command) t] ["Comments" (pg-show-all-portions 'comment) t]) ("Hide All" ["Proofs" (pg-show-all-portions 'proof 'hide) t] ["Commands" (pg-show-all-portions 'command 'hide) t] ["Comments" (pg-show-all-portions 'comment 'hide) t])) "Show/hide submenu.") (defvar proof-3-window-mode-policy (cons "3 Windows mode layout" '(["smart" (progn (customize-set-variable 'proof-three-window-mode-policy 'smart) (proof-layout-windows)) :style radio :selected (eq proof-three-window-mode-policy 'smart) :help "Adapt to frame width (C-c C-l to refresh)"] ["hybrid" (progn (customize-set-variable 'proof-three-window-mode-policy 'hybrid) (proof-layout-windows)) :style radio :selected (eq proof-three-window-mode-policy 'hybrid) :help "two column mode"] ["horizontal" (progn (customize-set-variable 'proof-three-window-mode-policy 'horizontal) (proof-layout-windows)) :style radio :selected (eq proof-three-window-mode-policy 'horizontal) :help "Three column mode"] ["vertical" (progn (customize-set-variable 'proof-three-window-mode-policy 'vertical) (proof-layout-windows)) :style radio :selected (eq proof-three-window-mode-policy 'vertical) :help "One column mode"]))) (defvar proof-buffer-menu (cons "Buffers" `(["Layout Windows" proof-layout-windows] ,proof-3-window-mode-policy "" ["Rotate Output Buffers" proof-display-some-buffers :visible (not proof-three-window-enable) :active (buffer-live-p proof-goals-buffer)] ["Clear Responses" pg-response-clear-displays :active (buffer-live-p proof-response-buffer)] "----" ["Active Scripting" (proof-switch-to-buffer proof-script-buffer) :active (buffer-live-p proof-script-buffer)] ["Goals" (proof-switch-to-buffer proof-goals-buffer t) :active (buffer-live-p proof-goals-buffer)] ["Response" (proof-switch-to-buffer proof-response-buffer t) :active (buffer-live-p proof-response-buffer)] ["Trace" (proof-switch-to-buffer proof-trace-buffer) :active (buffer-live-p proof-trace-buffer) :visible proof-shell-trace-output-regexp] ["Shell" (proof-switch-to-buffer proof-shell-buffer) :active (buffer-live-p proof-shell-buffer)])) "Proof General 3 window mode policy.") ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; "Quick" (or main) options ;; ;; First, make the togglers used in options menu below (proof-deftoggle proof-script-fly-past-comments) (proof-deftoggle proof-delete-empty-windows) (proof-deftoggle proof-shrink-windows-tofit) (proof-deftoggle proof-multiple-frames-enable proof-multiple-frames-toggle) (proof-deftoggle proof-layout-windows-on-visit-file proof-layout-windows-eagerly-toggle) (proof-deftoggle proof-three-window-enable proof-three-window-toggle) (proof-deftoggle proof-auto-raise-buffers proof-auto-raise-toggle) (proof-deftoggle proof-disappearing-proofs) (proof-deftoggle proof-full-annotation) (proof-deftoggle proof-colour-locked) (proof-deftoggle proof-sticky-errors) (proof-deftoggle proof-shell-quiet-errors) (proof-deftoggle proof-minibuffer-messages) (proof-deftoggle proof-output-tooltips) (proof-deftoggle proof-autosend-enable proof-autosend-toggle) (proof-deftoggle proof-fast-process-buffer) (proof-deftoggle proof-imenu-enable proof-imenu-toggle) (proof-deftoggle proof-keep-response-history) (proof-deftoggle proof-omit-proofs-option) (proof-eval-when-ready-for-assistant ;; togglers for settings separately configurable per-prover (proof-deftoggle-fn (proof-ass-sym unicode-tokens-enable) 'proof-unicode-tokens-toggle) (proof-deftoggle-fn (proof-ass-sym maths-menu-enable) 'proof-maths-menu-toggle)) (defun proof-keep-response-history () "Enable associated buffer histories following option `proof-keep-response-history'." (if proof-keep-response-history (proof-map-buffers (proof-associated-buffers) (bufhist-init)) (proof-map-buffers (proof-associated-buffers) (bufhist-exit)))) ;; Here is the menu (defconst proof-quick-opts-menu (cons "Quick Options" `( ;;; TODO: Add this in PG 4.0 once bufhist robust; see trac #169 ;;; ["Response history" proof-keep-response-history-toggle ;;; :style toggle ;;; :selected proof-keep-response-history] ("Processing" ["Omit Proofs" proof-omit-proofs-option-toggle :style toggle :selected proof-omit-proofs-option :active proof-omit-proofs-configured :help "Skip over proofs, admitting theorems, when asserting larger chunks"] ["Fast Process Buffer" proof-fast-process-buffer-toggle :style toggle :selected proof-fast-process-buffer :help "Use a fast loop when processing whole buffer (disables input)"] ["Electric Terminator" proof-electric-terminator-toggle :style toggle :selected proof-electric-terminator-enable :help "Automatically send commands when terminator typed"] ["Beep on Errors" proof-shell-quiet-errors-toggle :style toggle :selected (not proof-shell-quiet-errors) :help "Beep on errors or interrupts"] ["Fly Past Comments" proof-script-fly-past-comments-toggle :style toggle :selected proof-script-fly-past-comments :help "Coalesce and skip over successive comments"] ["Full Annotation" proof-full-annotation-toggle :style toggle :selected proof-full-annotation :help "Record full information to decorate scripts (may cause slowdown)"] ["Process Automatically" proof-autosend-toggle :style toggle :selected proof-autosend-enable :help "Automatically send commands when idle"] ("Automatic Processing Mode" ["Next Command" (customize-set-variable 'proof-autosend-all nil) :style radio :selected (eq proof-autosend-all nil) :active proof-autosend-enable :help "Automatically try out the next command"] ["Send Whole Buffer" (customize-set-variable 'proof-autosend-all t) :style radio :selected (eq proof-autosend-all t) :active proof-autosend-enable :help "Automatically send the whole buffer"])) ("Display" ["Toolbar" proof-toolbar-toggle :style toggle :visible (featurep 'tool-bar) :selected proof-toolbar-enable :help "Use the Proof General toolbar"] ["Unicode Tokens" (proof-unicode-tokens-toggle (if (boundp 'unicode-tokens-mode) (if unicode-tokens-mode 0 1) 1)) :active (proof-unicode-tokens-support-available) :style toggle :selected (and (boundp 'unicode-tokens-mode) unicode-tokens-mode) :help "Enable display of tokens as Unicode characters"] ["Minibuffer Messages" proof-minibuffer-messages-toggle :style toggle :selected proof-minibuffer-messages :help "Show progress messages in minibuffer"] ["Output Tooltips" proof-output-tooltips-toggle :style toggle :selected proof-output-tooltips :help "Add tooltips for prover output"] ["Auto Raise" proof-auto-raise-toggle :style toggle :selected proof-auto-raise-buffers :help "Automatically raise buffers when output arrives"] ["Use Three Panes" proof-three-window-toggle :style toggle :active (not proof-multiple-frames-enable) :selected proof-three-window-enable :help "Use three panes"] ;; We use non-Emacs terminology "Windows" in this menu to help ;; non-Emacs users. Cf. Gnome usability studies: menus saying ;; "Web Browser" more useful to novices than menus saying "Mozilla"!! ["Layout Eagerly" proof-layout-windows-eagerly-toggle :style toggle :selected proof-layout-windows-on-visit-file :help "Display prover output windows when script file is opened."] ["Multiple Windows" proof-multiple-frames-toggle :active (and window-system t) :style toggle :selected proof-multiple-frames-enable :help "Use multiple windows (Emacs frames) for display"] ["Delete Empty Panes" proof-delete-empty-windows-toggle :active (not proof-multiple-frames-enable) :style toggle :selected proof-delete-empty-windows :help "Dynamically remove empty panes from display"] ["Shrink to Fit" proof-shrink-windows-tofit-toggle :active (not proof-multiple-frames-enable) :style toggle :selected proof-shrink-windows-tofit :help "Dynamically shrink size of output panes to fit contents"] ["Colour Locked" proof-colour-locked-toggle :style toggle :selected proof-colour-locked :help "Add highlighting to locked (checked) text"] ["Sticky Errors" proof-sticky-errors-toggle :style toggle :selected proof-sticky-errors :help "Highlight commands that caused errors"] ["Disppearing Proofs" proof-disappearing-proofs-toggle :style toggle :selected proof-disappearing-proofs :help "Hide proofs as they are completed"] "----" ["Document Centred" proof-set-document-centred :help "Select options for document-centred working"] ["Default" proof-set-non-document-centred :help "Set options for classic Proof General interaction"]) ("Read Only" ["Strict Read Only" (customize-set-variable 'proof-strict-read-only t) :style radio :selected (eq proof-strict-read-only t) :help "Do not allow editing in processed region"] ["Undo On Edit" (customize-set-variable 'proof-strict-read-only 'retract) :style radio :selected (eq proof-strict-read-only 'retract) :help "Automatically retract on edits in processed region"] ["Freely Edit" (customize-set-variable 'proof-strict-read-only nil) :style radio :selected (null proof-strict-read-only) :help "No write protection, edit anywhere. Dangerous!"]) ("Follow Mode" ["Follow Locked Region" (customize-set-variable 'proof-follow-mode 'locked) :style radio :selected (eq proof-follow-mode 'locked) :help "Point follows the locked region"] ;; Not implemented. See Trac #187 ;; ["Follow On Success" ;; (customize-set-variable 'proof-follow-mode 'followsuccess) ;; :style radio ;; :selected (eq proof-follow-mode 'followdown)] ["Follow Locked Region Down" (customize-set-variable 'proof-follow-mode 'followdown) :style radio :selected (eq proof-follow-mode 'followdown) :help "Point follows the locked region when processsing"] ["Keep Locked Region Displayed" (customize-set-variable 'proof-follow-mode 'follow) :style radio :selected (eq proof-follow-mode 'follow) :help "Scroll to ensure end of lock region is visible"] ["Never Move" (customize-set-variable 'proof-follow-mode 'ignore) :style radio :selected (eq proof-follow-mode 'ignore) :help "Do not move cursor during processing"]) ("Deactivate Action" ["Retract" (customize-set-variable 'proof-auto-action-when-deactivating-scripting 'retract) :style radio :selected (eq proof-auto-action-when-deactivating-scripting 'retract)] ["Process" (customize-set-variable 'proof-auto-action-when-deactivating-scripting 'process) :style radio :selected (eq proof-auto-action-when-deactivating-scripting 'process)] ["Query" (customize-set-variable 'proof-auto-action-when-deactivating-scripting nil) :style radio :selected (null proof-auto-action-when-deactivating-scripting)]) ("Minor Modes" ["Unicode Maths Menu" (proof-maths-menu-toggle (if (boundp 'maths-menu-mode) (if maths-menu-mode 0 1) 1)) :active (proof-maths-menu-support-available) :style toggle :selected (and (boundp 'maths-menu-mode) maths-menu-mode) :help "Maths menu for inserting Unicode characters"] ["Index Menu" proof-imenu-toggle :active (stringp (locate-library "imenu")) :style toggle :selected proof-imenu-enable :help "Generate an index menu of definitions, display which function in modeline"] "----" ;; NB: next group not saved, just for convenience here to ;; hint they're defined for PG ["Outline" outline-minor-mode :active (stringp (locate-library "outline")) :style toggle :selected (and (boundp 'outline-minor-mode) outline-minor-mode) :help "Outline mode for folding (note: option not saved)"] ["Hide/Show" hs-minor-mode :active (stringp (locate-library "hideshow")) :style toggle :selected (and (boundp 'hs-minor-mode) hs-minor-mode) :help "Hide/Show mode for folding (note: option not saved)"] ["Speedbar" speedbar :active (stringp (locate-library "speedbar")) :style toggle :selected (and (boundp 'speedbar-frame) speedbar-frame) :help "Speedbar navigation window (note: option not saved)"]) "----" ["Reset Options" (proof-quick-opts-reset) (proof-quick-opts-changed-from-defaults-p)] ["Save Options" (proof-quick-opts-save) (proof-quick-opts-changed-from-saved-p)])) "Proof General quick options.") (defun proof-quick-opts-vars () "Return a list of the quick option variables." (list 'proof-electric-terminator-enable 'proof-autosend-enable 'proof-fast-process-buffer 'proof-script-fly-past-comments 'proof-disappearing-proofs 'proof-full-annotation 'proof-strict-read-only (proof-ass-sym unicode-tokens-enable) (proof-ass-sym maths-menu-enable) 'proof-toolbar-enable 'proof-keep-response-history 'proof-imenu-enable 'proof-shell-quiet-errors ;; Display sub-menu 'proof-minibuffer-messages 'proof-auto-raise-buffers 'proof-three-window-enable 'proof-delete-empty-windows 'proof-multiple-frames-enable 'proof-shrink-windows-tofit 'proof-multiple-frames-enable 'proof-colour-locked 'proof-sticky-errors ;; Follow mode sub-menu 'proof-follow-mode ;; Deactivate scripting action proof-auto-action-when-deactivating-scripting)) (defun proof-quick-opts-changed-from-defaults-p () ;; NB: would be nice to add. Custom support? t) (defun proof-quick-opts-changed-from-saved-p () ;; NB: would be nice to add. Custom support? t) ;; ;; Changing several options together (ugly UI) ;; (defun proof-set-document-centred () "Select options for document-centred working." (interactive) (proof-full-annotation-toggle 1) (proof-auto-raise-toggle 0) (proof-colour-locked-toggle 0) (proof-sticky-errors-toggle 1) (proof-autosend-toggle 1) (customize-set-variable 'proof-strict-read-only 'retract) (customize-set-variable 'proof-autosend-all t) (customize-set-variable 'proof-follow-mode 'ignore)) (defun proof-set-non-document-centred () "Set options for classic Proof General interaction." (interactive) ;; default: (proof-full-annotation-toggle 1) (proof-auto-raise-toggle 1) (proof-colour-locked-toggle 1) (proof-sticky-errors-toggle 0) (proof-autosend-toggle 0) ;; default: (customize-set-variable 'proof-strict-read-only 'retract) (customize-set-variable 'proof-autosend-all nil) (customize-set-variable 'proof-follow-mode 'ignore)) ;; ;; We have menu items for saving options and reseting them. ;; We could just store the settings automatically (no save), ;; but then the reset option would have to change to restore ;; to manufacturer settings (rather then user-stored ones). ;; (defun proof-quick-opts-save () "Save current values of PG Options menu items using custom." (interactive) (apply 'pg-custom-save-vars (proof-quick-opts-vars))) (defun proof-quick-opts-reset () "Reset PG Options menu to default (or user-set) values, using custom." (interactive) (apply 'pg-custom-reset-vars (proof-quick-opts-vars))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Main menu ;; (defconst proof-config-menu (list "----" ;; buffer menu might better belong in toolbar menu? proof-buffer-menu proof-quick-opts-menu) "Proof General configuration menu.") (defconst proof-advanced-menu (cons "Advanced" (append '(["Complete Identifier" proof-script-complete :help "Complete the identifier at point"] ["Insert Last Output" pg-insert-last-output-as-comment :active proof-shell-last-output :help "Insert the last output into the proof script as a comment"] ["Make Movie" pg-movie-export :help "Export processed portion as Movie XML file (enable Full Annotations first!)"]) (list "-----") proof-show-hide-menu (list "-----") (list (customize-menu-create 'proof-general)) (list (customize-menu-create 'proof-general-internals "Internals")))) "Advanced sub-menu of script functions and customize.") (defvar proof-upgrade-menu '(["Upgrade ELPA packages..." proof-upgrade-elpa-packages :help "Update all Emacs packages (including Proof General!)"]) "The Proof General generic menu for upgrading packages.") (defvar proof-menu '(["Next Error" proof-next-error :active pg-next-error-regexp] ["Scripting Active" proof-toggle-active-scripting :style toggle :selected (eq proof-script-buffer (current-buffer))]) "The Proof General generic menu for scripting buffers.") (defun proof-main-menu () "Construct and return PG main menu used in scripting buffers." (cons proof-general-name (append (proof-toolbar-scripting-menu) proof-menu proof-config-menu (list (customize-menu-create 'proof-user-options "Customize Options")) (list proof-advanced-menu) (list proof-help-menu) proof-upgrade-menu))) ;;;###autoload (defun proof-aux-menu () "Construct and return PG auxiliary menu used in non-scripting buffers." (cons proof-general-name (append (proof-toolbar-scripting-menu) proof-config-menu (list proof-help-menu)))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; ;;; Favourites mechanism for prover-specific menu ;;; (defun proof-menu-define-favourites-menu () "Return menu generated from `PA-favourites'." (let ((favs (reverse (proof-ass favourites))) ents) (while favs (setq ents (cons (apply 'proof-def-favourite (car favs)) ents)) (setq favs (cdr favs))) (setq proof-menu-favourites (list (cons "Favourites" (append ents ;; (list "----") doesn't work for adding before '(["Add Favourite" (call-interactively 'proof-add-favourite) t] ["Delete Favourite" (call-interactively 'proof-del-favourite) t] ["Save Favourites" (proof-save-favourites) t]))))))) ;;; Define stuff from favourites (defun proof-def-favourite (command inscript menuname &optional key new) "Define and a \"favourite\" proof assistant function. See doc of `proof-add-favourite' for first four arguments. Extra NEW flag means that this should be a new favourite, so check that function defined is not already bound. This function defines a function and returns a menu entry suitable for adding to the proof assistant menu." (let* ((menunames (split-string (downcase menuname))) (menuname-sym (proof-sym (mapconcat 'identity menunames "-"))) (menu-fn menuname-sym) (i 1)) (while (and new (fboundp menu-fn)) (setq menu-fn (intern (concat (symbol-name menuname-sym) "-" (int-to-string i)))) (cl-incf i)) (if inscript (eval `(proof-defshortcut ,menu-fn ,command ,key)) (eval `(proof-definvisible ,menu-fn ,command ,key))) ;; Return menu entry (vector menuname menu-fn t))) ;;; Commentary: ;; ;;; Code for adding "favourites" to the proof-assistant specific menu (defvar proof-make-favourite-cmd-history nil "History for proof-make-favourite.") (defvar proof-make-favourite-menu-history nil "History for proof-make-favourite.") (defun proof-save-favourites () "Save favourites in customization settings." (interactive) (pg-custom-save-vars (proof-ass-sym favourites))) (defun proof-del-favourite (menuname) "Delete \"favourite\" command recorded at MENUNAME." (interactive (list (completing-read "Menu item to delete: " (mapcar 'cddr (proof-ass favourites)) nil t))) (let* ((favs (proof-ass favourites)) (rmfavs (cl-remove-if (lambda (f) (string-equal menuname (cl-caddr f))) favs))) (unless (equal favs rmfavs) (easy-menu-remove-item proof-assistant-menu '("Favourites") menuname) (customize-set-variable (proof-ass-sym favourites) rmfavs)))) (defun proof-read-favourite () (let* ((guess (buffer-substring (save-excursion (beginning-of-line-text) (point)) (point))) (cmd (read-string (concat "Command to send to " proof-assistant ": ") guess proof-make-favourite-cmd-history)) (ins (y-or-n-p "Should command be recorded in script? ")) (men (read-string "Name of command on menu: " cmd proof-make-favourite-menu-history)) (key (if (y-or-n-p "Set a keybinding for this command? ") ;; FIXME: better validation here would be to check ;; this is a new binding, or remove old binding below. (read-key-sequence "Type the key to use (binding will be C-c C-a ): " nil t)))) ;; result (list cmd ins men key))) (defun proof-add-favourite (command inscript menuname &optional key) "Define and add a \"favourite\" proof-assisant function to the menu bar. The favourite function will issue COMMAND to the proof assistant. COMMAND is inserted into script (not sent immediately) if INSCRIPT non-nil. MENUNAME is the name of the function for the menu. KEY is the optional key binding." (interactive (proof-read-favourite)) (let* ((menu-entry (proof-def-favourite command inscript menuname key t)) (favs (proof-ass favourites)) (rmfavs (cl-remove-if (lambda (f) (string-equal menuname (cl-caddr f))) favs)) (newfavs (append rmfavs (list (list command inscript menuname key))))) ;; If def succeeds, add to customize var (customize-set-variable (proof-ass-sym favourites) newfavs) (easy-menu-add-item proof-assistant-menu '("Favourites") menu-entry "Add Favourite"))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; ;;; Proof assistant settings mechanism. ;;; (defun proof-menu-define-settings-menu () "Return menu generated from `proof-assistant-settings', update `proof-menu-settings'." (if proof-assistant-settings (let ((save (list "----" ["Reset Settings" (proof-settings-reset) (proof-settings-changed-from-defaults-p)] ["Save Settings" (proof-settings-save) (proof-settings-changed-from-saved-p)])) groups ents) ; todo: AFAICT the following statement does nothing and can be removed (mapc (lambda (stg) (add-to-list 'groups (get (car stg) 'pggroup))) proof-assistant-settings) (dolist (grp (reverse groups)) (let* ((gstgs (cl-mapcan (lambda (stg) (if (eq (get (car stg) 'pggroup) grp) (list stg))) proof-assistant-settings)) (cmds (mapcar (lambda (stg) (apply #'proof-menu-entry-for-setting stg)) (reverse gstgs)))) (setq ents (if grp (cons (cons grp cmds) ents) (append cmds (if (> (length groups) 1) '("----")) ents))))) (setq proof-menu-settings (list (cons "Settings" (nconc ents save))))))) (defun proof-menu-entry-name (symbol) "Return a nice menu entry name for SYMBOL." (let ((grp (get symbol 'pggroup)) (nm (symbol-name symbol))) (upcase-initials (replace-regexp-in-string "-" " " ;; strip the group name from the menu entry name. (if grp (replace-regexp-in-string (concat (downcase grp) ":") "" nm) nm))))) (defun proof-menu-entry-for-setting (symbol setting type descr) (let ((entry-name (proof-menu-entry-name symbol)) (pasym (proof-ass-symv symbol))) (cond ((eq type 'boolean) (vector entry-name (proof-deftoggle-fn pasym) :style 'toggle :selected pasym :help descr)) ((eq type 'integer) (vector entry-name (proof-defintset-fn pasym) :help descr)) ((eq type 'number) (vector entry-name (proof-deffloatset-fn pasym) :help descr)) ((eq type 'string) (vector entry-name (proof-defstringset-fn pasym) :help descr))))) (defun proof-settings-vars () "Return a list of proof assistant setting variables." (append (mapcar (lambda (setting) (proof-ass-symv (car setting))) proof-assistant-settings) proof-assistant-additional-settings)) (defun proof-settings-changed-from-defaults-p () ;; FIXME: would be nice to add. Custom support? t) (defun proof-settings-changed-from-saved-p () ;; FIXME: would be nice to add. Custom support? t) (defun proof-settings-save () "Save current values of proof assistant settings using Custom." (interactive) (apply 'pg-custom-save-vars (proof-settings-vars))) (defun proof-settings-reset () "Reset proof assistant settings to their default values." (interactive) (apply 'pg-custom-reset-vars (proof-settings-vars))) (defun proof-assistant-invisible-command-ifposs (cmd) "Send CMD as an \"invisible command\" if the proof process is available." ;; FIXME: better would be to queue the command, or even interrupt a ;; queue in progress. Also must send current settings at start of ;; session somehow. (This might happen automatically if a queue of ;; deffered commands is set, since defcustom calls proof-set-value ;; even to set the default/initial value?) (if (proof-shell-available-p) (progn (proof-shell-invisible-command cmd t) ;; refresh display, ;; FIXME: should only do if goals display is active, ;; messy otherwise. ;; (we need a new flag for "active goals display"). ;; PG 3.5 (patch 22.04.04): ;; Let's approximate that by looking at proof-nesting-depth. (if (and proof-showproof-command (> proof-nesting-depth 0)) (proof-shell-invisible-command proof-showproof-command)) ;; Could also repeat last command if non-state destroying. ))) (defun proof-maybe-askprefs () "If `proof-use-pgip-askprefs' is non-nil, try to issue . This will configure dynamic settings used in the current prover session and extend `proof-assistant-settings'. We first clear the dynamic settings from `proof-assistant-settings'." (when (and proof-use-pgip-askprefs proof-shell-issue-pgip-cmd) (let (newsettings) (dolist (setting proof-assistant-settings) (let ((name (car setting))) (if (get name 'pgdynamic) (undefpgcustom name) (push setting newsettings)))) (setq proof-assistant-settings newsettings)) (pg-pgip-askprefs))) (defun proof-assistant-settings-cmd (setting) "Return string for making SETTING in Proof General customization." (let ((expr (assq setting proof-assistant-settings))) (if (and expr (cadr expr)) (proof-assistant-format (cadr expr) (eval (proof-ass-symv (car expr))))))) (defun proof-assistant-settings-cmds () "Return strings for settings kept in Proof General customizations." (let (cmds) (dolist (setting proof-assistant-settings) (let ((sym (car setting)) (pacmd (cadr setting))) (if (and pacmd (or (not (get sym 'pgdynamic)) (proof-ass-differs-from-default sym))) (push (proof-assistant-format pacmd (eval (proof-ass-symv sym))) cmds)))) cmds)) (defvar proof-assistant-format-table (list (cons "%b" '(proof-assistant-format-bool curvalue)) (cons "%i" '(proof-assistant-format-int curvalue)) (cons "%f" '(proof-assistant-format-float curvalue)) (cons "%s" '(proof-assistant-format-string curvalue)) (cons "%l" '(proof-assistant-format-lambda curvalue))) "Table to use with `proof-format' for formatting CURVALUE for assistant. NB: variable `curvalue' is dynamically scoped (used in `proof-assistant-format').") (defun proof-assistant-format-bool (value) (if value proof-assistant-true-value proof-assistant-false-value)) (defun proof-assistant-format-int (value) (funcall proof-assistant-format-int-fn value)) (defun proof-assistant-format-float (value) (funcall proof-assistant-format-float-fn value)) (defun proof-assistant-format-string (value) (funcall proof-assistant-format-string-fn value)) (defun proof-assistant-format-lambda (value) (funcall value)) (defun proof-assistant-format (string curvalue) "Replace a format characters in STRING by formatted CURVALUE. Format character is one of %b, %i, %f, %s, or %l. Formatting suitable for current proof assistant, controlled by `proof-assistant-format-table' which see. Finally, apply `proof-assistant-setting-format' if non-nil. Alternatively, STRING can be a function which yields a string when applied to the CURVALUE. As another special case for boolean settings: the setting STRING can be a cons cell of two strings, the first one for true (non-nil value) and the second for false." (let ((setting (cond ((stringp string) ;; use % format characters ;; Dynbind for use in proof-assistant-format-table! (with-no-warnings (defvar curvalue)) (let ((curvalue curvalue)) (proof-format proof-assistant-format-table string))) ((functionp string) ;; call the function (funcall string curvalue)) ((consp string) ;; true/false options (if curvalue (car string) (cdr string))) (t ;; no idea what to do (error "Function proof-assistant-format: called with invalid string arg %s" string))))) (if proof-assistant-setting-format (funcall proof-assistant-setting-format setting) setting))) (provide 'proof-menu) ;;; proof-menu.el ends here PG-4.5/generic/proof-script.el000066400000000000000000003444261426357011200162730ustar00rootroot00000000000000;;; proof-script.el --- Major mode for proof assistant script files. -*- lexical-binding:t -*- ;; This file is part of Proof General. ;; Portions © Copyright 1994-2012 David Aspinall and University of Edinburgh ;; Portions © Copyright 2003-2021 Free Software Foundation, Inc. ;; Portions © Copyright 2001-2017 Pierre Courtieu ;; Portions © Copyright 2010, 2016 Erik Martin-Dorel ;; Portions © Copyright 2011-2013, 2016-2017 Hendrik Tews ;; Portions © Copyright 2015-2017 Clément Pit-Claudel ;; Authors: David Aspinall, Yves Bertot, Healfdene Goguen, ;; Thomas Kleymann and Dilip Sequeira ;; SPDX-License-Identifier: GPL-3.0-or-later ;;; Commentary: ;; ;; This implements the main mode for script management, including ;; parsing script buffers and setting spans inside them. ;; ;; Compile note: functions used here from proof-shell, pg-user, ;; pg-response, pg-goals auto-loaded to prevent circular dependency. ;;; Code: (require 'cl-lib) ; various (require 'span) ; abstraction of overlays/extents (require 'pg-vars) (require 'proof-utils) ; proof-utils macros (require 'proof-syntax) ; utils for manipulating syntax (eval-when-compile (require 'easymenu)) (defvar proof-mode-menu) (defvar proof-assistant-menu) (declare-function proof-shell-strip-output-markup "proof-shell" (string &optional push)) (declare-function proof-shell-make-associated-buffers "proof-shell" ()) (declare-function proof-layout-windows "pg-response" (&rest args)) (declare-function pg-response-warning "pg-response" (&rest args)) (declare-function proof-segment-up-to "proof-script") (declare-function proof-autosend-enable "pg-user") (declare-function proof-interrupt-process "pg-shell") (declare-function proof-cd-sync "pg-user" ()) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; PRIVATE VARIABLES ;; ;; Local variables used by proof-script-mode ;; ;; Buffer-local variables (deflocal proof-active-buffer-fake-minor-mode nil "An indication in the modeline that this is the *active* script buffer") (deflocal proof-script-buffer-file-name nil ;; NB: if buffer-file-name is nil for some other reason, this may break. "A copied value of buffer-file-name to cope with `find-alternative-file'. The `find-alternative-file' function has a nasty habit of setting the buffer file name to nil before running kill buffer, which breaks PG's kill buffer hook. This variable is used when buffer-file-name is nil.") (deflocal pg-script-portions nil "Alist of hash tables for symbols naming processed script portions.") ;;;###autoload (defun proof-ready-for-assistant (assistantsym &optional assistant-name) "Configure PG for symbol ASSISTANTSYM, name ASSISTANT-NAME. If ASSISTANT-NAME is omitted, look up in `proof-assistant-table'." (unless proof-assistant-symbol (let* ((sname (symbol-name assistantsym)) (assistant-name (or assistant-name (car-safe (cdr-safe (assoc assistantsym proof-assistant-table))) sname)) (cusgrp-rt ;; Normalized a bit to remove spaces and funny characters (replace-regexp-in-string "/\\|[ \t]+" "-" (downcase assistant-name))) (cusgrp (intern cusgrp-rt)) (cus-internals (intern (concat cusgrp-rt "-config"))) (elisp-dir sname) ; NB: dirname same as symbol name! (loadpath-elt (concat proof-home-directory elisp-dir "/"))) ;; FIXME: Yuck!! (eval `(progn ;; Make a customization group for this assistant (defgroup ,cusgrp nil ,(concat "Customization of user options for " assistant-name " Proof General.") :group 'proof-general) ;; And another one for internals (defgroup ,cus-internals nil ,(concat "Customization of internal settings for " assistant-name " configuration.") :group 'proof-general-internals :prefix ,(concat sname "-")) ;; Set the proof-assistant configuration variables ;; NB: tempting to use customize-set-variable: wrong! ;; Here we treat customize as extended docs for these ;; variables. (setq proof-assistant-cusgrp (quote ,cusgrp)) (setq proof-assistant-internals-cusgrp (quote ,cus-internals)) (setq proof-assistant ,assistant-name) (setq proof-assistant-symbol (quote ,assistantsym)) ;; define the per-prover settings which depend on above (require 'pg-custom) (setq proof-mode-for-shell (proof-ass-sym shell-mode)) (setq proof-mode-for-response (proof-ass-sym response-mode)) (setq proof-mode-for-goals (proof-ass-sym goals-mode)) (setq proof-mode-for-script (proof-ass-sym mode)) ;; Extend the load path if necessary (proof-add-to-load-path ,loadpath-elt) ;; Run hooks for late initialisation (run-hooks 'proof-ready-for-assistant-hook)) t)))) (defalias 'proof-active-buffer-fake-minor-mode #'proof-toggle-active-scripting) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Counting and naming proof elements ;; (defun proof-next-element-count (idiom) "Return count for next element of type IDIOM. This uses the size of the hash table for IDIOM." (let ((tbl (cdr-safe (assq idiom pg-script-portions)))) (if tbl (1+ (hash-table-count tbl)) 1))) (defun proof-element-id (idiom number) "Return a string identifier composed from symbol IDIOM and NUMBER." (concat (symbol-name idiom) "-" (int-to-string number))) (defun proof-next-element-id (idiom) "Return a string suitable for naming the next element of type IDIOM." (proof-element-id idiom (proof-next-element-count idiom))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Basic functions for handling the locked and queue regions ;; ;; -------------------------------------------------------------- ;; ;; Notes on regions in the scripting buffer. (da) ;; ;; The locked region is covered by a collection of non-overlaping ;; spans (spans are our abstraction of extents/overlays). ;; ;; Each span has a 'type property, one of: ;; ;; 'goalsave A goal..savegoal region in the buffer, a completed proof. ;; 'vanilla Initialised in proof-semis-to-vanillas, for ;; 'comment A comment outside a command. ;; 'proverproc A region closed by the prover, processed outwith PG ;; 'pbp A PBP command inserted automatically into the script ;; ;; For an unfinished proof, there is one extent for each command ;; or comment outside a command. For a finished proof, there ;; is one extent for the whole proof. ;; ;; A spans corresponding to a command has a 'cmd property, which is set ;; to a string of its command. This is the text in the buffer ;; stripped of leading whitespace and any comments. ;; ;; ** Variables (deflocal proof-locked-span nil "The locked span of the buffer. Each script buffer has its own locked span, which may be detached from the buffer. Proof General allows buffers in other modes also to be locked; these also have a non-nil value for this variable.") (deflocal proof-queue-span nil "The queue span of the buffer. May be detached if inactive or empty. Each script buffer has its own queue span, although only the active scripting buffer may have an active queue span.") ;; da: reason for buffer local queue span is because initialisation ;; in proof-init-segmentation can happen when a file is visited. ;; So nasty things might happen if a locked file is visited whilst ;; another buffer has a non-empty queue region being processed. (deflocal proof-overlay-arrow nil "Marker holding the overlay arrow position for this buffer.") ;; ** Getters and setters (defun proof-span-give-warning (&rest _args) "Give a warning message. Optional argument ARGS is ignored." (unless inhibit-read-only (message "You should not edit here!"))) (defun proof-span-read-only (span &optional always) "Make SPAN read-only, following variable `proof-strict-read-only' or ALWAYS." (if (or always (not (memq proof-strict-read-only '(nil retract)))) (span-read-only span) (span-write-warning span (if (eq proof-strict-read-only 'retract) 'proof-retract-before-change 'proof-span-give-warning)))) (defun proof-strict-read-only () "Set spans read-only according to variable `proof-strict-read-only'. Action is taken on all script buffers." ;; NB: read-only is synchronized in all script buffers (interactive) (proof-map-buffers (proof-buffers-in-mode proof-mode-for-script) (if (span-live-p proof-locked-span) (proof-span-read-only proof-locked-span)))) (defsubst proof-set-queue-endpoints (start end) "Set the queue span to be START, END." (span-set-endpoints proof-queue-span start end)) (defun proof-set-overlay-arrow (pos) "Set the position of the overlay marker to POS." (and (markerp proof-overlay-arrow) (set-marker proof-overlay-arrow (save-excursion (goto-char pos) (skip-chars-forward " \t\s\n") (unless (eq (point) (point-max)) (beginning-of-line) (point)))))) (defsubst proof-set-locked-endpoints (start end) "Set the locked span to be START, END." (span-set-endpoints proof-locked-span start end) (proof-set-overlay-arrow end)) (defsubst proof-detach-queue () "Remove the span for the queue region." (and proof-queue-span (span-detach proof-queue-span))) (defsubst proof-detach-locked () "Remove the span for the locked region." (and proof-locked-span (span-detach proof-locked-span)) (and (markerp proof-overlay-arrow) (set-marker proof-overlay-arrow nil))) (defsubst proof-set-queue-start (start) "Set the queue span to begin at START." (span-set-start proof-queue-span start)) (defsubst proof-set-locked-end (end) "Set the end of the locked region to be END. If END is at or before (point-min), remove the locked region. Otherwise set the locked region to be from (point-min) to END." (if (>= (point-min) end) ;; Detach queue span, otherwise may have read-only character at end. (proof-detach-locked) (proof-set-locked-endpoints (point-min) ;; safety in case called with end>point-max (min (point-max) end)))) (defsubst proof-set-queue-end (end) "Set the queue span to end at END." (if (or (>= (point-min) end) (not (span-live-p proof-queue-span)) (<= end (span-start proof-queue-span))) (proof-detach-queue) (span-set-end proof-queue-span end))) ;; ** Initialise spans for a buffer (defun proof-init-segmentation () "Initialise the queue and locked spans in a proof script buffer. Allocate spans if need be. The spans are detached from the buffer, so the regions are made empty by this function. Also clear list of script portions." ;; Initialise queue span, remove it from buffer. (unless proof-queue-span (setq proof-queue-span (span-make 1 1)) ;; (span-raise proof-queue-span) ) (span-set-property proof-queue-span 'start-closed t) (span-set-property proof-queue-span 'end-open t) (proof-span-read-only proof-queue-span 'always) (span-set-property proof-queue-span 'face 'proof-queue-face) (span-detach proof-queue-span) ;; Initialise locked span, remove it from buffer (unless proof-locked-span (setq proof-locked-span (span-make 1 1)) ;; (span-raise proof-locked-span) ) (span-set-property proof-locked-span 'start-closed t) (span-set-property proof-locked-span 'end-open t) (proof-span-read-only proof-locked-span) (proof-colour-locked-span) (span-detach proof-locked-span) (setq proof-overlay-arrow (make-marker)) (setq overlay-arrow-position proof-overlay-arrow) (setq proof-last-theorem-dependencies nil) (pg-clear-script-portions) (pg-clear-input-ring)) ;;;###autoload (defun proof-colour-locked () "Alter the colour of all locked regions according to variable `proof-colour-locked'." (interactive) (proof-map-buffers (proof-buffers-in-mode proof-mode-for-script) (and (span-live-p proof-locked-span) (proof-colour-locked-span)))) (defun proof-colour-locked-span () "Alter the colour of the locked region according to variable `proof-colour-locked'." (if proof-colour-locked (span-set-property proof-locked-span 'face 'proof-locked-face) (span-set-property proof-locked-span 'face nil))) (defun proof-sticky-errors () "Alter the colour of sticky errors to match `proof-sticky-errors'. This function is not yet implemented, so the colouring will stay in effect until the regions are next cleared, or only be added the next time an error is processed." ;; TODO: we need to tag spans separately as error spans, and ;; map over all spans in all buffers. ) ;; ** Restarting and clearing spans (defun proof-restart-buffers (buffers) "Remove all extents in BUFFERS and maybe reset `proof-script-buffer'. The high-level effect is that all members of BUFFERS are completely unlocked, including all the necessary cleanup. No effect on a buffer which is nil or killed. If one of the buffers is the current scripting buffer, then `proof-script-buffer' will deactivated." (mapcar (lambda (buffer) (save-excursion (if (buffer-live-p buffer) (with-current-buffer buffer (if proof-active-buffer-fake-minor-mode (setq proof-active-buffer-fake-minor-mode nil)) (proof-script-delete-spans (point-min) (point-max)) (setq pg-script-portions nil) (proof-detach-queue) (proof-detach-locked) (proof-init-segmentation))) (if (eq buffer proof-script-buffer) (setq proof-script-buffer nil)))) buffers)) (defun proof-script-buffers-with-spans () "Return a list of all buffers with spans. This is calculated by finding all the buffers with a non-nil value of proof-locked span." (let ((bufs-left (buffer-list)) bufs-got) (dolist (buf bufs-left bufs-got) (if (with-current-buffer buf proof-locked-span) (setq bufs-got (cons buf bufs-got)))))) (defun proof-script-remove-all-spans-and-deactivate () "Remove all spans from scripting buffers via `proof-restart-buffers'." (proof-restart-buffers (proof-script-buffers-with-spans))) (defun proof-script-clear-queue-spans-on-error (badspan &optional interruptp) "Remove the queue span from buffer, cleaning spans no longer queued. If BADSPAN is non-nil, assume that this was the span whose command caused the error. Go to the start of it if `proof-follow-mode' is 'locked. If INTERRUPTP is non-nil, do not consider BADSPAN itself as faulty. This is a subroutine used in proof-shell-handle-{error,interrupt}." (let ((start (proof-unprocessed-begin)) (end (proof-queue-or-locked-end)) (infop (span-live-p badspan))) (proof-detach-queue) (when infop (unless proof-autosend-running (when (eq proof-follow-mode 'locked) ;; jump to start of error: should this be configurable? (goto-char (span-start badspan)) (skip-chars-forward " \t\n"))) (unless interruptp (when proof-sticky-errors (pg-set-span-helphighlights badspan 'proof-script-highlight-error-face 'proof-script-sticky-error-face)))) (proof-script-delete-spans start end))) (defun proof-script-delete-spans (beg end) "Delete primary spans between BEG and END. Secondary 'pghelp spans are left." (span-delete-spans beg end 'type) (span-delete-spans beg end 'idiom) (span-delete-spans beg end 'pg-span) ) (defun proof-script-delete-secondary-spans (beg end) "Delete secondary spans between BEG and END (currently, 'pghelp spans)." (span-delete-spans beg end 'pghelp)) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Buffer position functions ;; ;;;###autoload (defun proof-unprocessed-begin () "Return end of locked region in current buffer or (point-min) otherwise. The position is actually one beyond the last locked character." (or (and proof-locked-span (span-end proof-locked-span)) (point-min))) (defun proof-script-end () "Return the character beyond the last non-whitespace character. This is the same position `proof-unprocessed-begin' ends up at when asserting the script. Works for any kind of buffer." (save-excursion (goto-char (point-max)) (skip-chars-backward " \t\n") (point))) (defun proof-queue-or-locked-end () "Return the end of the queue region, or locked region, or (point-min). This position should be the first writable position in the buffer. An appropriate point to move point to (or make sure is displayed) when a queue of commands is being processed." (or ;; span-end returns nil if span is detached (and proof-queue-span (span-end proof-queue-span)) (and proof-locked-span (span-end proof-locked-span)) (point-min))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Predicates for locked region. ;; ;;;###autoload (defun proof-locked-region-full-p () "Non-nil if the locked region covers all the buffer's non-whitespace. Works on any buffer." (save-excursion (goto-char (point-max)) (skip-chars-backward " \t\n") (>= (proof-unprocessed-begin) (point)))) ;;;###autoload (defun proof-locked-region-empty-p () "Non-nil if the locked region is empty. Works on any buffer." (eq (proof-unprocessed-begin) (point-min))) (defun proof-only-whitespace-to-locked-region-p () "Non-nil if only whitespace from char after point to end of locked region. Point must be after the locked region or this will signal an error." (save-excursion (or (eq (point) (point-max)) (forward-char 1)) (not (proof-re-search-backward "\\S-" (proof-unprocessed-begin) t)))) (defun proof-in-locked-region-p () "Non-nil if point is in locked region. Assumes script buffer current." (< (point) (proof-unprocessed-begin))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Misc movement functions ;; (defun proof-goto-end-of-locked (&optional switch) "Jump to the end of the locked region, maybe switching to script buffer. If called interactively or SWITCH is non-nil, switch to script buffer. If called interactively, a mark is set at the current location with `push-mark'" (interactive) (if (and proof-script-buffer (called-interactively-p 'any)) (push-mark)) (proof-with-script-buffer (if ;; there is an active scripting buffer and it's not displayed (and proof-script-buffer (not (get-buffer-window proof-script-buffer)) (or switch (called-interactively-p 'any))) ;; display it (switch-to-buffer proof-script-buffer)) (goto-char (proof-unprocessed-begin)))) ;; Careful: movement can happen when the user is typing, not very nice! (defun proof-goto-end-of-locked-if-pos-not-visible-in-window () "If the end of the locked region is not visible, jump to the end of it. A possible hook function for `proof-shell-handle-error-or-interrupt-hook'. Does nothing if there is no active scripting buffer, or if `proof-follow-mode' is set to 'ignore." (interactive) (if (and proof-script-buffer (not (eq proof-follow-mode 'ignore))) (unless (proof-end-of-locked-visible-p) (proof-goto-end-of-locked t)))) (defun proof-goto-end-of-locked-on-error-if-pos-not-visible-in-window () "As `proof-goto-end-of-locked-if-pos-not-visible-in-window', but not for interrupts. Intended as a hook function for `proof-shell-handle-error-or-interrupt-hook'." (interactive) (unless (eq proof-follow-mode 'ignore) (if (eq proof-shell-last-output-kind 'error) (proof-goto-end-of-locked-if-pos-not-visible-in-window))) (proof-with-current-buffer-if-exists proof-script-buffer (unless (proof-end-of-locked-visible-p) (pg-jump-to-end-hint)))) (defun proof-end-of-locked-visible-p () "Return non-nil if end of locked region is visible." (let* ((pos (proof-with-current-buffer-if-exists proof-script-buffer (proof-unprocessed-begin))) (win (and pos (get-buffer-window proof-script-buffer t)))) (and win (pos-visible-in-window-p pos)))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Names of proofs (and other parts) in a script. ;; ;; Elements are represented as spans (overlays). ;; ;; Each kind of part ("idiom") in a proof script has its own name ;; space. Idioms are named with symbols. ;; (defconst pg-idioms '(proof) "List of script element kinds PG is aware of for this prover.") (defconst pg-all-idioms (append pg-idioms '(comment command other)) "List of all possible script element kinds.") (defun pg-clear-script-portions () "Clear record of script portion names and types from internal list." (dolist (idtbl pg-script-portions) (maphash (lambda (_k span) (span-delete span)) (cdr idtbl)) (clrhash (cdr idtbl)))) (defun pg-remove-element (idiom id) "From the script portion IDIOM, remove the identifier ID." (let* ((elts (cdr-safe (assq idiom pg-script-portions))) (span (and elts (gethash idiom elts)))) (when span (span-detach span) ;; delete overlay, without pre-del fn (remhash id elts)))) (defun pg-get-element (idiomsym id) "Return proof script element of type IDIOMSYM with identifier ID. IDIOMSYM is a symbol, ID is a string." (cl-assert (symbolp idiomsym)) (cl-assert (stringp id)) (let ((idsym (intern id)) (elts (cdr-safe (assq idiomsym pg-script-portions)))) (if elts (gethash idsym elts)))) (defun pg-add-element (idiomsym id span &optional name) "Add element of type IDIOMSYM with identifier ID, referred to by SPAN. This records the element in `pg-script-portions' and sets span properties accordingly. IDIOMSYM is a symbol, whereas ID and optional NAME are strings. Identifiers must be unique for a given idiom; the optional NAME will be recorded as a textual name used instead of ID for users; NAME does not need to be unique. NAME is a name that comes from the proof script or prover output. It is recorded in the span with the 'rawname property." (cl-assert (symbolp idiomsym)) (cl-assert (stringp id)) (if name (cl-assert (stringp name))) (let* ((idsym (intern id)) (rawname name) (name (or name id)) (idiom (symbol-name idiomsym)) (delfn (lambda () (pg-remove-element idiomsym idsym))) (elts (cdr-safe (assq idiomsym pg-script-portions)))) (unless elts (setq pg-script-portions (cons (cons idiomsym (setq elts (make-hash-table))) pg-script-portions))) (if (gethash idsym elts) (proof-debug "Element named %s (type %s) was already in buffer." name idiom)) (puthash idsym span elts) ;; Idiom and ID are stored in the span as symbols; name as a string. (span-set-property span 'idiom idiomsym) (span-set-property span 'id idsym) (span-set-property span 'name name) (span-set-property span 'rawname rawname) (span-add-delete-action span delfn) ;; Ideally: would keep invisible property to be the idiom type ;; (span-set-property span 'invisible idiom) ;; BUT: problems overlapping invisible regions with ;; Unicode Tokens (crucial for hiding control sequences). ;; Nice behaviour in with isearch: open invisible regions temporarily. (span-set-property span 'isearch-open-invisible 'pg-open-invisible-span) (span-set-property span 'isearch-open-invisible-temporary 'pg-open-invisible-span))) (defun pg-invisible-prop (idiom) "Return an invisibility symbol for the given IDIOM. This is a value for the overlay 'invisible property." (intern (concat "pg-" (symbol-name (or idiom 'other))))) (defun pg-set-element-span-invisible (span invisiblep) "Function to adjust visibility of SPAN to INVISIBLEP. We use list values of the 'invisible property which contain private symbols, that should play well with other conforming modes and `buffer-invisibility-spec'." (let* ((invisible-prop (pg-invisible-prop (span-property span 'idiom))) (invisible-rest (remq invisible-prop (span-property span 'invisible)))) (span-set-property span 'invisible (if invisiblep (cons invisible-prop invisible-rest) invisible-rest)))) (defun pg-toggle-element-span-visibility (span) "Toggle visibility of SPAN." (pg-set-element-span-invisible span (not (span-property span 'invisible)))) (defun pg-open-invisible-span (span &optional invisible) "Function for `isearch-open-invisible' property." ;; alias (pg-set-element-span-invisible span invisible)) (defun pg-make-element-invisible (idiomsym id) "Make element of type IDIOMSYM and identifier ID invisible, with ellipsis." (let ((span (pg-get-element idiomsym id))) (if span (pg-set-element-span-invisible span t)))) (defun pg-make-element-visible (idiomsym id) "Make element of type IDIOMSYM and identifier ID visible." (let ((span (pg-get-element idiomsym id))) (if span (pg-set-element-span-invisible span nil)))) (defun pg-toggle-element-visibility (idiomsym id) "Toggle visibility of script element of type IDIOMSYM, named ID. IDIOMSYM is a symbol and ID is a strings." (let ((span (pg-get-element idiomsym id))) (if span (pg-toggle-element-span-visibility span)))) (defun pg-show-all-portions (idiom &optional hide) "Show or conceal portions of kind IDIOM; if HIDE is non-nil, conceal." (interactive (list (intern (completing-read (concat "Make " (if current-prefix-arg "in" "") "visible all regions of: ") (apply #'vector pg-idioms) nil t)) current-prefix-arg)) (let ((elts (cdr-safe (assq idiom pg-script-portions))) (alterfn (lambda (_k span) (pg-set-element-span-invisible span hide)))) (when elts (proof-with-script-buffer ; may be called from menu (maphash alterfn elts))))) (defun pg-add-proof-element (name span controlspan) "Add a span proof element (named NAME) to SPAN with parent CONTROLSPAN." (let ((proofid (proof-next-element-id 'proof))) (pg-add-element 'proof proofid span name) ;; Set id in controlspan [NB: intern here means symbol-name elsewhere] (span-set-property controlspan 'id (intern proofid)) ;; Make a navigable link between the two spans. (span-set-property span 'controlspan controlspan) (span-set-property controlspan 'children (cons span (span-property controlspan 'children))) (pg-set-span-helphighlights span proof-region-mouse-highlight-face) ;; (span-set-property span 'priority 10) ; lower than default (if proof-disappearing-proofs (pg-make-element-invisible 'proof proofid)))) (defun pg-span-name (span) "Return a user-level name for SPAN. This is based on its name and type. Each span has a 'type property, one of: 'goalsave A goal..savegoal region in the buffer, a completed proof. 'vanilla Initialised in proof-semis-to-vanillas, for 'comment A comment outside a command. 'proverproc A region closed by the prover, processed outwith PG 'pbp A PBP command inserted automatically into the script." (let ((type (span-property span 'type)) (idiom (span-property span 'idiom)) (rawname (span-property span 'rawname))) (cond (idiom (concat (upcase-initials (symbol-name idiom)) ;; only use rawnames, not internally generated ones (if (and rawname (not (equal rawname proof-unnamed-theorem-name))) (concat " [" rawname "]")))) ((or (eq type 'proof) (eq type 'goalsave)) (concat "Proof" (let ((name (span-property span 'name))) (if name (concat " of " name))))) ((eq type 'comment) "Comment") ((eq type 'vanilla) "Command") ((eq type 'pbp) "PBP command") ((eq type 'proverproc) "Prover-processed")))) (defvar pg-span-context-menu-keymap (let ((map (make-sparse-keymap "Keymap for context-sensitive menus on spans"))) (define-key map [down-mouse-3] #'pg-span-context-menu) map) "Keymap for the span context menu.") (defun pg-last-output-displayform () "Return displayable form of `proof-shell-last-output'. This is used to annotate the buffer with the result of proof steps." ;; NOTE: Isabelle/Isar used urgent messages (sigh) in its ordinary output. ;; ("Successful attempt..."). This loses here. (if (string= proof-shell-last-output "") "" (let* ((text (proof-shell-strip-output-markup (if (and (boundp 'unicode-tokens-mode) unicode-tokens-mode) (unicode-tokens-encode-str proof-shell-last-output) proof-shell-last-output)))) ;; HACK: for Isabelle which puts ugly leading \n's around proofstate. (if (and (> (length text) 0) (string= (substring text 0 1) "\n")) (setq text (substring text 1))) (if (and (> (length text) 0) (string= (substring text -1) "\n")) (setq text (substring text 0 -1))) text))) (defun pg-set-span-helphighlights (span &optional mouseface face) "Add a daughter help span for SPAN with help message, highlight, actions. The daughter span covers the non whitespace content of the main span. We add the last output (when non-empty) to the hover display, and also as the 'response property on the span. Optional argument MOUSEFACE means use the given face as a mouse highlight face, if it is a face, otherwise, if it is non-nil but not a face, do not add a mouse highlight. In any case, a mouse highlight and tooltip are only set if `proof-output-tooltips' is non-nil. Argument FACE means add 'face property FACE to the span." (let* ((output (pg-last-output-displayform)) (new-start (save-excursion (goto-char (span-start span)) (skip-chars-forward " \n\t") (point))) (new-end (save-excursion (goto-char (span-end span)) (skip-chars-backward " \n\t") (point))) (extended-start (max (1- new-start) (point-min))) (extended-end (min (1+ new-end) (point-max))) (newspan (span-make-modifying-removing-span extended-start extended-end))) (span-set-property span 'pg-helpspan newspan) ; link from parent (span-set-property newspan 'pghelp t) (span-set-property newspan 'response output) (when proof-output-tooltips (span-set-property newspan 'help-echo (if (<= (length output) 2) (pg-span-name span) output))) ;; Here's the message we used to show in minibuffer ;; when pg-show-hints was on: ;; ;; " (" ;; (substitute-command-keys ;; (if (span-property span 'idiom) ;; "with point in region, \\[pg-toggle-visibility] to show/hide; " ;; "\\\\[pg-span-context-menu]")) ;; " for menu)"))) (span-set-property newspan 'keymap pg-span-context-menu-keymap) (if (or (facep mouseface) (setq mouseface (unless mouseface 'proof-mouse-highlight-face))) (when proof-output-tooltips (span-set-property newspan 'mouse-face mouseface))) (if face (span-set-property newspan 'face face)) ;; (span-set-property newspan 'priority 50) )) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Multiple file handling ;; (defun proof-complete-buffer-atomic (buffer) "Ensure BUFFER marked completely processed, completing with a single step. If buffer already contains a locked region, only the remainder of the buffer is closed off atomically (although undo for the initial portion is unlikely to work, the decoration may be worth retaining). This works for buffers which are not in proof scripting mode too, to allow other files loaded by proof assistants to be marked read-only." (with-current-buffer buffer (save-excursion ;; prevent point moving if user viewing file (if (< (proof-unprocessed-begin) (proof-script-end)) (let ((span (span-make (proof-unprocessed-begin) (proof-script-end)))) ;; Reset queue and locked regions. (proof-init-segmentation) ;; End of locked region is always end of buffer (proof-set-locked-end (proof-script-end)) ;; Configure the overlay span (span-set-property span 'type 'proverproc) (pg-set-span-helphighlights span 'nohighlight)))))) ;; Note: desirable to clean odd asymmetry here: we have a nice setting ;; for proof-register-possibly-new-processed-file but something much ;; more complicated for retracting, because we allow a hook function ;; to calculate the new included files list. ;;;###autoload (defun proof-register-possibly-new-processed-file (file &optional informprover noquestions) "Register a possibly new FILE as having been processed by the prover. If INFORMPROVER is non-nil, the proof assistant will be told about this, to co-ordinate with its internal file-management. (Otherwise we assume that it is a message from the proof assistant which triggers this call). In this case, the user will be queried to save some buffers, unless NOQUESTIONS is non-nil. No action is taken if the file is already registered. A warning message is issued if the register request came from the proof assistant and Emacs has a modified buffer visiting the file." (let* ((cfile (file-truename file)) (buffer (find-buffer-visiting cfile))) (proof-debug (concat "Registering file " cfile (if (member cfile proof-included-files-list) " (already registered, no action)." "."))) (unless (member cfile proof-included-files-list) (and buffer (not informprover) (buffer-modified-p buffer) (pg-response-warning (concat "Changes to " (buffer-name buffer) " have not been saved!"))) ;; Add the new file onto the front of the list (setq proof-included-files-list (cons cfile proof-included-files-list)) ;; If the file is loaded into a buffer, make sure it is completely locked (if buffer (proof-complete-buffer-atomic buffer)) ;; Tell the proof assistant, if we should and if we can (if (and informprover proof-shell-inform-file-processed-cmd) (progn (if (and proof-query-file-save-when-activating-scripting (not noquestions)) (unwind-protect (save-some-buffers nil #'proof-query-save-this-buffer-p))) ;; Tell the prover (proof-shell-invisible-command (proof-format-filename proof-shell-inform-file-processed-cmd cfile) 'wait)))))) (defun proof-query-save-this-buffer-p () "Predicate testing whether `save-some-buffers' during scripting should query." (and (eq major-mode proof-mode-for-script) (not (eq (current-buffer) proof-script-buffer)))) (defun proof-inform-prover-file-retracted (rfile) "Send a message to the prover to tell it RFILE has been undone." (cond ((stringp proof-shell-inform-file-retracted-cmd) (proof-shell-invisible-command (proof-format-filename proof-shell-inform-file-retracted-cmd rfile) 'wait)) ;; If it's a function it might not actually be informing the prover at all, ;; but merely cleans up proof-included-files-list by its own magic. We ;; do the same thing as in proof-shell.el. ;; FIXME: clean and amalgamate this code. ((functionp proof-shell-inform-file-retracted-cmd) (let ((current-included proof-included-files-list)) (funcall proof-shell-inform-file-retracted-cmd rfile) (proof-restart-buffers (proof-files-to-buffers (cl-set-difference current-included proof-included-files-list))))))) (defun proof-auto-retract-dependencies (cfile &optional informprover) "Perhaps automatically retract the (linear) dependencies of CFILE. If `proof-auto-multiple-files' is nil, no action is taken. If CFILE does not appear on `proof-included-files-list', no action taken. Any buffers which are visiting files in `proof-included-files-list' before CFILE are retracted using `proof-protected-process-or-retract'. They are retracted in reverse order. Since the `proof-included-files-list' is examined, we expect scripting to be turned off before calling here (because turning it off could otherwise change `proof-included-files-list'). If INFORMPROVER is non-nil, the proof assistant will be told about this, using `proof-shell-inform-file-retracted-cmd', to co-ordinate with its internal file-management. Files which are not visited by any buffer are not retracted, on the basis that we may not have the information necessary to retract them -- spans that cover the buffer with definition/declaration information. A warning message is given for these cases, since it could cause inconsistency problems. NB! Retraction can cause recursive calls of this function. This is a subroutine for `proof-unregister-buffer-file-name'." (if proof-auto-multiple-files (let ((depfiles (reverse (cdr-safe (member cfile (reverse proof-included-files-list))))) rfile rbuf) (while (setq rfile (car-safe depfiles)) ;; If there's a buffer visiting a dependent file, retract it. ;; We test that the file to retract hasn't been retracted ;; already by a recursive call here. (But since we do retraction ;; in reverse order, this shouldn't happen...) (if (and (member rfile proof-included-files-list) (setq rbuf (find-buffer-visiting rfile))) (progn (proof-debug "Automatically retracting " rfile) (proof-protected-process-or-retract 'retract rbuf) (setq proof-included-files-list (delete rfile proof-included-files-list)) ;; Tell the proof assistant, if we should and we can. ;; This may be useful if we synchronise the *prover* with ;; PG's management of multiple files. If the *prover* ;; informs PG (better case), then we hope the prover will ;; retract dependent files and we shouldn't use this ;; degenerate (linear dependency) code. (if informprover (proof-inform-prover-file-retracted rfile))) ;; If no buffer available, issue a warning that nothing was done (pg-response-warning "Not retracting unvisited file " rfile)) (setq depfiles (cdr depfiles)))))) (defun proof-unregister-buffer-file-name (&optional informprover) "Remove current buffer's filename from the list of included files. No effect if the current buffer has no file name. If INFORMPROVER is non-nil, the proof assistant will be told about this, using `proof-shell-inform-file-retracted-cmd', to co-ordinate with its internal file-management. If `proof-auto-multiple-files' is non-nil, any buffers on `proof-included-files-list' before this one will be automatically retracted using `proof-auto-retract-dependencies'." (if buffer-file-name (let ((cfile (file-truename (or buffer-file-name proof-script-buffer-file-name)))) (proof-debug (concat "Unregistering file " cfile (if (not (member cfile proof-included-files-list)) " (not registered, no action)." "."))) (if (member cfile proof-included-files-list) (progn (proof-auto-retract-dependencies cfile informprover) (setq proof-included-files-list (delete cfile proof-included-files-list)) ;; If we're not allowed to undo into a processed ;; file, we had better remove all the history. (if proof-cannot-reopen-processed-files (proof-restart-buffers (list (current-buffer)))) ;; Tell the proof assistant, if we should and we can. ;; This case may be useful if there is a combined ;; management of multiple files between PG and prover. (if informprover (proof-inform-prover-file-retracted cfile))))))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Activating and Deactivating Scripting ;; ;; The notion of "active scripting buffer" clarifies how ;; scripting across multiple files is handled. Only one ;; script buffer is allowed to be active, and actions are ;; taken when scripting is turned off/on. ;; (defsubst proof-action-completed (action) (or (and (eq action 'retract) (proof-locked-region-empty-p)) (and (eq action 'process) (proof-locked-region-full-p)))) (defun proof-protected-process-or-retract (action &optional buffer) "If ACTION='process, process, If ACTION='retract, retract. Process or retract the current buffer, which should be the active scripting buffer, according to ACTION. Retract buffer BUFFER if set, otherwise use the current buffer. Gives a message in the minibuffer and busy-waits for the retraction or processing to complete. If it fails for some reason, an error is signalled here." (unless (or (eq action 'process) (eq action 'retract)) (error "Invalid argument (in proof-protected-process-or-retract)")) (let ((buf (or buffer (current-buffer)))) (with-current-buffer buf (unless (proof-action-completed action) (let ((fn (cond ((eq action 'process) 'proof-process-buffer) ((eq action 'retract) 'proof-retract-buffer))) (name (cond ((eq action 'process) "Processing") ((eq action 'retract) "Retracting")))) (unwind-protect (progn (message "%s buffer %s..." name buf) (funcall fn) (proof-shell-wait) ; busy wait (message "%s buffer %s...done." name buf) (sit-for 0)) ;; Test to see if action was successful (unless (proof-action-completed action) (error "%s of %s failed!" name buf)))))))) (defun proof-deactivate-scripting-auto () "Deactivate scripting without asking questions or raising errors. If the locked region is full, register the file as processed. Otherwise retract it. Errors are ignored" (ignore-errors (proof-deactivate-scripting (proof-with-script-buffer (if (proof-locked-region-full-p) 'process 'retract))))) (defun proof-deactivate-scripting-query-user-action () "Display the script and query the user for a deactivate action. Returns 'retract, 'process or finally nil if user declined." ;; Would be nicer to ask a single question, but ;; a nuisance to define our own dialogue since it ;; doesn't really fit with one of the standard ones. (save-window-excursion (unless ;; Test to see whether to display the buffer or not. Could ;; have user option here to avoid switching or maybe borrow ;; similar standard setting ;; save-some-buffers-query-display-buffer (or (eq (current-buffer) (window-buffer (selected-window))) (eq (selected-window) (minibuffer-window))) (unless (one-window-p) (delete-other-windows)) (switch-to-buffer proof-script-buffer t)) (let ((action (cond ((y-or-n-p (format "Scripting incomplete in buffer %s, retract? " proof-script-buffer)) 'retract) ((and (not proof-no-fully-processed-buffer) (y-or-n-p (format "Completely process buffer %s instead? " proof-script-buffer))) 'process)))) (or action (progn ;; Give an acknowledgement to user's choice ;; neither to assert or retract. (message "Scripting still active in %s" proof-script-buffer) ;; Delay because this can be followed by an error ;; message in proof-activate-scripting when trying ;; to switch to another scripting buffer. (sit-for 1) nil))))) (defun proof-deactivate-scripting-choose-action () "Select a deactivation action, 'process, 'retract or nil." (let ((auto-action (if (and proof-no-fully-processed-buffer (eq proof-auto-action-when-deactivating-scripting 'process)) nil proof-auto-action-when-deactivating-scripting))) (or auto-action (proof-deactivate-scripting-query-user-action)))) (defun proof-deactivate-scripting (&optional forcedaction) "Try to deactivate scripting for the active scripting buffer. Aims to set `proof-script-buffer' to nil and turn off the modeline indicator. No action is required there is no active scripting buffer. We make sure that the active scripting buffer either has no locked region or a full locked region (everything in it has been processed). If this is not already the case, we question the user whether to retract or assert, or automatically take the action indicated in the user option `proof-auto-action-when-deactivating-scripting'. If `proof-no-fully-processed-buffer' is t there is only the choice to fully retract the active scripting buffer. In this case the active scripting buffer is retracted even if it was fully processed. Setting `proof-auto-action-when-deactivating-scripting' to 'process is ignored in this case. If the scripting buffer is (or has become) fully processed, and it is associated with a file, it is registered on `proof-included-files-list'. Conversely, if it is (or has become) empty, we make sure that it is *not* registered. This is to be certain that the included files list behaves as we might expect with respect to the active scripting buffer, in an attempt to harmonize mixed scripting and file reading in the prover. This function either succeeds, fails because the user refused to process or retract a partly finished buffer, or gives an error message because retraction or processing failed. If this function succeeds, then `proof-script-buffer' is nil afterwards. The optional argument FORCEDACTION overrides the user option `proof-auto-action-when-deactivating-scripting' and prevents questioning the user. It is used to make a value for the `kill-buffer-hook' for scripting buffers, so that when a scripting buffer is killed it is always retracted." (interactive) (proof-with-current-buffer-if-exists proof-script-buffer ;; Examine buffer. ;; We must ensure that the locked region is either empty or full, ;; to make sense for multiple-file scripting. (A proof assistant ;; won't be able to process just part of a file typically; moreover ;; switching between buffers during a proof makes no sense.) (let* ((complete (or (proof-locked-region-empty-p) (and (not proof-no-fully-processed-buffer) (proof-locked-region-full-p)))) (action (unless complete (or forcedaction (proof-deactivate-scripting-choose-action))))) (if action (proof-protected-process-or-retract action)) (unless (and (not complete) (not action)) ;; If we get here, then the locked region is (now) either ;; completely empty or completely full. ;; We can immediately indicate that there is no active ;; scripting buffer (setq proof-previous-script-buffer proof-script-buffer) (setq proof-script-buffer nil) (if (proof-locked-region-full-p) ;; If locked region is full, make sure that this buffer ;; is registered on the included files list, and ;; let the prover know it can consider it processed. (if (or buffer-file-name proof-script-buffer-file-name) (proof-register-possibly-new-processed-file (or buffer-file-name proof-script-buffer-file-name) 'tell-the-prover forcedaction))) (if (proof-locked-region-empty-p) ;; If locked region is empty, make sure this buffer is ;; *off* the included files list. ;; FIXME: probably this isn't necessary: the ;; file should be unregistered by the retract ;; action, or in any case since it was only ;; partly processed. ;; FIXME 2: be careful about automatic ;; multiple file handling here, since it calls ;; for activating scripting elsewhere. ;; We move the onus on unregistering now to ;; the activate-scripting action. (proof-unregister-buffer-file-name)) ;; Turn off Scripting indicator here. (setq proof-active-buffer-fake-minor-mode nil) (force-mode-line-update) ;; Finally, run hooks (run-hooks 'proof-deactivate-scripting-hook))))) (defun proof-activate-scripting (&optional nosaves queuemode) "Ready prover and activate scripting for the current script buffer. The current buffer is prepared for scripting. No changes are necessary if it is already in Scripting minor mode. Otherwise, it will become the new active scripting buffer, provided scripting can be switched off in the previous active scripting buffer with `proof-deactivate-scripting'. Activating a new script buffer is a good time to ask if the user wants to save some buffers; this is done if the user option `proof-query-file-save-when-activating-scripting' is set and provided the optional argument NOSAVES is non-nil. The optional argument QUEUEMODE relaxes the test for a busy proof shell to allow one which has mode QUEUEMODE. In all other cases, a proof shell busy error is given. Finally, the hooks `proof-activate-scripting-hook' are run. This can be a useful place to configure the proof assistant for scripting in a particular file, for example, loading the correct theory, or whatever. If the hooks issue commands to the proof assistant (via `proof-shell-invisible-command') which result in an error, the activation is considered to have failed and an error is given." (interactive) (unless (eq proof-buffer-type 'script) (error "Must be running in a script buffer!")) (unless (equal (current-buffer) proof-script-buffer) ;; TODO: narrow the scope of this save-excursion. ;; Where is it needed? Maybe hook functions. (save-excursion ;; If there's another buffer currently active, we need to ;; deactivate it (also fixing up the included files list). (when proof-script-buffer (proof-deactivate-scripting) ;; Test whether deactivation worked (if proof-script-buffer (error "You cannot have more than one active scripting buffer!"))) ;; Ensure this buffer is off the included files list. If we ;; re-activate scripting in an already completed buffer, the ;; proof assistant may need to retract some dependencies. (proof-unregister-buffer-file-name 'tell-the-prover) ;; If automatic retraction happened in the above step, we may ;; have inadvertently activated scripting somewhere else. ;; Better turn it off again. This should succeed trivially. ;; NB: it seems that we could move the first test for an already ;; active buffer here, but it is more subtle: the first ;; deactivation can extend the proof-included-files list, which ;; would affect what retraction was done in ;; proof-unregister-buffer-file-name. (if proof-script-buffer (proof-deactivate-scripting)) (cl-assert (null proof-script-buffer) "Bug in proof-activate-scripting: deactivate failed.") ;; Set the active scripting buffer (setq proof-script-buffer (current-buffer)) ;; Fire up the prover (or check it's going the right way). (condition-case-unless-debug err (proof-shell-ready-prover queuemode) (error (setq proof-script-buffer nil) (signal (car err) (cdr err)))) ;; Initialise regions (if (proof-locked-region-empty-p) ; leave alone if non-empty (proof-init-segmentation)) ;; Turn on the minor mode, make it show up. (setq proof-active-buffer-fake-minor-mode t) (force-mode-line-update) ;; A good time to ask if the user wants to save some buffers ;; (idea being they may be included in imports at top of new buffer). (if (and proof-query-file-save-when-activating-scripting (not nosaves)) (save-some-buffers nil #'proof-query-save-this-buffer-p)) ;; Run hooks with a variable which suggests whether or not to ;; block. NB: The hook function may send commands to the ;; process which will re-enter this function, but should exit ;; immediately because scripting has been turned on now. (when proof-activate-scripting-hook (defvar activated-interactively) (let ((activated-interactively (called-interactively-p 'any))) (setq proof-shell-last-output-kind nil) (run-hooks 'proof-activate-scripting-hook) ;; If activate scripting functions caused an error, ;; prevent switching to another buffer. Might be better ;; to leave to specific instances, or simply run the hooks ;; as the last step before turning on scripting properly. (when (or (eq 'error proof-shell-last-output-kind) (eq 'interrupt proof-shell-last-output-kind)) (proof-deactivate-scripting) ;; turn off again! ;; Give an error to prevent further actions. (error "Scripting not activated because of error or interrupt"))))))) (defun proof-toggle-active-scripting (&optional arg) "Toggle active scripting mode in the current buffer. With ARG, turn on scripting iff ARG is positive." (interactive "P") (if (if (null arg) (not (eq proof-script-buffer (current-buffer))) (> (prefix-numeric-value arg) 0)) (progn (if proof-script-buffer ;; deactivate elsewhere first (call-interactively 'proof-deactivate-scripting)) (call-interactively 'proof-activate-scripting)) (call-interactively 'proof-deactivate-scripting))) ;; ;; End of activating and deactivating scripting section ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Processing the script management queue -- PART 1: "advancing" ;; ;; The proof-action-list contains a list of (span,command,action) ;; triples. The loop looks like: Execute the command, and if it's ;; successful, do action on span. If the command's not successful, we ;; bounce the rest of the queue and do some error processing. ;; ;; When a span has been processed, it is classified as ;; 'comment, 'goalsave, 'vanilla, etc. ;; ;; The main function for dealing with processed spans is ;; `proof-done-advancing' (defun proof-done-advancing (span) "The callback function for `assert-until-point'. Argument SPAN has just been processed. This is the callback for all the normal commands. Besides stuff that is not yet documented here, this function - extends the locked region - creates additional spans (without 'type property) for help, tooltips, color and menus - merges spans with 'type as needed to achieve atomic undo for proofs and sections - enters some commands and their spans in some database (with for me unknown purpose)" (let ((end (span-end span)) (cmd (span-property span 'cmd))) (proof-set-locked-end end) (if (span-live-p proof-queue-span) (proof-set-queue-start end)) (run-hooks 'proof-state-change-pre-hook) (cond ;; CASE 1: Comments just get highlighted ((eq (span-property span 'type) 'comment) (proof-done-advancing-comment span)) ;; CASE 2: Save command seen, now we may amalgamate spans. ((and (proof-string-match-safe proof-save-command-regexp cmd) (funcall proof-really-save-command-p span cmd) (cl-decf proof-nesting-depth) ;; [always non-nil/true] (if proof-nested-goals-history-p ;; For now, we only support this nesting behaviour: ;; don't amalgamate unless the nesting depth is 0, ;; i.e. we're in a top-level proof. ;; This assumes prover keeps history for nested proofs. ;; (was true for Isabelle/Isar). (eq proof-nesting-depth 0) t)) (proof-done-advancing-save span)) ;; CASE 3: Proof completed one step or more ago, non-save ;; command seen, no nested goals allowed. ;; ;; AFAICT case 3 is never taken for Coq. ;; ;; We make a fake goal-save from any previous ;; goal to the command before the present one. ;; ;; This allows smooth undoing in proofs which have no "qed" ;; statements. If your proof assistant doesn't allow these ;; "unclosed" proofs, then you can safely set ;; proof-completed-proof-behaviour. ((and proof-shell-proof-completed (or (and (eq proof-completed-proof-behaviour 'extend) (>= proof-shell-proof-completed 0)) (and (eq proof-completed-proof-behaviour 'closeany) (> proof-shell-proof-completed 0)) (and (eq proof-completed-proof-behaviour 'closegoal) (funcall proof-goal-command-p span)))) (proof-done-advancing-autosave span)) ;; CASE 4: A "Require" type of command is seen (Coq). ;; Case 4 has been flushed, because its functionality has been ;; superseeded by the new auto-compilation feature for Coq. ;; CASE 5: Some other kind of command (or a nested goal). (t (proof-done-advancing-other span))) ;; Add the processed command to the input ring (unless (or (not (span-live-p span)) (eq (span-property span 'type) 'comment)) (pg-add-to-input-history cmd))) ;; Finally: state of scripting may have changed now, run hooks. (run-hooks 'proof-state-change-hook)) (defun proof-done-advancing-comment (span) "A subroutine of `proof-done-advancing'. Add comment element for SPAN." ;; Add an element for a new span, which should span ;; the text of the comment. ;; FIXME: might be better to use regexps/skip spaces for matching ;; start/end of comments, rather than comment-start and ;; comment-end skip (which assumes comments are nicely formatted). ;; (let ((bodyspan (span-make (+ (length comment-start) (span-start span)) (- (span-end span) (max 1 (length comment-end))))) (id (proof-next-element-id 'comment))) (pg-add-element 'comment id bodyspan) (span-set-property span 'id (intern id)) (span-set-property span 'idiom 'comment) (let ((proof-shell-last-output "")) ; comments not sent, no last output (pg-set-span-helphighlights bodyspan)))) (defun proof-done-advancing-save (span) "Retire commands that close a proof or some other region. This is a subroutine of `proof-done-advancing'. Besides stuff that is not yet documented here, this function - creates additional spans (without 'type property) for help, tooltips, color and menus - in particular, adds the background color for omitted proofs - merges spans with 'type as needed to achieve atomic undo for proofs and sections; for Coq this is done at least for proofs and sections. - enters some commands and their spans in some database (with for me unknown purpose)" (unless (or (eq proof-shell-proof-completed 1) ;; (eq proof-assistant-symbol 'isar) ) ;; We expect saves to succeed only for recently completed top-level proofs. ;; NB: Wasn't true in Isar, because save commands could perform proof. ;; Note: not true in Coq either, if there is a command (eg. a Check) ;; between the tactic that finished the proof and the Qed. (proof-debug (format "PG: save command with proof-shell-proof-completed=%s, proof-nesting-depth=%s" proof-shell-proof-completed proof-nesting-depth))) (setq proof-shell-proof-completed nil) ;; FIXME: need subroutine here: (let ((gspan span) ; putative goal span (savestart (span-start span)) (saveend (span-end span)) (cmd (span-property span 'cmd)) ;; With the omit proofs feature (see ;; `proof-omit-proofs-configured'), the span of the Admitted ;; command that replaces the proof contains an ;; 'omitted-proof-region property, that holds the start and ;; end of the omitted proof for colouring. The property is ;; only inserted for omitted proofs in the replacing Admitted. (omitted-proof-region (span-property span 'omitted-proof-region)) lev nestedundos nam next) (and proof-save-with-hole-regexp (proof-string-match proof-save-with-hole-regexp cmd) ;; Give a message of a name if one can be determined (proof-minibuffer-message (format "proved %s" (setq nam (if (stringp proof-save-with-hole-result) (replace-match proof-save-with-hole-result nil nil cmd) (match-string proof-save-with-hole-result cmd)))))) ;; Search back for a goal command, deleting spans along the way: ;; they may be amalgamated into a single goal-save region, which ;; corresponds to the prover discarding the proof history. (setq lev 1) (setq nestedundos 0) (while (and gspan (> lev 0)) (setq next (prev-span gspan 'type)) (unless proof-arbitrary-undo-positions (span-delete gspan)) (setq gspan next) (if gspan (progn (setq cmd (span-property gspan 'cmd)) (cond ;; Ignore comments [may have null cmd setting] ((eq (span-property gspan 'type) 'comment)) ;; Nested goal saves: add in any nestedcmds ((eq (span-property gspan 'type) 'goalsave) (setq nestedundos (+ nestedundos 1 (or (span-property gspan 'nestedundos) 0)))) ;; Increment depth for a nested save, in case ;; prover supports history of nested proofs ((and proof-nested-goals-history-p proof-save-command-regexp (proof-string-match proof-save-command-regexp cmd)) (cl-incf lev)) ;; Decrement depth when a goal is hit ((funcall proof-goal-command-p gspan) (cl-decf lev)) ;; Remainder cases: see if command matches something we ;; should count for a global undo ((and proof-nested-undo-regexp (proof-string-match proof-nested-undo-regexp cmd)) (cl-incf nestedundos)) )))) (if (not gspan) ;; No goal span found! Issue a warning and do nothing more. (pg-response-warning "Proof General: script management confused, couldn't find goal span for save.") ;; If the name isn't set, try to set it from the goal, or as a ;; final desparate attempt, set the name to ;; proof-unnamed-theorem-name (Coq uses a default name for ;; unnamed theorems, believe it or not, and issues a ;; name-binding error for two unnamed theorems in a row!). (setq nam (or nam (proof-get-name-from-goal gspan) proof-unnamed-theorem-name)) (proof-make-goalsave gspan (span-end gspan) savestart saveend nam nestedundos) ;; In case SPAN (which is retired now) belongs to an admit ;; command that closes an omitted proof: create an additional ;; span for the different background color of the omitted span. ;; Start and end point of this span has been computed before in ;; `proof-script-omit-proofs'. This background color span is ;; registered in the span of the goal command for the only ;; reason to not leave it dangling around. (when omitted-proof-region (let ((omit-span (span-make (car omitted-proof-region) (cadr omitted-proof-region)))) (span-set-property omit-span 'face 'proof-omitted-proof-face) (span-set-property omit-span 'omitted-proof-span t) (span-set-property gspan 'omit-color-span omit-span))) ;; *** Theorem dependencies *** (if proof-last-theorem-dependencies (proof-depends-process-dependencies nam gspan))))) (defun proof-make-goalsave (gspan goalend savestart saveend nam &optional nestedundos) "Make new goal-save span, using GSPAN. Subroutine of `proof-done-advancing-save'. Argument GOALEND is the end of the goal." (unless proof-arbitrary-undo-positions (span-set-end gspan saveend) (span-set-property gspan 'type 'goalsave)) (span-set-property gspan 'idiom 'proof);; links to nested proof element (span-set-property gspan 'name nam) (and nestedundos (span-set-property gspan 'nestedundos nestedundos)) (pg-set-span-helphighlights gspan proof-region-mouse-highlight-face) ;; Now make a nested span covering the purported body of the proof, ;; and add to buffer-local list of elements. (let ((proofbodyspan (span-make goalend (if proof-script-integral-proofs saveend savestart)))) (pg-add-proof-element nam proofbodyspan gspan))) (defun proof-get-name-from-goal (gspan) "Try to return a goal name from GSPAN. Subroutine of `proof-done-advancing-save'." (let ((cmdstr (span-property gspan 'cmd))) (and proof-goal-with-hole-regexp (proof-string-match proof-goal-with-hole-regexp cmdstr) (if (stringp proof-goal-with-hole-result) (replace-match proof-goal-with-hole-result nil nil cmdstr) (match-string proof-goal-with-hole-result cmdstr))))) ;; FIXME: this next function should be more like proof-done-advancing-save, ;; perhaps simplifying the proof-completed-proof-behaviour functionality, ;; which isn't seriously used in any prover. At the moment the behaviour ;; here is incomplete compared with proof-done-advancing-save. ;; NB: in this function we assume non-nested proofs, which explains ;; some of the logic. There is no attempt to fix up proof-nesting-depth. ;; NB: 'extend behaviour is not currently compatible with appearance of ;; save commands, since proof-done-advancing-save allow for goalspan ;; already existing. (defun proof-done-advancing-autosave (span) "A subroutine of `proof-done-advancing'." ;; In the extend case, the context of proof grows until hit a save ;; or new goal. (if (eq proof-completed-proof-behaviour 'extend) (cl-incf proof-shell-proof-completed) (setq proof-shell-proof-completed nil)) (let* ((swallow (eq proof-completed-proof-behaviour 'extend)) (gspan (if swallow span (prev-span span 'type))) (newend (if swallow (span-end span) (span-start span))) (cmd (span-property span 'cmd)) (newgoal (funcall proof-goal-command-p span)) nam hitsave dels ncmd) ;; Search backwards to see if we can find a previous goal ;; before a save or the start of the buffer. ;; FIXME: this should really do the work done in ;; proof-done-advancing-save above, too, with nested undos, etc. (while ;; big ugly condition (and gspan (or (eq (span-property gspan 'type) 'comment) (and (setq ncmd (span-property gspan 'cmd)) (setq cmd ncmd) ; dynamic scope for funcall below (not (funcall proof-goal-command-p gspan)) (not (and proof-save-command-regexp (proof-string-match proof-save-command-regexp cmd) (funcall proof-really-save-command-p span cmd) (setq hitsave t)))))) (setq dels (cons gspan dels)) (setq gspan (prev-span gspan 'type))) (cond ((or hitsave (null gspan)) (proof-debug "Proof General strangeness: unclosed proof completed, but couldn't find its start!") (pg-set-span-helphighlights span)) ((and swallow newgoal) ;; If extending the region, goalsave already there; just highlight new region (setq proof-shell-proof-completed nil) (pg-set-span-helphighlights span)) (t ;; If, search back through spans, we haven't hit a save or the ;; start of the buffer, we make a fake goal-save region. ;; Delete spans between the previous goal and new command (mapc #'span-delete dels) ;; Try to set the name from the goal... [as above] (setq nam (or (proof-get-name-from-goal gspan) proof-unnamed-theorem-name)) ;; NB: if extending an already closed region, ought to delete ;; the body and extend that too: currently we make multiple nested ;; bodies, a bit messy. ;; (NB: savestart used for nested region: here use saveend) (proof-make-goalsave gspan (+ (span-start gspan) (length (or (span-property-safe gspan 'cmd)))) newend newend nam))))) (defun proof-done-advancing-other (span) (let ((bodyspan span) ;; might take subscript after first word/line (id (proof-next-element-id 'command))) ;; Hidable regions for commands: the problem is that they have no ;; natural surrounding region, so makes it difficult to define a ;; region for revealing again. (cond ((funcall proof-goal-command-p span) (pg-add-element 'statement id bodyspan) (cl-incf proof-nesting-depth)) (t (pg-add-element 'command id bodyspan))) (if proof-shell-proof-completed (cl-incf proof-shell-proof-completed)) (pg-set-span-helphighlights span proof-command-mouse-highlight-face))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Parsing functions for parsing commands in script ;; ;; Command parsing is suprisingly subtle with various possibilities of ;; command syntax (terminated, not terminated, or lisp-style), whether ;; or not PG silently ignores comments, etc. (defun proof-segment-up-to-parser (pos &optional _next-command-end) "Parse the script buffer from end of queue/locked region to POS. This partitions the script buffer into contiguous regions, classifying them by type. Return a list of lists of the form \(TYPE TEXT ENDPOS) where: TYPE is a symbol indicating the type of text found, either 'cmd or 'comment; TEXT is the string content taken from the buffer; ENDPOS is the position of the final character of the text. The behaviour around comments is set by `proof-script-fly-past-comments', which see. This version is used when `proof-script-parse-function' is set, to the function which parses the script segment by segment." (save-excursion (let* ((start (goto-char (proof-queue-or-locked-end))) (cur (1- start)) (seg t) prevtype realstart cmdseen segs) ;; Keep parsing until: ;; - we fail to find a segment (seg = nil) ;; - we go beyond the stop point (cur >= end) ;; - unless we're flying past comments, in which case ;; wait for a command (cmdseen<>nil) (while (and seg (or (< cur pos) (and proof-script-fly-past-comments (not cmdseen)))) ;; Skip whitespace before this element (skip-chars-forward " \t\n") (setq realstart (point)) (let* ((type (funcall proof-script-parse-function))) (setq seg nil) (cond ((eq type 'comment) (setq seg (list 'comment "" (point)))) ((eq type 'cmd) (setq cmdseen t) (setq seg (list 'cmd (buffer-substring-no-properties realstart (point)) (point)))) ((null type)) ; nothing left in buffer (t (error "Proof-segment-up-to-parser: bad TYPE value from proof-script-parse-function"))) ;; (if seg (progn ;; Add the new segment, coalescing comments if the ;; user likes it that way. I first made coalescing a ;; separate configuration option, but it works well ;; used in tandem with the fly-past behaviour. (setq segs (cons seg (if (and proof-script-fly-past-comments (eq type 'comment) (eq prevtype 'comment)) (cdr segs) segs))) ;; Update state (setq cur (point)) (setq prevtype type))))) ;; Return segment list segs))) (defun proof-script-generic-parse-find-comment-end () "Find the end of the comment point is at the start of. Nil if not found." (let ((notout t)) ;; Find end of comment (NB: doesn't undertand nested comments) (while (and notout (re-search-forward proof-script-comment-end-regexp nil 'movetolimit)) (setq notout (proof-buffer-syntactic-context))) (not (proof-buffer-syntactic-context)))) (defun proof-script-generic-parse-cmdend () "For `proof-script-parse-function' if `proof-script-command-end-regexp' set." (if (looking-at proof-script-comment-start-regexp) ;; Handle comments (if (proof-script-generic-parse-find-comment-end) 'comment) ;; Handle non-comments: assumed to be commands (let (foundend) ;; Find end of command (while (and (setq foundend (progn (and (re-search-forward proof-script-command-end-regexp nil t) (or (match-beginning 1) ;; optional start of white space (match-end 0))))) (proof-buffer-syntactic-context)) ;; inside a string or comment before the command end ) (if (and foundend (goto-char foundend) ; move to command end (not (proof-buffer-syntactic-context))) ;; Found command end outside string/comment 'cmd ;; Didn't find command end nil)))) ;; This was added for the fine-grained command structure of Isar ;; ;; It more involved than the case of just scanning for command end; we ;; have to find two successive command starts and go backwards from ;; the second. This coalesces comments following commands with ;; commands themselves, and sends them to the prover (only case where ;; it does). It's needed particularly for Isar's text command (text ;; {* foo *}) so we can define the buffer syntax for text as comment. ;; ;; To avoid doing that, we would need to scan also for comments but ;; it would be difficult to distinguish between: ;; complete command (* that's it *) ;; and ;; complete (* almost *) command ;; ;; Maybe the second case should be disallowed in command-start regexp ;; case? ;; ;; Another improvement idea might be to take into account both ;; command starts *and* ends, but let's leave that for another day. ;; ;; NB: proof-script-comment-start-regexp doesn't need to be the same ;; as (reqexp-quote comment-start). ;; (defun proof-script-generic-parse-cmdstart () "For `proof-script-parse-function' if `proof-script-command-start-regexp' is set." (let ((case-fold-search proof-case-fold-search)) (if (looking-at proof-script-comment-start-regexp) ;; Find end of comment (if (proof-script-generic-parse-find-comment-end) 'comment) ;; Handle non-comments: assumed to be commands (when (looking-at proof-script-command-start-regexp) ;; We've got at least the beginnings of a command, skip past it (goto-char (match-end 0)) (let (foundstart) ;; Find next command start (while (and (setq foundstart (and (re-search-forward proof-script-command-start-regexp nil 'movetolimit) (and (match-beginning 0) ;; jiggery pokery here is to move outside a ;; comment in case a comment start is considered to ;; be a command start (for non fly-past behaviour) (goto-char (match-beginning 0))))) (proof-buffer-syntactic-context) (goto-char (1+ (point)))) ;; loop while in a string/comment before the next command start ) (unless (proof-buffer-syntactic-context) ; not inside a comment/string (cond (foundstart ; found a second command start (goto-char foundstart) ; beginning of command start (skip-chars-backward " \t\n") ; end of previous command 'cmd) ((eq (point) (point-max)) ; At the end of the buffer (skip-chars-backward " \t\n") ; benefit of the doubt, let 'cmd))) ; the PA moan if it's incomplete ;; Return nil otherwise, no complete command found ))))) (defun proof-script-generic-parse-sexp () "Used for `proof-script-parse-function' if `proof-script-sexp-commands' is set." ;; Usual treatment of comments (if (looking-at proof-script-comment-start-regexp) ;; Find end of comment (if (proof-script-generic-parse-find-comment-end) 'comment) (let* ((parse-sexp-ignore-comments t) ; gobble comments into commands (end (scan-sexps (point) 1))) (if end (progn (goto-char end) 'cmd))))) (defun proof-semis-to-vanillas (semis &optional queueflags) "Create vanilla spans for SEMIS and a list for the queue. Proof terminator positions SEMIS has the form returned by the function `proof-segment-up-to'. The argument list is destroyed. The callback in each queue element is `proof-done-advancing'. If the variable `proof-script-preprocess' is set (to the name of a function), call that function to construct the first element of each queue item. The optional QUEUEFLAGS are added to each queue item." (let ((start (proof-queue-or-locked-end)) (file (or (buffer-file-name) (buffer-name))) (cb 'proof-done-advancing) span alist end) (setq semis (nreverse semis)) (save-match-data (dolist (semi semis) (setq end (nth 2 semi)) (setq span (span-make start end)) (if (eq (car semi) 'cmd) (progn ;; command span (let* ((cmd (nth 1 semi)) (qcmd (if proof-script-preprocess (funcall proof-script-preprocess file ;; ignore spaces at start of command (+ start (save-excursion (goto-char start) (skip-chars-forward " \t\n"))) end cmd) (list cmd))) (qitem (list span qcmd cb queueflags))) (span-set-property span 'type 'vanilla) (span-set-property span 'cmd cmd) (setq alist (cons qitem alist)))) ;; ignored text (let ((qitem (list span nil cb queueflags))) ; nil was `proof-no-command' (span-set-property span 'type 'comment) (setq alist (cons qitem alist)))) (setq start end))) (nreverse alist))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Moving point in proof script buffer ;; (defun proof-next-command-new-line () "Return non-nil if next command should start a new line." (or proof-next-command-on-new-line ; pg-vars (with-no-warnings (proof-ass one-command-per-line)))) (defun proof-script-next-command-advance () "Move point to the beginning of the next command if it's nearby. Assumes that point is at the end of a command." (interactive) (skip-chars-forward " \t") (if (and (eolp) (proof-next-command-new-line)) (forward-line))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Omit proofs feature. ;; ;; See `proof-omit-proofs-configured' for the feature. When the parsed ;; buffer content has been converted to vanilla spans, ;; `proof-script-omit-proofs' searches for complete opaque proofs in ;; there and replaces them with `proof-script-proof-admit-command'. (defun proof-move-over-whitespace-to-next-line (pos) "Return position of next line if one needs only to jump over white space. Utility function. In the current buffer, check if beginning of next line can be reached from POS by moving over white space (spaces, tabs) only. If yes return the beginning of next line, otherwise POS." (save-excursion (goto-char pos) (skip-chars-forward " \t") (setq pos (point)) (if (eolp) (1+ (point)) pos))) (defun proof-script-omit-proofs (vanillas) "Return a copy of VANILLAS with complete opaque proofs omitted. See `proof-omit-proofs-configured' for the description of the omit proofs feature. This function uses `proof-script-proof-start-regexp', `proof-script-proof-end-regexp' and `proof-script-definition-end-regexp' to search for complete opaque proofs in the action list VANILLAS. Complete opaque proofs are replaced by `proof-script-proof-admit-command'. The span of the admit command contains an 'omitted-proof-region property with the region of the omitted proof. This is used in `proof-done-advancing-save' to colour the omitted proof with `proof-omitted-proof-face'. Report an error to the (probably surprised) user if another proof start is found inside a proof." (cl-assert (and proof-omit-proofs-configured proof-script-proof-start-regexp proof-script-proof-end-regexp proof-script-definition-end-regexp proof-script-proof-admit-command) nil "proof-script omit proof feature not properly configured") (let (result maybe-result inside-proof proof-start-span-start proof-start-span-end item cmd) (while vanillas (setq item (car vanillas)) ;; cdr vanillas is at the end of the loop (setq cmd (mapconcat #'identity (nth 1 item) " ")) (if inside-proof (progn (if (string-match proof-script-proof-start-regexp cmd) ;; found another proof start inside a proof ;; stop omitting and pass the remainder unmodified ;; the result in `result' is aggregated in reverse ;; order, need to reverse vanillas (progn (setq result (nconc (nreverse vanillas) maybe-result result)) (setq maybe-result nil) (setq vanillas nil) ;; for Coq nobody will notice the warning, because ;; the error about nested proofs will pop up shortly ;; afterwards (display-warning '(proof-script) ;; use the end of the span, because the start is ;; usually on the preceding line (format (concat "found second proof start at line %d" " - are there nested proofs?") (line-number-at-pos (span-end (car item)))))) (if (string-match proof-script-proof-end-regexp cmd) (let ;; Reuse the Qed span for the whole proof, ;; including the faked Admitted command. ;; `proof-done-advancing' expects such a span. ((cmd-span (car item))) (span-set-property cmd-span 'type 'omitted-proof) (span-set-property cmd-span 'cmd proof-script-proof-admit-command) (span-set-endpoints cmd-span proof-start-span-end (span-end (car item))) ;; Throw away all commands between start of proof ;; and the current point, in particular, delete ;; all the spans. (mapc (lambda (item) (span-detach (car item))) maybe-result) (setq maybe-result nil) ;; Record start and end point for the fancy ;; colored span that marks the skipped proof. The ;; span will be created in ;; `proof-done-advancing-save' when ;; `proof-script-proof-admit-command' is retired. (span-set-property cmd-span 'omitted-proof-region ;; for the start take proper line start if possible (list (proof-move-over-whitespace-to-next-line proof-start-span-start) ;; For the end, don't extend to the end of ;; the line, because then the fancy color ;; span is behind the end of the proof span ;; and will get deleted when undoing just ;; behind that proof. (span-end (car item)))) (push (list cmd-span (list proof-script-proof-admit-command) 'proof-done-advancing nil) result) (setq inside-proof nil)) (if (string-match proof-script-definition-end-regexp cmd) ;; A proof ending in Defined or something similar. ;; Need to keep all commands from the start of the proof. (progn (setq result (cons item (nconc maybe-result result))) (setq maybe-result nil) (setq inside-proof nil)) ;; normal proof command - maybe it belongs to a ;; Defined, keep it separate, until we know. (push item maybe-result))))) ;; outside proof (if (string-match proof-script-proof-start-regexp cmd) (progn (setq maybe-result nil) ;; Keep the Proof using command in any case. (push item result) (setq proof-start-span-start (span-start (car item))) (setq proof-start-span-end (span-end (car item))) (setq inside-proof t)) ;; outside, no proof start - keep it unmodified (push item result))) (setq vanillas (cdr vanillas))) (nreverse (nconc maybe-result result)))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Assert-until-point. ;; ;; This function parses some region of the script buffer into ;; commands, and the adds the commands into the queue. ;; (defun proof-assert-until-point (&optional displayflags) "Process the region from the end of the locked-region until point." (if (proof-only-whitespace-to-locked-region-p) (error "At end of the locked region, nothing to do to!")) (proof-activate-scripting nil 'advancing) (let ((semis (save-excursion (skip-chars-backward " \t\n" (proof-queue-or-locked-end)) (proof-segment-up-to-using-cache (point))))) (if (eq 'unclosed-comment (car semis)) (setq semis (cdr semis))) (if (null semis) ; maybe inside a string or something. (error "I can't find any complete commands to process!")) (run-hooks 'proof-assert-command-hook) ;; sneak commands (real ones with a prompt) (proof-assert-semis semis displayflags))) (defun proof-assert-electric-terminator () "Insert the proof command terminator, and assert up to it. This is a little bit clever with placement of semicolons, and will try to avoid duplicating them in the buffer. When used in the locked region (and so with strict read only off), it always defaults to inserting a semi (nicer might be to parse for a comment, and insert or skip to the next semi)." (let ((mrk (point)) (termregexp (regexp-quote proof-terminal-string)) ins nwsp) (if (< mrk (proof-unprocessed-begin)) (insert proof-terminal-string) ; insert immediately in locked region (if (proof-only-whitespace-to-locked-region-p) (error "There's nothing to do!")) (skip-chars-backward " \t\n") (setq nwsp (point)) ; char after first non-whitespace (unless (or proof-electric-terminator-noterminator ;; before the terminal (looking-at termregexp) ;; after the terminal (and (re-search-backward termregexp (proof-unprocessed-begin) t) (goto-char nwsp) (eq (match-end 0) nwsp))) (insert proof-terminal-string) (setq ins t)) (proof-activate-scripting nil 'advancing) (let* ((pos (if proof-electric-terminator-noterminator (1- (point)) (point))) (semis (save-excursion (proof-segment-up-to-using-cache pos)))) (unless semis (error "Can't find a parseable command!")) (when (eq 'unclosed-comment (caar semis)) ;; delete spurious char in comment (if ins (backward-delete-char 1)) (goto-char mrk) (insert proof-terminal-string)) ;; assert the region (proof-assert-semis semis) (proof-script-next-command-advance))))) (defun proof-assert-semis (semis &optional displayflags) "Add to the command queue the list SEMIS of command positions. SEMIS must be a non-empty list, in reverse order (last position first). We assume that the list is contiguous and begins at (proof-queue-or-locked-end). We also delete help spans which appear in the same region (in the expectation that these may be overwritten). This function expects the buffer to be activated for advancing. If the omit proofs feature is active, complete opaque proofs will be omitted from the vanilla action list obtained from SEMIS." (cl-assert semis nil "proof-assert-semis: argument must be a list") (let ((startpos (proof-queue-or-locked-end)) (lastpos (nth 2 (car semis))) (vanillas (proof-semis-to-vanillas semis displayflags))) (proof-script-delete-secondary-spans startpos lastpos) (when (and proof-omit-proofs-option proof-omit-proofs-configured) (setq vanillas (proof-script-omit-proofs vanillas))) (proof-extend-queue lastpos vanillas))) (defvar proof--inhibit-retract-on-change nil) (defun proof-retract-before-change (beg end) "For `before-change-functions'. Retract to BEG unless BEG and END in comment. No effect if prover is busy." (unless (or (<= (proof-queue-or-locked-end) beg) proof--inhibit-retract-on-change (and (proof-inside-comment beg) ;; FIXME: This may mis fire if a change starts in a comment ;; and ends in another but with non-comment code in-between. (proof-inside-comment end))) (when proof-shell-busy (message "Interrupting prover") (proof-interrupt-process) (proof-shell-wait)) (save-excursion (save-match-data ;; see PG#41 (save-restriction ;; see Trac#403 (widen) (goto-char beg) (proof-retract-until-point) (proof-shell-wait)))))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; PBP call-backs ;; (defun proof-insert-pbp-command (cmd) "Insert CMD into the proof queue." (proof-activate-scripting) (let (span) (proof-goto-end-of-locked) (if (proof-next-command-new-line) (insert "\n")) (insert cmd) (setq span (span-make (proof-unprocessed-begin) (point))) (span-set-property span 'type 'pbp) (span-set-property span 'cmd cmd) (proof-start-queue (proof-unprocessed-begin) (point) (list (list span (list cmd) 'proof-done-advancing))))) (defun proof-insert-sendback-command (cmd) "Insert CMD into the proof script, execute assert-until-point." (proof-with-script-buffer (proof-goto-end-of-locked) (insert "\n") ;; could be user opt (insert cmd) (proof-assert-until-point))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Processing the script management queue -- PART 2: retracting ;; ;; Most of the hard work (computing the commands to do the retraction) ;; is implemented in the customisation module (e.g. coq.el), so ;; code here is fairly straightforward. ;; TODO: we need to adjust proof-nesting-depth appropriately here. ;; It would help to know the type of retraction which has just ;; occurred: a kill-proof may be assumed to set nesting depth ;; to zero; an undo sequence may alter it some other way. ;; NB: at the moment, the adjustment is made in the wrong place!! (defun proof-done-retracting (span) "Callback for `proof-retract-until-point'. We update display after proof process has reset its state. See also the documentation for `proof-retract-until-point'. Optionally delete the region corresponding to the proof sequence. After an undo, we clear the proof completed flag. The rationale is that undoing never leaves prover in a \"proof just completed\" state, which is true for some proof assistants (but probably not others)." ;; TODO: need to fixup proof-nesting-depth (setq proof-shell-proof-completed nil) (if (span-live-p span) (let ((start (span-start span)) (end (span-end span)) (killfn (span-property span 'remove-action))) ;; da: check for empty region seems odd here? ;; [prevents regions from being detached in set-locked-end] (unless (proof-locked-region-empty-p) (proof-set-locked-end start) (proof-set-queue-end start)) ;; Try to clean input history (NB: rely on order here) ;; PG 3.7 release: disable this, it's not yet robust. ;; (let ((cmds (spans-at-region-prop start end 'cmd)) ;; (fn (lambda (span) ;; (unless (eq (span-property span 'type) 'comment) ;; (pg-remove-from-input-history ;; (span-property span 'cmd)))))) ;; (mapc fn (reverse cmds))) (proof-script-delete-spans start end) (span-delete span) (if killfn (funcall killfn start end)))) ;; State of scripting may have changed now (run-hooks 'proof-state-change-pre-hook) (run-hooks 'proof-state-change-hook)) (defun proof-setup-retract-action (start end proof-commands remove-action &optional displayflags) "Make span from START to END which corresponds to retraction. Returns retraction action destined for proof shell queue, and make span. Action holds PROOF-COMMANDS and `proof-done-retracting' callback. Span deletion property set to function REMOVE-ACTION. DISPLAYFLAGS control output shown to user, see `proof-action-list'." (let ((span (span-make start end))) (span-set-property span 'remove-action remove-action) (list (list span proof-commands 'proof-done-retracting displayflags)))) (defun proof-last-goal-or-goalsave () "Return the span which is the last goal or save before point." (save-excursion (let ((span (span-at-before (proof-unprocessed-begin) 'type))) (while (and span (not (eq (span-property span 'type) 'goalsave)) (or (eq (span-property span 'type) 'proof) (eq (span-property span 'type) 'comment) (eq (span-property span 'type) 'proverproc) (not (funcall proof-goal-command-p span)))) (setq span (prev-span span 'type))) span))) ;; ;; NB: Should carefully explain/document this behaviour somewhere. ;; The undo is three-phase: ;; undo-cmd - ... - undo-cmd within proof ;; kill proof exit proof ;; forget-to-declaration forget target span ;; ;; It turns out that this behaviour is not quite right for Coq. ;; It might be simpler to just use a single undo/forget ;; command, which is called in all cases. ;; (defun proof-retract-target (target undo-action displayflags) "Retract the span TARGET and apply UNDO-ACTION to undone region if non-nil. Notice that this necessitates retracting any spans following TARGET, up to the end of the locked region. DISPLAYFLAGS control output shown to user, see `proof-action-list'." (let ((end (proof-unprocessed-begin)) (start (span-start target)) (span (if proof-arbitrary-undo-positions target (proof-last-goal-or-goalsave))) actions) ;; NB: first section only entered if proof-kill-goal-command is ;; non-nil. Otherwise we expect proof-find-and-forget-fn to do ;; all relevent work for arbitrary retractions. FIXME: clean up ;; Examine the last span in the locked region. ;; If the last goal or save span is not a proof or ;; prover processed file, we examine to see how to remove it. (if (and span proof-kill-goal-command (not (or (memq (span-property span 'type) '(goalsave proverproc))))) ;; If the goal or goalsave span ends before the target span, ;; then we are retracting within the last unclosed proof, ;; and the retraction just amounts to a number of undo ;; steps. ;; FIXME: really, there shouldn't be more work to do: so ;; why call proof-find-and-forget-fn later? (if (< (span-end span) (span-end target)) (progn ;; Skip comment/non-undoable spans at and immediately following target (setq span target) (while (and span (memq (span-property span 'type) '(comment proverproc))) (setq span (next-span span 'type))) ;; Calculate undos for the current open segment ;; of proof commands (setq actions (proof-setup-retract-action start end (if (null span) nil ; was: proof-no-command (funcall proof-count-undos-fn span)) undo-action) end start)) ;; Otherwise, start the retraction by killing off the ;; currently active goal. ;; FIXME: and couldn't we move the end upwards? ;; FIXME: hack proof-nesting-depth here. This is ;; in the wrong place: it should be done *after* the ;; retraction has succeeded. (setq proof-nesting-depth (1- proof-nesting-depth)) (setq actions (proof-setup-retract-action (span-start span) end (list proof-kill-goal-command) undo-action displayflags) end (span-start span)))) ;; Check the start of the target span lies before the end ;; of the locked region (should always be true since we don't ;; make spans outside the locked region at the moment)... ;; But end may have moved backwards above: this just checks whether ;; there is more retraction to be done. (if (> end start) (setq actions ;; Append a retract action to clear the entire start-end ;; region. Rely on proof-find-and-forget-fn to ;; calculate a command which "forgets" back to the first ;; definition, declaration, or whatever that comes after ;; the target span. (nconc actions (proof-setup-retract-action start end (funcall proof-find-and-forget-fn target) undo-action displayflags)))) (proof-start-queue (min start end) (proof-unprocessed-begin) actions 'retracting))) (defun proof-retract-until-point-interactive (&optional delete-region) "Tell the proof process to retract until point. If invoked outside a locked region, undo the last successfully processed command. If called with a prefix argument (DELETE-REGION non-nil), also delete the retracted region from the proof-script." (interactive "P") (proof-retract-until-point (if delete-region 'kill-region))) (defun proof-retract-until-point (&optional undo-action displayflags) "Set up the proof process for retracting until point. This calculates the commands to undo to the current point within the locked region. If invoked outside the locked region, undo the last successfully processed command. See `proof-retract-target'. After retraction has succeeded in the prover, the filter will call `proof-done-retracting'. If UNDO-ACTION is non-nil, it will then be invoked on the region in the proof script corresponding to the proof command sequence. DISPLAYFLAGS control output shown to user, see `proof-action-list'. Before the retraction is calculated, we enforce the file-level protocol with `proof-activate-scripting'. This has a couple of effects: 1. If the file is completely processed, we have to re-open it for scripting again which may involve retracting other (dependent) files. 2. We may query the user whether to save some buffers. Step 2 may seem odd -- we're undoing (in) the buffer, after all -- but what may happen is that when scripting starts going forward again, we hit a command that loads other files, but the user hasn't saved the latest edits. Therefore it is right to query saves here." (if (proof-locked-region-empty-p) (error "No locked region") (proof-activate-scripting) ;; enforce not busy to avoid retracting items from the queue region, ;; which is not supported currently, see #443 ;; (future: may allow retracting from queue in progress) (proof-shell-ready-prover) (unless (proof-locked-region-empty-p) ;; re-opening may discard locked region! (let ((span (span-at (point) 'type))) ;; If no span at point, retracts the last span in the buffer. (unless span (proof-goto-end-of-locked) (backward-char) (setq span (span-at (point) 'type))) (if span (progn (run-hooks 'proof-retract-command-hook) ;; sneak commands (real ones with a prompt) (proof-retract-target span undo-action displayflags)) ;; something wrong (proof-debug "proof-retract-until-point: couldn't find a span!")))))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Proof General scripting mode definition, part 1. ;; ;;;###autoload (define-derived-mode proof-mode prog-mode proof-general-name "Proof General major mode class for proof scripts. \\{proof-mode-map}" (proof-splash-message) (setq proof-buffer-type 'script) ;; Set default indent function (can be overriden in derived modes) (setq-local indent-line-function #'proof-indent-line) ;; During write-file it can happen that we re-set the mode for the ;; currently active scripting buffer. The user might also do this ;; for some reason. We could maybe let this pass through, but it ;; seems safest to treat it as a kill buffer operation (retract and ;; clear spans). NB: other situations cause double calls to proof-mode. (if (eq (current-buffer) proof-script-buffer) (proof-script-kill-buffer-fn)) ;; We set hook functions here rather than in proof-config-done so ;; that they can be adjusted by prover specific code if need be. (proof-script-set-buffer-hooks) ;; Set after change functions (proof-script-set-after-change-functions) (add-hook 'after-set-visited-file-name-hooks #'proof-script-set-visited-file-name nil t) (add-hook 'proof-activate-scripting-hook #'proof-cd-sync nil t)) ;; NB: proof-mode-map declared above (proof-menu-define-keys proof-mode-map) (proof-eval-when-ready-for-assistant (define-key proof-mode-map [(control c) (control a)] (proof-ass keymap))) (defun proof-script-set-visited-file-name () "Called when visited file name is changed. This is a hook function for `after-set-visited-file-name-hooks'. For some provers, the file from which script commands are being processed may be important, and if it is changed with \\[write-file], for example, we might have to retract the contents or inform the proof assistant of the new name. This should be done by adding additional functions to `after-set-visited-file-name-hooks'. At the least, we need to set the buffer local hooks again with `proof-script-set-buffer-hooks' which is what this function does, as well as setting `proof-script-buffer-file-name' (which see). This hook also gives a warning in case this is the active scripting buffer." (setq proof-script-buffer-file-name buffer-file-name) (if (eq (current-buffer) proof-script-buffer) (pg-response-warning "Active scripting buffer changed name; synchronization risked if prover tracks filenames!")) (proof-script-set-buffer-hooks)) (defun proof-script-set-buffer-hooks () "Set the hooks for a proof script buffer. The hooks set here are cleared by `write-file', so we use this function to restore them using `after-set-visited-file-name-hooks'." (add-hook 'kill-buffer-hook #'proof-script-kill-buffer-fn t t) ;; Reverting buffer is same as killing it as far as PG is concerned (add-hook 'before-revert-hook #'proof-script-kill-buffer-fn t t)) (defun proof-script-kill-buffer-fn () "Value of `kill-buffer-hook' for proof script buffers. Clean up before a script buffer is killed. If killing the active scripting buffer, run `proof-deactivate-scripting-auto'. Otherwise just do `proof-restart-buffers' to delete some spans from memory." ;; Deactivate scripting in the current buffer if need be, forcing ;; automatic retraction if the buffer is not fully processed. (if (eq (current-buffer) proof-script-buffer) (proof-deactivate-scripting-auto)) (proof-restart-buffers (list (current-buffer))) ;; Hide away goals, response, and tracing. This is a hack because ;; otherwise we can lead the user to frustration with the ;; dedicated windows nonsense. (proof-map-buffers (list proof-goals-buffer proof-response-buffer proof-trace-buffer) (bury-buffer (current-buffer)))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Proof General scripting mode definition - part 2 ;; ;; The functions proof-config-done[-related] are called after the ;; derived mode has made its settings. ;; The callback *-config-done mechanism is an irritating hack - there ;; should be some elegant mechanism for computing constants after the ;; child has configured. Should petition the author of "derived-mode" ;; about this! (defun proof-config-done-related () "Finish setup of Proof General scripting and related modes. This is a subroutine of `proof-config-done'. This is intended for proof assistant buffers which are similar to script buffers, but for which scripting is not enabled. In particular, we: lock the buffer if it appears on `proof-included-files-list'; configure font-lock support from `proof-script-font-lock-keywords'. This is used for Isabelle theory files, which share some scripting mode features, but are only ever processed atomically by the proof assistant." (setq proof-script-buffer-file-name buffer-file-name) (when proof-script-font-lock-keywords (setq font-lock-defaults (list '(proof-script-font-lock-keywords) ;; see defadvice in proof-syntax (fboundp (proof-ass-sym font-lock-fontify-syntactically-region))))) ;; Has buffer already been processed? ;; NB: call to file-truename is needed for GNU Emacs which ;; chooses to make buffer-file-truename abbreviate-file-name ;; form of file-truename. (and buffer-file-truename (member (file-truename buffer-file-truename) proof-included-files-list) (proof-complete-buffer-atomic (current-buffer))) (make-local-variable 'comment-start) (setq comment-start (concat proof-script-comment-start " ")) (make-local-variable 'comment-end) (setq comment-end ;; For end of line terminated comments, stays empty. (if (string-equal "" proof-script-comment-end) "" ;; Otherwise, an extra space before comment delimiter (concat " " proof-script-comment-end))) (unless proof-script-comment-start-regexp (setq proof-script-comment-start-regexp (regexp-quote proof-script-comment-start))) (unless proof-script-comment-end-regexp (setq proof-script-comment-end-regexp (if (string-equal "" proof-script-comment-end) (regexp-quote "\n") ;; end-of-line terminated comments (regexp-quote proof-script-comment-end)))) ;; FIXME: This is clearly bogus: it sets the *start* matcher based on the ;; *end* marker. But I'm not sure what's the right fix: OT1H the code is ;; careful to build a correct end-matcher, but OTOH it's not as careful as ;; the default code in newcomment.el anyway. So I'm tempted to just remove ;; this code altogether. (make-local-variable 'comment-start-skip) (unless comment-start-skip (setq comment-start-skip (if (string-equal "" proof-script-comment-end) (regexp-quote "\n") ;; end-of-line terminated comments (regexp-quote proof-script-comment-end))))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Generic defaults for hooks, based on regexps. ;; ;; The next step is to use proof-stringfn-match scheme more widely, to ;; allow settings which are string or fn, so we don't need both regexp ;; and function hooks, and so that the other hooks can be functions too. (defun proof-generic-goal-command-p (span) "Is SPAN a goal? Decide by matching with `proof-goal-command-regexp'." (proof-string-match-safe proof-goal-command-regexp (or (span-property span 'cmd) ""))) (defun proof-generic-state-preserving-p (cmd) "Is CMD state preserving? Match on `proof-non-undoables-regexp'." ;; FIXME: logic here is not quite finished: proof-non-undoables are ;; certainly not state preserving, but so are a bunch more things, ;; i.e. ordinary proof commands which may appear in proof scripts. ;; Might be better to add positive and negative regexps for ;; state-preserving tests (only one of which needs to be set). (not (proof-string-match-safe proof-non-undoables-regexp cmd))) (defun proof-generic-count-undos (span) "Count number of undos in SPAN, return commands needed to undo that far. Command is set using `proof-undo-n-times-cmd'. A default value for `proof-count-undos-fn'. For this function to work properly, you must configure `proof-undo-n-times-cmd' and `proof-ignore-for-undo-count'." (let ((case-fold-search proof-case-fold-search) (ct 0) str i (tl (length proof-terminal-string))) (while span (setq str (span-property span 'cmd)) (cond ((eq (span-property span 'type) 'vanilla) (unless (proof-stringfn-match proof-ignore-for-undo-count str) (cl-incf ct))) ((eq (span-property span 'type) 'pbp) (setq i 0) (while (< i (length str)) (if (string-equal (substring str i (+ i tl)) proof-terminal-string) (cl-incf ct)) (cl-incf i)))) (setq span (next-span span 'type))) (if (= ct 0) nil ; was proof-no-command (cond ((stringp proof-undo-n-times-cmd) (list (format proof-undo-n-times-cmd ct))) ((functionp proof-undo-n-times-cmd) (list (funcall proof-undo-n-times-cmd ct))))))) (defun proof-generic-find-and-forget (span) "Calculate a forget/undo command to forget back to SPAN. This is a long-range forget: we know that there is no open goal at the moment, so forgetting involves unbinding declarations, etc, rather than undoing proof steps. This generic implementation assumes it is enough to find the nearest following span with a `name' property, and retract that using `proof-forget-id-command' with the given name. If this behaviour is not correct, you must customize the function with something different." ;; Modelled on Isar's find-and-forget function, but less ;; general at the moment: will only issue one und command. ;; FIXME: would be much cleaner to wrap up the undo behaviour ;; also within proofs in this function. (cond ((not proof-forget-id-command) (proof-debug "proof-generic-find-and-forget: proof-forget-id-command is unset, no action taken.") "") (t (let (ans typ name answers cmd) (while span (setq ans nil) (setq cmd (span-property span 'cmd)) (setq typ (span-property span 'type)) (cond ;; comment, diagnostic, prover processed, nested proof command: skip ((or (eq typ 'comment) (eq typ 'proverproc) (eq typ 'proof) (and proof-ignore-for-undo-count cmd (proof-string-match proof-ignore-for-undo-count cmd)))) ;; some named element: use generic forget-id function; finish. ((setq name (span-property span 'name)) (setq ans (format proof-forget-id-command name)) (setq span nil))) (if ans (setq answers (cons ans answers))) (if span (setq span (next-span span 'type)))) answers)))) ;; ;; End of new generic functions ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Sanity checks on important settings ;; (defconst proof-script-important-settings '(proof-script-comment-start ; proof-script-comment-end proof-save-command-regexp ; [actually, some provers may not have save command] ; proof-goal-command-regexp ; not needed if proof-goal-command-p is set ; proof-goal-with-hole-regexp ; non-essential? ; proof-save-with-hole-regexp ; non-essential? ; proof-showproof-command ; non-essential ; proof-goal-command ; non-essential ; proof-save-command ; do ; proof-kill-goal-command ; do )) ;;;###autoload (defun proof-config-done () "Finish setup of Proof General scripting mode. Call this function in the derived mode for the proof assistant to finish setup which depends on specific proof assistant configuration." ;; Common configuration for shared script/other related buffers. (proof-config-done-related) ;; Make mode class "pg-sticky" so renaming doesn't change the mode. (put major-mode 'mode-class 'pg-sticky) (if (and proof-non-undoables-regexp (not proof-ignore-for-undo-count)) (setq proof-ignore-for-undo-count proof-non-undoables-regexp)) ;; Give warnings if some crucial settings haven't been made (dolist (sym proof-script-important-settings) (proof-warn-if-unset "proof-config-done" sym)) ;; Additional key def for (first character of) terminal string (if proof-terminal-string (progn ;; This key-binding was disabled following a request in PG issue #160. ;; (define-key proof-mode-map ;; (vconcat [(control c)] (vector (aref proof-terminal-string 0))) ;; #'proof-electric-terminator-toggle) (define-key proof-mode-map (vector (aref proof-terminal-string 0)) #'proof-electric-terminator))) ;; Toolbar, main menu (loads proof-toolbar,setting p.-toolbar-scripting-menu) (proof-toolbar-setup) ;; Menus: the Proof-General and the specific menu (proof-menu-define-main) (proof-menu-define-specific) ;; Define parsing functions (proof-setup-parsing-mechanism) ;; Setup imenu and add it to menu if enabled. (proof-setup-imenu) (proof-imenu-enable) ;; Save file-less script mode buffers in case of accidental exit (or (buffer-file-name) (setq buffer-offer-save t)) ;; Turn on autosend if enabled (proof-autosend-enable 'nomsg) ;; Invisibility management: show ellipsis (mapc (lambda (p) (add-to-invisibility-spec (cons (pg-invisible-prop p) t))) pg-all-idioms) ;; If we're excited to get going straightaway, make and layout windows (when proof-layout-windows-on-visit-file (proof-shell-make-associated-buffers) (proof-layout-windows)) ;; Allow reindenting the already-processed code without causing ;; a retraction. (add-function :around (local 'indent-line-function) #'(lambda (orig-fun &rest args) (let ((proof--inhibit-retract-on-change t)) (apply orig-fun args)))) ;; Make sure the user has been welcomed! (proof-splash-message)) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Subroutines of proof-config-done ;; (defun proof-setup-parsing-mechanism () "Choose parsing mechanism according to different kinds of script syntax. Choice of function depends on configuration setting." (unless (fboundp 'proof-segment-up-to) (defalias 'proof-segment-up-to #'proof-segment-up-to-parser) (cond (proof-script-parse-function ;; already set, nothing to do ) (proof-script-sexp-commands (setq proof-script-parse-function #'proof-script-generic-parse-sexp)) (proof-script-command-start-regexp (setq proof-script-parse-function #'proof-script-generic-parse-cmdstart)) ((or proof-script-command-end-regexp proof-terminal-string) (setq proof-script-parse-function #'proof-script-generic-parse-cmdend) (unless proof-script-command-end-regexp (proof-warn-if-unset "probof-config-done" 'proof-terminal-string) (setq proof-script-command-end-regexp (if proof-terminal-string (regexp-quote proof-terminal-string) "$")))) (t (error "Configuration error: must set `proof-terminal-string' or one of its friends"))))) (defun proof-setup-imenu () "Setup a default for imenu, perhaps using `proof-script-imenu-generic-expression'." (unless ;; already setup, leave it alone (and (boundp 'imenu-generic-expression) imenu-generic-expression) (set (make-local-variable 'imenu-generic-expression) (or proof-script-imenu-generic-expression (delq nil (list (if proof-goal-with-hole-regexp (list nil proof-goal-with-hole-regexp proof-goal-with-hole-result)) (if proof-save-with-hole-regexp (list "Saves" proof-save-with-hole-regexp proof-save-with-hole-result)))))))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Caching parse results for unedited portions of the buffer ;; ;; Added in PG 4.1 ;; ;; A simplistic first attempt: we only cache the last region that was ;; parsed. It would be better to maintain a parse cache for the ;; unedited prefix of the buffer or for individual segments like ;; PGIP Emacs PG does. Or to parse during idle like font-lock. ;; ;; We assume that extending the parsed region can only possibly affect ;; the last command in the cache but leaves the rest intact. (NB: in ;; Isabelle/Isar a command can be a proper prefix of a longer one and ;; there are no explicit terminators). (deflocal proof-segment-up-to-cache nil "Cache used to speed up parsing. Stores recent results of `proof-segment-up-to' in reverse order.") (deflocal proof-segment-up-to-cache-start 0) (deflocal proof-segment-up-to-cache-end 0) (deflocal proof-last-edited-low-watermark nil) (defun proof-segment-up-to-using-cache (pos &rest args) "A wrapper for `proof-segment-up-to' which uses a cache to speed things up." (let (res) (if (and proof-use-parser-cache ;; safety off valve proof-segment-up-to-cache (>= (proof-queue-or-locked-end) proof-segment-up-to-cache-start) (setq res (proof-segment-cache-contents-for pos)) ;; only use result if last edit point is >1 segment below (or (not proof-last-edited-low-watermark) (> proof-last-edited-low-watermark (nth 2 (car res))))) (progn (proof-debug "proof-segment-up-to-using-cache: re-using %d parse results" (length res)) res) ;; Cache not useful, perform a fresh parse (let ((semis (proof-segment-up-to pos args))) (setq proof-segment-up-to-cache (reverse semis)) (setq proof-segment-up-to-cache-start (proof-queue-or-locked-end)) (setq proof-segment-up-to-cache-end (if semis (nth 2 (car semis)) 0)) (when proof-last-edited-low-watermark (if (<= proof-last-edited-low-watermark proof-segment-up-to-cache-end) (setq proof-last-edited-low-watermark nil))) semis)))) (defun proof-segment-cache-contents-for (pos) ;; only return result if we have cache for complete region (when (<= pos proof-segment-up-to-cache-end) (let ((semis proof-segment-up-to-cache) (start (proof-queue-or-locked-end)) usedsemis semiend) (while semis (setq semiend (nth 2 (car semis))) (if (> semiend start) (setq usedsemis (cons (car semis) usedsemis))) (setq semis (if (or (< semiend pos) ;; matches parsing-until-find-something behaviour (and (= semiend pos) (not usedsemis))) (cdr semis)))) usedsemis))) (defun proof-script-after-change-function (start _end _prelength) "Value for `after-change-functions' in proof script buffers." (setq proof-last-edited-low-watermark (min (or proof-last-edited-low-watermark (point-max)) start)) (if (and (markerp proof-overlay-arrow) (marker-position proof-overlay-arrow) ; only move marker up: ;(< start (marker-position proof-overlay-arrow)) (>= start (proof-queue-or-locked-end))) (proof-set-overlay-arrow (proof-queue-or-locked-end)))) (defun proof-script-set-after-change-functions () "Set `after-change-functions' for script buffers." (add-hook 'after-change-functions #'proof-script-after-change-function nil t)) (provide 'proof-script) ;;; proof-script.el ends here PG-4.5/generic/proof-shell.el000066400000000000000000002311711426357011200160660ustar00rootroot00000000000000;;; proof-shell.el --- Proof General shell mode ;; This file is part of Proof General. ;; Portions © Copyright 1994-2012 David Aspinall and University of Edinburgh ;; Portions © Copyright 2003-2021 Free Software Foundation, Inc. ;; Portions © Copyright 2001-2017 Pierre Courtieu ;; Portions © Copyright 2010, 2016 Erik Martin-Dorel ;; Portions © Copyright 2011-2013, 2016-2017 Hendrik Tews ;; Portions © Copyright 2015-2017 Clément Pit-Claudel ;; Authors: David Aspinall, Yves Bertot, Healfdene Goguen, ;; Thomas Kleymann and Dilip Sequeira ;; SPDX-License-Identifier: GPL-3.0-or-later ;;; Commentary: ;; ;; Mode for buffer which interacts with proof assistant. ;; Includes management of a queue of commands waiting to be sent. ;; ;;; Code: (require 'cl-lib) ; cl-set-difference, cl-every (eval-when-compile (require 'span) (require 'proof-utils)) ;; declare a few functions and variables from proof-tree - if we ;; require proof-tree the compiler complains about a recusive ;; dependency. (declare-function proof-tree-urgent-action "proof-tree" (flags)) (declare-function proof-tree-handle-delayed-output "proof-tree" (old-proof-marker cmd flags span)) ;; without the nil initialization the compiler still warns about this variable (defvar proof-tree-external-display) (require 'scomint) (require 'pg-response) (require 'pg-goals) (require 'pg-user) ; proof-script, new-command-advance (require 'span) ;; ;; Internal variables used by proof shell ;; (defvar proof-marker nil "Marker in proof shell buffer pointing to previous command input.") (defvar proof-action-list nil "The main queue of things to do: spans, commands and actions. The value is a list of lists of the form (SPAN COMMANDS ACTION [DISPLAYFLAGS]) which is the queue of things to do. SPAN is a region in the sources, where COMMANDS come from. Often, additional properties are recorded as properties of SPAN. COMMANDS is a list of strings, holding the text to be send to the prover. It might be the empty list if nothing needs to be sent to the prover, such as, for comments. Usually COMMANDS contains just 1 string, but it might also contains more elements. The text should be obtained with `(mapconcat 'identity COMMANDS \" \")', where the last argument is a space. ACTION is the callback to be invoked when this item has been processed by the prover. For normal scripting items it is `proof-done-advancing', for retract items `proof-done-retracting', but there are more possibilities (e.g. `proof-done-invisible', `proof-shell-set-silent', `proof-shell-clear-silent' and `proof-tree-show-goal-callback'). The DISPLAYFLAGS are set for non-scripting commands or for when scripting should not bother the user. They may include 'invisible non-script command (`proof-shell-invisible-command') 'no-response-display do not display messages in *response* buffer 'no-error-display do not display errors/take error action 'no-goals-display do not goals in *goals* buffer 'proof-tree-show-subgoal item inserted by the proof-tree package 'priority-action item added via proof-add-to-priority-queue Note that 'invisible does not imply any of the others. If flags are non-empty, interactive cues will be surpressed. (E.g., printing hints). See the functions `proof-start-queue' and `proof-shell-exec-loop'.") (defvar proof-priority-action-list nil "Holds action items to be inserted at the head of `proof-action-list' ASAP. When the proof assistant is busy, one cannot push to the head of `proof-action-list`, because the head usually (but not always) contains the item that the proof assistant is currently executing. This list therefore holds the items to be executed before any other items in `proof-action-list'. Inside `proof-shell-exec-loop', when `proof-action-list' is in the right state, the content of this list is prepended to `proof-action-list'. Use `proof-add-to-priority-queue' to add items to this priority list, to ensure the proof assistant starts running, in case `proof-action-list' is currently empty. The items in this list are reversed, that is, the one added last and to be executed last is at the head.") (defsubst proof-shell-invoke-callback (listitem) "From `proof-action-list' LISTITEM, invoke the callback on the span." (condition-case err (funcall (nth 2 listitem) (car listitem)) (error (message "error escaping proof-shell-invoke-callback: %s" err) nil))) (defvar proof-second-action-list-active nil "Signals that some items are waiting outside of `proof-action-list'. If this is t it means that some items from the queue region are waiting for being processed in a place different from `proof-action-list'. In this case Proof General must behave as if `proof-action-list' would be non-empty, when it is, in fact, empty. This is used, for instance, for parallel background compilation for Coq: The Require command and the following items are not put into `proof-action-list' and are stored somewhere else until the background compilation finishes. Then those items are put into `proof-action-list' for getting processed.") ;; We record the last output from the prover and a flag indicating its ;; type, as well as a previous ("delayed") version for when the end ;; of the queue is reached or an error or interrupt occurs. ;; ;; See `proof-shell-last-output', `proof-shell-last-prompt' in ;; pg-vars.el (defvar proof-shell-last-goals-output "" "The last displayed goals string.") (defvar proof-shell-last-response-output "" "The last displayed response message.") (defvar proof-shell-delayed-output-start nil "A record of the start of the previous output in the shell buffer. The previous output is held back for processing at end of queue.") (defvar proof-shell-delayed-output-end nil "A record of the start of the previous output in the shell buffer. The previous output is held back for processing at end of queue.") (defvar proof-shell-delayed-output-flags nil "A copy of the `proof-action-list' flags for `proof-shell-delayed-output'.") (defvar proof-shell-interrupt-pending nil "A flag indicating an interrupt is pending. This ensures that the proof queue will be interrupted even if no interrupt message is printed from the prover after the last output.") (defvar proof-shell-exit-in-progress nil "A flag indicating that the current proof process is about to exit. This flag is set for the duration of `proof-shell-kill-function' to tell hooks in `proof-deactivate-scripting-hook' to refrain from calling `proof-shell-exit'.") ;; ;; Indicator and fake minor mode for active scripting buffer ;; (defcustom proof-shell-active-scripting-indicator '(:eval (propertize " Scripting " 'face (cond (proof-shell-busy 'proof-queue-face) ((eq proof-shell-last-output-kind 'error) 'proof-script-sticky-error-face) ((proof-with-current-buffer-if-exists proof-script-buffer (proof-locked-region-full-p)) 'font-lock-type-face) (t 'proof-locked-face)))) "Modeline indicator for active scripting buffer. Changes colour to indicate whether the shell is busy, etc." :type 'sexp :group 'proof-general-internals) (unless (assq 'proof-active-buffer-fake-minor-mode minor-mode-alist) (setq minor-mode-alist (append minor-mode-alist (list (list 'proof-active-buffer-fake-minor-mode proof-shell-active-scripting-indicator))))) ;; ;; Implementing the process lock ;; ;; Note that because Emacs Lisp code is single-threaded, there are no ;; concurrency issues here (a loop parsing process output cannot get ;; pre-empted by the user trying to send more input to the process, or ;; by the process filter trying to deal with more output). But the ;; lock allows for clear management of the queue. ;; ;; Three relevant functions: ;; ;; proof-shell-ready-prover ;; starts proof shell, gives error if it's busy. ;; ;; proof-activate-scripting (in proof-script.el) ;; calls proof-shell-ready-prover, and turns on scripting minor ;; mode for current (scripting) buffer. ;; ;; Also, an enabler predicate: ;; ;; proof-shell-available-p ;; returns non-nil if a proof shell is active and not locked. ;; ;;;###autoload (defun proof-shell-ready-prover (&optional queuemode) "Make sure the proof assistant is ready for a command. If QUEUEMODE is set, succeed if the proof shell is busy but has mode QUEUEMODE, which is a symbol or list of symbols. Otherwise, if the shell is busy, give an error. No change to current buffer or point." (proof-shell-start) (unless (or (not proof-shell-busy) (eq queuemode proof-shell-busy) (and (listp queuemode) (member proof-shell-busy queuemode))) (error "Proof process busy!"))) ;;;###autoload (defun proof-shell-live-buffer () "Return non-nil if ‘proof-shell-buffer’ is live." (and proof-shell-buffer (buffer-live-p proof-shell-buffer) ;; FIXME: Use process-live-p? (scomint-check-proc proof-shell-buffer))) ;;;###autoload (defun proof-shell-available-p () "Return non-nil if there is a proof shell active and available. No error messages. Useful as menu or toolbar enabler." (and (proof-shell-live-buffer) (not proof-shell-busy))) (defun proof-grab-lock (&optional queuemode) "Grab the proof shell lock, starting the proof assistant if need be. Runs `proof-state-change-hook' to notify state change. If QUEUEMODE is supplied, set the lock to that value." (proof-shell-ready-prover queuemode) (setq proof-shell-interrupt-pending nil proof-shell-busy (or queuemode t) proof-shell-last-queuemode proof-shell-busy) (run-hooks 'proof-state-change-pre-hook) (run-hooks 'proof-state-change-hook)) (defun proof-release-lock () "Release the proof shell lock. Clear `proof-shell-busy'." (setq proof-shell-busy nil)) ;; ;; Starting and stopping the proof shell ;; (defcustom proof-shell-fiddle-frames t "Non-nil if proof-shell functions should fire-up/delete frames like crazy." :type 'boolean :group 'proof-shell) (defvar proof-shell-filter-active nil "Variable equal to t if `proof-shell-filter' is running.") (defvar proof-shell-filter-was-blocked nil "Variable equal to t if a recursive call of `proof-shell-filter' was blocked. In this case `proof-shell-filter' must be called again after it finished.") (defun proof-shell-set-text-representation () "Adjust representation for current buffer, to match `proof-shell-unicode'." (unless proof-shell-unicode ;; Prevent interpretation of multi-byte characters. ;; Otherwise, chars 128-255 get remapped higher, breaking regexps (toggle-enable-multibyte-characters -1))) (defun proof-shell-make-associated-buffers () "Create the associated buffers and set buffer variables holding them." (let ((goals "*goals*") (resp "*response*") (trace "*trace*") (thms "*thms*")) (setq proof-goals-buffer (get-buffer-create goals)) (setq proof-response-buffer (get-buffer-create resp)) (if proof-shell-trace-output-regexp (setq proof-trace-buffer (get-buffer-create trace))) (if proof-shell-thms-output-regexp (setq proof-thms-buffer (get-buffer-create thms))) ;; Set the special-display-regexps now we have the buffer names (setq pg-response-special-display-regexp (proof-regexp-alt goals resp trace thms)))) (defun proof-strip-whitespace-at-end (string) "Return STRING stripped of all trailing whitespace." (while (string-match "[\r\n\t ]+$" string) (setq string (replace-match "" t t string))) string) (defvar proof-shell-before-process-hook nil "Functions run from `proof-shell-start' just before starting the prover process. Last chance to modify xxx-prog-args and xxx-prog-name") (defun proof-shell-start () "Initialise a shell-like buffer for a proof assistant. Does nothing if proof assistant is already running. Also generates goal and response buffers. If `proof-prog-name-ask' is set, query the user for the process command." (interactive) (unless (proof-shell-live-buffer) (setq proof-shell-filter-active nil) (setq proof-included-files-list nil) ; clear some state (let ((name (buffer-file-name (current-buffer)))) (if (and name proof-prog-name-guess proof-guess-command-line) (setq proof-prog-name (apply proof-guess-command-line (list name))))) (if proof-prog-name-ask ;; if this option is set, an absolute file name is better to show if possible (let ((prog-name (locate-file proof-prog-name exec-path exec-suffixes 1))) (setq proof-prog-name (proof-strip-whitespace-at-end (read-shell-command "Run process: " prog-name))))) ;; Once proof-prog-name is set (possibly asked to the user by the ;; code above), some final option setting may need to be done. (run-hooks 'proof-shell-before-process-hook) (let ((proc (downcase proof-assistant))) ;; Starting the inferior process (asynchronous) (let* ((prog-name-list1 (if (functionp (proof-ass-sym prog-args)) ;; complex assistants define -prog-args as function ;; that computes the argument list. (cons proof-prog-name (funcall (proof-ass-sym prog-args))) (if (proof-ass prog-args) ;; Intermediate complex assistants set the value ;; of -prog-args to the argument list. (cons proof-prog-name (proof-ass prog-args)) ;; Trivial assistants simply set proof-prog-name (split-string proof-prog-name)))) (prog-name-list ;; Splice in proof-rsh-command if it's non-nil (if (and proof-rsh-command (> (length proof-rsh-command) 0)) (append (split-string proof-rsh-command) prog-name-list1) prog-name-list1)) (prog-command-line (mapconcat 'identity prog-name-list " ")) (process-connection-type proof-shell-process-connection-type) ;; Trac #324, Trac #284: default with Emacs 23 variants ;; is t. nil gave marginally better results with "make ;; profile.isar" on homogenous test input. Top-level ;; Emacs loop causes slow down on Mac and Windows ports. (process-adaptive-read-buffering nil) ;; The next few settings control the proof assistant encoding. ;; See Elisp manual for recommendations for coding systems. ;; Modern versions of proof systems should be Unicode ;; clean, i.e., outputing only ASCII characters or using a ;; representation such as UTF-8. Old versions of PG ;; relied on control sequences using 8-bit characters with ;; codes between 127 and 255, this is now deprecated. ;; Backward compatibility: remove UTF-8 encoding if not ;; wanted; it conflicts with using chars 128-255 for ;; markup and results in blocking in C libraries. (process-environment (append (proof-ass prog-env) ; custom environment (if proof-shell-unicode ; if specials not used, process-environment ; leave it alone (cons (if (getenv "LANG") (format "LANG=%s" (replace-regexp-in-string "\\.UTF-8" "" (getenv "LANG"))) "LANG=C") (delete (concat "LANG=" (getenv "LANG")) process-environment))))) (normal-coding-system-for-read coding-system-for-read) (coding-system-for-read (if proof-shell-unicode (or (condition-case nil (check-coding-system 'utf-8) (error nil)) normal-coding-system-for-read) (if (string-match "Linux" (shell-command-to-string "uname")) 'raw-text normal-coding-system-for-read))) (coding-system-for-write coding-system-for-read)) (message "Starting: %s" prog-command-line) (apply 'scomint-make (append (list proc (car prog-name-list) nil) (cdr prog-name-list))) (setq proof-shell-buffer (get-buffer (concat "*" proc "*"))) (unless (proof-shell-live-buffer) ;; Give error now if shell buffer isn't live (process exited). We also ;; set the process filter to nil to avoid processing error messages ;; related to the process exit. (set-process-filter (get-buffer-process proof-shell-buffer) nil) (setq proof-shell-buffer nil) (error "Starting process: %s..failed" prog-command-line))) (proof-shell-make-associated-buffers) (with-current-buffer proof-shell-buffer ;; Clear and set text representation (see CVS history for comments) (erase-buffer) (proof-shell-set-text-representation) ;; Initialise associated buffers (with-current-buffer proof-response-buffer (erase-buffer) (proof-shell-set-text-representation) (funcall proof-mode-for-response)) (with-current-buffer proof-goals-buffer (erase-buffer) (proof-shell-set-text-representation) (funcall proof-mode-for-goals)) (proof-with-current-buffer-if-exists proof-trace-buffer (erase-buffer) (proof-shell-set-text-representation) (funcall proof-mode-for-response) (setq pg-response-eagerly-raise nil)) ;; Initialise shell mode (calls hook function, after process started) (funcall proof-mode-for-shell) ;; Check to see that the process is still going. If not, ;; switch buffer to display the error messages to the user. (unless (proof-shell-live-buffer) (switch-to-buffer proof-shell-buffer) (error "%s process exited!" proc)) ;; Setting modes initialises local variables which ;; may affect frame/buffer appearance: so we fire up frames ;; once this has been done. (if proof-shell-fiddle-frames ;; Call multiple-frames-enable in case we need to fire up ;; new frames (NB: sets specifiers to remove modeline) (save-selected-window (proof-multiple-frames-enable)))) (message "Starting %s process... done." proc)))) ;; ;; Shutting down proof shell and associated buffers ;; ;; Hooks here are handy for liaising with prover config stuff. (defvar proof-shell-kill-function-hooks nil "Functions run from `proof-shell-kill-function'.") (defun proof-shell-kill-function-kill-associated-buffers () "Kill the goal, response, and trace buffers, as well as frames if necessary." ;; Remove auxiliary windows, trying to stop proliferation of ;; frames (NB: loses if user has switched buffer in special frame) (if (and proof-multiple-frames-enable proof-shell-fiddle-frames) (proof-delete-all-associated-windows)) (let ((proof-shell-buffer nil)) ;; fool kill buffer hooks (dolist (buf '(proof-goals-buffer proof-response-buffer proof-trace-buffer)) (when (buffer-live-p (symbol-value buf)) (delete-windows-on (symbol-value buf)) (kill-buffer (symbol-value buf)) (set buf nil))))) (defun proof-shell-kill-function () "Function run when a proof-shell buffer is killed. Try to shut down the proof process nicely and clear locked regions and state variables. Value for `kill-buffer-hook' in shell buffer, called by `proof-shell-bail-out' if process exits." (let* ((alive (scomint-check-proc (current-buffer))) (proc (get-buffer-process (current-buffer))) (bufname (buffer-name))) (message "%s, cleaning up and exiting..." bufname) (let (prover-was-busy) ;; hook functions might set prover-was-busy (run-hooks 'proof-shell-signal-interrupt-hook)) (redisplay t) (when (and alive proc) (catch 'exited (setq proof-shell-exit-in-progress t) (set-process-sentinel proc (lambda (p m) (throw 'exited t))) ;; Turn off scripting (ensure buffers completely processed/undone) (proof-deactivate-scripting-auto) (proof-shell-wait (proof-ass quit-timeout)) ;; Try to shut down politely. (if proof-shell-quit-cmd (scomint-send-string proc (concat proof-shell-quit-cmd "\n")) (scomint-send-eof)) ;; Wait for it to die (let ((timecount (proof-ass quit-timeout)) (proc (get-buffer-process proof-shell-buffer))) (while (and (> timecount 0) (scomint-check-proc proof-shell-buffer)) (accept-process-output proc 1 nil 1) (cl-decf timecount))) ;; Still there, kill it rudely. (when (memq (process-status proc) '(open run stop)) (message "%s, cleaning up and exiting...killing process" bufname) (kill-process proc))) (set-process-sentinel proc nil)) ;; Clear all state (proof-script-remove-all-spans-and-deactivate) (proof-shell-clear-state) (run-hooks 'proof-shell-kill-function-hooks) (when proof-shell-kill-function-also-kills-associated-buffers (proof-shell-kill-function-kill-associated-buffers)) (setq proof-shell-exit-in-progress nil) (message "%s exited." bufname))) (defun proof-shell-clear-state () "Clear internal state of proof shell." (setq proof-action-list nil proof-included-files-list nil proof-shell-busy nil proof-shell-last-queuemode nil proof-shell-proof-completed nil proof-nesting-depth 0 proof-shell-silent nil proof-shell-last-output "" proof-shell-last-prompt "" proof-shell-last-output-kind nil proof-shell-delayed-output-start nil proof-shell-delayed-output-end nil proof-shell-delayed-output-flags nil)) (defun proof-shell-exit (&optional dont-ask) "Query the user and exit the proof process. This simply kills the `proof-shell-buffer' relying on the hook function `proof-shell-kill-function' to do the hard work. If optional argument DONT-ASK is non-nil, the proof process is terminated without confirmation. The kill function uses `-quit-timeout' as a timeout to wait after sending `proof-shell-quit-cmd' before rudely killing the process. This function should not be called if `proof-shell-exit-in-progress' is t, because a recursive call of `proof-shell-kill-function' will give strange errors." (interactive "P") (if (buffer-live-p proof-shell-buffer) (when (or dont-ask (yes-or-no-p (format "Exit %s process? " proof-assistant))) (let ((kill-buffer-query-functions nil)) ; avoid extra dialog (kill-buffer proof-shell-buffer)) (setq proof-shell-buffer nil)) (error "No proof shell buffer to kill!"))) (defun proof-shell-bail-out (process event) "Value for the process sentinel for the proof assistant PROCESS. If the proof assistant dies, run `proof-shell-kill-function' to cleanup and remove the associated buffers. The shell buffer is left around so the user may discover what killed the process. EVENT is the string describing the change." (message "Process %s %s, shutting down scripting..." process event) (proof-shell-kill-function) (message "Process %s %s, shutting down scripting...done." process event)) (defun proof-shell-restart () "Clear script buffers and send `proof-shell-restart-cmd'. All locked regions are cleared and the active scripting buffer deactivated. If the proof shell is busy, an interrupt is sent with `proof-interrupt-process' and we wait until the process is ready. The restart command should re-synchronize Proof General with the proof assistant, without actually exiting and restarting the proof assistant process. It is up to the proof assistant how much context is cleared: for example, theories already loaded may be \"cached\" in some way, so that loading them the next time round only performs a re-linking operation, not full re-processing. (One way of caching is via object files, used by Coq)." (interactive) (when proof-shell-busy (proof-interrupt-process) (proof-shell-wait)) (if (not (proof-shell-live-buffer)) (proof-shell-start) ;; start if not running ;; otherwise clear context (proof-script-remove-all-spans-and-deactivate) (proof-shell-clear-state) (with-current-buffer proof-shell-buffer (delete-region (point-min) (point-max))) (if (and (buffer-live-p proof-shell-buffer) proof-shell-restart-cmd) (proof-shell-invisible-command proof-shell-restart-cmd)))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Response buffer processing ;; (defvar proof-shell-urgent-message-marker nil "Marker in proof shell buffer pointing to end of last urgent message.") (defvar proof-shell-urgent-message-scanner nil "Marker in proof shell buffer pointing to scan start for urgent messages. This is only used in `proof-shell-process-urgent-message'.") (defun proof-shell-handle-error-output (start-regexp append-face) "Displays output from process in `proof-response-buffer'. The output is taken from `proof-shell-last-output' and begins the first match for START-REGEXP. If START-REGEXP is nil or no match can be found (which can happen if output has been garbled somehow), begin from the start of the output for this command. This is a subroutine of `proof-shell-handle-error'." (let ((string proof-shell-last-output) pos) (if (and start-regexp (setq pos (string-match start-regexp string))) (setq string (substring string pos))) ;; Erase if need be, and erase next time round too. (pg-response-maybe-erase t nil) ;; Coloring the whole message may be ugly ad hide better ;; coloring mechanism. (if proof-script-color-error-messages (pg-response-display-with-face string append-face) (pg-response-display-with-face string)))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Processing error output ;; (defun proof-shell-handle-error-or-interrupt (err-or-int flags) "React on an error or interrupt message triggered by the prover. The argument ERR-OR-INT should be set to 'error or 'interrupt which affects the action taken. For errors, we first flush unprocessed output (usually goals). The error message is the (usually) displayed in the response buffer. For interrupts, a warning message is displayed. In both cases we then sound a beep, clear the queue and spans and finally we call `proof-shell-handle-error-or-interrupt-hook'. Commands which are not part of regular script management (with FLAGS containing 'no-error-display) will not cause any display action. This is called in two places: (1) from the output processing functions, in case we find an error or interrupt message output, and (2) from the exec loop, in case of a pending interrupt which didn't cause prover output." (unless (memq 'no-error-display flags) (cond ((eq err-or-int 'interrupt) (pg-response-maybe-erase t t t) ; force cleaned now & next (proof-shell-handle-error-output (if proof-shell-truncate-before-error proof-shell-interrupt-regexp) 'proof-error-face) (pg-response-warning "Interrupt: script management may be in an inconsistent state (but it's probably okay)")) (t ; error (if proof-shell-delayed-output-start (save-excursion (proof-shell-handle-delayed-output))) (proof-shell-handle-error-output (if proof-shell-truncate-before-error proof-shell-error-regexp) 'proof-error-face) (proof-display-and-keep-buffer proof-response-buffer)))) (proof-with-current-buffer-if-exists proof-shell-buffer (proof-shell-error-or-interrupt-action err-or-int))) (defun proof-shell-error-or-interrupt-action (err-or-int) "Take action on errors or interrupts. ERR-OR-INT is a flag, 'error or 'interrupt. This is a subroutine of `proof-shell-handle-error-or-interrupt'. Must be called with proof shell buffer current. This function invokes `proof-shell-handle-error-or-interrupt-hook' unless the FLAGS for the command are non-nil (see `proof-action-list')." (unless proof-shell-quiet-errors (beep)) (let* ((fatalitem (car-safe proof-action-list)) (badspan (car-safe fatalitem)) (flags (if fatalitem (nth 3 fatalitem)))) (proof-with-current-buffer-if-exists proof-script-buffer (save-excursion (proof-script-clear-queue-spans-on-error badspan (eq err-or-int 'interrupt)))) ;; Note: coq-par-emergency-cleanup, which might be called via ;; proof-shell-handle-error-or-interrupt-hook below, assumes that ;; proof-action-list is empty on error. (setq proof-action-list nil) (proof-release-lock) (unless flags ;; Give a hint about C-c C-`. (NB: approximate test) (if (pg-response-has-error-location) (pg-next-error-hint)) ;; Run hooks for additional effects, e.g. highlight or moving pointer (run-hooks 'proof-shell-handle-error-or-interrupt-hook)))) (defun proof-goals-pos (span maparg) "Given a SPAN, return the start of it if corresponds to a goal, nil otherwise." (and (eq 'goal (car (span-property span 'proof-top-element))) (span-start span))) (defun proof-pbp-focus-on-first-goal () "If the `proof-goals-buffer' contains goals, bring the first one into view. This is a hook function for proof-shell-handle-delayed-output-hook." ) ;; PG 4.0 FIXME ; (let ; ((pos (map-extents 'proof-goals-pos proof-goals-buffer ; nil nil nil nil 'proof-top-element))) ; (and pos (set-window-point ; (get-buffer-window proof-goals-buffer t) pos))))) (defsubst proof-shell-string-match-safe (regexp string) "Like (string-match REGEXP STRING), but return nil if REGEXP is nil." (and regexp (string-match regexp string))) (defun proof-shell-handle-immediate-output (cmd start end flags) "See if the output between START and END must be dealt with immediately. To speed up processing, PG tries to avoid displaying output that the user will not have a chance to see. Some output must be handled immediately, however: these are errors, interrupts, goals and loopbacks (proof step hints/proof by pointing results). In this function we check, in turn: `proof-shell-interrupt-regexp' `proof-shell-error-regexp' `proof-shell-proof-completed-regexp' `proof-shell-result-start' Other kinds of output are essentially display only, so only dealt with if necessary. To extend this, set `proof-shell-handle-output-system-specific', which is a hook to take particular additional actions. This function sets variables: `proof-shell-last-output-kind', and the counter `proof-shell-proof-completed' which counts commands after a completed proof." (setq proof-shell-last-output-kind nil) ; unclassified (goto-char start) (cond ;; TODO: Isabelle has changed (since 2009) and is now amalgamating ;; output between prompts, and does e.g., ;; GOALS ;; ERROR ;; we need to override delayed output from the previous ;; command with delayed output from this command to handle that! ((proof-re-search-forward-safe proof-shell-interrupt-regexp end t) (setq proof-shell-last-output-kind 'interrupt) (proof-shell-handle-error-or-interrupt 'interrupt flags)) ((proof-re-search-forward-safe proof-shell-error-regexp end t) (setq proof-shell-last-output-kind 'error) (proof-shell-handle-error-or-interrupt 'error flags)) ((proof-re-search-forward-safe proof-shell-result-start end t) ;; NB: usually the action list is empty, strange results likely if ;; more commands follow. Therefore, this case might be delayed. (let (pstart pend) (setq pstart (+ 1 (match-end 0))) (re-search-forward proof-shell-result-end end t) (setq pend (- (match-beginning 0) 1)) (proof-shell-insert-loopback-cmd (buffer-substring-no-properties pstart pend))) (setq proof-shell-last-output-kind 'loopback) (proof-shell-exec-loop)) ((proof-re-search-forward-safe proof-shell-proof-completed-regexp end t) (setq proof-shell-proof-completed 0))) ; commands since complete ;; PG4.0 change: simplify and run earlier (if proof-shell-handle-output-system-specific (funcall proof-shell-handle-output-system-specific cmd proof-shell-last-output))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Interrupts ;; (defun proof-interrupt-process () "Interrupt the proof assistant. Warning! This may confuse Proof General. This sends an interrupt signal to the proof assistant, if Proof General thinks it is busy. This command is risky because we don't know whether the last command succeeded or not. The assumption is that it didn't, which should be true most of the time, and all of the time if the proof assistant has a careful handling of interrupt signals. Some provers may ignore (and lose) interrupt signals, or fail to indicate that they have been acted upon yet stop in the middle of output. In the first case, PG will terminate the queue of commands at the first available point. In the second case, you may need to press enter inside the prover command buffer (e.g., with Isabelle2009 press RET inside *isabelle*)." (interactive) (let ((prover-was-busy nil)) (unless (proof-shell-live-buffer) (error "Proof process not started!")) ;; Hook functions might set prover-was-busy. ;; In case `proof-action-list' is empty and only ;; `proof-second-action-list-active' is t, the hook functions ;; should clear the queue region and release the proof shell lock. ;; `coq-par-user-interrupt' actually does this. (run-hooks 'proof-shell-signal-interrupt-hook) (if proof-shell-busy (progn (setq proof-shell-interrupt-pending t) (with-current-buffer proof-shell-buffer (interrupt-process))) (unless prover-was-busy (error "Proof process not active!"))))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Low-level commands for shell communication ;; ;;;###autoload (defun proof-shell-insert (strings action &optional scriptspan) "Insert STRINGS at the end of the proof shell, call `scomint-send-input'. STRINGS is a list of strings (which will be concatenated), or a single string. The ACTION argument is a symbol which is typically the name of a callback for when each string has been processed. This calls `proof-shell-insert-hook'. The arguments ACTION and SCRIPTSPAN may be examined by the hook to determine how to modify the string variable (exploiting dynamic scoping) which will be the command actually sent to the shell. Note that the hook is not called for the empty (null) string or a carriage return. We strip the string of carriage returns before inserting it and updating `proof-marker' to point to the end of the newly inserted text. Do not use this function directly, or output will be lost. It is only used in `proof-add-to-queue' when we start processing a queue, and in `proof-shell-exec-loop', to process the next item." (cl-assert (or (stringp strings) (listp strings)) nil "proof-shell-insert: expected string list argument") (with-current-buffer proof-shell-buffer (goto-char (point-max)) ;; TEMP: next step: preprocess list of strings directly (let ((string (if (stringp strings) strings (apply 'concat strings)))) ;; Hook for munging `string' and other dirty hacks. (run-hooks 'proof-shell-insert-hook) ;; Replace CRs from string with spaces to avoid spurious prompts. (if proof-shell-strip-crs-from-input (setq string (subst-char-in-string ?\n ?\ string))) (insert string) ;; Advance the proof-marker, if synchronization has been gained. ;; Null marker => no yet synced; output is ignored. (unless (null (marker-position proof-marker)) (set-marker proof-marker (point))) (scomint-send-input)))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Code for manipulating proof queue ;; (defun proof-shell-action-list-item (cmd callback &optional flags) "Return action list entry run CMD with callback CALLBACK and FLAGS. The queue entry does not refer to a span in the script buffer." (list nil (list cmd) callback flags)) (defun proof-shell-set-silent (span) "Callback for `proof-shell-start-silent'. Very simple function but it's important to give it a name to help track what happens in the proof queue." (setq proof-shell-silent t)) (defun proof-shell-start-silent-item () "Return proof queue entry for starting silent mode." (proof-shell-action-list-item proof-shell-start-silent-cmd 'proof-shell-set-silent)) (defun proof-shell-clear-silent (span) "Callback for `proof-shell-stop-silent'. Very simple function but it's important to give it a name to help track what happens in the proof queue." (setq proof-shell-silent nil)) (defun proof-shell-stop-silent-item () "Return proof queue entry for stopping silent mode." (proof-shell-action-list-item proof-shell-stop-silent-cmd 'proof-shell-clear-silent)) (defsubst proof-shell-should-be-silent () "Non-nil if we should switch to silent mode based on size of queue." (if (and proof-shell-start-silent-cmd ; configured (not proof-full-annotation) ; always noisy (not proof-tree-external-display) ; no proof-tree display (not proof-shell-silent)) ; already silent ;; NB: to be more accurate we should only count number ;; of scripting items in the list (not e.g. invisibles). ;; More efficient: keep track of size of queue as modified. (>= (length proof-action-list) proof-shell-silent-threshold))) (defsubst proof-shell-should-not-be-silent () "Non-nil if we should switch to non silent mode based on size of queue." (if (and proof-shell-stop-silent-cmd ; configured proof-shell-silent) ; already non silent ;; NB: to be more accurate we should only count number ;; of scripting items in the list (not e.g. invisibles). ;; More efficient: keep track of size of queue as modified. (< (length proof-action-list) proof-shell-silent-threshold))) (defsubst proof-shell-insert-action-item (item) "Insert ITEM from `proof-action-list' into the proof shell." (proof-shell-insert (nth 1 item) (nth 2 item) (nth 0 item))) (defsubst proof-shell-slurp-comments () "Strip comments at front of `proof-action-list', returning items stripped. Comments are not sent to the prover." (let (cbitems nextitem) (while (and proof-action-list (not (nth 1 (setq nextitem (car proof-action-list))))) (setq cbitems (cons nextitem cbitems)) (setq proof-action-list (cdr proof-action-list))) (nreverse cbitems))) (defun proof-add-to-queue (queueitems &optional queuemode) "Chop off the vacuous prefix of the QUEUEITEMS and queue them. For each item with a nil command at the head of the list, invoke its callback and remove it from the list. Append the result onto `proof-action-list', and if the proof shell isn't already busy, grab the lock with QUEUEMODE and start processing the queue. If the proof shell is busy when this function is called, then QUEUEMODE must match the mode of the queue currently being processed." (when (and queueitems proof-action-list) ;; internal check: correct queuemode in force if busy ;; (should have proof-action-list<>nil -> busy) (and proof-shell-busy queuemode (unless (eq proof-shell-busy queuemode) (proof-debug "proof-append-alist: wrong queuemode detected for busy shell") (cl-assert (eq proof-shell-busy queuemode))))) (let ((nothingthere (null proof-action-list))) ;; Now extend or start the queue. (setq proof-action-list (nconc proof-action-list queueitems)) (when nothingthere ; process comments immediately (let ((cbitems (proof-shell-slurp-comments))) (mapc 'proof-shell-invoke-callback cbitems))) (if proof-action-list ;; something to do (progn (when (proof-shell-should-be-silent) ;; do this ASAP, either first or just after current command (setq proof-action-list (if nothingthere ; the first thing (cons (proof-shell-start-silent-item) proof-action-list) (cons (car proof-action-list) ; after current (cons (proof-shell-start-silent-item) (cdr proof-action-list)))))) ;; Sometimes the non silent mode needs to be set because a ;; previous error prevented to go back to non silent mode (when (proof-shell-should-not-be-silent) ;; do this ASAP, either first or just after current command (setq proof-action-list (if nothingthere ; the first thing (cons (proof-shell-stop-silent-item) proof-action-list) (cons (car proof-action-list) ; after current (cons (proof-shell-stop-silent-item) (cdr proof-action-list)))))) (when nothingthere ; start sending commands (proof-grab-lock queuemode) (setq proof-shell-last-output-kind nil) (proof-shell-insert-action-item (car proof-action-list)))) (if proof-second-action-list-active ;; primary action list is empty, but there are items waiting ;; somewhere else (proof-grab-lock queuemode) ;; nothing to do: maybe we completed a list of comments without sending them (proof-detach-queue))))) (defun proof-start-prover-with-priority-items-maybe () "Start processing priority items if necessary. If there are priority items and the proof shell is not busy with other items, then this function starts the prover with the priority items. This function relies on the invariants of `proof-shell-filter-active' and on `proof-action-list'. The latter is non-empty, if there is some item, which has not been fully processed yet. Note that inside `proof-shell-exec-loop' the priority items are processed without calling this function." (when (and proof-priority-action-list (null proof-action-list) (not proof-shell-filter-active)) ;; not sure how fast we end up in proof-shell-exec-loop, better to clear ;; proof-priority-action-list here before calling proof-add-to-queue (let ((copy proof-priority-action-list)) (setq proof-priority-action-list nil) ;; add to queue with the right mode - simply use the current mode (proof-add-to-queue (nreverse copy) proof-shell-busy)))) (defun proof-add-to-priority-queue (queueitem) "Add item to `proof-priority-action-list' and start the queue if necessary. Argument QUEUEITEM must be an action item as documented for `proof-action-list'. Add flag 'priority-action to QUEUEITEM, such that priority items can be recognized and the order of added priority items can be preserved." (let ((qi (list (car queueitem) (cadr queueitem) (cl-caddr queueitem) (cons 'priority-action (cl-cadddr queueitem))))) (push qi proof-priority-action-list) (proof-start-prover-with-priority-items-maybe))) ;;;###autoload (defun proof-start-queue (start end queueitems &optional queuemode) "Begin processing a queue of commands. If START is non-nil, START and END are buffer positions in the active scripting buffer for the queue region. This function calls ‘proof-add-to-queue’ with args QUEUEITEMS and QUEUEMODE." (if start (proof-set-queue-endpoints start end)) (proof-add-to-queue queueitems queuemode)) ;;;###autoload (defun proof-extend-queue (end queueitems) "Extend the current queue with QUEUEITEMS, queue end END. To make sense, the commands should correspond to processing actions for processing a region from (buffer-queue-or-locked-end) to END. The queue mode is set to 'advancing" (proof-set-queue-endpoints (proof-unprocessed-begin) end) (condition-case err (run-hooks 'proof-shell-extend-queue-hook) ((error quit) (proof-detach-queue) (signal (car err) (cdr err)))) (proof-add-to-queue queueitems 'advancing)) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; MAIN LOOP ;; (defun proof-shell-exec-loop () "Main loop processing the `proof-action-list', called from shell filter. `proof-action-list' contains a list of (SPAN COMMAND ACTION [FLAGS]) lists. If this function is called with a non-empty `proof-action-list', the head of the list is the previously executed command which succeeded. We execute the callback (ACTION SPAN) on the first item, then (ACTION SPAN) on any following items which have null as their cmd components. If a there is a next command after that, send it to the process. If the action list becomes empty, unlock the process and remove the queue region. The return value is non-nil if the action list is now empty or contains only invisible elements for Prooftree synchronization." (unless (null proof-action-list) (save-excursion (if proof-script-buffer ; switch to active script (set-buffer proof-script-buffer)) (let* ((item (car proof-action-list)) (flags (nth 3 item)) cbitems) ;; now we should invoke callback on just processed command, ;; but we delay this until sending the next command, attempting ;; to parallelize prover and Emacs somewhat. (PG 4.0 change) (setq proof-action-list (cdr proof-action-list)) (setq cbitems (cons item (proof-shell-slurp-comments))) ;; If proof-action-list is empty after removing the already ;; processed actions and the last action was not already ;; added by proof-shell-empty-action-list-command (prover ;; specific), call it. (when (and (null proof-action-list) (not (memq 'empty-action-list flags)) proof-shell-empty-action-list-command) (let* ((cmd (mapconcat 'identity (nth 1 item) " ")) (extra-cmds (apply proof-shell-empty-action-list-command (list cmd))) ;; tag all new items with 'empty-action-list (extra-items (mapcar (lambda (s) (proof-shell-action-list-item s 'proof-done-invisible (list 'invisible 'empty-action-list))) extra-cmds))) ;; action-list should be empty at this point (setq proof-action-list (append extra-items proof-action-list)))) ;; This is the point where old items have been removed from ;; proof-action-list and where the next item has not yet been ;; sent to the proof assistant. This is therefore one of the ;; few points where it is safe to manipulate ;; proof-action-list. The urgent proof-tree display actions ;; must therefore be called here, because they might add some ;; Show actions at the front of proof-action-list. (if proof-tree-external-display (proof-tree-urgent-action flags)) ;; Add priority actions to the front of proof-action-list. ;; Delay adding of priority items until there is no priority ;; item at the head of `proof-action-list', such that more ;; recently added priority items cannot overtake older items ;; that wait in `proof-action-list'. (when (and proof-priority-action-list (or (null proof-action-list) (not (member 'priority-action (nth 3 (car proof-action-list)))))) (setq proof-action-list (nconc (nreverse proof-priority-action-list) proof-action-list)) (setq proof-priority-action-list nil)) ;; if action list is (nearly) empty, ensure prover is noisy. (if (and proof-shell-silent (not (eq (nth 2 item) 'proof-shell-clear-silent)) (or (null proof-action-list) (null (cdr proof-action-list)))) ;; Insert the quieten command on head of queue (setq proof-action-list (cons (proof-shell-stop-silent-item) proof-action-list))) ;; pending interrupts: we want to stop the queue here (when proof-shell-interrupt-pending (mapc 'proof-shell-invoke-callback cbitems) (setq cbitems nil) (proof-shell-handle-error-or-interrupt 'interrupt flags)) (if proof-action-list ;; send the next command to the process. (proof-shell-insert-action-item (car proof-action-list))) ;; process the delayed callbacks now (mapc 'proof-shell-invoke-callback cbitems) (unless (or proof-action-list proof-second-action-list-active) ; release lock, cleanup (proof-release-lock) (proof-detach-queue) (unless flags ; hint after a batch of scripting (pg-processing-complete-hint)) (pg-finish-tracing-display)) (and (not proof-second-action-list-active) (let ((last-command (car (nth 1 (car (last proof-action-list)))))) (or (null proof-action-list) (cl-every (lambda (item) (memq 'proof-tree-show-subgoal (nth 3 item))) proof-action-list) ;; If the last command in proof-action-list is a "Show Proof" form then return t (when last-command (proof-shell-string-match-safe proof-show-proof-diffs-regexp last-command))))))))) (defun proof-shell-insert-loopback-cmd (cmd) "Insert command string CMD sent from prover into script buffer. String is inserted at the end of locked region, after a newline and indentation. Assumes `proof-script-buffer' is active." (unless (string-match "^\\s-*$" cmd) ; FIXME: assumes cmd is single line (with-current-buffer proof-script-buffer (let (span) (proof-goto-end-of-locked) (let ((proof-one-command-per-line t)) ; because pbp several commands (proof-script-new-command-advance)) (insert cmd) ;; NB: difference between ordinary commands and pbp is that ;; pbp can return *several* commands, that are treated as ;; a unit, i.e. sent to the proof assistant together. ;; FIXME da: this seems very similar to proof-insert-pbp-command ;; in proof-script.el. Should be unified, I suspect. (setq span (span-make (proof-unprocessed-begin) (point))) (span-set-property span 'type 'pbp) (span-set-property span 'cmd cmd) (proof-set-queue-endpoints (proof-unprocessed-begin) (point)) (setq proof-action-list (cons (car proof-action-list) (cons (list span cmd 'proof-done-advancing) (cdr proof-action-list)))))))) (defun proof-shell-process-urgent-message (start end) "Analyse urgent message between START and END for various cases. Cases are: *trace* output, included/retracted files, cleared goals/response buffer, variable setting, xml-encoded PGIP response, theorem dependency message or interactive output indicator. If none of these apply, display the text between START and END. The text between START and END should be a string that starts with text matching `proof-shell-eager-annotation-start' and ends with text matching `proof-shell-eager-annotation-end'." (goto-char start) (cond ((proof-looking-at-safe proof-shell-trace-output-regexp) (proof-shell-process-urgent-message-trace start end)) ((proof-looking-at-safe (car-safe proof-shell-process-file)) (let ((file (funcall (cdr proof-shell-process-file)))) (if (and file (not (string= file ""))) (proof-register-possibly-new-processed-file file)))) ((proof-looking-at-safe proof-shell-retract-files-regexp) (proof-shell-process-urgent-message-retract start end)) ((proof-looking-at-safe proof-shell-clear-response-regexp) (pg-response-maybe-erase nil t t)) ((proof-looking-at-safe proof-shell-clear-goals-regexp) (proof-clean-buffer proof-goals-buffer)) ((proof-looking-at-safe proof-shell-match-pgip-cmd) (pg-pgip-process-packet ;; NB: xml-parse-region ignores junk before XML (xml-parse-region start end))) ((proof-looking-at-safe proof-shell-theorem-dependency-list-regexp) (proof-shell-process-urgent-message-thmdeps)) ((proof-looking-at-safe proof-shell-theorem-dependency-list-regexp) (proof-shell-process-urgent-message-thmdeps)) ((proof-looking-at-safe proof-shell-interactive-prompt-regexp) (proof-shell-process-interactive-prompt-regexp)) (t (proof-shell-process-urgent-message-default start end)))) ;; ;; urgent message subroutines ;; (defun proof-shell-process-urgent-message-default (start end) "A subroutine of `proof-shell-process-urgent-message'." ;; Clear the response buffer this time, but not next, leave window. (pg-response-maybe-erase nil nil) (proof-minibuffer-message (buffer-substring-no-properties (save-excursion (re-search-forward proof-shell-eager-annotation-start end nil) (point)) (min end (save-excursion (end-of-line) (point)) (+ start 75)))) (pg-response-display-with-face (proof-shell-strip-eager-annotations start end) 'proof-eager-annotation-face)) (defun proof-shell-process-urgent-message-trace (start end) "Display a message in the tracing buffer. A subroutine of `proof-shell-process-urgent-message'." (proof-trace-buffer-display start end) (unless (and proof-trace-output-slow-catchup (pg-tracing-tight-loop)) (proof-display-and-keep-buffer proof-trace-buffer)) ;; If user quits during tracing output, send an interrupt ;; to the prover. Helps when Emacs is "choking". (if (and quit-flag proof-action-list) (proof-interrupt-process))) (defun proof-shell-process-urgent-message-retract (start end) "A subroutine of `proof-shell-process-urgent-message'. Take files off `proof-included-files-list' and call `proof-restart-buffers' to do the necessary clean-up on those buffers visiting a file that disappears from `proof-included-files-list'. So in some respect, this function is inverse to `proof-register-possibly-new-processed-file'." (let ((current-included proof-included-files-list)) (setq proof-included-files-list (funcall proof-shell-compute-new-files-list)) (let ((scrbuf proof-script-buffer)) ;; NB: we assume that no new buffers are *added* by ;; the proof-shell-compute-new-files-list (proof-restart-buffers (proof-files-to-buffers (cl-set-difference current-included proof-included-files-list))) (cond ;; Do nothing if there was no active scripting buffer ((not scrbuf)) ;; Do nothing if active buffer hasn't changed (may be nuked) ((eq scrbuf proof-script-buffer)) ;; Otherwise, active scripting buffer has been retracted. (t (setq proof-script-buffer nil)))))) (defun proof-shell-process-urgent-message-elisp () "A subroutine of `proof-shell-process-urgent-message'." (let ((variable (match-string 1)) (expr (match-string 2))) (condition-case nil (with-temp-buffer (insert expr) ; massive risk from malicious provers!! (set (intern variable) (eval-last-sexp t))) (t (proof-debug (concat "lisp error when obeying proof-shell-set-elisp-variable: \n" "setting `" variable "'\n to: \n" expr "\n")))))) (defun proof-shell-process-urgent-message-thmdeps () "A subroutine of `proof-shell-process-urgent-message'." (let ((names (match-string 1)) (deps (match-string 2)) (sep proof-shell-theorem-dependency-list-split)) (setq proof-last-theorem-dependencies (cons (split-string names sep) (split-string deps sep))))) (defun proof-shell-process-interactive-prompt-regexp () "Action taken when `proof-shell-interactive-prompt-regexp' is observed." (when (and (proof-shell-live-buffer) ; not already visible t) (switch-to-buffer proof-shell-buffer) (message "Prover expects input in %s buffer" proof-shell-buffer))) ;; ;; urgent message utilities ;; (defun proof-shell-strip-eager-annotations (start end) "Strip `proof-shell-eager-annotation-{START,END}' from region." (goto-char start) (if (re-search-forward proof-shell-eager-annotation-start end nil) (setq start (point))) (if (re-search-forward proof-shell-eager-annotation-end end nil) (setq end (match-beginning 0))) (buffer-substring-no-properties start end)) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; The proof shell process filter ;; (defun proof-shell-filter-wrapper (str-do-not-use) "Wrapper for `proof-shell-filter', protecting against parallel calls. In Emacs a process filter function can be called while the same filter is currently running for the same process, for instance, when the filter blocks on I/O. This wrapper protects the main entry point, `proof-shell-filter' against such parallel, overlapping calls. The argument STR-DO-NOT-USE contains the most recent output, but is discarded. `proof-shell-filter' collects the output from `proof-shell-buffer' (where it is inserted by `scomint-output-filter'), relieving this function from the task to buffer the output that arrives during parallel, overlapping calls." (if proof-shell-filter-active (progn (setq proof-shell-filter-was-blocked t)) (let ((call-proof-shell-filter t)) (while call-proof-shell-filter (setq proof-shell-filter-active t proof-shell-filter-was-blocked nil) (condition-case err (progn (proof-shell-filter) (setq proof-shell-filter-active nil)) ((error quit) (setq proof-shell-filter-active nil proof-shell-filter-was-blocked nil) (signal (car err) (cdr err)))) (setq call-proof-shell-filter proof-shell-filter-was-blocked))) ;; finally leaving proof-shell-filter - maybe somebody has added ;; priority items inside proof-shell-filter? (proof-start-prover-with-priority-items-maybe))) (defun proof-shell-filter () "Master filter for the proof assistant shell-process. A function for `scomint-output-filter-functions'. Deal with output and issue new input from the queue. This is an important internal function. The output must be collected from `proof-shell-buffer' for the following reason. This function might block inside `process-send-string' when sending input to the proof assistant or to prooftree. In this case Emacs might call the process filter again while the previous instance is still running. `proof-shell-filter-wrapper' detects and delays such calls but does not buffer the output. Handle urgent messages first. As many as possible are processed, using the function `proof-shell-process-urgent-messages'. If a prompt is seen, run `proof-shell-filter-manage-output' on the output between the new prompt and the last input (position of `proof-marker') or the last urgent message (position of `proof-shell-urgent-message-marker'), whichever is later. For example, in this case: PROMPT> INPUT OUTPUT-1 URGENT-MESSAGE-1 OUTPUT-2 URGENT-MESSAGE-2 OUTPUT-3 PROMPT> `proof-marker' points after INPUT. `proof-shell-urgent-message-marker' points after URGENT-MESSAGE-2, after both urgent messages have been processed by `proof-shell-process-urgent-messages'. Urgent messages always processed; they are intended to correspond to informational notes that the prover makes to inform the user or interface on progress. In this case, the ordinary outputs OUTPUT-1 and OUTPUT-2 are ignored; only OUTPUT-3 will be processed by `proof-shell-filter-manage-output'. Error or interrupt messages are expected to terminate an interactive output and appear last before a prompt and will always be processed. Error messages and interrupt messages are therefore *not* considered as urgent messages. The first time that a prompt is seen, `proof-marker' is initialised to the end of the prompt. This should correspond with initializing the process. After that, `proof-marker' is only changed when input is sent in `proof-shell-insert'." (save-excursion ;; Process urgent messages. (and proof-shell-eager-annotation-start (proof-shell-process-urgent-messages)) (let ((pos (marker-position proof-marker))) (if (not pos) (proof-shell-filter-first-command) (if proof-action-list ;; We were expecting some output. Wait until output is ;; complete. Only one piece of output is dealt with at a ;; time; we loose sync if there's more than one bit there. (let ((urgnt (marker-position proof-shell-urgent-message-marker)) (prev-prompt pos) (startpos pos) endpos) ;; Ignore any urgent messages that have already been dealt ;; with. This loses in the case mentioned above. Instead ;; might try to delete/filter out old urgent messages. (goto-char pos) (if (and urgnt (< startpos urgnt)) (setq startpos (goto-char urgnt)) ;; Otherwise, skip possibly a (fudge) space and new line (if (eq (char-after startpos) ?\ ) (setq startpos (goto-char (+ 2 startpos))) (setq startpos (goto-char (1+ startpos))))) ;; Find next prompt. (if (re-search-forward proof-shell-annotated-prompt-regexp nil t) (progn (setq endpos (match-beginning 0)) (setq proof-shell-last-prompt (buffer-substring-no-properties endpos (match-end 0))) (goto-char (point-max)) ;; Process output string. (proof-shell-filter-manage-output startpos endpos)))) ;; Not expecting output, ignore it. Busy flag should be clear. (if proof-shell-busy (progn (proof-debug "proof-shell-filter found empty action list yet proof shell busy.") (proof-release-lock)))))))) (defun proof-shell-filter-first-command () "Deal with initial output. A subroutine of `proof-shell-filter'. This initialises `proof-marker': we set marker to after the first prompt in the output buffer if one can be found now. The first time a prompt is seen we ignore any output that occurred before it, assuming that corresponds to uninteresting startup messages." (goto-char (point-min)) (if (re-search-forward proof-shell-annotated-prompt-regexp nil t) (progn (set-marker proof-marker (point)) (proof-shell-exec-loop)))) (defun proof-shell-process-urgent-messages () "Scan the shell buffer for urgent messages. Scanning starts from `proof-shell-urgent-message-scanner' or `scomint-last-input-end', which ever is later. We deal with strings between regexps `proof-shell-eager-annotation-start' and `proof-shell-eager-annotation-end'. We update `proof-shell-urgent-message-marker' to point to last message found. This is a subroutine of `proof-shell-filter'." (let ((pt (point)) (end t) lastend laststart (initstart (max (marker-position proof-shell-urgent-message-scanner) (marker-position scomint-last-input-end)))) (goto-char initstart) (while (and end (re-search-forward proof-shell-eager-annotation-start nil 'limit)) (setq laststart (match-beginning 0)) (if (setq end (re-search-forward proof-shell-eager-annotation-end nil t)) (save-excursion (setq lastend end) ;; Process the region including the annotations (proof-shell-process-urgent-message laststart lastend)))) (set-marker proof-shell-urgent-message-scanner (if end ;; couldn't find message start; move forward to avoid rescanning (max initstart (- (point) (1+ proof-shell-eager-annotation-start-length))) ;; incomplete message; leave marker at start of message laststart)) ;; Set position of last urgent message found (if lastend (set-marker proof-shell-urgent-message-marker lastend)) (goto-char pt))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Despatching output ;; (defun proof-shell-filter-manage-output (start end) "Subroutine of `proof-shell-filter' for output between START and END. First, we invoke `proof-shell-handle-immediate-output' which classifies and handles output that must be dealt with immediately. Other output (user display) is only displayed when the proof action list becomes empty, to avoid a confusing rapidly changing output that slows down processing. After processing the current output, the last step undertaken by the filter is to send the next command from the queue." (let ((span (caar proof-action-list)) (cmd (nth 1 (car proof-action-list))) (flags (nth 3 (car proof-action-list))) (old-proof-marker (marker-position proof-marker))) ;; A copy of the last message, verbatim, never modified. (setq proof-shell-last-output (buffer-substring-no-properties start end)) ;; sets proof-shell-last-output-kind (proof-shell-handle-immediate-output cmd start end flags) (unless proof-shell-last-output-kind ; dealt with already (setq proof-shell-delayed-output-start start) (setq proof-shell-delayed-output-end end) (setq proof-shell-delayed-output-flags flags) (if (proof-shell-exec-loop) (setq proof-shell-last-output-kind ;; only display result for last output (proof-shell-handle-delayed-output))) ;; send output to the proof tree visualizer (if proof-tree-external-display (proof-tree-handle-delayed-output old-proof-marker cmd flags span))))) (defsubst proof-shell-display-output-as-response (flags str) "If FLAGS permit, display response STR; set `proof-shell-last-response-output'." (setq proof-shell-last-response-output str) ; set even if not displayed (unless (memq 'no-response-display flags) (pg-response-display str))) (defun proof-shell-handle-delayed-output () "Display delayed goals/responses, when queue is stopped or completed. This function handles the cases of `proof-shell-output-kind' which are not dealt with eagerly during script processing, namely 'response and 'goals types. This is useful even with empty delayed output as it will empty the buffers. The delayed output is in the region \[proof-shell-delayed-output-start,proof-shell-delayed-output-end]. If no goals classified output is found, the whole output is displayed in the response buffer. If goals output is found, the last matching instance, possibly bounded by `proof-shell-end-goals-regexp', will be displayed in the goals buffer (and may be further analysed by Proof General). Any output that appears *before* the last goals output (but after messages classified as urgent, see `proof-shell-filter') will also be displayed in the response buffer. For example, if OUTPUT has this form: MESSSAGE-1 GOALS-1 MESSAGE-2 GOALS-2 JUNK then GOALS-2 will be displayed in the goals buffer, and MESSAGE-2 in the response buffer. JUNK will be ignored. Notice that the above alternation (and separation of JUNK) can only be distinguished if both `proof-shell-start-goals-regexp' and `proof-shell-end-goals-regexp' are set. With just the start goals regexp set, GOALS-2 JUNK will appear in the goals buffer and no response output would occur. The goals and response outputs are copied into `proof-shell-last-goals-output' and `proof-shell-last-response-output' respectively. The value returned is the value for `proof-shell-last-output-kind', i.e., 'goals or 'response." (let ((start proof-shell-delayed-output-start) (end proof-shell-delayed-output-end) (flags proof-shell-delayed-output-flags)) (goto-char start) (cond ((and proof-shell-start-goals-regexp (proof-re-search-forward proof-shell-start-goals-regexp end t)) (let* ((gmark (match-beginning 0)) ; start of goals message (gstart (or (match-end 1) ; start of actual display gmark)) (rstart start) ; possible response before goals (gend end) both) ; flag for response+goals (goto-char gstart) (while (re-search-forward proof-shell-start-goals-regexp end t) (setq gmark (match-beginning 0)) (setq gstart (or (match-end 1) gmark)) (setq gend (if (and proof-shell-end-goals-regexp (re-search-forward proof-shell-end-goals-regexp end t)) (progn (setq rstart (match-end 0)) (match-beginning 0)) end))) (setq proof-shell-last-goals-output (buffer-substring-no-properties gstart gend)) ;; FIXME heuristic: 4 allows for annotation in end-goals-regexp [is it needed?] (setq both (> (- gmark rstart) 4)) (if both (proof-shell-display-output-as-response flags (buffer-substring-no-properties rstart gmark))) ;; display goals output second so it persists in 2-pane mode (unless (memq 'no-goals-display flags) (pg-goals-display proof-shell-last-goals-output both)) ;; indicate a goals output has been given 'goals)) (t (proof-shell-display-output-as-response flags proof-shell-last-output) ;; indicate that (only) a response output has been given 'response)) ;; FIXME (CPC 2015-12-31): The documentation of this hook suggests that it ;; only gets run after new output has been displayed, but this isn't true at ;; the moment: indeed, it gets run even for invisible commands. ;; ;; This causes issues in company-coq, where completion uses invisible ;; commands to display the types of completion candidates; this causes the ;; goals and response buffers to scroll. I fixed it by adding checks to ;; coq-mode's hooks, but maybe we should do more. (run-hooks 'proof-shell-handle-delayed-output-hook))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Tracing slow down: prevent Emacs-consumes-all-CPU-displaying phenomenon ;; ;; Possible improvement: add user-controlled flag to turn on/off display (defvar pg-last-tracing-output-time (float-time) "Time of last tracing output, as recorded by (float-time).") (defvar pg-last-trace-output-count 0 "Count up to `pg-slow-mode-trigger-count'.") (defconst pg-slow-mode-trigger-count 20 "Number of fast trace messages before turning on slow mode.") (defconst pg-slow-mode-duration 3 "Maximum duration of slow mode in seconds.") (defconst pg-fast-tracing-mode-threshold 500000 "Minimum microsecond delay between tracing outputs that triggers slow mode.") (defun pg-tracing-tight-loop () "Return non-nil in case it seems like prover is dumping a lot of output. This is a performance hack to avoid Emacs consuming CPU when prover is output tracing information. Only works when system timer has microsecond count available." (let ((tm (float-time)) (dontprint pg-tracing-slow-mode)) (if pg-tracing-slow-mode (when ;; seconds differs by more than slow mode max duration (> (- tm pg-last-tracing-output-time) pg-slow-mode-duration) (setq dontprint nil)) (when ;; time since last tracing output less than threshold (and (< (- tm pg-last-tracing-output-time) (/ pg-fast-tracing-mode-threshold 1000000.0)) (>= (cl-incf pg-last-trace-output-count) pg-slow-mode-trigger-count)) ;; quickly consecutive tracing outputs: go into slow mode (setq dontprint t) (pg-slow-fontify-tracing-hint))) ;; return flag for non-printing is new value of slow mode (setq pg-last-tracing-output-time tm) (setq pg-tracing-slow-mode dontprint))) (defun pg-finish-tracing-display () "Handle the end of possibly voluminous tracing-style output. If the output update was slowed down, show it now." (proof-trace-buffer-finish) (when pg-tracing-slow-mode (proof-display-and-keep-buffer proof-trace-buffer) (setq pg-tracing-slow-mode nil)) (setq pg-last-trace-output-count 0)) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; proof-shell-invisible-command: for user-level commands. ;; ;;;###autoload (defun proof-shell-wait (&optional interrupt-on-input timeoutsecs) "Busy wait for `proof-shell-busy' to become nil, reading from prover. Needed between sequences of commands to maintain synchronization, because Proof General does not allow for the action list to be extended in some cases. Also is considerably faster than leaving the Emacs top-level command loop to read from the prover. Called by `proof-shell-invisible-command' and `proof-process-buffer' when setting `proof-fast-process-buffer' is enabled. If INTERRUPT-ON-INPUT is non-nil, return if input is received. If TIMEOUTSECS is a number, time out after that many seconds." (let* ((proverproc (get-buffer-process proof-shell-buffer)) (accepttime 0.01) (timecount (if (numberp timeoutsecs) (/ timeoutsecs accepttime)))) (when proverproc (while (and proof-shell-busy (not quit-flag) (if timecount (> (setq timecount (1- timecount)) 0) t) (not (and interrupt-on-input (input-pending-p)))) ;; TODO: check below OK on GE 22/23.1. See Trac #324 (accept-process-output proverproc accepttime nil 1)) (redisplay) (if quit-flag (error "Proof General: quit in proof-shell-wait"))))) (defun proof-done-invisible (span) "Callback for ‘proof-shell-invisible-command’. Call ‘proof-state-change-hook’." (run-hooks 'proof-state-change-pre-hook) (run-hooks 'proof-state-change-hook)) ;;;###autoload (defun proof-shell-invisible-command (cmd &optional wait invisiblecallback &rest flags) "Send CMD to the proof process. The CMD is `invisible' in the sense that it is not recorded in buffer. CMD may be a string or a string-yielding expression. Automatically add `proof-terminal-string' if necessary, examining `proof-shell-no-auto-terminate-commands'. By default, let the command be processed asynchronously. But if optional WAIT command is non-nil, wait for processing to finish before and after sending the command. In case CMD is (or yields) nil, do nothing. INVISIBLECALLBACK will be invoked after the command has finished, if it is set. It should probably run the hook variables `proof-state-change-hook'. FLAGS are additional flags to put onto the `proof-action-list'. The flag 'invisible is always added to FLAGS." (unless (stringp cmd) (setq cmd (eval cmd))) (if cmd (progn (unless (or (null proof-terminal-string) (not proof-shell-auto-terminate-commands) (string-match (concat (regexp-quote proof-terminal-string) "[ \t]*$") cmd)) (setq cmd (concat cmd proof-terminal-string))) (if wait (proof-shell-wait)) (proof-shell-ready-prover) ; start proof assistant; set vars. (let* ((callback (or invisiblecallback #'proof-done-invisible))) (proof-start-queue nil nil (list (proof-shell-action-list-item cmd callback (cons 'invisible flags))))) (if wait (proof-shell-wait))))) ;;;###autoload (defun proof-shell-invisible-cmd-get-result (cmd) "Execute CMD and return result as a string. This expects CMD to result in some theorem prover output. Ordinary output (and error handling) is disabled, and the result \(contents of `proof-shell-last-output') is returned as a string." (proof-shell-invisible-command cmd 'waitforit nil 'no-response-display 'no-error-display) proof-shell-last-output) ;;;###autoload (defun proof-shell-invisible-command-invisible-result (cmd) "Execute CMD for side effect in the theorem prover, waiting before and after. Error messages are displayed as usual." (proof-shell-invisible-command cmd 'waitforit nil 'no-response-display)) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; User-level functions depending on shell commands ;; ;; ;; Function to insert last prover output in comment. ;; Requested/suggested by Christophe Raffalli ;; (defun pg-insert-last-output-as-comment () "Insert the last output from the proof system as a comment in the proof script." (interactive) (if proof-shell-last-output (let ((beg (point))) (insert (proof-shell-strip-output-markup proof-shell-last-output)) (comment-region beg (point))))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Proof General shell mode definition ;; ;;;###autoload (define-derived-mode proof-shell-mode scomint-mode "proof-shell" "Proof General shell mode class for proof assistant processes" (setq proof-buffer-type 'shell) (proof-shell-clear-state) (buffer-disable-undo) ;; scomint customisation. (setq scomint-output-filter-functions (append (if proof-shell-strip-crs-from-output 'scomint-strip-ctrl-m) (list 'proof-shell-filter-wrapper))) (setq proof-marker ; follows prompt (make-marker) proof-shell-urgent-message-marker (make-marker) ; follows urgent messages proof-shell-urgent-message-scanner (make-marker)) ; last scan point (set-marker proof-shell-urgent-message-scanner (point-min)) ;; Make cut functions work with proof shell output (add-hook 'buffer-substring-filters 'proof-shell-strip-output-markup) ;; Note: before entering proof assistant specific code, we could ;; check that process is up and running. If not, could call the ;; sentinel to display the buffer, and give error. ) ;; ;; Sanity checks on important settings ;; (defconst proof-shell-important-settings '(proof-shell-annotated-prompt-regexp ; crucial )) ;;;###autoload (defun proof-shell-config-done () "Initialise the specific prover after the child has been configured. Every derived shell mode should call this function at the end of processing." (with-current-buffer proof-shell-buffer ;; Give warnings if some crucial settings haven't been made (dolist (sym proof-shell-important-settings) (proof-warn-if-unset "proof-shell-config-done" sym)) ;; Set font lock keywords, but turn off by default to save cycles. (setq font-lock-defaults '(proof-shell-font-lock-keywords)) (set (make-local-variable 'font-lock-global-modes) (list 'not proof-mode-for-shell)) (let ((proc (get-buffer-process proof-shell-buffer))) ;; Add the kill buffer function and process sentinel (add-hook 'kill-buffer-hook 'proof-shell-kill-function t t) (set-process-sentinel proc 'proof-shell-bail-out) ;; Pre-sync initialization command. Necessary for provers which ;; change output modes only after some initializations. (if proof-shell-pre-sync-init-cmd (proof-shell-insert proof-shell-pre-sync-init-cmd 'init-cmd)) ;; Flush pending output from startup (it gets hidden from the user) ;; while waiting for the prompt to appear (while (and (memq (process-status proc) '(open run)) (null (marker-position proof-marker))) (accept-process-output proc 1)) (if (memq (process-status proc) '(open run)) (progn ;; Also ensure that proof-action-list is initialised. (setq proof-action-list nil) ;; Send main intitialization command and wait for it to be ;; processed. ;; First, configure PGIP preferences (even before init cmd) ;; available: this allows setting them after the init cmd. (proof-maybe-askprefs) ;; Now send the initialisation commands. (unwind-protect (progn (run-hooks 'proof-shell-init-hook) (when proof-shell-init-cmd (if (listp proof-shell-init-cmd) (mapc 'proof-shell-invisible-command-invisible-result proof-shell-init-cmd) (proof-shell-invisible-command-invisible-result proof-shell-init-cmd))) (proof-shell-wait) (if proof-assistant-settings (mapcar (lambda (c) (proof-shell-invisible-command c t)) (proof-assistant-settings-cmds)))))))))) (provide 'proof-shell) ;;; proof-shell.el ends here PG-4.5/generic/proof-site.el000066400000000000000000000267051426357011200157300ustar00rootroot00000000000000;;; proof-site.el --- Loading stubs for Proof General -*- lexical-binding:t -*- ;; This file is part of Proof General. ;; Portions © Copyright 1994-2012 David Aspinall and University of Edinburgh ;; Portions © Copyright 2003-2021 Free Software Foundation, Inc. ;; Portions © Copyright 2001-2017 Pierre Courtieu ;; Portions © Copyright 2010, 2016 Erik Martin-Dorel ;; Portions © Copyright 2011-2013, 2016-2017 Hendrik Tews ;; Portions © Copyright 2015-2017 Clément Pit-Claudel ;; Author: David Aspinall ;; SPDX-License-Identifier: GPL-3.0-or-later ;;; Commentary: ;; ;; Loading stubs and configuration for site and choice of provers. ;; ;; NB: Normally users do not need to edit this file. Developers/installers ;; may want to adjust proof-assistant-table-default below. ;; ;; The environment variables PROOFGENERAL_HOME and PROOFGENERAL_ASSISTANTS ;; can be set to affect load behaviour; see info documentation. ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Master table of supported proof assistants. ;; ;;; Code: ;; Entries in proof-assistant-table-default are lists of the form ;; ;; (SYMBOL NAME FILE-EXTENSION [AUTOMODE-REGEXP] [IGNORED-EXTENSIONS-LIST]) ;; ;; FILE-EXTENSION is without dot ".". AUTOMODE-REGEXP is put into ;; auto-mode-alist, if it is not present, a regexp will be made up from ;; FILE-EXTENSION. IGNORED-EXTENSIONS-LIST, if present, is appended to ;; completion-ignored-extensions. See proof-assistant-table for more info. ;; (defconst proof-assistant-table-default '( ;; Main instances of PG. (coq "Coq" "v" nil (".vo" ".glob")) (easycrypt "EasyCrypt" "ec" "\\.eca?\\'") (phox "PhoX" "phx" nil (".phi" ".pho")) (qrhl "qRHL" "qrhl") ;; Cut-and-paste management only (pgshell "PG-Shell" "pgsh") (pgocaml "PG-OCaml" "pgml") (pghaskell "PG-Haskell" "pghci") ;; Incomplete/obsolete: ;; (demoisa "Isabelle Demo" "ML") ; obsolete ) "Default value for `proof-assistant-table', which see.") ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; PG version ;; (eval-and-compile ;; WARNING: do not edit next line (constant is edited in Makefile.devel) (defconst proof-general-version "Proof General Version 4.5." "Version string identifying Proof General release.")) (defconst proof-general-short-version (eval-when-compile (progn (string-match "Version \\([^ ]+\\)\\." proof-general-version) (match-string 1 proof-general-version)))) (defconst proof-general-version-year "2022") ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Top-level customization groups ;; (defgroup proof-general nil "Customization of Proof General." :group 'applications :prefix "proof-") (defgroup proof-general-internals nil "Customization of Proof General internals for proof assistant configuration." :group 'applications :group 'proof-general :prefix "proof-") ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Directories. Set at load time so compiled files can be relocated. ;; Load path must be extended manually during compilation. ;; (defconst proof-home-directory (let ((curfile (or (and load-in-progress load-file-name) buffer-file-name))) (if curfile (file-name-directory (directory-file-name (file-name-directory curfile))) (let ((s (getenv "PROOFGENERAL_HOME"))) (if s (file-name-as-directory s))))) "Directory where Proof General is installed. Based on where the file `proof-site.el' was loaded from. Falls back to consulting the environment variable `PROOFGENERAL_HOME' if proof-site.el couldn't know where it was executed from.") (defcustom proof-images-directory (expand-file-name "images/" proof-home-directory) "Where Proof General image files are installed. Ends with slash." :type 'directory :group 'proof-general-internals) (defcustom proof-info-directory (expand-file-name "doc/" proof-home-directory) "Where Proof General Info files are installed. Ends with slash." :type 'directory :group 'proof-general-internals) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; load path. Have one function that adds elements to load-path. ;; Distributions having specific requirements (such as using ;; debian-pkg-add-load-path-item on Debian) only need to change ;; this function. ;; (defun proof-add-to-load-path (dir) "Add DIR to `load-path' if not contained already." (add-to-list 'load-path dir)) (proof-add-to-load-path (expand-file-name "generic/" proof-home-directory)) (proof-add-to-load-path (expand-file-name "lib/" proof-home-directory)) ;; Declare some global variables and autoloads ;; FIXME: Many of the autoloaded functions in there are internal to PG, and ;; are useless until PG is loaded, so they shouldn't be defined just because ;; proof-site is loaded! (require 'proof-autoloads) (defvar Info-dir-contents) ;; Add the info directory to the Info path (if (file-exists-p proof-info-directory) ; for safety (if (and (boundp 'Info-directory-list) Info-directory-list) ;; Info is already initialized. Update its variables. (progn (add-to-list 'Info-directory-list proof-info-directory) (setq Info-dir-contents nil)) ;; Info is not yet initialized. Change its default. (add-to-list 'Info-default-directory-list proof-info-directory))) (defcustom proof-assistant-table (apply #'append (mapcar ;; Discard entries whose directories have been removed. (lambda (dne) (let ((atts (file-attributes (expand-file-name (symbol-name (car dne)) proof-home-directory)))) (if (and atts (eq 't (car atts))) (list dne) nil))) proof-assistant-table-default)) "Proof General's table of supported proof assistants. This is copied from `proof-assistant-table-default' at load time, removing any entries that do not have a corresponding directory under `proof-home-directory'. Each entry is a list of the form (SYMBOL NAME FILE-EXTENSION [AUTOMODE-REGEXP] [IGNORED-EXTENSIONS-LIST]) The NAME is a string, naming the proof assistant. The SYMBOL is used to form the name of the mode for the assistant, `SYMBOL-mode', run when files with AUTOMODE-REGEXP \(or with extension FILE-EXTENSION) are visited. If present, IGNORED-EXTENSIONS-LIST is a list of file-name extensions to be ignored when doing file-name completion (IGNORED-EXTENSIONS-LIST is added to `completion-ignored-extensions'). SYMBOL is also used to form the name of the directory and elisp file for the mode, which will be PROOF-HOME-DIRECTORY/SYMBOL/SYMBOL.el where PROOF-HOME-DIRECTORY is the value of the variable `proof-home-directory'." ;; FIXME: make the last two elements optional in the type :type '(repeat (list symbol string regexp string)) :group 'proof-general-internals) (defcustom proof-assistants nil (concat "Choice of proof assistants to use with Proof General. A list of symbols chosen from: " (mapconcat (lambda (astnt) (concat "`" (symbol-name (car astnt)) "'")) proof-assistant-table " ") ".\nIf nil, the default will be ALL available proof assistants. Each proof assistant defines its own instance of Proof General, providing session control, script management, etc. Proof General will be started automatically for the assistants chosen here. To avoid accidently invoking a proof assistant you don't have, only select the proof assistants you (or your site) may need. You can select which proof assistants you want by setting this variable before `proof-site.el' is loaded, or by setting the environment variable `PROOFGENERAL_ASSISTANTS' to the symbols you want, for example \"coq easycrypt\". Or you can edit the file `proof-site.el' itself. Note: to change proof assistant, you must start a new Emacs session.") :type (cons 'set (mapcar (lambda (astnt) (list 'const ':tag (nth 1 astnt) (nth 0 astnt))) proof-assistant-table)) :group 'proof-general) (defvar proof-general-configured-provers (or (mapcar #'intern (split-string (or (getenv "PROOFGENERAL_ASSISTANTS") ""))) proof-assistants (mapcar #'car proof-assistant-table)) "A list of the configured proof assistants. Set on startup to contents of environment variable PROOFGENERAL_ASSISTANTS, the Lisp variable `proof-assistants', or the contents of `proof-assistant-table'.") ;; Add auto-loads and load-path elements to support the ;; proof assistants selected, and define stub major mode functions (let ((assistants proof-general-configured-provers)) (while assistants (let* ((assistant (car assistants)) ; compiler bogus warning here (tableentry (or (assoc assistant proof-assistant-table) (error "Symbol %s is not in proof-assistant-table (in proof-site)" (symbol-name assistant)))) (assistant-name (nth 1 tableentry)) (regexp (or (nth 3 tableentry) (concat (regexp-quote ".") (regexp-quote (nth 2 tableentry)) "\\'"))) (sname (symbol-name assistant)) ;; NB: File name for each prover is the same as its symbol name! (elisp-file sname) ;; NB: Mode name for each prover is -mode! (proofgen-mode (intern (concat sname "-mode"))) ;; NB: Customization group for each prover is its l.c.'d name! ;; Stub to initialize and load specific code. (mode-stub ;; FIXME: Make it a closure with (:documentation EXP) ;; once we don't need compatibility with Emacs<25. `(lambda () ,(concat "Major mode for editing scripts for proof assistant " assistant-name ".\nThis is a stub which loads the real function.") (interactive) ;; Stop loading if proof-assistant is already set: ;; cannot work for more than one prover. (cond ((and (boundp 'proof-assistant) (not (string-equal proof-assistant ""))) (or (string-equal proof-assistant ,assistant-name) ;; If Proof General was partially loaded last time ;; and mode function wasn't redefined, be silent. (message (concat ,assistant-name " Proof General error: Proof General already in use for " proof-assistant)))) (t ;; prepare variables and load path (proof-ready-for-assistant (quote ,assistant) ,assistant-name) ;; load the real mode and invoke it. (load-library ,elisp-file) (,proofgen-mode)))))) (add-to-list 'auto-mode-alist (cons regexp proofgen-mode)) (unless (fboundp proofgen-mode) (fset proofgen-mode mode-stub)) (dolist (ext (nth 4 tableentry)) (add-to-list 'completion-ignored-extensions ext)) (setq assistants (cdr assistants))))) ;; ;; Easy entry points ;; (defun proof-chose-prover (prompt) (completing-read prompt (mapcar #'symbol-name proof-general-configured-provers))) (defun proofgeneral (prover) "Start proof general for prover PROVER." (interactive (list (proof-chose-prover "Start Proof General for theorem prover: "))) (proof-ready-for-assistant (intern prover) (nth 1 (assoc (intern prover) proof-assistant-table-default))) (require (intern prover))) (defun proof-visit-example-file (prover) "Visit a standardly named example file for prover PROVER." (interactive (list (proof-chose-prover "Visit example file for prover: "))) (find-file (expand-file-name (concat prover "/example." (nth 2 (assoc (intern prover) proof-assistant-table-default))) proof-home-directory))) (provide 'proof-site) ;;; proof-site.el ends here PG-4.5/generic/proof-splash.el000066400000000000000000000265201426357011200162510ustar00rootroot00000000000000;;; proof-splash.el --- Splash welcome screen for Proof General -*- lexical-binding: t; -*- ;; This file is part of Proof General. ;; Portions © Copyright 1994-2012 David Aspinall and University of Edinburgh ;; Portions © Copyright 2003-2021 Free Software Foundation, Inc. ;; Portions © Copyright 2001-2017 Pierre Courtieu ;; Portions © Copyright 2010, 2016 Erik Martin-Dorel ;; Portions © Copyright 2011-2013, 2016-2017 Hendrik Tews ;; Portions © Copyright 2015-2017 Clément Pit-Claudel ;; Author: David Aspinall ;; SPDX-License-Identifier: GPL-3.0-or-later ;;; Commentary: ;; ;; Provide splash screen for Proof General. ;; ;; The idea is to have a replacement for the usual splash screen. ;; This is slightly tricky: when to call proof-splash-display-screen? ;; We'd like to call it during loading/initialising. But it's hard to ;; make the screen persist after loading because of the action of ;; display-buffer invoked after the mode function during find-file. ;; ;; To approximate the best behaviour, we assume that this file is ;; loaded by a call to proof-mode. We display the screen now and add ;; a wait procedure temporarily to proof-mode-hook which prevents ;; redisplay until proof-splash-time has elapsed. ;; ;;; Code: (require 'proof-site) ;; ;; Customization of splash screen ;; (defcustom proof-splash-enable t "*If non-nil, display a splash screen when Proof General is loaded." :type 'boolean :group 'proof-user-options) (defcustom proof-splash-time 8 "Minimum number of seconds to display splash screen for. The splash screen may be displayed for a wee while longer than this, depending on how long it takes the machine to initialise Proof General." :type 'number :group 'proof-general-internals) (defcustom proof-splash-contents '(list (proof-get-image "ProofGeneral-splash.png") nil "Welcome to" (concat proof-assistant " Proof General!") nil (concat "Version " proof-general-short-version ".") nil (concat "© LFCS, University of Edinburgh & contributors " proof-general-version-year) nil nil :link '(" Read the " "Proof General documentation" (lambda (button) (info "ProofGeneral"))) :link '(" Please report problems on the " "Github issue tracker" (lambda (button) (browse-url "https://github.com/ProofGeneral/PG/issues")) "Report bugs at https://github.com/ProofGeneral/PG") :link '("Visit the " "Proof General Github page" (lambda (button) (browse-url "https://github.com/ProofGeneral/PG")) "PG is on Github at https://github.com/ProofGeneral/PG") :link '("or the " "homepage" (lambda (button) (browse-url "https://proofgeneral.github.io")) "Browse https://proofgeneral.github.io") nil :link '("Find out about Emacs on the Help menu -- start with the " "Emacs Tutorial" (lambda (button) (help-with-tutorial))) nil "See this screen again with Proof-General -> About" ) "Evaluated to configure splash screen displayed when entering Proof General. A list of the screen contents. If an element is a string or an image specifier, it is displayed centred on the window on its own line. If it is nil, a new line is inserted." :type 'sexp :group 'proof-general-internals) (defconst proof-splash-startup-msg '(if (featurep 'proof-config) nil ;; Display additional hint if we guess we're being loaded ;; by shell script rather than find-file. '(list "To start using Proof General, visit a proof script file" "for your prover, using C-x C-f or the File menu.")) "Additional form evaluated and put onto splash screen.") (defconst proof-splash-welcome "*Proof General Welcome*" "Name of the Proof General splash buffer.") (define-derived-mode proof-splash-mode fundamental-mode "Splash" "Mode for splash. \\{proof-splash-mode-map}" (set-buffer-modified-p nil) (setq buffer-read-only t)) (define-key proof-splash-mode-map "q" #'bury-buffer) (define-key proof-splash-mode-map [mouse-3] #'bury-buffer) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (defsubst proof-emacs-imagep (img) "See if IMG is an Emacs image descriptor." (and (listp img) (eq (car img) 'image))) (defun proof-get-image (name) "Load a PNG image NAME, or string on TTYs." (if (display-graphic-p) (find-image `((:type png :file ,(expand-file-name name proof-images-directory)))) (concat "[ image " name " ]"))) (defvar proof-splash-timeout-conf nil "Holds timeout ID and previous window config for proof splash screen.") (defun proof-splash-centre-spaces (glyph) "Return number of spaces to insert in order to center given GLYPH or string. Borrowed from startup-center-spaces." (let* ((avg-pixwidth (round (/ (frame-pixel-width) (frame-width)))) (fill-area-width (* avg-pixwidth (- fill-column left-margin))) (glyph-pixwidth (cond ((stringp glyph) (* avg-pixwidth (length glyph))) ((proof-emacs-imagep glyph) (car (with-no-warnings ; image-size not available in tty emacs (image-size glyph 'inpixels)))) (t (error "Function proof-splash-centre-spaces: bad arg"))))) (+ left-margin (round (/ (/ (- fill-area-width glyph-pixwidth) 2) avg-pixwidth))))) ;; We take some care to preserve the users window configuration ;; underneath the splash screen. This is just to be polite. ;; NB: not as polite as it could be: if minibuffer is active, ;; this may deactivate it. ;; NB2: There is something worse here: pending input ;; causes this function to spoil the mode startup, if the splash ;; buffer is killed before the input has been processed. ;; Symptom is ProofGeneral mode instead of the native script mode. ;; (defun proof-splash-remove-screen (&optional _nothing) "Remove splash screen and restore window config." (let ((splashbuf (get-buffer proof-splash-welcome))) (proof-splash-unset-frame-titles) (if (and splashbuf proof-splash-timeout-conf) (progn (if (get-buffer-window splashbuf) ;; Restore the window config if splash is being displayed (if (cdr proof-splash-timeout-conf) (set-window-configuration (cdr proof-splash-timeout-conf)))) ;; Indicate removed splash screen; disable timeout (disable-timeout (car proof-splash-timeout-conf)) (setq proof-splash-timeout-conf nil) (proof-splash-remove-buffer))))) (defun proof-splash-remove-buffer () "Remove the splash buffer if it's still present." (let ((splashbuf (get-buffer proof-splash-welcome))) (if splashbuf ;; Kill should be right, but it can cause core dump ;; on XEmacs (kill-buffer splashbuf) (TODO: check Emacs now) (if (eq (selected-window) (window-buffer (selected-window))) (bury-buffer splashbuf))))) (defvar proof-splash-seen nil "Flag indicating the user has been subjected to a welcome message.") (defun proof-splash-insert-contents () "Insert splash buffer contents into current buffer." (let* ((splash-contents (append (eval proof-splash-contents t) (eval proof-splash-startup-msg t))) s) (setq buffer-read-only nil) (erase-buffer) (while splash-contents (setq s (car splash-contents)) (cond ((proof-emacs-imagep s) (indent-to (proof-splash-centre-spaces s)) (insert-image s)) ((eq s :link) (setq splash-contents (cdr splash-contents)) (let ((spec (car splash-contents))) (if (functionp spec) (setq spec (funcall spec))) (indent-to (proof-splash-centre-spaces (concat (car spec) (cadr spec)))) (insert (car spec)) (insert-button (cadr spec) 'face (list 'link) 'action (nth 2 spec) 'help-echo (concat "mouse-2, RET: " (or (nth 3 spec) "Follow this link")) 'follow-link t))) ((stringp s) (indent-to (proof-splash-centre-spaces s)) (insert s))) (newline) (setq splash-contents (cdr splash-contents))) (goto-char (point-min)) (proof-splash-mode))) ;;;###autoload (defun proof-splash-display-screen (&optional timeout) "Save window config and display Proof General splash screen. If TIMEOUT is non-nil, time out outside this function, definitely by end of configuring proof mode. Otherwise, make a key binding to remove this buffer." (interactive "P") (proof-splash-set-frame-titles) (let* (;; Keep win config explicitly instead of pushing/popping because ;; if the user switches windows by hand in some way, we want ;; to ignore the saved value. Unfortunately there seems to ;; be no way currently to remove the top item of the stack. (winconf (current-window-configuration)) (curwin (get-buffer-window (current-buffer))) (curfrm (and curwin (window-frame curwin))) (inhibit-modification-hooks t) ; no font-lock, thank-you. ;; NB: maybe leave next one in for frame-crazy folk ;;(pop-up-frames nil) ; display in the same frame. (splashbuf (get-buffer-create proof-splash-welcome))) (with-current-buffer splashbuf (proof-splash-insert-contents) (let* ((splashwin (display-buffer splashbuf)) (splashfm (window-frame splashwin)) ;; Only save window config if we're on same frame (savedwincnf (if (eq curfrm splashfm) winconf))) (delete-other-windows splashwin) (when timeout (setq proof-splash-timeout-conf (cons (add-timeout proof-splash-time #'proof-splash-remove-screen nil) savedwincnf)) (add-hook 'proof-mode-hook #'proof-splash-timeout-waiter)))) (setq proof-splash-seen t))) (defalias 'pg-about #'proof-splash-display-screen) ;;;###autoload (defun proof-splash-message () "Make sure the user gets welcomed one way or another." (interactive) (unless (or proof-splash-seen noninteractive) (if proof-splash-enable (progn ;; disable ordinary emacs splash (setq inhibit-startup-message t) ;; Display the splash screen only after we're done setting things up, ;; otherwise it can have undesired interference. (run-with-timer 0 nil (let ((nci (not (called-interactively-p 'any)))) (lambda () (proof-splash-display-screen nci))))) ;; Otherwise, a message (message "Welcome to %s Proof General!" proof-assistant)) (setq proof-splash-seen t))) (defun proof-splash-timeout-waiter () "Wait for proof-splash-timeout or input, then remove self from hook." (while (and proof-splash-timeout-conf ;; timeout still active (not (input-pending-p))) (sit-for 0.1)) (if proof-splash-timeout-conf ;; not removed yet (proof-splash-remove-screen)) (if (fboundp 'next-command-event) ; 3.3: Emacs removed this (if (input-pending-p) (setq unread-command-events (cons (next-command-event) unread-command-events)))) (remove-hook 'proof-mode-hook #'proof-splash-timeout-waiter)) (defvar proof-splash-old-frame-title-format nil) (defun proof-splash-set-frame-titles () (let ((instance-name (concat (if (not (zerop (length proof-assistant))) (concat proof-assistant " ")) "Proof General"))) (setq proof-splash-old-frame-title-format frame-title-format) (setq frame-title-format (concat instance-name ": %b")))) (defun proof-splash-unset-frame-titles () (when proof-splash-old-frame-title-format (setq frame-title-format proof-splash-old-frame-title-format) (setq proof-splash-old-frame-title-format nil))) (provide 'proof-splash) ;;; proof-splash.el ends here PG-4.5/generic/proof-syntax.el000066400000000000000000000275341426357011200163130ustar00rootroot00000000000000;;; proof-syntax.el --- Functions for dealing with syntax ;; This file is part of Proof General. ;; Portions © Copyright 1994-2012 David Aspinall and University of Edinburgh ;; Portions © Copyright 2003-2018 Free Software Foundation, Inc. ;; Portions © Copyright 2001-2017 Pierre Courtieu ;; Portions © Copyright 2010, 2016 Erik Martin-Dorel ;; Portions © Copyright 2011-2013, 2016-2017 Hendrik Tews ;; Portions © Copyright 2015-2017 Clément Pit-Claudel ;; Authors: David Aspinall, Healfdene Goguen, ;; Thomas Kleymann, Dilip Sequiera ;; SPDX-License-Identifier: GPL-3.0-or-later ;;; Commentary: ;; ;;; Code: (require 'font-lock) (require 'proof-config) ; proof-case-fold-search (require 'pg-pamacs) ; proof-ass-sym (defsubst proof-ids-to-regexp (l) "Maps a non-empty list of tokens L to a regexp matching any element. Uses a regexp of the form \\_<...\\_>." (concat "\\_<" (regexp-opt l) ; was: (mapconcat 'identity l "\\|") "\\_>")) (defsubst proof-anchor-regexp (e) "Anchor (\\`) and group the regexp E." (concat "\\`\\(" e "\\)")) (defconst proof-no-regexp "\\<\\>" "A regular expression that never matches anything.") (defsubst proof-regexp-alt-list (args) "Return the regexp which matches any of the regexps ARGS." (mapconcat #'identity args "\\|")) (defsubst proof-regexp-alt (&rest args) "Return the regexp which matches any of the regexps ARGS." ;; see regexp-opt (NB: but that is for strings, not regexps) (proof-regexp-alt-list args)) (defsubst proof-re-search-forward-region (startre endre) "Search for a region delimited by regexps STARTRE and ENDRE. Return the start position of the match for STARTRE, or nil if a region cannot be found." (if (re-search-forward startre nil t) (let ((start (match-beginning 0))) (if (re-search-forward endre nil t) start)))) ;; Functions for string matching and searching that take into account ;; value of proof-case-fold-search. Last arg to string-match is not ;; applicable. (defsubst proof-search-forward (string &optional bound noerror count) "Like ‘search-forward’, but set ‘case-fold-search’ to ‘proof-case-fold-search’." (let ((case-fold-search proof-case-fold-search)) (search-forward string bound noerror count))) ;;;###autoload (defun proof-replace-regexp-in-string (regexp rep string) "Like ‘replace-regexp-in-string’, but set ‘case-fold-search’ to ‘proof-case-fold-search’." (let ((case-fold-search proof-case-fold-search)) (replace-regexp-in-string regexp rep string))) (defsubst proof-re-search-forward (regexp &optional bound noerror count) "Like ‘re-search-forward’, but set ‘case-fold-search’ to ‘proof-case-fold-search’." (let ((case-fold-search proof-case-fold-search)) (re-search-forward regexp bound noerror count))) (defsubst proof-re-search-backward (regexp &optional bound noerror count) "Like ‘re-search-backward’, but set ‘case-fold-search’ to ‘proof-case-fold-search’." (let ((case-fold-search proof-case-fold-search)) (re-search-backward regexp bound noerror count))) (defsubst proof-re-search-forward-safe (regexp &optional bound noerror count) "Like ‘re-search-forward’, but set ‘case-fold-search’ to ‘proof-case-fold-search’." (and regexp (let ((case-fold-search proof-case-fold-search)) (re-search-forward regexp bound noerror count)))) (defsubst proof-string-match (regexp string &optional start) "Like ‘string-match’, but set ‘case-fold-search’ to ‘proof-case-fold-search’." (let ((case-fold-search proof-case-fold-search)) (string-match regexp string start))) (defsubst proof-string-match-safe (regexp string &optional start) "Like ‘string-match’, but return nil if REGEXP or STRING is nil." (if (and regexp string) (proof-string-match regexp string start))) (defsubst proof-stringfn-match (regexp-or-fn string) "Like ‘proof-string-match’ if first arg is regexp, otherwise call it." (cond ((stringp regexp-or-fn) (proof-string-match regexp-or-fn string)) ((functionp regexp-or-fn) (funcall regexp-or-fn string)))) (defsubst proof-looking-at (regexp) "Like ‘looking-at’, but set ‘case-fold-search’ to ‘proof-case-fold-search’." (let ((case-fold-search proof-case-fold-search)) (looking-at regexp))) (defsubst proof-looking-at-safe (regexp) "Like ‘proof-looking-at’, but return nil if REGEXP is nil." (if regexp (proof-looking-at regexp))) ;; ;; Syntactic context ;; ;; A function named after one in XEmacs (defun proof-buffer-syntactic-context (&optional buffer) "Return the syntactic context of BUFFER at point. If BUFFER is nil or omitted, the current buffer is assumed. The returned value is one of the following symbols: nil ; meaning no special interpretation string ; meaning point is within a string comment ; meaning point is within a line comment" (save-excursion (if buffer (set-buffer buffer)) (let ((pp (syntax-ppss))) ;;(parse-partial-sexp (point-min) (point)))) (cond ((nth 3 pp) 'string) ;; ((nth 7 pp) 'block-comment) ;; "Stefan Monnier" suggests ;; distinguishing between block comments and ordinary comments ;; is problematic: not what XEmacs claims and different to what ;; (nth 7 pp) tells us in GNU Emacs. ((nth 4 pp) 'comment))))) (defsubst proof-looking-at-syntactic-context-default () "Default function for `proof-looking-at-syntactic-context'." (or (proof-buffer-syntactic-context) (save-match-data (when (proof-looking-at-safe proof-script-comment-start-regexp) 'comment)) (save-match-data (when (proof-looking-at-safe proof-string-start-regexp) 'string)))) (defun proof-looking-at-syntactic-context () "Determine if current point is at beginning or within comment/string context. If so, return a symbol indicating this ('comment or 'string). This function invokes if that is defined, otherwise it calls `proof-looking-at-syntactic-context'." (if (fboundp (proof-ass-sym syntactic-context)) (funcall (proof-ass-sym syntactic-context)) (proof-looking-at-syntactic-context-default))) (defun proof-inside-comment (pos) "Return non-nil if POS is inside a comment." (save-excursion (goto-char pos) (eq (proof-buffer-syntactic-context) 'comment))) (defun proof-inside-string (pos) "Return non-nil if POS is inside a comment." (save-excursion (goto-char pos) (eq (proof-buffer-syntactic-context) 'string))) ;; ;; Replacing matches ;; (defsubst proof-replace-string (string to-string) "Non-interactive `replace-string', using `proof-case-fold-search'." (while (proof-search-forward string nil t) (replace-match to-string nil t))) (defsubst proof-replace-regexp (regexp to-string) "Non-interactive `replace-regexp', using `proof-case-fold-search'." (while (proof-re-search-forward regexp nil t) (replace-match to-string nil nil))) (defsubst proof-replace-regexp-nocasefold (regexp to-string) "Non-interactive `replace-regexp', forcing `case-fold-search' to nil." (let ((case-fold-search nil)) (while (proof-re-search-forward regexp nil t) (replace-match to-string nil nil)))) ;; ;; Generic font-lock ;; (defvar proof-id "\\(\\w\\(\\w\\|\\s_\\)*\\)" "A regular expression for parsing identifiers.") ;; For font-lock, we treat ,-separated identifiers as one identifier ;; and refontify commata using \{proof-zap-commas}. (defun proof-zap-commas (limit) "Remove the face of all `,' from point to LIMIT. Meant to be used from `font-lock-keywords' as a way to unfontify commas in declarations and definitions. Useful for provers which have declarations of the form x,y,z:Ty All that can be said for it is that the previous ways of doing this were even more bogus...." (while (proof-search-forward "," limit t) (if (memq (get-text-property (1- (point)) 'face) '(proof-declaration-name-face font-lock-variable-name-face font-lock-function-name-face)) (put-text-property (1- (point)) (point) 'face nil)))) ;; ;; Font lock: providing an alternative syntactic fontify ;; region function. ;; ;; The hook font-lock-fontify-region-function is tempting but not ;; really a convenient place. We just want to replace the syntactic ;; fontification function. ;; ;; (defadvice font-lock-fontify-keywords-region ;; (before font-lock-fontify-keywords-advice (beg end &optional loudly)) ;; "Call proof assistant specific syntactic region fontify. ;; If it's bound, we call -font-lock-fontify-syntactically-region." ;; (when (and proof-buffer-type ;; (fboundp (proof-ass-sym font-lock-fontify-syntactically-region))) ;; (funcall (proof-ass-sym font-lock-fontify-syntactically-region) ;; beg end loudly))) ;; (ad-activate 'font-lock-fontify-keywords-region) ;; ;; Functions for doing something like "format" but with customizable ;; control characters. ;; ;;;###autoload (defun proof-format (alist string) "Format a string by matching regexps in ALIST against STRING. ALIST contains (REGEXP . REPLACEMENT) pairs where REPLACEMENT may be a string or sexp evaluated to get a string." (while alist (let ((idx 0)) (while (string-match (car (car alist)) string idx) (let ((replacement (cond ((stringp (cdr (car alist))) (cdr (car alist))) (t (eval (cdr (car alist))))))) (setq string (concat (substring string 0 (match-beginning 0)) replacement (substring string (match-end 0)))) (setq idx (+ (match-beginning 0) (length replacement)))))) (setq alist (cdr alist))) string) (defun proof-format-filename (string filename) "Format STRING by replacing quoted chars by escaped version of FILENAME. %e uses the canonicalized expanded version of filename (including directory, using `default-directory' -- see `expand-file-name'). %r uses the unadjusted (possibly relative) version of FILENAME. %m ('module') uses the basename of the file, without directory or extension. %s means the same as %e. Using %e can avoid problems with dumb proof assistants who don't understand ~, for example. For all these cases, the escapes in `proof-shell-filename-escapes' are processed. If STRING is in fact a function, instead invoke it on FILENAME and return the resulting (string) value." (cond ((functionp string) (funcall string filename)) (t (proof-format (list (cons "%s" (proof-format proof-shell-filename-escapes (expand-file-name filename))) (cons "%e" (proof-format proof-shell-filename-escapes (expand-file-name filename))) (cons "%r" (proof-format proof-shell-filename-escapes filename)) (cons "%m" (proof-format proof-shell-filename-escapes (file-name-nondirectory (file-name-sans-extension filename))))) string)))) ;; ;; Functions for inserting text into buffer. ;; ; Taken from Isamode ; ; %l - insert the value of isa-logic-name ; %s - insert the value returned by isa-current-subgoal (defun proof-insert (text) "Insert TEXT into the current buffer. TEXT may include these special characters: %p - place the point here after input Any other %-prefixed character inserts itself." ; would be quite nice to have this function: ;(isa-delete-pending-input) (let ((i 0) pos acc) (while (< i (length text)) (let ((ch (elt text i))) (if (not (eq ch ?%)) (setq acc (concat acc (char-to-string ch))) (setq i (1+ i)) (setq ch (elt text i)) (cond ;((eq ch ?l) ; (setq acc (concat acc isa-logic-name))) ;((eq ch ?s) ; (setq acc ; (concat acc ; (int-to-string ; (if (boundp 'isa-denoted-subgoal) ; isa-denoted-subgoal ; 1))))) ;((eq ch ?n) ; (if acc (insert acc)) ; (setq acc nil) ; (scomint-send-input)) ((eq ch ?p) (if acc (insert acc)) (setq acc nil) (setq pos (point))) (t (setq acc (concat acc (char-to-string ch))))))) (setq i (1+ i))) (if acc (insert acc)) (if pos (goto-char pos)))) (provide 'proof-syntax) ;;; proof-syntax.el ends here PG-4.5/generic/proof-toolbar.el000066400000000000000000000215161426357011200164210ustar00rootroot00000000000000;;; proof-toolbar.el --- Toolbar for Proof General ;; This file is part of Proof General. ;; Portions © Copyright 1994-2012 David Aspinall and University of Edinburgh ;; Portions © Copyright 2003, 2012, 2014 Free Software Foundation, Inc. ;; Portions © Copyright 2001-2017 Pierre Courtieu ;; Portions © Copyright 2010, 2016 Erik Martin-Dorel ;; Portions © Copyright 2011-2013, 2016-2017 Hendrik Tews ;; Portions © Copyright 2015-2017 Clément Pit-Claudel ;; Author: David Aspinall ;; SPDX-License-Identifier: GPL-3.0-or-later ;;; Commentary: ;; ;; It's a little bit tricky to add prover-specific items: ;; presently it must be done before this file is loaded. ;; We could improve on that by generating everything on-thy-fly ;; in proof-toolbar-setup. ;; ;; See `proof-toolbar-entries-default' and `-toolbar-entries' ;; in pg-custom.el for the default generic toolbar and ;; the per-prover toolbar contents variable. ;; ;;; Code: (eval-and-compile (require 'span) (require 'proof-utils) (require 'proof-config) (require 'tool-bar)) ; needed for some emacsen without X ;; ;; Function, icon, button names ;; (defun proof-toolbar-function (token) "Construct name of toolbar function for TOKEN." (intern (concat "proof-toolbar-" (symbol-name token)))) (defun proof-toolbar-icon (token) "Construct name of toolbar icon for TOKEN." (intern (concat "proof-toolbar-" (symbol-name token) "-icon"))) (defun proof-toolbar-enabler (token) "Construct name of toolbar enabler for TOKEN." (intern (concat "proof-toolbar-" (symbol-name token) "-enable-p"))) ;; ;; Now the toolbar icons and buttons ;; (defun proof-toolbar-make-icon (tle) "Make icon variable and icon list entry from a PA-toolbar-entries entry." (let* ((icon (car tle)) (toolbarp (nth 3 tle)) (iconname (symbol-name icon)) (iconvar (proof-toolbar-icon icon))) (when toolbarp (set iconvar (concat "epg-" iconname))))) (defun proof-toolbar-make-toolbar-items (map tles) "Make toolbar button descriptors from a PA-toolbar-entries entry." ;; Entry format: (TOKEN MENUNAME TOOLTIP TOOLBAR-P [VISIBLE-P]) (dolist (tle tles) (let* ((token (nth 0 tle)) (longtoken (intern (symbol-name token))) (includep (nth 3 tle)) (visiblep (nth 4 tle)) (icon (proof-toolbar-icon token)) (buttonfn (proof-toolbar-function token)) (enabler (proof-toolbar-enabler token)) (tooltip (and includep (nth 2 tle))) (props (append (list :help tooltip) (if (fboundp enabler) (list :enable (list enabler))) (if visiblep (list :visible visiblep))))) (if (eval includep) (apply 'tool-bar-local-item (eval icon) buttonfn longtoken map props))))) ;; ;; Code for displaying and refreshing toolbar ;; (defvar proof-toolbar-map nil "Proof mode toolbar button list. Set in `proof-toolbar-setup'.") (defun proof-toolbar-available-p () "Check if toolbar support is available in this Emacs." (and window-system (featurep 'tool-bar) ;; GNU Emacs tool-bar library (or (image-type-available-p 'xpm) ;; and XPM (image-type-available-p 'png)))) ;; or PNG ;;;###autoload (defun proof-toolbar-setup () "Initialize Proof General toolbar and enable it for all PG buffers. If `proof-toolbar-enable' is nil, change the buffer toolbars back the default toolbar." (interactive) (when (proof-toolbar-available-p) (unless proof-toolbar-map (setq proof-toolbar-map (make-sparse-keymap)) (if (boundp 'image-load-path) (add-to-list 'image-load-path proof-images-directory)) ; rude? (mapc 'proof-toolbar-make-icon (proof-ass toolbar-entries)) (proof-toolbar-make-toolbar-items proof-toolbar-map (proof-ass toolbar-entries))) (proof-map-buffers (append (proof-buffers-in-mode proof-mode-for-script) (proof-associated-buffers)) (when proof-toolbar-enable (set (make-local-variable 'tool-bar-map) proof-toolbar-map)) (when (not proof-toolbar-enable) (kill-local-variable 'tool-bar-map))))) (defun proof-toolbar-enable () "Take action when the toolbar is enabled or disabled." (proof-toolbar-setup) (redraw-display)) ;;;###autoload (autoload 'proof-toolbar-toggle "proof-toolbar") (proof-deftoggle proof-toolbar-enable proof-toolbar-toggle) ;; ;; ;; Proof General Toolbar and Scripting Menu Functions ;; -------------------------------------------------- ;; ;; Defaults functions are provided below for: up, down, restart ;; Code for specific provers may define the symbols below to use ;; the other buttons: next, prev, goal, qed (images are provided). ;; ;; proof-toolbar-next next function ;; proof-toolbar-next-enable enable predicate for next ;; ;; If no -enable function is defined, button is always enabled. ;; ;; To add support for more buttons or alter the default ;; images, -toolbar-entries should be adjusted. ;; See proof-config.el for that. ;; ;; Note that since the toolbar is displayed for goals and response ;; buffers too, enablers and command functions must potentially switch ;; buffer first. ;; ;; Undo (defalias 'proof-toolbar-undo 'proof-undo-last-successful-command) (defun proof-toolbar-undo-enable-p () (proof-with-script-buffer (and (proof-shell-available-p) (> (proof-unprocessed-begin) (point-min))))) ;; Delete (defalias 'proof-toolbar-delete 'proof-undo-and-delete-last-successful-command) (defun proof-toolbar-delete-enable-p () (proof-with-script-buffer (and (not buffer-read-only) (proof-shell-available-p) (> (proof-unprocessed-begin) (point-min))))) ;; Home (defalias 'proof-toolbar-home 'proof-goto-end-of-locked) ;; Next (defalias 'proof-toolbar-next 'proof-assert-next-command-interactive) (defun proof-toolbar-next-enable-p () (proof-with-script-buffer (not (proof-locked-region-full-p)))) ;; Goto (defalias 'proof-toolbar-goto 'proof-goto-point) (defun proof-toolbar-goto-enable-p () (eq proof-buffer-type 'script)) ;; Retract (defalias 'proof-toolbar-retract 'proof-retract-buffer) (defun proof-toolbar-retract-enable-p () (proof-with-script-buffer (not (proof-locked-region-empty-p)))) ;; Use (defalias 'proof-toolbar-use 'proof-process-buffer) (defalias 'proof-toolbar-use-enable-p 'proof-toolbar-next-enable-p) ;; Prooftree (defalias 'proof-toolbar-prooftree 'proof-tree-external-display-toggle) ;; Restart (defalias 'proof-toolbar-restart 'proof-shell-restart) ;; Goal (defalias 'proof-toolbar-goal 'proof-issue-goal) ;; QED (defalias 'proof-toolbar-qed 'proof-issue-save) (defun proof-toolbar-qed-enable-p () (proof-with-script-buffer (and proof-save-command proof-shell-proof-completed (proof-shell-available-p)))) ;; State (defalias 'proof-toolbar-state 'proof-prf) (defalias 'proof-toolbar-state-enable-p 'proof-shell-available-p) ;; Context (defalias 'proof-toolbar-context 'proof-ctxt) (defalias 'proof-toolbar-context-enable-p 'proof-shell-available-p) ;; Command (defalias 'proof-toolbar-command 'proof-minibuffer-cmd) (defalias 'proof-toolbar-command-enable-p 'proof-shell-available-p) ;; Help (I was an alias for this) (defun proof-toolbar-help () (interactive) (info "ProofGeneral")) ;; Find (defalias 'proof-toolbar-find 'proof-find-theorems) (defalias 'proof-toolbar-find-enable-p 'proof-shell-available-p) ;; Info (defalias 'proof-toolbar-info 'proof-query-identifier) (defalias 'proof-toolbar-info-enable-p 'proof-shell-available-p) ;; Visibility (not on toolbar) (defalias 'proof-toolbar-visibility 'pg-toggle-visibility) (defun proof-toolbar-visibility-enable-p () (span-property-safe (span-at (point) 'type) 'idiom)) ;; Interrupt (defalias 'proof-toolbar-interrupt 'proof-interrupt-process) (defun proof-toolbar-interrupt-enable-p () proof-shell-busy) ;; ;; Scripting Menu ;; ;; TODO: pass in map argument, don't use easymenu. ;;;###autoload (defun proof-toolbar-scripting-menu () "Menu made from the Proof General toolbar commands." (let (menu) (dolist (tle (proof-ass toolbar-entries)) ;; Entry format: (TOKEN MENUNAME TOOLTIP TOOLBAR-P VISIBLE-P) (let* ((token (car tle)) (menuname (cadr tle)) (tooltip (nth 2 tle)) (visiblep (nth 4 tle)) (enabler (proof-toolbar-enabler token)) (fnname (proof-toolbar-function token)) ;; fnval: remove defalias to get keybinding onto menu; ;; NB: function and alias must both be defined for this ;; to work!! (fnval (if (symbolp (symbol-function fnname)) (symbol-function fnname) fnname))) (when (and menuname (eval visiblep)) (setq menu (cons (vconcat (vector menuname fnval :help tooltip) (if (fboundp enabler) ;; NB: :active not :enable, for easymenu (vector :active (list (proof-toolbar-enabler token)))) (if visiblep (vector :visible visiblep))) menu))))) (reverse menu))) (provide 'proof-toolbar) ;;; proof-toolbar.el ends here PG-4.5/generic/proof-tree.el000066400000000000000000001460501426357011200157170ustar00rootroot00000000000000;;; proof-tree.el --- Proof General prooftree communication. -*- lexical-binding: t; -*- ;; This file is part of Proof General. ;; Portions © Copyright 1994-2012 David Aspinall and University of Edinburgh ;; Portions © Copyright 2003-2021 Free Software Foundation, Inc. ;; Portions © Copyright 2001-2017 Pierre Courtieu ;; Portions © Copyright 2010, 2016 Erik Martin-Dorel ;; Portions © Copyright 2011-2013, 2016-2017 Hendrik Tews ;; Portions © Copyright 2015-2017 Clément Pit-Claudel ;; Authors: Hendrik Tews ;; SPDX-License-Identifier: GPL-3.0-or-later ;;; Commentary: ;; ;; Generic code for the communication with prooftree. Prooftree ;; is an ocaml-gtk program that displays proof trees. ;; ;; The main problem with proof tree visualization is that Coq (and ;; probably other proof assistants as well) does not provide any ;; information about which subgoals are new and have been created by ;; the last proof command and which subgoals stem from older proof ;; commands. ;; ;; To solve this problem prooftree relies on unique identification ;; strings of goals, which are called goal or sequent ID's in the ;; code. With these ID's it is easy to keep track which goals are new. ;; ;; A second problem is that, for an undo command, Coq (and probably ;; other proof assistants as well) does not tell which subgoals and ;; which finished branches must be deleted. Therefore prooftree needs ;; a continuously increasing proof state number and keeps a complete ;; undo history for every proof. ;; ;; A third problem is that Coq (and probably other proof assistants as ;; well) is not able to generate the information for a proof tree in ;; the middle of a proof. Therefore, if the user wants to start the ;; proof-tree display in the middle of the proof, it is necessary to ;; retract to the start of the proof and then to reassert to the ;; previous end of the locked region. To achieve this, one has to call ;; `accept-process-output' at suitable points to let Proof General ;; process the `proof-action-list'. ;; ;; A fourth problem is that proof-tree display can only work when the ;; prover output is not suppressed (via `proof-full-annotation'). ;; `proof-shell-should-be-silent' takes care of that. ;; ;; The design of Prooftree, of the glue code inside Proof General ;; (mostly in this file) and of the communication protocol tries to ;; achieve the following two goals: ;; ;; * Functionality is preferably transferred into prooftree, to ;; enlarge Proof General not unnecessarily. ;; ;; * To avoid synchronization trouble the communication between ;; Proof General and prooftree is almost one way only: Only Proof ;; General sends display or undo commands to Prooftree. Prooftree ;; never requests any proof-state information from Proof General. ;; Prooftree only sends a quit message to Proof General when the ;; user closes the proof-tree display of the current proof. This ;; goal requires that some of the heuristics, which decide which ;; subgoals are new and which have to be refreshed, have to be ;; implemented here. ;; ;; In general the glue code here works on the delayed output. That is, ;; the glue code here runs when the next proof command has already ;; been sent to the proof assistant. The glue code makes a light ;; analysis on the output of the proof assistant, extracts the ;; necessary parts with regular expressions and sends appropriate ;; commands to prooftree. This is achieved by calling the main entry ;; here, the function `proof-tree-handle-delayed-output' from the ;; proof shell filter function after `proof-shell-exec-loop' has ;; finished. ;; ;; However, some aspects can not be delayed. Those are treated by ;; `proof-tree-urgent-action'. Its primary use is for inserting ;; special goal-displaying commands into `proof-action-list' before ;; the next real proof command runs. For Coq this needs to be done for ;; newly generated subgoals and for goals that contain an existential ;; variable that got instantiated in the last proof step. ;; ;; Actually, for every proof, Prooftree can display a set of disjunct ;; proof trees, which are organized into layers. More than one proof ;; tree in more than one layer is needed to support the Grap ;; Existential Variables command in Coq. There is one proof tree in ;; the first layer for the original goal. The second layer contains ;; all the goals that the first Grab Existential Variables command ;; created from uninstantiated existential variabes in the main proof. ;; The third layer contains the goals that the second Grap Existential ;; Variables created. ;;; Code: (eval-when-compile (require 'cl-lib)) ;cl-assert (eval-when-compile (require 'proof-shell)) ;; ;; User options ;; (defgroup proof-tree () "Customization for the proof tree visualizer" :group 'proof-general :package-version '(ProofGeneral . "4.2")) (defcustom proof-tree-program (proof-locate-executable "prooftree" t nil) "Command to invoke prooftree." :type 'string :group 'proof-tree) (defcustom proof-tree-arguments () "Command line arguments for prooftree." :type '(repeat string) :group 'proof-tree) ;; ;; Proof assistant options ;; (defgroup proof-tree-internals () "Proof assistant specific customization of prooftree." :group 'proof-general-internals :package-version '(ProofGeneral . "4.2")) ;; defcustom proof-tree-configured is in proof-config.el, because it is ;; needed in pg-custom.el (defcustom proof-tree-ignored-commands-regexp nil "Commands that should be ignored for the prooftree display. The output of commands matching this regular expression is not sent to prooftree. It should match commands that display additional information but do not make any proof progress. Leave at nil to act on all commands. For Coq this regular expression should contain all commands such as Lemma, that can start a proof." :type '(choice regexp (const nil)) :group 'proof-tree-internals) (defcustom proof-tree-navigation-command-regexp nil "Regexp to match a navigation command. A navigation command typically focusses on a different open goal without changing any of the open goals. Leave at nil if there are no navigation commands." :type '(choice regexp (const nil)) :group 'proof-tree-internals) (defcustom proof-tree-cheating-regexp nil "Regexp to match cheating proofer commands. A cheating command finishes the current goal without proving it to permit the user to first focus on other parts of the development. Examples are \"sorry\" in Isabelle and \"admit\" in Coq. Leave at nil if there are no cheating commands." :type '(choice regexp (const nil)) :group 'proof-tree-internals) (defcustom proof-tree-new-layer-command-regexp nil "Regexp to match proof commands that add new goals to a proof. This regexp must match the command that turns the proof assistant into prover mode, which adds the initial goal to the proof. It must further match commands that add additional goals after all previous goals have been proved." :type 'regexp :group 'proof-tree-internals) (defcustom proof-tree-current-goal-regexp nil "Regexp to match the current goal and its ID. The regexp is matched against the output of the proof assistant to extract the current goal with its ID. The regexp must have 2 grouping constructs, the first one matches just the ID, the second one the complete sequent text that is to be sent to prooftree." :type 'regexp :group 'proof-tree-internals) (defcustom proof-tree-update-goal-regexp nil "Regexp to match a goal and its ID. The regexp is matched against the output of additional show-goal commands inserted by Proof General with a command returned by `proof-tree-show-sequent-command'. Proof General inserts such commands to update the goal text in prooftree. This is necessary, for instance, when existential variables get instantiated. This regexp must have 2 grouping constructs, the first matching the ID of the goal, the second the complete sequent text." :type 'regexp :group 'proof-tree-internals) (defcustom proof-tree-additional-subgoal-ID-regexp nil "Regular expression to match ID's of additional subgoals. This regexp is used to extract the ID's of all additionally open goals. The regexp is used in a while loop and must match one subgoal ID with subgroup 1." :type 'regexp :group 'proof-tree-internals) (defcustom proof-tree-existential-regexp nil "Regexp to match existential variables. Existential variables exist for instance in Isabelle/Hol and in Coq. They are placeholders for terms that might (for Coq they must) get instantiated in a later stage of the proof. This regexp should match one existential variable in subgroup 1. It is used inside a while loop to extract all existential variables from the goal text or from a list of existential variables. Leave this variable at nil for proof assistants that do not have existential variables." :type '(choice regexp (const nil)) :group 'proof-tree-internals) (defcustom proof-tree-existentials-state-start-regexp nil "Regexp to match the start of the state display of existential variables. Together with `proof-tree-existentials-state-end-regexp', this regular expression is used to determine the state display of existential variables, which contains information about which existentials are still uninstantiated and about dependencies of instantiated existential variables. Leave this variable nil, if there is no such state display." :type '(choice regexp (const nil)) :group 'proof-tree-internals) (defcustom proof-tree-existentials-state-end-regexp nil "Regexp to match the end of the state display of existential variables. Together with `proof-tree-existentials-state-start-regexp', this regular expression is used to determine the state display of existential variables, which contains information about which existentials are still uninstantiated and about dependencies of instantiated existential variables. If this variable is nil (and if `proof-tree-existentials-state-start-regexp' is non-nil), then the state display expands to the end of the prover output." :type '(choice regexp (const nil)) :group 'proof-tree-internals) (defcustom proof-tree-branch-finished-regexp nil "Regexp to recognize that the current branch has been finished. This must match in precisely the following cases: - The current branch has been finished but there is no current open subgoal because the prover has not switched to the next subgoal. - The last open goal has been proved." :type 'regexp :group 'proof-tree-internals) (defcustom proof-tree-get-proof-info nil "Proof assistant specific function for information about the current proof. This function takes no arguments. It must return a list, which contains, in the following order: * the current state number (as positive integer) * the name of the current proof (as string) or nil The state number is used to implement undo in prooftree. The proof name is used to distinguish different proofs inside prooftree. The state number is interpreted as the state that has been reached after the last command has been processed. It must be consistent in the following sense. Firstly, it must be strictly increasing for successive commands that can be individually retracted. Secondly, the state number reported after some command X has been processed must be strictly greater than the state reported when X is retracted. Finally, state numbers of commands preceding X must be less than or equal the state reported when X is retracted (but no stuff before X)." :type 'function :group 'proof-tree-internals) (defcustom proof-tree-extract-instantiated-existentials nil "Proof assistant specific function for instantiated existential variables. This function must only be defined if the prover has existential variables, that is, if `proof-tree-existential-regexp' is non-nil. If defined, this function should return the list of currently instantiated existential variables as a list of strings. The function is called with `proof-shell-buffer' as current buffer and with two arguments start and stop, which designate the region containing the last output from the proof assistant. `proof-tree-extract-list' might be useful for writing this function." :type '(choice function (const nil)) :group 'proof-tree-internals) (defcustom proof-tree-show-sequent-command nil "Proof assistant specific function for a show-goal command. This function is applied to an ID of a goal and should return a command (as string) that will display the complete sequent with that ID. The regexp `proof-tree-update-goal-regexp' should match the output of the proof assistant for the returned command, such that `proof-tree-update-sequent' will update the sequent ID inside prooftree. If the proof assistant is unable to redisplay sequent ID the function should return nil and prooftree will not get updated." :type 'function :group 'proof-tree-internals) (defcustom proof-tree-find-begin-of-unfinished-proof nil "Proof assistant specific function for the start of the current proof. This function is called with no argument when the user switches the external proof-tree display on. Then, this function must determine if there is a currently unfinished proof for which the proof-tree display should be started. If yes this function must return the starting position of the command that started this proof. If there is no such proof, this function must return nil." :type 'function :group 'proof-tree-internals) (defcustom proof-tree-find-undo-position nil "Proof assistant specific function for finding the point to undo to. This function is used to convert the state number, which comes with an undo command from Prooftree, into a point position for `proof-retract-until-point'. This function is called in the current scripting buffer with the state number as argument. It must return a buffer position." :type 'function :group 'proof-tree-internals) (defcustom proof-tree-urgent-action-hook () "Normal hook for prooftree actions that cannot be delayed. This hook is called (indirectly) from inside `proof-shell-exec-loop' after the preceeding command and any comments that follow have been choped off `proof-action-list' and before the next command is sent to the proof assistant. This hook can therefore be used to insert additional commands into `proof-action-list' that must be executed before the next real proof command. Functions in this hook can rely on `proof-info' being bound to the result of `proof-tree-get-proof-info'. This hook is used, for instance, for Coq to insert Show commands for newly generated subgoals. (The normal Coq output does not contain the complete sequent text of newly generated subgoals.)" :type 'hook :group 'proof-tree-internals) ;; ;; Internal variables ;; (defvar proof-tree-external-display nil "Display proof trees in external prooftree windows if t. Actually, if this variable is t then the user requested an external proof-tree display. If there was no unfinished proof when proof-tree display was requested and if no proof has been started since then, then there is obviously no proof-tree display. In this case, this variable stays t and the proof-tree display will be started for the next proof. Controlled by `proof-tree-external-display-toggle'.") (defvar proof-tree-process nil "Emacs Lisp process object of the prooftree process.") (defconst proof-tree-process-name "proof-tree" "Name of the prooftree process for Emacs Lisp.") (defconst proof-tree-process-buffer-name (concat "*" proof-tree-process-name "*") "Name of the buffer for stdout and stderr of the prooftree process.") (defvar proof-tree-process-buffer nil "Buffer for stdout and stderr of the prooftree process.") (defconst proof-tree-emacs-exec-regexp "\nemacs exec: \\([-a-z]+\\) *\\([^\n]*\\)\n" "Regular expression to match callback commands from the prooftree process.") (defvar proof-tree-last-state 0 "Last state of the proof assistant. Used for undoing in prooftree.") (defvar proof-tree-current-proof nil "Name of the current proof or nil if there is none. This variable is only maintained and meaningful if `proof-tree-external-display' is t.") (defvar proof-tree-sequent-hash nil "Hash table to remember sequent ID's. Needed because some proof assistants do not distinguish between new subgoals, which have been created by the last proof command, and older, currently unfocussed subgoals. If Proof General meets a goal, it is treated as new subgoal if it is not in this hash yet. The hash is mostly used as a set of sequent ID's. However, for undo operations it is necessary to delete all those sequents from the hash that have been created in a state later than the undo state. For this purpose this hash maps sequent ID's to the state number in which the sequent has been created. The hash table is initialized in `proof-tree-start-process'.") (defvar proof-tree-existentials-alist nil "Alist mapping existential variables to sequent ID's. Used to remember which goals need a refresh when an existential variable gets instantiated. To support undo commands the old contents of this list must be stored in `proof-tree-existentials-alist-history'. To ensure undo is properly working, this variable should only be changed by using `proof-tree-delete-existential-assoc', `proof-tree-add-existential-assoc' or `proof-tree-clear-existentials'.") (defvar proof-tree-existentials-alist-history nil "Alist mapping state numbers to old values of `proof-tree-existentials-alist'. Needed for undo.") ;; ;; process filter function that receives prooftree output ;; (defvar proof-tree-output-marker nil "Marker in `proof-tree-process-buffer' pointing to new output. This marker points to the next piece of output that needs to get processed.") (defvar proof-tree-filter-continuation nil "Continuation when `proof-tree-process-filter' stops early. A function that handles a command from Prooftee might fail because not all data from Prooftee has yet arrived. In this case the continuation is stored in this variable and will be called from `proof-tree-process-filter' when more output arrives.") (defun proof-tree-stop-external-display () "Prooftree callback for the command \"stop-displaying\"." (if proof-tree-current-proof (message "External proof-tree display switched off")) (proof-tree-quit-proof) (setq proof-tree-external-display nil)) (defun proof-tree-handle-proof-tree-undo (data) "Handle an undo command that arrives from prooftree." (let ((undo-state (string-to-number data))) (if (and (integerp undo-state) (> undo-state 0)) (with-current-buffer proof-script-buffer (goto-char (funcall proof-tree-find-undo-position undo-state)) (proof-retract-until-point)) (display-warning '(proof-general proof-tree) "Prooftree sent an invalid state for undo" :warning)))) (defun proof-tree-insert-script (data) "Handle an insert-command command from Prooftree." (let ((command-length (string-to-number data))) (if (and (integerp command-length) (> command-length 0)) (condition-case nil (progn (insert (with-current-buffer proof-tree-process-buffer (buffer-substring proof-tree-output-marker (+ proof-tree-output-marker command-length)))) ;; received all text -> advance marker (set-marker proof-tree-output-marker (+ proof-tree-output-marker command-length) proof-tree-process-buffer)) (args-out-of-range ;; buffer substring failed because the end position is not ;; there yet ;; need to try again later (setq proof-tree-filter-continuation (lambda () (proof-tree-insert-script data))))) (display-warning '(proof-general proof-tree) "Prooftree sent an invalid data length for insert-command" :warning)))) (defun proof-tree-insert-output (string &optional message) "Insert output or a message into the prooftree process buffer. If MESSAGE is t, a message is inserted and `proof-tree-output-marker' is not touched. Otherwise, if `proof-tree-output-marker' is nil, it is set to point to the newly arrived output." (with-current-buffer proof-tree-process-buffer (let ((moving (= (point) (point-max)))) (save-excursion (when (and (not message) (not proof-tree-output-marker)) (setq proof-tree-output-marker (point-max-marker)) (set-marker-insertion-type proof-tree-output-marker nil)) (goto-char (point-max)) (insert string)) (if moving (goto-char (point-max)))))) (defun proof-tree-process-filter (_proc string) "Output filter for prooftree. Records the output in the prooftree process buffer and checks for callback function requests. Such callback functions might fail because the complete output from Prooftree has not arrived yet. In this case they store a continuation function in `proof-tree-filter-continuation that will be called when the next piece of output arrives. `proof-tree-output-marker' points to the next piece of Prooftree output that needs to get processed. If everything is processed, the marker is deleted and `proof-tree-insert-output' sets it again for the next output." (proof-tree-insert-output string) (let ((continuation proof-tree-filter-continuation) command-found command data) ;; clear continuation (setq proof-tree-filter-continuation nil) ;; call continuation -- this might set a continuation again (when continuation (funcall continuation)) (unless proof-tree-filter-continuation ;; there was no continuation or the continuation finished successfully ;; need to look for command after output marker (while (< proof-tree-output-marker (1+ (buffer-size proof-tree-process-buffer))) ;; there is something after the output marker (with-current-buffer proof-tree-process-buffer (save-excursion (goto-char proof-tree-output-marker) (setq command-found (proof-re-search-forward proof-tree-emacs-exec-regexp nil t)) (if command-found (progn (setq command (match-string 1) data (match-string 2)) (set-marker proof-tree-output-marker (point))) (set-marker proof-tree-output-marker (point-max))))) (when command-found (cond ((equal command "stop-displaying") (proof-tree-stop-external-display)) ((equal command "undo") (proof-tree-handle-proof-tree-undo data)) ((equal command "insert-proof-script") (proof-tree-insert-script data)) (t (display-warning '(proof-general proof-tree) (format "Unknown prooftree command %s" command) :warning)))))) ;; one of the handling functions might have set a continuation ;; if not we clear the output marker (unless proof-tree-filter-continuation (set-marker proof-tree-output-marker nil) (setq proof-tree-output-marker nil)))) ;; ;; Process creation ;; (defun proof-tree-process-sentinel (_proc event) "Sentinel for prooftee. Runs on process status changes and cleans up when prooftree dies." (proof-tree-insert-output (concat "\nsubprocess status change: " event) t) (unless (proof-tree-is-running) (proof-tree-stop-external-display) (setq proof-tree-process nil))) (defun proof-tree-start-process () "Start the external prooftree process. Does also initialize the communication channel and some internal variables." (let ((process-connection-type nil) ; use pipes, see emacs bug #24531 (old-proof-tree (get-process proof-tree-process-name))) ;; reset output marker (when proof-tree-output-marker (set-marker proof-tree-output-marker nil) (setq proof-tree-output-marker nil)) ;; create buffer (setq proof-tree-process-buffer (get-buffer-create proof-tree-process-buffer-name)) ;; first clean up any old processes (when old-proof-tree (delete-process old-proof-tree) (proof-tree-insert-output "\n\nProcess terminated by Proof General\n\n" t)) ;; now start the new process (proof-tree-insert-output "\nStart new prooftree process\n\n" t) (setq proof-tree-process (apply #'start-process proof-tree-process-name proof-tree-process-buffer proof-tree-program proof-tree-arguments)) (set-process-coding-system proof-tree-process 'utf-8-unix 'utf-8-unix) (set-process-filter proof-tree-process #'proof-tree-process-filter) (set-process-sentinel proof-tree-process #'proof-tree-process-sentinel) (set-process-query-on-exit-flag proof-tree-process nil) ;; other initializations (setq proof-tree-sequent-hash (make-hash-table :test 'equal) proof-tree-last-state 0 proof-tree-existentials-alist nil proof-tree-existentials-alist-history nil) (proof-tree-send-configure))) (defun proof-tree-is-running () "Return t if prooftree is properly running." (and proof-tree-process (eq (process-status proof-tree-process) 'run))) (defun proof-tree-ensure-running () "Ensure the prooftree process is running properly." (unless (proof-tree-is-running) (proof-tree-start-process))) ;; ;; Low-level communication primitives ;; (defconst proof-tree-protocol-version 3 "Version of the communication protocol between Proof General and Prooftree. Must be increased if one of the low-level communication primitives is changed.") (defun proof-tree-send-message (second-line data) "Send a complete message to Prooftree. Send a message with command line SECOND-LINE and all strings in DATA as data sections to Prooftree." (let ((second-line-len (string-bytes second-line))) (cl-assert (< second-line-len 999)) (process-send-string proof-tree-process (format "second line %03d\n%s\n%s%s" (1+ second-line-len) second-line (mapconcat #'identity data "\n") (if data "\n" ""))))) (defun proof-tree-send-configure () "Send the configure message." (proof-tree-send-message (format "configure for \"%s\" and protocol version %02d" proof-assistant proof-tree-protocol-version) ())) (defun proof-tree-send-goal-state (state proof-name command-string cheated-flag layer-flag current-sequent-id current-sequent-text additional-sequent-ids existential-info) "Send the current goal state to prooftree." ;; (message "PTSGS id %s sequent %s ex-info %s" ;; current-sequent-id current-sequent-text existential-info) (let* ((add-id-string (mapconcat #'identity additional-sequent-ids " ")) (second-line (format (concat "current-goals state %d current-sequent %s %s %s " "proof-name-bytes %d " "command-bytes %d sequent-text-bytes %d " "additional-id-bytes %d existential-bytes %d") state current-sequent-id (if cheated-flag "cheated" "not-cheated") (if layer-flag "new-layer" "current-layer") (1+ (string-bytes proof-name)) (1+ (string-bytes command-string)) (1+ (string-bytes current-sequent-text)) (1+ (string-bytes add-id-string)) (1+ (string-bytes existential-info))))) (proof-tree-send-message second-line (list proof-name command-string current-sequent-text add-id-string existential-info)))) (defun proof-tree-send-update-sequent (state proof-name sequent-id sequent-text) "Send the updated sequent text to prooftree." (let ((second-line (format (concat "update-sequent state %d sequent %s proof-name-bytes %d " "sequent-text-bytes %d") state sequent-id (1+ (string-bytes proof-name)) (1+ (string-bytes sequent-text))))) (proof-tree-send-message second-line (list proof-name sequent-text)))) (defun proof-tree-send-switch-goal (proof-state proof-name current-id) "Send switch-to command to prooftree." (let ((second-line (format "switch-goal state %d sequent %s proof-name-bytes %d" proof-state current-id (1+ (string-bytes proof-name))))) (proof-tree-send-message second-line (list proof-name)))) (defun proof-tree-send-branch-finished (state proof-name cmd-string cheated-flag existential-info) "Send branch-finished to prooftree." (proof-tree-send-message (format (concat "branch-finished state %d %s proof-name-bytes %d command-bytes %d " "existential-bytes %d") state (if cheated-flag "cheated" "not-cheated") (1+ (string-bytes proof-name)) (1+ (string-bytes cmd-string)) (1+ (string-bytes existential-info))) (list proof-name cmd-string existential-info))) (defun proof-tree-send-proof-complete (state proof-name) "Send proof-complete to prooftree." (proof-tree-send-message (format "proof-complete state %d proof-name-bytes %d" state (1+ (string-bytes proof-name))) (list proof-name))) (defun proof-tree-send-undo (proof-state) "Tell prooftree to undo." (let ((second-line (format "undo-to state %d" proof-state))) (proof-tree-send-message second-line nil))) (defun proof-tree-send-quit-proof (proof-name) "Tell prooftree to close the window for PROOF-NAME." (let ((second-line (format "quit-proof proof-name-bytes %d" (1+ (string-bytes proof-name))))) (proof-tree-send-message second-line (list proof-name)))) ;; ;; proof-tree-existentials-alist manipulations and history ;; (defun proof-tree-record-existentials-state (state &optional dont-copy) "Store the current state of `proof-tree-existentials-alist' for undo. Usually this involves making a copy of `proof-tree-existentials-alist' because of the destructive updates used on that list. If optional argument DONT-COPY is non-nil no copy is done." (setq proof-tree-existentials-alist-history (cons (cons state (if dont-copy proof-tree-existentials-alist (copy-alist proof-tree-existentials-alist))) proof-tree-existentials-alist-history))) (defun proof-tree-undo-state-var (proof-state var-symbol history-symbol) "Undo changes to VAR-SYMBOL using HISTORY-SYMBOL. This is a general undo function for variables that keep their undo information in a alist that maps state numbers to old values. Argument PROOF-STATE is the state to reestablish, VAR-SYMBOL is (the symbol of) the variable to undo and HISTORY-SYMBOL is (the symbol of) the undo history alist." (let ((undo-not-finished t) (history (symbol-value history-symbol)) (var (symbol-value var-symbol))) (while (and undo-not-finished history) (if (> (caar history) proof-state) (progn (setq var (cdr (car history))) (setq history (cdr history))) (setq undo-not-finished nil))) (set var-symbol var) (set history-symbol history))) (defun proof-tree-undo-existentials (proof-state) "Undo changes in `proof-tree-existentials-alist'. Change `proof-tree-existentials-alist' back to its contents in state PROOF-STATE." (proof-tree-undo-state-var proof-state 'proof-tree-existentials-alist 'proof-tree-existentials-alist-history)) (defun proof-tree-delete-existential-assoc (state ex-assoc) "Delete mapping EX-ASSOC from ‘proof-tree-existentials-alist’." (proof-tree-record-existentials-state state) (setq proof-tree-existentials-alist (delq ex-assoc proof-tree-existentials-alist))) (defun proof-tree-add-existential-assoc (state ex-var sequent-id) "Add the mapping EX-VAR -> SEQUENT-ID to ‘proof-tree-existentials-alist’. Do nothing if this mapping does already exist." (let ((ex-var-assoc (assoc ex-var proof-tree-existentials-alist))) (if ex-var-assoc (unless (member sequent-id (cdr ex-var-assoc)) (proof-tree-record-existentials-state state) (setcdr ex-var-assoc (cons sequent-id (cdr ex-var-assoc)))) (proof-tree-record-existentials-state state) (setq proof-tree-existentials-alist (cons (cons ex-var (list sequent-id)) proof-tree-existentials-alist))))) (defun proof-tree-clear-existentials () "Clear the mapping in `proof-tree-existentials-alist' and its history." (setq proof-tree-existentials-alist nil) (setq proof-tree-existentials-alist-history nil)) ;; ;; Process urgent output from the proof assistant ;; (defun proof-tree-show-goal-callback (state) "Callback for display-goal commands inserted by this package. Update the sequent and run hooks in `proof-state-change-hook'. Argument STATE is the state number (i.e., an integer) with which the update sequent command should be associated. The STATE is necessary, because a comment following a branching command cat get retired together with the branching command before the show-goal commands that update sequents are processed. The effect of the sequent update would therefore be undone when the comment alone is retracted. You CANNOT put this function directly as callback into `proof-action-list' because callbacks receive the span as argument and this function expects an integer! Rather you should call `proof-tree-make-show-goal-callback', which evaluates to a lambda expressions that you can put into `proof-action-list'." ;;(message "PTSGC %s" state) (proof-tree-update-sequent state) (run-hooks 'proof-state-change-pre-hook) (run-hooks 'proof-state-change-hook)) (defun proof-tree-make-show-goal-callback (state) "Create the callback for display-goal commands." (lambda (_span) (proof-tree-show-goal-callback state))) (defun proof-tree-urgent-action (flags) "Handle urgent points before the next item is sent to the proof assistant. Schedule goal updates when existential variables have changed and call `proof-tree-urgent-action-hook'. All this is only done if the current output does not come from a command (with the 'proof-tree-show-subgoal flag) that this package inserted itself. Urgent actions are only needed if the external proof display is currently running. Therefore this function should not be called when `proof-tree-external-display' is nil. This function assumes that the prover output is not suppressed. Therefore, `proof-tree-external-display' being t is actually a necessary precondition. The not yet delayed output is in the region \[proof-shell-delayed-output-start, proof-shell-delayed-output-end]." ;; (message "PTUA flags %s start %s end %s pal %s ptea %s" ;; flags ;; proof-shell-delayed-output-start ;; proof-shell-delayed-output-end ;; proof-action-list ;; proof-tree-existentials-alist) (let* ((proof-info (funcall proof-tree-get-proof-info)) (state (car proof-info)) (start proof-shell-delayed-output-start) (end proof-shell-delayed-output-end) inst-ex-vars) (unless (memq 'proof-tree-show-subgoal flags) (when (and (> state proof-tree-last-state) proof-tree-existential-regexp proof-tree-existentials-alist) ;; Only deal with existentials if this is not and undo ;; command, if the proof assistant actually has existentials ;; (i.e., proof-tree-existential-regexp is set) and if there ;; are some goals with existentials. (setq inst-ex-vars (with-current-buffer proof-shell-buffer (funcall proof-tree-extract-instantiated-existentials start end))) (dolist (ex-var inst-ex-vars) (let ((var-goal-assoc (assoc ex-var proof-tree-existentials-alist))) (when var-goal-assoc (dolist (sequent-id (cdr var-goal-assoc)) (let ((show-cmd (funcall proof-tree-show-sequent-command sequent-id))) (if show-cmd (setq proof-action-list (cons (proof-shell-action-list-item show-cmd (proof-tree-make-show-goal-callback state) '(no-goals-display no-response-display proof-tree-show-subgoal)) proof-action-list))))) (proof-tree-delete-existential-assoc state var-goal-assoc))))) (run-hooks 'proof-tree-urgent-action-hook)) ;; (message "PTUA END pal %s ptea %s" ;; proof-action-list ;; proof-tree-existentials-alist) )) ;; ;; Process output from the proof assistant ;; (defun proof-tree-quit-proof () "Reset internal state when there is no current proof any more. Because currently it is not possible to undo into the middle of a proof, we can safely flush the `proof-tree-sequent-hash' and `proof-tree-existentials-alist-history' when the current proof is finished or quit." (clrhash proof-tree-sequent-hash) (proof-tree-clear-existentials) (setq proof-tree-current-proof nil)) (defun proof-tree-register-existentials (current-state sequent-id sequent-text) "Register existential variables that appear in SEQUENT-TEXT. If SEQUENT-TEXT contains existential variables, then SEQUENT-ID is stored in `proof-tree-existentials-alist'." (if proof-tree-existential-regexp (let ((start 0)) (while (proof-string-match proof-tree-existential-regexp sequent-text start) (setq start (match-end 0)) (proof-tree-add-existential-assoc current-state (match-string 1 sequent-text) sequent-id))))) (defun proof-tree-extract-goals (start end) "Extract the current goal state information from the delayed output. If there is a current goal, return a list containing (in this order) the ID of the current sequent, the text of the current sequent and the list of ID's of additionally open goals. The delayed output is expected between START and END in the current buffer." (goto-char start) (if (proof-re-search-forward proof-tree-current-goal-regexp end t) (let ((sequent-id (match-string-no-properties 1)) (sequent-text (match-string-no-properties 2)) additional-goal-ids) (goto-char start) (while (proof-re-search-forward proof-tree-additional-subgoal-ID-regexp end t) (let ((other-id (match-string-no-properties 1))) (setq additional-goal-ids (cons other-id additional-goal-ids)))) (setq additional-goal-ids (nreverse additional-goal-ids)) (list sequent-id sequent-text additional-goal-ids)) nil)) (defun proof-tree-extract-list (start end start-regexp end-regexp item-regexp) "Extract items between START-REGEXP and END-REGEXP. In the region given by START and END, determine the subregion between START-REGEXP and END-REGEXP and return the list of all items in the subregion. An item is a match of subgroub 1 of ITEM-REGEXP. The items in the returned list have the same order as in the text. Return nil if START-REGEXP or ITEM-REGEXP is nil. The subregion extends up to END if END-REGEXP is nil." (let (result) (when (and start-regexp item-regexp) (goto-char start) (when (proof-re-search-forward start-regexp end t) (setq start (point)) (if (and end-regexp (proof-re-search-forward end-regexp end t)) (setq end (match-beginning 0))) (goto-char start) (while (proof-re-search-forward item-regexp end t) (setq result (cons (match-string-no-properties 1) result))))) (nreverse result))) (defun proof-tree-extract-existential-info (start end) "Extract the information display of existential variables. This function cuts out the text between `proof-tree-existentials-state-start-regexp' and `proof-tree-existentials-state-end-regexp' from the prover output, including the matches of these regular expressions. If the start regexp is nil, the empty string is returned. If the end regexp is nil, the match expands to the end of the prover output." (goto-char start) (if (and proof-tree-existentials-state-start-regexp (proof-re-search-forward proof-tree-existentials-state-start-regexp end t)) (progn (setq start (match-beginning 0)) (when (and proof-tree-existentials-state-end-regexp (proof-re-search-forward proof-tree-existentials-state-end-regexp end t)) (setq end (match-end 0))) (buffer-substring-no-properties start end)) "")) (defun proof-tree-handle-proof-progress (old-proof-marker cmd-string proof-info) "Send CMD-STRING and goals in delayed output to prooftree. This function is called if there is some real progress in a proof. This function sends the current state, the current goal and the list of additional open subgoals to Prooftree. Prooftree will sort out the rest. The delayed output is in the region \[proof-shell-delayed-output-start, proof-shell-delayed-output-end]. Urgent messages might be before that, following OLD-PROOF-MARKER, which contains the position of `proof-marker', before the next command was sent to the proof assistant." ;; (message "PTHPO cmd |%s| info %s flags %s proof-marker %s start %s end %s" ;; cmd proof-info flags ;; old-proof-marker ;; proof-shell-delayed-output-start ;; proof-shell-delayed-output-end) (let* ((start proof-shell-delayed-output-start) (end proof-shell-delayed-output-end) (proof-state (car proof-info)) (proof-name (cadr proof-info)) (cheated-flag (and proof-tree-cheating-regexp (proof-string-match proof-tree-cheating-regexp cmd-string))) current-goals) ;; Check first for special cases, because Coq's output for finished ;; branches is almost identical to proper goals. (goto-char old-proof-marker) (if (proof-re-search-forward proof-tree-branch-finished-regexp end t) (proof-tree-send-branch-finished proof-state proof-name cmd-string cheated-flag (proof-tree-extract-existential-info start end)) (goto-char start) (setq current-goals (proof-tree-extract-goals start end)) (when current-goals (let ((current-sequent-id (car current-goals)) (current-sequent-text (nth 1 current-goals)) ;; nth 2 current-goals contains the additional ID's (layer-flag (and proof-tree-new-layer-command-regexp (proof-string-match proof-tree-new-layer-command-regexp cmd-string)))) ;; send all to prooftree (proof-tree-send-goal-state proof-state proof-name cmd-string cheated-flag layer-flag current-sequent-id current-sequent-text (nth 2 current-goals) (proof-tree-extract-existential-info start end)) ;; put current sequent into hash (if it is not there yet) (unless (gethash current-sequent-id proof-tree-sequent-hash) (puthash current-sequent-id proof-state proof-tree-sequent-hash)) (proof-tree-register-existentials proof-state current-sequent-id current-sequent-text)))))) (defun proof-tree-handle-navigation (proof-info) "Handle a navigation command. This function is called if there was a navigation command, which results in a different goal being current now. The delayed output of the navigation command is in the region \[proof-shell-delayed-output-start, proof-shell-delayed-output-end]." (let ((start proof-shell-delayed-output-start) (end proof-shell-delayed-output-end) (proof-state (car proof-info)) (proof-name (cadr proof-info))) (goto-char start) (if (proof-re-search-forward proof-tree-current-goal-regexp end t) (let ((current-id (match-string-no-properties 1))) ;; send all to prooftree (proof-tree-send-switch-goal proof-state proof-name current-id))))) (defun proof-tree-handle-proof-command (old-proof-marker cmd proof-info) "Display current goal in prooftree unless CMD should be ignored." ;; (message "PTHPC") (let (;; (proof-state (car proof-info)) (cmd-string (mapconcat #'identity cmd " "))) (unless (and proof-tree-ignored-commands-regexp (proof-string-match proof-tree-ignored-commands-regexp cmd-string)) (if (and proof-tree-navigation-command-regexp (proof-string-match proof-tree-navigation-command-regexp cmd-string)) (proof-tree-handle-navigation proof-info) (proof-tree-handle-proof-progress old-proof-marker cmd-string proof-info))) (setq proof-tree-last-state (car proof-info)))) (defun proof-tree-handle-undo (proof-info) "Undo prooftree to current state. Send the undo command to prooftree and undo changes to the internal state of this package. The latter involves currently two points: * delete those goals from `proof-tree-sequent-hash' that have been generated after the state to which we undo now; * change proof-tree-existentials-alist back to its previous content." ;; (message "PTHU info %s" proof-info) (let ((proof-state (car proof-info))) ;; delete sequents from the hash (maphash (lambda (sequent-id state) (if (> state proof-state) (remhash sequent-id proof-tree-sequent-hash))) proof-tree-sequent-hash) ;; undo changes in other state vars (proof-tree-undo-existentials proof-state) (unless (equal (cadr proof-info) proof-tree-current-proof) ;; went back to a point before the start of the proof that we ;; are displaying; ;; or we have not started to display something (proof-tree-quit-proof)) ;; disable proof tree display when undoing to a point outside a proof (unless proof-tree-current-proof (setq proof-tree-external-display nil)) ;; send undo (if (proof-tree-is-running) (proof-tree-send-undo proof-state)) (setq proof-tree-last-state (- proof-state 1)))) (defun proof-tree-update-sequent (proof-state) "Prepare an update-sequent command for prooftree. This function processes delayed output that the proof assistant generated in response to commands that Proof General inserted in order to keep prooftree up-to-date. Such commands are tagged with a 'proof-tree-show-subgoal flag. This function uses `proof-tree-update-goal-regexp' to find a sequent and its ID in the delayed output. If something is found an appropriate update-sequent command is sent to prooftree. The update-sequent command is associated with state PROOF-STATE for proper undo effects, see also the comments for `proof-tree-show-goal-callback'. The delayed output is in the region \[proof-shell-delayed-output-start, proof-shell-delayed-output-end]." ;; (message "PTUS buf %s output %d-%d state %s" ;; (current-buffer) ;; proof-shell-delayed-output-start proof-shell-delayed-output-end ;; proof-state) (if (proof-tree-is-running) (with-current-buffer proof-shell-buffer (let* ((start proof-shell-delayed-output-start) (end proof-shell-delayed-output-end) (proof-info (funcall proof-tree-get-proof-info)) (proof-name (cadr proof-info))) (goto-char start) (if (proof-re-search-forward proof-tree-update-goal-regexp end t) (let ((sequent-id (match-string-no-properties 1)) (sequent-text (match-string-no-properties 2))) (proof-tree-send-update-sequent proof-state proof-name sequent-id sequent-text) ;; put current sequent into hash (if it is not there yet) (unless (gethash sequent-id proof-tree-sequent-hash) (puthash sequent-id proof-state proof-tree-sequent-hash)) (proof-tree-register-existentials proof-state sequent-id sequent-text))))))) (defun proof-tree-handle-delayed-output (old-proof-marker cmd flags _span) "Process delayed output for prooftree. This function is the main entry point of the Proof General prooftree support. It examines the delayed output in order to take appropriate actions and maintains the internal state. The delayed output to handle is in the region \[proof-shell-delayed-output-start, proof-shell-delayed-output-end]. Urgent messages might be before that, following OLD-PROOF-MARKER, which contains the position of `proof-marker', before the next command was sent to the proof assistant. All other arguments are (former) fields of the `proof-action-list' entry that is now finally retired. CMD is the command, FLAGS are the flags and SPAN is the span." ;; (message "PTHDO cmd %s flags %s span %s-%s" cmd flags ;; (if span (span-start span)) (if span (span-end span))) (cl-assert proof-tree-external-display) (unless (or (memq 'invisible flags) (memq 'proof-tree-show-subgoal flags)) (let* ((proof-info (funcall proof-tree-get-proof-info)) (current-proof-name (cadr proof-info))) (save-excursion (if (<= (car proof-info) proof-tree-last-state) ;; went back to some old state: there must have been an undo command (proof-tree-handle-undo proof-info) ;; else -- no undo command ;; first maintain proof-tree-current-proof (cond ((and (null proof-tree-current-proof) current-proof-name) ;; started a new proof (setq proof-tree-current-proof current-proof-name)) ((and proof-tree-current-proof (null current-proof-name)) ;; finished the current proof (proof-tree-send-proof-complete (car proof-info) proof-tree-current-proof) (proof-tree-quit-proof) (setq proof-tree-external-display nil)) ((and proof-tree-current-proof current-proof-name (not (equal proof-tree-current-proof current-proof-name))) ;; new proof before old was finished? (display-warning '(proof-general proof-tree) "Nested proofs are not supported in prooftree display" :warning) ;; try to keep consistency nevertheless (setq proof-tree-current-proof current-proof-name))) ;; send stuff to prooftree now (when current-proof-name ;; we are inside a proof: display something (proof-tree-ensure-running) (proof-tree-handle-proof-command old-proof-marker cmd proof-info))))))) ;; ;; Send undo command when leaving a buffer ;; (defun proof-tree-leave-buffer () "Send an undo command to prooftree when leaving a buffer." (if (and proof-tree-configured (proof-tree-is-running)) (proof-tree-send-undo 0))) (add-hook 'proof-deactivate-scripting-hook #'proof-tree-leave-buffer) ;; ;; User interface ;; (defun proof-tree-display-current-proof (proof-start) "Start an external proof-tree display for the current proof. Coq (and probably other proof assistants as well) does not support outputing the current proof tree. Therefore this function retracts to the start of the current proof, switches the proof-tree display on, and reasserts then until the former end of the locked region. Argument PROOF-START must contain the start position of the current proof." ;;(message "PTDCP %s" proof-tree-external-display) (unless (and proof-script-buffer (equal proof-script-buffer (current-buffer))) (error "Enabling prooftree inside a proof outside the current scripting buffer")) (proof-shell-ready-prover) (cl-assert proof-locked-span) (message "Start proof-tree display for current proof") (save-excursion (save-window-excursion (let ((locked-end (span-end proof-locked-span))) (goto-char proof-start) ;; enable external display to make sure the undo command is send (setq proof-tree-external-display t) (proof-retract-until-point) (while (consp proof-action-list) (accept-process-output)) ;; undo switched external display off; switch on again (setq proof-tree-external-display t) (goto-char locked-end) (proof-assert-until-point) (while (consp proof-action-list) (accept-process-output)))))) (defun proof-tree-external-display-toggle () "Toggle the external proof-tree display. When called outside a proof the external proof-tree display will be enabled for the next proof. When called inside a proof the proof display will be created for the current proof. If the external proof-tree display is currently on, then this toggle will switch it off. At the end of the proof the proof-tree display is switched off." (interactive) (unless proof-tree-configured (error "External proof-tree display not configured for %s" proof-assistant)) (cond (proof-tree-external-display ;; Currently on -> switch off (setq proof-tree-external-display nil) (when proof-tree-current-proof (proof-tree-send-quit-proof proof-tree-current-proof) (proof-tree-quit-proof)) (message "External proof-tree display switched off")) (t ;; Currently off (let ((proof-start (funcall proof-tree-find-begin-of-unfinished-proof))) ;; ensure internal variables are initialized, because otherwise ;; we cannot process undo's after this (proof-tree-ensure-running) (setq proof-tree-current-proof nil) (setq proof-tree-last-state (car (funcall proof-tree-get-proof-info))) (if proof-start ;; inside an unfinished proof -> start for this proof (proof-tree-display-current-proof proof-start) ;; outside a proof -> wait for the next proof (setq proof-tree-external-display t) (proof-tree-send-undo proof-tree-last-state) (message "External proof-tree display switched on for the next proof")))))) ;; ;; Trailer ;; (provide 'proof-tree) ;;; proof-tree.el ends here PG-4.5/generic/proof-unicode-tokens.el000066400000000000000000000125101426357011200177000ustar00rootroot00000000000000;;; proof-unicode-tokens.el --- Support Unicode tokens package ;; This file is part of Proof General. ;; Portions © Copyright 1994-2012 David Aspinall and University of Edinburgh ;; Portions © Copyright 2003-2018 Free Software Foundation, Inc. ;; Portions © Copyright 2001-2017 Pierre Courtieu ;; Portions © Copyright 2010, 2016 Erik Martin-Dorel ;; Portions © Copyright 2011-2013, 2016-2017 Hendrik Tews ;; Portions © Copyright 2015-2017 Clément Pit-Claudel ;; Author: David Aspinall ;; SPDX-License-Identifier: GPL-3.0-or-later ;;; Commentary: ;; ;; Support for Unicode Tokens package: per-prover global enabling, copying ;; configuration tables, adding mode hooks to turn on/off. ;; ;; Initialisation: ;; proof-unicode-tokens-init -> proof-unicode-tokens-reconfigure* ;; ;;; Code: (eval-when-compile (require 'scomint) ;; the following require causes make magic to fail with a recursive chain ;; (require 'proof-auxmodes) ; loaded by proof.el, autoloads us (require 'unicode-tokens)) ; it will be loaded by proof-auxmodes (require 'proof-config) ; config variables (defvar proof-unicode-tokens-initialised nil "Flag indicating whether or not we've performed startup.") (defun proof-unicode-tokens-init () "Set tables and configure hooks for modes." (proof-unicode-tokens-configure) (add-hook 'proof-shell-init-hook 'proof-unicode-tokens-configure-prover) (let ((hooks (mapcar (lambda (m) (intern (concat (symbol-name m) "-hook"))) (list proof-mode-for-script proof-mode-for-response proof-mode-for-goals)))) (dolist (hook hooks) (add-hook hook 'proof-unicode-tokens-mode-if-enabled))) (setq proof-unicode-tokens-initialised t)) (defun proof-unicode-tokens-configure () "Set the Unicode Tokens table from prover instances and initialise." (require 'unicode-tokens) ; load now, for unicode-tokens-configuration-variables (dolist (var unicode-tokens-configuration-variables) (if (boundp (proof-ass-symv var)) (set (intern (concat "unicode-tokens-" (symbol-name var) "-variable")) (proof-ass-symv var)))) (unicode-tokens-initialise)) ;;;###autoload (defun proof-unicode-tokens-mode-if-enabled () "Turn on or off the Unicode Tokens minor mode in this buffer." (unicode-tokens-mode (if (proof-ass unicode-tokens-enable) 1 0))) ;;;###autoload (defun proof-unicode-tokens-set-global (flag) "Set global status of unicode tokens mode for PG buffers to be FLAG. Turn on/off menu in all script buffers and ensure new buffers follow suit." (unless proof-unicode-tokens-initialised (proof-unicode-tokens-init)) ;; Configure if already running (proof-map-buffers (append (proof-buffers-in-mode proof-mode-for-script) (proof-associated-buffers) (proof-buffers-in-mode proof-tokens-extra-modes)) (unicode-tokens-mode (if flag 1 0))) (proof-unicode-tokens-configure-prover)) ;;;###autoload (defun proof-unicode-tokens-enable () "Turn on or off Unicode tokens mode in Proof General script buffer. This invokes `unicode-tokens-mode' to toggle the setting for the current buffer, and then sets PG's option for default to match. Also we arrange to have unicode tokens mode turn itself on automatically in future if we have just activated it for this buffer. Note: this function is called when the customize setting for the prover is changed." (interactive) (when (proof-unicode-tokens-support-available) ;; loads unicode-tokens (unless proof-unicode-tokens-initialised (proof-unicode-tokens-init)) (with-no-warnings ; spurious warning on `proof-unicode-tokens-set-global' (proof-unicode-tokens-set-global (not unicode-tokens-mode))))) ;;; ;;; Interface to custom to dynamically change tables (via proof-set-value) ;;; (defun proof-unicode-tokens-reconfigure () "Function called after a token configuration is changed. Switch off tokens in all script buffers, recalculate maps, turn on again." (interactive) (when proof-unicode-tokens-initialised ; not on startup (when (proof-ass unicode-tokens-enable) (proof-map-buffers (proof-buffers-in-mode proof-mode-for-script) (unicode-tokens-mode 0))) (proof-unicode-tokens-configure) (when (proof-ass unicode-tokens-enable) (proof-map-buffers (proof-buffers-in-mode proof-mode-for-script) (unicode-tokens-mode 1))))) ;; functions to dynamically change settings (eval-after-load "unicode-tokens" '(dolist (var unicode-tokens-configuration-variables) (funcall 'defalias (intern (concat "proof-" (symbol-name var))) 'proof-unicode-tokens-reconfigure))) ;;; ;;; Interface to shell ;;; (defun proof-unicode-tokens-configure-prover () (if (proof-ass unicode-tokens-enable) (proof-unicode-tokens-activate-prover) (proof-unicode-tokens-deactivate-prover))) (defun proof-unicode-tokens-activate-prover () (when (and proof-tokens-activate-command (proof-shell-live-buffer) (proof-shell-available-p)) (proof-shell-invisible-command-invisible-result proof-tokens-activate-command))) (defun proof-unicode-tokens-deactivate-prover () (when (and proof-tokens-deactivate-command (proof-shell-live-buffer) (proof-shell-available-p)) (proof-shell-invisible-command-invisible-result proof-tokens-deactivate-command))) (provide 'proof-unicode-tokens) ;;; proof-unicode-tokens.el ends here PG-4.5/generic/proof-useropts.el000066400000000000000000000442621426357011200166460ustar00rootroot00000000000000;;; proof-useropts.el --- Global user options for Proof General ;; This file is part of Proof General. ;; Portions © Copyright 1994-2012 David Aspinall and University of Edinburgh ;; Portions © Copyright 2003-2021 Free Software Foundation, Inc. ;; Portions © Copyright 2001-2017 Pierre Courtieu ;; Portions © Copyright 2010, 2016 Erik Martin-Dorel ;; Portions © Copyright 2011-2013, 2016-2017 Hendrik Tews ;; Portions © Copyright 2015-2017 Clément Pit-Claudel ;; Author: David Aspinall and others ;; SPDX-License-Identifier: GPL-3.0-or-later ;;; Commentary: ;; ;; User options for Proof General. ;; ;; The following variables are user options for Proof General. ;; ;; They appear in the 'proof-user-options' customize group and should ;; *not* normally be touched by prover specific code. ;; ;;; Code: (defgroup proof-user-options nil "User options for Proof General." :group 'proof-general :prefix "proof-") ;; ;; Take action when dynamically adjusting customize values ;; (defun proof-set-value (sym value) "Set a customize variable using `set-default' and a function. We first call `set-default' to set SYM to VALUE. Then if there is a function SYM (i.e. with the same name as the variable SYM), it is called to take some dynamic action for the new setting. If there is no function SYM, we try stripping `proof-assistant-symbol' and adding \"proof-\" instead to get a function name. This extends proof-set-value to work with generic individual settings. The dynamic action call only happens when values *change*: as an approximation we test whether proof-config is fully-loaded yet." (set-default sym value) (when (and (not noninteractive) (not (bound-and-true-p byte-compile-current-file)) ;FIXME: Yuck! (featurep 'pg-custom) (featurep 'proof-config)) (if (fboundp sym) (funcall sym) (if (boundp 'proof-assistant-symbol) (if (> (length (symbol-name sym)) (+ 3 (length (symbol-name proof-assistant-symbol)))) (let ((generic (intern (concat "proof" (substring (symbol-name sym) (length (symbol-name proof-assistant-symbol))))))) (if (fboundp generic) (funcall generic)))))))) (defcustom proof-electric-terminator-enable nil "*If non-nil, use electric terminator mode. If electric terminator mode is enabled, pressing a terminator will automatically issue `proof-assert-next-command' for convenience, to send the command straight to the proof process. If the command you want to send already has a terminator character, you don't need to delete the terminator character first. Just press the terminator somewhere nearby. Electric!" :type 'boolean :set 'proof-set-value :group 'proof-user-options) (defcustom proof-next-command-insert-space t "*If non-nil, PG will use heuristics to insert newlines or spaces in scripts. In particular, if electric terminator is switched on, spaces or newlines will be inserted as the user types commands to the prover." :type 'boolean :set 'proof-set-value :group 'proof-user-options) (defcustom proof-toolbar-enable t "*If non-nil, display Proof General toolbar for script buffers." :type 'boolean :set 'proof-set-value :group 'proof-user-options) (defcustom proof-imenu-enable nil "*If non-nil, display Imenu menu of items for script buffers." :type 'boolean :set 'proof-set-value :group 'proof-user-options) (defcustom proof-omit-proofs-option nil "Set to t to omit complete opaque proofs for speed reasons. When t, complete opaque proofs in the asserted region are not sent to the proof assistant (and thus not checked). For files with big proofs this can drastically reduce the processing time for the asserted region at the cost of not checking the proofs. For partial and non-opaque proofs in the asserted region all proof commands are sent to the proof assistant. Using a prefix argument for `proof-goto-point' (\\[proof-goto-point]) or `proof-process-buffer' (\\[proof-process-buffer]) temporarily disables omitting proofs." :type 'boolean :group 'proof-user-options) (defcustom pg-show-hints t "*Whether to display keyboard hints in the minibuffer." :type 'boolean :group 'proof-user-options) (defcustom proof-shell-quiet-errors t "If non-nil, be quiet about errors from the prover. Normally error messages cause a beep. Set this to t to prevent that." :type 'boolean :group 'proof-user-options) ;; FIXME: next one could be integer value for catchup delay (defcustom proof-trace-output-slow-catchup t "*If non-nil, try to redisplay less often during frequent trace output. Proof General will try to configure itself to update the display of tracing output infrequently when the prover is producing rapid, perhaps voluminous, output. This counteracts the situation that otherwise Emacs may consume more CPU than the proof assistant, trying to fontify and refresh the display as fast as output appears." :type 'boolean :group 'proof-user-options) (defcustom proof-strict-state-preserving t "*Whether Proof General is strict about the state preserving test. Proof General lets the user send arbitrary commands to the proof engine with `proof-minibuffer-cmd'. To attempt to preserve synchronization, there may be a test `proof-state-preserving-p' configured which prevents the user issuing certain commands directly (instead, they may only be entered as part of the script). Clever or arrogant users may want to avoid this test, which is done if this `proof-strict-state-preserving' is turned off (nil)." :type 'boolean :group 'proof-user-options) (defcustom proof-strict-read-only 'retract "*Whether Proof General is strict about the read-only region in buffers. If non-nil, an error is given when an attempt is made to edit the read-only region, except for the special value 'retract which means undo first. If nil, Proof General is more relaxed (but may give you a reprimand!)." :type '(choice (const :tag "Do not allow edits" t) (const :tag "Allow edits but automatically retract first" retract) (const :tag "Allow edits without restriction" nil)) :set 'proof-set-value :group 'proof-user-options) (defcustom proof-three-window-enable t "*Whether response and goals buffers have dedicated windows. If non-nil, Emacs windows displaying messages from the prover will not be switchable to display other windows. This option can help manage your display. Setting this option triggers a three-buffer mode of interaction where the goals buffer and response buffer are both displayed, rather than the two-buffer mode where they are switched between. It also prevents Emacs automatically resizing windows between proof steps. If you use several frames (the same Emacs in several windows on the screen), you can force a frame to stick to showing the goals or response buffer." :type 'boolean :set 'proof-set-value :group 'proof-user-options) (defcustom proof-multiple-frames-enable nil "*Whether response and goals buffers have separate frames. If non-nil, Emacs will make separate frames (screen windows) for the goals and response buffers, by altering the Emacs variable `special-display-regexps'." :type 'boolean :set 'proof-set-value :group 'proof-user-options) ; Pierre: I really don't think this option is useful. remove? (defcustom proof-layout-windows-on-visit-file nil "*Whether to eagerly create auxiliary buffers and display windows. If non-nil, the output buffers are created and (re-)displayed as soon as a proof script file is visited. Otherwise, the buffers are created and displayed lazily. See `proof-layout-windows'." :type 'boolean :set 'proof-set-value :group 'proof-user-options) (defcustom proof-three-window-mode-policy 'smart "*Window splitting policy for three window mode. - If 'vertical then never split horizontally. - If 'horizontal then always have scripting buffer on the right and goal and response buffers on the left (one above the other). - If 'smart or anything else: 'horizontal when the window is wide enough and 'vertical otherwise. The width threshold is given by `split-width-threshold'. See `proof-layout-windows'." :type '(choice (const :tag "Adapt to current frame width" smart) (const :tag "Horizontal (three columns)" horizontal) (const :tag "Horizontal (two columns)" hybrid) (const :tag "Vertical" vertical)) :group 'proof-user-options) (defcustom proof-delete-empty-windows nil "*If non-nil, automatically remove windows when they are cleaned. For example, at the end of a proof the goals buffer window will be cleared; if this flag is set it will automatically be removed. If you want to fix the sizes of your windows you may want to set this variable to 'nil' to avoid windows being deleted automatically. If you use multiple frames, only the windows in the currently selected frame will be automatically deleted." :type 'boolean :group 'proof-user-options) (defcustom proof-shell-kill-function-also-kills-associated-buffers t "*If non-nil, when `proof-shell-kill-function' is called, clean up buffers. For example, `proof-shell-kill-function' is called when buffers are retracted when switching between proof script files. It may make sense to set this to `nil' when `proof-multiple-frames-enable' is set to prevent proof general from killing frames that you want to be managed by a window manager instead of within emacs." :type 'boolean :group 'proof-user-options) (defcustom proof-shrink-windows-tofit nil "*If non-nil, automatically shrink output windows to fit contents. In single-frame mode, this option will reduce the size of the goals and response windows to fit their contents." :type 'boolean :group 'proof-user-options) (defcustom proof-auto-raise-buffers t "*If non-nil, automatically raise buffers to display latest output. If this is not set, buffers and windows will not be managed by Proof General." :type 'boolean :group 'proof-user-options) (defcustom proof-colour-locked t "*If non-nil, colour the locked region with `proof-locked-face'. If this is not set, buffers will have no special face set on locked regions." :type 'boolean :set 'proof-set-value :group 'proof-user-options) (defcustom proof-sticky-errors nil "*If non-nil, add highlighting to regions which gave errors. Intended to complement `proof-colour-locked'." :type 'boolean :set 'proof-set-value :group 'proof-user-options) (defcustom proof-query-file-save-when-activating-scripting t "*If non-nil, query user to save files when activating scripting. Often, activating scripting or executing the first scripting command of a proof script will cause the proof assistant to load some files needed by the current proof script. If this option is non-nil, the user will be prompted to save some unsaved buffers in case any of them corresponds to a file which may be loaded by the proof assistant. You can turn this option off if the save queries are annoying, but be warned that with some proof assistants this may risk processing files which are out of date with respect to the loaded buffers!" :type 'boolean :group 'proof-user-options) (defcustom proof-prog-name-ask nil "*If non-nil, query user which program to run for the inferior process." :type 'boolean :group 'proof-user-options) (defcustom proof-prog-name-guess nil "*If non-nil, use `proof-guess-command-line' to guess `proof-prog-name'. This option is compatible with `proof-prog-name-ask'. No effect if `proof-guess-command-line' is nil." :type 'boolean :group 'proof-user-options) (defcustom proof-tidy-response t "*Non-nil indicates that the response buffer should be cleared often. The response buffer can be set either to accumulate output, or to clear frequently. With this variable non-nil, the response buffer is kept tidy by clearing it often, typically between successive commands (just like the goals buffer). Otherwise the response buffer will accumulate output from the prover." :type 'boolean :group 'proof-user-options) (defcustom proof-keep-response-history nil "*Whether to keep a browsable history of responses. With this feature enabled, the buffers used for prover responses will have a history that can be browsed without processing/undoing in the prover. \(Changes to this variable take effect after restarting the prover)." :type 'boolean :set 'proof-set-value :group 'proof-user-options) (defcustom pg-input-ring-size 32 "*Size of history ring of previous successfully processed commands." :type 'integer :group 'proof-user-options) (defcustom proof-general-debug nil "*Non-nil to run Proof General in debug mode. This changes some behaviour (e.g. markup stripping) and displays debugging messages in the response buffer. To avoid erasing messages shortly after they're printed, set `proof-tidy-response' to nil. This is only useful for PG developers." :type 'boolean :group 'proof-user-options) (defcustom proof-use-parser-cache t "*Non-nil to use a simple parsing cache. This can be helpful when editing and reprocessing large files. This variable exists to disable the cache in case of problems." :type 'boolean :group 'proof-user-options) (defcustom proof-follow-mode 'locked "*Choice of how point moves with script processing commands. One of the symbols: 'locked, 'follow, 'followdown, 'ignore. If 'locked, point sticks to the end of the locked region. If 'follow, point moves just when needed to display the locked region end. If 'followdown, point if necessary to stay in writeable region If 'ignore, point is never moved after movement commands or on errors. If you choose 'ignore, you can find the end of the locked using \\[proof-goto-end-of-locked]" :type '(choice (const :tag "Follow locked region" locked) (const :tag "Follow locked region down" followdown) (const :tag "Keep locked region displayed" follow) (const :tag "Never move" ignore)) :group 'proof-user-options) ;; Note: the auto action might be improved a bit: for example, when ;; scripting is turned off because another buffer is being retracted, ;; we almost certainly want to retract the currently edited buffer as ;; well (use case is somebody realising a change has to made in an ;; ancestor file). And in that case (supposing file being unlocked is ;; an ancestor), it seems unlikely that we need to query for saves. (defcustom proof-auto-action-when-deactivating-scripting nil "*If 'retract or 'process, do that when deactivating scripting. With this option set to 'retract or 'process, when scripting is turned off in a partly processed buffer, the buffer will be retracted or processed automatically. With this option unset (nil), the user is questioned instead. Proof General insists that only one script buffer can be partly processed: all others have to be completely processed or completely unprocessed. This is to make sure that handling of multiple files makes sense within the proof assistant. NB: A buffer is completely processed when all non-whitespace is locked (coloured blue); a buffer is completely unprocessed when there is no locked region. For some proof assistants (such as Coq) fully processed buffers make no sense. Setting this option to 'process has then the same effect as leaving it unset (nil). (This behaviour is controlled by `proof-no-fully-processed-buffer'.)" :type '(choice (const :tag "No automatic action; query user" nil) (const :tag "Automatically retract" retract) (const :tag "Automatically process" process)) :group 'proof-user-options) (defcustom proof-rsh-command nil "*Shell command prefix to run a command on a remote host. For example, ssh bigjobs Would cause Proof General to issue the command `ssh bigjobs coqtop' to start Coq remotely on our large compute server called `bigjobs'. The protocol used should be configured so that no user interaction \(passwords, or whatever) is required to get going. For proper behaviour with interrupts, the program should also communicate signals to the remote host." :type '(choice string (const nil)) :group 'proof-user-options) (defcustom proof-disappearing-proofs nil "*Non-nil causes Proof General to hide proofs as they are completed." :type 'boolean :group 'proof-user-options) (defcustom proof-full-annotation nil "*Non-nil causes Proof General to record output for all proof commands. Proof output is recorded as it occurs interactively; normally if many steps are taken at once, this output is suppressed. If this setting is used to enable it, the proof script can be annotated with full details. See also `proof-output-tooltips' to enable automatic display of output on mouse hovers." :type 'boolean :group 'proof-user-options) (defcustom proof-output-tooltips t "*Non-nil causes Proof General to add tooltips for prover output. Hovers will be added when this option is non-nil. Prover outputs can be displayed when the mouse hovers over the region that produced it and output is available (see `proof-full-annotation'). If output is not available, the type of the output region is displayed. Changes of this option will not be reflected in already-processed regions of the script." :type 'boolean :group 'proof-user-options) (defcustom proof-minibuffer-messages nil "*Non-nil causes Proof General to issue minibuffer messages. Minibuffer messages are issed when urgent messages are seen from the prover. You can disable the display of these if they are distracting or too frequent." :type 'boolean :group 'proof-user-options) (defcustom proof-autosend-enable nil "*Non-nil causes Proof General to automatically process the script." :type 'boolean :set 'proof-set-value :group 'proof-user-options) (defcustom proof-autosend-delay 0.8 "*Delay before autosend starts sending commands." :type 'float :set 'proof-set-value :group 'proof-user-options) (defcustom proof-autosend-all nil "*If non-nil, auto send will process whole buffer; otherwise just the next command." :type 'boolean :group 'proof-user-options) (defcustom proof-fast-process-buffer (or (featurep 'ns) ; Mac OS X ; or Windows (speed up TBC, see Trac #308) (memq system-type '(windows-nt ms-dos cygwin))) "*If non-nil, `proof-process-buffer' will use a busy wait to process. This results in faster processing, but disables simultaneous user interaction. This setting gives a big speed-up on certain platforms/Emacs ports, for example Mac OS X." :type 'boolean :group 'proof-user-options) (provide 'proof-useropts) ;;; proof-useropts.el ends here PG-4.5/generic/proof-utils.el000066400000000000000000000747411426357011200161270ustar00rootroot00000000000000;;; proof-utils.el --- Proof General utility functions and macros ;; This file is part of Proof General. ;; Portions © Copyright 1994-2012 David Aspinall and University of Edinburgh ;; Portions © Copyright 2003-2018 Free Software Foundation, Inc. ;; Portions © Copyright 2001-2017 Pierre Courtieu ;; Portions © Copyright 2010, 2016, 2021 Erik Martin-Dorel ;; Portions © Copyright 2011-2013, 2016-2017 Hendrik Tews ;; Portions © Copyright 2015-2017 Clément Pit-Claudel ;; Author: David Aspinall and others ;; SPDX-License-Identifier: GPL-3.0-or-later ;;; Commentary: ;; ;; Loading note: this file is required immediately from proof.el, so ;; no autoloads cookies are added here. ;; ;; Compilation note: see etc/development-tips.txt ;; ;;; Code: (eval-when-compile (require 'cl-lib)) ;; ;; Give Emacs version mismatch error here. ;; ;; This file is loaded early, and may be first compiled file ;; loaded if proof-site.el is loaded instead of proof-site.elc. ;; (eval-and-compile (defun pg-emacs-version-cookie () (format "GNU Emacs %d.%d" emacs-major-version emacs-minor-version)) (defconst pg-compiled-for (eval-when-compile (pg-emacs-version-cookie)) "Version of Emacs we're compiled for (or running on, if interpreted).")) (if (or (not (boundp 'emacs-major-version)) (< emacs-major-version 23) (featurep 'xemacs)) (error "Proof General is not compatible with Emacs %s" emacs-version)) (unless (equal pg-compiled-for (pg-emacs-version-cookie)) (warn "Proof General compiled for %s but running on %s: \"make clean; make\" is recommended." pg-compiled-for (pg-emacs-version-cookie))) (require 'proof-site) ; basic vars (require 'pg-pamacs) ; macros for pa config (require 'proof-config) ; config vars (require 'bufhist) ; bufhist (require 'proof-syntax) ; syntax utils (require 'proof-autoloads) ; interface fns (require 'scomint) ; for proof-shell-live-buffer ;; ;; Handy macros ;; (defmacro proof-with-current-buffer-if-exists (buf &rest body) "Like ‘with-current-buffer’ if BUF exists and is live, otherwise nothing." `(if (buffer-live-p ,buf) (with-current-buffer ,buf ,@body))) ;; Slightly specialized version of above. This is used in commands ;; which work from different PG buffers (goals, response), typically ;; bound to toolbar commands. (defmacro proof-with-script-buffer (&rest body) "Execute BODY in some script buffer: current buf, else ‘proof-script-buffer’. Return nil if not a script buffer or if no active scripting buffer." (declare (debug t)) `(cond ((eq proof-buffer-type 'script) (progn ,@body)) ((buffer-live-p proof-script-buffer) (with-current-buffer proof-script-buffer ,@body)))) (defmacro proof-map-buffers (buflist &rest body) "Eval BODY on each buffer in BUFLIST, if it exists." `(dolist (buf ,buflist) (proof-with-current-buffer-if-exists buf ,@body))) (defmacro proof-sym (string) "Return symbol for current proof assistant using STRING." `(intern (concat (symbol-name proof-assistant-symbol) "-" ,string))) (defsubst proof-try-require (symbol) "Try requiring SYMBOL. No error if the file for SYMBOL isn't found." (condition-case () (require symbol) (file-error nil)) (featurep symbol)) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Facility to upgrade all ELPA packages (including ProofGeneral) ;; ;;;###autoload (defun proof-upgrade-elpa-packages () "Upgrade all ELPA packages (using package.el)." (interactive) (unless (proof-try-require 'package) (error "The package feature is not available!")) (let ((package-menu-async nil)) (package-list-packages) (package-menu-mark-upgrades) (let ((use-dialog-box nil)) ;; make `y-or-n-p' show up within the minibuffer ;; even if `proof-upgrade-elpa-packages' is called interactively ;; to avoid any dialog-box overflow if many packages are updated (package-menu-execute)))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Simplified version of save-some-buffers, with useful arg ;; (defun proof-save-some-buffers (buffers) "Query the user whether to save each of BUFFERS." ;; code based on extract from files.el in XEmacs 21.4.14 (map-y-or-n-p (lambda (buffer) (if (and (buffer-modified-p buffer) (not (buffer-base-buffer buffer)) (buffer-file-name buffer)) ;; we deliberately don't switch to show the buffer; ;; let's assume user can see it or knows what's in it. (format "Save file %s? " (buffer-file-name buffer)))) (lambda (buffer) (set-buffer buffer) (condition-case () (save-buffer) (error nil))) buffers)) (defun proof-save-this-buffer () "Query the user whether to save the current buffer." (if (and (buffer-modified-p) (buffer-file-name (current-buffer)) (y-or-n-p (format "Save file %s? " (buffer-file-name (current-buffer))))) (save-buffer))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Buffers and filenames (defun proof-file-truename (filename) "Return the true name of the file FILENAME or nil if file non-existent." (and filename (file-exists-p filename) (file-truename filename))) (defun proof-files-to-buffers (filenames) "Convert a list of FILENAMES into a list of BUFFERS." (let (bufs buf) (dolist (file filenames) (if (setq buf (find-buffer-visiting file)) (setq bufs (cons buf bufs)))) bufs)) (defun proof-buffers-in-mode (mode &optional buflist) "Return a list of the buffers in the buffer list in major mode MODE. Restrict to BUFLIST if it's set." (let ((bufs-left (or buflist (buffer-list))) bufs-got) (dolist (buf bufs-left bufs-got) (if (with-current-buffer buf (eq mode major-mode)) (setq bufs-got (cons buf bufs-got)))))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Associated buffers ;; (defun pg-save-from-death () "Prevent this associated buffer from being killed: merely erase it. A hook function for `kill-buffer-hook'. This is a fairly crude and not-entirely-robust way to prevent the user accidently killing an associated buffer." (if (and (proof-shell-live-buffer) proof-buffer-type) (progn (let ((bufname (buffer-name))) (bufhist-erase-buffer) (set-buffer-modified-p nil) (bury-buffer) (error "Warning: buffer %s not killed; still associated with prover process" bufname))))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Key functions (defun proof-define-keys (map kbl) "Add in MAP the keybindings KBL. The argument KBL is a list of tuples (K . F) where K is a keybinding \(vector) and F the designated function." (mapcar (lambda (kbl) (let ((k (car kbl)) (f (cdr kbl))) (define-key map k f))) kbl)) (defun pg-remove-specials (&optional start end) "Remove special characters in region. Default to whole buffer. Leave point at END." (let ((start (or start (point-min))) (end (or end (point-max)))) (goto-char start) (while (re-search-forward pg-special-char-regexp end t) (replace-match "")) (goto-char end))) (defun pg-remove-specials-in-string (string) (proof-replace-regexp-in-string pg-special-char-regexp "" string)) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Messaging and display functions ;; (defun proof-safe-split-window-vertically () (if (<= (window-height) (* 2 window-min-height)) (enlarge-window (+ 3 (* 2 window-min-height)))) (split-window-vertically)) (defun proof-warn-if-unset (tag sym) "Give a warning (with TAG) if symbol SYM is unbound or nil." (unless (and (boundp sym) (symbol-value sym)) (warn "Proof General %s: %s is unset." tag (symbol-name sym)))) (defvar proof-advertise-layout-freq 30 "Frequency for PG messages to be displayed from time to time.") (defvar proof-advertise-layout-count proof-advertise-layout-freq "Counter used to display PG messages from time to time.") (defun proof-get-window-for-buffer (buffer) "Find a window for BUFFER, display it there, return the window. NB: may change the selected window. This function is a wrapper on ‘display-buffer’. The idea is that if the user has opened and closed some windows we want to preserve the layout by only switching buffer in already pg-associate windows. So if the buffer is not already displayed, we try to reuse an existing associated window, even if in 3-win mode. If no such window exists, we fall back to ‘display-buffer’ while protecting script buffer to be hidden or split. Experimentally we display a message from time to time advertising \\[proof-layout-windows]." ;; IF there *isn't* a visible window showing buffer... (unless (get-buffer-window buffer 0) (if proof-three-window-enable (if (< proof-advertise-layout-count 30) (cl-incf proof-advertise-layout-count) (message (substitute-command-keys "Hit \\[proof-layout-windows] to reset layout")) (setq proof-advertise-layout-count 0))) ;; THEN either we are in 2 wins mode and we must switch the assoc ;; window to buffer OR we deleted a window by mistake and we ;; behave as if in 2 win mode instead of calling display-buffer ;; (stability for the user). If no assoc win exists then we are in ;; trouble: let display-buffer decide but avoid hiding the script buffer. (if (= (count-windows) 1) ;; only one window: fallback to display-buffer (display-buffer buffer) ;; There is at least 2 windows, let us find some assoc ones. (let* ((assoc-wins (proof-associated-windows)) ;; may be nil if no assoc frame (win-to-use (and assoc-wins (car assoc-wins)))) ;; let us switch the buffer in this window even if protected (3-win mode) (if win-to-use (let ((prot (window-dedicated-p win-to-use))) (set-window-dedicated-p win-to-use nil) (set-window-buffer win-to-use buffer) (set-window-dedicated-p win-to-use prot)) ;; if no assoc win then let display-buffer decide but ;; protect script buffer from disappearing. (let ((win-proof-script (car-safe (get-buffer-window-list proof-script-buffer)))) (set-window-dedicated-p win-proof-script t) ; avoid to hide script buffer at all cost (let ((res (display-buffer buffer))) ; return this but revert the dedicated flag first (set-window-dedicated-p win-proof-script nil) res)))))) ;; Return the window, hopefully the one we first thought of. (get-buffer-window buffer 0)) (defun proof-display-and-keep-buffer (buffer &optional pos force) "Display BUFFER and make window according to display mode. If optional POS is present, will set point to POS. Otherwise move point to the end of the buffer. Ensure that point is visible in window." (if (or force proof-auto-raise-buffers) (save-excursion (save-selected-window (let ((window (proof-get-window-for-buffer buffer))) (if (window-live-p window) ;; [fails sometimes?] (progn ;; Set the size and point position. (if proof-three-window-enable (set-window-dedicated-p window proof-three-window-enable)) (select-window window) (if proof-shrink-windows-tofit (proof-resize-window-tofit) ;; If we're not shrinking to fit, allow the size of ;; this window to change. [NB: might be nicer to ;; fix the size based on user choice] (setq window-size-fixed nil)) ;; For various reasons, point may get moved around in ;; response buffer. Attempt to normalise its position. (goto-char (or pos (point-max))) (if pos (beginning-of-line) (skip-chars-backward "\n\t ")) ;; Ensure point visible. Again, window may have died ;; inside shrink to fit, for some reason (when (window-live-p window) (unless (pos-visible-in-window-p (point) window) (recenter -1)))))))))) (defun proof-clean-buffer (buffer) "Erase BUFFER and hide from display if ‘proof-delete-empty-windows’ set. Auto deletion only affects selected frame. (We assume that the selected frame is the one showing the script buffer.) No effect if buffer is dead." (if (buffer-live-p buffer) (with-current-buffer buffer (let ((inhibit-read-only t)) (unless (eq 0 (buffer-size)) ;; checkpoint unless already empty (bufhist-checkpoint-and-erase))) (set-buffer-modified-p nil) (if (eq buffer proof-response-buffer) (setq pg-response-next-error nil)) ; all error msgs lost! (if proof-delete-empty-windows (delete-windows-on buffer t))))) (defun pg-internal-warning (message &rest args) "Display internal warning MESSAGE with ARGS as for format." (let ((formatted (apply 'format message args))) (if (fboundp 'display-warning) (display-warning 'proof-general formatted) (message formatted)))) ;;;###autoload (defun proof-debug (msg &rest args) "Issue the debugging message (format MSG ARGS) in the *PG Debug* buffer. If flag `proof-general-debug' is nil, do nothing." (when proof-general-debug (with-current-buffer (get-buffer-create "*PG Debug*") (help-mode) (let ((formatted (apply 'format msg args)) (warning-minimum-log-level :debug) (warning-minimum-level :debug) (buffer-read-only nil)) (display-warning 'proof-general formatted :debug "*PG Debug*"))))) ;; Utility used in the "Buffers" menu, and throughout (defun proof-switch-to-buffer (buf &optional noselect) "Switch to or display buffer BUF in other window unless already displayed. If optional arg NOSELECT is true, don't switch, only display it. No action if BUF is nil or killed." (and (buffer-live-p buf) ; maybe use proof-display-and-keep-buffer ? (unless (eq buf (window-buffer (selected-window))) (if noselect (display-buffer buf 'not-this-window) (let ((pop-up-windows t)) (pop-to-buffer buf 'not-this-window 'norecord)))))) ;; Originally based on `shrink-window-if-larger-than-buffer', which ;; has a pretty weird implementation. ;; FIXME: GNU Emacs has useful "window-size-fixed" which we use ;; HOWEVER, it's still not quite the right thing, it seems to me. ;; We'd like to specifiy a *minimum size* for a given buffer, ;; not a maximum. With a frame split with just goals/response ;; we'd still get resize errors here using window-size-fixed. ;; FIXME: shrink-to-fit doesn't really work in three-buffer mode, ;; since shrinking one of the associated buffers tends to enlarge the ;; other (rather than just enlarging the proof state) (defun proof-resize-window-tofit (&optional window) "Shrink the WINDOW to be as small as possible to display its contents. Do not shrink to less than `window-min-height' lines. Do nothing if the buffer contains more lines than the present window height, or if some of the window's contents are scrolled out of view, or if the window is not the full width of the frame, or if the window is the only window of its frame." ;; da: actually seems okay in this case (interactive) (or window (setq window (selected-window))) ;; some checks before resizing to avoid messing custom display ;; [probably somewhat superfluous/extra rare] (if (or ;; The frame must not be minibuffer-only. (eq (frame-parameter (window-frame window) 'minibuffer) 'only) ;; We've got more than one window, right? (= 1 (let ((frame (selected-frame))) (select-frame (window-frame window)) (unwind-protect ;; [why is this protected?] (count-windows) (select-frame frame) (select-window window)))) ;; the window is the full width, right? ;; [if not, we may be in horiz-split scheme, problematic] (not (zerop (car (window-edges window)))) ;not leftmost (not (>= (nth 2 (window-edges window)) ;not rightmost (frame-width (window-frame window))))) ;; OK, we're not going to adjust the height here. Moreover, ;; we'll make sure the height can be changed elsewhere. (setq window-size-fixed nil) (with-current-buffer (window-buffer window) (let* ;; weird test cases: ;; cur=45, max=23, desired=121, extraline=0 ;; current height ;;; (cur-height (window-height window)) ;; Most window is allowed to grow to ((max-height (/ (frame-height (window-frame window)) (if proof-three-window-enable ;; we're in three-window-mode with ;; all horizontal splits, so share the height. 3 ;; Otherwise assume a half-and-half split. 2))) ;; I find that I'm willing to use a bit more than the max in ;; those cases where it allows me to see the whole ;; response/goal. --Stef (absolute-max-height (truncate (/ (frame-height (window-frame window)) (if proof-three-window-enable ;; we're in three-window-mode with ;; all horizontal splits, so share the height. 2 ;; Otherwise assume a half-and-half split. 1.5)))) ;; If buffer ends with a newline and point is right after it, then ;; add a final empty line (to display the cursor). (extraline (if (and (eobp) (bolp)) 1 0)) ;; (test-pos (- (point-max) extraline)) ;; Direction of resizing based on whether max position is ;; currently visible. [ FIXME: not completely sensible: ;; may be displaying end fraction of buffer! ] ;; (shrink (pos-visible-in-window-p test-pos window)) ;; Likely desirable height is given by count-lines (desired-height ;; FIXME: is count-lines too expensive for v.large ;; buffers? Probably not an issue for us, but one ;; wonders at the shrink to fit strategy. ;; NB: way to calculate pixel fraction? (+ extraline (count-lines (point-min) (point-max)))) (safe-desired-height ;; Under certain circumstances (involving a non-nil ;; line-spacing), a desired-height of 1 (which happens ;; quite often, eg for an empty response buffer) gives an ;; error inside set-window-text-height. The reason for ;; this is quite complicated, it involves rounding issues ;; and emacs' habbit to sometimes resize a window by 2 ;; pixels. (max 2 desired-height))) ;; Let's shrink or expand. Uses new GNU Emacs function. (let ((window-size-fixed nil)) (set-window-text-height window ;; As explained earlier: use abs-max-height ;; but only if that makes it display all. (if (> safe-desired-height absolute-max-height) max-height safe-desired-height))) (if (window-live-p window) (progn (if (>= (window-text-height window) desired-height) (set-window-start window (point-min))) ;; window-size-fixed is a GNU Emacs buffer local variable ;; which determines window size of buffer. ;; (setq window-size-fixed (window-height window)) )))))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Function for submitting bug reports. ;; (defun proof-submit-bug-report () "Submit an bug report or other report for Proof General." (interactive) (require 'reporter) (let ((reporter-prompt-for-summary-p "(Very) brief summary of problem or suggestion: ")) (reporter-submit-bug-report "da+pg-bugs@inf.ed.ac.uk" "Proof General" (list 'proof-general-version 'proof-assistant) nil nil "*** Proof General now uses Trac for project management and bug reporting, please go to: *** *** http://proofgeneral.inf.ed.ac.uk/trac/search *** *** To see if your bug has been reported already, and a new ticket if not. *** To report a bug, either register yourself as a user, or use the generic account *** username \"pgemacs\" with password \"pgemacs\" *** *** Please only continue with this email mechanism instead IF YOU REALLY MUST. *** The address is not monitored very often and quite possibly will be ignored. *** *** When reporting a bug, please include a small test case for us to repeat it. *** Please also check that it is not already covered in the BUGS or FAQ files that came with *** the distribution, or the latest versions at *** http://proofgeneral.inf.ed.ac.uk/BUGS and *** http://proofgeneral.inf.ed.ac.uk/FAQ "))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; ;;; Utils for making functions to adjust user settings ;;; (defun proof-deftoggle-fn (var &optional othername) "Define a function -toggle for toggling a boolean customize setting VAR. Args as for the macro `proof-deftoggle', except will be evaluated." (eval `(defun ,(if othername othername (intern (concat (symbol-name var) "-toggle"))) (&optional arg) ,(concat "Toggle `" (symbol-name var) "'. With ARG, turn on iff ARG>0. This function simply uses customize-set-variable to set the variable.") ; It was constructed with `proof-deftoggle-fn'." (interactive "P") (customize-set-variable (quote ,var) (if (null arg) (not ,var) (> (prefix-numeric-value arg) 0)))))) (defmacro proof-deftoggle (var &optional othername) "Define a function VAR-toggle for toggling a boolean customize setting VAR. The toggle function uses `customize-set-variable' to change the variable. OTHERNAME gives an alternative name than the default -toggle. The name of the defined function is returned." `(progn (declare-function ,(if othername othername (intern (concat (symbol-name var) "-toggle"))) "proof-utils") (proof-deftoggle-fn (quote ,var) (quote ,othername)))) (defun proof-defintset-fn (var &optional othername) "Define a function -intset for setting an integer customize setting VAR. Args as for the macro `proof-defintset', except will be evaluated." (eval `(defun ,(if othername othername (intern (concat (symbol-name var) "-intset"))) (arg) ,(concat "Set `" (symbol-name var) "' to ARG. This function simply uses customize-set-variable to set the variable. It was constructed with `proof-defintset-fn'.") (interactive (list (read-number (format "Value for %s (int, currently %s): " (symbol-name (quote ,var)) (symbol-value (quote ,var)))))) (unless (integerp arg) ;; type-check to avoid customize type mismatch (error "Value should be an integer!")) (customize-set-variable (quote ,var) arg)))) (defmacro proof-defintset (var &optional othername) "Define a function -intset for setting an integer customize setting VAR. The setting function uses `customize-set-variable' to change the variable. OTHERNAME gives an alternative name than the default -intset. The name of the defined function is returned." `(proof-defintset-fn (quote ,var) (quote ,othername))) (defun proof-deffloatset-fn (var &optional othername) "Define a function -floatset for setting an float customize setting VAR. Args as for the macro `proof-deffloatset', except will be evaluated." (eval `(defun ,(if othername othername (intern (concat (symbol-name var) "-floatset"))) (arg) ,(concat "Set `" (symbol-name var) "' to ARG. This function simply uses customize-set-variable to set the variable. It was constructed with `proof-deffloatset-fn'.") (interactive (list (read-number (format "Value for %s (float, currently %s): " (symbol-name (quote ,var)) (symbol-value (quote ,var)))))) (customize-set-variable (quote ,var) arg)))) (defmacro proof-deffloatset (var &optional othername) "Define a function -floatset for setting an float customize setting VAR. The setting function uses `customize-set-variable' to change the variable. OTHERNAME gives an alternative name than the default -floatset. The name of the defined function is returned." `(proof-deffloatset-fn (quote ,var) (quote ,othername))) (defun proof-defstringset-fn (var &optional othername) "Define a function OTHERNAME for setting an string customize setting VAR. OTHERNAME defaults to `VAR-stringset'." (eval `(defun ,(or othername (intern (concat (symbol-name var) "-stringset"))) (arg) ,(concat "Set `" (symbol-name var) "' to ARG. This function simply uses `customize-set-variable' to set the variable. It was constructed with `proof-defstringset-fn'.") (interactive (list (read-string (format "Value for %s (default %s): " (symbol-name (quote ,var)) (symbol-value (quote ,var))) nil nil (symbol-value (quote ,var))))) (customize-set-variable (quote ,var) arg)))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; ;;; Macris for defining user-level functions (previously in proof-menu.el) ;;; (defun proof-escape-keymap-doc (string) "Avoid action of `substitute-command-keys' on STRING." (replace-regexp-in-string "\\\\" "\\\\=\\\\" string)) (defmacro proof-defshortcut (fn string &optional key) "Define shortcut function FN to insert STRING, optional keydef KEY. This is intended for defining proof assistant specific functions. STRING is inserted using `proof-insert', which see. KEY is added onto proof assistant map." `(progn (if ,key (define-key (proof-ass keymap) (quote ,key) (quote ,fn))) (defun ,fn () ,(concat "Shortcut command to insert " (proof-escape-keymap-doc string) " into the current buffer.\nThis simply calls `proof-insert', which see.") (interactive) (proof-insert ,string)))) (defmacro proof-definvisible (fn string &optional key) "Define function FN to send STRING to proof assistant, optional keydef KEY. This is intended for defining proof assistant specific functions. STRING is sent using `proof-shell-invisible-command', which see. STRING may be a string or a function which returns a string. KEY is added onto proof assistant map." `(progn (if ,key (define-key (proof-ass keymap) (quote ,key) (quote ,fn))) (defun ,fn () ,(concat "Command to send " (if (stringp string) (proof-escape-keymap-doc string) "an instruction") " to the proof assistant.") (interactive) ,(if (stringp string) (list 'proof-shell-invisible-command string) (list 'proof-shell-invisible-command (eval string)))))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; ;;; Interface to custom lib ;;; ;; EMACSFIXME: A function that custom could provide. (defun pg-custom-save-vars (&rest variables) "Save custom vars VARIABLES." (dolist (symbol variables) (let ((value (get symbol 'customized-value))) ;; See customize-save-customized; adjust properties so ;; that custom-save-all will save the value. (when value (put symbol 'saved-value value) (custom-push-theme 'theme-value symbol 'user 'set value) (put symbol 'customized-value nil)))) (custom-save-all)) ;; FIXME: this doesn't do quite same thing as reset button, ;; which *removes* a setting from `custom-set-variables' list ;; in custom.el. Instead, this adds something to a ;; custom-reset-variables list. (defun pg-custom-reset-vars (&rest variables) "Reset custom vars VARIABLES to their default values." ;; FIXME: probably this XEmacs specific (apply 'custom-reset-variables (mapcar (lambda (var) (list var 'default)) variables))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Finding executables ;; (defun proof-locate-executable (progname &optional returnnopath extrapath) "Search for PROGNAME on environment PATH. Return the full path to PROGNAME, or nil. If RETURNNOPATH is non-nil, return PROGNAME even if we can't find a full path. EXTRAPATH is a list of extra path components." (or (let ((exec-path (append exec-path extrapath))) (executable-find progname)) (if returnnopath progname))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Word utility ;; ;; This is adapted from simple.el in GNU Emacs 23. (defun pg-current-word-pos (&optional strict really-word) "Return the start and end positions of symbol that point is on (or nearby). The return value includes no text properties. If optional arg STRICT is non-nil, return nil unless point is within or adjacent to a symbol or word. In all cases the value can be nil if there is no word nearby. The function, belying its name, normally finds a symbol. If optional arg REALLY-WORD is non-nil, it finds just a word." (save-excursion (let* ((oldpoint (point)) (start (point)) (end (point)) (syntaxes (if really-word "w" "w_")) (not-syntaxes (concat "^" syntaxes))) (skip-syntax-backward syntaxes) (setq start (point)) (goto-char oldpoint) (skip-syntax-forward syntaxes) (setq end (point)) (when (and (eq start oldpoint) (eq end oldpoint) ;; Point is neither within nor adjacent to a word. (not strict)) ;; Look for preceding word in same line. (skip-syntax-backward not-syntaxes (save-excursion (beginning-of-line) (point))) (if (bolp) ;; No preceding word in same line. ;; Look for following word in same line. (progn (skip-syntax-forward not-syntaxes (save-excursion (end-of-line) (point))) (setq start (point)) (skip-syntax-forward syntaxes) (setq end (point))) (setq end (point)) (skip-syntax-backward syntaxes) (setq start (point)))) ;; If we found something nonempty, return it as a pair of positions. (unless (= start end) (cons start end))))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Stripping output and message ;; (defsubst proof-shell-strip-output-markup (string &optional push) "Strip output markup from STRING. Convenience function to call function `proof-shell-strip-output-markup'. Optional argument PUSH is ignored." (funcall proof-shell-strip-output-markup string)) (defun proof-minibuffer-message (str) "Output STR in minibuffer." (if proof-minibuffer-messages (message "%s" ;; to escape format characters (concat "[" proof-assistant "] " ;; TODO: rather than stripping, could try fontifying (proof-shell-strip-output-markup str))))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Extracting visible text in a buffer ;; ;; NB: this is possible automatic alternative to proof-shell-strip-output, ;; but is more reliable to have specific setting. ;; ;; (defun proof-buffer-substring-visible (start end) ;; "Return the substring from START to END with no invisible property set." ;; (let ((pos start) ;; (vis (get-text-property start 'invisible)) ;; (result "") ;; nextpos) ;; (while (and (< pos end) ;; (setq nextpos (next-single-property-change pos 'invisible ;; nil end))) ;; (unless (get-text-property pos 'invisible) ;; (setq result (concat result (buffer-substring-no-properties ;; pos nextpos)))) ;; (setq pos nextpos)) ;; (unless (get-text-property end 'invisible) ;; (setq result (concat result (buffer-substring-no-properties ;; pos end)))))) (provide 'proof-utils) ;;; proof-utils.el ends here PG-4.5/generic/proof.el000066400000000000000000000031161426357011200147550ustar00rootroot00000000000000;;; proof.el --- Proof General theorem prover interface -*- lexical-binding:t -*- ;; This file is part of Proof General. ;; Portions © Copyright 1994-2012 David Aspinall and University of Edinburgh ;; Portions © Copyright 2003-2018 Free Software Foundation, Inc. ;; Portions © Copyright 2001-2017 Pierre Courtieu ;; Portions © Copyright 2010, 2016 Erik Martin-Dorel ;; Portions © Copyright 2011-2013, 2016-2017 Hendrik Tews ;; Portions © Copyright 2015-2017 Clément Pit-Claudel ;; Authors: David Aspinall, Yves Bertot, Healfdene Goguen, ;; Thomas Kleymann and Dilip Sequeira ;; SPDX-License-Identifier: GPL-3.0-or-later ;; Keywords: languages ;;; Commentary: ;; ;; This file loads Proof General. It is required by the ;; individual prover modes. Loading order of PG is: ;; ;; 1. proof-site (variables, autoloads & stubs for mode functions) ;; 2. stub -mode function sets proof-assistant-symbol and related variables ;; 3. prover-dependent variables defined in pg-custom ;; 4. stub explicitly loads /.el and execute real mode function ;; 5. .el requires this file, rest of PG loaded here ;; 6. further modules loaded by autoloads/prover-specific requires. ;; ;; ;;; Code: (require 'proof-site) ; site/prover config, global vars, autoloads (require 'proof-utils) ; utilities (require 'proof-config) ; configuration variables (require 'proof-auxmodes) ; auxmode functions (require 'proof-script) ; script mode (require 'proof-tree) ; proof tree visualization with prooftree (require 'proof-shell) ; shell mode (provide 'proof) ;;; proof.el ends here PG-4.5/images/000077500000000000000000000000001426357011200131365ustar00rootroot00000000000000PG-4.5/images/ProofGeneral-splash.png000066400000000000000000002020031426357011200175140ustar00rootroot00000000000000PNG  IHDR6^3gAMA asRGB cHRMz&u0`:pQ<bKGD pHYs55 !CwIDATxw|iv?o$@p3 ;fwg*Y,ɖ+Jk+?[VdZ$+Jyf'qs@"+? !9$4@wWU]s{sC:tСC:tСC:tСC:tСC:tСC:tСC:tСC:tСC7p 4MTBRJ]JiH)4)X[oЄRB(";BH)B [$ !j#t5!Da;vLN+}H; ( (ZMBRJH6o))eZJR .u* ORBka|ˆ(}2޺JSt ]ץ5]4M;i~EQ !'i ήa {0 rEQd !QI)A)(}aaEQ&";# C- C0"eu-j (4PQ PQMPZ4K @Ŀ[O}7 W)uFD^HNHU}z@D~ޞ"4MC7t  (~B=(ʫBRʲB=ztOm޼M0 SRn)尔r4Qmh)^a 0 P0lVʾP(* *LZB%I\#;Wyiڻqns ݀[tpK.^ïyD^$iia4>(몪Άa9rd Q0Eц(GQ- A ~:5 h[\C()bhfh Y9R.aPﱚfHbw6tCSpp b6X@tLIJi't]^U/ !^(oYa۲e ͔l # Ýan`>lo5b:z2PLE=B/W5Ziu~]ri7pK.i`۶cYI]׿iEyA1EQpرޫ7q(RaxoEAp=˻XP:F@O]fVjYZbխiI[tNzBc[r $iضZ5nW"(R+7nm۶ !a_E0|unuU0f P -cfL̬113f,b"sP\ܲXh9, ۶ke1 K~V8EUU'VzO: n;a۾};rD"0 ?y\h4A[4K20s6v51Fli"[(";Kؒ+MKN4,"HL|]hf>Ǐ_&mfzzl6=8F!ZrTS2zl ̜c![nuD-$A'pCZ %~Yl,sWC]ױvdi_uEiaʃ.un aۼy3B3 ;jZu]m\"ї̘PDGގHKnW}usuGD(i$z"أhBc@ؙUX666=lVJs=̬IjP+g9ײ#fo{B/į0:ȋpK.:~ H$D"q²4'"|{jmÆ ukƯJV $dƲ$SIQA'l\">n!#TUŶmm۟4폅/J)fU #P(|^+F hR'w #_ +GZ檺*:( eJmaCQou)%+n.Eoo/KKKUftϠJG:\5BAW>q"S:v_'b(Np uwDQa!]Bb:Jׯ,_E:a۸q#ahtPjY6kޱ/p"@8ְ{ؽ TS%tCܺKް].(;t]GQ4罥2a G Ŭ|x dJjUVZ4mqEVv3vO M=+~vQF5z 1!cWTU=wƱ–m[u]'C~ӽD'*٘GQf;bƴD>:۵6009~X,^dg6[!D93$Uuʬuwwz^.7C^ǤCE1c״8ީ(PNQ+b–ֹR9wu7K8wA5)$XӨ7(u=l6[$^Sf#Ž@ SCTKog?} Z*rZZZzTUldE,TUEJjQqDz$ڡCN`t8 Նn2 l6[Xn"iܹ)hFLvpiG|t+oQוŏTQUul޼yGjX}HDuctupEՓ+84J |SUueYs1+c 0 P Ґ[WFc3$Sjw([ Vz+Ί[s EQ>"4Kj`,YCj(y,--=RV[Ӵ˛#-–Hp{ 蒑DNw >pQ(ji]acn\zzzB 쎢()ڐ $mjVٴiJrE֪&슢LSC)n.wKjY0 ٲeJs˅M4(8ƦB\Yѡu"ҁI $q]Bz+5+2y DJHN:Y1`u4 Q(qBn +"lAZAMcu&`u[ <06jjT!i"N6uRZi"+ґnRrlW*Cm@nj5 J:tqtd *J>o[.l l߾@on0r[6 b^bo*\آ(bqqQH)vB[YDyqpQt}xu]ߪKRoiw%B`YB-{!7F~~#pB"#44[H)ZtVbtx3H}k>bTUmo\ ɓrtt4h-Q,)fXS|IwW\W}tg,)q\/,Q.X)C-٬u[uX$y{z,jUu'E#!~d m#DlFQ@8x^0p*W%|C!n#czמ=/NWituݔë,XX,n4'JFs˅MJiNb&YTx]#=ۛ"|ߡVsK4 ^+ d"ev~+B!2_]+cf85=#9+}<([bSn/~~j M !m322}"K:㜷BoooǍBA_Oo<{'avp-(FRTv0{we2aźT---IEQ.?Ϊ!l8FxhT-NQUUcǎ] !XZZbii&IR"Õp˒ِ!Jݞ%n.W+"l@q0SAo [G7~5mNJLd% MF7IX4|[v.A# #dGYu*ǃ X,MH)QeVӴ į4j+:^FU*8oVid8ͥTYRB2ip^yHaD5\Gq=uXN3PTҎa#7:6|3XӅBl6)bAF U!=ܵ2}F5ᇾSJQ\eqq?)%Mww UU(=m#AcNyDmJ}F}F}-6 "lZOx Hx%b`eY_꒫y"aESԥeYG5U>[)4{+R@ѫh4ސm !(LMM]XR!VEu9L CbiD~l4 "4@PL=e`dL1Гe\{K*wPSՔd2}╕ەXqaK&g|T*'J݉Go"iHѠpPa 0z@1sᄎEݔrLRh|L(֭+=ċXQa;{,6l0}mY2*(Z̚vQ0PC&=AR ~.\P!z쎢CÏ.-/˟#Tiɇ(WqbRv1szR˗w, f"3e9mgY0 ޥX2'N`ll,45{ʧJ$פl AFԑ%~ئ Ln:AQvZvSUМ7_h&̚YP "%gAiDbdL I̼fiEd׀ YJEFú/.Ŋ @Eaxܲ_iZ ($׿f%I0DQ[T1 Fўmm4DQt×WE2ţDD̾Z*bm$#jSXhthCiDP'jՅ;"w ̘G2,VI$aƫjBbn 8(ʚ mT"tBkR%s_1[4Qx6H&IMcuqhdvAH0s)G Q۶Y~='O\Y xW4M=z#y#s{5p'ǰ[999,kPV(ϕ-\.G:}c:t8=|BZ{"[I $I%S:R;[tDl( "PxƻrLmۦa'tVնj `iint]?FUTM~ wλ%ծbkYkǎ>Ӫj ʀi)!SF#&C %4K29v&K}oL&_?rѤ@\EwFi7{ 0oHe!EVEFz9!e5e@bc5fƮfi8.1ȘPRR(QyuBB!DBo}RQjqGWE<]]]g(JASsD䅘9 6Q5Q>Zt[(a^B~# po'rL"A#@xc26Z:599ٞe``"VbDRi?&u]0՗07t'~DRwvI[26;A~ o-?mǔݗ їDTGd2^C2TCh4/VzhVzP(JPU(4!6Eݡ}^x gukRtmPq~֮jwtzzŶ600+B8҇}\.w݋LJ<5jBP`ǺlcX,ل2 /&zS"PUՓ:VK`-dԲgk0Bb+#p7*L M,۶H)|6+ !ʚyQQoK\&p^+M)YBKtCj8)հ:IjZ×\*@U :L&1 q%A}/ΗeI^T)a`]w|}T!Oӓ8<]긛t!øȵNۊUTKCO6gV[t)MN AZ Ozp!QQ9]D4OFQt (J- 洢(V4[Y׷QAgq",y.͊u#y!rYV[hS})\*X֥ǨZr|8TU3⼴0 ۫.;}jg;k-=h[~B㇜]jpPl8a}O25&%t:? Lu\ڈh1 E!^EcwZf;\%"ڪeO"0t]r#lWA>'"GJEhVf\ +-,' "zjZi =8s~DPy7\Bu̙P]Xvr-EAu <"sss377gϞevv|3:/_aE׆uW#BTX56?Mg77!b=w'K[*]-Èr<)Sg`[W9>[7_SLE]U3oOja@dǂQUW}jSUTUm>WV捗M T*1??߶,d`p BRT3Zd]]]0::zɈxe_x$Wo\@ 0&g✸$}]JҋDÝCrI!`C_Tl9ޛܖZQ[˱FW\UDusuJNjx%̢^'͉ʩ2H$"MJJYUR,ri3zƯX20&wj\zK!^]t~  8Yo飿/uK* "\Ŷm$rDL$樂v0dZѬv~U^>"Io2OɄ*uYm~]wL񒱳8ģ\Co#=I4UadiuM NUw8FmFi@i/{"Am[rH$eYNzӊ^ էf,kNJNeu'Uз|QZȻ6{0>WeиXXYfKΒZE? ^-'aH$H$yv✷ke}/]7!B.H\"B̔/fJ $IŹmIZ]i exAtmyqY؈M(KcpJt2[v:XӘo`\7GӴVfJMӦ6nchrA\зkY2>z{]Uyg(i+oszbG>2]%-7EQnʚQ*y핽>tomԘJ .̓ (%xtBͻX?Cjv0[3~{ϞS zUl6ph7]%M+G+,V=X7N6gslJ_w|= b @OX6Aͧ4^$v[^27!z[vI$i Ldk("4M[TUu]z[W}6/ƻ&4?t:CxBE7/ʫ|cs} ?ľ9cܲrG乞RJ?VSh% zu"vE@rD xo\)tUh/|0(.S+9<{t/b9˯lo -벼Av g14BjO .-!`/'߷[vch*ţj3R"":} 5\dPv(|s[|ܶ3 ХEA '%ȓTWOqlR'k݀*y]*͌I~u>g/~C=c z5IS00 bQ+ EPK|N 791T\˷>.K'=.!t.//3DrϨ)hvl؊^&jJsR/^:s/I(B$zt%nsϺM/a|I KWk8ˉ*se*4RJNnkbËԦd702תF=@h( 2=="Cm)RC;G 8{{.cIPq9[؍I&I4&Lai LC`CI7bP߲0zdq~M≔$r0لxᇔ8[SKL.ۂv%˨gc87?̎,fBkYJ#eӼzr Ca$ΒK|`fapQ$4g>e~̔ jEq(.TZ0 uiF=jEA@BJ9(e@ &$/,P{8,ּM誊31߽:E]b`.fKDנ# > ;g2Q- &=Bf$})HRy,T&̖ 5Ǐ+5şK||ۃ# l /pdW% U|nC;C#92]3-y~1~ Gq8 R'Z%x"7lfS0$~@WU_^EAQZ [&%u6`nGOZ#a|ì&ol~mQ-$ٟDFЋF^HƮ tMi74Qt[_[k z4Oa,Bp5bKWG计)DH_;<ǡ2U׿lܫ[ZMe/{ر.`. غvS*n{B&Yyz8TO?Ix5k8آ{m_ooMC& -l}- Tjk}đP`֦+a!g hEj&G֓Khc[{IN\fFz Uz҇Zs&#I.)nsIZk3/.i1_ H/Toy")4Gv 0T"UӋu)ɥf(.93I6>-}5(oGD"؟<3O!ytMi>xZNWڑ2k!.35 Q="^)eXU[klR[XW' ̖\I,]8&4/gRwC둑8^ XG5o=3l:+7¸yLzq# !Qj4#@"[ ^{v2X05st%CqIh,Y1MAh"ض *oKWX1TcQX"] Mc=uJsHTxT3'FR}A#0Dsռj@E9)ej%s "T" }'obc}oETEa@KUR'"B٣,V] ~KY_Y9Q2nS>n-58A@&"^tZ 4MATtMAtSGTUAiZ6Bi5,$a$ ߏ |6]͖ T3Nl֬ѓ:ZBG5 ].xBtz vEq."ûke A(%A$ ˆŪbg*sjvE&|,|0xwx ?V\}iƘ5KÕQ%m-lBP@*Uе3mxRJR?cdo[l <[>w5ȻeqP벜)\%dRA=0,6p.~Gz",d כ;A"td2]]&c*a9Qնȩ^.غdKB|?C|?B  h8>CP.+.KؠTr=:e?$ e,|fSO-.=m˔Zb/eۚLӅ57`r/eBk ".󃈿}e@£{yybosշ9BVlQahI)ofA76) (,ЈHצH*m!al0֟摍=|<eXNm%B; @u C(@Wʌ:ݕaH CzS*Rx^Ƃ50#NDDlb?ZҴԦ(.X6ftCES鲋=ɸh>j,rsUkט0?_Tr(x!)xzBʚY3kōqZ\Y_INs?hao[mTzzsuK7"aj<})Rn7&6D(]. C%lTjzs[ EOOL./O'I.aeme(o[DRrx̱fl-$ҏpK:aGSr9m[ؼ[z]c?m먪,\eff,,:4R+s [M4ZiE]4LhضiMKP!6Ιd l[C .IM ѴRPy,T.sTӓ%ff,Lר(Ib]&VN`Llsެ畛pՖFSܵ.k2NMXzn;dmΖO DQ-vZX֚N@|'LlTLܱE .=i٨$j "j5g+4GS&wsܽcy VNxy&TSFжZ5yH\?O mTs=Htl[2TYA2mϙXzm[z u 3N.r|b'c[:]tTĹ=6V ]нaû{ޱ\@mtkr B.{N9&WM ͥQ )eXޮs>POpL)*.e3ETEi:_U],KnC [jZ66ڵ)s&]]&HqεH)i4|L-q||X-"BmcؘY3^Bw(`0kQu}*OI b2T|*?:vxjCٟY~W~eEr [HɅ:ܱ>@"ei̖fV;Į^F8%ʓeGW{q]d2 .ǎ33Lq/\]g)aDd\l*ҝ7Ka]>kx|?Xr8{%E&ϖ(L/EMIŽAͬ'}i\c]()%i>898xD|.biBQ!o*X5TB@Ay^,b*"yYLx*J(Y?屏N1=8v\-d{h^!Œ2BUQH*=66DzNnm;A0\q0>āCs9EJS:vM?ݛ@OJ ]5! ouQ~I.O$RTE*kzB i1fSws'1 R8^>]U1{=ƶ!]b7fkBkOJIP9q /a[*Ɇ.F4a@{پ߷rej#;0Cs0}UEr A?kZs\GnBU@HFH)A+v6G  M}CLy "?Ëfjl'{U̙*NS&3PNH}ƙxq18`,wn˳a\m6۷᧷R(68qgc,_`aBOh]mCkvwq׏vyӛJ!u J.kp,5Pt`dԓc<(eg?yRٍ(1Y[/ql3_>C_ͦ ۷ټ1CwM_o7D35]9^ym:Qxt -eKZKDtp^' `J)Wfk>Ӝ,rv2H &I"їDe;wK( m- C(J-Ju^6Ueú,}fҼSe|?jquX>0ՙKs&G3}W7[61MkX&g^xyݯ"E,4Z[#p7地kˊ]diiyEEQ Dl jXk86rAuۀE/;oycf,=6ۓ7ca}3|+Y?KMnKLlu!8YFi^nۖ;\??X^s=J Nd8uRnLl[rV9=Y= +#[6$/;,SejSUnԚVnRpլ䲶U/lwO>'Z^V%< Z h4fv\*wl c9t,z~0E/-nc4c]ף<{wu4̊v hYEۥd2TUQIO`學 vNJsVJ)W604(?UTl4+VGbv9W'"{/\??g(羱8h.e\0}V0 xם98yW&N017GLT#c&{]m-rd+0vU+lhf7^.7J)rzgI[山-]5RJ4Mcll|#$ ~7~z7?=]5d̈́Oeqz:h __&C&6rj~Ns`rbRHT #m jz1' tBG50QPY)a[i6l@Q+J{aa!J,z \.wTUE4r֭{رco6O;BW}}ݸ (̩QT 4*ȵR#w/VkaaR!"&0RVmcd 4Skv+tzEjUtU'L?yt]gbbb%ذaa؎wx`gemąq / ElyL6]D"eYdYH$ 022B__tY>O^S!`pl#7{jZHRs h?G,V3̲XDBh Y٘Ձ{?x`!h1 rܞT*_۲e GY>6nx\\r S0Ml6i0_l6]qrgΜرc?py݀(r$V2ź;@BbwuRzS"'@m;17S0_.6f~ IESnoUxpw4Mr T'+KtǏVMkMO>_t.g!]*.u_sbHrEchxmzJ&Y̆aJÐFqTK%*zu\= Q}]SU M5, imMҴHZ&I"m[, бti BWtAtRDCHZwX}hgf8|vSjxAh˚0&zB+kٓ4Q| $TflA0e&ZA7A/qضm8N"0ֶboWFv-WmԊ?麎eYm׮eMYEOO=== TBj4pzNu]|Gi6 %}m?0e7gEcF|$Leeۤla0MAҴ C5MQP V3},/s/8(I\vs2"y8*RFhAluwjss2nqWu=e`eM̜6 M݆V ]sptT !]]]L&_m0 ǎE!x3?+= [['>zZFAL󞖻r x*2QSr틨-baHM>je%j4-\8CױL2IdT"E2aJqt*I+E&ę)կJw/غMIiƠTw3q>KyMHg_سq?~?\ƍ|{fcq.%>:Bf͛,,n'TE׿[?qvn݊8S6:6Cg=t#.W RT(*fhiͲJ,R UKZǦر\ۻ1ՎzEaܶmy&3v. zQǩ t'e۬Q p/9ԼXT8KNh-K)@uU<*4 !JELy۶QQ/axڥXuroߎ(DEY[JR@BJi ,,,awXȠY܅pdR˱t5Ԝ_ ;m⓿h/|.RN~_q޼yqlC7^{~ߓfHB`o>Ǯ}G%""Vs¤( J+9wU̪hؗ=No]UN$w?ض}P/j8:nEa5JeE.-1W*XRs\0*Ь&lDAd2T*`RJ+ Ug-쥞qF0 TJI0ιpIiOirZ#T|71<~pۼͣ#?/gM>ӻvmEiq˭M+PETE=RѠRXBGmᕉ +|+]At(ؾ?7ǟ__o<ϼ16tUuco#RJRMo. Y72rY܊1z;Fvw-TzK!;.z=vcE\XdXyhFW+H-UU?Ew; ZU-lWKd艢HQ#9fP5k_pW#^Y~7ϿMccJ3rh[ |#<P+Y+{]cf0 < ;/^|G>S?ez(B3=3uW Nu4@|n Es;qOqWsϑH$sUUFqƲJ[[BؚIk0D4FGYwږ'^̞̞woXM7ckHA)zEN$wǝo?e|r;7m;.!M !j) >>؃drx\-T-wҝMw<={CXP?at*Q%-[oQ׵gfݨF*z^0 q]wus lV;҉{דd7o%V*QE XV /Ɉ_c׎m& ة:OnRؾu3Ͻ2'͛ɤ%$f2I8ݩ4G9|4= °8/(3T;};_*{A{uNMOӛћˡjGEJ%wukfeխÙ9E!J(?J\^CtۋiW.r4}I75_inz$曬! g{.K xQȿ½-kM7\\Zc^3^xCLpƍe)e'+dm <*F1.RQs]x4O}B[E\'r{{]`ij )#?zg_afwJd㜯[[7340/gϲmkA3Lt ױT=Nqi۾͛xP5MPgxw>}wz|G.Da矧VM亻1na#bk L&_SUaʎ Maw]T*ZèoBpe 8 ww>bwV ;ʆai7'&8|$cCt_[J+Oezv1̕g\h義~!qz'x~^^سRJ>!Nw\&RJʫ.,p(<[mW)lT5۶?츢+2aj<2»?Nb}hT+2q/}wn_$eqJXȅ`lrx|ǎ1nfJ%~<`POtZAyF~{q^;tl k^1B`%XBOMr#WrQ5#`>A*чo/Dl0ӏ?;߉m83ūW^詓(B>ok O7e +RQ<7a:{X-wEQ88>WvnwtWl<*JjϾ8v4#WmhAo.GRa;twmgl76VQA5PCC<I'933뇎W_c#8G.&aY겥f7CؼC'N_J-#p]DQ8y,_5y`+e<똦I*zFJ[7mVzoŖ<{*JWw>0u /:WwSX.Pot 'L;DIX׬H0驳>= #7'nB)2b'_w݅m;y=|cS(uunYܻJ*981p?==7}![*_'u|a!/+H$d"+॥7^rd|Jx;ށqnDMNw3xcƂ3Whƽ`9r|yy~ 6]{ɼ.2= **z5xr䙳?pOS'9F6Mr]],J>Ϧr Лˑ훒."+I6_ _ٽMUYvMY+4矧˲wlEQtܒD ׾αӧIӎm 8v [^܉;~B `Tb|flWw=t_,fyՊ(|#o|8qWws8NqLݠ+$ɰuxtїϓI+/{8z4yxtN6,.YDRb[lw/?S^?rяydyoImhq zqgM'Wٶy#ϻΕlj@B:qg,g{2φkyC;YKo.K.K/k*3}۷sffg_{͑'9O_;n];{PYibdp?ԧ׾ơ }:%Xoy]|>)Z tg3|ǮW7^w񱧞Xo=;GX*s19cJ%GӴ lZ3Бc<ȃ@e#Rŗ_~3_!g'c}{׻x{ٲ~IåU_R\&[6s1yy<$me)%D ܳ19=>zr7 /8 ظ1Յ>TUq>jLQomon;RTUi.nV]iqv~O< =y;O=Ț5|3ȫ{sW_WtgTK%n?s#J];8Z4! øSV) |ʵjIaQD>P,gf8=3g}5}}ؼog=0#)U<[6O?>s;~?O?h.ZI8wѸ= <2F?uM}[[Bؖkl"Ӆ"kzضi,3,д7>Ѥ=[MTW~|O|^o{)dvQ1~瓟6y;׼ cC?wI>i/xR>zJ< e&g^X8T ʮ'#BVRSu5d-heY9)>͖ٵmF+<{*xGC;v>)~/ xhl˺vTJ ]'Ns$yt'0di(/+ }3텭)jQZ stU e)2]i=}==W5ݽwm~Wy;t_?^~~awFQC|?s>ŝ7/g$4EN=ˡL09=CV8@JW;̢&mld:PU, 4\%3xg^`tRMعu 1tWDT>w_*/ 㞻6a\pܮqb&Aqc͌ !(J@YEQ<#!Dj+'[tb y?{ =|OaJ$1 U(QX9]e #놸kowmA Z}"EIw;=GO}?>λxo{lZEu##O<~.۵rI^9x\S뛞$;Ѓ0u!4uYM+&cAAMX?3KCNMZe߱c?O_w7sVm DkkE,];g^x{w'd_ !}0;7_ئ9;71(ʩogn{akA\*zu8GTbn5_I%r?S8>9$?ɟՕ;{y1 Ƒ"p~_|Ͽ| _^ڿ=xQۖa|>FR5obNs $캇{w=D_7bADrN mM/p?Hzo=lW_~eK$mul۰6q0== fv Do?yҗ+W_ѝ;;MPEA؝煁OpR>p`|ZA*BU:TU-BxB ĿotW'޵F#?|W^ _$mی 1C} JQws(/ǿ_bp|Ʊ (\$P=ޱG-ϼ"O?}Am ~F\_w/y]ʿ9}>֮]Z-z:v!0y MDF8,~x-gBgyqݽW3@QR=,CC 3f #I2$DUQOMJ C;M|W]|w}l M.)p{ug)l_+iU^ L/!HHHHHBHFBHh!% BC0۸"ɶzVz3J⽯\;;s<~80=YͶ3:P3 vj,o?>CCC/s.b34:S!HrZMSS#MW,* 4;vaˎlش]#<%J@qŊXŻowp=3kogw/p NRV`YC!wquW?wO?/&G\f=T*.fns^goYz"V.ZG~o /C}o?o>lӝp[,z>?y?v7KyIY/ŝ|6oɇ|5V^AB N6]ѐ_;vl@STiP6tSʹݶ8N TKGVv n%Kپwg8X7C7ͣ6],>?M2) b_<0_.\{ ::gVj=Uݨ k!X:AQ͒$\(mbbzSQ$ 0(Wp Ϻ)*dm|>PIQ_%I" FXp^}%S_1`<ٻ=+WիKyŗGyrF]q)k;M}mooOoǷw7<Ú%KKwN^ڼ?/}K/^咛 ˒ &Q@$.m˘9Cr$=RevLtA+VKG 񡷿 1tB@6%1d"P*QVɕ+e*]ǴlL0 L"M7Oͺݾ?D+Tqkaq0uZ۱ٲg/uE>m'b(N"pM(V3zcuZښ=j7$";p{MmM۶X6֠v~O/k>WZ>})>ُVdM3 Fs?#ηqÏ;f݋/<̛3du^ڼ_YC+kJW\]f1UW>_t@ p1k.ynFS)ZUx2IAteŇ?oEQu_q"q`5%5pUg7>CZ BHKVܦmgNC֑e<IDAT2ֲ3:'_ꓵ.Splۭ{0;4x$Pm"Ims5'<ZVSx8}rp8+7g !$iDe '3S1-a6jujŧEa?\+0%%]˹Xb9p%#ŲPeX`>ر{/=<`߁^>wa !.dydv> <ᗲn%W6I6_kG 2$_::^iN[jk_d&K}$qfXsI98<> x<"_`qg8ŷ@,kkZ.S.W+b9];^/EX5K~zsh+7d~'wqR,-}H"qllˆW(Qn6nBZ%ꃕJ%r q㊢ BJJ8&f `wO[vㆹ^8Ȳ*+kwCS;Zѯ%w '#5u,Oχ/ zYp(q]8j(L{{30:E )e8 d6ˆ&eY~DDžDĨ[F,ˤs9)T c:c+yrK !Ǝx[.'.k?psjX V|x" zÓqWHF72 Wk^m\&IBqYŔޑQ@TI\\Fe7l;n7MоwlA I@xՉm I*=NqW ô,m݊GUM,Wu^-\mD"T**id Szٶ8&*ν=\zJ% m}_񃗞U*f)zsuI>zHW#'E0-X_G}2I0Jx$rFgkŲ_~2IA:c| ImWq^=\89,(iNm&ŔD}$&ҹ߱ g,j: ãJOK企㐈H&PѰ\]vH$rr! DTbp|U:* ؎æݻt}Z҅ Al0 e )OHʨBWc#P[)YBFB AKe k>&p\WC1Lt,Z5+)2ǰ,'&^s2U] Z`U+JWo^e\0Vð(ET&3~ڪ*D~"a:gם'p('t^KXdb"u6g89񰰫sf$t`x|On!I O`Yx<$IV ߜ:KM,!c463pTE ;P*fN8BkU]b+O](t`BTJbu83eƆ:>}#ç|* vwV%==d ^/x.'ElB$Ic,hYln#}sUMM^ܼ}zgN8DK.WpNҮ"@er kzr KgȅJt19 ǃ@<%R3@jk:[k0Mكmx^Kj,gt6.bmq$(JRa2xn78O?~"X H4 8K1$VU(+H$4Cǡ.  l>vY7T82P7.Iz۶9{tvq[RmSUQ(U* I4" xUem8? .ˮkH^֬\NvBS}=eMq%/-f]T5mcmE R8p$I;UU-qm$I<^Y2ѱqyr̞MscxT.һ I\qj$!0hkbW5%K.bKiiZ'>EQhn՗1~7h]*!̉ qʋff=נ*M 8Cxj¥ Y8BPTؼ6yIr3/ .C!QeXHRdRB,>OUU/b sÏ߹x@wk+-8/nʺ6ƛ?q?o.6nO]r)gTzZ*lymm,Z8'גڱ Ao@4t]4Ml ɲ"Ia֝$C ="7\;dTK$h4@:?O˲(WHBS98'ZO EnwS H^踠\ўŢ.vCXMy |f=~V._kV@| 3FlB ˢX.#Kayٶ$Iyǹ 5$%cڎî3jө#nYX5o~x3ؾbBDYN' ܟd= zM.x"믣ڵ#cB*i0wd]k(@$*g8خ:BU/_.WUMg6NOQ$I=gt_\p I>UU'zg< lan} G;sǢREijjAUȲ秽}+V^N& r輅m|BnjlG`ܹG=`iZI^شg7xbwqE#,YLM[Qdxl!'n=ЇcYH$ˈ"2"Xvg̳_/*c-oG_ ]pR× 砪eYaïQ!md;EkQ7̩NUY_;Xj'tRQwx:M0<!|mscO?'I}[w2%~78}U292{{,]Z_O&?8;vӸbuK 65ԎQPHھ6PLC 9lh s,~ TP8Q${"@uGG x<ď>b&aw(ض%Dk.0|CQ|^٬u.[vϪ^/`D]M<D*Ŝ9-Ǘ&mV._v?VOYap\-utzm oyMc1>寰 !2t,k3[.>GbͪnRsP;Qd4H~ޏr,W>65=j"! "/qNOJԶZʈJlSBz9 y7kxNP8YQ (>?BHPd}{~0_ͪ|PdaJ\y󍴵4̘+.?lٱ6n[Huj|%,[uW]K|;,k|xd;Eb"6rK6.I37 OLXL{ eۦR,I&Oi~֕8Nв,x\`,9,<nYQ.X*EGs ;$IFV"#e etEOne6fmw G{Y|wއg|öF#\s\s8EZ4-UUz<Ua>n̟Bǀ%T)C5˶e ?`pt 0h#GOjm ` (B x `cccݻwRU}^/4;{4 20C!śo-ty =إ~ zyֆz>ຫ.%C8ӄ%  |^ :8!L T5 ˲ܲQv\CѶ]kqj]Yc|VVN ީGeYRkqBl۷x~$,`;9󭈴5X,qb9X#ǩAȭA "{\P$#௑Tv]@EVNh#½9 tE*_RWFļH4\3AڵrgꩋHB029ɺ[ yLlܵk0w⏎mEl+o$S(DPJr,Xe `e󻺺"a^eY w>;* #$ic"g.-v='8t@JˑmO]uDٴI.],m~LB\44Ƣtd CC3Pm5K_2LSPOǣtww֡dɒ%24ϕJ;M$IZ+ j,˿ %˶yfǂ!́ LU+b pAjo+#n SBBUd N-.54逸f"+$}rY:|3&'Ȏx[Y ]eYRlr?m۾|…gҥ,[Ltww˲JbxeBBs?`¶mEymS-{?2ʂcTLK3pt$^V>eWp,L.@8A浴pc3JQ.<[~}>_^1EQzdYE{ 0rT*bXXex(4wyN6$I1EQm0k] A]t W֬Y̆ 8F&bx<q.V-\H{Sq/,YQ F94GUyӍ\z2485B+@ !yI=k z9~|ャ7[V.0m' xgyÊ𲞇ZL9GVUrvu8/[ʵWZ;הZiji2XrH$~888﯍;WUjBTTU# ޒN=KYRB8+;]qޭ9ۻsv!IbY_e7IpX!H3߰y^|^/~)I##{ {ܲj%~x @``lSdN+bWKE%#Ѐ/t9pƛm#:Z(W* EFRJ%,F$~ 8!Efmn}O2#P;q:H[DT7|)*#Fk 0 sG5cDT*#^`0z<XvړΩ \x1)߻;vڢ$ 0G̾wr U6:bhzZRٗ6|bB}$LX"N ϯײdN+Wv/G\&D"p(THf\)DQ`ڶv0OhH&hBwxmg-6lիVzQTJqhK;>w{~֬XN}}9w[n9w?bSFIT.__ÿ_ߏ$K|}ho;H2Y}5Y#\ȣkٯ}/~㇬ۼpE˹lr Ovnc%!ذm;ST5Wm10IOotw^z -Dv=g0H,I4l̝Su`4?X엙L9W-)戭]QeqH6_UU|1v8@C"]u!!ОL2Jlں% rfN0 o.c.wXNpm;v7_opU˗;O>L]]!5KwK6E0 3q䮇m?+ W/^ĻI*իVq8D{}T:N$IipPS?9>Ǔ;vHuuuwtt:JAbK$ ^00K''iH$X`1286ƚ%Ib(rQH&˦]y',߉( e`hϯǟX,2nXuOg'  ﳟ⚫p.΁}Ķ@dV-.vIARe=|w_߹nv n}e\ѽd(JrQ6r{n$q`hW\5x[X0Vb ܜXԎ;2J tǂ'?y?)v:ۛ;# FY'7d6]D0^`2#W(Pt.]lv8`+SkdrttݾsM!`݋ygx'd2$Ldמ}|w7~~=J%nj H$gJ-0t7yY+C A~Io= $7w^z)tuFBbqUW`n4IāA?`}5xrX>wvߡKhUds_?Yi$|>_;>oH ^LYmc0.Oì^[2NzKc2ɢyPTr>CBB~Z[dc݋Y>/s=W+.e u._?C#d2Y6n׾#>$q|9Kj gJsM7jKp äop< _C~ر!r\޺f5oZemms=zz.rtt9-{իeJc a9!@nu`;oMBv2|)_2{%J>}<p61|ˊݣcc-uu|{||iGFF;򺫮 nгtǓ)}r-xu1?mew.|444j1p]K8h)ת#ߴ]ϳ/mwh0 xkgy{;K̡1S>v ò{8?uis_l.[֬u nI rȔJ72nY' *|>ĦM^SGZ288;psCүy߇mBQd~ll+??8\n02UUb<'W"4 `͘25jYL&6,$_,102}Xe/lΞ^RmhKuݭʹ}^> B=|Gn*~h뮥U ,ߟ﯑Nv0,Lh6Q0JSuU% ځ@%$I8gϞWe4^s[GGrӪ_JTPU! dH4^K:g b1A"«( #`nK sMhnya7oM[.[nxW^9#^-픅 +NlRJb5צ0 bd9]{ٹ!&3YLB$ Υ4bdvM8?3VX{(Eȣ%]]4băATYFf:rVE 2B\\iYȊ!|)}$8cŶ|>-jLfT`X$^/M._իVt|[ ܴz5B04D" IyrI޴j%Wv/d/{x_>AZXl +-aŲ%,_$Pؚʴ9Vgz9tC,)̓6EֵŲp=Js``aq&Y*5YnU,niZ  H$RU۟WYW4HB=B?|t+-|oΈ 6#|]]''mo<"?b$$}UV8t/sJnh9K}ԵuTkd EQlEQ4EQUU$i,/ !6J[Q8;^cw5Il .DUUIӴ5Mbxe\4&+X͙&e}>?w|7]q7t/$*gya~!&CӲ(k:#,=ccf8CH hd݁1*UP( xq8 $iP1 !TUdY7wn5Klض$IuiZ~X,^T*Z_Owk ]bTGe"ges_?:ye1J񓧞=uuL LNr`|LgAGk,`~]$!p \#މ tӤ9òl ]:Bxf[C#*^xTFxrbpm˲0 0tSV)**ZEӨTT4 0(_qI $147XF p'+|zOm [ZhK& }ٽWR3,}t55 :$Mq 2e'w]NJvY>& !H̾}|_PTbp8k-UUٶOų^6E4ղjuU\k`D(D8৪lX^WUypf\Yeb$ItvDvb ҅C JcZtuW^$JLD\!W.-ɕ˔U*NU7M41L ˶ܸ8&FOm8"pn;uPd4J"!sFC!D~>~].$8|sW~sbdAs4ʂf47^_G"z~P4{j"nh9mb[EQ) b:+::f"}?YQkkcCO OL@ (?eT6ulr,ŋSWWXqUmhƕa,4-4M,uۦ˲z=覅fBB~?sCȒLRPSTWh@Q ˲(\|};( aUTkA^ǩYYћfhiZa膉aYURr%⺨˪2,VRVynv a6;ڸ_YPdyZ/""IZ߿{|HCƶzLäRO*؆E2b^Ms<~윩Ou>#F3 B"W+G׭ qQGtu@skJV-U*Yq#JG(nYR,EqعsݟsvtwwcY,G6۶ڶȶV۶I9a$J"~?~@ZS Y,EUUM+"\.X*K6Muu8CP`|y֩LBP4^9w0˸$|C}򯦋F_$A'}eZU|Hn2OYN\f0eX܆#u Yyvy!ڒI޴j%+vU3Gp㒔acԴUZ [iI$hz<*!dC#D]CCsʕnL-!=:B1y5);_UYPTu@/,H00V-ҲP4Hz4,d:wxvnr0#`׀V($m&>HWW؎*#i 4,NUu]w]o?U;mOgaK_?[E--=&!pܷamʅ {!+KpBdFGyUWQ,RL&d"Q]LڶMRePٛ2eI"גB^7c,T*ڻ_{{|PkC)ws7Gy$)X,^Tz]>FA>[x7ҘHPɎQH 㰆S+Gc-L_=Ãd9^"#.*UyK 'h*, ,a>O˯`$v;*p6a`p+~_"//?pǃaIQQP p0V42#ilˡa;Ȥ'ظ>~ö!YWϚNgqX -75Ɏ/md\ɚN$T88oFWLLLx<.E"Mp9q-jm9# !BT9!Ĩ$ICB}$mBJXW vpu /ޮQwJ5Bzy7\fp,HXjz6,)D(*7Qy^~ĒЈaJt0=[mshM$nwz==k3lڝjjdy{; iFN fmр{nx$̷~yCJrM$i(r({eYض-;#6IltGBXܓa6y b…&V۶4k5MT*e) rEkfqGVBvrR.wبSŔRT;2ʆ;:FR)s\%~NFٵgap\r*4}ɍ[{9Oa[`Eˎ/+G? ַ~,]vrvC^5Flv4d I Ms^݅S1u\Q&SؚE2d~s󛚘[_O}4OUQ^P=O"@p8LZX,:&onDߏqgNeP5a0ɲ}`M} (rCx;/\]>SvaeR, tm A+kt-]aoe^<|A:::f?ګWD]]ՙYcc;L=:11iJ&ds|;e֮fFRhlOR̕e&7[_ѹ+imm _y{رc|}|34>W_>)+  E* -W%|Wwb($K,\I(*SSǴV 4u4bh:\XIvmXC]z~mo{n߻.KPHb`04MKN]4MtGO7ţ/;8̛ϪUzg^2>>ax|W E(BR?9]4u4$]<$^Mq.n#.0r`g{>8>oŝGx`Zydd9``m,Zjb0t]! 8 j(!2E"׻_UgdY~D]ضmZk',B룻nxuC8q0mەٽ #ոۯ:EQ$i_RL&b*L|NKڈ$E>ɑ4 l\ ˴PԃӢ~MshSGQ.TȧF23oK:5M_k#DZœu ]y !Bmۭe!IecY3ۘիLg TrF&Tᗁeݷojχiu]|_ɆV?fl>Aλ~M /Nr/K/"7Ęi$Ixry,FpxfOHs淐ȑ˒3wQ:ѱhJM0L ZES4M,ݶeYS?`cԈBX0oCPwG?Mt.@(GugƳE)~d[,H$P(x&2Ebkl!Pb䶟 IL2U`b8žЫ: 5BHf,K)_Zy}8x<8ěY)yqM^3gC3 t]4գY$h]䘄(2ΣigٳHr`BL7Je6?68 G[uy>OedE5yJSuiaQ)Tjf9oKҧ{P}*i1r` ǁBHn2⪴yYb;O1o< @Q+J% <0*ݮEBʅى x$!Jmmۿu֑fyɧHDE[e刏9(y|ߤ8ܢ\.OO};w<%B/ñ $I!,&O=UiHÜ:B =¶/01Kl)$W&R.otsehp"L9q\';M 0bo|>@X^p0[2Pg>TUw~w\B-o~&&&xO'hjma+ۦ55tY Pԩ;8NP1y,NYb;OQR$ ހIkw{?b!E0tp"=zUn?[lK.菰,~HƗя7K_YnH&|_ynXԇԲBqIPٻӴ%cjQ_y=vٷlbCtuu(JRA4ZeDc#dƳ#jP-i$ʱ^<^l6%\wމ8TUv܉k}U(WI2$Jq7/}cl۶|??cdtO{$ T$3t=/' е|^M>_<>fǙy,*f ---lذ͛nZ@AR[n_:/-13vZ Xe'\m; \6YNiVm6yp`3HM0N)~8H2ayqF,XIXaǺ= B_**6Qߚ$ϳc۾Jxh60aG"$|C@v5%t\ASGO1[>ea!}۲km`m]ڎ$KT2žfq1늞m[ӴHhIh~֪}_! l4LUtoۿe͕崕Ut`@s#_"NZyf~zOilaNB:09wg?/Ff4 rE-u"Sג8X] + mjyY<”rmWTպ`t2]X(KHhÂUG3o9h[j֭\.bM|I!`C$kKm"S2:2ʡ" ]N'.!?3?䉭61UIm <'-9S704I4 w:IY%,T˲4X]Awţ^ևfB0wqK/w'!لl߾׳4xe;8 PR0M{߽t-K8:&847Pלg[/RZYco-k[HI6^3_Lg-LDb^1f] S)V?裱X}p<'ZEñ|. /v,Gi]i/sqZ:90C3螃$K kIp`G?j XQ$alP¡,CQcc|e׮]"!&Ҥ2 ŵ"#2"2! ou5p5 ' ^KfG IP̖Jrbn`J?%sEQN㼺iX$ ˁ$xA !(d 鰸סilg`'L ٵ$xGc[ VT*Q.)JT*e2|1-RDTX*,IRAu v,,±ʩ*Tkų@R\rjpXtzZ=aNy!KngR 0Kl dYFbRH2|qգP-U5_w{-˦wGmAKW;C.B!Fz"U-L1 >顎<ʊ+ꪫ_7 ^϶s}'s:,0w ހJ:lǢ\.STVdYFfrx|BB@!_ Q,Y\ƲmClN9ueM BhgR 0Kl kȪ|!L Y݂#֕K3>8ɢ5ǽUy^##'\*};|Pcw+ Wa/_ OlclDb?qGݰ? y=;y'kb?ʒ;qjfn]4MOO͜,jYC Btg21Kl:;;1MYVP41u㸲!^ZE!± m'^u-IB xDPN *JQ5 {~W޼?@Vdףz\q`(?_}7 zFϿ-[HeGE4O>ۄ"|Ɨ~qiQKU(K4i\ I$ !Jyc<6 ܬǧC51"3{Q\^+<KS͏j:憢G(B%|>!cS.k58w{ iIBe4qqڝضCz/ct`lx4r|Z >$IȲ|uqe}>:v/}\yJrʾS0ѫ|p RBM?%s͛_[zOjiUKU ĶlMq ݤRP̗ F`cN:B,haBz}I!S4^l'Sf]Ե$ٿ?B!¡`2/PhLu" uY?^VE$ufh mȒ ︜l@zJÜ: Lቑl3I5J\ɡ4m [I4Pt?z_͖ۑ  ZwM>${ƨf:QVN؄ 5N6Waf-sMMM.Mӂހ䅦P.qpg ,-=zȪ2]fδn1N)Y0w`$HC[s łt,mZS}F5ex?Bim݊7mE%?Dnl+ɶKٿkl{-DyWT_ɾ2ٷ 8hU"SR!$)%0پ,f1C9`0(JZtsx|I{eU_e)NA - ˴Pj7:lW1Z! lNsJE9Wm0CGhH:w~JB  #)SJ_of !dTox륬~p14գx\tg 5Ϡzdu]RUubD pxUEG4f,ð,0UeI|-0uu8f<=>l,ӚVd ,!:-7IːѷkV,her$;oCeIy|x< ^U!7}A8pg Do|dxB'l`u_F|H#%5:j<3} fP.I6.Q-Iv vVI3^5dɭ1clz_sTawIHNh[Ja6xc .&Q,KK%2ٌ"B! %Xyx|4GEVz}xU" UG CD#Q¡0᰻b1Rj~c^ʗAⵒI wYfDggT Mӂ TGA%wqU!aHf"$ _{/2-a?J͙B5{ZaxeSgo|HT IfȤ3yLL|+`bc`Vu*+^LH8R2{C˼&dI2,1qxNI6őe C7 x"5'z~aA8T*˧׎q9VxiMc[-ղ$K(V8~jЁQ8nE(f n)?J;wq{_GˇgS2sP%ǧ̫ldR),Bl.K6̐JlIaX66BQEXزȹ( lFu-unfٴPUuB1|YfD-jR27YAUǶlT2=:NR$#on!Zv˴)KȊ|JՒqeOn'~xҽz>cj$U( N =b%s7i+ȭA7EiuOki{s--o)g|L|dLl޼G>L]KYYԜUYN,f'w%sj]VeəׯYNew+cW75- x (* UAQͤNk.I&Bl*O$BUU<z*ԳdW~Eϟ[knẸe `j:Lη]A{Q|7\GI߻Pg3.ƿt?dk>D=óFHV9YWH]IzibYb;0w\n&|W+Uo($9q|E)5[B݃ؖ!RiTZh$ dBX`&X!USƞC%a{SȏR),KE^<^ZU6L-I/R1Zr9zUbJTG ?:&l$t16pEJ2"IB`IH8%s ,裏6qk475+_]&7u&ӺP4$Lr@Qe% CKQʗSD{g\U9of-^%rbIٓ t%CL[`)KZNB:@ 44- 5M !Npl+dmYIwɎ#)4O~w~1O s vCm^NAjZ2b!`W(MT]j96a>Ǣ cem%H-;B@V8όr2'EiP#G Uwg|ϳ ?bb+YiZjP LRH!N#9t:xw{7Z:@)}ᄏ}?_Ch\Ҁε+i,=%sOM_L L !TM~r$RqȪNj Y wAN,8Fl P˖-$Iqm)YK!ttK#?^@TÃȎLwۂTB[&{z̖s/LہAmCKC_-p}\ʅ2 $X2d:+[Ic$Y 7,ZT}03&;r-[}v6x8omoCy7n"@pSjkmwC'MvgSOBjТڔ 椀OEcW3r$!BH__[6o~ZCAn4>.F/_WlX>֛os!ZZov|s_= m&P4,/cҥM- I!c-\BaTm-J)&1L`W<9&x*~k~ $J):ڗ4:׶Lq<鷼GaH۶Eh258v8$I|cO8;7U+ǎ)2>Ԑ|o`ۋ-+^ވl{I&lPUՠ$ s}!WH(lxןD,hX6vQke /ÍQYwBF\0bGs^uoSwIzvgW .P(˖y4!:#/x oF }]2"\xKFk \BѴ>J)hI!µ\* ]?J>Nםʏ8w Ͼ_0Ώ Ϟ܌緽O jS5D(W*'p Y`/j7/O(l^#D} ;+=80Ɔplv=Ͽ@{誂ր=y}699Ȳ I Ca[,WGyqg{ŝ̉1z16m:\m"TBe—^ͳ0O_&bUYNc!(DJMMM s>apW LHQsΝ̐$B6E:vE)Io4Mc$-7C)g0JAYU伪?cYex;I6 eDd7nX:ow{8zXݵ!xG?Eɪ~l?G=Fc8w GLLӴ !lFXZ]DOO}TMa7 r,wcH/JEW ( syy4U%ecPr8`]pwƶ}9=ªX(+e(f YKD[,bnmKL(l ^tuuYB'u]ߡ(;b-a'{O!;CX`DHՄ1'= aض֬&.??jz$;n[=XmWVqp !My>pχ? f0* |:'4(e_MYUUwʲ'B'Ws`J:::&qky\T*\υՐ l-) |=ChM0-n9;"c [j1 p߽yQ^"?R5Eݶ=!D`)}p Lp1%`Roe a³=B( 4M4M;) $m%"B(8Fc[LLL`bbl֪egNĤfrBD i"( ) pB` (֝xvO/ģaz }. tLw$qHÑ}b4,%DPQ((TP)0 Vنm:p,*tչ^p bȗ1q:,E]\2ܗH$~F(ʗdYoBlfs}BRDOOzqMZQ,zc\^T$?LHW#(ybVw,u %G_lƦ[dliiy={16؏Z\>"ކ߆=ChϺT] MUJaT*xǦgÒUm&# :3yjIY1`m8f٦ (PU˲<X1v@7!$CzF"8p`oA ۫UVRJ<ϫpqo}84yG(cBUGӴ~QUMlb\~oTR,aap^([$ڦfw3nPѰ NX}ɗ7m&lۆ8pgdLwn> 3"vr ?"4cY av~Mh>*"ǵSЩeBw6 ͽ0 ׅ!"Dɵ PS`X!ٹO ((@\/ǁ_j Y^{\oxE onuܹHC;o(\uޏqC1H##D^ȏ:ǂQ9p."ܮqR5;PpJkyEѳZJ";56vPpaZj'pLý~F,kΌo7L2ep (K׼]0l ۽st:h z{:cD^"h[!f la'wNu4quzYkϢ(\ټTc|棃wR ˲LӜTJ0ZIt:jXX1c0 A_pޗ7vT0l0ApN( 3a}WgA :҈a;DPW}UAV8wl[)˲8$l^^pZkqIE_+Νk>~JD"iq.Zψzm'-0 uz3 3Ŏ1alf'(& Ǹ^3DA3_=x6j'xa|۳ݽruH$ڰ<Z?n]|.$CO4H|Rk=EєiwiǻznF X-xmY6 KufN06{5lcl422Nݷ ZBG3$"udrudwPDtOaxDt)LOOmgRG8ODk$`$ks2ВZd3aL0V'8'MXI kBY݅~ƚR >nyI+WiBk !jGZ[+#I&e$6Z몈|h?!"'O6 [j-qJH$66:]H>!"l6r"MC"c2==PJeMӜ𨈼LDp S Bt/@{.D:A%etz +eh1ִL3%%Q;Mm;+`6R7Zg\R[>@aMNNRqX) A7HZAylhAmfiVƆgƙv4vFrͅ}V;L"Jmtzk_Zg/_\6#LtCIqF ø<~t@gFj~~~ SQ{elj^v6ܜxn!+mw7Na&ѱ_\[˭NЮxf6jבކ5> Ν[;a9$燴֯]"zG8j<< ' 9Br, {Y MDt;t45 -hY k4%3j>wʕ&"l~~ `ֲwxzVDt^_b*Xi RάtʂCѮкV΋j\a3@s:m\E&A2~!FQi>Io>2"S0!@y۶_#"5"vZ V anR$ǒHN\IDV@ɺ3B465>tmj5ZZ/hM)''O `Ttpȱcǎ^ZA^Vm{ZL;c#9Dj2H "ȏԃnPBX@i+u44-WSBf2^}Z_qvE#a}~TD EZ*Z$ `%-$FH 1ypfBGjmˡP/Ѹ@sn졡ղ{m TߧIOH*jmR!pG2Hɹ0l_y":8F BR՝~^Cb wmTdnMD~zXq~LD>(˨[!sFf:+clAs u79O^n~v nT*[Cyܹ Ŝ{RD>ET*^߼C{02G`; DtD^tDn*cj[[i2jm6:""yph hzxxj?EQ\.Ztp S@b4@MD^Aw3({֝s5K[)$ #H@)\ZԩSvfDt0\Z_V%}w͹"slvW(Zkކ3;_uKIkڅ*g۶ j+ߟ>}Dw F=&"~\.T*ݰD AH{ H&lcGKDD^o̭QgKW7oum&2 `Yux={ڮ^Dt`0\g 8_Zd aQ89#1ߝaޅ*lR sxM硕RHfmZkOD, ß;{gl$dLi Q|aaVk%ƒ{t$C5 x Hëx>ލR,:?l/d' Hk6DDLֲ_ZF $BhPv%i."+NEz*'"#D!; Cj5Z-)em|dfrz̸iYYYA^Mj*o>+m a%`B:팍d0$d7^Ȟp-\:j!###jUž&S8c0ޏnwLZHMOւ(dGQzf 0IJ ;\}k>o bn{}?-XIk0$":P(h{+HLw6i XFX5zofJ 9]V(2D״,.."`&M}r3b^b @r,T@ӈ$d7!{L)J /N3dc ׻ljj}"#ZM*ʺcb(ΠLQ qw3mh# ۫ ""mȷ)ޞT*uZnI .ߌxxaaq/o a["ݦLetCZ2u;$FHOe  #J|>{V1d ׻(|[\FXwv0#0l~  Ra = i(Sm)duXUPJ4ͧv]t^glc%ǎ;a 0~SOL#1P:t a/dHBv!;c4ՙl˲Jo,]\BtXd&!B+,J}Ť&S}dXBD4VN,vo5dm90EkT>7T*MhW1\"Q%fȫagQ   vׇlCvos2۶sJ7*rv&a&C ׻P(|@DR\\Hr#> e1jȞLðNwaoPJ3[ D{zdRQk[\\\!DWq֚h%0Fg`?l7 َѝxɵ![k ˲rݐB`d2 Dz +~^KV[w,1c&"ڧ:]:kCTc lV{ ߨzkP9"D;zMOO'L%'O-$38""a0N`윋LBvwcOZ\.W+ Ţ!peW*,hϐm n7di7z;Weًr"hO?Czl6DUR v{y DDu!7dOm=d7M,˚QJP(8ϿP,]IDpCN81fG(^^^^QLNJY!1 >>ٽ=-i8dv|lZ,0M^GK׿KD[pCFFF ͦTuǒI<0ʅDDNl1`XDfw55٩ [m1 Cj5۶m4B`eJRco?zg\̯ uBF"FDfwkUоw| Z aqaOȓlRP8_,YM ;`nn><{eee13ibSP&2V"et ePZ0ڿmF#J: d{ۈFl۞TJ=ᯔ DDw@>yCRAZwlx.DžDDwti+CAj!{PBb$x:KhZhZ0MӰ,GZ/"o|$eDѵWD _2+T"r-lwg  KAtg(p `8)$SA30dGQz 8N0'-l6Rt*Bԇ6rG ݜHDDkv4\suX-)A+[5H'4DpÛbQ0ޝfBb]`MBEru&$3܆ꖔ0әVFxoC "Ri A߰}_Tnò,˶'orgJ9#!0\߆R_iG{[ &^2 58B"":кbJb&L e*(KJ8RI!o0D^Gp]w0wrl6t\f>1\߆\.R'|7cBGXBDD;NSRn wT}$"$I JE6&[r|F` ׷P(_D^WTKB+$jIPZNbwf-mLDj2 +mxnB[E\1 |~8?ZlS1\ߢɤeYD_[`I j9IC)%1^w6ۢvAj2 i[yFћ~ݎ"Ŧ; -G)SAXw q. rs""'סdMw\ 7.#镊]_1F{BDP(e=h4;R ׷P(<zٻrLg30""- ۮ ecv獕~ĉlS>y/w42""C Ar4dvwnH$L|[. =[ToLt@0\oLXD^S08 DDDV7:6+n!7( §bs#&m pĉgq'omg^4 1؂h-eLLh.6Dz[+뺏|bi@C&eml}ne5 !['g`;}ǵX^^(z-Ͽ|GJt{A)Ho*HM0 mxjW"ֿ???\ҁpu2B ܑDDDtX) G^}#vT_j2+µZ  ۶`DbނI}Zk̤52Tyh8eǔfka^ش0\oG8^9i'd4Av>o>3nʕ+}ggg06TJ#2ah9O#ю =8}\rMo8qvn0n]"bAkM72.I&qp0ĕ+WjF /f0~n @NȘNGrV}Qիh4Z ]*toVe3B:Ș7n0sͲ""+1+!MqE?UbV"&"":2G0X&3a:O333 HLpZ(eXDDD{ ?wncii ZW 6p I@⧎C08G3}:2|8?Ä }DDD&_qn;V,h4DD;0<:`oLDdPk""CJYz4~5n]'Nx逆HgDDD[H`Sc|EX\\DcJ_>2!p}c ޸,c}q{ r( ED`OQ. sCFE;?`hcSDDD2@b^TB^?1??`*0\oBDA H#"A=_h;Ԇ_}AG1ˏ3abU0SKKK{Mhg8~=@{r^C 1 n}i7:Re)(ˀ$FH$`PWSHz*GDZ+}"&&&7Mgggӕ xHs ^iqbAGE`,Dj(\n#,FfP#Jq,XVE5|?X)VP.WJJf#g*0fBb$d̤Q DDFyx6(;l6Q,Q(UDO< hO0\onpMZGhڨ_q!malz 'E/w5#GƑN%JHdRH&\R 8hlZkhlR+xg~_JvJ eXiɱ$G3H&a:&1_\h;VT8j (i`ބݷh@GFwJG^څjkņ@ɤ07{xx⮻f02Ñ1$nRDJ ./bq?/>5|s_ :#g*=DffdNv隘z`m;mtnnkNJyM{*5eT̾.[ U(FFT 5u@'P ȋk%x01Qi$JXq>g|k߀u~ћ 9$'P1FKu\slmcjj a<[.\py@CcGE(p-sH&78-:^i|*F7_|1;{t7GcQ(Ema q@" J0,; p!ҙ_Y<'JZkxR)l"+} 4 "YV߿T iX uSD67 A5g+/%.~^7G}"I#"CDaAЀWKheDҹܬ׵ bvJOa [7<~$>ٿo'7ΡvB4wKB =MDt[ݝGFCz ~KKKEAALٟVJbbqG<GCVP|8oë_8-?}~2h5Mha+v(ssxdW_ c +mc0rag6^`IDD[yYLMMuo?uԟd40 כ_EKVVV;hd:h-5Q|~UHñ-<=};^q}:g2˨Wϣ.Ap("U|>ӗFr"3\HDtR>ya#XweYi_[Ν;wv0#A`Y&5R! iy(PBTa3R#;6;޴PEm4WQ)Dqj9dp=̟x>'QڀWl#=A[M"'bSm$1>>~eY{Y}*MrEAHej24Wqq/-r814S|#>O>~[06VAP҅?3OqGΘcn6f3U~",6ѭlH<$(ݶmWJg;&r܌|wR39Bjb'N!*'XUW0 c}/>cý:ҳpX^|rf`sls1ؖ +h-41a_DD%"pGJmU1ຮXl6r|z@ä=gMrq(TV[w,1@47A#@,=ȋL&o&8'oaKrqQ @찋G_<XXcaba3=LRhKvlTkvt:t:jɩ`D.Zkc&2̱ i%P{MGzӸtCmP8~,{ED8}VJY6:m36j?8FHRa䆆>QTV}!m &apfZ]w143h^naETOW`8OD6+ +_GcF I< S6N)؀_:OC:mٸTT:;naބ8m0UEڳ)C!odSh"W3ֿO 621l_{nW>̔ g^"-뛃xt:m+Mӿ| &&&&5?J:bK^WP;WX?W?#Gk+K;qt#)̞"\ l{C#":0 _מo4͡b? MEpw^GY+pm J_/4 <##O+[>oXZZ™3gpY;wΝW/.Ǖ+Q*!lۆi W&'28:=K DNF3DD`{< W4DaL[DF߿V^ -p=CQ.0 ~#̯&k8MtMO?W^E^yaAQױ/ayy LKLMaij{"?[Hhp 3 x;c7Cϐ7Q(^७V ]; ]98Q;_Ӌ@ s?A/]MpFCk/xMETUrC;=?[eVZ%H&hIz]+a"J q̲?h47"}&rܫEUvóYXi֠* 4Al6w~;Vo-|c&E!o>r3fKd2H$;r枻G7N&<;m0aׯ] iql۾Z*>?!MhC"/.+-oyqNn~ԧnZxgx87ܲm?Ћ&vKtNDsY ~ee)?sĉh'1\߄0'w4(P?`Y 'Qx5>rVA}XXXص \gk %m2][Xq^)簾 "ZJ"z7KmTNw7,~{/Z回Gkgy:ގ sڀÓxaj_bkV"6_:ٷóy(D"Ob 5 !jh^m Lo=/G–u),/< saiiis/CP>Y_&=DDۑ9:ܽj7w݀뛈xYkm[7_@GۧcJ/`ff?z< zS[:WTٳgvk7)j7ͺ=tFB o֭~'"͉>.hoWN٩7>V\BUUqdYttt}}==hooG">U]]]nHx,j&%D@ 5GRJ;KHShq*.(J}$9 5jƺ+UkE W^\vuG6{|g'v G(=("M IDAT1@ rO0~NH$Os8FT yDmthsvp6 4X L ?mxvuU>m* K 'sg}~<L̈́>U]xOlzkC2lRCOO7(ݽZbvx~SH%ð i]|&`P.H-8" !Dcmhj&|/|LJU;>0ϭnTmhe.\իO|޽ V'OUys @@ JBE3 8jB";^M<! ܧB&Ák!Fuù ~{Z6;u%h&> m[68EfŝZ@9$Rg_#ЋGQ+*X,OF]BAJ;M~1O۷8q8? ʣ_1=KUx<_V{-Y^KGG:w]aYM? &lLKUe ?@ 4|CjY =jW{eh+,˂aOsNnx$_lx+Ķ@ 8񰐄g@iT*E-A]9zq "*ցD"~yè4oa{ӧO7?>g/ Rt.].l݆\UM7z[ 0"Qn[(8%݁sMX`0H>+o֐]TX (z;08S-ȸ퐤Ƽלv+jLn0elJkm݆Y0vgU`w!J>=h"ٮ5Hen8"2ڟ0\FuTUpahhs[<]i<@9Ob\,6G H˂Je'i>G(XzttwwcjR H=W8]TL(Z#| P rD!G0*L= JLa l8) Q"G| XXZZBOOB)D5bT*5yY8RK`.U6qGᐊOp8p~4j@(c)^ó=xFq;>om}Zq߳<8:`.k%5-QHa jR A)"VnFA.3lV0ЧtO˲P.L&e~V)z,--%xpu~՜spvl%A_D`3P LtrL+XILD sYG Ax uQ,f !A|7!c犢|+RYY#ڟmLN mmiA3mm`huݜw8h2 )"! #T!ǔY_&$w|B\.[ l1+WpxqG+dz8~! 4W-nՅv'Dz38.Itd"|o\TX@,o|6A/c5૝=צ2AM_mln̛0f+.Ajc-^SΆʅU7o^B C) m&5ŜZc#En2O$B\=LOgR4;[?mp/H/kU\Rܼyim-N#J5ܸ>X9@\h=BuLa`0B0Rkv$1 \ UBp;>,̈́VS!#eB򊗜 RX4L %C# $IoCT)B\M}:~;|j}3=,~{EC:ZJ:s\t 7|Jr9h$y7-aJ<jwW.LBu}FVp/{ J-BJ"G&TPm&3!ErƜQݤ:REՁ*׏!R9H;N+333uKHN#'s^% 1\[`[km͛[nfs^8Ǯ}DBr\{7n8XO 9tspai&*:*%+\wV$DˆtDB+ML`*͒`D:tEQZ-b\.em#C}8ΏC#wh]r8``Q _RFE\oQv9nܸQJ q$ˠ54<jjC+׍B!Gezknm *S:ylYv*xiElsD:PS*j%m„C%63rT*I?!!du``࿖esL&]Vėd"smWE@ α"(!x ,Dv/@$1ȲԐ朣\֑F$GQuF$U(IuY,̈́>C,oY^EAX #QDb 2Um@%("QT7Vڲ@^?>?8u?JRuS`""1DXeV!`u g\.cll7H]k!#[6=nv+|S"p.Y(Oa.U9FI*S2!zE ǂ97_  T\hCeir,gʓweYT*uRVE{{:ctu>?MO@~ H6 +|0CYྏiwO4>`m,ٳnD kJuoGFFZ?#xĄ9[\.AxUoNó[;0!kĖz[ܦ*z{{~ok=9j%FpQA("o0AMgP Ԕc|}_@eÛGY_ lD HoJ%P(sPpࣣq ;,}} P9arjw ٹs_H"hu]oĔF<b JmĽDzR !ƧSD:#x_D݈vn-%L;z!ʦ)%C4R]`rc7*7B\6!|f(JFq̾9Gߺ2z\!) 8-'*344Jw_0*p][vP,kD 1ֻhfUhGڮx??ٷgP]0o-&JBEL$cWׇ$?gsal̽3 3S 039'r$1tuum}-DvyTlFࠌ@邇)ԤF"r¹0:D˃xM<ptxQ<(?^B[ ]>[.>!f7VB\2sQ(3̆"&0A}|kNOOòͶmP(/{-s5o+ B䨲 zB*HlJBep"D:|/"wjJ`>71}r2ˆdȋ8nlH&misX"xIK;C'wMӬOY)3L epQ -b }###[n'ox1bQ---\0vt?3s(>\C ]Q|j.&mc(U[3Y]nŁ2E/XoA,Nu+=`B q $H! Y@ % !1D73V UjQ(O;~0v]fG/P_<xl6|= #X,,cے$vنSΆGgK6|é8COw6q8p|NJlf٠zUU01GѨ\,q|pHGɡ#h$O?z(/wa=cy'@,Ed0c%VH.p \5 ͍2pOCuS|" Q) L.<}a(Bd(R,x<c;CY.*Mc"n5V5?+HGhm >ۼE裏P[nܹ 73.C~k! ji8Ǎcnw>@2g2P 9HRW76A,;Ն[E^a4aLY'TH"!l8>;yTtSD5[ h!P)}~=ϫYT* q)Z:g}W$6tT"-TGD>\Á]o60c΀Sq@)Wkkضmܽ{#0t|4iڮVl\:7@I>iJESb_TD/wAbwg'T> $h "H &j ÷=u8" wp j*S@lDaUWsD(J O5Mۺ_k7_CReYI*HQ?!"۳ۇk8pMoo1cne5 W511tvvmOw]J 2S}.'gpC Ky(ÏoL^ _PBp7Oiͩ" 'BQ ol$@ȈƑLB Ip S9]Յ*OO!%Q! λFRѤKnbf !(Jhkt!Gdv:9<Ӄo*j⹊ RNrnJ~+yci=^(t@ͯ5r֭mC8׆S]MT*hoo?k9^} X߶iD:s'sTu™\C'2tnclQ66Brt4aj:@Ѯ(˃jv'r89F Ԭ!Ϩ֐D,b/R+n|~>$$I0]9­L7ݶ?-&|﵏yq|^1j 0p0l 9ˑ`no|,8f[ΝsE-{6`b~, ٦6N <5A&֘QN!Uvrm"@T[ Ra\ksׇ1o k ƌ9@- TLTVH#1gBay+<^qNU;s,#3BȘi6iy!HT*g2R],:;MA4ӯOFP ޟ@eB|χUT]8}GԑL7muoFXD<G$`1xͳj{P$ =8T|l;nQ6O{3@Yf UJvv-\ɵI*Ln/äj-# {xl6|^T#ڎȲYEQ*\w\Gqr#"?^\} @+t/qV p`L8'tܹ \ޛ}`AGA *AI2"0T(}׌44M+msAqdt]wR}BEar}7SqΆ!EZClK-dITWՄhGrLl.Qx-q,KдŽU`:c De[w1>>xmhw Ip=SE| t7EN=tbLm TQ$R#}c҈g(=(p7ʄM޿@l(0/9BEQ9iIxl( әL$IǩȃN32beS|4^;u'p[/BM@69GJ!E$J`i& rK߹Hd>>}R;dYܞFay|>RX,EQa&^-ضBÛ7,!}6p*ZFeC/]{lL<:޶ABMPS[=(~` %]@|DHT!G/IepMƼp>11Ri`9s@~(|.0 ΢R@Q(ҔJwp|pS.¹2Zr\;N>NQ/\KV)|b'x7>b6FȠwEu@ KHPG_7fY>C`?n#RfapLi3 P(,dIu]wèlp^³>E'֒s>Xnk ؟=ێOK;dg*0%e<ޟu`J30W4tY,a2 Bma$ \}c[qP)4Z$/[ -'ݢ/$I\(c׭Ow !MQ؆2)"CMMW·'K$ڟ EY'!rTP6P`rZuItP=-ǞoF4܎Cks˲P(077)`nnXZZ1;;ɇÇiy } pq.Zq3lǻ4|b'=Ŀ- ;3e60U%<=Ev1XT"5VU)9.'P%i:pM:ˈgy(Q_rӡֶ -VBu' AUURf>I;6qBhe2c Ȏ k~*̽5rkPgJ֝!c d6*pNP8(,|[Sz{{e)d vLV}84QTP.Q*P*:Usp8]W79GY[&<Ui܊t _бRJs3S:490W2ٳQDq71p6PK5?J}pXOD2Rm2 wB!F>P+=F)E,J>Ӧ,!uDF$I,˙ eTe,sԄٕj I@ 2 9@*ի{B1^ժצ"qxm;Nqx<]ױ>QA MƲl'0Q{&N{G[j b잞O gs5ux왂.v"R݄^:M2JSeKCiH=Ha2Sq*:PP6EAC}^:HJ)WjU-FT*R)1uBY`yWu(Fg@@-SAI{F%R 26 DY.05=~θތvJ]Om/ҥK`}7lf[Z EBݭފ 2Q:vw 9ێo ln(ٮ"%8뫿GCi}ٵP:P JRSƬsGe<ʈɏfPFO(IRD?!u FG%IzYjZ ȣ^/ wVur8';[ PkyZwep`.>|k絆}}F~ !, C)իWqb(>|ϮU#{5B`BSCYdx(w< `?]0q/Dh?G.ұN_H;^J\A?p[nó# wid k!.Z0E!ivI; T*USctZ^?ʱf;ǚ$OBT0Q0mT5yK;Ѿ{AKK #?uԡeJB( 4M._\.)y8 w)J#; V !s|MZڱ@% MȲ(æin=H{`ip]/ *!`j +zA(eQ(vܯnF"@{{;A4s=T*//WD yko[>22HJ\DnOp\R/^ĭ"k-WTgxYF8>n!:oV sb1H$3TӴM\Ff!(z.BT90, *S|ۄ`ߕ֍!i9O?كXlhM>}<[!22,zzzׇ$ (J)(% @$D"ٳ8w/o0?`Ts.xDŽQHN#}.H}'h/1ͼvw@br*9#"[*ّk(`櫈v6)I hpMdPUPB4iuGufyV?;c˲,Z{ey\H$rA188^r9B"/-Q]ֆoXX h8\z3]WP? uswp[%teg;X<,#͑{`W"5;1Np(hu1Ɩmy1LfqL&skrEPj00M,~8nNgvհx S89RX^IWqU5>ttt 0<<|ϯ0dos޶0:@)hXx^uQU$~v{p\6LB?uɂmiR&a=.,]IlmSN>Ghk$#33!%"xgl }'@R%HvтQpUpЀ*v BQȲ Ixś׮,s# K]mG/=x>nǻ?О!Jx.0bJ;nhM]q\U%Ulү@),!G8 r}Gq}JG7!" !(=([s~^nj*!RGJF!(JTgyPb m=L>tLS's0J~f߸҅LY}{O %"sfbb${ހ&|LJĻ7އ)>m὏mv9YoEv}\t:h58ޙ)Wz!cQ$PRXe5RDB?P: s2V5?Ƀ""[p,!*~7ij!gPy`',y 4Md2ig|߇V#Faq7ʴ%bkC+KP ?9buw%2`WP*Zx0^@[6e8tLĵko{z- lèrd.!s>$4 Ζp} ޛ<0{nГDg@6%re Kv-T”B% M䨌P rLT 9Gehl4Q -첍tp8 UU!UM>l4B\!}/ɲT*׈!C`! {!9w@%ӿخnSBO a(! s %M$\KK'ʠ𳨏 s,/'?~s1wx}劏cid/N>Ƿݗ7$3,ܘ٢/]lzMpu0|8 ?"!o\@[٘Ϝ!UqwrLamh#B% 9)>`";(w9Y,#2ؤi>Bb:1ƾ9'jn]×?~{IcJ7paժݫQQ VP(V`t*,* `&{CuT ݶG6JerW:/Eŧw~2ۿ}-t OfoR\;5pW3+28әՁ nϔP2Zj*i>>eBHXE  w2BЉ<)jrM@k]->bbQI#rf}zyn?Z7:Fbۮ$Qo\Fdqm{?qPA+*s k쌡Ox7u]uLn'6n|XO +'JH ޷.́kNb+0W  yQ_sR9 *xv8٢Bu'7 yx8F| ʔG}ZG3SCH/<i57T*4g}B ènN0EgX|rT׆i|L.LV_s]) jJSXh81 9+oO7(oVrO# fxH7OC:Q E?}o-e ϟjCjgg`:;V/<=Q%<9LIeM@6ox)vF.NJn:%W 8l%8B-1Dk(cAB\A˲n?%I>y#NW(ߡJ^49The2Cq}O ۸dL? @EM\~1]TfP K3QW1r e edTQCuqֻ ōY5\y½.\>ގ!3o\};U:C\?]MX,[xLRɰ ti߯?[4:'0lc󕖋[P)$lTK$BҊ.`uo+"vFej9UӴ#GD"1{Y k/@RP]xwrW^xr0Қ^Y8pAé\aQIpF4LLNӝ8`nv>|aS_2ظ񡅇. Kh3wuXaO}hs`d7ʝG2sB/]r1̾= ˗[&d`TeruzD] T$Rd.^.8Z!F4MQSvR,T*H)eNl#ֻB(]ix$&~WT@ݏ,|ż5N$+ջH2"^ Q]}T: I1(Q֖,y]=-k﮵{dDDI`LΝsw?^U03=]3sSz^}_wb<5?zf!e6W橃D7 :ql,++iZ}! wƱ #۾4Qd  =1ʳ%3F= +b#%-M uX,bfnn/~}5Ҹ ,kزX,8Zz#hl .Cl WT75CwvbI]JɌ͏Oل2Eh3ll!ta8{nZ#7m<|A IDAT8SΟ׏;ǹ|id2\}!p١P~}D:lXc9ݰl/;|8ǷNs|8i9$i>ݍa?=y݋/M=kluM#F$Pj۟ERFXO@Ct*C誊ؾ_;_51(?r/[sskMo4i lvv=hXDmuw4rH"Wᝡ_|JMHB!MY.2,'r]ndwO֛p&)KbfeN09킩rWM[6nŇ7~0?.v6+;4󝳼xzB7  𾖡ao]ʎɫ58 o^veދ-; 0& PN)'K̝ň"sb-9K&۶g6֝M(GCP!DK67]@Q-V! .Onjz1B̈IÞ sswbINOے񭈔Tl\64LR)W<*} &]\WЗ/A9Tyk mOOw-]s|s8WTo`L>uN>~_uw|}u.ڱQFoڝR5!xpS[V_7̨pd*kZhK0ř"c/04=7R(BQ?yx PٺΙ6E4)p?kS5F Ǔx]- K;IQv-֋LPK3jn <;Gf$K p$1>Ilۡ/233sAJy]楒Ǚ 6.cSŢ$P3(FؼbBγwu$1>b$0r[[gs!vG8?Y Zخi_??ߝ?(-Vn,#]eޚ.soΑOy[YE!IJ>)%`o%4M),ԼՁ 3߁6~CEx}^\q;t4+KOR&LllA;tFIO29U[=+^&Ώ}h?-MBAt\SRJ* BL&G2bn.I.X,b697KZJ.ٌWEa4D'N1xKEPw?nu7O H5̹,e;C]| -\\3ci~{ȗh_?z]oww[_9l`["pKzx.2Nϐ:$3ɝzn#E}`l& i#os!T02~p<{ͪX2^kHHS9MdW}K F/Hg*s<9^zef;MZ[LtMG54MC$^KJ 8<)tj$ncc3s.S3.Dl [XVc{nHq=Όg[#IQFT'~p'Z#Z<9%tM٤.|w _{7m-<)9H9E~O1'fHKqpGDc+n:#t !v,q"sJXwnihi"<X_cBJqʼnCJѹ/Bj";`HSɔ)ɏdI&K$. qx qF ۮ+I.^83dep&xl_+{nr5 [rӗ/S7!=~Xgg{CI.N]y5;|5?Ӯ԰L˷yU'tһBt I;J3ۓ'rpHGG$ֿVF^4]trq tA@uu8XI\/slB[,}RzF^wc#-n + {( sdSey1)ѰF8,%pH#` AiT??*)|\%\(=yI,qlMb{##h6]S$c&[DwM3l74gpM?IMd6T+A5[בȱ1@g5sM,|&=O𖚤؏Fɏ t>MAYE7ka;Y[?dF2V?b1J\?eC-IGjSʬ|O :Wd_?}_|i}GA錐oPI))ImRiDbLait4M,uxxuv$ՎoJuK'%D ČYa=hr_C~ }4GW<)ll9NMȗmL3Ë27OJ{b/t|ٹ7_?o|кvW"į|h?\v\ʎRsGyzǼfBjSMtkEU J2wjԹ9F_&u!I;0#&ϺfѤsm2dYV#0e3sb:ehӈ.P;IlWrarǕՓr1 |g'tF*st{k?PS/=ři=M48C3vĖm{r'Ū[ Zlas Pv95\aL:R O_\?5@t=W^oo|j𧎅.t044CC354SG7׃es) O{73y_1%0xto O`O[ӍehC=Im"%tnjEq r|8u]MgZԢ'"%#שNQ+̐8iQѪZ=׆hU󪡖Y+]xK#8R:b 5z^R @·fmM^y{žSƋn>k=C},OJH3FB(?sd7n¸ (6٩ _,<j_xom&~n~ mYЛXD}L(nVZW;`Huuyi+kqb;݀NZF00_s 9xtV  h|4G_=nڍdR 5/}ǶehExg5ko^7~w_^º!l_>¯|p 1ۺa'ck>f_Gu'8?r"-\Bt>NPaWs<4ivC lVQr1]pؾ +u,^ԩĹ04?5*ƍQD40B v}/S @gh)%Bsx ASܳVkخ,}t#k^t(/:+H_P"M`Lʩ}Bby.GJ{UYR=!F"Rs.N͕Lrq/kXVEI**,]!jsݯgM̈3'|1RYevdGS3$Syo(Wpy:)2/>FL~zB`jEdŁ]}ucQoC!Vm !B :}m1HY*>3w|p'فѴ+urOoϽ6~өVݲ)gʔJ%\"ۙZNԼ,o[˯E)oYjg Um* 40cN# 15Vm&xI&E^>;+K7鍔/fbOw.umV(nF2bYaFpfkW_(q]爕BhUkڙqAM ¯} 2;1I%E{]L?~GR}4hzpY\-h3c"_}{ʝ =Rɔ)͖(('K8Eb@] C5,K4u,K'``+` I0h }ijh 4MUگk/ ,LGȳ-zO^qOJP?Όy4 (TΝ-V\^>;t@!j6}&)q^:;L*'ˑyy]U EJ|\ҕ8%rDa2Oa@9]-\6 `  3 @kKx,@4 1 Mt]ցfu/躎iMYP<)+.MPP*26ej*\tD>_Tvpo\t[r)d|?aL !MA̘/u'%Ͻ6ȋm)Lqo3x$ &mWJ+.oqj4ͳwu򑻻IDtm"/d*{훥+q"<}MUi]B&M!vv7f4&vM!0B +$ja) ltd$##'+J[JO▪;Y"3hA+flj c%a7:zdaɂګ؆yM*o}`%U*"FXKkUo(q]DJPWRq<^%[C=<t=T;{hʼn{q,/$¸%+owxZxo(wOo%/rTeD ho;LG{DC@@Hʅʬzx8ݡRq<ʽ\+gBuHt'1M c2|!Uo VZ5>v4E$l]]JIJ%LL2Udr*PK03'-S*;Q ;al0Z_pk[KKI=jMv0w4|+7Z!`Z#Kj$s,\TBGxoj;:m)sl @CCp_qsb`:BbTNJ QɔOɍd)͕pκB@(hafZ,}S*ў8\r)2t"c2s%Rɭ..$"]7ZH-aV9}/􅬮 t]#ԉFM4-ZCc&ѨI!@0Xn ]_hys_^TE#]1g;k»XIKLNs,.1>%.Q*ҕ8P nC`  BmB-!z@oMB:o#FWV&-w.@" omϊi!5j+kI)UT69N[#85t~M9sf:(VܪB>tK_qnQVtKUg(q]T+R[a[%?׃x& ̞0_kkٕc?ęs3$SU[K"#yvn'Yu6nR(ek3iOU*wh}o ySz0wz\iUQݘzOf*0=S+_̱wgH+qBNMֱit]d_袿`p D#o d2%.^7Gx.(*+_^Y6V,@tG`uZy^ByM 4E]ں&:gϞ=jrl,?_N1)mH3{rrjuQ?>Ub/c啇ZD:3=<@-.Y.;L8qj6Ļ'ʭoA&0B>Pn—lc`nضm\9e5M4ml."NoIcڐGv$UE zv4SO1Dg|ۃ{|V|(7 8gϝϞ;G8lģo34# /έ^l)N%LlWHG3j*PlwX>R*R%!DQC[-&gK1FuOzd'WTFo?Swԓ{S?yo}oʟU(B&й?M@B8tC<Wy3UHn$Kn$fiCvʼnv#ʧPlC"u8铓7}X*!9===iu]7688D\wuWʩ2SoOή؞\5hN?hBJgϝ?B}0M} {o#1>ylKsA^}cq5L|#bmg{\y*[a 8}-G:UJy֡q9ZCޫVܩYNϮآ\?{/Is3Wq<&r{w_񓓤ҥ.h "XO3< FBʘd>c|||f QZuN8y޾al{AO[^ywԅ `"χ>O, _p/G(\P/BZCE{k躅J'NM/ֱQff WYF"? #]/SߧivBӴ9)K.Mm=J\9H$C)### h=}EV%'L6J9Z |c9B:S oV1z m֖ >unyLS<%^;:L~m-Hm76ՙKHO2jZm'pU}}}X\L؇6*.'g91t4Mp=]023WKy7M(=6Ghn NxM\Syaf֮hA7HeDH) }Bڶhhh| QQ|#Iꉪ0xDg?~d¿7p1:(* :3[+_}2 O=kY ix#;d˼8y=J:]Z-$̑"P3 &"h/*֤ wBLfa=s<4lѢp]<leb"LdKORNH_NNk R[B4swʹ^)t xry8S\?sKcds*ROP\?Œ;gc-!k'{S}`tvff_̫H=Bq(:67=ѷhhhi b\C'F!ߟ{0- +Dg{FC!H93KuCC^:V9k-@ssNg!˭M455 %RUt AJH+$}~,-M!ֆG ==M \YUg $Xb+$7]D A*ܚJ\$BT*BL"ш)aP(1<c.m!UkɣN,lp+fHŎ Fȍ(NW\K!%IŷJ\9 !R4LOOyKhFGGxq-yY Bq(NI'FMZCh9f_3/̒J/,’$7ňQk>T V( ?\\q \T*5EC cKryh-BP\l7pl11kس'x I yܒSrq.^s$ҕ~ <ũŵi_L&[4@:&KҎe:I آ* Ɛ|Q^ym4W͎EUF\O6s<Sd2D4`E, % _-a޾ V VE J5"T9WA:OJmONNbK**ֺ&# ŭM>o:_shlחH)+r1eyGv0Cn4K-B|ODiG,~_Տ z!|b DU 8%oV5*%6){w$ry`0H{{ u%o5śǦp}v'I`^M v[z%ǿrYۚ]AZRy*JmcR~fvvvYks4EBqyy/@_LO/,2t}qa^>sWΜ%ϯ|P t'1"& D;A~.c{+B.RGT3V*+tuqITER?d2ޮ mJz1+sg"ΖfɧzKx)&RmNΐ>$%njZVX]8rjO??y]!W +6o }fff6Mhkk# n b X,Eys0>!y'G0?~SSʚd.ej -# zPzw]۶SSSN ---D"BPd8Q,4M]6m/D=wsir?*ʋR/L 4j F(ˈb(qB8SSSLFbNP(nյWMI[CÚL;X2'NrEW$3-<Seʩ)A;F;11/[+nsˍEem#g㳳|hT BRb z(JKĵ&?u]M_pvȾDA3ʪxGiDn4K%]AtJ(uJiDijF?MRhhu\o#~>͒dl,K kBqKyy\Rպ]hO>̻| ήlxD+PkRE=794^% }}}RW.`u6ewqT?wlժ˖\$rԘ^JB-R萘`/$$@h_BM16`c,زmvѬڒ<>fVg9y FA)Mj!M%X0IB*2n/56bSOlܶ kvHiQ!!BvSkE@sssDEiJ “qUE IDAT`0JSPԩBv;4#A,lG˴ivcƍ`0IDdʈakpRêٌggIV5L\Ak!{<)V1 ؐ)mcܹs|mG.\"fVU|]##elNfL L[yg3 .0MMM(A1$MJb0X jG^tExꩧKi:tZ,8eֹ̪8 G/E[_^lE$ŞI"$k Z+N(.M)]uilltRjH8UUUy`0&YNE$wq83cʕih8-1 Pe 1ot~ܼl }>_j6(1\&VZW&%3b^ℐp1apB%}Su\g`03#;=0>?xviXv-뮴y5N'X`DUk[ # "/}:Z3aTt1m"N=Tr)I\[[ZpCw]"  FG)4l;}[ G\2B%CVf)ZHCǽ#Yl6#7o>@J & Accф᰼}DUUUW`0хҩH?_p8bO? 7܀/9BQY" =B cXmL8R*,CE1_P$BZ[[` n`UEQ^~S/ a0cNp.t5:ǡ_WpG4 o?fYfVUG}䱥sAG|p ww7ϰ{lN1 -[bS+:w6 'rdXjP+-,ڌC7z_w, Qށpp8,dV^*++QVVV1R 6ަ8. /^ B'*nw}xgӦ0j\x1r:F{Qŋw{ݑ@<h8JhǴ}>ߺ+Z[5F,$@KZVY ZEaC":S555 Qr۷# "qD`0vN.&;G.!$ 3gDKK k/TVVfmގD"Xl+yӧGJ}T멞9wo$ b(Jhk aMG'Vw=JjZ+$lm {X=`kXP]] A>gwvvn(*'-L\O rZ8V>t: :Q(2S72R9EDBqEA]]ϟ: UUU/v:|>>j@g?BIv j A!L<4AmP=Up8PYY BKx[l^eNz[i={-bm۶}hc0;T3c2AN81o޼]f>?Dh~>n۶mC{{;:::}v !}8BnjvArhslΝwJ)z{H-P0֞܆ͽGZKkP-m8 RD|憯ÛWVVrpx({pWY@n',P Q__qNQ2lPȲYfǼyPUUI*ѩϕFBB@OOz{{ߏA|>B!DQ?4TT}^3gBڍjĬ= B{p{7nt=]Nl` Ӂ5YphaB@vDY $ @;u!(++{5C91B[f={v q^e˖Q\1's]}*5!(B$H͆j̙3sAuuuZBbBK0ۋAx<x^hN$cJYUU8zأ,}G4֣w(EG_g')B('[whh>mATZ6}4Cd0u!UUU:{{{҂ \|/S F)KkzɌ'xE @HUUaX`QYY ˅r\.l6 Yg4 H`0YeNp)saeԔ9f4`zy9DalzQfaLk< ѿe ⱱnkq[98p46Kx<)00~?n7!|>ADQDQhvm" f8x<ܺukZvYf$h f,,ٳgIlybI)C^/100Axޜ MӲ&/&pDA,Hx.ZPaaG"˰2dQG2B:IQѴ q 9Vl]Ghе `pT>m3O[PaBv>R`h¿Q{$$y!緶> `|OMM1g8>F3ƅ5ae$+ƦMCŤ_hhh@cc#(JZ&!"#$xQer \h SN̝2uKﷷ6,}}|᚛pzOOOZjE]]]VƘKIy fӚa6 ݞ-WVVUUUZIl !bD"i@ ! $>/)sU'Ҋy0P$ 6Y]UXYQni:,I"!ŮA`.:0o^LlA mJgh()=+O XD*,cJĆ׌ E`p͛?ENx8innvPJ?6mݺSEEGC1u[.*)l%I,˰lp\I1Ǔx<$ BGLO=A`Zt:QSSTWWt&.Mr%'MZMBD"bI<M~#38Ұ-C$vUA.6E1÷EσK~ f)5= >Gmۋ`4:'q2J6P <>hZ)8u.rj^Hsss#M~kB!broԯh"J!#uHj[ee%0o<֢&sGάSJH$Ud9/"$ɦH||Il>\E.R즇yX0[eyX0^2Na+"E"σ𶌉FdL;K)z"Oo/cN:s 6lۆAty,* d"6&(|>x6WBPYYiO$`S GfϞ?qˣѨՕp8֭o Ji0rfE!_Ů/F;ORDQnJ&VfŒ.CUU g)^Mr=CӴd^HN"{<@Nf%X_BT+ưXV% XVbٮHRRPLӊQUP9R|> "04a,#t"i-[nVt=F [HTKZi\&CP p ts[SA4Z:88NAKvijj:z8mۖ^]]~6 DxvZ,+k`%2m̃Sv/eYFYY1c s8l6[2 N$.AF8μzSűY=6S0̦X,D"Y"̊0YE("K lEEeX(ˆ"U,'˻ !$UEYUl.dUeOG{4}Ĵ hÚNl7irBl"a ș_ ( !?kmm,jo˜/qodr<#p:i"֭7"m>څ~xQIE䔠WUJBI )E/ EÁ p7@)0uA)֤gƌu(H$F,O).+9¼V&4Q1hևLCjdW}$e$ 7E1ҋ9NڴE#Ss3"8̳fxl z;Ihw4ITYMV`SENZ+ I! Fs i{moC}`R8[Q r'|US8m1,nl@X&8)/M^[Z4HX@}X }ִ7s/W]Jzu[(mȮ\i1cl޼}0u)RthSooo=d4`W=N(6/fDjDkfVfSifFTZLR*Aiߌ ("ľ)*l Ev8;Qo(>K~i=X|K{ 5 w ×QZ +*T$Aep]2<[=wu -X8 ۍX$JǦ@)E$`>F[o~D/'1v pu[m UNDjsm2ℐu=TFa lMӚ :180"90,jE$BUdX6 Î2*]e(w:`*dP_>,X]~)m'__ymw<|QM6ދ/lؚup}a&b8bYQX-E²+J^Pd9c^/CC|qEQR7Bǃ֞lEǃ`4:69CR@r gn 6KR `ļ#eee(++qG:;;#*n) !M% h4i9`FaA, IQlUUXT6 ͊2=)vج*Y,D={YȐD°ם t|౬~c<96z!'}vL‘οV<+9+]uee _Cm"F7Qb@eH(7S^M0.XKbY#J wB$H`,F󡳿=G↛%md Ld˼!u:9i@r2Jmmm|ks9s,QA@2-ևԆ|ץf}ȇP ;&C|a>"Hǝ8uA(s:VƩaVV`4I°Y!<y8x G01my]ؔbR஗^ƚδ{4U0spٍa<:Ι3 $~8HېDp<IQ!HU!"8sXyAT,YA_2~" ||E#cPhԘ v} `T(@fTe .%JRBu 6{pE\.A3 =Ƹ4779?f IDATOup""*3/So}<Os,ee'  ĵb qMCLK_DZBGBב:t}/L+;؆O) _bpx2RR&8>9L(n'B֌nw1nCpO—_^|^N;/3\uXS}c_ qOfyw8ˇcvl^-ݹ-𽣎*Ig%ƢȪ A 2Q/"z2f;v-Ꮁmxuc1Dx Q0` z{?>xI`9h!9e(.%}d TuzvY5+DF1̅թRZCF)qLJ42J @ BJ)O)U4GNiZrtḽJ. {EwrOEOL)/fuG'zm246=hH$pW᥷ͺI;isf6`+N)d.V<s~pW9G&rFA8C(s<QU O!ya Fsc_Ͽ8MKQ0SO$@46`$k w %c$$NEz"y- I<χ#յ-E)DV !x$aGSm 5 ̛#&4֢*ƄDbnBTUEUUN'8k͛7z}0 \(r,+8P( マWVN۶X}#^{z_go|Gq7## }$1!<)q Ph2lwXXjkWQJkPjb1 =%{>$˰2fTV D'D8%VeTUU@RLr3ƤBJ !'G"SdQGI㾄dGNSYPeߟ¯.Ai5yiOQ$5VmY3̋f͓͛NĬ&8++as`u:lP,VHbDIp#킟)|y$ش=*bͧS PwqvYbdVlV =BadCg๷ނ$XĪ،)Ś>;hh@]E,#N)n̢ IPVXପӧrtTףXʠ% d*x{zR5p:4혎Mnn.N9o1PEAӞ{ѨdMSPû)>(΅w&)իߕ>+ZӽZsTŒvQV{h.&;֠S+Vd51~ςQIJH [XpTe5nǥ,N!OR݊"[o}ʺneܚsJa1P;k6$%kUDY߃ObKw_;2+b<FW8[~'uhλ34`2~nC,c$!ȺE oZa)L\. @va˓P lyf~׋R^4Ĭl1rUf-ƕvզcWm@vT^^kX$ۍsľdIkO= uGw7|84̟.OSWZGƁb4gQq@fqX-*mo͒-~u_pͿA'Q(%,b}>t]G$8)-#+匯ucƤҥnh,IW1B)C ￟1cƙ#2Cr,[ -ʆxL yNo=;5kpףhFVU66"s.ڰ_u51ɽe0E 4aTkb82]BX0&KBH9-k++ %>0auGg6Qp<bc~ w*|jהUWÑ5{ܹ9kZ?)'[ʝ|4?vͥr(npMز Fq\0CKzEy^,%(r ץ@)fT& @+){+*gp,F0[J;/.ux!wŊ ^Ȩ3-t9CJ0Yc*JLQC׆,AGg0iVGd&|?ߞ| (Kb<ǡ"Vau"K1\]]n6D1&KiӦ9pG*Ř3|ԖC, ]?0u1\pydm)ůrV}iV Er͜YFNl]׿ vwKrg7g?4I\^y%[6%UQrP}l`>!}F)5 u u (J9!%'SCc<E<ǔ<-/S]M$ᱞg8]yXuqMÒsܳd8B龱>6Lg4\9ت`ODzG9r>K~;|W7`ko/;uΘפD:$gX,9:&K*p~kBɓo?iDA?|쨘ԎbB}X`^uqMKoƎ_.\1qvu5͘g3Bhs!* !8`=GqӒ !GlloW]_'_|M Fhȴv@įiEeVn4Mq$I< b5ᢥ7ӌbz X3o:͚}rؘ B "g$gqsN)ś+WW\v1 i8 $qJ&K* ;)x8L@n'ćٹKrBTTUTWEUeEuhr gx !hh) n#y$Ëᱮ{_0#Osixqʒ+7erQT{VtJAAz f'ki+!.A8dxeryGsd)ܪ1|a16]H"sGQ\t)>ٴ+paV)5?o 46CRBY~Bpgqύ?ݚ;+ǩW\{~(~dIL;[ŒMa5#\gLnGƤR:׊,]LxsnG"xӶ \jƩ|FNOÊמ)cq t3GXY~$Ejp*2yY}eXOl1JOk g}+^5?:@qO^|x|` 7 =ote+da0;lv ]d뺎hhJښ5&L\&@j}Zؠ"NwHfm6#?_t2h7^UD"~/}0>O GufKw/@4<"br{a?܄M=c9 C]'_/ٌyR>S(J P "fqZ1"(A!vY+lD\k(lc_cӘD9kFnf5cl:w>迳bs@J<̞u_q6ul]A84DvJĪ!s4=C!pE_?Oc!pm$2q|lƤ3KJ:5mmdԇs$tY*k_,O՚LcImu>~mG^z YgF 8^gGG )cbb4~z# N2 p%hM}G73]ؒ5$ )K=O<ٌSѧmp/l!YrM)eDVurkwwwֶY4Ğ-My,cTUW×3][` `{<*N?۽'COuݸC1fx>xwaKއDxWq܅ᦿOQOCm}̝v֑"Z$ Du Bʵ'|mi^>, GA幷3F$xq弾}6_w8Fy;**P9q?~_8C "u]ǺV7k~>-ƀǃ֭+ނbCL"#ch% X<#c%ץIΓO?ao9į@Udd!,z!󿏇z#- N=E)EGw7.V|+o#eO,7[vxyri@4qO$Oy뺎XiFH,ӌyL aE"eb\K`ن i_xn; o77lQߔR쳸D)`Ƃ U#.̺{>ƽ>ZՍN0Ƹc!9:WxN6{qɗ?",aRn7o;`sIDAr&K MU})C /!.A( Yظ/zF۴`fAӌ;s<ޛ@=p1- jkr^8Пq&bQvL3_܀}Q1WVcL4iZ-*neKX PQm1'Ջ/y~&bXcIG)xgj~("b=Rn}xPL35.%ƘuiD)S)xfʬ,]ra_ZO43W{~KONj ^Y:*TO$dC"(~,> YFӚmV x?o~i5Uy%^.ȑ-}6.=̴e܊G_~B# ̂H4ן. ! ~1FEG0FMyyBIkjppe;/ラqtmͿׄcŢ3NEǖ.|~cZ"XJ)n?e8PS|}{=Щ/'ޱ@u aH}`{-ʵ#pt]G[Wy |nQ]΢,M!s,;?b'`C{;o߼ͥ!Ͼ&) 1=u Q^7 c_x8\.B"n.1ưW{ ByϒR";:3O<6OK 낢( Nzs&躎{~ VH9sZ8yP#=wݍGHnq$z9׎<^gAKf5}zŕxir61 [~ig[ϰ9#h*~>nuK[ yJ!/˜0q]DluNb!i*5O8\qY̦1\v!^~_9`g_&xeϣa|Ȳ?BԴ;@lˈ8L IDAT#N9BlÍ+NǸ7Y1r X(m{ νZ{g8SqCdd ,FPJ l!%Hyy}>_'pGU턐o?`V ήÍ?>?iQR.!h5?x1ndDxS=ɚ8 X۹%z?ZpO,eLH@B3RS+񝓎åׇySb8ַ_.~ (+MU'| =mhSr%ڷu}{R|ڊu?kI qpV qgҶɲ k<σYc\:{):2CKvXm8c !6|T5;{/}G{%K )2lV+֎mʺxF|ng2$ ͆2B @ٍ6~Z]FI!Fb3]8tp19 [g| [{zP[ ͖w,{ bAc#\2;־m^Z,ZWdRYY(C:*Mۺ믧mX,Z v_*&! b6#Sϔ}.xǹ}'WX-޻;n,8exiٲ as0 }xiR\r͵|siFcv<⫸⨳/A1aڡ'ba''_ycTX //_]{~yןкeP5^xw`zMu>gx嗧DHCFg(EYfLE6vdO}&z=ej88:^;7J w OF%qzUUdߏ525!8{znŰo[VW^:qWM fBcpK/ X,|;taZ&lMipy?~7>>A#[ qM~;;q'؃eB2|w!ގӮ ?qLә(lf50F⦸&0כl6\xv)cRS1aBȷ{{{ȷ-swpe yt@kS&zq`{/"#[XzHxgpᕿ@(O4Gr✳&d]z"ի=My~3'd-ak^DG88ȒÁy7qem3e[.`blc1!) nn&&/餒M!B ${/.ظwVhX}~ϓ'jFs%K3{{!#틞ݻAATB㎓i^|Wd=ۡ#0۫J4%j7q:?_ܰʃ"6*355ȣͩA !x떛aСE\Qݐ濉J)f?jZ0 PJM999W$$C !alctXч~gJssQ]Z͎GV^ ݐq8rխW"(œ[aǞmn7{RR|2'͆][E` kr9#3}QyťeX|.r`FFr2fFGA@P\ɞeUlk "Z¼+  |/|RэZSw܁Ke9lM&\Ao@B&B 5sLnAmB@^@)=ϏӓRZHhb9ׁjn=[(pEša%a`?#piww\9m*tmEvr#Ǝ#55xkٯkt'Nڈ/E)WOtNy @QwB"FQ!)>z֫Qb${wށ[+Phz ?;$%ᆙqB>}UWc7Q^]ڃD]:}~yz[m6lݹo߇ذuD !zpرHGtd$ry|)ř":!r232pӬY5p d!:tojI4*6̞8!#>VךfbXdv0=LwW? ^t~NNg~oy`0B, :Be2~~(EٳXeDgt>]Á]z\]iX|F1r@)T* _!S'd]q**Ͼ ć_||m0Hõ3f;n]#WO4iRBA^YY;m*z:yWm5xn⢢g0g60?l  RiN'6݋'N`\Px  P-}- }§K~ƂeYJyC-&dw]﴿N̡aL'XxfQ[)oSgr=/"XyAyvI}^=3BB5;;;@J/RBƙf5;,rP[ cU%8nVE>p'F /A _zz$&`y0!eV+~۶=hR ccM#GbpuWAјMybL(9WG$P8v\7>,qt J-0nP<;><8; +/>0ӄ@B,s~Zgc@LddHmL#G`hFv:K(6ؼo?6݇ Ç+z 7?j1DVCbn)ał1\(W]]oLL«n[C>F?ƻ}yB}B6Qmd,}E\yL|(*)m9<[.;́:Hz6ṋaÅ٢@Rs>A(z#(( FG".-%$ `8koBj4j5kfM?<wb+xljæ PmEcZ@) A 3q+V`u9xV&j  \u=+8qNgõ3+@Dㅫ+xGq۳ϡ- =p'@,Vר5 U' !66輣fㇷ¢U+_Qc=,xH$`xCnwEsܾP qEkE;|>! k A)xΉC3Wh|41@"s@;ㅂ|&\5[wc!]3 m/c'6 ~u "Z\sŸaLDFtMplFшyy8p$rΞEyu Lf3`,,@rD!Q)([zlZ "obVotž[p/trKJ/_~AdC3pŔޯ4AT1o\̙2}>}Zќ\bd6ރ}ǏViFg<)x0z-\8؀ ʾ QT#.onupEs [Xϗ,^Cf \uHGAXwMf߮\~.=ګE&9qPAp@en4붋uu%ӫ!jTj˱鋅~ڲ2:z}@h*r48k7d,TJbc10#MiǡgR"pIxlQ1x,YcH:\.4}R<~H߿&N۾CyUu#DƂ7@= %uSij\֒BPeQ؎怫s;C:]\^7~]Gx|>`܌)#G58PPZ|&ey0*:!%ݻz~ƧA^Q`,992RJ{x.$z$qjMM Z{)rl\yxƖÆ;UBXL;Ͻ G CLہ=0o_ptvNL3 "?Չ9p}v]@lv;৵Q4mn0 4j5z$vDv^KAMf؎%, !kSbĀ.(K<7XˍBie%~ C^FGo4{Flϱ;{MAJJ fggؗR"( %ѥ<0̛Z.O? \`ԶhJAٽ;t5bހ [/?Jw(P2س[Q1 ±=XEx6 'GrRRx:&!.Oq;sSUm-<n ruH4cݺ!!U`&8;_xQ0Vfgg{ڗa n"C)q]Y]z ᚻb#GQh5IJ¤1v$B|4O) ͆²2:r{GaYM&ADaq . F1#2Ƚwan}~+/_z~M5Rl=ps} \|1TFp/|M٭;n2WW 5=8Z6n&C\rs.` 'D7w^}&7KWc#hD6@_RZJ=0qpL5~,`ј4bnߎu ɒ <;GoFI$[&%7Tӄ`gՖ- {_G·Ha$--CEbAeFLd&׊c۷cg h*̘05zUVu  Lh%00- Q˙v8064tAع ;Fu]]sinex73c'p`J( ̛;7͞u^ ]9~G z&$cGH̼h2 :S&]~ 6o%"-~#-AW]2?Wc'KrU BTJ%z'$`:zz[p`M觟<:-9ٓG6[X[߮iݻUj4H浹 < ˄Ym6[gD $%%NaFO-v gwWN=\.#o݊?"VYOaC٢oڕ7c/="5փ'O},ڎRe5XF,Z= QXQQHON!1r$AΛ+]dQc4zܦGnx0z@i;NzAAs@Fk*+#c.C ap{7,ˢO>VtoH:IMM}CCJKKBk"gO?pee7|OspcmfCYyoކ~þCGP^Q)(B.GNݺa@j FԞ=jR*;q8]PĆ={DiOOI#gOU*1w8شw/v*j<&铔7݈1wi$RYG䗔q1x{0arۛ=S5z<+Xݏ4T4 IDATLR| ;q ℨ!wGCIee'NEyؒ y h>xxPTlaȲ2I!$Cᄐ=6=+1u(?ͬ8[bgFَU r%!@ԅ7p80[,(Į}av?tE3zt\-3q1f`Dh4RSJQZYKa9I(r|LnJl}h\B[+PJq2;<46 sMͳg#`hSp1ZvP((DQy9xJA)Ł'q_Ę-7ytP˄)fϿG+PmD+bZmj>_ub6kj5e=GjauK*R.Y11k4'Μ=?.]2(ķ+V+h0_?\;c: [vN[.ΘM{GYcS͎W? 1n=A栁زj 8|[vns{'a}زo?z]W^ 2yr y9+8'X_su/<9S1$ut6wt8p:8w@&dDV=kR)M^alv; 4Z-aÇdC]yFT JJPPYJc=V88t R w>͆z5\k`,x"Fн)\}hLߘC)A0o.^Ó,$J*+Ek=DdfWv2Msصh}T(0o_ze.hLT(0=k,EEvEu-YW:gSj-yWB~h.e V,FN^>&q&xJq*?Oz4{NZ Br9>xYKvKͪo0a쫰ڧse+X BFKİ^0htP2#ʋqsN9D.&Lnĵ! -%/e/ïkւ;5F#5hn5Z'/{_~ 74`Yظ'ҭI P:ߌȩ.Ǘ{7c}@)꼸nBpwZd,kg]w_kukJJ!!pTsjHG0, BR!`(9vvv F(2itd`Nd2029X  Z*2\&e=gynU#2Ng^ᜳcצ`dEc)z>CסK=8am~K6+2 }Vxh\Qd =KƁkeQXThVk `3qo?8mߎ> 6VW=4Gm׃RA1Dw;/?> sWV=P]W~,_^=qi 6\{+V5M<ȣgu7pɸqy *mιD#"BX6x`K<8_ &v;f\s3>_}96L˄urŽ㧋ƍRc0+ .lb ad+Pj4AtIJBLb"㡋JL[ _{TR;ld r9NTTT+3$qB[;nWF球 Zo5Da\#ٻ}ו𺳀ĹR)qe8{Zh458< ٗ{ aI^y턨hXg +^صzܽ1Tpe~o1}K}: #, .2~D 0_qT~!"cH; 2{vm'XN.{\;d0F jj[~!XEjro|DocȀAy y]{ 2q=g*^> vjŐ,jF؁)Pq|wwrBEGDDo2$$CJi>Zj s>I iZ\!Z[5)g| J9pߵ{v>"bl,Ł'tR{xEmDQ1U8{|>Ŵɱ=^z]Ǣ8@X hotĢa`dǢh}[VxJQO{qqUR.7݈喔TzQ"duB)5D;1A"\FLF(v:9,uW',޽{/+fC:VO*)MС i{YV kp<煦EL2Gع0n52<ֹ%q v,7Qs{Z%xS1ZԋnN[o$.LP}K G&yR`aQʉg= ii aqg~kϑkos /D(-nF Cܵ[RT R$!$)rPJsq䚧yVmmD+8ò7D,ngk^/ 5w;2p:2Jx"-5xަB@DtT1E1 p؂hkZ%j}ӧ8$q5~lG))k6퀱1mSA)34L;fW D]ݸSwr;7<-3w~9CN` )QB-1j_xmz+UFĸy\Sztډ\@_矢7Ft]!y.A!LEEE!0H\wF'Vnϑkc2'0`"S9]~ǽ kxXcO]Q#FX]2(qk"Ӊs35_/nz-_I"uSS*B[ׄArVWѣ#@e#{u6 ~;}AXUTDӪr3 I]U, 0` haw8P^~Z8 wKNaڜ]~D@!'5V2)hB-J(,O9Sg 41zexa/myί?É1Ϡ - %(nx?[ )oA)řb/\wt?iڦAˑBO1 sX9PzhM8/CV͆6@ff_b=]粌Iލ];O@Y-8TZFnMysZ9-*€ x00DG Qy)J 3{v Q(.-k;x v5! dV|EM.!R&$q)ϣ|L)E?^n#N(^7Ŋ9kJ ַ݆\q=#k  àO(l]3j oeZ,Sxx .GNO'"!0RA&SBu99921CJ q!B(ϣ36Y,ǨT*9sf_&&H:),,BLP<[{qp+d,B`@lD}GNՒN&An{fyńѩ"-.Qz=tZa1` (`WB)m$lAQtBIJeb T3PTƯhW}$;G#T*אuxP" kh *{gA8a=u6:+< `v1Z`S^=fnיs$v|hLw$Ji>{kw/,J e8TQdr4t IDATGy-e2zlf: [.1O]*a WS'ZQJM-Z }Nk:W'=k <8!׺Vxټ瓒h$ql<]<+ZE{ m{ۮ=O3܀c.9[yyD7Ul1ǕUa&#OܼeQ>9ᙂAg1t>ƃUuukd2, JiIIII$<"0RzkQQSӹ\[okU*OJ<_[gmi1 G)+(ʱ$ADc,e79Df',:V57")h;Ax{Hx@AІuo/J\toLH0"5EK)ŏKW-5DwM[^8^()8SPcI7Ç 9 |$I\ k_kL&h#FX '.-! pXChmߍt$Q*,gRnIRqBxn=+NkCv:j!X2BR+_&&H: Zmz])/zź*F'FUHdƶ{}27w?FWFD+D>476AqXbθ [h5Du=q&'$Nw<3ڤV=KU"$q! Èĵ/еZ3JMhLJ)N?nqq1Np]\r%eܫ`:mp5u"84ѫGqKrOkO]#{2PJz>$Ji)JhM(Zk[ tGZ/iN_4\B@¿HF-soÞ-~S'[{} WԀ3znn|~N)@ǢjcDhEjMW`ρCޜG)soܕ:Qj$#B4f=~ L<'Mk 9V;^9p= `+5n Xm RUJKup p劵fⶈi2#SSˊ<ǥ+| !r`Z q·1D 2HԔYRБ.r˲蟞is2?a v؊oݎFSwou"$q&PJbqSR%QBڌn'$oފJzGEFț,ދ&˅b Q)+V 3R^ձwJRVUt.a:J |+6"W)z>$R"%*ޮ"EF4%eؽ߷GrrJs-&&|q;'pW݆yDGEB. J+W$;!͑<8qRW* Rz$% I\  j SmxoKJ'6ߴ[n,Zu<(磥HǍ9B\zhl>˲r.v7!*s3:x:XSWFJǾDp!0 C8ZV˳NF$aAaiyO0 n^> #OO,;˪;J= HMMR)Ĭ>e *և{7WwZ*ws88phт8n'%TH:)g>Ҫ.v]!4kNR$Ɯe^pR@#8U*QofFF㧠_PĂ5P`Y!+kgc䋑 ㊈rUF|l1e$6<{ZC@t+*"nr0 JZ?MM"HuPs>L Q+5^ lijHzjјĵۅFJha'Y0F51Bm@ZZ&G^:A> ""#FCEz >3g^Q}3}^؄{L& eBԊWM$XS⮌QkPJH#!{k )d,("-j5HUVUcE2h#C]z$/%3on120ytAa3f㻃eۿ. }5 ܒa$%E<ۦ[8ԆQ=-DTe`RJ͏K|`eP јVR[9OPAaiiu% :ڀ#0l(DG/`Yݺuǘ1Я`' `v΋yt𔢪6|Tm릈5rDG߭+#A$ 'BHSfN|Ajsv6[7tBq}^({8o4y):p;H\L z$&x cGrrJ'P7vOر9|bbEM #GÈcfh-%b5uu~/;Ziu^HfӾ}sZnjz먄DH: [TKM⺪m#*d&' L&3~^S!E^׼ xÎO$L"p K.R{XEbB3YYѷo?DFF7\w%##sGB\\9b] wz0ccD72u6-L[m՛ƚ2^wh, z "225 Y&aHJ!:* r2rjqq1``dq&_:Hs<،@@XǾ$>6V~#-lEUHi"PB'ZmH)u$ VHJvBRD{Ÿ̡>GS #dF8䔵4f0^c 4@b+:_˽3˲Z֗o \.(*: ۑ%Zd2DEF#*2K)x<\6\Uy~g[گ)!elQ^]C$\rXjyZ( U B\=5pj)1B OA((.Z-m;;u2rv//(Ė:)ws, ))i8-^~81xGdcpBE[^O6H,ɶLMCd[PH:?dkk!4V+<&,>)++k!p'{0**]TDf"RKAGs'Z8[6橬C|\"Dq231 @ rYRK81>m2b%c&l}ccoRR$cZyk?qmkDjݒE}~ەN0NxXp}L`M=ܞcdۈ?9P8[R 'MQcF8R +c'""{LTdb% '8ej4匝ل|,[&!N\ ˆ6nFt^؟8T,yh}>B6|'6,>Eu׬y昈HΒF 0vZV0.bt6l'H$?#FؘJ+d 8%x@ֻ6S{pHvFEF&ƧZT|A)&-GNg/=]F6Zš݅ק(nwbe߾^Czb}F]:D?) G1V(Z7h:lLL8 ÆBN ȑc1< $%50IkB3>`tD.3ϟ!vL(F~lFOEWR++}ӧ?9&&'"h$'8PJ=555=#dYT]2κGf'%!+1Q2VRVl2fXmJT1bi>|s lL)^ZVd FWxq5pT_<ѧt,911&+@)lC 1 >+IKuC#E}BZK !VF<#dԅ8d+ BN\S{TJ.)E06sTX??1][:3NLr1u I-|(ZiNڦF! Q!)p)0 {rˆc&p>WGXƭph0xsƤ AνZw.>7Ԕ>0NL8GL T^?,Yu J)YDoq8{>UЪ)󧟉kBmvvϣ(mU8 CC}JK 3>j?3 ]n7fd,#bgVl]pd݆ק8( Qˌ -5-ضkcq^z1x {0WI !8 -gk.)=}7^CsXS26l##ODmS,+)8ow15*`t Oq:JGʖG}(sd͎%×uy*8[L=j\K{fTJ%xǷLRlSl{CPwCXp-8`ߒdl_3Μ+ Vt5e{wB},B_g}Mp򀄐Xp}SSSylނgLl /JR6@RNp\p F{ ]~|>Rq|uHGڄ1|L$6 ]VΤRW?h3#W1FS-:Pu 1^8@̓TD*A"9'Bm_QqȐ;mޤ#Bۑ,fpjV H2Vn op p$ZOBq9mɍrqm4 B|Y~1<2F#nK)_I6v̋B6OgNbס#@)l M(Z EKW"7(YPEGI{4(ah*8 2Q_ ^zQ<}~KU z 6!KDWn-nPñD)GD2q 7$59h1Ko{C E$~;b \3P]]ݤ+xQ(p{ ;z( 6?Y%56IhԶACc}~6\>H21K  %1J%c0Q#sR\x(,) 9*5Z׀ʍ[CrIŏs?FFzUq jt"q)Kq 5:.V.I ՗3GYu5i9>%G_.?I a!zu=7G Qq+Z@^46&[/=hOXCa 6i3z pW*/ѭdaWsAB-' F-BlSlPn5w/H]{018⻯qӇSJYg9۰a>DEEIEQ]zdɘAQi =5~lW?RSl+g]^f0…Fޅ̌ChsQÆbŏ_hF̺|+lw*-klZ0*Q Pb B qSp-(lkJȓvSSc Z?Ɍ%JV\3&i Fvf8 8 IDAT9Gi42IPܣClN2&zݛ`,ǯõDFz E_ fo۰o ?̠F{Pe ݅Pk0t%?_,-gKjn iGDy)h 9p7㔇\3MMMǍQTp-(+F ˵Clbʪ{C+>.o qcY%v?LhFo>!+?洰Շ3]-.9.9(xAmno`o֔hqX Q neӕ~eNt* IOꜝ)˄t?+:Iɹ^{Էnk#/k+CAMd,-%ה7J%3>~Rl~|1|sΕ\Y` .f8}A϶mvSvV|?͌P> be,YޟD׌6JKK+Js={z혤.7~ٶ]7 ^>qQ# Qw:O NW@kӦg`xL؂M;6?I!ɶVD|<)]&S ZX.s=,Vbt hR;!R}f 嵵apdLLSR*Z]uy3w{|;7,F7 Iűli/1@{fO@ad;#!b0}sbJYǚu=@1NIXp͐ 'I/(Xfmخ ds:b^>On39Y,p'Z׭oB^clH{R`'yl`D{]H \y;lh MhCaqBM1㤃 %%%[)fF#_ukؤ8rT46IƲfw0kM-nefx5} "#Jטa"W׶?2!< -Rd@RB<2p9ga7sQu`;bi`t.N (^_jx5>DPj?PRUW;yQ`[q;j+ƌǂ}0NlN6fF!k\jaZv57 !Pi4pج6 +e6 jr(!:F'(p @ٽwQBL8S&Q]Bz8!:F>'!@bT 5nUjϑ#$cgF_(\v;Tm6f 8lڏ @ $M')ϐA)b|EQ S A 54HƲfkfs5 kjT#"0%ZKH-]vj@(5==<BO rjMT,7k&4WUmo0P--jSJR_svk/8_Pr8pݠ'cpo=! / D׭ y?ځDkyZDe&P[1(Np~F`Xo 4υ<&ۼȥF@94[ kL?^-~uuނ=8䦄) ~! Tbn/'vDzם`4Ped,)1hp=RW`0 O@bTP bh$-Fr,?Qp""@9"|f4KlNL.sHV"7'َRrQ`B !+d. 'L-Bg^^jQ GmSғGt|_~[SJ;?_22$%3ǍCjb"jZޟJB>2׌>G5RreXˍEE1Z;oxA=]ϮwIŃD2 F0G%kgDϊsOV4(pi :73d` 64/R|l}K7ndB؜? 4lqxe6 z^㄂E ̘8E,a5# NB2B"|j뛛QV]krU'U+* 쯹l&"Ǐ# hQ#K`0)G9?$UXԅ&?lGi ~r@)EU.'JBqx;d (t%8Kk^{.#\3:Dw ֧\R+/3KT\\}ArɘZM~P/-^e`0N(ۧ9*"N] 9n7~ߺm#X}9|CRl;p@264= >!lFjo0,77\|lp 3z{8A̴ܗ !!rrrXBXp&Z-{_c'ܞqt]BB}FXnV&}yi! J0*x$ekv4WIәIH]=xwVV+j}TEكb^^+\}5d---z~EzzzV?#---Q?T*7Br\)6f C Hdᒒ_P 6曳MV+_~b V!ǔ:`GF+e0םn]P2)SsRۭF E_\,yq91WrLÇ{]ZTO`@CC!iz^nؿP \UUv{!:B,0F_W5fo!8h<($7XBΟ~&8?F $J ~@Hk03&Jٺ- ) ͆YTug,Y&q䥦y[<-}QQIh͊0$s:#).zAFE1^_ s^5//CQ   TPJSy ‚kFVT*(|4G8Ȟ,wr Ht;jD[ 2 n5Jܠ8g`)W]dߕ||U'Iϕs̰ c>3.7'0PSGƓwwf3Je^ߦ/'YT^a^^^# !PJ#F#***T*Je}1ߓ507ǣa0XvlݿǏ|t7 >~9h0I fr"#3Ī+8 v[DH (yh% HU1 9TL(5jln. ~v\w;ZŤAڶSccy`0r &[ z}g15EE81a01YgLVTVVB"99( &J7ǽSXXXcOp}=iBHۛn`n~j 0#&ixx1SQfeGfip BӅqbs?IM~t+c+bá3۶AÇ%ǜ3bD)knGƐ! o_ o}%_0;,F#F#xGDDt:j5q\ 㦷~>::FEE!nPPB/(p`0ptYM%11 (>T\\\F`XC#x<8e_Vx)H SP?Z,2 FHc}54\np-"}}ذ P>$WJF{iP< Y؂={lW_U*<}ם?ocd^^fUUU(..FII  jE)@@M)n7f3PZZTWWDdd$)-*..akF)++sY3kjBAYz`*FD#BH~A!DJW`0qVЍAO8Di~ve< i֪TЪU9-Fnj mIɒ]NۋԜ\%'wOv5HR ZkgwhM nnK !m/<PJt[yPgZ ]e݂k.R]&')qvj݌8I[54zT/_6~~Y.9(BEQXx49pAE؝N`Q䗔F#l\nw,qP+@R\1vPCBLLk J!==5<_zFm*++zBqV]vU}=chU Z-vt:L2m/|51yr2{t X3M+4>b싋R(x%z.FGG#-mj[k rJ^ex^D!93OV8CVṹ{܆R ѧyxD]YHmq(e a0z @||dRڋT7j}$jjϣĤ ?BX 1G񧇞Rg}CWm=cj]AP1Y,be;+&N跍]bhF޽(޻O;?<σ8I`MEf8;wdEj)ْ ʰ#JKKQJK4 > Q&'[Փ'JO~} xcxM`T-!)EeŊ[ʮ"~dl^ԡ& Rnvp{,fI&R8m6ԗ讝8|V6^>:^I°S( s{orB|ϿfxVӦv;L9mEUVyB{ƈ!/(ܵ;wjkr8@EQܛPJqa3QWZݻQg*qPxo-^zɱU|; fZtttLSS$tFua|LҜ 5':N'$'&`YK/|':ܖzAt/l11d5`0`PPRcW˚5vd)ۓ&J] ,96Bٶ (B1rDfܿr䄩 Evv{`ǁW(P(+ޒHB((⍻=f#x<EG8f#I.;{"T4I/  *(g`5#(FtFQrbb\{f :Z6Mkݮֺ}?~9;!&O >UN@`gWXl6ڴo[Cq8-+ ?e㸰44L&%}%w IDAT;<ҍJ 44'O j'Tq9q%ԵEc<222|tZQQQEMVs 8CT4a0b.km(~ߖ-saeGJp]őb0kvxW~6 TJ?G3ŽU07,6[e:\tø'i>5!9ɸ py"3)-ViP󈍎ɼZmj­>SkBpH 2K=nN) Hd>MO?kB3}\3P(qj?)S:^/\ΙÙOMEC{qphlvڿ_a\n+?!˅|}]2a/=UFPp%f-&3Vl܊T@JL .;&4؉jR`2ޗf5'a\nNR 44;"|jd֭k3o&h\30M* l޻혷k*"ޘ7.wlT|ZZ,_+J+'MĔe߳ *8 ҀA#.]?Ͽ.WCH)OXB3/®57imRl֔R4Z0wbeρu|T2O]y>LX@ ZR0Xlv˨m׸ SEcF$P%,_m؈Wy fB6%$$v6vlJݬـ-W_RDK凴*%n< ۋ$.e7݁o>ycGheu w9H DYO8|<$6nP66F |&P0:Fk:TET7bw?hiEƱ1r:1YOYHVzvӉG|Ms)s lZ;oqС̵Po4eeTpWp8TVVV`#$nh4PduJ*_YTfh xLL?B{j|֙8RiQIn۴>.2o޾GM?z_X6ᴳ.ĆYw W]ޠXpq)~#L<;(()&M\!62p`M)`vHde=gJ)^c+(mӧLV c B0!dftJ]%xqqqr{[du׌!}䣠@1w^(0ryQՈ1A5ߋKIu;ԫRVqYu\ؼ{?nr]x/PU QQfd<ׅOS쬠>{OXcdlPZzP*BTHc}:#؝.],_KrIAZZ-˹&'b), ---UqqqR*IERl4bˆHPJҥp{<240ݧR(0b@vT*:N,[N =HXزcl_фϿ֫6>4{i? ,foct孧C! -Xz|My}NYpe3́Ш]e6lXw_[#5ppX<6k`9`Ve  kP EqZ_TbjRfQQmV5t5SŠ!%77bl6T ef,fBc;V[o Kk/!s@zWDF7_g_9pb{o"2r]vO7 C{F &jN ӉGݯ+ը밞#qi0.'uvDeS3~~6q왹uڜ9UVqAq  1~fl.(;dpgPTT,s)X:jJ !#%Er !֭C뀧T*jrmQđՑhxÐtJݸaGv@b!0v4Vް ~V){B`!?p{'#~^ 6FVÖDCV7^ӉMw\n,_376aap8칸۰跕p8;ͺ<_#M^B(x-Zjق;WW CYU=jipرeT@;󫤸8p>[_:)Aϓ8XQw[?5^ h4J)]@aN{*#(PJGTTT^}!3Qڍ}l$''jNj@r2~|M Ʉ;@I}=Y*3V&w^}Ǎ i7> ~ zJUJ%r^~]֔x>[?>3Μ֭ 5{qڼ!R ݎrb-,_² x<@.S ļ<$jΪ5ȑic9Voۆ?Pd/cؓd-]u~K@8Cbb"t:(VJşlAwe6^%&7^Qe2Cqqq())|nt&z+޳>_YEDhq-7ᑿލ4% Uym8pHӨxwC ش}'^xm߼ ݅<_jg[ngjQ\Q_VǂqhI SS0} ȀV K?,@iqn7Ϝ^o̝'^xfgI@ш7lʪj` Wgkז6z6BȄ 8}Oy8眶ow鐜 łv {% Ζ]f4Fr +ˎ矓~\v bgr/4o=~irEυFFфU7b%h6ța}⡻oLZ/8]2V.J*t&*=|vG5! yzd$Cn]r /`lW!g@-n| $R<:w& }C&߼T*h@)BVXX^-#.#ldggV(N'WQ!-EE᧷B1U[DFF"-pVUU{H{~ꢋ솳C#D/Ζ)GQyV ?.[=:.i%B8k0䦤 R굆TJ|: sE' }="]y\xFRAQ\W6LLLDH`0d2B2Š^_BYSS#?_:+(,/O?x#L).--46x>~YYdD]sf (uT*wx0qh=bR[/> ϗgyv34=Y;[7\(* [ӊ_Pk/*,$DGzqxp履mFGcGvx̮|<λ04{kjGFxhXr>l?,sUl󈋋CLL !VQJ-**5$eaG׿M{cc#Z|b&18N{!"xG2Bpof6t'EWY55A٪ٟ``@?[RaqbƙS˾L!/y(.+بHA.]1 {s^We/(ЂGxcʫ8$AZl,ʮ'wxF}rYȁqy2W ]8PQ_wFYCCzjTCӵMl_tmqBOnQ<5@|ii}G ǹwBrssAn#I|N+/o۶fg؂_oϫV9M6i;nWϺiL/PJaٱs~lܺ55x( d㬩0zİN\OyDLa )p8]Ƕ}ؼ{?j\8$t99J c=!l6>%cR[#sNFFxMM}~*.9QGddd[PM)}#bW+qfuuRex|+t#qhےFCՊ{tf Wm!ѣcR ӦM)EuC~\K7lZ45NzΞ: !7`0C޿!+ x .-&cÎ=Xe'> ,%%#56cr1.'P):n`5mW8OqG۶wx幷wV}%Kcm!H9$4N $!vR! 5B 7 \%*V/Zi̼]kd\wvڎw3{ŷXpphڙ:v y0M`$y3]Dw!IUUrrrM=ERB644Y F'Iil24 Gt y({ӏpoS6X|pN4ᑧ|VϛG;=7\,$eax}}lؾm= F"$v!]R>!į_444M,:YqeI x<'̷,K,K#HxK-_\6D9Xֈ[9"G:DaDq‘(=lk oh.!%$/v]륶e8={MMS3O\MQ6 dR"忿}}tv(#q)e ]J@ccc~,<0E]]ݩ#m"*9)-,7m4MH?eycq]wgl˗wW_Myq1HƵoNiY\aܝ|\xԑX iֶf^kl}` ]Aq1sfֱl"8l13gR\TJZ=.f]yY`Il&x7 i覱M-ljjy{]}{-ShQ[\L|r].l,ɷ+^]9z̬KNBa?6Ept:q8F-RnYv0477&^c,Y9)mh4TUV,]?R?ϼ:7qN^x!d{?1r+`Vuukzɓ\PYgHNoB&;A#NSGmu%f ;r|9984M˞ܻrTƈp IDATdچe|oiDh, ۻzhIK{'흴vtE@p$J0*c,v8(͡* w{HmqmEpY{8ջ+~[ْȍd㥔2-G+hil64M(NJ)V!ĿXVSSS d,lHq5UERWYA_ ]x/~ :BJq|RN<6Y{v8; #l {q۶B4\N'VU2wV=sf3ʲ2 p9l:'~*zyn7MA)oW^I;i3grG%E!}rM?|Wp8(//'$J)_R>'FC.Y0eQWWW)8VJ)'EafU?T_ ZI)=!w)iұe~?yckiksӒtu+5n+0D*Ʀz&X_Qt]rRTX@Ei)UeTQUQNUEetۦu-Y>Uއec`6LH4F`0D@z7@@ ~`0p8B,0 Lsϝ v!PUV¬*ް ++g.'?{vV̝éK8Eu@'zӗ,7ݪS`}\tw2J`H)sEJ)@J !4֯!e2 A$!Ue100@00*t88r|>$͚cLA0HD$1x#4 L#i{G58|<.^KG\>/(e^kh`s{y99|Qh!x kDx'[ t n0cO'Bv:x)*ȣ |EyQQK/_ˉ'(h*(BH!Hh=}eYXiY9}kG"CC ;?8H`p@!ÄQ"ibYHZ0%j`͡ 0gF  p;m:I.UiÇ/egS?k55dt⮻$G$i)J)Qǻ |+p4 4MB|apfɲ9G,M.B\YE?lAҷzfY)aAUNR LN.d:#ˋ,riQ˵?F_:TΨtRp,JKoonBS+N^ZEO r'Ҵ$q`0}`]]lNG @x'Iʣ\QPu Mnq9x.n ˉJ:MOg5 tر:**棷 B24B6aJ BeYAผhJIn.KjjXT]EeA]?B<>]I'! a|;ǒcIr3K :4m==G"Su9l<~%͙]U 9bamZ b4tvM4vuMږ_M$0ͤ@r xN{M_Ǵ̿daq9RV\Hei b*ԔR/&/׋nn'.)e[z"KmFUa!ΞZNBP {eqyOmz#BaEc/|{Zes:;ڍڏn'rss)((@QB444,K.TWWTURQ>)%h`0H8Ks\.*.*,?/yn^3v8w~m p?~QkMZrYTJNыr֪U̩ac&C *!)M]]mnfSG'Nڎ7O"0ctttÄc1bY`VMOF=n'>|e%E (._T@a9w2¯'ljO۶wW,#;P`x߄(}>N?l ԑ^7g6^hʇygEa~E= pR1{6}]xxRI+pE0[6:ˁ!:Df9Xϱ,!eB2@XE4epppB{4HtUîiFcq'疗7n>[.HTWbRV,]JeI) Bwt0`;"%E Ż-40M>"uYSvRbH*p,FCI=04phh"A0#"*SBYS#ݎǕM/Ћ )˥0o$O=߇/NjaGSUtMKCѼ+Sekk{zZݢ\^'iD<1apjkǦi̕'8ȷ HZϡ"mOP5%KS'h~o~>eFg_t[۶O8xRR"ȭ}{7Y)a#^[[{(' !r ) 8CCC &єqr>Ev;d G-\@}evDz, $L0 2 M[!NSKh0 GsI%%~?$DE" b Gc Ǣc1±8xo4'>I#(PO jcN!TMQECaZ|漳…g'ݎkZR$kMX<Ι:zՌuw %F$7Hp|sΡ*+% =]q9gdҧM:B(Xf.?8y ᬲR.^Bo^Fz4 0ws4ТiT(VQ޿,YȊ, %%%ndzB)ߪeYq"HX,gwS8vbE2"rSB;,"H`d]*bwOUUv;^+ZExE?\{ v)'2"M:Hi%;kY2Ēr@% بhx4IɿyST>˒;D:ЊIglj* ) 6Mǡku=Ғ8a0?_>;H>%^^θϼyjU*RzuO^trŬZ0UVT<8o&v;?scKG{[f˖14]'uݔJ7rOocҥE󑛛;Wpi555MI,K'+-Z(8WqP۵, 0H$J ﱾ12}MJ-)n7N3]q>vttx_^y%y99WA<e>nDr!(1爙8L+  "'/.{,GϚyEEe~Gz*r)8um?ÓO9 wi<|==fkJ|%%!,G_/&ߏd'[8o;JseYe`,KɊ,#9 EY!&J6}$t&jJQjBJY-(R"RJU10 I4Xgqq1999# VTdy4+cRƁ>u`se) eC˗sg?S1жic9)/wO= Q(ʢq)6]gx3hr^N_MӸ93hoog@R+:sWS9Rkq0 zf\;#(aKG1TE!a9?o.=ֺ78sr/qUTp'uP5pz\?9RzF/~f|dMJ"m6~JJPdI0xw}Ѵ ˚|Bn7>UURR2]du,I)siCqq1R~!KJݝsfO@  !ڥ뀗alWU0EQ~(6]MERҵmd-_cqzli(XBPZSBwk1?ԕǼ'_y .b~h"zzzXreZ =b&t& [{ngqu5klЫ},^O\3+j;0s5Ucf{S|0!(X"%^Ʀn7б(B*N|| .,0'H"v2"RJZ[y72: Mp\Bgv02d2)e6A!đi]Ip8I)oD"N˲,ҩ(. !2(iFDQaCXlkxR !N,K#8& 7]5M=b06DlnWz. 'KiM16 #n^ k{n;>EMp,Η{qiq#ଳ⪫=*UVy܇$0HD"qwޘYxiڸFQ)ɨbQTOft\z|+fB~{rD"htZXYtG+_*++u=!Xа~/v7KC}HȒeg̘U!UBIǥ?njjzHL'JJJ^ZRqK㊋/&?7wuI)ii}A&n4vv1l~ GhKJTE('"7n>vz:I }XoI3Uż3{B$nO j%!ʫo|Ʀ4OS?|"h4j488ʕ+P)q=i EI,.,9^BCc[\ToN8MRZ4s뭷sez|CS\U^7.vS^ƥr )NO\zۍGi  N)w<2mdu,#:γ!֭[_ F#Ӱ~oj!DatwwgX8&ϯ`_/MM&LIv s;]IJ$}C!^o 6=88iErE#FB/Bw4u۾#ᨣb͚5,?'~뾍^ PP4PGmm#{MwH uQu]̘yc؈ajժc8|UB,g(0D4$- mCkzʼ#g@2ۏP__;nW_򊙼V|D";j!!8XFIo?Pߛmsy"( g朣JWVEUYǨ' omWoѸ6vrT0FDQbibtT˅n4uRfuidl$#{=WWW;t]?GJy², ,?p)APFbs}|/J 76o߿K9 py]n5̤XrRhG&UU4 ]'p 1A)ma;C,{Y %˾g=쪫+gr| 9c'm پe ??Gɧ.^<_wwg( ̝SGAMӈ㼽n.XXЇ>DEE'|2=+yo77XO=7w=6olquQ.C  0I 0O eҖ/70QTe'2+p:"3l|iygHﴤE$6uՂ-uss6̫ŋQ9'۲L>z2^_֮ L8vCoohk4yy8nl:r9N$:~_UQWƹ|oeW\SϿ"iGOJii.uq9 DQV.\ě\=Iw .8d;˺u3nSiH IDATu7b䐗*`Y[BM[n)K,ΒePUcBMJI$a```† B~.9NXlN s7HyMGx_XV12tJX'yp\477>l{zKlz "s=jkko~êU&tZZZ[[dn gkO-BՑZ6:"8(,˟rPlo0/;agAe%̚Emq1cR4.75 -?a NXwfN܊rR_vQRJCJy#H$qpY#esY/ju]D)"!D#TDABи|jHF9gWWsyl|Wȑԏ޶6CC\ 876kRPP@KKK:xg?˙ǯ$Om?P43b| },K24 m)Lsc&37D ߕ h|yq뭷F,ˢO<1#};~v^DxhkUkK.1M|_GMn J}ee"#-} X]Ų$<[)BUUJJJp\tvv;C,G"Z[<72w~g}x7xyQwlk͌:N>?=nhii(o,6,*Փ[# ݼiv?z,O6B!,Bn)!ߟWEp^:vmm3U S/A>*Use:34Ԙ4Cat oq EQplT3Yu8 IWp-(DLr984?l:o}5 #777%+Tdu,c;aI/B9+YE4 n^Lp6n  &L|# ޞ͟,y%Z £RNKV.ͧ!ŷl@Opzqg9aX[Gvx<;N6mDeee]#Ɨ^z)Oj&yɇY8wή ͟ݸE]~w{ݻBKK ˗/5[Xɶ}ȫ yqaE}zE2 Z7o+7Lpl,"r\4]goܚ~v;R> )%xP(01L(v* S^Lӹۙ$ EEQUEt.\^nw3+$ai0 8ݼ[PPUEnn.v}GJ2W}reYfu?eraJqRXibt$)#E4UšnJ|tu::xN6g%%04vu^bQ ُ&eꮆrX˲nB|+t^NZjvujmR1FmzY  ݮ3c~56IJçZQVc"q69C(͟?w}w^TOSz?V.8#@n3W^#Cjnf>O`&s'sW`sLy[66'Ov:3sZ2ioh"qkuv@<~tWU?>g}cS?oihrQ\\iH)K)2Mͱ i4M[-< X:کvXb6 Bd\Qln\.' λ ˕sM7} f'pokH޸t}1j፧N?e6mZi9.YΫjv9Ino,b{c'o7̗wxq#>ǯx`fO!|@)g;jVTJy(+:!Qт;LȘ*:6 UU܊c+H/oduCΒejl3fI),VG!ʤT$d^0h4w+½B#J'&yBа Ng6ro" JY|NZ ]={q}F.*ו+!G9^yq=}>c:ǯ{vZ73Нo;`]9<ęgIG_O?|x|Sh3 yXqtPgRXt<*f%}ķFBq"Bx}*fQRU8 X=mO|ۻ%K-7 L1$H\cbLHnhCosIpp1 Yd]Zݝ>3sf"X{Μ6E}~kVn u+k J}d(#/^6Mԏh넯ը8E]^ulٲek\dYƋ/[ou ;<09so{p9@uc%6\[\qOtٟ`ZrVb™IPߍ5l(_Pth;Ձsl+QV^8)8=ǎ!22 >oJ=z% l`mT f Bc-3s.]c $EI$PK87+Oq8I_fOVURz%!-TI$I[[UU Lz6ªPOWksVGUx)Ҍ ';fNX3l !BdM6,1r!BN;UX)nėm&""THZY*65N(`>N}݇tlD"+Vॗ^B$K c hP J DI>h$6yR֔ 6Ǚľ8,<7jW_2] v,ej׮9躙֖p*j)j aXJc c (@`_@ @0!1֚}tIӑQņt2kg 3OCp˲\-IR!d5cl+(6.`{:w N6LScQB)gġd 냪r -+.d_8q~U DQmcl C18T2*{nhAySO}*WJO=> I&Akk+RٌmBa{ݜk3B|!/޴ rFAn!>u]G4JT.dHoЃ~z+SqR\.B!0~922yLy#Smp.9$+[<-.Y$,B(jcJX`c1Fdه= !E9ރA(BܽE7KXuτgZZPSJQR?@ ykGʚ)>+L`3בHsلZF:iZoѱd2{ R} z̊1Fdmftm=WcoC=B2\vẗDJ}l(G*>xNko/>@\S%?s圏pf7Yags8E ΥCpBYKkjj6͖NE!PJ,*!$"7I:44dlvX{*ULn'-򢺱MiC"8i\`Lx[>uӕacg.ų>~\=ŽH:wȑ#XzαP  z/ZwD_ȋt$i5m"kK*d}\WPv| Ψ+(()눏$BNˈ17T_8цӯ7 %:9, L+cy{2~ZI躎VB)dՅxmmFX_hNō% }ettoy[pСiu\2 k.ƀu37h FQX9Pit"d}2)x 8FG!H}%ehX]o=/֑eUBO1w:MOS'Nfglbl eNeAt$c) "6` 81UECgssazT.0GHZsxxNPJ5s5Ù2SU=cq}夥ҽdM=Jgt [x ׶:G.y"c@*'>GP&vh@]K#y9?ʉ'p7_U:lٳgrsTTB Q !Dޠޠx>#/`C1(kMh>r@YMɌϭ*(*^FNn~cl;D \\"p !]{& cSc*P4Cuc包5"q@fגj߿{zzd}zgFZ0r"n "@PwrxYvލo2!tEww74>[5K+p'exqܨһh(NJ͍Xq)B"KS2?g'BS5 t  nJMMM{ug15ÙEQ@^pUx}as+j&mQ>քT/WW׬ d|ߑ#Gb1&^x5FA6~7xWSҲ-bfM/X }}}`+_ -^]N7tV, eF3"B`wQTW4vyĘ=H'ǿ MmGvASTc& B(& p87<p&PI*F3k:y1ϧוa麆Y9efMc'"z{{NpXiz{{ <9&PB'xo:hJ H>Fm݆~zҬِd^z%7)ڦaUs~n~b\m"J*GNɠ@#4S4?{+4ADbUEf p( (ZL! 5s+gBZ[[DQ,v5 HCt!`g|aƥpyfߨ$>@& =>nժUϲ,N]]]o~;3T!4EhgβEQ&o横\Vu]EsQ@Y=kMQ|d҆ h3"Jɋ:[,#HRHDSȤdhYata9Ќm1. ,, p8@ դRvL֟hj۲vӬBPfN˗c^|EH`K eY;}f_ Pe?{gƍlCuC4;W+<~#1d8\vT4iMx{.Y2cFb8{&5cɒ%icSO=CA4|hB\r5lkEڵkV5d2صknv$qBs ]T 7|!/ܾ'\IiÙh;݁L \+а|A${~t@0tHKeee !dif|?FECE(V!^"NfK۩("o z7jn^pc\;N|&H4_L$غu+ u]]]hkkix衇/}"Ag?Ys4&%7]i/%h cs!R.>|޴ e{8 !(KKf&)ù(>3`z !\bTn'JBXڋTdØ d9_-,+UGAJIQ˖-C(23}QlݺO$|>yCk?Db1}سgeǃGy\?vݥbѡ׊ 鍘0R,Š-Ml31M!~9Λ n p8EPJ&f'≒nv bI\+H DRz&610?|,… 6eeet? EWA JT N)5 AH+15zvbQSXSJqFv>d2L&L&UUMaӃ~Eºb w}捂dP8 XqJ\؞\/kZ9ca X'>X3pވpqpNH*QYUGEf"+H%];:\vZ$M,رcGQgF7w z׻gmx7bEc:EO'6t:>(N>ΝÝwiɪfaxm7'Dyy9N:^{|ny5Md,1S \O46M7ǎ?6Nc,<9.9zcl9cwTE %J 4U`xC=Ös(Eb"L/[n; ^\}s 5N !<^@)o}+஻]we׮] HַO~E.o&1|($ ǏTWְB"_@`۸9lpKji9F|xYt:` Dgѱ~r8K!`xx\Wb ]iCYm F*9 3@&zjQ(PUx<>UpA|G&wi%KcׅaTև(Fk*+\}FI]7Z)}݇>|\裏rvB!8N躎}uKv {)! B褓*z>#򰢾 Y3D8=4F2~"lulC1d>? DIhꍠvvfRye0(*" wL]RR~({Vt aS].HArUH)wikIPUUݎ+WD۾};~a455YF|A(o\װ qN搐ZN+`-x"+D. 5W@݊k_؈&ga-gAkc"mi%DKcsHp#&v*\tܳ]'o SPsyhjjBSSqI BtԘ^$ `_w;`W@rN2$JJJp8@A0c=ǚRYY_طo/_ngϞL$tǼL0o\]MӠ V l15%z`/Y󆁋kcB);D"eN_ԏҚBYgB4[:N!6 Z /XDx|>G?2 6|j6w 6B@f#nv3l* 6*BL&Aek{]w݅|#/΁lٲF95kqTtw cC=P?ڊWPRB.}7Yp- PJ5KKpzH'h?ӅU3oVp;@( w^A6F-YϢ_&0]Uv-uU24Lz_k׮)_>K%w!M1i8sOl(H&-à DA+- 1< b.ἡkp:@ |aoQ̤G[gu csj/N. d2Vq$IK 4DPTXH-bݐ-7S3Xn%XcyCa ؎YWY`:A/,y]MKpcb~}6 DID&A|41㋨/XpbY #px1y8DhIoP'O HREueG6l 3,H@2WܹSRQW`Yk\af5 Bα-P(:Od;(=W]\a Lԋq0p8 K,)Th !zf %>T3*Plqe].?:PԘX&wܹ,!9qرhAʋ5]&H )6O=mnnfK*{:;;e&bݎUƵ s'"^ ώu\ ΘlG`8.9A"}.b:8\ՖPRiq+hZog>{s d؞S&躎d,mkt:y.»,n'NP.['X&X(HS4d"@#vhYH!E;#12CrhQJs|3HR\c.*w1Oۮwۋ}̤U901T0LBH\\s8ozxùq:o#HN[.@8p9IHƧK(}3%11؝5#ЇC/pE%}梢(8u8G5' %?\IUZAh\PTAbڙ>|L%?/j䅬ziň&pd۴ϵ؝"/F7W FLq87\\s89;%|N?߅&'g}A[,"1מ;G[15 $&͜lB\xKm_[5M;_[2co"$AǍ㖉Ӄ˿, OnsP MqX+v=g$\B c,2eLyyf]ב;UsuA D\}V13qy:MFV->'||?ڲ4f}a#T0\yS:>#CNkVCMkX]k+ ]Cx/́Ԓҋz-D4S?wI.\Tp.c\.W#!ĭ(i%:Bp AQqmWF8{p 4a(y)OjI8l(VL%lv9F^IRxxCiSbN2tyC5sC)=8%Ua؝v܏'Jv͚ܺ"cB\fY}"ΑN޼O~b>W%+R[:;1=zw}3:oo8iyf? cbү`whˎ  'W.$D~$ Kr15sB!⺲|fe;(6ݰk\Y`> {Q8y%vLd#<.$I8p\ҳdWfwjt̡:.\뿶x]tX}i"8omxʓ-9DzK/]D$Sp㒫\z.\DxsTkuݴBBPZ3 y1<0 ]1BW T"5 %t)["*P/#ӼRڒOJ(6?Μ9[$ItuuaΝxe(d,MګWGm \bQ2 zvH|¦Aז*Mΰ9fיR1\BZ/p8ePJmtE]3wq&%w#H]d8=N5ӪS"PCo022'OӦ=-8a '$"%8`2 ~zppHt_~xW̩[^W{"`X{*+€T"\C"Ɖ KA@hƢY;ORTGùL!|>2x`UEE*F7Iw3H9$4}Vיt\r{_!6*!gP(A[H9y'|}}}f׿uj|.۱/=- IDAT#suZ<1iDυ^dRL氡& Ⱦ"Jey/VcеNy s5sdp cl>W\^'v=W|ł 'c)0Wo[1#VZ в_|>_Lz]zUݻQ]mկ~e*jN+kpD;c$$%5]CC)((-MO9vzp2ucIp8/ 刪J4MB( !wv>9iEaBKE=LT qޮCYu1f\uܹb/~‹׭|ӛ6,535U`cqys mFxš6ojĪPX *P8Ք ef$vc?~ޚipr\PJwUk.IsES5xntaˍ-bt(!c7mX޶"'݅DaFP/ST*.F pp_@2I:zEeHu$U @>CÇё̗ו!!MB(PgJ ( L#D,]ۀ3FIM!;mbY4+Ԕ8=Nxnr=G(=nbǻ0:n24QgMaù !X#YŻMdaw1ӝhXU;2ľ3fU0\/ա|A/.;Ɍe#Pm F0pi ~u@0. 2bÐ *11KX+}}}OZmt1tN\S *RA&B%cyjzlB(@,`%%t&_eh=_ J F4<~7V4ѓGp8.9 Yu$t@x^;sK"mȀL3kb jq@e?ߚhAᙖǞ`aؼy3>H$T*e>$44$2 2 48EA&ABNAQ 5*4[( v @!g PQt;@T<9%t Bj:%3ބ|.GpMhK c0G$ +הR>ù ų̀%Ey;GΖ {3{$sˬi:N;m.W.)X[Y3LAre}ݰl}.AQ!2dE"+d2 2ht$RFFFH$? G/ 5&R`Y@E &s.BIl.AVҍ;/ 87҂֓h\ tڄB*Ip8\\s8(^@yx+%UQ1<0 YG]8fDI+WEI@IU5 .xʽ5d T\n$IDX/B@뺎t:mt*2RѨ)GGGH$L&H$H$,UT:eL{(h,fًbTsqƌ7?Q6 P[\ʵm!ee!H$ubOht]!Й%Fh>r\^L++67k 9x`{^?xf1$)0 JʪxƟ)p\pą1sU5Me𑳱+f5=B< z4E4E",\Z w Nx yA! o&UkHP'ڇyù6o]QW6'a`:g%s2=B݊yVoljTܨkrJjTrF`ŵ=}!ÿYV^(h=Ӆ_'ίMYe:ÉכqS( rlqN!ƤIA64]gPd0( mcyKe0=rUt:X,χ8vNƝ+jAЂ&pDpq\F,].[ϟߺl",,!f7EB6߸~^!p|)s]bdϹ\{Mհ#Q?6v(LZ4'_uMR>m|"?׸w"Ͻۦ/?gUJ3wgY7? ٯN'Cu E&v£z8ep8 ZB[esr !աy?cFPdB3sSb"ne*5dbL<i}rLh,X^/8;{L_ "F#wEXҴViWnGwrDf-h}Orh 7~6G#''@2ཌྷGSEǛ dPi7m%@׌ 4477Ypq\4554E'HV|ΐN}}ړ&YE۩syaTBf̤xI1h{MHR6sᲛ|cAx{0|ӟ8 3kES5vǩm0?G[&f,=UcV|m*JL~d|d_߾{*TEE2“?+8wwOD֏^M5b&]iC<Ot@U Ɔ#P+O``ș2:jT/֍t)\ !/_p8[,;T*? YTYđMBt֓ ז}Vm[/5}aAiڝ&nEC=е|iJTIoRYW>7B"`'RmiU_quP~@_Ȥl5ܸX?~k~c k&g?+Gbm_`t(fw;%沪j3w [,0̆Gaɾ'atGk2`Vp8 L;>ׂN'3dFDٵBKD(f.ƞm"\)+4uUFyo' T5 1FPU8]< `1ᯪjFϯi~w߾zt7qbz|jB?;>x5:[zз,kU/Hv[߷>tI'v0܊Mʍ Ȥ ~G( <>~[pwc$蚎T<0΃ k粁k͏` c L^V-҉9 C]p޾ i>la=v?Y2WJKpd̟9^9i7n!rxݢ(W_D8P^sWZZ3@ ANT%߉t*8!XmVn\oYeSNx\ᅣ(qC5@wq5=+412xC3@~Bbj 910_󦃋kMN}}}5c,=?ualJ)^ n$tUC&-#NI`APbo=u je:.~1{HiiD_5ՙS>b :7/W^yeP(χ`0@ `0ߏP(  enffA$Q͎ Qۻv2<*++M`-!ToI ;\0BȬn"Yq*}'=ǑayC)bv@-(Qd5.0I*3 sPZSUh?e&ĆxH^lǁ Kp`1Q J(Z ͸t?^:=MkQXYt׭ P٦;fi3h]g`t*UV*TE5~V5( MѠkj8ذq UѠȊ>tt! ! sk y mVE1 !$;'tvr#ٜM,I !g\s8\\s8orc;!HLE&-#6'3̀}O·rgģ<Xq)Nw 7=waMpXɍ]xVz^B0$XA 77Zk:[z!HDI4}ҔRP dXd!} f>4]h;Ձdj .Phr[>wYp.#o% x-!JY,d-I!\tdR2t]l?tjm/ܹv8vx.BP v2ptI`õk&<~7m\ {HJlp2bXΘ9NFQeW\qTUE2D&,ːeJZA"iEǘ.]eЇT<EVZ) H2"ihp z8!3*FtX6ECW59-CSEUTF"0k{"@!H¤\,z[>{{0Issw6&$!A 068`p~_lcBFXBIH(+9*GuLΆٙ]3NW_M;5oB8QZB8@4"7)ЬYD#]$p4U\Fsࡿgyl^#`H23kMpFO{]q}Ccrdگ/?܅&4^Wg4-[p]L&CVVQTjTU* jRDRRP.)J-199IPoAVZb8x3+fi.@% R1B  /q\lfbx qIgȧyh=hM\# \k˴Ņ0 CMhT(^A(qP\)[:S'.>d]p @XGl[ 0<*oGIϸ:*򪓆Nz,C3I `x׈Zϱ\q!W!iH'/ k7n˵=H$D,\.GZ4M/ b|>OT Ţ|cFyH/vЬ5kބ&Dc"@5h=`uAPFӵrk^&mx2*l!ɬo{ETk+)ea]@8Meۧҟ|^Vt<ìZ#AA˴9v` qNRv<ǟ0سKn؊Vۦ2\epG&}.^:Ա4W2m˓&\cWx MD 2/d!-$>ǩTT*uZz$.?4-,2E_y rrٯ7*Jܟ3ŅEձ^nߓiҕ\}"oؼ'RJ'ϫʵB BkEӴBZ1eölP$D\F=Bѽ0k^;aꍾ`R㱗;4$P#`l ?S ]֡gߏlKp͗;R%-1n"r=íD"SسAhDg;Eut]ߑ}hhh:RJloM4M۶jX4MgX$vhrr eY!ؿ?^Y*ҕFYYh^`UBqĵBq"x 4N4q*p {@=F`< ۾WJ u]e|nOLI?nnJJ8_2ڋ֜uhƶwP̕90>;؉ IDAT|-S= CkvryֻlٻˁUotu9hI̪EXa%|q|@1WG^h77q$ 0\.T(1ki cx6_aHӡ{-ld϶ !#B42YymqBQy*zt7Ï3ޓɿdc]+B3oī-ko L ?FvlD77wXU=?]frKX/|߹i =ڌRBq^ĵBq288*\߸lߠkMױy1| lˡR&;xv>ű1JM^%7l! 0vxvECzh˴1kibc'$Ց6I.]4,HN{⁍M6G&)fKT˵Fja+҄幔s#zNy@׾h~mJPV'$ֺr680o=ёRJy7@P\po'BqVu5B@\n[/dF.MMs|וN[W Bt]p[t2Yfrئ b}z,T폾U|ѷ,W!߽m/gr- =I+놡{QҋgMBл#hp#OxOxz?t\wە<& _zZ4s_?ѱeic 'Qf#(Bx6K0B(qP\`,oݳkYk,*s jK{oiî5MCM_\y~sg]7=k8:Ev*}6&iie5I%Nilw]7OLSbD{oMF%}ZJl1Q.WO]U;1@h:Cyz'?/<$3ǞGjaש켈Ko䎑>u3'Nzy𯮤Zdz~$㩒xAvkn![: ]PwQ)f忝 :!QVmZ"ąnX]hH=/3Pd15ҕC= v1qtf:.SL#x% Dkkp%<<%2DaZ:ɀ,rm:U#_nT8]ƑH̛8WFee۽ffl?;.n`t}H /ۍ$zi<ߧI.WvlZJ0 ~2QOqklBqAĵBqi9Oc˛ \-| ĺcl Emg} ؄pĥWID746гxtS>^glK05N7]Gwַ%M-ԈgXjqzM3fI#4!E+VQIq V%UcE_ݴ|RJ\/B7);mrr(cQWlŅl+R:dǽ\pM?̌NǾs6'tS"шRV,˪h; Ckvh['Z7YM5 :R-{m0Ӱ躆Bqܤ.@R̕}mQʖ8:EXanddrdr[DG_ۢoC]  >&2c{={ |ьF0A0Fc ]^%lʫnh W ׵42eko` ccU9?P sś?Obn{I$̌>W@{s/|4-W}K?N0uɒOh\ᴐу ;88eئm5n ә) tn'sNn"&HL&I&R)$---qK$-iF0Ɔk?t%wQ\ zd(YBt tҏj62#T(+ B(z58>ߺP\n:Ci~L[#l)D8>yꈔү\ϰbB::lz˴;4Gwruim=ɮg:.3Yʅ F zH#`^vrR.`/O$u,۶?exǦP*ݛmn aBOO/Γ$Dx"N*UHx؜q ʸV(^(qP\ !n|FW夑=].IKvk+c5}9fW>AG3u=]M"п=3>n64cccdgHOP(4JR<;UjZ]L{q~6RHaz4M($h ˴8#ul\XLs۲j n:.:.tJJZ?"Qjh5֮nKJiTUʕ2jl6KRvX(fr9ffffzzliۙ,"{0HD%FO3ojOv0$;í_eφKxC;9-{^˹¶lTd{h(I!s;:BZPZB󭍠[r<|\Gg#s_z \|>OX$S*(E*JS!B/OR) x q\̊4|1v˚Us2tB ŪAkG!4[/o}de `tp-eC$>44KQEI)rd&Μ3m:aÜ纭ʂ]P:2o~>N.g;+m-*Vt\P=o rpg mNa/aKćMe13r/ z吷Oƭ\j1TLn½<$Z0 HF wb[}nے\??ֈKRƸժ_ N355E.4M^z%o(ytiLm8%!|iP(.|V(s4M{7@0gRU8@$~kRk89`CTضJ>U[\)V3 %v]LdCbi[哿ᆯ\r裄a>W)#L&=7QD?tγ҄qoxpow{==WF7y᷾?=8G\כyB} ߽棌? i;C'⽑[ǬԦsXΛS@K>y'Mfbo/Ǵ2&ӆt%e# I)m@ WUox'X+ bߺL2 +%7[Mm=K[&ɓMm췔/Q}pz)Ttmc9*&f%vZl`,Ƈ+wuoqK aI.P}/L:SwuH\g ؞O u p`2YP4vL  99i;|M©:HOԯH% Ҳ)"yZRRZ_::kZL<}cٶnZHl}G~~?! V́8ɱgь .P(^(qPض}a-Z}zO֙cVMjs&qѤgV9_MBt鱌Dmn'GuλZb\}| gm3z,cWe>Mr62RXO$_<{ۯ-ž/ˎO}_[_bgz(K3`+L<`*/k}D$6<[I8o u[r.g̡th f1?o09xqL{Wh8 bĵBqiOb%D7tZ[usu d˽ЉÔejUWM|)Y۶`_P'=6,$BbiO h hXh'pŜ-H3]*W9oN09n׮cĀr HOO9ՇG_`flɑOxcBm a` vSM(LPpo]$kq3hu[O=v.W|i t"'e2. UteSg҆4ѕBXyV(_4M~Y[s*Bx^kmO%F,#G '9S߶T0vh#`Zl\Jp "8MsebZiH 'rzraI!IqKll6+e?xpw+B^\C:.C$FF IDAT (`ݷp~<đOxˮ!(ĵS5qjHIyd#lt O:_sɂ̬&E>^ W\phd zw>a #+<4B(qP mxp\.s? MCf{O0ɣ 6qt(|LBï-<F@' MF1:`P$4f; /C۱]<~"ڬDĒR%2/4^uiY+Qގl{v7TM7]xy)}ӴpקV4[w"PG# ӎ/fofݏkA\)׼g-#tvɛZMZF"ꥁWw`D0NjND"ǶQ7I={Gv5OԔݕj~<9u03_[t%BqĵBq~"?-ϣ(P̕I>fo4К&S"7b.QRԨ+URD1W";Zff @z5](ec[noOuN3NMIu$ *5䟾|˴L"'8Vئgq1qrO;s-4/2?tr|M{z(@bӀ]Ee,<D@ p&VfݚhU87\@-\n߻vjݧ/2<:m%>9״/Ls@!ּ`zj̝{{W8Ox @k^IbS?kz^! i+?ϯz{C GxZvF^HF^[{YOu9/_{r ~bqH!ğ_B2)8٫FɌBGVj< bu: )iG-82uRa rC݃:C>!hh^= q [[vpMזȚM{|a&Lzf˶  B6R!!q\`cǎZC,vzyz$>wҦ\tϻkwy[nmM"e󯼝_yIlkv/cWjC/CJr6 F$D{ CSoS<8 HУ!b()@\;G EWR(V>HP*C@?1ٞ5?>yX5?x|/F[sϺ1B+n>k䕢R?1;YRЀza mN,t%{KGm?JWW}}AGGҒjx"N" vt]B״UGBQb6ڴ't#`KGn ԯlݼѿ:k>4?n&ێ2 \hIRAOZ{_~=Bm=ٕBX9V_PCCC !jZSJڭk~~u%`6JRX V􅦔E|x~#O}gJ͛8[Enht5A8+մ !-)z7ifaV6i399$;w.O4bxxߟHIu,v>KFy7ːu\O`II $89=YfbV-jUjbVLeئO4kr mΎN("LH$HRR)ikk.:::|D#px۟K\ƩY8Z ؒ@.o| L?2#8i\˦W`7bB 䖯@oj[GP2PZ80J)Ǵt$$|@1[DfA(RO4RL=*)Bt׎88 zZcOm^F0$laq]יY]9eSEy^U(O88F~!Z[[蠯:;;ꢧVHR$I2D  /Ƌ/_g11|%)$=G\79pƣP(VJ\+6l,0Y8.Ó'>"Yq-4dl3BxW s"Wf7ru\Oxŷm:~2m"nZ5O*&R ۴aff}--a5I$Kww7}}}tuuUx^[c^ֱJAA${m.ZW٧JÖh5ЁJ 29*y-aו 9<Ƶ]dcRIo_/==twwS>iX,©w4/]JYvg$*WJ\+ R͎`YUDRQY5 GC'8I{wlJRR.T8s#Gd˵jGIřB.[dž[J۳U#{1C8but'-麄"+#;5o\JJGP.߲B bppp} k۶q_ljXEwdg ϺלU!%]Iv*ǁ33ŶGi.dӕ8g  ?b292)&xޖ7:xjFztɑiS٦I 7U1G}ڵk ش+;:BPZ8ذa= 7QP-|5_&?U̪sآ)$BuM$'Kk[۴9sG3\^u^[FɄ󉐮df2KPu]v=o7_=D,C5tC'  ?sIڬЎ%WbG8I׺uhVrSSS;BPZ8zJ񪑑U/#rozurѫ.ҕ2~t~QˈX*+6еc.;He|> r3~'oMtyT1]JɁ¯y KnJP+u]Q&LQ.TR%o[h^JIkW˪ddJn1n뺌 )JVa6yŃ~ڜJr."]0XpBX%,BCCCO !뷎Ĺm7fdd(ûG'_ԯFP+Ym2Wm:iY 5OrMo hTsHej1X2JG_;$[hv'ӮDf\rhrL kB1%UmWjᎾ" ٞW_x~CM˅C!_7޺ K3TyvC/3{vNnk+_^eVHWKU&N{LznDbaz[^I#4VU*de ՙQP, *FW/WkWsMb2>J؁16_=D%FlNLmf)% d']ŬY29,YH!R):hi%:?ҧʹصJhH)Klv$*W *GJBn4:uv>or٣]GJ{O|'}n|`;n{={fhݺ Q!7]/?=P*a{iL?ԋkHRJ\ץVSj&H"B[O+]$o-J`m"3Y'a4&3IӅeڥB8OQZX!^O5XJLv*DZ\r[]gt|=|Gh=|cin-|w|kXsdrr%l'k)%i33%7[h>ߠX*{>HQ>Lx|h/E>OLC/!Ց+I̚u“%!A#Iz^*bQζv]Iv:ߏb8ͳBqĵBB8s}=a//iY?/y>sϯ9W ׿7G? {)%٩٩܂ Mkd{WU V¬xB!ⅳ BqĵB?B>xZMcH8~~?x㻶_; &6*t?Ak4&<8S(%Ui4W BoiK卷r-l̇ /]%2o}inQ6elU6) / Z|-BJE}+u@SteS+)%ûFŸ꽔_?Bg 빤 }t)a̜JJIf|@{|!p E}+4_RZ`)abc;u|P̖UfO(֯ey=g?_4?CǟmJ\Y ~sZklv㊎ęX5 !c)j{P(Dkb322r o0v,ƾ*L\6C3J[A!l۶ޚ2) Yz uܥۃ76=aCe\wI]wBUdz;;l,t @ԁ̰h-hnobE!,˅߻d2ٿ#,i皐em,\[[: ]Q/#gߖD2'kjcx7RA@ q5ty`]+VcUJT@*ya'Y2-.uM9EAY(&dI&_j{г:.ܲ);;>P= o\xරqKBr=ĞK167=6a{z>YBP 5slIDATdp!dyBx<]qw$% ?~ uvLr,-~'v?$.ti?h!?ޜ:^EB`g;]uz4IEQ Ȥ} ?:BrF5!P"⣱XLZ$̦rx/`otG8?2ʊߏ o+m<>s>t-Y7o|:sI{ۑȼ_,oE$I`Lq!PpMrUѨ/m[6vUޱx#!L}cE,SNјP*c (koo B)B5!gc7x %5BuО#8Fwý#K+]j'd%*R@j`Al\.z:`!Ë5&BC5!g.-oB|*5k * $wHdяHNJL67z,\4r/<E~$7>FݘyVUlo;;3ƃ\ 0Ua^-RpոW ?~|!q\rH&X-صb 455GoG?#2m vz gJX4Mqp÷<[l۟Da{Gt& dGry(86ur[@v */VE!d٢sH<7ě,Z]]jkkKJ'-$w y8LÂmxYi lsߨ([Q9'q?}];?/Hh$R<X9'sg^yv !؝H$\B! 9q !v*QYYyʢ* 썣-ee~#{Wr `n&zl܀]?\riYx艟?2ϡb@.8%6dbC=صE t zɲիWCa c!3Dm9G||7kCP4¶mfQUaΡFB@QC6O +rI otɲor4Up L=i@˸Niow=X.%4ԭƍ6oq|;xʪW`Eelc2r/qpg_ݧ(~˟l 4]Gٚa_ǚj\|97-#y8z{aV7/1TUUVc2'\B< |1v#)JahhsD?"ea4BPUPx;Q~D#YZFPwC{zmŷ2VGn{mOõW_5snftw˼_\ 2,h ~w@˲:~!vr{zz'ܙBA>.sEͭod}?!bll ###%A ң*VA0[np A@a!2Y rQ7K ￾Yr#~uAkظa\\Z (R m;0ua6m8\dF$!aʕ`ٜ?V! e !B;cRL& EpTE][- :\K7Qrb;d/gsu 5H{-}wioi}=λb\k9~½m,gvm\S .`&Ri M)j ʠjh4k;;;'=BfkBȔp/j!t] va!"ږ(!*qr_;|}7|e!j/+7c7(z^? `MWw(9,ӂeڰ-݀ pν}sNph cHda2jTI!d2[%: !$ !R__Rc1Z4MCOm1j&;0n"О^WK7ngqz WD#܎ʕO"+i~ \ PT=8 Bk6Lt3͖p7h"9RFGG>caה!U!Jھumxo" vPmaa0 dYMӶ^Fa N?  9.vWw^ӆVFKމ 7s S)Lj-f"!;niҒ$# AUU(rdQ9?0M鮮 !dN(&,$}B:iڔLbP X0jvxdq+{0ۙ.KSU555`ecxK/Kp3(n@I{l}Gmuͺv/в:2Yw¡ieEQWJ^|t1Od===yZ2;:!d B6;J20vj7_k`&zp(ӿٍ~WQQ20v[&+Ӹ`00qȱN(8gzVGAdƲ^[|eP`@咮1@: WBg$IsRkBșZZZb#1pK62 4LӜْ$ 555PUv[ ڎXL&OY2 o~>qǭ_j]ۋkn{$aekO.XBllJq cʛpP@,Zq!DA/8ڶ9Zzr(eY1ao`ɀ!,cK 1rwwאC]M5n{6|w֧EƯw P3Z"IC7, t|yEAyy_!cB!^f'2 !dQpMYtu`|@1_!`&lBKp +UTT@UU䳦7'&ڿ`)4)ϯXP+/ڈm[%ף|Ds |#sjBu.L:tlǭ `X ~iA!;!%d/"!E(&,)mmm1!ĵnb]@WNd6,4Mj 'EA @0{8;vo1lƘi']g"$!P P[]l޴l\X ?ܱJĭYkAߚ;a6- v]+]ܽ# " y;NZa89߶;;;@4!G5!dI|u>o ]secXYa1 !>VO+O_Qz E:v[́'A`NDK&1d-\[wv`&C3`,vFBHOup_NOn"h`Bɣl566V|{c̆;)nTqs1}lXf>.A=Ӳ,R)diu: /fX\*l*=g+r1k&`0u8 1/mt](L$21 !djE$cpAu۶UgK>iF1AbdYc&)(pBē{!ׄ23RssZYoBkF~bR۶a6Lӄa,R|O'gye$AQ/.ϓL ! xFcdžA4! !dn:I1I젓\.ޒeYF$^|rp4| ?9?9O&cY!dPpM!kkkc3c$I,hcBDc`18L4nǑN'Dڀq>~qN8J2ф((&3rY:BDž;cG9l6@]:!dIBիWWͱT*{hh("B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!KJ2:oIENDB` PG-4.5/images/README000066400000000000000000000016101426357011200140140ustar00rootroot00000000000000$Id$ # Image credits ## Icons and button graphics Most of the images in this directory were made with The Gimp and Inkscape. They were created in my spare time as a donation to the Proof General project. The images here are released under the Creative Commons license, see https://creativecommons.org/licenses/by-sa/3.0/ The Inkscape-based search icon includes portions from Andrew Fitzsimon's Etiquette search icon (under CC 2.0). [ Inkscape-based icons forthcoming ] Note for developers: the sources for images have been moved to the PG graphics repository. David Aspinall ## Proof General logo The 2016 “chibi” icons were contributed by Yoshihiro Imai (http://proofcafe.org/~yoshihiro503/, http://proofcafe.org/wiki/Generaltan). They are available under the CC-BY-SA 3.0 license; for more information, see https://creativecommons.org/licenses/by-sa/3.0/PG-4.5/images/epg-abort.png000066400000000000000000000004631426357011200155270ustar00rootroot00000000000000PNG  IHDRw=IDATHT1n@=#~)""%J/JI}gP!infv6c"1q*?j%HR v-NQRk5&̘ lV6Sěd/Fw&UB 4^F;8%HBy袻_5H /γYp6 +htoa}W,Wy9ȊJ"jy`TH$D$D|n*g|>EGlCK[IENDB`PG-4.5/images/epg-abort.xpm000066400000000000000000000016141426357011200155460ustar00rootroot00000000000000/* XPM */ static char * epg_abort_xpm[] = { "24 24 12 1", " c None", ". c #870D0D", "+ c #E1C2C2", "@ c #860C0C", "# c #FEFDFD", "$ c #CA9494", "% c #C28585", "& c #FEFCFC", "* c #FFFEFE", "= c #FDFBFB", "- c #FCF9F9", "; c #9C3939", " ", " ", " ", " ", " ", " .. +@ ", " .. #$@@ ", " .. #%@@ ", " .. &%@@ ", " .. #* $@@ ", " @. * +@@ ", " ......@@@..... ", " .....@@....... ", " .. #+@@ * *# ", " ..=+@@ &**** ", " .@$@@ * ", " .@@@*** ", " ..@-**** ", " $@@* * * ", " ;@ ", " ", " ", " ", " "}; PG-4.5/images/epg-command.png000066400000000000000000000015341426357011200160360ustar00rootroot00000000000000PNG  IHDRw=#IDATH;l[es8>NIcB!Rڅv@\Hܶԕ!V6$$a`JD*C($-ni_J b˳~~WqE;N>}y 2lٖJqAF *H їRwDq:Ξ}:55̓']tϾ:U̗k"A4$ #@Ð:*014IP(yeܽQJA*ADZJZ ;_e=T&2t=%C)D.ciUaQB XX eNϗBWڛwz}{r4K\7[:c,JAETorN)бs&m; Fl-![ uf׹\ck."ϝ*cIa& U>*7_߅EN8X>ǥ&7q!0c m2bĩBhqr=V]qX%@l7 {T֚[0Pdθc|:Ono?i{aP՘.HfJEfF'X5=1FrdQA}lo)Qy{t$3tv'eR(*U $ &'_^%hT䃷>~}]ڼZc9kT U_7;Qſh##vl+vkeNHҡ\Ǜ8kr*~IENDB`PG-4.5/images/epg-command.xpm000066400000000000000000000105731426357011200160610ustar00rootroot00000000000000/* XPM */ static char * epg_command_xpm[] = { "24 24 198 2", " c None", ". c #F0ECE9", "+ c #D0C1B5", "@ c #C39E81", "# c #A37451", "$ c #966B48", "% c #A97C59", "& c #BA8D69", "* c #C09370", "= c #BE9473", "- c #BB9476", "; c #BD9677", "> c #BC9678", ", c #B99578", "' c #C19F84", ") c #C9AA91", "! c #D1B299", "~ c #D1B59F", "{ c #7C7C8E", "] c #A5A5AD", "^ c #E5E4E3", "/ c #E7E3DF", "( c #E7DBD1", "_ c #CFB29B", ": c #C39169", "< c #D69766", "[ c #D99966", "} c #D49563", "| c #CA8E5E", "1 c #CD8F5F", "2 c #CB8C5D", "3 c #BF8658", "4 c #BF8659", "5 c #C48A5B", "6 c #C3885B", "7 c #BD8457", "8 c #C2885A", "9 c #C88D5D", "0 c #C58A5C", "a c #8989A4", "b c #ADADB2", "c c #CEC7C0", "d c #A37F63", "e c #D19667", "f c #D99865", "g c #D69765", "h c #CC9060", "i c #8B6241", "j c #573C27", "k c #64442B", "l c #533825", "m c #4A3E37", "n c #685547", "o c #836753", "p c #745E4E", "q c #765F4F", "r c #85859D", "s c #AFAFB0", "t c #D4C5B9", "u c #B38058", "v c #D39260", "w c #C28657", "x c #BC8154", "y c #BA8154", "z c #C38759", "A c #CC8E5D", "B c #D59462", "C c #C58A5B", "D c #C18859", "E c #B47F54", "F c #876B55", "G c #CDCDCD", "H c #DBDBDB", "I c #EAEAEA", "J c #78788D", "K c #B5B5B5", "L c #C0B5AD", "M c #865D3E", "N c #C7895A", "O c #D79562", "P c #D69462", "Q c #D18F5D", "R c #A76F47", "S c #7C5032", "T c #91613E", "U c #956541", "V c #9A6843", "W c #A77249", "X c #C28456", "Y c #D3915E", "Z c #D38F5C", "` c #BC8A67", " . c #CEBEB2", ".. c #717185", "+. c #B7B7B7", "@. c #A6A5A5", "#. c #2D2118", "$. c #624028", "%. c #865A39", "&. c #7A5235", "*. c #6A452B", "=. c #432A1A", "-. c #65442C", ";. c #BE8558", ">. c #BE8457", ",. c #B88156", "'. c #C28759", "). c #D1905E", "!. c #CE8754", "~. c #8B6C58", "{. c #737387", "]. c #B1B1B1", "^. c #B7B2AE", "/. c #3D2D22", "(. c #25170E", "_. c #1A100A", ":. c #0A0604", "<. c #010000", "[. c #4A3423", "}. c #A2704A", "|. c #B47D52", "1. c #7B5234", "2. c #865B3A", "3. c #825939", "4. c #855A3A", "5. c #815637", "6. c #6D462B", "7. c #665448", "8. c #969696", "9. c #C5B8AE", "0. c #9A704F", "a. c #996843", "b. c #654129", "c. c #170F09", "d. c #513926", "e. c #A27049", "f. c #BB8054", "g. c #8F6341", "h. c #7E5739", "i. c #6C4B31", "j. c #5D3F28", "k. c #433226", "l. c #85807D", "m. c #BFBFBF", "n. c #76768C", "o. c #757575", "p. c #B2A49A", "q. c #B98861", "r. c #D89764", "s. c #C58758", "t. c #7F5233", "u. c #1D130C", "v. c #926745", "w. c #7D5639", "x. c #6A462D", "y. c #8E5D3B", "z. c #885A39", "A. c #7A5133", "B. c #6B462C", "C. c #3F3128", "D. c #797992", "E. c #606060", "F. c #9E9591", "G. c #A27C61", "H. c #D09264", "I. c #D4925F", "J. c #C68050", "K. c #422A19", "L. c #754E32", "M. c #865A3A", "N. c #8C603E", "O. c #442E1D", "P. c #22160D", "Q. c #2F241C", "R. c #524943", "S. c #8A8785", "T. c #535365", "U. c #2D2D2F", "V. c #676666", "W. c #C1BBB8", "X. c #CAB5A5", "Y. c #B89983", "Z. c #807268", "`. c #6A6561", " + c #6C645E", ".+ c #443327", "++ c #573924", "@+ c #643F26", "#+ c #7E6F63", "$+ c #CBCBCB", "%+ c #0E0E10", "&+ c #555557", "*+ c #F3F3F3", "=+ c #E0DFDF", "-+ c #B0AEAC", ";+ c #A4A09F", ">+ c #D7D5D5", ",+ c #FDFDFD", " ", " ", " ", " ", " ", " ", " . + @ # $ % & * = - ; ; > , ' ) ! ~ ", "{ ] ^ / ( _ : < [ [ [ } | 1 2 3 4 5 6 7 8 9 0 5 ", "a b c d e [ [ [ f [ [ [ [ g h i j k l m n o p q ", "r s t u [ [ [ [ v w x y z A B C D E F G H H I ", "J K L M N O P Q R S T U V W X Y Z ` . ", "..+.@.#.$.%.&.*.=.-.;.N >.,.'.).!.~. ", "{.].^./.(._.:.<.[.}.|.1.2.3.4.5.6.7. ", "{.8.9.0.a.b.c.<.d.e.f.g.h.i.j.k.l.m. ", "n.o.p.q.r.s.t.u.v.w.x.y.z.A.B.C. ", "D.E.F.G.H.I.J.K.L.M.N.O.P.Q.R.S. ", "T.U.V.W. X.Y.Z.`. +.+++@+#+$+ ", "%+&+ *+=+-+;+>+,+ ", " ", " ", " ", " ", " ", " "}; PG-4.5/images/epg-context.png000066400000000000000000000015711426357011200161050ustar00rootroot00000000000000PNG  IHDRw=@IDATHOHcG?y]bTzhsBRSրETP!G/"h/{)kvIڢ"h%/IS!&&yϙ4!kc e?0o3ofȇ8lL|Nlj8Fi055zhh苾ժH$~9<O>T&UUrY6R.KO3̗XBJ-Ty^._jj Bkkk7G].âatPu>xb c #8B8B8B", ", c #EDEDED", "' c #8E8E8E", ") c #6E6E6E", "! c #505050", "~ c #0A0A0A", "{ c #1B1B1B", "] c #C0C0C0", "^ c #ECECEC", "/ c #A5A5A5", "( c #616161", "_ c #2F2F2F", ": c #090909", "< c #5E5E5E", "[ c #C4C4C4", "} c #BCBCBC", "| c #181818", "1 c #7E7E7E", "2 c #8D8D8D", "3 c #888888", "4 c #767676", "5 c #010101", "6 c #4C4C4C", "7 c #525252", "8 c #030303", "9 c #464646", "0 c #818181", "a c #919191", "b c #474747", "c c #070707", "d c #A4A4A4", "e c #121212", "f c #6F6F6F", "g c #D3D3D3", "h c #FBFBFB", "i c #FDFDFD", "j c #E1E1E1", "k c #3D3D3D", "l c #0D0D0D", "m c #050505", "n c #BABABA", "o c #E6E6E6", "p c #CECECE", "q c #B8B8B8", "r c #0B0B0B", "s c #565656", "t c #222222", "u c #B9B9B9", "v c #FCFCFC", "w c #FEFEFE", "x c #EBEBEB", "y c #3A3A3A", "z c #999999", "A c #9B9B9B", "B c #000000", "C c #494949", "D c #B2B2B2", "E c #131313", "F c #2D2D2D", "G c #C5C5C5", "H c #4A4A4A", "I c #303030", "J c #393939", "K c #E4E4E4", "L c #171717", "M c #797979", "N c #939393", "O c #C7C7C7", "P c #404040", "Q c #BDBDBD", "R c #868686", "S c #F4F4F4", "T c #9F9F9F", "U c #F6F6F6", "V c #AFAFAF", "W c #FAFAFA", "X c #3C3C3C", "Y c #F7F7F7", "Z c #F3F3F3", "` c #959595", " . c #EFEFEF", ".. c #636363", "+. c #333333", "@. c #E3E3E3", "#. c #D5D5D5", "$. c #7A7A7A", "%. c #F8F8F8", "&. c #7B7B7B", "*. c #101010", "=. c #7C7C7C", "-. c #F0F0F0", ";. c #E8E8E8", ">. c #444444", ",. c #B0B0B0", "'. c #989898", "). c #252525", "!. c #555555", "~. c #E2E2E2", "{. c #CBCBCB", "]. c #373737", "^. c #1D1D1D", "/. c #545454", "(. c #353535", "_. c #8F8F8F", ":. c #D9D9D9", "<. c #A8A8A8", "[. c #656565", "}. c #CFCFCF", "|. c #2C2C2C", "1. c #B7B7B7", "2. c #BBBBBB", "3. c #D7D7D7", " ", " ", " ", " ", " . + + @ # + + + $ ", " % & * * * = - ; > * * * = ", " , ' * ) ! ~ ~ ~ { ] ^ / * ( _ : : ~ < [ ", " } * ) | | 1 2 3 4 5 6 * 7 8 9 0 a 0 b c d ", " * * e f g h i j [ [ k l m n o h h p [ q r q ", " * s t u v w x y c z A B C x D E F G H 7 ", " * I J $ w w K L 8 M x B 2 i N c e O 2 B ", " * I P w w w v Q R S B T U = V W T 5 ", " 0 I P w w w w w w w B T w w T B ", " } I X Y w w w w w w Z B ` i w i ` 5 ", " ...+.@.w w w w w i #.B $.%. w %.&.E ", " *.=.-.w w w w ;.>.B B g %. %.g 5 ,. ", " '.).!.#.;.~.{.].^.] /.(._.:.^ :._.(./.^ ", " <.7 5 5 5 c [.}. ) |.B B B |.) ", " $ 1.1.1.2. 3.1.1.1.3. ", " ", " ", " ", " ", " "}; PG-4.5/images/epg-find.png000066400000000000000000000015261426357011200153410ustar00rootroot00000000000000PNG  IHDRw=IDATHKhSYƿ{$MhR> *#'FB񁸑.Q]f3N]Uc &MyXܜVnۜw?0FbwdYSڈ<-jR|R{VY=oղPpXO_7ch| bB5q(;<4*!7^8ut x"ЩU"Qߧu 1F`>c{sV2:E«)gW0&CLt5-Mv(''$?zy's< <9 (缷PF{5 }i8fBnWEQ` ̔\޾yj)#dt X$?N#ϻ@EѫV5kfh4.vhݠ 4\6ziB(>BEQ68*F\K@۝69lph#@m,' C:p(2n0t,t]¡MrnZ|\oq0]( zn/v1ƺ&H1MSx<"[dz&k9vzkYtˊF٣@y}A|G|>ϪVl6D"pa5H W}Έ$%^ c #E4E4E4", ", c #DDEEF6", "' c #95C6DD", ") c #92C7DA", "! c #93CEE6", "~ c #BEE7F3", "{ c #AEDFEF", "] c #BAE7F3", "^ c #A5C7D0", "/ c #97ABB5", "( c #A3A3A3", "_ c #BAD9E6", ": c #B3E0EF", "< c #B5E5F2", "[ c #C3EDF6", "} c #CAF1F8", "| c #C9F1F8", "1 c #CFF4F9", "2 c #E0FCFE", "3 c #C2E5F0", "4 c #F2F8F9", "5 c #FCFCFC", "6 c #D2D2D2", "7 c #53595C", "8 c #A3D6E9", "9 c #B9E8F4", "0 c #CFF3FA", "a c #E1FDFE", "b c #E4FDFE", "c c #EAFEFE", "d c #EFFEFE", "e c #E7FFFF", "f c #D9F2F2", "g c #9EA9A9", "h c #CCCCCC", "i c #FDFDFD", "j c #898989", "k c #8F9E9E", "l c #C8F0F8", "m c #D3F6FA", "n c #ECFFFF", "o c #F9FFFF", "p c #FEFFFF", "q c #EBFFFF", "r c #E4FEFE", "s c #DBF1F4", "t c #EEF4F7", "u c #FBFBFB", "v c #99A2A5", "w c #B7D4DB", "x c #D5F7FB", "y c #E3FEFE", "z c #E6FFFF", "A c #F6FFFF", "B c #F7FFFF", "C c #D7F0F1", "D c #95ABB1", "E c #CED7DC", "F c #A6B0B5", "G c #A6C5CD", "H c #E5FFFF", "I c #F1FFFF", "J c #FBFFFF", "K c #EDFFFF", "L c #C3D9D9", "M c #444A4B", "N c #B1B2B2", "O c #F9F9F9", "P c #DFDFDF", "Q c #B0B0B1", "R c #CACECF", "S c #CBD3D6", "T c #C0DDE0", "U c #DAF3F3", "V c #E8FFFF", "W c #E0FBFC", "X c #ACCDD6", "Y c #41555E", "Z c #AEAEAE", "` c #EBEBEB", " . c #909090", ".. c #3F3F3F", "+. c #363C3F", "@. c #93B2C1", "#. c #C9E5F2", "$. c #BACACF", "%. c #7D9297", "&. c #D4F1F4", "*. c #E3FDFD", "=. c #E1FBFB", "-. c #CFE7E7", ";. c #B2C8C9", ">. c #99BECB", ",. c #A7C0C8", "'. c #5C6468", "). c #7E7E7E", "!. c #444444", "~. c #1D1D1D", "{. c #222222", "]. c #292F31", "^. c #697981", "/. c #D9DCDD", "(. c #ABC3CF", "_. c #92B6C4", ":. c #9FC4CF", "<. c #C5E4EA", "[. c #899B9C", "}. c #718A91", "|. c #4D6A77", "1. c #5D8599", "2. c #B9C8CD", "3. c #A7A7A7", "4. c #FAFAFA", "5. c #D6D6D6", "6. c #979797", "7. c #2D2D2D", "8. c #161616", "9. c #353535", "0. c #282828", "a. c #575757", "b. c #D4D4D4", "c. c #E8ECEE", "d. c #747E83", "e. c #394E58", "f. c #82A4B3", "g. c #4A6876", "h. c #4F6E7D", "i. c #486775", "j. c #5A6970", "k. c #6A6A6A", "l. c #474747", "m. c #3C3C3C", "n. c #424242", "o. c #464646", "p. c #4F4F4F", "q. c #D6D7D7", "r. c #EFF1F2", "s. c #D1D6D9", "t. c #CDCFD0", "u. c #DBDDDE", "v. c #7C7C7C", "w. c #494949", "x. c #676767", "y. c #C9C9C9", "z. c #C3C3C3", "A. c #E9E9E9", " ", " ", " ", " ", " . + @ ", " # $ % & * = - ; > ", " , ' ) ! ~ { ] ^ / ", " ( _ : < [ } | 1 2 3 4 5 ", " 6 7 8 9 0 a b c d e f g h ", " i j k l m a n o p q r s t ", " u v w x y z A B e C D E ", " F G H H H I J o K H L M N ", " O P Q R S T U H H z e V H W X Y Z ", " ` 6 ...+.@.#.$.%.&.*.H =.-.;.>.,.'. ", " ).!.~.{.].^./. (._.:.<.[.}.|.1.2.3.4. ", " 5.6.7.8.7.9.0.a.b. c.d.e.f.g.h.i.j. O ", "> k.l.m.n.o.n.p. q.r.s.t.u. 5 ", " v.w.x.3.y.z.A. ", " ", " ", " ", " ", " ", " "}; PG-4.5/images/epg-goal.png000066400000000000000000000020541426357011200153400ustar00rootroot00000000000000PNG  IHDRw=IDATHoheyݻL,M %0 K04FR #5AJrXail"6͜:}>jZ·s8\Xb 3A!0CzV {8#L,!!@Q 0"b+%nEqΉ93#&swY#dk)IV$)yiR"FHͫ6 z8}>~ש3Ps};1QLxܼy8+RSS Mp*I2R|Hr_]֦ lʌ W.Ѽ}΢Qy^jxCkExg6}Q3?H8j1AP3('br$y'ϵ>ö](ƥ'z c7`u9+gi)4]e/]榭/䣮ǼռOh[I6sTgii蠩k="-,_7[ֽ@TPv|E ɖUAMk @nh"5'Uu:qM}ГW{? k- Uuӵ.S?b;=φgcUsʱc]X'/"< 9z 4^|6894F1sr+K|M$I2O$#r:>BUNɁپ}KlDaH"$$jLy8_)ӈXc| Y<.{[TbWg8+W>E&ĉC/`EA 9|/lp{ɔfɤg#?[(`0F9p( X1ElD`"6Og "F+Wպ?BYu#8588TVA%&uo/nɿ1IENDB`PG-4.5/images/epg-goal.xpm000066400000000000000000000124701426357011200153630ustar00rootroot00000000000000/* XPM */ static char * epg_goal_xpm[] = { "24 24 258 2", " c None", ". c #ABE3A3", "+ c #ABE49E", "@ c #A5E097", "# c #99D08C", "$ c #9CC475", "% c #92B863", "& c #8ABD65", "* c #7DBF67", "= c #87D470", "- c #89D873", "; c #87DA74", "> c #7DD667", ", c #7FD664", "' c #78D65D", ") c #76D85D", "! c #70D957", "~ c #74D857", "{ c #6CD152", "] c #67CC4E", "^ c #6AD951", "/ c #69CD52", "( c #6CCD4B", "_ c #6CDB50", ": c #71DC53", "< c #BAE9AB", "[ c #AEDA9E", "} c #9FB674", "| c #5F541F", "1 c #656D33", "2 c #40522F", "3 c #4D7542", "4 c #5F9152", "5 c #659E58", "6 c #558745", "7 c #65A353", "8 c #5D9A4A", "9 c #4F8C41", "0 c #569B48", "a c #4E943E", "b c #3D752D", "c c #3F722A", "d c #559734", "e c #5E9835", "f c #579A36", "g c #60BF49", "h c #6FDB56", "i c #BFE2B1", "j c #909A68", "k c #A4A460", "l c #859458", "m c #6A692D", "n c #5C5A22", "o c #5E5C24", "p c #5A5720", "q c #565C22", "r c #3E4016", "s c #3C4318", "t c #3F4516", "u c #3E6726", "v c #447F32", "w c #478D36", "x c #69D44E", "y c #C0D7B8", "z c #90986C", "A c #A3C098", "B c #000000", "C c #84A178", "D c #95B785", "E c #7D9A6E", "F c #7CA469", "G c #89BB79", "H c #88B670", "I c #95CA75", "J c #78A958", "K c #74AA59", "L c #6FB859", "M c #7AAE49", "N c #305827", "O c #305E25", "P c #63C84C", "Q c #C5D3BC", "R c #ABAF87", "S c #9EB499", "T c #8BA481", "U c #60785A", "V c #92BB85", "W c #769A69", "X c #7BA86A", "Y c #669859", "Z c #56824A", "` c #80C068", " . c #67B351", ".. c #CFD4C4", "+. c #B6B992", "@. c #A1B49A", "#. c #8C9C85", "$. c #7C8D77", "%. c #A9CBA0", "&. c #89A781", "*. c #86A57A", "=. c #86B47A", "-. c #79A86D", ";. c #8FCA7D", ">. c #5C8854", ",. c #80C06F", "'. c #619A55", "). c #5A954B", "!. c #D1D4CB", "~. c #C6C4A8", "{. c #C9D6C3", "]. c #BAD4B6", "^. c #819D79", "/. c #91B586", "(. c #ADE0A3", "_. c #89B483", ":. c #7CA96F", "<. c #8CC579", "[. c #557C4A", "}. c #44693A", "|. c #517F44", "1. c #CDC8C2", "2. c #DCD7C6", "3. c #ADB4A7", "4. c #98A294", "5. c #C2DDC1", "6. c #CEECC8", "7. c #CDEAC0", "8. c #A4CC98", "9. c #79A271", "0. c #517647", "a. c #D3CDC4", "b. c #D8D4CE", "c. c #DCDCD8", "d. c #B4B9B3", "e. c #CAD2CA", "f. c #DDEBD8", "g. c #DAEAD6", "h. c #D7EBD2", "i. c #D4E8CD", "j. c #CEE9C6", "k. c #CBE7C7", "l. c #CDEAC2", "m. c #C8E9B9", "n. c #C1E7B2", "o. c #BAE6B1", "p. c #B7E7AA", "q. c #B4E3A5", "r. c #4E6849", "s. c #5E8156", "t. c #99D78C", "u. c #D8CFC3", "v. c #E7E5E5", "w. c #DBDFDB", "x. c #EAEEE9", "y. c #E7ECE3", "z. c #E0EBDF", "A. c #DCECDA", "B. c #D8EADA", "C. c #D8E9D4", "D. c #D6E8CF", "E. c #D6EBCD", "F. c #CBEBC2", "G. c #CEE6C1", "H. c #C4E7BB", "I. c #C3E8B8", "J. c #BEE7B1", "K. c #83AE77", "L. c #ACE79E", "M. c #D0C8BC", "N. c #C3C3C3", "O. c #909091", "P. c #CDC9CC", "Q. c #E9E6E7", "R. c #EDECEE", "S. c #ECEDE9", "T. c #EBF0EA", "U. c #E9EDE6", "V. c #E6ECE7", "W. c #E1EBE2", "X. c #E3EBE1", "Y. c #DEECDA", "Z. c #DBEBD6", "`. c #D5E9D0", " + c #D3EACF", ".+ c #D0E9CA", "++ c #CCE8C6", "@+ c #C7E8BF", "#+ c #8C7B3D", "$+ c #A2C097", "%+ c #B2DBA9", "&+ c #B4E8AD", "*+ c #CFCBC0", "=+ c #A3916C", "-+ c #C1C1C3", ";+ c #E1E1E4", ">+ c #EEEBEB", ",+ c #ECECED", "'+ c #EDEDEE", ")+ c #EDEDED", "!+ c #EFF0EE", "~+ c #EFEDEE", "{+ c #EDEBED", "]+ c #EAECE7", "^+ c #E7EDE6", "/+ c #E3ECE3", "(+ c #E0E9E1", "_+ c #DFECDB", ":+ c #DFEDD7", "<+ c #D7ECCE", "[+ c #D5EBCC", "}+ c #AEA167", "|+ c #BBCBA7", "1+ c #C8E5BD", "2+ c #C1E8B9", "3+ c #E1DCD4", "4+ c #CABDA4", "5+ c #ECECEE", "6+ c #EAECEC", "7+ c #EEEEEF", "8+ c #EEECED", "9+ c #ECEDEE", "0+ c #EDECEC", "a+ c #EEEDEC", "b+ c #ECEDEB", "c+ c #ECEDEC", "d+ c #E9EEE9", "e+ c #E9EDE5", "f+ c #E7EDE4", "g+ c #E8EADF", "h+ c #E1EAE0", "i+ c #DEEEDA", "j+ c #DBE9D5", "k+ c #CDD6B1", "l+ c #D1E0BE", "m+ c #D1EAC7", "n+ c #CDEAC6", "o+ c #EDE8EA", "p+ c #EAE6E3", "q+ c #EFEFED", "r+ c #EDEDEC", "s+ c #EDEDEF", "t+ c #EEEEED", "u+ c #EBECEC", "v+ c #ECECEB", "w+ c #EEEEEC", "x+ c #EEEDED", "y+ c #EBEDEC", "z+ c #EBEEEA", "A+ c #EDECEA", "B+ c #EBEBE8", "C+ c #E9EAE5", "D+ c #E5ECE3", "E+ c #E4EBE3", "F+ c #DEEBD8", "G+ c #DBEAD8", "H+ c #DAEBD4", "I+ c #DFEED9", " ", " ", " ", " ", " ", ". + @ # $ % & * = - ; > , ' ) ! ~ { ] ^ / ( _ : ", "< [ } | | | 1 2 3 4 5 6 7 8 9 0 a b c d e f g h ", "i j | k l | | | m n o p | q r s t | | | u v w x ", "y | z A B C D E B F G H B I B J K B L M | N O P ", "Q | R S B B T B U B V W B X B B Y Z B ` | B B .", "..| +.B @.#.B $.%.B &.B *.B =.-.;.B >.,.| '.B ).", "!.| ~.B {.B B B ].B B B ^./.(._.B :.B <.| [.}.|.", "1.| 2.B B 3.4.B B 5.6.7.B B B B 8.B 9.B | B B 0.", "a.| b.B c.d.B e.f.g.h.i.j.k.l.m.n.o.p.q.| r.s.t.", "u.| v.B B B w.x.y.z.A.B.C.D.E.F.G.H.I.J.| B K.L.", "M.| N.O.P.Q.R.S.T.U.V.W.X.Y.Z.`. +.+++@+#+$+%+&+", "*+=+-+;+>+,+'+)+!+~+{+]+^+/+(+_+:+g.<+[+}+|+1+2+", "3+4+5+,+6+5+7+8+9+0+a+b+c+d+e+f+g+h+i+j+k+l+m+n+", "o+p+a+q+6+r+s+t+u+v+w+9+x+y+z+A+B+C+D+E+F+G+H+I+", " ", " ", " ", " ", " "}; PG-4.5/images/epg-goto.png000066400000000000000000000006141426357011200153660ustar00rootroot00000000000000PNG  IHDRw=SIDATH=KP#ЛtgA7un.NiE6A;MAqbz 5|:wɽ'ys)p݋?XFzCjpnM`7fKLl}PfJ)}Nf5[lTaO!"i+51=c:@]n șdEH,J3 A ;`:> Q-&Ez6}59۽3cQ< P.]\7*|MOISC|} WJlUfiRla@yZ_'BgqP vuXv *X)~\IENDB`PG-4.5/images/epg-goto.xpm000066400000000000000000000026471426357011200154160ustar00rootroot00000000000000/* XPM */ static char * epg_goto_xpm[] = { "24 24 48 1", " c None", ". c #B26363", "+ c #8F1D1D", "@ c #8A1414", "# c #D2A4A4", "$ c #BB7575", "% c #8B1616", "& c #870D0D", "* c #C08181", "= c #C58A8A", "- c #8C1616", "; c #C38686", "> c #BE7B7B", ", c #8D1818", "' c #B87070", ") c #E6CCCC", "! c #E8D0D0", "~ c #D0A0A0", "{ c #8D1919", "] c #880E0E", "^ c #870E0E", "/ c #B06060", "( c #EFDFDF", "_ c #9D3A3A", ": c #9A3535", "< c #ECD8D8", "[ c #CE9D9D", "} c #870F0F", "| c #BC7878", "1 c #BA7474", "2 c #D3A6A6", "3 c #F4E9E9", "4 c #E5CBCB", "5 c #8B1515", "6 c #880F0F", "7 c #E9D2D2", "8 c #F1E2E2", "9 c #F5EAEA", "0 c #DEBCBC", "a c #8A1313", "b c #D7ADAD", "c c #EFDEDE", "d c #D5ABAB", "e c #EDDADA", "f c #D9B3B3", "g c #B16262", "h c #E0C1C1", "i c #DBB8B8", " ", " ", " ", " ", " ", " . + ", " @# $@ ", " %&* =&% ", " -&&; >&&- ", " ,&&&' )! ~&&&, ", " {&&]^/(_:<[^]&&{ ", " ,&&&&{ }} |&&&&, ", " -&&&&! 1234&&&&- ", " 5&&67 89 0%&&5 ", " a&6b c&&a ", " 6&d e&6 ", " %f g& ", " h i ", " ", " ", " ", " ", " ", " "}; PG-4.5/images/epg-help.png000066400000000000000000000016261426357011200153520ustar00rootroot00000000000000PNG  IHDRw=]IDATHKoexn2c;D ID*R [ 6l-Xg؁E,Jʅ@JVN38n;:z~#A;OܯyQ%nOx<2}J$HG4 Q}pkmP9?`h!5A lZƌ:.Ci,=bD# {>!x|lfytd R 3dRO""C_?P5KcбUp&w 5hMmdGbzhuE#"!Ve&*Nɦ+sGD FeUdFbQjSwl+HXtuַ+ػY(Ch*S &/->~勓Ԛ R ȲxTB(WfmobJub[[bxhgє AE!gYy &R@@ D1˻WYQT a*e1a+;yn& Kpb׭ Z\4N4Ӱ]~g%^4(VlWtUC|ϥ9  >(:!ss| c #889788", ", c #0C250D", "' c #243114", ") c #62622C", "! c #9B9A5C", "~ c #65652D", "{ c #2A4D1D", "] c #113212", "^ c #102E11", "/ c #153B15", "( c #225A23", "_ c #233E13", ": c #1B3612", "< c #133413", "[ c #0F2C0F", "} c #0C230D", "| c #1F3014", "1 c #808045", "2 c #8D8D54", "3 c #737537", "4 c #244D1C", "5 c #1B4C1C", "6 c #143815", "7 c #113312", "8 c #1A461B", "9 c #276025", "0 c #1D461B", "a c #163A16", "b c #172E11", "c c #142D10", "d c #394621", "e c #5F6533", "f c #395024", "g c #254619", "h c #3D5E24", "i c #32632A", "j c #123312", "k c #235E24", "l c #253A12", "m c #1F4D1F", "n c #123212", "o c #1A2710", "p c #313C1E", "q c #242817", "r c #27261A", "s c #2A281A", "t c #32311C", "u c #454422", "v c #67692E", "w c #5F712E", "x c #2D4B20", "y c #19471A", "z c #224918", "A c #1A4519", "B c #172B16", "C c #45423B", "D c #161311", "E c #121212", "F c #1D1F1F", "G c #292B2A", "H c #2C302E", "I c #2C2F2E", "J c #373533", "K c #6C6A4D", "L c #6D7231", "M c #20431A", "N c #123412", "O c #204B19", "P c #1B3510", "Q c #31382A", "R c #0F0E0D", "S c #20211B", "T c #312820", "U c #513A31", "V c #433028", "W c #513B32", "X c #44342A", "Y c #34332B", "Z c #2F342F", "` c #423F2F", " . c #3F5722", ".. c #103011", "+. c #1F3711", "@. c #13170C", "#. c #343024", "$. c #704F40", "%. c #5E4336", "&. c #A97C67", "*. c #8B6354", "=. c #CF967C", "-. c #C18C71", ";. c #BD8870", ">. c #8E6957", ",. c #1D1F16", "'. c #1E3216", "). c #122F10", "!. c #695741", "~. c #2C2118", "{. c #372820", "]. c #695247", "^. c #916C61", "/. c #564238", "(. c #443428", "_. c #4A392A", ":. c #BD9178", "<. c #CDA386", "[. c #193916", "}. c #393022", "|. c #1A150D", "1. c #211C16", "2. c #3C332A", "3. c #543E36", "4. c #252119", "5. c #1E1910", "6. c #2E2416", "7. c #9F8873", "8. c #FACBAB", "9. c #866C50", "0. c #726050", "a. c #231C13", "b. c #27231D", "c. c #5B463D", "d. c #B8836E", "e. c #342E27", "f. c #221C11", "g. c #322718", "h. c #B09C85", "i. c #F3C5A6", "j. c #F4BB9F", "k. c #826758", "l. c #2E271E", "m. c #43352E", "n. c #855F50", "o. c #EDB59A", "p. c #795E51", "q. c #3E3228", "r. c #433628", "s. c #B99785", "t. c #DEB49D", "u. c #BF8775", "v. c #9A705E", "w. c #4D3832", "x. c #5E443C", "y. c #7A574B", "z. c #BC8B77", "A. c #C3937D", "B. c #8D6455", "C. c #D5907D", "D. c #C29D90", "E. c #C8A492", "F. c #98765F", "G. c #99705C", "H. c #574039", "I. c #694B40", "J. c #5D3E35", "K. c #66463B", "L. c #966555", "M. c #79584A", "N. c #C48C78", "O. c #B0958B", "P. c #AC9284", "Q. c #A87A63", "R. c #4C372F", "S. c #65352F", "T. c #592A27", "U. c #291616", "V. c #442916", "W. c #482F1B", "X. c #40291A", "Y. c #805850", "Z. c #87746B", "`. c #BE836D", " + c #5A4036", ".+ c #825C4D", "++ c #5D4037", "@+ c #79564C", "#+ c #9A6254", "$+ c #835C47", "%+ c #664431", "&+ c #8F473C", "*+ c #946C5F", "=+ c #D28C78", "-+ c #895D4F", ";+ c #624539", ">+ c #533C34", ",+ c #876256", "'+ c #C7917F", ")+ c #E1A591", "!+ c #FDCDAD", "~+ c #F6C4A7", "{+ c #C29C80", "]+ c #8F6353", "^+ c #AA7362", "/+ c #60453B", "(+ c #75554A", "_+ c #8F685D", ":+ c #EBAF97", "<+ c #FACAB0", "[+ c #FED4B2", "}+ c #F1BC9E", "|+ c #8E7663", "1+ c #654D46", "2+ c #715247", "3+ c #9C7265", "4+ c #BA8878", "5+ c #F3BBA2", "6+ c #DAAD96", "7+ c #8E6A5D", "8+ c #544948", " ", " ", " . + @ # $ % & * = - ; ", " > + , ' ) ! ~ { ] ^ / ( _ ", " : < [ } | 1 2 3 4 5 6 7 8 9 ", " 0 a + b c d e f g h i j 7 k l ", " m n o p q r s t u v w x ] y z ", " A B C D E F G H I J K L M N O ", " P Q R S T U V W X Y Z ` ...+. ", " @.#.$.%.&.*.=.-.;.>.,.'.). ", " !.~.{.].^./.(._.:.<.[. ", " }.|.1.2.3.4.5.6.7.8.9. ", " 0.a.b.c.d.e.f.g.h.i.j. ", " k.l.m.n.o.p.q.r.s.t.u. ", " v.w.x.y.z.A.B.C.D.E.F. ", " G.H.I.J.K.L.M.N.O.P. ", " Q.R.S.T.U.V.W.X.Y.Z. ", " `. +.+++@+#+$+%+&+*+ ", " =+-+;+>+,+'+)+!+~+{+ ", " ]+^+/+(+_+:+<+[+}+|+ ", " 1+2+3+4+5+6+7+8+ ", " ", " ", " "}; PG-4.5/images/epg-home.png000066400000000000000000000015201426357011200153430ustar00rootroot00000000000000PNG  IHDRw=sRGBbKGD pHYs  IDATH͖OSAs()m(`c$b`FIX>#uʅQ1nFh4Q$Q0̽."R'99y9_"X!wIu!IGIU@[BeUnQL$[%+ΐ$oG7J;(/N=^&{*].k8s:BtۈV<!GO.,-E2EC{}A BiZmi<#SSC##85>6URKR=WdKD"8Dp>`Y ZUpk='9cH 0P!^mmJࣀ;rөNN"sfr^\L4ќ׿8m>U\[.w9x,mzzW]oCC@7[M-6J8aw:8<翈0 ( (朜˳kE@Hkw"HZuM+.T 6dP iYYfMMTUxW c #DE9E9E", ", c #892423", "' c #8A2423", ") c #C16F6F", "! c #DC9797", "~ c #D48080", "{ c #DD9C9C", "] c #AA4F4F", "^ c #DFA1A1", "/ c #B65F5F", "( c #DD9A9A", "_ c #D07676", ": c #CF7272", "< c #D37E7E", "[ c #DE9D9D", "} c #B66666", "| c #DE9F9F", "1 c #AA5252", "2 c #DD9D9D", "3 c #D17979", "4 c #D27A7A", "5 c #D78888", "6 c #D37D7D", "7 c #8A2625", "8 c #9F4342", "9 c #DB9999", "0 c #CF7A7A", "a c #CB6D6D", "b c #CC6F6F", "c c #DC9B9B", "d c #973534", "e c #D59292", "f c #CE7979", "g c #C76767", "h c #D69090", "i c #BA6666", "j c #8E2A29", "k c #D08989", "l c #CC7B7B", "m c #C36262", "n c #C56868", "o c #D48F8F", "p c #B96565", "q c #C98181", "r c #D49090", "s c #BF5C5C", "t c #C16262", "u c #D49292", "v c #B66161", "w c #8C2B2A", "x c #D08888", "y c #BD5858", "z c #BC5757", "A c #BD5959", "B c #D08A8A", "C c #CB8181", "D c #B95454", "E c #B85151", "F c #CC8181", "G c #C77878", "H c #B54F4F", "I c #B44C4C", "J c #B14949", "K c #B04646", "L c #C37272", "M c #882221", "N c #BC6666", "O c #AD4343", "P c #AC4141", "Q c #BD6868", "R c #B65B5B", "S c #A93D3D", "T c #A83B3B", "U c #B85E5E", "V c #892221", "W c #B35454", "X c #A73A3A", "Y c #A63838", "Z c #B45656", "` c #B15050", " . c #B15151", ".. c #882322", " ", " ", " . ", " + @ # $ $ $ $ ", " % & * = - $ ; > , ", " ' ) ! ~ { ] $ ^ ^ , ", " ' / ( _ : < [ } > | , ", " # 1 2 3 : : : 4 5 6 > , ", " 7 8 9 0 a a a a a a b c $ ", " d e f g g g g g g g g h i ' ", " j k l m m m m m m m m m n o p % ", " ' q r s s s s s s s s s s s t u v ' ", " $ $ w x y z z z z z z z z z z A B 7 $ $ ", " $ C D E E E E E E E E E E D F $ ", " $ G H I I I I I I I I I I H G $ ", " $ ) J K K K K K K K K K K K L M ", " $ N O P P P P P P P P P P P Q M ", " $ R S T T T T T T T T T T T U V ", " $ W X Y Y Y Y Y Y Y Y Y Y Y Z M ", " $ ` ` ` ` ` . . . . . . . . ... ", " $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ ", " ", " ", " "}; PG-4.5/images/epg-info.png000066400000000000000000000013241426357011200153500ustar00rootroot00000000000000PNG  IHDRw=IDATHAOQLږB PPRjAhhqC%K7$- kMƥ ? K1H +h$iDiv3.ԶqIbsλΝ,m떠$X ĵ4w|@b@l|)H=Nr<G/8ꭝ6j,@~@9,"O@1qtN4".,d僶/H犕ep.;Pio0qUspEx0,hiin`{{q xV-A~p\FF<{PUiH{&;Ӧk:ݿ#jimNz2K 5TA S,-#8$\qXӌU+JꠧA/;8LW0v(SSe *(p^Ѻɍ\ xn^,BsL(JΒJid:ނhok5qSxpx]>ӓɬ|` x4K)Uz( 4yS@|&I/.&x $݅8 W;XٲBNt4dslusT/o'2IENDB`PG-4.5/images/epg-info.xpm000066400000000000000000000056701426357011200154000ustar00rootroot00000000000000/* XPM */ static char * epg_info_xpm[] = { "24 24 106 2", " c None", ". c #FBFBFC", "+ c #F2F2F5", "@ c #EEEEF3", "# c #FCFCFD", "$ c #D6D6E6", "% c #AAAAD7", "& c #7878C1", "* c #6969BB", "= c #F3F3F4", "- c #B7B7D5", "; c #4242BB", "> c #1818B6", ", c #0606BB", "' c #2323C6", ") c #4242CE", "! c #2B2BC4", "~ c #1818B7", "{ c #4141BA", "] c #8888CB", "^ c #2A2ABA", "/ c #0101BD", "( c #6F6FDA", "_ c #D3D3F3", ": c #7979DC", "< c #0000BE", "[ c #2929BA", "} c #FEFEFE", "| c #BCBCD6", "1 c #7D7DDD", "2 c #EEEEFA", "3 c #8888E0", "4 c #0101BE", "5 c #D6D6E5", "6 c #4141BB", "7 c #0202BD", "8 c #1717C3", "9 c #2B2BC8", "0 c #2A2AC7", "a c #1818C3", "b c #FCFCFC", "c c #A9A9D7", "d c #0808BF", "e c #7171DA", "f c #D8D8F4", "g c #1717B6", "h c #7878C2", "i c #0707BB", "j c #0505BE", "k c #4343CF", "l c #8181DE", "m c #C1C1EF", "n c #F8F8FD", "o c #8E8EE2", "p c #0606BC", "q c #6666BC", "r c #0909BF", "s c #8686E0", "t c #6666BB", "u c #8282DF", "v c #F0F0F4", "w c #7171BF", "x c #0404BC", "y c #7171C0", "z c #FAFAFB", "A c #A2A2D3", "B c #1515B7", "C c #D0D0E4", "D c #3939BA", "E c #F8F8FA", "F c #A2A2CE", "G c #1B1BBB", "H c #0303BE", "I c #2727C8", "J c #4B4BD1", "K c #A7A7E8", "L c #FAFAFD", "M c #AFAFEA", "N c #4040CE", "O c #0F0FC2", "P c #A2A2CF", "Q c #EEEEF0", "R c #6D6DC2", "S c #1414BB", "T c #E7E7F8", "U c #EAEAF9", "V c #EDEDFA", "W c #EBEBF9", "X c #C8C8F1", "Y c #2F2FCA", "Z c #1414BC", "` c #EFEFF0", " . c #A2A2C9", ".. c #2D2DBC", "+. c #3E3EC5", "@. c #5D5DD3", "#. c #5959D4", "$. c #5B5BCC", "%. c #3C3CC0", "&. c #C1C1DA", "*. c #8A8ACC", "=. c #5B5BBF", "-. c #4D4DBC", ";. c #F8F8F9", ">. c #E4E4EB", ",. c #DEDEE7", " ", " ", " ", " . + @ @ + . ", " # $ % & * * & % $ # ", " = - ; > , ' ) ! ~ { - = ", " = ] ^ / / / ( _ : < < [ ] = ", " } | [ / / / / 1 2 3 < < 4 [ | } ", " 5 6 < / 7 8 9 9 0 a < < < < 6 5 ", " b c ~ < / d e f f _ : < < < < g c b ", " + h i < / j k l m n o < < < < p h + ", " @ q 4 < / / j r s n o < < < < < q @ ", " @ t / < / / / / u n o < < < < < q @ ", " v w x < / / / / u n o < < < < x y v ", " z A B < / / / / u n o < < < < B A z ", " C D < / / / / u n o < < < < D C ", " E F G / H I J K L M N O < G P E ", " Q R S r : T U V W X Y Z R Q ", " ` ...+.@.#.#.@.$.%. .` ", " . &.*.=.-.-.=.*.&.. ", " ;.>.,.,.>.;. ", " ", " ", " "}; PG-4.5/images/epg-interrupt.png000066400000000000000000000004011426357011200164440ustar00rootroot00000000000000PNG  IHDRw=IDATH1 @EߊA, ҋxoHm 4 V" DXd``vߟC}(RW%X-,^fgDɸAc \:Y~~{lȑf&syZT\sjao|[wl;X}aQ9 F xE$|U ^ya >OVu IENDB`PG-4.5/images/epg-interrupt.xpm000066400000000000000000000020271426357011200164720ustar00rootroot00000000000000/* XPM */ static char * epg_interrupt_xpm[] = { "24 24 21 1", " c None", ". c #FFC9C9", "+ c #FF6868", "@ c #FF2828", "# c #FF0000", "$ c #FF0707", "% c #FFD1D1", "& c #FF4848", "* c #FF4F4F", "= c #FFC8C8", "- c #FF6C6C", "; c #FF1717", "> c #FF8888", ", c #FFA6A6", "' c #FF3E3E", ") c #FF5D5D", "! c #FFCACA", "~ c #FF7777", "{ c #FF6161", "] c #FF7C7C", "^ c #FFCDCD", " ", " ", " ", " ", " .+@#$@+% ", " +########+ ", " &##########* ", " +############+ ", " =##############= ", " -;;;;;;;;;;;;;;- ", " > > ", " ", " , , ", " '))))))))))))))' ", " +##############+ ", " =##############! ", " +############~ ", " &##########{ ", " +########] ", " =+@#$@+^ ", " ", " ", " ", " "}; PG-4.5/images/epg-next.png000066400000000000000000000002701426357011200153720ustar00rootroot00000000000000PNG  IHDRw=IDATHc`0h҅_^k#> Є2+?AK Ȳ H ൈDCEM 2+?*3(TD$R, +' dI5x7DrIENDB`PG-4.5/images/epg-next.xpm000066400000000000000000000014221426357011200154120ustar00rootroot00000000000000/* XPM */ static char * epg_next_xpm[] = { "24 24 4 1", " c None", ". c #870D0D", "+ c #CE9C9C", "@ c #E8D1D1", " ", " ", " ", " ", " ", " .+@ ", " ....+ ", " ......+ ", " ........+ ", " ..........+ ", " ............+ ", " .............. ", " ............+ ", " ..........+ ", " ........+ ", " ......+ ", " ....+ ", " .+@ ", " ", " ", " ", " ", " ", " "}; PG-4.5/images/epg-prooftree.png000066400000000000000000000005331426357011200164230ustar00rootroot00000000000000PNG  IHDRw=sRGBbKGD pHYs  tIME4ۻIDATH= 1Ȫ(v7x ,-C+Ԣ`9VM-+:UHxyɛ>uyD1iz4H<.R bK%*R/|K@+.oIENDB`PG-4.5/images/epg-prooftree.xpm000066400000000000000000000014101426357011200164360ustar00rootroot00000000000000/* XPM */ static char * epg_prooftree_xpm[] = { "24 24 3 1", " c None", ". c #A52A2A", "+ c #0000FF", " ", " ", " . ", " . ", " . ", " ..... ", " . ", " . ", " . ", " ", " ++ .. ", " + .. ", " + .. ", " + .. ", " + .. ", " + . ", " + . ", " + . ", " +++++ ..... ", " + . ", " + . ", " + . ", " ", " "}; PG-4.5/images/epg-qed.png000066400000000000000000000022651426357011200151730ustar00rootroot00000000000000PNG  IHDRw=|IDATHoU?t3Ӗ -hQ7.h4ưи11Fݔ[W,4bHhKByCKΣNg~{*?{'9{n#qe.0h7}_ X#3[ם) A\WHE4R b8;U~`n˵Yeiaӣu5ؖ!KI6i35[3<ڲ+b=I1cE!% hЄ2Fc;qd8G/`z9}pˁ-75S) 4 6!S'/a0U@!`}W! -fIsuP"^pȟ,.-Qn f'AR]ii~ge  %6YBBe +$RHi%#Vd:(R(-R ײxp6\Nd[j#RR)6ɡ(d]6a}ۂ8ZhzLN(-Gp mCH$,ɐ0ɵ;q>3%j&\.Nٽw*`j( ,^^|j2_|(% u1 ͶϿ<wW(.P,אR#c/͔R#eLRf'_hK0][;ҰH\G2b;90+V=y:z{dxQf ɤC+jC AjMJF+a|a H-JkgǨk,6J|VK"D6EcqʎSYXfa 35'(@;4IIrN+%}ijϿIiB,%mߴ5!xqGGDJ8"ʥ0e]~LàX^`eq|A;u閷ȫ=?{〾cAS]j "Jpr;J;&a;IENDB`PG-4.5/images/epg-qed.xpm000066400000000000000000000146271426357011200152200ustar00rootroot00000000000000/* XPM */ static char * epg_qed_xpm[] = { "24 24 328 2", " c None", ". c #321D18", "+ c #36201A", "@ c #422922", "# c #432B24", "$ c #38251F", "% c #1F2219", "& c #8D8F8A", "* c #3E231D", "= c #502E25", "- c #663F33", "; c #653F34", "> c #462A21", ", c #3E2821", "' c #37251F", ") c #30231E", "! c #2D221F", "~ c #29211D", "{ c #212219", "] c #2B3223", "^ c #394932", "/ c #2B3826", "( c #412723", "_ c #3D2420", ": c #462923", "< c #502C22", "[ c #784333", "} c #B36A50", "| c #A15E47", "1 c #6D4030", "2 c #57372D", "3 c #442F27", "4 c #3A2B25", "5 c #352A25", "6 c #2F2622", "7 c #2A241F", "8 c #2A241E", "9 c #24211A", "0 c #22211A", "a c #25281D", "b c #394831", "c c #A4C096", "d c #6D8D64", "e c #945D53", "f c #512F2B", "g c #452823", "h c #4B2A23", "i c #693A2D", "j c #B86547", "k c #FDD0A5", "l c #F2B385", "m c #AD6248", "n c #6A4334", "o c #50382F", "p c #473731", "q c #4B3F39", "r c #413833", "s c #3F3731", "t c #363029", "u c #302C24", "v c #2C2B22", "w c #303225", "x c #49573C", "y c #9FB990", "z c #7C9B71", "A c #BC8175", "B c #5D3934", "C c #50302B", "D c #56312A", "E c #7A4536", "F c #DB8059", "G c #FEFBED", "H c #FEE8CA", "I c #D27D5B", "J c #835544", "K c #6A4F44", "L c #685852", "M c #7A7472", "N c #635C57", "O c #474039", "P c #3A332C", "Q c #322D26", "R c #2E2C23", "S c #414635", "T c #59654C", "U c #546349", "V c #3F4934", "W c #7F534D", "X c #613E39", "Y c #50312D", "Z c #56332D", "` c #7A493D", " . c #CD7E60", ".. c #F2AE81", "+. c #E79064", "@. c #9A5942", "#. c #6D4639", "$. c #634A41", "%. c #867E7A", "&. c #F0E4CB", "*. c #7E7D78", "=. c #4C453D", "-. c #3E3730", ";. c #38322A", ">. c #4D5140", ",. c #555C48", "'. c #333326", "). c #38392A", "!. c #36372A", "~. c #533635", "{. c #6A4642", "]. c #5C3B38", "^. c #623F3B", "/. c #784D44", "(. c #8C5547", "_. c #945643", ":. c #9D5E47", "<. c #764A3A", "[. c #604035", "}. c #594239", "|. c #655751", "1. c #8B8680", "2. c #645E57", "3. c #4E453C", "4. c #413A30", "5. c #555845", "6. c #4E503F", "7. c #342F26", "8. c #353025", "9. c #3E392C", "0. c #3F392E", "a. c #3F292C", "b. c #503536", "c. c #6A4845", "d. c #6B4946", "e. c #67433E", "f. c #6D463E", "g. c #7B4D41", "h. c #915C47", "i. c #5D3B32", "j. c #573C34", "k. c #533D35", "l. c #56453D", "m. c #5C4F46", "n. c #4C4138", "o. c #4B4136", "p. c #5A5846", "q. c #51513F", "r. c #342D23", "s. c #342E24", "t. c #40382B", "u. c #534638", "v. c #665544", "w. c #402B30", "x. c #472F33", "y. c #654748", "z. c #5F4040", "A. c #614140", "B. c #62403E", "C. c #6C453F", "D. c #825344", "E. c #583931", "F. c #523A33", "G. c #533E36", "H. c #544238", "I. c #544539", "J. c #504637", "K. c #595342", "L. c #575340", "M. c #3D3427", "N. c #3B3227", "O. c #3F3529", "P. c #483C2F", "Q. c #886F5B", "R. c #E1CFB9", "S. c #483139", "T. c #50393F", "U. c #523A3F", "V. c #5A3E41", "W. c #614144", "X. c #5F3D3F", "Y. c #674341", "Z. c #8A5847", "`. c #774F41", " + c #503A34", ".+ c #513C35", "++ c #544237", "@+ c #594B3B", "#+ c #5E533F", "$+ c #686047", "%+ c #514430", "&+ c #423727", "*+ c #403627", "=+ c #3B3125", "-+ c #473B2D", ";+ c #7B6452", ">+ c #C6AC95", ",+ c #573F4A", "'+ c #5D444E", ")+ c #573E46", "!+ c #5B3E44", "~+ c #67434A", "{+ c #905C67", "]+ c #8D5C64", "^+ c #87594F", "/+ c #724C41", "(+ c #4A3531", "_+ c #4C3931", ":+ c #544236", "<+ c #696048", "[+ c #796D4E", "}+ c #958154", "|+ c #77653F", "1+ c #5C4E34", "2+ c #463B2A", "3+ c #473C2D", "4+ c #4F4335", "5+ c #56483A", "6+ c #635244", "7+ c #795C6E", "8+ c #634956", "9+ c #583E48", "0+ c #5F4249", "a+ c #845963", "b+ c #ECBCC1", "c+ c #DAA5AC", "d+ c #7B504F", "e+ c #734C41", "f+ c #48332E", "g+ c #43322B", "h+ c #544839", "i+ c #6B6247", "j+ c #A28C59", "k+ c #F8EBCB", "l+ c #E9DAAC", "m+ c #99885E", "n+ c #665940", "o+ c #493F2F", "p+ c #372E23", "q+ c #342B22", "r+ c #312720", "s+ c #9B7693", "t+ c #624758", "u+ c #543B47", "v+ c #553B44", "w+ c #67454E", "x+ c #895665", "y+ c #90606C", "z+ c #5F3E3F", "A+ c #744C3F", "B+ c #4B352E", "C+ c #45372F", "D+ c #5B5341", "E+ c #66553E", "F+ c #AB9561", "G+ c #FDF1DB", "H+ c #F8EAC7", "I+ c #938155", "J+ c #4D412D", "K+ c #362D20", "L+ c #B48BAC", "M+ c #705567", "N+ c #59424E", "O+ c #4E3841", "P+ c #4C353D", "Q+ c #4D333A", "R+ c #563C40", "S+ c #4C3536", "T+ c #7B5140", "U+ c #4A362F", "V+ c #504B3E", "W+ c #473B2F", "X+ c #514231", "Y+ c #A28D5B", "Z+ c #9C895B", "`+ c #615338", " @ c #4A402E", ".@ c #332B1F", "+@ c #806279", "@@ c #5D4655", "#@ c #493540", "$@ c #402E36", "%@ c #3E2B32", "&@ c #3D2A30", "*@ c #433034", "=@ c #453232", "-@ c #764E3E", ";@ c #51453A", ">@ c #443B32", ",@ c #3D332A", "'@ c #43382C", ")@ c #5C4F3A", "!@ c #534632", "~@ c #3F3526", "{@ c #2E271C", "]@ c #3C2C36", "^@ c #37272F", "/@ c #302228", "(@ c #2D1F24", "_@ c #322427", ":@ c #3E2F2E", "<@ c #825A47", "[@ c #615443", "}@ c #594638", "|@ c #423B30", "1@ c #F5E8C5", "2@ c #4A4034", "3@ c #332A20", "4@ c #2F271D", "5@ c #352C22", "6@ c #3C2D38", "7@ c #2C1F26", "8@ c #291E23", "9@ c #281D22", "0@ c #291D20", "a@ c #332B29", "b@ c #7D6A52", "c@ c #645442", "d@ c #755540", "e@ c #F3D9B5", "f@ c #322B23", "g@ c #918C8F", "h@ c #261E1F", "i@ c #573C30", "j@ c #50372C", "k@ c #3D2921", "l@ c #33221C", "m@ c #28201D", " ", " ", " ", " . + @ # $ % & ", " * = - ; > , ' ) ! ~ { ] ^ / ", " ( _ : < [ } | 1 2 3 4 5 6 7 8 9 0 a b c d ", " e f g h i j k l m n o p q r s t u v w x y z ", " A B C D E F G H I J K L M N O P Q R S T U V ", " W X Y Z ` ...+.@.#.$.%.&.*.=.-.;.>.,.'.).!. ", " ~.{.].^./.(._.:.<.[.}.|.1.2.3.4.5.6.7.8.9.0. ", " a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v. ", " w.x.y.z.A.B.C.D.E.F.G.H.I.J.K.L.M.N.O.P.Q.R. ", " S.T.U.V.W.X.Y.Z.`. +.+++@+#+$+%+&+*+=+-+;+>+ ", " ,+'+)+!+~+{+]+^+/+(+_+:+<+[+}+|+1+2+3+4+5+6+ ", " 7+8+9+0+a+b+c+d+e+f+g+h+i+j+k+l+m+n+o+p+q+r+ ", " s+t+u+v+w+x+y+z+A+B+C+D+E+F+G+H+I+J+K+ ", " L+M+N+O+P+Q+R+S+T+U+V+W+X+H+Y+Z+`+ @.@ ", " +@@@#@$@%@&@*@=@-@;@>@,@'@H+)@!@~@{@ ", " +@+@]@^@/@(@_@:@<@[@}@|@1@2@3@4@5@ ", " 6@+@+@7@8@9@0@a@b@c@d@e@H+f@ ", " +@g@ h@i@j@k@l@m@ ", " ", " ", " "}; PG-4.5/images/epg-restart.png000066400000000000000000000003441426357011200161020ustar00rootroot00000000000000PNG  IHDRw=IDATHK0 D/؞$RYQ)' t  Hl2;y]wkV7y4 2I2g'xXhTI+r$(̫wh*3L aڷE.DmYpA@5?y>y3l[$Qx}pL\IENDB`PG-4.5/images/epg-restart.xpm000066400000000000000000000014251426357011200161230ustar00rootroot00000000000000/* XPM */ static char * epg_restart_xpm[] = { "24 24 4 1", " c None", ". c #C58989", "+ c #870D0D", "@ c #D5AAAA", " ", " ", " ", " ", " .+++. ", " .+++++++ ", " .+++++++++ ", " +++. .+ ", " +++. + ", " +++++++ +++ ", " @++++++ +++++ ", " +++++ ++++++@ ", " +++ +++++++ ", " + .+++ ", " +. .+++ ", " +++++++++. ", " +++++++. ", " .+++. ", " ", " ", " ", " ", " ", " "}; PG-4.5/images/epg-retract.png000066400000000000000000000002731426357011200160630ustar00rootroot00000000000000PNG  IHDRw=IDATH1 d[y@I eD"R:U@ѻZJ5x|(%xsA!hSS` !Eh Aҭx}f_di} 5|GIENDB`PG-4.5/images/epg-retract.xpm000066400000000000000000000014251426357011200161030ustar00rootroot00000000000000/* XPM */ static char * epg_retract_xpm[] = { "24 24 4 1", " c None", ". c #870D0D", "+ c #860C0C", "@ c #CB9797", " ", " ", " ", " ", " ", " .......+..... ", " ............. ", " @.@ ", " ... ", " @...@ ", " ..... ", " @.....@ ", " ....... ", " @.......@ ", " ......... ", " @.........@ ", " ........... ", " ............. ", " ", " ", " ", " ", " ", " "}; PG-4.5/images/epg-state.png000066400000000000000000000015521426357011200155400ustar00rootroot00000000000000PNG  IHDRw=1IDATHMH+W"EC"Հ ލ )-ܮ,nHѥ tSr/ .f T 5.(th%ĜEtY(}<^^{@~ WC7ව ȆezX*hXρ;< õX,&r, 2X,&p xՏ_𹪪ON[P^t]I&ߤ.7F" Ƀ_Jls922?GGG~~뮮On*{||K<f0rh O\.e, v/ I'VtIENDB`PG-4.5/images/epg-state.xpm000066400000000000000000000063311426357011200155600ustar00rootroot00000000000000/* XPM */ static char * epg_state_xpm[] = { "24 24 124 2", " c None", ". c #D7D7D7", "+ c #B7B7B7", "@ c #BBBBBB", "# c #F2F2F2", "$ c #6E6E6E", "% c #2C2C2C", "& c #000000", "* c #CFCFCF", "= c #656565", "- c #070707", "; c #010101", "> c #525252", ", c #A8A8A8", "' c #ECECEC", ") c #545454", "! c #353535", "~ c #8F8F8F", "{ c #D9D9D9", "] c #C0C0C0", "^ c #1D1D1D", "/ c #373737", "( c #CBCBCB", "_ c #E2E2E2", ": c #E8E8E8", "< c #D5D5D5", "[ c #555555", "} c #252525", "| c #989898", "1 c #B0B0B0", "2 c #D3D3D3", "3 c #F8F8F8", "4 c #444444", "5 c #FEFEFE", "6 c #F0F0F0", "7 c #7C7C7C", "8 c #101010", "9 c #131313", "0 c #7B7B7B", "a c #7A7A7A", "b c #FDFDFD", "c c #E3E3E3", "d c #333333", "e c #636363", "f c #EFEFEF", "g c #959595", "h c #F3F3F3", "i c #F7F7F7", "j c #3C3C3C", "k c #303030", "l c #BCBCBC", "m c #9F9F9F", "n c #404040", "o c #818181", "p c #FAFAFA", "q c #AFAFAF", "r c #949494", "s c #F6F6F6", "t c #F4F4F4", "u c #868686", "v c #BDBDBD", "w c #FCFCFC", "x c #808080", "y c #8D8D8D", "z c #C7C7C7", "A c #121212", "B c #939393", "C c #EBEBEB", "D c #797979", "E c #030303", "F c #171717", "G c #E4E4E4", "H c #393939", "I c #4A4A4A", "J c #C5C5C5", "K c #2D2D2D", "L c #B2B2B2", "M c #494949", "N c #9B9B9B", "O c #999999", "P c #3A3A3A", "Q c #B9B9B9", "R c #222222", "S c #565656", "T c #B8B8B8", "U c #0B0B0B", "V c #C4C4C4", "W c #CECECE", "X c #FBFBFB", "Y c #E6E6E6", "Z c #BABABA", "` c #050505", " . c #0D0D0D", ".. c #3D3D3D", "+. c #E1E1E1", "@. c #6F6F6F", "#. c #A4A4A4", "$. c #474747", "%. c #919191", "&. c #464646", "*. c #4C4C4C", "=. c #767676", "-. c #888888", ";. c #7E7E7E", ">. c #181818", ",. c #5E5E5E", "'. c #0A0A0A", "). c #090909", "!. c #2F2F2F", "~. c #616161", "{. c #A5A5A5", "]. c #1B1B1B", "^. c #505050", "/. c #8E8E8E", "(. c #EDEDED", "_. c #8B8B8B", ":. c #B1B1B1", "<. c #DCDCDC", "[. c #848484", "}. c #979797", "|. c #C1C1C1", "1. c #EEEEEE", "2. c #C8C8C8", "3. c #DADADA", " ", " ", " ", " ", " ", " . + + + . @ + + + # ", " $ % & & & % $ * = - ; ; ; > , ", " ' ) ! ~ { ' { ~ ! ) ] ^ / ( _ : < [ } | ", " 1 ; 2 3 3 2 & & 4 : 5 5 5 5 6 7 8 ", " 9 0 3 5 3 a & < b 5 5 5 5 5 c d e f ", " ; g b 5 b g & h 5 5 5 5 5 5 i j k l ", " & m 5 5 m & 5 5 5 5 5 5 5 n k o ", " ; m p q r s m & t u v w 5 5 5 n k x ", " & y z A - B b y & C D E F G 5 5 # H k x ", " > I J K 9 L C M & N O - P C 5 w Q R S x ", " T U T V W X X Y Z ` ...V V +.b X 2 @.A x x ", " #.- $.o %.o &.E > x *.; =.-.y ;.>.>.$ x l ", " V ,.'.).).!.~.x {.' ] ].'.'.'.^.$ x /.(. ", " r x x x _.:. <.r x x x [.}. ", " # |.|.|.1. 2.|.|.3. ", " ", " ", " ", " "}; PG-4.5/images/epg-undo.png000066400000000000000000000002631426357011200153630ustar00rootroot00000000000000PNG  IHDRw=zIDATHc`0RאazXb! Ĩ%R &r &J k5 iA;/j LI- R W> *cEcU,gU-@`Y4 F1$@7V=IENDB`PG-4.5/images/epg-undo.xpm000066400000000000000000000014221426357011200154010ustar00rootroot00000000000000/* XPM */ static char * epg_undo_xpm[] = { "24 24 4 1", " c None", ". c #E8D1D1", "+ c #CE9C9C", "@ c #870D0D", " ", " ", " ", " ", " ", " .+@ ", " +@@@@ ", " +@@@@@@ ", " +@@@@@@@@ ", " +@@@@@@@@@@ ", " +@@@@@@@@@@@@ ", " @@@@@@@@@@@@@@ ", " +@@@@@@@@@@@@ ", " +@@@@@@@@@@ ", " +@@@@@@@@ ", " +@@@@@@ ", " +@@@@ ", " .+@ ", " ", " ", " ", " ", " ", " "}; PG-4.5/images/epg-use.png000066400000000000000000000002751426357011200152150ustar00rootroot00000000000000PNG  IHDRw=IDATH;1 =+5'{lЮc[eZ'3+^hڶ5{/ \=((yJb֞qJ\Sdpn[ae>)*n]}*`v:#gFX$IENDB`PG-4.5/images/epg-use.xpm000066400000000000000000000014211426357011200152270ustar00rootroot00000000000000/* XPM */ static char * epg_use_xpm[] = { "24 24 4 1", " c None", ". c #870D0D", "+ c #CB9797", "@ c #860C0C", " ", " ", " ", " ", " ", " ............. ", " ........... ", " +.........+ ", " ......... ", " +.......+ ", " ....... ", " +.....+ ", " ..... ", " +...+ ", " ... ", " +.+ ", " ............. ", " .......@..... ", " ", " ", " ", " ", " ", " "}; PG-4.5/images/hiddenproof.xpm000066400000000000000000000031461426357011200161710ustar00rootroot00000000000000/* XPM */ static char * hiddenproof_xpm[] = { "16 16 84 1", " c None", ". c #F7DFFF", "+ c #F4D3FF", "@ c #F1C7FF", "# c #EEBAFF", "$ c #EBAEFF", "% c #E8A0FF", "& c #E594FF", "* c #E287FF", "= c #DF7CFF", "- c #DC70FF", "; c #AE22FE", "> c #F3CFFF", ", c #29202B", "' c #281E2B", ") c #281D2B", "! c #271B2B", "~ c #27182B", "{ c #26152B", "] c #26142B", "^ c #DB6CFF", "/ c #D85FFF", "( c #8200DC", "_ c #000000", ": c #EFBFFF", "< c #ECB3FF", "[ c #E9A7FF", "} c #E69BFF", "| c #E38FFF", "1 c #E082FF", "2 c #DD76FF", "3 c #DA68FF", "4 c #D75DFF", "5 c #D44FFF", "6 c #7200BF", "7 c #ECB0FF", "8 c #281B2B", "9 c #27192B", "0 c #26162B", "a c #25122B", "b c #25102B", "c c #D759FF", "d c #D44DFF", "e c #D140FF", "f c #7000BE", "g c #DC6FFF", "h c #D962FF", "i c #D657FF", "j c #D349FF", "k c #D03EFF", "l c #CD30FF", "m c #6C00B6", "n c #E492FF", "o c #25112B", "p c #D552FF", "q c #D247FF", "r c #CF3AFF", "s c #CC2EFF", "t c #C921FF", "u c #6100A3", "v c #D144FF", "w c #CE37FF", "x c #CB2AFF", "y c #C81FFF", "z c #C511FF", "A c #DD72FF", "B c #250F2B", "C c #240C2B", "D c #240A2B", "E c #23072B", "F c #CB27FF", "G c #C71AFF", "H c #C50FFF", "I c #C202FF", "J c #DB69FF", "K c #CA25FF", "L c #C717FF", "M c #C40CFF", "N c #C100FF", "O c #6200A6", "P c #B42BFE", "Q c #7D00D0", "R c #6700AE", "S c #590096", " ", " ", " ", " .+@#$%&*=-; ", " >,')!~{]^/(_ ", " :<[}|123456_ ", " 7890{abcdef_ ", " %&*=ghijklm_ ", " n{]o/pqrstu_ ", " 12345vwxyzu_ ", " AbBCDEFGHIu_ ", " JijklKLMNNO_ ", " P(QfffRuuuS_ ", " ___________ ", " ", " "}; PG-4.5/lib/000077500000000000000000000000001426357011200124375ustar00rootroot00000000000000PG-4.5/lib/README000066400000000000000000000003531426357011200133200ustar00rootroot00000000000000This directory contains general library lisp files. Some of these have been developed as part of the Proof General project; others have been taken from other sources. See individual files for copyright holder and license details. PG-4.5/lib/bufhist.el000066400000000000000000000316111426357011200144270ustar00rootroot00000000000000;; bufhist.el --- keep read-only history of buffer contents for browsing -*- lexical-binding: t; -*- ;; This file is part of Proof General. ;; Portions © Copyright 1994-2012 David Aspinall and University of Edinburgh ;; Portions © Copyright 2003-2021 Free Software Foundation, Inc. ;; Portions © Copyright 2001-2017 Pierre Courtieu ;; Portions © Copyright 2010, 2016 Erik Martin-Dorel ;; Portions © Copyright 2011-2013, 2016-2017 Hendrik Tews ;; Portions © Copyright 2015-2017 Clément Pit-Claudel ;; Author: David Aspinall ;; Keywords: tools ;; SPDX-License-Identifier: GPL-3.0-or-later ;; This file is distributed under the terms of the GNU General Public ;; License, Version 3 or later. Find a copy of the GPL with your version of ;; GNU Emacs or Texinfo. ;;; Commentary: ;; ;; This library implements a minor mode for which keeps a ring history of ;; buffer contents. Intended to be used for small buffers which are ;; intermittently updated (e.g. status panels/displays), for which history ;; browsing is useful. ;; ;; TODO: this will be replaced by a more PG-specific and efficient ;; approach which keep regions within a single buffer rather than ;; copying strings in and out. That way we can use cloned (indirect) ;; buffers which allow independent browsing of the history. ;; ;; FIXMEs: - autoloading this doesn't work too well. ;; - advice on erase-buffer doesn't work ;; - duplicated first item in ring after clear (& on startup). ;; - buttons are put at top of buffer but inserts happen before them ;; ;;; Code: (require 'ring) (declare-function bufhist-ordinary-erase-buffer "bufhist") ;;; First a function which ought to be in ring.el (defun bufhist-ring-update (ring index newitem) "Update RING at position INDEX with NEWITEM." (if (ring-empty-p ring) (error "Accessing an empty ring") (let* ((hd (car ring)) (ln (car (cdr ring))) (vec (cdr (cdr ring)))) (aset vec (ring-index index hd ln (length vec)) newitem)))) ;;; Now our code (defgroup bufhist nil "In-memory history of buffer contents" :group 'tools) (defcustom bufhist-ring-size 30 "Default size of buffer history ring." :type 'integer) (defvar bufhist-ring nil "Ring history of buffer. Always non-empty.") (defvar bufhist-ring-pos nil "Current position in ring history of buffer.") (defvar bufhist-lastswitch-modified-tick nil "Value of (buffer-modified-tick) at last switch buffer.") (defvar bufhist-read-only-history t "Whether history is editable.") (defvar bufhist-saved-mode-line-format nil "Ordinary value of `mode-line-format' for this buffer.") (defvar bufhist-normal-read-only nil "Ordinary value `buffer-read-only' for this buffer.") (defvar bufhist-top-point 0 "Poistion of top of real buffer contents, after buttons.") (defun bufhist-mode-line-format-entry () (when bufhist-ring-pos (let* ((histpos (- (ring-length bufhist-ring) bufhist-ring-pos)) (histsize (ring-length bufhist-ring)) (desc (format "History %d of %d; mouse-1 previous; mouse-3 next" histpos histsize)) (indicator (format "[%d/%d]" histpos histsize))) (propertize indicator 'help-echo desc 'keymap (eval-when-compile (let ((map (make-sparse-keymap))) ;; FIXME: clicking can go wrong here because the ;; current buffer can be something else which has no hist! (define-key map [mode-line mouse-1] #'bufhist-prev) (define-key map [mode-line mouse-3] #'bufhist-next) ;; (define-key map [mode-line control mouse-1] #'bufhist-first) ;; (define-key map [mode-line control mouse-3] #'bufhist-last) map)) 'mouse-face 'mode-line-highlight)))) ;simple: ; '(" [hist:" ; (:eval (int-to-string (- (ring-length bufhist-) ; bufhist-ring-pos))) "/" ; (:eval (int-to-string (ring-length bufhist-ring))) "]")) ;;; Minor mode (define-obsolete-variable-alias 'bufhist-minor-mode-map 'bufhist-mode-map "2021") (defconst bufhist-mode-map (let ((map (make-sparse-keymap))) ;; (define-key map [mouse-2] #'bufhist-popup-menu) (define-key map [(meta left)] #'bufhist-prev) (define-key map [(meta right)] #'bufhist-next) (define-key map [(meta up)] #'bufhist-first) (define-key map [(meta down)] #'bufhist-last) (define-key map [(meta c)] #'bufhist-clear) (define-key map [(meta d)] #'bufhist-delete) map) "Keymap for `bufhist-minor-mode'.") ;;;###autoload (define-minor-mode bufhist-mode "Minor mode retaining an in-memory history of the buffer contents. Commands:\\ \\[bufhist-prev] bufhist-prev go back in history \\[bufhist-next] bufhist-next go forward in history \\[bufhist-first] bufhist-first go to first item in history \\[bufhist-last] bufhist-last go to last (current) item in history. \\[bufhist-clear] bufhist-clear clear history. \\[bufhist-delete] bufhist-clear delete current item from history." :lighter "" (if bufhist-mode (bufhist-init) (bufhist-exit))) (make-variable-buffer-local 'bufhist-ring) (make-variable-buffer-local 'bufhist-ring-pos) (make-variable-buffer-local 'bufhist-lastswitch-modified-tick) (make-variable-buffer-local 'bufhist-read-only-history) (make-variable-buffer-local 'bufhist-top-point) (defun bufhist-get-buffer-contents () "Return the stored representation of the current buffer contents. This is as a pair (POINT . CONTENTS)." (cons (point) (buffer-substring bufhist-top-point (point-max)))) (fset 'bufhist-ordinary-erase-buffer (symbol-function 'erase-buffer)) ;(defalias 'bufhist-ordinary-erase-buffer 'erase-buffer) (defun bufhist-restore-buffer-contents (buf) "Restore BUF as the contents of the current buffer." (bufhist-ordinary-erase-buffer) (bufhist-insert-buttons) (insert (cdr buf)) ;; don't count this as a buffer update (setq bufhist-lastswitch-modified-tick (buffer-modified-tick)) (goto-char (car buf))) (defun bufhist-checkpoint () "Add buffer contents to the ring history. No action if not in bufhist mode." (interactive) (if bufhist-mode ;; safety (ring-insert bufhist-ring (bufhist-get-buffer-contents)))) ;; Unfortunately, erase-buffer doesn't call before-change-functions. ;; We could provide advice for erase-buffer, but instead make this part of API. (defun bufhist-erase-buffer () "Erase buffer contents, maybe running bufhist-before-change-function first." (if (and bufhist-mode (memq 'bufhist-before-change-function before-change-functions)) (let ((inhibit-modification-hooks t)) (bufhist-before-change-function))) (erase-buffer) (bufhist-insert-buttons)) (defun bufhist-checkpoint-and-erase () "Add buffer contents to history then erase. Only erase if not in bufhist mode." (interactive) (bufhist-checkpoint) (bufhist-erase-buffer)) (defun bufhist-switch-to-index (n &optional nosave browsing) "Switch to position N in buffer history, maybe updating history. If optional NOSAVE is non-nil, do not try to save current contents." (unless (equal n bufhist-ring-pos) ;; we're moving to different position (let ((tick (buffer-modified-tick))) ;; Save changes back to history for most recent contents or for ;; older contents if we have read-write history (unless (or nosave (and bufhist-read-only-history (not (eq bufhist-ring-pos 0))) (equal tick bufhist-lastswitch-modified-tick)) ;; If we're browsing away from position 0, checkpoint instead ;; of updating. ;; NB: logic here should ideally keep flag to say whether ;; changes are "during" a browse or not. This is going ;; to result in too many checkpoints if we have manual ;; editing. (if (and browsing (eq bufhist-ring-pos 0)) ;(progn (bufhist-checkpoint) ; (setq n (1+ n))) ;; Otherwise update in-position (bufhist-ring-update bufhist-ring bufhist-ring-pos (bufhist-get-buffer-contents)))) (setq bufhist-lastswitch-modified-tick tick) (let ((before-change-functions nil) (buffer-read-only nil)) (bufhist-restore-buffer-contents (ring-ref bufhist-ring n))) (if bufhist-read-only-history (setq buffer-read-only (if (eq n 0) bufhist-normal-read-only t))) (setq bufhist-ring-pos n) (force-mode-line-update) (if browsing (message "History position %d of %d in %s" (- (ring-length bufhist-ring) n) (ring-length bufhist-ring) (buffer-name)))))) (defun bufhist-first () "Switch to most oldest buffer contents." (interactive) (bufhist-switch-to-index (1- (ring-length bufhist-ring)) nil 'browsing)) (defun bufhist-last () "Switch to last (most recent; current) buffer contents." (interactive) (bufhist-switch-to-index 0 nil 'browsing)) (defun bufhist-prev (&optional n) "Browse backward in the history of buffer contents. If N is omitted or nil, move backward by one item." (interactive "p") (bufhist-switch-to-index (mod (+ bufhist-ring-pos (or n 1)) (ring-length bufhist-ring)) nil 'browsing)) (defun bufhist-next (&optional n) "Browse forward in the history of buffer contents. If N is omitted or nil, move forward by one item." (interactive "p") (bufhist-prev (- (or n 1)))) (defun bufhist-delete () "Delete the current item in the buffer history." (interactive) (message "History item deleted from buffer %s." (buffer-name)) (unless (eq 0 bufhist-ring-pos) (ring-remove bufhist-ring bufhist-ring-pos) (bufhist-switch-to-index (1- bufhist-ring-pos) 'nosave))) ;; FIXME: glitch here: we get duplicated first item after clear. ;; Bit like on startup: we always get empty buffer/current contents ;; twice. Reason is because of invariant of non-empty ring; ;; when we checkpoint we always add to ring. (defun bufhist-clear () "Clear history." (interactive) (message "Buffer history in %s cleared." (buffer-name)) (bufhist-switch-to-index 0 'nosave) (setq bufhist-ring (make-ring (ring-size bufhist-ring))) (setq bufhist-ring-pos 0) (bufhist-checkpoint) (setq bufhist-lastswitch-modified-tick (buffer-modified-tick)) (force-mode-line-update)) ;; Setup functions ;;;###autoload (defun bufhist-init (&optional readwrite ringsize) "Initialise a ring history for the current buffer. The history will be read-only unless READWRITE is non-nil. For read-only histories, edits to the buffer switch to the latest version. If RINGSIZE is omitted or nil, the size defaults to ‘bufhist-ring-size’." (interactive) (setq bufhist-ring (make-ring (or ringsize bufhist-ring-size))) (setq bufhist-normal-read-only buffer-read-only) (setq bufhist-read-only-history (not readwrite)) (setq bufhist-ring-pos 0) (setq bufhist-saved-mode-line-format mode-line-format) (save-excursion (goto-char (point-min)) (bufhist-insert-buttons)) (bufhist-checkpoint) (setq mode-line-format (cons '(bufhist-mode (:eval (bufhist-mode-line-format-entry))) ;; surely it's always a list, but in case not (if (listp mode-line-format) mode-line-format (list mode-line-format)))) (force-mode-line-update) (make-local-variable 'before-change-functions) (bufhist-set-readwrite readwrite)) ;;;###autoload (defun bufhist-exit () "Stop keeping ring history for current buffer." (interactive) (bufhist-switch-to-index 0) (setq bufhist-ring-pos nil) (bufhist-set-readwrite t) (setq mode-line-format bufhist-saved-mode-line-format) (force-mode-line-update)) (defun bufhist-set-readwrite (readwrite) "Set `before-change-functions' for read-only history." (if readwrite ;; edit directly (progn (setq before-change-functions (remq 'bufhist-before-change-function before-change-functions))) ; (ad-disable-advice 'erase-buffer 'before 'bufhist-last-advice))) ;; readonly history: switch to latest contents (setq before-change-functions (cons 'bufhist-before-change-function before-change-functions)))) ; (ad-enable-advice 'erase-buffer 'before 'bufhist-last-advice)))) ;; Restore the latest buffer contents before changes from elsewhere. (defun bufhist-before-change-function (&rest _) "Restore the most recent contents of the buffer before changes." (bufhist-switch-to-index 0)) ;; Unfortunately, erase-buffer does not call before-change-function ; (defadvice erase-buffer (before bufhist-last-advice activate) ; (if (and bufhist-mode bufhist-read-only-history) ; (bufhist-last))) ; (ad-activate-on 'erase-buffer))) ;;; ;;; Buttons ;;; (define-button-type 'bufhist-next 'follow-link t 'help-echo "Next" 'action #'bufhist-next) (define-button-type 'bufhist-prev 'follow-link t 'help-echo "Previous" 'action #'bufhist-prev) ;; Little bit tricky: inserts by clients start at (point-min) which ;; is going to insert above these buttons (defun bufhist-insert-buttons () (when bufhist-mode (let ((inhibit-read-only t)) (save-excursion (goto-char (point-min)) (insert-text-button " < " :type 'bufhist-prev) (insert " ") (insert-text-button " > " :type 'bufhist-next) (insert "\n\n") (setq bufhist-top-point (point)))))) (provide 'bufhist) ;;; bufhist.el ends here PG-4.5/lib/holes.el000066400000000000000000000640321426357011200141000ustar00rootroot00000000000000;;; holes.el --- a little piece of elisp to define holes in your buffer -*- lexical-binding:t -*- ;; This file is part of Proof General. ;; Portions © Copyright 1994-2012 David Aspinall and University of Edinburgh ;; Portions © Copyright 2003-2021 Free Software Foundation, Inc. ;; Portions © Copyright 2001-2017 Pierre Courtieu ;; Portions © Copyright 2010, 2016 Erik Martin-Dorel ;; Portions © Copyright 2011-2013, 2016-2017 Hendrik Tews ;; Portions © Copyright 2015-2017 Clément Pit-Claudel ;; This file uses spans, an interface for extent (XEmacs) and overlays ;; (emacs), by Healfdene Goguen for the proofgeneral mode. ;; ;; Credits also to Stefan Monnier for great help in making this file ;; cleaner. ;; ;; Further cleanups by David Aspinall. ;; This software is free software; you can redistribute it and/or ;; modify it under the terms of the GNU General Public ;; License version 3 or later, as published by the Free Software Foundation. ;; ;; This software is distributed in the hope that it will be useful, ;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ;; ;; See the GNU General Public License for more details ;; (enclosed in the file COPYING). ;;; Commentary: ;; ;; See documentation in variable holes-short-doc. ;; ;; See documentation of `holes-mode'. ;;; Code: (require 'span) (eval-when-compile (require 'cl-lib)) ;;; ;;; initialization ;;; (defvar holes-default-hole (let ((ol (make-overlay 0 0))) (delete-overlay ol) ol) "An empty detached hole used as the default hole. You should not use this variable.") (defvar holes-active-hole holes-default-hole "The current active hole. There can be only one active hole at a time, and this is this one. This is not buffer local.") ;;; ;;; Customizable ;;; (defgroup holes nil "Customization for Holes minor mode." :prefix "holes-" :group 'editing) (defcustom holes-empty-hole-string "#" "String to be inserted for empty hole (don't put an empty string)." :type 'string) (defcustom holes-empty-hole-regexp "#\\|@{\\([^{}]*\\)}" "Regexp denoting a hole in abbrevs. Subgroup 1 is treated specially: if it matches, it is assumed that everything before it and after it in the regexp matches delimiters which should be removed when making the text into a hole." :type 'regexp) ;(defcustom holes-search-limit 1000 ; "Number of chars to look forward when looking for the next hole, unused for now.") ;unused for the moment ;; The following is customizable by a command of the form: ;;for dark background ;;(custom-set-faces ;; '(holes-active-hole-face ;; ((((type x) (class color) (background light)) ;; (:background "paleVioletRed"))) ;; ) ;; ) (defface active-hole-face '((((class grayscale) (background light)) :background "dimgrey") (((class grayscale) (background dark)) :background "LightGray") (((class color) (background dark)) :background "darkred" :foreground "white") (((class color) (background light)) :background "paleVioletRed" :foreground "black")) "Font Lock face used to highlight the active hole.") (defface inactive-hole-face '((((class grayscale) (background light)) :background "lightgrey") (((class grayscale) (background dark)) :background "Grey") (((class color) (background dark)) :background "mediumblue" :foreground "white") (((class color) (background light)) :background "lightsteelblue" :foreground "black")) "Font Lock face used to highlight the active hole.") ;;; ;;; Keymaps ;;; (defvar hole-map (let ((map (make-sparse-keymap))) (define-key map [(mouse-1)] #'holes-mouse-set-active-hole) (define-key map [(mouse-3)] #'holes-mouse-destroy-hole) (define-key map [(mouse-2)] #'holes-mouse-forget-hole) map) "Keymap to use on the holes's overlays. This keymap is used only when point is on a hole. See `holes-mode-map' for the keymap of `holes-mode'.") (defvar holes-mode-map (let ((map (make-sparse-keymap))) (define-key map [(control c) (h)] #'holes-set-make-active-hole) (define-key map [(control c) (control y)] #'holes-replace-update-active-hole) (define-key map [(control meta down-mouse-1)] #'holes-mouse-set-make-active-hole) (define-key map [(control meta shift down-mouse-1)] #'holes-mouse-replace-active-hole) (define-key map [(control c) (control j)] #'holes-set-point-next-hole-destroy) map) "Keymap of `holes-mode'. This one is active whenever we are on a buffer where `holes-mode' is active. This is not the keymap used on holes's overlay (see `hole-map' instead).") (easy-menu-define nil (list holes-mode-map) "Menu used in Holes minor mode." '("Holes" ;; da: I tidied this menu a bit. I personally think this "trick" ;; of inserting strings to add documentation looks like a real ;; mess in menus ... I've removed it for the three below since ;; the docs below appear in popup in messages anyway. ;; ;; "Make a hole active click on it" ;; "Disable a hole click on it (button 2)" ;; "Destroy a hole click on it (button 3)" ["Make Hole At Point" holes-set-make-active-hole t] ["Make Selection A Hole" holes-set-make-active-hole t] ["Replace Active Hole By Selection" holes-replace-update-active-hole t] ["Jump To Active Hole" holes-set-point-next-hole-destroy t] ["Forget All Holes" holes-clear-all-buffer-holes t] ;; look a bit better at the bottom "---" ["About Holes" holes-show-doc t] "Hint: make hole with mouse: C-M-select" "Hint: replace hole with mouse: C-M-Shift-select" )) ;;; ;;; Utility functions ;;; (defun holes-region-beginning-or-nil () "Return the beginning of the acitve region, or nil." (and mark-active (region-beginning))) (defun holes-region-end-or-nil () "Return the end of the acitve region, or nil." (and mark-active (region-end))) (defun holes-copy-active-region () "Copy and retuurn the active region." (cl-assert mark-active nil "the region is not active now.") (copy-region-as-kill (region-beginning) (region-end)) (car kill-ring)) (defun holes-is-hole-p (span) "Non-nil if SPAN is a HOLE." (span-property span 'hole)) (defun holes-hole-start-position (hole) "Return start position of HOLE." (cl-assert (holes-is-hole-p hole) t "holes-hole-start-position: %s is not a hole") (span-start hole)) (defun holes-hole-end-position (hole) "Return end position of HOLE." (cl-assert (holes-is-hole-p hole) t "holes-hole-end-position: %s is not a hole") (span-end hole)) (defun holes-hole-buffer (hole) "Return the buffer of HOLE." "Internal." (cl-assert (holes-is-hole-p hole) t "holes-hole-buffer: %s is not a hole") (span-buffer hole)) (defun holes-hole-at (&optional pos) "Return the hole (a span) at POS in current buffer. If pos is not in a hole raises an error." (span-at (or pos (point)) 'hole)) (defun holes-active-hole-exist-p () "Return t if the active hole exists and is not empty (ie detached). Use this to know if the active hole is set and usable (don't use the active-hole-marker variable)." (not (span-detached-p holes-active-hole))) (defun holes-active-hole-start-position () "Return the position of the start of the active hole. See `active-hole-buffer' to get its buffer. Returns an error if active hole doesn't exist (the marker is set to nothing)." (cl-assert (holes-active-hole-exist-p) t "holes-active-hole-start-position: no active hole") (holes-hole-start-position holes-active-hole)) (defun holes-active-hole-end-position () "Return the position of the start of the active hole. See `active-hole-buffer' to get its buffer. Returns an error if active hole doesn't exist (the marker is set to nothing)." (cl-assert (holes-active-hole-exist-p) t "holes-active-hole-end-position: no active hole") (holes-hole-end-position holes-active-hole)) (defun holes-active-hole-buffer () "Return the buffer containing the active hole. Raise an error if the active hole is not set. Don't care if the active hole is empty." (cl-assert (holes-active-hole-exist-p) t "holes-active-hole-buffer: no active hole") (holes-hole-buffer holes-active-hole)) (defun holes-goto-active-hole () "Set point to active hole. Raises an error if active-hole is not set." (interactive) (cl-assert (holes-active-hole-exist-p) t "holes-goto-active-hole: no active hole") (goto-char (holes-active-hole-start-position))) (defun holes-highlight-hole-as-active (hole) "Highlight a HOLE with the `active-hole-face'. DON'T USE this as it would break synchronization (non active hole highlighted)." (cl-assert (holes-is-hole-p hole) t "holes-highlight-hole-as-active: %s is not a hole") (set-span-face hole 'active-hole-face)) (defun holes-highlight-hole (hole) "Highlight a HOLE with the not active face. DON'T USE this as it would break synchronization (active hole non highlighted)." (cl-assert (holes-is-hole-p hole) t "holes-highlight-hole: %s is not a hole") (set-span-face hole 'inactive-hole-face)) (defun holes-disable-active-hole () "Disable the active hole. The goal remains but is not the active one anymore. Does nothing if the active hole is already disable." (if (not (holes-active-hole-exist-p)) () ;; HACK: normal hole color, this way undo will show this hole ;; normally and not as active hole. Ideally, undo should restore ;; the active hole, but it doesn't, so we put the 'not active' ;; color. (holes-highlight-hole holes-active-hole) (setq holes-active-hole holes-default-hole))) (defun holes-set-active-hole (hole) "Set active hole to HOLE. Error if HOLE is not a hole." (cl-assert (holes-is-hole-p hole) t "holes-set-active-hole: %s is not a hole") (if (holes-active-hole-exist-p) (holes-highlight-hole holes-active-hole)) (setq holes-active-hole hole) (holes-highlight-hole-as-active holes-active-hole)) (defun holes-is-in-hole-p (&optional pos) "Return non-nil if POS (default: point) is in a hole, nil otherwise." (holes-hole-at pos)) (defun holes-make-hole (start end) "Make and return an (span) hole from START to END." (let ((ext (span-make start end))) (set-span-properties ext `(hole t mouse-face highlight priority 100 ;; what should I put here? I want big priority face secondary-selection start-open nil end-open t duplicable t evaporate t ;; really disappear if empty ;; pointer frame-icon-glyph keymap ,hole-map help-echo "this is a \"hole\", button 2 to forget, button 3 to destroy, button 1 to make active" 'balloon-help "this is a \"hole\", button 2 to forget, button 3 to destroy, button 1 to make active")) ext)) (defun holes-make-hole-at (&optional start end) "Make a hole from START to END. If no arg default hole after point. If only one arg: error. Return the span." (interactive) (let* ((rstart (or start (holes-region-beginning-or-nil) (point))) (rend (or end (holes-region-end-or-nil) (point)))) (if (eq rstart rend) (progn (goto-char rstart) (insert holes-empty-hole-string) (setq rend (point)))) (holes-make-hole rstart rend))) (defun holes-clear-hole (hole) "Clear the HOLE." (cl-assert (holes-is-hole-p hole) t "holes-clear-hole: %s is not a hole") (if (and (holes-active-hole-exist-p) (eq holes-active-hole hole)) (holes-disable-active-hole)) (span-delete hole)) (defun holes-clear-hole-at (&optional pos) "Clear hole at POS (default=point)." (interactive) (if (not (holes-is-in-hole-p (or pos (point)))) (error "Holes-clear-hole-at: no hole here")) (holes-clear-hole (holes-hole-at (or pos (point))))) (defun holes-map-holes (function &optional buffer from to) "Map function FUNCTION across holes in buffer BUFFER. Operate between character positions FROM and TO." (fold-spans function buffer from to nil nil 'hole)) (defun holes-clear-all-buffer-holes (&optional start end) "Clear all holes leaving their contents. Operate betwenn START and END if non nil." (interactive) (holes-disable-active-hole) (span-mapcar-spans 'holes-clear-hole (or start (point-min)) (or end (point-max)) 'hole)) ;; limit ? (defun holes-next (pos buffer) "Return the first hole after POS in BUFFER. Or after the hole at pos if there is one (default pos=point). If no hole found, return nil." (holes-map-holes (lambda (h _) (and (holes-is-hole-p h) h)) buffer pos)) (defun holes-next-after-active-hole () "Internal." (cl-assert (holes-active-hole-exist-p) t "next-active-hole: no active hole") (holes-next (holes-active-hole-end-position) (holes-active-hole-buffer))) (defun holes-set-active-hole-next (&optional buffer pos) "Set the active hole in BUFFER to the first hole after POS. Default pos = point and buffer = current." (interactive) (let ((nxthole (holes-next (or pos (point)) (or buffer (current-buffer))))) (if nxthole (holes-set-active-hole nxthole) (holes-disable-active-hole)))) ;;;(defun holes-set-active-hole-next-after-active () ;; "sets the active hole to the first hole after active ;; hole.";;;; ;;; (interactive) ;; (holes-next-after-active-hole) ;;) (defun holes-replace-segment (start end str &optional buffer) "Erase chars between START and END, and replace them with STR. Operate in buffer BUFFER." (with-current-buffer (or buffer (current-buffer)) (goto-char end) ;; Insert before deleting, so the markers at `start' and `end' ;; don't get mixed up together. (insert str) (delete-region start end))) (defun holes-replace (str &optional thehole) "Replace the current hole by STR, replace THEHOLE instead if given. Do not use this, it breaks the right colorization of the active goal(FIXME?). Use `replace-active-hole' instead." (if (and (not thehole) (not (holes-active-hole-exist-p))) (error "No hole to fill") ;; defensive: replacing the hole should make it detached and ;; therefore inexistent. other reason: this is a hack: unhighlight ;; so that undo wont show it highlighted) (if (and (holes-active-hole-exist-p) thehole (eq holes-active-hole thehole)) (holes-disable-active-hole) ) (let ((exthole (or thehole holes-active-hole))) (holes-replace-segment (holes-hole-start-position exthole) (holes-hole-end-position exthole) (or str (car kill-ring)) ;kill ring? (span-buffer exthole) ) (span-detach exthole) ;; this seems necessary for span overlays, ;; where the buffer attached to the span is not removed ;; automatically by the fact that the span is removed from the ;; buffer (holes-replace-segment should perhaps take care of ;; that) ))) (defun holes-replace-active-hole (&optional str) "Replace the active hole by STR, if no str is given, then put the selection instead." (if (not (holes-active-hole-exist-p)) nil (holes-replace (or str (current-kill 0) (error "Nothing to put in hole")) holes-active-hole))) (defun holes-replace-update-active-hole (&optional str) "Replace the active hole by STR. Like `holes-replace-active-hole', but then sets the active hole to the following hole if it exists." (interactive) (cl-assert (holes-active-hole-exist-p) t "holes-replace-update-active-hole: no active hole") (if (holes-active-hole-exist-p) (let ((nxthole (holes-next-after-active-hole))) (holes-replace-active-hole (or str (and mark-active (holes-copy-active-region)) (current-kill 0) (error "Nothing to put in hole"))) (if nxthole (holes-set-active-hole nxthole) (setq holes-active-hole holes-default-hole))))) (defun holes-delete-update-active-hole () "Deletes the active hole and supresses its content. Sets `holes-active-hole' to the next hole if it exists." (interactive) (holes-replace-update-active-hole "")) ;;;###autoload (defun holes-set-make-active-hole (&optional start end) "Make a new hole between START and END or at point, and make it active." (interactive) (holes-set-active-hole (holes-make-hole-at start end))) ;; mouse stuff, I want to make something close to `mouse-track-insert' ;; of XEmacs, but with modifier ctrl-meta and ctrl-meta-shift ;; Emacs and XEmacs have different ways of dealing with mouse ;; selection, but `mouse-track'(XEmacs) mouse-drag-region(Emacs) ;; have nearly the same meaning for me. So I define this ;; track-mouse-selection. (defalias 'holes-track-mouse-selection #'mouse-drag-track) (defsubst holes-track-mouse-clicks () "See `mouse-track-click-count'." (+ mouse-selection-click-count 1)) (defun holes-mouse-replace-active-hole (event) "Replace the active hole with one under mouse EVENT." (interactive "*e") (holes-track-mouse-selection event) (save-excursion ;;HACK: nothing if one click (but a second is perhaps coming) (if (and (eq (holes-track-mouse-clicks) 1) (not mark-active)) () (if (not mark-active) (error "Nothing to put in hole") (holes-replace-update-active-hole (current-kill 0)) (message "hole replaced"))))) (defun holes-destroy-hole (&optional span) "Destroy the hole SPAN." (interactive) (let* ((sp (or span (holes-hole-at (point)) (error "No hole to destroy")))) (save-excursion (if (and (holes-active-hole-exist-p) (eq sp holes-active-hole)) (holes-disable-active-hole)) (holes-replace "" sp) (span-detach sp)) (message "hole killed"))) (defsubst holes-hole-at-event (event) "Return the hole at EVENT." (span-at-event event 'hole)) (defun holes-mouse-destroy-hole (event) "Destroy the hole at EVENT." (interactive "*e") (holes-destroy-hole (holes-hole-at-event event))) ;;;(span-at-event EVENT &optional PROPERTY BEFORE AT-FLAG) ;;comprend pas?? (defun holes-mouse-forget-hole (event) "Delete and deactivate the hole at EVENT." (interactive "*e") (save-excursion (let ((ext (holes-hole-at-event event))) (if (eq ext holes-active-hole) (holes-disable-active-hole)) (span-detach ext))) (message "hole deleted")) (defun holes-mouse-set-make-active-hole (event) "Make a new hole at EVENT click activate it." (interactive "*e") (holes-track-mouse-selection event) (if (and (eq (holes-track-mouse-clicks) 1) (not mark-active)) (holes-set-make-active-hole (point) (point)) (if mark-active (holes-set-make-active-hole) (let ((ext (holes-hole-at-event event))) (if (and ext (holes-is-hole-p ext)) (error "Already a hole here") (holes-set-active-hole (holes-make-hole-at))))))) (defun holes-mouse-set-active-hole (event) "Make the hole at EVENT click active." (interactive "*e") (let ((ext (holes-hole-at-event event))) (if (and ext (holes-is-hole-p ext)) (holes-set-active-hole ext) (error "No hole here")))) (defun holes-set-point-next-hole-destroy () "Move the point to current active hole (if any and if in current buffer). Destroy it and makes the next hole active if any." (interactive) (cl-assert (holes-active-hole-exist-p) nil "no active hole") (cl-assert (eq (current-buffer) (holes-active-hole-buffer)) nil "active hole not in this buffer") (holes-goto-active-hole) (holes-delete-update-active-hole)) ;; utilities to be used in conjunction with abbrevs. ;; The idea is to put abbrevs of the form: ;;(define-abbrev-table 'tuareg-mode-abbrev-table ;; '( ;; ("l" "let # = # in" replace-#-after-abbrev2 0) ;; ) ;; ) ;; where replace-#-after-abbrev2 should be a function which replace the ;; two #'s (two occurences going backward from abbrev expantion point) ;; by holes and leave point at the first # (deleting ;; it). holes-set-point-next-hole-destroy allow to go to the next hole. ;;following function allow to replace occurrences of a string by a ;;hole. (defun holes-replace-string-by-holes-backward (limit) "Change each occurrence of REGEXP into a hole. Sets the active hole to the last created hole and unsets it if no hole is created. Return the number of holes created. The LIMIT argument bounds the search; it is a buffer position. The match found must not begin before that position. A value of nil means search to the beginning of the accessible portion of the buffer." (holes-disable-active-hole) (let ((n 0)) (save-excursion (while (re-search-backward holes-empty-hole-regexp limit t) (cl-incf n) (if (not (match-end 1)) (holes-make-hole (match-beginning 0) (match-end 0)) (holes-make-hole (match-beginning 1) (match-end 1)) ;; delete end first to avoid shifting of marks (delete-region (match-end 1) (match-end 0)) (delete-region (match-beginning 0) (match-beginning 1))) (holes-set-active-hole-next))) n)) (defun holes-skeleton-end-hook () "Default hook after a skeleton insertion: put holes at each interesting position." ;; Not all versions of skeleton provide `skeleton-positions' and the ;; corresponding @ operation :-( (when (boundp 'skeleton-positions) (dolist (pos skeleton-positions) ;; put holes here (holes-set-make-active-hole pos pos)))) (defconst holes-jump-doc (concat "Hit \\[holes-set-point-next-hole-destroy] to jump " "to active hole. C-h v holes-doc to see holes doc.") "Shortcut reminder string for jumping to active hole.") (defun holes-replace-string-by-holes-backward-jump (pos &optional noindent alwaysjump) "Put holes between POS and point, backward, indenting. \"#\" and \"@{..}\" between this positions will become holes. If NOINDENT is non-nil, skip the indenting step. If ALWAYSJUMP is non-nil, jump to the first hole even if more than one." (unless noindent (save-excursion (indent-region pos (point) nil))) (let ((n (holes-replace-string-by-holes-backward pos))) (pcase n (`0 nil) ; no hole, stay here. (`1 (goto-char pos) (holes-set-point-next-hole-destroy)) ; if only one hole, go to it. (_ (goto-char pos) (when alwaysjump (holes-set-point-next-hole-destroy)) (unless (active-minibuffer-window) ; otherwise minibuffer gets hidden (message (substitute-command-keys "\\[holes-set-point-next-hole-destroy] to jump to active hole. \\[holes-short-doc] to see holes doc."))))))) ;;;###autoload (define-minor-mode holes-mode "Toggle Holes minor mode. With arg, turn Outline minor mode on if arg is positive, off otherwise. The mode `holes-mode' is meant to help program editing. It is useful to build complicated expressions by copy pasting several peices of text from different parts of a buffer (or even from different buffers). HOLES A hole is a piece of (highlighted) text that may be replaced by another part of text later. There is no information stored on the file for holes, so you can save and modify files containing holes with no harm... You can even insert or delete characters inside holes like any other characters. USE At any time only one particular hole, called \"active\", can be \"filled\". Holes can be in several buffers but there is always one or zero active hole globally. It is highlighted with a different color. Functions described below have default shortcuts when `holes-mode' is on that you can customize. TO DEFINE A HOLE, two methods: o Select a region with keyboard or mouse, then use \\[holes-set-make-active-hole]. If the selected region is empty, then a hole containing # is created at point. o Select text with mouse while pressing ctrl and meta (`C-M-select'). If the selected region is empty (i.e. if you just click while pressing ctrl+meta), then a hole containing # is created. TO ACTIVATE A HOLE, click on it with the button 1 of your mouse. The previous active hole will be deactivated. TO FORGET A HOLE without deleting its text, click on it with the button 2 (middle) of your mouse. TO DESTROY A HOLE and delete its text, click on it with the button 3 of your mouse. TO FILL A HOLE with a text selection, first make sure it is active, then two methods: o Select text with keyboard or mouse and hit \\[holes-replace-update-active-hole] o Select text with mouse while pressing ctrl, meta and shift (`C-M-S-select'). This is a generalization of the `mouse-track-insert' feature of XEmacs. This method allows you to fill different holes faster than with the usual copy-paste method. After replacement the next hole is automatically made active so you can fill it immediately by hitting again \\[holes-replace-update-active-hole] or `C-M-S-select'. TO JUMP TO THE ACTIVE HOLE, just hit \\[holes-set-point-next-hole-destroy]. You must be in the buffer containing the active hole. the point will move to the active hole, and the active hole will be destroyed so you can type something to put at its place. The following hole is automatically made active, so you can hit \\[holes-set-point-next-hole-destroy] again. It is useful in combination with abbreviations. For example in `coq-mode' \"fix\" is an abbreviation for Fixpoint # (# : #) {struct #} : # := #, where each # is a hole. Then hitting \\[holes-set-point-next-hole-destroy] goes from one hole to the following and you can fill-in each hole very quickly. COMBINING HOLES AND SKELETONS `holes' minor mode is made to work with minor mode `skeleton' minor mode. KNOWN BUGS o Don't try to make overlapping holes, it doesn't work. (what would it mean anyway?) o Cutting or pasting a hole will not produce new holes, and undoing on holes cannot make holes re-appear." :lighter " Holes" (if holes-mode (add-hook 'skeleton-end-hook #'holes-skeleton-end-hook nil t) (remove-hook 'skeleton-end-hook #'holes-skeleton-end-hook t) (holes-clear-all-buffer-holes))) ;;;###autoload (defun holes-abbrev-complete () "Complete abbrev by putting holes and indenting. Moves point at beginning of expanded text. Put this function as call-back for your abbrevs, and just expanded \"#\" and \"@{..}\" will become holes." (if holes-mode (holes-replace-string-by-holes-backward-jump last-abbrev-location))) ;;;###autoload (defun holes-insert-and-expand (s) "Insert S, expand it and replace #s and @{]s by holes." ;; insert the expansion of abbrev s, and replace #s by holes. It was ;; possible to implement it with a simple ((insert s) (expand-abbrev)) ;; but undo would show the 2 steps, which is bad. (let ((pos (point)) (ins (abbrev-expansion s))) (insert (or ins s)) (setq last-abbrev-location pos) (holes-abbrev-complete))) (provide 'holes) ;;; holes.el ends here PG-4.5/lib/local-vars-list.el000066400000000000000000000131311426357011200157740ustar00rootroot00000000000000;;; local-vars.el --- local variables list utilities ;; This file is part of Proof General. ;; Portions © Copyright 1994-2012 David Aspinall and University of Edinburgh ;; Portions © Copyright 2003-2021 Free Software Foundation, Inc. ;; Portions © Copyright 2001-2017 Pierre Courtieu ;; Portions © Copyright 2010, 2016 Erik Martin-Dorel ;; Portions © Copyright 2011-2013, 2016-2017 Hendrik Tews ;; Portions © Copyright 2015-2017 Clément Pit-Claudel ;; Authors: Pierre Courtieu ;; Maintainer: Pierre Courtieu ;; This software is free software; you can redistribute it and/or ;; modify it under the terms of the GNU General Public ;; License version 3 or later, as published by the Free Software Foundation. ;; ;; This software is distributed in the hope that it will be useful, ;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ;; ;; See the GNU General Public License for more details ;; (enclosed in the file COPYING). ;;; Commentary: ;; ;; See documentation in variable local-var-list-doc ;; ;; TODO: Rely on hack-file-local-variables instead ;;; Code: (defconst local-vars-list-doc nil "From Emacs Info: A file can contain a \"local variables list\", which specifies the values to use for certain Emacs variables when that file is edited. See info node \"(emacs)File Variables\". local-vars-list provides two useful functions: \\[local-vars-list-get] that reads a local variable value at the end of the file. \\[local-vars-list-set] that writes a local variable value at the end of the file.") (defun local-vars-list-find () "Find the local variable definition paragraph. Return a list containing the prefix and the suffix of its first line, or throw 'notfound if not found. Sets the point at the beginning of the second line of the paragraph." (goto-char (point-max)) (catch 'notfound (if (not (re-search-backward "Local Variables:" nil t)) (throw 'notfound nil)) (let ((bol (save-excursion (beginning-of-line) (point))) (eol (save-excursion (end-of-line) (point))) (lpattern) (rpattern)) (setq lpattern (buffer-substring bol (point))) (re-search-forward "Local Variables:" eol t) (setq rpattern (buffer-substring (point) eol)) (forward-line 1) (beginning-of-line) (cons lpattern (cons rpattern nil))))) (defun local-vars-list-goto-var (symb lpat rpat) "Search a line defining local variable symb at current line and below. If successful set point to the beginning of the *value* and return t. Otherwise set point to the beginning of the last line of the local variables list (the one containing \"End:\"), and return nil. lpat and rpat are the suffix and prefix of the local variable list. Note: this function must be called when at the beginning of a local variable definition (or at the \"End:\" line)." (let* ((symbname (symbol-name symb)) (found nil) (endreached nil) (eol)) (while (and (not found) (not endreached)) (setq eol (save-excursion (end-of-line) (point))) (search-forward lpat eol) (re-search-forward "\\([^ :]+\\):" eol) (let ((varname (match-string 1))) (cond ((string-equal varname "End") (setq endreached t) (beginning-of-line)) ((string-equal varname symbname) (setq found t)) (t (forward-line 1) (beginning-of-line))))) (if found t nil))) ; precond: really be on a var def line (defun local-vars-list-get-current (lpat rpat) "Return the value written in the local variable list at current line. lpat and rpat are the suffix and prefix of the local variable list. Note: this function must be called when at the beginning of a local variable definition (or at the \"End:\" line)." (let ((bol (save-excursion (beginning-of-line) (point))) (eol (save-excursion (end-of-line) (point))) (varname "")) (catch 'notfound (if (not (search-forward lpat eol t)) (throw 'notfound nil)) (if (not (re-search-forward "\\([^ :]+\\):" eol t)) (throw 'notfound nil)) (setq varname (match-string 1)) (let ((boexp (point))) (if (not (search-forward rpat eol t)) (throw 'notfound nil)) (search-backward rpat bol) ; should always succeed (read (buffer-substring boexp (point))))))) ; TODO: catch errors here? ;; Only looks for file local vars. Not dir local vars. (defun local-vars-list-get (symb) "Return the value written in the local variable list for variable symb. Raises an error if symb is not in the list. Note: Using `file-local-variables-alist' is not comfortable here since editing by hand the file variable zone does not modify this alist. Proceed by looking in the file instead." (save-excursion (let* ((lrpat (local-vars-list-find)) (dummy (if lrpat t (error "Local variables zone not found"))) (lpat (car lrpat)) (rpat (car (cdr lrpat))) ) (beginning-of-line) (if (local-vars-list-goto-var symb lpat rpat) t (error "Variable %s not found" symb)) (beginning-of-line) (local-vars-list-get-current lpat rpat)))) (defun local-vars-list-get-safe (symb) "Return true if variable SYMB belongs to the local variable list of the current buffer." (condition-case nil (local-vars-list-get symb) (error nil))) (defun local-vars-list-set (symb val) "Write the value val in the local variable list for variable symb. If the variable is already specified in the list, replace the value. If no local variable list is found, create one at the end of the buffer first." (add-file-local-variable symb val)) (provide 'local-vars-list) ;; Local Variables: *** ;; fill-column: 85 *** ;; indent-tabs-mode: nil *** ;; End: *** (provide 'local-vars-list) ;;; local-vars-list.el ends here PG-4.5/lib/maths-menu.el000066400000000000000000000277431426357011200150540ustar00rootroot00000000000000;;; maths-menu.el --- insert maths characters from a menu -*- lexical-binding:t; coding: utf-8 -*- ;; This file is part of Proof General. ;; Portions © Copyright 1994-2012 David Aspinall and University of Edinburgh ;; Portions © Copyright 2003-2021 Free Software Foundation, Inc. ;; Portions © Copyright 2001-2017 Pierre Courtieu ;; Portions © Copyright 2010, 2016 Erik Martin-Dorel ;; Portions © Copyright 2011-2013, 2016-2017 Hendrik Tews ;; Portions © Copyright 2015-2017 Clément Pit-Claudel ;; Author: Dave Love ;; Keywords: convenience ;; Version for Proof General modified by David Aspinall, 2007-8. ;; - Hooks added to insert tokenised versions of unicode characters. ;; - Added more characters to the menus. ;; - Define insertion functions following menu names (useful for keybindings) ;; This file is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation; either version 3, or (at your option) ;; any later version. ;; This file is distributed in the hope that it will be useful, ;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License ;; along with GNU Emacs; see the file COPYING. If not, write to ;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330, ;; Boston, MA 02111-1307, USA. ;;; Commentary: ;; Defines a minor mode which defines a menu bar item allowing a wide ;; range of maths/technical characters (roughly the LaTeX repertoire) ;; to be inserted into the buffer by selecting menu items. ;; Menu display only works properly under X with Gtk menus and if the ;; menu uses a font with a suitable repertoire. (Lucid and Motif ;; toolkit menus can't display multilingual text. I don't know about ;; MS Windows menus.) It will work with tmm in tty mode iff the tty ;; displays Unicode. The tmm version (via F10) is also useful under a ;; window system when the menus don't display the characters ;; correctly, but where the symbols have word syntax, tmm won't ;; provide an ASCII selector for them, which can be a pain to use ;; without a mouse. ;; See also the TeX and sgml Quail input modes. These will probably ;; behave better if you can remember the input sequences. For ;; instance, this minor mode won't give you the ability to insert into ;; the minibuffer via the menu, though presumably it could be added to ;; the minibuffer menu. ;;; Code: (defvar maths-menu-filter-predicate (lambda (_char) t) "Predicate function used to filter menu elements.") (defvar maths-menu-tokenise-insert #'insert "Function used to insert possibly formatted or escaped character.") (defun maths-menu-build-menu (spec) (let ((map (make-sparse-keymap "Characters"))) (dolist (pane spec) (let* ((name (pop pane)) (pane-map (make-sparse-keymap name))) (define-key-after map (vector (intern name)) (cons name pane-map)) (dolist (elt pane) (let ((fname (intern (concat "maths-menu-insert-" (replace-regexp-in-string " " "-" (cadr elt)))))) (fset fname (lambda () (interactive) (funcall maths-menu-tokenise-insert (car elt)))) (define-key-after pane-map (vector (intern (string (car elt)))) ; convenient unique symbol (list 'menu-item (format "%c (%s)" (car elt) (cadr elt)) fname :visible `(funcall maths-menu-filter-predicate ,(car elt)))))))) map)) (defvar maths-menu-menu (maths-menu-build-menu '(("Logic" (?∧ "and") (?∨ "or") (?∀ "for all") (?∃ "there exists") (?∄ "there does not exist") (?⊤ "down tack") (?⊥ "up tack")) ("Binops 1" (?± "plus-minus sign") (?∓ "minus-or-plus sign") (?× "multiplication sign") (?÷ "division sign") (?− "minus sign") (?∗ "asterisk operator") (?⋆ "star operator") (?○ "white circle") (?• "bullet") (?· "middle dot") (?∩ "intersection") (?∪ "union") (?⊎ "multiset union") (?⊓ "square cap") (?⊔ "square cup") (?∨ "logical or") (?∧ "logical and") (?∖ "set minus") (?≀ "wreath product")) ("Binops 2" (?⋄ "diamond operator") (?△ "white up-pointing triangle") (?▽ "white down-pointing triangle") (?◃ "white left-pointing small triangle") (?▹ "white right-pointing small triangle") (?◁ "white left-pointing triangle") (?▷ "white right-pointing triangle") (?⊕ "circled plus") (?⊖ "circled minus") (?⊗ "circled times") (?⊘ "circled division slash") (?⊙ "circled dot operator") (?◯ "large circle") (?† "dagger") (?‡ "double dagger") (?⊴ "normal subgroup of or equal to") (?⊵ "contains as normal subgroup or equal to")) ("Relations 1" (?≤ "less-than or equal to") (?≺ "precedes") (?≪ "much less-than") (?⊂ "subset of") (?⊆ "subset of or equal to") (?⊏ "square image of") (?⊑ "square image of or equal to") (?∈ "element of") (?∉ "not an element of") (?⊢ "right tack") (?≥ "greater-than or equal to") (?≻ "succeeds") (?≽ "succeeds or equal to") (?≫ "much greater-than") (?⊃ "superset of") (?⊇ "superset of or equal to") (?⊐ "square original of") (?⊒ "square original of or equal to") (?∋ "contains as member") (?≡ "identical to") (?≢ "not identical to") ) ("Relations 2" (?⊣ "left tack") (?∼ "tilde operator") (?≃ "asymptotically equal to") (?≍ "equivalent to") (?≈ "almost equal to") (?≅ "approximately equal to") (?≠ "not equal to") (?≐ "approaches the limit") (?∝ "proportional to") (?⊧ "models") (?∣ "divides") (?∥ "parallel to") (?⋈ "bowtie") (?⋈ "bowtie") (?⌣ "smile") (?⌢ "frown") (?≙ "estimates") (?⋿ "z notation bag membership")) ("Arrows" (?← "leftwards arrow") (?⇐ "leftwards double arrow") (?→ "rightwards arrow") (?⇒ "rightwards double arrow") (?↔ "left right arrow") (?⇔ "left right double arrow") (?↦ "rightwards arrow from bar") (?↩ "leftwards arrow with hook") (?↼ "leftwards harpoon with barb upwards") (?↽ "leftwards harpoon with barb downwards") (?⇌ "rightwards harpoon over leftwards harpoon") (?↦ "rightwards arrow from bar") (?↪ "rightwards arrow with hook") (?⇀ "rightwards harpoon with barb upwards") (?⇁ "rightwards harpoon with barb downwards") (?↝ "rightwards wave arrow") (?↑ "upwards arrow") (?⇑ "upwards double arrow") (?↓ "downwards arrow") (?⇓ "downwards double arrow") (?↕ "up down arrow") (?↗ "north east arrow") (?↘ "south east arrow") (?↙ "south west arrow") (?↖ "north west arrow") (?⇛ "rightwards triple arrow")) ("Long arrows" (?⟶ "long rightwards arrow") (?⟷ "long left right arrow") (?⟸ "long left double arrow") (?⟹ "long right double arrow") (?⟺ "long left right double arrow") (?⟻ "long left arrow from bar") (?⟼ "long right arrow from bar") (?⟽ "long left double arrow bar") (?⟾ "long right double arrow from bar") (?⟿ "long rightwards squiggle arrow")) ("Symbols 1" (?ℵ "alef symbol") ; don't use letter alef (avoid bidi confusion) (?ℏ "planck constant over two pi") (?ı "latin small letter dotless i") (?ℓ "script small l") (?℘ "script capital p") (?ℜ "black-letter capital r") (?ℑ "black-letter capital i") (?℧ "inverted ohm sign") (?′ "prime") (?∅ "empty set") (?∇ "nabla") (?√ "square root") (?∛ "cube root") (?∠ "angle") (?¬ "not sign") (?♯ "music sharp sign") (?∂ "partial differential") (?∞ "infinity") ) ("Symbols 2" (?□ "white square") (?◇ "white diamond") (?▵ "white up-pointing small triangle") (?∑ "n-ary summation") (?∏ "n-ary product") (?∐ "n-ary coproduct") (?∫ "integral") (?∮ "contour integral") (?⋂ "n-ary intersection") (?⋃ "n-ary union") (?⋁ "n-ary logical or") (?⋀ "n-ary logical and") (?ℕ "double-struck capital n") (?ℙ "double-struck capital p") (?ℚ "double-struck capital q") (?ℝ "double-struck capital r") (?ℤ "double-struck capital z") (?ℐ "script capital i") (?ƛ "latin small letter lambda with stroke") (?∴ "therefore") (?… "horizontal ellipsis") (?⋯ "midline horizontal ellipsis") (?⋮ "vertical ellipsis") (?⋱ "down right diagonal ellipsis") (?⋰ "up right diagonal ellipsis") (?⦁ "z notation spot") (?⦂ "z notation type colon")) ("Delimiters" (?\⌊ "left floor") (?\⌈ "left ceiling") (?\〈 "left-pointing angle bracket") (?\⌋ "right floor") (?\⌉ "right ceiling") (?\〉 "right-pointing angle bracket") (?\〚 "left white square bracket") (?\〛 "right white square bracket") (?\《 "left double angle bracket") (?\》 "right double angle bracket") (?\⦇ "z notation left image bracket") (?\⦈ "z notation right image bracket") (?\⦉ "z notation left binding bracket") (?\⦊ "z notation right binding bracket")) ("Greek LC" (?α "alpha") (?β "beta") (?γ "gamma") (?δ "delta") (?ε "epsilon") (?ζ "zeta") (?η "eta") (?θ "theta") (?ϑ "theta symbol") (?ι "iota") (?κ "kappa") (?λ "lamda") (?μ "mu") (?ν "nu") (?ξ "xi") (?π "pi") (?ϖ "pi symbol") (?ρ "rho") (?ϱ "rho symbol") (?σ "sigma") (?ς "final sigma") (?τ "tau") (?υ "upsilon") (?φ "phi") (?ϕ "phi symbol") (?χ "chi") (?ψ "psi") (?ω "omega")) ("Greek UC" (?Γ "Gamma") (?Δ "Delta") (?Θ "Theta") (?Λ "Lamda") (?Ξ "Xi") (?Π "Pi") (?Σ "Sigma") (?Υ "Upsilon") (?Φ "Phi") (?Ψ "Psi") (?Ω "Omega")) ("Sub/super" (?⁽ "superscript left parenthesis") (?⁾ "superscript right parenthesis") (?⁺ "superscript plus sign") (?⁻ "superscript minus") (?⁰ "superscript zero") (?¹ "superscript one") (?² "superscript two") (?³ "superscript three") (?⁴ "superscript four") (?⁵ "superscript five") (?⁶ "superscript six") (?⁷ "superscript seven") (?⁸ "superscript eight") (?⁹ "superscript nine") (?₍ "subscript left parenthesis") (?₎ "subscript right parenthesis") (?₊ "subscript plus sign") (?₋ "subscript minus") (?₀ "subscript zero") (?₁ "subscript one") (?₂ "subscript two") (?₃ "subscript three") (?₄ "subscript four") (?₅ "subscript five") (?₆ "subscript six") (?₇ "subscript seven") (?₈ "subscript eight") (?₉ "subscript nine"))))) (defvar maths-menu-mode-map (let ((map (make-sparse-keymap))) (define-key map [menu-bar maths] `(menu-item "Maths" ,maths-menu-menu :help "Menu of maths characters to insert")) map)) ;;;###autoload (define-minor-mode maths-menu-mode "Install a menu for entering mathematical characters. Uses window system menus only when they can display multilingual text. Otherwise the menu-bar item activates the text-mode menu system. This mode is only useful with a font which can display the maths repertoire." :lighter nil) (provide 'maths-menu) ;;; maths-menu.el ends here PG-4.5/lib/pg-dev.el000066400000000000000000000123631426357011200141500ustar00rootroot00000000000000;;; pg-dev.el --- Developer settings for Proof General ;; This file is part of Proof General. ;; Portions © Copyright 1994-2012 David Aspinall and University of Edinburgh ;; Portions © Copyright 2003-2021 Free Software Foundation, Inc. ;; Portions © Copyright 2001-2017 Pierre Courtieu ;; Portions © Copyright 2010, 2016 Erik Martin-Dorel ;; Portions © Copyright 2011-2013, 2016-2017 Hendrik Tews ;; Portions © Copyright 2015-2017 Clément Pit-Claudel ;; Author: David Aspinall and others ;; SPDX-License-Identifier: GPL-3.0-or-later ;;; Commentary: ;; ;; Some configuration of Emacs Lisp mode for developing PG, not needed ;; for ordinary users. ;; ;;; Code: (require 'whitespace) (eval-when-compile (require 'proof-site)) (with-no-warnings (setq proof-general-debug t)) ;; Use checkdoc, eldoc, Flyspell, whitespace, copyright update ;; and byte compilation on save: (add-hook 'emacs-lisp-mode-hook (lambda () (checkdoc-minor-mode 1) (eldoc-mode 1) (flyspell-prog-mode) (customize-set-variable 'whitespace-action '(cleanup)) (define-key emacs-lisp-mode-map [(control c)(control c)] 'emacs-lisp-byte-compile) (add-hook 'write-file-functions 'whitespace-write-file-hook nil t) (add-hook 'before-save-hook 'copyright-update nil t))) ;; Fill in template for new files (add-hook 'find-file-hook 'auto-insert) ;; Configure indentation for our macros (put 'proof-if-setting-configured 'lisp-indent-function 1) (put 'proof-eval-when-ready-for-assistant 'lisp-indent-function 1) (put 'proof-define-assistant-command 'lisp-indent-function 'defun) (put 'proof-define-assistant-command-witharg 'lisp-indent-function 'defun) (put 'defpgcustom 'lisp-indent-function 'defun) (put 'proof-map-buffers 'lisp-indent-function 'defun) (put 'proof-with-current-buffer-if-exists 'lisp-indent-function 'defun) (defconst pg-dev-lisp-font-lock-keywords (list (concat "(\\(def" ;; also proof-def ;; Function like things: ;; Variable like things "\\(pgcustom\\|pacustom\\)\\)" ;; Any whitespace and declared object. "[ \t'\(]*" "\\(\\sw+\\)?") '(1 font-lock-keyword-face) '(3 (cond ((match-beginning 2) 'font-lock-variable-name-face) (t 'font-lock-function-name-face)) nil t))) ;; Not working, see font-lock.el for usual emacs lisp settings. ;;(add-hook 'emacs-lisp-mode-hook ;; (lambda () ;; (font-lock-add-keywords nil ;; 'pg-dev-lisp-font-lock-keywords))) ;; ;; Path set for a clean environment to byte-compile within Emacs ;; without loading. ;; (defun pg-loadpath () (interactive) (proof-add-to-load-path "../generic/") (proof-add-to-load-path "../lib/")) ;;; ;;; Unload utility (not wholly successful) ;;; (defun unload-pg () "Attempt to unload Proof General (for development use only)." (interactive) (mapcar (lambda (feat) (condition-case nil (unload-feature feat 'force) (error nil))) '(proof-splash pg-assoc pg-xml proof-depends proof-indent proof-site proof-shell proof-menu pg-pbrpm pg-pgip proof-script proof-autoloads pg-response pg-goals proof-toolbar proof-easy-config proof-config proof proof-utils proof-syntax pg-user pg-custom proof-maths-menu proof-unicode-tokens pg-thymodes pg-autotest ;; coq-abbrev coq-db coq-unicode-tokens coq-local-vars coq coq-syntax coq-indent coq-autotest))) ;; ;; Proling interesting packages ;; (require 'elp) ;;;###autoload (defun profile-pg () "Configure Proof General for profiling. Use \\[elp-results] to see results." (interactive) (elp-instrument-package "proof-") (elp-instrument-package "pg-") (elp-instrument-package "scomint") (elp-instrument-package "unicode-tokens") (elp-instrument-package "coq") (elp-instrument-package "span") (elp-instrument-package "replace-") ; for replace-regexp etc (elp-instrument-package "re-search-") ; for re-search-forwad etc (elp-instrument-package "skip-chars-") ; for skip chars etc (elp-instrument-list '(string-match match-string re-search-forward re-search-backward skip-chars-forward skip-chars-backward goto-char insert set-marker marker-position nreverse nconc mapc member redisplay sit-for overlay-put overlay-start overlay-end make-overlay buffer-live-p kill-buffer process-status get-buffer-process delete-overlay move-overlay accept-process-output)) (elp-instrument-package "font-lock")) ;; improve readability of profile results, give milliseconds (defun elp-pack-number (number width) (format (concat "%" (number-to-string (- width 3)) ".2f") (* 100 (string-to-number number)))) ;; ;; Make references to bugs clickable; [e.g., trac #1] ;; (defun pg-bug-references () (interactive) (if (fboundp 'bug-reference-mode) (with-no-warnings (bug-reference-mode 1) (setq bug-reference-bug-regexp "\\(?:[Tt]rac ?#\\)\\([0-9]+\\)" bug-reference-url-format "http://proofgeneral.inf.ed.ac.uk/trac/ticket/%s")))) (add-hook 'emacs-lisp-mode-hook 'pg-bug-references) (add-hook 'coq-mode-hook 'pg-bug-references) (add-hook 'emacs-lisp-mode-hook 'goto-address-mode) (provide 'pg-dev) ;;; pg-dev.el ends here PG-4.5/lib/pg-fontsets.el000066400000000000000000000045101426357011200152320ustar00rootroot00000000000000;;; pg-fontsets.el --- Define fontsets useful for Proof General ;; This file is part of Proof General. ;; Portions © Copyright 1994-2012 David Aspinall and University of Edinburgh ;; Portions © Copyright 2003, 2012, 2014 Free Software Foundation, Inc. ;; Portions © Copyright 2001-2017 Pierre Courtieu ;; Portions © Copyright 2010, 2016 Erik Martin-Dorel ;; Portions © Copyright 2011-2013, 2016-2017 Hendrik Tews ;; Portions © Copyright 2015-2017 Clément Pit-Claudel ;; Author: David Aspinall ;; SPDX-License-Identifier: GPL-3.0-or-later ;;; Commentary: ;; ;; Define some fontsets to try to select fonts that display many symbols. ;; ;; Select one of these fontsets via the menu Options -> Set Font/Fontset ;; or, with M-x set-default-font ;; ;; Recommended & free fonts to install on your system are: ;; ;; DejaVu LGC (Sans and Sans Mono). See http://dejavu.sourceforge.net ;; Liberation (Sans and Mono). See https://fedorahosted.org/liberation-fonts/ ;; ;;; Code: (require 'fontset) (defcustom pg-fontsets-default-fontset nil "*Name of default fontset to use with Proof General." :type 'string :group 'proof-user-options) (defvar pg-fontsets-names nil "*List of fontsets to use with Proof General.") (defun pg-fontsets-make-fontsetsizes (basefont) (dolist (size '(10 12 14 18 22)) (add-to-list 'pg-fontsets-names (create-fontset-from-fontset-spec (replace-regexp-in-string "%T" (car (split-string basefont)) (replace-regexp-in-string "%S" (int-to-string size) (replace-regexp-in-string "%F" basefont "-*-%F-*-*-*--%S-*-*-*-*-*-fontset-PG%T, gnu-unifont:-*-%F-*-*-*--%S-*-*-*-*-*-iso10646-1" ;ascii:-*-%F-medium-r-normal--%S-*-*-*-*-*-mac-roman, ;latin-iso8859-1:-*-%F-medium-r-normal--%S-*-*-*-*-*-mac-roman, ;mule-unicode-0100-24ff:-*-%F-medium-r-normal--%S--*-*-*-*-*-iso10646-1, ;mule-unicode-2500-33ff:-*-%F-medium-r-normal--%S--*-*-*-*-*-iso10646-1, ;mule-unicode-e000-ffff:-*-%F-medium-r-normal--%S--*-*-*-*-*-iso10646-1" ))))))) (defconst pg-fontsets-base-fonts '("dejavu lgc sans mono" "liberation mono" "stixregular" "lucidasanstypewriter")) (defun pg-fontsets-make-fontsets () (setq pg-fontsets-names nil) (mapcar 'pg-fontsets-make-fontsetsizes pg-fontsets-base-fonts)) (pg-fontsets-make-fontsets) (provide 'pg-fontsets) ;;; pg-fontsets.el ends here PG-4.5/lib/proof-compat.el000066400000000000000000000050271426357011200153730ustar00rootroot00000000000000;;; proof-compat.el --- Operating system and Emacs version compatibility -*- lexical-binding:t -*- ;; This file is part of Proof General. ;; Portions © Copyright 1994-2012 David Aspinall and University of Edinburgh ;; Portions © Copyright 2003-2018 Free Software Foundation, Inc. ;; Portions © Copyright 2001-2017 Pierre Courtieu ;; Portions © Copyright 2010, 2016 Erik Martin-Dorel ;; Portions © Copyright 2011-2013, 2016-2017 Hendrik Tews ;; Portions © Copyright 2015-2017 Clément Pit-Claudel ;; Author: David Aspinall and others ;; SPDX-License-Identifier: GPL-3.0-or-later ;;; Commentary: ;; ;; This file collects together compatibility hacks for different ;; operating systems and Emacs versions. This is to help keep ;; track of them. ;; ;; The development policy for Proof General (since v3.7) is for the ;; main codebase to be written for the latest stable version of ;; GNU Emacs, following GNU Emacs advice on obsolete function calls. ;; ;; Since Proof General 4.0, XEmacs is not supported at all. ;; ;;; Code: (require 'cl-lib) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; ;;; Modifications and adjustments ;;; ;; Remove a custom setting. Needed to support dynamic reconfiguration. ;; (We'd prefer that repeated defcustom calls acted like repeated ;; "defvar treated as defconst" in XEmacs) (defun pg-custom-undeclare-variable (symbol) "Remove a custom setting SYMBOL. Done by removing all properties mentioned by custom library. The symbol itself is left defined, in case it has been changed in the current Emacs session." (dolist (prop '(default standard-value force-value variable-comment saved-variable-comment variable-documentation group-documentation custom-set custom-get custom-options custom-requests custom-group custom-prefix custom-tag custom-links custom-version saved-value theme-value theme-face)) (cl-remprop symbol prop))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; A naughty hack to completion.el ;; ;; At the moment IMO completion too eagerly adds stuff to ;; its database: the completion-before-command function ;; makes every suffix be added as a completion! (eval-after-load "completion" '(defun completion-before-command () (if (and (symbolp this-command) (get this-command 'completion-function)) (funcall (get this-command 'completion-function))))) (provide 'proof-compat) ;;; proof-compat.el ends here PG-4.5/lib/scomint.el000066400000000000000000000270371426357011200144460ustar00rootroot00000000000000;;; scomint.el --- Simplified comint for less interactive shells ;; This file is part of Proof General. ;; Portions © Copyright 1994-2012 David Aspinall and University of Edinburgh ;; Portions © Copyright 2003, 2012, 2014 Free Software Foundation, Inc. ;; Portions © Copyright 2001-2017 Pierre Courtieu ;; Portions © Copyright 2010, 2016 Erik Martin-Dorel ;; Portions © Copyright 2011-2013, 2016-2017 Hendrik Tews ;; Portions © Copyright 2015-2017 Clément Pit-Claudel ;; Author: David Aspinall ;; SPDX-License-Identifier: GPL-3.0-or-later ;;; Commentary: ;; ;; This is a heavily simplified comint for Proof General. ;; Much of the code is taken from comint.el. ;; ;; The reason to provide this is to remove some of ;; the interactive features which are otherwise ;; hard to disentangle. ;; ;;; Code: (defvar scomint-buffer-maximum-size 800000 "The maximum size in characters for SComint buffers. SComint buffers are truncated from the top to be no greater than this number, if non-nil.") (defvar scomint-output-filter-functions nil "Functions to call after output is inserted into the buffer.") (defvar scomint-mode-map (let ((map (make-sparse-keymap))) (define-key map "\C-m" 'scomint-send-input) (define-key map "\C-c\C-c" 'scomint-interrupt-process) map)) (defvar scomint-last-input-start nil) (defvar scomint-last-input-end nil) (defvar scomint-last-output-start nil) (defvar scomint-exec-hook nil "Hook run each time a process is exec'd by `scomint-exec'. This is called after the process is cranked up. It is useful for things that must be done each time a process is executed in a Comint mode buffer.") (put 'scomint-output-filter-functions 'permanent-local t) (put 'scomint-mode 'mode-class 'special) (define-derived-mode scomint-mode fundamental-mode "SComint" "Major mode for interacting with a background inferior interpreter. Interpreter name is same as buffer name, sans the asterisks. Return at end of buffer sends line as input. Return not at end copies rest of line to end and sends it. \\{scomint-mode-map} Entry to this mode runs the hooks on `scomint-mode-hook'." (setq mode-line-process '(":%s")) (set (make-local-variable 'scomint-last-input-start) (point-min-marker)) (set (make-local-variable 'scomint-last-input-end) (point-min-marker)) (set (make-local-variable 'scomint-last-output-start) (make-marker)) (set (make-local-variable 'window-point-insertion-type) t) ; Emacs 23-ism? (make-local-variable 'font-lock-defaults) (setq font-lock-defaults '(nil t)) (add-hook 'change-major-mode-hook 'font-lock-defontify nil t) (set (make-local-variable 'next-line-add-newlines) nil)) (defsubst scomint-check-proc (buffer) "Return non-nil if there is a living process associated w/buffer BUFFER. Living means the status is `open', `run', or `stop'. BUFFER can be either a buffer or the name of one." (let ((proc (get-buffer-process buffer))) (and proc (memq (process-status proc) '(open run stop))))) ;;;###autoload (defun scomint-make-in-buffer (name buffer program &optional startfile &rest switches) "Make a Comint process NAME in BUFFER, running PROGRAM. If BUFFER is nil, it defaults to NAME surrounded by `*'s. PROGRAM should be either a string denoting an executable program to create via `start-file-process', or a cons pair of the form (HOST . SERVICE) denoting a TCP connection to be opened via `open-network-stream'. If there is already a running process in that buffer, it is not restarted. Optional fourth arg STARTFILE is the name of a file to send the contents of to the process. If PROGRAM is a string, the remaining SWITCHES are arguments to PROGRAM." (unless (or (fboundp 'start-process) (fboundp 'start-file-process)) (error "Multi-processing is not supported for this system")) (setq buffer (get-buffer-create (or buffer (concat "*" name "*")))) ;; If no process, or nuked process, crank up a new one and put buffer in ;; comint mode. Otherwise, leave buffer and existing process alone. (unless (scomint-check-proc buffer) (with-current-buffer buffer (unless (derived-mode-p 'scomint-mode) (scomint-mode))) ; Install local vars, mode, keymap, ... (scomint-exec buffer name program startfile switches)) buffer) ;;;###autoload (defun scomint-make (name program &optional startfile &rest switches) "Make a Comint process NAME in a buffer, running PROGRAM. The name of the buffer is made by surrounding NAME with `*'s. PROGRAM should be either a string denoting an executable program to create via `start-file-process', or a cons pair of the form (HOST . SERVICE) denoting a TCP connection to be opened via `open-network-stream'. If there is already a running process in that buffer, it is not restarted. Optional third arg STARTFILE is the name of a file to send the contents of the process to. If PROGRAM is a string, the remaining SWITCHES are arguments to PROGRAM." (apply #'scomint-make-in-buffer name nil program startfile switches)) (defun scomint-exec (buffer name command startfile switches) "In buffer BUFFER, start up a process named NAME for Comint modes. Runs the given COMMAND with output to STARTFILE. SWITCHES contains the arguments passed to the COMMAND. Blasts any old process running in the buffer. Doesn't set the buffer mode. You can use this to cheaply run a series of processes in the same Comint buffer. The hook `scomint-exec-hook' is run after each exec." (with-current-buffer buffer (let ((proc (get-buffer-process buffer))) ; Blast any old process. (if proc (delete-process proc))) ;; Crank up a new process (let ((proc (if (consp command) (open-network-stream name buffer (car command) (cdr command)) (scomint-exec-1 name buffer command switches)))) (set-process-filter proc 'scomint-output-filter) ;; Jump to the end, and set the process mark. (goto-char (point-max)) (set-marker (process-mark proc) (point)) ;; Feed it the startfile. (cond (startfile ;;This is guaranteed to wait long enough ;;but has bad results if the comint does not prompt at all ;; (while (= size (buffer-size)) ;; (sleep-for 1)) ;;I hope 1 second is enough! (sleep-for 1) (goto-char (point-max)) (insert-file-contents startfile) (setq startfile (buffer-substring (point) (point-max))) (delete-region (point) (point-max)) (scomint-send-string proc startfile))) (run-hooks 'scomint-exec-hook) buffer))) ;; This auxiliary function cranks up the process for comint-exec in ;; the appropriate environment. (defun scomint-exec-1 (name buffer command switches) (let ((process-environment (nconc ;; If using termcap, we specify `emacs' as the terminal type ;; because that lets us specify a width. ;; If using terminfo, we specify `dumb' because that is ;; a defined terminal type. `emacs' is not a defined terminal type ;; and there is no way for us to define it here. ;; Some programs that use terminfo get very confused ;; if TERM is not a valid terminal type. ;; ;; There is similar code in compile.el. (if (and (boundp 'system-uses-terminfo) system-uses-terminfo) (list "TERM=dumb" "TERMCAP=" (format "COLUMNS=%d" (window-width))) (list "TERM=emacs" (format "TERMCAP=emacs:co#%d:tc=unknown:" (window-width)))) (unless (getenv "EMACS") (list "EMACS=t")) (list (format "INSIDE_EMACS=%s,comint" emacs-version)) process-environment)) (default-directory (if (file-accessible-directory-p default-directory) default-directory "/")) proc decoding encoding changed) (let ((exec-path (if (file-name-directory command) ;; If the command has slashes, make sure we ;; first look relative to the current directory. (cons default-directory exec-path) exec-path))) (setq proc (apply (if (fboundp 'start-file-process) ;; da: start-file-process is Emacs23 only 'start-file-process 'start-process) name buffer command switches))) ;; Some file name handler cannot start a process, fe ange-ftp. (unless (processp proc) (error "No process started")) (let ((coding-systems (process-coding-system proc))) (setq decoding (car coding-systems) encoding (cdr coding-systems))) ;; Even if start-file-process left the coding system for encoding data ;; sent from the process undecided, we had better use the same one ;; as what we use for decoding. But, we should suppress EOL ;; conversion. (if (and decoding (not encoding)) (setq encoding (coding-system-change-eol-conversion decoding 'unix) changed t)) (if changed (set-process-coding-system proc decoding encoding)) proc)) (defalias 'scomint-send-string 'process-send-string) (defun scomint-send-eof () "Send an EOF to the current buffer's process." (interactive) (condition-case nil ;; this fails if process has died already (scomint-send-input t t) (error nil)) (process-send-eof)) (defun scomint-send-input (&optional no-newline artificial) "Send input to process. After the process output mark, sends all text from the process mark to point as input to the process. This command also sends and inserts a final newline, unless NO-NEWLINE is non-nil." (interactive) ;; Note that the input string does not include its terminal newline. (let ((proc (get-buffer-process (current-buffer)))) (let* ((pmark (process-mark proc)) (start (marker-position pmark))) (unless (< (point) start) ;; Update the markers before we send the input ;; in case we get output amidst sending the input. (set-marker scomint-last-input-start pmark) (unless no-newline (insert ?\n)) (set-marker scomint-last-input-end (point)) (set-marker (process-mark proc) (point)) (process-send-region proc start (point)))))) ;; TODO: run this on a timer rather than on every I/O (defun scomint-truncate-buffer (&optional string) "Truncate the buffer to `scomint-buffer-maximum-size'." (interactive) (if scomint-buffer-maximum-size (save-excursion (save-restriction (widen) (if (> (point-max) scomint-buffer-maximum-size) (let ((inhibit-read-only t)) (delete-region (point-min) (- (point-max) scomint-buffer-maximum-size)))))))) (defun scomint-strip-ctrl-m (&optional string) "Strip trailing `^M' characters from the current output group." (interactive) (let ((pmark (process-mark (get-buffer-process (current-buffer))))) (save-excursion (condition-case nil (goto-char (if (called-interactively-p 'any) scomint-last-input-end scomint-last-output-start)) (error nil)) (while (re-search-forward "\r+$" pmark t) (replace-match "" t t))))) ;; The purpose of using this filter for comint processes is to keep ;; comint-last-input-end from moving forward when output is inserted. (defun scomint-output-filter (process string) (let ((oprocbuf (process-buffer process))) ;; First check for killed buffer or no input. (when (and string (buffer-live-p oprocbuf)) (with-current-buffer oprocbuf ;; Insert STRING (let (;; The point should float after any insertion we do. (saved-point (copy-marker (point) t))) (goto-char (process-mark process)) (set-marker scomint-last-output-start (point)) (insert string) ;; Advance process-mark (set-marker (process-mark process) (point)) ;; Run these hooks with point where the user had it. (goto-char saved-point) (run-hook-with-args 'scomint-output-filter-functions string) ;; (scomint-truncate-buffer) (set-marker saved-point (point))))))) (defun scomint-interrupt-process () (interactive) (interrupt-process)) (provide 'scomint) ;;; scomint.el ends here PG-4.5/lib/span.el000066400000000000000000000206301426357011200137230ustar00rootroot00000000000000;;; span.el --- Datatype of "spans" for Proof General -*- lexical-binding:t -*- ;; This file is part of Proof General. ;; Portions © Copyright 1994-2012 David Aspinall and University of Edinburgh ;; Portions © Copyright 2003-2021 Free Software Foundation, Inc. ;; Portions © Copyright 2001-2017 Pierre Courtieu ;; Portions © Copyright 2010, 2016 Erik Martin-Dorel ;; Portions © Copyright 2011-2013, 2016-2017 Hendrik Tews ;; Portions © Copyright 2015-2017 Clément Pit-Claudel ;; Author: Healfdene Goguen ;; Maintainer: David Aspinall ;; SPDX-License-Identifier: GPL-3.0-or-later ;;; Commentary: ;; ;; Spans are our abstraction of extents/overlays. Nowadays ;; we implement them directly with overlays. ;; ;; FIXME: eliminate aliases and directly use overlays ;; ;;; Code: (defalias 'span-start #'overlay-start) (defalias 'span-end #'overlay-end) (defalias 'span-set-property #'overlay-put) (defalias 'span-property #'overlay-get) (defun span-make (&rest args) (let ((span (apply #'make-overlay args))) (span-set-property span 'pg-span t) span)) (defalias 'span-detach #'delete-overlay) (defalias 'span-set-endpoints #'move-overlay) (defalias 'span-buffer #'overlay-buffer) (defun span-p (ol) "Check if an overlay OL belongs to PG." (overlay-get ol 'pg-span)) (defun span-read-only-hook (&rest _) (unless inhibit-read-only (user-error "Region is read-only"))) (defun span-read-only (span) "Set SPAN to be read only." ;; Note: using the standard 'read-only property does not work. ;; (overlay-put span 'read-only t)) (span-set-property span 'modification-hooks '(span-read-only-hook)) (span-set-property span 'insert-in-front-hooks '(span-read-only-hook))) (defun span-write-warning (span fun) "Give a warning message when SPAN is changed, unless `inhibit-read-only' is non-nil." (let ((funs (list (lambda (_span afterp beg end &rest _) (if (and (not afterp) (not inhibit-read-only)) (funcall fun beg end)))))) (span-set-property span 'modification-hooks funs) (span-set-property span 'insert-in-front-hooks funs))) ;; We use end first because proof-locked-queue is often changed, and ;; its starting point is always 1 (defun span-lt (s u) (or (< (span-end s) (span-end u)) (and (eq (span-end s) (span-end u)) (< (span-start s) (span-start u))))) (defun spans-filter (overlays prop &optional val) "Filter OVERLAYS to those with PROP (optionally matching VAL)." (let (ols) (dolist (ol overlays) (when (span-p ol) (let* ((propval (overlay-get ol prop)) (keep (if val (eq propval val) propval))) (when keep (push ol ols))))) ols)) (defun spans-at-point-prop (pt prop) (spans-filter (overlays-at pt) prop)) (defun spans-at-region-prop (start end prop) "Return a list of the spans in START END with PROP." (spans-filter (overlays-in start end) prop)) (defun span-at (pt prop) "Return some SPAN at point PT with property PROP." (car-safe (spans-at-point-prop pt prop))) (defun span-delete (span) "Run the 'span-delete-actions and delete SPAN." (mapc #'funcall (span-property span 'span-delete-actions)) (delete-overlay span)) (defun span-add-delete-action (span action) "Add ACTION to the list of functions called when SPAN is deleted." (span-set-property span 'span-delete-actions (cons action (span-property span 'span-delete-actions)))) ;; The next two change ordering of list of spans: (defun span-mapcar-spans (fn start end prop) "Map function FN over spans between START and END with property PROP." (mapcar fn (spans-at-region-prop start end prop))) (defun span-mapc-spans (fn start end prop) "Apply function FN to spans between START and END with property PROP." (mapc fn (spans-at-region-prop start end prop))) (defun span-mapcar-spans-inorder (fn start end prop) "Map function FN over spans between START and END with property PROP." (mapcar fn (sort (spans-at-region-prop start end prop) 'span-lt))) (defun span-at-before (pt prop) "Return the smallest SPAN at before PT with property PROP. A span is before PT if it begins before the character before PT." (let ((ols (if (eq (point-min) pt) nil ;; (overlays-at pt) (overlays-in (1- pt) pt)))) (setq ols (spans-filter ols prop)) ;; Eliminate the case of an empty overlay at (1- pt). (dolist (ol (prog1 ols (setq ols nil))) (if (>= (overlay-end ol) pt) (push ol ols))) ;; "Get the smallest". I have no idea what that means, so I just do ;; something somewhat random but vaguely meaningful. -Stef (car (last (sort ols 'span-lt))))) (defun prev-span (span prop) "Return span before SPAN with property PROP." (span-at-before (span-start span) prop)) ; overlays are [start, end) (defun next-span (span prop) "Return span after SPAN with property PROP." ;; Presuming the span-extents.el is the reference, its code does the ;; same as the code below. (span-at (span-end span) prop)) (defun span-live-p (span) "Return non-nil if SPAN is in a live buffer." (and span (overlay-buffer span) (buffer-live-p (overlay-buffer span)))) ;; (defun span-raise (_span) ;; "Set priority of SPAN to make it appear above other spans." ;; ;; FIXME: Emacs already uses a "shorter goes above" which takes care of ;; ;; preventing a span from seeing another. So don't play with ;; ;; priorities, please! ;; ;; (span-set-property span 'priority 100) ;; ) (defun span-string (span) (with-current-buffer (overlay-buffer span) (buffer-substring-no-properties (overlay-start span) (overlay-end span)))) (defun set-span-properties (span plist) "Set SPAN's properties from PLIST which is a plist." (while plist (overlay-put span (car plist) (cadr plist)) (setq plist (cddr plist)))) (defun span-at-event (event &optional prop) "Find a span at position of EVENT, with property PROP (default 'span)." (car (spans-filter (overlays-at (posn-point (event-start event))) (or prop 'span)))) (defun fold-spans (f &optional buffer from to maparg _ignored-flags prop val) (with-current-buffer (or buffer (current-buffer)) (let ((ols (overlays-in (or from (point-min)) (or to (point-max)))) res) ;; Check the PROP. (setq ols (spans-filter ols prop val)) ;; Iterate in order. (setq ols (sort ols 'span-lt)) (while (and ols (not (setq res (funcall f (pop ols) maparg))))) res))) (defun span-detached-p (span) "Is this SPAN detached? nil for no, t for yes." (null (overlay-buffer span))) (defun set-span-face (span face) "Set the FACE of a SPAN." (overlay-put span 'face face)) (defun set-span-keymap (span map) "Set the keymap of SPAN to MAP." (overlay-put span 'keymap map)) ;; ;; Generic functions built on low-level concrete ones. ;; (defun span-delete-spans (start end prop) "Delete all spans between START and END with property PROP set." (span-mapc-spans 'span-delete start end prop)) (defun span-property-safe (span name) "Get the property of span SPAN with property name NAME. Like ‘span-property’, but return nil if SPAN is nil." (and span (span-property span name))) (defun span-set-start (span value) "Set the start point of SPAN to VALUE." (span-set-endpoints span value (span-end span))) (defun span-set-end (span value) "Set the end point of SPAN to VALUE." (span-set-endpoints span (span-start span) value)) ;; ;; Handy overlay utils ;; (defun span-make-self-removing-span (beg end &rest props) "Add a self-removing span from BEG to END with properties PROPS. The span will remove itself after a timeout of 2 seconds." (let ((ol (span-make beg end))) (while props (overlay-put ol (car props) (cadr props)) (setq props (cddr props))) (add-timeout 2 'delete-overlay ol) ol)) (defun span-delete-self-modification-hook (span &rest _) "Hook for overlay modification-hooks, which deletes SPAN." (if (span-live-p span) (span-delete span))) (defun span-make-modifying-removing-span (beg end &rest props) "Add a self-removing span from BEG to END with properties PROPS. The span will remove itself after any edit within its range. Return the span." (let ((ol (span-make beg end))) (while props (overlay-put ol (car props) (cadr props)) (setq props (cddr props))) (span-set-property ol 'modification-hooks (list #'span-delete-self-modification-hook)) ol)) (provide 'span) ;;; span.el ends here PG-4.5/lib/texi-docstring-magic.el000066400000000000000000000376511426357011200170160ustar00rootroot00000000000000;;; texi-docstring-magic.el --- munge internal docstrings into texi -*- lexical-binding: t; -*- ;; This file is part of Proof General. ;; Portions © Copyright 1994-2012 David Aspinall and University of Edinburgh ;; Portions © Copyright 2003-2021 Free Software Foundation, Inc. ;; Portions © Copyright 2001-2017 Pierre Courtieu ;; Portions © Copyright 2010, 2016 Erik Martin-Dorel ;; Portions © Copyright 2011-2013, 2016-2017 Hendrik Tews ;; Portions © Copyright 2015-2017 Clément Pit-Claudel ;; Author: David Aspinall ;; Keywords: lisp, docs, tex ;; SPDX-License-Identifier: GPL-3.0-or-later ;; This file is distributed under the terms of the GNU General Public ;; License, Version 3 or later. Find a copy of the GPL with your version of ;; GNU Emacs or Texinfo. ;;; Commentary: ;; ;; This package generates Texinfo source fragments from Emacs ;; docstrings. This avoids documenting functions and variables in ;; more than one place, and automatically adds Texinfo markup to ;; docstrings. ;; ;; It relies heavily on you following the Elisp documentation ;; conventions to produce sensible output, check the Elisp manual ;; for details. In brief: ;; ;; * The first line of a docstring should be a complete sentence. ;; * Arguments to functions should be written in upper case: ARG1..ARGN ;; * User options (variables users may want to set) should have docstrings ;; beginning with an asterisk. ;; ;; Usage: ;; ;; Write comments of the form: ;; ;; @c TEXI DOCSTRING MAGIC: my-package-function-or-variable-name ;; ;; In your texi source, mypackage.texi. From within an Emacs session ;; where my-package is loaded, visit mypackage.texi and run ;; M-x texi-docstring-magic to update all of the documentation strings. ;; ;; This will insert @defopt, @deffn and the like underneath the ;; magic comment strings. ;; ;; The default value for user options will be printed. ;; ;; Symbols are recognized if they are defined for faces, functions, ;; or variables (in that order). ;; ;; Automatic markup rules: ;; ;; 1. Indented lines are gathered into a @lisp environment. ;; 2. Pieces of text `stuff' or surrounded in quotes marked up with @samp. ;; 3. Words *emphasized* are made @strong{emphasized} ;; 4. Words sym-bol which are symbols become @code{sym-bol}. ;; 5. Upper cased words ARG corresponding to arguments become @var{arg}. ;; In fact, you can use any word longer than three letters, so that ;; metavariables can be used easily. ;; FIXME: to escape this, use `ARG' ;; 6. Words 'sym which are lisp-quoted are marked with @code{'sym}. ;; ;; ----- ;; ;; Useful key binding when writing Texinfo: ;; ;; (define-key TeXinfo-mode-map "C-cC-d" 'texi-docstring-magic-insert-magic) ;; ;; ----- ;; ;; Useful enhancements to do: ;; ;; * Tweak replacement: at the moment it skips blank lines ;; under magic comment. ;; * Use customize properties (e.g. group, simple types) ;; * Look for a "texi-docstring" property for symbols ;; so TeXInfo can be defined directly in case automatic markup ;; goes badly wrong. ;; * Add tags to special comments so that user can specify face, ;; function, or variable binding for a symbol in case more than ;; one binding exists. ;; ;; ------ ;; ;; Thanks to: Christoph Conrad for an Emacs compatibility fix. ;; ;; ;;; Code: (defun texi-docstring-magic-find-face (face) "Return non-nil if FACE is a face name; nil otherwise. A face name can be a string or a symbol. Compatibility between FSF Emacs and XEmacs." (or (facep face) (and (fboundp 'find-face) (find-face face)))) (defun texi-docstring-magic-splice-sep (strings sep) "Return concatenation of STRINGS spliced together with separator SEP." (let (str) (while strings (setq str (concat str (car strings))) (if (cdr strings) (setq str (concat str sep))) (setq strings (cdr strings))) str)) (defvar texi-docstring--args) (defvar texi-docstring--in-quoted-region) (defconst texi-docstring-magic-munge-table `(;; 0. Escape @, { and } characters ("\\(@\\)" t "@@") ("\\({\\)" t "@{") ("\\(}\\)" t "@}") ;; 1. Indented lines are gathered into @lisp environment. ("^\\(\n\\|.+\\)$" t ,(lambda (docstring) (let ((line (match-string 0 docstring))) (if (save-match-data (string-match "^[ \t]" line)) ;; whitespace (if texi-docstring--in-quoted-region line (setq texi-docstring--in-quoted-region t) (concat "@lisp\n" line)) ;; non-white space/carriage return (if (and texi-docstring--in-quoted-region (not (equal line "\n"))) (progn (setq texi-docstring--in-quoted-region nil) (concat "@end lisp\n" line)) line))))) ;; 2. Pieces of text `stuff' or surrounded in quotes ;; are marked up with @samp. NB: Must be backquote ;; followed by forward quote for this to work. ;; Can't use two forward quotes else problems with ;; symbols. ;; Odd hack: because ' is a word constituent in text/texinfo ;; mode, putting this first enables the recognition of args ;; and symbols put inside quotes. ("\\(`\\([^']+\\)'\\)" t ,(lambda (docstring) (concat "@samp{" (match-string 2 docstring) "}"))) ;; 3. Words *emphasized* are made @strong{emphasized} ("\\(\\*\\(\\w+\\)\\*\\)" t ,(lambda (docstring) (concat "@strong{" (match-string 2 docstring) "}"))) ;; 4. Words sym-bol which are symbols become @code{sym-bol}. ;; Must have at least one hyphen to be recognized, ;; terminated in whitespace, end of line, or punctuation. ;; Only consider symbols made from word constituents ;; and hyphen. ("\\(\\(\\w+-\\(\\w\\|-\\)+\\)\\)\\(\\s)\\|\\s-\\|\\s.\\|$\\)" ,(lambda (docstring) (or (boundp (intern (match-string 2 docstring))) (fboundp (intern (match-string 2 docstring))))) ,(lambda (docstring) (concat "@code{" (match-string 2 docstring) "}" (match-string 4 docstring)))) ;; 5. Upper cased words ARG corresponding to arguments become ;; @var{arg} ;; In fact, include any word so long as it is more than 3 characters ;; long. (Comes after symbols to avoid recognizing the ;; lowercased form of an argument as a symbol) ;; FIXME: maybe we don't want to downcase stuff already ;; inside @samp ;; FIXME: should - terminate? should _ be included? ("\\([A-Z0-9_\\-]+\\)\\(/\\|)\\|}\\|\\s-\\|\\s.\\|$\\)" ,(lambda (docstring) (or (> (length (match-string 1 docstring)) 3) (member (downcase (match-string 1 docstring)) texi-docstring--args))) ,(lambda (docstring) (concat "@var{" (downcase (match-string 1 docstring)) "}" (match-string 2 docstring)))) ;; 6. Words 'sym which are lisp quoted are ;; marked with @code. ("\\(\\(\\s-\\|^\\)'\\(\\(\\w\\|-\\)+\\)\\)\\(\\s)\\|\\s-\\|\\s.\\|$\\)" t ,(lambda (docstring) (concat (match-string 2 docstring) "@code{'" (match-string 3 docstring) "}" (match-string 5 docstring)))) ;; 7,8. Clean up for @lisp environments left with spurious newlines ;; after 1. ("\\(\\(^\\s-*$\\)\n@lisp\\)" t "@lisp") ("\\(\\(^\\s-*$\\)\n@end lisp\\)" t "@end lisp") ;; 9. Hack to remove @samp{@var{...}} sequences. ;; Changed to just @samp of uppercase. ("\\(@samp{@var{\\([^}]+\\)}}\\)" t ,(lambda (docstring) (concat "@samp{" (upcase (match-string 2 docstring)) "}")))) "Table of regexp matches and replacements used to markup docstrings. Format of table is a list of elements of the form (REGEXP PREDICATE REPLACEMENT) If REGEXP matches and PREDICATE holds, then REPLACEMENT is used to replace the match. PREDICATE and REPLACEMENT can be functions taking the docstring as argument and they can use the dynamically scoped variables `texi-docstring--args' and `texi-docstring--in-quoted-region'. Match string 1 is assumed to determine the length of the matched item, hence where parsing restarts from. The replacement must cover the whole match (match string 0), including any whitespace included to delimit matches.") (defun texi-docstring-magic-untabify (string) "Convert tabs in STRING into multiple spaces." (with-temp-buffer (insert string) (untabify (point-min) (point-max)) (buffer-string))) (defun texi-docstring--funcall (f arg) (if (functionp f) (funcall f arg) f)) (defun texi-docstring-magic-munge-docstring (docstring args) "Markup DOCSTRING for texi according to regexp matches." ;; FIXME(EMD): seems buggy as ARGS is not used (let ((case-fold-search nil) (texi-docstring--args args)) (setq docstring (texi-docstring-magic-untabify docstring)) (dolist (test texi-docstring-magic-munge-table) (let ((regexp (nth 0 test)) (predicate (nth 1 test)) (replace (nth 2 test)) (i 0) texi-docstring--in-quoted-region) (while (and (< i (length docstring)) (string-match regexp docstring i)) (setq i (match-end 1)) (if (texi-docstring--funcall predicate docstring) (let* ((origlength (- (match-end 0) (match-beginning 0))) (replacement (texi-docstring--funcall replace docstring)) (newlength (length replacement))) (setq docstring (replace-match replacement t t docstring)) (setq i (+ i (- newlength origlength)))))) (if texi-docstring--in-quoted-region (setq docstring (concat docstring "\n@end lisp")))))) ;; Force a new line after (what should be) the first sentence, ;; if not already a new paragraph. (let* ((pos (string-match "\n" docstring)) (needscr (and pos (not (string= "\n" (substring docstring (1+ pos) (+ pos 2))))))) (if (and pos needscr) (concat (substring docstring 0 pos) "@*\n" (substring docstring (1+ pos))) docstring))) (defun texi-docstring-magic-texi (env grp name docstring args &optional endtext) "Make a texi def environment ENV for entity NAME with DOCSTRING." (concat "@def" env (if grp (concat " " grp) "") " " name " " (texi-docstring-magic-splice-sep args " ") ;; " " ;; (texi-docstring-magic-splice-sep extras " ") "\n" (texi-docstring-magic-munge-docstring docstring args) "\n" (or endtext "") "@end def" env "\n")) (defun texi-docstring-magic-format-default (default) "Make a default value string for the value DEFAULT. Markup as @code{stuff} or @lisp stuff @end Lisp." ;; NB: might be nice to use a 'default-value-description ;; property here, in case the default value is computed. (let ((text (format "%S" default))) (concat "\nThe default value is " (if (string-match "\n" text) ;; Carriage return will break @code, use @lisp (if (stringp default) (concat "the string: \n@lisp\n" default "\n@end lisp\n") (concat "the value: \n@lisp\n" text "\n@end lisp\n")) (concat "@code{" text "}.\n"))))) (defun texi-docstring-magic-texi-for (symbol &optional noerror) (cond ;; Faces ((texi-docstring-magic-find-face symbol) (let* ((face symbol) (name (symbol-name face)) (docstring (or (face-doc-string face) "Not documented.")) (useropt (eq ?* (string-to-char docstring)))) ;; Chop off user option setting (if useropt (setq docstring (substring docstring 1))) (texi-docstring-magic-texi "fn" "Face" name docstring nil))) ((boundp symbol) ;; Variables. (let* ((variable symbol) (name (symbol-name variable)) (docstring (or (documentation-property variable 'variable-documentation) "Not documented.")) (useropt (eq ?* (string-to-char docstring))) (default (if useropt (texi-docstring-magic-format-default (default-value symbol))))) ;; Chop off user option setting (if useropt (setq docstring (substring docstring 1))) (texi-docstring-magic-texi (if useropt "opt" "var") nil name docstring nil default))) ((fboundp symbol) ;; Functions. Functions with same name as variables are documented ;; as variables. ;; We don't handle macros, aliases, or compiled fns properly. (let* ((function symbol) (name (symbol-name function)) (docstring (or (documentation function) "Not documented.")) (def (symbol-function function)) (macrop (eq 'macro (car-safe def))) (argsyms (cond ((eq (car-safe def) 'lambda) (nth 1 def)) ((eq (car-safe def) 'closure) (nth 2 def)))) (args (mapcar #'symbol-name argsyms))) (cond ((commandp function) (texi-docstring-magic-texi "fn" "Command" name docstring args)) (macrop (texi-docstring-magic-texi "fn" "Macro" name docstring args)) (t (texi-docstring-magic-texi "un" nil name docstring args))))) (noerror (message "Warning: symbol `%s' not defined" (symbol-name symbol)) "") (t (error "Don't know anything about symbol %s" (symbol-name symbol))))) (defconst texi-docstring-magic-comment "@c TEXI DOCSTRING MAGIC:" "Magic string in a texi buffer expanded into @defopt, or @deffn.") ;;;###autoload (defun texi-docstring-magic (&optional noerror) "Update all texi docstring magic annotations in buffer. With prefix arg, no errors on unknown symbols. (This results in @def .. @end being deleted if not known)." (interactive "P") (save-excursion (goto-char (point-min)) ;; Since emacs 26 grave accent and apostrophe are translated to ;; unicode single quotation marks, \"`foo'" becomes "‘foo’", see ;; Section Documentation -> Text Quoting Style (24.4 in emacs 27) ;; in the elisp manual. This translation happens apparently ;; already when accessing the documentation strings with ;; `documentation-property' or similar functions; breaking the ;; regular expressions for transforming the doc strings in this ;; module. Set `text-quoting-style' to get the doc strings without ;; this translation. (let ((text-quoting-style 'grave) (magic (concat "^" (regexp-quote texi-docstring-magic-comment) "\\s-*\\(\\(\\w\\|-\\)+\\)[ \t]*$")) p symbol deleted) (while (re-search-forward magic nil t) (setq symbol (intern (match-string 1))) (forward-line) (setq p (point)) ;; delete any whitespace following magic comment (skip-chars-forward " \n\t") (delete-region p (point)) ;; If comment already followed by an environment, delete it. (if (and (looking-at "@def\\(\\w+\\)\\s-") (search-forward (concat "@end def" (match-string 1)) nil t)) (progn (forward-line) (delete-region p (point)) (setq deleted t))) (insert (texi-docstring-magic-texi-for symbol noerror)) (unless deleted ;; Follow newly inserted @def with a single blank. (insert "\n")))))) (defun texi-docstring-magic-face-at-point () (ignore-errors (let ((stab (syntax-table))) (unwind-protect (save-excursion (set-syntax-table emacs-lisp-mode-syntax-table) (or (not (zerop (skip-syntax-backward "_w"))) (eq (char-syntax (char-after (point))) ?w) (eq (char-syntax (char-after (point))) ?_) (forward-sexp -1)) (skip-chars-forward "'") (let ((obj (read (current-buffer)))) (and (symbolp obj) (texi-docstring-magic-find-face obj) obj))) (set-syntax-table stab))))) (defun texi-docstring-magic-insert-magic (symbol) (interactive (let* ((v (or (variable-at-point) (and (fboundp 'function-at-point) (function-at-point)) (and (fboundp 'function-called-at-point) (function-called-at-point)) (texi-docstring-magic-face-at-point))) (val (let ((enable-recursive-minibuffers t)) (completing-read (if v (format "Magic docstring for symbol (default %s): " v) "Magic docstring for symbol: ") obarray (lambda (sym) (or (boundp sym) (fboundp sym) (texi-docstring-magic-find-face sym))) t nil 'variable-history)))) (list (if (equal val "") v (intern val))))) (insert "\n" texi-docstring-magic-comment " " (symbol-name symbol))) (provide 'texi-docstring-magic) (provide 'texi-docstring-magic) ;;; texi-docstring-magic.el ends here PG-4.5/lib/unicode-chars.el000066400000000000000000007423011426357011200155140ustar00rootroot00000000000000;;; unicode-chars.el --- table of Unicode characters ;; This file is part of Proof General. ;; Portions © Copyright 1994-2012 David Aspinall and University of Edinburgh ;; Portions © Copyright 2003, 2012, 2014 Free Software Foundation, Inc. ;; Portions © Copyright 2001-2017 Pierre Courtieu ;; Portions © Copyright 2010, 2016 Erik Martin-Dorel ;; Portions © Copyright 2011-2013, 2016-2017 Hendrik Tews ;; Portions © Copyright 2015-2017 Clément Pit-Claudel ;; Author: David Aspinall ;;; Commentary: ;; ;; Adapted from Norman Walsh's unichars.el (iso8879 names removed) ;; ;; The names are standard, see ;; http://www.unicode.org/unicode/standard/standard.html ;; http://www.unicode.org/Public/UNIDATA ;;; Code: (defvar unicode-chars-alist '(;Unicode name Codept ("NULL" . #x000000) ("START OF HEADING" . #x000001) ("START OF TEXT" . #x000002) ("END OF TEXT" . #x000003) ("END OF TRANSMISSION" . #x000004) ("ENQUIRY" . #x000005) ("ACKNOWLEDGE" . #x000006) ("BELL" . #x000007) ("BACKSPACE" . #x000008) ("CHARACTER TABULATION" . #x000009) ("LINE FEED (LF)" . #x00000a) ("LINE TABULATION" . #x00000b) ("FORM FEED (FF)" . #x00000c) ("CARRIAGE RETURN (CR)" . #x00000d) ("SHIFT OUT" . #x00000e) ("SHIFT IN" . #x00000f) ("DATA LINK ESCAPE" . #x000010) ("DEVICE CONTROL ONE" . #x000011) ("DEVICE CONTROL TWO" . #x000012) ("DEVICE CONTROL THREE" . #x000013) ("DEVICE CONTROL FOUR" . #x000014) ("NEGATIVE ACKNOWLEDGE" . #x000015) ("SYNCHRONOUS IDLE" . #x000016) ("END OF TRANSMISSION BLOCK;" . #x000017) ("CANCEL" . #x000018) ("END OF MEDIUM" . #x000019) ("SUBSTITUTE" . #x00001a) ("ESCAPE" . #x00001b) ("INFORMATION SEPARATOR FOUR" . #x00001c) ("INFORMATION SEPARATOR THREE" . #x00001d) ("INFORMATION SEPARATOR TWO" . #x00001e) ("INFORMATION SEPARATOR ONE" . #x00001f) ("SPACE" . #x000020) ("EXCLAMATION MARK" . #x000021) ("QUOTATION MARK" . #x000022) ("NUMBER SIGN" . #x000023) ("DOLLAR SIGN" . #x000024) ("PERCENT SIGN" . #x000025) ("AMPERSAND" . #x000026) ("APOSTROPHE" . #x000027) ("LEFT PARENTHESIS" . #x000028) ("RIGHT PARENTHESIS" . #x000029) ("ASTERISK" . #x00002a) ("PLUS SIGN" . #x00002b) ("COMMA" . #x00002c) ("HYPHEN-MINUS" . #x00002d) ("FULL STOP" . #x00002e) ("SOLIDUS" . #x00002f) ("DIGIT ZERO" . #x000030) ("DIGIT ONE" . #x000031) ("DIGIT TWO" . #x000032) ("DIGIT THREE" . #x000033) ("DIGIT FOUR" . #x000034) ("DIGIT FIVE" . #x000035) ("DIGIT SIX" . #x000036) ("DIGIT SEVEN" . #x000037) ("DIGIT EIGHT" . #x000038) ("DIGIT NINE" . #x000039) ("COLON" . #x00003a) ("SEMICOLON" . #x00003b) ("LESS-THAN SIGN" . #x00003c) ("EQUALS SIGN" . #x00003d) ("GREATER-THAN SIGN" . #x00003e) ("QUESTION MARK" . #x00003f) ("COMMERCIAL AT" . #x000040) ("LATIN CAPITAL LETTER A" . #x000041) ("LATIN CAPITAL LETTER B" . #x000042) ("LATIN CAPITAL LETTER C" . #x000043) ("LATIN CAPITAL LETTER D" . #x000044) ("LATIN CAPITAL LETTER E" . #x000045) ("LATIN CAPITAL LETTER F" . #x000046) ("LATIN CAPITAL LETTER G" . #x000047) ("LATIN CAPITAL LETTER H" . #x000048) ("LATIN CAPITAL LETTER I" . #x000049) ("LATIN CAPITAL LETTER J" . #x00004a) ("LATIN CAPITAL LETTER K" . #x00004b) ("LATIN CAPITAL LETTER L" . #x00004c) ("LATIN CAPITAL LETTER M" . #x00004d) ("LATIN CAPITAL LETTER N" . #x00004e) ("LATIN CAPITAL LETTER O" . #x00004f) ("LATIN CAPITAL LETTER P" . #x000050) ("LATIN CAPITAL LETTER Q" . #x000051) ("LATIN CAPITAL LETTER R" . #x000052) ("LATIN CAPITAL LETTER S" . #x000053) ("LATIN CAPITAL LETTER T" . #x000054) ("LATIN CAPITAL LETTER U" . #x000055) ("LATIN CAPITAL LETTER V" . #x000056) ("LATIN CAPITAL LETTER W" . #x000057) ("LATIN CAPITAL LETTER X" . #x000058) ("LATIN CAPITAL LETTER Y" . #x000059) ("LATIN CAPITAL LETTER Z" . #x00005a) ("LEFT SQUARE BRACKET" . #x00005b) ("REVERSE SOLIDUS" . #x00005c) ("RIGHT SQUARE BRACKET" . #x00005d) ("CIRCUMFLEX ACCENT" . #x00005e) ("LOW LINE" . #x00005f) ("GRAVE ACCENT" . #x000060) ("LATIN SMALL LETTER A" . #x000061) ("LATIN SMALL LETTER B" . #x000062) ("LATIN SMALL LETTER C" . #x000063) ("LATIN SMALL LETTER D" . #x000064) ("LATIN SMALL LETTER E" . #x000065) ("LATIN SMALL LETTER F" . #x000066) ("LATIN SMALL LETTER G" . #x000067) ("LATIN SMALL LETTER H" . #x000068) ("LATIN SMALL LETTER I" . #x000069) ("LATIN SMALL LETTER J" . #x00006a) ("LATIN SMALL LETTER K" . #x00006b) ("LATIN SMALL LETTER L" . #x00006c) ("LATIN SMALL LETTER M" . #x00006d) ("LATIN SMALL LETTER N" . #x00006e) ("LATIN SMALL LETTER O" . #x00006f) ("LATIN SMALL LETTER P" . #x000070) ("LATIN SMALL LETTER Q" . #x000071) ("LATIN SMALL LETTER R" . #x000072) ("LATIN SMALL LETTER S" . #x000073) ("LATIN SMALL LETTER T" . #x000074) ("LATIN SMALL LETTER U" . #x000075) ("LATIN SMALL LETTER V" . #x000076) ("LATIN SMALL LETTER W" . #x000077) ("LATIN SMALL LETTER X" . #x000078) ("LATIN SMALL LETTER Y" . #x000079) ("LATIN SMALL LETTER Z" . #x00007a) ("LEFT CURLY BRACKET" . #x00007b) ("VERTICAL LINE" . #x00007c) ("RIGHT CURLY BRACKET" . #x00007d) ("TILDE" . #x00007e) ("DELETE" . #x00007f) ("BREAK PERMITTED HERE" . #x000082) ("NO BREAK HERE" . #x000083) ("NEXT LINE (NEL)" . #x000085) ("START OF SELECTED AREA" . #x000086) ("END OF SELECTED AREA" . #x000087) ("CHARACTER TABULATION SET" . #x000088) ("CHARACTER TABULATION WITH JUSTIFICATION" . #x000089) ("LINE TABULATION SET" . #x00008a) ("PARTIAL LINE FORWARD" . #x00008b) ("PARTIAL LINE BACKWARD" . #x00008c) ("REVERSE LINE FEED" . #x00008d) ("SINGLE SHIFT TWO" . #x00008e) ("SINGLE SHIFT THREE" . #x00008f) ("DEVICE CONTROL STRING" . #x000090) ("PRIVATE USE ONE" . #x000091) ("PRIVATE USE TWO" . #x000092) ("SET TRANSMIT STATE" . #x000093) ("CANCEL CHARACTER" . #x000094) ("MESSAGE WAITING" . #x000095) ("START OF GUARDED AREA" . #x000096) ("END OF GUARDED AREA" . #x000097) ("START OF STRING" . #x000098) ("SINGLE CHARACTER INTRODUCER" . #x00009a) ("CONTROL SEQUENCE INTRODUCER" . #x00009b) ("STRING TERMINATOR" . #x00009c) ("OPERATING SYSTEM COMMAND" . #x00009d) ("PRIVACY MESSAGE" . #x00009e) ("APPLICATION PROGRAM COMMAND" . #x00009f) ("NO-BREAK SPACE" . #x0000a0) ("INVERTED EXCLAMATION MARK" . #x0000a1) ("CENT SIGN" . #x0000a2) ("POUND SIGN" . #x0000a3) ("CURRENCY SIGN" . #x0000a4) ("YEN SIGN" . #x0000a5) ("BROKEN BAR" . #x0000a6) ("SECTION SIGN" . #x0000a7) ("DIAERESIS" . #x0000a8) ("COPYRIGHT SIGN" . #x0000a9) ("FEMININE ORDINAL INDICATOR" . #x0000aa) ("LEFT-POINTING DOUBLE ANGLE QUOTATION MARK" . #x0000ab) ("NOT SIGN" . #x0000ac) ("SOFT HYPHEN" . #x0000ad) ("REGISTERED SIGN" . #x0000ae) ("MACRON" . #x0000af) ("DEGREE SIGN" . #x0000b0) ("PLUS-MINUS SIGN" . #x0000b1) ("SUPERSCRIPT TWO" . #x0000b2) ("SUPERSCRIPT THREE" . #x0000b3) ("ACUTE ACCENT" . #x0000b4) ("MICRO SIGN" . #x0000b5) ("PILCROW SIGN" . #x0000b6) ("MIDDLE DOT" . #x0000b7) ("CEDILLA" . #x0000b8) ("SUPERSCRIPT ONE" . #x0000b9) ("MASCULINE ORDINAL INDICATOR" . #x0000ba) ("RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK" . #x0000bb) ("VULGAR FRACTION ONE QUARTER" . #x0000bc) ("VULGAR FRACTION ONE HALF" . #x0000bd) ("VULGAR FRACTION THREE QUARTERS" . #x0000be) ("INVERTED QUESTION MARK" . #x0000bf) ("LATIN CAPITAL LETTER A WITH GRAVE" . #x0000c0) ("LATIN CAPITAL LETTER A WITH ACUTE" . #x0000c1) ("LATIN CAPITAL LETTER A WITH CIRCUMFLEX" . #x0000c2) ("LATIN CAPITAL LETTER A WITH TILDE" . #x0000c3) ("LATIN CAPITAL LETTER A WITH DIAERESIS" . #x0000c4) ("LATIN CAPITAL LETTER A WITH RING ABOVE" . #x0000c5) ("LATIN CAPITAL LETTER AE" . #x0000c6) ("LATIN CAPITAL LETTER C WITH CEDILLA" . #x0000c7) ("LATIN CAPITAL LETTER E WITH GRAVE" . #x0000c8) ("LATIN CAPITAL LETTER E WITH ACUTE" . #x0000c9) ("LATIN CAPITAL LETTER E WITH CIRCUMFLEX" . #x0000ca) ("LATIN CAPITAL LETTER E WITH DIAERESIS" . #x0000cb) ("LATIN CAPITAL LETTER I WITH GRAVE" . #x0000cc) ("LATIN CAPITAL LETTER I WITH ACUTE" . #x0000cd) ("LATIN CAPITAL LETTER I WITH CIRCUMFLEX" . #x0000ce) ("LATIN CAPITAL LETTER I WITH DIAERESIS" . #x0000cf) ("LATIN CAPITAL LETTER ETH" . #x0000d0) ("LATIN CAPITAL LETTER N WITH TILDE" . #x0000d1) ("LATIN CAPITAL LETTER O WITH GRAVE" . #x0000d2) ("LATIN CAPITAL LETTER O WITH ACUTE" . #x0000d3) ("LATIN CAPITAL LETTER O WITH CIRCUMFLEX" . #x0000d4) ("LATIN CAPITAL LETTER O WITH TILDE" . #x0000d5) ("LATIN CAPITAL LETTER O WITH DIAERESIS" . #x0000d6) ("MULTIPLICATION SIGN" . #x0000d7) ("LATIN CAPITAL LETTER O WITH STROKE" . #x0000d8) ("LATIN CAPITAL LETTER U WITH GRAVE" . #x0000d9) ("LATIN CAPITAL LETTER U WITH ACUTE" . #x0000da) ("LATIN CAPITAL LETTER U WITH CIRCUMFLEX" . #x0000db) ("LATIN CAPITAL LETTER U WITH DIAERESIS" . #x0000dc) ("LATIN CAPITAL LETTER Y WITH ACUTE" . #x0000dd) ("LATIN CAPITAL LETTER THORN" . #x0000de) ("LATIN SMALL LETTER SHARP S" . #x0000df) ("LATIN SMALL LETTER A WITH GRAVE" . #x0000e0) ("LATIN SMALL LETTER A WITH ACUTE" . #x0000e1) ("LATIN SMALL LETTER A WITH CIRCUMFLEX" . #x0000e2) ("LATIN SMALL LETTER A WITH TILDE" . #x0000e3) ("LATIN SMALL LETTER A WITH DIAERESIS" . #x0000e4) ("LATIN SMALL LETTER A WITH RING ABOVE" . #x0000e5) ("LATIN SMALL LETTER AE" . #x0000e6) ("LATIN SMALL LETTER C WITH CEDILLA" . #x0000e7) ("LATIN SMALL LETTER E WITH GRAVE" . #x0000e8) ("LATIN SMALL LETTER E WITH ACUTE" . #x0000e9) ("LATIN SMALL LETTER E WITH CIRCUMFLEX" . #x0000ea) ("LATIN SMALL LETTER E WITH DIAERESIS" . #x0000eb) ("LATIN SMALL LETTER I WITH GRAVE" . #x0000ec) ("LATIN SMALL LETTER I WITH ACUTE" . #x0000ed) ("LATIN SMALL LETTER I WITH CIRCUMFLEX" . #x0000ee) ("LATIN SMALL LETTER I WITH DIAERESIS" . #x0000ef) ("LATIN SMALL LETTER ETH" . #x0000f0) ("LATIN SMALL LETTER N WITH TILDE" . #x0000f1) ("LATIN SMALL LETTER O WITH GRAVE" . #x0000f2) ("LATIN SMALL LETTER O WITH ACUTE" . #x0000f3) ("LATIN SMALL LETTER O WITH CIRCUMFLEX" . #x0000f4) ("LATIN SMALL LETTER O WITH TILDE" . #x0000f5) ("LATIN SMALL LETTER O WITH DIAERESIS" . #x0000f6) ("DIVISION SIGN" . #x0000f7) ("LATIN SMALL LETTER O WITH STROKE" . #x0000f8) ("LATIN SMALL LETTER U WITH GRAVE" . #x0000f9) ("LATIN SMALL LETTER U WITH ACUTE" . #x0000fa) ("LATIN SMALL LETTER U WITH CIRCUMFLEX" . #x0000fb) ("LATIN SMALL LETTER U WITH DIAERESIS" . #x0000fc) ("LATIN SMALL LETTER Y WITH ACUTE" . #x0000fd) ("LATIN SMALL LETTER THORN" . #x0000fe) ("LATIN SMALL LETTER Y WITH DIAERESIS" . #x0000ff) ("LATIN CAPITAL LETTER A WITH MACRON" . #x000100) ("LATIN SMALL LETTER A WITH MACRON" . #x000101) ("LATIN CAPITAL LETTER A WITH BREVE" . #x000102) ("LATIN SMALL LETTER A WITH BREVE" . #x000103) ("LATIN CAPITAL LETTER A WITH OGONEK" . #x000104) ("LATIN SMALL LETTER A WITH OGONEK" . #x000105) ("LATIN CAPITAL LETTER C WITH ACUTE" . #x000106) ("LATIN SMALL LETTER C WITH ACUTE" . #x000107) ("LATIN CAPITAL LETTER C WITH CIRCUMFLEX" . #x000108) ("LATIN SMALL LETTER C WITH CIRCUMFLEX" . #x000109) ("LATIN CAPITAL LETTER C WITH DOT ABOVE" . #x00010a) ("LATIN SMALL LETTER C WITH DOT ABOVE" . #x00010b) ("LATIN CAPITAL LETTER C WITH CARON" . #x00010c) ("LATIN SMALL LETTER C WITH CARON" . #x00010d) ("LATIN CAPITAL LETTER D WITH CARON" . #x00010e) ("LATIN SMALL LETTER D WITH CARON" . #x00010f) ("LATIN CAPITAL LETTER D WITH STROKE" . #x000110) ("LATIN SMALL LETTER D WITH STROKE" . #x000111) ("LATIN CAPITAL LETTER E WITH MACRON" . #x000112) ("LATIN SMALL LETTER E WITH MACRON" . #x000113) ("LATIN CAPITAL LETTER E WITH BREVE" . #x000114) ("LATIN SMALL LETTER E WITH BREVE" . #x000115) ("LATIN CAPITAL LETTER E WITH DOT ABOVE" . #x000116) ("LATIN SMALL LETTER E WITH DOT ABOVE" . #x000117) ("LATIN CAPITAL LETTER E WITH OGONEK" . #x000118) ("LATIN SMALL LETTER E WITH OGONEK" . #x000119) ("LATIN CAPITAL LETTER E WITH CARON" . #x00011a) ("LATIN SMALL LETTER E WITH CARON" . #x00011b) ("LATIN CAPITAL LETTER G WITH CIRCUMFLEX" . #x00011c) ("LATIN SMALL LETTER G WITH CIRCUMFLEX" . #x00011d) ("LATIN CAPITAL LETTER G WITH BREVE" . #x00011e) ("LATIN SMALL LETTER G WITH BREVE" . #x00011f) ("LATIN CAPITAL LETTER G WITH DOT ABOVE" . #x000120) ("LATIN SMALL LETTER G WITH DOT ABOVE" . #x000121) ("LATIN CAPITAL LETTER G WITH CEDILLA" . #x000122) ("LATIN SMALL LETTER G WITH CEDILLA" . #x000123) ("LATIN CAPITAL LETTER H WITH CIRCUMFLEX" . #x000124) ("LATIN SMALL LETTER H WITH CIRCUMFLEX" . #x000125) ("LATIN CAPITAL LETTER H WITH STROKE" . #x000126) ("LATIN SMALL LETTER H WITH STROKE" . #x000127) ("LATIN CAPITAL LETTER I WITH TILDE" . #x000128) ("LATIN SMALL LETTER I WITH TILDE" . #x000129) ("LATIN CAPITAL LETTER I WITH MACRON" . #x00012a) ("LATIN SMALL LETTER I WITH MACRON" . #x00012b) ("LATIN CAPITAL LETTER I WITH BREVE" . #x00012c) ("LATIN SMALL LETTER I WITH BREVE" . #x00012d) ("LATIN CAPITAL LETTER I WITH OGONEK" . #x00012e) ("LATIN SMALL LETTER I WITH OGONEK" . #x00012f) ("LATIN CAPITAL LETTER I WITH DOT ABOVE" . #x000130) ("LATIN SMALL LETTER DOTLESS I" . #x000131) ("LATIN CAPITAL LIGATURE IJ" . #x000132) ("LATIN SMALL LIGATURE IJ" . #x000133) ("LATIN CAPITAL LETTER J WITH CIRCUMFLEX" . #x000134) ("LATIN SMALL LETTER J WITH CIRCUMFLEX" . #x000135) ("LATIN CAPITAL LETTER K WITH CEDILLA" . #x000136) ("LATIN SMALL LETTER K WITH CEDILLA" . #x000137) ("LATIN SMALL LETTER KRA" . #x000138) ("LATIN CAPITAL LETTER L WITH ACUTE" . #x000139) ("LATIN SMALL LETTER L WITH ACUTE" . #x00013a) ("LATIN CAPITAL LETTER L WITH CEDILLA" . #x00013b) ("LATIN SMALL LETTER L WITH CEDILLA" . #x00013c) ("LATIN CAPITAL LETTER L WITH CARON" . #x00013d) ("LATIN SMALL LETTER L WITH CARON" . #x00013e) ("LATIN CAPITAL LETTER L WITH MIDDLE DOT" . #x00013f) ("LATIN SMALL LETTER L WITH MIDDLE DOT" . #x000140) ("LATIN CAPITAL LETTER L WITH STROKE" . #x000141) ("LATIN SMALL LETTER L WITH STROKE" . #x000142) ("LATIN CAPITAL LETTER N WITH ACUTE" . #x000143) ("LATIN SMALL LETTER N WITH ACUTE" . #x000144) ("LATIN CAPITAL LETTER N WITH CEDILLA" . #x000145) ("LATIN SMALL LETTER N WITH CEDILLA" . #x000146) ("LATIN CAPITAL LETTER N WITH CARON" . #x000147) ("LATIN SMALL LETTER N WITH CARON" . #x000148) ("LATIN SMALL LETTER N PRECEDED BY APOSTROPHE" . #x000149) ("LATIN CAPITAL LETTER ENG" . #x00014a) ("LATIN SMALL LETTER ENG" . #x00014b) ("LATIN CAPITAL LETTER O WITH MACRON" . #x00014c) ("LATIN SMALL LETTER O WITH MACRON" . #x00014d) ("LATIN CAPITAL LETTER O WITH BREVE" . #x00014e) ("LATIN SMALL LETTER O WITH BREVE" . #x00014f) ("LATIN CAPITAL LETTER O WITH DOUBLE ACUTE" . #x000150) ("LATIN SMALL LETTER O WITH DOUBLE ACUTE" . #x000151) ("LATIN CAPITAL LIGATURE OE" . #x000152) ("LATIN SMALL LIGATURE OE" . #x000153) ("LATIN CAPITAL LETTER R WITH ACUTE" . #x000154) ("LATIN SMALL LETTER R WITH ACUTE" . #x000155) ("LATIN CAPITAL LETTER R WITH CEDILLA" . #x000156) ("LATIN SMALL LETTER R WITH CEDILLA" . #x000157) ("LATIN CAPITAL LETTER R WITH CARON" . #x000158) ("LATIN SMALL LETTER R WITH CARON" . #x000159) ("LATIN CAPITAL LETTER S WITH ACUTE" . #x00015a) ("LATIN SMALL LETTER S WITH ACUTE" . #x00015b) ("LATIN CAPITAL LETTER S WITH CIRCUMFLEX" . #x00015c) ("LATIN SMALL LETTER S WITH CIRCUMFLEX" . #x00015d) ("LATIN CAPITAL LETTER S WITH CEDILLA" . #x00015e) ("LATIN SMALL LETTER S WITH CEDILLA" . #x00015f) ("LATIN CAPITAL LETTER S WITH CARON" . #x000160) ("LATIN SMALL LETTER S WITH CARON" . #x000161) ("LATIN CAPITAL LETTER T WITH CEDILLA" . #x000162) ("LATIN SMALL LETTER T WITH CEDILLA" . #x000163) ("LATIN CAPITAL LETTER T WITH CARON" . #x000164) ("LATIN SMALL LETTER T WITH CARON" . #x000165) ("LATIN CAPITAL LETTER T WITH STROKE" . #x000166) ("LATIN SMALL LETTER T WITH STROKE" . #x000167) ("LATIN CAPITAL LETTER U WITH TILDE" . #x000168) ("LATIN SMALL LETTER U WITH TILDE" . #x000169) ("LATIN CAPITAL LETTER U WITH MACRON" . #x00016a) ("LATIN SMALL LETTER U WITH MACRON" . #x00016b) ("LATIN CAPITAL LETTER U WITH BREVE" . #x00016c) ("LATIN SMALL LETTER U WITH BREVE" . #x00016d) ("LATIN CAPITAL LETTER U WITH RING ABOVE" . #x00016e) ("LATIN SMALL LETTER U WITH RING ABOVE" . #x00016f) ("LATIN CAPITAL LETTER U WITH DOUBLE ACUTE" . #x000170) ("LATIN SMALL LETTER U WITH DOUBLE ACUTE" . #x000171) ("LATIN CAPITAL LETTER U WITH OGONEK" . #x000172) ("LATIN SMALL LETTER U WITH OGONEK" . #x000173) ("LATIN CAPITAL LETTER W WITH CIRCUMFLEX" . #x000174) ("LATIN SMALL LETTER W WITH CIRCUMFLEX" . #x000175) ("LATIN CAPITAL LETTER Y WITH CIRCUMFLEX" . #x000176) ("LATIN SMALL LETTER Y WITH CIRCUMFLEX" . #x000177) ("LATIN CAPITAL LETTER Y WITH DIAERESIS" . #x000178) ("LATIN CAPITAL LETTER Z WITH ACUTE" . #x000179) ("LATIN SMALL LETTER Z WITH ACUTE" . #x00017a) ("LATIN CAPITAL LETTER Z WITH DOT ABOVE" . #x00017b) ("LATIN SMALL LETTER Z WITH DOT ABOVE" . #x00017c) ("LATIN CAPITAL LETTER Z WITH CARON" . #x00017d) ("LATIN SMALL LETTER Z WITH CARON" . #x00017e) ("LATIN SMALL LETTER LONG S" . #x00017f) ("LATIN SMALL LETTER B WITH STROKE" . #x000180) ("LATIN CAPITAL LETTER B WITH HOOK" . #x000181) ("LATIN CAPITAL LETTER B WITH TOPBAR" . #x000182) ("LATIN SMALL LETTER B WITH TOPBAR" . #x000183) ("LATIN CAPITAL LETTER TONE SIX" . #x000184) ("LATIN SMALL LETTER TONE SIX" . #x000185) ("LATIN CAPITAL LETTER OPEN O" . #x000186) ("LATIN CAPITAL LETTER C WITH HOOK" . #x000187) ("LATIN SMALL LETTER C WITH HOOK" . #x000188) ("LATIN CAPITAL LETTER AFRICAN D" . #x000189) ("LATIN CAPITAL LETTER D WITH HOOK" . #x00018a) ("LATIN CAPITAL LETTER D WITH TOPBAR" . #x00018b) ("LATIN SMALL LETTER D WITH TOPBAR" . #x00018c) ("LATIN SMALL LETTER TURNED DELTA" . #x00018d) ("LATIN CAPITAL LETTER REVERSED E" . #x00018e) ("LATIN CAPITAL LETTER SCHWA" . #x00018f) ("LATIN CAPITAL LETTER OPEN E" . #x000190) ("LATIN CAPITAL LETTER F WITH HOOK" . #x000191) ("LATIN SMALL LETTER F WITH HOOK" . #x000192) ("LATIN CAPITAL LETTER G WITH HOOK" . #x000193) ("LATIN CAPITAL LETTER GAMMA" . #x000194) ("LATIN SMALL LETTER HV" . #x000195) ("LATIN CAPITAL LETTER IOTA" . #x000196) ("LATIN CAPITAL LETTER I WITH STROKE" . #x000197) ("LATIN CAPITAL LETTER K WITH HOOK" . #x000198) ("LATIN SMALL LETTER K WITH HOOK" . #x000199) ("LATIN SMALL LETTER L WITH BAR" . #x00019a) ("LATIN SMALL LETTER LAMBDA WITH STROKE" . #x00019b) ("LATIN CAPITAL LETTER TURNED M" . #x00019c) ("LATIN CAPITAL LETTER N WITH LEFT HOOK" . #x00019d) ("LATIN SMALL LETTER N WITH LONG RIGHT LEG" . #x00019e) ("LATIN CAPITAL LETTER O WITH MIDDLE TILDE" . #x00019f) ("LATIN CAPITAL LETTER O WITH HORN" . #x0001a0) ("LATIN SMALL LETTER O WITH HORN" . #x0001a1) ("LATIN CAPITAL LETTER OI" . #x0001a2) ("LATIN SMALL LETTER OI" . #x0001a3) ("LATIN CAPITAL LETTER P WITH HOOK" . #x0001a4) ("LATIN SMALL LETTER P WITH HOOK" . #x0001a5) ("LATIN LETTER YR" . #x0001a6) ("LATIN CAPITAL LETTER TONE TWO" . #x0001a7) ("LATIN SMALL LETTER TONE TWO" . #x0001a8) ("LATIN CAPITAL LETTER ESH" . #x0001a9) ("LATIN LETTER REVERSED ESH LOOP" . #x0001aa) ("LATIN SMALL LETTER T WITH PALATAL HOOK" . #x0001ab) ("LATIN CAPITAL LETTER T WITH HOOK" . #x0001ac) ("LATIN SMALL LETTER T WITH HOOK" . #x0001ad) ("LATIN CAPITAL LETTER T WITH RETROFLEX HOOK" . #x0001ae) ("LATIN CAPITAL LETTER U WITH HORN" . #x0001af) ("LATIN SMALL LETTER U WITH HORN" . #x0001b0) ("LATIN CAPITAL LETTER UPSILON" . #x0001b1) ("LATIN CAPITAL LETTER V WITH HOOK" . #x0001b2) ("LATIN CAPITAL LETTER Y WITH HOOK" . #x0001b3) ("LATIN SMALL LETTER Y WITH HOOK" . #x0001b4) ("LATIN CAPITAL LETTER Z WITH STROKE" . #x0001b5) ("LATIN SMALL LETTER Z WITH STROKE" . #x0001b6) ("LATIN CAPITAL LETTER EZH" . #x0001b7) ("LATIN CAPITAL LETTER EZH REVERSED" . #x0001b8) ("LATIN SMALL LETTER EZH REVERSED" . #x0001b9) ("LATIN SMALL LETTER EZH WITH TAIL" . #x0001ba) ("LATIN LETTER TWO WITH STROKE" . #x0001bb) ("LATIN CAPITAL LETTER TONE FIVE" . #x0001bc) ("LATIN SMALL LETTER TONE FIVE" . #x0001bd) ("LATIN LETTER INVERTED GLOTTAL STOP WITH STROKE" . #x0001be) ("LATIN LETTER WYNN" . #x0001bf) ("LATIN LETTER DENTAL CLICK" . #x0001c0) ("LATIN LETTER LATERAL CLICK" . #x0001c1) ("LATIN LETTER ALVEOLAR CLICK" . #x0001c2) ("LATIN LETTER RETROFLEX CLICK" . #x0001c3) ("LATIN CAPITAL LETTER DZ WITH CARON" . #x0001c4) ("LATIN CAPITAL LETTER D WITH SMALL LETTER Z WITH CARON" . #x0001c5) ("LATIN SMALL LETTER DZ WITH CARON" . #x0001c6) ("LATIN CAPITAL LETTER LJ" . #x0001c7) ("LATIN CAPITAL LETTER L WITH SMALL LETTER J" . #x0001c8) ("LATIN SMALL LETTER LJ" . #x0001c9) ("LATIN CAPITAL LETTER NJ" . #x0001ca) ("LATIN CAPITAL LETTER N WITH SMALL LETTER J" . #x0001cb) ("LATIN SMALL LETTER NJ" . #x0001cc) ("LATIN CAPITAL LETTER A WITH CARON" . #x0001cd) ("LATIN SMALL LETTER A WITH CARON" . #x0001ce) ("LATIN CAPITAL LETTER I WITH CARON" . #x0001cf) ("LATIN SMALL LETTER I WITH CARON" . #x0001d0) ("LATIN CAPITAL LETTER O WITH CARON" . #x0001d1) ("LATIN SMALL LETTER O WITH CARON" . #x0001d2) ("LATIN CAPITAL LETTER U WITH CARON" . #x0001d3) ("LATIN SMALL LETTER U WITH CARON" . #x0001d4) ("LATIN CAPITAL LETTER U WITH DIAERESIS AND MACRON" . #x0001d5) ("LATIN SMALL LETTER U WITH DIAERESIS AND MACRON" . #x0001d6) ("LATIN CAPITAL LETTER U WITH DIAERESIS AND ACUTE" . #x0001d7) ("LATIN SMALL LETTER U WITH DIAERESIS AND ACUTE" . #x0001d8) ("LATIN CAPITAL LETTER U WITH DIAERESIS AND CARON" . #x0001d9) ("LATIN SMALL LETTER U WITH DIAERESIS AND CARON" . #x0001da) ("LATIN CAPITAL LETTER U WITH DIAERESIS AND GRAVE" . #x0001db) ("LATIN SMALL LETTER U WITH DIAERESIS AND GRAVE" . #x0001dc) ("LATIN SMALL LETTER TURNED E" . #x0001dd) ("LATIN CAPITAL LETTER A WITH DIAERESIS AND MACRON" . #x0001de) ("LATIN SMALL LETTER A WITH DIAERESIS AND MACRON" . #x0001df) ("LATIN CAPITAL LETTER A WITH DOT ABOVE AND MACRON" . #x0001e0) ("LATIN SMALL LETTER A WITH DOT ABOVE AND MACRON" . #x0001e1) ("LATIN CAPITAL LETTER AE WITH MACRON" . #x0001e2) ("LATIN SMALL LETTER AE WITH MACRON" . #x0001e3) ("LATIN CAPITAL LETTER G WITH STROKE" . #x0001e4) ("LATIN SMALL LETTER G WITH STROKE" . #x0001e5) ("LATIN CAPITAL LETTER G WITH CARON" . #x0001e6) ("LATIN SMALL LETTER G WITH CARON" . #x0001e7) ("LATIN CAPITAL LETTER K WITH CARON" . #x0001e8) ("LATIN SMALL LETTER K WITH CARON" . #x0001e9) ("LATIN CAPITAL LETTER O WITH OGONEK" . #x0001ea) ("LATIN SMALL LETTER O WITH OGONEK" . #x0001eb) ("LATIN CAPITAL LETTER O WITH OGONEK AND MACRON" . #x0001ec) ("LATIN SMALL LETTER O WITH OGONEK AND MACRON" . #x0001ed) ("LATIN CAPITAL LETTER EZH WITH CARON" . #x0001ee) ("LATIN SMALL LETTER EZH WITH CARON" . #x0001ef) ("LATIN SMALL LETTER J WITH CARON" . #x0001f0) ("LATIN CAPITAL LETTER DZ" . #x0001f1) ("LATIN CAPITAL LETTER D WITH SMALL LETTER Z" . #x0001f2) ("LATIN SMALL LETTER DZ" . #x0001f3) ("LATIN CAPITAL LETTER G WITH ACUTE" . #x0001f4) ("LATIN SMALL LETTER G WITH ACUTE" . #x0001f5) ("LATIN CAPITAL LETTER HWAIR" . #x0001f6) ("LATIN CAPITAL LETTER WYNN" . #x0001f7) ("LATIN CAPITAL LETTER N WITH GRAVE" . #x0001f8) ("LATIN SMALL LETTER N WITH GRAVE" . #x0001f9) ("LATIN CAPITAL LETTER A WITH RING ABOVE AND ACUTE" . #x0001fa) ("LATIN SMALL LETTER A WITH RING ABOVE AND ACUTE" . #x0001fb) ("LATIN CAPITAL LETTER AE WITH ACUTE" . #x0001fc) ("LATIN SMALL LETTER AE WITH ACUTE" . #x0001fd) ("LATIN CAPITAL LETTER O WITH STROKE AND ACUTE" . #x0001fe) ("LATIN SMALL LETTER O WITH STROKE AND ACUTE" . #x0001ff) ("LATIN CAPITAL LETTER A WITH DOUBLE GRAVE" . #x000200) ("LATIN SMALL LETTER A WITH DOUBLE GRAVE" . #x000201) ("LATIN CAPITAL LETTER A WITH INVERTED BREVE" . #x000202) ("LATIN SMALL LETTER A WITH INVERTED BREVE" . #x000203) ("LATIN CAPITAL LETTER E WITH DOUBLE GRAVE" . #x000204) ("LATIN SMALL LETTER E WITH DOUBLE GRAVE" . #x000205) ("LATIN CAPITAL LETTER E WITH INVERTED BREVE" . #x000206) ("LATIN SMALL LETTER E WITH INVERTED BREVE" . #x000207) ("LATIN CAPITAL LETTER I WITH DOUBLE GRAVE" . #x000208) ("LATIN SMALL LETTER I WITH DOUBLE GRAVE" . #x000209) ("LATIN CAPITAL LETTER I WITH INVERTED BREVE" . #x00020a) ("LATIN SMALL LETTER I WITH INVERTED BREVE" . #x00020b) ("LATIN CAPITAL LETTER O WITH DOUBLE GRAVE" . #x00020c) ("LATIN SMALL LETTER O WITH DOUBLE GRAVE" . #x00020d) ("LATIN CAPITAL LETTER O WITH INVERTED BREVE" . #x00020e) ("LATIN SMALL LETTER O WITH INVERTED BREVE" . #x00020f) ("LATIN CAPITAL LETTER R WITH DOUBLE GRAVE" . #x000210) ("LATIN SMALL LETTER R WITH DOUBLE GRAVE" . #x000211) ("LATIN CAPITAL LETTER R WITH INVERTED BREVE" . #x000212) ("LATIN SMALL LETTER R WITH INVERTED BREVE" . #x000213) ("LATIN CAPITAL LETTER U WITH DOUBLE GRAVE" . #x000214) ("LATIN SMALL LETTER U WITH DOUBLE GRAVE" . #x000215) ("LATIN CAPITAL LETTER U WITH INVERTED BREVE" . #x000216) ("LATIN SMALL LETTER U WITH INVERTED BREVE" . #x000217) ("LATIN CAPITAL LETTER S WITH COMMA BELOW" . #x000218) ("LATIN SMALL LETTER S WITH COMMA BELOW" . #x000219) ("LATIN CAPITAL LETTER T WITH COMMA BELOW" . #x00021a) ("LATIN SMALL LETTER T WITH COMMA BELOW" . #x00021b) ("LATIN CAPITAL LETTER YOGH" . #x00021c) ("LATIN SMALL LETTER YOGH" . #x00021d) ("LATIN CAPITAL LETTER H WITH CARON" . #x00021e) ("LATIN SMALL LETTER H WITH CARON" . #x00021f) ("LATIN CAPITAL LETTER N WITH LONG RIGHT LEG" . #x000220) ("LATIN CAPITAL LETTER OU" . #x000222) ("LATIN SMALL LETTER OU" . #x000223) ("LATIN CAPITAL LETTER Z WITH HOOK" . #x000224) ("LATIN SMALL LETTER Z WITH HOOK" . #x000225) ("LATIN CAPITAL LETTER A WITH DOT ABOVE" . #x000226) ("LATIN SMALL LETTER A WITH DOT ABOVE" . #x000227) ("LATIN CAPITAL LETTER E WITH CEDILLA" . #x000228) ("LATIN SMALL LETTER E WITH CEDILLA" . #x000229) ("LATIN CAPITAL LETTER O WITH DIAERESIS AND MACRON" . #x00022a) ("LATIN SMALL LETTER O WITH DIAERESIS AND MACRON" . #x00022b) ("LATIN CAPITAL LETTER O WITH TILDE AND MACRON" . #x00022c) ("LATIN SMALL LETTER O WITH TILDE AND MACRON" . #x00022d) ("LATIN CAPITAL LETTER O WITH DOT ABOVE" . #x00022e) ("LATIN SMALL LETTER O WITH DOT ABOVE" . #x00022f) ("LATIN CAPITAL LETTER O WITH DOT ABOVE AND MACRON" . #x000230) ("LATIN SMALL LETTER O WITH DOT ABOVE AND MACRON" . #x000231) ("LATIN CAPITAL LETTER Y WITH MACRON" . #x000232) ("LATIN SMALL LETTER Y WITH MACRON" . #x000233) ("LATIN SMALL LETTER TURNED A" . #x000250) ("LATIN SMALL LETTER ALPHA" . #x000251) ("LATIN SMALL LETTER TURNED ALPHA" . #x000252) ("LATIN SMALL LETTER B WITH HOOK" . #x000253) ("LATIN SMALL LETTER OPEN O" . #x000254) ("LATIN SMALL LETTER C WITH CURL" . #x000255) ("LATIN SMALL LETTER D WITH TAIL" . #x000256) ("LATIN SMALL LETTER D WITH HOOK" . #x000257) ("LATIN SMALL LETTER REVERSED E" . #x000258) ("LATIN SMALL LETTER SCHWA" . #x000259) ("LATIN SMALL LETTER SCHWA WITH HOOK" . #x00025a) ("LATIN SMALL LETTER OPEN E" . #x00025b) ("LATIN SMALL LETTER REVERSED OPEN E" . #x00025c) ("LATIN SMALL LETTER REVERSED OPEN E WITH HOOK" . #x00025d) ("LATIN SMALL LETTER CLOSED REVERSED OPEN E" . #x00025e) ("LATIN SMALL LETTER DOTLESS J WITH STROKE" . #x00025f) ("LATIN SMALL LETTER G WITH HOOK" . #x000260) ("LATIN SMALL LETTER SCRIPT G" . #x000261) ("LATIN LETTER SMALL CAPITAL G" . #x000262) ("LATIN SMALL LETTER GAMMA" . #x000263) ("LATIN SMALL LETTER RAMS HORN" . #x000264) ("LATIN SMALL LETTER TURNED H" . #x000265) ("LATIN SMALL LETTER H WITH HOOK" . #x000266) ("LATIN SMALL LETTER HENG WITH HOOK" . #x000267) ("LATIN SMALL LETTER I WITH STROKE" . #x000268) ("LATIN SMALL LETTER IOTA" . #x000269) ("LATIN LETTER SMALL CAPITAL I" . #x00026a) ("LATIN SMALL LETTER L WITH MIDDLE TILDE" . #x00026b) ("LATIN SMALL LETTER L WITH BELT" . #x00026c) ("LATIN SMALL LETTER L WITH RETROFLEX HOOK" . #x00026d) ("LATIN SMALL LETTER LEZH" . #x00026e) ("LATIN SMALL LETTER TURNED M" . #x00026f) ("LATIN SMALL LETTER TURNED M WITH LONG LEG" . #x000270) ("LATIN SMALL LETTER M WITH HOOK" . #x000271) ("LATIN SMALL LETTER N WITH LEFT HOOK" . #x000272) ("LATIN SMALL LETTER N WITH RETROFLEX HOOK" . #x000273) ("LATIN LETTER SMALL CAPITAL N" . #x000274) ("LATIN SMALL LETTER BARRED O" . #x000275) ("LATIN LETTER SMALL CAPITAL OE" . #x000276) ("LATIN SMALL LETTER CLOSED OMEGA" . #x000277) ("LATIN SMALL LETTER PHI" . #x000278) ("LATIN SMALL LETTER TURNED R" . #x000279) ("LATIN SMALL LETTER TURNED R WITH LONG LEG" . #x00027a) ("LATIN SMALL LETTER TURNED R WITH HOOK" . #x00027b) ("LATIN SMALL LETTER R WITH LONG LEG" . #x00027c) ("LATIN SMALL LETTER R WITH TAIL" . #x00027d) ("LATIN SMALL LETTER R WITH FISHHOOK" . #x00027e) ("LATIN SMALL LETTER REVERSED R WITH FISHHOOK" . #x00027f) ("LATIN LETTER SMALL CAPITAL R" . #x000280) ("LATIN LETTER SMALL CAPITAL INVERTED R" . #x000281) ("LATIN SMALL LETTER S WITH HOOK" . #x000282) ("LATIN SMALL LETTER ESH" . #x000283) ("LATIN SMALL LETTER DOTLESS J WITH STROKE AND HOOK" . #x000284) ("LATIN SMALL LETTER SQUAT REVERSED ESH" . #x000285) ("LATIN SMALL LETTER ESH WITH CURL" . #x000286) ("LATIN SMALL LETTER TURNED T" . #x000287) ("LATIN SMALL LETTER T WITH RETROFLEX HOOK" . #x000288) ("LATIN SMALL LETTER U BAR" . #x000289) ("LATIN SMALL LETTER UPSILON" . #x00028a) ("LATIN SMALL LETTER V WITH HOOK" . #x00028b) ("LATIN SMALL LETTER TURNED V" . #x00028c) ("LATIN SMALL LETTER TURNED W" . #x00028d) ("LATIN SMALL LETTER TURNED Y" . #x00028e) ("LATIN LETTER SMALL CAPITAL Y" . #x00028f) ("LATIN SMALL LETTER Z WITH RETROFLEX HOOK" . #x000290) ("LATIN SMALL LETTER Z WITH CURL" . #x000291) ("LATIN SMALL LETTER EZH" . #x000292) ("LATIN SMALL LETTER EZH WITH CURL" . #x000293) ("LATIN LETTER GLOTTAL STOP" . #x000294) ("LATIN LETTER PHARYNGEAL VOICED FRICATIVE" . #x000295) ("LATIN LETTER INVERTED GLOTTAL STOP" . #x000296) ("LATIN LETTER STRETCHED C" . #x000297) ("LATIN LETTER BILABIAL CLICK" . #x000298) ("LATIN LETTER SMALL CAPITAL B" . #x000299) ("LATIN SMALL LETTER CLOSED OPEN E" . #x00029a) ("LATIN LETTER SMALL CAPITAL G WITH HOOK" . #x00029b) ("LATIN LETTER SMALL CAPITAL H" . #x00029c) ("LATIN SMALL LETTER J WITH CROSSED-TAIL" . #x00029d) ("LATIN SMALL LETTER TURNED K" . #x00029e) ("LATIN LETTER SMALL CAPITAL L" . #x00029f) ("LATIN SMALL LETTER Q WITH HOOK" . #x0002a0) ("LATIN LETTER GLOTTAL STOP WITH STROKE" . #x0002a1) ("LATIN LETTER REVERSED GLOTTAL STOP WITH STROKE" . #x0002a2) ("LATIN SMALL LETTER DZ DIGRAPH" . #x0002a3) ("LATIN SMALL LETTER DEZH DIGRAPH" . #x0002a4) ("LATIN SMALL LETTER DZ DIGRAPH WITH CURL" . #x0002a5) ("LATIN SMALL LETTER TS DIGRAPH" . #x0002a6) ("LATIN SMALL LETTER TESH DIGRAPH" . #x0002a7) ("LATIN SMALL LETTER TC DIGRAPH WITH CURL" . #x0002a8) ("LATIN SMALL LETTER FENG DIGRAPH" . #x0002a9) ("LATIN SMALL LETTER LS DIGRAPH" . #x0002aa) ("LATIN SMALL LETTER LZ DIGRAPH" . #x0002ab) ("LATIN LETTER BILABIAL PERCUSSIVE" . #x0002ac) ("LATIN LETTER BIDENTAL PERCUSSIVE" . #x0002ad) ("MODIFIER LETTER SMALL H" . #x0002b0) ("MODIFIER LETTER SMALL H WITH HOOK" . #x0002b1) ("MODIFIER LETTER SMALL J" . #x0002b2) ("MODIFIER LETTER SMALL R" . #x0002b3) ("MODIFIER LETTER SMALL TURNED R" . #x0002b4) ("MODIFIER LETTER SMALL TURNED R WITH HOOK" . #x0002b5) ("MODIFIER LETTER SMALL CAPITAL INVERTED R" . #x0002b6) ("MODIFIER LETTER SMALL W" . #x0002b7) ("MODIFIER LETTER SMALL Y" . #x0002b8) ("MODIFIER LETTER PRIME" . #x0002b9) ("MODIFIER LETTER DOUBLE PRIME" . #x0002ba) ("MODIFIER LETTER TURNED COMMA" . #x0002bb) ("MODIFIER LETTER APOSTROPHE" . #x0002bc) ("MODIFIER LETTER REVERSED COMMA" . #x0002bd) ("MODIFIER LETTER RIGHT HALF RING" . #x0002be) ("MODIFIER LETTER LEFT HALF RING" . #x0002bf) ("MODIFIER LETTER GLOTTAL STOP" . #x0002c0) ("MODIFIER LETTER REVERSED GLOTTAL STOP" . #x0002c1) ("MODIFIER LETTER LEFT ARROWHEAD" . #x0002c2) ("MODIFIER LETTER RIGHT ARROWHEAD" . #x0002c3) ("MODIFIER LETTER UP ARROWHEAD" . #x0002c4) ("MODIFIER LETTER DOWN ARROWHEAD" . #x0002c5) ("MODIFIER LETTER CIRCUMFLEX ACCENT" . #x0002c6) ("CARON" . #x0002c7) ("MODIFIER LETTER VERTICAL LINE" . #x0002c8) ("MODIFIER LETTER MACRON" . #x0002c9) ("MODIFIER LETTER ACUTE ACCENT" . #x0002ca) ("MODIFIER LETTER GRAVE ACCENT" . #x0002cb) ("MODIFIER LETTER LOW VERTICAL LINE" . #x0002cc) ("MODIFIER LETTER LOW MACRON" . #x0002cd) ("MODIFIER LETTER LOW GRAVE ACCENT" . #x0002ce) ("MODIFIER LETTER LOW ACUTE ACCENT" . #x0002cf) ("MODIFIER LETTER TRIANGULAR COLON" . #x0002d0) ("MODIFIER LETTER HALF TRIANGULAR COLON" . #x0002d1) ("MODIFIER LETTER CENTRED RIGHT HALF RING" . #x0002d2) ("MODIFIER LETTER CENTRED LEFT HALF RING" . #x0002d3) ("MODIFIER LETTER UP TACK" . #x0002d4) ("MODIFIER LETTER DOWN TACK" . #x0002d5) ("MODIFIER LETTER PLUS SIGN" . #x0002d6) ("MODIFIER LETTER MINUS SIGN" . #x0002d7) ("BREVE" . #x0002d8) ("DOT ABOVE" . #x0002d9) ("RING ABOVE" . #x0002da) ("OGONEK" . #x0002db) ("SMALL TILDE" . #x0002dc) ("DOUBLE ACUTE ACCENT" . #x0002dd) ("MODIFIER LETTER RHOTIC HOOK" . #x0002de) ("MODIFIER LETTER CROSS ACCENT" . #x0002df) ("MODIFIER LETTER SMALL GAMMA" . #x0002e0) ("MODIFIER LETTER SMALL L" . #x0002e1) ("MODIFIER LETTER SMALL S" . #x0002e2) ("MODIFIER LETTER SMALL X" . #x0002e3) ("MODIFIER LETTER SMALL REVERSED GLOTTAL STOP" . #x0002e4) ("MODIFIER LETTER EXTRA-HIGH TONE BAR" . #x0002e5) ("MODIFIER LETTER HIGH TONE BAR" . #x0002e6) ("MODIFIER LETTER MID TONE BAR" . #x0002e7) ("MODIFIER LETTER LOW TONE BAR" . #x0002e8) ("MODIFIER LETTER EXTRA-LOW TONE BAR" . #x0002e9) ("MODIFIER LETTER YIN DEPARTING TONE MARK" . #x0002ea) ("MODIFIER LETTER YANG DEPARTING TONE MARK" . #x0002eb) ("MODIFIER LETTER VOICING" . #x0002ec) ("MODIFIER LETTER UNASPIRATED" . #x0002ed) ("MODIFIER LETTER DOUBLE APOSTROPHE" . #x0002ee) ("COMBINING GRAVE ACCENT" . #x000300) ("COMBINING ACUTE ACCENT" . #x000301) ("COMBINING CIRCUMFLEX ACCENT" . #x000302) ("COMBINING TILDE" . #x000303) ("COMBINING MACRON" . #x000304) ("COMBINING OVERLINE" . #x000305) ("COMBINING BREVE" . #x000306) ("COMBINING DOT ABOVE" . #x000307) ("COMBINING DIAERESIS" . #x000308) ("COMBINING HOOK ABOVE" . #x000309) ("COMBINING RING ABOVE" . #x00030a) ("COMBINING DOUBLE ACUTE ACCENT" . #x00030b) ("COMBINING CARON" . #x00030c) ("COMBINING VERTICAL LINE ABOVE" . #x00030d) ("COMBINING DOUBLE VERTICAL LINE ABOVE" . #x00030e) ("COMBINING DOUBLE GRAVE ACCENT" . #x00030f) ("COMBINING CANDRABINDU" . #x000310) ("COMBINING INVERTED BREVE" . #x000311) ("COMBINING TURNED COMMA ABOVE" . #x000312) ("COMBINING COMMA ABOVE" . #x000313) ("COMBINING REVERSED COMMA ABOVE" . #x000314) ("COMBINING COMMA ABOVE RIGHT" . #x000315) ("COMBINING GRAVE ACCENT BELOW" . #x000316) ("COMBINING ACUTE ACCENT BELOW" . #x000317) ("COMBINING LEFT TACK BELOW" . #x000318) ("COMBINING RIGHT TACK BELOW" . #x000319) ("COMBINING LEFT ANGLE ABOVE" . #x00031a) ("COMBINING HORN" . #x00031b) ("COMBINING LEFT HALF RING BELOW" . #x00031c) ("COMBINING UP TACK BELOW" . #x00031d) ("COMBINING DOWN TACK BELOW" . #x00031e) ("COMBINING PLUS SIGN BELOW" . #x00031f) ("COMBINING MINUS SIGN BELOW" . #x000320) ("COMBINING PALATALIZED HOOK BELOW" . #x000321) ("COMBINING RETROFLEX HOOK BELOW" . #x000322) ("COMBINING DOT BELOW" . #x000323) ("COMBINING DIAERESIS BELOW" . #x000324) ("COMBINING RING BELOW" . #x000325) ("COMBINING COMMA BELOW" . #x000326) ("COMBINING CEDILLA" . #x000327) ("COMBINING OGONEK" . #x000328) ("COMBINING VERTICAL LINE BELOW" . #x000329) ("COMBINING BRIDGE BELOW" . #x00032a) ("COMBINING INVERTED DOUBLE ARCH BELOW" . #x00032b) ("COMBINING CARON BELOW" . #x00032c) ("COMBINING CIRCUMFLEX ACCENT BELOW" . #x00032d) ("COMBINING BREVE BELOW" . #x00032e) ("COMBINING INVERTED BREVE BELOW" . #x00032f) ("COMBINING TILDE BELOW" . #x000330) ("COMBINING MACRON BELOW" . #x000331) ("COMBINING LOW LINE" . #x000332) ("COMBINING DOUBLE LOW LINE" . #x000333) ("COMBINING TILDE OVERLAY" . #x000334) ("COMBINING SHORT STROKE OVERLAY" . #x000335) ("COMBINING LONG STROKE OVERLAY" . #x000336) ("COMBINING SHORT SOLIDUS OVERLAY" . #x000337) ("COMBINING LONG SOLIDUS OVERLAY" . #x000338) ("COMBINING RIGHT HALF RING BELOW" . #x000339) ("COMBINING INVERTED BRIDGE BELOW" . #x00033a) ("COMBINING SQUARE BELOW" . #x00033b) ("COMBINING SEAGULL BELOW" . #x00033c) ("COMBINING X ABOVE" . #x00033d) ("COMBINING VERTICAL TILDE" . #x00033e) ("COMBINING DOUBLE OVERLINE" . #x00033f) ("COMBINING GRAVE TONE MARK" . #x000340) ("COMBINING ACUTE TONE MARK" . #x000341) ("COMBINING GREEK PERISPOMENI" . #x000342) ("COMBINING GREEK KORONIS" . #x000343) ("COMBINING GREEK DIALYTIKA TONOS" . #x000344) ("COMBINING GREEK YPOGEGRAMMENI" . #x000345) ("COMBINING BRIDGE ABOVE" . #x000346) ("COMBINING EQUALS SIGN BELOW" . #x000347) ("COMBINING DOUBLE VERTICAL LINE BELOW" . #x000348) ("COMBINING LEFT ANGLE BELOW" . #x000349) ("COMBINING NOT TILDE ABOVE" . #x00034a) ("COMBINING HOMOTHETIC ABOVE" . #x00034b) ("COMBINING ALMOST EQUAL TO ABOVE" . #x00034c) ("COMBINING LEFT RIGHT ARROW BELOW" . #x00034d) ("COMBINING UPWARDS ARROW BELOW" . #x00034e) ("COMBINING GRAPHEME JOINER" . #x00034f) ("COMBINING DOUBLE TILDE" . #x000360) ("COMBINING DOUBLE INVERTED BREVE" . #x000361) ("COMBINING DOUBLE RIGHTWARDS ARROW BELOW" . #x000362) ("COMBINING LATIN SMALL LETTER A" . #x000363) ("COMBINING LATIN SMALL LETTER E" . #x000364) ("COMBINING LATIN SMALL LETTER I" . #x000365) ("COMBINING LATIN SMALL LETTER O" . #x000366) ("COMBINING LATIN SMALL LETTER U" . #x000367) ("COMBINING LATIN SMALL LETTER C" . #x000368) ("COMBINING LATIN SMALL LETTER D" . #x000369) ("COMBINING LATIN SMALL LETTER H" . #x00036a) ("COMBINING LATIN SMALL LETTER M" . #x00036b) ("COMBINING LATIN SMALL LETTER R" . #x00036c) ("COMBINING LATIN SMALL LETTER T" . #x00036d) ("COMBINING LATIN SMALL LETTER V" . #x00036e) ("COMBINING LATIN SMALL LETTER X" . #x00036f) ("GREEK NUMERAL SIGN" . #x000374) ("GREEK LOWER NUMERAL SIGN" . #x000375) ("GREEK YPOGEGRAMMENI" . #x00037a) ("GREEK QUESTION MARK" . #x00037e) ("GREEK TONOS" . #x000384) ("GREEK DIALYTIKA TONOS" . #x000385) ("GREEK CAPITAL LETTER ALPHA WITH TONOS" . #x000386) ("GREEK ANO TELEIA" . #x000387) ("GREEK CAPITAL LETTER EPSILON WITH TONOS" . #x000388) ("GREEK CAPITAL LETTER ETA WITH TONOS" . #x000389) ("GREEK CAPITAL LETTER IOTA WITH TONOS" . #x00038a) ("GREEK CAPITAL LETTER OMICRON WITH TONOS" . #x00038c) ("GREEK CAPITAL LETTER UPSILON WITH TONOS" . #x00038e) ("GREEK CAPITAL LETTER OMEGA WITH TONOS" . #x00038f) ("GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS" . #x000390) ("GREEK CAPITAL LETTER ALPHA" . #x000391) ("GREEK CAPITAL LETTER BETA" . #x000392) ("GREEK CAPITAL LETTER GAMMA" . #x000393) ("GREEK CAPITAL LETTER DELTA" . #x000394) ("GREEK CAPITAL LETTER EPSILON" . #x000395) ("GREEK CAPITAL LETTER ZETA" . #x000396) ("GREEK CAPITAL LETTER ETA" . #x000397) ("GREEK CAPITAL LETTER THETA" . #x000398) ("GREEK CAPITAL LETTER IOTA" . #x000399) ("GREEK CAPITAL LETTER KAPPA" . #x00039a) ("GREEK CAPITAL LETTER LAMDA" . #x00039b) ("GREEK CAPITAL LETTER MU" . #x00039c) ("GREEK CAPITAL LETTER NU" . #x00039d) ("GREEK CAPITAL LETTER XI" . #x00039e) ("GREEK CAPITAL LETTER OMICRON" . #x00039f) ("GREEK CAPITAL LETTER PI" . #x0003a0) ("GREEK CAPITAL LETTER RHO" . #x0003a1) ("GREEK CAPITAL LETTER SIGMA" . #x0003a3) ("GREEK CAPITAL LETTER TAU" . #x0003a4) ("GREEK CAPITAL LETTER UPSILON" . #x0003a5) ("GREEK CAPITAL LETTER PHI" . #x0003a6) ("GREEK CAPITAL LETTER CHI" . #x0003a7) ("GREEK CAPITAL LETTER PSI" . #x0003a8) ("GREEK CAPITAL LETTER OMEGA" . #x0003a9) ("GREEK CAPITAL LETTER IOTA WITH DIALYTIKA" . #x0003aa) ("GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA" . #x0003ab) ("GREEK SMALL LETTER ALPHA WITH TONOS" . #x0003ac) ("GREEK SMALL LETTER EPSILON WITH TONOS" . #x0003ad) ("GREEK SMALL LETTER ETA WITH TONOS" . #x0003ae) ("GREEK SMALL LETTER IOTA WITH TONOS" . #x0003af) ("GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS" . #x0003b0) ("GREEK SMALL LETTER ALPHA" . #x0003b1) ("GREEK SMALL LETTER BETA" . #x0003b2) ("GREEK SMALL LETTER GAMMA" . #x0003b3) ("GREEK SMALL LETTER DELTA" . #x0003b4) ("GREEK SMALL LETTER EPSILON" . #x0003b5) ("GREEK SMALL LETTER ZETA" . #x0003b6) ("GREEK SMALL LETTER ETA" . #x0003b7) ("GREEK SMALL LETTER THETA" . #x0003b8) ("GREEK SMALL LETTER IOTA" . #x0003b9) ("GREEK SMALL LETTER KAPPA" . #x0003ba) ("GREEK SMALL LETTER LAMDA" . #x0003bb) ("GREEK SMALL LETTER MU" . #x0003bc) ("GREEK SMALL LETTER NU" . #x0003bd) ("GREEK SMALL LETTER XI" . #x0003be) ("GREEK SMALL LETTER OMICRON" . #x0003bf) ("GREEK SMALL LETTER PI" . #x0003c0) ("GREEK SMALL LETTER RHO" . #x0003c1) ("GREEK SMALL LETTER FINAL SIGMA" . #x0003c2) ("GREEK SMALL LETTER SIGMA" . #x0003c3) ("GREEK SMALL LETTER TAU" . #x0003c4) ("GREEK SMALL LETTER UPSILON" . #x0003c5) ("GREEK SMALL LETTER PHI" . #x0003c6) ("GREEK SMALL LETTER CHI" . #x0003c7) ("GREEK SMALL LETTER PSI" . #x0003c8) ("GREEK SMALL LETTER OMEGA" . #x0003c9) ("GREEK SMALL LETTER IOTA WITH DIALYTIKA" . #x0003ca) ("GREEK SMALL LETTER UPSILON WITH DIALYTIKA" . #x0003cb) ("GREEK SMALL LETTER OMICRON WITH TONOS" . #x0003cc) ("GREEK SMALL LETTER UPSILON WITH TONOS" . #x0003cd) ("GREEK SMALL LETTER OMEGA WITH TONOS" . #x0003ce) ("GREEK BETA SYMBOL" . #x0003d0) ("GREEK THETA SYMBOL" . #x0003d1) ("GREEK UPSILON WITH HOOK SYMBOL" . #x0003d2) ("GREEK UPSILON WITH ACUTE AND HOOK SYMBOL" . #x0003d3) ("GREEK UPSILON WITH DIAERESIS AND HOOK SYMBOL" . #x0003d4) ("GREEK PHI SYMBOL" . #x0003d5) ("GREEK PI SYMBOL" . #x0003d6) ("GREEK KAI SYMBOL" . #x0003d7) ("GREEK LETTER ARCHAIC KOPPA" . #x0003d8) ("GREEK SMALL LETTER ARCHAIC KOPPA" . #x0003d9) ("GREEK LETTER STIGMA" . #x0003da) ("GREEK SMALL LETTER STIGMA" . #x0003db) ("GREEK LETTER DIGAMMA" . #x0003dc) ("GREEK SMALL LETTER DIGAMMA" . #x0003dd) ("GREEK LETTER KOPPA" . #x0003de) ("GREEK SMALL LETTER KOPPA" . #x0003df) ("GREEK LETTER SAMPI" . #x0003e0) ("GREEK SMALL LETTER SAMPI" . #x0003e1) ("COPTIC CAPITAL LETTER SHEI" . #x0003e2) ("COPTIC SMALL LETTER SHEI" . #x0003e3) ("COPTIC CAPITAL LETTER FEI" . #x0003e4) ("COPTIC SMALL LETTER FEI" . #x0003e5) ("COPTIC CAPITAL LETTER KHEI" . #x0003e6) ("COPTIC SMALL LETTER KHEI" . #x0003e7) ("COPTIC CAPITAL LETTER HORI" . #x0003e8) ("COPTIC SMALL LETTER HORI" . #x0003e9) ("COPTIC CAPITAL LETTER GANGIA" . #x0003ea) ("COPTIC SMALL LETTER GANGIA" . #x0003eb) ("COPTIC CAPITAL LETTER SHIMA" . #x0003ec) ("COPTIC SMALL LETTER SHIMA" . #x0003ed) ("COPTIC CAPITAL LETTER DEI" . #x0003ee) ("COPTIC SMALL LETTER DEI" . #x0003ef) ("GREEK KAPPA SYMBOL" . #x0003f0) ("GREEK RHO SYMBOL" . #x0003f1) ("GREEK LUNATE SIGMA SYMBOL" . #x0003f2) ("GREEK LETTER YOT" . #x0003f3) ("GREEK CAPITAL THETA SYMBOL" . #x0003f4) ("GREEK LUNATE EPSILON SYMBOL" . #x0003f5) ("GREEK REVERSED LUNATE EPSILON SYMBOL" . #x0003f6) ("CYRILLIC CAPITAL LETTER IE WITH GRAVE" . #x000400) ("CYRILLIC CAPITAL LETTER IO" . #x000401) ("CYRILLIC CAPITAL LETTER DJE" . #x000402) ("CYRILLIC CAPITAL LETTER GJE" . #x000403) ("CYRILLIC CAPITAL LETTER UKRAINIAN IE" . #x000404) ("CYRILLIC CAPITAL LETTER DZE" . #x000405) ("CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I" . #x000406) ("CYRILLIC CAPITAL LETTER YI" . #x000407) ("CYRILLIC CAPITAL LETTER JE" . #x000408) ("CYRILLIC CAPITAL LETTER LJE" . #x000409) ("CYRILLIC CAPITAL LETTER NJE" . #x00040a) ("CYRILLIC CAPITAL LETTER TSHE" . #x00040b) ("CYRILLIC CAPITAL LETTER KJE" . #x00040c) ("CYRILLIC CAPITAL LETTER I WITH GRAVE" . #x00040d) ("CYRILLIC CAPITAL LETTER SHORT U" . #x00040e) ("CYRILLIC CAPITAL LETTER DZHE" . #x00040f) ("CYRILLIC CAPITAL LETTER A" . #x000410) ("CYRILLIC CAPITAL LETTER BE" . #x000411) ("CYRILLIC CAPITAL LETTER VE" . #x000412) ("CYRILLIC CAPITAL LETTER GHE" . #x000413) ("CYRILLIC CAPITAL LETTER DE" . #x000414) ("CYRILLIC CAPITAL LETTER IE" . #x000415) ("CYRILLIC CAPITAL LETTER ZHE" . #x000416) ("CYRILLIC CAPITAL LETTER ZE" . #x000417) ("CYRILLIC CAPITAL LETTER I" . #x000418) ("CYRILLIC CAPITAL LETTER SHORT I" . #x000419) ("CYRILLIC CAPITAL LETTER KA" . #x00041a) ("CYRILLIC CAPITAL LETTER EL" . #x00041b) ("CYRILLIC CAPITAL LETTER EM" . #x00041c) ("CYRILLIC CAPITAL LETTER EN" . #x00041d) ("CYRILLIC CAPITAL LETTER O" . #x00041e) ("CYRILLIC CAPITAL LETTER PE" . #x00041f) ("CYRILLIC CAPITAL LETTER ER" . #x000420) ("CYRILLIC CAPITAL LETTER ES" . #x000421) ("CYRILLIC CAPITAL LETTER TE" . #x000422) ("CYRILLIC CAPITAL LETTER U" . #x000423) ("CYRILLIC CAPITAL LETTER EF" . #x000424) ("CYRILLIC CAPITAL LETTER HA" . #x000425) ("CYRILLIC CAPITAL LETTER TSE" . #x000426) ("CYRILLIC CAPITAL LETTER CHE" . #x000427) ("CYRILLIC CAPITAL LETTER SHA" . #x000428) ("CYRILLIC CAPITAL LETTER SHCHA" . #x000429) ("CYRILLIC CAPITAL LETTER HARD SIGN" . #x00042a) ("CYRILLIC CAPITAL LETTER YERU" . #x00042b) ("CYRILLIC CAPITAL LETTER SOFT SIGN" . #x00042c) ("CYRILLIC CAPITAL LETTER E" . #x00042d) ("CYRILLIC CAPITAL LETTER YU" . #x00042e) ("CYRILLIC CAPITAL LETTER YA" . #x00042f) ("CYRILLIC SMALL LETTER A" . #x000430) ("CYRILLIC SMALL LETTER BE" . #x000431) ("CYRILLIC SMALL LETTER VE" . #x000432) ("CYRILLIC SMALL LETTER GHE" . #x000433) ("CYRILLIC SMALL LETTER DE" . #x000434) ("CYRILLIC SMALL LETTER IE" . #x000435) ("CYRILLIC SMALL LETTER ZHE" . #x000436) ("CYRILLIC SMALL LETTER ZE" . #x000437) ("CYRILLIC SMALL LETTER I" . #x000438) ("CYRILLIC SMALL LETTER SHORT I" . #x000439) ("CYRILLIC SMALL LETTER KA" . #x00043a) ("CYRILLIC SMALL LETTER EL" . #x00043b) ("CYRILLIC SMALL LETTER EM" . #x00043c) ("CYRILLIC SMALL LETTER EN" . #x00043d) ("CYRILLIC SMALL LETTER O" . #x00043e) ("CYRILLIC SMALL LETTER PE" . #x00043f) ("CYRILLIC SMALL LETTER ER" . #x000440) ("CYRILLIC SMALL LETTER ES" . #x000441) ("CYRILLIC SMALL LETTER TE" . #x000442) ("CYRILLIC SMALL LETTER U" . #x000443) ("CYRILLIC SMALL LETTER EF" . #x000444) ("CYRILLIC SMALL LETTER HA" . #x000445) ("CYRILLIC SMALL LETTER TSE" . #x000446) ("CYRILLIC SMALL LETTER CHE" . #x000447) ("CYRILLIC SMALL LETTER SHA" . #x000448) ("CYRILLIC SMALL LETTER SHCHA" . #x000449) ("CYRILLIC SMALL LETTER HARD SIGN" . #x00044a) ("CYRILLIC SMALL LETTER YERU" . #x00044b) ("CYRILLIC SMALL LETTER SOFT SIGN" . #x00044c) ("CYRILLIC SMALL LETTER E" . #x00044d) ("CYRILLIC SMALL LETTER YU" . #x00044e) ("CYRILLIC SMALL LETTER YA" . #x00044f) ("CYRILLIC SMALL LETTER IE WITH GRAVE" . #x000450) ("CYRILLIC SMALL LETTER IO" . #x000451) ("CYRILLIC SMALL LETTER DJE" . #x000452) ("CYRILLIC SMALL LETTER GJE" . #x000453) ("CYRILLIC SMALL LETTER UKRAINIAN IE" . #x000454) ("CYRILLIC SMALL LETTER DZE" . #x000455) ("CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I" . #x000456) ("CYRILLIC SMALL LETTER YI" . #x000457) ("CYRILLIC SMALL LETTER JE" . #x000458) ("CYRILLIC SMALL LETTER LJE" . #x000459) ("CYRILLIC SMALL LETTER NJE" . #x00045a) ("CYRILLIC SMALL LETTER TSHE" . #x00045b) ("CYRILLIC SMALL LETTER KJE" . #x00045c) ("CYRILLIC SMALL LETTER I WITH GRAVE" . #x00045d) ("CYRILLIC SMALL LETTER SHORT U" . #x00045e) ("CYRILLIC SMALL LETTER DZHE" . #x00045f) ("CYRILLIC CAPITAL LETTER OMEGA" . #x000460) ("CYRILLIC SMALL LETTER OMEGA" . #x000461) ("CYRILLIC CAPITAL LETTER YAT" . #x000462) ("CYRILLIC SMALL LETTER YAT" . #x000463) ("CYRILLIC CAPITAL LETTER IOTIFIED E" . #x000464) ("CYRILLIC SMALL LETTER IOTIFIED E" . #x000465) ("CYRILLIC CAPITAL LETTER LITTLE YUS" . #x000466) ("CYRILLIC SMALL LETTER LITTLE YUS" . #x000467) ("CYRILLIC CAPITAL LETTER IOTIFIED LITTLE YUS" . #x000468) ("CYRILLIC SMALL LETTER IOTIFIED LITTLE YUS" . #x000469) ("CYRILLIC CAPITAL LETTER BIG YUS" . #x00046a) ("CYRILLIC SMALL LETTER BIG YUS" . #x00046b) ("CYRILLIC CAPITAL LETTER IOTIFIED BIG YUS" . #x00046c) ("CYRILLIC SMALL LETTER IOTIFIED BIG YUS" . #x00046d) ("CYRILLIC CAPITAL LETTER KSI" . #x00046e) ("CYRILLIC SMALL LETTER KSI" . #x00046f) ("CYRILLIC CAPITAL LETTER PSI" . #x000470) ("CYRILLIC SMALL LETTER PSI" . #x000471) ("CYRILLIC CAPITAL LETTER FITA" . #x000472) ("CYRILLIC SMALL LETTER FITA" . #x000473) ("CYRILLIC CAPITAL LETTER IZHITSA" . #x000474) ("CYRILLIC SMALL LETTER IZHITSA" . #x000475) ("CYRILLIC CAPITAL LETTER IZHITSA WITH DOUBLE GRAVE ACCENT" . #x000476) ("CYRILLIC SMALL LETTER IZHITSA WITH DOUBLE GRAVE ACCENT" . #x000477) ("CYRILLIC CAPITAL LETTER UK" . #x000478) ("CYRILLIC SMALL LETTER UK" . #x000479) ("CYRILLIC CAPITAL LETTER ROUND OMEGA" . #x00047a) ("CYRILLIC SMALL LETTER ROUND OMEGA" . #x00047b) ("CYRILLIC CAPITAL LETTER OMEGA WITH TITLO" . #x00047c) ("CYRILLIC SMALL LETTER OMEGA WITH TITLO" . #x00047d) ("CYRILLIC CAPITAL LETTER OT" . #x00047e) ("CYRILLIC SMALL LETTER OT" . #x00047f) ("CYRILLIC CAPITAL LETTER KOPPA" . #x000480) ("CYRILLIC SMALL LETTER KOPPA" . #x000481) ("CYRILLIC THOUSANDS SIGN" . #x000482) ("COMBINING CYRILLIC TITLO" . #x000483) ("COMBINING CYRILLIC PALATALIZATION" . #x000484) ("COMBINING CYRILLIC DASIA PNEUMATA" . #x000485) ("COMBINING CYRILLIC PSILI PNEUMATA" . #x000486) ("COMBINING CYRILLIC HUNDRED THOUSANDS SIGN" . #x000488) ("COMBINING CYRILLIC MILLIONS SIGN" . #x000489) ("CYRILLIC CAPITAL LETTER SHORT I WITH TAIL" . #x00048a) ("CYRILLIC SMALL LETTER SHORT I WITH TAIL" . #x00048b) ("CYRILLIC CAPITAL LETTER SEMISOFT SIGN" . #x00048c) ("CYRILLIC SMALL LETTER SEMISOFT SIGN" . #x00048d) ("CYRILLIC CAPITAL LETTER ER WITH TICK" . #x00048e) ("CYRILLIC SMALL LETTER ER WITH TICK" . #x00048f) ("CYRILLIC CAPITAL LETTER GHE WITH UPTURN" . #x000490) ("CYRILLIC SMALL LETTER GHE WITH UPTURN" . #x000491) ("CYRILLIC CAPITAL LETTER GHE WITH STROKE" . #x000492) ("CYRILLIC SMALL LETTER GHE WITH STROKE" . #x000493) ("CYRILLIC CAPITAL LETTER GHE WITH MIDDLE HOOK" . #x000494) ("CYRILLIC SMALL LETTER GHE WITH MIDDLE HOOK" . #x000495) ("CYRILLIC CAPITAL LETTER ZHE WITH DESCENDER" . #x000496) ("CYRILLIC SMALL LETTER ZHE WITH DESCENDER" . #x000497) ("CYRILLIC CAPITAL LETTER ZE WITH DESCENDER" . #x000498) ("CYRILLIC SMALL LETTER ZE WITH DESCENDER" . #x000499) ("CYRILLIC CAPITAL LETTER KA WITH DESCENDER" . #x00049a) ("CYRILLIC SMALL LETTER KA WITH DESCENDER" . #x00049b) ("CYRILLIC CAPITAL LETTER KA WITH VERTICAL STROKE" . #x00049c) ("CYRILLIC SMALL LETTER KA WITH VERTICAL STROKE" . #x00049d) ("CYRILLIC CAPITAL LETTER KA WITH STROKE" . #x00049e) ("CYRILLIC SMALL LETTER KA WITH STROKE" . #x00049f) ("CYRILLIC CAPITAL LETTER BASHKIR KA" . #x0004a0) ("CYRILLIC SMALL LETTER BASHKIR KA" . #x0004a1) ("CYRILLIC CAPITAL LETTER EN WITH DESCENDER" . #x0004a2) ("CYRILLIC SMALL LETTER EN WITH DESCENDER" . #x0004a3) ("CYRILLIC CAPITAL LIGATURE EN GHE" . #x0004a4) ("CYRILLIC SMALL LIGATURE EN GHE" . #x0004a5) ("CYRILLIC CAPITAL LETTER PE WITH MIDDLE HOOK" . #x0004a6) ("CYRILLIC SMALL LETTER PE WITH MIDDLE HOOK" . #x0004a7) ("CYRILLIC CAPITAL LETTER ABKHASIAN HA" . #x0004a8) ("CYRILLIC SMALL LETTER ABKHASIAN HA" . #x0004a9) ("CYRILLIC CAPITAL LETTER ES WITH DESCENDER" . #x0004aa) ("CYRILLIC SMALL LETTER ES WITH DESCENDER" . #x0004ab) ("CYRILLIC CAPITAL LETTER TE WITH DESCENDER" . #x0004ac) ("CYRILLIC SMALL LETTER TE WITH DESCENDER" . #x0004ad) ("CYRILLIC CAPITAL LETTER STRAIGHT U" . #x0004ae) ("CYRILLIC SMALL LETTER STRAIGHT U" . #x0004af) ("CYRILLIC CAPITAL LETTER STRAIGHT U WITH STROKE" . #x0004b0) ("CYRILLIC SMALL LETTER STRAIGHT U WITH STROKE" . #x0004b1) ("CYRILLIC CAPITAL LETTER HA WITH DESCENDER" . #x0004b2) ("CYRILLIC SMALL LETTER HA WITH DESCENDER" . #x0004b3) ("CYRILLIC CAPITAL LIGATURE TE TSE" . #x0004b4) ("CYRILLIC SMALL LIGATURE TE TSE" . #x0004b5) ("CYRILLIC CAPITAL LETTER CHE WITH DESCENDER" . #x0004b6) ("CYRILLIC SMALL LETTER CHE WITH DESCENDER" . #x0004b7) ("CYRILLIC CAPITAL LETTER CHE WITH VERTICAL STROKE" . #x0004b8) ("CYRILLIC SMALL LETTER CHE WITH VERTICAL STROKE" . #x0004b9) ("CYRILLIC CAPITAL LETTER SHHA" . #x0004ba) ("CYRILLIC SMALL LETTER SHHA" . #x0004bb) ("CYRILLIC CAPITAL LETTER ABKHASIAN CHE" . #x0004bc) ("CYRILLIC SMALL LETTER ABKHASIAN CHE" . #x0004bd) ("CYRILLIC CAPITAL LETTER ABKHASIAN CHE WITH DESCENDER" . #x0004be) ("CYRILLIC SMALL LETTER ABKHASIAN CHE WITH DESCENDER" . #x0004bf) ("CYRILLIC LETTER PALOCHKA" . #x0004c0) ("CYRILLIC CAPITAL LETTER ZHE WITH BREVE" . #x0004c1) ("CYRILLIC SMALL LETTER ZHE WITH BREVE" . #x0004c2) ("CYRILLIC CAPITAL LETTER KA WITH HOOK" . #x0004c3) ("CYRILLIC SMALL LETTER KA WITH HOOK" . #x0004c4) ("CYRILLIC CAPITAL LETTER EL WITH TAIL" . #x0004c5) ("CYRILLIC SMALL LETTER EL WITH TAIL" . #x0004c6) ("CYRILLIC CAPITAL LETTER EN WITH HOOK" . #x0004c7) ("CYRILLIC SMALL LETTER EN WITH HOOK" . #x0004c8) ("CYRILLIC CAPITAL LETTER EN WITH TAIL" . #x0004c9) ("CYRILLIC SMALL LETTER EN WITH TAIL" . #x0004ca) ("CYRILLIC CAPITAL LETTER KHAKASSIAN CHE" . #x0004cb) ("CYRILLIC SMALL LETTER KHAKASSIAN CHE" . #x0004cc) ("CYRILLIC CAPITAL LETTER EM WITH TAIL" . #x0004cd) ("CYRILLIC SMALL LETTER EM WITH TAIL" . #x0004ce) ("CYRILLIC CAPITAL LETTER A WITH BREVE" . #x0004d0) ("CYRILLIC SMALL LETTER A WITH BREVE" . #x0004d1) ("CYRILLIC CAPITAL LETTER A WITH DIAERESIS" . #x0004d2) ("CYRILLIC SMALL LETTER A WITH DIAERESIS" . #x0004d3) ("CYRILLIC CAPITAL LIGATURE A IE" . #x0004d4) ("CYRILLIC SMALL LIGATURE A IE" . #x0004d5) ("CYRILLIC CAPITAL LETTER IE WITH BREVE" . #x0004d6) ("CYRILLIC SMALL LETTER IE WITH BREVE" . #x0004d7) ("CYRILLIC CAPITAL LETTER SCHWA" . #x0004d8) ("CYRILLIC SMALL LETTER SCHWA" . #x0004d9) ("CYRILLIC CAPITAL LETTER SCHWA WITH DIAERESIS" . #x0004da) ("CYRILLIC SMALL LETTER SCHWA WITH DIAERESIS" . #x0004db) ("CYRILLIC CAPITAL LETTER ZHE WITH DIAERESIS" . #x0004dc) ("CYRILLIC SMALL LETTER ZHE WITH DIAERESIS" . #x0004dd) ("CYRILLIC CAPITAL LETTER ZE WITH DIAERESIS" . #x0004de) ("CYRILLIC SMALL LETTER ZE WITH DIAERESIS" . #x0004df) ("CYRILLIC CAPITAL LETTER ABKHASIAN DZE" . #x0004e0) ("CYRILLIC SMALL LETTER ABKHASIAN DZE" . #x0004e1) ("CYRILLIC CAPITAL LETTER I WITH MACRON" . #x0004e2) ("CYRILLIC SMALL LETTER I WITH MACRON" . #x0004e3) ("CYRILLIC CAPITAL LETTER I WITH DIAERESIS" . #x0004e4) ("CYRILLIC SMALL LETTER I WITH DIAERESIS" . #x0004e5) ("CYRILLIC CAPITAL LETTER O WITH DIAERESIS" . #x0004e6) ("CYRILLIC SMALL LETTER O WITH DIAERESIS" . #x0004e7) ("CYRILLIC CAPITAL LETTER BARRED O" . #x0004e8) ("CYRILLIC SMALL LETTER BARRED O" . #x0004e9) ("CYRILLIC CAPITAL LETTER BARRED O WITH DIAERESIS" . #x0004ea) ("CYRILLIC SMALL LETTER BARRED O WITH DIAERESIS" . #x0004eb) ("CYRILLIC CAPITAL LETTER E WITH DIAERESIS" . #x0004ec) ("CYRILLIC SMALL LETTER E WITH DIAERESIS" . #x0004ed) ("CYRILLIC CAPITAL LETTER U WITH MACRON" . #x0004ee) ("CYRILLIC SMALL LETTER U WITH MACRON" . #x0004ef) ("CYRILLIC CAPITAL LETTER U WITH DIAERESIS" . #x0004f0) ("CYRILLIC SMALL LETTER U WITH DIAERESIS" . #x0004f1) ("CYRILLIC CAPITAL LETTER U WITH DOUBLE ACUTE" . #x0004f2) ("CYRILLIC SMALL LETTER U WITH DOUBLE ACUTE" . #x0004f3) ("CYRILLIC CAPITAL LETTER CHE WITH DIAERESIS" . #x0004f4) ("CYRILLIC SMALL LETTER CHE WITH DIAERESIS" . #x0004f5) ("CYRILLIC CAPITAL LETTER YERU WITH DIAERESIS" . #x0004f8) ("CYRILLIC SMALL LETTER YERU WITH DIAERESIS" . #x0004f9) ("EN QUAD" . #x002000) ("EM QUAD" . #x002001) ("EN SPACE" . #x002002) ("EM SPACE" . #x002003) ("THREE-PER-EM SPACE" . #x002004) ("FOUR-PER-EM SPACE" . #x002005) ("SIX-PER-EM SPACE" . #x002006) ("FIGURE SPACE" . #x002007) ("PUNCTUATION SPACE" . #x002008) ("THIN SPACE" . #x002009) ("HAIR SPACE" . #x00200a) ("ZERO WIDTH SPACE" . #x00200b) ("ZERO WIDTH NON-JOINER" . #x00200c) ("ZERO WIDTH JOINER" . #x00200d) ("LEFT-TO-RIGHT MARK" . #x00200e) ("RIGHT-TO-LEFT MARK" . #x00200f) ("HYPHEN" . #x002010) ("NON-BREAKING HYPHEN" . #x002011) ("FIGURE DASH" . #x002012) ("EN DASH" . #x002013) ("EM DASH" . #x002014) ("HORIZONTAL BAR" . #x002015) ("DOUBLE VERTICAL LINE" . #x002016) ("DOUBLE LOW LINE" . #x002017) ("LEFT SINGLE QUOTATION MARK" . #x002018) ("RIGHT SINGLE QUOTATION MARK" . #x002019) ("SINGLE LOW-9 QUOTATION MARK" . #x00201a) ("SINGLE HIGH-REVERSED-9 QUOTATION MARK" . #x00201b) ("LEFT DOUBLE QUOTATION MARK" . #x00201c) ("RIGHT DOUBLE QUOTATION MARK" . #x00201d) ("DOUBLE LOW-9 QUOTATION MARK" . #x00201e) ("DOUBLE HIGH-REVERSED-9 QUOTATION MARK" . #x00201f) ("DAGGER" . #x002020) ("DOUBLE DAGGER" . #x002021) ("BULLET" . #x002022) ("TRIANGULAR BULLET" . #x002023) ("ONE DOT LEADER" . #x002024) ("TWO DOT LEADER" . #x002025) ("HORIZONTAL ELLIPSIS" . #x002026) ("HYPHENATION POINT" . #x002027) ("LINE SEPARATOR" . #x002028) ("PARAGRAPH SEPARATOR" . #x002029) ("LEFT-TO-RIGHT EMBEDDING" . #x00202a) ("RIGHT-TO-LEFT EMBEDDING" . #x00202b) ("POP DIRECTIONAL FORMATTING" . #x00202c) ("LEFT-TO-RIGHT OVERRIDE" . #x00202d) ("RIGHT-TO-LEFT OVERRIDE" . #x00202e) ("NARROW NO-BREAK SPACE" . #x00202f) ("PER MILLE SIGN" . #x002030) ("PER TEN THOUSAND SIGN" . #x002031) ("PRIME" . #x002032) ("DOUBLE PRIME" . #x002033) ("TRIPLE PRIME" . #x002034) ("REVERSED PRIME" . #x002035) ("REVERSED DOUBLE PRIME" . #x002036) ("REVERSED TRIPLE PRIME" . #x002037) ("CARET" . #x002038) ("SINGLE LEFT-POINTING ANGLE QUOTATION MARK" . #x002039) ("SINGLE RIGHT-POINTING ANGLE QUOTATION MARK" . #x00203a) ("REFERENCE MARK" . #x00203b) ("DOUBLE EXCLAMATION MARK" . #x00203c) ("INTERROBANG" . #x00203d) ("OVERLINE" . #x00203e) ("UNDERTIE" . #x00203f) ("CHARACTER TIE" . #x002040) ("CARET INSERTION POINT" . #x002041) ("ASTERISM" . #x002042) ("HYPHEN BULLET" . #x002043) ("FRACTION SLASH" . #x002044) ("LEFT SQUARE BRACKET WITH QUILL" . #x002045) ("RIGHT SQUARE BRACKET WITH QUILL" . #x002046) ("DOUBLE QUESTION MARK" . #x002047) ("QUESTION EXCLAMATION MARK" . #x002048) ("EXCLAMATION QUESTION MARK" . #x002049) ("TIRONIAN SIGN ET" . #x00204a) ("REVERSED PILCROW SIGN" . #x00204b) ("BLACK LEFTWARDS BULLET" . #x00204c) ("BLACK RIGHTWARDS BULLET" . #x00204d) ("LOW ASTERISK" . #x00204e) ("REVERSED SEMICOLON" . #x00204f) ("CLOSE UP" . #x002050) ("TWO ASTERISKS ALIGNED VERTICALLY" . #x002051) ("COMMERCIAL MINUS SIGN" . #x002052) ("QUADRUPLE PRIME" . #x002057) ("MEDIUM MATHEMATICAL SPACE" . #x00205f) ("WORD JOINER" . #x002060) ("FUNCTION APPLICATION" . #x002061) ("INVISIBLE TIMES" . #x002062) ("INVISIBLE SEPARATOR" . #x002063) ("INHIBIT SYMMETRIC SWAPPING" . #x00206a) ("ACTIVATE SYMMETRIC SWAPPING" . #x00206b) ("INHIBIT ARABIC FORM SHAPING" . #x00206c) ("ACTIVATE ARABIC FORM SHAPING" . #x00206d) ("NATIONAL DIGIT SHAPES" . #x00206e) ("NOMINAL DIGIT SHAPES" . #x00206f) ("SUPERSCRIPT ZERO" . #x002070) ("SUPERSCRIPT LATIN SMALL LETTER I" . #x002071) ("SUPERSCRIPT FOUR" . #x002074) ("SUPERSCRIPT FIVE" . #x002075) ("SUPERSCRIPT SIX" . #x002076) ("SUPERSCRIPT SEVEN" . #x002077) ("SUPERSCRIPT EIGHT" . #x002078) ("SUPERSCRIPT NINE" . #x002079) ("SUPERSCRIPT PLUS SIGN" . #x00207a) ("SUPERSCRIPT MINUS" . #x00207b) ("SUPERSCRIPT EQUALS SIGN" . #x00207c) ("SUPERSCRIPT LEFT PARENTHESIS" . #x00207d) ("SUPERSCRIPT RIGHT PARENTHESIS" . #x00207e) ("SUPERSCRIPT LATIN SMALL LETTER N" . #x00207f) ("SUBSCRIPT ZERO" . #x002080) ("SUBSCRIPT ONE" . #x002081) ("SUBSCRIPT TWO" . #x002082) ("SUBSCRIPT THREE" . #x002083) ("SUBSCRIPT FOUR" . #x002084) ("SUBSCRIPT FIVE" . #x002085) ("SUBSCRIPT SIX" . #x002086) ("SUBSCRIPT SEVEN" . #x002087) ("SUBSCRIPT EIGHT" . #x002088) ("SUBSCRIPT NINE" . #x002089) ("SUBSCRIPT PLUS SIGN" . #x00208a) ("SUBSCRIPT MINUS" . #x00208b) ("SUBSCRIPT EQUALS SIGN" . #x00208c) ("SUBSCRIPT LEFT PARENTHESIS" . #x00208d) ("SUBSCRIPT RIGHT PARENTHESIS" . #x00208e) ("EURO-CURRENCY SIGN" . #x0020a0) ("COLON SIGN" . #x0020a1) ("CRUZEIRO SIGN" . #x0020a2) ("FRENCH FRANC SIGN" . #x0020a3) ("LIRA SIGN" . #x0020a4) ("MILL SIGN" . #x0020a5) ("NAIRA SIGN" . #x0020a6) ("PESETA SIGN" . #x0020a7) ("RUPEE SIGN" . #x0020a8) ("WON SIGN" . #x0020a9) ("NEW SHEQEL SIGN" . #x0020aa) ("DONG SIGN" . #x0020ab) ("EURO SIGN" . #x0020ac) ("KIP SIGN" . #x0020ad) ("TUGRIK SIGN" . #x0020ae) ("DRACHMA SIGN" . #x0020af) ("GERMAN PENNY SIGN" . #x0020b0) ("PESO SIGN" . #x0020b1) ("COMBINING LEFT HARPOON ABOVE" . #x0020d0) ("COMBINING RIGHT HARPOON ABOVE" . #x0020d1) ("COMBINING LONG VERTICAL LINE OVERLAY" . #x0020d2) ("COMBINING SHORT VERTICAL LINE OVERLAY" . #x0020d3) ("COMBINING ANTICLOCKWISE ARROW ABOVE" . #x0020d4) ("COMBINING CLOCKWISE ARROW ABOVE" . #x0020d5) ("COMBINING LEFT ARROW ABOVE" . #x0020d6) ("COMBINING RIGHT ARROW ABOVE" . #x0020d7) ("COMBINING RING OVERLAY" . #x0020d8) ("COMBINING CLOCKWISE RING OVERLAY" . #x0020d9) ("COMBINING ANTICLOCKWISE RING OVERLAY" . #x0020da) ("COMBINING THREE DOTS ABOVE" . #x0020db) ("COMBINING FOUR DOTS ABOVE" . #x0020dc) ("COMBINING ENCLOSING CIRCLE" . #x0020dd) ("COMBINING ENCLOSING SQUARE" . #x0020de) ("COMBINING ENCLOSING DIAMOND" . #x0020df) ("COMBINING ENCLOSING CIRCLE BACKSLASH" . #x0020e0) ("COMBINING LEFT RIGHT ARROW ABOVE" . #x0020e1) ("COMBINING ENCLOSING SCREEN" . #x0020e2) ("COMBINING ENCLOSING KEYCAP" . #x0020e3) ("COMBINING ENCLOSING UPWARD POINTING TRIANGLE" . #x0020e4) ("COMBINING REVERSE SOLIDUS OVERLAY" . #x0020e5) ("COMBINING DOUBLE VERTICAL STROKE OVERLAY" . #x0020e6) ("COMBINING ANNUITY SYMBOL" . #x0020e7) ("COMBINING TRIPLE UNDERDOT" . #x0020e8) ("COMBINING WIDE BRIDGE ABOVE" . #x0020e9) ("COMBINING LEFTWARDS ARROW OVERLAY" . #x0020ea) ("ACCOUNT OF" . #x002100) ("ADDRESSED TO THE SUBJECT" . #x002101) ("DOUBLE-STRUCK CAPITAL C" . #x002102) ("DEGREE CELSIUS" . #x002103) ("CENTRE LINE SYMBOL" . #x002104) ("CARE OF" . #x002105) ("CADA UNA" . #x002106) ("EULER CONSTANT" . #x002107) ("SCRUPLE" . #x002108) ("DEGREE FAHRENHEIT" . #x002109) ("SCRIPT SMALL G" . #x00210a) ("SCRIPT CAPITAL H" . #x00210b) ("BLACK-LETTER CAPITAL H" . #x00210c) ("DOUBLE-STRUCK CAPITAL H" . #x00210d) ("PLANCK CONSTANT" . #x00210e) ("PLANCK CONSTANT OVER TWO PI" . #x00210f) ("SCRIPT CAPITAL I" . #x002110) ("BLACK-LETTER CAPITAL I" . #x002111) ("SCRIPT CAPITAL L" . #x002112) ("SCRIPT SMALL L" . #x002113) ("L B BAR SYMBOL" . #x002114) ("DOUBLE-STRUCK CAPITAL N" . #x002115) ("NUMERO SIGN" . #x002116) ("SOUND RECORDING COPYRIGHT" . #x002117) ("SCRIPT CAPITAL P" . #x002118) ("DOUBLE-STRUCK CAPITAL P" . #x002119) ("DOUBLE-STRUCK CAPITAL Q" . #x00211a) ("SCRIPT CAPITAL R" . #x00211b) ("BLACK-LETTER CAPITAL R" . #x00211c) ("DOUBLE-STRUCK CAPITAL R" . #x00211d) ("PRESCRIPTION TAKE" . #x00211e) ("RESPONSE" . #x00211f) ("SERVICE MARK" . #x002120) ("TELEPHONE SIGN" . #x002121) ("TRADE MARK SIGN" . #x002122) ("VERSICLE" . #x002123) ("DOUBLE-STRUCK CAPITAL Z" . #x002124) ("OUNCE SIGN" . #x002125) ("OHM SIGN" . #x002126) ("INVERTED OHM SIGN" . #x002127) ("BLACK-LETTER CAPITAL Z" . #x002128) ("TURNED GREEK SMALL LETTER IOTA" . #x002129) ("KELVIN SIGN" . #x00212a) ("ANGSTROM SIGN" . #x00212b) ("SCRIPT CAPITAL B" . #x00212c) ("BLACK-LETTER CAPITAL C" . #x00212d) ("ESTIMATED SYMBOL" . #x00212e) ("SCRIPT SMALL E" . #x00212f) ("SCRIPT CAPITAL E" . #x002130) ("SCRIPT CAPITAL F" . #x002131) ("TURNED CAPITAL F" . #x002132) ("SCRIPT CAPITAL M" . #x002133) ("SCRIPT SMALL O" . #x002134) ("ALEF SYMBOL" . #x002135) ("BET SYMBOL" . #x002136) ("GIMEL SYMBOL" . #x002137) ("DALET SYMBOL" . #x002138) ("INFORMATION SOURCE" . #x002139) ("ROTATED CAPITAL Q" . #x00213a) ("DOUBLE-STRUCK SMALL GAMMA" . #x00213d) ("DOUBLE-STRUCK CAPITAL GAMMA" . #x00213e) ("DOUBLE-STRUCK CAPITAL PI" . #x00213f) ("DOUBLE-STRUCK N-ARY SUMMATION" . #x002140) ("TURNED SANS-SERIF CAPITAL G" . #x002141) ("TURNED SANS-SERIF CAPITAL L" . #x002142) ("REVERSED SANS-SERIF CAPITAL L" . #x002143) ("TURNED SANS-SERIF CAPITAL Y" . #x002144) ("DOUBLE-STRUCK ITALIC CAPITAL D" . #x002145) ("DOUBLE-STRUCK ITALIC SMALL D" . #x002146) ("DOUBLE-STRUCK ITALIC SMALL E" . #x002147) ("DOUBLE-STRUCK ITALIC SMALL I" . #x002148) ("DOUBLE-STRUCK ITALIC SMALL J" . #x002149) ("PROPERTY LINE" . #x00214a) ("TURNED AMPERSAND" . #x00214b) ("VULGAR FRACTION ONE THIRD" . #x002153) ("VULGAR FRACTION TWO THIRDS" . #x002154) ("VULGAR FRACTION ONE FIFTH" . #x002155) ("VULGAR FRACTION TWO FIFTHS" . #x002156) ("VULGAR FRACTION THREE FIFTHS" . #x002157) ("VULGAR FRACTION FOUR FIFTHS" . #x002158) ("VULGAR FRACTION ONE SIXTH" . #x002159) ("VULGAR FRACTION FIVE SIXTHS" . #x00215a) ("VULGAR FRACTION ONE EIGHTH" . #x00215b) ("VULGAR FRACTION THREE EIGHTHS" . #x00215c) ("VULGAR FRACTION FIVE EIGHTHS" . #x00215d) ("VULGAR FRACTION SEVEN EIGHTHS" . #x00215e) ("FRACTION NUMERATOR ONE" . #x00215f) ("ROMAN NUMERAL ONE" . #x002160) ("ROMAN NUMERAL TWO" . #x002161) ("ROMAN NUMERAL THREE" . #x002162) ("ROMAN NUMERAL FOUR" . #x002163) ("ROMAN NUMERAL FIVE" . #x002164) ("ROMAN NUMERAL SIX" . #x002165) ("ROMAN NUMERAL SEVEN" . #x002166) ("ROMAN NUMERAL EIGHT" . #x002167) ("ROMAN NUMERAL NINE" . #x002168) ("ROMAN NUMERAL TEN" . #x002169) ("ROMAN NUMERAL ELEVEN" . #x00216a) ("ROMAN NUMERAL TWELVE" . #x00216b) ("ROMAN NUMERAL FIFTY" . #x00216c) ("ROMAN NUMERAL ONE HUNDRED" . #x00216d) ("ROMAN NUMERAL FIVE HUNDRED" . #x00216e) ("ROMAN NUMERAL ONE THOUSAND" . #x00216f) ("SMALL ROMAN NUMERAL ONE" . #x002170) ("SMALL ROMAN NUMERAL TWO" . #x002171) ("SMALL ROMAN NUMERAL THREE" . #x002172) ("SMALL ROMAN NUMERAL FOUR" . #x002173) ("SMALL ROMAN NUMERAL FIVE" . #x002174) ("SMALL ROMAN NUMERAL SIX" . #x002175) ("SMALL ROMAN NUMERAL SEVEN" . #x002176) ("SMALL ROMAN NUMERAL EIGHT" . #x002177) ("SMALL ROMAN NUMERAL NINE" . #x002178) ("SMALL ROMAN NUMERAL TEN" . #x002179) ("SMALL ROMAN NUMERAL ELEVEN" . #x00217a) ("SMALL ROMAN NUMERAL TWELVE" . #x00217b) ("SMALL ROMAN NUMERAL FIFTY" . #x00217c) ("SMALL ROMAN NUMERAL ONE HUNDRED" . #x00217d) ("SMALL ROMAN NUMERAL FIVE HUNDRED" . #x00217e) ("SMALL ROMAN NUMERAL ONE THOUSAND" . #x00217f) ("ROMAN NUMERAL ONE THOUSAND C D" . #x002180) ("ROMAN NUMERAL FIVE THOUSAND" . #x002181) ("ROMAN NUMERAL TEN THOUSAND" . #x002182) ("ROMAN NUMERAL REVERSED ONE HUNDRED" . #x002183) ("LEFTWARDS ARROW" . #x002190) ("UPWARDS ARROW" . #x002191) ("RIGHTWARDS ARROW" . #x002192) ("DOWNWARDS ARROW" . #x002193) ("LEFT RIGHT ARROW" . #x002194) ("UP DOWN ARROW" . #x002195) ("NORTH WEST ARROW" . #x002196) ("NORTH EAST ARROW" . #x002197) ("SOUTH EAST ARROW" . #x002198) ("SOUTH WEST ARROW" . #x002199) ("LEFTWARDS ARROW WITH STROKE" . #x00219a) ("RIGHTWARDS ARROW WITH STROKE" . #x00219b) ("LEFTWARDS WAVE ARROW" . #x00219c) ("RIGHTWARDS WAVE ARROW" . #x00219d) ("LEFTWARDS TWO HEADED ARROW" . #x00219e) ("UPWARDS TWO HEADED ARROW" . #x00219f) ("RIGHTWARDS TWO HEADED ARROW" . #x0021a0) ("DOWNWARDS TWO HEADED ARROW" . #x0021a1) ("LEFTWARDS ARROW WITH TAIL" . #x0021a2) ("RIGHTWARDS ARROW WITH TAIL" . #x0021a3) ("LEFTWARDS ARROW FROM BAR" . #x0021a4) ("UPWARDS ARROW FROM BAR" . #x0021a5) ("RIGHTWARDS ARROW FROM BAR" . #x0021a6) ("DOWNWARDS ARROW FROM BAR" . #x0021a7) ("UP DOWN ARROW WITH BASE" . #x0021a8) ("LEFTWARDS ARROW WITH HOOK" . #x0021a9) ("RIGHTWARDS ARROW WITH HOOK" . #x0021aa) ("LEFTWARDS ARROW WITH LOOP" . #x0021ab) ("RIGHTWARDS ARROW WITH LOOP" . #x0021ac) ("LEFT RIGHT WAVE ARROW" . #x0021ad) ("LEFT RIGHT ARROW WITH STROKE" . #x0021ae) ("DOWNWARDS ZIGZAG ARROW" . #x0021af) ("UPWARDS ARROW WITH TIP LEFTWARDS" . #x0021b0) ("UPWARDS ARROW WITH TIP RIGHTWARDS" . #x0021b1) ("DOWNWARDS ARROW WITH TIP LEFTWARDS" . #x0021b2) ("DOWNWARDS ARROW WITH TIP RIGHTWARDS" . #x0021b3) ("RIGHTWARDS ARROW WITH CORNER DOWNWARDS" . #x0021b4) ("DOWNWARDS ARROW WITH CORNER LEFTWARDS" . #x0021b5) ("ANTICLOCKWISE TOP SEMICIRCLE ARROW" . #x0021b6) ("CLOCKWISE TOP SEMICIRCLE ARROW" . #x0021b7) ("NORTH WEST ARROW TO LONG BAR" . #x0021b8) ("LEFTWARDS ARROW TO BAR OVER RIGHTWARDS ARROW TO BAR" . #x0021b9) ("ANTICLOCKWISE OPEN CIRCLE ARROW" . #x0021ba) ("CLOCKWISE OPEN CIRCLE ARROW" . #x0021bb) ("LEFTWARDS HARPOON WITH BARB UPWARDS" . #x0021bc) ("LEFTWARDS HARPOON WITH BARB DOWNWARDS" . #x0021bd) ("UPWARDS HARPOON WITH BARB RIGHTWARDS" . #x0021be) ("UPWARDS HARPOON WITH BARB LEFTWARDS" . #x0021bf) ("RIGHTWARDS HARPOON WITH BARB UPWARDS" . #x0021c0) ("RIGHTWARDS HARPOON WITH BARB DOWNWARDS" . #x0021c1) ("DOWNWARDS HARPOON WITH BARB RIGHTWARDS" . #x0021c2) ("DOWNWARDS HARPOON WITH BARB LEFTWARDS" . #x0021c3) ("RIGHTWARDS ARROW OVER LEFTWARDS ARROW" . #x0021c4) ("UPWARDS ARROW LEFTWARDS OF DOWNWARDS ARROW" . #x0021c5) ("LEFTWARDS ARROW OVER RIGHTWARDS ARROW" . #x0021c6) ("LEFTWARDS PAIRED ARROWS" . #x0021c7) ("UPWARDS PAIRED ARROWS" . #x0021c8) ("RIGHTWARDS PAIRED ARROWS" . #x0021c9) ("DOWNWARDS PAIRED ARROWS" . #x0021ca) ("LEFTWARDS HARPOON OVER RIGHTWARDS HARPOON" . #x0021cb) ("RIGHTWARDS HARPOON OVER LEFTWARDS HARPOON" . #x0021cc) ("LEFTWARDS DOUBLE ARROW WITH STROKE" . #x0021cd) ("LEFT RIGHT DOUBLE ARROW WITH STROKE" . #x0021ce) ("RIGHTWARDS DOUBLE ARROW WITH STROKE" . #x0021cf) ("LEFTWARDS DOUBLE ARROW" . #x0021d0) ("UPWARDS DOUBLE ARROW" . #x0021d1) ("RIGHTWARDS DOUBLE ARROW" . #x0021d2) ("DOWNWARDS DOUBLE ARROW" . #x0021d3) ("LEFT RIGHT DOUBLE ARROW" . #x0021d4) ("UP DOWN DOUBLE ARROW" . #x0021d5) ("NORTH WEST DOUBLE ARROW" . #x0021d6) ("NORTH EAST DOUBLE ARROW" . #x0021d7) ("SOUTH EAST DOUBLE ARROW" . #x0021d8) ("SOUTH WEST DOUBLE ARROW" . #x0021d9) ("LEFTWARDS TRIPLE ARROW" . #x0021da) ("RIGHTWARDS TRIPLE ARROW" . #x0021db) ("LEFTWARDS SQUIGGLE ARROW" . #x0021dc) ("RIGHTWARDS SQUIGGLE ARROW" . #x0021dd) ("UPWARDS ARROW WITH DOUBLE STROKE" . #x0021de) ("DOWNWARDS ARROW WITH DOUBLE STROKE" . #x0021df) ("LEFTWARDS DASHED ARROW" . #x0021e0) ("UPWARDS DASHED ARROW" . #x0021e1) ("RIGHTWARDS DASHED ARROW" . #x0021e2) ("DOWNWARDS DASHED ARROW" . #x0021e3) ("LEFTWARDS ARROW TO BAR" . #x0021e4) ("RIGHTWARDS ARROW TO BAR" . #x0021e5) ("LEFTWARDS WHITE ARROW" . #x0021e6) ("UPWARDS WHITE ARROW" . #x0021e7) ("RIGHTWARDS WHITE ARROW" . #x0021e8) ("DOWNWARDS WHITE ARROW" . #x0021e9) ("UPWARDS WHITE ARROW FROM BAR" . #x0021ea) ("UPWARDS WHITE ARROW ON PEDESTAL" . #x0021eb) ("UPWARDS WHITE ARROW ON PEDESTAL WITH HORIZONTAL BAR" . #x0021ec) ("UPWARDS WHITE ARROW ON PEDESTAL WITH VERTICAL BAR" . #x0021ed) ("UPWARDS WHITE DOUBLE ARROW" . #x0021ee) ("UPWARDS WHITE DOUBLE ARROW ON PEDESTAL" . #x0021ef) ("RIGHTWARDS WHITE ARROW FROM WALL" . #x0021f0) ("NORTH WEST ARROW TO CORNER" . #x0021f1) ("SOUTH EAST ARROW TO CORNER" . #x0021f2) ("UP DOWN WHITE ARROW" . #x0021f3) ("RIGHT ARROW WITH SMALL CIRCLE" . #x0021f4) ("DOWNWARDS ARROW LEFTWARDS OF UPWARDS ARROW" . #x0021f5) ("THREE RIGHTWARDS ARROWS" . #x0021f6) ("LEFTWARDS ARROW WITH VERTICAL STROKE" . #x0021f7) ("RIGHTWARDS ARROW WITH VERTICAL STROKE" . #x0021f8) ("LEFT RIGHT ARROW WITH VERTICAL STROKE" . #x0021f9) ("LEFTWARDS ARROW WITH DOUBLE VERTICAL STROKE" . #x0021fa) ("RIGHTWARDS ARROW WITH DOUBLE VERTICAL STROKE" . #x0021fb) ("LEFT RIGHT ARROW WITH DOUBLE VERTICAL STROKE" . #x0021fc) ("LEFTWARDS OPEN-HEADED ARROW" . #x0021fd) ("RIGHTWARDS OPEN-HEADED ARROW" . #x0021fe) ("LEFT RIGHT OPEN-HEADED ARROW" . #x0021ff) ("FOR ALL" . #x002200) ("COMPLEMENT" . #x002201) ("PARTIAL DIFFERENTIAL" . #x002202) ("THERE EXISTS" . #x002203) ("THERE DOES NOT EXIST" . #x002204) ("EMPTY SET" . #x002205) ("INCREMENT" . #x002206) ("NABLA" . #x002207) ("ELEMENT OF" . #x002208) ("NOT AN ELEMENT OF" . #x002209) ("SMALL ELEMENT OF" . #x00220a) ("CONTAINS AS MEMBER" . #x00220b) ("DOES NOT CONTAIN AS MEMBER" . #x00220c) ("SMALL CONTAINS AS MEMBER" . #x00220d) ("END OF PROOF" . #x00220e) ("N-ARY PRODUCT" . #x00220f) ("N-ARY COPRODUCT" . #x002210) ("N-ARY SUMMATION" . #x002211) ("MINUS SIGN" . #x002212) ("MINUS-OR-PLUS SIGN" . #x002213) ("DOT PLUS" . #x002214) ("DIVISION SLASH" . #x002215) ("SET MINUS" . #x002216) ("ASTERISK OPERATOR" . #x002217) ("RING OPERATOR" . #x002218) ("BULLET OPERATOR" . #x002219) ("SQUARE ROOT" . #x00221a) ("CUBE ROOT" . #x00221b) ("FOURTH ROOT" . #x00221c) ("PROPORTIONAL TO" . #x00221d) ("INFINITY" . #x00221e) ("RIGHT ANGLE" . #x00221f) ("ANGLE" . #x002220) ("MEASURED ANGLE" . #x002221) ("SPHERICAL ANGLE" . #x002222) ("DIVIDES" . #x002223) ("DOES NOT DIVIDE" . #x002224) ("PARALLEL TO" . #x002225) ("NOT PARALLEL TO" . #x002226) ("LOGICAL AND" . #x002227) ("LOGICAL OR" . #x002228) ("INTERSECTION" . #x002229) ("UNION" . #x00222a) ("INTEGRAL" . #x00222b) ("DOUBLE INTEGRAL" . #x00222c) ("TRIPLE INTEGRAL" . #x00222d) ("CONTOUR INTEGRAL" . #x00222e) ("SURFACE INTEGRAL" . #x00222f) ("VOLUME INTEGRAL" . #x002230) ("CLOCKWISE INTEGRAL" . #x002231) ("CLOCKWISE CONTOUR INTEGRAL" . #x002232) ("ANTICLOCKWISE CONTOUR INTEGRAL" . #x002233) ("THEREFORE" . #x002234) ("BECAUSE" . #x002235) ("RATIO" . #x002236) ("PROPORTION" . #x002237) ("DOT MINUS" . #x002238) ("EXCESS" . #x002239) ("GEOMETRIC PROPORTION" . #x00223a) ("HOMOTHETIC" . #x00223b) ("TILDE OPERATOR" . #x00223c) ("REVERSED TILDE" . #x00223d) ("INVERTED LAZY S" . #x00223e) ("SINE WAVE" . #x00223f) ("WREATH PRODUCT" . #x002240) ("NOT TILDE" . #x002241) ("MINUS TILDE" . #x002242) ("ASYMPTOTICALLY EQUAL TO" . #x002243) ("NOT ASYMPTOTICALLY EQUAL TO" . #x002244) ("APPROXIMATELY EQUAL TO" . #x002245) ("APPROXIMATELY BUT NOT ACTUALLY EQUAL TO" . #x002246) ("NEITHER APPROXIMATELY NOR ACTUALLY EQUAL TO" . #x002247) ("ALMOST EQUAL TO" . #x002248) ("NOT ALMOST EQUAL TO" . #x002249) ("ALMOST EQUAL OR EQUAL TO" . #x00224a) ("TRIPLE TILDE" . #x00224b) ("ALL EQUAL TO" . #x00224c) ("EQUIVALENT TO" . #x00224d) ("GEOMETRICALLY EQUIVALENT TO" . #x00224e) ("DIFFERENCE BETWEEN" . #x00224f) ("APPROACHES THE LIMIT" . #x002250) ("GEOMETRICALLY EQUAL TO" . #x002251) ("APPROXIMATELY EQUAL TO OR THE IMAGE OF" . #x002252) ("IMAGE OF OR APPROXIMATELY EQUAL TO" . #x002253) ("COLON EQUALS" . #x002254) ("EQUALS COLON" . #x002255) ("RING IN EQUAL TO" . #x002256) ("RING EQUAL TO" . #x002257) ("CORRESPONDS TO" . #x002258) ("ESTIMATES" . #x002259) ("EQUIANGULAR TO" . #x00225a) ("STAR EQUALS" . #x00225b) ("DELTA EQUAL TO" . #x00225c) ("EQUAL TO BY DEFINITION" . #x00225d) ("MEASURED BY" . #x00225e) ("QUESTIONED EQUAL TO" . #x00225f) ("NOT EQUAL TO" . #x002260) ("IDENTICAL TO" . #x002261) ("NOT IDENTICAL TO" . #x002262) ("STRICTLY EQUIVALENT TO" . #x002263) ("LESS-THAN OR EQUAL TO" . #x002264) ("GREATER-THAN OR EQUAL TO" . #x002265) ("LESS-THAN OVER EQUAL TO" . #x002266) ("GREATER-THAN OVER EQUAL TO" . #x002267) ("LESS-THAN BUT NOT EQUAL TO" . #x002268) ("GREATER-THAN BUT NOT EQUAL TO" . #x002269) ("MUCH LESS-THAN" . #x00226a) ("MUCH GREATER-THAN" . #x00226b) ("BETWEEN" . #x00226c) ("NOT EQUIVALENT TO" . #x00226d) ("NOT LESS-THAN" . #x00226e) ("NOT GREATER-THAN" . #x00226f) ("NEITHER LESS-THAN NOR EQUAL TO" . #x002270) ("NEITHER GREATER-THAN NOR EQUAL TO" . #x002271) ("LESS-THAN OR EQUIVALENT TO" . #x002272) ("GREATER-THAN OR EQUIVALENT TO" . #x002273) ("NEITHER LESS-THAN NOR EQUIVALENT TO" . #x002274) ("NEITHER GREATER-THAN NOR EQUIVALENT TO" . #x002275) ("LESS-THAN OR GREATER-THAN" . #x002276) ("GREATER-THAN OR LESS-THAN" . #x002277) ("NEITHER LESS-THAN NOR GREATER-THAN" . #x002278) ("NEITHER GREATER-THAN NOR LESS-THAN" . #x002279) ("PRECEDES" . #x00227a) ("SUCCEEDS" . #x00227b) ("PRECEDES OR EQUAL TO" . #x00227c) ("SUCCEEDS OR EQUAL TO" . #x00227d) ("PRECEDES OR EQUIVALENT TO" . #x00227e) ("SUCCEEDS OR EQUIVALENT TO" . #x00227f) ("DOES NOT PRECEDE" . #x002280) ("DOES NOT SUCCEED" . #x002281) ("SUBSET OF" . #x002282) ("SUPERSET OF" . #x002283) ("NOT A SUBSET OF" . #x002284) ("NOT A SUPERSET OF" . #x002285) ("SUBSET OF OR EQUAL TO" . #x002286) ("SUPERSET OF OR EQUAL TO" . #x002287) ("NEITHER A SUBSET OF NOR EQUAL TO" . #x002288) ("NEITHER A SUPERSET OF NOR EQUAL TO" . #x002289) ("SUBSET OF WITH NOT EQUAL TO" . #x00228a) ("SUPERSET OF WITH NOT EQUAL TO" . #x00228b) ("MULTISET" . #x00228c) ("MULTISET MULTIPLICATION" . #x00228d) ("MULTISET UNION" . #x00228e) ("SQUARE IMAGE OF" . #x00228f) ("SQUARE ORIGINAL OF" . #x002290) ("SQUARE IMAGE OF OR EQUAL TO" . #x002291) ("SQUARE ORIGINAL OF OR EQUAL TO" . #x002292) ("SQUARE CAP" . #x002293) ("SQUARE CUP" . #x002294) ("CIRCLED PLUS" . #x002295) ("CIRCLED MINUS" . #x002296) ("CIRCLED TIMES" . #x002297) ("CIRCLED DIVISION SLASH" . #x002298) ("CIRCLED DOT OPERATOR" . #x002299) ("CIRCLED RING OPERATOR" . #x00229a) ("CIRCLED ASTERISK OPERATOR" . #x00229b) ("CIRCLED EQUALS" . #x00229c) ("CIRCLED DASH" . #x00229d) ("SQUARED PLUS" . #x00229e) ("SQUARED MINUS" . #x00229f) ("SQUARED TIMES" . #x0022a0) ("SQUARED DOT OPERATOR" . #x0022a1) ("RIGHT TACK" . #x0022a2) ("LEFT TACK" . #x0022a3) ("DOWN TACK" . #x0022a4) ("UP TACK" . #x0022a5) ("ASSERTION" . #x0022a6) ("MODELS" . #x0022a7) ("TRUE" . #x0022a8) ("FORCES" . #x0022a9) ("TRIPLE VERTICAL BAR RIGHT TURNSTILE" . #x0022aa) ("DOUBLE VERTICAL BAR DOUBLE RIGHT TURNSTILE" . #x0022ab) ("DOES NOT PROVE" . #x0022ac) ("NOT TRUE" . #x0022ad) ("DOES NOT FORCE" . #x0022ae) ("NEGATED DOUBLE VERTICAL BAR DOUBLE RIGHT TURNSTILE" . #x0022af) ("PRECEDES UNDER RELATION" . #x0022b0) ("SUCCEEDS UNDER RELATION" . #x0022b1) ("NORMAL SUBGROUP OF" . #x0022b2) ("CONTAINS AS NORMAL SUBGROUP" . #x0022b3) ("NORMAL SUBGROUP OF OR EQUAL TO" . #x0022b4) ("CONTAINS AS NORMAL SUBGROUP OR EQUAL TO" . #x0022b5) ("ORIGINAL OF" . #x0022b6) ("IMAGE OF" . #x0022b7) ("MULTIMAP" . #x0022b8) ("HERMITIAN CONJUGATE MATRIX" . #x0022b9) ("INTERCALATE" . #x0022ba) ("XOR" . #x0022bb) ("NAND" . #x0022bc) ("NOR" . #x0022bd) ("RIGHT ANGLE WITH ARC" . #x0022be) ("RIGHT TRIANGLE" . #x0022bf) ("N-ARY LOGICAL AND" . #x0022c0) ("N-ARY LOGICAL OR" . #x0022c1) ("N-ARY INTERSECTION" . #x0022c2) ("N-ARY UNION" . #x0022c3) ("DIAMOND OPERATOR" . #x0022c4) ("DOT OPERATOR" . #x0022c5) ("STAR OPERATOR" . #x0022c6) ("DIVISION TIMES" . #x0022c7) ("BOWTIE" . #x0022c8) ("LEFT NORMAL FACTOR SEMIDIRECT PRODUCT" . #x0022c9) ("RIGHT NORMAL FACTOR SEMIDIRECT PRODUCT" . #x0022ca) ("LEFT SEMIDIRECT PRODUCT" . #x0022cb) ("RIGHT SEMIDIRECT PRODUCT" . #x0022cc) ("REVERSED TILDE EQUALS" . #x0022cd) ("CURLY LOGICAL OR" . #x0022ce) ("CURLY LOGICAL AND" . #x0022cf) ("DOUBLE SUBSET" . #x0022d0) ("DOUBLE SUPERSET" . #x0022d1) ("DOUBLE INTERSECTION" . #x0022d2) ("DOUBLE UNION" . #x0022d3) ("PITCHFORK" . #x0022d4) ("EQUAL AND PARALLEL TO" . #x0022d5) ("LESS-THAN WITH DOT" . #x0022d6) ("GREATER-THAN WITH DOT" . #x0022d7) ("VERY MUCH LESS-THAN" . #x0022d8) ("VERY MUCH GREATER-THAN" . #x0022d9) ("LESS-THAN EQUAL TO OR GREATER-THAN" . #x0022da) ("GREATER-THAN EQUAL TO OR LESS-THAN" . #x0022db) ("EQUAL TO OR LESS-THAN" . #x0022dc) ("EQUAL TO OR GREATER-THAN" . #x0022dd) ("EQUAL TO OR PRECEDES" . #x0022de) ("EQUAL TO OR SUCCEEDS" . #x0022df) ("DOES NOT PRECEDE OR EQUAL" . #x0022e0) ("DOES NOT SUCCEED OR EQUAL" . #x0022e1) ("NOT SQUARE IMAGE OF OR EQUAL TO" . #x0022e2) ("NOT SQUARE ORIGINAL OF OR EQUAL TO" . #x0022e3) ("SQUARE IMAGE OF OR NOT EQUAL TO" . #x0022e4) ("SQUARE ORIGINAL OF OR NOT EQUAL TO" . #x0022e5) ("LESS-THAN BUT NOT EQUIVALENT TO" . #x0022e6) ("GREATER-THAN BUT NOT EQUIVALENT TO" . #x0022e7) ("PRECEDES BUT NOT EQUIVALENT TO" . #x0022e8) ("SUCCEEDS BUT NOT EQUIVALENT TO" . #x0022e9) ("NOT NORMAL SUBGROUP OF" . #x0022ea) ("DOES NOT CONTAIN AS NORMAL SUBGROUP" . #x0022eb) ("NOT NORMAL SUBGROUP OF OR EQUAL TO" . #x0022ec) ("DOES NOT CONTAIN AS NORMAL SUBGROUP OR EQUAL" . #x0022ed) ("VERTICAL ELLIPSIS" . #x0022ee) ("MIDLINE HORIZONTAL ELLIPSIS" . #x0022ef) ("UP RIGHT DIAGONAL ELLIPSIS" . #x0022f0) ("DOWN RIGHT DIAGONAL ELLIPSIS" . #x0022f1) ("ELEMENT OF WITH LONG HORIZONTAL STROKE" . #x0022f2) ("ELEMENT OF WITH VERTICAL BAR AT END OF HORIZONTAL STROKE" . #x0022f3) ("SMALL ELEMENT OF WITH VERTICAL BAR AT END OF HORIZONTAL STROKE" . #x0022f4) ("ELEMENT OF WITH DOT ABOVE" . #x0022f5) ("ELEMENT OF WITH OVERBAR" . #x0022f6) ("SMALL ELEMENT OF WITH OVERBAR" . #x0022f7) ("ELEMENT OF WITH UNDERBAR" . #x0022f8) ("ELEMENT OF WITH TWO HORIZONTAL STROKES" . #x0022f9) ("CONTAINS WITH LONG HORIZONTAL STROKE" . #x0022fa) ("CONTAINS WITH VERTICAL BAR AT END OF HORIZONTAL STROKE" . #x0022fb) ("SMALL CONTAINS WITH VERTICAL BAR AT END OF HORIZONTAL STROKE" . #x0022fc) ("CONTAINS WITH OVERBAR" . #x0022fd) ("SMALL CONTAINS WITH OVERBAR" . #x0022fe) ("Z NOTATION BAG MEMBERSHIP" . #x0022ff) ("DIAMETER SIGN" . #x002300) ("ELECTRIC ARROW" . #x002301) ("HOUSE" . #x002302) ("UP ARROWHEAD" . #x002303) ("DOWN ARROWHEAD" . #x002304) ("PROJECTIVE" . #x002305) ("PERSPECTIVE" . #x002306) ("WAVY LINE" . #x002307) ("LEFT CEILING" . #x002308) ("RIGHT CEILING" . #x002309) ("LEFT FLOOR" . #x00230a) ("RIGHT FLOOR" . #x00230b) ("BOTTOM RIGHT CROP" . #x00230c) ("BOTTOM LEFT CROP" . #x00230d) ("TOP RIGHT CROP" . #x00230e) ("TOP LEFT CROP" . #x00230f) ("REVERSED NOT SIGN" . #x002310) ("SQUARE LOZENGE" . #x002311) ("ARC" . #x002312) ("SEGMENT" . #x002313) ("SECTOR" . #x002314) ("TELEPHONE RECORDER" . #x002315) ("POSITION INDICATOR" . #x002316) ("VIEWDATA SQUARE" . #x002317) ("PLACE OF INTEREST SIGN" . #x002318) ("TURNED NOT SIGN" . #x002319) ("WATCH" . #x00231a) ("HOURGLASS" . #x00231b) ("TOP LEFT CORNER" . #x00231c) ("TOP RIGHT CORNER" . #x00231d) ("BOTTOM LEFT CORNER" . #x00231e) ("BOTTOM RIGHT CORNER" . #x00231f) ("TOP HALF INTEGRAL" . #x002320) ("BOTTOM HALF INTEGRAL" . #x002321) ("FROWN" . #x002322) ("SMILE" . #x002323) ("UP ARROWHEAD BETWEEN TWO HORIZONTAL BARS" . #x002324) ("OPTION KEY" . #x002325) ("ERASE TO THE RIGHT" . #x002326) ("X IN A RECTANGLE BOX" . #x002327) ("KEYBOARD" . #x002328) ("LEFT-POINTING ANGLE BRACKET" . #x002329) ("RIGHT-POINTING ANGLE BRACKET" . #x00232a) ("ERASE TO THE LEFT" . #x00232b) ("BENZENE RING" . #x00232c) ("CYLINDRICITY" . #x00232d) ("ALL AROUND-PROFILE" . #x00232e) ("SYMMETRY" . #x00232f) ("TOTAL RUNOUT" . #x002330) ("DIMENSION ORIGIN" . #x002331) ("CONICAL TAPER" . #x002332) ("SLOPE" . #x002333) ("COUNTERBORE" . #x002334) ("COUNTERSINK" . #x002335) ("APL FUNCTIONAL SYMBOL I-BEAM" . #x002336) ("APL FUNCTIONAL SYMBOL SQUISH QUAD" . #x002337) ("APL FUNCTIONAL SYMBOL QUAD EQUAL" . #x002338) ("APL FUNCTIONAL SYMBOL QUAD DIVIDE" . #x002339) ("APL FUNCTIONAL SYMBOL QUAD DIAMOND" . #x00233a) ("APL FUNCTIONAL SYMBOL QUAD JOT" . #x00233b) ("APL FUNCTIONAL SYMBOL QUAD CIRCLE" . #x00233c) ("APL FUNCTIONAL SYMBOL CIRCLE STILE" . #x00233d) ("APL FUNCTIONAL SYMBOL CIRCLE JOT" . #x00233e) ("APL FUNCTIONAL SYMBOL SLASH BAR" . #x00233f) ("APL FUNCTIONAL SYMBOL BACKSLASH BAR" . #x002340) ("APL FUNCTIONAL SYMBOL QUAD SLASH" . #x002341) ("APL FUNCTIONAL SYMBOL QUAD BACKSLASH" . #x002342) ("APL FUNCTIONAL SYMBOL QUAD LESS-THAN" . #x002343) ("APL FUNCTIONAL SYMBOL QUAD GREATER-THAN" . #x002344) ("APL FUNCTIONAL SYMBOL LEFTWARDS VANE" . #x002345) ("APL FUNCTIONAL SYMBOL RIGHTWARDS VANE" . #x002346) ("APL FUNCTIONAL SYMBOL QUAD LEFTWARDS ARROW" . #x002347) ("APL FUNCTIONAL SYMBOL QUAD RIGHTWARDS ARROW" . #x002348) ("APL FUNCTIONAL SYMBOL CIRCLE BACKSLASH" . #x002349) ("APL FUNCTIONAL SYMBOL DOWN TACK UNDERBAR" . #x00234a) ("APL FUNCTIONAL SYMBOL DELTA STILE" . #x00234b) ("APL FUNCTIONAL SYMBOL QUAD DOWN CARET" . #x00234c) ("APL FUNCTIONAL SYMBOL QUAD DELTA" . #x00234d) ("APL FUNCTIONAL SYMBOL DOWN TACK JOT" . #x00234e) ("APL FUNCTIONAL SYMBOL UPWARDS VANE" . #x00234f) ("APL FUNCTIONAL SYMBOL QUAD UPWARDS ARROW" . #x002350) ("APL FUNCTIONAL SYMBOL UP TACK OVERBAR" . #x002351) ("APL FUNCTIONAL SYMBOL DEL STILE" . #x002352) ("APL FUNCTIONAL SYMBOL QUAD UP CARET" . #x002353) ("APL FUNCTIONAL SYMBOL QUAD DEL" . #x002354) ("APL FUNCTIONAL SYMBOL UP TACK JOT" . #x002355) ("APL FUNCTIONAL SYMBOL DOWNWARDS VANE" . #x002356) ("APL FUNCTIONAL SYMBOL QUAD DOWNWARDS ARROW" . #x002357) ("APL FUNCTIONAL SYMBOL QUOTE UNDERBAR" . #x002358) ("APL FUNCTIONAL SYMBOL DELTA UNDERBAR" . #x002359) ("APL FUNCTIONAL SYMBOL DIAMOND UNDERBAR" . #x00235a) ("APL FUNCTIONAL SYMBOL JOT UNDERBAR" . #x00235b) ("APL FUNCTIONAL SYMBOL CIRCLE UNDERBAR" . #x00235c) ("APL FUNCTIONAL SYMBOL UP SHOE JOT" . #x00235d) ("APL FUNCTIONAL SYMBOL QUOTE QUAD" . #x00235e) ("APL FUNCTIONAL SYMBOL CIRCLE STAR" . #x00235f) ("APL FUNCTIONAL SYMBOL QUAD COLON" . #x002360) ("APL FUNCTIONAL SYMBOL UP TACK DIAERESIS" . #x002361) ("APL FUNCTIONAL SYMBOL DEL DIAERESIS" . #x002362) ("APL FUNCTIONAL SYMBOL STAR DIAERESIS" . #x002363) ("APL FUNCTIONAL SYMBOL JOT DIAERESIS" . #x002364) ("APL FUNCTIONAL SYMBOL CIRCLE DIAERESIS" . #x002365) ("APL FUNCTIONAL SYMBOL DOWN SHOE STILE" . #x002366) ("APL FUNCTIONAL SYMBOL LEFT SHOE STILE" . #x002367) ("APL FUNCTIONAL SYMBOL TILDE DIAERESIS" . #x002368) ("APL FUNCTIONAL SYMBOL GREATER-THAN DIAERESIS" . #x002369) ("APL FUNCTIONAL SYMBOL COMMA BAR" . #x00236a) ("APL FUNCTIONAL SYMBOL DEL TILDE" . #x00236b) ("APL FUNCTIONAL SYMBOL ZILDE" . #x00236c) ("APL FUNCTIONAL SYMBOL STILE TILDE" . #x00236d) ("APL FUNCTIONAL SYMBOL SEMICOLON UNDERBAR" . #x00236e) ("APL FUNCTIONAL SYMBOL QUAD NOT EQUAL" . #x00236f) ("APL FUNCTIONAL SYMBOL QUAD QUESTION" . #x002370) ("APL FUNCTIONAL SYMBOL DOWN CARET TILDE" . #x002371) ("APL FUNCTIONAL SYMBOL UP CARET TILDE" . #x002372) ("APL FUNCTIONAL SYMBOL IOTA" . #x002373) ("APL FUNCTIONAL SYMBOL RHO" . #x002374) ("APL FUNCTIONAL SYMBOL OMEGA" . #x002375) ("APL FUNCTIONAL SYMBOL ALPHA UNDERBAR" . #x002376) ("APL FUNCTIONAL SYMBOL EPSILON UNDERBAR" . #x002377) ("APL FUNCTIONAL SYMBOL IOTA UNDERBAR" . #x002378) ("APL FUNCTIONAL SYMBOL OMEGA UNDERBAR" . #x002379) ("APL FUNCTIONAL SYMBOL ALPHA" . #x00237a) ("NOT CHECK MARK" . #x00237b) ("RIGHT ANGLE WITH DOWNWARDS ZIGZAG ARROW" . #x00237c) ("SHOULDERED OPEN BOX" . #x00237d) ("BELL SYMBOL" . #x00237e) ("VERTICAL LINE WITH MIDDLE DOT" . #x00237f) ("INSERTION SYMBOL" . #x002380) ("CONTINUOUS UNDERLINE SYMBOL" . #x002381) ("DISCONTINUOUS UNDERLINE SYMBOL" . #x002382) ("EMPHASIS SYMBOL" . #x002383) ("COMPOSITION SYMBOL" . #x002384) ("WHITE SQUARE WITH CENTRE VERTICAL LINE" . #x002385) ("ENTER SYMBOL" . #x002386) ("ALTERNATIVE KEY SYMBOL" . #x002387) ("HELM SYMBOL" . #x002388) ("CIRCLED HORIZONTAL BAR WITH NOTCH" . #x002389) ("CIRCLED TRIANGLE DOWN" . #x00238a) ("BROKEN CIRCLE WITH NORTHWEST ARROW" . #x00238b) ("UNDO SYMBOL" . #x00238c) ("MONOSTABLE SYMBOL" . #x00238d) ("HYSTERESIS SYMBOL" . #x00238e) ("OPEN-CIRCUIT-OUTPUT H-TYPE SYMBOL" . #x00238f) ("OPEN-CIRCUIT-OUTPUT L-TYPE SYMBOL" . #x002390) ("PASSIVE-PULL-DOWN-OUTPUT SYMBOL" . #x002391) ("PASSIVE-PULL-UP-OUTPUT SYMBOL" . #x002392) ("DIRECT CURRENT SYMBOL FORM TWO" . #x002393) ("SOFTWARE-FUNCTION SYMBOL" . #x002394) ("APL FUNCTIONAL SYMBOL QUAD" . #x002395) ("DECIMAL SEPARATOR KEY SYMBOL" . #x002396) ("PREVIOUS PAGE" . #x002397) ("NEXT PAGE" . #x002398) ("PRINT SCREEN SYMBOL" . #x002399) ("CLEAR SCREEN SYMBOL" . #x00239a) ("LEFT PARENTHESIS UPPER HOOK" . #x00239b) ("LEFT PARENTHESIS EXTENSION" . #x00239c) ("LEFT PARENTHESIS LOWER HOOK" . #x00239d) ("RIGHT PARENTHESIS UPPER HOOK" . #x00239e) ("RIGHT PARENTHESIS EXTENSION" . #x00239f) ("RIGHT PARENTHESIS LOWER HOOK" . #x0023a0) ("LEFT SQUARE BRACKET UPPER CORNER" . #x0023a1) ("LEFT SQUARE BRACKET EXTENSION" . #x0023a2) ("LEFT SQUARE BRACKET LOWER CORNER" . #x0023a3) ("RIGHT SQUARE BRACKET UPPER CORNER" . #x0023a4) ("RIGHT SQUARE BRACKET EXTENSION" . #x0023a5) ("RIGHT SQUARE BRACKET LOWER CORNER" . #x0023a6) ("LEFT CURLY BRACKET UPPER HOOK" . #x0023a7) ("LEFT CURLY BRACKET MIDDLE PIECE" . #x0023a8) ("LEFT CURLY BRACKET LOWER HOOK" . #x0023a9) ("CURLY BRACKET EXTENSION" . #x0023aa) ("RIGHT CURLY BRACKET UPPER HOOK" . #x0023ab) ("RIGHT CURLY BRACKET MIDDLE PIECE" . #x0023ac) ("RIGHT CURLY BRACKET LOWER HOOK" . #x0023ad) ("INTEGRAL EXTENSION" . #x0023ae) ("HORIZONTAL LINE EXTENSION" . #x0023af) ("UPPER LEFT OR LOWER RIGHT CURLY BRACKET SECTION" . #x0023b0) ("UPPER RIGHT OR LOWER LEFT CURLY BRACKET SECTION" . #x0023b1) ("SUMMATION TOP" . #x0023b2) ("SUMMATION BOTTOM" . #x0023b3) ("TOP SQUARE BRACKET" . #x0023b4) ("BOTTOM SQUARE BRACKET" . #x0023b5) ("BOTTOM SQUARE BRACKET OVER TOP SQUARE BRACKET" . #x0023b6) ("RADICAL SYMBOL BOTTOM" . #x0023b7) ("LEFT VERTICAL BOX LINE" . #x0023b8) ("RIGHT VERTICAL BOX LINE" . #x0023b9) ("HORIZONTAL SCAN LINE-1" . #x0023ba) ("HORIZONTAL SCAN LINE-3" . #x0023bb) ("HORIZONTAL SCAN LINE-7" . #x0023bc) ("HORIZONTAL SCAN LINE-9" . #x0023bd) ("DENTISTRY SYMBOL LIGHT VERTICAL AND TOP RIGHT" . #x0023be) ("DENTISTRY SYMBOL LIGHT VERTICAL AND BOTTOM RIGHT" . #x0023bf) ("DENTISTRY SYMBOL LIGHT VERTICAL WITH CIRCLE" . #x0023c0) ("DENTISTRY SYMBOL LIGHT DOWN AND HORIZONTAL WITH CIRCLE" . #x0023c1) ("DENTISTRY SYMBOL LIGHT UP AND HORIZONTAL WITH CIRCLE" . #x0023c2) ("DENTISTRY SYMBOL LIGHT VERTICAL WITH TRIANGLE" . #x0023c3) ("DENTISTRY SYMBOL LIGHT DOWN AND HORIZONTAL WITH TRIANGLE" . #x0023c4) ("DENTISTRY SYMBOL LIGHT UP AND HORIZONTAL WITH TRIANGLE" . #x0023c5) ("DENTISTRY SYMBOL LIGHT VERTICAL AND WAVE" . #x0023c6) ("DENTISTRY SYMBOL LIGHT DOWN AND HORIZONTAL WITH WAVE" . #x0023c7) ("DENTISTRY SYMBOL LIGHT UP AND HORIZONTAL WITH WAVE" . #x0023c8) ("DENTISTRY SYMBOL LIGHT DOWN AND HORIZONTAL" . #x0023c9) ("DENTISTRY SYMBOL LIGHT UP AND HORIZONTAL" . #x0023ca) ("DENTISTRY SYMBOL LIGHT VERTICAL AND TOP LEFT" . #x0023cb) ("DENTISTRY SYMBOL LIGHT VERTICAL AND BOTTOM LEFT" . #x0023cc) ("SQUARE FOOT" . #x0023cd) ("RETURN SYMBOL" . #x0023ce) ("SYMBOL FOR NULL" . #x002400) ("SYMBOL FOR START OF HEADING" . #x002401) ("SYMBOL FOR START OF TEXT" . #x002402) ("SYMBOL FOR END OF TEXT" . #x002403) ("SYMBOL FOR END OF TRANSMISSION" . #x002404) ("SYMBOL FOR ENQUIRY" . #x002405) ("SYMBOL FOR ACKNOWLEDGE" . #x002406) ("SYMBOL FOR BELL" . #x002407) ("SYMBOL FOR BACKSPACE" . #x002408) ("SYMBOL FOR HORIZONTAL TABULATION" . #x002409) ("SYMBOL FOR LINE FEED" . #x00240a) ("SYMBOL FOR VERTICAL TABULATION" . #x00240b) ("SYMBOL FOR FORM FEED" . #x00240c) ("SYMBOL FOR CARRIAGE RETURN" . #x00240d) ("SYMBOL FOR SHIFT OUT" . #x00240e) ("SYMBOL FOR SHIFT IN" . #x00240f) ("SYMBOL FOR DATA LINK ESCAPE" . #x002410) ("SYMBOL FOR DEVICE CONTROL ONE" . #x002411) ("SYMBOL FOR DEVICE CONTROL TWO" . #x002412) ("SYMBOL FOR DEVICE CONTROL THREE" . #x002413) ("SYMBOL FOR DEVICE CONTROL FOUR" . #x002414) ("SYMBOL FOR NEGATIVE ACKNOWLEDGE" . #x002415) ("SYMBOL FOR SYNCHRONOUS IDLE" . #x002416) ("SYMBOL FOR END OF TRANSMISSION BLOCK" . #x002417) ("SYMBOL FOR CANCEL" . #x002418) ("SYMBOL FOR END OF MEDIUM" . #x002419) ("SYMBOL FOR SUBSTITUTE" . #x00241a) ("SYMBOL FOR ESCAPE" . #x00241b) ("SYMBOL FOR FILE SEPARATOR" . #x00241c) ("SYMBOL FOR GROUP SEPARATOR" . #x00241d) ("SYMBOL FOR RECORD SEPARATOR" . #x00241e) ("SYMBOL FOR UNIT SEPARATOR" . #x00241f) ("SYMBOL FOR SPACE" . #x002420) ("SYMBOL FOR DELETE" . #x002421) ("BLANK SYMBOL" . #x002422) ("OPEN BOX" . #x002423) ("SYMBOL FOR NEWLINE" . #x002424) ("SYMBOL FOR DELETE FORM TWO" . #x002425) ("SYMBOL FOR SUBSTITUTE FORM TWO" . #x002426) ("OCR HOOK" . #x002440) ("OCR CHAIR" . #x002441) ("OCR FORK" . #x002442) ("OCR INVERTED FORK" . #x002443) ("OCR BELT BUCKLE" . #x002444) ("OCR BOW TIE" . #x002445) ("OCR BRANCH BANK IDENTIFICATION" . #x002446) ("OCR AMOUNT OF CHECK" . #x002447) ("OCR DASH" . #x002448) ("OCR CUSTOMER ACCOUNT NUMBER" . #x002449) ("OCR DOUBLE BACKSLASH" . #x00244a) ("CIRCLED DIGIT ONE" . #x002460) ("CIRCLED DIGIT TWO" . #x002461) ("CIRCLED DIGIT THREE" . #x002462) ("CIRCLED DIGIT FOUR" . #x002463) ("CIRCLED DIGIT FIVE" . #x002464) ("CIRCLED DIGIT SIX" . #x002465) ("CIRCLED DIGIT SEVEN" . #x002466) ("CIRCLED DIGIT EIGHT" . #x002467) ("CIRCLED DIGIT NINE" . #x002468) ("CIRCLED NUMBER TEN" . #x002469) ("CIRCLED NUMBER ELEVEN" . #x00246a) ("CIRCLED NUMBER TWELVE" . #x00246b) ("CIRCLED NUMBER THIRTEEN" . #x00246c) ("CIRCLED NUMBER FOURTEEN" . #x00246d) ("CIRCLED NUMBER FIFTEEN" . #x00246e) ("CIRCLED NUMBER SIXTEEN" . #x00246f) ("CIRCLED NUMBER SEVENTEEN" . #x002470) ("CIRCLED NUMBER EIGHTEEN" . #x002471) ("CIRCLED NUMBER NINETEEN" . #x002472) ("CIRCLED NUMBER TWENTY" . #x002473) ("PARENTHESIZED DIGIT ONE" . #x002474) ("PARENTHESIZED DIGIT TWO" . #x002475) ("PARENTHESIZED DIGIT THREE" . #x002476) ("PARENTHESIZED DIGIT FOUR" . #x002477) ("PARENTHESIZED DIGIT FIVE" . #x002478) ("PARENTHESIZED DIGIT SIX" . #x002479) ("PARENTHESIZED DIGIT SEVEN" . #x00247a) ("PARENTHESIZED DIGIT EIGHT" . #x00247b) ("PARENTHESIZED DIGIT NINE" . #x00247c) ("PARENTHESIZED NUMBER TEN" . #x00247d) ("PARENTHESIZED NUMBER ELEVEN" . #x00247e) ("PARENTHESIZED NUMBER TWELVE" . #x00247f) ("PARENTHESIZED NUMBER THIRTEEN" . #x002480) ("PARENTHESIZED NUMBER FOURTEEN" . #x002481) ("PARENTHESIZED NUMBER FIFTEEN" . #x002482) ("PARENTHESIZED NUMBER SIXTEEN" . #x002483) ("PARENTHESIZED NUMBER SEVENTEEN" . #x002484) ("PARENTHESIZED NUMBER EIGHTEEN" . #x002485) ("PARENTHESIZED NUMBER NINETEEN" . #x002486) ("PARENTHESIZED NUMBER TWENTY" . #x002487) ("DIGIT ONE FULL STOP" . #x002488) ("DIGIT TWO FULL STOP" . #x002489) ("DIGIT THREE FULL STOP" . #x00248a) ("DIGIT FOUR FULL STOP" . #x00248b) ("DIGIT FIVE FULL STOP" . #x00248c) ("DIGIT SIX FULL STOP" . #x00248d) ("DIGIT SEVEN FULL STOP" . #x00248e) ("DIGIT EIGHT FULL STOP" . #x00248f) ("DIGIT NINE FULL STOP" . #x002490) ("NUMBER TEN FULL STOP" . #x002491) ("NUMBER ELEVEN FULL STOP" . #x002492) ("NUMBER TWELVE FULL STOP" . #x002493) ("NUMBER THIRTEEN FULL STOP" . #x002494) ("NUMBER FOURTEEN FULL STOP" . #x002495) ("NUMBER FIFTEEN FULL STOP" . #x002496) ("NUMBER SIXTEEN FULL STOP" . #x002497) ("NUMBER SEVENTEEN FULL STOP" . #x002498) ("NUMBER EIGHTEEN FULL STOP" . #x002499) ("NUMBER NINETEEN FULL STOP" . #x00249a) ("NUMBER TWENTY FULL STOP" . #x00249b) ("PARENTHESIZED LATIN SMALL LETTER A" . #x00249c) ("PARENTHESIZED LATIN SMALL LETTER B" . #x00249d) ("PARENTHESIZED LATIN SMALL LETTER C" . #x00249e) ("PARENTHESIZED LATIN SMALL LETTER D" . #x00249f) ("PARENTHESIZED LATIN SMALL LETTER E" . #x0024a0) ("PARENTHESIZED LATIN SMALL LETTER F" . #x0024a1) ("PARENTHESIZED LATIN SMALL LETTER G" . #x0024a2) ("PARENTHESIZED LATIN SMALL LETTER H" . #x0024a3) ("PARENTHESIZED LATIN SMALL LETTER I" . #x0024a4) ("PARENTHESIZED LATIN SMALL LETTER J" . #x0024a5) ("PARENTHESIZED LATIN SMALL LETTER K" . #x0024a6) ("PARENTHESIZED LATIN SMALL LETTER L" . #x0024a7) ("PARENTHESIZED LATIN SMALL LETTER M" . #x0024a8) ("PARENTHESIZED LATIN SMALL LETTER N" . #x0024a9) ("PARENTHESIZED LATIN SMALL LETTER O" . #x0024aa) ("PARENTHESIZED LATIN SMALL LETTER P" . #x0024ab) ("PARENTHESIZED LATIN SMALL LETTER Q" . #x0024ac) ("PARENTHESIZED LATIN SMALL LETTER R" . #x0024ad) ("PARENTHESIZED LATIN SMALL LETTER S" . #x0024ae) ("PARENTHESIZED LATIN SMALL LETTER T" . #x0024af) ("PARENTHESIZED LATIN SMALL LETTER U" . #x0024b0) ("PARENTHESIZED LATIN SMALL LETTER V" . #x0024b1) ("PARENTHESIZED LATIN SMALL LETTER W" . #x0024b2) ("PARENTHESIZED LATIN SMALL LETTER X" . #x0024b3) ("PARENTHESIZED LATIN SMALL LETTER Y" . #x0024b4) ("PARENTHESIZED LATIN SMALL LETTER Z" . #x0024b5) ("CIRCLED LATIN CAPITAL LETTER A" . #x0024b6) ("CIRCLED LATIN CAPITAL LETTER B" . #x0024b7) ("CIRCLED LATIN CAPITAL LETTER C" . #x0024b8) ("CIRCLED LATIN CAPITAL LETTER D" . #x0024b9) ("CIRCLED LATIN CAPITAL LETTER E" . #x0024ba) ("CIRCLED LATIN CAPITAL LETTER F" . #x0024bb) ("CIRCLED LATIN CAPITAL LETTER G" . #x0024bc) ("CIRCLED LATIN CAPITAL LETTER H" . #x0024bd) ("CIRCLED LATIN CAPITAL LETTER I" . #x0024be) ("CIRCLED LATIN CAPITAL LETTER J" . #x0024bf) ("CIRCLED LATIN CAPITAL LETTER K" . #x0024c0) ("CIRCLED LATIN CAPITAL LETTER L" . #x0024c1) ("CIRCLED LATIN CAPITAL LETTER M" . #x0024c2) ("CIRCLED LATIN CAPITAL LETTER N" . #x0024c3) ("CIRCLED LATIN CAPITAL LETTER O" . #x0024c4) ("CIRCLED LATIN CAPITAL LETTER P" . #x0024c5) ("CIRCLED LATIN CAPITAL LETTER Q" . #x0024c6) ("CIRCLED LATIN CAPITAL LETTER R" . #x0024c7) ("CIRCLED LATIN CAPITAL LETTER S" . #x0024c8) ("CIRCLED LATIN CAPITAL LETTER T" . #x0024c9) ("CIRCLED LATIN CAPITAL LETTER U" . #x0024ca) ("CIRCLED LATIN CAPITAL LETTER V" . #x0024cb) ("CIRCLED LATIN CAPITAL LETTER W" . #x0024cc) ("CIRCLED LATIN CAPITAL LETTER X" . #x0024cd) ("CIRCLED LATIN CAPITAL LETTER Y" . #x0024ce) ("CIRCLED LATIN CAPITAL LETTER Z" . #x0024cf) ("CIRCLED LATIN SMALL LETTER A" . #x0024d0) ("CIRCLED LATIN SMALL LETTER B" . #x0024d1) ("CIRCLED LATIN SMALL LETTER C" . #x0024d2) ("CIRCLED LATIN SMALL LETTER D" . #x0024d3) ("CIRCLED LATIN SMALL LETTER E" . #x0024d4) ("CIRCLED LATIN SMALL LETTER F" . #x0024d5) ("CIRCLED LATIN SMALL LETTER G" . #x0024d6) ("CIRCLED LATIN SMALL LETTER H" . #x0024d7) ("CIRCLED LATIN SMALL LETTER I" . #x0024d8) ("CIRCLED LATIN SMALL LETTER J" . #x0024d9) ("CIRCLED LATIN SMALL LETTER K" . #x0024da) ("CIRCLED LATIN SMALL LETTER L" . #x0024db) ("CIRCLED LATIN SMALL LETTER M" . #x0024dc) ("CIRCLED LATIN SMALL LETTER N" . #x0024dd) ("CIRCLED LATIN SMALL LETTER O" . #x0024de) ("CIRCLED LATIN SMALL LETTER P" . #x0024df) ("CIRCLED LATIN SMALL LETTER Q" . #x0024e0) ("CIRCLED LATIN SMALL LETTER R" . #x0024e1) ("CIRCLED LATIN SMALL LETTER S" . #x0024e2) ("CIRCLED LATIN SMALL LETTER T" . #x0024e3) ("CIRCLED LATIN SMALL LETTER U" . #x0024e4) ("CIRCLED LATIN SMALL LETTER V" . #x0024e5) ("CIRCLED LATIN SMALL LETTER W" . #x0024e6) ("CIRCLED LATIN SMALL LETTER X" . #x0024e7) ("CIRCLED LATIN SMALL LETTER Y" . #x0024e8) ("CIRCLED LATIN SMALL LETTER Z" . #x0024e9) ("CIRCLED DIGIT ZERO" . #x0024ea) ("NEGATIVE CIRCLED NUMBER ELEVEN" . #x0024eb) ("NEGATIVE CIRCLED NUMBER TWELVE" . #x0024ec) ("NEGATIVE CIRCLED NUMBER THIRTEEN" . #x0024ed) ("NEGATIVE CIRCLED NUMBER FOURTEEN" . #x0024ee) ("NEGATIVE CIRCLED NUMBER FIFTEEN" . #x0024ef) ("NEGATIVE CIRCLED NUMBER SIXTEEN" . #x0024f0) ("NEGATIVE CIRCLED NUMBER SEVENTEEN" . #x0024f1) ("NEGATIVE CIRCLED NUMBER EIGHTEEN" . #x0024f2) ("NEGATIVE CIRCLED NUMBER NINETEEN" . #x0024f3) ("NEGATIVE CIRCLED NUMBER TWENTY" . #x0024f4) ("DOUBLE CIRCLED DIGIT ONE" . #x0024f5) ("DOUBLE CIRCLED DIGIT TWO" . #x0024f6) ("DOUBLE CIRCLED DIGIT THREE" . #x0024f7) ("DOUBLE CIRCLED DIGIT FOUR" . #x0024f8) ("DOUBLE CIRCLED DIGIT FIVE" . #x0024f9) ("DOUBLE CIRCLED DIGIT SIX" . #x0024fa) ("DOUBLE CIRCLED DIGIT SEVEN" . #x0024fb) ("DOUBLE CIRCLED DIGIT EIGHT" . #x0024fc) ("DOUBLE CIRCLED DIGIT NINE" . #x0024fd) ("DOUBLE CIRCLED NUMBER TEN" . #x0024fe) ("BOX DRAWINGS LIGHT HORIZONTAL" . #x002500) ("BOX DRAWINGS HEAVY HORIZONTAL" . #x002501) ("BOX DRAWINGS LIGHT VERTICAL" . #x002502) ("BOX DRAWINGS HEAVY VERTICAL" . #x002503) ("BOX DRAWINGS LIGHT TRIPLE DASH HORIZONTAL" . #x002504) ("BOX DRAWINGS HEAVY TRIPLE DASH HORIZONTAL" . #x002505) ("BOX DRAWINGS LIGHT TRIPLE DASH VERTICAL" . #x002506) ("BOX DRAWINGS HEAVY TRIPLE DASH VERTICAL" . #x002507) ("BOX DRAWINGS LIGHT QUADRUPLE DASH HORIZONTAL" . #x002508) ("BOX DRAWINGS HEAVY QUADRUPLE DASH HORIZONTAL" . #x002509) ("BOX DRAWINGS LIGHT QUADRUPLE DASH VERTICAL" . #x00250a) ("BOX DRAWINGS HEAVY QUADRUPLE DASH VERTICAL" . #x00250b) ("BOX DRAWINGS LIGHT DOWN AND RIGHT" . #x00250c) ("BOX DRAWINGS DOWN LIGHT AND RIGHT HEAVY" . #x00250d) ("BOX DRAWINGS DOWN HEAVY AND RIGHT LIGHT" . #x00250e) ("BOX DRAWINGS HEAVY DOWN AND RIGHT" . #x00250f) ("BOX DRAWINGS LIGHT DOWN AND LEFT" . #x002510) ("BOX DRAWINGS DOWN LIGHT AND LEFT HEAVY" . #x002511) ("BOX DRAWINGS DOWN HEAVY AND LEFT LIGHT" . #x002512) ("BOX DRAWINGS HEAVY DOWN AND LEFT" . #x002513) ("BOX DRAWINGS LIGHT UP AND RIGHT" . #x002514) ("BOX DRAWINGS UP LIGHT AND RIGHT HEAVY" . #x002515) ("BOX DRAWINGS UP HEAVY AND RIGHT LIGHT" . #x002516) ("BOX DRAWINGS HEAVY UP AND RIGHT" . #x002517) ("BOX DRAWINGS LIGHT UP AND LEFT" . #x002518) ("BOX DRAWINGS UP LIGHT AND LEFT HEAVY" . #x002519) ("BOX DRAWINGS UP HEAVY AND LEFT LIGHT" . #x00251a) ("BOX DRAWINGS HEAVY UP AND LEFT" . #x00251b) ("BOX DRAWINGS LIGHT VERTICAL AND RIGHT" . #x00251c) ("BOX DRAWINGS VERTICAL LIGHT AND RIGHT HEAVY" . #x00251d) ("BOX DRAWINGS UP HEAVY AND RIGHT DOWN LIGHT" . #x00251e) ("BOX DRAWINGS DOWN HEAVY AND RIGHT UP LIGHT" . #x00251f) ("BOX DRAWINGS VERTICAL HEAVY AND RIGHT LIGHT" . #x002520) ("BOX DRAWINGS DOWN LIGHT AND RIGHT UP HEAVY" . #x002521) ("BOX DRAWINGS UP LIGHT AND RIGHT DOWN HEAVY" . #x002522) ("BOX DRAWINGS HEAVY VERTICAL AND RIGHT" . #x002523) ("BOX DRAWINGS LIGHT VERTICAL AND LEFT" . #x002524) ("BOX DRAWINGS VERTICAL LIGHT AND LEFT HEAVY" . #x002525) ("BOX DRAWINGS UP HEAVY AND LEFT DOWN LIGHT" . #x002526) ("BOX DRAWINGS DOWN HEAVY AND LEFT UP LIGHT" . #x002527) ("BOX DRAWINGS VERTICAL HEAVY AND LEFT LIGHT" . #x002528) ("BOX DRAWINGS DOWN LIGHT AND LEFT UP HEAVY" . #x002529) ("BOX DRAWINGS UP LIGHT AND LEFT DOWN HEAVY" . #x00252a) ("BOX DRAWINGS HEAVY VERTICAL AND LEFT" . #x00252b) ("BOX DRAWINGS LIGHT DOWN AND HORIZONTAL" . #x00252c) ("BOX DRAWINGS LEFT HEAVY AND RIGHT DOWN LIGHT" . #x00252d) ("BOX DRAWINGS RIGHT HEAVY AND LEFT DOWN LIGHT" . #x00252e) ("BOX DRAWINGS DOWN LIGHT AND HORIZONTAL HEAVY" . #x00252f) ("BOX DRAWINGS DOWN HEAVY AND HORIZONTAL LIGHT" . #x002530) ("BOX DRAWINGS RIGHT LIGHT AND LEFT DOWN HEAVY" . #x002531) ("BOX DRAWINGS LEFT LIGHT AND RIGHT DOWN HEAVY" . #x002532) ("BOX DRAWINGS HEAVY DOWN AND HORIZONTAL" . #x002533) ("BOX DRAWINGS LIGHT UP AND HORIZONTAL" . #x002534) ("BOX DRAWINGS LEFT HEAVY AND RIGHT UP LIGHT" . #x002535) ("BOX DRAWINGS RIGHT HEAVY AND LEFT UP LIGHT" . #x002536) ("BOX DRAWINGS UP LIGHT AND HORIZONTAL HEAVY" . #x002537) ("BOX DRAWINGS UP HEAVY AND HORIZONTAL LIGHT" . #x002538) ("BOX DRAWINGS RIGHT LIGHT AND LEFT UP HEAVY" . #x002539) ("BOX DRAWINGS LEFT LIGHT AND RIGHT UP HEAVY" . #x00253a) ("BOX DRAWINGS HEAVY UP AND HORIZONTAL" . #x00253b) ("BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL" . #x00253c) ("BOX DRAWINGS LEFT HEAVY AND RIGHT VERTICAL LIGHT" . #x00253d) ("BOX DRAWINGS RIGHT HEAVY AND LEFT VERTICAL LIGHT" . #x00253e) ("BOX DRAWINGS VERTICAL LIGHT AND HORIZONTAL HEAVY" . #x00253f) ("BOX DRAWINGS UP HEAVY AND DOWN HORIZONTAL LIGHT" . #x002540) ("BOX DRAWINGS DOWN HEAVY AND UP HORIZONTAL LIGHT" . #x002541) ("BOX DRAWINGS VERTICAL HEAVY AND HORIZONTAL LIGHT" . #x002542) ("BOX DRAWINGS LEFT UP HEAVY AND RIGHT DOWN LIGHT" . #x002543) ("BOX DRAWINGS RIGHT UP HEAVY AND LEFT DOWN LIGHT" . #x002544) ("BOX DRAWINGS LEFT DOWN HEAVY AND RIGHT UP LIGHT" . #x002545) ("BOX DRAWINGS RIGHT DOWN HEAVY AND LEFT UP LIGHT" . #x002546) ("BOX DRAWINGS DOWN LIGHT AND UP HORIZONTAL HEAVY" . #x002547) ("BOX DRAWINGS UP LIGHT AND DOWN HORIZONTAL HEAVY" . #x002548) ("BOX DRAWINGS RIGHT LIGHT AND LEFT VERTICAL HEAVY" . #x002549) ("BOX DRAWINGS LEFT LIGHT AND RIGHT VERTICAL HEAVY" . #x00254a) ("BOX DRAWINGS HEAVY VERTICAL AND HORIZONTAL" . #x00254b) ("BOX DRAWINGS LIGHT DOUBLE DASH HORIZONTAL" . #x00254c) ("BOX DRAWINGS HEAVY DOUBLE DASH HORIZONTAL" . #x00254d) ("BOX DRAWINGS LIGHT DOUBLE DASH VERTICAL" . #x00254e) ("BOX DRAWINGS HEAVY DOUBLE DASH VERTICAL" . #x00254f) ("BOX DRAWINGS DOUBLE HORIZONTAL" . #x002550) ("BOX DRAWINGS DOUBLE VERTICAL" . #x002551) ("BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE" . #x002552) ("BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE" . #x002553) ("BOX DRAWINGS DOUBLE DOWN AND RIGHT" . #x002554) ("BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE" . #x002555) ("BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE" . #x002556) ("BOX DRAWINGS DOUBLE DOWN AND LEFT" . #x002557) ("BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE" . #x002558) ("BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE" . #x002559) ("BOX DRAWINGS DOUBLE UP AND RIGHT" . #x00255a) ("BOX DRAWINGS UP SINGLE AND LEFT DOUBLE" . #x00255b) ("BOX DRAWINGS UP DOUBLE AND LEFT SINGLE" . #x00255c) ("BOX DRAWINGS DOUBLE UP AND LEFT" . #x00255d) ("BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE" . #x00255e) ("BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE" . #x00255f) ("BOX DRAWINGS DOUBLE VERTICAL AND RIGHT" . #x002560) ("BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE" . #x002561) ("BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE" . #x002562) ("BOX DRAWINGS DOUBLE VERTICAL AND LEFT" . #x002563) ("BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE" . #x002564) ("BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE" . #x002565) ("BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL" . #x002566) ("BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE" . #x002567) ("BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE" . #x002568) ("BOX DRAWINGS DOUBLE UP AND HORIZONTAL" . #x002569) ("BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE" . #x00256a) ("BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE" . #x00256b) ("BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL" . #x00256c) ("BOX DRAWINGS LIGHT ARC DOWN AND RIGHT" . #x00256d) ("BOX DRAWINGS LIGHT ARC DOWN AND LEFT" . #x00256e) ("BOX DRAWINGS LIGHT ARC UP AND LEFT" . #x00256f) ("BOX DRAWINGS LIGHT ARC UP AND RIGHT" . #x002570) ("BOX DRAWINGS LIGHT DIAGONAL UPPER RIGHT TO LOWER LEFT" . #x002571) ("BOX DRAWINGS LIGHT DIAGONAL UPPER LEFT TO LOWER RIGHT" . #x002572) ("BOX DRAWINGS LIGHT DIAGONAL CROSS" . #x002573) ("BOX DRAWINGS LIGHT LEFT" . #x002574) ("BOX DRAWINGS LIGHT UP" . #x002575) ("BOX DRAWINGS LIGHT RIGHT" . #x002576) ("BOX DRAWINGS LIGHT DOWN" . #x002577) ("BOX DRAWINGS HEAVY LEFT" . #x002578) ("BOX DRAWINGS HEAVY UP" . #x002579) ("BOX DRAWINGS HEAVY RIGHT" . #x00257a) ("BOX DRAWINGS HEAVY DOWN" . #x00257b) ("BOX DRAWINGS LIGHT LEFT AND HEAVY RIGHT" . #x00257c) ("BOX DRAWINGS LIGHT UP AND HEAVY DOWN" . #x00257d) ("BOX DRAWINGS HEAVY LEFT AND LIGHT RIGHT" . #x00257e) ("BOX DRAWINGS HEAVY UP AND LIGHT DOWN" . #x00257f) ("UPPER HALF BLOCK" . #x002580) ("LOWER ONE EIGHTH BLOCK" . #x002581) ("LOWER ONE QUARTER BLOCK" . #x002582) ("LOWER THREE EIGHTHS BLOCK" . #x002583) ("LOWER HALF BLOCK" . #x002584) ("LOWER FIVE EIGHTHS BLOCK" . #x002585) ("LOWER THREE QUARTERS BLOCK" . #x002586) ("LOWER SEVEN EIGHTHS BLOCK" . #x002587) ("FULL BLOCK" . #x002588) ("LEFT SEVEN EIGHTHS BLOCK" . #x002589) ("LEFT THREE QUARTERS BLOCK" . #x00258a) ("LEFT FIVE EIGHTHS BLOCK" . #x00258b) ("LEFT HALF BLOCK" . #x00258c) ("LEFT THREE EIGHTHS BLOCK" . #x00258d) ("LEFT ONE QUARTER BLOCK" . #x00258e) ("LEFT ONE EIGHTH BLOCK" . #x00258f) ("RIGHT HALF BLOCK" . #x002590) ("LIGHT SHADE" . #x002591) ("MEDIUM SHADE" . #x002592) ("DARK SHADE" . #x002593) ("UPPER ONE EIGHTH BLOCK" . #x002594) ("RIGHT ONE EIGHTH BLOCK" . #x002595) ("QUADRANT LOWER LEFT" . #x002596) ("QUADRANT LOWER RIGHT" . #x002597) ("QUADRANT UPPER LEFT" . #x002598) ("QUADRANT UPPER LEFT AND LOWER LEFT AND LOWER RIGHT" . #x002599) ("QUADRANT UPPER LEFT AND LOWER RIGHT" . #x00259a) ("QUADRANT UPPER LEFT AND UPPER RIGHT AND LOWER LEFT" . #x00259b) ("QUADRANT UPPER LEFT AND UPPER RIGHT AND LOWER RIGHT" . #x00259c) ("QUADRANT UPPER RIGHT" . #x00259d) ("QUADRANT UPPER RIGHT AND LOWER LEFT" . #x00259e) ("QUADRANT UPPER RIGHT AND LOWER LEFT AND LOWER RIGHT" . #x00259f) ("BLACK SQUARE" . #x0025a0) ("WHITE SQUARE" . #x0025a1) ("WHITE SQUARE WITH ROUNDED CORNERS" . #x0025a2) ("WHITE SQUARE CONTAINING BLACK SMALL SQUARE" . #x0025a3) ("SQUARE WITH HORIZONTAL FILL" . #x0025a4) ("SQUARE WITH VERTICAL FILL" . #x0025a5) ("SQUARE WITH ORTHOGONAL CROSSHATCH FILL" . #x0025a6) ("SQUARE WITH UPPER LEFT TO LOWER RIGHT FILL" . #x0025a7) ("SQUARE WITH UPPER RIGHT TO LOWER LEFT FILL" . #x0025a8) ("SQUARE WITH DIAGONAL CROSSHATCH FILL" . #x0025a9) ("BLACK SMALL SQUARE" . #x0025aa) ("WHITE SMALL SQUARE" . #x0025ab) ("BLACK RECTANGLE" . #x0025ac) ("WHITE RECTANGLE" . #x0025ad) ("BLACK VERTICAL RECTANGLE" . #x0025ae) ("WHITE VERTICAL RECTANGLE" . #x0025af) ("BLACK PARALLELOGRAM" . #x0025b0) ("WHITE PARALLELOGRAM" . #x0025b1) ("BLACK UP-POINTING TRIANGLE" . #x0025b2) ("WHITE UP-POINTING TRIANGLE" . #x0025b3) ("BLACK UP-POINTING SMALL TRIANGLE" . #x0025b4) ("WHITE UP-POINTING SMALL TRIANGLE" . #x0025b5) ("BLACK RIGHT-POINTING TRIANGLE" . #x0025b6) ("WHITE RIGHT-POINTING TRIANGLE" . #x0025b7) ("BLACK RIGHT-POINTING SMALL TRIANGLE" . #x0025b8) ("WHITE RIGHT-POINTING SMALL TRIANGLE" . #x0025b9) ("BLACK RIGHT-POINTING POINTER" . #x0025ba) ("WHITE RIGHT-POINTING POINTER" . #x0025bb) ("BLACK DOWN-POINTING TRIANGLE" . #x0025bc) ("WHITE DOWN-POINTING TRIANGLE" . #x0025bd) ("BLACK DOWN-POINTING SMALL TRIANGLE" . #x0025be) ("WHITE DOWN-POINTING SMALL TRIANGLE" . #x0025bf) ("BLACK LEFT-POINTING TRIANGLE" . #x0025c0) ("WHITE LEFT-POINTING TRIANGLE" . #x0025c1) ("BLACK LEFT-POINTING SMALL TRIANGLE" . #x0025c2) ("WHITE LEFT-POINTING SMALL TRIANGLE" . #x0025c3) ("BLACK LEFT-POINTING POINTER" . #x0025c4) ("WHITE LEFT-POINTING POINTER" . #x0025c5) ("BLACK DIAMOND" . #x0025c6) ("WHITE DIAMOND" . #x0025c7) ("WHITE DIAMOND CONTAINING BLACK SMALL DIAMOND" . #x0025c8) ("FISHEYE" . #x0025c9) ("LOZENGE" . #x0025ca) ("WHITE CIRCLE" . #x0025cb) ("DOTTED CIRCLE" . #x0025cc) ("CIRCLE WITH VERTICAL FILL" . #x0025cd) ("BULLSEYE" . #x0025ce) ("BLACK CIRCLE" . #x0025cf) ("CIRCLE WITH LEFT HALF BLACK" . #x0025d0) ("CIRCLE WITH RIGHT HALF BLACK" . #x0025d1) ("CIRCLE WITH LOWER HALF BLACK" . #x0025d2) ("CIRCLE WITH UPPER HALF BLACK" . #x0025d3) ("CIRCLE WITH UPPER RIGHT QUADRANT BLACK" . #x0025d4) ("CIRCLE WITH ALL BUT UPPER LEFT QUADRANT BLACK" . #x0025d5) ("LEFT HALF BLACK CIRCLE" . #x0025d6) ("RIGHT HALF BLACK CIRCLE" . #x0025d7) ("INVERSE BULLET" . #x0025d8) ("INVERSE WHITE CIRCLE" . #x0025d9) ("UPPER HALF INVERSE WHITE CIRCLE" . #x0025da) ("LOWER HALF INVERSE WHITE CIRCLE" . #x0025db) ("UPPER LEFT QUADRANT CIRCULAR ARC" . #x0025dc) ("UPPER RIGHT QUADRANT CIRCULAR ARC" . #x0025dd) ("LOWER RIGHT QUADRANT CIRCULAR ARC" . #x0025de) ("LOWER LEFT QUADRANT CIRCULAR ARC" . #x0025df) ("UPPER HALF CIRCLE" . #x0025e0) ("LOWER HALF CIRCLE" . #x0025e1) ("BLACK LOWER RIGHT TRIANGLE" . #x0025e2) ("BLACK LOWER LEFT TRIANGLE" . #x0025e3) ("BLACK UPPER LEFT TRIANGLE" . #x0025e4) ("BLACK UPPER RIGHT TRIANGLE" . #x0025e5) ("WHITE BULLET" . #x0025e6) ("SQUARE WITH LEFT HALF BLACK" . #x0025e7) ("SQUARE WITH RIGHT HALF BLACK" . #x0025e8) ("SQUARE WITH UPPER LEFT DIAGONAL HALF BLACK" . #x0025e9) ("SQUARE WITH LOWER RIGHT DIAGONAL HALF BLACK" . #x0025ea) ("WHITE SQUARE WITH VERTICAL BISECTING LINE" . #x0025eb) ("WHITE UP-POINTING TRIANGLE WITH DOT" . #x0025ec) ("UP-POINTING TRIANGLE WITH LEFT HALF BLACK" . #x0025ed) ("UP-POINTING TRIANGLE WITH RIGHT HALF BLACK" . #x0025ee) ("LARGE CIRCLE" . #x0025ef) ("WHITE SQUARE WITH UPPER LEFT QUADRANT" . #x0025f0) ("WHITE SQUARE WITH LOWER LEFT QUADRANT" . #x0025f1) ("WHITE SQUARE WITH LOWER RIGHT QUADRANT" . #x0025f2) ("WHITE SQUARE WITH UPPER RIGHT QUADRANT" . #x0025f3) ("WHITE CIRCLE WITH UPPER LEFT QUADRANT" . #x0025f4) ("WHITE CIRCLE WITH LOWER LEFT QUADRANT" . #x0025f5) ("WHITE CIRCLE WITH LOWER RIGHT QUADRANT" . #x0025f6) ("WHITE CIRCLE WITH UPPER RIGHT QUADRANT" . #x0025f7) ("UPPER LEFT TRIANGLE" . #x0025f8) ("UPPER RIGHT TRIANGLE" . #x0025f9) ("LOWER LEFT TRIANGLE" . #x0025fa) ("WHITE MEDIUM SQUARE" . #x0025fb) ("BLACK MEDIUM SQUARE" . #x0025fc) ("WHITE MEDIUM SMALL SQUARE" . #x0025fd) ("BLACK MEDIUM SMALL SQUARE" . #x0025fe) ("LOWER RIGHT TRIANGLE" . #x0025ff) ("BLACK SUN WITH RAYS" . #x002600) ("CLOUD" . #x002601) ("UMBRELLA" . #x002602) ("SNOWMAN" . #x002603) ("COMET" . #x002604) ("BLACK STAR" . #x002605) ("WHITE STAR" . #x002606) ("LIGHTNING" . #x002607) ("THUNDERSTORM" . #x002608) ("SUN" . #x002609) ("ASCENDING NODE" . #x00260a) ("DESCENDING NODE" . #x00260b) ("CONJUNCTION" . #x00260c) ("OPPOSITION" . #x00260d) ("BLACK TELEPHONE" . #x00260e) ("WHITE TELEPHONE" . #x00260f) ("BALLOT BOX" . #x002610) ("BALLOT BOX WITH CHECK" . #x002611) ("BALLOT BOX WITH X" . #x002612) ("SALTIRE" . #x002613) ("WHITE SHOGI PIECE" . #x002616) ("BLACK SHOGI PIECE" . #x002617) ("REVERSED ROTATED FLORAL HEART BULLET" . #x002619) ("BLACK LEFT POINTING INDEX" . #x00261a) ("BLACK RIGHT POINTING INDEX" . #x00261b) ("WHITE LEFT POINTING INDEX" . #x00261c) ("WHITE UP POINTING INDEX" . #x00261d) ("WHITE RIGHT POINTING INDEX" . #x00261e) ("WHITE DOWN POINTING INDEX" . #x00261f) ("SKULL AND CROSSBONES" . #x002620) ("CAUTION SIGN" . #x002621) ("RADIOACTIVE SIGN" . #x002622) ("BIOHAZARD SIGN" . #x002623) ("CADUCEUS" . #x002624) ("ANKH" . #x002625) ("ORTHODOX CROSS" . #x002626) ("CHI RHO" . #x002627) ("CROSS OF LORRAINE" . #x002628) ("CROSS OF JERUSALEM" . #x002629) ("STAR AND CRESCENT" . #x00262a) ("FARSI SYMBOL" . #x00262b) ("ADI SHAKTI" . #x00262c) ("HAMMER AND SICKLE" . #x00262d) ("PEACE SYMBOL" . #x00262e) ("YIN YANG" . #x00262f) ("TRIGRAM FOR HEAVEN" . #x002630) ("TRIGRAM FOR LAKE" . #x002631) ("TRIGRAM FOR FIRE" . #x002632) ("TRIGRAM FOR THUNDER" . #x002633) ("TRIGRAM FOR WIND" . #x002634) ("TRIGRAM FOR WATER" . #x002635) ("TRIGRAM FOR MOUNTAIN" . #x002636) ("TRIGRAM FOR EARTH" . #x002637) ("WHEEL OF DHARMA" . #x002638) ("WHITE FROWNING FACE" . #x002639) ("WHITE SMILING FACE" . #x00263a) ("BLACK SMILING FACE" . #x00263b) ("WHITE SUN WITH RAYS" . #x00263c) ("FIRST QUARTER MOON" . #x00263d) ("LAST QUARTER MOON" . #x00263e) ("MERCURY" . #x00263f) ("FEMALE SIGN" . #x002640) ("EARTH" . #x002641) ("MALE SIGN" . #x002642) ("JUPITER" . #x002643) ("SATURN" . #x002644) ("URANUS" . #x002645) ("NEPTUNE" . #x002646) ("PLUTO" . #x002647) ("ARIES" . #x002648) ("TAURUS" . #x002649) ("GEMINI" . #x00264a) ("CANCER" . #x00264b) ("LEO" . #x00264c) ("VIRGO" . #x00264d) ("LIBRA" . #x00264e) ("SCORPIUS" . #x00264f) ("SAGITTARIUS" . #x002650) ("CAPRICORN" . #x002651) ("AQUARIUS" . #x002652) ("PISCES" . #x002653) ("WHITE CHESS KING" . #x002654) ("WHITE CHESS QUEEN" . #x002655) ("WHITE CHESS ROOK" . #x002656) ("WHITE CHESS BISHOP" . #x002657) ("WHITE CHESS KNIGHT" . #x002658) ("WHITE CHESS PAWN" . #x002659) ("BLACK CHESS KING" . #x00265a) ("BLACK CHESS QUEEN" . #x00265b) ("BLACK CHESS ROOK" . #x00265c) ("BLACK CHESS BISHOP" . #x00265d) ("BLACK CHESS KNIGHT" . #x00265e) ("BLACK CHESS PAWN" . #x00265f) ("BLACK SPADE SUIT" . #x002660) ("WHITE HEART SUIT" . #x002661) ("WHITE DIAMOND SUIT" . #x002662) ("BLACK CLUB SUIT" . #x002663) ("WHITE SPADE SUIT" . #x002664) ("BLACK HEART SUIT" . #x002665) ("BLACK DIAMOND SUIT" . #x002666) ("WHITE CLUB SUIT" . #x002667) ("HOT SPRINGS" . #x002668) ("QUARTER NOTE" . #x002669) ("EIGHTH NOTE" . #x00266a) ("BEAMED EIGHTH NOTES" . #x00266b) ("BEAMED SIXTEENTH NOTES" . #x00266c) ("MUSIC FLAT SIGN" . #x00266d) ("MUSIC NATURAL SIGN" . #x00266e) ("MUSIC SHARP SIGN" . #x00266f) ("WEST SYRIAC CROSS" . #x002670) ("EAST SYRIAC CROSS" . #x002671) ("UNIVERSAL RECYCLING SYMBOL" . #x002672) ("RECYCLING SYMBOL FOR TYPE-1 PLASTICS" . #x002673) ("RECYCLING SYMBOL FOR TYPE-2 PLASTICS" . #x002674) ("RECYCLING SYMBOL FOR TYPE-3 PLASTICS" . #x002675) ("RECYCLING SYMBOL FOR TYPE-4 PLASTICS" . #x002676) ("RECYCLING SYMBOL FOR TYPE-5 PLASTICS" . #x002677) ("RECYCLING SYMBOL FOR TYPE-6 PLASTICS" . #x002678) ("RECYCLING SYMBOL FOR TYPE-7 PLASTICS" . #x002679) ("RECYCLING SYMBOL FOR GENERIC MATERIALS" . #x00267a) ("BLACK UNIVERSAL RECYCLING SYMBOL" . #x00267b) ("RECYCLED PAPER SYMBOL" . #x00267c) ("PARTIALLY-RECYCLED PAPER SYMBOL" . #x00267d) ("DIE FACE-1" . #x002680) ("DIE FACE-2" . #x002681) ("DIE FACE-3" . #x002682) ("DIE FACE-4" . #x002683) ("DIE FACE-5" . #x002684) ("DIE FACE-6" . #x002685) ("WHITE CIRCLE WITH DOT RIGHT" . #x002686) ("WHITE CIRCLE WITH TWO DOTS" . #x002687) ("BLACK CIRCLE WITH WHITE DOT RIGHT" . #x002688) ("BLACK CIRCLE WITH TWO WHITE DOTS" . #x002689) ("UPPER BLADE SCISSORS" . #x002701) ("BLACK SCISSORS" . #x002702) ("LOWER BLADE SCISSORS" . #x002703) ("WHITE SCISSORS" . #x002704) ("TELEPHONE LOCATION SIGN" . #x002706) ("TAPE DRIVE" . #x002707) ("AIRPLANE" . #x002708) ("ENVELOPE" . #x002709) ("VICTORY HAND" . #x00270c) ("WRITING HAND" . #x00270d) ("LOWER RIGHT PENCIL" . #x00270e) ("PENCIL" . #x00270f) ("UPPER RIGHT PENCIL" . #x002710) ("WHITE NIB" . #x002711) ("BLACK NIB" . #x002712) ("CHECK MARK" . #x002713) ("HEAVY CHECK MARK" . #x002714) ("MULTIPLICATION X" . #x002715) ("HEAVY MULTIPLICATION X" . #x002716) ("BALLOT X" . #x002717) ("HEAVY BALLOT X" . #x002718) ("OUTLINED GREEK CROSS" . #x002719) ("HEAVY GREEK CROSS" . #x00271a) ("OPEN CENTRE CROSS" . #x00271b) ("HEAVY OPEN CENTRE CROSS" . #x00271c) ("LATIN CROSS" . #x00271d) ("SHADOWED WHITE LATIN CROSS" . #x00271e) ("OUTLINED LATIN CROSS" . #x00271f) ("MALTESE CROSS" . #x002720) ("STAR OF DAVID" . #x002721) ("FOUR TEARDROP-SPOKED ASTERISK" . #x002722) ("FOUR BALLOON-SPOKED ASTERISK" . #x002723) ("HEAVY FOUR BALLOON-SPOKED ASTERISK" . #x002724) ("FOUR CLUB-SPOKED ASTERISK" . #x002725) ("BLACK FOUR POINTED STAR" . #x002726) ("WHITE FOUR POINTED STAR" . #x002727) ("STRESS OUTLINED WHITE STAR" . #x002729) ("CIRCLED WHITE STAR" . #x00272a) ("OPEN CENTRE BLACK STAR" . #x00272b) ("BLACK CENTRE WHITE STAR" . #x00272c) ("OUTLINED BLACK STAR" . #x00272d) ("HEAVY OUTLINED BLACK STAR" . #x00272e) ("PINWHEEL STAR" . #x00272f) ("SHADOWED WHITE STAR" . #x002730) ("HEAVY ASTERISK" . #x002731) ("OPEN CENTRE ASTERISK" . #x002732) ("EIGHT SPOKED ASTERISK" . #x002733) ("EIGHT POINTED BLACK STAR" . #x002734) ("EIGHT POINTED PINWHEEL STAR" . #x002735) ("SIX POINTED BLACK STAR" . #x002736) ("EIGHT POINTED RECTILINEAR BLACK STAR" . #x002737) ("HEAVY EIGHT POINTED RECTILINEAR BLACK STAR" . #x002738) ("TWELVE POINTED BLACK STAR" . #x002739) ("SIXTEEN POINTED ASTERISK" . #x00273a) ("TEARDROP-SPOKED ASTERISK" . #x00273b) ("OPEN CENTRE TEARDROP-SPOKED ASTERISK" . #x00273c) ("HEAVY TEARDROP-SPOKED ASTERISK" . #x00273d) ("SIX PETALLED BLACK AND WHITE FLORETTE" . #x00273e) ("BLACK FLORETTE" . #x00273f) ("WHITE FLORETTE" . #x002740) ("EIGHT PETALLED OUTLINED BLACK FLORETTE" . #x002741) ("CIRCLED OPEN CENTRE EIGHT POINTED STAR" . #x002742) ("HEAVY TEARDROP-SPOKED PINWHEEL ASTERISK" . #x002743) ("SNOWFLAKE" . #x002744) ("TIGHT TRIFOLIATE SNOWFLAKE" . #x002745) ("HEAVY CHEVRON SNOWFLAKE" . #x002746) ("SPARKLE" . #x002747) ("HEAVY SPARKLE" . #x002748) ("BALLOON-SPOKED ASTERISK" . #x002749) ("EIGHT TEARDROP-SPOKED PROPELLER ASTERISK" . #x00274a) ("HEAVY EIGHT TEARDROP-SPOKED PROPELLER ASTERISK" . #x00274b) ("SHADOWED WHITE CIRCLE" . #x00274d) ("LOWER RIGHT DROP-SHADOWED WHITE SQUARE" . #x00274f) ("UPPER RIGHT DROP-SHADOWED WHITE SQUARE" . #x002750) ("LOWER RIGHT SHADOWED WHITE SQUARE" . #x002751) ("UPPER RIGHT SHADOWED WHITE SQUARE" . #x002752) ("BLACK DIAMOND MINUS WHITE X" . #x002756) ("LIGHT VERTICAL BAR" . #x002758) ("MEDIUM VERTICAL BAR" . #x002759) ("HEAVY VERTICAL BAR" . #x00275a) ("HEAVY SINGLE TURNED COMMA QUOTATION MARK ORNAMENT" . #x00275b) ("HEAVY SINGLE COMMA QUOTATION MARK ORNAMENT" . #x00275c) ("HEAVY DOUBLE TURNED COMMA QUOTATION MARK ORNAMENT" . #x00275d) ("HEAVY DOUBLE COMMA QUOTATION MARK ORNAMENT" . #x00275e) ("CURVED STEM PARAGRAPH SIGN ORNAMENT" . #x002761) ("HEAVY EXCLAMATION MARK ORNAMENT" . #x002762) ("HEAVY HEART EXCLAMATION MARK ORNAMENT" . #x002763) ("HEAVY BLACK HEART" . #x002764) ("ROTATED HEAVY BLACK HEART BULLET" . #x002765) ("FLORAL HEART" . #x002766) ("ROTATED FLORAL HEART BULLET" . #x002767) ("MEDIUM LEFT PARENTHESIS ORNAMENT" . #x002768) ("MEDIUM RIGHT PARENTHESIS ORNAMENT" . #x002769) ("MEDIUM FLATTENED LEFT PARENTHESIS ORNAMENT" . #x00276a) ("MEDIUM FLATTENED RIGHT PARENTHESIS ORNAMENT" . #x00276b) ("MEDIUM LEFT-POINTING ANGLE BRACKET ORNAMENT" . #x00276c) ("MEDIUM RIGHT-POINTING ANGLE BRACKET ORNAMENT" . #x00276d) ("HEAVY LEFT-POINTING ANGLE QUOTATION MARK ORNAMENT" . #x00276e) ("HEAVY RIGHT-POINTING ANGLE QUOTATION MARK ORNAMENT" . #x00276f) ("HEAVY LEFT-POINTING ANGLE BRACKET ORNAMENT" . #x002770) ("HEAVY RIGHT-POINTING ANGLE BRACKET ORNAMENT" . #x002771) ("LIGHT LEFT TORTOISE SHELL BRACKET ORNAMENT" . #x002772) ("LIGHT RIGHT TORTOISE SHELL BRACKET ORNAMENT" . #x002773) ("MEDIUM LEFT CURLY BRACKET ORNAMENT" . #x002774) ("MEDIUM RIGHT CURLY BRACKET ORNAMENT" . #x002775) ("DINGBAT NEGATIVE CIRCLED DIGIT ONE" . #x002776) ("DINGBAT NEGATIVE CIRCLED DIGIT TWO" . #x002777) ("DINGBAT NEGATIVE CIRCLED DIGIT THREE" . #x002778) ("DINGBAT NEGATIVE CIRCLED DIGIT FOUR" . #x002779) ("DINGBAT NEGATIVE CIRCLED DIGIT FIVE" . #x00277a) ("DINGBAT NEGATIVE CIRCLED DIGIT SIX" . #x00277b) ("DINGBAT NEGATIVE CIRCLED DIGIT SEVEN" . #x00277c) ("DINGBAT NEGATIVE CIRCLED DIGIT EIGHT" . #x00277d) ("DINGBAT NEGATIVE CIRCLED DIGIT NINE" . #x00277e) ("DINGBAT NEGATIVE CIRCLED NUMBER TEN" . #x00277f) ("DINGBAT CIRCLED SANS-SERIF DIGIT ONE" . #x002780) ("DINGBAT CIRCLED SANS-SERIF DIGIT TWO" . #x002781) ("DINGBAT CIRCLED SANS-SERIF DIGIT THREE" . #x002782) ("DINGBAT CIRCLED SANS-SERIF DIGIT FOUR" . #x002783) ("DINGBAT CIRCLED SANS-SERIF DIGIT FIVE" . #x002784) ("DINGBAT CIRCLED SANS-SERIF DIGIT SIX" . #x002785) ("DINGBAT CIRCLED SANS-SERIF DIGIT SEVEN" . #x002786) ("DINGBAT CIRCLED SANS-SERIF DIGIT EIGHT" . #x002787) ("DINGBAT CIRCLED SANS-SERIF DIGIT NINE" . #x002788) ("DINGBAT CIRCLED SANS-SERIF NUMBER TEN" . #x002789) ("DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT ONE" . #x00278a) ("DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT TWO" . #x00278b) ("DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT THREE" . #x00278c) ("DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT FOUR" . #x00278d) ("DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT FIVE" . #x00278e) ("DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT SIX" . #x00278f) ("DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT SEVEN" . #x002790) ("DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT EIGHT" . #x002791) ("DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT NINE" . #x002792) ("DINGBAT NEGATIVE CIRCLED SANS-SERIF NUMBER TEN" . #x002793) ("HEAVY WIDE-HEADED RIGHTWARDS ARROW" . #x002794) ("HEAVY SOUTH EAST ARROW" . #x002798) ("HEAVY RIGHTWARDS ARROW" . #x002799) ("HEAVY NORTH EAST ARROW" . #x00279a) ("DRAFTING POINT RIGHTWARDS ARROW" . #x00279b) ("HEAVY ROUND-TIPPED RIGHTWARDS ARROW" . #x00279c) ("TRIANGLE-HEADED RIGHTWARDS ARROW" . #x00279d) ("HEAVY TRIANGLE-HEADED RIGHTWARDS ARROW" . #x00279e) ("DASHED TRIANGLE-HEADED RIGHTWARDS ARROW" . #x00279f) ("HEAVY DASHED TRIANGLE-HEADED RIGHTWARDS ARROW" . #x0027a0) ("BLACK RIGHTWARDS ARROW" . #x0027a1) ("THREE-D TOP-LIGHTED RIGHTWARDS ARROWHEAD" . #x0027a2) ("THREE-D BOTTOM-LIGHTED RIGHTWARDS ARROWHEAD" . #x0027a3) ("BLACK RIGHTWARDS ARROWHEAD" . #x0027a4) ("HEAVY BLACK CURVED DOWNWARDS AND RIGHTWARDS ARROW" . #x0027a5) ("HEAVY BLACK CURVED UPWARDS AND RIGHTWARDS ARROW" . #x0027a6) ("SQUAT BLACK RIGHTWARDS ARROW" . #x0027a7) ("HEAVY CONCAVE-POINTED BLACK RIGHTWARDS ARROW" . #x0027a8) ("RIGHT-SHADED WHITE RIGHTWARDS ARROW" . #x0027a9) ("LEFT-SHADED WHITE RIGHTWARDS ARROW" . #x0027aa) ("BACK-TILTED SHADOWED WHITE RIGHTWARDS ARROW" . #x0027ab) ("FRONT-TILTED SHADOWED WHITE RIGHTWARDS ARROW" . #x0027ac) ("HEAVY LOWER RIGHT-SHADOWED WHITE RIGHTWARDS ARROW" . #x0027ad) ("HEAVY UPPER RIGHT-SHADOWED WHITE RIGHTWARDS ARROW" . #x0027ae) ("NOTCHED LOWER RIGHT-SHADOWED WHITE RIGHTWARDS ARROW" . #x0027af) ("NOTCHED UPPER RIGHT-SHADOWED WHITE RIGHTWARDS ARROW" . #x0027b1) ("CIRCLED HEAVY WHITE RIGHTWARDS ARROW" . #x0027b2) ("WHITE-FEATHERED RIGHTWARDS ARROW" . #x0027b3) ("BLACK-FEATHERED SOUTH EAST ARROW" . #x0027b4) ("BLACK-FEATHERED RIGHTWARDS ARROW" . #x0027b5) ("BLACK-FEATHERED NORTH EAST ARROW" . #x0027b6) ("HEAVY BLACK-FEATHERED SOUTH EAST ARROW" . #x0027b7) ("HEAVY BLACK-FEATHERED RIGHTWARDS ARROW" . #x0027b8) ("HEAVY BLACK-FEATHERED NORTH EAST ARROW" . #x0027b9) ("TEARDROP-BARBED RIGHTWARDS ARROW" . #x0027ba) ("HEAVY TEARDROP-SHANKED RIGHTWARDS ARROW" . #x0027bb) ("WEDGE-TAILED RIGHTWARDS ARROW" . #x0027bc) ("HEAVY WEDGE-TAILED RIGHTWARDS ARROW" . #x0027bd) ("OPEN-OUTLINED RIGHTWARDS ARROW" . #x0027be) ("WHITE DIAMOND WITH CENTRED DOT" . #x0027d0) ("AND WITH DOT" . #x0027d1) ("ELEMENT OF OPENING UPWARDS" . #x0027d2) ("LOWER RIGHT CORNER WITH DOT" . #x0027d3) ("UPPER LEFT CORNER WITH DOT" . #x0027d4) ("LEFT OUTER JOIN" . #x0027d5) ("RIGHT OUTER JOIN" . #x0027d6) ("FULL OUTER JOIN" . #x0027d7) ("LARGE UP TACK" . #x0027d8) ("LARGE DOWN TACK" . #x0027d9) ("LEFT AND RIGHT DOUBLE TURNSTILE" . #x0027da) ("LEFT AND RIGHT TACK" . #x0027db) ("LEFT MULTIMAP" . #x0027dc) ("LONG RIGHT TACK" . #x0027dd) ("LONG LEFT TACK" . #x0027de) ("UP TACK WITH CIRCLE ABOVE" . #x0027df) ("LOZENGE DIVIDED BY HORIZONTAL RULE" . #x0027e0) ("WHITE CONCAVE-SIDED DIAMOND" . #x0027e1) ("WHITE CONCAVE-SIDED DIAMOND WITH LEFTWARDS TICK" . #x0027e2) ("WHITE CONCAVE-SIDED DIAMOND WITH RIGHTWARDS TICK" . #x0027e3) ("WHITE SQUARE WITH LEFTWARDS TICK" . #x0027e4) ("WHITE SQUARE WITH RIGHTWARDS TICK" . #x0027e5) ("MATHEMATICAL LEFT WHITE SQUARE BRACKET" . #x0027e6) ("MATHEMATICAL RIGHT WHITE SQUARE BRACKET" . #x0027e7) ("MATHEMATICAL LEFT ANGLE BRACKET" . #x0027e8) ("MATHEMATICAL RIGHT ANGLE BRACKET" . #x0027e9) ("MATHEMATICAL LEFT DOUBLE ANGLE BRACKET" . #x0027ea) ("MATHEMATICAL RIGHT DOUBLE ANGLE BRACKET" . #x0027eb) ("UPWARDS QUADRUPLE ARROW" . #x0027f0) ("DOWNWARDS QUADRUPLE ARROW" . #x0027f1) ("ANTICLOCKWISE GAPPED CIRCLE ARROW" . #x0027f2) ("CLOCKWISE GAPPED CIRCLE ARROW" . #x0027f3) ("RIGHT ARROW WITH CIRCLED PLUS" . #x0027f4) ("LONG LEFTWARDS ARROW" . #x0027f5) ("LONG RIGHTWARDS ARROW" . #x0027f6) ("LONG LEFT RIGHT ARROW" . #x0027f7) ("LONG LEFTWARDS DOUBLE ARROW" . #x0027f8) ("LONG RIGHTWARDS DOUBLE ARROW" . #x0027f9) ("LONG LEFT RIGHT DOUBLE ARROW" . #x0027fa) ("LONG LEFTWARDS ARROW FROM BAR" . #x0027fb) ("LONG RIGHTWARDS ARROW FROM BAR" . #x0027fc) ("LONG LEFTWARDS DOUBLE ARROW FROM BAR" . #x0027fd) ("LONG RIGHTWARDS DOUBLE ARROW FROM BAR" . #x0027fe) ("LONG RIGHTWARDS SQUIGGLE ARROW" . #x0027ff) ("RIGHTWARDS TWO-HEADED ARROW WITH VERTICAL STROKE" . #x002900) ("RIGHTWARDS TWO-HEADED ARROW WITH DOUBLE VERTICAL STROKE" . #x002901) ("LEFTWARDS DOUBLE ARROW WITH VERTICAL STROKE" . #x002902) ("RIGHTWARDS DOUBLE ARROW WITH VERTICAL STROKE" . #x002903) ("LEFT RIGHT DOUBLE ARROW WITH VERTICAL STROKE" . #x002904) ("RIGHTWARDS TWO-HEADED ARROW FROM BAR" . #x002905) ("LEFTWARDS DOUBLE ARROW FROM BAR" . #x002906) ("RIGHTWARDS DOUBLE ARROW FROM BAR" . #x002907) ("DOWNWARDS ARROW WITH HORIZONTAL STROKE" . #x002908) ("UPWARDS ARROW WITH HORIZONTAL STROKE" . #x002909) ("UPWARDS TRIPLE ARROW" . #x00290a) ("DOWNWARDS TRIPLE ARROW" . #x00290b) ("LEFTWARDS DOUBLE DASH ARROW" . #x00290c) ("RIGHTWARDS DOUBLE DASH ARROW" . #x00290d) ("LEFTWARDS TRIPLE DASH ARROW" . #x00290e) ("RIGHTWARDS TRIPLE DASH ARROW" . #x00290f) ("RIGHTWARDS TWO-HEADED TRIPLE DASH ARROW" . #x002910) ("RIGHTWARDS ARROW WITH DOTTED STEM" . #x002911) ("UPWARDS ARROW TO BAR" . #x002912) ("DOWNWARDS ARROW TO BAR" . #x002913) ("RIGHTWARDS ARROW WITH TAIL WITH VERTICAL STROKE" . #x002914) ("RIGHTWARDS ARROW WITH TAIL WITH DOUBLE VERTICAL STROKE" . #x002915) ("RIGHTWARDS TWO-HEADED ARROW WITH TAIL" . #x002916) ("RIGHTWARDS TWO-HEADED ARROW WITH TAIL WITH VERTICAL STROKE" . #x002917) ("RIGHTWARDS TWO-HEADED ARROW WITH TAIL WITH DOUBLE VERTICAL STROKE" . #x002918) ("LEFTWARDS ARROW-TAIL" . #x002919) ("RIGHTWARDS ARROW-TAIL" . #x00291a) ("LEFTWARDS DOUBLE ARROW-TAIL" . #x00291b) ("RIGHTWARDS DOUBLE ARROW-TAIL" . #x00291c) ("LEFTWARDS ARROW TO BLACK DIAMOND" . #x00291d) ("RIGHTWARDS ARROW TO BLACK DIAMOND" . #x00291e) ("LEFTWARDS ARROW FROM BAR TO BLACK DIAMOND" . #x00291f) ("RIGHTWARDS ARROW FROM BAR TO BLACK DIAMOND" . #x002920) ("NORTH WEST AND SOUTH EAST ARROW" . #x002921) ("NORTH EAST AND SOUTH WEST ARROW" . #x002922) ("NORTH WEST ARROW WITH HOOK" . #x002923) ("NORTH EAST ARROW WITH HOOK" . #x002924) ("SOUTH EAST ARROW WITH HOOK" . #x002925) ("SOUTH WEST ARROW WITH HOOK" . #x002926) ("NORTH WEST ARROW AND NORTH EAST ARROW" . #x002927) ("NORTH EAST ARROW AND SOUTH EAST ARROW" . #x002928) ("SOUTH EAST ARROW AND SOUTH WEST ARROW" . #x002929) ("SOUTH WEST ARROW AND NORTH WEST ARROW" . #x00292a) ("RISING DIAGONAL CROSSING FALLING DIAGONAL" . #x00292b) ("FALLING DIAGONAL CROSSING RISING DIAGONAL" . #x00292c) ("SOUTH EAST ARROW CROSSING NORTH EAST ARROW" . #x00292d) ("NORTH EAST ARROW CROSSING SOUTH EAST ARROW" . #x00292e) ("FALLING DIAGONAL CROSSING NORTH EAST ARROW" . #x00292f) ("RISING DIAGONAL CROSSING SOUTH EAST ARROW" . #x002930) ("NORTH EAST ARROW CROSSING NORTH WEST ARROW" . #x002931) ("NORTH WEST ARROW CROSSING NORTH EAST ARROW" . #x002932) ("WAVE ARROW POINTING DIRECTLY RIGHT" . #x002933) ("ARROW POINTING RIGHTWARDS THEN CURVING UPWARDS" . #x002934) ("ARROW POINTING RIGHTWARDS THEN CURVING DOWNWARDS" . #x002935) ("ARROW POINTING DOWNWARDS THEN CURVING LEFTWARDS" . #x002936) ("ARROW POINTING DOWNWARDS THEN CURVING RIGHTWARDS" . #x002937) ("RIGHT-SIDE ARC CLOCKWISE ARROW" . #x002938) ("LEFT-SIDE ARC ANTICLOCKWISE ARROW" . #x002939) ("TOP ARC ANTICLOCKWISE ARROW" . #x00293a) ("BOTTOM ARC ANTICLOCKWISE ARROW" . #x00293b) ("TOP ARC CLOCKWISE ARROW WITH MINUS" . #x00293c) ("TOP ARC ANTICLOCKWISE ARROW WITH PLUS" . #x00293d) ("LOWER RIGHT SEMICIRCULAR CLOCKWISE ARROW" . #x00293e) ("LOWER LEFT SEMICIRCULAR ANTICLOCKWISE ARROW" . #x00293f) ("ANTICLOCKWISE CLOSED CIRCLE ARROW" . #x002940) ("CLOCKWISE CLOSED CIRCLE ARROW" . #x002941) ("RIGHTWARDS ARROW ABOVE SHORT LEFTWARDS ARROW" . #x002942) ("LEFTWARDS ARROW ABOVE SHORT RIGHTWARDS ARROW" . #x002943) ("SHORT RIGHTWARDS ARROW ABOVE LEFTWARDS ARROW" . #x002944) ("RIGHTWARDS ARROW WITH PLUS BELOW" . #x002945) ("LEFTWARDS ARROW WITH PLUS BELOW" . #x002946) ("RIGHTWARDS ARROW THROUGH X" . #x002947) ("LEFT RIGHT ARROW THROUGH SMALL CIRCLE" . #x002948) ("UPWARDS TWO-HEADED ARROW FROM SMALL CIRCLE" . #x002949) ("LEFT BARB UP RIGHT BARB DOWN HARPOON" . #x00294a) ("LEFT BARB DOWN RIGHT BARB UP HARPOON" . #x00294b) ("UP BARB RIGHT DOWN BARB LEFT HARPOON" . #x00294c) ("UP BARB LEFT DOWN BARB RIGHT HARPOON" . #x00294d) ("LEFT BARB UP RIGHT BARB UP HARPOON" . #x00294e) ("UP BARB RIGHT DOWN BARB RIGHT HARPOON" . #x00294f) ("LEFT BARB DOWN RIGHT BARB DOWN HARPOON" . #x002950) ("UP BARB LEFT DOWN BARB LEFT HARPOON" . #x002951) ("LEFTWARDS HARPOON WITH BARB UP TO BAR" . #x002952) ("RIGHTWARDS HARPOON WITH BARB UP TO BAR" . #x002953) ("UPWARDS HARPOON WITH BARB RIGHT TO BAR" . #x002954) ("DOWNWARDS HARPOON WITH BARB RIGHT TO BAR" . #x002955) ("LEFTWARDS HARPOON WITH BARB DOWN TO BAR" . #x002956) ("RIGHTWARDS HARPOON WITH BARB DOWN TO BAR" . #x002957) ("UPWARDS HARPOON WITH BARB LEFT TO BAR" . #x002958) ("DOWNWARDS HARPOON WITH BARB LEFT TO BAR" . #x002959) ("LEFTWARDS HARPOON WITH BARB UP FROM BAR" . #x00295a) ("RIGHTWARDS HARPOON WITH BARB UP FROM BAR" . #x00295b) ("UPWARDS HARPOON WITH BARB RIGHT FROM BAR" . #x00295c) ("DOWNWARDS HARPOON WITH BARB RIGHT FROM BAR" . #x00295d) ("LEFTWARDS HARPOON WITH BARB DOWN FROM BAR" . #x00295e) ("RIGHTWARDS HARPOON WITH BARB DOWN FROM BAR" . #x00295f) ("UPWARDS HARPOON WITH BARB LEFT FROM BAR" . #x002960) ("DOWNWARDS HARPOON WITH BARB LEFT FROM BAR" . #x002961) ("LEFTWARDS HARPOON WITH BARB UP ABOVE LEFTWARDS HARPOON WITH BARB DOWN" . #x002962) ("UPWARDS HARPOON WITH BARB LEFT BESIDE UPWARDS HARPOON WITH BARB RIGHT" . #x002963) ("RIGHTWARDS HARPOON WITH BARB UP ABOVE RIGHTWARDS HARPOON WITH BARB DOWN" . #x002964) ("DOWNWARDS HARPOON WITH BARB LEFT BESIDE DOWNWARDS HARPOON WITH BARB RIGHT" . #x002965) ("LEFTWARDS HARPOON WITH BARB UP ABOVE RIGHTWARDS HARPOON WITH BARB UP" . #x002966) ("LEFTWARDS HARPOON WITH BARB DOWN ABOVE RIGHTWARDS HARPOON WITH BARB DOWN" . #x002967) ("RIGHTWARDS HARPOON WITH BARB UP ABOVE LEFTWARDS HARPOON WITH BARB UP" . #x002968) ("RIGHTWARDS HARPOON WITH BARB DOWN ABOVE LEFTWARDS HARPOON WITH BARB DOWN" . #x002969) ("LEFTWARDS HARPOON WITH BARB UP ABOVE LONG DASH" . #x00296a) ("LEFTWARDS HARPOON WITH BARB DOWN BELOW LONG DASH" . #x00296b) ("RIGHTWARDS HARPOON WITH BARB UP ABOVE LONG DASH" . #x00296c) ("RIGHTWARDS HARPOON WITH BARB DOWN BELOW LONG DASH" . #x00296d) ("UPWARDS HARPOON WITH BARB LEFT BESIDE DOWNWARDS HARPOON WITH BARB RIGHT" . #x00296e) ("DOWNWARDS HARPOON WITH BARB LEFT BESIDE UPWARDS HARPOON WITH BARB RIGHT" . #x00296f) ("RIGHT DOUBLE ARROW WITH ROUNDED HEAD" . #x002970) ("EQUALS SIGN ABOVE RIGHTWARDS ARROW" . #x002971) ("TILDE OPERATOR ABOVE RIGHTWARDS ARROW" . #x002972) ("LEFTWARDS ARROW ABOVE TILDE OPERATOR" . #x002973) ("RIGHTWARDS ARROW ABOVE TILDE OPERATOR" . #x002974) ("RIGHTWARDS ARROW ABOVE ALMOST EQUAL TO" . #x002975) ("LESS-THAN ABOVE LEFTWARDS ARROW" . #x002976) ("LEFTWARDS ARROW THROUGH LESS-THAN" . #x002977) ("GREATER-THAN ABOVE RIGHTWARDS ARROW" . #x002978) ("SUBSET ABOVE RIGHTWARDS ARROW" . #x002979) ("LEFTWARDS ARROW THROUGH SUBSET" . #x00297a) ("SUPERSET ABOVE LEFTWARDS ARROW" . #x00297b) ("LEFT FISH TAIL" . #x00297c) ("RIGHT FISH TAIL" . #x00297d) ("UP FISH TAIL" . #x00297e) ("DOWN FISH TAIL" . #x00297f) ("TRIPLE VERTICAL BAR DELIMITER" . #x002980) ("Z NOTATION SPOT" . #x002981) ("Z NOTATION TYPE COLON" . #x002982) ("LEFT WHITE CURLY BRACKET" . #x002983) ("RIGHT WHITE CURLY BRACKET" . #x002984) ("LEFT WHITE PARENTHESIS" . #x002985) ("RIGHT WHITE PARENTHESIS" . #x002986) ("Z NOTATION LEFT IMAGE BRACKET" . #x002987) ("Z NOTATION RIGHT IMAGE BRACKET" . #x002988) ("Z NOTATION LEFT BINDING BRACKET" . #x002989) ("Z NOTATION RIGHT BINDING BRACKET" . #x00298a) ("LEFT SQUARE BRACKET WITH UNDERBAR" . #x00298b) ("RIGHT SQUARE BRACKET WITH UNDERBAR" . #x00298c) ("LEFT SQUARE BRACKET WITH TICK IN TOP CORNER" . #x00298d) ("RIGHT SQUARE BRACKET WITH TICK IN BOTTOM CORNER" . #x00298e) ("LEFT SQUARE BRACKET WITH TICK IN BOTTOM CORNER" . #x00298f) ("RIGHT SQUARE BRACKET WITH TICK IN TOP CORNER" . #x002990) ("LEFT ANGLE BRACKET WITH DOT" . #x002991) ("RIGHT ANGLE BRACKET WITH DOT" . #x002992) ("LEFT ARC LESS-THAN BRACKET" . #x002993) ("RIGHT ARC GREATER-THAN BRACKET" . #x002994) ("DOUBLE LEFT ARC GREATER-THAN BRACKET" . #x002995) ("DOUBLE RIGHT ARC LESS-THAN BRACKET" . #x002996) ("LEFT BLACK TORTOISE SHELL BRACKET" . #x002997) ("RIGHT BLACK TORTOISE SHELL BRACKET" . #x002998) ("DOTTED FENCE" . #x002999) ("VERTICAL ZIGZAG LINE" . #x00299a) ("MEASURED ANGLE OPENING LEFT" . #x00299b) ("RIGHT ANGLE VARIANT WITH SQUARE" . #x00299c) ("MEASURED RIGHT ANGLE WITH DOT" . #x00299d) ("ANGLE WITH S INSIDE" . #x00299e) ("ACUTE ANGLE" . #x00299f) ("SPHERICAL ANGLE OPENING LEFT" . #x0029a0) ("SPHERICAL ANGLE OPENING UP" . #x0029a1) ("TURNED ANGLE" . #x0029a2) ("REVERSED ANGLE" . #x0029a3) ("ANGLE WITH UNDERBAR" . #x0029a4) ("REVERSED ANGLE WITH UNDERBAR" . #x0029a5) ("OBLIQUE ANGLE OPENING UP" . #x0029a6) ("OBLIQUE ANGLE OPENING DOWN" . #x0029a7) ("MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING UP AND RIGHT" . #x0029a8) ("MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING UP AND LEFT" . #x0029a9) ("MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING DOWN AND RIGHT" . #x0029aa) ("MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING DOWN AND LEFT" . #x0029ab) ("MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING RIGHT AND UP" . #x0029ac) ("MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING LEFT AND UP" . #x0029ad) ("MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING RIGHT AND DOWN" . #x0029ae) ("MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING LEFT AND DOWN" . #x0029af) ("REVERSED EMPTY SET" . #x0029b0) ("EMPTY SET WITH OVERBAR" . #x0029b1) ("EMPTY SET WITH SMALL CIRCLE ABOVE" . #x0029b2) ("EMPTY SET WITH RIGHT ARROW ABOVE" . #x0029b3) ("EMPTY SET WITH LEFT ARROW ABOVE" . #x0029b4) ("CIRCLE WITH HORIZONTAL BAR" . #x0029b5) ("CIRCLED VERTICAL BAR" . #x0029b6) ("CIRCLED PARALLEL" . #x0029b7) ("CIRCLED REVERSE SOLIDUS" . #x0029b8) ("CIRCLED PERPENDICULAR" . #x0029b9) ("CIRCLE DIVIDED BY HORIZONTAL BAR AND TOP HALF DIVIDED BY VERTICAL BAR" . #x0029ba) ("CIRCLE WITH SUPERIMPOSED X" . #x0029bb) ("CIRCLED ANTICLOCKWISE-ROTATED DIVISION SIGN" . #x0029bc) ("UP ARROW THROUGH CIRCLE" . #x0029bd) ("CIRCLED WHITE BULLET" . #x0029be) ("CIRCLED BULLET" . #x0029bf) ("CIRCLED LESS-THAN" . #x0029c0) ("CIRCLED GREATER-THAN" . #x0029c1) ("CIRCLE WITH SMALL CIRCLE TO THE RIGHT" . #x0029c2) ("CIRCLE WITH TWO HORIZONTAL STROKES TO THE RIGHT" . #x0029c3) ("SQUARED RISING DIAGONAL SLASH" . #x0029c4) ("SQUARED FALLING DIAGONAL SLASH" . #x0029c5) ("SQUARED ASTERISK" . #x0029c6) ("SQUARED SMALL CIRCLE" . #x0029c7) ("SQUARED SQUARE" . #x0029c8) ("TWO JOINED SQUARES" . #x0029c9) ("TRIANGLE WITH DOT ABOVE" . #x0029ca) ("TRIANGLE WITH UNDERBAR" . #x0029cb) ("S IN TRIANGLE" . #x0029cc) ("TRIANGLE WITH SERIFS AT BOTTOM" . #x0029cd) ("RIGHT TRIANGLE ABOVE LEFT TRIANGLE" . #x0029ce) ("LEFT TRIANGLE BESIDE VERTICAL BAR" . #x0029cf) ("VERTICAL BAR BESIDE RIGHT TRIANGLE" . #x0029d0) ("BOWTIE WITH LEFT HALF BLACK" . #x0029d1) ("BOWTIE WITH RIGHT HALF BLACK" . #x0029d2) ("BLACK BOWTIE" . #x0029d3) ("TIMES WITH LEFT HALF BLACK" . #x0029d4) ("TIMES WITH RIGHT HALF BLACK" . #x0029d5) ("WHITE HOURGLASS" . #x0029d6) ("BLACK HOURGLASS" . #x0029d7) ("LEFT WIGGLY FENCE" . #x0029d8) ("RIGHT WIGGLY FENCE" . #x0029d9) ("LEFT DOUBLE WIGGLY FENCE" . #x0029da) ("RIGHT DOUBLE WIGGLY FENCE" . #x0029db) ("INCOMPLETE INFINITY" . #x0029dc) ("TIE OVER INFINITY" . #x0029dd) ("INFINITY NEGATED WITH VERTICAL BAR" . #x0029de) ("DOUBLE-ENDED MULTIMAP" . #x0029df) ("SQUARE WITH CONTOURED OUTLINE" . #x0029e0) ("INCREASES AS" . #x0029e1) ("SHUFFLE PRODUCT" . #x0029e2) ("EQUALS SIGN AND SLANTED PARALLEL" . #x0029e3) ("EQUALS SIGN AND SLANTED PARALLEL WITH TILDE ABOVE" . #x0029e4) ("IDENTICAL TO AND SLANTED PARALLEL" . #x0029e5) ("GLEICH STARK" . #x0029e6) ("THERMODYNAMIC" . #x0029e7) ("DOWN-POINTING TRIANGLE WITH LEFT HALF BLACK" . #x0029e8) ("DOWN-POINTING TRIANGLE WITH RIGHT HALF BLACK" . #x0029e9) ("BLACK DIAMOND WITH DOWN ARROW" . #x0029ea) ("BLACK LOZENGE" . #x0029eb) ("WHITE CIRCLE WITH DOWN ARROW" . #x0029ec) ("BLACK CIRCLE WITH DOWN ARROW" . #x0029ed) ("ERROR-BARRED WHITE SQUARE" . #x0029ee) ("ERROR-BARRED BLACK SQUARE" . #x0029ef) ("ERROR-BARRED WHITE DIAMOND" . #x0029f0) ("ERROR-BARRED BLACK DIAMOND" . #x0029f1) ("ERROR-BARRED WHITE CIRCLE" . #x0029f2) ("ERROR-BARRED BLACK CIRCLE" . #x0029f3) ("RULE-DELAYED" . #x0029f4) ("REVERSE SOLIDUS OPERATOR" . #x0029f5) ("SOLIDUS WITH OVERBAR" . #x0029f6) ("REVERSE SOLIDUS WITH HORIZONTAL STROKE" . #x0029f7) ("BIG SOLIDUS" . #x0029f8) ("BIG REVERSE SOLIDUS" . #x0029f9) ("DOUBLE PLUS" . #x0029fa) ("TRIPLE PLUS" . #x0029fb) ("LEFT-POINTING CURVED ANGLE BRACKET" . #x0029fc) ("RIGHT-POINTING CURVED ANGLE BRACKET" . #x0029fd) ("TINY" . #x0029fe) ("MINY" . #x0029ff) ("N-ARY CIRCLED DOT OPERATOR" . #x002a00) ("N-ARY CIRCLED PLUS OPERATOR" . #x002a01) ("N-ARY CIRCLED TIMES OPERATOR" . #x002a02) ("N-ARY UNION OPERATOR WITH DOT" . #x002a03) ("N-ARY UNION OPERATOR WITH PLUS" . #x002a04) ("N-ARY SQUARE INTERSECTION OPERATOR" . #x002a05) ("N-ARY SQUARE UNION OPERATOR" . #x002a06) ("TWO LOGICAL AND OPERATOR" . #x002a07) ("TWO LOGICAL OR OPERATOR" . #x002a08) ("N-ARY TIMES OPERATOR" . #x002a09) ("MODULO TWO SUM" . #x002a0a) ("SUMMATION WITH INTEGRAL" . #x002a0b) ("QUADRUPLE INTEGRAL OPERATOR" . #x002a0c) ("FINITE PART INTEGRAL" . #x002a0d) ("INTEGRAL WITH DOUBLE STROKE" . #x002a0e) ("INTEGRAL AVERAGE WITH SLASH" . #x002a0f) ("CIRCULATION FUNCTION" . #x002a10) ("ANTICLOCKWISE INTEGRATION" . #x002a11) ("LINE INTEGRATION WITH RECTANGULAR PATH AROUND POLE" . #x002a12) ("LINE INTEGRATION WITH SEMICIRCULAR PATH AROUND POLE" . #x002a13) ("LINE INTEGRATION NOT INCLUDING THE POLE" . #x002a14) ("INTEGRAL AROUND A POINT OPERATOR" . #x002a15) ("QUATERNION INTEGRAL OPERATOR" . #x002a16) ("INTEGRAL WITH LEFTWARDS ARROW WITH HOOK" . #x002a17) ("INTEGRAL WITH TIMES SIGN" . #x002a18) ("INTEGRAL WITH INTERSECTION" . #x002a19) ("INTEGRAL WITH UNION" . #x002a1a) ("INTEGRAL WITH OVERBAR" . #x002a1b) ("INTEGRAL WITH UNDERBAR" . #x002a1c) ("JOIN" . #x002a1d) ("LARGE LEFT TRIANGLE OPERATOR" . #x002a1e) ("Z NOTATION SCHEMA COMPOSITION" . #x002a1f) ("Z NOTATION SCHEMA PIPING" . #x002a20) ("Z NOTATION SCHEMA PROJECTION" . #x002a21) ("PLUS SIGN WITH SMALL CIRCLE ABOVE" . #x002a22) ("PLUS SIGN WITH CIRCUMFLEX ACCENT ABOVE" . #x002a23) ("PLUS SIGN WITH TILDE ABOVE" . #x002a24) ("PLUS SIGN WITH DOT BELOW" . #x002a25) ("PLUS SIGN WITH TILDE BELOW" . #x002a26) ("PLUS SIGN WITH SUBSCRIPT TWO" . #x002a27) ("PLUS SIGN WITH BLACK TRIANGLE" . #x002a28) ("MINUS SIGN WITH COMMA ABOVE" . #x002a29) ("MINUS SIGN WITH DOT BELOW" . #x002a2a) ("MINUS SIGN WITH FALLING DOTS" . #x002a2b) ("MINUS SIGN WITH RISING DOTS" . #x002a2c) ("PLUS SIGN IN LEFT HALF CIRCLE" . #x002a2d) ("PLUS SIGN IN RIGHT HALF CIRCLE" . #x002a2e) ("VECTOR OR CROSS PRODUCT" . #x002a2f) ("MULTIPLICATION SIGN WITH DOT ABOVE" . #x002a30) ("MULTIPLICATION SIGN WITH UNDERBAR" . #x002a31) ("SEMIDIRECT PRODUCT WITH BOTTOM CLOSED" . #x002a32) ("SMASH PRODUCT" . #x002a33) ("MULTIPLICATION SIGN IN LEFT HALF CIRCLE" . #x002a34) ("MULTIPLICATION SIGN IN RIGHT HALF CIRCLE" . #x002a35) ("CIRCLED MULTIPLICATION SIGN WITH CIRCUMFLEX ACCENT" . #x002a36) ("MULTIPLICATION SIGN IN DOUBLE CIRCLE" . #x002a37) ("CIRCLED DIVISION SIGN" . #x002a38) ("PLUS SIGN IN TRIANGLE" . #x002a39) ("MINUS SIGN IN TRIANGLE" . #x002a3a) ("MULTIPLICATION SIGN IN TRIANGLE" . #x002a3b) ("INTERIOR PRODUCT" . #x002a3c) ("RIGHTHAND INTERIOR PRODUCT" . #x002a3d) ("Z NOTATION RELATIONAL COMPOSITION" . #x002a3e) ("AMALGAMATION OR COPRODUCT" . #x002a3f) ("INTERSECTION WITH DOT" . #x002a40) ("UNION WITH MINUS SIGN" . #x002a41) ("UNION WITH OVERBAR" . #x002a42) ("INTERSECTION WITH OVERBAR" . #x002a43) ("INTERSECTION WITH LOGICAL AND" . #x002a44) ("UNION WITH LOGICAL OR" . #x002a45) ("UNION ABOVE INTERSECTION" . #x002a46) ("INTERSECTION ABOVE UNION" . #x002a47) ("UNION ABOVE BAR ABOVE INTERSECTION" . #x002a48) ("INTERSECTION ABOVE BAR ABOVE UNION" . #x002a49) ("UNION BESIDE AND JOINED WITH UNION" . #x002a4a) ("INTERSECTION BESIDE AND JOINED WITH INTERSECTION" . #x002a4b) ("CLOSED UNION WITH SERIFS" . #x002a4c) ("CLOSED INTERSECTION WITH SERIFS" . #x002a4d) ("DOUBLE SQUARE INTERSECTION" . #x002a4e) ("DOUBLE SQUARE UNION" . #x002a4f) ("CLOSED UNION WITH SERIFS AND SMASH PRODUCT" . #x002a50) ("LOGICAL AND WITH DOT ABOVE" . #x002a51) ("LOGICAL OR WITH DOT ABOVE" . #x002a52) ("DOUBLE LOGICAL AND" . #x002a53) ("DOUBLE LOGICAL OR" . #x002a54) ("TWO INTERSECTING LOGICAL AND" . #x002a55) ("TWO INTERSECTING LOGICAL OR" . #x002a56) ("SLOPING LARGE OR" . #x002a57) ("SLOPING LARGE AND" . #x002a58) ("LOGICAL OR OVERLAPPING LOGICAL AND" . #x002a59) ("LOGICAL AND WITH MIDDLE STEM" . #x002a5a) ("LOGICAL OR WITH MIDDLE STEM" . #x002a5b) ("LOGICAL AND WITH HORIZONTAL DASH" . #x002a5c) ("LOGICAL OR WITH HORIZONTAL DASH" . #x002a5d) ("LOGICAL AND WITH DOUBLE OVERBAR" . #x002a5e) ("LOGICAL AND WITH UNDERBAR" . #x002a5f) ("LOGICAL AND WITH DOUBLE UNDERBAR" . #x002a60) ("SMALL VEE WITH UNDERBAR" . #x002a61) ("LOGICAL OR WITH DOUBLE OVERBAR" . #x002a62) ("LOGICAL OR WITH DOUBLE UNDERBAR" . #x002a63) ("Z NOTATION DOMAIN ANTIRESTRICTION" . #x002a64) ("Z NOTATION RANGE ANTIRESTRICTION" . #x002a65) ("EQUALS SIGN WITH DOT BELOW" . #x002a66) ("IDENTICAL WITH DOT ABOVE" . #x002a67) ("TRIPLE HORIZONTAL BAR WITH DOUBLE VERTICAL STROKE" . #x002a68) ("TRIPLE HORIZONTAL BAR WITH TRIPLE VERTICAL STROKE" . #x002a69) ("TILDE OPERATOR WITH DOT ABOVE" . #x002a6a) ("TILDE OPERATOR WITH RISING DOTS" . #x002a6b) ("SIMILAR MINUS SIMILAR" . #x002a6c) ("CONGRUENT WITH DOT ABOVE" . #x002a6d) ("EQUALS WITH ASTERISK" . #x002a6e) ("ALMOST EQUAL TO WITH CIRCUMFLEX ACCENT" . #x002a6f) ("APPROXIMATELY EQUAL OR EQUAL TO" . #x002a70) ("EQUALS SIGN ABOVE PLUS SIGN" . #x002a71) ("PLUS SIGN ABOVE EQUALS SIGN" . #x002a72) ("EQUALS SIGN ABOVE TILDE OPERATOR" . #x002a73) ("DOUBLE COLON EQUAL" . #x002a74) ("TWO CONSECUTIVE EQUALS SIGNS" . #x002a75) ("THREE CONSECUTIVE EQUALS SIGNS" . #x002a76) ("EQUALS SIGN WITH TWO DOTS ABOVE AND TWO DOTS BELOW" . #x002a77) ("EQUIVALENT WITH FOUR DOTS ABOVE" . #x002a78) ("LESS-THAN WITH CIRCLE INSIDE" . #x002a79) ("GREATER-THAN WITH CIRCLE INSIDE" . #x002a7a) ("LESS-THAN WITH QUESTION MARK ABOVE" . #x002a7b) ("GREATER-THAN WITH QUESTION MARK ABOVE" . #x002a7c) ("LESS-THAN OR SLANTED EQUAL TO" . #x002a7d) ("GREATER-THAN OR SLANTED EQUAL TO" . #x002a7e) ("LESS-THAN OR SLANTED EQUAL TO WITH DOT INSIDE" . #x002a7f) ("GREATER-THAN OR SLANTED EQUAL TO WITH DOT INSIDE" . #x002a80) ("LESS-THAN OR SLANTED EQUAL TO WITH DOT ABOVE" . #x002a81) ("GREATER-THAN OR SLANTED EQUAL TO WITH DOT ABOVE" . #x002a82) ("LESS-THAN OR SLANTED EQUAL TO WITH DOT ABOVE RIGHT" . #x002a83) ("GREATER-THAN OR SLANTED EQUAL TO WITH DOT ABOVE LEFT" . #x002a84) ("LESS-THAN OR APPROXIMATE" . #x002a85) ("GREATER-THAN OR APPROXIMATE" . #x002a86) ("LESS-THAN AND SINGLE-LINE NOT EQUAL TO" . #x002a87) ("GREATER-THAN AND SINGLE-LINE NOT EQUAL TO" . #x002a88) ("LESS-THAN AND NOT APPROXIMATE" . #x002a89) ("GREATER-THAN AND NOT APPROXIMATE" . #x002a8a) ("LESS-THAN ABOVE DOUBLE-LINE EQUAL ABOVE GREATER-THAN" . #x002a8b) ("GREATER-THAN ABOVE DOUBLE-LINE EQUAL ABOVE LESS-THAN" . #x002a8c) ("LESS-THAN ABOVE SIMILAR OR EQUAL" . #x002a8d) ("GREATER-THAN ABOVE SIMILAR OR EQUAL" . #x002a8e) ("LESS-THAN ABOVE SIMILAR ABOVE GREATER-THAN" . #x002a8f) ("GREATER-THAN ABOVE SIMILAR ABOVE LESS-THAN" . #x002a90) ("LESS-THAN ABOVE GREATER-THAN ABOVE DOUBLE-LINE EQUAL" . #x002a91) ("GREATER-THAN ABOVE LESS-THAN ABOVE DOUBLE-LINE EQUAL" . #x002a92) ("LESS-THAN ABOVE SLANTED EQUAL ABOVE GREATER-THAN ABOVE SLANTED EQUAL" . #x002a93) ("GREATER-THAN ABOVE SLANTED EQUAL ABOVE LESS-THAN ABOVE SLANTED EQUAL" . #x002a94) ("SLANTED EQUAL TO OR LESS-THAN" . #x002a95) ("SLANTED EQUAL TO OR GREATER-THAN" . #x002a96) ("SLANTED EQUAL TO OR LESS-THAN WITH DOT INSIDE" . #x002a97) ("SLANTED EQUAL TO OR GREATER-THAN WITH DOT INSIDE" . #x002a98) ("DOUBLE-LINE EQUAL TO OR LESS-THAN" . #x002a99) ("DOUBLE-LINE EQUAL TO OR GREATER-THAN" . #x002a9a) ("DOUBLE-LINE SLANTED EQUAL TO OR LESS-THAN" . #x002a9b) ("DOUBLE-LINE SLANTED EQUAL TO OR GREATER-THAN" . #x002a9c) ("SIMILAR OR LESS-THAN" . #x002a9d) ("SIMILAR OR GREATER-THAN" . #x002a9e) ("SIMILAR ABOVE LESS-THAN ABOVE EQUALS SIGN" . #x002a9f) ("SIMILAR ABOVE GREATER-THAN ABOVE EQUALS SIGN" . #x002aa0) ("DOUBLE NESTED LESS-THAN" . #x002aa1) ("DOUBLE NESTED GREATER-THAN" . #x002aa2) ("DOUBLE NESTED LESS-THAN WITH UNDERBAR" . #x002aa3) ("GREATER-THAN OVERLAPPING LESS-THAN" . #x002aa4) ("GREATER-THAN BESIDE LESS-THAN" . #x002aa5) ("LESS-THAN CLOSED BY CURVE" . #x002aa6) ("GREATER-THAN CLOSED BY CURVE" . #x002aa7) ("LESS-THAN CLOSED BY CURVE ABOVE SLANTED EQUAL" . #x002aa8) ("GREATER-THAN CLOSED BY CURVE ABOVE SLANTED EQUAL" . #x002aa9) ("SMALLER THAN" . #x002aaa) ("LARGER THAN" . #x002aab) ("SMALLER THAN OR EQUAL TO" . #x002aac) ("LARGER THAN OR EQUAL TO" . #x002aad) ("EQUALS SIGN WITH BUMPY ABOVE" . #x002aae) ("PRECEDES ABOVE SINGLE-LINE EQUALS SIGN" . #x002aaf) ("SUCCEEDS ABOVE SINGLE-LINE EQUALS SIGN" . #x002ab0) ("PRECEDES ABOVE SINGLE-LINE NOT EQUAL TO" . #x002ab1) ("SUCCEEDS ABOVE SINGLE-LINE NOT EQUAL TO" . #x002ab2) ("PRECEDES ABOVE EQUALS SIGN" . #x002ab3) ("SUCCEEDS ABOVE EQUALS SIGN" . #x002ab4) ("PRECEDES ABOVE NOT EQUAL TO" . #x002ab5) ("SUCCEEDS ABOVE NOT EQUAL TO" . #x002ab6) ("PRECEDES ABOVE ALMOST EQUAL TO" . #x002ab7) ("SUCCEEDS ABOVE ALMOST EQUAL TO" . #x002ab8) ("PRECEDES ABOVE NOT ALMOST EQUAL TO" . #x002ab9) ("SUCCEEDS ABOVE NOT ALMOST EQUAL TO" . #x002aba) ("DOUBLE PRECEDES" . #x002abb) ("DOUBLE SUCCEEDS" . #x002abc) ("SUBSET WITH DOT" . #x002abd) ("SUPERSET WITH DOT" . #x002abe) ("SUBSET WITH PLUS SIGN BELOW" . #x002abf) ("SUPERSET WITH PLUS SIGN BELOW" . #x002ac0) ("SUBSET WITH MULTIPLICATION SIGN BELOW" . #x002ac1) ("SUPERSET WITH MULTIPLICATION SIGN BELOW" . #x002ac2) ("SUBSET OF OR EQUAL TO WITH DOT ABOVE" . #x002ac3) ("SUPERSET OF OR EQUAL TO WITH DOT ABOVE" . #x002ac4) ("SUBSET OF ABOVE EQUALS SIGN" . #x002ac5) ("SUPERSET OF ABOVE EQUALS SIGN" . #x002ac6) ("SUBSET OF ABOVE TILDE OPERATOR" . #x002ac7) ("SUPERSET OF ABOVE TILDE OPERATOR" . #x002ac8) ("SUBSET OF ABOVE ALMOST EQUAL TO" . #x002ac9) ("SUPERSET OF ABOVE ALMOST EQUAL TO" . #x002aca) ("SUBSET OF ABOVE NOT EQUAL TO" . #x002acb) ("SUPERSET OF ABOVE NOT EQUAL TO" . #x002acc) ("SQUARE LEFT OPEN BOX OPERATOR" . #x002acd) ("SQUARE RIGHT OPEN BOX OPERATOR" . #x002ace) ("CLOSED SUBSET" . #x002acf) ("CLOSED SUPERSET" . #x002ad0) ("CLOSED SUBSET OR EQUAL TO" . #x002ad1) ("CLOSED SUPERSET OR EQUAL TO" . #x002ad2) ("SUBSET ABOVE SUPERSET" . #x002ad3) ("SUPERSET ABOVE SUBSET" . #x002ad4) ("SUBSET ABOVE SUBSET" . #x002ad5) ("SUPERSET ABOVE SUPERSET" . #x002ad6) ("SUPERSET BESIDE SUBSET" . #x002ad7) ("SUPERSET BESIDE AND JOINED BY DASH WITH SUBSET" . #x002ad8) ("ELEMENT OF OPENING DOWNWARDS" . #x002ad9) ("PITCHFORK WITH TEE TOP" . #x002ada) ("TRANSVERSAL INTERSECTION" . #x002adb) ("FORKING" . #x002adc) ("NONFORKING" . #x002add) ("SHORT LEFT TACK" . #x002ade) ("SHORT DOWN TACK" . #x002adf) ("SHORT UP TACK" . #x002ae0) ("PERPENDICULAR WITH S" . #x002ae1) ("VERTICAL BAR TRIPLE RIGHT TURNSTILE" . #x002ae2) ("DOUBLE VERTICAL BAR LEFT TURNSTILE" . #x002ae3) ("VERTICAL BAR DOUBLE LEFT TURNSTILE" . #x002ae4) ("DOUBLE VERTICAL BAR DOUBLE LEFT TURNSTILE" . #x002ae5) ("LONG DASH FROM LEFT MEMBER OF DOUBLE VERTICAL" . #x002ae6) ("SHORT DOWN TACK WITH OVERBAR" . #x002ae7) ("SHORT UP TACK WITH UNDERBAR" . #x002ae8) ("SHORT UP TACK ABOVE SHORT DOWN TACK" . #x002ae9) ("DOUBLE DOWN TACK" . #x002aea) ("DOUBLE UP TACK" . #x002aeb) ("DOUBLE STROKE NOT SIGN" . #x002aec) ("REVERSED DOUBLE STROKE NOT SIGN" . #x002aed) ("DOES NOT DIVIDE WITH REVERSED NEGATION SLASH" . #x002aee) ("VERTICAL LINE WITH CIRCLE ABOVE" . #x002aef) ("VERTICAL LINE WITH CIRCLE BELOW" . #x002af0) ("DOWN TACK WITH CIRCLE BELOW" . #x002af1) ("PARALLEL WITH HORIZONTAL STROKE" . #x002af2) ("PARALLEL WITH TILDE OPERATOR" . #x002af3) ("TRIPLE VERTICAL BAR BINARY RELATION" . #x002af4) ("TRIPLE VERTICAL BAR WITH HORIZONTAL STROKE" . #x002af5) ("TRIPLE COLON OPERATOR" . #x002af6) ("TRIPLE NESTED LESS-THAN" . #x002af7) ("TRIPLE NESTED GREATER-THAN" . #x002af8) ("DOUBLE-LINE SLANTED LESS-THAN OR EQUAL TO" . #x002af9) ("DOUBLE-LINE SLANTED GREATER-THAN OR EQUAL TO" . #x002afa) ("TRIPLE SOLIDUS BINARY RELATION" . #x002afb) ("LARGE TRIPLE VERTICAL BAR OPERATOR" . #x002afc) ("DOUBLE SOLIDUS OPERATOR" . #x002afd) ("WHITE VERTICAL BAR" . #x002afe) ("N-ARY WHITE VERTICAL BAR" . #x002aff) ("IDEOGRAPHIC SPACE" . #x003000) ("IDEOGRAPHIC COMMA" . #x003001) ("IDEOGRAPHIC FULL STOP" . #x003002) ("DITTO MARK" . #x003003) ("JAPANESE INDUSTRIAL STANDARD SYMBOL" . #x003004) ("IDEOGRAPHIC ITERATION MARK" . #x003005) ("IDEOGRAPHIC CLOSING MARK" . #x003006) ("IDEOGRAPHIC NUMBER ZERO" . #x003007) ("LEFT ANGLE BRACKET" . #x003008) ("RIGHT ANGLE BRACKET" . #x003009) ("LEFT DOUBLE ANGLE BRACKET" . #x00300a) ("RIGHT DOUBLE ANGLE BRACKET" . #x00300b) ("LEFT CORNER BRACKET" . #x00300c) ("RIGHT CORNER BRACKET" . #x00300d) ("LEFT WHITE CORNER BRACKET" . #x00300e) ("RIGHT WHITE CORNER BRACKET" . #x00300f) ("LEFT BLACK LENTICULAR BRACKET" . #x003010) ("RIGHT BLACK LENTICULAR BRACKET" . #x003011) ("POSTAL MARK" . #x003012) ("GETA MARK" . #x003013) ("LEFT TORTOISE SHELL BRACKET" . #x003014) ("RIGHT TORTOISE SHELL BRACKET" . #x003015) ("LEFT WHITE LENTICULAR BRACKET" . #x003016) ("RIGHT WHITE LENTICULAR BRACKET" . #x003017) ("LEFT WHITE TORTOISE SHELL BRACKET" . #x003018) ("RIGHT WHITE TORTOISE SHELL BRACKET" . #x003019) ("LEFT WHITE SQUARE BRACKET" . #x00301a) ("RIGHT WHITE SQUARE BRACKET" . #x00301b) ("WAVE DASH" . #x00301c) ("REVERSED DOUBLE PRIME QUOTATION MARK" . #x00301d) ("DOUBLE PRIME QUOTATION MARK" . #x00301e) ("LOW DOUBLE PRIME QUOTATION MARK" . #x00301f) ("POSTAL MARK FACE" . #x003020) ("HANGZHOU NUMERAL ONE" . #x003021) ("HANGZHOU NUMERAL TWO" . #x003022) ("HANGZHOU NUMERAL THREE" . #x003023) ("HANGZHOU NUMERAL FOUR" . #x003024) ("HANGZHOU NUMERAL FIVE" . #x003025) ("HANGZHOU NUMERAL SIX" . #x003026) ("HANGZHOU NUMERAL SEVEN" . #x003027) ("HANGZHOU NUMERAL EIGHT" . #x003028) ("HANGZHOU NUMERAL NINE" . #x003029) ("IDEOGRAPHIC LEVEL TONE MARK" . #x00302a) ("IDEOGRAPHIC RISING TONE MARK" . #x00302b) ("IDEOGRAPHIC DEPARTING TONE MARK" . #x00302c) ("IDEOGRAPHIC ENTERING TONE MARK" . #x00302d) ("HANGUL SINGLE DOT TONE MARK" . #x00302e) ("HANGUL DOUBLE DOT TONE MARK" . #x00302f) ("WAVY DASH" . #x003030) ("VERTICAL KANA REPEAT MARK" . #x003031) ("VERTICAL KANA REPEAT WITH VOICED SOUND MARK" . #x003032) ("VERTICAL KANA REPEAT MARK UPPER HALF" . #x003033) ("VERTICAL KANA REPEAT WITH VOICED SOUND MARK UPPER HALF" . #x003034) ("VERTICAL KANA REPEAT MARK LOWER HALF" . #x003035) ("CIRCLED POSTAL MARK" . #x003036) ("IDEOGRAPHIC TELEGRAPH LINE FEED SEPARATOR SYMBOL" . #x003037) ("HANGZHOU NUMERAL TEN" . #x003038) ("HANGZHOU NUMERAL TWENTY" . #x003039) ("HANGZHOU NUMERAL THIRTY" . #x00303a) ("VERTICAL IDEOGRAPHIC ITERATION MARK" . #x00303b) ("MASU MARK" . #x00303c) ("PART ALTERNATION MARK" . #x00303d) ("IDEOGRAPHIC VARIATION INDICATOR" . #x00303e) ("IDEOGRAPHIC HALF FILL SPACE" . #x00303f) ("HIRAGANA LETTER SMALL A" . #x003041) ("HIRAGANA LETTER A" . #x003042) ("HIRAGANA LETTER SMALL I" . #x003043) ("HIRAGANA LETTER I" . #x003044) ("HIRAGANA LETTER SMALL U" . #x003045) ("HIRAGANA LETTER U" . #x003046) ("HIRAGANA LETTER SMALL E" . #x003047) ("HIRAGANA LETTER E" . #x003048) ("HIRAGANA LETTER SMALL O" . #x003049) ("HIRAGANA LETTER O" . #x00304a) ("HIRAGANA LETTER KA" . #x00304b) ("HIRAGANA LETTER GA" . #x00304c) ("HIRAGANA LETTER KI" . #x00304d) ("HIRAGANA LETTER GI" . #x00304e) ("HIRAGANA LETTER KU" . #x00304f) ("HIRAGANA LETTER GU" . #x003050) ("HIRAGANA LETTER KE" . #x003051) ("HIRAGANA LETTER GE" . #x003052) ("HIRAGANA LETTER KO" . #x003053) ("HIRAGANA LETTER GO" . #x003054) ("HIRAGANA LETTER SA" . #x003055) ("HIRAGANA LETTER ZA" . #x003056) ("HIRAGANA LETTER SI" . #x003057) ("HIRAGANA LETTER ZI" . #x003058) ("HIRAGANA LETTER SU" . #x003059) ("HIRAGANA LETTER ZU" . #x00305a) ("HIRAGANA LETTER SE" . #x00305b) ("HIRAGANA LETTER ZE" . #x00305c) ("HIRAGANA LETTER SO" . #x00305d) ("HIRAGANA LETTER ZO" . #x00305e) ("HIRAGANA LETTER TA" . #x00305f) ("HIRAGANA LETTER DA" . #x003060) ("HIRAGANA LETTER TI" . #x003061) ("HIRAGANA LETTER DI" . #x003062) ("HIRAGANA LETTER SMALL TU" . #x003063) ("HIRAGANA LETTER TU" . #x003064) ("HIRAGANA LETTER DU" . #x003065) ("HIRAGANA LETTER TE" . #x003066) ("HIRAGANA LETTER DE" . #x003067) ("HIRAGANA LETTER TO" . #x003068) ("HIRAGANA LETTER DO" . #x003069) ("HIRAGANA LETTER NA" . #x00306a) ("HIRAGANA LETTER NI" . #x00306b) ("HIRAGANA LETTER NU" . #x00306c) ("HIRAGANA LETTER NE" . #x00306d) ("HIRAGANA LETTER NO" . #x00306e) ("HIRAGANA LETTER HA" . #x00306f) ("HIRAGANA LETTER BA" . #x003070) ("HIRAGANA LETTER PA" . #x003071) ("HIRAGANA LETTER HI" . #x003072) ("HIRAGANA LETTER BI" . #x003073) ("HIRAGANA LETTER PI" . #x003074) ("HIRAGANA LETTER HU" . #x003075) ("HIRAGANA LETTER BU" . #x003076) ("HIRAGANA LETTER PU" . #x003077) ("HIRAGANA LETTER HE" . #x003078) ("HIRAGANA LETTER BE" . #x003079) ("HIRAGANA LETTER PE" . #x00307a) ("HIRAGANA LETTER HO" . #x00307b) ("HIRAGANA LETTER BO" . #x00307c) ("HIRAGANA LETTER PO" . #x00307d) ("HIRAGANA LETTER MA" . #x00307e) ("HIRAGANA LETTER MI" . #x00307f) ("HIRAGANA LETTER MU" . #x003080) ("HIRAGANA LETTER ME" . #x003081) ("HIRAGANA LETTER MO" . #x003082) ("HIRAGANA LETTER SMALL YA" . #x003083) ("HIRAGANA LETTER YA" . #x003084) ("HIRAGANA LETTER SMALL YU" . #x003085) ("HIRAGANA LETTER YU" . #x003086) ("HIRAGANA LETTER SMALL YO" . #x003087) ("HIRAGANA LETTER YO" . #x003088) ("HIRAGANA LETTER RA" . #x003089) ("HIRAGANA LETTER RI" . #x00308a) ("HIRAGANA LETTER RU" . #x00308b) ("HIRAGANA LETTER RE" . #x00308c) ("HIRAGANA LETTER RO" . #x00308d) ("HIRAGANA LETTER SMALL WA" . #x00308e) ("HIRAGANA LETTER WA" . #x00308f) ("HIRAGANA LETTER WI" . #x003090) ("HIRAGANA LETTER WE" . #x003091) ("HIRAGANA LETTER WO" . #x003092) ("HIRAGANA LETTER N" . #x003093) ("HIRAGANA LETTER VU" . #x003094) ("HIRAGANA LETTER SMALL KA" . #x003095) ("HIRAGANA LETTER SMALL KE" . #x003096) ("COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK" . #x003099) ("COMBINING KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK" . #x00309a) ("KATAKANA-HIRAGANA VOICED SOUND MARK" . #x00309b) ("KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK" . #x00309c) ("HIRAGANA ITERATION MARK" . #x00309d) ("HIRAGANA VOICED ITERATION MARK" . #x00309e) ("HIRAGANA DIGRAPH YORI" . #x00309f) ("KATAKANA-HIRAGANA DOUBLE HYPHEN" . #x0030a0) ("KATAKANA LETTER SMALL A" . #x0030a1) ("KATAKANA LETTER A" . #x0030a2) ("KATAKANA LETTER SMALL I" . #x0030a3) ("KATAKANA LETTER I" . #x0030a4) ("KATAKANA LETTER SMALL U" . #x0030a5) ("KATAKANA LETTER U" . #x0030a6) ("KATAKANA LETTER SMALL E" . #x0030a7) ("KATAKANA LETTER E" . #x0030a8) ("KATAKANA LETTER SMALL O" . #x0030a9) ("KATAKANA LETTER O" . #x0030aa) ("KATAKANA LETTER KA" . #x0030ab) ("KATAKANA LETTER GA" . #x0030ac) ("KATAKANA LETTER KI" . #x0030ad) ("KATAKANA LETTER GI" . #x0030ae) ("KATAKANA LETTER KU" . #x0030af) ("KATAKANA LETTER GU" . #x0030b0) ("KATAKANA LETTER KE" . #x0030b1) ("KATAKANA LETTER GE" . #x0030b2) ("KATAKANA LETTER KO" . #x0030b3) ("KATAKANA LETTER GO" . #x0030b4) ("KATAKANA LETTER SA" . #x0030b5) ("KATAKANA LETTER ZA" . #x0030b6) ("KATAKANA LETTER SI" . #x0030b7) ("KATAKANA LETTER ZI" . #x0030b8) ("KATAKANA LETTER SU" . #x0030b9) ("KATAKANA LETTER ZU" . #x0030ba) ("KATAKANA LETTER SE" . #x0030bb) ("KATAKANA LETTER ZE" . #x0030bc) ("KATAKANA LETTER SO" . #x0030bd) ("KATAKANA LETTER ZO" . #x0030be) ("KATAKANA LETTER TA" . #x0030bf) ("KATAKANA LETTER DA" . #x0030c0) ("KATAKANA LETTER TI" . #x0030c1) ("KATAKANA LETTER DI" . #x0030c2) ("KATAKANA LETTER SMALL TU" . #x0030c3) ("KATAKANA LETTER TU" . #x0030c4) ("KATAKANA LETTER DU" . #x0030c5) ("KATAKANA LETTER TE" . #x0030c6) ("KATAKANA LETTER DE" . #x0030c7) ("KATAKANA LETTER TO" . #x0030c8) ("KATAKANA LETTER DO" . #x0030c9) ("KATAKANA LETTER NA" . #x0030ca) ("KATAKANA LETTER NI" . #x0030cb) ("KATAKANA LETTER NU" . #x0030cc) ("KATAKANA LETTER NE" . #x0030cd) ("KATAKANA LETTER NO" . #x0030ce) ("KATAKANA LETTER HA" . #x0030cf) ("KATAKANA LETTER BA" . #x0030d0) ("KATAKANA LETTER PA" . #x0030d1) ("KATAKANA LETTER HI" . #x0030d2) ("KATAKANA LETTER BI" . #x0030d3) ("KATAKANA LETTER PI" . #x0030d4) ("KATAKANA LETTER HU" . #x0030d5) ("KATAKANA LETTER BU" . #x0030d6) ("KATAKANA LETTER PU" . #x0030d7) ("KATAKANA LETTER HE" . #x0030d8) ("KATAKANA LETTER BE" . #x0030d9) ("KATAKANA LETTER PE" . #x0030da) ("KATAKANA LETTER HO" . #x0030db) ("KATAKANA LETTER BO" . #x0030dc) ("KATAKANA LETTER PO" . #x0030dd) ("KATAKANA LETTER MA" . #x0030de) ("KATAKANA LETTER MI" . #x0030df) ("KATAKANA LETTER MU" . #x0030e0) ("KATAKANA LETTER ME" . #x0030e1) ("KATAKANA LETTER MO" . #x0030e2) ("KATAKANA LETTER SMALL YA" . #x0030e3) ("KATAKANA LETTER YA" . #x0030e4) ("KATAKANA LETTER SMALL YU" . #x0030e5) ("KATAKANA LETTER YU" . #x0030e6) ("KATAKANA LETTER SMALL YO" . #x0030e7) ("KATAKANA LETTER YO" . #x0030e8) ("KATAKANA LETTER RA" . #x0030e9) ("KATAKANA LETTER RI" . #x0030ea) ("KATAKANA LETTER RU" . #x0030eb) ("KATAKANA LETTER RE" . #x0030ec) ("KATAKANA LETTER RO" . #x0030ed) ("KATAKANA LETTER SMALL WA" . #x0030ee) ("KATAKANA LETTER WA" . #x0030ef) ("KATAKANA LETTER WI" . #x0030f0) ("KATAKANA LETTER WE" . #x0030f1) ("KATAKANA LETTER WO" . #x0030f2) ("KATAKANA LETTER N" . #x0030f3) ("KATAKANA LETTER VU" . #x0030f4) ("KATAKANA LETTER SMALL KA" . #x0030f5) ("KATAKANA LETTER SMALL KE" . #x0030f6) ("KATAKANA LETTER VA" . #x0030f7) ("KATAKANA LETTER VI" . #x0030f8) ("KATAKANA LETTER VE" . #x0030f9) ("KATAKANA LETTER VO" . #x0030fa) ("KATAKANA MIDDLE DOT" . #x0030fb) ("KATAKANA-HIRAGANA PROLONGED SOUND MARK" . #x0030fc) ("KATAKANA ITERATION MARK" . #x0030fd) ("KATAKANA VOICED ITERATION MARK" . #x0030fe) ("KATAKANA DIGRAPH KOTO" . #x0030ff) ("LATIN SMALL LIGATURE FF" . #x00fb00) ("LATIN SMALL LIGATURE FI" . #x00fb01) ("LATIN SMALL LIGATURE FL" . #x00fb02) ("LATIN SMALL LIGATURE FFI" . #x00fb03) ("LATIN SMALL LIGATURE FFL" . #x00fb04) ("LATIN SMALL LIGATURE LONG S T" . #x00fb05) ("LATIN SMALL LIGATURE ST" . #x00fb06) ("ARMENIAN SMALL LIGATURE MEN NOW" . #x00fb13) ("ARMENIAN SMALL LIGATURE MEN ECH" . #x00fb14) ("ARMENIAN SMALL LIGATURE MEN INI" . #x00fb15) ("ARMENIAN SMALL LIGATURE VEW NOW" . #x00fb16) ("ARMENIAN SMALL LIGATURE MEN XEH" . #x00fb17) ("HEBREW LETTER YOD WITH HIRIQ" . #x00fb1d) ("HEBREW POINT JUDEO-SPANISH VARIKA" . #x00fb1e) ("HEBREW LIGATURE YIDDISH YOD YOD PATAH" . #x00fb1f) ("HEBREW LETTER ALTERNATIVE AYIN" . #x00fb20) ("HEBREW LETTER WIDE ALEF" . #x00fb21) ("HEBREW LETTER WIDE DALET" . #x00fb22) ("HEBREW LETTER WIDE HE" . #x00fb23) ("HEBREW LETTER WIDE KAF" . #x00fb24) ("HEBREW LETTER WIDE LAMED" . #x00fb25) ("HEBREW LETTER WIDE FINAL MEM" . #x00fb26) ("HEBREW LETTER WIDE RESH" . #x00fb27) ("HEBREW LETTER WIDE TAV" . #x00fb28) ("HEBREW LETTER ALTERNATIVE PLUS SIGN" . #x00fb29) ("HEBREW LETTER SHIN WITH SHIN DOT" . #x00fb2a) ("HEBREW LETTER SHIN WITH SIN DOT" . #x00fb2b) ("HEBREW LETTER SHIN WITH DAGESH AND SHIN DOT" . #x00fb2c) ("HEBREW LETTER SHIN WITH DAGESH AND SIN DOT" . #x00fb2d) ("HEBREW LETTER ALEF WITH PATAH" . #x00fb2e) ("HEBREW LETTER ALEF WITH QAMATS" . #x00fb2f) ("HEBREW LETTER ALEF WITH MAPIQ" . #x00fb30) ("HEBREW LETTER BET WITH DAGESH" . #x00fb31) ("HEBREW LETTER GIMEL WITH DAGESH" . #x00fb32) ("HEBREW LETTER DALET WITH DAGESH" . #x00fb33) ("HEBREW LETTER HE WITH MAPIQ" . #x00fb34) ("HEBREW LETTER VAV WITH DAGESH" . #x00fb35) ("HEBREW LETTER ZAYIN WITH DAGESH" . #x00fb36) ("HEBREW LETTER TET WITH DAGESH" . #x00fb38) ("HEBREW LETTER YOD WITH DAGESH" . #x00fb39) ("HEBREW LETTER FINAL KAF WITH DAGESH" . #x00fb3a) ("HEBREW LETTER KAF WITH DAGESH" . #x00fb3b) ("HEBREW LETTER LAMED WITH DAGESH" . #x00fb3c) ("HEBREW LETTER MEM WITH DAGESH" . #x00fb3e) ("HEBREW LETTER NUN WITH DAGESH" . #x00fb40) ("HEBREW LETTER SAMEKH WITH DAGESH" . #x00fb41) ("HEBREW LETTER FINAL PE WITH DAGESH" . #x00fb43) ("HEBREW LETTER PE WITH DAGESH" . #x00fb44) ("HEBREW LETTER TSADI WITH DAGESH" . #x00fb46) ("HEBREW LETTER QOF WITH DAGESH" . #x00fb47) ("HEBREW LETTER RESH WITH DAGESH" . #x00fb48) ("HEBREW LETTER SHIN WITH DAGESH" . #x00fb49) ("HEBREW LETTER TAV WITH DAGESH" . #x00fb4a) ("HEBREW LETTER VAV WITH HOLAM" . #x00fb4b) ("HEBREW LETTER BET WITH RAFE" . #x00fb4c) ("HEBREW LETTER KAF WITH RAFE" . #x00fb4d) ("HEBREW LETTER PE WITH RAFE" . #x00fb4e) ("HEBREW LIGATURE ALEF LAMED" . #x00fb4f) ("ARABIC LETTER ALEF WASLA ISOLATED FORM" . #x00fb50) ("ARABIC LETTER ALEF WASLA FINAL FORM" . #x00fb51) ("ARABIC LETTER BEEH ISOLATED FORM" . #x00fb52) ("ARABIC LETTER BEEH FINAL FORM" . #x00fb53) ("ARABIC LETTER BEEH INITIAL FORM" . #x00fb54) ("ARABIC LETTER BEEH MEDIAL FORM" . #x00fb55) ("ARABIC LETTER PEH ISOLATED FORM" . #x00fb56) ("ARABIC LETTER PEH FINAL FORM" . #x00fb57) ("ARABIC LETTER PEH INITIAL FORM" . #x00fb58) ("ARABIC LETTER PEH MEDIAL FORM" . #x00fb59) ("ARABIC LETTER BEHEH ISOLATED FORM" . #x00fb5a) ("ARABIC LETTER BEHEH FINAL FORM" . #x00fb5b) ("ARABIC LETTER BEHEH INITIAL FORM" . #x00fb5c) ("ARABIC LETTER BEHEH MEDIAL FORM" . #x00fb5d) ("ARABIC LETTER TTEHEH ISOLATED FORM" . #x00fb5e) ("ARABIC LETTER TTEHEH FINAL FORM" . #x00fb5f) ("ARABIC LETTER TTEHEH INITIAL FORM" . #x00fb60) ("ARABIC LETTER TTEHEH MEDIAL FORM" . #x00fb61) ("ARABIC LETTER TEHEH ISOLATED FORM" . #x00fb62) ("ARABIC LETTER TEHEH FINAL FORM" . #x00fb63) ("ARABIC LETTER TEHEH INITIAL FORM" . #x00fb64) ("ARABIC LETTER TEHEH MEDIAL FORM" . #x00fb65) ("ARABIC LETTER TTEH ISOLATED FORM" . #x00fb66) ("ARABIC LETTER TTEH FINAL FORM" . #x00fb67) ("ARABIC LETTER TTEH INITIAL FORM" . #x00fb68) ("ARABIC LETTER TTEH MEDIAL FORM" . #x00fb69) ("ARABIC LETTER VEH ISOLATED FORM" . #x00fb6a) ("ARABIC LETTER VEH FINAL FORM" . #x00fb6b) ("ARABIC LETTER VEH INITIAL FORM" . #x00fb6c) ("ARABIC LETTER VEH MEDIAL FORM" . #x00fb6d) ("ARABIC LETTER PEHEH ISOLATED FORM" . #x00fb6e) ("ARABIC LETTER PEHEH FINAL FORM" . #x00fb6f) ("ARABIC LETTER PEHEH INITIAL FORM" . #x00fb70) ("ARABIC LETTER PEHEH MEDIAL FORM" . #x00fb71) ("ARABIC LETTER DYEH ISOLATED FORM" . #x00fb72) ("ARABIC LETTER DYEH FINAL FORM" . #x00fb73) ("ARABIC LETTER DYEH INITIAL FORM" . #x00fb74) ("ARABIC LETTER DYEH MEDIAL FORM" . #x00fb75) ("ARABIC LETTER NYEH ISOLATED FORM" . #x00fb76) ("ARABIC LETTER NYEH FINAL FORM" . #x00fb77) ("ARABIC LETTER NYEH INITIAL FORM" . #x00fb78) ("ARABIC LETTER NYEH MEDIAL FORM" . #x00fb79) ("ARABIC LETTER TCHEH ISOLATED FORM" . #x00fb7a) ("ARABIC LETTER TCHEH FINAL FORM" . #x00fb7b) ("ARABIC LETTER TCHEH INITIAL FORM" . #x00fb7c) ("ARABIC LETTER TCHEH MEDIAL FORM" . #x00fb7d) ("ARABIC LETTER TCHEHEH ISOLATED FORM" . #x00fb7e) ("ARABIC LETTER TCHEHEH FINAL FORM" . #x00fb7f) ("ARABIC LETTER TCHEHEH INITIAL FORM" . #x00fb80) ("ARABIC LETTER TCHEHEH MEDIAL FORM" . #x00fb81) ("ARABIC LETTER DDAHAL ISOLATED FORM" . #x00fb82) ("ARABIC LETTER DDAHAL FINAL FORM" . #x00fb83) ("ARABIC LETTER DAHAL ISOLATED FORM" . #x00fb84) ("ARABIC LETTER DAHAL FINAL FORM" . #x00fb85) ("ARABIC LETTER DUL ISOLATED FORM" . #x00fb86) ("ARABIC LETTER DUL FINAL FORM" . #x00fb87) ("ARABIC LETTER DDAL ISOLATED FORM" . #x00fb88) ("ARABIC LETTER DDAL FINAL FORM" . #x00fb89) ("ARABIC LETTER JEH ISOLATED FORM" . #x00fb8a) ("ARABIC LETTER JEH FINAL FORM" . #x00fb8b) ("ARABIC LETTER RREH ISOLATED FORM" . #x00fb8c) ("ARABIC LETTER RREH FINAL FORM" . #x00fb8d) ("ARABIC LETTER KEHEH ISOLATED FORM" . #x00fb8e) ("ARABIC LETTER KEHEH FINAL FORM" . #x00fb8f) ("ARABIC LETTER KEHEH INITIAL FORM" . #x00fb90) ("ARABIC LETTER KEHEH MEDIAL FORM" . #x00fb91) ("ARABIC LETTER GAF ISOLATED FORM" . #x00fb92) ("ARABIC LETTER GAF FINAL FORM" . #x00fb93) ("ARABIC LETTER GAF INITIAL FORM" . #x00fb94) ("ARABIC LETTER GAF MEDIAL FORM" . #x00fb95) ("ARABIC LETTER GUEH ISOLATED FORM" . #x00fb96) ("ARABIC LETTER GUEH FINAL FORM" . #x00fb97) ("ARABIC LETTER GUEH INITIAL FORM" . #x00fb98) ("ARABIC LETTER GUEH MEDIAL FORM" . #x00fb99) ("ARABIC LETTER NGOEH ISOLATED FORM" . #x00fb9a) ("ARABIC LETTER NGOEH FINAL FORM" . #x00fb9b) ("ARABIC LETTER NGOEH INITIAL FORM" . #x00fb9c) ("ARABIC LETTER NGOEH MEDIAL FORM" . #x00fb9d) ("ARABIC LETTER NOON GHUNNA ISOLATED FORM" . #x00fb9e) ("ARABIC LETTER NOON GHUNNA FINAL FORM" . #x00fb9f) ("ARABIC LETTER RNOON ISOLATED FORM" . #x00fba0) ("ARABIC LETTER RNOON FINAL FORM" . #x00fba1) ("ARABIC LETTER RNOON INITIAL FORM" . #x00fba2) ("ARABIC LETTER RNOON MEDIAL FORM" . #x00fba3) ("ARABIC LETTER HEH WITH YEH ABOVE ISOLATED FORM" . #x00fba4) ("ARABIC LETTER HEH WITH YEH ABOVE FINAL FORM" . #x00fba5) ("ARABIC LETTER HEH GOAL ISOLATED FORM" . #x00fba6) ("ARABIC LETTER HEH GOAL FINAL FORM" . #x00fba7) ("ARABIC LETTER HEH GOAL INITIAL FORM" . #x00fba8) ("ARABIC LETTER HEH GOAL MEDIAL FORM" . #x00fba9) ("ARABIC LETTER HEH DOACHASHMEE ISOLATED FORM" . #x00fbaa) ("ARABIC LETTER HEH DOACHASHMEE FINAL FORM" . #x00fbab) ("ARABIC LETTER HEH DOACHASHMEE INITIAL FORM" . #x00fbac) ("ARABIC LETTER HEH DOACHASHMEE MEDIAL FORM" . #x00fbad) ("ARABIC LETTER YEH BARREE ISOLATED FORM" . #x00fbae) ("ARABIC LETTER YEH BARREE FINAL FORM" . #x00fbaf) ("ARABIC LETTER YEH BARREE WITH HAMZA ABOVE ISOLATED FORM" . #x00fbb0) ("ARABIC LETTER YEH BARREE WITH HAMZA ABOVE FINAL FORM" . #x00fbb1) ("ARABIC LETTER NG ISOLATED FORM" . #x00fbd3) ("ARABIC LETTER NG FINAL FORM" . #x00fbd4) ("ARABIC LETTER NG INITIAL FORM" . #x00fbd5) ("ARABIC LETTER NG MEDIAL FORM" . #x00fbd6) ("ARABIC LETTER U ISOLATED FORM" . #x00fbd7) ("ARABIC LETTER U FINAL FORM" . #x00fbd8) ("ARABIC LETTER OE ISOLATED FORM" . #x00fbd9) ("ARABIC LETTER OE FINAL FORM" . #x00fbda) ("ARABIC LETTER YU ISOLATED FORM" . #x00fbdb) ("ARABIC LETTER YU FINAL FORM" . #x00fbdc) ("ARABIC LETTER U WITH HAMZA ABOVE ISOLATED FORM" . #x00fbdd) ("ARABIC LETTER VE ISOLATED FORM" . #x00fbde) ("ARABIC LETTER VE FINAL FORM" . #x00fbdf) ("ARABIC LETTER KIRGHIZ OE ISOLATED FORM" . #x00fbe0) ("ARABIC LETTER KIRGHIZ OE FINAL FORM" . #x00fbe1) ("ARABIC LETTER KIRGHIZ YU ISOLATED FORM" . #x00fbe2) ("ARABIC LETTER KIRGHIZ YU FINAL FORM" . #x00fbe3) ("ARABIC LETTER E ISOLATED FORM" . #x00fbe4) ("ARABIC LETTER E FINAL FORM" . #x00fbe5) ("ARABIC LETTER E INITIAL FORM" . #x00fbe6) ("ARABIC LETTER E MEDIAL FORM" . #x00fbe7) ("ARABIC LETTER UIGHUR KAZAKH KIRGHIZ ALEF MAKSURA INITIAL FORM" . #x00fbe8) ("ARABIC LETTER UIGHUR KAZAKH KIRGHIZ ALEF MAKSURA MEDIAL FORM" . #x00fbe9) ("ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH ALEF ISOLATED FORM" . #x00fbea) ("ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH ALEF FINAL FORM" . #x00fbeb) ("ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH AE ISOLATED FORM" . #x00fbec) ("ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH AE FINAL FORM" . #x00fbed) ("ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH WAW ISOLATED FORM" . #x00fbee) ("ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH WAW FINAL FORM" . #x00fbef) ("ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH U ISOLATED FORM" . #x00fbf0) ("ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH U FINAL FORM" . #x00fbf1) ("ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH OE ISOLATED FORM" . #x00fbf2) ("ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH OE FINAL FORM" . #x00fbf3) ("ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH YU ISOLATED FORM" . #x00fbf4) ("ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH YU FINAL FORM" . #x00fbf5) ("ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH E ISOLATED FORM" . #x00fbf6) ("ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH E FINAL FORM" . #x00fbf7) ("ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH E INITIAL FORM" . #x00fbf8) ("ARABIC LIGATURE UIGHUR KIRGHIZ YEH WITH HAMZA ABOVE WITH ALEF MAKSURA ISOLATED FORM" . #x00fbf9) ("ARABIC LIGATURE UIGHUR KIRGHIZ YEH WITH HAMZA ABOVE WITH ALEF MAKSURA FINAL FORM" . #x00fbfa) ("ARABIC LIGATURE UIGHUR KIRGHIZ YEH WITH HAMZA ABOVE WITH ALEF MAKSURA INITIAL FORM" . #x00fbfb) ("ARABIC LETTER FARSI YEH ISOLATED FORM" . #x00fbfc) ("ARABIC LETTER FARSI YEH FINAL FORM" . #x00fbfd) ("ARABIC LETTER FARSI YEH INITIAL FORM" . #x00fbfe) ("ARABIC LETTER FARSI YEH MEDIAL FORM" . #x00fbff) ("VARIATION SELECTOR-1" . #x00fe00) ("VARIATION SELECTOR-2" . #x00fe01) ("VARIATION SELECTOR-3" . #x00fe02) ("VARIATION SELECTOR-4" . #x00fe03) ("VARIATION SELECTOR-5" . #x00fe04) ("VARIATION SELECTOR-6" . #x00fe05) ("VARIATION SELECTOR-7" . #x00fe06) ("VARIATION SELECTOR-8" . #x00fe07) ("VARIATION SELECTOR-9" . #x00fe08) ("VARIATION SELECTOR-10" . #x00fe09) ("VARIATION SELECTOR-11" . #x00fe0a) ("VARIATION SELECTOR-12" . #x00fe0b) ("VARIATION SELECTOR-13" . #x00fe0c) ("VARIATION SELECTOR-14" . #x00fe0d) ("VARIATION SELECTOR-15" . #x00fe0e) ("VARIATION SELECTOR-16" . #x00fe0f) ("COMBINING LIGATURE LEFT HALF" . #x00fe20) ("COMBINING LIGATURE RIGHT HALF" . #x00fe21) ("COMBINING DOUBLE TILDE LEFT HALF" . #x00fe22) ("COMBINING DOUBLE TILDE RIGHT HALF" . #x00fe23) ("PRESENTATION FORM FOR VERTICAL TWO DOT LEADER" . #x00fe30) ("PRESENTATION FORM FOR VERTICAL EM DASH" . #x00fe31) ("PRESENTATION FORM FOR VERTICAL EN DASH" . #x00fe32) ("PRESENTATION FORM FOR VERTICAL LOW LINE" . #x00fe33) ("PRESENTATION FORM FOR VERTICAL WAVY LOW LINE" . #x00fe34) ("PRESENTATION FORM FOR VERTICAL LEFT PARENTHESIS" . #x00fe35) ("PRESENTATION FORM FOR VERTICAL RIGHT PARENTHESIS" . #x00fe36) ("PRESENTATION FORM FOR VERTICAL LEFT CURLY BRACKET" . #x00fe37) ("PRESENTATION FORM FOR VERTICAL RIGHT CURLY BRACKET" . #x00fe38) ("PRESENTATION FORM FOR VERTICAL LEFT TORTOISE SHELL BRACKET" . #x00fe39) ("PRESENTATION FORM FOR VERTICAL RIGHT TORTOISE SHELL BRACKET" . #x00fe3a) ("PRESENTATION FORM FOR VERTICAL LEFT BLACK LENTICULAR BRACKET" . #x00fe3b) ("PRESENTATION FORM FOR VERTICAL RIGHT BLACK LENTICULAR BRACKET" . #x00fe3c) ("PRESENTATION FORM FOR VERTICAL LEFT DOUBLE ANGLE BRACKET" . #x00fe3d) ("PRESENTATION FORM FOR VERTICAL RIGHT DOUBLE ANGLE BRACKET" . #x00fe3e) ("PRESENTATION FORM FOR VERTICAL LEFT ANGLE BRACKET" . #x00fe3f) ("PRESENTATION FORM FOR VERTICAL RIGHT ANGLE BRACKET" . #x00fe40) ("PRESENTATION FORM FOR VERTICAL LEFT CORNER BRACKET" . #x00fe41) ("PRESENTATION FORM FOR VERTICAL RIGHT CORNER BRACKET" . #x00fe42) ("PRESENTATION FORM FOR VERTICAL LEFT WHITE CORNER BRACKET" . #x00fe43) ("PRESENTATION FORM FOR VERTICAL RIGHT WHITE CORNER BRACKET" . #x00fe44) ("SESAME DOT" . #x00fe45) ("WHITE SESAME DOT" . #x00fe46) ("DASHED OVERLINE" . #x00fe49) ("CENTRELINE OVERLINE" . #x00fe4a) ("WAVY OVERLINE" . #x00fe4b) ("DOUBLE WAVY OVERLINE" . #x00fe4c) ("DASHED LOW LINE" . #x00fe4d) ("CENTRELINE LOW LINE" . #x00fe4e) ("WAVY LOW LINE" . #x00fe4f) ("SMALL COMMA" . #x00fe50) ("SMALL IDEOGRAPHIC COMMA" . #x00fe51) ("SMALL FULL STOP" . #x00fe52) ("SMALL SEMICOLON" . #x00fe54) ("SMALL COLON" . #x00fe55) ("SMALL QUESTION MARK" . #x00fe56) ("SMALL EXCLAMATION MARK" . #x00fe57) ("SMALL EM DASH" . #x00fe58) ("SMALL LEFT PARENTHESIS" . #x00fe59) ("SMALL RIGHT PARENTHESIS" . #x00fe5a) ("SMALL LEFT CURLY BRACKET" . #x00fe5b) ("SMALL RIGHT CURLY BRACKET" . #x00fe5c) ("SMALL LEFT TORTOISE SHELL BRACKET" . #x00fe5d) ("SMALL RIGHT TORTOISE SHELL BRACKET" . #x00fe5e) ("SMALL NUMBER SIGN" . #x00fe5f) ("SMALL AMPERSAND" . #x00fe60) ("SMALL ASTERISK" . #x00fe61) ("SMALL PLUS SIGN" . #x00fe62) ("SMALL HYPHEN-MINUS" . #x00fe63) ("SMALL LESS-THAN SIGN" . #x00fe64) ("SMALL GREATER-THAN SIGN" . #x00fe65) ("SMALL EQUALS SIGN" . #x00fe66) ("SMALL REVERSE SOLIDUS" . #x00fe68) ("SMALL DOLLAR SIGN" . #x00fe69) ("SMALL PERCENT SIGN" . #x00fe6a) ("SMALL COMMERCIAL AT" . #x00fe6b) ("ARABIC FATHATAN ISOLATED FORM" . #x00fe70) ("ARABIC TATWEEL WITH FATHATAN ABOVE" . #x00fe71) ("ARABIC DAMMATAN ISOLATED FORM" . #x00fe72) ("ARABIC TAIL FRAGMENT" . #x00fe73) ("ARABIC KASRATAN ISOLATED FORM" . #x00fe74) ("ARABIC FATHA ISOLATED FORM" . #x00fe76) ("ARABIC FATHA MEDIAL FORM" . #x00fe77) ("ARABIC DAMMA ISOLATED FORM" . #x00fe78) ("ARABIC DAMMA MEDIAL FORM" . #x00fe79) ("ARABIC KASRA ISOLATED FORM" . #x00fe7a) ("ARABIC KASRA MEDIAL FORM" . #x00fe7b) ("ARABIC SHADDA ISOLATED FORM" . #x00fe7c) ("ARABIC SHADDA MEDIAL FORM" . #x00fe7d) ("ARABIC SUKUN ISOLATED FORM" . #x00fe7e) ("ARABIC SUKUN MEDIAL FORM" . #x00fe7f) ("ARABIC LETTER HAMZA ISOLATED FORM" . #x00fe80) ("ARABIC LETTER ALEF WITH MADDA ABOVE ISOLATED FORM" . #x00fe81) ("ARABIC LETTER ALEF WITH MADDA ABOVE FINAL FORM" . #x00fe82) ("ARABIC LETTER ALEF WITH HAMZA ABOVE ISOLATED FORM" . #x00fe83) ("ARABIC LETTER ALEF WITH HAMZA ABOVE FINAL FORM" . #x00fe84) ("ARABIC LETTER WAW WITH HAMZA ABOVE ISOLATED FORM" . #x00fe85) ("ARABIC LETTER WAW WITH HAMZA ABOVE FINAL FORM" . #x00fe86) ("ARABIC LETTER ALEF WITH HAMZA BELOW ISOLATED FORM" . #x00fe87) ("ARABIC LETTER ALEF WITH HAMZA BELOW FINAL FORM" . #x00fe88) ("ARABIC LETTER YEH WITH HAMZA ABOVE ISOLATED FORM" . #x00fe89) ("ARABIC LETTER YEH WITH HAMZA ABOVE FINAL FORM" . #x00fe8a) ("ARABIC LETTER YEH WITH HAMZA ABOVE INITIAL FORM" . #x00fe8b) ("ARABIC LETTER YEH WITH HAMZA ABOVE MEDIAL FORM" . #x00fe8c) ("ARABIC LETTER ALEF ISOLATED FORM" . #x00fe8d) ("ARABIC LETTER ALEF FINAL FORM" . #x00fe8e) ("ARABIC LETTER BEH ISOLATED FORM" . #x00fe8f) ("ARABIC LETTER BEH FINAL FORM" . #x00fe90) ("ARABIC LETTER BEH INITIAL FORM" . #x00fe91) ("ARABIC LETTER BEH MEDIAL FORM" . #x00fe92) ("ARABIC LETTER TEH MARBUTA ISOLATED FORM" . #x00fe93) ("ARABIC LETTER TEH MARBUTA FINAL FORM" . #x00fe94) ("ARABIC LETTER TEH ISOLATED FORM" . #x00fe95) ("ARABIC LETTER TEH FINAL FORM" . #x00fe96) ("ARABIC LETTER TEH INITIAL FORM" . #x00fe97) ("ARABIC LETTER TEH MEDIAL FORM" . #x00fe98) ("ARABIC LETTER THEH ISOLATED FORM" . #x00fe99) ("ARABIC LETTER THEH FINAL FORM" . #x00fe9a) ("ARABIC LETTER THEH INITIAL FORM" . #x00fe9b) ("ARABIC LETTER THEH MEDIAL FORM" . #x00fe9c) ("ARABIC LETTER JEEM ISOLATED FORM" . #x00fe9d) ("ARABIC LETTER JEEM FINAL FORM" . #x00fe9e) ("ARABIC LETTER JEEM INITIAL FORM" . #x00fe9f) ("ARABIC LETTER JEEM MEDIAL FORM" . #x00fea0) ("ARABIC LETTER HAH ISOLATED FORM" . #x00fea1) ("ARABIC LETTER HAH FINAL FORM" . #x00fea2) ("ARABIC LETTER HAH INITIAL FORM" . #x00fea3) ("ARABIC LETTER HAH MEDIAL FORM" . #x00fea4) ("ARABIC LETTER KHAH ISOLATED FORM" . #x00fea5) ("ARABIC LETTER KHAH FINAL FORM" . #x00fea6) ("ARABIC LETTER KHAH INITIAL FORM" . #x00fea7) ("ARABIC LETTER KHAH MEDIAL FORM" . #x00fea8) ("ARABIC LETTER DAL ISOLATED FORM" . #x00fea9) ("ARABIC LETTER DAL FINAL FORM" . #x00feaa) ("ARABIC LETTER THAL ISOLATED FORM" . #x00feab) ("ARABIC LETTER THAL FINAL FORM" . #x00feac) ("ARABIC LETTER REH ISOLATED FORM" . #x00fead) ("ARABIC LETTER REH FINAL FORM" . #x00feae) ("ARABIC LETTER ZAIN ISOLATED FORM" . #x00feaf) ("ARABIC LETTER ZAIN FINAL FORM" . #x00feb0) ("ARABIC LETTER SEEN ISOLATED FORM" . #x00feb1) ("ARABIC LETTER SEEN FINAL FORM" . #x00feb2) ("ARABIC LETTER SEEN INITIAL FORM" . #x00feb3) ("ARABIC LETTER SEEN MEDIAL FORM" . #x00feb4) ("ARABIC LETTER SHEEN ISOLATED FORM" . #x00feb5) ("ARABIC LETTER SHEEN FINAL FORM" . #x00feb6) ("ARABIC LETTER SHEEN INITIAL FORM" . #x00feb7) ("ARABIC LETTER SHEEN MEDIAL FORM" . #x00feb8) ("ARABIC LETTER SAD ISOLATED FORM" . #x00feb9) ("ARABIC LETTER SAD FINAL FORM" . #x00feba) ("ARABIC LETTER SAD INITIAL FORM" . #x00febb) ("ARABIC LETTER SAD MEDIAL FORM" . #x00febc) ("ARABIC LETTER DAD ISOLATED FORM" . #x00febd) ("ARABIC LETTER DAD FINAL FORM" . #x00febe) ("ARABIC LETTER DAD INITIAL FORM" . #x00febf) ("ARABIC LETTER DAD MEDIAL FORM" . #x00fec0) ("ARABIC LETTER TAH ISOLATED FORM" . #x00fec1) ("ARABIC LETTER TAH FINAL FORM" . #x00fec2) ("ARABIC LETTER TAH INITIAL FORM" . #x00fec3) ("ARABIC LETTER TAH MEDIAL FORM" . #x00fec4) ("ARABIC LETTER ZAH ISOLATED FORM" . #x00fec5) ("ARABIC LETTER ZAH FINAL FORM" . #x00fec6) ("ARABIC LETTER ZAH INITIAL FORM" . #x00fec7) ("ARABIC LETTER ZAH MEDIAL FORM" . #x00fec8) ("ARABIC LETTER AIN ISOLATED FORM" . #x00fec9) ("ARABIC LETTER AIN FINAL FORM" . #x00feca) ("ARABIC LETTER AIN INITIAL FORM" . #x00fecb) ("ARABIC LETTER AIN MEDIAL FORM" . #x00fecc) ("ARABIC LETTER GHAIN ISOLATED FORM" . #x00fecd) ("ARABIC LETTER GHAIN FINAL FORM" . #x00fece) ("ARABIC LETTER GHAIN INITIAL FORM" . #x00fecf) ("ARABIC LETTER GHAIN MEDIAL FORM" . #x00fed0) ("ARABIC LETTER FEH ISOLATED FORM" . #x00fed1) ("ARABIC LETTER FEH FINAL FORM" . #x00fed2) ("ARABIC LETTER FEH INITIAL FORM" . #x00fed3) ("ARABIC LETTER FEH MEDIAL FORM" . #x00fed4) ("ARABIC LETTER QAF ISOLATED FORM" . #x00fed5) ("ARABIC LETTER QAF FINAL FORM" . #x00fed6) ("ARABIC LETTER QAF INITIAL FORM" . #x00fed7) ("ARABIC LETTER QAF MEDIAL FORM" . #x00fed8) ("ARABIC LETTER KAF ISOLATED FORM" . #x00fed9) ("ARABIC LETTER KAF FINAL FORM" . #x00feda) ("ARABIC LETTER KAF INITIAL FORM" . #x00fedb) ("ARABIC LETTER KAF MEDIAL FORM" . #x00fedc) ("ARABIC LETTER LAM ISOLATED FORM" . #x00fedd) ("ARABIC LETTER LAM FINAL FORM" . #x00fede) ("ARABIC LETTER LAM INITIAL FORM" . #x00fedf) ("ARABIC LETTER LAM MEDIAL FORM" . #x00fee0) ("ARABIC LETTER MEEM ISOLATED FORM" . #x00fee1) ("ARABIC LETTER MEEM FINAL FORM" . #x00fee2) ("ARABIC LETTER MEEM INITIAL FORM" . #x00fee3) ("ARABIC LETTER MEEM MEDIAL FORM" . #x00fee4) ("ARABIC LETTER NOON ISOLATED FORM" . #x00fee5) ("ARABIC LETTER NOON FINAL FORM" . #x00fee6) ("ARABIC LETTER NOON INITIAL FORM" . #x00fee7) ("ARABIC LETTER NOON MEDIAL FORM" . #x00fee8) ("ARABIC LETTER HEH ISOLATED FORM" . #x00fee9) ("ARABIC LETTER HEH FINAL FORM" . #x00feea) ("ARABIC LETTER HEH INITIAL FORM" . #x00feeb) ("ARABIC LETTER HEH MEDIAL FORM" . #x00feec) ("ARABIC LETTER WAW ISOLATED FORM" . #x00feed) ("ARABIC LETTER WAW FINAL FORM" . #x00feee) ("ARABIC LETTER ALEF MAKSURA ISOLATED FORM" . #x00feef) ("ARABIC LETTER ALEF MAKSURA FINAL FORM" . #x00fef0) ("ARABIC LETTER YEH ISOLATED FORM" . #x00fef1) ("ARABIC LETTER YEH FINAL FORM" . #x00fef2) ("ARABIC LETTER YEH INITIAL FORM" . #x00fef3) ("ARABIC LETTER YEH MEDIAL FORM" . #x00fef4) ("ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE ISOLATED FORM" . #x00fef5) ("ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE FINAL FORM" . #x00fef6) ("ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE ISOLATED FORM" . #x00fef7) ("ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE FINAL FORM" . #x00fef8) ("ARABIC LIGATURE LAM WITH ALEF WITH HAMZA BELOW ISOLATED FORM" . #x00fef9) ("ARABIC LIGATURE LAM WITH ALEF WITH HAMZA BELOW FINAL FORM" . #x00fefa) ("ARABIC LIGATURE LAM WITH ALEF ISOLATED FORM" . #x00fefb) ("ARABIC LIGATURE LAM WITH ALEF FINAL FORM" . #x00fefc) ("ZERO WIDTH NO-BREAK SPACE" . #x00feff) ("REPLACEMENT CHARACTER" . #x00fffd) ("MATHEMATICAL BOLD CAPITAL A" . #x01d400) ("MATHEMATICAL BOLD CAPITAL B" . #x01d401) ("MATHEMATICAL BOLD CAPITAL C" . #x01d402) ("MATHEMATICAL BOLD CAPITAL D" . #x01d403) ("MATHEMATICAL BOLD CAPITAL E" . #x01d404) ("MATHEMATICAL BOLD CAPITAL F" . #x01d405) ("MATHEMATICAL BOLD CAPITAL G" . #x01d406) ("MATHEMATICAL BOLD CAPITAL H" . #x01d407) ("MATHEMATICAL BOLD CAPITAL I" . #x01d408) ("MATHEMATICAL BOLD CAPITAL J" . #x01d409) ("MATHEMATICAL BOLD CAPITAL K" . #x01d40a) ("MATHEMATICAL BOLD CAPITAL L" . #x01d40b) ("MATHEMATICAL BOLD CAPITAL M" . #x01d40c) ("MATHEMATICAL BOLD CAPITAL N" . #x01d40d) ("MATHEMATICAL BOLD CAPITAL O" . #x01d40e) ("MATHEMATICAL BOLD CAPITAL P" . #x01d40f) ("MATHEMATICAL BOLD CAPITAL Q" . #x01d410) ("MATHEMATICAL BOLD CAPITAL R" . #x01d411) ("MATHEMATICAL BOLD CAPITAL S" . #x01d412) ("MATHEMATICAL BOLD CAPITAL T" . #x01d413) ("MATHEMATICAL BOLD CAPITAL U" . #x01d414) ("MATHEMATICAL BOLD CAPITAL V" . #x01d415) ("MATHEMATICAL BOLD CAPITAL W" . #x01d416) ("MATHEMATICAL BOLD CAPITAL X" . #x01d417) ("MATHEMATICAL BOLD CAPITAL Y" . #x01d418) ("MATHEMATICAL BOLD CAPITAL Z" . #x01d419) ("MATHEMATICAL BOLD SMALL A" . #x01d41a) ("MATHEMATICAL BOLD SMALL B" . #x01d41b) ("MATHEMATICAL BOLD SMALL C" . #x01d41c) ("MATHEMATICAL BOLD SMALL D" . #x01d41d) ("MATHEMATICAL BOLD SMALL E" . #x01d41e) ("MATHEMATICAL BOLD SMALL F" . #x01d41f) ("MATHEMATICAL BOLD SMALL G" . #x01d420) ("MATHEMATICAL BOLD SMALL H" . #x01d421) ("MATHEMATICAL BOLD SMALL I" . #x01d422) ("MATHEMATICAL BOLD SMALL J" . #x01d423) ("MATHEMATICAL BOLD SMALL K" . #x01d424) ("MATHEMATICAL BOLD SMALL L" . #x01d425) ("MATHEMATICAL BOLD SMALL M" . #x01d426) ("MATHEMATICAL BOLD SMALL N" . #x01d427) ("MATHEMATICAL BOLD SMALL O" . #x01d428) ("MATHEMATICAL BOLD SMALL P" . #x01d429) ("MATHEMATICAL BOLD SMALL Q" . #x01d42a) ("MATHEMATICAL BOLD SMALL R" . #x01d42b) ("MATHEMATICAL BOLD SMALL S" . #x01d42c) ("MATHEMATICAL BOLD SMALL T" . #x01d42d) ("MATHEMATICAL BOLD SMALL U" . #x01d42e) ("MATHEMATICAL BOLD SMALL V" . #x01d42f) ("MATHEMATICAL BOLD SMALL W" . #x01d430) ("MATHEMATICAL BOLD SMALL X" . #x01d431) ("MATHEMATICAL BOLD SMALL Y" . #x01d432) ("MATHEMATICAL BOLD SMALL Z" . #x01d433) ("MATHEMATICAL ITALIC CAPITAL A" . #x01d434) ("MATHEMATICAL ITALIC CAPITAL B" . #x01d435) ("MATHEMATICAL ITALIC CAPITAL C" . #x01d436) ("MATHEMATICAL ITALIC CAPITAL D" . #x01d437) ("MATHEMATICAL ITALIC CAPITAL E" . #x01d438) ("MATHEMATICAL ITALIC CAPITAL F" . #x01d439) ("MATHEMATICAL ITALIC CAPITAL G" . #x01d43a) ("MATHEMATICAL ITALIC CAPITAL H" . #x01d43b) ("MATHEMATICAL ITALIC CAPITAL I" . #x01d43c) ("MATHEMATICAL ITALIC CAPITAL J" . #x01d43d) ("MATHEMATICAL ITALIC CAPITAL K" . #x01d43e) ("MATHEMATICAL ITALIC CAPITAL L" . #x01d43f) ("MATHEMATICAL ITALIC CAPITAL M" . #x01d440) ("MATHEMATICAL ITALIC CAPITAL N" . #x01d441) ("MATHEMATICAL ITALIC CAPITAL O" . #x01d442) ("MATHEMATICAL ITALIC CAPITAL P" . #x01d443) ("MATHEMATICAL ITALIC CAPITAL Q" . #x01d444) ("MATHEMATICAL ITALIC CAPITAL R" . #x01d445) ("MATHEMATICAL ITALIC CAPITAL S" . #x01d446) ("MATHEMATICAL ITALIC CAPITAL T" . #x01d447) ("MATHEMATICAL ITALIC CAPITAL U" . #x01d448) ("MATHEMATICAL ITALIC CAPITAL V" . #x01d449) ("MATHEMATICAL ITALIC CAPITAL W" . #x01d44a) ("MATHEMATICAL ITALIC CAPITAL X" . #x01d44b) ("MATHEMATICAL ITALIC CAPITAL Y" . #x01d44c) ("MATHEMATICAL ITALIC CAPITAL Z" . #x01d44d) ("MATHEMATICAL ITALIC SMALL A" . #x01d44e) ("MATHEMATICAL ITALIC SMALL B" . #x01d44f) ("MATHEMATICAL ITALIC SMALL C" . #x01d450) ("MATHEMATICAL ITALIC SMALL D" . #x01d451) ("MATHEMATICAL ITALIC SMALL E" . #x01d452) ("MATHEMATICAL ITALIC SMALL F" . #x01d453) ("MATHEMATICAL ITALIC SMALL G" . #x01d454) ("MATHEMATICAL ITALIC SMALL I" . #x01d456) ("MATHEMATICAL ITALIC SMALL J" . #x01d457) ("MATHEMATICAL ITALIC SMALL K" . #x01d458) ("MATHEMATICAL ITALIC SMALL L" . #x01d459) ("MATHEMATICAL ITALIC SMALL M" . #x01d45a) ("MATHEMATICAL ITALIC SMALL N" . #x01d45b) ("MATHEMATICAL ITALIC SMALL O" . #x01d45c) ("MATHEMATICAL ITALIC SMALL P" . #x01d45d) ("MATHEMATICAL ITALIC SMALL Q" . #x01d45e) ("MATHEMATICAL ITALIC SMALL R" . #x01d45f) ("MATHEMATICAL ITALIC SMALL S" . #x01d460) ("MATHEMATICAL ITALIC SMALL T" . #x01d461) ("MATHEMATICAL ITALIC SMALL U" . #x01d462) ("MATHEMATICAL ITALIC SMALL V" . #x01d463) ("MATHEMATICAL ITALIC SMALL W" . #x01d464) ("MATHEMATICAL ITALIC SMALL X" . #x01d465) ("MATHEMATICAL ITALIC SMALL Y" . #x01d466) ("MATHEMATICAL ITALIC SMALL Z" . #x01d467) ("MATHEMATICAL BOLD ITALIC CAPITAL A" . #x01d468) ("MATHEMATICAL BOLD ITALIC CAPITAL B" . #x01d469) ("MATHEMATICAL BOLD ITALIC CAPITAL C" . #x01d46a) ("MATHEMATICAL BOLD ITALIC CAPITAL D" . #x01d46b) ("MATHEMATICAL BOLD ITALIC CAPITAL E" . #x01d46c) ("MATHEMATICAL BOLD ITALIC CAPITAL F" . #x01d46d) ("MATHEMATICAL BOLD ITALIC CAPITAL G" . #x01d46e) ("MATHEMATICAL BOLD ITALIC CAPITAL H" . #x01d46f) ("MATHEMATICAL BOLD ITALIC CAPITAL I" . #x01d470) ("MATHEMATICAL BOLD ITALIC CAPITAL J" . #x01d471) ("MATHEMATICAL BOLD ITALIC CAPITAL K" . #x01d472) ("MATHEMATICAL BOLD ITALIC CAPITAL L" . #x01d473) ("MATHEMATICAL BOLD ITALIC CAPITAL M" . #x01d474) ("MATHEMATICAL BOLD ITALIC CAPITAL N" . #x01d475) ("MATHEMATICAL BOLD ITALIC CAPITAL O" . #x01d476) ("MATHEMATICAL BOLD ITALIC CAPITAL P" . #x01d477) ("MATHEMATICAL BOLD ITALIC CAPITAL Q" . #x01d478) ("MATHEMATICAL BOLD ITALIC CAPITAL R" . #x01d479) ("MATHEMATICAL BOLD ITALIC CAPITAL S" . #x01d47a) ("MATHEMATICAL BOLD ITALIC CAPITAL T" . #x01d47b) ("MATHEMATICAL BOLD ITALIC CAPITAL U" . #x01d47c) ("MATHEMATICAL BOLD ITALIC CAPITAL V" . #x01d47d) ("MATHEMATICAL BOLD ITALIC CAPITAL W" . #x01d47e) ("MATHEMATICAL BOLD ITALIC CAPITAL X" . #x01d47f) ("MATHEMATICAL BOLD ITALIC CAPITAL Y" . #x01d480) ("MATHEMATICAL BOLD ITALIC CAPITAL Z" . #x01d481) ("MATHEMATICAL BOLD ITALIC SMALL A" . #x01d482) ("MATHEMATICAL BOLD ITALIC SMALL B" . #x01d483) ("MATHEMATICAL BOLD ITALIC SMALL C" . #x01d484) ("MATHEMATICAL BOLD ITALIC SMALL D" . #x01d485) ("MATHEMATICAL BOLD ITALIC SMALL E" . #x01d486) ("MATHEMATICAL BOLD ITALIC SMALL F" . #x01d487) ("MATHEMATICAL BOLD ITALIC SMALL G" . #x01d488) ("MATHEMATICAL BOLD ITALIC SMALL H" . #x01d489) ("MATHEMATICAL BOLD ITALIC SMALL I" . #x01d48a) ("MATHEMATICAL BOLD ITALIC SMALL J" . #x01d48b) ("MATHEMATICAL BOLD ITALIC SMALL K" . #x01d48c) ("MATHEMATICAL BOLD ITALIC SMALL L" . #x01d48d) ("MATHEMATICAL BOLD ITALIC SMALL M" . #x01d48e) ("MATHEMATICAL BOLD ITALIC SMALL N" . #x01d48f) ("MATHEMATICAL BOLD ITALIC SMALL O" . #x01d490) ("MATHEMATICAL BOLD ITALIC SMALL P" . #x01d491) ("MATHEMATICAL BOLD ITALIC SMALL Q" . #x01d492) ("MATHEMATICAL BOLD ITALIC SMALL R" . #x01d493) ("MATHEMATICAL BOLD ITALIC SMALL S" . #x01d494) ("MATHEMATICAL BOLD ITALIC SMALL T" . #x01d495) ("MATHEMATICAL BOLD ITALIC SMALL U" . #x01d496) ("MATHEMATICAL BOLD ITALIC SMALL V" . #x01d497) ("MATHEMATICAL BOLD ITALIC SMALL W" . #x01d498) ("MATHEMATICAL BOLD ITALIC SMALL X" . #x01d499) ("MATHEMATICAL BOLD ITALIC SMALL Y" . #x01d49a) ("MATHEMATICAL BOLD ITALIC SMALL Z" . #x01d49b) ("MATHEMATICAL SCRIPT CAPITAL A" . #x01d49c) ("MATHEMATICAL SCRIPT CAPITAL C" . #x01d49e) ("MATHEMATICAL SCRIPT CAPITAL D" . #x01d49f) ("MATHEMATICAL SCRIPT CAPITAL G" . #x01d4a2) ("MATHEMATICAL SCRIPT CAPITAL J" . #x01d4a5) ("MATHEMATICAL SCRIPT CAPITAL K" . #x01d4a6) ("MATHEMATICAL SCRIPT CAPITAL N" . #x01d4a9) ("MATHEMATICAL SCRIPT CAPITAL O" . #x01d4aa) ("MATHEMATICAL SCRIPT CAPITAL P" . #x01d4ab) ("MATHEMATICAL SCRIPT CAPITAL Q" . #x01d4ac) ("MATHEMATICAL SCRIPT CAPITAL S" . #x01d4ae) ("MATHEMATICAL SCRIPT CAPITAL T" . #x01d4af) ("MATHEMATICAL SCRIPT CAPITAL U" . #x01d4b0) ("MATHEMATICAL SCRIPT CAPITAL V" . #x01d4b1) ("MATHEMATICAL SCRIPT CAPITAL W" . #x01d4b2) ("MATHEMATICAL SCRIPT CAPITAL X" . #x01d4b3) ("MATHEMATICAL SCRIPT CAPITAL Y" . #x01d4b4) ("MATHEMATICAL SCRIPT CAPITAL Z" . #x01d4b5) ("MATHEMATICAL SCRIPT SMALL A" . #x01d4b6) ("MATHEMATICAL SCRIPT SMALL B" . #x01d4b7) ("MATHEMATICAL SCRIPT SMALL C" . #x01d4b8) ("MATHEMATICAL SCRIPT SMALL D" . #x01d4b9) ("MATHEMATICAL SCRIPT SMALL F" . #x01d4bb) ("MATHEMATICAL SCRIPT SMALL H" . #x01d4bd) ("MATHEMATICAL SCRIPT SMALL I" . #x01d4be) ("MATHEMATICAL SCRIPT SMALL J" . #x01d4bf) ("MATHEMATICAL SCRIPT SMALL K" . #x01d4c0) ("MATHEMATICAL SCRIPT SMALL L" . #x01d4c1) ("MATHEMATICAL SCRIPT SMALL M" . #x01d4c2) ("MATHEMATICAL SCRIPT SMALL N" . #x01d4c3) ("MATHEMATICAL SCRIPT SMALL P" . #x01d4c5) ("MATHEMATICAL SCRIPT SMALL Q" . #x01d4c6) ("MATHEMATICAL SCRIPT SMALL R" . #x01d4c7) ("MATHEMATICAL SCRIPT SMALL S" . #x01d4c8) ("MATHEMATICAL SCRIPT SMALL T" . #x01d4c9) ("MATHEMATICAL SCRIPT SMALL U" . #x01d4ca) ("MATHEMATICAL SCRIPT SMALL V" . #x01d4cb) ("MATHEMATICAL SCRIPT SMALL W" . #x01d4cc) ("MATHEMATICAL SCRIPT SMALL X" . #x01d4cd) ("MATHEMATICAL SCRIPT SMALL Y" . #x01d4ce) ("MATHEMATICAL SCRIPT SMALL Z" . #x01d4cf) ("MATHEMATICAL BOLD SCRIPT CAPITAL A" . #x01d4d0) ("MATHEMATICAL BOLD SCRIPT CAPITAL B" . #x01d4d1) ("MATHEMATICAL BOLD SCRIPT CAPITAL C" . #x01d4d2) ("MATHEMATICAL BOLD SCRIPT CAPITAL D" . #x01d4d3) ("MATHEMATICAL BOLD SCRIPT CAPITAL E" . #x01d4d4) ("MATHEMATICAL BOLD SCRIPT CAPITAL F" . #x01d4d5) ("MATHEMATICAL BOLD SCRIPT CAPITAL G" . #x01d4d6) ("MATHEMATICAL BOLD SCRIPT CAPITAL H" . #x01d4d7) ("MATHEMATICAL BOLD SCRIPT CAPITAL I" . #x01d4d8) ("MATHEMATICAL BOLD SCRIPT CAPITAL J" . #x01d4d9) ("MATHEMATICAL BOLD SCRIPT CAPITAL K" . #x01d4da) ("MATHEMATICAL BOLD SCRIPT CAPITAL L" . #x01d4db) ("MATHEMATICAL BOLD SCRIPT CAPITAL M" . #x01d4dc) ("MATHEMATICAL BOLD SCRIPT CAPITAL N" . #x01d4dd) ("MATHEMATICAL BOLD SCRIPT CAPITAL O" . #x01d4de) ("MATHEMATICAL BOLD SCRIPT CAPITAL P" . #x01d4df) ("MATHEMATICAL BOLD SCRIPT CAPITAL Q" . #x01d4e0) ("MATHEMATICAL BOLD SCRIPT CAPITAL R" . #x01d4e1) ("MATHEMATICAL BOLD SCRIPT CAPITAL S" . #x01d4e2) ("MATHEMATICAL BOLD SCRIPT CAPITAL T" . #x01d4e3) ("MATHEMATICAL BOLD SCRIPT CAPITAL U" . #x01d4e4) ("MATHEMATICAL BOLD SCRIPT CAPITAL V" . #x01d4e5) ("MATHEMATICAL BOLD SCRIPT CAPITAL W" . #x01d4e6) ("MATHEMATICAL BOLD SCRIPT CAPITAL X" . #x01d4e7) ("MATHEMATICAL BOLD SCRIPT CAPITAL Y" . #x01d4e8) ("MATHEMATICAL BOLD SCRIPT CAPITAL Z" . #x01d4e9) ("MATHEMATICAL BOLD SCRIPT SMALL A" . #x01d4ea) ("MATHEMATICAL BOLD SCRIPT SMALL B" . #x01d4eb) ("MATHEMATICAL BOLD SCRIPT SMALL C" . #x01d4ec) ("MATHEMATICAL BOLD SCRIPT SMALL D" . #x01d4ed) ("MATHEMATICAL BOLD SCRIPT SMALL E" . #x01d4ee) ("MATHEMATICAL BOLD SCRIPT SMALL F" . #x01d4ef) ("MATHEMATICAL BOLD SCRIPT SMALL G" . #x01d4f0) ("MATHEMATICAL BOLD SCRIPT SMALL H" . #x01d4f1) ("MATHEMATICAL BOLD SCRIPT SMALL I" . #x01d4f2) ("MATHEMATICAL BOLD SCRIPT SMALL J" . #x01d4f3) ("MATHEMATICAL BOLD SCRIPT SMALL K" . #x01d4f4) ("MATHEMATICAL BOLD SCRIPT SMALL L" . #x01d4f5) ("MATHEMATICAL BOLD SCRIPT SMALL M" . #x01d4f6) ("MATHEMATICAL BOLD SCRIPT SMALL N" . #x01d4f7) ("MATHEMATICAL BOLD SCRIPT SMALL O" . #x01d4f8) ("MATHEMATICAL BOLD SCRIPT SMALL P" . #x01d4f9) ("MATHEMATICAL BOLD SCRIPT SMALL Q" . #x01d4fa) ("MATHEMATICAL BOLD SCRIPT SMALL R" . #x01d4fb) ("MATHEMATICAL BOLD SCRIPT SMALL S" . #x01d4fc) ("MATHEMATICAL BOLD SCRIPT SMALL T" . #x01d4fd) ("MATHEMATICAL BOLD SCRIPT SMALL U" . #x01d4fe) ("MATHEMATICAL BOLD SCRIPT SMALL V" . #x01d4ff) ("MATHEMATICAL BOLD SCRIPT SMALL W" . #x01d500) ("MATHEMATICAL BOLD SCRIPT SMALL X" . #x01d501) ("MATHEMATICAL BOLD SCRIPT SMALL Y" . #x01d502) ("MATHEMATICAL BOLD SCRIPT SMALL Z" . #x01d503) ("MATHEMATICAL FRAKTUR CAPITAL A" . #x01d504) ("MATHEMATICAL FRAKTUR CAPITAL B" . #x01d505) ("MATHEMATICAL FRAKTUR CAPITAL D" . #x01d507) ("MATHEMATICAL FRAKTUR CAPITAL E" . #x01d508) ("MATHEMATICAL FRAKTUR CAPITAL F" . #x01d509) ("MATHEMATICAL FRAKTUR CAPITAL G" . #x01d50a) ("MATHEMATICAL FRAKTUR CAPITAL J" . #x01d50d) ("MATHEMATICAL FRAKTUR CAPITAL K" . #x01d50e) ("MATHEMATICAL FRAKTUR CAPITAL L" . #x01d50f) ("MATHEMATICAL FRAKTUR CAPITAL M" . #x01d510) ("MATHEMATICAL FRAKTUR CAPITAL N" . #x01d511) ("MATHEMATICAL FRAKTUR CAPITAL O" . #x01d512) ("MATHEMATICAL FRAKTUR CAPITAL P" . #x01d513) ("MATHEMATICAL FRAKTUR CAPITAL Q" . #x01d514) ("MATHEMATICAL FRAKTUR CAPITAL S" . #x01d516) ("MATHEMATICAL FRAKTUR CAPITAL T" . #x01d517) ("MATHEMATICAL FRAKTUR CAPITAL U" . #x01d518) ("MATHEMATICAL FRAKTUR CAPITAL V" . #x01d519) ("MATHEMATICAL FRAKTUR CAPITAL W" . #x01d51a) ("MATHEMATICAL FRAKTUR CAPITAL X" . #x01d51b) ("MATHEMATICAL FRAKTUR CAPITAL Y" . #x01d51c) ("MATHEMATICAL FRAKTUR SMALL A" . #x01d51e) ("MATHEMATICAL FRAKTUR SMALL B" . #x01d51f) ("MATHEMATICAL FRAKTUR SMALL C" . #x01d520) ("MATHEMATICAL FRAKTUR SMALL D" . #x01d521) ("MATHEMATICAL FRAKTUR SMALL E" . #x01d522) ("MATHEMATICAL FRAKTUR SMALL F" . #x01d523) ("MATHEMATICAL FRAKTUR SMALL G" . #x01d524) ("MATHEMATICAL FRAKTUR SMALL H" . #x01d525) ("MATHEMATICAL FRAKTUR SMALL I" . #x01d526) ("MATHEMATICAL FRAKTUR SMALL J" . #x01d527) ("MATHEMATICAL FRAKTUR SMALL K" . #x01d528) ("MATHEMATICAL FRAKTUR SMALL L" . #x01d529) ("MATHEMATICAL FRAKTUR SMALL M" . #x01d52a) ("MATHEMATICAL FRAKTUR SMALL N" . #x01d52b) ("MATHEMATICAL FRAKTUR SMALL O" . #x01d52c) ("MATHEMATICAL FRAKTUR SMALL P" . #x01d52d) ("MATHEMATICAL FRAKTUR SMALL Q" . #x01d52e) ("MATHEMATICAL FRAKTUR SMALL R" . #x01d52f) ("MATHEMATICAL FRAKTUR SMALL S" . #x01d530) ("MATHEMATICAL FRAKTUR SMALL T" . #x01d531) ("MATHEMATICAL FRAKTUR SMALL U" . #x01d532) ("MATHEMATICAL FRAKTUR SMALL V" . #x01d533) ("MATHEMATICAL FRAKTUR SMALL W" . #x01d534) ("MATHEMATICAL FRAKTUR SMALL X" . #x01d535) ("MATHEMATICAL FRAKTUR SMALL Y" . #x01d536) ("MATHEMATICAL FRAKTUR SMALL Z" . #x01d537) ("MATHEMATICAL DOUBLE-STRUCK CAPITAL A" . #x01d538) ("MATHEMATICAL DOUBLE-STRUCK CAPITAL B" . #x01d539) ("MATHEMATICAL DOUBLE-STRUCK CAPITAL D" . #x01d53b) ("MATHEMATICAL DOUBLE-STRUCK CAPITAL E" . #x01d53c) ("MATHEMATICAL DOUBLE-STRUCK CAPITAL F" . #x01d53d) ("MATHEMATICAL DOUBLE-STRUCK CAPITAL G" . #x01d53e) ("MATHEMATICAL DOUBLE-STRUCK CAPITAL I" . #x01d540) ("MATHEMATICAL DOUBLE-STRUCK CAPITAL J" . #x01d541) ("MATHEMATICAL DOUBLE-STRUCK CAPITAL K" . #x01d542) ("MATHEMATICAL DOUBLE-STRUCK CAPITAL L" . #x01d543) ("MATHEMATICAL DOUBLE-STRUCK CAPITAL M" . #x01d544) ("MATHEMATICAL DOUBLE-STRUCK CAPITAL O" . #x01d546) ("MATHEMATICAL DOUBLE-STRUCK CAPITAL S" . #x01d54a) ("MATHEMATICAL DOUBLE-STRUCK CAPITAL T" . #x01d54b) ("MATHEMATICAL DOUBLE-STRUCK CAPITAL U" . #x01d54c) ("MATHEMATICAL DOUBLE-STRUCK CAPITAL V" . #x01d54d) ("MATHEMATICAL DOUBLE-STRUCK CAPITAL W" . #x01d54e) ("MATHEMATICAL DOUBLE-STRUCK CAPITAL X" . #x01d54f) ("MATHEMATICAL DOUBLE-STRUCK CAPITAL Y" . #x01d550) ("MATHEMATICAL DOUBLE-STRUCK SMALL A" . #x01d552) ("MATHEMATICAL DOUBLE-STRUCK SMALL B" . #x01d553) ("MATHEMATICAL DOUBLE-STRUCK SMALL C" . #x01d554) ("MATHEMATICAL DOUBLE-STRUCK SMALL D" . #x01d555) ("MATHEMATICAL DOUBLE-STRUCK SMALL E" . #x01d556) ("MATHEMATICAL DOUBLE-STRUCK SMALL F" . #x01d557) ("MATHEMATICAL DOUBLE-STRUCK SMALL G" . #x01d558) ("MATHEMATICAL DOUBLE-STRUCK SMALL H" . #x01d559) ("MATHEMATICAL DOUBLE-STRUCK SMALL I" . #x01d55a) ("MATHEMATICAL DOUBLE-STRUCK SMALL J" . #x01d55b) ("MATHEMATICAL DOUBLE-STRUCK SMALL K" . #x01d55c) ("MATHEMATICAL DOUBLE-STRUCK SMALL L" . #x01d55d) ("MATHEMATICAL DOUBLE-STRUCK SMALL M" . #x01d55e) ("MATHEMATICAL DOUBLE-STRUCK SMALL N" . #x01d55f) ("MATHEMATICAL DOUBLE-STRUCK SMALL O" . #x01d560) ("MATHEMATICAL DOUBLE-STRUCK SMALL P" . #x01d561) ("MATHEMATICAL DOUBLE-STRUCK SMALL Q" . #x01d562) ("MATHEMATICAL DOUBLE-STRUCK SMALL R" . #x01d563) ("MATHEMATICAL DOUBLE-STRUCK SMALL S" . #x01d564) ("MATHEMATICAL DOUBLE-STRUCK SMALL T" . #x01d565) ("MATHEMATICAL DOUBLE-STRUCK SMALL U" . #x01d566) ("MATHEMATICAL DOUBLE-STRUCK SMALL V" . #x01d567) ("MATHEMATICAL DOUBLE-STRUCK SMALL W" . #x01d568) ("MATHEMATICAL DOUBLE-STRUCK SMALL X" . #x01d569) ("MATHEMATICAL DOUBLE-STRUCK SMALL Y" . #x01d56a) ("MATHEMATICAL DOUBLE-STRUCK SMALL Z" . #x01d56b) ("MATHEMATICAL BOLD FRAKTUR CAPITAL A" . #x01d56c) ("MATHEMATICAL BOLD FRAKTUR CAPITAL B" . #x01d56d) ("MATHEMATICAL BOLD FRAKTUR CAPITAL C" . #x01d56e) ("MATHEMATICAL BOLD FRAKTUR CAPITAL D" . #x01d56f) ("MATHEMATICAL BOLD FRAKTUR CAPITAL E" . #x01d570) ("MATHEMATICAL BOLD FRAKTUR CAPITAL F" . #x01d571) ("MATHEMATICAL BOLD FRAKTUR CAPITAL G" . #x01d572) ("MATHEMATICAL BOLD FRAKTUR CAPITAL H" . #x01d573) ("MATHEMATICAL BOLD FRAKTUR CAPITAL I" . #x01d574) ("MATHEMATICAL BOLD FRAKTUR CAPITAL J" . #x01d575) ("MATHEMATICAL BOLD FRAKTUR CAPITAL K" . #x01d576) ("MATHEMATICAL BOLD FRAKTUR CAPITAL L" . #x01d577) ("MATHEMATICAL BOLD FRAKTUR CAPITAL M" . #x01d578) ("MATHEMATICAL BOLD FRAKTUR CAPITAL N" . #x01d579) ("MATHEMATICAL BOLD FRAKTUR CAPITAL O" . #x01d57a) ("MATHEMATICAL BOLD FRAKTUR CAPITAL P" . #x01d57b) ("MATHEMATICAL BOLD FRAKTUR CAPITAL Q" . #x01d57c) ("MATHEMATICAL BOLD FRAKTUR CAPITAL R" . #x01d57d) ("MATHEMATICAL BOLD FRAKTUR CAPITAL S" . #x01d57e) ("MATHEMATICAL BOLD FRAKTUR CAPITAL T" . #x01d57f) ("MATHEMATICAL BOLD FRAKTUR CAPITAL U" . #x01d580) ("MATHEMATICAL BOLD FRAKTUR CAPITAL V" . #x01d581) ("MATHEMATICAL BOLD FRAKTUR CAPITAL W" . #x01d582) ("MATHEMATICAL BOLD FRAKTUR CAPITAL X" . #x01d583) ("MATHEMATICAL BOLD FRAKTUR CAPITAL Y" . #x01d584) ("MATHEMATICAL BOLD FRAKTUR CAPITAL Z" . #x01d585) ("MATHEMATICAL BOLD FRAKTUR SMALL A" . #x01d586) ("MATHEMATICAL BOLD FRAKTUR SMALL B" . #x01d587) ("MATHEMATICAL BOLD FRAKTUR SMALL C" . #x01d588) ("MATHEMATICAL BOLD FRAKTUR SMALL D" . #x01d589) ("MATHEMATICAL BOLD FRAKTUR SMALL E" . #x01d58a) ("MATHEMATICAL BOLD FRAKTUR SMALL F" . #x01d58b) ("MATHEMATICAL BOLD FRAKTUR SMALL G" . #x01d58c) ("MATHEMATICAL BOLD FRAKTUR SMALL H" . #x01d58d) ("MATHEMATICAL BOLD FRAKTUR SMALL I" . #x01d58e) ("MATHEMATICAL BOLD FRAKTUR SMALL J" . #x01d58f) ("MATHEMATICAL BOLD FRAKTUR SMALL K" . #x01d590) ("MATHEMATICAL BOLD FRAKTUR SMALL L" . #x01d591) ("MATHEMATICAL BOLD FRAKTUR SMALL M" . #x01d592) ("MATHEMATICAL BOLD FRAKTUR SMALL N" . #x01d593) ("MATHEMATICAL BOLD FRAKTUR SMALL O" . #x01d594) ("MATHEMATICAL BOLD FRAKTUR SMALL P" . #x01d595) ("MATHEMATICAL BOLD FRAKTUR SMALL Q" . #x01d596) ("MATHEMATICAL BOLD FRAKTUR SMALL R" . #x01d597) ("MATHEMATICAL BOLD FRAKTUR SMALL S" . #x01d598) ("MATHEMATICAL BOLD FRAKTUR SMALL T" . #x01d599) ("MATHEMATICAL BOLD FRAKTUR SMALL U" . #x01d59a) ("MATHEMATICAL BOLD FRAKTUR SMALL V" . #x01d59b) ("MATHEMATICAL BOLD FRAKTUR SMALL W" . #x01d59c) ("MATHEMATICAL BOLD FRAKTUR SMALL X" . #x01d59d) ("MATHEMATICAL BOLD FRAKTUR SMALL Y" . #x01d59e) ("MATHEMATICAL BOLD FRAKTUR SMALL Z" . #x01d59f) ("MATHEMATICAL SANS-SERIF CAPITAL A" . #x01d5a0) ("MATHEMATICAL SANS-SERIF CAPITAL B" . #x01d5a1) ("MATHEMATICAL SANS-SERIF CAPITAL C" . #x01d5a2) ("MATHEMATICAL SANS-SERIF CAPITAL D" . #x01d5a3) ("MATHEMATICAL SANS-SERIF CAPITAL E" . #x01d5a4) ("MATHEMATICAL SANS-SERIF CAPITAL F" . #x01d5a5) ("MATHEMATICAL SANS-SERIF CAPITAL G" . #x01d5a6) ("MATHEMATICAL SANS-SERIF CAPITAL H" . #x01d5a7) ("MATHEMATICAL SANS-SERIF CAPITAL I" . #x01d5a8) ("MATHEMATICAL SANS-SERIF CAPITAL J" . #x01d5a9) ("MATHEMATICAL SANS-SERIF CAPITAL K" . #x01d5aa) ("MATHEMATICAL SANS-SERIF CAPITAL L" . #x01d5ab) ("MATHEMATICAL SANS-SERIF CAPITAL M" . #x01d5ac) ("MATHEMATICAL SANS-SERIF CAPITAL N" . #x01d5ad) ("MATHEMATICAL SANS-SERIF CAPITAL O" . #x01d5ae) ("MATHEMATICAL SANS-SERIF CAPITAL P" . #x01d5af) ("MATHEMATICAL SANS-SERIF CAPITAL Q" . #x01d5b0) ("MATHEMATICAL SANS-SERIF CAPITAL R" . #x01d5b1) ("MATHEMATICAL SANS-SERIF CAPITAL S" . #x01d5b2) ("MATHEMATICAL SANS-SERIF CAPITAL T" . #x01d5b3) ("MATHEMATICAL SANS-SERIF CAPITAL U" . #x01d5b4) ("MATHEMATICAL SANS-SERIF CAPITAL V" . #x01d5b5) ("MATHEMATICAL SANS-SERIF CAPITAL W" . #x01d5b6) ("MATHEMATICAL SANS-SERIF CAPITAL X" . #x01d5b7) ("MATHEMATICAL SANS-SERIF CAPITAL Y" . #x01d5b8) ("MATHEMATICAL SANS-SERIF CAPITAL Z" . #x01d5b9) ("MATHEMATICAL SANS-SERIF SMALL A" . #x01d5ba) ("MATHEMATICAL SANS-SERIF SMALL B" . #x01d5bb) ("MATHEMATICAL SANS-SERIF SMALL C" . #x01d5bc) ("MATHEMATICAL SANS-SERIF SMALL D" . #x01d5bd) ("MATHEMATICAL SANS-SERIF SMALL E" . #x01d5be) ("MATHEMATICAL SANS-SERIF SMALL F" . #x01d5bf) ("MATHEMATICAL SANS-SERIF SMALL G" . #x01d5c0) ("MATHEMATICAL SANS-SERIF SMALL H" . #x01d5c1) ("MATHEMATICAL SANS-SERIF SMALL I" . #x01d5c2) ("MATHEMATICAL SANS-SERIF SMALL J" . #x01d5c3) ("MATHEMATICAL SANS-SERIF SMALL K" . #x01d5c4) ("MATHEMATICAL SANS-SERIF SMALL L" . #x01d5c5) ("MATHEMATICAL SANS-SERIF SMALL M" . #x01d5c6) ("MATHEMATICAL SANS-SERIF SMALL N" . #x01d5c7) ("MATHEMATICAL SANS-SERIF SMALL O" . #x01d5c8) ("MATHEMATICAL SANS-SERIF SMALL P" . #x01d5c9) ("MATHEMATICAL SANS-SERIF SMALL Q" . #x01d5ca) ("MATHEMATICAL SANS-SERIF SMALL R" . #x01d5cb) ("MATHEMATICAL SANS-SERIF SMALL S" . #x01d5cc) ("MATHEMATICAL SANS-SERIF SMALL T" . #x01d5cd) ("MATHEMATICAL SANS-SERIF SMALL U" . #x01d5ce) ("MATHEMATICAL SANS-SERIF SMALL V" . #x01d5cf) ("MATHEMATICAL SANS-SERIF SMALL W" . #x01d5d0) ("MATHEMATICAL SANS-SERIF SMALL X" . #x01d5d1) ("MATHEMATICAL SANS-SERIF SMALL Y" . #x01d5d2) ("MATHEMATICAL SANS-SERIF SMALL Z" . #x01d5d3) ("MATHEMATICAL SANS-SERIF BOLD CAPITAL A" . #x01d5d4) ("MATHEMATICAL SANS-SERIF BOLD CAPITAL B" . #x01d5d5) ("MATHEMATICAL SANS-SERIF BOLD CAPITAL C" . #x01d5d6) ("MATHEMATICAL SANS-SERIF BOLD CAPITAL D" . #x01d5d7) ("MATHEMATICAL SANS-SERIF BOLD CAPITAL E" . #x01d5d8) ("MATHEMATICAL SANS-SERIF BOLD CAPITAL F" . #x01d5d9) ("MATHEMATICAL SANS-SERIF BOLD CAPITAL G" . #x01d5da) ("MATHEMATICAL SANS-SERIF BOLD CAPITAL H" . #x01d5db) ("MATHEMATICAL SANS-SERIF BOLD CAPITAL I" . #x01d5dc) ("MATHEMATICAL SANS-SERIF BOLD CAPITAL J" . #x01d5dd) ("MATHEMATICAL SANS-SERIF BOLD CAPITAL K" . #x01d5de) ("MATHEMATICAL SANS-SERIF BOLD CAPITAL L" . #x01d5df) ("MATHEMATICAL SANS-SERIF BOLD CAPITAL M" . #x01d5e0) ("MATHEMATICAL SANS-SERIF BOLD CAPITAL N" . #x01d5e1) ("MATHEMATICAL SANS-SERIF BOLD CAPITAL O" . #x01d5e2) ("MATHEMATICAL SANS-SERIF BOLD CAPITAL P" . #x01d5e3) ("MATHEMATICAL SANS-SERIF BOLD CAPITAL Q" . #x01d5e4) ("MATHEMATICAL SANS-SERIF BOLD CAPITAL R" . #x01d5e5) ("MATHEMATICAL SANS-SERIF BOLD CAPITAL S" . #x01d5e6) ("MATHEMATICAL SANS-SERIF BOLD CAPITAL T" . #x01d5e7) ("MATHEMATICAL SANS-SERIF BOLD CAPITAL U" . #x01d5e8) ("MATHEMATICAL SANS-SERIF BOLD CAPITAL V" . #x01d5e9) ("MATHEMATICAL SANS-SERIF BOLD CAPITAL W" . #x01d5ea) ("MATHEMATICAL SANS-SERIF BOLD CAPITAL X" . #x01d5eb) ("MATHEMATICAL SANS-SERIF BOLD CAPITAL Y" . #x01d5ec) ("MATHEMATICAL SANS-SERIF BOLD CAPITAL Z" . #x01d5ed) ("MATHEMATICAL SANS-SERIF BOLD SMALL A" . #x01d5ee) ("MATHEMATICAL SANS-SERIF BOLD SMALL B" . #x01d5ef) ("MATHEMATICAL SANS-SERIF BOLD SMALL C" . #x01d5f0) ("MATHEMATICAL SANS-SERIF BOLD SMALL D" . #x01d5f1) ("MATHEMATICAL SANS-SERIF BOLD SMALL E" . #x01d5f2) ("MATHEMATICAL SANS-SERIF BOLD SMALL F" . #x01d5f3) ("MATHEMATICAL SANS-SERIF BOLD SMALL G" . #x01d5f4) ("MATHEMATICAL SANS-SERIF BOLD SMALL H" . #x01d5f5) ("MATHEMATICAL SANS-SERIF BOLD SMALL I" . #x01d5f6) ("MATHEMATICAL SANS-SERIF BOLD SMALL J" . #x01d5f7) ("MATHEMATICAL SANS-SERIF BOLD SMALL K" . #x01d5f8) ("MATHEMATICAL SANS-SERIF BOLD SMALL L" . #x01d5f9) ("MATHEMATICAL SANS-SERIF BOLD SMALL M" . #x01d5fa) ("MATHEMATICAL SANS-SERIF BOLD SMALL N" . #x01d5fb) ("MATHEMATICAL SANS-SERIF BOLD SMALL O" . #x01d5fc) ("MATHEMATICAL SANS-SERIF BOLD SMALL P" . #x01d5fd) ("MATHEMATICAL SANS-SERIF BOLD SMALL Q" . #x01d5fe) ("MATHEMATICAL SANS-SERIF BOLD SMALL R" . #x01d5ff) ("MATHEMATICAL SANS-SERIF BOLD SMALL S" . #x01d600) ("MATHEMATICAL SANS-SERIF BOLD SMALL T" . #x01d601) ("MATHEMATICAL SANS-SERIF BOLD SMALL U" . #x01d602) ("MATHEMATICAL SANS-SERIF BOLD SMALL V" . #x01d603) ("MATHEMATICAL SANS-SERIF BOLD SMALL W" . #x01d604) ("MATHEMATICAL SANS-SERIF BOLD SMALL X" . #x01d605) ("MATHEMATICAL SANS-SERIF BOLD SMALL Y" . #x01d606) ("MATHEMATICAL SANS-SERIF BOLD SMALL Z" . #x01d607) ("MATHEMATICAL SANS-SERIF ITALIC CAPITAL A" . #x01d608) ("MATHEMATICAL SANS-SERIF ITALIC CAPITAL B" . #x01d609) ("MATHEMATICAL SANS-SERIF ITALIC CAPITAL C" . #x01d60a) ("MATHEMATICAL SANS-SERIF ITALIC CAPITAL D" . #x01d60b) ("MATHEMATICAL SANS-SERIF ITALIC CAPITAL E" . #x01d60c) ("MATHEMATICAL SANS-SERIF ITALIC CAPITAL F" . #x01d60d) ("MATHEMATICAL SANS-SERIF ITALIC CAPITAL G" . #x01d60e) ("MATHEMATICAL SANS-SERIF ITALIC CAPITAL H" . #x01d60f) ("MATHEMATICAL SANS-SERIF ITALIC CAPITAL I" . #x01d610) ("MATHEMATICAL SANS-SERIF ITALIC CAPITAL J" . #x01d611) ("MATHEMATICAL SANS-SERIF ITALIC CAPITAL K" . #x01d612) ("MATHEMATICAL SANS-SERIF ITALIC CAPITAL L" . #x01d613) ("MATHEMATICAL SANS-SERIF ITALIC CAPITAL M" . #x01d614) ("MATHEMATICAL SANS-SERIF ITALIC CAPITAL N" . #x01d615) ("MATHEMATICAL SANS-SERIF ITALIC CAPITAL O" . #x01d616) ("MATHEMATICAL SANS-SERIF ITALIC CAPITAL P" . #x01d617) ("MATHEMATICAL SANS-SERIF ITALIC CAPITAL Q" . #x01d618) ("MATHEMATICAL SANS-SERIF ITALIC CAPITAL R" . #x01d619) ("MATHEMATICAL SANS-SERIF ITALIC CAPITAL S" . #x01d61a) ("MATHEMATICAL SANS-SERIF ITALIC CAPITAL T" . #x01d61b) ("MATHEMATICAL SANS-SERIF ITALIC CAPITAL U" . #x01d61c) ("MATHEMATICAL SANS-SERIF ITALIC CAPITAL V" . #x01d61d) ("MATHEMATICAL SANS-SERIF ITALIC CAPITAL W" . #x01d61e) ("MATHEMATICAL SANS-SERIF ITALIC CAPITAL X" . #x01d61f) ("MATHEMATICAL SANS-SERIF ITALIC CAPITAL Y" . #x01d620) ("MATHEMATICAL SANS-SERIF ITALIC CAPITAL Z" . #x01d621) ("MATHEMATICAL SANS-SERIF ITALIC SMALL A" . #x01d622) ("MATHEMATICAL SANS-SERIF ITALIC SMALL B" . #x01d623) ("MATHEMATICAL SANS-SERIF ITALIC SMALL C" . #x01d624) ("MATHEMATICAL SANS-SERIF ITALIC SMALL D" . #x01d625) ("MATHEMATICAL SANS-SERIF ITALIC SMALL E" . #x01d626) ("MATHEMATICAL SANS-SERIF ITALIC SMALL F" . #x01d627) ("MATHEMATICAL SANS-SERIF ITALIC SMALL G" . #x01d628) ("MATHEMATICAL SANS-SERIF ITALIC SMALL H" . #x01d629) ("MATHEMATICAL SANS-SERIF ITALIC SMALL I" . #x01d62a) ("MATHEMATICAL SANS-SERIF ITALIC SMALL J" . #x01d62b) ("MATHEMATICAL SANS-SERIF ITALIC SMALL K" . #x01d62c) ("MATHEMATICAL SANS-SERIF ITALIC SMALL L" . #x01d62d) ("MATHEMATICAL SANS-SERIF ITALIC SMALL M" . #x01d62e) ("MATHEMATICAL SANS-SERIF ITALIC SMALL N" . #x01d62f) ("MATHEMATICAL SANS-SERIF ITALIC SMALL O" . #x01d630) ("MATHEMATICAL SANS-SERIF ITALIC SMALL P" . #x01d631) ("MATHEMATICAL SANS-SERIF ITALIC SMALL Q" . #x01d632) ("MATHEMATICAL SANS-SERIF ITALIC SMALL R" . #x01d633) ("MATHEMATICAL SANS-SERIF ITALIC SMALL S" . #x01d634) ("MATHEMATICAL SANS-SERIF ITALIC SMALL T" . #x01d635) ("MATHEMATICAL SANS-SERIF ITALIC SMALL U" . #x01d636) ("MATHEMATICAL SANS-SERIF ITALIC SMALL V" . #x01d637) ("MATHEMATICAL SANS-SERIF ITALIC SMALL W" . #x01d638) ("MATHEMATICAL SANS-SERIF ITALIC SMALL X" . #x01d639) ("MATHEMATICAL SANS-SERIF ITALIC SMALL Y" . #x01d63a) ("MATHEMATICAL SANS-SERIF ITALIC SMALL Z" . #x01d63b) ("MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL A" . #x01d63c) ("MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL B" . #x01d63d) ("MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL C" . #x01d63e) ("MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL D" . #x01d63f) ("MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL E" . #x01d640) ("MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL F" . #x01d641) ("MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL G" . #x01d642) ("MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL H" . #x01d643) ("MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL I" . #x01d644) ("MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL J" . #x01d645) ("MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL K" . #x01d646) ("MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL L" . #x01d647) ("MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL M" . #x01d648) ("MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL N" . #x01d649) ("MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL O" . #x01d64a) ("MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL P" . #x01d64b) ("MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL Q" . #x01d64c) ("MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL R" . #x01d64d) ("MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL S" . #x01d64e) ("MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL T" . #x01d64f) ("MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL U" . #x01d650) ("MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL V" . #x01d651) ("MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL W" . #x01d652) ("MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL X" . #x01d653) ("MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL Y" . #x01d654) ("MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL Z" . #x01d655) ("MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL A" . #x01d656) ("MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL B" . #x01d657) ("MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL C" . #x01d658) ("MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL D" . #x01d659) ("MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL E" . #x01d65a) ("MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL F" . #x01d65b) ("MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL G" . #x01d65c) ("MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL H" . #x01d65d) ("MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL I" . #x01d65e) ("MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL J" . #x01d65f) ("MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL K" . #x01d660) ("MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL L" . #x01d661) ("MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL M" . #x01d662) ("MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL N" . #x01d663) ("MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL O" . #x01d664) ("MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL P" . #x01d665) ("MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL Q" . #x01d666) ("MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL R" . #x01d667) ("MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL S" . #x01d668) ("MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL T" . #x01d669) ("MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL U" . #x01d66a) ("MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL V" . #x01d66b) ("MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL W" . #x01d66c) ("MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL X" . #x01d66d) ("MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL Y" . #x01d66e) ("MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL Z" . #x01d66f) ("MATHEMATICAL MONOSPACE CAPITAL A" . #x01d670) ("MATHEMATICAL MONOSPACE CAPITAL B" . #x01d671) ("MATHEMATICAL MONOSPACE CAPITAL C" . #x01d672) ("MATHEMATICAL MONOSPACE CAPITAL D" . #x01d673) ("MATHEMATICAL MONOSPACE CAPITAL E" . #x01d674) ("MATHEMATICAL MONOSPACE CAPITAL F" . #x01d675) ("MATHEMATICAL MONOSPACE CAPITAL G" . #x01d676) ("MATHEMATICAL MONOSPACE CAPITAL H" . #x01d677) ("MATHEMATICAL MONOSPACE CAPITAL I" . #x01d678) ("MATHEMATICAL MONOSPACE CAPITAL J" . #x01d679) ("MATHEMATICAL MONOSPACE CAPITAL K" . #x01d67a) ("MATHEMATICAL MONOSPACE CAPITAL L" . #x01d67b) ("MATHEMATICAL MONOSPACE CAPITAL M" . #x01d67c) ("MATHEMATICAL MONOSPACE CAPITAL N" . #x01d67d) ("MATHEMATICAL MONOSPACE CAPITAL O" . #x01d67e) ("MATHEMATICAL MONOSPACE CAPITAL P" . #x01d67f) ("MATHEMATICAL MONOSPACE CAPITAL Q" . #x01d680) ("MATHEMATICAL MONOSPACE CAPITAL R" . #x01d681) ("MATHEMATICAL MONOSPACE CAPITAL S" . #x01d682) ("MATHEMATICAL MONOSPACE CAPITAL T" . #x01d683) ("MATHEMATICAL MONOSPACE CAPITAL U" . #x01d684) ("MATHEMATICAL MONOSPACE CAPITAL V" . #x01d685) ("MATHEMATICAL MONOSPACE CAPITAL W" . #x01d686) ("MATHEMATICAL MONOSPACE CAPITAL X" . #x01d687) ("MATHEMATICAL MONOSPACE CAPITAL Y" . #x01d688) ("MATHEMATICAL MONOSPACE CAPITAL Z" . #x01d689) ("MATHEMATICAL MONOSPACE SMALL A" . #x01d68a) ("MATHEMATICAL MONOSPACE SMALL B" . #x01d68b) ("MATHEMATICAL MONOSPACE SMALL C" . #x01d68c) ("MATHEMATICAL MONOSPACE SMALL D" . #x01d68d) ("MATHEMATICAL MONOSPACE SMALL E" . #x01d68e) ("MATHEMATICAL MONOSPACE SMALL F" . #x01d68f) ("MATHEMATICAL MONOSPACE SMALL G" . #x01d690) ("MATHEMATICAL MONOSPACE SMALL H" . #x01d691) ("MATHEMATICAL MONOSPACE SMALL I" . #x01d692) ("MATHEMATICAL MONOSPACE SMALL J" . #x01d693) ("MATHEMATICAL MONOSPACE SMALL K" . #x01d694) ("MATHEMATICAL MONOSPACE SMALL L" . #x01d695) ("MATHEMATICAL MONOSPACE SMALL M" . #x01d696) ("MATHEMATICAL MONOSPACE SMALL N" . #x01d697) ("MATHEMATICAL MONOSPACE SMALL O" . #x01d698) ("MATHEMATICAL MONOSPACE SMALL P" . #x01d699) ("MATHEMATICAL MONOSPACE SMALL Q" . #x01d69a) ("MATHEMATICAL MONOSPACE SMALL R" . #x01d69b) ("MATHEMATICAL MONOSPACE SMALL S" . #x01d69c) ("MATHEMATICAL MONOSPACE SMALL T" . #x01d69d) ("MATHEMATICAL MONOSPACE SMALL U" . #x01d69e) ("MATHEMATICAL MONOSPACE SMALL V" . #x01d69f) ("MATHEMATICAL MONOSPACE SMALL W" . #x01d6a0) ("MATHEMATICAL MONOSPACE SMALL X" . #x01d6a1) ("MATHEMATICAL MONOSPACE SMALL Y" . #x01d6a2) ("MATHEMATICAL MONOSPACE SMALL Z" . #x01d6a3) ("MATHEMATICAL BOLD CAPITAL ALPHA" . #x01d6a8) ("MATHEMATICAL BOLD CAPITAL BETA" . #x01d6a9) ("MATHEMATICAL BOLD CAPITAL GAMMA" . #x01d6aa) ("MATHEMATICAL BOLD CAPITAL DELTA" . #x01d6ab) ("MATHEMATICAL BOLD CAPITAL EPSILON" . #x01d6ac) ("MATHEMATICAL BOLD CAPITAL ZETA" . #x01d6ad) ("MATHEMATICAL BOLD CAPITAL ETA" . #x01d6ae) ("MATHEMATICAL BOLD CAPITAL THETA" . #x01d6af) ("MATHEMATICAL BOLD CAPITAL IOTA" . #x01d6b0) ("MATHEMATICAL BOLD CAPITAL KAPPA" . #x01d6b1) ("MATHEMATICAL BOLD CAPITAL LAMDA" . #x01d6b2) ("MATHEMATICAL BOLD CAPITAL MU" . #x01d6b3) ("MATHEMATICAL BOLD CAPITAL NU" . #x01d6b4) ("MATHEMATICAL BOLD CAPITAL XI" . #x01d6b5) ("MATHEMATICAL BOLD CAPITAL OMICRON" . #x01d6b6) ("MATHEMATICAL BOLD CAPITAL PI" . #x01d6b7) ("MATHEMATICAL BOLD CAPITAL RHO" . #x01d6b8) ("MATHEMATICAL BOLD CAPITAL THETA SYMBOL" . #x01d6b9) ("MATHEMATICAL BOLD CAPITAL SIGMA" . #x01d6ba) ("MATHEMATICAL BOLD CAPITAL TAU" . #x01d6bb) ("MATHEMATICAL BOLD CAPITAL UPSILON" . #x01d6bc) ("MATHEMATICAL BOLD CAPITAL PHI" . #x01d6bd) ("MATHEMATICAL BOLD CAPITAL CHI" . #x01d6be) ("MATHEMATICAL BOLD CAPITAL PSI" . #x01d6bf) ("MATHEMATICAL BOLD CAPITAL OMEGA" . #x01d6c0) ("MATHEMATICAL BOLD NABLA" . #x01d6c1) ("MATHEMATICAL BOLD SMALL ALPHA" . #x01d6c2) ("MATHEMATICAL BOLD SMALL BETA" . #x01d6c3) ("MATHEMATICAL BOLD SMALL GAMMA" . #x01d6c4) ("MATHEMATICAL BOLD SMALL DELTA" . #x01d6c5) ("MATHEMATICAL BOLD SMALL EPSILON" . #x01d6c6) ("MATHEMATICAL BOLD SMALL ZETA" . #x01d6c7) ("MATHEMATICAL BOLD SMALL ETA" . #x01d6c8) ("MATHEMATICAL BOLD SMALL THETA" . #x01d6c9) ("MATHEMATICAL BOLD SMALL IOTA" . #x01d6ca) ("MATHEMATICAL BOLD SMALL KAPPA" . #x01d6cb) ("MATHEMATICAL BOLD SMALL LAMDA" . #x01d6cc) ("MATHEMATICAL BOLD SMALL MU" . #x01d6cd) ("MATHEMATICAL BOLD SMALL NU" . #x01d6ce) ("MATHEMATICAL BOLD SMALL XI" . #x01d6cf) ("MATHEMATICAL BOLD SMALL OMICRON" . #x01d6d0) ("MATHEMATICAL BOLD SMALL PI" . #x01d6d1) ("MATHEMATICAL BOLD SMALL RHO" . #x01d6d2) ("MATHEMATICAL BOLD SMALL FINAL SIGMA" . #x01d6d3) ("MATHEMATICAL BOLD SMALL SIGMA" . #x01d6d4) ("MATHEMATICAL BOLD SMALL TAU" . #x01d6d5) ("MATHEMATICAL BOLD SMALL UPSILON" . #x01d6d6) ("MATHEMATICAL BOLD SMALL PHI" . #x01d6d7) ("MATHEMATICAL BOLD SMALL CHI" . #x01d6d8) ("MATHEMATICAL BOLD SMALL PSI" . #x01d6d9) ("MATHEMATICAL BOLD SMALL OMEGA" . #x01d6da) ("MATHEMATICAL BOLD PARTIAL DIFFERENTIAL" . #x01d6db) ("MATHEMATICAL BOLD EPSILON SYMBOL" . #x01d6dc) ("MATHEMATICAL BOLD THETA SYMBOL" . #x01d6dd) ("MATHEMATICAL BOLD KAPPA SYMBOL" . #x01d6de) ("MATHEMATICAL BOLD PHI SYMBOL" . #x01d6df) ("MATHEMATICAL BOLD RHO SYMBOL" . #x01d6e0) ("MATHEMATICAL BOLD PI SYMBOL" . #x01d6e1) ("MATHEMATICAL ITALIC CAPITAL ALPHA" . #x01d6e2) ("MATHEMATICAL ITALIC CAPITAL BETA" . #x01d6e3) ("MATHEMATICAL ITALIC CAPITAL GAMMA" . #x01d6e4) ("MATHEMATICAL ITALIC CAPITAL DELTA" . #x01d6e5) ("MATHEMATICAL ITALIC CAPITAL EPSILON" . #x01d6e6) ("MATHEMATICAL ITALIC CAPITAL ZETA" . #x01d6e7) ("MATHEMATICAL ITALIC CAPITAL ETA" . #x01d6e8) ("MATHEMATICAL ITALIC CAPITAL THETA" . #x01d6e9) ("MATHEMATICAL ITALIC CAPITAL IOTA" . #x01d6ea) ("MATHEMATICAL ITALIC CAPITAL KAPPA" . #x01d6eb) ("MATHEMATICAL ITALIC CAPITAL LAMDA" . #x01d6ec) ("MATHEMATICAL ITALIC CAPITAL MU" . #x01d6ed) ("MATHEMATICAL ITALIC CAPITAL NU" . #x01d6ee) ("MATHEMATICAL ITALIC CAPITAL XI" . #x01d6ef) ("MATHEMATICAL ITALIC CAPITAL OMICRON" . #x01d6f0) ("MATHEMATICAL ITALIC CAPITAL PI" . #x01d6f1) ("MATHEMATICAL ITALIC CAPITAL RHO" . #x01d6f2) ("MATHEMATICAL ITALIC CAPITAL THETA SYMBOL" . #x01d6f3) ("MATHEMATICAL ITALIC CAPITAL SIGMA" . #x01d6f4) ("MATHEMATICAL ITALIC CAPITAL TAU" . #x01d6f5) ("MATHEMATICAL ITALIC CAPITAL UPSILON" . #x01d6f6) ("MATHEMATICAL ITALIC CAPITAL PHI" . #x01d6f7) ("MATHEMATICAL ITALIC CAPITAL CHI" . #x01d6f8) ("MATHEMATICAL ITALIC CAPITAL PSI" . #x01d6f9) ("MATHEMATICAL ITALIC CAPITAL OMEGA" . #x01d6fa) ("MATHEMATICAL ITALIC NABLA" . #x01d6fb) ("MATHEMATICAL ITALIC SMALL ALPHA" . #x01d6fc) ("MATHEMATICAL ITALIC SMALL BETA" . #x01d6fd) ("MATHEMATICAL ITALIC SMALL GAMMA" . #x01d6fe) ("MATHEMATICAL ITALIC SMALL DELTA" . #x01d6ff) ("MATHEMATICAL ITALIC SMALL EPSILON" . #x01d700) ("MATHEMATICAL ITALIC SMALL ZETA" . #x01d701) ("MATHEMATICAL ITALIC SMALL ETA" . #x01d702) ("MATHEMATICAL ITALIC SMALL THETA" . #x01d703) ("MATHEMATICAL ITALIC SMALL IOTA" . #x01d704) ("MATHEMATICAL ITALIC SMALL KAPPA" . #x01d705) ("MATHEMATICAL ITALIC SMALL LAMDA" . #x01d706) ("MATHEMATICAL ITALIC SMALL MU" . #x01d707) ("MATHEMATICAL ITALIC SMALL NU" . #x01d708) ("MATHEMATICAL ITALIC SMALL XI" . #x01d709) ("MATHEMATICAL ITALIC SMALL OMICRON" . #x01d70a) ("MATHEMATICAL ITALIC SMALL PI" . #x01d70b) ("MATHEMATICAL ITALIC SMALL RHO" . #x01d70c) ("MATHEMATICAL ITALIC SMALL FINAL SIGMA" . #x01d70d) ("MATHEMATICAL ITALIC SMALL SIGMA" . #x01d70e) ("MATHEMATICAL ITALIC SMALL TAU" . #x01d70f) ("MATHEMATICAL ITALIC SMALL UPSILON" . #x01d710) ("MATHEMATICAL ITALIC SMALL PHI" . #x01d711) ("MATHEMATICAL ITALIC SMALL CHI" . #x01d712) ("MATHEMATICAL ITALIC SMALL PSI" . #x01d713) ("MATHEMATICAL ITALIC SMALL OMEGA" . #x01d714) ("MATHEMATICAL ITALIC PARTIAL DIFFERENTIAL" . #x01d715) ("MATHEMATICAL ITALIC EPSILON SYMBOL" . #x01d716) ("MATHEMATICAL ITALIC THETA SYMBOL" . #x01d717) ("MATHEMATICAL ITALIC KAPPA SYMBOL" . #x01d718) ("MATHEMATICAL ITALIC PHI SYMBOL" . #x01d719) ("MATHEMATICAL ITALIC RHO SYMBOL" . #x01d71a) ("MATHEMATICAL ITALIC PI SYMBOL" . #x01d71b) ("MATHEMATICAL BOLD ITALIC CAPITAL ALPHA" . #x01d71c) ("MATHEMATICAL BOLD ITALIC CAPITAL BETA" . #x01d71d) ("MATHEMATICAL BOLD ITALIC CAPITAL GAMMA" . #x01d71e) ("MATHEMATICAL BOLD ITALIC CAPITAL DELTA" . #x01d71f) ("MATHEMATICAL BOLD ITALIC CAPITAL EPSILON" . #x01d720) ("MATHEMATICAL BOLD ITALIC CAPITAL ZETA" . #x01d721) ("MATHEMATICAL BOLD ITALIC CAPITAL ETA" . #x01d722) ("MATHEMATICAL BOLD ITALIC CAPITAL THETA" . #x01d723) ("MATHEMATICAL BOLD ITALIC CAPITAL IOTA" . #x01d724) ("MATHEMATICAL BOLD ITALIC CAPITAL KAPPA" . #x01d725) ("MATHEMATICAL BOLD ITALIC CAPITAL LAMDA" . #x01d726) ("MATHEMATICAL BOLD ITALIC CAPITAL MU" . #x01d727) ("MATHEMATICAL BOLD ITALIC CAPITAL NU" . #x01d728) ("MATHEMATICAL BOLD ITALIC CAPITAL XI" . #x01d729) ("MATHEMATICAL BOLD ITALIC CAPITAL OMICRON" . #x01d72a) ("MATHEMATICAL BOLD ITALIC CAPITAL PI" . #x01d72b) ("MATHEMATICAL BOLD ITALIC CAPITAL RHO" . #x01d72c) ("MATHEMATICAL BOLD ITALIC CAPITAL THETA SYMBOL" . #x01d72d) ("MATHEMATICAL BOLD ITALIC CAPITAL SIGMA" . #x01d72e) ("MATHEMATICAL BOLD ITALIC CAPITAL TAU" . #x01d72f) ("MATHEMATICAL BOLD ITALIC CAPITAL UPSILON" . #x01d730) ("MATHEMATICAL BOLD ITALIC CAPITAL PHI" . #x01d731) ("MATHEMATICAL BOLD ITALIC CAPITAL CHI" . #x01d732) ("MATHEMATICAL BOLD ITALIC CAPITAL PSI" . #x01d733) ("MATHEMATICAL BOLD ITALIC CAPITAL OMEGA" . #x01d734) ("MATHEMATICAL BOLD ITALIC NABLA" . #x01d735) ("MATHEMATICAL BOLD ITALIC SMALL ALPHA" . #x01d736) ("MATHEMATICAL BOLD ITALIC SMALL BETA" . #x01d737) ("MATHEMATICAL BOLD ITALIC SMALL GAMMA" . #x01d738) ("MATHEMATICAL BOLD ITALIC SMALL DELTA" . #x01d739) ("MATHEMATICAL BOLD ITALIC SMALL EPSILON" . #x01d73a) ("MATHEMATICAL BOLD ITALIC SMALL ZETA" . #x01d73b) ("MATHEMATICAL BOLD ITALIC SMALL ETA" . #x01d73c) ("MATHEMATICAL BOLD ITALIC SMALL THETA" . #x01d73d) ("MATHEMATICAL BOLD ITALIC SMALL IOTA" . #x01d73e) ("MATHEMATICAL BOLD ITALIC SMALL KAPPA" . #x01d73f) ("MATHEMATICAL BOLD ITALIC SMALL LAMDA" . #x01d740) ("MATHEMATICAL BOLD ITALIC SMALL MU" . #x01d741) ("MATHEMATICAL BOLD ITALIC SMALL NU" . #x01d742) ("MATHEMATICAL BOLD ITALIC SMALL XI" . #x01d743) ("MATHEMATICAL BOLD ITALIC SMALL OMICRON" . #x01d744) ("MATHEMATICAL BOLD ITALIC SMALL PI" . #x01d745) ("MATHEMATICAL BOLD ITALIC SMALL RHO" . #x01d746) ("MATHEMATICAL BOLD ITALIC SMALL FINAL SIGMA" . #x01d747) ("MATHEMATICAL BOLD ITALIC SMALL SIGMA" . #x01d748) ("MATHEMATICAL BOLD ITALIC SMALL TAU" . #x01d749) ("MATHEMATICAL BOLD ITALIC SMALL UPSILON" . #x01d74a) ("MATHEMATICAL BOLD ITALIC SMALL PHI" . #x01d74b) ("MATHEMATICAL BOLD ITALIC SMALL CHI" . #x01d74c) ("MATHEMATICAL BOLD ITALIC SMALL PSI" . #x01d74d) ("MATHEMATICAL BOLD ITALIC SMALL OMEGA" . #x01d74e) ("MATHEMATICAL BOLD ITALIC PARTIAL DIFFERENTIAL" . #x01d74f) ("MATHEMATICAL BOLD ITALIC EPSILON SYMBOL" . #x01d750) ("MATHEMATICAL BOLD ITALIC THETA SYMBOL" . #x01d751) ("MATHEMATICAL BOLD ITALIC KAPPA SYMBOL" . #x01d752) ("MATHEMATICAL BOLD ITALIC PHI SYMBOL" . #x01d753) ("MATHEMATICAL BOLD ITALIC RHO SYMBOL" . #x01d754) ("MATHEMATICAL BOLD ITALIC PI SYMBOL" . #x01d755) ("MATHEMATICAL SANS-SERIF BOLD CAPITAL ALPHA" . #x01d756) ("MATHEMATICAL SANS-SERIF BOLD CAPITAL BETA" . #x01d757) ("MATHEMATICAL SANS-SERIF BOLD CAPITAL GAMMA" . #x01d758) ("MATHEMATICAL SANS-SERIF BOLD CAPITAL DELTA" . #x01d759) ("MATHEMATICAL SANS-SERIF BOLD CAPITAL EPSILON" . #x01d75a) ("MATHEMATICAL SANS-SERIF BOLD CAPITAL ZETA" . #x01d75b) ("MATHEMATICAL SANS-SERIF BOLD CAPITAL ETA" . #x01d75c) ("MATHEMATICAL SANS-SERIF BOLD CAPITAL THETA" . #x01d75d) ("MATHEMATICAL SANS-SERIF BOLD CAPITAL IOTA" . #x01d75e) ("MATHEMATICAL SANS-SERIF BOLD CAPITAL KAPPA" . #x01d75f) ("MATHEMATICAL SANS-SERIF BOLD CAPITAL LAMDA" . #x01d760) ("MATHEMATICAL SANS-SERIF BOLD CAPITAL MU" . #x01d761) ("MATHEMATICAL SANS-SERIF BOLD CAPITAL NU" . #x01d762) ("MATHEMATICAL SANS-SERIF BOLD CAPITAL XI" . #x01d763) ("MATHEMATICAL SANS-SERIF BOLD CAPITAL OMICRON" . #x01d764) ("MATHEMATICAL SANS-SERIF BOLD CAPITAL PI" . #x01d765) ("MATHEMATICAL SANS-SERIF BOLD CAPITAL RHO" . #x01d766) ("MATHEMATICAL SANS-SERIF BOLD CAPITAL THETA SYMBOL" . #x01d767) ("MATHEMATICAL SANS-SERIF BOLD CAPITAL SIGMA" . #x01d768) ("MATHEMATICAL SANS-SERIF BOLD CAPITAL TAU" . #x01d769) ("MATHEMATICAL SANS-SERIF BOLD CAPITAL UPSILON" . #x01d76a) ("MATHEMATICAL SANS-SERIF BOLD CAPITAL PHI" . #x01d76b) ("MATHEMATICAL SANS-SERIF BOLD CAPITAL CHI" . #x01d76c) ("MATHEMATICAL SANS-SERIF BOLD CAPITAL PSI" . #x01d76d) ("MATHEMATICAL SANS-SERIF BOLD CAPITAL OMEGA" . #x01d76e) ("MATHEMATICAL SANS-SERIF BOLD NABLA" . #x01d76f) ("MATHEMATICAL SANS-SERIF BOLD SMALL ALPHA" . #x01d770) ("MATHEMATICAL SANS-SERIF BOLD SMALL BETA" . #x01d771) ("MATHEMATICAL SANS-SERIF BOLD SMALL GAMMA" . #x01d772) ("MATHEMATICAL SANS-SERIF BOLD SMALL DELTA" . #x01d773) ("MATHEMATICAL SANS-SERIF BOLD SMALL EPSILON" . #x01d774) ("MATHEMATICAL SANS-SERIF BOLD SMALL ZETA" . #x01d775) ("MATHEMATICAL SANS-SERIF BOLD SMALL ETA" . #x01d776) ("MATHEMATICAL SANS-SERIF BOLD SMALL THETA" . #x01d777) ("MATHEMATICAL SANS-SERIF BOLD SMALL IOTA" . #x01d778) ("MATHEMATICAL SANS-SERIF BOLD SMALL KAPPA" . #x01d779) ("MATHEMATICAL SANS-SERIF BOLD SMALL LAMDA" . #x01d77a) ("MATHEMATICAL SANS-SERIF BOLD SMALL MU" . #x01d77b) ("MATHEMATICAL SANS-SERIF BOLD SMALL NU" . #x01d77c) ("MATHEMATICAL SANS-SERIF BOLD SMALL XI" . #x01d77d) ("MATHEMATICAL SANS-SERIF BOLD SMALL OMICRON" . #x01d77e) ("MATHEMATICAL SANS-SERIF BOLD SMALL PI" . #x01d77f) ("MATHEMATICAL SANS-SERIF BOLD SMALL RHO" . #x01d780) ("MATHEMATICAL SANS-SERIF BOLD SMALL FINAL SIGMA" . #x01d781) ("MATHEMATICAL SANS-SERIF BOLD SMALL SIGMA" . #x01d782) ("MATHEMATICAL SANS-SERIF BOLD SMALL TAU" . #x01d783) ("MATHEMATICAL SANS-SERIF BOLD SMALL UPSILON" . #x01d784) ("MATHEMATICAL SANS-SERIF BOLD SMALL PHI" . #x01d785) ("MATHEMATICAL SANS-SERIF BOLD SMALL CHI" . #x01d786) ("MATHEMATICAL SANS-SERIF BOLD SMALL PSI" . #x01d787) ("MATHEMATICAL SANS-SERIF BOLD SMALL OMEGA" . #x01d788) ("MATHEMATICAL SANS-SERIF BOLD PARTIAL DIFFERENTIAL" . #x01d789) ("MATHEMATICAL SANS-SERIF BOLD EPSILON SYMBOL" . #x01d78a) ("MATHEMATICAL SANS-SERIF BOLD THETA SYMBOL" . #x01d78b) ("MATHEMATICAL SANS-SERIF BOLD KAPPA SYMBOL" . #x01d78c) ("MATHEMATICAL SANS-SERIF BOLD PHI SYMBOL" . #x01d78d) ("MATHEMATICAL SANS-SERIF BOLD RHO SYMBOL" . #x01d78e) ("MATHEMATICAL SANS-SERIF BOLD PI SYMBOL" . #x01d78f) ("MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL ALPHA" . #x01d790) ("MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL BETA" . #x01d791) ("MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL GAMMA" . #x01d792) ("MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL DELTA" . #x01d793) ("MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL EPSILON" . #x01d794) ("MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL ZETA" . #x01d795) ("MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL ETA" . #x01d796) ("MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL THETA" . #x01d797) ("MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL IOTA" . #x01d798) ("MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL KAPPA" . #x01d799) ("MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL LAMDA" . #x01d79a) ("MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL MU" . #x01d79b) ("MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL NU" . #x01d79c) ("MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL XI" . #x01d79d) ("MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL OMICRON" . #x01d79e) ("MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL PI" . #x01d79f) ("MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL RHO" . #x01d7a0) ("MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL THETA SYMBOL" . #x01d7a1) ("MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL SIGMA" . #x01d7a2) ("MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL TAU" . #x01d7a3) ("MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL UPSILON" . #x01d7a4) ("MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL PHI" . #x01d7a5) ("MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL CHI" . #x01d7a6) ("MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL PSI" . #x01d7a7) ("MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL OMEGA" . #x01d7a8) ("MATHEMATICAL SANS-SERIF BOLD ITALIC NABLA" . #x01d7a9) ("MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL ALPHA" . #x01d7aa) ("MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL BETA" . #x01d7ab) ("MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL GAMMA" . #x01d7ac) ("MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL DELTA" . #x01d7ad) ("MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL EPSILON" . #x01d7ae) ("MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL ZETA" . #x01d7af) ("MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL ETA" . #x01d7b0) ("MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL THETA" . #x01d7b1) ("MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL IOTA" . #x01d7b2) ("MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL KAPPA" . #x01d7b3) ("MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL LAMDA" . #x01d7b4) ("MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL MU" . #x01d7b5) ("MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL NU" . #x01d7b6) ("MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL XI" . #x01d7b7) ("MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL OMICRON" . #x01d7b8) ("MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL PI" . #x01d7b9) ("MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL RHO" . #x01d7ba) ("MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL FINAL SIGMA" . #x01d7bb) ("MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL SIGMA" . #x01d7bc) ("MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL TAU" . #x01d7bd) ("MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL UPSILON" . #x01d7be) ("MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL PHI" . #x01d7bf) ("MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL CHI" . #x01d7c0) ("MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL PSI" . #x01d7c1) ("MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL OMEGA" . #x01d7c2) ("MATHEMATICAL SANS-SERIF BOLD ITALIC PARTIAL DIFFERENTIAL" . #x01d7c3) ("MATHEMATICAL SANS-SERIF BOLD ITALIC EPSILON SYMBOL" . #x01d7c4) ("MATHEMATICAL SANS-SERIF BOLD ITALIC THETA SYMBOL" . #x01d7c5) ("MATHEMATICAL SANS-SERIF BOLD ITALIC KAPPA SYMBOL" . #x01d7c6) ("MATHEMATICAL SANS-SERIF BOLD ITALIC PHI SYMBOL" . #x01d7c7) ("MATHEMATICAL SANS-SERIF BOLD ITALIC RHO SYMBOL" . #x01d7c8) ("MATHEMATICAL SANS-SERIF BOLD ITALIC PI SYMBOL" . #x01d7c9) ("MATHEMATICAL BOLD DIGIT ZERO" . #x01d7ce) ("MATHEMATICAL BOLD DIGIT ONE" . #x01d7cf) ("MATHEMATICAL BOLD DIGIT TWO" . #x01d7d0) ("MATHEMATICAL BOLD DIGIT THREE" . #x01d7d1) ("MATHEMATICAL BOLD DIGIT FOUR" . #x01d7d2) ("MATHEMATICAL BOLD DIGIT FIVE" . #x01d7d3) ("MATHEMATICAL BOLD DIGIT SIX" . #x01d7d4) ("MATHEMATICAL BOLD DIGIT SEVEN" . #x01d7d5) ("MATHEMATICAL BOLD DIGIT EIGHT" . #x01d7d6) ("MATHEMATICAL BOLD DIGIT NINE" . #x01d7d7) ("MATHEMATICAL DOUBLE-STRUCK DIGIT ZERO" . #x01d7d8) ("MATHEMATICAL DOUBLE-STRUCK DIGIT ONE" . #x01d7d9) ("MATHEMATICAL DOUBLE-STRUCK DIGIT TWO" . #x01d7da) ("MATHEMATICAL DOUBLE-STRUCK DIGIT THREE" . #x01d7db) ("MATHEMATICAL DOUBLE-STRUCK DIGIT FOUR" . #x01d7dc) ("MATHEMATICAL DOUBLE-STRUCK DIGIT FIVE" . #x01d7dd) ("MATHEMATICAL DOUBLE-STRUCK DIGIT SIX" . #x01d7de) ("MATHEMATICAL DOUBLE-STRUCK DIGIT SEVEN" . #x01d7df) ("MATHEMATICAL DOUBLE-STRUCK DIGIT EIGHT" . #x01d7e0) ("MATHEMATICAL DOUBLE-STRUCK DIGIT NINE" . #x01d7e1) ("MATHEMATICAL SANS-SERIF DIGIT ZERO" . #x01d7e2) ("MATHEMATICAL SANS-SERIF DIGIT ONE" . #x01d7e3) ("MATHEMATICAL SANS-SERIF DIGIT TWO" . #x01d7e4) ("MATHEMATICAL SANS-SERIF DIGIT THREE" . #x01d7e5) ("MATHEMATICAL SANS-SERIF DIGIT FOUR" . #x01d7e6) ("MATHEMATICAL SANS-SERIF DIGIT FIVE" . #x01d7e7) ("MATHEMATICAL SANS-SERIF DIGIT SIX" . #x01d7e8) ("MATHEMATICAL SANS-SERIF DIGIT SEVEN" . #x01d7e9) ("MATHEMATICAL SANS-SERIF DIGIT EIGHT" . #x01d7ea) ("MATHEMATICAL SANS-SERIF DIGIT NINE" . #x01d7eb) ("MATHEMATICAL SANS-SERIF BOLD DIGIT ZERO" . #x01d7ec) ("MATHEMATICAL SANS-SERIF BOLD DIGIT ONE" . #x01d7ed) ("MATHEMATICAL SANS-SERIF BOLD DIGIT TWO" . #x01d7ee) ("MATHEMATICAL SANS-SERIF BOLD DIGIT THREE" . #x01d7ef) ("MATHEMATICAL SANS-SERIF BOLD DIGIT FOUR" . #x01d7f0) ("MATHEMATICAL SANS-SERIF BOLD DIGIT FIVE" . #x01d7f1) ("MATHEMATICAL SANS-SERIF BOLD DIGIT SIX" . #x01d7f2) ("MATHEMATICAL SANS-SERIF BOLD DIGIT SEVEN" . #x01d7f3) ("MATHEMATICAL SANS-SERIF BOLD DIGIT EIGHT" . #x01d7f4) ("MATHEMATICAL SANS-SERIF BOLD DIGIT NINE" . #x01d7f5) ("MATHEMATICAL MONOSPACE DIGIT ZERO" . #x01d7f6) ("MATHEMATICAL MONOSPACE DIGIT ONE" . #x01d7f7) ("MATHEMATICAL MONOSPACE DIGIT TWO" . #x01d7f8) ("MATHEMATICAL MONOSPACE DIGIT THREE" . #x01d7f9) ("MATHEMATICAL MONOSPACE DIGIT FOUR" . #x01d7fa) ("MATHEMATICAL MONOSPACE DIGIT FIVE" . #x01d7fb) ("MATHEMATICAL MONOSPACE DIGIT SIX" . #x01d7fc) ("MATHEMATICAL MONOSPACE DIGIT SEVEN" . #x01d7fd) ("MATHEMATICAL MONOSPACE DIGIT EIGHT" . #x01d7fe) ("MATHEMATICAL MONOSPACE DIGIT NINE" . #x01d7ff))) ;; taken from xmlunicode.el, also by Norman Walsh. ;; Modified a bit by me to use its own help-style buffer ;;;###autoload (defun unicode-chars-list-chars () "Insert each Unicode character into a buffer. Lets you see which characters are available for literal display in your Emacs font." (interactive) (pop-to-buffer "*unicode-chars*") (let ((chars unicode-chars-alist) char codept name) (while chars (setq char (car chars)) (setq chars (cdr chars)) (setq name (car char)) (setq codept (cdr char)) (if (< codept #xffff) (progn (insert (format "#x%06x " codept)) (insert-char codept 1) (insert (format " %s\n" name))))))) (provide 'unicode-chars) ;;; unicode-chars.el ends here PG-4.5/lib/unicode-tokens.el000066400000000000000000001533441426357011200157220ustar00rootroot00000000000000;;; unicode-tokens.el --- Support for control and symbol tokens -*- lexical-binding: t; -*- ;; This file is part of Proof General. ;; Portions © Copyright 1994-2012 David Aspinall and University of Edinburgh ;; Portions © Copyright 2003-2021 Free Software Foundation, Inc. ;; Portions © Copyright 2001-2017 Pierre Courtieu ;; Portions © Copyright 2010, 2016 Erik Martin-Dorel ;; Portions © Copyright 2011-2013, 2016-2017 Hendrik Tews ;; Portions © Copyright 2015-2017 Clément Pit-Claudel ;; Author: David Aspinall ;; SPDX-License-Identifier: GPL-3.0-or-later ;; This is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation; either version 3, or (at your option) ;; any later version. ;; This software is distributed in the hope that it will be useful, ;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License ;; along with GNU Emacs; see the file COPYING. If not, write to the ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, ;; Boston, MA 02111-1307, USA. ;;; Commentary: ;; ;; This is a replacement for X-Symbol for Proof General. ;; ;; Functions to display tokens that represent Unicode characters and ;; control code sequences for changing the layout. Tokens are useful ;; for programs that do not understand a Unicode encoding. ;; ;; Desirable improvements/enhancements ;; ;; -- insert tokens via numeric code (extra format string), cf HTML ;; -- simplify: unify region and control settings? ;; -- simplify/optimise property handling ;; -- support multiple modes with mode-local configs at once ;;; Code: (require 'cl-lib) (require 'quail) (eval-when-compile (require 'maths-menu)) ; nuke compile warnings ;; ;; Customizable user options ;; (defgroup unicode-tokens-options nil "User options for Unicode Tokens mode." :group 'faces :prefix "unicode-tokens-") (defcustom unicode-tokens-add-help-echo t "If non-nil, add mouse hover (or minibuffer messages) to show tokens." :type 'boolean :group 'unicode-tokens-options) (defun unicode-tokens-toggle-add-help-echo () "Toggle option ‘unicode-tokens-add-help-echo’." (interactive) (customize-set-variable 'unicode-tokens-add-help-echo (not unicode-tokens-add-help-echo)) (if (fboundp 'font-lock-flush) ;Emacs-25 (font-lock-flush) ;; NB: approximate, should refontify all... (with-no-warnings (font-lock-fontify-buffer)))) ;; ;; Variables that should be set by client modes ;; ;; Each variable may be set directly or indirectly; see ;; `unicode-tokens-copy-configuration-variables' below. ;; (defvar unicode-tokens-token-symbol-map nil "Mapping of token names to compositions. A list, each element of which is a list (TOKNAME COMPOSITION FONTSYMB ...) A composition is typically a single Unicode character string, but can be more complex: see documentation of `compose-region'. TOKNAMEs may be repeated. The first one with a usable composition according to `unicode-tokens-usable-composition', if any. The sequence of FONTSYMB are optional. Each FONTSYMB is a symbol indicating a set of additional text properties, looked up in `unicode-tokens-fontsymb-properties'. By default, tokens are displayed in `unicode-tokens-symbol-font-face'.") (defvar unicode-tokens-token-format "%s" "Format string for formatting token a name into a token. Will be regexp quoted for matching. Not used for matching if `unicode-tokens-token-variant-format-regexp' is set. Also used to format shortcuts.") (defvar unicode-tokens-token-variant-format-regexp nil "A regular expression which matches a token variant. Will not be regexp quoted, and will be formatted with a nested regexp that matches any token. An example would be: \\\\(%s\\\\)\\\\(:?\\w+\\\\) which matches plain token strings optionally followed by a colon and variant name. Once set, (match-string 1) should be the name of the token whereas (match-string 0) matches the longer text, if any. If set, this variable is used instead of `unicode-tokens-token-format'.") (defvar unicode-tokens-shortcut-alist nil "An alist of keyboard shortcuts to unicode strings. The alist is added to the input mode for tokens. The shortcuts are only used for input convenience; no reverse mapping back to shortucts is performed. Behaviour is like abbrev.") (defvar unicode-tokens-shortcut-replacement-alist nil "Overrides `unicode-tokens-shortcut-alist'. Used for `unicode-tokens-replace-shortcuts'.") ;; ;; Variables that may optionally be set in client modes ;; (defvar unicode-tokens-control-region-format-regexp nil "A regexp for control regions, with up to two %s placeholders. When fomatted with arguments START END, results in a regexp that matches a control region. There should be three delimited subexpressions: (match-string 1) and (match-string 3) are hidden, and (match-string 2) has the display control applied.") (defvar unicode-tokens-control-char-format-regexp nil "A format string for control characters, possibly with a %s placeholder. When fomatted with arguments STRING, results in a regexp that matches a control character sequence. There should be two delimited subexpressions: (match-string 1) is hidden and (match-string 2) has the display control applied.") (defvar unicode-tokens-control-regions nil "A list of control regions.") (defvar unicode-tokens-control-characters nil "A list of control characters.") (defvar unicode-tokens-control-char-format nil "A format string for inserting a control character sequence.") (defvar unicode-tokens-control-region-format-start nil "A format string for begining a control region sequence.") (defvar unicode-tokens-control-region-format-end nil "A format string for ending a control region sequence.") (defvar unicode-tokens-tokens-customizable-variables nil "A list of lists (NAME VAR) of variables for a customize submenu.") ;; ;; A list of the above variables ;; (defconst unicode-tokens-configuration-variables '(token-symbol-map token-format token-variant-format-regexp shortcut-alist shortcut-replacement-alist control-region-format-regexp control-region-format-start control-region-format-end control-char-format-regexp control-char-format control-regions control-characters tokens-customizable-variables)) (defun unicode-tokens-config (sym) "Construct the symbol name `unicode-tokens-SYM'." (intern (concat "unicode-tokens-" (symbol-name sym)))) (defun unicode-tokens-config-var (sym) "Construct the symbol name `unicode-tokens-SYM-variable'." (intern (concat "unicode-tokens-" (symbol-name sym) "-variable"))) (dolist (sym unicode-tokens-configuration-variables) ;; FIXME: This dolist loop does nothing! (lambda (sym) (eval `(defvar ,(unicode-tokens-config-var sym) nil ,(format "Name of a variable used to configure %s.\nValue should be a symbol." (symbol-name (unicode-tokens-config sym)))) t))) (defun unicode-tokens-copy-configuration-variables () "Initialise the configuration variables by copying from variable names. Each configuration variable may be set directly or indirectly by client; modes an indirect setting is made by this function from a variable named -variable, e.g., `unicode-tokens-token-symbol-map' will be initialised from `unicode-tokens-token-symbol-map-variable', if it is bound; it should be the name of a variable." (dolist (sym unicode-tokens-configuration-variables) (let ((var (unicode-tokens-config-var sym))) (if (and (boundp var) (not (null (symbol-value var)))) (set (unicode-tokens-config sym) (symbol-value (symbol-value (unicode-tokens-config-var sym))))))) (unless unicode-tokens-shortcut-replacement-alist (setq unicode-tokens-shortcut-replacement-alist unicode-tokens-shortcut-alist)) (unless unicode-tokens-tokens-customizable-variables (setq unicode-tokens-tokens-customizable-variables (list (list "Token Map" (symbol-value (unicode-tokens-config-var 'token-symbol-map))) (list "Shortcut List" (symbol-value (unicode-tokens-config-var 'shortcut-alist))))))) ;; ;; Variables set in the mode ;; (defvar unicode-tokens-token-list nil "List of usable token names in order from `unicode-tokens-token-symbol-map'.") (defvar unicode-tokens-hash-table nil "Hash table mapping token names (strings) to composition and properties.") (defvar unicode-tokens-token-match-regexp nil "Regular expression used by font-lock to match known tokens. The match should span the whole token; (match-string 1) should span the token name, if that is shorter. The value is calculated by `unicode-tokens-calculate-token-match'.") (defvar unicode-tokens-uchar-hash-table nil "Hash table mapping unicode strings to symbolic token names. This is used for an approximate reverse mapping, see `unicode-tokens-paste'.") (defvar unicode-tokens-uchar-regexp nil "Regular expression matching converted tokens. This is used for an approximate reverse mapping, see `unicode-tokens-paste'.") ;; ;; Faces ;; (defgroup unicode-tokens-faces nil "The faces used in Unicode Tokens mode." :group 'faces) ;; ;; This is a fallback for when fontconfig is not used/available. ;; ;; NB: even with fontconfig, name aliasing has undesirable effects ;; (e.g., can end up with version of font without anti-aliasing) ;; (defconst unicode-tokens-font-family-alternatives '(("STIXGeneral" "DejaVu Sans Mono" "DejaVuLGC Sans Mono" "Lucida Grande" "Lucida Sans Unicode" "Apple Symbols") ("Script" "Lucida Calligraphy" "URW Chancery L" "Zapf Chancery") ("Fraktur" "Lucida Blackletter" "Isabella" "URW Bookman L"))) (if (boundp 'face-font-family-alternatives) (custom-set-default 'face-font-family-alternatives (append face-font-family-alternatives unicode-tokens-font-family-alternatives))) (defface unicode-tokens-symbol-font-face '((t :family "STIXGeneral")) ;; best, but needs installation/config ; '((t :family "DejaVu Sans Mono")) ;; more reliable default on Ubuntu "The default font used for symbols. Only :family and :slant attributes are used." :group 'unicode-tokens-faces) ;; (defface unicode-tokens-large-symbol-font-face ;; '((t :family "STIXSizeThreeSym")) ;; "The font used for large symbols." ;; :group 'unicode-tokens-faces) (defface unicode-tokens-script-font-face '((t :family "URW Chancery L" :slant italic)) "Script font face." :group 'unicode-tokens-faces) (defface unicode-tokens-fraktur-font-face '((t :family "Fraktur")) "Fraktur font face." :group 'unicode-tokens-faces) (defface unicode-tokens-serif-font-face '((t :family "Times New Roman")) "Serif (roman) font face." :group 'unicode-tokens-faces) (defface unicode-tokens-sans-font-face '((t :family "Sans")) "Sans serif font face." :group 'unicode-tokens-faces) (defface unicode-tokens-highlight-face '((((min-colors 88) (background dark)) (:background "yellow1" :foreground "black")) (((background dark)) (:background "yellow" :foreground "black")) (((min-colors 88)) (:background "yellow1")) (t (:background "yellow"))) "Face used for highlighting in Unicode tokens." :group 'unicode-tokens-faces) (defconst unicode-tokens-fonts '(symbol script fraktur serif sans) ; large-symbol "A list of the faces used for setting fonts for Unicode Tokens.") ;; ;; Standard text properties used to build fontification ;; (defconst unicode-tokens-fontsymb-properties '((sub "Lower" (display (raise -0.4))) (sup "Raise" (display (raise 0.4))) (bold "Bold" (face (:weight bold))) (italic "Italic" (face (:slant italic))) (big "Bigger" (face (:height 1.5))) (small "Smaller" (face (:height 0.75))) (underline "Underline" (face (:underline t))) (overline "Overline" (face (:overline t))) ;; NB: symbols for fonts need to be as in unicode-tokens-fonts (script "Script font" (face unicode-tokens-script-font-face)) (frakt "Frakt font" (face unicode-tokens-fraktur-font-face)) (serif "Serif font" (face unicode-tokens-serif-font-face)) (sans "Sans font" (face unicode-tokens-sans-font-face)) ; (large-symbol "Large Symbol font" ; (face unicode-tokens-large-symbol-font-face)) (keyword "Keyword face" (face font-lock-keyword-face)) (function "Function name face" (face font-lock-function-name-face)) (type "Type face" (face font-lock-type-face)) (preprocessor "Preprocessor face" (face font-lock-preprocessor-face)) (doc "Documentation face" (face font-lock-preprocessor-face)) (builtin "Builtin face" (face font-lock-builtin-face)) (tacticals "Tacticals face" (face proof-tacticals-name-face))) "Association list mapping a symbol to a name and list of text properties. Used in `unicode-tokens-token-symbol-map', `unicode-tokens-control-regions', and `unicode-tokens-control-characters'. Several symbols can be used at once, in `unicode-tokens-token-symbol-map'.") (define-widget 'unicode-tokens-token-symbol-map 'lazy "Type for customize variables used to set `unicode-tokens-token-symbol-map'." :offset 4 :tag "Token symbol map" :type ;; TODO: improve this so customize editing is more pleasant. (list 'repeat :tag "Map entries" (append '(list :tag "Mapping" (string :tag "Token name") (sexp :tag "Composition")) (list (append '(set :tag "Text property styles" :inline t) (mapcar (lambda (fsp) (list 'const :tag (cadr fsp) (car fsp))) unicode-tokens-fontsymb-properties)))))) (define-widget 'unicode-tokens-shortcut-alist 'lazy "Type for customize variables used to set `unicode-tokens-shortcut-alist'." :offset 4 :tag "Shortcut list" :type '(repeat :tag "Shortcut list" (cons (string :tag "Shortcut sequence") (string :tag "Buffer string")))) ;; ;; Calculating font-lock-keywords ;; (defconst unicode-tokens-font-lock-extra-managed-props '(composition help-echo display invisible) "Value for `font-lock-extra-managed-props' here.") (defun unicode-tokens-font-lock-keywords () "Calculate and return value for `font-lock-keywords'. This function also initialises the important tables for the mode." ;; Credit to Stefan Monnier for much slimmer original version (let ((hash (make-hash-table :test 'equal)) (ucharhash (make-hash-table :test 'equal)) toks uchars) (dolist (x unicode-tokens-token-symbol-map) (let ((tok (car x)) (comp (cadr x))) (when (unicode-tokens-usable-composition comp) (unless (gethash tok hash) (puthash tok (cdr x) hash) (push tok toks) (if (stringp comp) ;; reverse map only for string comps (unless (or (gethash comp ucharhash) ;; ignore plain chars for reverse map (string-match "[a-zA-Z0-9]+" comp)) (push comp uchars) (puthash comp tok ucharhash))))))) (when toks (setq unicode-tokens-hash-table hash) (setq unicode-tokens-uchar-hash-table ucharhash) (setq unicode-tokens-uchar-regexp (regexp-opt uchars)) (setq unicode-tokens-token-match-regexp (unicode-tokens-calculate-token-match toks)) (setq unicode-tokens-token-list (nreverse toks)) (cons `(,unicode-tokens-token-match-regexp (0 (unicode-tokens-help-echo) prepend) (0 (unicode-tokens-font-lock-compose-symbol 1) prepend)) (unicode-tokens-control-font-lock-keywords))))) (defun unicode-tokens-calculate-token-match (toks) "Calculate value for `unicode-tokens-token-match-regexp'." ; (with-syntax-table (standard-syntax-table) ;; hairy logic based on Coq-style vs Isabelle-style configs (if (string= "" (format unicode-tokens-token-format "")) ;; no special token format, parse separate words/symbols (let* ((tokextra (cl-remove "^\\(?:\\sw\\|\\s_\\)+$" toks :test 'string-match)) (toksymbwrd (cl-set-difference toks tokextra)) ;; indentifier that are not pure words (toksymb (cl-remove "^\\(?:\\sw\\)+$" toksymbwrd :test 'string-match)) ;; pure words (tokwrd (cl-set-difference toksymbwrd toksymb)) (idorop (concat "\\(\\_<" (regexp-opt toksymb) "\\_>\\|\\(?:\\<" (regexp-opt tokwrd) "\\>\\)\\|\\(?:\\B" (regexp-opt tokextra) "\\B\\)\\)"))) (if unicode-tokens-token-variant-format-regexp (format unicode-tokens-token-variant-format-regexp idorop) idorop)) ;; otherwise, assumption is that token syntax delimits tokens (if unicode-tokens-token-variant-format-regexp (format unicode-tokens-token-variant-format-regexp (regexp-opt toks)) (regexp-opt (mapcar (lambda (tok) (format unicode-tokens-token-format tok)) toks)))));) (defun unicode-tokens-usable-composition (comp) "Return non-nil if the composition COMP seems to be usable. The check is with `char-displayable-p'." (cond ((stringp comp) (cl-reduce (lambda (x y) (and x (char-displayable-p y))) comp :initial-value t)) ((characterp comp) (char-displayable-p comp)) (comp ;; assume any other non-null is OK t))) (defun unicode-tokens-help-echo () "Return a help-echo text property to display the contents of match string." (if unicode-tokens-add-help-echo (list 'face nil 'help-echo (match-string 0)))) (defvar unicode-tokens-show-symbols nil "Non-nil to reveal symbol (composed) tokens instead of compositions.") (defun unicode-tokens-interpret-composition (comp) "Turn the composition string COMP into an argument for `compose-region'." (cond ((and (stringp comp) (= 1 (length comp))) comp) ((stringp comp) ;; change a longer string into a sequence placing glyphs left-to-right. (let ((chars (nreverse (string-to-list comp))) (sep '(5 . 3)) res) (while chars (setq res (cons (car chars) res)) (if (setq chars (cdr chars)) (setq res (cons sep res)))) res)) (t comp))) (defun unicode-tokens-font-lock-compose-symbol (match) "Compose a sequence of chars into a symbol. Regexp match data number MATCH selects the token name, while match number 1 matches the text to be replaced. Token name from MATCH is searched for in `unicode-tokens-hash-table'. The face property is set to the :family and :slant attriubutes taken from `unicode-tokens-symbol-font-face'." (let* ((start (match-beginning 0)) (end (match-end 0)) (compps (gethash (match-string match) unicode-tokens-hash-table)) (propsyms (cdr-safe compps)) (comp (car-safe compps))) (if (and comp (not unicode-tokens-show-symbols)) (compose-region start end (unicode-tokens-interpret-composition comp))) (if propsyms (let ((props (unicode-tokens-symbs-to-props propsyms))) (while props (font-lock-append-text-property start end (car props) (cadr props)) (setq props (cddr props))))) (unless (or unicode-tokens-show-symbols (cl-intersection unicode-tokens-fonts propsyms)) (font-lock-append-text-property start end 'face ;; just use family and slant to enhance merging with other faces (list :family (face-attribute 'unicode-tokens-symbol-font-face :family))) (if (face-attribute 'unicode-tokens-symbol-font-face :slant) (font-lock-append-text-property start end 'face (list :slant (face-attribute 'unicode-tokens-symbol-font-face :slant)))) ) ;; [returning face property here seems to have no effect?] nil)) (defun unicode-tokens-prepend-text-properties-in-match (props matchno) (let ((start (match-beginning matchno)) (end (match-end matchno))) (while props (unicode-tokens-prepend-text-property start end (car props) (cadr props)) (setq props (cddr props))) nil)) ;; this is adapted from font-lock-prepend-text-property, which ;; currently fails to merge property values for 'face property properly. ;; e.g., it makes (:slant italic (:weight bold font-lock-string-face)) ;; rather than (:slant italic :weight bold font-lock-string-face) ;; (defun unicode-tokens-prepend-text-property (start end prop value &optional object) "Prepend to one property of the text from START to END. Arguments PROP and VALUE specify the property and value to append to the value already in place. The resulting property values are always lists. Optional argument OBJECT is the string or buffer containing the text." (let ((val (if (listp value) value (list value))) next prev) (while (/= start end) (setq next (next-single-property-change start prop object end) prev (get-text-property start prop object)) ;; Canonicalize old forms of face property. (and (memq prop '(face font-lock-face)) (listp prev) (or (keywordp (car prev)) (memq (car prev) '(foreground-color background-color))) (setq prev (list prev))) (setq prev (if (listp prev) prev (list prev))) ;; hack to flatten erroneously nested face property lists (if (and (memq prop '(face font-lock-face)) (listp (car prev)) (null (cdr prev))) (setq prev (car prev))) (put-text-property start next prop (append prev val) object) (setq start next)))) (defun unicode-tokens-show-symbols (&optional arg) "Toggle variable `unicode-tokens-show-symbols'. With ARG, turn on iff positive." (interactive "P") (setq unicode-tokens-show-symbols (if (null arg) (not unicode-tokens-show-symbols) (> (prefix-numeric-value arg) 0))) (if (fboundp 'font-lock-flush) ;Emacs-25 (font-lock-flush) (with-no-warnings (font-lock-fontify-buffer)))) (defun unicode-tokens-symbs-to-props (symbs &optional facenil) "Turn the property name list SYMBS into a list of text properties. Symbols are looked up in `unicode-tokens-fontsymb-properties'. Optional argument FACENIL means set the face property to nil, unless 'face is in the property list." (let (props ps) (dolist (s symbs) (setq ps (cdr-safe (cdr-safe (assoc s unicode-tokens-fontsymb-properties)))) (dolist (p ps) (setq props (append p props)))) (if (and facenil (not (memq 'face props))) (setq props (append '(face nil) props))) props)) ;; ;; Control tokens: as "characters" CTRL ;; and regions BEGINCTRL ENDCTRL ;; (defvar unicode-tokens-show-controls nil "Non-nil supresses hiding of control tokens.") (defun unicode-tokens-show-controls (&optional arg) "Toggle variable `unicode-tokens-show-controls'. With ARG, turn on iff positive." (interactive "P") (setq unicode-tokens-show-controls (if (null arg) (not unicode-tokens-show-controls) (> (prefix-numeric-value arg) 0))) (when unicode-tokens-show-controls (remove-from-invisibility-spec 'unicode-tokens-show-controls)) (when (not unicode-tokens-show-controls) (add-to-invisibility-spec 'unicode-tokens-show-controls)) (redraw-display)) (defun unicode-tokens-control-char (_name s &rest props) `(,(format unicode-tokens-control-char-format-regexp (regexp-quote s)) (1 '(face nil invisible unicode-tokens-show-controls) prepend) ;; simpler but buggy with font-lock-prepend-text-property: ;; (2 ',(unicode-tokens-symbs-to-props props t) prepend) (2 (unicode-tokens-prepend-text-properties-in-match ',(unicode-tokens-symbs-to-props props t) 2) prepend) )) (defun unicode-tokens-control-region (_name start end &rest props) `(,(format unicode-tokens-control-region-format-regexp (regexp-quote start) (regexp-quote end)) (1 '(face nil invisible unicode-tokens-show-controls) prepend) ;; simpler but buggy with font-lock-prepend-text-property: ;; (2 ',(unicode-tokens-symbs-to-props props t) prepend) (2 (unicode-tokens-prepend-text-properties-in-match ',(unicode-tokens-symbs-to-props props t) 2) prepend) (3 '(face nil invisible unicode-tokens-show-controls) prepend) )) (defun unicode-tokens-control-font-lock-keywords () (append (mapcar (lambda (args) (apply #'unicode-tokens-control-char args)) unicode-tokens-control-characters) (mapcar (lambda (args) (apply #'unicode-tokens-control-region args)) unicode-tokens-control-regions))) ;; ;; Shortcuts for typing, using quail ;; (defvar unicode-tokens-use-shortcuts t "Non-nil means use `unicode-tokens-shortcut-alist' if set.") (defun unicode-tokens-use-shortcuts (&optional arg) "Toggle variable `unicode-tokens-use-shortcuts'. With ARG, turn on iff positive." (interactive "P") (setq unicode-tokens-use-shortcuts (if (null arg) (not unicode-tokens-use-shortcuts) (> (prefix-numeric-value arg) 0))) (if unicode-tokens-use-shortcuts (set-input-method "Unicode tokens") (set-input-method nil))) (quail-define-package "Unicode tokens" "UTF-8" "u" t "Input method for tokens or unicode characters, application specific short-cuts" nil t nil nil nil nil nil ; max shortest, could try t nil nil nil t) (defun unicode-tokens-map-ordering (s1 s2) "Ordering on (car S1, car S2): order longer strings first." (>= (length (car s1)) (length (car s2)))) ; core dump caused when quail active, but not by quail. ;(defun unicode-tokens-shortcut-will-crash-emacs (ustring) ; "Work around a nasty Emacs bug that causes a core dump." ; (> 1 (length ustring))) (defun unicode-tokens-quail-define-rules () "Define the token and shortcut input rules. Calculated from `unicode-tokens-token-name-alist' and `unicode-tokens-shortcut-alist'." (eval `(quail-define-rules ,@(mapcar (lambda (x) (let ((shortcut (car x)) (ustring (cdr x))) (list shortcut (vector ustring)))) (sort (copy-sequence unicode-tokens-shortcut-alist) #'unicode-tokens-map-ordering))) t)) ;; ;; User-level functions ;; (defun unicode-tokens-insert-token (tok) "Insert symbolic token named TOK, giving a message." (interactive (list (completing-read "Insert token: " unicode-tokens-hash-table))) (let ((ins (format unicode-tokens-token-format tok))) (insert ins) (message "Inserted %s" ins))) (defun unicode-tokens-annotate-region (name) "Annotate region with region markup tokens for scheme NAME. Available annotations chosen from `unicode-tokens-control-regions'." (interactive (let ((completion-ignore-case t)) (list (completing-read "Annotate region with: " unicode-tokens-control-regions nil 'requirematch)))) (cl-assert (assoc name unicode-tokens-control-regions)) (let* ((entry (assoc name unicode-tokens-control-regions)) (beg (region-beginning)) (end (region-end)) (begtok (format unicode-tokens-control-region-format-start (nth 1 entry))) (endtok (format unicode-tokens-control-region-format-end (nth 2 entry)))) (when (> beg end) (setq beg end) (setq end (region-beginning))) (goto-char beg) (insert begtok) (goto-char (+ end (- (point) beg))) (insert endtok))) (defun unicode-tokens-insert-control (name) "Insert a control symbol sequence. NAME is from `unicode-tokens-control-characters'." (interactive (list (completing-read "Insert control symbol: " unicode-tokens-control-characters nil 'requirematch))) (cl-assert (assoc name unicode-tokens-control-characters)) (insert (format unicode-tokens-control-char-format (cadr (assoc name unicode-tokens-control-characters))))) (defun unicode-tokens-insert-uchar-as-token (char) "Insert CHAR as a symbolic token, if possible." (let ((tok (gethash char unicode-tokens-uchar-hash-table))) (when tok (unicode-tokens-insert-token tok)))) (defun unicode-tokens-delete-token-near-point () "Delete the token near point; try first before point, then after." (interactive) (if (or (re-search-backward unicode-tokens-token-match-regexp (save-excursion (beginning-of-line) (point)) t) (re-search-forward unicode-tokens-token-match-regexp (save-excursion (end-of-line) (point)) t)) (kill-region (match-beginning 0) (match-end 0)))) (defun unicode-tokens-delete-backward-char (&optional arg) "Delete the last ARG visually presented characters. This accounts for tokens having a single character presentation but multiple characters in the underlying buffer." (interactive "p") (if arg (while (> arg 0) (unicode-tokens-delete-backward-1) (setq arg (1- arg))) (unicode-tokens-delete-backward-1))) (defun unicode-tokens-delete-char (&optional arg) "Delete the next ARG visually presented characters. This accounts for tokens having a single character presentation but multiple characters in the underlying buffer." (interactive "p") (if arg (while (> arg 0) (unicode-tokens-delete-1) (setq arg (1- arg))) (unicode-tokens-delete-1))) (defun unicode-tokens-delete-backward-1 () "Delete the last visually presented character. This accounts for tokens having a single character presentation but multiple characters in the underlying buffer." (let (tokst tokend) (save-match-data (save-excursion (setq tokst (re-search-backward unicode-tokens-token-match-regexp (save-excursion (beginning-of-line) (point)) t)) (setq tokend (match-end 0)))) ;(message "End is: %d and point is: %d" tokend (point)) (if (and tokst (= (point) tokend)) (delete-region tokst tokend) (delete-char -1)))) (defun unicode-tokens-delete-1 () "Delete the following visually presented character. This accounts for tokens having a single character presentation but multiple characters in the underlying buffer." (let (tokend) (save-match-data (save-excursion (if (looking-at unicode-tokens-token-match-regexp) (setq tokend (match-end 0))))) (if tokend (delete-region (point) tokend) (delete-char 1)))) ;; TODO: behaviour with unknown tokens not good. Should ;; use separate regexp for matching tokens known or not known. (defun unicode-tokens-prev-token () "Return the token before point, matching with `unicode-tokens-token-match-regexp'." (let ((match (re-search-backward unicode-tokens-token-match-regexp (save-excursion (beginning-of-line 0) (point)) t))) (if match (match-string 1)))) (defun unicode-tokens-rotate-token-forward (&optional n) "Rotate the token before point by N steps in the table." (interactive "p") (if (> (point) (point-min)) (save-match-data (let (;; (pos (point)) (token (unicode-tokens-prev-token))) (when (not token) (goto-char (point)) (error "Cannot find token before point")) (when token (let* ((tokennumber (cl-search (list token) unicode-tokens-token-list :test #'equal)) (numtoks (hash-table-count unicode-tokens-hash-table)) (newtok (if tokennumber (nth (mod (+ tokennumber (or n 1)) numtoks) unicode-tokens-token-list)))) (when newtok (delete-region (match-beginning 0) (match-end 0)) (insert (format unicode-tokens-token-format newtok))) (when (not newtok) ;; FIXME: currently impossible case (message "Token not in tables: %s" token)))))))) (defun unicode-tokens-rotate-token-backward (&optional n) "Rotate the token before point, by -N steps in the token list." (interactive "p") (unicode-tokens-rotate-token-forward (if n (- n) -1))) (defun unicode-tokens-replace-shortcut-match (&rest _ignore) "Subroutine for `unicode-tokens-replace-shortcuts'." (let* ((match (match-string-no-properties 0)) (repl (if match (cdr-safe (assoc match unicode-tokens-shortcut-replacement-alist))))) (if repl (regexp-quote repl)))) ;; handy for legacy Isabelle files, probably not useful in general. (defun unicode-tokens-replace-shortcuts () "Query-replace shortcuts in the buffer with compositions they expand to. Starts from point." (interactive) (let ((shortcut-regexp (regexp-opt (mapcar #'car unicode-tokens-shortcut-replacement-alist)))) ;; override the display of the regexp because it's huge! ;; (doesn't help with C-h: need way to programmatically show string) (cl-flet ((query-replace-descr (str) (if (eq str shortcut-regexp) "shortcut" str))) (perform-replace shortcut-regexp (cons 'unicode-tokens-replace-shortcut-match nil) t t nil)))) (defun unicode-tokens-replace-unicode-match (&rest _ignore) "Subroutine for `unicode-tokens-replace-unicode'." (let* ((useq (match-string-no-properties 0)) (token (gethash useq unicode-tokens-uchar-hash-table))) (if token (regexp-quote (format unicode-tokens-token-format token))))) (defun unicode-tokens-replace-unicode () "Query-replace unicode seq. in the buffer with tokens having same appearance. Starts from point." (interactive) (let ((uchar-regexp unicode-tokens-uchar-regexp)) ;; override the display of the regexp because it's huge! ;; (doesn't help with C-h: need way to programmatically show string) (cl-flet ((query-replace-descr (str) (if (eq str uchar-regexp) "unicode presentation" str))) (perform-replace uchar-regexp (cons 'unicode-tokens-replace-unicode-match nil) t t nil)))) ;; ;; Token and shortcut tables ;; (defun unicode-tokens-copy-token (tokname) "Copy the token TOKNAME into the kill ring." (interactive "s") (kill-new (format unicode-tokens-token-format tokname) (eq last-command 'unicode-tokens-copy-token))) (define-button-type 'unicode-tokens-list 'help-echo "mouse-2, RET: copy this character" 'face nil 'action #'(lambda (button) (unicode-tokens-copy-token (button-get button 'unicode-token)))) (defun unicode-tokens-list-tokens () "Show a buffer of all tokens." (interactive) (with-output-to-temp-buffer "*Unicode Tokens List*" (with-current-buffer standard-output (make-local-variable 'unicode-tokens-show-symbols) (setq unicode-tokens-show-symbols nil) (unicode-tokens-mode) (setq tab-width 7) (insert "Hover to see token. Mouse-2 or RET to copy into kill ring.\n") (let ((count 10) (toks unicode-tokens-token-list) tok) ;; display in originally given order (while (or (/= 1 (mod count 10)) toks) (unless (null toks) (setq tok (car toks))) (if (/= 0 (mod count 10)) (insert "\t") (insert "\n") (unless (null toks) (insert (format "%4d. " (/ count 10)))) (if (= 0 (mod count 20)) (overlay-put (make-overlay (save-excursion (forward-line -1) (point)) (point)) 'face 'header-line)) (insert " ")) (cl-incf count) (if (null toks) (insert " ") (insert-text-button (format unicode-tokens-token-format tok) :type 'unicode-tokens-list 'unicode-token tok) (setq toks (cdr toks)))))))) (defun unicode-tokens-list-shortcuts () "Show a buffer of all the shortcuts available." (interactive) (with-output-to-temp-buffer "*Unicode Tokens Shortcuts*" (with-current-buffer standard-output (make-local-variable 'unicode-tokens-show-symbols) (setq unicode-tokens-show-symbols nil) (unicode-tokens-mode) (let (grey start) (dolist (short unicode-tokens-shortcut-alist) (setq start (point)) (insert "Typing " (car short) "\tinserts \t" (cdr short) "\n") (if (setq grey (not grey)) (overlay-put (make-overlay start (point)) 'face 'header-line))))))) (defalias 'unicode-tokens-list-unicode-chars #'unicode-chars-list-chars) (defun unicode-tokens-encode-in-temp-buffer (str fn) "Compute an encoded version of STR and call FN onto." (with-temp-buffer (insert str) (goto-char (point-min)) (while (re-search-forward unicode-tokens-token-match-regexp nil t) ;; TODO: interpret more exotic compositions here (let* ((tstart (match-beginning 0)) (tend (match-end 0)) (comp (car-safe (gethash (match-string 1) unicode-tokens-hash-table)))) (when comp (delete-region tstart tend) ;; TODO: improve this: interpret vector, strip tabs (insert comp)))) ;; gross approximation to compose-region (funcall fn (point-min) (point-max)))) (defun unicode-tokens-encode (beg end) "Return a unicode encoded version of the presentation in region BEG..END." (unicode-tokens-encode-in-temp-buffer (buffer-substring-no-properties beg end) 'buffer-substring)) ;;;###autoload (defun unicode-tokens-encode-str (str) "Return a unicode encoded version presentation of STR." (unicode-tokens-encode-in-temp-buffer str 'buffer-substring)) (defun unicode-tokens-copy (beg end) "Copy presentation of region between BEG and END. This is an approximation; it makes assumptions about the behaviour of symbol compositions, and will lose layout information." (interactive "r") ;; cf kill-ring-save, uncode-tokens-font-lock-compose-symbol (unicode-tokens-encode-in-temp-buffer (buffer-substring-no-properties beg end) 'copy-region-as-kill)) (defun unicode-tokens-paste () "Paste text from clipboard, converting Unicode to tokens where possible." (interactive) (let ((start (point)) end) ;; da: notice bug in Emacs 23 snapshot (at least) on Ubuntu 9.04 ;; that gives wrong default to x-select-enable-clipboard ;; need: (setq x-select-enable-clipboard t) (clipboard-yank) (setq end (point-marker)) (while (re-search-backward unicode-tokens-uchar-regexp start t) (let* ((useq (match-string 0)) (token (gethash useq unicode-tokens-uchar-hash-table)) (pos (point))) (when token (replace-match (format unicode-tokens-token-format token) t t) (goto-char pos)))) (goto-char end) (set-marker end nil))) (defvar unicode-tokens-highlight-unicode nil "Non-nil to highlight Unicode characters.") (defconst unicode-tokens-unicode-highlight-patterns '(("[^\000-\177]" (0 'unicode-tokens-highlight-face t))) "Font lock patterns for highlighting Unicode tokens.") (defun unicode-tokens-highlight-unicode () "Hilight Unicode characters in the buffer. Toggles highlighting of Unicode characters used in the buffer beyond the legacy 8-bit character set codes. This is useful to manually determine if a buffer contains Unicode or tokenised symbols." (interactive) (setq unicode-tokens-highlight-unicode (not unicode-tokens-highlight-unicode)) (unicode-tokens-highlight-unicode-setkeywords) (if (fboundp 'font-lock-flush) ;Emacs-25 (font-lock-flush) (with-no-warnings (font-lock-fontify-buffer)))) (defun unicode-tokens-highlight-unicode-setkeywords () "Adjust font lock keywords according to variable `unicode-tokens-highlight-unicode'." (if unicode-tokens-highlight-unicode (font-lock-add-keywords nil unicode-tokens-unicode-highlight-patterns) (font-lock-remove-keywords nil unicode-tokens-unicode-highlight-patterns))) ;; ;; Minor mode ;; (defun unicode-tokens-initialise () "Perform initialisation for Unicode Tokens minor mode. This function calculates `font-lock-keywords' and other configuration variables." (interactive) (unicode-tokens-copy-configuration-variables) (let ((flks (unicode-tokens-font-lock-keywords))) (put 'unicode-tokens-font-lock-keywords major-mode flks) (unicode-tokens-quail-define-rules) (unicode-tokens-define-menu) flks)) ;; not as expected ;; (defun unicode-tokens-restart () ;; (interactive) ;; (unicode-tokens-mode 0) ;; (put 'unicode-tokens-font-lock-keywords major-mode nil) ;; (setq font-lock-set-defaults nil) ;; (unicode-tokens-mode 1)) (defvar unicode-tokens-mode-map (make-sparse-keymap) "Key map used for Unicode Tokens mode.") (defvar unicode-tokens-display-table (let ((disptab (make-display-table))) (set-display-table-slot disptab 'selective-display (vector ?\ #x0022ef ?\ )) disptab) "Display table for Unicode Tokens mode. Alters ellipsis character.") (define-minor-mode unicode-tokens-mode "Toggle Tokens mode for current buffer. With optional argument ARG, turn Tokens mode on if ARG is positive, otherwise turn it off. In Unicode Tokens mode (Utoks appears in the modeline), a sequence of characters in the buffer (a token) may be presented instead as a Unicode character. The underlying buffer contents is not changed, only what is presented on the display. Other tokens may be used to control layout, for example, enabling sub/super scripts, bold and italic fonts, etc. Keyboard shortcut sequences for entering tokens quickly can be defined. Tokens mode needs configuration with a set of tokens, their presentation forms, and keyboard shortcuts. See documentation in `unicode-tokens.el' for more information. Commands available are: \\{unicode-tokens-mode-map}" :keymap unicode-tokens-mode-map :init-value nil :lighter " Utoks" :group 'unicode-tokens (let ((flks (get 'unicode-tokens-font-lock-keywords major-mode))) (when unicode-tokens-mode (unless flks (setq flks (unicode-tokens-initialise))) ;; make sure buffer can display 16 bit chars (if (and (fboundp 'set-buffer-multibyte) (not (buffer-base-buffer))) (set-buffer-multibyte t)) (make-local-variable 'font-lock-extra-managed-props) (when (not unicode-tokens-show-controls) (add-to-invisibility-spec 'unicode-tokens-show-controls)) (make-local-variable 'unicode-tokens-highlight-unicode) ;; a convention: ;; - set default for font-lock-extra-managed-props ;; as property on major mode symbol (ordinarily nil). (font-lock-add-keywords nil flks) (setq font-lock-extra-managed-props (get 'font-lock-extra-managed-props major-mode)) (mapc (lambda (p) (add-to-list 'font-lock-extra-managed-props p)) unicode-tokens-font-lock-extra-managed-props) (unicode-tokens-highlight-unicode-setkeywords) (if (fboundp 'font-lock-flush) ;Emacs-25 (font-lock-flush) (with-no-warnings (font-lock-fontify-buffer))) ;; experimental: this may be rude for non-nil standard tables (setq buffer-display-table unicode-tokens-display-table) (if unicode-tokens-use-shortcuts (set-input-method "Unicode tokens")) ;; adjust maths menu to insert tokens (set (make-local-variable 'maths-menu-filter-predicate) (lambda (uchar) (gethash (char-to-string uchar) unicode-tokens-uchar-hash-table))) (set (make-local-variable 'maths-menu-tokenise-insert) (lambda (uchar) (unicode-tokens-insert-token (gethash (char-to-string uchar) unicode-tokens-uchar-hash-table))))) (when (not unicode-tokens-mode) (remove-from-invisibility-spec 'unicode-tokens-show-controls) (when flks (unless (fboundp 'font-lock-flush) ;Emacs-25 (font-lock-unfontify-buffer)) (setq font-lock-extra-managed-props (get 'font-lock-extra-managed-props major-mode)) (setq font-lock-set-defaults nil) ; force font-lock-set-defaults to reinit (if (fboundp 'font-lock-flush) ;Emacs-25 (font-lock-flush) (with-no-warnings (font-lock-fontify-buffer))) (set-input-method nil)) ;; experimental: this may be rude for non-nil standard tables (setq buffer-display-table nil) ;; Remove hooks from maths menu (kill-local-variable 'maths-menu-filter-predicate) (kill-local-variable 'maths-menu-tokenise-insert)))) ;; ;; Font selection ;; (when (fboundp 'ns-respond-to-change-font) ;; A nasty hack to ns-win.el for Mac OS X support ;; Tricky because we get a callback on font changes, but not when ;; the window is closed. How do we know when user is finished? (when (not (fboundp 'old-ns-respond-to-change-font)) (fset 'old-ns-respond-to-change-font (symbol-function 'ns-respond-to-change-font))) (when (not (fboundp 'old-ns-popup-font-panel)) (fset 'old-ns-popup-font-panel (symbol-function 'ns-popup-font-panel))) (defvar unicode-tokens-respond-to-change-font nil) (defun ns-respond-to-change-font (&rest args) (interactive) (cond (unicode-tokens-respond-to-change-font (unicode-tokens-set-font-var-aux unicode-tokens-respond-to-change-font (with-no-warnings ns-input-font))) (t (apply #'old-ns-respond-to-change-font args)))) (defun ns-popup-font-panel (&rest args) (setq unicode-tokens-respond-to-change-font nil) (with-no-warnings (apply #'old-ns-popup-font-panel args))) (defun unicode-tokens-popup-font-panel (fontvar) (setq unicode-tokens-respond-to-change-font fontvar) (with-no-warnings (old-ns-popup-font-panel))) ) ;; parameterised version of function from menu-bar.el (Emacs 23.1) ;; this now copes with Emacs 23.1, Emacs 22, Mac OS X Emacs 23.1. (defun unicode-tokens-set-font-var (fontvar) "Interactively select a font for FONTVAR." (interactive) (if (fboundp 'ns-popup-font-panel) (with-no-warnings (unicode-tokens-popup-font-panel fontvar)) (let (;; spec (font (cond ((fboundp 'x-select-font) (x-select-font)) ((fboundp 'mouse-select-font) (mouse-select-font)) (t (unicode-tokens-mouse-set-font))))) (unicode-tokens-set-font-var-aux fontvar font)))) (defun unicode-tokens-set-font-var-aux (fontvar font) "A subroutine of `unicode-tokens-set-font-var'." (when font ;; Trac #311 - sometimes (on Linux/xft) :font doesn't work but ;; :family does. (condition-case nil (set-face-attribute fontvar (selected-frame) ;; da: don't try to reset these for token fonts. ;; :weight 'normal :slant 'normal :width 'normal :font font) (error (set-face-attribute fontvar (selected-frame) :width 'normal :family font))) (let ((font-object (face-attribute fontvar :font)) spec) (set-face-attribute fontvar t :font font-object) (setq spec (list (list t (face-attr-construct fontvar)))) (put fontvar 'customized-face spec) (custom-push-theme 'theme-face fontvar 'user 'set spec) (put fontvar 'face-modified nil)) ;; da: add this to make sure fonts set by font lock are altered (dolist (f (frame-list)) (and (display-graphic-p f) (dolist (w (window-list f)) (with-current-buffer (window-buffer w) ;; FIXME: Why should we need to re-fontify those buffers? We've ;; only changed the definition of some faces, whereas font-lock ;; only choose which faces to use: the two are independent! (when font-lock-mode (font-lock-fontify-buffer)))))))) ;; based on mouse-set-font from mouse.el in Emacs 22.2.1 (defun unicode-tokens-mouse-set-font () "Select an Emacs font from a list of known good fonts and fontsets." (unless (display-multi-font-p) (error "Cannot change fonts on this display")) (car-safe ; just choose first ; (original cycles through trying set-default-font (x-popup-menu (if (listp last-nonmenu-event) last-nonmenu-event (list '(0 0) (selected-window))) ;; Append list of fontsets currently defined. (append x-fixed-font-alist (list (generate-fontset-menu)))))) (defsubst unicode-tokens-face-font-sym (fontsym) "Return the symbol unicode-tokens-FONTSYM-font-face." (intern (concat "unicode-tokens-" (symbol-name fontsym) "-font-face"))) (defun unicode-tokens-set-font-restart (fontsym) "Open a dialog to set the font for FONTSYM, and reinitialise." (let ((facevar (unicode-tokens-face-font-sym fontsym))) (unicode-tokens-set-font-var facevar) (unicode-tokens-initialise) ;; FIXME: Why do we need this here? (font-lock-fontify-buffer))) ;; ;; interface to custom ;; (defun unicode-tokens-save-fonts () "Save the customized font variables." ;; save all customized faces (tricky to do less) (interactive) (apply #'unicode-tokens-custom-save-faces (mapcar #'unicode-tokens-face-font-sym unicode-tokens-fonts))) (defun unicode-tokens-custom-save-faces (&rest faces) "Save custom faces FACES." (dolist (symbol faces) (let ((face (get symbol 'customized-face))) ;; See customize-save-customized; adjust properties so ;; that custom-save-all will save the face. (when face (put symbol 'saved-face face) (custom-push-theme 'theme-value symbol 'user 'set face) (put symbol 'customized-face nil)))) (custom-save-all)) ;; ;; Key bindings ;; (define-key unicode-tokens-mode-map [remap delete-backward-char] #'unicode-tokens-delete-backward-char) (define-key unicode-tokens-mode-map [remap delete-char] #'unicode-tokens-delete-char) ;; support delete selection mode (put 'unicode-tokens-delete-backward-char 'delete-selection 'supersede) (put 'unicode-tokens-delete-char 'delete-selection 'supersede) (defvar unicode-tokens-quail-translation-keymap (let ((quail-current-package (assoc "Unicode tokens" quail-package-alist))) (quail-translation-keymap))) ;; FIXME: does this work? (define-key unicode-tokens-quail-translation-keymap [remap quail-delete-last-char] #'unicode-tokens-quail-delete-last-char) (defun unicode-tokens-quail-delete-last-char () (interactive) (if unicode-tokens-mode (if (= (length quail-current-key) 1) (progn (quail-abort-translation) (unicode-tokens-delete-backward-char)) (quail-delete-last-char)) (quail-delete-last-char))) ; (setq quail-current-key (substring quail-current-key 0 -1)) ; (quail-delete-region) ; (quail-update-translation (quail-translate-key)))) (define-key unicode-tokens-mode-map [(control ?,)] #'unicode-tokens-rotate-token-backward) (define-key unicode-tokens-mode-map [(control ?.)] #'unicode-tokens-rotate-token-forward) (define-key unicode-tokens-mode-map [(control c) (control t) (control t)] #'unicode-tokens-insert-token) (define-key unicode-tokens-mode-map [(control c) (control backspace)] #'unicode-tokens-delete-token-near-point) (define-key unicode-tokens-mode-map [(control c) (control t) (control r)] #'unicode-tokens-annotate-region) (define-key unicode-tokens-mode-map [(control c) (control t) (control e)] #'unicode-tokens-insert-control) (define-key unicode-tokens-mode-map [(control c) (control t) (control z)] #'unicode-tokens-show-symbols) (define-key unicode-tokens-mode-map [(control c) (control t) (control t)] #'unicode-tokens-show-controls) ;; ;; Menu ;; (defun unicode-tokens-customize-submenu () (mapcar (lambda (cv) (let ((v (cadr cv))) (vector (car cv) (lambda () (interactive) (customize-variable v))))) unicode-tokens-tokens-customizable-variables)) (defun unicode-tokens-define-menu () "Define Tokens menu." (easy-menu-define unicode-tokens-menu unicode-tokens-mode-map "Tokens menu" (cons "Tokens" (list ["Insert Token..." unicode-tokens-insert-token] ["Next Token" unicode-tokens-rotate-token-forward] ["Prev Token" unicode-tokens-rotate-token-backward] ["Delete Token" unicode-tokens-delete-token-near-point] (cons "Format Char" (mapcar (lambda (fmt) (vector (car fmt) (lambda () (interactive) (unicode-tokens-insert-control (car fmt))) :help (concat "Format next item as " (downcase (car fmt))))) unicode-tokens-control-characters)) (cons "Format Region" (mapcar (lambda (fmt) (vector (car fmt) (lambda () (interactive) (unicode-tokens-annotate-region (car fmt))) :help (concat "Format region as " (downcase (car fmt))) :active 'mark-active)) unicode-tokens-control-regions)) "---" ["List Tokens" unicode-tokens-list-tokens] ["List Shortcuts" unicode-tokens-list-shortcuts] ["List Unicode Characters" unicode-tokens-list-unicode-chars] "---" ["Copy As Unicode" unicode-tokens-copy :active 'mark-active :help "Copy presentation form of text from buffer, converting tokens to Unicode"] ["Paste From Unicode" unicode-tokens-paste :active (and kill-ring (not buffer-read-only)) :help "Paste from clipboard, converting Unicode to tokens where possible"] ["Replace Shortcuts" unicode-tokens-replace-shortcuts :help "Query-replace shortcut sequences with compositions they stand for, starting from point"] ["Replace Unicode" unicode-tokens-replace-unicode :help "Query-replace Unicode characters with tokens where possible, starting from point"] "---" ["Reveal Control Tokens" unicode-tokens-show-controls :style toggle :selected unicode-tokens-show-controls :active (or unicode-tokens-control-region-format-regexp unicode-tokens-control-char-format-regexp) :help "Prevent hiding of control tokens"] ["Reveal Symbol Tokens" unicode-tokens-show-symbols :style toggle :selected unicode-tokens-show-symbols :help "Show tokens for symbols"] ["Highlight Real Unicode Chars" unicode-tokens-highlight-unicode :style toggle :selected unicode-tokens-highlight-unicode :help "Hightlight non-8bit characters in buffer which are saved as Unicode"] ["Enable Shortcuts" unicode-tokens-use-shortcuts :style toggle :selected unicode-tokens-use-shortcuts :active unicode-tokens-shortcut-alist :help "Use short cuts for typing tokens"] ["Add Token Hovers" unicode-tokens-toggle-add-help-echo :style toggle :selected unicode-tokens-add-help-echo :help "Use hover popups (or minibuffer messages) to show underlying tokens"] "---" (cons "Customize" (unicode-tokens-customize-submenu)) (cons "Set Font" (append (mapcar (lambda (var) (vector (upcase-initials (symbol-name var)) (lambda () (interactive) (unicode-tokens-set-font-restart var)) :help (concat "Set the " (symbol-name var) " font"))) unicode-tokens-fonts) (list "----" ["Save Fonts" unicode-tokens-save-fonts :help "Save the customized font choices"] ["Make Fontsets" (lambda () (interactive) (require 'pg-fontsets)) :active (not (featurep 'pg-fontsets)) :help "Define fontsets (for Options->Set fontsets)" :visible (< emacs-major-version 23) ; not useful on 23, ;; at least when font menu provided. Drawback: this ;; is done too late: displayable tokens have already been ;; chosen now, before fontsets generated. ;; Never mind: non-issue with platform fonts menu. ]))))))) (provide 'unicode-tokens) ;;; unicode-tokens.el ends here PG-4.5/obsolete/000077500000000000000000000000001426357011200135055ustar00rootroot00000000000000PG-4.5/obsolete/demoisa/000077500000000000000000000000001426357011200151265ustar00rootroot00000000000000PG-4.5/obsolete/demoisa/README000066400000000000000000000035741426357011200160170ustar00rootroot00000000000000Example Proof General instance for Isabelle Written by David Aspinall. Status: demonstration, only works for obsolete Isabelle versions ======================================== "Isabelle Proof General in 30 setqs" This is a whittled down version of Isabelle Proof General, supplied as an (almost) minimal demonstration of how to instantiate Proof General to a particular proof assistant. You can use this as a template to get support for a new assistant going. (I did for HOL Proof General). This mode uses the unadulterated terminal interface of Isabelle, to demonstrate that hacking the proof assistant is not necessary to get basic features working. And it really works! You you get a toolbar, menus, short-cut keys, script management for multiple files, a function menu, ability to run proof assistant remotely, etc, etc. To try it out, set in the shell PROOFGENERAL_ASSISTANTS=demoisa before invoking Emacs. (Of course, you need Isabelle installed). What's missing? 1. A few handy commands (e.g. proof-find-theorems-command) 2. Syntax settings and highlighting for proof scripts 3. Indentation for proof scripts 4. Special markup characters in output for robustness 5. True script management for multiple files (automatic mode is used) 6. Proof by pointing How easy is it to add all that? 1. Trivial. 2. A table specifying syntax codes for characters (strings, brackets, etc) and some regexps; depends on complexity of syntax. 3. A bit of elisp to scan script; depends on complexity of syntax. 4. Needs hacking in the proof assistant: how hard is to hack your assistant to do this? 5. Depends on file management mechanism in the prover, may need hacking there to send messages. But automatic multiple files may be all you need anyway. 6. Non trivial (but worth a go). See demoisa.el and demoisa-easy.el for more details. ======================================== $Id$ PG-4.5/obsolete/demoisa/demoisa-easy.el000066400000000000000000000045751426357011200200430ustar00rootroot00000000000000;; demoisa-easy.el --- Example Proof General instance for Isabelle ;; ;; Copyright (C) 1999 LFCS Edinburgh. ;; ;; Author: David Aspinall ;; ;; $Id$ ;; ;; This is an alternative version of demoisa.el which uses the ;; proof-easy-config macro to do most of the work. ;; ;; This mechanism is recommended for new instantiations of ;; Proof General since it follows a regular pattern, and we can more ;; easily adapt it in the future to new versions of Proof General ;; using alternative architectures. It is still easy to augment ;; with additional elisp functions and other settings. ;; ;; The most important setting is `proof-shell-annotated-prompt-regexp' ;; used to recognize prompt texts from the prover. ;; ;; See demoisa.el and the Adapting Proof General manual for more ;; documentation. Please do read the documentation of the variables ;; to understand how things work. ;; ;; To test this file you must rename it demoisa.el. ;; (require 'proof-site) (proof-ready-for-assistant 'demoisa) (require 'proof) (require 'proof-easy-config) ; easy configure mechanism (proof-easy-config 'demoisa "Isabelle Demo" proof-prog-name "isabelle" proof-terminal-string ";" proof-script-comment-start "(*" proof-script-comment-end "*)" proof-goal-command-regexp "^Goal" proof-save-command-regexp "^qed" proof-goal-with-hole-regexp "qed_goal \"\\(\\(.*\\)\\)\"" proof-save-with-hole-regexp "qed \"\\(\\(.*\\)\\)\"" proof-non-undoables-regexp "undo\\|back" proof-goal-command "Goal \"%s\";" proof-save-command "qed \"%s\";" proof-kill-goal-command "Goal \"PROP no_goal_set\";" proof-showproof-command "pr()" proof-undo-n-times-cmd "pg_repeat undo %s;" proof-auto-multiple-files t proof-shell-cd-cmd "cd \"%s\"" proof-shell-interrupt-regexp "Interrupt" proof-shell-start-goals-regexp "Level [0-9]" proof-shell-end-goals-regexp "val it" proof-shell-quit-cmd "quit();" proof-assistant-home-page "http://www.cl.cam.ac.uk/Research/HVG/Isabelle/" proof-shell-annotated-prompt-regexp "^\\(val it = () : unit\n\\)?\\(ML\\)?> " proof-shell-error-regexp "\\*\\*\\*\\|^.*Error:\\|^uncaught exception \\|^Exception- " proof-shell-init-cmd "fun pg_repeat f 0 = () | pg_repeat f n = (f(); pg_repeat f (n-1));" proof-shell-proof-completed-regexp "^No subgoals!" proof-shell-eager-annotation-start "^\\[opening \\|^###\\|^Reading") (provide 'demoisa) ;;; demoisa-easy.el ends here PG-4.5/obsolete/demoisa/demoisa.el000066400000000000000000000106471426357011200171010ustar00rootroot00000000000000;; demoisa.el Example Proof General instance for Isabelle ;; ;; Copyright (C) 1999 LFCS Edinburgh. ;; ;; Author: David Aspinall ;; ;; $Id$ ;; ;; ================================================================= ;; ;; See README in this directory for an introduction. ;; ;; NEW INSTANCES: please use demoisa-easy.el as a basis instead. ;; ;; Basic configuration is controlled by one line in `proof-site.el'. ;; It has this line in proof-assistant-table: ;; ;; (demoisa "Isabelle Demo" "\\.ML\\'") ;; ;; From this it loads this file "demoisa/demoisa.el" whenever ;; a .ML file is visited, and sets the mode to `demoisa-mode' ;; (defined below). ;; ;; I've called this instance "Isabelle Demo Proof General" just to ;; avoid confusion with the real "Isabelle Proof General" in case the ;; demo gets loaded by accident. ;; ;; To make the line above take precedence over the real Isabelle mode ;; later in the table, set PROOFGENERAL_ASSISTANTS=demoisa in the ;; shell before starting Emacs (or customize proof-assistants). ;; (require 'proof) ; load generic parts (require 'pg-goals) (require 'pg-response) ;; ======== User settings for Isabelle ======== ;; ;; Defining variables using customize is pretty easy. ;; You should do it at least for your prover-specific user options. ;; ;; proof-site provides us with two customization groups ;; automatically: (based on the name of the assistant) ;; ;; 'isabelledemo - User options for Isabelle Demo Proof General ;; 'isabelledemo-config - Configuration of Isabelle Proof General ;; (constants, but may be nice to tweak) ;; ;; The first group appears in the menu ;; ProofGeneral -> Customize -> Isabelledemo ;; The second group appears in the menu: ;; ProofGeneral -> Internals -> Isabelledemo config ;; (defcustom isabelledemo-prog-name "isabelle" "*Name of program to run Isabelle." :type 'file :group 'isabelledemo) (defcustom isabelledemo-web-page "http://www.cl.cam.ac.uk/Research/HVG/isabelle.html" "URL of web page for Isabelle." :type 'string :group 'isabelledemo-config) ;; ;; ======== Configuration of generic modes ======== ;; (defun demoisa-config () "Configure Proof General scripting for Isabelle." (setq proof-terminal-string ";" proof-script-comment-start "(*" proof-script-comment-end "*)" proof-goal-command-regexp "^Goal" proof-save-command-regexp "^qed" proof-goal-with-hole-regexp "qed_goal \"\\(\\(.*\\)\\)\"" proof-save-with-hole-regexp "qed \"\\(\\(.*\\)\\)\"" proof-non-undoables-regexp "undo\\|back" proof-undo-n-times-cmd "pg_repeat undo %s;" proof-showproof-command "pr()" proof-goal-command "Goal \"%s\";" proof-save-command "qed \"%s\";" proof-kill-goal-command "Goal \"PROP no_goal_set\";" proof-assistant-home-page isabelledemo-web-page proof-prog-name isabelledemo-prog-name proof-auto-multiple-files t)) (defun demoisa-shell-config () "Configure Proof General shell for Isabelle." (setq proof-shell-annotated-prompt-regexp "^\\(val it = () : unit\n\\)?\\(ML\\)?> " proof-shell-cd-cmd "cd \"%s\"" proof-shell-interrupt-regexp "Interrupt" proof-shell-error-regexp "\\*\\*\\*\\|^.*Error:\\|^uncaught exception \\|^Exception- " proof-shell-start-goals-regexp "Level [0-9]" proof-shell-end-goals-regexp "val it" proof-shell-proof-completed-regexp "^No subgoals!" proof-shell-eager-annotation-start "^\\[opening \\|^###\\|^Reading" proof-shell-init-cmd ; define a utility function, in a lib somewhere? "fun pg_repeat f 0 = () | pg_repeat f n = (f(); pg_repeat f (n-1));" proof-shell-quit-cmd "quit();")) ;; ;; ======== Defining the derived modes ======== ;; ;; The derived modes set the variables, then call the ;; -config-done function to complete configuration. (define-derived-mode demoisa-mode proof-mode "Isabelle Demo script" nil (demoisa-config) (proof-config-done)) (define-derived-mode demoisa-shell-mode proof-shell-mode "Isabelle Demo shell" nil (demoisa-shell-config) (proof-shell-config-done)) (define-derived-mode demoisa-response-mode proof-response-mode "Isabelle Demo response" nil (proof-response-config-done)) (define-derived-mode demoisa-goals-mode proof-goals-mode "Isabelle Demo goals" nil (proof-goals-config-done)) ;; A more sophisticated instantiation might set font-lock-keywords to ;; add highlighting, or some of the proof by pointing markup ;; configuration for the goals buffer. (provide 'demoisa) PG-4.5/pghaskell/000077500000000000000000000000001426357011200136435ustar00rootroot00000000000000PG-4.5/pghaskell/pghaskell.el000066400000000000000000000035551426357011200161470ustar00rootroot00000000000000;;; pghaskell.el --- Proof General for Haskell scripts. ;; This file is part of Proof General. ;; Portions © Copyright 1994-2012 David Aspinall and University of Edinburgh ;; Portions © Copyright 2003, 2012, 2014 Free Software Foundation, Inc. ;; Portions © Copyright 2001-2017 Pierre Courtieu ;; Portions © Copyright 2010, 2016 Erik Martin-Dorel ;; Portions © Copyright 2011-2013, 2016-2017 Hendrik Tews ;; Portions © Copyright 2015-2017 Clément Pit-Claudel ;; Author: David Aspinall. ;;; Commentary: ;; ;; This instance of PG is handy just for using script management to ;; cut-and-paste into a buffer running Haskell (ghci) ;; ;; I'm providing this so that tool demonstrators may use it instead of ;; tediously doing cut-and-paste of commands from a file. No history ;; management, and nothing to do with theorem proving really! ;; ;; To use this instance of PG, visit a file with the ".pghci" extension ;; or type ;; ;; M-x pghaskell-mode ;; ;; in an ordinary .h file. (Check that you have enabled the instance ;; in proof-site.el). ;; ;;; Code: (require 'proof-easy-config) (require 'proof-syntax) (proof-easy-config 'pghaskell "PG-Haskell" proof-prog-name "ghci" ;; BELOW HERE TO COMPLETE proof-terminal-string ";;" proof-script-comment-start "(*" proof-script-comment-end "*)" proof-shell-annotated-prompt-regexp "^# " ;; matches interpreter prompts ;; Syntax table suitable for Haskell; see Elisp documentation of `modify-syntax-entry' proof-script-syntax-table-entries '(?\` "\"" ?\$ "." ?\/ "." ?\\ "." ?+ "." ?- "." ?= "." ?% "." ?< "." ?> "." ?\& "." ?. "w" ?_ "w" ?\' "w" ?\| "." ?\* ". 23n" ?\( "()1" ?\) ")(4") ;; next setting is just to prevent warning proof-save-command-regexp proof-no-regexp ) (provide 'pghaskell) ;;; pghaskell.el ends here PG-4.5/pgocaml/000077500000000000000000000000001426357011200133135ustar00rootroot00000000000000PG-4.5/pgocaml/pgocaml.el000066400000000000000000000034701426357011200152630ustar00rootroot00000000000000;;; pgocaml.el --- Proof General for OCaml scripts. ;; This file is part of Proof General. ;; Portions © Copyright 1994-2012 David Aspinall and University of Edinburgh ;; Portions © Copyright 2003, 2012, 2014 Free Software Foundation, Inc. ;; Portions © Copyright 2001-2017 Pierre Courtieu ;; Portions © Copyright 2010, 2016 Erik Martin-Dorel ;; Portions © Copyright 2011-2013, 2016-2017 Hendrik Tews ;; Portions © Copyright 2015-2017 Clément Pit-Claudel ;; Author: David Aspinall ;;; Commentary: ;; ;; This instance of PG is handy just for using script management to ;; cut-and-paste into a buffer running OCaml ;; ;; I'm providing this so that tool demonstrators may use it instead of ;; tediously doing cut-and-paste of commands from a file. No history ;; management, and nothing to do with theorem proving really! ;; ;; To use this instance of PG, visit a file with the ".pgml" extension ;; or type ;; ;; M-x pgocaml-mode ;; ;; in an ordinary .ml file. (Check that you have enabled the instance ;; in proof-site.el). ;; ;;; Code: (require 'proof-easy-config) (require 'proof-syntax) (proof-easy-config 'pgocaml "PG-OCaml" proof-prog-name "ocaml" proof-terminal-string ";;" proof-script-comment-start "(*" proof-script-comment-end "*)" proof-shell-annotated-prompt-regexp "^# " ;; matches interpreter prompts ;; Syntax table suitable for OCaml; see Elisp documentation of `modify-syntax-entry' proof-script-syntax-table-entries '(?\` "\"" ?\$ "." ?\/ "." ?\\ "." ?+ "." ?- "." ?= "." ?% "." ?< "." ?> "." ?\& "." ?. "w" ?_ "w" ?\' "w" ?\| "." ?\* ". 23n" ?\( "()1" ?\) ")(4") ;; next setting is just to prevent warning proof-save-command-regexp proof-no-regexp ) (provide 'pgocaml) ;;; pgocaml.el ends here PG-4.5/pgshell/000077500000000000000000000000001426357011200133275ustar00rootroot00000000000000PG-4.5/pgshell/README000066400000000000000000000013211426357011200142040ustar00rootroot00000000000000Proof General for shell scripts/simple command interpreters. Author: David Aspinall Status: Supported; experimental ==================================================================== This instance of PG is handy just for using script management to cut-and-paste into a buffer running an ordinary shell of some kind. I'm providing this so that tool demonstrators may use it instead of tediously doing cut-and-paste of commands from a file. No history management, and nothing to do with theorem proving really! To use this instance of PG, visit a file with the ".pgsh" extension. You can modify the settings in pgshell.el to suit your application (e.g. run some program other than the shell). Feedback welcome. PG-4.5/pgshell/example.pgsh000066400000000000000000000012131426357011200156420ustar00rootroot00000000000000# This is an example shell script for processing # with the script management of Proof General. # # It demonstrates the usefulness of PG simply for # sending a pre-defined sequence of commands to # some command-line interpreter, here /bin/sh. # # To adjust this for your needs, edit pgshell.el # (or copy and rename it). # # $Id$ # # What time is it? date; # What machine am I on? uname -a; # What files are here? ls -lt; # Notes: # # * Commands have to be terminated by ';'. Alternative is to write # your own scanner to recognize the start of the next command. # # * Undo has no effect, of course, it just navigates in the file. # PG-4.5/pgshell/pgshell.el000066400000000000000000000032351426357011200153120ustar00rootroot00000000000000;;; pgshell.el --- Proof General for shell scripts. ;; This file is part of Proof General. ;; Portions © Copyright 1994-2012 David Aspinall and University of Edinburgh ;; Portions © Copyright 2003, 2012, 2014 Free Software Foundation, Inc. ;; Portions © Copyright 2001-2017 Pierre Courtieu ;; Portions © Copyright 2010, 2016 Erik Martin-Dorel ;; Portions © Copyright 2011-2013, 2016-2017 Hendrik Tews ;; Portions © Copyright 2015-2017 Clément Pit-Claudel ;; Author: David Aspinall. ;;; Commentary: ;; ;; This instance of PG is handy just for using script management to ;; cut-and-paste into a buffer running an ordinary shell of some kind. ;; ;; I'm providing this so that tool demonstrators may use it instead of ;; tediously doing cut-and-paste of commands from a file. No history ;; management, and nothing to do with theorem proving really! ;; ;; To use this instance of PG, visit a file with the ".pgsh" extension. ;; ;; Feedback welcome. ;;; Code: (require 'proof-easy-config) (require 'proof-syntax) (proof-easy-config 'pgshell "PG-Shell" proof-prog-name "/bin/sh" ;; or your program proof-terminal-string ";" ;; end of commands proof-script-comment-start "\#" ;; comments proof-shell-annotated-prompt-regexp "^.*[$] $" ;; matches prompts proof-script-fly-past-comments t ;; nice for single-line ;; Syntax table gets font-locking and editing features for comments. ;; see Elisp documentation of `modify-syntax-entry' proof-script-syntax-table-entries '(?\# "<" ?\n ">") ;; next setting is just to prevent warning proof-save-command-regexp proof-no-regexp ) (provide 'pgshell) ;;; pgshell.el ends here PG-4.5/phox/000077500000000000000000000000001426357011200126475ustar00rootroot00000000000000PG-4.5/phox/phox.el000066400000000000000000000122101426357011200141430ustar00rootroot00000000000000;;; phox.el --- Major mode for the PhoX proof assistant ;; This file is part of Proof General. ;; Copyright © 2017 Christophe Raffalli ;;; Commentary: ;; (require 'proof-site) ;;; Code: (proof-ready-for-assistant 'phox) (require 'proof) (require 'proof-easy-config) ; easy configure mechanism (defconst phox-goal-regexp "\\(prop\\(osition\\)?\\)\\|\\(lem\\(ma\\)?\\)\\|\\(fact\\)\\|\\(cor\\(ollary\\)?\\)\\(theo\\(rem\\)?\\)") (proof-easy-config 'phox "PhoX" proof-prog-name "phox" proof-terminal-string "." proof-script-command-end-regexp"[.][ \n\t\r]" proof-script-comment-start "(*" proof-script-comment-end "*)" proof-script-syntax-table-entries '(?\( "()1" ?\) ")(4" ?* ". 23" ?$ "w" ?_ "w" ?. "w") proof-shell-syntax-table-entries '(?\( "()1" ?\) ")(4" ?* ". 23" ?$ "w" ?_ "w" ?. "w") proof-goal-command-regexp (concat "^" phox-goal-regexp) proof-save-command-regexp "^save" proof-goal-with-hole-regexp (concat "^" phox-goal-regexp "\\(\\([a-zA-Z0-9_$]*\\)\\) ") proof-save-with-hole-regexp "save \\(\\([a-zA-Z0-9_$]*\\)\\).[ \n\t\r]" proof-non-undoables-regexp "\\(undo\\)\\|\\(abort\\)\\|\\(show\\)\\(.*\\)[ \n\t\r]" proof-goal-command "fact \"%s\"." proof-save-command "save \"%s\"." proof-kill-goal-command "abort." proof-showproof-command "show." proof-undo-n-times-cmd "undo %s." proof-auto-multiple-files t proof-shell-cd-cmd "cd \"%s\"." proof-shell-interrupt-regexp "Interrupt." proof-shell-start-goals-regexp "goal [0-9]+/[0-9]+" proof-shell-end-goals-regexp "%PhoX%" proof-shell-quit-cmd "quit." proof-assistant-home-page "http://www.lama.univ-savoie.fr/~raffalli/phox.html" proof-shell-annotated-prompt-regexp "^\\(>PhoX>\\)\\|\\(%PhoX%\\) " ; proof-shell-error-regexp "\\*\\*\\*\\|^.*Error:\\|^uncaught exception \\|^Exception- " proof-shell-init-cmd "" ; proof-shell-proof-completed-regexp "^No subgoals!" proof-script-font-lock-keywords '("Cst" "Import" "Use" "Sort" "new_intro" "new_elim" "new_rewrite" "add_path" "author" "cd" "claim" "close_def" "def" "del" "documents" "depend" "elim_after_intro" "export" "edel" "eshow" "flag" "goal" "include" "institute" "path" "print_sort" "priority" "quit" "save" "search" "tex" "tex_syntax" "title" "proposition" "prop" "lemma" "lem" "fact" "corollary" "cor" "theorem" "theo" ; proof command, FIXME: another color "abort" "absurd" "apply" "axiom" "constraints" "elim" "from" "goals" "intros" "intro" "instance" "local" "lefts" "left" "next" "rewrite" "rewrite_hyp" "rename" "rmh" "trivial" "slh" "use" "undo" "unfold" "unfold_hyp") ) ;; code for displaying unicode borrowed from ;; Erik Parmann, Pål Drange latex-pretty-symbol ;; cf. https://bitbucket.org/mortiferus/latex-pretty-symbols.el (require 'cl-lib) (defun substitute-pattern-with-unicode-symbol (pattern symbol) "Add a font lock hook to replace the matched part of PATTERN with the Unicode symbol SYMBOL. Symbol can be the symbol directly, no lookup needed." (interactive) (font-lock-add-keywords nil `((,pattern (0 (progn (compose-region (match-beginning 1) (match-end 1) ,symbol 'decompose-region) nil)))))) (defun substitute-patterns-with-unicode-symbol (patterns) "Mapping over PATTERNS, calling SUBSTITUTE-PATTERN-WITH-UNICODE for each of the patterns." (mapcar #'(lambda (x) (substitute-pattern-with-unicode-symbol (car x) (cl-second x))) patterns)) (defun phox-symbol-regex (str) "Gets a string, e.g. Alpha, returns the regexp matching the escaped version of it in Phox code, with no chars in [a-z0-9A-Z] after it." (interactive "MString:") (concat "[^!%&*+,-/:;≤=>@\\^`#|~]\\(" str "\\)[^!%&*+,-/:;≤=>@\\^`#|~]")) (defun phox-word-regex (str) "Gets a string, e.g. Alpha, returns the regexp matching the escaped version of it in Phox code, with no chars in [a-z0-9A-Z] after it." (interactive "MString:") (concat "\\b\\(" str "\\)\\b")) ;;Goto http://www.fileformat.info/info/unicode/block/mathematical_operators/list.htm and copy the needed character (defun phox-unicode-simplified () "Adds a bunch of font-lock rules to display phox commands as their unicode counterpart" (interactive) (substitute-patterns-with-unicode-symbol (list ;;These need to be on top, before the versions which are not subscriptet (list (phox-symbol-regex "<=")"≤") (list (phox-symbol-regex ">=")"≥") (list (phox-symbol-regex "!=")"≠") (list (phox-symbol-regex ":<")"∈") (list (phox-symbol-regex ":") "∈") (list (phox-symbol-regex "/\\\\")"∀") (list (phox-symbol-regex "\\\\/")"∃") (list (phox-symbol-regex "<->")"↔") (list (phox-symbol-regex "-->")"⟶") (list (phox-symbol-regex "->")"→") (list (phox-symbol-regex "~")"¬") (list (phox-symbol-regex "&")"∧") (list (phox-word-regex "or")"∨") ))) (add-hook 'phox-mode-hook 'phox-unicode-simplified) (add-hook 'phox-goals-mode-hook 'phox-unicode-simplified) (add-hook 'phox-response-mode-hook 'phox-unicode-simplified) (provide 'phox) ;;; phox.el ends here PG-4.5/phox/sqrt2.phx000066400000000000000000000124561426357011200144530ustar00rootroot00000000000000tex title = "Proof that square root of 2 is not rational" author = "Christophe Raffalli, Paul Rozire" institute = "LAMA, Universit\\'e de Savoie, PPS, Universit\\'e Paris VII" documents = math . Import nat. flag auto_lvl 2. flag auto_type true. (*! math \section{The library.} There are two proof rules used \underline{explicitely} from the library : \begin{itemize} \item \verb#elim (N n) with [case].# case reasonning on integers, using \[ $$case.N \]. \item \verb#elim (N n) with [wf]#: well founded induction for the natural order on integers, using \[ $$well_founded.N \]. \end{itemize} and the followings theorems. \begin{itemize} \item \verb#demorganl# a set of rewrite rules for Demorgan's law. \item \verb#calcul.N# a set of rewrite rules for natural numbers. \item \verb#odd_or_even.N#: \[ $$odd_or_even.N \]. \item \verb#lesseq.case1.N#: \[ $$lesseq.case1.N \]. \item \verb#lesseq.imply.not.greater.N#: \[ $$lesseq.imply.not.greater.N \]. \end{itemize} Comments: As the default elimination rule on integers is structural induction, it is natural to use explicitly these two rules. The first three theorems are also natural to use explicitly. The last could probably be removed by adding some \verb#new_intro# or \verb#new_elim# in the library. \verb#lesseq.case1.N# is more problematic, It would require to extend the system with some kind of binary elimination rule (with two principal premices ?). \section{Some basic lemmas.} They should be included in the library ? *) lemma not_odd_and_even.N /\y,z:N( N2 * y != N1 + N2 * z). (*! math \begin{lemma}\label{not_odd_and_even.N} An integer can not be odd and even: $$ \[ $0 \] $$ \end{lemma} \begin{proof} By induction over \[ y \] , then by case over \[ z \] . \end{proof} *) intro 2. (* induction over y *) elim H. (* y := 0 *) trivial. (* y0 -> S y0 *) intros. (* case over z *) elim H2 with [case]. (* z := 0 *) trivial. (* z := S y1 *) intro. prove N2 + N2 * y0 = N2 + N1 + N2 * y1. from N2 * S y0 = N1 + N2 + N2 * y1. from N2 * S y0 = N1 + (N2 + N2 * y1). from H5. lefts G. elim H1 with H6. save. fact sum_square.N /\x,y:N (x + y)^N2 = x^N2 + N2*x*y + y^N2. (*! math \begin{lemma}\label{sum_square.N} $$ \[ $0 \] $$ \end{lemma} \begin{proof} Easy. \end{proof} *) intros. rewrite calcul.N mul.left.distributive.N mul.right.distributive.N add.associative.N. intro. save. fact less.exp.N /\n,x,y:N( x <= y -> x^n <= y^n). (*! math \begin{lemma}\label{less.exp.N} $$ \[ $0 \] $$ \end{lemma} \begin{proof} By induction over \[ n \]. \end{proof} *) intros. elim H. trivial. rewrite calcul.N. trivial. save. fact less_r.exp.N /\n,x,y:N( x^n < y^n -> x < y). (*! math \begin{lemma}\label{less_r.exp.N} $$ \[ $0 \] $$ \end{lemma} \begin{proof} Follows from lemma \ref{less.exp.N}. \end{proof} *) intros. elim lesseq.case1.N with y and x. apply less.exp.N with n and H3. elim lesseq.imply.not.greater.N with y^n and x^n. save. fact less.ladd.N /\x,y:N (N0 < y -> x < x + y). (*! math \begin{lemma}\label{less.ladd.N} $$ \[ $0 \] $$ \end{lemma} \begin{proof} Easy induction over \[ x \]. \end{proof} *) intros. trivial. (* elim H. trivial. trivial. *) save. (*! math \section{The proof itself} *) (** The proof itself. *) theorem n.square.pair /\n:N /\p:N( n^N2=N2*p -> \/q:N n=N2*q). (*! math \begin{lemma}\label{n.square.pair} If the square of \[ n \] is even then \[ n \] is even: $$ \[ $0 \] $$ \end{lemma} \begin{proof} *) intros. apply odd_or_even.N with H. lefts G $\/ $& $or. (*! math We assume \[ $$H1 \] ( \[ H1 \] ). We distinguish two cases. If \[ n \] is even we get what we want. *) trivial. (*! math If \[ n \] is odd we have \[ $$H3 \] *) prove n^N2 = N1 + N2*(N2*y^N2+N2*y). (*! math which implies \[ $0 \] *) rewrite H3 sum_square.N. from N1+(N2*(N2*y)+ N2*(y *(N2*y)))= N1+N2 * ?1. intro. (*! math and this gives a contradiction by lemma \ref{not_odd_and_even.N} using ( \[ H1 \] ). \end{proof} *) rewrite_hyp G H1. elim not_odd_and_even.N with G. save. lem decrease /\m,n : N (m^ N2 = N2 * n^ N2 -> N0 < n -> n < m). (*! math \begin{lemma}\label{decrease} $$ \[ $0 \] $$ \end{lemma} \begin{proof} Using lemma \ref{less_r.exp.N} and lemma \ref{less.ladd.N}. \end{proof} *) intros. elim less_r.exp.N with N2. prove m^N2 = n^N2 + n^N2. axiom H1. (* fonctionne sans *) elim less.ladd.N. trivial =H0 H2. save. theorem square2_irrat /\m,n : N (m^ N2 = N2 * n^ N2 -> m = N0 & n = N0). (*! math \begin{theorem} The square-root of 2 is irrational. For this we just need to prove the following: $$ \[ $0 \] $$ \end{theorem} \begin{proof} *) intro 2. elim H with [wf]. (*! math We prove \[ $0 \] by well founded induction over \[ m \]. Induction hypothesis is \[ H1 \] : \[ $$H1 \]. *) intros. elim H2 with [case]. (* cas n=0 *) intro. rewrite_hyp H3 H4 calcul.N. trivial. (*! math if \[ n = N0 \] the result is trivial. Suppose now that \[ n > N0 \]. *) (* cas n > 0 *) apply decrease with H3 and N0 < n. trivial. (*! math Using lemma \ref{decrease} we get \[ $$G \]. *) elim n.square.pair with H3. left H6. (*! math Using lemma \ref{n.square.pair} we get \[ q \] such that \[ $$H7 \] *) (*! math The result follow by using induction hypothesis \[ H1 \] , *) elim H1 with G then q. rewrite_hyp H3 H7. (*! math using \[ $0 \] which follows from \[$$H3 \]. *) prove N2 * (N2 * q ^N2) = N2 * n ^ N2. from H3. left G0. trivial 0. (*! math \end{proof} *) save. PG-4.5/previous-art/000077500000000000000000000000001426357011200143315ustar00rootroot00000000000000PG-4.5/previous-art/doc/000077500000000000000000000000001426357011200150765ustar00rootroot00000000000000PG-4.5/previous-art/doc/ProofGeneral-image.jpg000066400000000000000000001230221426357011200212430ustar00rootroot00000000000000JFIFccC  !"$"$C" N !1A"Qaq#2B3Rbr$4C%Sc&56Ddt2!1AQ"2aq#BR ?R)@)JP R)@)JP R)@)JP U3cFYo1z 6ɾ;$p $$$\>fݖ]x"Y%= {싒]?J,cwڕw,NZR照Sl뮵 O#ҵi; V;c7 -{,如PxqPy"U`kt4hyEn+`V䟆ʹ *7jޫyK%I7l]2Lp-$~[06Ufҹm$P GW^%+o3 #DZ\8/j6#j>er}SJi_u*8wswUJ:OPBNMR!iq Z JG)JP R)@)JP R)@)JP R)@)JP R)@)JP R)@)JP R)@)JP Lo x9_3aY>d$DH@cưxV8u}vHI$I$$ ߻\ŻP4 ;c&*U, TGOp{؟QM~U*ԳU+e kC}b9yKR:BU|&U'P뼑p傷7}$$XQIH_,8#VQs^3񦱜IN  ]@5Zi)/*$G"< H"Fwq|JUřL)& V?ήEU8>Kz7v8.u )R 9S;\{-cHB/#e :PLr#'Oe 4bKc }JTy,Ow}*ɑ6ծ7:6@uS@ڽA?lAzɦjJХ)]:)JP R)@)JP R)@)JP R)@)JP R)@)JP R)@)JP[L/ Z2pt6)P70;WGj9g|S2ܶ]؃ݶIHBR DY}/,_o o!3pX)WcjǨiU;OZRxBΫ6)5W$ϔZSGʠ]A#iq0Jp#rv&U02(\87*W??\)U.؄05lAHv>uWzz\T3= VVH4-T× P5-:h2mg m5(0RJ `p*=#מݼθC,ȺA>4ǪuMeݬac mͫCxZJ?Knm_2w[u*Hr+XK^$(R$5yT,in^zKi-*x%ippxfMfj*8{_q\IG'j ǕzP>iLVe+,-e'Ҧ) ҠA?brU2 Bw0cץbiPY iTdh}q u=&"T<@5";nm۹yumڂ 6 ϑjF 2F*6**Z2Zߢi3{%ѯC9t:Jzg)JP R)@)JP R)@)JP R)@)JP R)@)JP R)@)J׿HLMк}BJ\)JVA&)(de%97؜^+0v ; K-$ ”V?iH3;~⭫l{Wn)97&A-;NG@>{ԇFzTUndR\\$:GFu"Ou)͍QRuG5b-Fʏu$[ :V.B iiQ#P$򭿀aY$,{`Ow+V#gxucn8bk{@PLd)RBa&TJ⳼I y ()wXoD' 0 9qX_isK c btj1ZNJku;pQ ZZR9nγEZem&V#G#ً4A`pB,D-'tz~51kkCW%*|-'*0y*qLp>UۼFU^)"cnGzG]>+`%)\mEOYŚo?αeaav W)UвoU$t*^Ay:ܤ(wI2 0|܌#ۉvn\5yj~iqPaIRL"|pI߿e). Tcq;g$f |ӕ0~ղwj-=)Zf‚;}3Rq{̝v.Aw h7ԑ*pd }7HR)JJRR()JJRR()JJRR()JJRR()JJRR_LfÂe\E`,qkZOڠ];\+ڶ:F;6aˢݲ'JlPƤ(YurW[=|]nCڭe)Q$aGsNA*x+r RԨzM-baFdo*efU^CNڔ:ΐ$ 'Ak4 e-6qҁ>2H8U/*1,QT.)*iĔ*A n~{An݋xl}\[n+A t;VZCiR֣ veɈjCO!,? hC$jn4'qVozݺn(!3&$Sr%`pyoˍK0xA P"7H"FUYMݮpD8-uԭC6.=Au̸5`y_2аoni #S$^{8>'Gԛ_g&_GR5Jٲd)e8p$3y^_.æV96lY$C qRA#hھ 3pG@M]g7qୀ# [ Uy3ހu|ưGK8պUg!26 l_mV f?=w^',3.&2c>-fReĺm6MTqΔ{yt>>jXR\Hq&I"x>u 3a}/x9+VY֕ II?y;{jnyp|I%J)?E;jGho_2?;^WNjijxI+קCW\߇.$&>n[29'SIc.+4.IA<+QB{d捙 ]`X5eCFA)0Ax#Ț휵 \.Z]lФA` H_F+\ժv@ò}e=t3jNdjn)JW{B)@)JP R)@)JP R)@)JP R)@)JP R)@)JP fgNWi-0җnI!-/dT°S;un$JzUN爨(Y'vY1V@o*'s5v9/87!ưxlx !IJb2yN- *y(R#5rkIm,o ,@2NvLrOÍ*E7..Yq\5ܢ͗UܕkdofnKpPJҝ! %Mԩh)҆ȍ,pl=W.RQQxQQkC KH#xjјly#ViAԂy332_gJ,_IH#ks}|R.>鄕|PQE-^7yY^lBnqS#|^71t8L X-1aƆ]>s+ yZF]9iy3v*lhwxDܩ/ꥂOս᚜/iè2 0b/,qDGB{ ̶\H`J_w#K ,N?&G9KxOv,MT NJ΂R~[.vv\Ńaŷ Tz( /K)pK\[.U:CZ!=zEX+y6ّ>q.?٦ݫ"v'ITIWl]d\URC&H,'a!@vV^šHWZ6S2Rwy;yyy}K#8oF'q 78_+cCYS{F\8ҊDQ:dL+YٲwrT5,J2~X\q]I*JY: 0f "k >r.13 8mսĬꖠ\ SND, iQrqJ?zw5-Լ=@L]@m[8u^htL|) Ǧ RSO{?W/`˔xs+bw/-R@IP9VDRB)JP R)@)JP R)@)JP R)@)JP R)@)JP RZca.pe, ^X:*u^V'G̖{ɗ*PY8TBPRP v27ϏԃHS8 f;x>Uc?qgtˬ>ۭ6`@"FM0O5}st# "~uZuo|Gd|kݠ2).A7+PDOk{SS7h )m ]vf֘|"=Ս%(mm`X>#q?a+yլ!*R`$ $ס6Dw.PAdOg݂qlW] +(OZcAv?;V*Z$$DŽ0Nہ1 pqjd n+$W }rdf4.7uԚ'b5jP^lY<08aurZRzUOX~jJR9O'qOZ{E+K*X1VA?^)c\7h?Q{9t {%\N;(t>E>1;F±F "epɴjQ2 -";O3m6`en7yRFcT:̬Si1f0ʠZk2FaåJS܎ߥYߛJ%[s-}e6]qxm[)Wցㅤ5 S<{V岷YiAZK Swa3ݭӭ)%*L  yXv7(ǰd&pFH%p!ˉpU긺Ȩ" e"CtK]|i7zl,ϴm@+B$aVŰlŐZMbn‹ ^Y" BaMNXJۭey? u|jԆ,ALΝj Շ.u86Z*r pb:M OJ]/+m9V^mlmq0:Htv\Yq/(\6NP2 ][Gˮ[؞he#֋)OxA)Tvr[eo]-,y[0s \c(/.ۯM:VhS߀V1Zt#-\߂JR()JJRR()JJRR()JJRR()JJRR()JJRR9UHpBՐEvy&;)G)q$,2<%W}qҧ\Ny7B޿ilMs*"TKC/cl+mpli[ζVofCK8\'H.9IG 9°<#iN9\KSWnvVe&]U#ri^3[Kd9pRI)5xn~̏BA!Z|{`Mm{T{eW]Cm=zdcזx ZTGX*ÒBPv?T"%`BB+:#b$pXa 07&WJ>##m$ksIYq|<)͚KI;%M+N񹝇5KRkqv\)iD*(fGLNUl0|. -Z@m[~KqÉb!JR-()JJRR()JJRR()JJRR()JJRR()JJRR(oEo0% [km+:qjJB1N'^7m.} QGv |%qI x5sp[<ݮ)1iqq{l4:k:G @~`oXy )%FNyQ'y<f"74b{ en]b\u$#Ң[glnOG4?H#Zd&fƃ%5lI6dV1]/PGtP>e*ԐN@ԕ ;$P޹C ~RʜmD% A)s_6WR P x&|ꉭȿMɴ/[i<3\ʶV.EBg-Ѕ{WEޤy5vlvxkͰ~z]F*BJV( [axucLo}X2Vݩ0Y 72 u}'`- Yeahm[$|w$$$I$՛!^ |wVPU [2zҴ IܓY=zvy<(鞟RR)@)JP R)@)JP R)@)JP R)@)JP R)@)JP RYnbX ݨi.A[J#@v8vSq*%Gt.}^q!KTLHJrdw~v}S~)#xZa+\{ltMxx}Ij3e!"0ȸZ4j[m;r-XN0Ǿ4PԨ+dvwMb7IiR(c:$!)$!n뙦 mHUh)D%J3^KFۡ/3A㡊,-ڻRP)%P`)I"'bROǥtFd5he4nc}4UYbS tP0ܐ'B‘q gIAu2-hWŮ^gœH{'$%@rILY% =ކˈ R\iamڒA5g(E d9rJ. Q}pEIWj3Vlk+u5׭5IQHX6JI@ 0bk23j|;3y&UrM+FTOxv\u*-.8) HyfiJvc]&qzlEezXWiD_x{ hGMo%*Hq@+"w}gݢ޴,'?Oʳ=[[ۭAJiDpHVbW)[,R()JJRR()JJRR()JJRR()JJRR()JJRR(bEw5ذ␴]]>bPtroAȷͳ}Cz-1b^&|@V@e?zyqfGy$<@D ֵ"'ciczSWʹ)E2ޕ4*)O6%'쿎 Qm7A*s>iUpÉI%RG)q H؎[شp0 rᵕr|HJP6!IHX"B]bpn#lE:ySD)IRFS! {W(1yypnVږ/>L 2ga#+66dv@$]ͧzMVn I=tzz3OF>%Yv}fnbbO>stXK @$oZ%b6kfn+Bp)$o>_/ʷxznm5a)ϏY2ۑ:4gG߾Dž R|ӧʴu` 30 Eڈݵ&H)%D 2gQqnTZWOֆk+a"+.n`iQ)֮ŕbSwTscخɺJO-4@BW1`':R"fc.̴~h{X#t1 O;*g9S7/eLm ;k!$FZpDJ jRL]Ofobҵ%xwRa=PlV퐽_Wnݩ?Ci XuB WK\.ŭPBX{AK4Dw\)$`BD,jh:*U5) ݚJ6|?'Yn$.+pWUp[Jݨ;zq?-YwR Z7f z+^}.^?M<++YR)@)JP R)@)JP R)@)JP R)@)JP R)@)JP Rvhp) DhjAI]gnֺ3Z?}]Zۥ*ui >p z֊+iAqL̉"~@ cC+׳4cSZVA*RxQ".}iv):FZשFym>Tər8 kjT<څs,%a4ݜ"yǖXVU.uȘ3k(זX}:TkD zrTa.afTg6Х .( c\V᷸ln%{*+Pȭgv˩lC);:]&Ż@%GxzT'ݒ:TgV*t`D&c=y}٩7Nn|GacZ 93usn?;V\-!1̫hJ'aH -6 2ͰuȓZwWq|߃Cx2>ꭙIql>H?hmII1R՜.h\BPczb E^nw"J.ZvPi$uHd TcҲ %(PB@C w䨨5wW ; uAO5W.4YDdj6umW:dbRJ)Nǩުq7$R()JJRR()JJRR()JJRR()JJRR()JJRR()J&4^A!M۸`Msle{V- *߹N_ć;kJc Ee%E&AXurD~{cnMZ!CZ "Żt6[Jgu I;mctB[)Ր8HHv<*۫K{+evnNg+ &7*x?#p$ky)Ԁ@l=bYZZ)l(} Wfv۬x}LӜ'D\w.K%գN,l|{2J5Y~n\B3׫K[H\ӶR"1샎f{'W'TOO; l#XhDPOZͫfBTCYChoR2FޛU06-šiF*_s6r˪XP*JUM;vpiC肇0"nL[߼mJeSWsNM3xܬ;eCX0=*lUk_ԏsPrIv৓uYZ"kD'ЀSg2:!kL~gj- 7.!Ci#J`HíH+$#;u 5IlYq\JHRwQ`]ؘ`&-zbnҝe %R>&}vz5(&NR j&Y=mR;Ҳ;;妚 nkϩAR+>~Dkaed:%j#x3Bem6ڪlT(t䬺WL2%,2$LRp&@-v)(HY\F ~gZ4*tϓ:2愄!(Hҕ)@)JP R)@)JP R)@)JP R)@)JP R)@)JP R)@)JP R7"kU3 wVc˙s#]*E-!e JTn$BB0ׄXv Ż**lL@#"ܓ=劃'gKSn2 (cZLCHHLN_n[a);1 p$&Þh#_ ۅ2R\ h 'U/K5)&'}j햗;ϬYCmBd)7?:{cm.L}v6awڮ+} ^V\Yķzngd/ГqxŝOd`V@J9޲K7NU6ڀҥw9lP<2dEdb\ {gU&O@vSw$W\- R\'qt >~UNL1<-2NB`5)j #hU]qF{[jJ|0@0zx"aιCj [-$kQ|rjΙ,vՊg,TRTìhBP`, 0A6iO{\%0g-+GXwh׌ecVԅАN%ITj:LO'j'g} RӢ)@)JP R)@)JP R)@)JP R)@)JP R)@)JP R{LUy[ٰ4 A)i5,I2Wv~"[տa6b5 @ZuO:t:1ۻS]f☳nŕ-8uW-ڴU:DGmK"U[2ě~0*ݛe  ;#m uGs[#a7xfrnV])-Ie =$; 2ڝ\aeCĈ')>zVz ǰKvB)P0t0T_*,7KH":$f{#)]JBHyDbgҧCV̏*ͬ6H &~~15md% Gqk\k_CJ(k )#&k`vc|y,ܔ nZ3F6Np+ƱoܝsY@%";?'k%!J~“!#u$JEwcJe?G$mnn$RXCM$J@O|ʀkb8Z҅i"R <~*heKWXś/'p>~#+>_=]D\@z@䝅b5Yr˪Z m53m[[j|DwVaε3ݻiIHRj0  c:yK3ɏɻhf hb 0#JYڹ?׌bWRvۼXB^XJY1!2LuZzٛ˞4 EÚJUw2ZhBC0f|}k}#I( I ۏI̙{(LO}FV1=w2}]f5[<A)Rzqɂ[`KLb>5u/[OƮʾyyl,qܿmql1.PI_}g;,iVa\@+DPD?51]7R9; F7gd\ )G쀈tS'a'i)ՔB{j)Z ")@)JP R)@)JP R)@)JP R)@)JP R)@)^.^fˋ[eV(%(HI'`Z-u!ƕiMH?\6 J7I$(`!0#_,Ӗ.0QaC?+IH$n"D DH?i}囱g T ]<*+Zv^/Ás@%jZR"<*&H$%˕jYTI'ߚO>f٧_tI㠨Z9y7=ntMߥVt]bk  5ݶ*<5q@Ycvv Kה \|bHRtiQڷE .Y`_nݗ}6h*RL7$WRgL9 ݸM0 -6H seײAN`NoʷkO]=>[cɮ+ ہ;v+^6Vvwf.p<Ӈ=!1d6lA BBS욺pwvo^ r@3>ՕxQA;yrġ=PI%.(Qwkwx y H:a)*{eR dOA;IŰn/vR[MڊIR?635SAuaRzG_ά4KQe\wl KpT#O_nr}d $FŘ/fŻ2NeQF//hvٻ,P#zSki^}*M8Bc= fN[an' +i†L|`]X5ua Tl9 &0|7/ HðuRݕ; Z_J%]ifxB >Im]c77ٸ@u>iS~t۬8ivOTWn}[NN %hJРH #ξwg=v %6!ԟ);wOsiSR6';.5W$X'eҴ_IvM=u.֟~-LD*x"@2sOw qn@RȂ|)p$ Lu ==)J()JJRR()JJRR()JJRR;@Bduuadz$6i`!CY9Ev7Cw퐕 B3`u/HAcθ互L|j&F"HOkfݛ&.hy TlT799~cצixJc e J$b8P肙Nϭ@IHҤ1PK+$ٓsKM5#Šn-)&$O; ܸ!D% KZ !GUZ}dkZ?$*{g(x=T/];:%u8W[l>%:k$01xUܗD7ij.K( >O\Õt? JZBJL{':V+-a!@UdZjJ=y$IHۯy~d2selݮh@ mə?YF5- Dr}.)k؉qޣ؆7ɻ:w^Yd'F"̠rcagS#*u[G3qwf ~f`vwp6GgN l4,S%l b6 -h+_mAڭ/+e;|(}Xyg'p7oH& S2ՠR9_43 vMSlRNK̑ϖ*v uA72p$ya i"IwCe@M6j8͜sWw-yB 'P;G_vFkr.nzǩ4Zf[H-]UZ307NgǚJRj0Im :@㥕$|bʵ6#|Z,QzUuz02M`؛}=\gBJP8Z QT@#GUg>C6iҔ2;AoH PRBu6!0|=E^oT)Dp|*'H%aCjֆqL$<$b"WjI lxwe\AGΩ+,(q~Q &WuVhѯ:-;zٞ~t(=]JDQ] WJ_Q5!3?Wв#ׂ:I#P˟NMA"C['x5,YEI1ӏx@JgrzNEH H "g`~T:]Ƿ- sp$Ay@@?zҧ8a*C9*Q$}mTrAMqµtgyT MVsvK֒;Ef(a9[.w9etL_4 QL>U%IЇ~N:Co>?ךK2C.XQ=x%DvߕR!58)J1JRR()JJRR()JV 0 wN[Ե8J$$mȫCM!JQ\s0; q@:TF/n *W{a>a-;nʐ-m|B6K9Q\QioNLq)Iĥ6O?wɒ vQݤ1G+2Ԡ8_q^BDY'үHt+H9*?:ڐB*PTb?qE-Š3Ϛ?*Oi?U?0%e2zHz{n4%A0GHV(-&cV ^NOzVSX[nN~EQcu+S L:X nCpjZS=7Z.BT"4!H ex'db-di`ۈ2Gf[r%H+XI܀zVw5w#\I+8y$OI:ՆU:5a׹]$S>OQev\4jTOGVY|06q|67G yZjSk88 BoA0:R?O?rj2b ~Bޠ $fJ8n dI$yi:ض;;V-a>GtUNqM5ebR.2 Nm1H ~u˽saĝ7H& kyZ91eX&]!r&uMBpO^uaZWr0r\ObЮ'POʢb۱vڱejҒ-KQ+M_5~N5~L׳qs%}E,PAJ0bR&`=+'+,4a {Ĭui%!ZT9BP'p+y:rfDz,'1k>! L,'@:T=DU峂smJ~f 30t1 d-M,MAZLF"2nm۸uumڂ 6 2Rt{)R$)JP R)@)JP R+퉜/./[ƿil5yx+FRQV3w-egiůx,$i_ %NYqH ceT_ ԵkqR(xBsW2">^%)Sj)KErI;+ΞaDңtu*w~_e;j%?W͖̯5J#"6w?UNP6&6ӼyXpyG?Ь+;:z,X}ll 9}JN]y-CꍐR @zVĖE=7حaXoąi$fP|ҧԓ1PU'V)efBM/ejQqkBw& >֮IH 2 'b@򎕇$<ܹ ezKliBYe0! ʁs<(fÃ\^"K)wruxv:;oQ+s ڇ_R~0dIUfUlSqhwJ07>_ƽ줭aCdL6z/]nC+JIJ7sjՕ!9:e3bX *w %@$+`AV]v!- $`*Z[Z@ < Dڵ#8k?Po Y sV{{Fh)Y*m^0?\/a\0 $0 e)’tUlKR H+"#;2,U#uu'*-!!Ilw9DiDzim ;lv>^A) ־e,-@3 ~Ua Vgީ-k/0 NBl[eVD ڶac=]a72N*)[NZBZfT:[<)#\SqvFn.E1#3`c8/lԂA( ~|vU&=`^!:Uup1)J*$쯴<L83CBo,f`$9D6cʧfSɗҔK)JJRR()J 85<ıR pB6;D5_]x'|z j*Q̒vk{039m| %*q*΄)cc#b\|}A 'IQ<.,J9UGD.!CRz&61AyQVֹPf_OU4$(%*jd{>[\QP dÊ9ץ%R! ;ꚷࠫ۞`dm(__ L:IO?|x ɀ7m)Q(@}m)$$LN^IL%(۝ Q*,F9kmM;kc%*)6V^~FJ)%ȍv$?ǧcbI 1m wsZ3j˘j t UggÖҗ4g5'|j۪UֲA2dgΜSDӊL|D3Q$iqB'^mQH b'b'b*׈^()]7>_6BmVN taF␰ڤL*ݭ:]AǤՔ[FGTPLJdƳТܩH:V&bxq=8(ma/\) 60$xm됗/# zR3$e R^_sEan%ERtlr7Pa)Vy(;PȬC "h >Ur~_98)yAjL涷cwnӎ4'RR)!'*}hHJtЊȻ?^! NwVsY59,ٴ3Vqw SpncSb`5X嶓W*Gne]I jثhG#ו93̜ܝۨЇRH V U{W& Z9ZN4=)n!@c m JKl sx׿Ja!KtM#ʴHW\m\pω $'σU8J4\02\27ԩtASl >_q RZ?{.KA@HD`zu*ܔ"mzUul,X/a:*>.ۻQfuʦ%zEu8^3u#oo"ӝf<-\b_vUZHQ@ ?Ր4$LOq[;'ssW Q$:VOOɗXrI [6V;l 8LDȆYWDs'NA R8t? ı.Ewv׌\ 0[S$Lqq\71`vXp7MI*b  oڡHۓOJKTmwwl.6XrXu ZRgFZe)JuP$VF2dV`-^0Jmk,L+N-ݖ2&"f,+RbYHmKZ7).F7jkV'f{ZbZ>‚LrtE]ti.{&ϳeV,Xf]E”[44$%:%RdQ.Ic9u) I1YGsUxv ǮmmJPRBB/\1`xl̥QR$WE)S5؄5msRuT7~ ;WVHHKɉ<>5nmdJ;*$U(MVRU QKz"=߉ ;TKBU7 A8T;!X K8L~ϵ\;za2%ٹiJVH)@)JP Rf62JqUkn0)q!7E#vj\h6AEuzH2R6 $L$Fd[9n/._uRu(KQJQ;I>f}a) 7'auUm3$$I<|y +CfG?76$8njω5ATuV7,:v$$A@~5l[%Œ AQRP N$peR$#WWҔS:č>Uo[AGJCD?dTbee Q pz)aC{ET T%!C _VΟ -ǧ_Q]VR);ʓ=ykAT#Ic%#O85蔪PAn8?1C4t?/Q^JTYy[@F0S iZ mAg,4R"FyyqYРHP|N[ €S1s>f޺!DT sH˂*%Dsnո WL]ERtU<|jŷn :֘$VM@[\5oڮ@HqHiA$F J։?xǷVlk:GzcxRCm^1Q`nD*'D o:V5hعO>_` 67E-PreHNQL(9cDž,J\δzŶcWNxJ1A Z̩d'ONv޽/&^ k9}gĂ^ m)'X[kuDɕ?ޮ9k I1r<-nY%-TT'o'kcR5R abӥ̬A)J]<XifD>!- &BP__^ud$ x&iw6O"m(}T7l*HRRKhJ3ީ'Sp71wKL8$%&N`ImfXJͧTZjZ@ d(@Y7eٙy C8"L)i,(t6; E ږM &S >|Jcy/pRAò|1ƁFÚH[ Y;Ha ^Fųk&TĞ_{I Q HuzV=[-ƙ}ja*X:W;6CWKh-.&FY',nI -Ӎ):J؂>Do3X.XY[6bBl\u@+l<ۄ$ 2dK)̯~,\ k7.m{:jl˙ 1P|% +B[!d&U؊|.-,;qsFF)Oٍ)  fOb.44bNk<}y@b7KÊmuПnj׮ ~?^?6O3Z%j%V?3׏*p`׉Jʠm}+pǜp'tQY 46b*c~w>On.TۣRe A{Ē65!ähm:BwU!- >>EgL< *mQ B:9JC[PZ̊} C (!Jtnʈ pQ@t֪ (t|qD omPR<}u@WR`8u]$+@PQ *Fιgx9ܸ5ƔQCpdn#mJti7}jUtCW<]؇i8u,KzQr;N* u=LVخ.7tÈRAn8km^ܬz~9ZMɑҔKE)JJR%R֠JL<9bx9_; $p@8Oey)**6CS? l@Z㑷N ɩ|c>R-oQ Aw>AyAO/$yPVJI7T &'QE1EPԨ #*.R,δ]QU ₥F~JD'}ZFۍ$>jJT{ֵ{@|? x_a\\N (AY6IWGsYW ȸeWvDTJCEEIpߏ Ux+aL)R9ԓMG:OL=s^N':D8@=2+V{ǂ@؅xN%R%@OfwijB*'I烿{P!.&=ObT7` uƄVF*JTqV[ sdbN"/tJ"J@*Z-ӲG vտ"'liHIHF]:Id-kc}S 1(Jyҧ9% !:FDʢ:% p<ޫTH ycHq:yMUx@':{}q\rV{q$#5r{^^\'XM%pXKb JP'R`& Ys4`x1LACmJF&6s |w&ٞLT;I'DUrI XoTeSI>T| zQ:\:OyjKIB5lIJ= U@2ڸzv!4G>DBF6= OQrd\G-fvA=).*9M8~xx#b?HaiA֭w {Po )ۡ[l%jQFJͷ;# (|Sy}RgpAj1cK!(lT6zR2G#+TˊrS Jw'YOa*םYF|XK+VD;Z{r3 } /ᎶDtfi)mIY:V[jnvZAmﴝrJ J#m9})ĭp݉+Hf8Iz֖z92 5siop0HL;WQ}95+Sap rQI)Jx=ۚ1oweuov򐇙Z;֓HZHQӱc>Ui> h9ݻjZ%JNPD֭en^e{v]g cOZRPB΢DiN^Uin ë>ϱw.m0Fv @AtBq 4:ŽfSJOC&0Lf8Q!H HH;xcWZ!e.Œ@2R$H3\<ئ|cye)j SJ*Q`cɌ'1b6M: Tk۝XZ* ƾ.)!3>$up`bbݿh8VK, Ph5aՋutPl 3mn-adCuov>*H>dsEVuJJ(bQQ';#zf? XڮHfy;][ $$({Wp& S5rQVZBZ8[@Ơz5"3&ERe+hm$ ;'*3QHCd'n~doٶ.wФOhv71nw1QLJl q ’ңR?J?nyqnS)#l'|$j *+HQ25sgROq jB#*uxW$H|(6&@ʩ-:6RBgz$X_[\Hmޡc,G"EN(vBG>*I .aŬ=WRDG>cڝR&(h?u' |"߹EՠoE} 6V KAIF|S^NK J h\%D +clIV>Qӧ1Űmk &TԋBuk&YLչd]77vKXBS,87*0$q[+O/.oq/@@C}a l01c+嫻R3mv]p!`NbGqjȗ"?zKJQ G?ux2$$Q;⢣ԛhoԒwo'.U8FRRi$VݜZܳ{`,k9}|4[֚=`2$*@;aX;J 5c guRWv$%JL/+_h(]3w(!*w;1hsq`$ ˋ9SGJ[e{GGplLZ᯴n jW$t Gj9e3vq:~ &R kqpGVm:|Lwe1?*V ̷;H?zx}K/:RVBTuO|U*'"ά-Dm91F#I+ozCyײƑ;O߯L@'7 褞:[Rɵ*NPԢI]6j"#x)[EgKM 5 Ys}Lq/3RwTAf=f.ZdmǏEp HOA2H~UMpH.A5UQUQSH$1$jyKRFn#oHYklO^BnZMǹ34oߥdG.nmHI\#p uS'G: w [wmĘԅήMh݁;ծ /tF;\}CwLF<^izTq+@3Ձa0 >2 ܎P^ (/ҐJ#ҳ|^l_A H#d1I>xS6XRT?W;3t{Knɂ`tNYF|9ڈ *TK`(o.T%-2gާ( Rx tW!.'hC.*T,8, ~f\Lu{hWx;.BVJA0x=vKʩ+mr܃q;!CSTJTߝu)jDLJTH2F+{T4ȅIG]}b[?!B>U=sl޶.Pmul$ ^q9q 2`, py5I/[l6ZI'PxarF@><9e|C٨ 'i IhqCY!-"I NKIVfD :K0{. Z713/ [EݩjaBBX;;06WS~ nҵ T/n~R{(@ۮoJк=|-+[,'+o/ iGz[ J@?y$Ěs~g{LW ˸´»5rt4-K: JP:\z^*KSP)IەLxL5j+^+^^"嫄( pAkm BTBHQ5A]Φɟ"Wx⍏q }5s޲FH* i8oĤo[uO˘Iŝ ] %RJ8=6-r+mn Z]!)I<%iq$AOqaku&6׋qi P-0t *&*NMYD4Д`ߺO~Sx3)_Xupr5AeՀ)YJ;USrBH\aLj"GMiߚ8/g\plS alʰ»Г.RRG@s=jWNkwosc]";Vm0&@c_i%lͽc*E9j?)+i RRU@lg7;*u̾ xjje Ei H=NL;c c6-ԛ:R24\Zpo'<{Sm0&ŸJGF $n154ݙĢڿÁemOx xuF؍dͲeYMSh}i I+9}X+r$oylR/Z\ j2$|kg.f"[Zٶ 6RBAo^0->kQy']^3&QjÓ-8\D|1(IBvL/;|Hb-ze[wa<\Yp3dmj_S<' %_vȉ2ӭ}JA DF>?}eEs?#Rsm~{uHAiE[yED`sBQݑcԨ%Ev!D@gJJ*Ȟ 4 :REu>lJAtx&wZ7QCW<(w@3 h^\-S1Idv̲B+{%x%rd}k2=| JUM_恈g | ]8׺CcЅf2}_-)eNTD%HI>321_%}j*0>?iS*[Wpd:޹ *TH'OT땍<"VAPN~5LܭQ$a@Qgb%2y1Q7ChF|\$D:X[TMER9R$dGL@H?Hɭx8΅HB'zY ЌeZ IUԥ5ȝ>g_Q2c-Ӎ~NiC-6uiJ!:Ԥ%DDq6Rjx Pl=VTۍ?V_qi(3dz<]1j RP$k ĬBURx8_hӎ0h+6a;{dҟ__Z3^. q[k#IR@5~ȗz13|˄,J}3 lkW=kI|랚9Dɮ0 mS_QPܲndH5*$]2up=f?xҼ䬾RW*`8It.$o:o_߳fƞiF' paXSxu[q $:*Gw4 $~`W\ҥ+DĚQm DO>^ф.ZjwQ%:>WR#:]R1p+:oUuaXAt@"zVHߩ?΢qDdjҢ[I; C> = H q;('8 JCb`ijI0[L1piPS$ˎl[޲1d ;nS [iPt\)%0VOƼ0դm2$m%ɶGZvc_{nnD\/P/ܪJRi+lL4Y&dhm|Y?;kgKJrw&IEqaikSXiRTF`q]!{l{\]G^'n~u8./%no냻rʶXFyjRmWBB<;;I<=&p;<ӊ >*-J!ЦP \ W ؔiC~ +=S5U8"ꕩV Jۧ;Q8҅kGk^YbL[a{]mpEXKIvt(uJ$$ D &~jy1' %(ØZM»ԣR( v؃Nc̸csneeAUARV0AVj H>֠T^{#+W-1\68,z.t JnvÛ/ EoY[r[uo\,1K *%0v'>ֻUF:Ǜs=O]ٻSC-ߨknC<$_vwcB.˛L7,^_:(ZD(B ܀(t^_1|'4f{Yi7ݻS@%,dajP Ihۇk`xl]iLL}Bd8w&6x5$:kS"i*Ia)Iʮ]}(ӎGDbEW2 Җ!*#R;$h&ռ&fɸPsm}zw*`!ƞKqdPK`G\޻F:^ Yjrܼ*nH5J2G'WVm|JLD'I"))ʫ4JHPU za#H^-Ʃ5Ä: Ùޣ#z54%9lP#4E[e@t57 u_~% 2n)@LO7ge  uGgJZ?rdu3W\vn{}tM3R2byxfO˖Hs_x,j 6R@"$*;F߹CocOwŶta0'|\\ =Wvy^.;w-ړGJ;r U^jtd5+ SHCzP;2?xQN#\^SuPB pf*2t UJoΩ* 2:tdmC6XίNZkLi(*~~u۫k3a@#J ?t-&T{1;@V]Gh˞\A)sHHF$}U`4%:JVgy+IR~;~uNя\Ғ GEEJ*B33`l:Y'WI mć+Hmm|zUJY0>] ਲ਼^YAVט $y=+`d|ˊ&ԭM5qA^)VzfFEw0v*Sf^RTu'H>;P7ɪ`4 0S޴`b'HQ(HyVD, [=zk H7+#`]2&1)˘M6:SC}E.nfU7 8Ńqvȃ2Q)RJFfrWJTީT䑺?Ҧ[!$86'IE$J7DyqRp̉ZWv6n=jxZ"O@޸d\*w70ڵ*9 ׆Seem$8R%@i3|r&BRP9ێ}k·XГ t#ޠJt#q1K!vtDE@ JS*H ޕq v:JTe߬JƵ*P:`qI(PV/Bj V^ԤwAI`uiKlGTTRIGK]6{W aTլJ)< )m@'j۟j39%gJ@PId5hx)I7WWLD #5hhH FIޮthBve"B]!HSݧRTG WJ&4n3NH)KlL!S=8Dzm\rGTuHm?x$}+Í0RԐwǚ=jcm!ЅݩJ3cJ˦@SR߱C I(⁉'ix{{%).0;Oj[R~ބ'|kvSKp,jJ>eRJ(GeH)5)~-}#zT CiGO R[|} ~˲7g2ө'aH'ӯʧYL4|2}* JiGvfSPR4l9Ȳ ΒIZy@5:TA+"4<8J֔`uc.:]_x2tF$u_? ce'.l[^'nf8w+NEI:S) \K9eWW}kŠЄ%vBKzQ3Ov`-EݥAҥWGI#$ D29#_{vҎ;  18n+NÐZG}H dvNuZ[p%U Q:Qʀ QI4BIQiI~UNܟ1Rdԏ?O^ pxBB}$LDr}?q z,NLq\JMFPSIa}Tbݐt׿ֽ2<5]v >֝}?b]:)S&*şqVHSPG ?'W]ߎnJQ#'H~]do='><p@Duo8%fF܉MrakzH ӴV;T'RAQ@__G0p$At$:LA<*d+0=Ϸ>mU^ G==f`L? \wku_R \,]4I*i& BV ,gqL?%4@$u)?mJ\QH*!6)ךsLb?P詏:НJ z﷞.mTU-z\~U-%EB[be:Ε,o֮v'L;/lr͛iOڶ%T I!g& U%} ˏY[`$˦u`(jӸ6 qLmn^ч\ܕF:Fm>@ovi-4(HBbQ2s'2[RJAE.!u C6 .uI#ڎ(J\@I:k{WTV<3 %H ȉĨ+W?A 7+fWOk-AD+O1>ɯTMu % f#޾\!@vHWt7-TLJ4W@7u! 9)=)g#:%+}5p$AIWMtipFUIRVDJTz|*3('5|Gu% 7#I >$D~nFGU\-k#T2wP+P=]ݤBJ}▮(`cU%RV6QIZFήQgB TJ ~>u]ZR{(xz--iEG@ۏVC9pv@* :G)/Lᙲ9 PA岵.F$ $\23lU\iZI_rWjJLH Aбl&Dl!gsRn. C6KR<]OμVKo\%(6LKH2vܬ T'mnT`'e6y+.TF+iq-Iجo=?Zqn}J;${V@{HR|HAT*#﷐T?lk=IFl91QPZ7%eֲm$ˆ+%P~A?5n8tw)JdR9۶W!ְm*MNڷ$iƐIUqlXV.p<zP0OPD@v3_`y7- n,8TR8R Nc#jXX-$I7v qG@k~n9A< ƫB@OT2|J)i:@$i0}jNVf|ҩSpG&n˒E'۟zPCf޺{eyWaҔ;WyՓ*J0|i ['oF]G(g^IZ{F'q=+c&$ְCpIɑ.KmʠA|9t(îؤ5.$DHR.H8}ңW=z>KǥUg y));I,;!;kçp6x[o0k`yԨEj;nqDd %/)3wmP\OrO:%?#ިG52ϩOi p#AZJDN$UIBӶ~{Wnd #U ".P腑1~lЧHlѱqJH@}̓OE#xUME4[[!:* icWVe1Q^_MB#ÚA|?߭rLݑ-B-APq_X%x5xN5[q-O ; MB-mi* ڹ #IE:-)SX6+WChʌoĪOXە\8I0#׊: ;cLܽpJ Ҷ_ -u.<*ց#ҽ*ҧbA'_} %Bp`@]P (xyU0ie.mCzg\Q LZʖ).$¦ uifpsUcpHv؁;\?\BKA/ @*`:FLMU[=j ͍Ѓ}*j$r+<[}௳'j:gp}dT0WH09VEɤ[; H"@oH)u I#/[ @cV(!~^rdz_-yN/gXho-$Jz.A;Lv{#8v6UUv- B1ʕ"5jC*Z"Z\TJ7|Gq=COR1LvMalTxR@Q҂3Wt 0Kk+i%IW'֤`i6U͘^RYv;;慄^KR$+B>פٻ.H7N~6>ԡ`zCq)AӧJ!: T V0a)> uF^ts'UJ *BgB6''gd[e0P606E')!> S[:ئt<Vq9;d8 $VSi(Wh=ȨQ9_ 5&ﳁں }{'PcRTr3Q^ gi@\ϰk&ȟTrKdxRڽ 9]T* fKBь OYY1ӧ"U۳vRPh07ȑ|+Zj~'mE-Ҕ}ɟrI6;g,PV34[u3M ܆ne6տ£r\tdG ]Xrzzک{݇vkV5}U& m6r;?yI'T~ΝVWW[dbYzS |6rp& *0Һ̖5dE}4GWvQg_jg X[urX-'*Ɉ?J;G#Zbm $ہ+X #~RJ(Wm9r9 TrRԞGkGQW?*i#6s>#[j=Ҏ@X CEH$JCSd)iPMD3Lj7#)Tr[șJP"@> dҞ>W+}">9%+K#cmzjl9SgP7>_ҷ86*mB|e ,(sQT(A@$-Sܭ5lgP/.[+3=Q)g3ɫJt'H|mv?X˭)HDaK۞Y2Do~w?ү=xupTTc J,1(e)JR()JJRsFI1˯ E$7iN@a W,sHAB)@)JP R)@)JP R)@)JP R)@)JP R)@)JP R)@)JP R)@)JP R)@)JP RPG-4.5/previous-art/etc/000077500000000000000000000000001426357011200151045ustar00rootroot00000000000000PG-4.5/previous-art/etc/desktop/000077500000000000000000000000001426357011200165555ustar00rootroot00000000000000PG-4.5/previous-art/etc/desktop/icons/000077500000000000000000000000001426357011200176705ustar00rootroot00000000000000PG-4.5/previous-art/etc/desktop/icons/16x16/000077500000000000000000000000001426357011200204555ustar00rootroot00000000000000PG-4.5/previous-art/etc/desktop/icons/16x16/proofgeneral.png000066400000000000000000000013521426357011200236470ustar00rootroot00000000000000PNG  IHDRagAMA abKGDC pHYs  tIME ,: gIDAT8ˍ?LaƟqr\@+B5"&Ͱ:`L4&GuɅU0`&&h BlK{w\7jM88\i-3+yoќUac WS1P&,TuH^86aBUȍnF`lk86r @R1bq4LYyJVЛ6`掱•b.Zl#6MYQjD*\:Ow!TQ(-JY4naҟ||(uq]񉇷2x ~\Y4y~$P5̸!kb, |^GsMk(XEcޱ KLvCw=Ao>.}-tt֫cJcQa~]0]RKp)%U v+ş}ag1< {GTwm,cs 7qGџK}2ŧYd~8dqzQIS) !r_ D "QrʬIENDB`PG-4.5/previous-art/etc/desktop/icons/32x32/000077500000000000000000000000001426357011200204515ustar00rootroot00000000000000PG-4.5/previous-art/etc/desktop/icons/32x32/proofgeneral.png000066400000000000000000000036661426357011200236550ustar00rootroot00000000000000PNG  IHDR szzgAMA abKGDC pHYs  tIME +)\a3IDATXíoG?3ݗ^_nvR7 !TEjBtņU,MEbUu@DL۴yر:}3,\VMHb9s#M㌴%B]aITi:.T;ce$Ƅ3I+ޙ{_:QpJJ ;tRp ɇ ul(=6Z]&U]blQ_k8v3\؟@iEҋ0D6A]!ے-w ֢zQؠZ(%hVxn!H¨10׎X;Zd2Cc˥ws$Wt2ZZSwD3\6W\mz}yʘْaTTGM״ ݬaM1gۍPyRhKR)l0=Qc\Q:>/+,nq|;cwx~OC7E0@v_./Q穓3[O\AJ^7L8HteyFG%RMܸv#( ?x)j9͍s zCCød:8yxb!iza1 ϟ8V@g:c[R292asRJy#U „˻мfsBqJy4Qpyy Ӵ 㩔gfec_n|Evzl:=&k#lڬ5[20emk?o]kY\^njci,JIa.qי7-\yʹET*5LX-ڝ ,C vOJHpjF3~bgN25VC謉'8˻o8ɾw=$DiJm Ŭ>/8>HsUB1h?==VGk5(odzfkh;[}}z4+~+'F]Yik(Y0=2!a\Vz(')o1M+X?MV!_2UwУgGUvvv)H}ORpmR1>@2io_1MFfUбD m_UzF&K&(C5 GesKUy0g=E.86m4F"B/S5[+_}70EaHL Sl$-QJnwxdb+W)u"F!z%n޺E+l "iIT+ K)LVu$H)  XwX@HVΎQ-76hw:D*bf R^%-^O_(X#RWM@=AV;OHfvpť%mW!kb-nJk璽T}X|qciH(@NԦ^`2Щbdd&ݤt$H!pr6Ғ{ XܰF6xIENDB`PG-4.5/previous-art/etc/desktop/icons/48x48/000077500000000000000000000000001426357011200204675ustar00rootroot00000000000000PG-4.5/previous-art/etc/desktop/icons/48x48/proofgeneral.png000066400000000000000000000115461426357011200236670ustar00rootroot00000000000000PNG  IHDR00WgAMA abKGDC pHYs  tIME ,5kIDATh]ُeuk}ιC[su%@f$@q 6QRHH=z眽W>.u}ϴk}߷*ʵ ր3*(DuS(ke\I7Y(HB:(X#:w= W0UeZ++At*`N1A4`\ BӲhaN K|TƇe$:N!Tef@._t!>335̌lPsH4B*^8jI b" eYǢ>ٸcAzEU12g8!0*(P%0s&-\4ry[69jWAj;<"3րA0҄"!O]U )\&nOjP$2pкU$#R.=ʖC,b'5"KąAt_Bfgr) q{lrטPMH'1P:a+ĐѠ9A#}:`\4DcsKheTW5>Bg s7Y!3P =1dZTN*ʙ.ok\Øtڎ=<6PTcSx\zR)b?KӅVf㌐[!7S6gVh9p餓B2ȤXuܲ׮-cg""\\n}ʀkKH/;'D\B#IAg(PXs :C#T*5YXYY(rZk .3ؖX+udB)E]RgF g([Fm s؄OHp U`2Ã5`z`aTz bN(?Hf!V`5 *` XZ~5'% 03fFCܹKiwUȭަXm!&eyT2>c  UBY^4M?4Dv eUHzp_j%L=8Õ U% 2޾ |rc}yz!g;2Q Id:1*ԪإE*"7Ff(ըVSt}WԴka)Vqeҕ>'d[F31ua|N'!Ay&*bȌP Sp,޶iE5j.I TO@v[7L~}ŕ!dȥV.'c3=b {S\lOm$XBuP5&"3qcUT淾~ဠJݡ]Di8x<vFV:=YcM3FRd\嵳\8ۭnAa@>d9^}Vg7E$M 'B(Ht^F1*x5t<rx2"n|!,v6WGϧOn৞V.d'RbؠchPR~ؕ%&k`+1t\}qk`C2.hQh;.gS>wxxx~<x+S uiQ$|hB9$@S~!"nN›t4yZAWCOT<>}d¤c~ˏNƠgɟWˏG%/ÿ*jLiiݞ -#V)eΐ3X_"Ȋz=)_<~t2*{dyynL6 1뽾%ƝLHRsߠim`̳pb,(ﲹFYFg,gsu&++,9saiy i)5ݢ?GIjIk/pƚhXVSBz4QI2v!2DY׬rUzRB`uqk \Zk1>\5h@Tɲvf58%tF%s0[b7<0V$)S'<9%7~q+dYF]tmvZX.s|6^{FӒNa #xxm@p,YbLӕ8J}!kEA\,m!n~Pd~'2xʝYc#ƒ\Xw~eR~y7׿:[heb6XzWͦ(U;_ MM3M^@nbp 'SNczEε<睝,dL, *1֏ ĸ蚔׉!cVOI 8b׭)P2s-.rKK,s}._h\׿FϦ]O=䳇_` >3tcrb1 h.1T Β;FP zMl3z6mcy9вO8M8k.qesI.MA语l|I7k OoMmv*n4șy47iZv͑el.x~2Σ]ȸx쐥na*'SXh搈p#Pa{~hUgk2=S")OF8FCer_<`K7Ytx~2msfJvgsg KMrV%wMQHFȮ)iEof|ÿ= ɅUsYTs~mkXE~s>>[;QuٕTЬ-3)oDfF= $SuNfUon=:ٺ˟˴Ez.Eⅳ;9j2!w>{#>m,oS u¿Fk1FfSǬ]qJѹY/tōG'ܨjmd4޽K[]('<FY{Ohq圍 |ˉVpsI %l%L E&^nN'z WW^zPg^xn|Ǔ8^z%m9UXԅ '+jk9U@5o',u0Z[]c:z2Xe ׮?&d6ϼ7jt;]{{@%ǓߪEn.ٶm1W\M+8-lURN=~>l7ڋ훭G{9.sGS>k\t6?yǣ4gOwRzdjXS,e SJSb`UdVG۹QTtVU܉-?ӚPj87DUW cQW؈L"jY_];;|=[ypqd<{ϝ]޽ z۲iT Mq1p2-Woz\ɉ5d|!ǵbN/PC}`4Q%,) x G\'~{Ç 縎= qqI }oQnj_Zl*T(b <>~Bx~t"x}Fx)+r<`<`ew?$kgBi5-17jETfFi(,W&Ry:$1 w0鴻3Nv :0x_S.v:|tCGCrԃ0q|"UUSXW=xNY4+sq_xc*ƣ֔(1˵cakT-ýgL]{vr=l'N,H, U) ~YfOftRTr&T1PgQӊ9Us3a_+FLdYFAZ) N+g(֏|J5?Y==?05440ƴEa|lǏz&*{*,xy;6#IF)nl:s 4#+51C#vZ濩NJ8v&"hcXG6YƼSW':ں*"tJgpxQyf(h)  ×ESHBDI†^W߂laĨq52!xkedd::>gH!4z*Mb("  BB@ >44зw`PGS+& -&>:=^E>6* =?F>"""56D誓$b%gX"rTIstr*Dv6þu9T*K!*ʬX6cU $F.UZ5.~{wKILfcbb, :9:3% &Dl-9b颌`80U455|B@ )9K)!D`t1Ȣm/N,šx^)K&Xp  w'J$$^$mn16##A5/&/+1nTJ#:&#!Ȗo+hjZ}zxܡҵJUFOcP*V W@1"y&}Ҭ?f- I;@i"cNrfvh#l_iךsAg톛f1\$EpH]yzFZ&7Agrb&1_eLeډ4ho2gA %n6n p|BH +bf!T#Fdiڀ9g)X'I[rcgC_uYk g<(i-(zrmVW q RhG`@%'Gv<߂~G㜘rpب,{hYEf6ȧmf$P9jFPVsļェ"vs(cR[%*מyYI pybuf:{l8gFj/0Ì E'~fF,r xl{Kl}8ilIXwmk1+qK2gn-/&y tٸu j@a6s ?XCmspC[umK”m&R ]hx#)zArL*4-qF&S`r2l &{C7q7"(eQ2󘫩93=0[ĮI)nqÔh7e}6Q/ӘL51UkI]|mrfB^$w2]{IKc JPv$fuj8wȠ}%LG(6a30Y ®oj\5 @%>1Io0:&"N^x>"N5%XP/ 3czέrTVy٬OIv!)RRTԥPiGj\tfti2(h|56ɉzҥն5FgP^) %QLoj=( -uoYPaVժ$00W 聬6(LH&. TiP|SˤGwyڏƅ/H8ϧ{3`zTr+<`9raDKd\u#܏oZzj iZ.EvΒSLbAW㹪˘h#!emY%|~HBc֗B BAek&4b0?*&obsY/ŅBa "vFS+:vk-L@fNNĮX嶹tV1UIӂS2쾻.ё{-cI/M>_-"$xos]i}xY zU 0Y{6<~n@]N36Wi&I{JTxhlO($s~^=g;W\y]l^B.qWw3N]6wnΏCg3I.3gmtL9j.9ضl 7q4|¹O .ipnGÏPe y=\z' twL!@K%t|h`j"+|4%#QBDRvSbW#%+Gz~K6bl^$l- vk_$C&E=6U@FŗL '/3F̀ Wy.d70gW9c@j#1@@zUDtgpBB{ Vy7\ 00`30`mr&3{ir.a7!vWSv-,0} NypJrHR4, =$(]7\Հ bP+Љp E M`Іr 0f]W G{̓dGy(gEӢW8)>^ց{2E S$pFķY562p B! p2d  `=`2`YGy.sg%dl#3qs_ EftgXtP*E2X ։, g`E +j kgg9[i+PQ(No>@T[tS $g Yp h!E0PUpgb=0|E+uCBZ"b]s'$EE>Ts $_^2!9$6NI :`Kp  .~6@t"sZu` 0 Puh9|,PER#JRmy lz5$yRPG9vXd0Ep 906Fp0 0 Iplip`'/$aq3y3iH‹ 7TBPrkC56J* dh 92`7B\ ,ʢy ɞpn[@`@8b3OViue$a KPU'Ys^SGy &V.@$- lʦo 0`\ x 0ZUP: RbuInz"(,W8B0F~Ŷ^%@8%5@gep`  \p ml qڦqj@UA024Ca`pa-3ieӡvW0bybeTP#: YPF@ڦ@_ x@ Pz@pY0@w3FH*e!J;i:3(ksbe{2,˂qp 㠮m` 0p p -J  BҐdE {VЛKaT,[Sb-nr=a#xm 0D}   bI@p p 槛 HXp 7tḴ"ޡih_P+_ˋaCBC)Q FP%@ts   t__p ǐ.@v)d#/e.6U #yRQwkFlcoJ>tI @ 5!@` ݐ $j h* `  Հ{Cz9GD(/s=)L  B ,*! `  I0 ż` I@ tp^*d Qt;S{s3E8YbXXt9rڿ W P N0Nـ P ;  @x @ sPV`ȷ*9s0eT4ine18WP88Ld+IR<@,Ϡ P ِ P * ~ 0 *PŐ R@< [, Ĝ[{Hlz!:4c  - ӼLà p( ~` !b0V,+s c0r5X=fI@AbPcBPQ!>=c {0Ѵ  \? ?P 0@ )~֩ 40& jffRЭ92~քf"u|yg}OmHC,b$٦ 0ŀ <^ 04֡0 4nP 0 * n=00IFŕ9 H%>";'eQ0BzͶJ4[jtk  ذ0 v?P `=L<?pƐ ] ְ! |5E\7s:rb3p@Zcw v:Mú"PD>, ] аR ޢ@`= ۼޣ ?0 ưJdi[eÁSA3WE="Pat9O1>dXߡar p m )`N` Y N w @PB4ްP W:;yC(uz#T%l yMuQ;@ `.uYP Ԡt@)t3` PILBZƝ"KZIpyFhP3t>::PB  0 u @iBW )m%)._bfJu7s'wiotR3^;[0ߩ i@0+B+P3n 3`Tt3TD˸ I+A/i 2.g0 PŊ@AǼrA Z@{48a%DC$~t1BUTREeKQ>z@Tb/\ YPP$hQg`H ͞ ? VZ2Q*PΩzS"qs@Fڤ5w9Q54Lr P)rp԰ T0r097. @ Yɀ d-<wh閒SdK.8 eD=g9G2]GHD :<$dA Ä$DN8%dXM#:<zon{8ȓ5*%٢dB%$=rP`2ٶ$H L"p-bԀ2/I&IH](WA S@8$xG<Nn尵( h{[5;2r1tWs ^LOB5 hC NZb3Ƶ"10s^b᱆.ez,-&*mХxɲp$ݐi f0#TQ65,bEX/6E;.́&@{N6S"$(G6% :l*xA'b2Ŵ xG?) aV׏yŘ;hn"z;sϠk#">CkCz터Ƒ,H^bGARQ!S^$gG"a~VV4i~stÓ9';E2eHlDee;@+!P*E86 to* 4 D 8PD cȀE j  X0"$*OʓO~sV+/@RMѩ3è#~-;P `bCnldŘ< 19 ,_X ^PbdNptвU FDȂHH;@d\@gjaYG1lbS21` Edo( N[h(A&%kf0#^(BD aU Sk3 $dN#Jz ؀4ʑ 8Ő,0 l PAd0@+be 8A'mK!k~<\G0qM CBD d2N335 dCck8\l$%S@s:V`?RaPA6np̂`Ny(#M0*bF5"uE4 b9&AD-䑍.2 ٰW|p*suN6<` mx;te?4kKؗB HZI`9sK4ݖ(_@yPD5!&X"Q:.yhA@DQP1&Ӗx>#=[VwDKDlXx\@>@xa@=D!#z@ k`qH4JPNfzyTZ;ϨɁ]R@F9ےUnŰ~0QbF)|b M 2 np 0r9$x+)( Y3A<?9fp9X/cHF~H"i93@Ai >#7 (L"j{:w ڊa+hj+Hă@1TZ ID^J,bIhpt8X;,Ks)'K2THID+&OP@{e:N `Qb霄y6IG;l#h#G.;ف6 .  c#0l$ "`/$dK) -H) 7h_ 1r p'tiG)R+R1MؤZ="+DJ4%ʀ9>ٹ'*>u3 $E hQ dGs%IDE ѭYASXh) B"p7 YՎHt3ٕ) bihz]ZpHPhAy]7M ‚ bTc8Ȇ/H14H L Ob1HhA;R݋\[-g܈lB x ۏVx% yPajCMTaYl4 /ZD>Y$37=泎hjy+ 7@WZ ~ O@)_A(I EM 0yO4c(X1Ph$ H;Y>lΆѢ:ԅء+kY :R:yLGhd†yDQy;x <BLJe9ؓJY)gJcyCN͘th> ׆#ZZZxNN_{Gh.['벣YId-*O]t 41^(`15oȊ22ac]m&޳D !zܮj:H0~)r#"[l)0(& P9zM!Buޠ1pZ+L*2ުAi-ik>j&bێ9p ٮ/<Ȅ4H<>^^5_H*.wRIsK{(bztXZXK@bB7LqD!P:APp4`@4{`c<{*4L6tԣ/r!tH/Y LGX^P1D(3r1A&9~JGUDaNhP@T腶Z4~OR.J|tD<%m^젅Ctl THkWl Lhj>NbPJ8 Ahh oA {c_{HZ0iV[8KduhN=ıBQOiQ'$;p^ZFL{nhT`@40a<{j8&tjހg=0SЃ&τ8pXd*>]uijņJT/Nl5wkOd<Oc/i _p1Pk5oq4n煌JhTPO(X@L8LKsi`io8"p)orﮦ}: ZBhk(VtvF^p ժ>/HK`BXBC(Bhh(v4XHJ>Vn&<|iuS0CHuozX́XHsevunkT>nX>895@-hpKXkfxCnv6k8[hK0k'"t AcPI0H uS Coc}X:~Z[vv4_sazjfiXT:9qKvAgcph4ZPW8hxp:(b엓4*^J3?&mȷui.WŦ皇ypvo O07 `D{fi/x?F{ 4d'X0Bp9߀[6jY~wzi&h'xm_x_j@v틧7HH^h1#g >w1T!? uMХEX JE DF4,ݺ@YL}G r2QX8 hB_*z%V@:veaZ]3j<-LZQwW5\9c6ࡆ tW &Ck\jײ]B8`g&; `/ujF!L,BХKQҗ UӘ!\FO PDcGTR Zǭ(VDY0]r(IEP%PQ)4$D5A}MBhWX%}`Ә> (Lb H3}Sv2V]Z츂\Uc%-ycIreW!,X.a iTji/]RW*&R[K4G v& ,ژX=ԼVs_H I,(Bf hs,uEԮzyڜnէeFv ,YB bؚ=Y7L -rA#eVs@5!b3jc4Utܖ$MڥoA1ͭFŬ94Kܼ$cqyNall$e?cQ;cS&_ňtVҎjĊm=aYKY4M$p%jFRʴZ1x0Ns^Ĩn  cO 9'yRy{,6,(^@^/ADxbE$޺XVW,HX 0( Sjda`01;"8jV}mՀ~T0yxTM0ɻ F7t tR S%熘Tl;9e:2pa'p:=0)(eop3@j(?O*{ջQt,c M $gpᢋ (`ǤҨL_ UR?@fDxx2#hxj*pHpcQ5]s^S,@wAqG -\ IT5ܢxgЀlc 1P1}޲OghUBŊ|`,]>,BDa2E]ia\!qNFkSO gc4/8OpCX9!c­1K5Z JķgNhV8qu: $:Q&z𕡠|''tbN@5H<ĥ/u K>锬T TR+h96Xڨ.9DG-je|$X0ʨT=Q=% hm Q?E GJ%KP}S9V ? =J>a4*6WCpfYWf&06TVQ!LݾXڏPg@0K8?P!n pkp$:h'vs a'89b" ` <C?0pԀIE-7Dr0|Z#7{bRjJc=Dxpׂ{DwGBn?~0B N@0 ZmDk}MѪwj}ü-[\:G PԖ!#{h#/@601+L.!߉ lO䀩p:m QGwB؍CC?^}49@!!5 xS>.@?5?HE, M!qџJ74╙Fȟf$qDU0ȄhL914B)B0@Dde0$4L [(-)@$Ce]WdYmumv  hoho 4aQKh L*ܓ zJZx)x vFXg3L!LbF<16@,6@Vz@ ´+N*4sbR+m|=DN쟴TpPTig31 LС(zd_ZܛdȎZ LdD/1\B)9x2,4@" r)@c-2^݈iauJ@#hUeŨxGrM@ޟ6L29ZLB4P\K,sȀJӘҽζFm wQ`YG :-9Ŷ@n d9h/"@<òZ`DEQxu)EMuJP쳌яAD^Ci.'ЎEL}3xK5St"T@bƖ!d `=" 4@ NBF -dgKL( AbAf䭭҂>\x%m ̡ *T LGA@@܆mC ^on)!0 sj%- a**Il,EHJh5xj6[eJh8KYTB`(ye:nb?q,ѱ>)PRGf.1{z7܂-aHHI$LlW Y4AJJ: s!4\@=$=)B[ʋ;A?H|,Y%l31Et-*P|m3KRYh[gY\PSa%jA \\n!>b\׶*[`Aa q< 0+^37 Q&CmfuVe\6DGcLQ>߼HH @ @<@DC#x\8AT@@9E|mccA<eQalgА).COqÕɜzf5xbRWgкMQ6k=*H09ȃLhA#D0Ԁ&AhC%WbG$.n-s[TÕHQeUj8$5L xJ\$XkM%\ _@@@ &C\*&@+\_Ah0H|6becґ9D gcTtD4ekW]8`Qy`.ʟxs^uJV.3 7pb7z>DBwA1HAC  @&CK(x~v+4@::.q:du^)%WՕ=\1!g5X7KM?K_@#`$@00@?C+70Lc |+t`A`#3l[&aRԤ]ҫ#q̲eC" Xf<ҫd67B h9t B_A#L&D&H+X@|mK6߲}ҡ%g";A4W'=qՂ^ؓ>Ndx5i.׭'U'SY7LhB>̡GA>AB$t-A+(|Ba}$Y3*zx΁9*Q+ŊZP"Q&A@V]Q"D5B!K,~ԫXb많T?>i2KGJ#'2p' 0<ðxbDhdT hn鸥J5 E{)Q̛gծX JPkR(j9 b*Bfgƭj vYDshY; FL?Pxd/ KҶeX}c4]ȑeo ƺ]05ZabB1ˊ,ѐzj녷hK%TJ/٪*, E k#8 ĒSR\ŮrA2đB|m.73@Zz: F#2@ `٤[ACJ Pֈ7lF 8 ٠+ @+[uaE!ұ"2raQb0=/ 7bZJ64m7P:ў2Ӓ@S7+@S租P37oDn^q["9HBރTBI1υiF㯪^m8H5& 8u .L8B@O^cM Bc$TŅnM3P&lҍz [`P p@36i&_tqRBwBXk Dj W g=B*@Nda]:נ\7[1WDT@۽8jՈ#9J;eS =b!T|eEUZ`ycM`)0-q7\'6{MJ ֎`B5kCt3(38CQ_HFCz#P DN^{w{ă"CÅu=g?+18{rhoA~ -N;'%"H@hqO%4! 4@ s8 ok#A qC=D!E$lhD%.MtX$pP*f٢E10_ #ψ&;PG-4.5/previous-art/images/ProofGeneral-image.jpg000066400000000000000000000373731426357011200217600ustar00rootroot00000000000000JFIFHHCreated with The GIMPC     C  "  G!1"AQ 2aq#BR Cr$%3bcs6!1AQaq"2B$34r ?z@% "<:x8+ 1ʻ $F7fXBnpbީt-̠IZJ vͰEd6!#3׃cqyмI;Z0{ċ--ƓYMZ]o*7= p`k/>A_/ubay{%?}M>!VRT,AA0C~.<3|jc!#!A HH6u TB_9 +}%WXǞ<-"`cA\HO6kQPy_yamPͺc׀A-iuR$oU>X Tˆ=qcH~/U)/YW7/.Es!n@B@'h$\&HGZ1T}x`ڙ ueol'D̟Г2 lmFǛᬇHy&l#ؐ-~0^Bf>76m9f"sSy>qJ KbɷģitʏgxQ#4s?^,f"#{;O>Xd7ϙ4 %W<9NIJK, m>\ \v ,K\FǧMn,UI*RˋT0j< ) PErFEZMimV\Ļ!CrP%v*)rSر;_h>NɺYr!ӛpo `6]Isz~!O:|\;GzsRwsp]Q&3_݉i$Rr}5kނllpz#L:+6jRE8ΘaX!Ĵ5[zzZ/ab:׽) :OS7h-s)WќhN.#_#3y(q#pwHr6r a4p*%$$=[G#TR76%K!iBm 6C `nm}㓅%v&#<Ԕk0fCJ1ddPA0n$$/KKzfđk 3\1GQi9ډ߁~xHH2@)Q8+q:1N:_< RA=p8 ʹ}ј"Pt+ ]G 6nik^~om3 n9s>)N.U X*ZE1l 6m>@kb'FJXG$`<;I&vS=۰QY3a䑃Z.A[KDhQB }0:.T4VStT@*X <r"ؐ&f;ܽCe =!!@<ϖ'.DnAӲ?>WA*[]Ҧ(rD&v*j{%o؂ m <(= ^n%ERn":g缪a>ƌWjC Ѭ#.9#uNLh$(by8Y7I4NޤAqjC|n!+PS.H"^i}lUz UuڍGhej&,i-cEi=پ;O<A{?/VҺc؎ZH닷gGϱreOL-tՖL"C U+t\|;dGiWf} ߃%Ǒ"6\t67(*Rm`σqnQ!34.&Ǘ]ЪP*ۛ)*Ēx8Q2@!}E$nث]*(#hSrZfX=Otx=?,X3Q/;'qeQ U"6D*NF4Be5iP'ҔbkM$% Q4<__n~s7?2}Q  })`\q5JKGOةĤkk.ͥəlinOYlmI X.}ԌU}tTjsVQ2j)P%M4RD r%S.E1 E|)g1zvP/R>`o3?ʯreֲXD(*2R>wġݽjm(Qo"-": O,__f#n"Y.n?\og553uF(Bp_Xw"jD;ٺ0&WrrJELr|$ 8Ƚ;8jdWFy8wJ3~SPT@P3h+KSH$ I>_jVQsVMIӪJohR~X5'(Je^B{ξglEv/pmZ'bTJHԴn) W+`7f"F·dvc=3Dg<ZbFT)SKSqiRڶ!m+CI]Ž:Ks&v)2dʄ# x3DS!d~IqJFa-%-NP:2#;ͶQ늷`Kmܷۚ>RlHq,#vj9*!h:z`޲gfyrt uaX(*%_u)V[(w{m;Zy a ~7J7 q AMp2c(JJ:|gRӍ  Zx>;mlz`G,D`U0n]whxCa-(e @P6c0!EqD(qЕ\$ry'E%D=|!V y4z& A+ҳ^D[]08B~8974-?v/c Ob!i@Z6Jx>@l$,>nғ:'FȄ sW^W7sY=Ae~]k.MȇjSضX -mEȗS~/阨d,qҏd.挏/2D\6 Je5nw)A@Y)6Ζ\"]ԛn7'ܚ=UrT^uӞmL 'DByvV*꺮TN)tvynIS͡).90jLZu{Qm~2VCM@nI'8켙2sʏ7#0aj#e:8vc.9_ ֌%7UQ35Pt2:\bߙH)DƶJϼ9p(Bz@*t'_:UKF>́BT$ ۢ}BH7 %k#+U^q{Px`8sA@@ظ0ͷSbq'>^{_0T}@Vl<FhDaɤHܤ~pUaN(=JRqa`TvdARꛌHy'6vE 93Sՙ W% C/յѕX2 ZX%%A+FӔ))lzcuE b{&~bh̓V.Cly+zm0mlH7ZG &m $ e \էT'YJ>8[d\tSt*w1зH뮯cQYPWlVm>DQ̕!&W;V@rG84{/ҡft Hax %?tk'qd?,jq \GM^4-ZsI2K*ss5)/w$" +TFhzӘ6`?QEMkj4Y},>!bVORo0,Ut:zc/^{G1\VR=cG y$ ^QZU& )j6E-=Vy`:P,mnAů ꆚ9ȏ(cSg >S!G $}}0G*{'ߛ"g1ﺖ)+<%I>dy7jAmIxvo,yTꎚh44jUw^jgrZ6ORqhPdVwMd6*ޠ0e4uܭ4s}WBNĬ)k&Xu هGOygdYXeĥ0RTV}$+Pxne1Pӊ@5ştL%{^;|?ۯC+dv\52ەfM%GBT~?!kPt<7qCC*xzƬh7jn5{Yh[uYFHA pGyգ9Li(uKGtQ<i,hu,cQ$9xۭT fFq>&P?Tօnq)5̺6mNEΝ Z %·M%ziG*6\ۛQЄf [6`zy[X$Dozz>8Pl$na,0o Duwp0U`֚!hx!YOx;5\!6 2#Ä8ۦ>7>tRb8XQ׮<{־U.Opi H kJNɿ%yD躗`Y%%! Dp7L[Njn(:gbH 3kJ[ZT[W|h~ېx[21iΟzsJv.Nm:vD{RKcJU̗.È&: ZBH#q$^L_,…e]G/0[ }*9'0;>;(TϥROIb?":SK'3{PAw@E=::SjRc}‚Tzct jr\E$!@ZTc^ʚ0@Y CEaRm$\ s ?͙Gp&7݇aJ?)ҸXr]+Q?tEHWk.f"Z 8H WoӶƱ>VlhYbIv] ҋ%A.۔} $FD혙8(>Vn.fcN^ȴE6c)R( q剛0K*+Rq|O}}mpo3(lq=pK+u~z6U䐓 CV -,|za6N&2L{bzyf-eoK1@]֌{u1 S]UϦ~=ƒ==00xS2i1.=pUǠe,(|$<~o6qTc4GB'beJ ubD7}n6Ip\ڟ8aϨmwNsdUY- )IÜXS-{Yڷw LXju}|Y#?/TRJd2Ûon:uIŎ/g.;Uэ^Rӊ\\.bO+JF=.Em p8o?/>•keCO=9}~WI׋\ƆVGrfEșL9UX)` mQ>Ğ'.6Aar!J/;{R 񋃱'.V4E y~yowg]/<-s 1u.=}Og[ۿcvǷ!T9W[I_~&Ď\HuKڻ;JtvR/.DK.x%dq<۟(hV=AZlJ!A PBBM \^b"Z@rS WUY8@a+aPBH6P F;v=d/Pc\[e'W;}Xhk̸i-=,?gJ[9Fi`*d 2g!@nHHgi[n[(y? j|ʝm1YZc'* 6gyLo\l|qQNfNQ3ZmYgRufDL@ ARq72Kj ,zv6bzor&6>̐0z"bz.<Z@yx +l;ī K-G9jr fco ~,֤4學'pI..$.@#foYunDLiKBRڏj>Dr<RX)Oy%LQP1TWX7o=VcBx\7fhu]a-# )IZhu7]ywW au]YpRHnyYJi)Vј-$nG xLiDw&㰥,8i(j~VFum"O<|N\xc<1,j$X o$y:}%X6›G8ޡӲWk|)#j?\͏6ǭZlHSq@@LRڏBݥVHA78؊?KMb,wM[Jn#5sfkjm\ɰ~FmaB2FyCfSujBɷV7|MsEu#0ΟTZ(c!*,;#yt z 12TjR HJG~fu/y o턋Ϯ-!lxfV~hrz63aVwGnl~]u;QtƍUnS[mp8[gm,zkF5Q7d(䟰],N{b ܨ A~IR>ۗS3Э<[s ,]#8oQ$6Y\#nZ3=ȭ2 p}^m/qז=j>C̑B^gmP$ |TGi|mHnԕl6RE}-|RIR~CK >Ve9QKa} 퇳魲iFq$lSZ GPJ7$ nU`.E<`QH崬 NU`mDkhW@Pm`t޷<+^tjMTVV ]ĞQO>PZ{HԦR䂟?uG!H$9b{)l8 Y w}dQ8$ -p>KV/8\߁cgJshޡ%m?8vf^uNv^*m EpAW?flHJEϖ#Y}uW{hh6ԣ gY9nRPUgG>!ӚbԪ?FP7I z 9>ʼn]3AIC:Ow%A-<!;Ŧp;s߄H\k<*KGs,~‟NPjqJ\I?Q_D+U#Jq QI_*)3D= ?Ƴd=EPrb6KzyGmW- KAɯ^{;荭 'ulk2lewUȿa\~nlن>`:vMQ=O:G]eQHJ<+;&8ZޑKJW'ĺWL߅b}1r%2~"Ԕ8(_^>edv m$q%rrc Uʵh\*AX@J2^.6w˅ UO칡}u2Rtϯ]h'ʮ9;S'W/?03ӞaMĥ;ų}ݽ;>~N4jz:}[J@Ry Hi;qåP9;;1jv}δL,DVM\FHQ-詒Tcl2_t@-7 j5?Qr*8Z0MMOnm\(_~<8x $lp"׊wkQjZcX0Q3%T*RɒQtPQ,%cv,zj]Fv쯜)*SȧʣftnV{32[o)*&qź}4QTڦeTv6KC$i6%)nRB{JvOe=RW&aƥ0Ȍ fq6/dPEnB"yU' +kC X+iߕQLHT.SJ) [%+;=:A2n5=UÎ.1$q*Ax>;s=HUZ%KI,$Z=qYQ$xnz}.q$J <.8%3tTre>R@Nfu;/.M#7Qna<_C),ҝXSYJ.?(i̺*:P\# - >NSbԫY'H91fgde}L}^`)+H6H))ぃ{fxqE=E=U)aPu>6`nΏ2k~O&鮠v}iDZx;% r=NDƍS.ۂT)PVP%)9'+Fj AZinx-K*Y[W'iA/ɉ;?-TH!+q X%>@ <l־hi2€뱪L%V8B [~E'UQ ;x;wXA|YUrHD(J7U/|% 7"(2Y<"B h; nO> ?:30 *.,DFD1bvq#U(ePx RnglRSOPld6u4KV%E.G:56\ 77q&:Tɑtƒ#uS c>$6[;'iQE#⽑<.ƽL'yTOTǷiNSYN}l ԝgǭs6m-КJrFb#u$wt>"mWd-ey<]wҫqsPEjL?( 3e'C4JQe,le9IJ}4*SWQl8y&2ŭb}N98Ei[Z@~vUyErxTu5ۓK}P&).4lG*S֔(RF.zff,s:[Tڽ=Ra@Q ~1=䤀ڷ۾M2\ 3]:%IR{ͩOybn. 83 ګE#V'cdiX)q=,| p %gLUkkZNԭi{(Oղy[9q_4ƔDeU!+ޝT}>[:ϖ}ڋg>1qeZB &q SM+ @!)ZyS3hPKL~4gRm[EJHIacvj>\\p(U/(% DI63 |ْTRxQ|Ы mZHO@d2/(ክ[[@Y=]+Tay!_*Sұd~pZ nXu, >+1)dQ%ǃq?u#4mTeʜT9l-D9$0|-F9+Io#JUe.M..9iviVPܾr`u.ޡ6Hkicsh;@V(%K}K0vGvh53AH>EOAb?O+n}EXHBKBTSoS^m@/[s5nB4SS芦P [<8xjR$8rR܇,9dY!IKeB|byDVw\m~XZwQ[$p 1Z>RЃӏ 3;l*o.ZçeSh!B暽6=n7%g]/vpYxs6y.6 X)sn$[׃dj:qw4H͕6|׎:BXLx|7W@[Xv.I$6QeGA<oK}Q:6VWwK_uJT!N6V@Bwiƞ{== R"S+b2|6ƫT ATi;nRjOXh_ 'kPiQ+ Y/ŬeЕ sʐۦQXQ*)X &ZH!$/L'(ūnzXՌh_~ˡE99)zXn!#wKqſvֲh <.z)&s[9ڝXDT{e(*%@!KZBP,%#rNq'e 4jGyB3S*Y+qRlE\syHZtL/&j/ʗLja\()Wxr6[SM&g)+%W%G_~9]DSj4Z(Sj*XRH ܒn9#~ 5{LWfXw.I7\X}ƏOj'2& r$MJ[-#f͠]zc}5.92H99ԫQߐT|3 æդq!۲\2:_`Ѣ3 R~3('GQʼb-)YUʐʂ~1]I>牾1MRw>@L1~GD#pWnʔ6oYuEIbv0ڲ7$dԣ`oɽ~\aXH"&/cQY۷О:Ou,žUB !afqbˡWry 3UE'LB@mII_s"ިD]lju\j4Wy T-v{zXi%N5S(Ѭ8)<q1J[U;AU/:fɺy pnLķ yL@qӖz觔@O,O2Z)N.GCVVu /烂paOwϕxQrW8";eDD?5کi  o+ }p.-+m.M(n-@-q%$쩚&qq) X~_LUFVT-,3'TS jkH@/WR@lst2]:3擌VWPG-4.5/previous-art/images/ProofGeneral-splash.png000066400000000000000000001670271426357011200221740ustar00rootroot00000000000000PNG  IHDRgAMA asRGB cHRMz&u0`:pQ<bKGD pHYs  ~IDATxڔieٕa39geU @csGvts$25ESG8²VmʦH1DE9F@ t U@͕UYY9ᜳ^?>˂"|;k}[߇1APU BBEDR~$`DD4,T5/ SD^zLu/G._PUU("O8 D`$D$PۏȂL@P!U@A (a!~&@ )+" ,ީMtcvwg\ӈ!\(_+t:r3˅0MLZD6iD( 0ؽYH?-l"  @@PJ$}/W|O~({{窊orhUA5W-U%\ްVHAe/};- +"/br] iG@Ӓ@QA{1 t{U5+ @CX EDH !!PhnRPv{P:uQxDFUA$!@wA)mtniaVh/_; UUU#^4413Q}7rFJP$n6iwB!EN BgƏ [ $qm"+J:{%0 HLx Q PWKB$(AC{O?Reâ"`wuIۉ&]|Քni{,y R8݈iWhΚ>uGN hu~)ҧ7@@QS@ "*(ȖMEI#J@UhL3!lSEL1% Ŷ! tbmʴ9Vwa?Hn!%1E셻ZXjmoAk4Hs*?†. $XJDB A" CJ́50CRիDR`UP p'bʆl@]t)6\z* r{\ʃ6-N{=mnR`ثciD D5ꮪTb06 JYF?R@D;Q +$j{!{T  0 ! B0DY""" "( (ň@EvG3w<v瑱 $JtjJ "] B"_^t".v)jBBۊv;B^ZI0&^n"J0+ES{酞>D;{<A=&/ E@4C.dD`"D(1u)0 *")0)a9yV;Z dIcn*` Bu5K芩E 0Rs;Sr-`[Iu%g XVEˤ6Ul-VX:hJJ$wX{kUbA a ۥ"(W(^zK| 1y[f _WM3#MPDDD>}])TT#)i+At{ q_cfrvbw(tjZL4[WW}}8=ӹVkXb'CEwoëxP"j f DZ& j8@(U`qAB󦶹v07260yI13C"-jbAWtyIE).;x6d={jE"%B^VPYԕU>.=XlwWXF+!rL!7^҈W("!j:TBBH"[\ڿq9 ȄH*DI#"%@mkxXce%:BBW,c| ~ ecO,^+OxBDJ86Nx?D$L"ey0 yPe 05,d RQP- Q V"xI:P3$AU)SJ]k^)]ړjau {Nj![ E>SeƜ[˿[]ݽ衢䳿8NTD- qQrq{x+kF"RDXA,O  8.@% 2"0 ql5"΃S01F 7vЮ%5azJcFR/KdN^@cX6q}$k/\m^`Aоni/kSj Ҹe@TP܂@ hZ]B "b`27L~"^ao˶섆ųYbB00ZCS*,L+o Է7PA+weЗ?!kڅ1ァ a*_h-iY @が 񤣄B@Hn!jIH*13!iI], l 3G9*EU@bh'hQQAH#h:Gb8°4Ӹ4.b\6 `oR.yJbwY**QA\ficK̟zC$PųB(!m?X+M[tR?MimLjlvB Hf57bH 12!f&&&&@h{ҋ%Ef +*##MY2(r xmIO DHaxE ٠ڜ @i]hth\?r V'q~A^8L[PxIe<)=Rh.SLcu-b\o@ VG| AAp y6A\ @H 0xlwO ܆4:(B*TcTF4!C-H#EQ"7ɰ1a}k5HS"3KmG骶N C]Wʨ- "_C@H@J@J`mP/Ʌ>(<`5r,9'P9|A!P@dJX<& `"EiPZ LJo\(zM]LL'BB`i,zL|!HW쾟dJﵗ詶~#kvfWI &1dÚW&2=Hi#jV0]E~ b0ڦڃ̧Q!zFm(2o'HR [\E(+VRԓ&T9' R]2P0A1FU=,p2sHbsG{[USKX^Y%&oS>¸>Tu%A\R]Ķ#Jm\EWJ )puIz牧=~Ձ8j033vH#>!QUQU$QR@ Q YK˔S KUnL ) 7'k!6Bɨ@x VLgW!eֱSڂiW]B{uamI *65{ReAlP w,iJA)#%RS&5Rd٩AlTHPDTx_@{Փo,×Óaꂫ%&bfC&;)!@5(B@ˬv1 U'tYCl] ~jWӻ]+u V~j` 8񙊅> vqL{i#ibz,]1Fb$'$Ch iCgQFVȃj@H"JHt# u=_~ˏ\^ߘ؜\޼vbaMNF'cc2  FTbTdBaKhMe3D L'\Q-8sF]B\؋+8;uC1*Jo .)^+;gV`ak 'Dz9GP3a#H@2"( * ##R,"{Bz>,˲^\9os֭;ȹ%ؕslcEPהHܚ %xe& UyrmY#yk{'k?ܨ P9?hsxT M]BmEBDLH@@D@eQp  #qˋ;=a+\% 鉺ruBeK-R¸bV ZleEP<G8P dte5&VLNOv G8H{s ԟ#\eG7 mrڒŏ> "ԕjͣ-qE[@lɽ"xoY#D@`Ni/mT$1qO|}!̑53epqn8<PT ƓEUĈv#"kMjXAZ|1mfp)ju\':8u3 ZZ>.>l65쬝=Nҥ }خOlF=HwIQ\ "'@DQ4B΀\ ҋr ;s$lQduk'm5LTը!ܸ1v{cJZ=.ܰ 8%&YfAs*i@DTEk1ǜIZ fIzG~.;*n9.t g^o@"Rɥ-FƆCKGB]90^\M`IXUe!ۣҠ* "ꃦٍ6< Rd잁i b'ҮP!U&v*۫:. 8wi *X;SOݽ{6!aԗ\G`74(fŰ4U9b.>=x$!D`hq{c]룾F MU䬱1tIKnU{S48"UpAT,%ը.,t! .zE*9ek(q"RAc"Fe.Du"UMdc¼(QTG>#7 JwɟߞZ"X+"(J(`RxS6b1'Dk-2īo\h6BAe0h{̈bق=`=([  PAv m&SeEsVc[OC8iݤdu +sXPr *(ReU@HJ -muBp&<ϋ"[aQ2O>u[ U[rV3!y1X#("+2Sb٠pX!'D M/ j03 p{ 2 4^)ŸŗjO+%Z~d:c̎F'5_w -ϾttVu@%L&Q" :Q@C3МC=D5@RNbe5XCbDY0{5@2(  G'>tZeGjjo5XvA~bD@d Ü#Uh 3IDDZmBäĄ Ȁ` FA( Q@`_>F$[c٭K.B_ާp:aa,c,K_Hv@ĂT ̬ԖZ}y'(U9ï@kg!YxN,S w4ɧ2mZ7{EaJ Hd,ֆmN8:9B㢊XXp zM숕mvVF8LYGY]|f9, i{($Izq~MKJe1q9Z[#7B!#z4R bs~9F̡SD&(I d QdML.^Ȋyu12g=pvtptnc C€`%2FlZ$7U=_Xih([E v2JH>(h;-SH p쟵$oq)Dx+ȴocnt{G͸h8NL[]\z v--"E Tbs$'qB8N(DPDY@0!N õqQ_GcLr<;>߸u˖|wVo,13h3ȘUU  YaE<X6d!Y44F3&&# JqI@1%#UE#}f-U~6E(L@Q"`HKzS} ]ØJ'l%~E"o(G!O.ml q+&ETEQ0dԇ7!yUkKR䆘FJ" &[Qn."\g(=C2S Dg,4؁YȢfZHrnsBQ tD*6~;C6 Plv#SU[4k;`H)/%q4.Mvqt 9z-c8zBgqgEQ8!m a9Č4HI|$^UPDE-#Ak0Pfwk{s`>gY|;yd&CCh%o{Wo,<[`,߻1}yϓ1ɳt _b!Xk1^ afF$Qa;@B9Nj'*HA˔~zzN7oj򚉑sbqSXD!KKv4k3*>qT/jU/ZTxyYTMX,{o^KKW_ͯ}߻ygިR hvv}k<m+ta}&CM݄1s$ !c90boBY|4̋`8?~{s2Gwܹq?'1YԳY5sy M]ۿ'ۯ=^}?w7ͽ#;ʋjږ9B'\!n<:[R+#'ƦiXSerJWI]ӃM0Ԫ(ђ6Mnhk}᤾$ [;6"iT^4D /IC]ƫ4qGv?ύ:K/꜐Zhl8ݻo/88ÐTv}(Ggh}O׶_izÿ?/?ffQ9836QA@Bp.R 6"@Pext% 0)*$نZT" pp*e4!Zd(&:*v/ sӤ3҃BDv[H*Q!O 3 JAq ">!KSUM1ڍ7"AvGo}7y[{C@c f`YY9B ϏOsp«}kka&kkB!*މywx~$z5] @i0ROyNS1C:bIoNc[孤!7{dqBpku9ǒ#~B}m#D|XV>q)JfS2"%U^Q ' Vb}4)tT/} * hR%ibZ&2'>5_~$Y:GR!jOpw ֑cQYC2gDf.5Rρ45uBs\Un'zq7{7§>U~{kϪPb&"4>*c \Bܠ"YB0˲pm> sǟ1ο߸ȵq__ݝ! 4AQ(TߨXU'*z#!zi><YҠsۖ ]?%.;^p ]vuuWIwlvpNr:@MRk%ca8L(I༄B+P1-AE~۪P% [ZWfS2 w^@#D$B"CQ{_UM|WUTnb>oJ3g>};w[2#y{2Tޣ:ÑGLd,3̔w߾sB uJ牉N{35Ohъ6Ic*E{e"Kzm]n"i# d0VzW hS'yͦ$|~5[Ȱ],a]Ϧ3$.8RI rC!"+}ݨ*3SD1C(g;o|kW> o;8\k/#+QkJY j025M& >hӈSR߻Շ>__{k_UUD52eƖe> rcss{ke-߿px{ts_u]C55d`VY5{7/?'o?|rw>ORtw`6$@E l-I=hc/+Ł`:9}j zvv*3?; D2q*IAVPSΫaiy}="_~ŸWi!Enl_zŋ.nmm'l%T9:::>>~Ws듍/>ԓ:iܺK/wlkywo[+s}Sx3WuL* >b$,KL2(Uy1)kNTauX'@ ^@EA|Y8pýffK?//ώM (d O>ĥӣ۷n}A]͛6W<$4%xԀEQonn^g_3_W;o˜__:/wxoBfZWd lTMP5(4D1ؓb -[\=EMEorNjsKG%E HS1*>zz%aNr.3|VfK28%)(*#Ae`: ^N6~,&E,s/~ַ~pqもN66~+׮ܺ,gh OSDbOIWPZ([y&g Vagoߺ+PdfG?o5+?`|-~!59R͐Qvs_}n(UĴfIPHm' ?Թ (t:=Dhxшc`I8Ves_{qf z(}O./iXEYD,*@]]_*ZB1/yⱇw}o_*5.^?ci^~酷*[(JDEQ"*P ,+*WU $\MD.@bA.c_O_7ݝ{ŌP-x|O~w BsJ9e[LFxw(XPBQ9#-AE`C(30Kp ¯Ư_G??7osR7n6޹uo܅8#A^C$U2k nFAES552i~|uP/M]!vquZ[9tap9"w҇8AB0-r3ѺQ&I}\ Bԋ hP_P*pڕG7/ܾ\l|ܧw~7wn=]c+֊r}8q9GavimkGϯeyRh=o2f\),ٲ*dH-f}o_4MS,2/16H&̚,;ws)dJLԩV6<`2Zi\2m7c痢 |rFV3{2+AXTfD*A$#Sy)kHhB=u~A'Vq<*?S&tҗsoܹuc<,ֆID-qYhX- në/>wFqb8$uE'ĺw Wc˜PEObXKOw?IhHюȋ1$&l:`7*";wE_\SϾq_G͍a6̀>|ڇh(2Ėq2lN7,3ռ6^ x`Fd4aQF#v__?[d?y߸tLXkdb2bL=(FPԉ̀[bg:> FQV'i*DmG ^>tKN}knIAQXI +((! hkkJl45·\?o|K_?l^1eQESؼ( 2+([.x8zܕ狜}hf LFËkέ]^v{2O&ph!̘Ar6r܇~GܢYTM~ؗnfp@p4:=jSJ/*c;5xЁԒe(EA;n6h(c1=> RWŜOmj-( -}^840#kYjPj*g9L,꺚A ٛ.C?ɚ-rZk"Yf.,c8f^5; G^`2Gd̆9ˆPdE.ln逸x_-ns15(0ΐP4bdÅ<9wVހMz E uZz]m@MT9R+]GӣY Cʊk7Z+*--k$o wⅩ+Zzmc}|`R/@{7F>~Z;ȋ"ِV:<< D,G"v#8o2Ca>)|6O3ύܬZ68`( V⧋|:_Գr>d6'>,+{ES 2Qa `dvP p^%U4Rv6QW؈$6,u411tmZK DZ/% tΨ8agKh'M񸅈awXNFAsEG4&(ū礪~3(ˁUέ{N83ƈLToߝTp4o~i\P"7s> MUf cvwwXܼ> r_<+wwU9oywo߸=~a3{{߼N80`L @PDeX[ftzأHSN KD /zIڙDC֒WTcD&,+,ޕOrB C>rPDU@]v2T!̧nm{ˊ+6FO}/D|85֦5!G A꺞ϫ\}\Ea^>XA^ ̽'޸td8*PŪw׾Xr ]_b8 iS<+VGQ3i9m<^*W@Xs`s"ju<*Yn 6VG`mqHNMfuY "'֤RN/%%HBvpuickc}#_zχΙ ܳ7 myߺyt&d-/Í<3%!Ksqk}Yc̸-fq9@y+޴r }hlhxESd?5sƟ]C?x_";xbhdbq;Zm^)ThEWlK?alkUVEJ>47 WWX"@sWdVS&4Ci\VƹܲqP /ٵazxdvE}n{E"6\?ݼ{mm]炆n޾xp0pڨsѕܹwgݻ?mNP*3,w1.?_t?ڧ׋"0{>/[ Gkne Y`~pA" Ʋhh8!:IzWw%g9rjw6 ŕъ>xO\'j5bM DɿVtXUN E@BfyoFݸǟ ^]>^I\X |W^FG7nzdS~˯1U`r (hbEwo2ksvzxT"(%Mtq)KN_)!/[na۹䴗 ,Ԣ_A'}z-Ҫk /8h.oc廐OyMN8&&r'u%>\ˋ].FjSwo޽+5"i 48yd2:7L?cÒ\;~Ez50(\~'+RU)WMm*!`ƈȽ,pi+=T/DGhBb]T ǮKvuq':oFoV"pPՅׁKmZ޳ ]aE@ 4fgAa3~po|/kxΟKXkM,:\GſtmK0fᚲ,Op(YP(,YT4fiR/ɛt}G:%խőxi*Qb_wXX<eP$D^8#0 #PTN  hDeV1 Ɋbܽ]lADFy&`fC퉖γe6Pf!!ATu3n|-,”,% 2s䢁 yhs{/TL&T9M6 (G)LFDwD$AN>;VL@06X)a0*etee\mSUJ*%[7Dzwl1H!Po*oT&V5_CQ02c/kRy2g3(k 9qy6}ŁT[g&&71g!c2,3A930͎c똘Y?vqNP5ĺZӻ=ӟ Q("#rLJ|t0]6lq叓Pu)<'3V0dmg➎ZM\tFt7(ؓo8Z8pqq;w߹1So޹P(\(˲Z3%eYV 7Y6zՇ_:cSf%yeZk1Qh@ˢ,qQdhx8O\ !ѭ@36&f'RRAWRjǓ]%ɮ,;ҮT&?_lA"ɢ(a{D99nakQch9-*Ph?[kb[oɧ r2 [TUc!iȰtI$$D^x?xI?c.)A}0gei 0(y聊AKvm<<^lDu k/|kJB*QI>E+9mPW2zHPBn-=p_bo6e9n&o:ְvpH9P1Lߤ2WlI?cO ,W'~W޼}>onyiqBfkl( G7綯mmOz83 0flvBȖ"ê0,p8(Ǘ/];ϟjMk{^zE X1#rcɜm}YԥiG:`wjqtfhi~z7WICMbZhhh!4Ux$um9DQq0e08#r׮3lG·~kÍ""mrEԨNJвAQ=ID|q,7y~e<+ 65)aܶN(K5E `0. wnuөf] I_aMc^@#eDD!jcj7<;]< Jl}(y $I[l zjwsS,V^}FNCN汫r@z/-w{f KgquN9konW̧|pp@N;espN"DIsĨmF+׊,CY<ϭXڷ/~E5e#[kTq-!D4Ƭ |Tà kkιC r<+b $(OX?٦MGQ?_)wS^ Nc gL֓ ÒOMO9ZơH,!Az0jZg`(*jQ}\hzmAQ&׆Íɘ3Clm4A%1l%n2UU-l{.s;66GAY뙱"bͯΏ}ዪh Γ4UW,-b3BWak90^p~8"pv|4ͥK1dYVdYeL-huTЮ@U9mwh͟4!( ʻr5ZxN@?gbR*J#HjlP( /:7B}d`m4KMpAFޗE]׏}#efy> \Ybf&Enx͛ӣG A""*sPY,;4M]&xm2OQls@J30MRwiI_Juce S+,=W4rK+I'3|hRU$Dv=Heik󴳿BstMyV7(3vs2.m-y@ZzVݕnPPH P2 N[4>fk5E"[oo'H-A GG|{έhRf>/^RU=1!xL O !?6ÿ\\΁sX/ɧ Go[ox7 ɲ,SBjΒ4.maowS#ƌXV5Xr!0HKVozX\ vDU$\q//i)mxhQZ WV;Q X὏=Ay#ۏ?E].;w7/^ HhMviCx7Ȳh|ᇂHݼZ4Ν?ui{ks}m8@f!+l^ϼQY;wL[{5e_ßGݝ4+,[Fk-< ϿHܵGn߹~NVJKD}=j\Nq 6}?OĎ9x z2Emj K z{rA{M@k{G:,*w3\s3{6Ɠ/|AfnTkx<,KO@SZĈvBPPW|-+9Wя@G^+ϫX jUy.3?>>.ܹW.fߺ}歷'{;;oVaho7eOfy>V\@=y3̰08)dhmnMi%a^xspI.S()%BEZ-RX^].+h.Oj=Tt_8gy]8"g Qb;<{|C̴6d7ƓAQXb gY=_(-n߹jQַ]>#kg>Շ?';go]}G\p[69IiTdv8e rf5Y<^B6*a}~}4[^NI%y>%BWȨKk[90sв,OpK8aEx!Xď~`0ˬaTFV"UjGlɋ"Hrŏ|Cבx\=,}#{_}+6-ΝPp4YU\Yf<b{}REY&%92 -~72!EVzk߈jűYZvɪ 1j1=jK?[v>)0jEԕLUZbF;YbOEOS#D/ P_Y8x鍛c ͲQHKte5@ QB11+"#S"yƛ7nk>koxQ`0x |Q{看h,AA *d 8acj_9b2{*( ,YfzJNK>SOnbwu8GիzsvvG>}lr R$6*C!ki@[FSL@q}@V@b-Q" _/7X5Č2cJk2Anb/D}mGŵTN{LJxѝh8so^|a}k<9$Ad,[˅ $H%&_󅆂^y aJN߸PL5ޤ讂"ɵ 8s|.' ރͼ$~v5bednVF0+GX SH~l䞘f))CHOt ]A0\S<6Y}]L @ypW#L,xޜŢno|sK 2Ge>ݻu۪<ȕ;;w^-H +< :eTҫ[D6&̢L22WﰄjӶepr žf>8' KrY9[S0#'ǠF<{vs%v9^ֹْybP{ Y%#F\%!JYvT0 `cp}}r8yp8 l9ٔswn/y- 3.)SrM^HQͻ֖ǣ fYgcLAL$VsY+Dk`< H 4D ؙĎXxD0>-)/B8Xqԕ^~)׾PoD{}x""/zx||=ZdFHacm-cbfFA㣣dKO-riNIRP58Еҳh8K~(X! }?~CQ6 /|>/َT׵dksc4"D_7*na p^хiUu( ˛ߚgv0&+ ED< qCټrߺq?/ol]~k٠4 )Ak ̰ \b%:-g;ڔf'"gCJ/#uϽZV,:N~=ۇu @$ a慨u"ƴscF)m]5G{`'`?gX`vxL +'6L@T Aj,4];wQT-fwwgoflla! dVqa@4xdRfi*)nK^y2Y,-#39!c RfMި cdP ڢVse >'*&`[.`HMUcB9H"K⤔[*;;ElN4<@@4 Pג5o԰)8C@ڞ$p2`@ UCC3>yʊ%l7Sҥ89AEHg8+mq'iv!LR-"Iɱ< %yhqi=Ճ1& gL9Wn Ž{mo]x`QyANV$Ì מȾ}d4(skmpP ^TcT`0LgU-ڜ-A5h.U67&^ԀG:OP׮q*@9QEҺLzUmO 55#RQf9zų[&XQi*OBI$:nH?sqt2]Yѧ>@nZ:Z#jvr.V~,9bzYoG2qݱ9aF@BeI iPAP,6moE A@54! yYpU>ꍬ0nl=?=zzs1?tޘF%=XEhcAYrsxGA,[,0l燕}hm0w<`gw>Ύ!8VYkӦ ySQجn/l\W-BGPkk׿wʂmƦ Z4MsJDN15Zk`DY09.t -kjM1g{NMgC9\ޝqx#($'9g3d#bEݼs[ţ!hO+T7CqXEqAT駞|F;W7K8xn}\ 8q}4pn2(FIS-pQcZ m!#]}2g[NZŻ ʀ q4(jSRa bY T @ۨŕ:A6[LHElTzĖOb+ѤG:_;h6QЪRu5ꀵn 1$ok iA32DeBdևE)h`--qYl'|plFlJ[zy[BTS7_}O?Ie!@)s Ũ|G\3N!kYU3+Bw GF2BAd嫬AR=#kNªCuul1 ( | 1D-ުDEjYVU5WGbC"✫jJ<ޞ:OE6oQE!aY&Ȳ̲!(0sĊ@ASI" = WtۭXzyP]!v:>ֶzV!)!M[H5"iFWiyVvoBLFv6viv*h<g M!a⦪˼&@(Pͦ ?SS`:;Z̼"`1@Q0:pL (4b Yd^0r` 7E:@R@dKO h) ;I5vSv\Y&D+XZUմ/% DT>Hl:3G NMҮHnvJw9!**D%dU=NAD)kd xdlѹddx<r!b T.lP̆]&HݸEU!CPKRA&D#3T/AH[""ޓBC  2DKry?wPgk[E%lHWCCǀDA{d~o lÖTJ' Qɒ@ Ai俁D A6e/Q,'Êp4/*w"Ne=^,8D@@Ti.>!bLJ =Q3p+}rlW.( !NBҺ &ZPϹmp;ؑkWXR KѪYVOO<.s!W:2 pJ{!.:xzluѠ(ony~|px||F"&zb "o(&[ZTm[MB?gbe!K7M@(Ȱ4^$ULl0##܌1:TګXѠ&d@Qa4:g,ωFѰ,,, fdfr,AF*@bo%bQ}J!Rʶ¢ݑIiϻ"Q7N?Ȗy"KӐ`qŢJ*R:6\<9i}uaty.lj`0ѸJ*@ ‚jH=4>4uYd-CƘ` !YTH8kȲpm8EU5H$ WEYcFX(pP8q'PACtWN5YcW 4 qʩWG'joˈU1`Z%^ pE[2[F.]ʵ]tF/y"t󩙣1Kd"xLB df~rjQJ:sJAo}us ̫Q&A6lȓ@AUD0*ZeEyn|òx8ȲLmeE &(T`@UUl^V?qoWsVAxPLIT1yIA;kjwݮ:P:^%҂8I)rԛE-ϥ'7L"VAHkr:q=!:$SNI0L~?Ͽ'l;;\ sa9!0. 55̨Tج "SE&'_fd\nmnlOAh3r(reTb15h:ʕi/?\y E\')/]OЉ3'Ԍщ?tb4KBzaLYZr'JL@v.Z՗BM]OaВCY;AFFv4y7_Ǯno?ܽй.^TI@78a:ŪEY9QA`m8 $:Qhc{"ƽN$I\?[GeH;.BEe\pТQdsՇ~twHӹ agum][[Gƪ93MʇKS7E]\|f|vs[[2e IEHy]Mw?>uwGʷ`w{ >vsg,p㾠R"5ըG8KyK4'awnI-Q1Jt [Kj.VB{5QhP8턃ah )⣟lC{`j~0sMsp7xF0 6q" i 277f̋\TZۖH@@Mu<߿wgw}ӟ KH E=;&CA@bLhΏ &Tkzt VPR*'VFaYPV'V eH2,E׭۶eaݺpQ?_D 7Z'?_׿bi"8ǡf;lSLJ_Ʒn޺օ[sŇ;&ϲ y>/^3fXdNH 5 gSD޻;Us{w[^~eon]\ $6B4B5@B(D-:'/݈ ixke!5`}J)kYjQ^Z}u]_(0iHJdMt 2I8A iP={o2b+(A.nn\νyp#ދGWι,72G6yj D0%ԥ. zƝ^{{E@?>HTQ46t(r҅|YGЬ -\1_Xkkm~mcݖE: ޹{[6m;`Œ "bV9'wvv^x7n9<{phʩ)F??/+>w…drackD2\S"Y@]3x !: xA:GIDI`SK34IDW 7.L-H P9cBuWX=u:UEEjj-sTA^MYAZ(/ Voxjbp4 2O0v` (rwz0*r0(JY3צl];ڈ8tn߿E=6//}G~r>(]{G`.SEa՛[1[7&tgaЖRruqy@e6SNEve5etA ٢EUγ\\Ha|^n3UpdjO!TQQQ>"{/y !q/ɬctYvbk{sU5@b$AlZђ%ZvmGG`wGXaݒ[ nM $HHbk@Yw8g:7l9g7@3ʦϼ'xr(_6Ms)5..CXm6aOOOaujYj$ܿq|q@AC uKܚ|j86gdL?c}H`d=&^[A0/v k{sݶ>v%ih+& k_e0oؿ_}=KU`DML7nY A9xk85]? d*9E) R(Rj)% [%&$QJ8G ]4M1zۇGž!v]7fmۄ[jryyy<=?&|ayh|#W1`R4*fG P= !` 4pA6mGq,oi#FMq!DAӃßzN/_z{W}H)&a|I"bޞtpp})e^cCPj*Shnܼxpqy VPCmjR8>_,_˛z_ uhs|m*1%/ YoC6^]..J)>fZZk\ϋalZ-U јcHպ뚃7opuy3 1j#E*B[IoݩӛBcɔr!~1, voTc.`)yc1k.,^*|zzONOZQ$uPUdhmaB 3f9zqu(Z(V#jDcL5 +5bq`&޸KoĈFU  TGCIXq;,u;[ \'4 *4) VTJCuP *&"R0TsW-ZZݛ/(`ZnfMuH%D٢[ e\-j"!!m6f6W1mEJIioo}=[yS!R3\ni>m↛뼒WWWM"Q   ܿw~tYZJA#nf*"I宦]כific۶5HJ*>'Rw6fRb>X5M\\^b`ת(ZT-0"}Dؕc$OuLL A6:!4t`c䈪ZRPT}g5YۦF$:8_oVRK"UFU0,޽{C)ELPUrY{n1 CͥM^Rva269pVꨙQ${Z?=LS6pDhæ_7g{t(Z5D`1Zh{F})QhQDLcl2432PSUͥ0*3dڶJ60LZ!@8HY_pfmj %s!` LGV@\ц J~jRASj07*2 jH"*HDm`"(Z88^duqyMLV&?m}BDƒܺqKZu X@Ue5y5MR[^?>ZX4 6?O9bsџxb4䋋z\.^ՊoEՊ.]:)^[iYν7E33z2P_SU"oAb4ͰYW"e' b,B#H8G4CSSH!<"[%~- L)v]Ǒk@tu6 m_+F.2!)0 Ml7Qν0Ewl6mJD89f[gpj C F|@ Z O6ܹcg'''2sFրAP-e^_^^"~f֗BDU YfwHM)ey9˜B ƈhH]G l8V{PCu*y>k˫˺ !"U^QmJtY@SCiqjf\D` 6v.Dd"Zٷ cARJ7kfٰRj5XDqnJ!4"r`DHDLQUJ|s>;;[ݾR0D^n6<`еsxpzfƈDҰWQ%_[C׫EzˋNNN"'D|O/..e޶#J ! zXաv{~ OHF".ҁR S,e#bzMD hv*PEUt۔*(sY&2@IPiYgf1;yJ$U 9BFL15UZVHQ-WyMx7c !}fVJ&٬3Zk CJ6Dd8""a%oslShj[$tFc$o֫41sxw>=*]6仟Ոco\nK ߵN䔆gUkJ6mR24IDܡzyLD!39C&/s|5ħn*}hR8J)(QQ*1Ym2XIA!fV֪>$`bfdԄ0bs4 %wA7$fnB@TcR`e3bFHAFjd5g@D FDk@r"/~QD4ƨ` IqoLu*|wiޞ]]@)倫ݻ[x@Dfz:E\_]mJ)Ą : `-㫥Zͨ5gDkKZq82q1Fj" !51[60R"BR%\0`=fGwib9#PrͬMZG"D!nr1ncT,*-s&03"j _m~_<;;# "€&DՓ~S(q1 ;9}{o2PSjE.QE|?q'U{o\2,yܦi3ZkFDcl|췂[<@`[kċA5 ܿq|q" c "I3*3&3%V\ss!Q۶#1BuXawEi̴i1RjȦ2:}|a@ b}t00!L  #C#"c_70!p@HqQ|l-^Wfy}Y^]=~TlxȃZ۶yI6Y̱ 1$88*i1.ĔR24fFmB !%"$&Q Lb1il Kn. Lw` "5Gaʼmr?Hňb#xCd6BgsIHċM~(&c)V9fG-~D9rbBл,. Hu7kf睍9Qw(e[R&|@R#~G@MӤ"ɉSαrY,Fa s<}F}ԴJ|ͳaI)iCm'@JB$b"5PZ0 %S ӁHz'̾g[lg^1%[mZ23@R0&&rRST3tcɇ7c'>|Pf"REXDTa"cׇx̼7Ts܊f++10qQZ Tہ" "4!#1^@́CPft^}m~\m@ ͫ߻Ȓ lf})k-r||VjUMnܸ;0^cc) w%)ؤ$ĀKM"Ffj64#!Hxn ؕ_\V3#jjTtMT$fP͔6 `!Dj硷ZH$ƈEU_p$>69"J",fREďa:F9#>s5FNCCե&PgPSV]>rEjb6="^?XaUî뼎I)Q@dE{}|n 8P - (BڼiyyYGR15aelliWI_XKC ԘT2!0*Z-B ,~%3ѐ0 6 !je_tMD%26t+H1[1ȞT[cb#;&v6"1 %/l6uL`V:܀n^r[CLIji Ąc11-w?::Mh6W˯|+jʉ$c$F;;r!0U)84ivrMCUDqlDso=J˾"##r1 R9)ibLd1-sB&54 bbv r7+T-Ʀq{й6ACS f&*H3-T՚UUE]Q#Cɹ_3Ʀ喑 :1\xxvdE# 9B*⃷޹mPB`ܽ{Dbh3_| 3m&ƨD@D@733"Cטt܈H-աggh dbChcE YE pibVUĎB &ԚUJ-#V19'7>C,Rƹ6c̠㨖 5 ɐx;"na& lShV*RhQEY P43a:6u1R ϿBЗ^A!$) BS1٬z.I #Q4V"j0Z|(#TGFOљ' O,0S`dR"9A&61j ]l GʝX1P3fZk 25,b'nj|c0x;g jXjC)䜇aHVAF4VUP3)u: TJO 3C~#,I͇ &h" 7y}yy|@ch4N[Ewk/o5fF@ zIOᘢ"tĎ3jGtۜ钽0 ̆cd-&J5[Q!%@C@&C30k7u)V%ZUGm']SXĮA >̪qbRM*uӦ֖ѪF {/V}Ab;r1U̙6[6\@Qq>̓*Ν;>??WZUcJ Rw DfXū31ADRJeȾ G9MqXjd&eU%f6"r?&vfcDf^W\( kTkw}2,Z]]-]pwyryu~~ Q!B jǷO-&F< W!"G6* B< mqiQRm,j7˶4e!whPafB'oQk%*UT@D<<'/"nPGIXuY*ԀԆ!p10qͱplP!s)DT˜YNΎ9̑/"'|)Y+Rz}ry~~u~rvrv~{oKMU&Rܿ3:N΢#""V\eL|g~MӿszNm/s|*STJ؉8)iSB908ADMb &IMm`/غ&P J XP#e8us9«oʋC- cLm3^?4V`":vFUlyd qu~oG7K%ҏO~G}3 5K)s-C-C-EjU-+g *[A^z7JJ?c~7x!?8zD[Eo"?1.(vn<3F3fKrv*`m}b"UӢRPm[Jj""RnzkQIu_"cLmÑ- 2C1j!֐G?|ݿo~*Ư9| G %@ԓG eo])MF,!6,FUa"f 5K]WasquafE*"_9Z+V) C7  Qw P10h^szl֖:»oЂ":yuUۦ7n~/^?cZU#`)*EM쩧F#16]TF; @U[k-jGEi1;^/+i{WŕkA#yq }DH&N&ZeRETU|,i(* Ur4c{_x7MCh`(5 !SmRln>;;"jgZBVkm?ifqx-^ou킃f3Sܶ 3YUK F_"YuNUs-Ĩڨ%U;/Wa鬽_[fy^W_VU*Ǹ.C۔XލE\4}E}$vmg!*LRk-9B*` U +ԘXmя|{vzrzw_|^wVWϛ!WQCx~vooc?яSn7S?<̓=vr}/? $ ݳwC)/E f  {]7``a9A50jќ3o"2oﲟw?Grz'#H0'8aE$R2hd{ 3\@qssDͬ|h9~=ҽAkg\90hmns91}? ^9Os@y4cHD1$E5YׁŃ??}L]3 !9+ 8D!hbu|n:ݼyIӓb~[墛8뒙)US)el6WW }yj)akh::-SY1> }{D̪f-gCKMuf0a[S:g~Wx96YR8ܿרasuZVρޥ c)|„љ$2%UUY;oL +/"Sla1Nr:3  j1])28ƑA=טl'w&gF >p7̖R`q1ˊ*!LD؇ BL"w0"1*HDT-DL*TEu DUƭYĦkuP`đ9j5Oê*;:P%&4lz155PCLi$FZfASڥH@PJhۋǛyBn,.VkX/y< 5j}VdP0f3 ZΒcR4v֘4Ljv<3VQQVN6|8𑀠q沓f<:1Lî#'Q( WEFZcM6O|t 33r7v,t>;:X֘"%@,^UG ƛp[23 dw̍L23#]ѓNj. ԥV+1e9{/.^-RStM{B9@$"U%uބ=_nj7|}bVk>fgg)j;6խBiUGNv%.$X?tJ͈H:ykWi?~"^֙!;2)-Z܋ TK̬aJȎK2^mAhBRY˨NDw~IMȌF6\.ML\#xDEcQ //`fBjQ {7Ӭ@g9r@UAm jɦTGal$"G9Wwпk?ԾlNs3k[ro6=>S&ܺyȩvطYkwɂP'._ckj NUroMl !#,}v,F$:|<\! FfVsYNNz <-Evy 93qVnَ;k+ Dttt4 '"hG7>VUk-hmLPKhW톾_j^!#7^|WWWny]96]!׉d8Hͬ4Mʹi!ɧ,gw8sLT$hi8uLv~9 h2kk>(Աl/B!0VmS_ Cr7ffM"[jBH/.?}<:wZ>+؏j;÷Otjɟɽ#jSZ dj DJ fb bI^0xa: η;GxC ѭ1=i8$uVQ 8A>LaUIQ?ݧoZw(ULTxlP|)257;~mfW1Op*"DV6 C?%L Lp}61'}??=;< #Ń? 'GɟɃf" n߼+/!7rus()ZQ}\c۸6t2LI[ČM"&}#Dao?HDMU̴T2a001ߺz7OfvqqJ)!S WW14Y{FY}+-5-*i;:8G?β^^q 7[7o<ݓo8q7x᦯Uƍ~`}O̒+@z[ԏ['Rr֝J*0Bwx{2%ck)=LAƹ?CUQɅV#&R̬jqWf1S,b~a0:Ն$1ƜcQ!#OǩRPAw(@"0!0@s,xԧREh+&B1Ui:\$#jM1nyj&uCiB6Hzso~cJoKou;f믿}gfz||Q;7N0`swhR5R9F`,Y yvZE „lS!/ݭhm&looА GQDPzHosJņ>5BD=vg6o7AcxU"J)@ǫDtC~~CpcoRjo߾};f1WkN8[*ժ뺪ujӘ|W/ͫo|ŗx;LJo>{S~ |YN (  ("[Z)76–ud#q]Jn9n; vnR`,UDڶB35SFxfXu,bN νPvxQ%:s#U@dvUnFBNjȉr‡,8]f(}۶40 )%[9<&+1pCU:/|Mbj}&B=w?4rS>S1}{*ry{? UmPď̷/}O=R*U)} "٤ N9jdT}<3]sUPU]{ƏZgKPvx[bt׎vpZp7э,lD-1Pk @7"2a#o(*U@J 00kkkG{v_ZkRr/;::<;/eYBul_^K7j,uġFd (Pb6~Cll{{{ "8yrX\Sz̩߳m^cKjq p'J7m* fRݤNhf9bS*jHGD Fϋ@Dd0)B<:8մR2:IDlbsפ|1^;orlny_+Ȩ&錍k%`4ff -ac}EIC &c]:Vq2HߗiQ&jR]Ta?_/|O͚6_,ON/kY|9 ũ;]^^V3 e -" *E&,8 "0 B!57_|xӊ&1Lp=t)";a#hScd 8TdTE,dbPxRG zsNmkNsRZCpLN7s-lVUJBH"eA#zJ>!n1!U9b┒/OW+":><}|ÃyDLGyڥص1 ̜WC2|zq^auuvv6^򠪃+1 ФPWKU1W՚ J B 95S)ũS0yVbMRW^{O769sZj8_]1boK&ƮiUv^T{KMF 0 @|O9%@TD$!ppCuZen=Qy (ad!N)Us\C[i Itd8Iv@FnaUbQDfP$"H5²n]}lpxprɴo Tu=U^MMYU3"frWUK_W g_myLۿ:䣛SB>3wb"$_kֺwPL?B,!$T !?qKǝajaҐ]訒&-B =OTj5ԭ%#@_YrP@j cKxttiE%D (!"'\+:|O)}uZj ˋD%&Je.܏)-Oχg'{o/O?o֯'g~~iZؿyΝ;/Ow>O|'b1ˏߺͱ3kSO=ko"@FcUHvmqK]v((.9)AmrٝS9 `Ƶ]:隈0dJ4Zܺu'7$Z+B2}،2r|{UFa2ruREѐP)Y,X,PY{o& ɷ_yggҷ?;'{{eƎ??oO=~{^y  B߆Pծcݲ +8{sq1GQSbZݪk SUI,8 @Ջ-4;jRR 1JFsA#D&j1h zcbgrOvܶ1ðYn\F lhT-"u4zڦ: ?{}~ɧ>]^Я WWLJG7o|s}`vpt|_៝sKw=ܦf3lSw^ߟ/{o>scoU Q6ZO0cag |1uWp4? [:hzx}0 dbvѭ;77n(/^ǻ?S0Cy(yl_M]KbAܞ6K w:?xC?_^{moo/o}o}'&g}wn_}C麦=!H &hyI#fbUmGk6U)RH5T32ڑт D`k)G (`Ð#U=8\ڵ9ѹ#yvHc==bA16M3iDLQO)Ūì̺nL%R0fXGGǿo}_{Oo|?r`޽7޿W^y?q?3b n?>>͝'(eɻwOj»6|[% )UlD5w8I^6HN5(rL%A57׊o5}GjE$@ XjϽes}ɼ !XխUBu{%hM~h#68ɮR:J וTϪ؀Jxpw~s_׿ɟW'~uZ—Wj7^gSr\׾o=x;G~G/.?cf *ϡCɉ&b;w11!,s5p!oxS $BpZ()z(W:։c!#dcy, XjD#53cf{볛xϹG"̊PUBD6 "oϑWD\UQQw_*Z@?g~+_Zu!>__~>'>i>яuǟղWA^wۿKW?_ٟ믽[N/w?tĿo7ͷON 3bRS-jM3 ŪiG>!Ƅg=cBŤ֒fp*9r13)=scZ=G<1[t Bߥo^קR%y5ϤLAPG1e7UfS..~xO||n_|ot^yo~{K^yPC_R D #q,CûMEDSq?@"F6:*qh {/piSj+3!<~l'xIS)@(l!: T& )rW@,X5##5U1QrV-4@wB-wϧ~b=zfr;6"LcBk*V 8цylFoW2=0g*YDDȿRe^&"*jʁQqj52D6CofBL0` LMm$b+OT`А6aTĶm#P.W,hy0DfV}]ce*5 l J2]V╦e5&&UbUR1yY 蹥  @FƆ*^ 6IT֝:>,"Zk l(䤐Zt**5s ޮc'H6:sLRBY9rH %HTmV7cf&56m̭W736CoY !6E£#SVx;/倈_7Am̌43`D2jf6`ψ\TFjD!&2)"deL 9hQhh4ETSWkEh7ƭH7a lEܺߐDfT1C{틷NL1ƔBjea'QbcdWb^92WUj13W}ozvmHAm66l6;a A Ęs0Zߚh \U5$VjE -C6MӘh_K5!:!$8U͵wW] űKvQ1NPƣp^[2PPLSS7w+l'Cm? ]Hidv۩C!h ((\JP- ox! BнDiGs ވ(mDVkc 0Ml?<8xn VA\UP!b&Bfm`EhARhd"ƨ D$PUAAY s E$[ZGa "M][fPxO|1ETddolTVMY1O"s/ߌ$9 d-AwH@DF5rYJ~L<Ŵm&uhT@f) _+o=fOտ莎x?> U7ϿW_ÓdƠ7 f{7\Q=Cc\S ELQQLL67׍'lv뢿-Rsι L!1 C̈6? i1"Wժǟ|LVE3)a˖ w4$IUp]:m#`~_8:QoԜ#3ɧ7j-SS6e)C{oE4Ǐnj}5lf4:A kB|-7Ves ̀W~W}Tk W0<2vjdJߝkFv1D̘RhfM;oSB Ȁ *RALY|=ǟ_ryj̆>ͰYm6~ܬrYED0 BH촉iJHYjQEYGi5Q740G]C_D,u1r(Cl6띷O./{ů~arxi7q/0m_wol31b/B״)&FVUPC0}<|g0Eaocn]d"YdAk"ך Z-0,0lnx-l1,eǷY!XjεRLͅk1>OZ}VT_"PɞT@x)e*@@\daHRjε֪ynz$%f1 P&YW^>'U;kueſYrk<6?#?O/RZV*["6۷o8S ݪ@ZxEn1!`܇XaȵfjR5g{[gO Vmf] ȓTb))v}ꉾ VͰɥUqQڌaRCDL{CnEIH; O(3|RFĵsӛ7oahѣZ`o(׼?爁=#X7)+лBZ@jjQygLk,)XB@ܳO-#P ״*;LLɆ㡾Z(.L5YNi@@@\كzݿOOHJP쑝LCf wj ̻V cls<L.g{ AhW}jι70uEHryy9kc)ԢDaz-T!!Šf9&G{{dbHMjwk֯L&@Dmj}c!2Pˏ͌=cwNiUV=Sc732Jhfnm=:xݛG~gf٘'p||oa9juuqٯ7 伐k7٬],fe͓\wSoVܴ?)&ND9~J#H B1B2@ш1S4Eೞan@l~f(oТs/c`W3J$!'B4-"撥VxY- UҊfCfٛl vuG3y] ?v]q#΄f6;w\]\VZkfH$K-=p|tY?7~WyMqޘ( a)kOʑo>fƾ&o4v,05#QU:aE@aG%hi7:zqRtJrFKr)m$aZrjyQTɅ"|# y]ZJkK'o3 k[xcw|a0WD{b`4UЬ E ɜ.akgxU & %2k)ikO١}x"PԢ w}뭷}ﻳGhMJ{/#p(Ԫezf"@R7oL0Hmm)n`W:e熃ScxSlf<SJggy5䡂a0HL哓+'zz.2"TDiL*Vku/s=qdfO?.o~eߖ]& fjg6Tܷx|P!F~`03vC# [ռ 1RC VkA\1Z[R!$W1Qd`)%4@TU^}'~7b,C^βh;;ɫ3hEV[^l֭KͫU0/ð4r̊[ 2f]Gj`dO1F;v#\ eJްmmf)qfժi:j-D`$F_|//_{sb@ HàV BjS(RXS&@ODܪ/CO 9"3VZ~SdERj,(L&6*M;gkn.|gݸ3ٗS /܊f,qg3)2ogFxB?FU8 3" (V#]cmQ%:RƁ^)rZEM!Qfz٫7ԭs~-t x-@WWWa(*6b>oAfħh!o5x?9ܩ”:Ԏ$xz)%8LL1`@BZsQ-ժ15*iTk_@@{?~ӟl}k!B5K4cDH{F$$hjY5qEK$jUd4QhZm~ TLFK ;G !8ԇ]޾j^0ڬ7Ԝb|CdNtip0ͺ:"` btYa5bh/C%9`K1-]VEv2q?R$v,r:@ [g"C jtwZ7yVU$5+_K>XeU*j0 .aBDt P)T"Y?DHL`Y%FB& хF1W׹ɫo:":1[6);nnYzn1 %\ "?EJEsG~=JZg:qZ,Rՙe>V&0O|W|:X !`RN e]81yeu*斎CּVE#k̑X!pHR0 !x}:RZ KAGnv>&ktӡV?_ަNVmu"3WSTPC+<<IhQTwt^OB akMB>)fv\1ǔ\'zj?eW@K@DbJ:qaqα۬E !DǾ϶]^C"[r!f硿xm;hߋz[D(RJi ّG_ mi5ިGser^'n`.?v~99pdw"ƀ\M!013ӄZG+uAHT݀i0t]Z.K?hќzz:n.\7̜l} @jl"f @ܙOȃsSweyx`6k\P:<9좚♘VNc6vvӴMi'VƁI@ &oѭi]6Ffڍ0B"-;12xB !P NFp]|tJ.h`ul۶%fTVm04[5ǭc J؉[CfRhusY VM!p"4)62kՐ,V@ׇ6wݍ{:QExcQvE;i#1Ey t[80cvsՆZq䐡*@QIfcBbA=Em>Ū!R8Pur9~HJUlKNؖt!f\aVsi5M> hD c 0 vEOݚsMb1 P4Z0>,~rI۵zlaQ&"x25'nh:%wtjjܰ]ќ:Bpͣ2pHiӘ\4XqZ19;P:n"X*ERJYjJ.,?L(%5=Lt-\&&oØkU&"7y}PHB0t%`RUצڙka3y>2N{Sm:ǻ>0xbMă*7 6R XQR @g~#GNa10@l<!9;(c !N˛&m80bZz&SgI5Li)KUB-CwP]U ~ 6ب/c 86b%I  јɭK`(UޭaV%9~9ZLEl6UeU)Z{=!/}kl+W^j Z8?N.إ`gh Ǩ0[c7ӷ"(!"8i˅Ɲޛ&]>S dY|{L@e[ DAc74}E~ w03r ntm*}!5LoۦRW4.,)c 'v"ҟQP&^ZJ?v8okXei -k1!:yK.Y[OL6y4$\eJWĚ */4KcJ)%xq?W\"ds'f$Bžw]&`#X1[ tEXtcommentCreated with The GIMP99%%tEXtdate:create2016-05-24T22:33:57-04:00%tEXtdate:modify2016-05-24T22:23:30-04:00tEXtjpeg:colorspace2,uU tEXtjpeg:sampling-factor2x2,1x1,1x1IIENDB`PG-4.5/proof-general.el000066400000000000000000000071541426357011200147620ustar00rootroot00000000000000;;; proof-general.el --- A generic Emacs interface for proof assistants -*- lexical-binding: t; -*- ;; This file is part of Proof General. ;; Portions © Copyright 1994-2012 David Aspinall and University of Edinburgh ;; Portions © Copyright 2003-2021 Free Software Foundation, Inc. ;; Portions © Copyright 2001-2017 Pierre Courtieu ;; Portions © Copyright 2010, 2016 Erik Martin-Dorel ;; Portions © Copyright 2011-2013, 2016-2017 Hendrik Tews ;; Portions © Copyright 2015-2017 Clément Pit-Claudel ;; Authors: (see the AUTHORS file distributed along the sources) ;; URL: https://proofgeneral.github.io/ ;; Package-Requires: ((emacs "25.2")) ;; Version: 4.5 ;; The software is free software: you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation, either version 3 of the License, or ;; (at your option) any later version. ;; This program is distributed in the hope that it will be useful, ;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License ;; along with this program. If not, see . ;;; Commentary: ;; Proof General is a generic Emacs interface for proof assistants ;; (also known as interactive theorem provers). ;; ;; It is supplied ready to use for the proof assistants Coq, ;; EasyCrypt, qrhl, and PhoX. ;; ;; See https://proofgeneral.github.io/ for installation instructions ;; and online documentation. Or browse the accompanying info manual: ;; (info-display-manual "ProofGeneral") ;; ;; Regarding the Coq proof assistant, you may be interested in the ;; company-coq extension of ProofGeneral (also available in MELPA). ;;; Code: ;; Proof General's initialization code (in generic/proof-site) is relatively ;; complex, in part because it was written before package.el existed, and in ;; part because package.el still doesn't look for autoloads in subdirectories. ;; This file is a thin, package.el-friendly wrapper around generic/proof-site, ;; suitable for execution on Emacs start-up. It serves two purposes: ;; ;; * Setting up the load path when byte-compiling PG. ;; * Loading a minimal PG setup on startup (not all of Proof General, of course; ;; mostly mode hooks and autoloads). ;;;###autoload (eval-and-compile (defvar pg-init--script-full-path (or (bound-and-true-p byte-compile-current-file) (and load-in-progress load-file-name) (buffer-file-name))) (defvar pg-init--pg-root (file-name-directory pg-init--script-full-path))) ;;;###autoload (unless (bound-and-true-p byte-compile-current-file) ;; This require breaks compilation, so it must only run when loading the package. (require 'proof-site (expand-file-name "generic/proof-site" pg-init--pg-root))) (eval-when-compile ;; FIXME: [ This is used during installation of the ELPA package ] ;; We presume that this file will be compiled before any of the files in ;; sub-directories and we presume that all files are compiled within the same ;; session, so we here add to load-path all the subdirectories so ;; that files in (say) coq/ can (require 'coq-foo) and the compiler will find ;; the corresponding file. (let ((byte-compile-directories '("generic" "lib" "coq" "easycrypt" "pghaskell" "pgocaml" "pgshell" "phox" "qrhl" ))) (dolist (dir byte-compile-directories) (add-to-list 'load-path (expand-file-name dir pg-init--pg-root))))) (provide 'proof-general) ;;; proof-general.el ends here PG-4.5/qrhl/000077500000000000000000000000001426357011200126375ustar00rootroot00000000000000PG-4.5/qrhl/qrhl-input.el000066400000000000000000000464561426357011200153030ustar00rootroot00000000000000;;; qrhl-input.el --- Quail package for TeX-style input for qrhl-tool in ProofGeneral -*- lexical-binding: t -*- ;; Copyright (C) 2001-2022 Free Software Foundation, Inc. ;; Copyright (C) 2001-2011 ;; National Institute of Advanced Industrial Science and Technology (AIST) ;; Registration Number H14PRO021 ;; Copyright (C) 2017-2022 University of Tartu ;; Author: TAKAHASHI Naoto ;; Dave Love ;; Dominique Unruh ;; SPDX-License-Identifier: GPL-3.0-or-later ;;; Commentary: ;; Modified by Dominique Unruh to adapt to the specific requirements of qrhl-tool (https://dominique-unruh.github.io/qrhl-tool/). ;; Based on latin-ltx.el from Emacs 26.3 (https://git.savannah.gnu.org/cgit/emacs.git/tree/lisp/leim/quail/latin-ltx.el?h=emacs-26.3) ;; Main changes: ;; - Changed input method name to "qrhl" ;; - Changed prefix from latin-ltx to qrhl-input ;; - Changed unicode symbol for \cdot, \llbracket, \rrbracket ;; - Disabled sequences starting with _ ;; - Appended extra input sequences in the end ;; - Changed to lexical binding ;; - Made code compatible with Emacs 25 (@monnier) ;;; Code: (require 'quail) (quail-define-package "qrhl" "UTF-8" "\\q " t "LaTeX-like input method for use in the qrhl-tool." '(("\t" . quail-completion)) t t nil nil nil nil nil nil nil t) (eval-when-compile (require 'cl-lib) (defconst qrhl-input--mark-map '(("DOT BELOW" . "d") ("DOT ABOVE" . ".") ("OGONEK" . "k") ("CEDILLA" . "c") ("CARON" . "v") ;; ("HOOK ABOVE" . ??) ("MACRON" . "=") ("BREVE" . "u") ("TILDE" . "~") ("GRAVE" . "`") ("CIRCUMFLEX" . "^") ("DIAERESIS" . "\"") ("DOUBLE ACUTE" . "H") ("ACUTE" . "'"))) (defconst qrhl-input--mark-re (regexp-opt (mapcar #'car qrhl-input--mark-map))) (defun qrhl-input--ascii-p (char) (and (characterp char) (< char 128))) (defmacro qrhl-input--define-rules (&rest rules) (load "uni-name") (let ((newrules ())) (dolist (rule rules) (pcase rule (`(,_ ,(pred characterp)) (push rule newrules)) ;; Normal quail rule. (`(,seq ,re) (let* ((count 0) (re (eval re t)) (ucs-names (ucs-names)) (process-one-entry (lambda (name char) (when (and (characterp char) ;; Ignore char-ranges. (string-match re name)) (let ((keys (if (stringp seq) (replace-match seq nil nil name) (funcall (eval seq t) name char)))) (if (listp keys) (dolist (x keys) (setq count (1+ count)) (push (list x char) newrules)) (setq count (1+ count)) (push (list keys char) newrules))))))) ;; Emacs-25's `ucs-names' returned an alist rather than a hash ;; table and that changed to a hash-table in Emacs-26. (if (hash-table-p ucs-names) (maphash process-one-entry ucs-names) (dolist (pair ucs-names) (funcall process-one-entry (car pair) (cdr pair)))) ;; (message "qrhl-input: %d mappings for %S" count re) )))) (setq newrules (delete-dups newrules)) (let ((rules (copy-sequence newrules))) (while rules (let ((rule (pop rules))) (when (assoc (car rule) rules) (let ((conflicts (list (cadr rule))) (tail rules) c) (while (setq c (assoc (car rule) tail)) (push (cadr c) conflicts) (setq tail (cdr (memq c tail))) (setq rules (delq c rules))) (message "Conflict for %S: %S" (car rule) (apply #'string conflicts))))))) (let ((inputs (mapcar #'car newrules))) (setq inputs (delete-dups inputs)) (message "qrhl-input: %d rules (+ %d conflicts)!" (length inputs) (- (length newrules) (length inputs)))) `(quail-define-rules ,@(nreverse newrules))))) (qrhl-input--define-rules ("!`" ?¡) ("\\pounds" ?£) ;; ("{\\pounds}" ?£) ("\\S" ?§) ;; ("{\\S}" ?§) ("$^a$" ?ª) ("$\\pm$" ?±) ("\\pm" ?±) ("$^2$" ?²) ("$^3$" ?³) ("\\P" ?¶) ;; ("{\\P}" ?¶) ("$\\cdot$" ?⋅) ("\\cdot" ?⋅) ("$^1$" ?¹) ("$^o$" ?º) ("?`" ?¿) ((lambda (name char) (let* ((c (if (match-end 1) (downcase (match-string 2 name)) (match-string 2 name))) (mark1 (cdr (assoc (match-string 3 name) qrhl-input--mark-map))) (mark2 (if (match-end 4) (cdr (assoc (match-string 4 name) qrhl-input--mark-map)))) (marks (if mark2 (concat mark1 "\\" mark2) mark1))) (cl-assert mark1) (cons (format "\\%s{%s}" marks c) ;; Exclude "d" because we use "\\dh" for something else. (unless (member (or mark2 mark1) '("d"));; "k" (list (format "\\%s%s" marks c)))))) (concat "\\`LATIN \\(?:CAPITAL\\|SMAL\\(L\\)\\) LETTER \\(.\\) WITH \\(" qrhl-input--mark-re "\\)\\(?: AND \\(" qrhl-input--mark-re "\\)\\)?\\'")) ((lambda (name char) (let* ((mark (cdr (assoc (match-string 1 name) qrhl-input--mark-map)))) (cl-assert mark) (list (format "\\%s" mark)))) (concat "\\`COMBINING \\(" qrhl-input--mark-re "\\)\\(?: ACCENT\\)?\\'")) ((lambda (name char) (unless (qrhl-input--ascii-p char) (let* ((mark (cdr (assoc (match-string 1 name) qrhl-input--mark-map)))) (cl-assert mark) (list (format "\\%s{}" mark))))) (concat "\\`\\(?:SPACING \\)?\\(" qrhl-input--mark-re "\\)\\(?: ACCENT\\)?\\'")) ("\\AA" ?Å) ;; ("{\\AA}" ?Å) ("\\AE" ?Æ) ;; ("{\\AE}" ?Æ) ("$\\times$" ?×) ("\\times" ?×) ("\\O" ?Ø) ;; ("{\\O}" ?Ø) ("\\ss" ?ß) ;; ("{\\ss}" ?ß) ("\\aa" ?å) ;; ("{\\aa}" ?å) ("\\ae" ?æ) ;; ("{\\ae}" ?æ) ("$\\div$" ?÷) ("\\div" ?÷) ("\\o" ?ø) ;; ("{\\o}" ?ø) ("\\~{\\i}" ?ĩ) ("\\={\\i}" ?ī) ("\\u{\\i}" ?ĭ) ("\\i" ?ı) ;; ("{\\i}" ?ı) ("\\^{\\j}" ?ĵ) ("\\L" ?Ł) ;; ("{\\L}" ?Ł) ("\\l" ?ł) ;; ("{\\l}" ?ł) ("\\H" ?̋) ("\\H{}" ?˝) ("\\U{o}" ?ő) ("\\Uo" ?ő) ;; FIXME: Was it just a typo? ("\\OE" ?Œ) ;; ("{\\OE}" ?Œ) ("\\oe" ?œ) ;; ("{\\oe}" ?œ) ("\\v{\\i}" ?ǐ) ("\\={\\AE}" ?Ǣ) ("\\=\\AE" ?Ǣ) ("\\={\\ae}" ?ǣ) ("\\=\\ae" ?ǣ) ("\\v{\\j}" ?ǰ) ("\\'{\\AE}" ?Ǽ) ("\\'\\AE" ?Ǽ) ("\\'{\\ae}" ?ǽ) ("\\'\\ae" ?ǽ) ("\\'{\\O}" ?Ǿ) ("\\'\\O" ?Ǿ) ("\\'{\\o}" ?ǿ) ("\\'\\o" ?ǿ) ("\\," ? ) ("\\/" ?‌) ("\\:" ? ) ("\\;" ? ) ;; ;; Dominique Unruh: Disabling _1 etc. ;; ((lambda (name char) ;; (let* ((base (concat (match-string 1 name) (match-string 3 name))) ;; (basechar (cdr (assoc base (ucs-names))))) ;; (when (qrhl-input--ascii-p basechar) ;; (string (if (match-end 2) ?^ ?_) basechar)))) ;; "\\(.*\\)SU\\(?:B\\|\\(PER\\)\\)SCRIPT \\(.*\\)") ((lambda (name _char) (let* ((basename (match-string 2 name)) (name (if (match-end 1) (capitalize basename) (downcase basename)))) (concat "^" (if (> (length name) 1) "\\") name))) "\\`MODIFIER LETTER \\(?:SMALL\\|CAPITA\\(L\\)\\) \\([[:ascii:]]+\\)\\'") ;; ((lambda (name char) (format "^%s" (downcase (match-string 1 name)))) ;; "\\`MODIFIER LETTER SMALL \\(.\\)\\'") ;; ("^\\1" "\\`MODIFIER LETTER CAPITAL \\(.\\)\\'") ("^o_" ?º) ("^{SM}" ?℠) ("^{TEL}" ?℡) ("^{TM}" ?™) ("\\b" ?̱) ("\\rq" ?’) ;; FIXME: Provides some useful entries (yen, euro, copyright, registered, ;; currency, minus, micro), but also a lot of dubious ones. ((lambda (name char) (unless (or (qrhl-input--ascii-p char) ;; We prefer COMBINING LONG SOLIDUS OVERLAY for \not. (member name '("NOT SIGN"))) (concat "\\" (downcase (match-string 1 name))))) "\\`\\([^- ]+\\) SIGN\\'") ((lambda (name char) ;; "GREEK SMALL LETTER PHI" (which is \phi) and "GREEK PHI SYMBOL" ;; (which is \varphi) are reversed in `ucs-names', so we define ;; them manually. (unless (string-match-p "\\" name) (concat "\\" (funcall (if (match-end 1) #' capitalize #'downcase) (match-string 2 name))))) "\\`GREEK \\(?:SMALL\\|CAPITA\\(L\\)\\) LETTER \\([^- ]+\\)\\'") ("\\phi" ?ϕ) ("\\Box" ?□) ("\\Bumpeq" ?≎) ("\\Cap" ?⋒) ("\\Cup" ?⋓) ("\\Diamond" ?◇) ("\\Downarrow" ?⇓) ("\\H{o}" ?ő) ("\\Im" ?ℑ) ("\\Join" ?⋈) ("\\Leftarrow" ?⇐) ("\\Leftrightarrow" ?⇔) ("\\Ll" ?⋘) ("\\Lleftarrow" ?⇚) ("\\Longleftarrow" ?⇐) ("\\Longleftrightarrow" ?⇔) ("\\Longrightarrow" ?⇒) ("\\Lsh" ?↰) ("\\Re" ?ℜ) ("\\Rightarrow" ?⇒) ("\\Rrightarrow" ?⇛) ("\\Rsh" ?↱) ("\\Subset" ?⋐) ("\\Supset" ?⋑) ("\\Uparrow" ?⇑) ("\\Updownarrow" ?⇕) ("\\Vdash" ?⊩) ("\\Vert" ?‖) ("\\Vvdash" ?⊪) ("\\aleph" ?ℵ) ("\\amalg" ?∐) ("\\angle" ?∠) ("\\approx" ?≈) ("\\approxeq" ?≊) ("\\ast" ?∗) ("\\asymp" ?≍) ("\\backcong" ?≌) ("\\backepsilon" ?∍) ("\\backprime" ?‵) ("\\backsim" ?∽) ("\\backsimeq" ?⋍) ("\\backslash" ?\\) ("\\barwedge" ?⊼) ("\\because" ?∵) ("\\beth" ?ℶ) ("\\between" ?≬) ("\\bigcap" ?⋂) ("\\bigcirc" ?◯) ("\\bigcup" ?⋃) ("\\bigstar" ?★) ("\\bigtriangledown" ?▽) ("\\bigtriangleup" ?△) ("\\bigvee" ?⋁) ("\\bigwedge" ?⋀) ("\\blacklozenge" ?✦) ("\\blacksquare" ?▪) ("\\blacktriangle" ?▴) ("\\blacktriangledown" ?▾) ("\\blacktriangleleft" ?◂) ("\\blacktriangleright" ?▸) ("\\bot" ?⊥) ("\\bowtie" ?⋈) ("\\boxminus" ?⊟) ("\\boxplus" ?⊞) ("\\boxtimes" ?⊠) ("\\bullet" ?•) ("\\bumpeq" ?≏) ("\\cap" ?∩) ("\\cdots" ?⋯) ("\\centerdot" ?⋅) ("\\checkmark" ?✓) ("\\chi" ?χ) ("\\circ" ?∘) ("\\circeq" ?≗) ("\\circlearrowleft" ?↺) ("\\circlearrowright" ?↻) ("\\circledR" ?®) ("\\circledS" ?Ⓢ) ("\\circledast" ?⊛) ("\\circledcirc" ?⊚) ("\\circleddash" ?⊝) ("\\clubsuit" ?♣) ("\\coloneq" ?≔) ("\\complement" ?∁) ("\\cong" ?≅) ("\\coprod" ?∐) ("\\cup" ?∪) ("\\curlyeqprec" ?⋞) ("\\curlyeqsucc" ?⋟) ("\\curlypreceq" ?≼) ("\\curlyvee" ?⋎) ("\\curlywedge" ?⋏) ("\\curvearrowleft" ?↶) ("\\curvearrowright" ?↷) ("\\dag" ?†) ("\\dagger" ?†) ("\\daleth" ?ℸ) ("\\dashv" ?⊣) ("\\ddag" ?‡) ("\\ddagger" ?‡) ("\\ddots" ?⋱) ("\\diamond" ?⋄) ("\\diamondsuit" ?♢) ("\\divideontimes" ?⋇) ("\\doteq" ?≐) ("\\doteqdot" ?≑) ("\\dotplus" ?∔) ("\\dotsquare" ?⊡) ("\\downarrow" ?↓) ("\\downdownarrows" ?⇊) ("\\downleftharpoon" ?⇃) ("\\downrightharpoon" ?⇂) ("\\ell" ?ℓ) ("\\emptyset" ?∅) ("\\eqcirc" ?≖) ("\\eqcolon" ?≕) ("\\eqslantgtr" ?⋝) ("\\eqslantless" ?⋜) ("\\equiv" ?≡) ("\\exists" ?∃) ("\\fallingdotseq" ?≒) ("\\flat" ?♭) ("\\forall" ?∀) ("\\frac1" ?⅟) ("\\frac12" ?½) ("\\frac13" ?⅓) ("\\frac14" ?¼) ("\\frac15" ?⅕) ("\\frac16" ?⅙) ("\\frac18" ?⅛) ("\\frac23" ?⅔) ("\\frac25" ?⅖) ("\\frac34" ?¾) ("\\frac35" ?⅗) ("\\frac38" ?⅜) ("\\frac45" ?⅘) ("\\frac56" ?⅚) ("\\frac58" ?⅝) ("\\frac78" ?⅞) ("\\frown" ?⌢) ("\\ge" ?≥) ("\\geq" ?≥) ("\\geqq" ?≧) ("\\geqslant" ?≥) ("\\gets" ?←) ("\\gg" ?≫) ("\\ggg" ?⋙) ("\\gimel" ?ℷ) ("\\gnapprox" ?⋧) ("\\gneq" ?≩) ("\\gneqq" ?≩) ("\\gnsim" ?⋧) ("\\gtrapprox" ?≳) ("\\gtrdot" ?⋗) ("\\gtreqless" ?⋛) ("\\gtreqqless" ?⋛) ("\\gtrless" ?≷) ("\\gtrsim" ?≳) ("\\gvertneqq" ?≩) ("\\hbar" ?ℏ) ("\\heartsuit" ?♥) ("\\hookleftarrow" ?↩) ("\\hookrightarrow" ?↪) ("\\iff" ?⇔) ("\\imath" ?ı) ("\\in" ?∈) ("\\infty" ?∞) ("\\int" ?∫) ("\\intercal" ?⊺) ("\\langle" ?⟨) ;; Was ?〈, see bug#12948. ("\\lbrace" ?{) ("\\lbrack" ?\[) ("\\lceil" ?⌈) ("\\ldots" ?…) ("\\le" ?≤) ("\\leadsto" ?↝) ("\\leftarrow" ?←) ("\\leftarrowtail" ?↢) ("\\leftharpoondown" ?↽) ("\\leftharpoonup" ?↼) ("\\leftleftarrows" ?⇇) ;; ("\\leftparengtr" ?〈), see bug#12948. ("\\leftrightarrow" ?↔) ("\\leftrightarrows" ?⇆) ("\\leftrightharpoons" ?⇋) ("\\leftrightsquigarrow" ?↭) ("\\leftthreetimes" ?⋋) ("\\leq" ?≤) ("\\leqq" ?≦) ("\\leqslant" ?≤) ("\\lessapprox" ?≲) ("\\lessdot" ?⋖) ("\\lesseqgtr" ?⋚) ("\\lesseqqgtr" ?⋚) ("\\lessgtr" ?≶) ("\\lesssim" ?≲) ("\\lfloor" ?⌊) ("\\lhd" ?◁) ("\\rhd" ?▷) ("\\ll" ?≪) ("\\llcorner" ?⌞) ("\\lnapprox" ?⋦) ("\\lneq" ?≨) ("\\lneqq" ?≨) ("\\lnsim" ?⋦) ("\\longleftarrow" ?←) ("\\longleftrightarrow" ?↔) ("\\longmapsto" ?↦) ("\\longrightarrow" ?→) ("\\looparrowleft" ?↫) ("\\looparrowright" ?↬) ("\\lozenge" ?✧) ("\\lq" ?‘) ("\\lrcorner" ?⌟) ("\\ltimes" ?⋉) ("\\lvertneqq" ?≨) ("\\maltese" ?✠) ("\\mapsto" ?↦) ("\\measuredangle" ?∡) ("\\mho" ?℧) ("\\mid" ?∣) ("\\models" ?⊧) ("\\mp" ?∓) ("\\multimap" ?⊸) ("\\nLeftarrow" ?⇍) ("\\nLeftrightarrow" ?⇎) ("\\nRightarrow" ?⇏) ("\\nVDash" ?⊯) ("\\nVdash" ?⊮) ("\\nabla" ?∇) ("\\napprox" ?≉) ("\\natural" ?♮) ("\\ncong" ?≇) ("\\ne" ?≠) ("\\nearrow" ?↗) ("\\neg" ?¬) ("\\neq" ?≠) ("\\nequiv" ?≢) ("\\newline" ?
) ("\\nexists" ?∄) ("\\ngeq" ?≱) ("\\ngeqq" ?≱) ("\\ngeqslant" ?≱) ("\\ngtr" ?≯) ("\\ni" ?∋) ("\\nleftarrow" ?↚) ("\\nleftrightarrow" ?↮) ("\\nleq" ?≰) ("\\nleqq" ?≰) ("\\nleqslant" ?≰) ("\\nless" ?≮) ("\\nmid" ?∤) ("\\not" ?̸) ;FIXME: conflict with "NOT SIGN" ¬. ("\\notin" ?∉) ("\\nparallel" ?∦) ("\\nprec" ?⊀) ("\\npreceq" ?⋠) ("\\nrightarrow" ?↛) ("\\nshortmid" ?∤) ("\\nshortparallel" ?∦) ("\\nsim" ?≁) ("\\nsimeq" ?≄) ("\\nsubset" ?⊄) ("\\nsubseteq" ?⊈) ("\\nsubseteqq" ?⊈) ("\\nsucc" ?⊁) ("\\nsucceq" ?⋡) ("\\nsupset" ?⊅) ("\\nsupseteq" ?⊉) ("\\nsupseteqq" ?⊉) ("\\ntriangleleft" ?⋪) ("\\ntrianglelefteq" ?⋬) ("\\ntriangleright" ?⋫) ("\\ntrianglerighteq" ?⋭) ("\\nvDash" ?⊭) ("\\nvdash" ?⊬) ("\\nwarrow" ?↖) ("\\odot" ?⊙) ("\\oint" ?∮) ("\\ominus" ?⊖) ("\\oplus" ?⊕) ("\\oslash" ?⊘) ("\\otimes" ?⊗) ("\\par" ?
) ("\\parallel" ?∥) ("\\partial" ?∂) ("\\perp" ?⊥) ("\\pitchfork" ?⋔) ("\\prec" ?≺) ("\\precapprox" ?≾) ("\\preceq" ?≼) ("\\precnapprox" ?⋨) ("\\precnsim" ?⋨) ("\\precsim" ?≾) ("\\prime" ?′) ("\\prod" ?∏) ("\\propto" ?∝) ("\\qed" ?∎) ("\\quad" ? ) ("\\rangle" ?\⟩) ;; Was ?〉, see bug#12948. ("\\rbrace" ?}) ("\\rbrack" ?\]) ("\\rceil" ?⌉) ("\\rfloor" ?⌋) ("\\rightarrow" ?→) ("\\rightarrowtail" ?↣) ("\\rightharpoondown" ?⇁) ("\\rightharpoonup" ?⇀) ("\\rightleftarrows" ?⇄) ("\\rightleftharpoons" ?⇌) ;; ("\\rightparengtr" ?⦔) ;; Was ?〉, see bug#12948. ("\\rightrightarrows" ?⇉) ("\\rightthreetimes" ?⋌) ("\\risingdotseq" ?≓) ("\\rtimes" ?⋊) ("\\sbs" ?﹨) ("\\searrow" ?↘) ("\\setminus" ?∖) ("\\sharp" ?♯) ("\\shortmid" ?∣) ("\\shortparallel" ?∥) ("\\sim" ?∼) ("\\simeq" ?≃) ("\\smallamalg" ?∐) ("\\smallsetminus" ?∖) ("\\smallsmile" ?⌣) ("\\smile" ?⌣) ("\\spadesuit" ?♠) ("\\sphericalangle" ?∢) ("\\sqcap" ?⊓) ("\\sqcup" ?⊔) ("\\sqsubset" ?⊏) ("\\sqsubseteq" ?⊑) ("\\sqsupset" ?⊐) ("\\sqsupseteq" ?⊒) ("\\square" ?□) ("\\squigarrowright" ?⇝) ("\\star" ?⋆) ("\\straightphi" ?φ) ("\\subset" ?⊂) ("\\subseteq" ?⊆) ("\\subseteqq" ?⊆) ("\\subsetneq" ?⊊) ("\\subsetneqq" ?⊊) ("\\succ" ?≻) ("\\succapprox" ?≿) ("\\succcurlyeq" ?≽) ("\\succeq" ?≽) ("\\succnapprox" ?⋩) ("\\succnsim" ?⋩) ("\\succsim" ?≿) ("\\sum" ?∑) ("\\supset" ?⊃) ("\\supseteq" ?⊇) ("\\supseteqq" ?⊇) ("\\supsetneq" ?⊋) ("\\supsetneqq" ?⊋) ("\\surd" ?√) ("\\swarrow" ?↙) ("\\therefore" ?∴) ("\\thickapprox" ?≈) ("\\thicksim" ?∼) ("\\to" ?→) ("\\top" ?⊤) ("\\triangle" ?▵) ("\\triangledown" ?▿) ("\\triangleleft" ?◃) ("\\trianglelefteq" ?⊴) ("\\triangleq" ?≜) ("\\triangleright" ?▹) ("\\trianglerighteq" ?⊵) ("\\twoheadleftarrow" ?↞) ("\\twoheadrightarrow" ?↠) ("\\ulcorner" ?⌜) ("\\uparrow" ?↑) ("\\updownarrow" ?↕) ("\\upleftharpoon" ?↿) ("\\uplus" ?⊎) ("\\uprightharpoon" ?↾) ("\\upuparrows" ?⇈) ("\\urcorner" ?⌝) ("\\u{i}" ?ĭ) ("\\vDash" ?⊨) ((lambda (name char) ;; "GREEK SMALL LETTER PHI" (which is \phi) and "GREEK PHI SYMBOL" ;; (which is \varphi) are reversed in `ucs-names', so we define ;; them manually. (unless (string-match-p "\\" name) (concat "\\var" (downcase (match-string 1 name))))) "\\`GREEK \\([^- ]+\\) SYMBOL\\'") ("\\varphi" ?φ) ("\\varprime" ?′) ("\\varpropto" ?∝) ("\\varsigma" ?ς) ("\\vartriangleleft" ?⊲) ("\\vartriangleright" ?⊳) ("\\vdash" ?⊢) ("\\vdots" ?⋮) ("\\vee" ?∨) ("\\veebar" ?⊻) ("\\vert" ?|) ("\\wedge" ?∧) ("\\wp" ?℘) ("\\wr" ?≀) ("\\Bbb{N}" ?ℕ) ; AMS commands for blackboard bold ("\\Bbb{P}" ?ℙ) ; Also sometimes \mathbb. ("\\Bbb{R}" ?ℝ) ("\\Bbb{Z}" ?ℤ) ("--" ?–) ("---" ?—) ;; We used to use ~ for NBSP but that's inconvenient and may even look like ;; a bug where the user finds his ~ key doesn't insert a ~ any more. ("\\ " ? ) ("\\\\" ?\\) ("\\mathscr{I}" ?ℐ) ; moment of inertia ("\\Smiley" ?☺) ("\\blacksmiley" ?☻) ("\\Frowny" ?☹) ("\\Letter" ?✉) ("\\permil" ?‰) ;; Probably not useful enough: ;; ("\\Telefon" ?☎) ; there are other possibilities ;; ("\\Radioactivity" ?☢) ;; ("\\Biohazard" ?☣) ;; ("\\Male" ?♂) ;; ("\\Female" ?♀) ;; ("\\Lightning" ?☇) ;; ("\\Mercury" ?☿) ;; ("\\Earth" ?♁) ;; ("\\Jupiter" ?♃) ;; ("\\Saturn" ?♄) ;; ("\\Uranus" ?♅) ;; ("\\Neptune" ?♆) ;; ("\\Pluto" ?♇) ;; ("\\Sun" ?☉) ;; ("\\Writinghand" ?✍) ;; ("\\Yinyang" ?☯) ;; ("\\Heart" ?♡) ("\\dh" ?ð) ("\\DH" ?Ð) ("\\th" ?þ) ("\\TH" ?Þ) ("\\lnot" ?¬) ("\\ordfeminine" ?ª) ("\\ordmasculine" ?º) ("\\lambdabar" ?ƛ) ("\\celsius" ?℃) ;; by analogy with lq, rq: ("\\ldq" ?\“) ("\\rdq" ?\”) ("\\defs" ?≙) ; per fuzz/zed ;; ("\\sqrt[3]" ?∛) ("\\llbracket" ?\⟦) ; stmaryrd ("\\rrbracket" ?\⟧) ;; ("\\lbag" ?\〚) ; fuzz ;; ("\\rbag" ?\〛) ("\\ldata" ?\《) ; fuzz/zed ("\\rdata" ?\》) ;; From Karl Eichwalder. ("\\glq" ?‚) ("\\grq" ?‘) ("\\glqq" ?„) ("\\\"`" ?„) ("\\grqq" ?“) ("\\\"'" ?“) ("\\flq" ?‹) ("\\frq" ?›) ("\\flqq" ?\«) ("\\\"<" ?\«) ("\\frqq" ?\») ("\\\">" ?\») ("\\-" ?­) ;; soft hyphen ("\\textmu" ?µ) ("\\textfractionsolidus" ?⁄) ("\\textbigcircle" ?⃝) ("\\textmusicalnote" ?♪) ("\\textdied" ?✝) ("\\textcolonmonetary" ?₡) ("\\textwon" ?₩) ("\\textnaira" ?₦) ("\\textpeso" ?₱) ("\\textlira" ?₤) ("\\textrecipe" ?℞) ("\\textinterrobang" ?‽) ("\\textpertenthousand" ?‱) ("\\textbaht" ?฿) ("\\textnumero" ?№) ("\\textdiscount" ?⁒) ("\\textestimated" ?℮) ("\\textopenbullet" ?◦) ("\\textlquill" ?\⁅) ("\\textrquill" ?\⁆) ("\\textcircledP" ?℗) ("\\textreferencemark" ?※) ) ;; Dominique's rules for qrhl-tool: (quail-define-rules ((append . t)) ("\\ox" ?⊗) ("\\ket" ["|⟩"]) ("\\ket0" ["|0⟩"]) ("\\ket1" ["|1⟩"]) ("[|" ["⟦"]) ("|]" ["⟧"]) (">>" ?») ("\\Cla" ["ℭ𝔩𝔞"]) ("\\qeq" ["≡𝔮"]) ) (provide 'qrhl-input) ;;; qrhl-input.el ends here PG-4.5/qrhl/qrhl.el000066400000000000000000000125541426357011200141360ustar00rootroot00000000000000;;; qrhl.el --- Mode for qrhl-tool theorem prover -*- lexical-binding: t -*- ;; This file is part of Proof General. ;; Copyright © 2017–2022 University of Tartu ;; Author: Dominique Unruh ;; SPDX-License-Identifier: GPL-3.0-or-later ;;; Commentary: ;; See also https://dominique-unruh.github.io/qrhl-tool/ ;;; Code: (require 'proof) (require 'proof-easy-config) (require 'proof-script) ;For proof-generic-count-undos. (require 'qrhl-input) (defcustom qrhl-input-method "qrhl" "Input method to use when editing qRHL proof scripts" :type '(string) :group 'qrhl) (defcustom qrhl-prog-name "qrhl" "Name/path of the qrhl-prover command. (Restart Emacs after changing this.)" :type '(string) :group 'qrhl) (defun qrhl-find-and-forget (span) (proof-generic-count-undos span)) (defvar qrhl-focus-cmd-regexp (let* ((number "[0-9]+") (white "[[:blank:]]*") (number-or-range (concat number "\\(" white "-" white number "\\)?")) (range-list (concat number-or-range "\\(" white "," white number-or-range "\\)*")) (focus-label "\\({\\|}\\|[+*-]+\\)") (focus-cmd (concat "\\(" range-list white ":" white "\\)?" focus-label)) ) focus-cmd)) (defun qrhl-forward-regex (regex) "If text starting at point matches REGEX, move to end of the match and return t. Otherwise return nil" (and (looking-at regex) (goto-char (match-end 0)) t)) (defun qrhl-parse-regular-command () "Find the period-terminated command starting at point. Moves to its end. Returns t if this worked." (let ((pos (save-excursion (progn (while (or ; skip forward over regular chars, period with non-white, quoted string (qrhl-forward-regex "\\([^.{(\"]+\\|\\.[^ \t\n]\\|\"\\([^\"]+\\)\"\\)") (and (looking-at "[{(]") (forward-list)) )) (and (qrhl-forward-regex "\\.") (point)) )))) (princ pos) (and pos (goto-char pos) t))) (defun qrhl-parse-focus-command () (and (looking-at qrhl-focus-cmd-regexp) (goto-char (match-end 0)))) (defun qrhl-proof-script-parse-function () "Finds the command/comment starting at the point" (or (and (qrhl-forward-regex "#[^\n]*\n") 'comment) (and (qrhl-parse-focus-command) 'cmd) (and (qrhl-parse-regular-command) 'cmd))) (defvar qrhl-font-lock-subsuperscript '(("\\(⇩\\)\\([^[:space:]]\\)" . ((2 '(face subscript display (raise -0.3))) (1 '(face nil display "")))) ("\\(⇧\\)\\([^[:space:]]\\)" . ((2 '(face superscript display (raise 0.3))) (1 '(face nil display ""))))) "Font-lock configuration for displaying sub/superscripts that are prefixed by ⇩/⇧") (defvar qrhl-font-lock-keywords ; Very simple configuration of keywords: highlights all occurrences, even if they are not actually keywords (e.g., when they are part of a term) (append qrhl-font-lock-subsuperscript '("lemma" "qrhl" "include" "quantum" "program" "equal" "simp" "isabelle" "isa" "var" "qed" "skip")) "Font-lock configuration for qRHL proof scripts") (proof-easy-config 'qrhl "qRHL" proof-prog-name qrhl-prog-name ;; We need to give some option here, otherwise `proof-prog-name' is ;; interpreted as a shell command which leads to problems if the file name ;; contains spaces (see the documentation for `proof-prog-name'). qrhl-prog-args '("--emacs") ;;proof-script-command-end-regexp "\\.[ \t]*$" proof-script-parse-function #'qrhl-proof-script-parse-function proof-shell-annotated-prompt-regexp "^\\(\\.\\.\\.\\|qrhl\\)> " ;;proof-script-comment-start-regexp "#" ;;proof-script-comment-end "\n" proof-shell-error-regexp "^\\(\\[ERROR\\]\\|Exception\\)" proof-undo-n-times-cmd "undo %s." proof-find-and-forget-fn 'qrhl-find-and-forget proof-shell-start-goals-regexp "^[0-9]+ subgoals:\\|^Goal:\\|^No current goal\\.\\|^In cheat mode\\.\\|^No focused goals (use " proof-shell-proof-completed-regexp "^No current goal.$" proof-shell-eager-annotation-start "\\*\\*\\* " proof-shell-eager-annotation-start-length 4 proof-no-fully-processed-buffer t proof-shell-filename-escapes '(("\\\\" . "\\\\") ("\"" . "\\\"")) proof-shell-cd-cmd "changeDirectory \"%s\"." ;; ProofGeneral produces warning when this is not set. But we don't want ;; goal/save commands to be recognized because that makes ProofGeneral do an ;; atomic undo. proof-save-command-regexp "\\`a\\`" ;AKA `regexp-unmatchable' in Emacs-27 proof-tree-external-display nil proof-script-font-lock-keywords qrhl-font-lock-keywords proof-goals-font-lock-keywords qrhl-font-lock-keywords proof-response-font-lock-keywords qrhl-font-lock-keywords proof-shell-unicode t ) ; buttoning functions follow https://superuser.com/a/331896/748969 (define-button-type 'qrhl-find-file-button 'follow-link t 'action #'qrhl-find-file-button) (defun qrhl-find-file-button (button) (find-file (buffer-substring (button-start button) (button-end button)))) (defun qrhl-buttonize-buffer () "Turn all include commands in a qRHL proof script into clickable buttons" (interactive) (remove-overlays) (save-excursion (goto-char (point-min)) (while (re-search-forward "include\s*\"\\([^\"]+\\)\"\s*\\." nil t) (make-button (match-beginning 1) (match-end 1) :type 'qrhl-find-file-button)))) (add-hook 'qrhl-mode-hook (lambda () (set-input-method qrhl-input-method) (set-variable 'electric-indent-mode nil t) (qrhl-buttonize-buffer))) (provide 'qrhl)