Compare commits

...

113 Commits

Author SHA1 Message Date
CismonX a5837defce
fix link
continuous-integration/drone/push Build is passing Details
continuous-integration/drone Build is passing Details
2022-02-10 02:49:27 +08:00
CismonX 5e86022e32
fix link; update gitignore
continuous-integration/drone/push Build is passing Details
2022-02-10 02:46:03 +08:00
CismonX 229d84bd2d
bugfix: snippet completion for block commands
continuous-integration/drone/push Build is passing Details
2022-02-02 14:53:46 +08:00
CismonX c3e33c3340
Update dependencies 2022-02-02 14:32:45 +08:00
CismonX 2275b94c1d
Prepare for v0.2.3
continuous-integration/drone/push Build is passing Details
continuous-integration/drone/tag Build is passing Details
2021-10-23 21:52:58 +08:00
CismonX 7820db6955
Fix locale.
continuous-integration/drone/push Build is passing Details
2021-10-23 02:58:40 +08:00
CismonX 26c8d32129
Refactor code.
continuous-integration/drone/push Build is passing Details
2021-10-23 02:36:51 +08:00
CismonX c111ec89a0
Normalize paths. 2021-10-23 02:35:49 +08:00
CismonX 3896bf44db
Update dependencies. 2021-10-23 02:31:15 +08:00
CismonX d165537d60
Prepare for v0.2.2
continuous-integration/drone/push Build is passing Details
continuous-integration/drone/tag Build is passing Details
2021-10-02 23:35:17 +08:00
CismonX 1707ece4bc
GNU Texinfo latest version: 6.7 -> 6.8 2021-10-02 23:15:57 +08:00
CismonX f5c8ae309c
Bugfix for Windows builds. 2021-10-02 22:56:50 +08:00
CismonX 2fd2a025c3
Update build scripts.
continuous-integration/drone/push Build is passing Details
2021-10-02 01:30:37 +08:00
CismonX 84a5c506fe
Update dependencies. 2021-10-02 00:47:49 +08:00
CismonX 2004131b6c
Update dependencies.
continuous-integration/drone/push Build is passing Details
2021-09-10 11:41:02 +08:00
CismonX 3ecb2a5b03
Refactor code.
continuous-integration/drone/push Build is passing Details
2021-08-12 01:23:04 +08:00
CismonX b3b9644af0
Update dependencies 2021-08-12 01:18:38 +08:00
CismonX 1b80cb315d
Update README.
continuous-integration/drone/push Build is passing Details
2021-07-25 18:08:35 +08:00
CismonX c0f0fd2ea5
Update dependencies. 2021-07-25 18:07:01 +08:00
CismonX 829a35679e
Update CI script (update node to 14.17).
continuous-integration/drone/push Build is passing Details
2021-05-25 17:01:32 +08:00
CismonX 96ae0b8f24
Refactor code so that line length <= 79. 2021-05-25 17:00:27 +08:00
CismonX 4145c8a64f
Update dependencies. 2021-05-25 12:20:19 +08:00
CismonX 6cff7138f0
Optimize build configuration. 2021-05-25 12:17:36 +08:00
CismonX 1dbafb6c97
Rename private properties. 2021-05-25 12:16:56 +08:00
CismonX 0651e8187d
Fix build script.
continuous-integration/drone/push Build is passing Details
2021-05-05 04:44:30 +08:00
CismonX db7490ffe6
Prepare for v0.2.0
continuous-integration/drone/push Build is passing Details
2021-05-05 03:46:57 +08:00
CismonX 4cdc5f7c9b
Update documentation. 2021-05-05 03:43:37 +08:00
CismonX a44da4088f
Update dependencies. 2021-05-05 03:41:13 +08:00
CismonX dd2294f59c
Update documentation.
continuous-integration/drone/push Build is passing Details
2021-04-29 20:23:46 +08:00
CismonX c09d267d66
Update configuration options. 2021-04-29 20:17:49 +08:00
CismonX c0f1a64ab8
Update dependencies.
continuous-integration/drone/push Build is passing Details
2021-04-27 18:52:51 +08:00
CismonX 464685fda9
Support disabling section numbers in preview. 2021-04-27 18:36:25 +08:00
CismonX ba9e6a6b2a
Support extra include paths for preview.
continuous-integration/drone/push Build is passing Details
2021-04-25 20:44:56 +08:00
CismonX 6006881fb9
Update dependencies.
continuous-integration/drone/push Build is passing Details
2021-04-25 01:40:26 +08:00
CismonX 8dcde6fdaa
Fix scripts. 2021-04-25 01:39:48 +08:00
CismonX f562c3fdf1
Remove requirement for package `node-html-parser`.
continuous-integration/drone/push Build is passing Details
2021-04-23 20:38:07 +08:00
CismonX b8ca0df55d
Update changelog.
continuous-integration/drone/push Build is passing Details
2021-04-22 20:53:14 +08:00
CismonX 63e7461965
Fix environment variables in `exec()` util. 2021-04-22 20:40:04 +08:00
CismonX dc6d470823
Remove `node-html-parser` from license notice. 2021-04-22 20:37:57 +08:00
CismonX 2ea65b714e
Remove "Display Images" section from manual. 2021-04-22 20:37:01 +08:00
CismonX 7c4c04600f
Support definition of Texinfo variables in config. 2021-04-22 17:07:55 +08:00
CismonX d5b84cdd7b
Refactor code. 2021-04-22 17:07:13 +08:00
CismonX 165bf9f583
Update language-configuration.json
continuous-integration/drone/push Build is passing Details
2021-04-21 17:29:53 +08:00
CismonX 19e34d8ed6
Refactor build scripts. 2021-04-21 17:25:24 +08:00
CismonX e69ec067f2
Update dependencies. 2021-04-21 17:17:43 +08:00
CismonX 7db91d9f69
Remove completion for rarely used @-commands.
continuous-integration/drone/push Build is passing Details
2021-04-20 14:58:02 +08:00
CismonX 9c82892bae
Refactor code.
continuous-integration/drone/push Build is passing Details
2021-04-19 20:43:20 +08:00
CismonX f86534985b
Do not transform URIs of online images. 2021-04-16 18:58:52 +08:00
CismonX c647d7d86b
Update documentation.
continuous-integration/drone/push Build is passing Details
2021-04-15 19:06:46 +08:00
CismonX 18a4b41881
Update dependencies. 2021-04-15 19:06:23 +08:00
CismonX c6476aaa6b
Remove configuration item `texinfo.preview.force`. 2021-04-15 19:00:49 +08:00
CismonX bdfb435526
Update documentation.
continuous-integration/drone/push Build is passing Details
2021-04-14 17:41:07 +08:00
CismonX 9f5981a418
Cleanup tsconfig.json
continuous-integration/drone/push Build is passing Details
2021-04-12 20:33:14 +08:00
CismonX c7e045828b
Update README. 2021-04-12 20:32:24 +08:00
CismonX 523ba13259
Update git repo URL. 2021-04-12 20:06:11 +08:00
CismonX 8be7d243d0
Rearrange .gitignore 2021-04-12 19:11:52 +08:00
CismonX df56d4a023
Update documentation.
continuous-integration/drone/push Build is passing Details
2021-04-10 13:35:00 +08:00
CismonX d0db855704
Change documentation license to CC-BY-SA 4.0.
continuous-integration/drone/push Build is passing Details
2021-04-06 20:30:20 +08:00
CismonX e95a5022fc
Update documentation.
continuous-integration/drone/push Build is passing Details
2021-04-06 01:07:22 +08:00
CismonX 17aa040cbf
Reduce vsix file size.
continuous-integration/drone/push Build is passing Details
2021-04-04 05:27:34 +08:00
CismonX ea6532afd4
Shorter description for configuration items. 2021-04-04 03:23:10 +08:00
CismonX f15f987b09
Git ignore generated manuals. 2021-04-04 02:59:58 +08:00
CismonX 1437a71b79
Update documentation.
continuous-integration/drone/push Build is passing Details
2021-04-02 19:54:51 +08:00
CismonX 6417e41d8b
Reduce vsix file size.
continuous-integration/drone/push Build is passing Details
2021-04-02 16:36:40 +08:00
CismonX a01f08e618
Update documentation.
continuous-integration/drone/push Build is passing Details
2021-04-01 18:41:56 +08:00
CismonX 7471e013e2
Update documentation.
continuous-integration/drone/push Build is passing Details
2021-03-31 20:51:29 +08:00
CismonX d2cbf9e189
Re-calculate block information on document save. 2021-03-31 20:51:09 +08:00
CismonX ca770ac65c
Update documentation.
continuous-integration/drone/push Build is passing Details
2021-03-30 20:26:48 +08:00
CismonX 7c4a2014a0
Add vsce to devDependencies. 2021-03-30 18:12:45 +08:00
CismonX fb89436091
Hide CodeLens if HTML preview is not available. 2021-03-30 18:11:06 +08:00
CismonX 1bfc52efba
Update documentation.
continuous-integration/drone/push Build is passing Details
2021-03-30 03:08:20 +08:00
CismonX f1321cf097
Update documentation.
continuous-integration/drone/push Build is passing Details
2021-03-29 18:57:37 +08:00
CismonX e657b3d997
Update repository URL. 2021-03-29 18:57:20 +08:00
CismonX 66b3f004c0
Update documentation.
continuous-integration/drone/push Build is passing Details
2021-03-29 17:00:05 +08:00
CismonX a44c292164
Fix key bindings. 2021-03-29 16:00:40 +08:00
CismonX a235a81e3b
Update build script.
continuous-integration/drone/push Build is passing Details
2021-03-29 02:59:27 +08:00
CismonX 181942a8cd
Add user manual.
continuous-integration/drone/push Build is passing Details
2021-03-29 02:46:49 +08:00
CismonX f89d9026a1
Migrate repo to Savannah. 2021-03-29 02:02:09 +08:00
CismonX 2965538991
Reduce vsix file size. 2021-03-29 01:38:07 +08:00
CismonX 4511fea6fa
Update dependencies. 2021-03-29 01:02:06 +08:00
CismonX 343c6e50d9
Add license notice in JSON files.
continuous-integration/drone/push Build is passing Details
2021-03-23 00:19:48 +08:00
CismonX 634bac057d
Fix package.sh (array is a bash feature)
continuous-integration/drone/push Build is passing Details
2021-03-22 12:41:27 +08:00
CismonX 5c4c27633c
Cleanup changelog.
continuous-integration/drone/push Build is failing Details
2021-03-18 19:55:44 +08:00
CismonX a604e02594
Update dependencies. 2021-03-18 16:47:17 +08:00
CismonX 6e9502bb1a
Update license notices. 2021-03-18 15:35:59 +08:00
CismonX dfb63ce3f5
Add script for packaging. 2021-03-18 14:31:29 +08:00
CismonX d9c86edd4e
Cleanup README.
continuous-integration/drone/push Build is passing Details
2021-03-17 20:15:30 +08:00
CismonX 6ed4767b18
Add license notice. 2021-03-17 20:11:48 +08:00
CismonX 5f7c15b309
Relicense project to GPL.
continuous-integration/drone/push Build is passing Details
2021-03-16 20:01:13 +08:00
CismonX ddee7b28b9
Do not use json with comments. 2021-03-16 20:00:12 +08:00
CismonX 222f0f8e12
Rearrange code.
continuous-integration/drone/push Build is passing Details
2021-03-15 20:43:38 +08:00
CismonX 036d427247
Update ignore files. 2021-03-15 15:58:57 +08:00
CismonX dddb74cb88
Update dependencies.
continuous-integration/drone/push Build is passing Details
2021-03-15 15:44:27 +08:00
CismonX add475deb1
Update license year. 2021-03-12 17:51:08 +08:00
CismonX 413ec7783b
Changelog cleanup. 2021-03-12 17:50:54 +08:00
CismonX 7b6bb43836
Allows to update indicator status by clicking. 2021-03-12 17:46:43 +08:00
CismonX 658b44fe50
Add GNU Texinfo version indicator in status bar.
continuous-integration/drone/push Build is passing Details
2021-03-11 21:35:44 +08:00
CismonX 05a524b593
Update dependencies. 2021-03-11 18:15:16 +08:00
CismonX 80674a20c3
Make converter reentrant. 2021-03-11 12:34:06 +08:00
CismonX 2d08ad4b88
Do not include dependency license in vsix package. 2021-03-11 12:08:35 +08:00
CismonX 9b2e0aa5d6
Prepare for v0.1.4
continuous-integration/drone/push Build is passing Details
2021-02-23 18:47:51 +08:00
CismonX 1e89170312
Update dependencies. 2021-02-23 18:33:28 +08:00
CismonX 6fef748039
Support custom CSS for preview.
continuous-integration/drone/push Build is passing Details
2021-02-22 15:06:05 +08:00
CismonX d0cd0f8fcd
Prepare for v0.1.3
continuous-integration/drone/push Build is passing Details
continuous-integration/drone/tag Build is passing Details
2021-02-09 17:12:29 +08:00
CismonX b00289b015
Fix completion of block command `@detailmenu`. 2021-02-09 16:40:24 +08:00
CismonX 320caa24ed
Update dependencies. 2021-02-09 16:34:45 +08:00
CismonX 3ed7b19135
Switch to self-hosted CI (Drone).
continuous-integration/drone/push Build is passing Details
2021-01-24 05:34:06 +08:00
CismonX fd077f1664
Update dependencies. 2021-01-24 04:57:48 +08:00
CismonX 5dab79db16
Stop using Git LFS. 2021-01-24 04:27:41 +08:00
CismonX c718f370ae
Prepare for v0.1.2 2020-12-31 14:42:10 +08:00
CismonX d089f57160
Update dependencies. 2020-12-31 14:37:05 +08:00
CismonX cca9786748
Update "go to file" icon ID. 2020-12-31 14:33:15 +08:00
CismonX 11b8bde3b1
v0.1.1 2020-11-30 11:56:55 +08:00
41 changed files with 6047 additions and 2116 deletions

17
.drone.yml Normal file
View File

@ -0,0 +1,17 @@
#
# Copyright (C) 2020,2021 CismonX <admin@cismon.net>
#
# Copying and distribution of this file, with or without modification, are
# permitted in any medium without royalty, provided the copyright notice and
# this notice are preserved. This file is offered as-is, without any warranty.
#
kind: pipeline
type: docker
name: default
steps:
- name: build
image: node:14.18
commands:
- npm --unsafe-perm ci
- npm run package

1
.gitattributes vendored
View File

@ -1 +0,0 @@
*.png filter=lfs diff=lfs merge=lfs -text

16
.gitignore vendored
View File

@ -1,4 +1,14 @@
.vscode/
out/
node_modules/
#
# Copyright (C) 2020,2021 CismonX <admin@cismon.net>
#
# Copying and distribution of this file, with or without modification, are
# permitted in any medium without royalty, provided the copyright notice and
# this notice are preserved. This file is offered as-is, without any warranty.
#
*.asc
*.vsix
.vscode/
node_modules/
out/
texinfo-*.d/

View File

@ -1,9 +0,0 @@
dist: bionic
language: node_js
node_js:
- node
- lts/*
script:
- npm run vscode:prepublish

View File

@ -1,9 +1,22 @@
.vscode/**
src/**
scripts/**
#
# Copyright (C) 2020,2021 CismonX <admin@cismon.net>
#
# Copying and distribution of this file, with or without modification, are
# permitted in any medium without royalty, provided the copyright notice and
# this notice are preserved. This file is offered as-is, without any warranty.
#
**/*.map
**/*.ts
.drone.yml
.gitignore
.gitattributes
.travis.yml
**/tsconfig.json
**/*.map
**/*.ts
.vscode/
doc/
LICENSE_NOTICE.md
node_modules/
src/
scripts/
texinfo-*.d/
tsconfig.json

View File

@ -1,5 +1,55 @@
<!--
Copyright (C) 2020,2021,2022 CismonX <admin@cismon.net>
Copying and distribution of this file, with or without modification, are
permitted in any medium without royalty, provided the copyright notice and
this notice are preserved. This file is offered as-is, without any warranty.
-->
# Changelog
## v0.2.4 - 02/02/2022
* Fix a bug which breaks the snippet completion of block commands.
## v0.2.3 - 10/23/2021
* Fix a bug which prevents diagnostic info from displaying correctly in GNU Texinfo 6.8, and on Windows platform.
## v0.2.2 - 10/03/2021
* Fix a bug which breaks configuration `preview.includePaths` on Windows.
* Remove completion for commands which are deprecated in GNU Texinfo 6.8.
## v0.2.1 - 05/05/2021
* Fix an error in build script which produces corrupted metadata in `.vsix` package.
## v0.2.0 - 05/05/2021
* Add version indicator (as status bar item).
* Add user manual.
* Optimize code completion.
* Optimize configuration items.
* Optimize HTML preview.
* Change license from MIT to GPL-3.0-or-later.
## v0.1.4 - 02/23/2021
* Support loading custom CSS for HTML preview.
## v0.1.3 - 02/09/2021
* Fix a bug in completion of block command `@detailmenu`.
## v0.1.2 - 12/31/2020
* Update the "go-to-file" icon ID in Code Lens, as the original icon ID no longer exists in the latest version of VSCode.
## v0.1.1 - 11/30/2020
* Fix a bug in completion of brace command `@code`.
## v0.1.0 - 11/16/2020
Initial release.
* Initial release.

687
LICENSE
View File

@ -1,21 +1,674 @@
MIT License
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (c) 2020 CismonX <admin@cismon.net>
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
Preamble
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
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.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
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 <https://www.gnu.org/licenses/>.
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:
<program> Copyright (C) <year> <name of author>
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
<https://www.gnu.org/licenses/>.
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
<https://www.gnu.org/licenses/why-not-lgpl.html>.

49
LICENSE_NOTICE.md Normal file
View File

@ -0,0 +1,49 @@
<!--
Copyright (C) 2021 CismonX <admin@cismon.net>
Copying and distribution of this file, with or without modification, are
permitted in any medium without royalty, provided the copyright notice and
this notice are preserved. This file is offered as-is, without any warranty.
-->
# License Notice
## Other project files
Project files listed below cannot carry a license notice by themselves, due to
file format restrictions.
assets/texinfo.png
They should be treated as if they each contains the following text:
Copyright (C) 2020,2021 CismonX <admin@cismon.net>
Copying and distribution of this file, with or without modification, are
permitted in any medium without royalty, provided the copyright notice and
this notice are preserved. This file is offered as-is, without any warranty.
## Files from other projects
Source code from the projects listed below are **not** part of vscode-texinfo.
However, when building the project, they are downloaded, compiled, and packaged
into a single binary file alongside with vscode-texinfo.
| Project | Copyright Holder | License |
| - | - | - |
| [Texinfo syntax highlighting] | John Gardner | [ISC](https://github.com/Alhadis/language-texinfo/blob/master/LICENSE.md) |
The following projects are required during runtime of vscode-texinfo, but as
separate programs.
| Project | Copyright Holder | License |
| - | - | - |
| [Visual Studio Code] | Microsoft Corporation | [MIT](https://github.com/microsoft/vscode/blob/main/LICENSE.txt) |
| [GNU Texinfo] | Free Software Foundation | [GPL-3.0](https://git.savannah.gnu.org/cgit/texinfo.git/tree/COPYING)-or-later |
<!-- Reference Links -->
[Texinfo syntax highlighting]: https://github.com/Alhadis/language-texinfo
[Visual Studio Code]: https://github.com/microsoft/vscode
[GNU Texinfo]: https://www.gnu.org/software/texinfo

View File

@ -1,60 +1,36 @@
<!--
Copyright (C) 2020,2021 CismonX <admin@cismon.net>
Copying and distribution of this file, with or without modification, are
permitted in any medium without royalty, provided the copyright notice and
this notice are preserved. This file is offered as-is, without any warranty.
-->
# vscode-texinfo
[![Build Status](https://travis-ci.com/texinfo-lang/vscode-texinfo.svg)](https://travis-ci.com/github/texinfo-lang/vscode-texinfo)
[![MIT License](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
[![Build Status]][Drone CI] [![License]](LICENSE)
Texinfo language support for Visual Studio Code.
## About
## Features
vscode-texinfo is an extension of Visual Studio Code which aims at improving
user experience for editing Texinfo documents.
* **Syntax Highlighting**
* Provided by the same [TextMate grammar](https://github.com/Alhadis/language-texinfo/blob/v1.0.0/grammars/texinfo.cson) as [used in GitHub](https://github.com/github/linguist/pull/4589).
* **Code Completion**
* Completion and code snippets for most @\-commands.
* **Preview**
* Display HTML preview in a webview.
* Texinfo to HTML conversion is provided by [GNU Texinfo](https://www.gnu.org/software/texinfo).
* **Folding**
* Fold on nodes, block commands and multiline comments.
* Breadcrumb navigation of folding blocks.
* **Diagnostics**
* Show diagnostic information in editor based on error and warning messages generated by GNU Texinfo.
Major features include:
* Syntax Highlighting
* Code Completion
* HTML Preview
* Block Folding
* Breadcrumb Navigation
* Diagnostics
<details>
<summary>Screenshots:</summary>
## Getting Started
Display preview:
![preview](https://user-images.githubusercontent.com/19173506/98842831-15355880-2485-11eb-9a12-a709d930ac05.png)
For instructions about how to install, use, and contribute to vscode-texinfo,
see the [online user manual].
Code completion:
![completion](https://user-images.githubusercontent.com/19173506/98842873-254d3800-2485-11eb-8cef-78a534b08b84.png)
<!-- Reference Links -->
Breadcrumb navigation:
![navigation](https://user-images.githubusercontent.com/19173506/98842850-1ebec080-2485-11eb-8da7-2d167ea86ccf.png)
Folding:
![folding](https://user-images.githubusercontent.com/19173506/98842863-21b9b100-2485-11eb-85f9-d6c9d317d307.png)
Diagnostics:
![diagnostics](https://user-images.githubusercontent.com/19173506/98842883-28482880-2485-11eb-9399-6046e8873014.png)
</details>
## Requirements
* Visual Studio Code version >= 1.40.0. Legacy versions may also work.
* A latest version of GNU Texinfo.
## Extension Settings
See `File -> Preferences -> Settings -> Extensions -> Texinfo` for details. The settings are self-explanatory.
## Notes
* If syntax highlighting is not satisfactory, try another color theme (e.g. Solarized Light/Dark, Monokai) where keyword/operator colors are distinct.
* Preview content is updated on document save rather than document change, as Texinfo documents tend to be rather large, and incremental conversion is not yet supported.
* For macOS users: Preinstalled GNU Texinfo distribution is very old. Use a latest one instead. This can be easily done by `brew install texinfo` and change extension setting `texinfo.makeinfo` value.
## Future Plans
* Implement [Language Server Protocol](https://microsoft.github.io/language-server-protocol) for the Texinfo language, preferably by extending GNU Texinfo, to alleviate the limitations of the current implementaion.
[Build Status]: https://shields.io/drone/build/cismonx/vscode-texinfo?server=https%3A%2F%2Fdrone.cismon.net
[Drone CI]: https://drone.cismon.net/cismonx/vscode-texinfo
[License]: https://img.shields.io/badge/license-GPL--3.0--or--later-blue.svg
[online user manual]: https://nongnu.org/vscode-texinfo/manual

Binary file not shown.

Before

Width:  |  Height:  |  Size: 129 B

After

Width:  |  Height:  |  Size: 4.6 KiB

13
doc/.gitignore vendored Normal file
View File

@ -0,0 +1,13 @@
#
# Copyright (C) 2021 CismonX <admin@cismon.net>
#
# Copying and distribution of this file, with or without modification, are
# permitted in any medium without royalty, provided the copyright notice and
# this notice are preserved. This file is offered as-is, without any warranty.
#
*.aux
*.info
*.log
*.toc
version.texi

477
doc/vscode-texinfo.texi Normal file
View File

@ -0,0 +1,477 @@
\input texinfo @c -*-texinfo-*-
@c %**start of header
@setfilename vscode-texinfo.info
@include version.texi
@settitle User Manual for vscode-texinfo
@c %**end of header
@set vscode-docs-url https://code.visualstudio.com/docs
@set vscode-api-url https://code.visualstudio.com/api
@set gnu-texinfo-docs https://www.gnu.org/software/texinfo/manual/texinfo
@tex
\global\def\linkcolor{0 0 1}
\global\def\urlcolor{0 0 1}
\global\urefurlonlylinktrue
@end tex
@copying
This manual is for vscode-texinfo (version @value{VERSION}), an extension of
Visual Studio Code.
Copyright @copyright{} 2021 CismonX <admin@@cismon.net>
@quotation
This manual is licensed under a
@url{https://creativecommons.org/licenses/by-sa/4.0/,
Creative Commons Attribution-ShareAlike 4.0 International License}.
@end quotation
@end copying
@titlepage
@title vscode-texinfo
@subtitle Texinfo Support for Visual Studio Code, version @value{VERSION}
@author CismonX
@page
@vskip 0pt plus 1filll
@insertcopying
@end titlepage
@summarycontents
@contents
@ifnottex
@node Top
@top vscode-texinfo
This manual is for vscode-texinfo (version @value{VERSION}), an extension of
Visual Studio Code.
Copyright @copyright{} 2021 CismonX <admin@@cismon.net>
This manual is licensed under a
@url{https://creativecommons.org/licenses/by-sa/4.0/,
Creative Commons Attribution-ShareAlike 4.0 International License}.
@end ifnottex
@menu
* Overview:: Brief overview of vscode-texinfo.
* Installation:: Install vscode-texinfo.
* Basic Usage:: Basic features of vscode-texinfo.
* Advanced Usage:: Advanced features of vscode-texinfo.
@end menu
@node Overview
@chapter Overview
Texinfo is a typesetting language designed for writing software manuals. It's
the official documention format for GNU projects, but not as popular in modern
non-GNU free software projects.
One of the main reasons is the lack of editor support. While Emacs does offer a
``texinfo-mode'', however, Emacs is not widely used among average software
developers.
We believe that Texinfo deserves more users, for it is an excellent format for
writing software manuals, as well as other technical materials. We chose Visual
Studio Code, one of the most popular code editors as of year 2020, and
developed this very extension, vscode-texinfo, which provides some useful
features for Visual Studio Code regarding the Texinfo format, in the hope that
more developers can benefit from it.
vscode-texinfo 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 @url{https://www.gnu.org/licenses/gpl-3.0-standalone.html,
version 3 of the License}, or (at your option) any later version.
@menu
* Contributing:: Contribute to vscode-texinfo.
@end menu
@node Contributing
@section Contributing
This project is hosted on @url{https://sv.gnu.org/p/vscode-texinfo, Savannah}.
Any kind of contribution is welcome, including bug reports, patches, and
general discussions regarding the usage of vscode-texinfo.
Before you submit something, please make sure that you have read this manual,
and no one else has posted the same content.
@node Installation
@chapter Installation
vscode-texinfo cannot be run standalone. It can only be used as an extension of
Visual Studio Code.
It is recommended to use a free distribution of Visual Studio Code,
@url{https://github.com/VSCodium/vscodium, VSCodium}, instead of the official
binary release, which is proprietary software. You can also build it from
@url{https://github.com/microsoft/vscode, source} yourself.
@quotation Note
Theoretically vscode-texinfo can work with any version of Visual Studio Code
since 1.40, but not all versions are tested. It's recommended to install a
latest release.
@end quotation
The easiest way to install vscode-texinfo is from the extension marketplace.
Click the ``Extensions'' tab on Visual Studio Code's sidebar, type ``texinfo''
and you can find and install this extension (Extension ID:
@code{CismonX.texinfo}).
@menu
* Manual Installation:: Download and install vscode-texinfo manually.
* Build from Source:: Build vscode-texinfo from source code.
@end menu
@node Manual Installation
@section Manual Installation
You can manually download the @code{.vsix} file, from either Savannah's
@url{https://dl.sv.gnu.org/releases/vscode-texinfo/, download area},
@url{https://open-vsx.org/extension/CismonX/texinfo, Open VSX Registry}, or the
proprietary Visual Studio Marketplace.
Before you install a @code{.vsix} file downloaded from a third party,
you should check whether the file matches a trusted signature:
@set vsix-name texinfo-@value{VERSION}.vsix
@ifhtml
@example
wget -O cismonx.gpg.asc "https://sv.gnu.org/people/viewgpg.php?user_id=214244"
gpg --import cismonx.gpg.asc
wget https://dl.sv.gnu.org/releases/vscode-texinfo/@value{vsix-name}.sig.asc
gpg --verify @value{vsix-name}.sig.asc @value{vsix-name}
@end example
@end ifhtml
@ifnothtml
@example
wget -O cismonx.gpg.asc \
"https://sv.gnu.org/people/viewgpg.php?user_id=214244"
gpg --import cismonx.gpg.asc
wget "https://dl.sv.gnu.org/releases/vscode-texinfo/
@value{vsix-name}.sig.asc"
gpg --verify @value{vsix-name}.sig.asc @value{vsix-name}
@end example
@end ifnothtml
Finally, install the @code{.vsix} file to Visual Studio Code via command
palette: @code{Extensions: Install from VSIX...}.
@node Build from Source
@section Build from Source
You can generate the @code{.vsix} file from the source code of vscode-texinfo.
First, clone the source code repository:
@example
git clone https://git.sv.gnu.org/git/vscode-texinfo.git
cd vscode-texinfo
@end example
Then, install dependencies with Node Package Manager, and build the project:
@example
npm ci
npm run package
@end example
If the operation is successful, a @code{texinfo-@{VERSION@}.vsix} file will be
generated under the root directory of the source code repository.
@node Basic Usage
@chapter Basic Usage
There are several basic features of vscode-texinfo which can be used
out-of-the-box.
@menu
* Syntax Highlighting:: Syntax highlighting for Texinfo documents.
* Code Completion:: Show completion list for @@-commands.
* Block Folding:: Collapse or expand code blocks.
* Breadcrumb Navigation:: Navigate between different contexts.
@end menu
@node Syntax Highlighting
@section Syntax Highlighting
The syntax highlighting solution is provided by
@url{https://github.com/Alhadis/language-texinfo, this TextMate Grammar}, which
is originally made for Atom, and also used in GitHub Linguist.
To enable Texinfo syntax highlighting when editing a file, it should be
recognized as a Texinfo document by Visual Studio Code. For file names with
suffix @code{.texi}, @code{.txi} or @code{.texinfo}, this process should be
automatic. If not, find and click the status bar item with ``Select Language
Mode'' tooltip, then choose ``Texinfo'' in the menu which just popped up.
If syntax highlighting does not look satisfactory, try another color theme
where keyword/operator colors are distinct. Some good examples are Solarized
Light/Dark, Monokai, etc.
For details about how to @url{@value{vscode-docs-url}
/languages/overview#_changing-the-language-for-the-selected-file,
change language mode} or @url{@value{vscode-docs-url}/getstarted/themes
#_selecting-the-color-theme, select color theme}, see the Visual Studio Code
User Guide.
@node Code Completion
@section Code Completion
When typing a @@-command in a Texinfo document, vscode-texinfo can display a
completion list so that you don't have to type the entire command.
There are two kinds of completion items: The command itself, and code snippets
related to that command.
A typical example of code snippet is the completion of a block command, say,
@code{@@example}. When applying completion, the generated code looks like:
@example
@@example
@@end example
@end example
The cursor falls between @code{@@example} and @code{@@end example}, where you
can finish the content of the @code{@@example} block. After that, press Tab to
bail out of the block.
Code snippet completion can be disabled by switching off the configuration item
@code{texinfo.completion.enableSnippets}.
When code snippet completion is enabled, completion of commands which relate to
code snippets is disabled by default. You can re-enable it on by switching off
@code{texinfo.completion.hideSnippetCommands}.
@quotation Note
Code completion provided by vscode-texinfo does not recognize much of Texinfo's
semantics, and completion may appear in contexts where it should not exist.
This is a known bug (which cannot be fixed in near future, unless a
@url{https://microsoft.github.io/language-server-protocol/, language server}
for Texinfo is implemented, which is not trivial).
@end quotation
@node Block Folding
@section Block Folding
Block folding allows you to collapse a block of code in a Texinfo document, so
that you can navigate through the remaining part of the document more easily.
Three types of code blocks can be recognized by vscode-texinfo:
@itemize @bullet
@item Block commands
@item Chapters, sections and subsections
@item Consecutive lines of comments
@end itemize
While editing a Texinfo document, you can collapse or expand a code block
either by clicking the folding icon to the left of the first line of the block,
or by invoking a corresponding command. See the Visual Studio Code User Guide
for @url{@value{vscode-docs-url}/editor/codebasics#_folding, details}.
@quotation Note
Due to performance issues, the block hierarchy of a Texinfo document is
re-calculated only when total line count changes, or when the document is
saved.
@end quotation
@node Breadcrumb Navigation
@section Breadcrumb Navigation
Using the navigation bar, you can navigate through the code blocks defined in
@ref{Block Folding} (excluding blocks of comment lines). Titles of chapters and
sections are shown.
See the Visual Studio Code User Guide for more information about
@url{@value{vscode-docs-url}/editor/editingevolved#_breadcrumbs, Breadcrumbs}.
@node Advanced Usage
@chapter Advanced Usage
Some more advanced features of vscode-texinfo is available if GNU Texinfo is
correctly installed and configured on your device.
@url{https://www.gnu.org/software/texinfo, GNU Texinfo} is the official (and
the only known) full implementation of Texinfo. On most platforms, it can be
easily installed using a package manager. For example, if you're using a
Debian-based GNU/Linux distribution, you can install GNU Texinfo with:
@example
sudo apt-get install texinfo
@end example
GNU Texinfo provides a CLI program @code{makeinfo}, a.k.a. @code{texi2any},
which converts a Texinfo document to some other format, like HTML, PDF,
plain text, etc.
To specify the location of @code{makeinfo}, edit the configuration item
@code{texinfo.makeinfo}. If it's not located in @code{$PATH}, an absolute path
should be specified. Also note that the path should not contain any command
line arguments.
To check whether GNU Texinfo is correctly installed and configured, see
@ref{Version Indicator}.
@menu
* Version Indicator:: Show the installed version of GNU Texinfo
* HTML Preview:: Display document preview in HTML format.
* Diagnosis:: Show diagnostic information.
@end menu
@node Version Indicator
@section Version Indicator
The version indicator is a status bar item with text ``GNU Texinfo''. It is
located on the right side of the status bar, which is shown when the active
text editor contains a Texinfo document.
If you see a @b{check icon} and the version of GNU Texinfo, then
congratulations, you're all set. If a @b{cross icon} is displayed, it means
that GNU Texinfo is @emph{not} correctly installed and configured.
If a @b{warning icon} is displayed, it means that the currently installed GNU
Texinfo is outdated, or has an unrecognizable version number. In that case,
some features may not work as expected.
@quotation Note
The version indicator does not automatically refresh since the activation of
the extension. To manually trigger a refresh, click the status bar item.
@end quotation
@node HTML Preview
@section HTML Preview
You can generate the HTML preview of a Texinfo document in Visual Studio Code,
to see how the document looks like when displayed online.
In the active text editor which contains a Texinfo document, click the ``Show
Preview'' button on the top right of the editor. A webview will be created in a
split editor (if not already), and the HTML preview will be displayed there.
The ``Show Preview'' command is also available in command palette, and has a
default @code{Ctrl+K V} key binding (on GNU/Linux).
The HTML used for preview is generated by @code{makeinfo --html --nosplit}, and
Texinfo source is read from disk, instead of taken from a
@url{@value{vscode-api-url}/references/vscode-api#TextDocument,
@code{vscode.TextDocument}}. The editor may prompt you to save to file when
trying to display preview of a document which does not yet exist on disk, so
that the preview can be displayed.
An opened preview automatically tracks the behaviour of the corresponding
document. When the document is saved, the preview will refresh. When the editor
holding the document is closed, the preview also closes.
Texinfo documents tend to be rather large, and @code{makeinfo} may take some
time to finish. When you see an ``(Updating)'' in the title of a preview, it
means that the preview is being updated.
@menu
* Custom CSS:: Use custom stylesheets for HTML preview.
* Goto Node:: Jump to a node in preview.
* Misc Settings:: Miscellaneous configuration options regarding preview.
@end menu
@node Custom CSS
@subsection Custom CSS
You can use a custom CSS to make the HTML preview look prettier. To configure
this, edit the configuration option @code{texinfo.preview.customCSS}. The CSS
file can either be an online or a local (starting with @code{file://})
resource.
A good example is @url{https://www.gnu.org/software/gnulib/manual.css}, which
is popular among manuals of GNU projects. (Note: May require some tinkering
when used with darker editor themes)
@node Goto Node
@subsection Goto Node
Above each @code{@@node} line in a Texinfo document, a code lens with text
``Goto node in preview'' is shown. On click, it makes the HTML preview jump to
the corresponding location.
@quotation Note
@code{@@node} lines
@url{@value{gnu-texinfo-docs}/html_node/HTML-Xref-Command-Expansion.html,
allow @@-commands}, which is not handled in vscode-texinfo due to performance
considerations. For these nodes, this feature does not work.
@end quotation
To disable this feature and hide the code lenses, switch off the configuation
item @code{texinfo.enableCodeLens}.
See the Visual Studio Code User Guide for more information about
@url{@value{vscode-api-url}/references/vscode-api#CodeLens, CodeLens}.
@node Misc Settings
@subsection Misc Settings
There are some other settings which can affect the behaviour and appearance of
HTML previews.
@itemize @bullet
@item @code{texinfo.preview.errorLimit}: Number of errors which @code{makeinfo}
can produce before quitting. (@code{--error-limit=NUM})
@item @code{texinfo.preview.includePaths}: Array of extra paths to search for
@code{@@include} files. (@code{-I PATH})
@item @code{texinfo.preview.maxSize}: Max allowed size for the genereated HTML
file before it's displayed in the preview. Files larger than this limit will
trigger an error.
@item @code{texinfo.preview.noHeaders}: When enabled, headers and menus are no
longer displayed in preview. (@code{--no-headers})
@item @code{texinfo.preview.noNumberSections}: When enabled, do not display
chapter and section numbers in preview. (@code{--no-number-sections})
@item @code{texinfo.preview.noValidation}: When enabled, node cross-references
are not validated. (@code{--no-validate})
@item @code{texinfo.preview.variables}: Array of variables to define (as with
@code{@@set}). If a variable has a value, use the ASCII space character to
separate key and value.
@end itemize
@node Diagnosis
@section Diagnosis
Diagnosis can help you locate syntactic and semantic problems in a Texinfo
document, by parsing the error output of @code{makeinfo} and display the
diagnostic information on the editor.
The diagnostic information of a document is calculated automatically, whenever
an attempt to generate preview is made.
By default, all error and warning messages are shown. To disable warnings,
switch on the configuration item @code{texinfo.diagnosis.noWarnings}.
@bye

40
ext/html-preview.pm Normal file
View File

@ -0,0 +1,40 @@
#
# ext/html-preview.pm
#
# Copyright (C) 2021 CismonX <admin@cismon.net>
#
# This file is part of vscode-texinfo.
#
# vscode-texinfo 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.
#
# vscode-texinfo 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
# vscode-texinfo. If not, see <https://www.gnu.org/licenses/>.
#
use strict;
sub vscode_convert_image_uri {
my ( $self, $cmdname, $command, $args ) = @_;
my $filename = $args->[0]->{'monospacetext'};
my $prefix
= ( defined($filename)
&& rindex( $filename, 'http://', 0 ) == -1
&& rindex( $filename, 'https://', 0 ) == -1 )
? $self->{'parser'}->{'values'}->{'__vscode_texinfo_image_uri_base'}
: undef;
$self->set_conf( 'IMAGE_LINK_PREFIX', $prefix );
return &{ $self->default_commands_conversion($cmdname) }(@_);
}
texinfo_register_command_formatting( 'image', \&vscode_convert_image_uri );
1;

View File

@ -1,11 +1,16 @@
/**
* Copyright (C) 2020,2021 CismonX <admin@cismon.net>
*
* Copying and distribution of this file, with or without modification, are
* permitted in any medium without royalty, provided the copyright notice and
* this notice are preserved. This file is offered as-is, without any warranty.
*/
{
"comments": {
"lineComment": "@c",
},
"brackets": [
["{", "}"],
["[", "]"],
["(", ")"],
],
"autoClosingPairs": [
["{", "}"],

3139
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,48 +1,60 @@
{
"_copyrightNotice": [
"Copyright (C) 2020,2021,2022 CismonX <admin@cismon.net>",
"Copying and distribution of this file, with or without modification,",
"are permitted in any medium without royalty, provided the copyright notice and this notice are preserved.",
"This file is offered as-is, without any warranty."
],
"name": "texinfo",
"displayName": "Texinfo Language Support",
"description": "Provides basic editing experience for Texinfo documents, including syntax highlighting, code completion, HTML preview, etc.",
"description": "Texinfo language support for Visual Studio Code",
"publisher": "cismonx",
"version": "0.1.0",
"version": "0.2.4",
"author": {
"name": "CismonX",
"email": "admin@cismon.net",
"url": "https://cismon.net"
},
"license": "MIT",
"license": "GPL-3.0-or-later",
"homepage": "https://sv.gnu.org/p/vscode-texinfo",
"repository": {
"type": "git",
"url": "https://github.com/texinfo-lang/vscode-texinfo"
"url": "https://git.sv.gnu.org/cgit/vscode-texinfo.git"
},
"icon": "assets/texinfo.png",
"devDependencies": {
"@types/node": "^14.14.7",
"@types/terser-webpack-plugin": "^5.0.2",
"@types/node": "^14.17.29",
"@types/vscode": "~1.40.0",
"@types/webpack": "^4.41.25",
"@typescript-eslint/eslint-plugin": "^4.7.0",
"@typescript-eslint/parser": "^4.7.0",
"@types/webpack": "^5.28.0",
"@typescript-eslint/eslint-plugin": "^5.10.2",
"@typescript-eslint/parser": "^5.10.2",
"cson": "^7.20.0",
"eslint": "^7.13.0",
"json": "^10.0.0",
"language-texinfo": "^1.0.0",
"node-html-parser": "^2.0.0",
"ts-loader": "^8.0.11",
"ts-node": "^9.0.0",
"typescript": "^4.0.5",
"webpack": "^5.4.0",
"webpack-cli": "^4.2.0"
"eslint": "^8.8.0",
"json": "^11.0.0",
"json5": "^2.2.0",
"language-texinfo": "^1.1.0",
"minify-xml": "^3.3.1",
"ts-loader": "^9.2.6",
"ts-node": "^10.4.0",
"typescript": "^4.5.5",
"vsce": "^2.6.6",
"webpack": "^5.68.0",
"webpack-cli": "^4.9.2"
},
"scripts": {
"vscode:prepublish": "webpack --mode production",
"package": "./scripts/package.sh",
"build": "webpack --mode development",
"prepare": "sh ./scripts/prepare.sh",
"prepare": "./scripts/prepare.sh",
"lint": "eslint --ext ts --fix src",
"watch": "webpack --mode development --watch"
},
"eslintConfig": {
"root": true,
"ignorePatterns": "out/**",
"ignorePatterns": [
"out/**",
"scripts/**"
],
"parser": "@typescript-eslint/parser",
"plugins": [
"@typescript-eslint"
@ -59,7 +71,7 @@
"max-len": [
"warn",
{
"code": 120
"code": 79
}
],
"@typescript-eslint/explicit-module-boundary-types": "off",
@ -88,6 +100,10 @@
{
"command": "texinfo.preview.goto",
"title": "Goto node in preview"
},
{
"command": "texinfo.indicator.click",
"title": "Refresh indicator status"
}
],
"menus": {
@ -101,6 +117,11 @@
"command": "texinfo.preview.goto",
"when": "false",
"group": "navigation"
},
{
"command": "texinfo.indicator.click",
"when": "false",
"group": "navigation"
}
],
"editor/title": [
@ -122,63 +143,73 @@
"configuration": {
"title": "Texinfo",
"properties": {
"texinfo.makeinfo": {
"type": "string",
"default": "makeinfo",
"markdownDescription": "Path to the `makeinfo` (or `texi2any`) command. If not located in `$PATH`, an absolute path should be specified.\n\nThe value should not contain any command-line arguments, just the filename."
},
"texinfo.enableCodeLens": {
"type": "boolean",
"default": true,
"markdownDescription": "Enable code lens on node identifiers which jumps to the corresponding nodes in preview."
},
"texinfo.completion.enableSnippets": {
"type": "boolean",
"default": true,
"markdownDescription": "Show snippets in code completion items.\n\nIf disabled, only commands are shown."
"description": "Show snippets in code completion items."
},
"texinfo.completion.hideSnippetCommands": {
"type": "boolean",
"default": true,
"markdownDescription": "When snippet is enabled, hide the snippets' corresponding commands from completion items."
"description": "When snippet is enabled, hide the snippets' corresponding commands from completion items."
},
"texinfo.preview.noHeaders": {
"texinfo.diagnosis.noWarnings": {
"type": "boolean",
"default": false,
"markdownDescription": "Suppress node separators in preview.\n\nThis corresponds to the `--no-headers` option of `makeinfo`."
"description": "Do not show warnings in diagnosis."
},
"texinfo.preview.maxSize": {
"type": "integer",
"default": "2",
"minimum": 1,
"maximum": 16,
"markdownDescription": "Max allowed size (in MiB) for the preview document."
"texinfo.enableCodeLens": {
"type": "boolean",
"default": true,
"description": "Enable code lens on node identifiers which jumps to the corresponding nodes in preview."
},
"texinfo.makeinfo": {
"type": "string",
"default": "makeinfo",
"description": "Path to the makeinfo (or texi2any) command."
},
"texinfo.preview.customCSS": {
"type": "string",
"default": "",
"description": "URI of custom CSS for preview."
},
"texinfo.preview.errorLimit": {
"type": "integer",
"default": 100,
"minimum": 0,
"markdownDescription": "Max number of errors before quit when trying to display preview.\n\nThis corresponds to the `--error-limit=NUM` option of `makeinfo`."
"description": "Max number of errors before quit when trying to display preview."
},
"texinfo.preview.force": {
"texinfo.preview.includePaths": {
"type": "array",
"default": [],
"description": "Extra paths to search for @include files."
},
"texinfo.preview.maxSize": {
"type": "integer",
"default": 2,
"minimum": 1,
"maximum": 16,
"description": "Max allowed size (in MiB) for the preview document."
},
"texinfo.preview.noHeaders": {
"type": "boolean",
"default": false,
"markdownDescription": "Preserve preview even if errors.\n\nThis corresponds to the `--force` option of `makeinfo`."
"description": "Suppress node separators in preview."
},
"texinfo.preview.noNumberSections": {
"type": "boolean",
"default": false,
"description": "Do not display chapter and section numbers in preview"
},
"texinfo.preview.noValidation": {
"type": "boolean",
"default": false,
"markdownDescription": "Supress node cross-reference validation.\n\nThis corresponds to the `--no-validate` option of `makeinfo`."
"description": "Supress node cross-reference validation."
},
"texinfo.preview.noWarnings": {
"type": "boolean",
"default": false,
"markdownDescription": "Suppress warnings.\n\nThis corresponds to the `--no-warn` option of `makeinfo`."
},
"texinfo.preview.displayImage": {
"type": "boolean",
"default": false,
"markdownDescription": "Whether to display images in in the preview.\n\nIf image display is not needed, turn off this option to improve preview performance."
"texinfo.preview.variables": {
"type": "array",
"default": [],
"description": "Define variables (as with @set)."
}
}
},

33
scripts/make-vsix.js Normal file
View File

@ -0,0 +1,33 @@
/**
* Copyright (C) 2021 CismonX <admin@cismon.net>
*
* Copying and distribution of this file, with or without modification, are
* permitted in any medium without royalty, provided the copyright notice and
* this notice are preserved. This file is offered as-is, without any warranty.
*/
const fs = require('fs');
const yazl = require('yazl');
async function addPathToZipFile(zipFile, path) {
for (file of await fs.promises.readdir(path, { withFileTypes: true })) {
const name = `${path}/${file.name}`;
if (file.isDirectory()) {
await addPathToZipFile(zipFile, name);
} else {
zippedPath = name.substr(name.indexOf('/') + 1);
console.log(`+ ${zippedPath}`);
zipFile.addFile(name, zippedPath);
}
}
}
(async () => {
const vsixFile = process.argv.pop();
console.log(`Creating ${vsixFile}:`);
const zipFile = new yazl.ZipFile();
zipFile.outputStream.pipe(fs.createWriteStream(vsixFile))
.on('close', () => console.log(`Finish creating ${vsixFile}`));
await addPathToZipFile(zipFile, `${vsixFile}.d`);
zipFile.end();
})()

View File

@ -0,0 +1,18 @@
/**
* Copyright (C) 2021 CismonX <admin@cismon.net>
*
* Copying and distribution of this file, with or without modification, are
* permitted in any medium without royalty, provided the copyright notice and
* this notice are preserved. This file is offered as-is, without any warranty.
*/
// Removes entries from package.json which is not required in the .vsix file,
// so that the file size can be reduced.
delete this._copyrightNotice;
delete this.devDependencies;
delete this.eslintConfig;
delete this.scripts.build;
delete this.scripts.prepare;
delete this.scripts.lint;
delete this.scripts.watch;
delete this.scripts.package;

41
scripts/package.sh Executable file
View File

@ -0,0 +1,41 @@
#!/usr/bin/env bash
#
# Copyright (C) 2021 CismonX <admin@cismon.net>
#
# Copying and distribution of this file, with or without modification, are
# permitted in any medium without royalty, provided the copyright notice and
# this notice are preserved. This file is offered as-is, without any warranty.
#
VSIX_FILE_NAME=texinfo-$(json -f package.json version).vsix
PACKAGE_JSON_CLEANUP_JS=$(cat ./scripts/package-json-cleanup.js)
vsce package --baseContentUrl=$(json -f package.json repository.url)/tree
unzip -d $VSIX_FILE_NAME{.d,}
cd $VSIX_FILE_NAME.d
MINIFY_XML_OPTIONS='--no-shorten-namespaces
--no-remove-unused-namespaces
--no-remove-unused-default-namespace'
minify-xml $MINIFY_XML_OPTIONS --output \[Content_Types\].xml{,}
minify-xml $MINIFY_XML_OPTIONS --output extension.vsixmanifest{,}
cd extension
# Minify JSON files.
json -j0 -I -e "$PACKAGE_JSON_CLEANUP_JS" -f package.json
perl -pi -e 'chomp if eof' package.json
json5 -o language-configuration.json{,}
# Remove comments from Markdown files.
tail -n +9 README.md > _ && mv _ README.md
tail -n +9 CHANGELOG.md > _ && mv _ CHANGELOG.md
cd ext
# Minify Perl scripts.
# You can install perltidy with `cpan Perl::Tidy`
if [[ -x "$(command -v perltidy)" ]]; then
perltidy --mangle -dac -b html-preview.pm
rm html-preview.pm.bak
fi
cd ../../..
# Re-package .vsix file.
node ./scripts/make-vsix.js $VSIX_FILE_NAME
rm -r $VSIX_FILE_NAME.d

View File

@ -1,8 +1,17 @@
#!/usr/bin/env sh
#
# Copyright (C) 2020,2021 CismonX <admin@cismon.net>
#
# Copying and distribution of this file, with or without modification, are
# permitted in any medium without royalty, provided the copyright notice and
# this notice are preserved. This file is offered as-is, without any warranty.
#
SRC_PATH=./node_modules/language-texinfo
DEST_PATH=./out/grammars
mkdir -p $DEST_PATH
cp $SRC_PATH/LICENSE.md $DEST_PATH
# Convert TextMate grammar from CSON to JSON, as VSCode cannot recognize CSON ones.
cson2json $SRC_PATH/grammars/texinfo.cson | json -j0 > $DEST_PATH/texinfo.json
# Convert TextMate grammar to JSON, as VSCode cannot recognize CSON ones.
cson2json $SRC_PATH/grammars/texinfo.cson | json5 > $DEST_PATH/texinfo.json
VERSION=$(json -f package.json version)
echo "@set VERSION $VERSION" > ./doc/version.texi

View File

@ -1,57 +1,134 @@
/**
* document.ts
*
* @author CismonX <admin@cismon.net>
* @license MIT
* context_mapping.ts
*
* Copyright (C) 2020,2021 CismonX <admin@cismon.net>
*
* This file is part of vscode-texinfo.
*
* vscode-texinfo 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.
*
* vscode-texinfo 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
* vscode-texinfo. If not, see <https://www.gnu.org/licenses/>.
*/
import * as vscode from 'vscode';
import DocumentContext from './contexts/document';
import GlobalContext from './global_context';
import { prompt } from './utils/misc';
/**
* Manage mappings between Texinfo documents and corresponding contexts.
* Manage mappings between Texinfo documents and corresponding
* document-specific contexts.
*/
export default class ContextMapping implements vscode.Disposable {
private static singleton?: ContextMapping;
static get instance() {
return ContextMapping.singleton ??= new ContextMapping();
}
static getDocumentContext(document: vscode.TextDocument) {
let documentContext = ContextMapping.instance.value.get(document);
export default class ContextMapping implements vscode.Disposable
{
/**
* Get context of a Texinfo document. Create one if not exists.
*
* @param document
* @returns
*/
getDocumentContext(document: vscode.TextDocument) {
let documentContext = this._map.get(document);
if (documentContext === undefined) {
ContextMapping.instance.value.set(document, documentContext = new DocumentContext(document));
documentContext
= new DocumentContext(this._globalContext, document);
this._map.set(document, documentContext);
}
return documentContext;
}
static onDocumentUpdate(event: vscode.TextDocumentChangeEvent) {
const documentContext = ContextMapping.getDocumentContextIfExist(event.document);
dispose() {
this._map
.forEach(documentContext => documentContext.getPreview()?.close());
}
constructor(private readonly _globalContext: GlobalContext) {
_globalContext.subscribe(
vscode.commands.registerTextEditorCommand(
'texinfo.preview.show',
this._showPreview.bind(this),
),
vscode.commands.registerCommand(
'texinfo.preview.goto',
this._gotoPreview.bind(this),
),
vscode.workspace.onDidChangeTextDocument(
this._onDocumentUpdate.bind(this),
),
vscode.workspace.onDidCloseTextDocument(
this._onDocumentClose.bind(this),
),
vscode.workspace.onDidSaveTextDocument(
this._onDocumentSave.bind(this),
),
);
}
private readonly _map = new Map<vscode.TextDocument, DocumentContext>();
private _tryGetDocumentContext(document: vscode.TextDocument) {
return document.languageId === 'texinfo'
? this.getDocumentContext(document) : undefined;
}
/**
* Jump to the corresponding section of document preview by node name.
*
* @param document
* @param nodeName
*/
private _gotoPreview(document: vscode.TextDocument, nodeName: string) {
this.getDocumentContext(document).initPreview().goto(nodeName);
}
private _onDocumentClose(document: vscode.TextDocument) {
this._map.get(document)?.getPreview()?.close();
this._map.delete(document);
}
private _onDocumentSave(document: vscode.TextDocument) {
const documentContext = this._tryGetDocumentContext(document);
if (documentContext === undefined) {
return;
}
documentContext.foldingRange.clear();
documentContext.getPreview()?.updateWebview();
}
private _onDocumentUpdate(event: vscode.TextDocumentChangeEvent) {
const documentContext = this._tryGetDocumentContext(event.document);
if (documentContext?.foldingRange.update(event.contentChanges)) {
documentContext.documentSymbol.clear();
}
}
static onDocumentSave(document: vscode.TextDocument) {
const documentContext = ContextMapping.getDocumentContextIfExist(document);
documentContext?.getPreview()?.updateWebview();
}
static onDocumentClose(document: vscode.TextDocument) {
ContextMapping.instance.value.get(document)?.getPreview()?.close();
ContextMapping.instance.value.delete(document);
}
private static getDocumentContextIfExist(document: vscode.TextDocument) {
return document.languageId === 'texinfo' ? ContextMapping.getDocumentContext(document) : undefined;
}
private readonly value = new Map<vscode.TextDocument, DocumentContext>();
dispose() {
this.value.forEach(documentContext => documentContext.getPreview()?.close());
ContextMapping.singleton = undefined;
/**
* Create (if not yet created) and show preview for a Texinfo document.
*
* @param editor The editor where the document is being held.
*/
private async _showPreview(editor: vscode.TextEditor) {
const document = editor.document;
// Only show preview for saved files, as we're not gonna send
// document content to `makeinfo` via STDIN.
// Instead, the file will be loaded from disk.
if (document.isUntitled &&
!await prompt('Save this document to display preview.', 'Save')
) {
return;
}
if (document.isDirty && !await document.save()) {
return;
}
this.getDocumentContext(document).initPreview().show();
}
}

View File

@ -1,11 +1,26 @@
/**
* contexts/document.ts
*
* @author CismonX <admin@cismon.net>
* @license MIT
*
* Copyright (C) 2020,2021 CismonX <admin@cismon.net>
*
* This file is part of vscode-texinfo.
*
* vscode-texinfo 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.
*
* vscode-texinfo 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
* vscode-texinfo. If not, see <https://www.gnu.org/licenses/>.
*/
import * as vscode from 'vscode';
import GlobalContext from '../global_context';
import DocumentSymbolContext from './document_symbol';
import FoldingRangeContext from './folding_range';
import PreviewContext from './preview';
@ -13,25 +28,28 @@ import PreviewContext from './preview';
/**
* Holds all contexts for a Texinfo document.
*/
export default class DocumentContext {
readonly foldingRange = new FoldingRangeContext(this.document);
export default class DocumentContext
{
readonly foldingRange = new FoldingRangeContext(this);
readonly documentSymbol = new DocumentSymbolContext(this);
private preview?: PreviewContext;
initPreview() {
return this.preview ??= new PreviewContext(this);
return this._preview ??= new PreviewContext(this);
}
getPreview() {
return this.preview;
return this._preview;
}
closePreview() {
this.preview = undefined;
this._preview = undefined;
}
constructor(readonly document: vscode.TextDocument) {}
constructor(
readonly globalContext: GlobalContext,
readonly document: vscode.TextDocument,
) {}
private _preview?: PreviewContext;
}

View File

@ -1,8 +1,22 @@
/**
* contexts/document_symbol.ts
*
* @author CismonX <admin@cismon.net>
* @license MIT
*
* Copyright (C) 2020,2021 CismonX <admin@cismon.net>
*
* This file is part of vscode-texinfo.
*
* vscode-texinfo 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.
*
* vscode-texinfo 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
* vscode-texinfo. If not, see <https://www.gnu.org/licenses/>.
*/
import * as vscode from 'vscode';
@ -13,41 +27,52 @@ import { FoldingRange, Optional } from '../utils/types';
/**
* Context for symbols in a Texinfo document.
*/
export default class DocumentSymbolContext {
private document = this.documentContext.document;
private documentSymbols?: vscode.DocumentSymbol[];
get values() {
return this.documentSymbols ??= this.calculcateDocumentSymbols();
export default class DocumentSymbolContext
{
get documentSymbols() {
return this._documentSymbols ??= this._calculcateDocumentSymbols();
}
clear() {
this.documentSymbols = undefined;
this._documentSymbols = undefined;
}
constructor(private readonly documentContext: DocumentContext) {}
constructor(private readonly _documentContext: DocumentContext) {}
private _documentSymbols?: vscode.DocumentSymbol[];
private readonly _document = this._documentContext.document;
/**
* Calculate document symbols based on folding ranges.
*/
private calculcateDocumentSymbols() {
const ranges = Array<Optional<FoldingRange>>(this.document.lineCount);
this.documentContext.foldingRange.values.forEach(range => range.kind ?? (ranges[range.start] = range));
private _calculcateDocumentSymbols() {
const ranges = Array<Optional<FoldingRange>>(this._document.lineCount);
this._documentContext.foldingRange.foldingRanges
.filter(range => range.kind === undefined)
.forEach(range => ranges[range.start] = range);
return foldingRangeToSymbols(ranges, 0, ranges.length);
}
}
function foldingRangeToSymbols(ranges: readonly Optional<FoldingRange>[], start: number, end: number) {
function foldingRangeToSymbols(
ranges: readonly Optional<FoldingRange>[],
start: number,
end: number,
) {
const symbols = <vscode.DocumentSymbol[]>[];
for (let idx = start; idx < end; ++idx) {
const node = ranges[idx];
if (node === undefined) continue;
const range = lineNumToRange(idx, node.end);
const selectionRange = lineNumToRange(idx);
const symbol = new vscode.DocumentSymbol('@' + node.name, node.detail,
vscode.SymbolKind.String, range, selectionRange);
if (node === undefined) {
continue;
}
const symbol = new vscode.DocumentSymbol(
'@' + node.name,
node.detail,
vscode.SymbolKind.String,
lineNumToRange(idx, node.end), // full range
lineNumToRange(idx), // selection range
);
symbol.children = foldingRangeToSymbols(ranges, idx + 1, node.end);
symbols.push(symbol);
idx = node.end;

View File

@ -1,208 +1,283 @@
/**
* contexts/folding_range.ts
*
* @author CismonX <admin@cismon.net>
* @license MIT
*
* Copyright (C) 2020,2021 CismonX <admin@cismon.net>
*
* This file is part of vscode-texinfo.
*
* vscode-texinfo 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.
*
* vscode-texinfo 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
* vscode-texinfo. If not, see <https://www.gnu.org/licenses/>.
*/
import * as vscode from 'vscode';
import { lineNumToRange } from '../utils/misc';
import { FoldingRange, Range, NamedLine } from '../utils/types';
import DocumentContext from './document';
/**
* Stores information about folding ranges for a document.
*
* Actually, more than folding ranges (e.g. code lens) is handled within this context, so I believe
* we should use another name...
* Actually, more than folding ranges (e.g. code lens) is handled within
* this context, so perhaps we should use another name...
*/
export default class FoldingRangeContext {
/**
* Regex for matching subsection/section/chapter (-like) commands.
*/
private static readonly nodeFormat = RegExp('^@(?:(node)|(subsection|unnumberedsubsec|appendixsubsec|subheading)|' +
'(section|unnumberedsec|appendixsec|heading)|(chapter|unnumbered|appendix|majorheading|chapheading)) (.*)$');
export default class FoldingRangeContext
{
/**
* Get VSCode folding ranges from the context.
*/
get values() {
return this.foldingRanges ?? this.calculateFoldingRanges();
get foldingRanges() {
return this._foldingRanges ?? this._calculateFoldingRanges();
}
/**
* Get node values of document as VSCode code lenses.
*/
get nodeValues() {
this.foldingRanges ?? this.calculateFoldingRanges();
return this.nodes;
this._foldingRanges ?? this._calculateFoldingRanges();
return this._nodes;
}
private foldingRanges?: FoldingRange[];
private nodes = <vscode.CodeLens[]>[];
private commentRange?: Range;
private headerStart?: number;
private closingChapter?: number;
private closingSection?: number;
private closingSubsection?: number;
/**
* Update folding range context based on document change event.
*
* @param events Events describing the changes in the document.
*/
update(events: readonly vscode.TextDocumentContentChangeEvent[]) {
if (this.foldingRanges === undefined) return false;
this._contentMayChange = true;
if (this._foldingRanges === undefined) {
return false;
}
const eol = this._document.eol === vscode.EndOfLine.LF ? '\n' : '\r\n';
for (const event of events) {
const updatedLines = event.text.split(this.document.eol === vscode.EndOfLine.LF ? '\n' : '\r\n').length;
// Clear cached folding range when line count changes.
if (updatedLines !== 1 || event.range.start.line !== event.range.end.line) {
this.foldingRanges = undefined;
this.nodes = [];
if (event.text.split(eol).length !== 1 ||
event.range.start.line !== event.range.end.line
) {
this._foldingRanges = undefined;
this._nodes = [];
return true;
}
}
return false;
}
clear() {
if (this._contentMayChange) {
this._foldingRanges = undefined;
}
}
constructor(private readonly _documentContext: DocumentContext) {}
private readonly _document = this._documentContext.document;
/**
* Regex for matching subsection/section/chapter (-like) commands.
*/
private static readonly _nodeFormat = RegExp('^@(?:(node)|' +
'(subsection|unnumberedsubsec|appendixsubsec|subheading)|' +
'(section|unnumberedsec|appendixsec|heading)|' +
'(chapter|unnumbered|appendix|majorheading|chapheading)) (.*)$');
private _foldingRanges?: FoldingRange[];
private _nodes = <vscode.CodeLens[]>[];
private _commentRange?: Range;
private _headerStart?: number;
private _closingChapter?: number;
private _closingSection?: number;
private _closingSubsection?: number;
private _contentMayChange = true;
private _addRange(start: number, end: number, extraArgs: {
name?: string,
detail?: string,
kind?: vscode.FoldingRangeKind
}) {
const items = {
name: extraArgs.name ?? '',
detail: extraArgs.detail ?? '',
start,
end,
kind: extraArgs.kind,
};
(this._foldingRanges ??= []).push(items);
}
/**
* Calculate and update folding ranges for the document.
*
* @param start Starting line number.
* @param end Ending line number.
*/
private calculateFoldingRanges() {
this.foldingRanges = [];
this.clearTemporaries();
private _calculateFoldingRanges() {
this._contentMayChange = false;
this._foldingRanges = [];
this._clearTemporaries();
let closingBlocks = <NamedLine[]>[];
let lastLine = this.document.lineCount - 1;
let lastLine = this._document.lineCount - 1;
let verbatim = false;
for (let idx = lastLine; idx >= 0; --idx) {
const line = this.document.lineAt(idx).text;
if (!line.startsWith('@')) continue;
const line = this._document.lineAt(idx).text.trimLeft();
if (!line.startsWith('@')) {
continue;
}
if (!verbatim) {
if (line === '@bye') {
lastLine = idx;
// Abort anything after `@bye`.
this.foldingRanges = [];
this._foldingRanges = [];
closingBlocks = [];
this.clearTemporaries();
this._clearTemporaries();
continue;
}
if (this._processComment(line, idx)) {
continue;
}
if (this.processComment(line, idx)) continue;
}
// Process block.
if (line.startsWith('@end ')) {
if (verbatim) continue;
if (verbatim) {
continue;
}
const name = line.substring(5).trimRight();
name === 'verbatim' && (verbatim = true);
if (name === 'verbatim') {
verbatim = true;
}
closingBlocks.push({ name: name, line: idx });
continue;
}
if (!verbatim && this.processNode(line, idx, lastLine)) continue;
if (!verbatim && this._processNode(line, idx, lastLine)) {
continue;
}
const closingBlock = closingBlocks.pop();
if (closingBlock === undefined) continue;
if (line.substring(1, closingBlock.name.length + 2).trim() === closingBlock.name) {
this.addRange(idx, closingBlock.line, { name: closingBlock.name });
// If `verbatim == true` goes here, this line must be the `@verbatim` line.
if (closingBlock === undefined) {
continue;
}
const name = closingBlock.name;
if (line.substring(1, name.length + 2).trim() === name) {
this._addRange(idx, closingBlock.line, { name: name });
// If `verbatim == true` goes here,
// this line must be the `@verbatim` line.
verbatim = false;
} else {
closingBlocks.push(closingBlock);
}
}
if (this.commentRange !== undefined) {
this.addRange(this.commentRange.start, this.commentRange.end, { kind: vscode.FoldingRangeKind.Comment });
if (this._commentRange !== undefined) {
this._addRange(
this._commentRange.start,
this._commentRange.end,
{ kind: vscode.FoldingRangeKind.Comment },
);
}
return this.foldingRanges;
return this._foldingRanges;
}
private processComment(lineText: string, lineNum: number) {
if (!lineText.startsWith('@c')) return false;
if (!lineText.startsWith(' ', 2) && !lineText.startsWith('omment ', 2)) return false;
private _clearTemporaries() {
this._commentRange = undefined;
this._headerStart = undefined;
this._nodes = [];
this._closingSubsection = this._closingSection = this._closingChapter
= undefined;
}
private _getLastTextLine(lineNum: number, limit = 3) {
for (let idx = lineNum; idx > lineNum - limit; --idx) {
const line = this._document.lineAt(idx).text;
if (line.startsWith('@node ')) {
return idx - 1;
}
if (line === '') {
return idx;
}
}
return lineNum;
}
private _processComment(lineText: string, lineNum: number) {
if (!lineText.startsWith('@c')) {
return false;
}
if (lineText.charAt(2) != ' ' && !lineText.startsWith('omment ', 2)) {
return false;
}
// Check for opening/closing header.
if (lineText.startsWith('%**', lineText[2] === ' ' ? 3 : 9)) {
if (this.headerStart === undefined) {
this.headerStart = lineNum;
if (this._headerStart === undefined) {
this._headerStart = lineNum;
} else {
this.addRange(lineNum, this.headerStart, { kind: vscode.FoldingRangeKind.Region });
this.headerStart = undefined;
this._addRange(lineNum, this._headerStart,
{ kind: vscode.FoldingRangeKind.Region });
this._headerStart = undefined;
}
return true;
}
if (this.commentRange === undefined) {
this.commentRange = { start: lineNum, end: lineNum };
} else if (this.commentRange.start - 1 === lineNum) {
this.commentRange.start = lineNum;
if (this._commentRange === undefined) {
this._commentRange = { start: lineNum, end: lineNum };
} else if (this._commentRange.start - 1 === lineNum) {
this._commentRange.start = lineNum;
} else {
this.addRange(this.commentRange.start, this.commentRange.end, { kind: vscode.FoldingRangeKind.Comment });
this.commentRange = undefined;
this._addRange(this._commentRange.start, this._commentRange.end,
{ kind: vscode.FoldingRangeKind.Comment });
this._commentRange = undefined;
}
return true;
}
constructor(private readonly document: vscode.TextDocument) {}
private processNode(lineText: string, lineNum: number, lastLineNum: number) {
const result = lineText.match(FoldingRangeContext.nodeFormat);
if (result === null) return false;
private _processNode(
lineText: string,
lineNum: number,
lastLineNum: number,
) {
const result = lineText.match(FoldingRangeContext._nodeFormat);
if (result === null) {
return false;
}
// Node identifier.
if (result[1] !== undefined) {
this.nodes.push(new vscode.CodeLens(lineNumToRange(lineNum), {
title: '$(search-goto-file) Goto node in preview',
this._nodes.push(new vscode.CodeLens(lineNumToRange(lineNum), {
title: '$(go-to-file) Goto node in preview',
command: 'texinfo.preview.goto',
arguments: [this.document, result[5]],
arguments: [this._document, result[5]],
}));
return true;
}
// Subsection level node.
if (result[2] !== undefined) {
this.addRange(lineNum, this.closingSubsection ?? lastLineNum, { name: result[2], detail: result[5] });
this.closingSubsection = this.getLastTextLine(lineNum - 1);
this._addRange(lineNum, this._closingSubsection ?? lastLineNum,
{ name: result[2], detail: result[5] });
this._closingSubsection = this._getLastTextLine(lineNum - 1);
return true;
}
// Section level node.
if (result[3] !== undefined) {
this.addRange(lineNum, this.closingSection ?? lastLineNum, { name: result[3], detail: result[5] });
this.closingSubsection = this.closingSection = this.getLastTextLine(lineNum - 1);
this._addRange(lineNum, this._closingSection ?? lastLineNum,
{ name: result[3], detail: result[5] });
this._closingSubsection = this._closingSection
= this._getLastTextLine(lineNum - 1);
return true;
}
// Chapter level node.
if (result[4] !== undefined) {
this.addRange(lineNum, this.closingChapter ?? lastLineNum, { name: result[4], detail: result[5] });
this.closingSubsection = this.closingSection = this.closingChapter = this.getLastTextLine(lineNum - 1);
this._addRange(lineNum, this._closingChapter ?? lastLineNum,
{ name: result[4], detail: result[5] });
this._closingSubsection = this._closingSection
= this._closingChapter = this._getLastTextLine(lineNum - 1);
return true;
}
return false;
}
private getLastTextLine(lineNum: number, limit = 3) {
for (let idx = lineNum; idx > lineNum - limit; --idx) {
const line = this.document.lineAt(idx).text;
if (line.startsWith('@node ')) return idx - 1;
if (line === '') return idx;
}
return lineNum;
}
private addRange(start: number, end: number, extraArgs: {
name?: string,
detail?: string,
kind?: vscode.FoldingRangeKind
}) {
(this.foldingRanges ??= [])
.push({ name: extraArgs.name ?? '', detail: extraArgs.detail ?? '', start, end, kind: extraArgs.kind });
}
private clearTemporaries() {
this.commentRange = undefined;
this.headerStart = undefined;
this.nodes = [];
this.closingSubsection = this.closingSection = this.closingChapter = undefined;
}
}

View File

@ -1,125 +1,135 @@
/**
* contexts/preview.ts
*
* @author CismonX <admin@cismon.net>
* @license MIT
*
* Copyright (C) 2020,2021 CismonX <admin@cismon.net>
*
* This file is part of vscode-texinfo.
*
* vscode-texinfo 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.
*
* vscode-texinfo 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
* vscode-texinfo. If not, see <https://www.gnu.org/licenses/>.
*/
import * as path from 'path';
import * as vscode from 'vscode';
import DocumentContext from './document';
import ContextMapping from '../context_mapping';
import Diagnosis from '../diagnosis';
import Logger from '../logger';
import Options from '../options';
import Converter from '../utils/converter';
import { getNodeHtmlRef, prompt } from '../utils/misc';
import { Operator, Optional } from '../utils/types';
/**
* Stores information of a Texinfo document preview.
*/
export default class PreviewContext {
export default class PreviewContext
{
close() {
this._disposables.forEach(event => event.dispose());
this._panel.dispose();
this._documentContext.closePreview();
// Only show diagnostic information when the preview is active.
this._diagnosis.delete(this._document);
}
/**
* Create (if not yet created) and show preview for a Texinfo document.
*
* @param editor The editor where the document is being held.
*/
static async showPreview(editor: vscode.TextEditor) {
const document = editor.document;
// Only show preview for saved files, as we're not gonna send document content to `makeinfo` via STDIN.
// Instead, the file will be loaded from disk.
if (document.isUntitled) {
if (!await prompt('Save this document to display preview.', 'Save')) return;
if (!await document.save()) return;
goto(nodeName: string) {
const message = { command: 'goto', value: getNodeHtmlRef(nodeName) };
this._webview.postMessage(message);
}
show() {
this._panel.reveal();
}
async updateWebview() {
if (this._updating) {
this._pendingUpdate = true;
return;
}
ContextMapping.getDocumentContext(document).initPreview().panel.reveal();
this._updating = true;
this._pendingUpdate = false;
// Inform the user that the preview is updating, when `makeinfo`
// takes too long.
setTimeout(() => this._updating && this._updateTitle(), 500);
const converter = new Converter(
this._document.fileName,
this._globalContext.path + '/ext/html-preview.pm',
this._globalContext.options,
this._logger,
);
const { data, error } = await converter.toHTML(
path => this._webview.asWebviewUri(path),
this._script,
);
if (error) {
this._logger.log(error);
this._diagnosis.update(this._document, error);
} else {
this._diagnosis.delete(this._document);
}
if (data === undefined) {
prompt(`Failed to show preview for ${this._document.fileName}.`,
'Show log', true)
.then(result => result && this._logger.show());
} else {
this._webview.html = data;
}
this._updating = false;
this._updateTitle();
this._pendingUpdate && this.updateWebview();
}
/**
* Jump to the corresponding section of document preview by node name.
*
* @param document
* @param nodeName
*/
static gotoPreview(document: vscode.TextDocument, nodeName: string) {
ContextMapping.getDocumentContext(document).initPreview().panel.webview
.postMessage({ command: 'goto', value: getNodeHtmlRef(nodeName) });
constructor(private readonly _documentContext: DocumentContext) {
const options = {
enableFindWidget: true,
retainContextWhenHidden: true,
enableScripts: true,
};
this._panel = vscode.window.createWebviewPanel(
'texinfo.preview', '',
vscode.ViewColumn.Beside,
options,
);
this._webview = this._panel.webview;
this._disposables.push(this._panel.onDidDispose(() => this.close()));
this._updateTitle();
this.updateWebview();
}
private readonly document = this.documentContext.document;
private readonly _document = this._documentContext.document;
private readonly _globalContext = this._documentContext.globalContext;
private readonly _diagnosis = this._globalContext.diagnosis;
private readonly _logger = this._globalContext.logger;
private readonly panel: vscode.WebviewPanel;
private readonly disposables = <vscode.Disposable[]>[];
private readonly _disposables = <vscode.Disposable[]>[];
/**
* Whether the preview is updating.
*/
private updating = false;
private readonly _panel: vscode.WebviewPanel;
private readonly _webview: vscode.Webview;
/**
* Whether a preview update request is pending.
*/
private pendingUpdate = false;
private _pendingUpdate = false;
close() {
this.disposables.forEach(event => event.dispose());
this.panel.dispose();
this.documentContext.closePreview();
// Only show diagnostic information when the preview is active.
Diagnosis.delete(this.document);
}
/**
* Whether the preview is updating.
*/
private _updating = false;
async updateWebview() {
if (this.updating) {
this.pendingUpdate = true;
return;
/**
* Generate script used for jumping to the corresponding location of
* preview with code lens.
*/
private get _script() {
if (!this._globalContext.options.enableCodeLens) {
return undefined;
}
this.updating = true;
this.pendingUpdate = false;
// Inform the user that the preview is updating if `makeinfo` takes too long.
setTimeout(() => this.updating && this.updateTitle(), 500);
const { data, error } = await new Converter(this.document.fileName, this.imageTransformer, this.script)
.convert();
if (error) {
Logger.log(error);
Diagnosis.update(this.document, error);
} else {
Diagnosis.delete(this.document);
}
if (data === undefined) {
prompt(`Failed to show preview for ${this.document.fileName}.`, 'Show log', true)
.then(result => result && Logger.show());
} else {
this.panel.webview.html = data;
}
this.updating = false;
this.updateTitle();
this.pendingUpdate && this.updateWebview();
}
constructor(private readonly documentContext: DocumentContext) {
this.panel = vscode.window.createWebviewPanel('texinfo.preview', '', vscode.ViewColumn.Beside,
{ enableFindWidget: true, retainContextWhenHidden: true, enableScripts: true });
this.disposables.push(this.panel.onDidDispose(() => this.close()));
this.updateTitle();
this.updateWebview();
}
private get imageTransformer(): Optional<Operator<string>> {
if (!Options.displayImage) return undefined;
const pathName = path.dirname(this.document.fileName);
return src => {
const srcUri = vscode.Uri.file(pathName + '/' + src);
// To display images in webviews, image URIs in HTML should be converted to VSCode-recognizable ones.
return this.panel.webview.asWebviewUri(srcUri).toString();
};
}
private get script() {
if (!Options.enableCodeLens) return undefined;
return "window.addEventListener('message', event => {" +
"const message = event.data;" +
"switch (message.command) {" +
@ -132,9 +142,9 @@ export default class PreviewContext {
"})";
}
private updateTitle() {
const updating = this.updating ? '(Updating) ' : '';
const fileName = path.basename(this.document.fileName);
this.panel.title = `${updating}Preview ${fileName}`;
private _updateTitle() {
const updating = this._updating ? '(Updating) ' : '';
const fileName = path.basename(this._document.fileName);
this._panel.title = `${updating}Preview ${fileName}`;
}
}

View File

@ -1,23 +1,41 @@
/**
* diagnosis.ts
*
* @author CismonX <admin@cismon.net>
* @license MIT
*
* Copyright (C) 2020,2021 CismonX <admin@cismon.net>
*
* This file is part of vscode-texinfo.
*
* vscode-texinfo 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.
*
* vscode-texinfo 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
* vscode-texinfo. If not, see <https://www.gnu.org/licenses/>.
*/
import * as path from 'path';
import * as vscode from 'vscode';
import { lineNumToRange } from './utils/misc';
import { escapeStringForRegExp, lineNumToRange } from './utils/misc';
import { isDefined } from './utils/types';
/**
* Manage diagnostic information of Texinfo documents.
*/
export default class Diagnosis implements vscode.Disposable {
private static singleton?: Diagnosis;
static get instance() {
return Diagnosis.singleton ??= new Diagnosis();
export default class Diagnosis implements vscode.Disposable
{
/**
* Remove a document's diagnostic entry from the collection.
*
* @param document
*/
delete(document: vscode.TextDocument) {
this._diagnostics.delete(document.uri);
}
/**
@ -26,30 +44,47 @@ export default class Diagnosis implements vscode.Disposable {
* @param document
* @param logText
*/
static update(document: vscode.TextDocument, logText: string) {
const fileName = document.uri.path;
const diagnostics = logText.split('\n').filter(line => line.startsWith(fileName))
.map(line => logLineToDiagnostic(line.substring(fileName.length + 1))).filter(isDefined);
Diagnosis.instance.diagnostics.set(document.uri, diagnostics);
update(document: vscode.TextDocument, logText: string) {
const fileName = path.basename(document.uri.path);
const regex = new RegExp(`${escapeStringForRegExp(fileName)}:\\d+:`);
const diagnostics = logText.split('\n')
.map(line => line.length > 0 ? line.match(regex) : null)
.map(result => {
const index = result?.index;
const line = result?.input;
if (index === undefined || line === undefined) {
return undefined;
}
const logText = line.substring(index + fileName.length + 1);
return logToDiagnostic(logText);
})
.filter(isDefined);
this._diagnostics.set(document.uri, diagnostics);
}
static delete(document: vscode.TextDocument) {
Diagnosis.instance.diagnostics.delete(document.uri);
}
private readonly diagnostics = vscode.languages.createDiagnosticCollection('texinfo');
dispose() {
this.diagnostics.dispose();
Diagnosis.singleton = undefined;
this._diagnostics.dispose();
}
private readonly _diagnostics
= vscode.languages.createDiagnosticCollection('texinfo');
}
function logLineToDiagnostic(lineText: string) {
const lineNum = Number.parseInt(lineText) - 1;
// Ignore error that does not correspond a line.
if (Number.isNaN(lineNum)) return undefined;
/**
* Convert a `makeinfo` error log line to a VSCode `Diagnostic` object.
*
* @param lineText
* @returns
*/
function logToDiagnostic(lineText: string) {
const lineNum = parseInt(lineText) - 1;
// Ignore error that does not correspond to a line in document.
if (isNaN(lineNum)) {
return undefined;
}
const message = lineText.substring(lineNum.toString().length + 2);
const severity = message.startsWith('warning:') ? vscode.DiagnosticSeverity.Warning : undefined;
const severity = message.startsWith('warning:')
? vscode.DiagnosticSeverity.Warning
: undefined;
return new vscode.Diagnostic(lineNumToRange(lineNum), message, severity);
}

View File

@ -1,33 +1,27 @@
/**
* extension.ts
*
* @author CismonX <admin@cismon.net>
* @license MIT
*
* Copyright (C) 2020,2021 CismonX <admin@cismon.net>
*
* This file is part of vscode-texinfo.
*
* vscode-texinfo 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.
*
* vscode-texinfo 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
* vscode-texinfo. If not, see <https://www.gnu.org/licenses/>.
*/
import * as vscode from 'vscode';
import ContextMapping from './context_mapping';
import Diagnosis from './diagnosis';
import Logger from './logger';
import Options from './options';
import PreviewContext from './contexts/preview';
import CodeLensProvider from './providers/code_lens';
import CompletionItemProvider from './providers/completion_item';
import DocumentSymbolProvider from './providers/document_symbol';
import FoldingRangeProvider from './providers/folding_range';
import GlobalContext from './global_context';
export function activate(context: vscode.ExtensionContext) {
context.subscriptions.push(
ContextMapping.instance, Diagnosis.instance, Logger.instance, Options.instance,
vscode.workspace.onDidChangeTextDocument(ContextMapping.onDocumentUpdate),
vscode.workspace.onDidSaveTextDocument(ContextMapping.onDocumentSave),
vscode.workspace.onDidCloseTextDocument(ContextMapping.onDocumentClose),
vscode.workspace.onDidChangeConfiguration(Options.clear),
vscode.commands.registerTextEditorCommand('texinfo.preview.show', PreviewContext.showPreview),
vscode.commands.registerCommand('texinfo.preview.goto', PreviewContext.gotoPreview),
vscode.languages.registerCodeLensProvider('texinfo', new CodeLensProvider()),
vscode.languages.registerCompletionItemProvider('texinfo', new CompletionItemProvider(), '@'),
vscode.languages.registerDocumentSymbolProvider('texinfo', new DocumentSymbolProvider()),
vscode.languages.registerFoldingRangeProvider('texinfo', new FoldingRangeProvider()),
);
new GlobalContext(context);
}

88
src/global_context.ts Normal file
View File

@ -0,0 +1,88 @@
/**
* global_context.ts
*
* Copyright (C) 2021 CismonX <admin@cismon.net>
*
* This file is part of vscode-texinfo.
*
* vscode-texinfo 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.
*
* vscode-texinfo 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
* vscode-texinfo. If not, see <https://www.gnu.org/licenses/>.
*/
import * as vscode from 'vscode';
import ContextMapping from './context_mapping';
import Diagnosis from './diagnosis';
import Indicator from './indicator';
import Logger from './logger';
import Options from './options';
import CodeLensProvider from './providers/code_lens';
import CompletionItemProvider from './providers/completion_item';
import DocumentSymbolProvider from './providers/document_symbol';
import FoldingRangeProvider from './providers/folding_range';
/**
* Manage extension-level global-scope contexts.
*/
export default class GlobalContext
{
readonly contextMapping = new ContextMapping(this);
readonly diagnosis = new Diagnosis;
readonly indicator = new Indicator(this);
readonly logger = new Logger;
readonly path = this._context.extensionPath;
/**
* Note: `Options`' no singleton.
*
* Do not wire directly, always use `globalContext.options` instead.
*/
get options() {
return this._options ??= new Options;
}
subscribe(...items: vscode.Disposable[]) {
this._context.subscriptions.push(...items);
}
constructor(private readonly _context: vscode.ExtensionContext) {
this.subscribe(
this.contextMapping,
this.diagnosis,
this.indicator,
this.logger,
vscode.languages.registerCodeLensProvider(
'texinfo',
new CodeLensProvider(this),
),
vscode.languages.registerCompletionItemProvider(
'texinfo',
new CompletionItemProvider(this),
'@',
),
vscode.languages.registerDocumentSymbolProvider(
'texinfo',
new DocumentSymbolProvider(this),
),
vscode.languages.registerFoldingRangeProvider(
'texinfo',
new FoldingRangeProvider(this),
),
vscode.workspace.onDidChangeConfiguration(
() => this._options = undefined,
),
);
}
private _options?: Options;
}

110
src/indicator.ts Normal file
View File

@ -0,0 +1,110 @@
/**
* indicator.ts
*
* Copyright (C) 2020,2021 CismonX <admin@cismon.net>
*
* This file is part of vscode-texinfo.
*
* vscode-texinfo 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.
*
* vscode-texinfo 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
* vscode-texinfo. If not, see <https://www.gnu.org/licenses/>.
*/
import * as vscode from 'vscode';
import GlobalContext from './global_context';
import { exec } from './utils/misc';
/**
* Shows whether GNU Texinfo is properly installed and configured.
*/
export default class Indicator implements vscode.Disposable
{
get canDisplayPreview() {
return this._canDisplayPreview;
}
dispose() {
this._statusBarItem.dispose();
}
constructor(private readonly _globalContext: GlobalContext) {
_globalContext.subscribe(
vscode.commands.registerCommand(
'texinfo.indicator.click',
this._click.bind(this),
),
vscode.window.onDidChangeActiveTextEditor(
this._refresh.bind(this),
),
);
this._updateStatus()
.then(() => this._refresh(vscode.window.activeTextEditor));
}
private _canDisplayPreview = false;
private readonly _statusBarItem = vscode.window.createStatusBarItem(
vscode.StatusBarAlignment.Right, 100);
/**
* Calls when the status bar item is clicked.
*/
private async _click() {
await this._updateStatus();
this._refresh(vscode.window.activeTextEditor);
}
/**
* Refresh the show/hide status of the indicator based on given editor.
*
* @param editor
*/
private _refresh(editor?: vscode.TextEditor) {
if (editor?.document.languageId === 'texinfo') {
this._statusBarItem.show();
} else {
this._statusBarItem.hide();
}
}
/**
* Update the installation status of GNU Texinfo,
* by checking `makeinfo --version`.
*/
private async _updateStatus() {
const options = this._globalContext.options;
const output
= await exec(options.makeinfo, ['--version'], options.maxSize);
const result = output.data?.match(/\(GNU texinfo\) (.*)\n/);
let tooltip = '', icon: string, version = '';
if (result && result[1]) {
version = result[1];
if (!isNaN(+version) && +version < 6.8) {
icon = '$(warning)';
tooltip = `GNU Texinfo (${options.makeinfo}) ` +
`is outdated (${version} < 6.8).`;
} else {
// Unrecognizable version. Assume it is okay.
icon = '$(check)';
}
this._canDisplayPreview = true;
} else {
icon = '$(close)';
tooltip = `GNU Texinfo (${options.makeinfo}) ` +
`is not correctly installed or configured.`;
this._canDisplayPreview = false;
}
this._statusBarItem.command = 'texinfo.indicator.click';
this._statusBarItem.text = `${icon} GNU Texinfo ${version}`;
this._statusBarItem.tooltip = tooltip;
}
}

View File

@ -1,8 +1,22 @@
/**
* logger.ts
*
* @author CismonX <admin@cismon.net>
* @license MIT
*
* Copyright (C) 2020,2021 CismonX <admin@cismon.net>
*
* This file is part of vscode-texinfo.
*
* vscode-texinfo 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.
*
* vscode-texinfo 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
* vscode-texinfo. If not, see <https://www.gnu.org/licenses/>.
*/
import * as vscode from 'vscode';
@ -10,31 +24,24 @@ import * as vscode from 'vscode';
/**
* Logger which prints message to VSCode output channel.
*/
export default class Logger implements vscode.Disposable {
private static singleton?: Logger;
static get instance() {
return Logger.singleton ??= new Logger();
export default class Logger implements vscode.Disposable
{
log(message: string) {
const dateTime = new Date().toLocaleString(
undefined,
{ hour12: false }
);
this._outputChannel.appendLine(`[ ${dateTime} ]\n${message}`);
}
static log(message: string) {
const dateTime = new Date().toLocaleString(undefined, { hour12: false });
Logger.instance.outputChannel.appendLine(`[ ${dateTime} ]\n${message}`);
show() {
this._outputChannel.show(true);
}
static show() {
Logger.instance.outputChannel.show(true);
}
private outputChannel: vscode.OutputChannel;
dispose() {
Logger.instance.outputChannel.dispose();
Logger.singleton = undefined;
this._outputChannel.dispose();
}
private constructor() {
this.outputChannel = vscode.window.createOutputChannel('Texinfo');
}
private readonly _outputChannel
= vscode.window.createOutputChannel('Texinfo');
}

View File

@ -1,8 +1,22 @@
/**
* options.ts
*
* @author CismonX <admin@cismon.net>
* @license MIT
*
* Copyright (C) 2020,2021 CismonX <admin@cismon.net>
*
* This file is part of vscode-texinfo.
*
* vscode-texinfo 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.
*
* vscode-texinfo 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
* vscode-texinfo. If not, see <https://www.gnu.org/licenses/>.
*/
import * as vscode from 'vscode';
@ -10,83 +24,78 @@ import * as vscode from 'vscode';
/**
* Fetch extension option values.
*
* See `contributes.configuration` of package.json for details.
* See the `contributes.configuration` entry in package.json for details.
*/
export default class Options implements vscode.Disposable {
private static singleton?: Options;
static get instance() {
return Options.singleton ??= new Options('texinfo');
export default class Options
{
get enableSnippets() {
return this._getBoolean('completion.enableSnippets');
}
static get makeinfo() {
return Options.instance.getString('makeinfo');
get hideSnippetCommands() {
return this._getBoolean('completion.hideSnippetCommands');
}
static get enableCodeLens() {
return Options.instance.getBoolean('enableCodeLens');
get noWarnings() {
return this._getBoolean('diagnosis.noWarnings');
}
static get enableSnippets() {
return Options.instance.getBoolean('completion.enableSnippets');
get enableCodeLens() {
return this._getBoolean('enableCodeLens');
}
static get hideSnippetCommands() {
return Options.instance.getBoolean('completion.hideSnippetCommands');
get makeinfo() {
return this._getString('makeinfo');
}
static get noHeaders() {
return Options.instance.getBoolean('preview.noHeaders');
get customCSS() {
return this._getString('preview.customCSS');
}
static get maxSize() {
return Options.instance.getNumber('preview.maxSize') * 1024 * 1024;
get errorLimit() {
return this._getNumber('preview.errorLimit');
}
static get errorLimit() {
return Options.instance.getNumber('preview.errorLimit');
get includePaths() {
return this._getArray('preview.includePaths');
}
static get force() {
return Options.instance.getBoolean('preview.force');
get maxSize() {
return this._getNumber('preview.maxSize') * 1024 * 1024;
}
static get noValidation() {
return Options.instance.getBoolean('preview.noValidation');
get noHeaders() {
return this._getBoolean('preview.noHeaders');
}
static get noWarnings() {
return Options.instance.getBoolean('preview.noWarnings');
get noNumberSections() {
return this._getBoolean('preview.noNumberSections');
}
static get displayImage() {
return Options.instance.getBoolean('preview.displayImage');
get noValidation() {
return this._getBoolean('preview.noValidation');
}
static clear() {
Options.singleton = undefined;
get variables() {
return this._getArray('preview.variables');
}
private readonly configuration: vscode.WorkspaceConfiguration;
private readonly _configuration
= vscode.workspace.getConfiguration('texinfo');
private constructor(section: string) {
this.configuration = vscode.workspace.getConfiguration(section);
private _getArray(section: string): readonly string[] {
return this._configuration.get(section, []);
}
private getString(section: string) {
return this.configuration.get(section, '');
private _getBoolean(section: string) {
return this._configuration.get(section, false);
}
private getBoolean(section: string) {
return this.configuration.get(section, false);
private _getNumber(section: string) {
return this._configuration.get(section, 0);
}
private getNumber(section: string) {
return this.configuration.get(section, 0);
}
dispose() {
Options.singleton = undefined;
private _getString(section: string) {
return this._configuration.get(section, '');
}
}

View File

@ -1,21 +1,42 @@
/**
* providers/code_lens.ts
*
* @author CismonX <admin@cismon.net>
* @license MIT
*
* Copyright (C) 2020,2021 CismonX <admin@cismon.net>
*
* This file is part of vscode-texinfo.
*
* vscode-texinfo 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.
*
* vscode-texinfo 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
* vscode-texinfo. If not, see <https://www.gnu.org/licenses/>.
*/
import * as vscode from 'vscode';
import ContextMapping from '../context_mapping';
import Options from '../options';
import GlobalContext from '../global_context';
/**
* Provide code lenses for Texinfo document.
*/
export default class CodeLensProvider implements vscode.CodeLensProvider {
export default class CodeLensProvider implements vscode.CodeLensProvider
{
provideCodeLenses(document: vscode.TextDocument) {
if (!Options.enableCodeLens) return undefined;
return ContextMapping.getDocumentContext(document).foldingRange.nodeValues;
if (!this._globalContext.options.enableCodeLens) {
return undefined;
}
if (!this._globalContext.indicator.canDisplayPreview) {
return undefined;
}
return this._globalContext.contextMapping
.getDocumentContext(document).foldingRange.nodeValues;
}
constructor(private readonly _globalContext: GlobalContext) {}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,19 +1,37 @@
/**
* providers/document_symbol.ts
*
* @author CismonX <admin@cismon.net>
* @license MIT
*
* Copyright (C) 2020,2021 CismonX <admin@cismon.net>
*
* This file is part of vscode-texinfo.
*
* vscode-texinfo 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.
*
* vscode-texinfo 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
* vscode-texinfo. If not, see <https://www.gnu.org/licenses/>.
*/
import * as vscode from 'vscode';
import ContextMapping from '../context_mapping';
import GlobalContext from '../global_context';
/**
* Provide document symbol information for Texinfo documents.
*/
export default class DocumentSymbolProvider implements vscode.DocumentSymbolProvider {
export default class DocumentSymbolProvider
implements vscode.DocumentSymbolProvider
{
provideDocumentSymbols(document: vscode.TextDocument) {
return ContextMapping.getDocumentContext(document).documentSymbol.values;
return this._globalContext.contextMapping
.getDocumentContext(document).documentSymbol.documentSymbols;
}
constructor(private readonly _globalContext: GlobalContext) {}
}

View File

@ -1,19 +1,37 @@
/**
* providers/folding_range.ts
*
* @author CismonX <admin@cismon.net>
* @license MIT
*
* Copyright (C) 2020,2021 CismonX <admin@cismon.net>
*
* This file is part of vscode-texinfo.
*
* vscode-texinfo 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.
*
* vscode-texinfo 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
* vscode-texinfo. If not, see <https://www.gnu.org/licenses/>.
*/
import * as vscode from 'vscode';
import ContextMapping from '../context_mapping';
import GlobalContext from '../global_context';
/**
* Provide folding range info for Texinfo documents.
*/
export default class FoldingRangeProvider implements vscode.FoldingRangeProvider {
export default class FoldingRangeProvider
implements vscode.FoldingRangeProvider
{
provideFoldingRanges(document: vscode.TextDocument) {
return ContextMapping.getDocumentContext(document).foldingRange.values;
return this._globalContext.contextMapping
.getDocumentContext(document).foldingRange.foldingRanges;
}
constructor(private readonly _globalContext: GlobalContext) {}
}

View File

@ -1,46 +1,100 @@
/**
* converter.ts
*
* @author CismonX <admin@cismon.net>
* @license MIT
* utils/converter.ts
*
* Copyright (C) 2020,2021 CismonX <admin@cismon.net>
*
* This file is part of vscode-texinfo.
*
* vscode-texinfo 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.
*
* vscode-texinfo 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
* vscode-texinfo. If not, see <https://www.gnu.org/licenses/>.
*/
import * as path from 'path';
import * as vscode from 'vscode';
import Logger from '../logger';
import Options from '../options';
import DOM from './dom';
import { exec } from './misc';
import { exec, normalizePath } from './misc';
import { Operator } from './types';
/**
* Texinfo to HTML converter.
* Converter which converts file from Texinfo to other formats.
*/
export default class Converter {
/**
* The options to be passed to the `makeinfo` command.
*/
private readonly options = ['-o', '-', '--no-split', '--html'];
export default class Converter
{
async toHTML(imgTransformer: Operator<vscode.Uri>, insertScript?: string) {
const pathUri = vscode.Uri.file(path.dirname(this._pathName) + '/');
const newPath = normalizePath(imgTransformer(pathUri).toString());
const options = ['-o-', '--no-split', '--html',
`--error-limit=${this._options.errorLimit}`,
`--init-file=${this._initFile}`,
'-D', `__vscode_texinfo_image_uri_base ${newPath}`,
];
this._options.noHeaders && options.push('--no-headers');
this._options.noNumberSections && options.push('--no-number-sections');
this._options.noValidation && options.push('--no-validate');
this._options.noWarnings && options.push('--no-warn');
if (insertScript !== undefined) {
options.push('-c', `EXTRA_HEAD <script>${insertScript}</script>`);
}
this._addIncludePaths(this._options.includePaths, options);
this._defineVariables(this._options.variables, options);
this._includeCustomCSS(this._options.customCSS, options);
return await exec(
this._options.makeinfo,
options.concat(normalizePath(this._pathName)),
this._options.maxSize,
);
}
constructor(
private readonly path: string,
private readonly imgTransformer?: Operator<string>,
private readonly insertScript?: string,
) {
Options.noHeaders && this.options.push('--no-headers');
Options.force && this.options.push('--force');
Options.noValidation && this.options.push('--no-validate');
Options.noWarnings && this.options.push('--no-warn');
this.options.push(`--error-limit=${Options.errorLimit}`);
private readonly _pathName: string,
private readonly _initFile: string,
private readonly _options: Options,
private readonly _logger: Logger,
) {}
private _addIncludePaths(paths: readonly string[], options: string[]) {
if (paths.length === 0) {
return;
}
const separator = process.platform === 'win32' ? ';' : ':';
options.push('-I', paths.join(separator));
}
async convert() {
const result = await exec(Options.makeinfo, this.options.concat(this.path), Options.maxSize);
if (result.data !== undefined) {
// No worry about performance here, as the DOM is lazily initialized.
const dom = new DOM(result.data);
this.imgTransformer && dom.transformImageUri(this.imgTransformer);
this.insertScript && dom.insertScript(this.insertScript);
result.data = dom.outerHTML;
private _defineVariables(variables: readonly string[], options: string[]) {
variables.forEach(varName => options.push('-D', varName));
}
private _includeCustomCSS(cssFileURI: string, options: string[]) {
if (!cssFileURI) {
return;
}
try {
const uri = vscode.Uri.parse(cssFileURI, true);
switch (uri.scheme) {
case 'file':
options.push(`--css-include=${normalizePath(uri.fsPath)}`);
break;
case 'http':
case 'https':
options.push(`--css-ref=${uri.toString()}`);
break;
default:
throw URIError;
}
} catch (e) {
this._logger
.log(`Cannot load custom CSS. Invalid URI: '${cssFileURI}'`);
}
return result;
}
}

View File

@ -1,53 +0,0 @@
/**
* utils/dom.ts
*
* @author CismonX <admin@cismon.net>
* @license MIT
*/
import * as htmlparser from 'node-html-parser';
import { Operator } from './types';
/**
* DOM manipulation utilities.
*/
export default class DOM {
private dom?: htmlparser.HTMLElement;
private changed = false;
private get value() {
return this.dom ??= htmlparser.parse(this.html);
}
get outerHTML() {
if (this.changed) {
this.html = this.value.outerHTML;
this.changed = false;
}
return this.html;
}
/**
* Transform and replace the `src` attribute value of all `img` elements from HTML using given function.
*
* @param transformer
*/
transformImageUri(transformer: Operator<string>) {
const elements = this.value.querySelectorAll('img');
if (elements.length === 0) return;
elements.forEach(element => {
const src = element.getAttribute('src');
src && element.setAttribute('src', transformer(src));
});
this.changed = true;
}
insertScript(script: string) {
this.value.querySelector('head').insertAdjacentHTML('beforeend', `<script>${script}</script>`);
this.changed = true;
}
constructor(private html: string) {}
}

View File

@ -1,14 +1,39 @@
/**
* utils/misc.ts
*
* @author CismonX <admin@cismon.net>
* @license MIT
*
* Copyright (C) 2020,2021 CismonX <admin@cismon.net>
*
* This file is part of vscode-texinfo.
*
* vscode-texinfo 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.
*
* vscode-texinfo 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
* vscode-texinfo. If not, see <https://www.gnu.org/licenses/>.
*/
import * as child_process from 'child_process';
import * as path from 'path';
import * as vscode from 'vscode';
import { ExecResult } from './types';
/**
* Escape string to match verbatim in regular expression.
*
* @param str The string to be escaped.
* @returns The escaped string.
*/
export function escapeStringForRegExp(str: string) {
return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
}
/**
* Execute command and fetch output.
*
@ -18,15 +43,18 @@ import { ExecResult } from './types';
* @returns The output data, or `undefined` if execution fails.
*/
export function exec(path: string, args: string[], maxBuffer: number) {
return new Promise<ExecResult>(resolve => {
child_process.execFile(path, args, { maxBuffer: maxBuffer }, (error, stdout, stderr) => {
if (error) {
resolve({ error: stderr ? stderr : error.message });
} else {
resolve({ data: stdout, error: stderr });
}
});
});
return new Promise<ExecResult>(
resolve => child_process.execFile(path, args,
{
env: { ...process.env, LC_MESSAGES: 'en_US.UTF-8' },
maxBuffer: maxBuffer,
},
(error, stdout, stderr) => resolve(error
? { error: stderr ? stderr : error.message }
: { data: stdout, error: stderr }
)
)
);
}
/**
@ -38,7 +66,8 @@ export function exec(path: string, args: string[], maxBuffer: number) {
* @returns Whether the user clicked the button.
*/
export async function prompt(message: string, label: string, error = false) {
const func = error ? vscode.window.showErrorMessage : vscode.window.showInformationMessage;
const func = error ?
vscode.window.showErrorMessage : vscode.window.showInformationMessage;
return label === await func(message, label);
}
@ -60,7 +89,8 @@ export function lineNumToRange(startLine: number, endLine = startLine) {
* @param charCode ASCII code of character.
*/
export function isAlpha(charCode: number) {
return charCode >= 97 && charCode <= 122 || charCode >= 65 && charCode <= 90;
return (charCode >= 97 && charCode <= 122)
|| (charCode >= 65 && charCode <= 90);
}
/**
@ -69,16 +99,17 @@ export function isAlpha(charCode: number) {
* @param charCode ASCII code of character.
*/
export function isAlnum(charCode: number) {
return isAlpha(charCode) || charCode >= 48 && charCode <= 57;
return isAlpha(charCode) || (charCode >= 48 && charCode <= 57);
}
/**
* Get corresponding HTML cross-reference name by node name.
*
* See section *HTML Cross-reference Node Name Expansion* in the Texinfo manual.
* See section *HTML Cross-reference Node Name Expansion* in the
* GNU Texinfo manual.
*
* TODO: Node name is not displayed verbatim, leading to wrong HTML xref when containing commands.
* Fix this when migrating to LSP.
* TODO: Node name is not displayed verbatim, leading to wrong HTML xref when
* containing commands. Fix this when migrating to LSP.
*
* @param nodeName
*/
@ -92,5 +123,22 @@ export function getNodeHtmlRef(nodeName: string) {
.join(''))
.join('-');
const firstCharCode = result.charCodeAt(0);
return isAlpha(firstCharCode) ? result : 'g_t_00' + firstCharCode.toString(16) + result.substring(1);
return isAlpha(firstCharCode)
? result
: 'g_t_00' + firstCharCode.toString(16) + result.substring(1);
}
export function normalizePath(pathName: string) {
pathName = path.normalize(pathName);
if (process.platform === 'win32') {
// On Windows, when passing the path of input file to makeinfo,
// using backslashes in path name breaks some other command line
// options (notably, -I).
// Not sure if this is a bug of makeinfo, or perl, or neither.
//
// TODO: We should look into this issue sometime later.
return pathName.replace(/\\/g, '/');
} else {
return pathName;
}
}

View File

@ -1,25 +1,53 @@
/**
* utils/types.ts
*
* @author CismonX <admin@cismon.net>
* @license MIT
*
* Copyright (C) 2020,2021 CismonX <admin@cismon.net>
*
* This file is part of vscode-texinfo.
*
* vscode-texinfo 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.
*
* vscode-texinfo 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
* vscode-texinfo. If not, see <https://www.gnu.org/licenses/>.
*/
import * as vscode from 'vscode';
export type Optional<T> = T | undefined;
export type CompletionItem = vscode.CompletionItem & {
snippet?: boolean,
};
export type ExecResult = {
data?: string,
error: string,
};
export type FoldingRange = vscode.FoldingRange & {
name: string,
detail: string,
};
export type NamedLine = {
name: string,
line: number,
};
export type Operator<T> = (arg: T) => T;
export type Range = { start: number, end: number };
export type Optional<T> = T | undefined;
export type NamedLine = { name: string, line: number };
export type ExecResult = { data?: string, error: string };
export type FoldingRange = vscode.FoldingRange & { name: string, detail: string };
export type CompletionItem = vscode.CompletionItem & { snippet?: boolean };
export type Range = {
start: number,
end: number,
};
export function isDefined<T>(value: Optional<T>): value is T {
return value !== undefined;

View File

@ -1,11 +1,14 @@
/**
* Copyright (C) 2020,2021 CismonX <admin@cismon.net>
*
* Copying and distribution of this file, with or without modification, are
* permitted in any medium without royalty, provided the copyright notice and
* this notice are preserved. This file is offered as-is, without any warranty.
*/
{
"compilerOptions": {
"module": "CommonJS",
"target": "ES2019",
"outDir": "out",
"lib": [
"ES2019",
],
"esModuleInterop": true,
"strictNullChecks": true,
"sourceMap": true,
@ -14,7 +17,8 @@
"noImplicitReturns": true,
},
"exclude": [
"node_modules",
"*.config.ts",
"node_modules",
"scripts",
],
}

View File

@ -1,30 +1,50 @@
/**
* Copyright (C) 2020,2021 CismonX <admin@cismon.net>
*
* Copying and distribution of this file, with or without modification, are
* permitted in any medium without royalty, provided the copyright notice and
* this notice are preserved. This file is offered as-is, without any warranty.
*/
import * as path from 'path';
import * as webpack from 'webpack';
import { argv } from 'process';
import TerserPlugin from 'terser-webpack-plugin';
const isProduction = 'production' === argv[argv.indexOf('--mode') + 1];
const config: webpack.Configuration = {
target: 'node',
entry: './src/extension.ts',
output: {
path: path.resolve(__dirname, 'out'),
filename: 'extension.js',
libraryTarget: 'commonjs2',
library: {
type: "commonjs2",
},
devtoolModuleFilenameTemplate: '../[resource-path]',
},
devtool: 'source-map',
devtool: isProduction ? false : 'source-map',
optimization: {
concatenateModules: true,
minimize: true,
minimize: isProduction,
minimizer: [
new TerserPlugin({
extractComments: false,
terserOptions: {
compress: {
unsafe: true,
unsafe_arrows: true,
},
format: {
comments: false,
},
mangle: {
module: true,
properties: {
regex: /^_/,
},
},
},
}),
],