Windows: product names, the editors, WSL; the Linux page's image step
Assembled from development commit c3c40f6c8fca. Since 830b193: on Windows the
products carry Windows names (ktext.exe, klammertext.dll, document.dll,
reflect.dll) and the console's output code page is UTF-8 for a run; the
editor tooling works on Windows (VS Code, Sublime Text, Vim, with the
interpreter's name chosen by platform) and Notepad++ joins it
(doc/edit/notepadpp: a User Defined Language and two Run-menu commands);
a sixth install page, doc/install/windows_wsl_install.md, for Linux
inside WSL; the Windows page opens with the three routes and gains its
editor section, the PowerShell quoting and Path notes; the Linux page
installs OpenImageIO from the python3-openimageio package and verifies
with kdiag --machine; the README lists all six install pages. Linux and
macOS behaviour is unchanged.
This commit is contained in:
1 parent
830b19394d
commit
ee8bcf5300
33 files changed
+741
-122
No files matched your search
+3
-1
@@ -1,7 +1,9 @@
|
|||||||
# Build artifacts
|
# Build artifacts (Windows: *.dll, *.pyd; the commands are under bin/)
|
||||||
*.o
|
*.o
|
||||||
*.d
|
*.d
|
||||||
*.so
|
*.so
|
||||||
|
*.dll
|
||||||
|
*.pyd
|
||||||
__pycache__/
|
__pycache__/
|
||||||
|
|
||||||
# Editor / OS cruft
|
# Editor / OS cruft
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ Installation guides are in [`doc/install/`](doc/install/):
|
|||||||
|
|
||||||
- Linux, from source — `doc/install/linux_source_install.md`
|
- Linux, from source — `doc/install/linux_source_install.md`
|
||||||
- macOS, from source — `doc/install/macos_source_install.md`
|
- macOS, from source — `doc/install/macos_source_install.md`
|
||||||
|
- Windows, from source (native) — `doc/install/windows_source_install.md`
|
||||||
|
- Windows, Linux inside WSL — `doc/install/windows_wsl_install.md`
|
||||||
- Linux, container — `doc/install/linux_container_install.md`
|
- Linux, container — `doc/install/linux_container_install.md`
|
||||||
- macOS, container — `doc/install/macos_container_install.md`
|
- macOS, container — `doc/install/macos_container_install.md`
|
||||||
|
|
||||||
@@ -51,7 +53,7 @@ are regenerated on each release — patches cannot be merged directly.
|
|||||||
Report problems (or send patches) to the author; accepted changes are
|
Report problems (or send patches) to the author; accepted changes are
|
||||||
applied to the development tree and appear in a following snapshot.
|
applied to the development tree and appear in a following snapshot.
|
||||||
|
|
||||||
This snapshot was assembled from development commit `f344a37d772c`.
|
This snapshot was assembled from development commit `c3c40f6c8fca`.
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
|
|||||||
+3
-2
@@ -1,5 +1,6 @@
|
|||||||
# bin
|
# bin
|
||||||
|
|
||||||
This directory holds the built Klammertext command executables (`ktext`,
|
This directory holds the built Klammertext command executables (`ktext`,
|
||||||
`kdesc`, `kdiag`) after you build Klammertext with `make -C com`.
|
`kdesc`, `kdiag`) after you build Klammertext with `make -C com`. On
|
||||||
It is empty in the repository.
|
Windows the library and the compiler's runtime DLLs are copied here too,
|
||||||
|
so `bin\` alone needs to be on the `Path`. It is empty in the repository.
|
||||||
+15
-12
@@ -13,8 +13,10 @@ COMMANDS := kdiag kdesc ktext
|
|||||||
# Build output directory: commands are linked directly into ../bin, so there is
|
# Build output directory: commands are linked directly into ../bin, so there is
|
||||||
# exactly one copy of each (no redundant executables in com/) and make still
|
# exactly one copy of each (no redundant executables in com/) and make still
|
||||||
# tracks them by path for incremental builds.
|
# tracks them by path for incremental builds.
|
||||||
|
# The targets carry the system's executable suffix (makefile.env's EXE) so
|
||||||
|
# that on Windows the file gcc writes, ktext.exe, is the target itself.
|
||||||
BINDIR := ../bin
|
BINDIR := ../bin
|
||||||
BINCOMMANDS := $(addprefix $(BINDIR)/,$(COMMANDS))
|
BINCOMMANDS := $(addprefix $(BINDIR)/,$(addsuffix $(EXE),$(COMMANDS)))
|
||||||
|
|
||||||
# System install location (out-of-tree). Override on the command line, e.g.
|
# System install location (out-of-tree). Override on the command line, e.g.
|
||||||
# make install PREFIX=/opt DESTDIR=/tmp/stage
|
# make install PREFIX=/opt DESTDIR=/tmp/stage
|
||||||
@@ -23,7 +25,7 @@ DESTDIR ?=
|
|||||||
|
|
||||||
# Shared library location
|
# Shared library location
|
||||||
LIBDIR := ../lib
|
LIBDIR := ../lib
|
||||||
LIBRARY := $(LIBDIR)/libklammertext.so
|
LIBRARY := $(LIBDIR)/$(KLAMMERTEXT_LIBFILE)
|
||||||
|
|
||||||
# Linker flags for commands
|
# Linker flags for commands
|
||||||
COM_LDFLAGS := $(EXPORT_DYNAMIC) -Wl,-rpath,'$(ORIGIN)/../lib' -L$(LIBDIR)
|
COM_LDFLAGS := $(EXPORT_DYNAMIC) -Wl,-rpath,'$(ORIGIN)/../lib' -L$(LIBDIR)
|
||||||
@@ -36,7 +38,7 @@ ifneq (,$(filter MINGW% MSYS%,$(UNAME_S)))
|
|||||||
MANIFEST_OBJ := manifest.o
|
MANIFEST_OBJ := manifest.o
|
||||||
# The DLLs beside the commands (makefile.env explains); with them, bin/ on
|
# The DLLs beside the commands (makefile.env explains); with them, bin/ on
|
||||||
# PATH is all a Windows user needs besides Python.
|
# PATH is all a Windows user needs besides Python.
|
||||||
RUNTIME_DLLS := $(addprefix $(BINDIR)/,libklammertext.so $(GCC_RUNTIME_DLLS))
|
RUNTIME_DLLS := $(addprefix $(BINDIR)/,$(KLAMMERTEXT_LIBFILE) $(GCC_RUNTIME_DLLS))
|
||||||
else
|
else
|
||||||
MANIFEST_OBJ :=
|
MANIFEST_OBJ :=
|
||||||
RUNTIME_DLLS :=
|
RUNTIME_DLLS :=
|
||||||
@@ -46,8 +48,9 @@ endif
|
|||||||
DEPFILES := $(addsuffix .d,$(COMMANDS))
|
DEPFILES := $(addsuffix .d,$(COMMANDS))
|
||||||
|
|
||||||
# Compiler flags for dependency generation ($(@F) keeps the .d files in com/,
|
# Compiler flags for dependency generation ($(@F) keeps the .d files in com/,
|
||||||
# not in the ../bin output directory).
|
# not in the ../bin output directory; $(basename) drops the .exe so the file
|
||||||
DEPFLAGS = -MMD -MP -MF $(@F).d
|
# is ktext.d on every system, the name DEPFILES includes and clean removes).
|
||||||
|
DEPFLAGS = -MMD -MP -MF $(basename $(@F)).d
|
||||||
|
|
||||||
.PHONY: all clean redo clang mac sks install
|
.PHONY: all clean redo clang mac sks install
|
||||||
|
|
||||||
@@ -65,7 +68,7 @@ commands : $(BINCOMMANDS) $(RUNTIME_DLLS)
|
|||||||
ifneq (,$(filter MINGW% MSYS%,$(UNAME_S)))
|
ifneq (,$(filter MINGW% MSYS%,$(UNAME_S)))
|
||||||
manifest.o : klammertext.rc klammertext.manifest
|
manifest.o : klammertext.rc klammertext.manifest
|
||||||
windres $< $@
|
windres $< $@
|
||||||
$(BINDIR)/libklammertext.so : $(LIBRARY) | $(BINDIR)
|
$(BINDIR)/$(KLAMMERTEXT_LIBFILE) : $(LIBRARY) | $(BINDIR)
|
||||||
cp $< $@
|
cp $< $@
|
||||||
$(BINDIR)/%.dll : $(GCC_BIN)%.dll | $(BINDIR)
|
$(BINDIR)/%.dll : $(GCC_BIN)%.dll | $(BINDIR)
|
||||||
cp $< $@
|
cp $< $@
|
||||||
@@ -86,18 +89,18 @@ sks : | mac
|
|||||||
$(MAKE) -C $(KS)/document
|
$(MAKE) -C $(KS)/document
|
||||||
|
|
||||||
# Explicit rules for each command - link against shared library, output to bin/
|
# Explicit rules for each command - link against shared library, output to bin/
|
||||||
$(BINDIR)/kdiag : kdiag.cpp $(LIBRARY) $(MANIFEST_OBJ) | $(BINDIR)
|
$(BINDIR)/kdiag$(EXE) : kdiag.cpp $(LIBRARY) $(MANIFEST_OBJ) | $(BINDIR)
|
||||||
$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(DEPFLAGS) $(COM_LDFLAGS) $(LDFLAGS) $< $(MANIFEST_OBJ) -o $@ $(KLAMMERTEXT_LIB) $(LDLIBS)
|
$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(DEPFLAGS) $(COM_LDFLAGS) $(LDFLAGS) $< $(MANIFEST_OBJ) -o $@ $(KLAMMERTEXT_LIB) $(LDLIBS)
|
||||||
|
|
||||||
$(BINDIR)/kdesc : kdesc.cpp $(LIBRARY) $(MANIFEST_OBJ) | $(BINDIR)
|
$(BINDIR)/kdesc$(EXE) : kdesc.cpp $(LIBRARY) $(MANIFEST_OBJ) | $(BINDIR)
|
||||||
$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(DEPFLAGS) $(COM_LDFLAGS) $(LDFLAGS) $< $(MANIFEST_OBJ) -o $@ $(KLAMMERTEXT_LIB) $(LDLIBS)
|
$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(DEPFLAGS) $(COM_LDFLAGS) $(LDFLAGS) $< $(MANIFEST_OBJ) -o $@ $(KLAMMERTEXT_LIB) $(LDLIBS)
|
||||||
|
|
||||||
$(BINDIR)/ktext : ktext.cpp $(LIBRARY) $(MANIFEST_OBJ) | $(BINDIR)
|
$(BINDIR)/ktext$(EXE) : ktext.cpp $(LIBRARY) $(MANIFEST_OBJ) | $(BINDIR)
|
||||||
$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(DEPFLAGS) $(COM_LDFLAGS) $(LDFLAGS) $< $(MANIFEST_OBJ) -o $@ $(KLAMMERTEXT_LIB) $(LDLIBS)
|
$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(DEPFLAGS) $(COM_LDFLAGS) $(LDFLAGS) $< $(MANIFEST_OBJ) -o $@ $(KLAMMERTEXT_LIB) $(LDLIBS)
|
||||||
|
|
||||||
# Out-of-tree system install (copies; the build tree stays intact). The
|
# Out-of-tree system install (copies; the build tree stays intact). The
|
||||||
# installed commands still need KLAMMERTEXT_HOME pointing at a Klammertext tree
|
# installed commands still need KLAMMERTEXT_HOME pointing at a Klammertext tree
|
||||||
# for sks/ and the Python modules; their rpath finds libklammertext.so in
|
# for sks/ and the Python modules; their rpath finds the library in
|
||||||
# $(PREFIX)/lib.
|
# $(PREFIX)/lib.
|
||||||
install : all
|
install : all
|
||||||
install -d $(DESTDIR)$(PREFIX)/bin $(DESTDIR)$(PREFIX)/lib
|
install -d $(DESTDIR)$(PREFIX)/bin $(DESTDIR)$(PREFIX)/lib
|
||||||
@@ -115,9 +118,9 @@ else
|
|||||||
$(MAKE) -C $(KS)/kutil clean
|
$(MAKE) -C $(KS)/kutil clean
|
||||||
$(MAKE) -C $(KS)/target clean
|
$(MAKE) -C $(KS)/target clean
|
||||||
$(MAKE) -C $(KS)/document clean
|
$(MAKE) -C $(KS)/document clean
|
||||||
# ref/reflect.so links against libklammertext.so and is dlopened, so
|
# ref/reflect$(DSO) links against the library and is dlopened, so
|
||||||
# it shares the class layouts: a stale one after a header change is
|
# it shares the class layouts: a stale one after a header change is
|
||||||
# the same memory-corruption hazard as a stale sks/document.so.
|
# the same memory-corruption hazard as a stale sks/document$(DSO).
|
||||||
$(MAKE) -C $(K)/ref clean
|
$(MAKE) -C $(K)/ref clean
|
||||||
$(MAKE) -C $(K)/kpy clean
|
$(MAKE) -C $(K)/kpy clean
|
||||||
$(MAKE) clean
|
$(MAKE) clean
|
||||||
|
|||||||
+10
-6
@@ -1,7 +1,7 @@
|
|||||||
# Klammertext editor support
|
# Klammertext editor support
|
||||||
|
|
||||||
Editing support for Klammertext files (`.kt` documents and `.k` klammer
|
Editing support for Klammertext files (`.kt` documents and `.k` klammer
|
||||||
definitions) in four editors, built around one shared implementation.
|
definitions) in five editors, built around one shared implementation.
|
||||||
|
|
||||||
| Directory | Contents |
|
| Directory | Contents |
|
||||||
|---|---|
|
|---|---|
|
||||||
@@ -10,6 +10,7 @@ definitions) in four editors, built around one shared implementation.
|
|||||||
| `sublime/` | Sublime Text package. Syntax file plus thin plugin wrappers that import the shared core directly (Sublime's plugin host is Python). |
|
| `sublime/` | Sublime Text package. Syntax file plus thin plugin wrappers that import the shared core directly (Sublime's plugin host is Python). |
|
||||||
| `vim/` | Vim plugin. Syntax/ftplugin files plus commands that run the shared core's CLI; with `+python3`, the core also runs in-process (`=` operator, live match highlighting). |
|
| `vim/` | Vim plugin. Syntax/ftplugin files plus commands that run the shared core's CLI; with `+python3`, the core also runs in-process (`=` operator, live match highlighting). |
|
||||||
| `vscode/` | Visual Studio Code extension. TextMate grammar plus a dependency-free extension that spawns the language server and speaks LSP to it. |
|
| `vscode/` | Visual Studio Code extension. TextMate grammar plus a dependency-free extension that spawns the language server and speaks LSP to it. |
|
||||||
|
| `notepadpp/` | Notepad++ (Windows). A User Defined Language for the highlighting, and two Run-menu commands that pass the current file through the shared core's CLI (delimiter check, reindent). No plugin host, so nothing structural runs in-process. |
|
||||||
|
|
||||||
## The architecture
|
## The architecture
|
||||||
|
|
||||||
@@ -41,7 +42,8 @@ document/range formatting (reindentation), documentHighlight and
|
|||||||
definition (the matcher), and a `klammertext.alignTable` command. The
|
definition (the matcher), and a `klammertext.alignTable` command. The
|
||||||
VS Code extension is its first client; any LSP client works — Neovim's
|
VS Code extension is its first client; any LSP client works — Neovim's
|
||||||
built-in LSP, Emacs eglot, Sublime's LSP package — with a one-line
|
built-in LSP, Emacs eglot, Sublime's LSP package — with a one-line
|
||||||
configuration pointing at `python3 klammertext_ls.py`.
|
configuration pointing at `python3 klammertext_ls.py` (on Windows
|
||||||
|
`python klammertext_ls.py`).
|
||||||
|
|
||||||
Syntax highlighting and cursor-latency features stay native in each editor
|
Syntax highlighting and cursor-latency features stay native in each editor
|
||||||
(a tokenizer or a per-keystroke matcher cannot round-trip to Python), so
|
(a tokenizer or a per-keystroke matcher cannot round-trip to Python), so
|
||||||
@@ -68,10 +70,12 @@ Two kinds of artifact cannot read it and restate parts of it by hand:
|
|||||||
defcustoms, checked byte-for-byte against the shared core by
|
defcustoms, checked byte-for-byte against the shared core by
|
||||||
`tst/editor_test.sh`.
|
`tst/editor_test.sh`.
|
||||||
2. **The static syntax files** — the literal-klammer set (`@code`) appears
|
2. **The static syntax files** — the literal-klammer set (`@code`) appears
|
||||||
in the Sublime `.sublime-syntax`, the Vim `syntax/klammertext.vim`, and
|
in the Sublime `.sublime-syntax`, the Vim `syntax/klammertext.vim`, the
|
||||||
the VS Code `tmLanguage.json` grammar (and the Emacs defcustom). When
|
VS Code `tmLanguage.json` grammar, and the Notepad++ `Klammertext.udl.xml`
|
||||||
you add a literal klammer, change them together; each file's header
|
(and the Emacs defcustom). When you add a literal klammer, change them
|
||||||
carries the same SYNC note.
|
together; each file's header carries the same SYNC note. The UDL can
|
||||||
|
hold only names that are not prefixes of other klammer names (it has
|
||||||
|
no word boundary), so it carries `code` and not `c`.
|
||||||
|
|
||||||
## Testing
|
## Testing
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,114 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!--
|
||||||
|
Klammertext.udl.xml - Notepad++ User Defined Language for Klammertext
|
||||||
|
(.kt documents and .k klammer definitions). Highlighting only: Notepad++
|
||||||
|
has no Python plugin host and no built-in language-server client, so the
|
||||||
|
structural tools of the shared core (doc/edit/shared/klammertext_edit.py)
|
||||||
|
are reached through Run-menu commands instead; README.md has them.
|
||||||
|
|
||||||
|
What it colours, and how (a UDL is a fixed set of token classes, not a
|
||||||
|
grammar; the choices below are the closest fit):
|
||||||
|
|
||||||
|
@@@name, @@@ system commands Keywords1, prefix match, orange
|
||||||
|
@@name, @@ klammer definitions Keywords2, prefix match, green
|
||||||
|
@name, @ klammer applications Keywords3, prefix match, blue
|
||||||
|
The groups are checked in order, longest run first,
|
||||||
|
so @@name is not taken for an @ followed by a name.
|
||||||
|
A named close (name@) is coloured only at its @.
|
||||||
|
^X ^UUUU^ ^' escapes Keywords4, prefix match, the
|
||||||
|
default colour: consumed so the character after the
|
||||||
|
caret is never read as a delimiter, shown as text
|
||||||
|
(as the Emacs mode does).
|
||||||
|
# ... removal to end of line line comment, grey; only
|
||||||
|
when the # is the first thing on its line
|
||||||
|
(forcePureLC), because a UDL comment cannot tell
|
||||||
|
"# comment" from the whitespace operators #- #+ #/,
|
||||||
|
which would otherwise grey the rest of their line.
|
||||||
|
#[ ... ]# removal of a region block comment, grey, folds.
|
||||||
|
## #- #+ #/ the other # forms Operators2, marker red.
|
||||||
|
| : bars and option marks Operators1, marker red.
|
||||||
|
@code ... code@ verbatim interior Delimiters1, muted, nothing
|
||||||
|
inside it is coloured. The other literal klammer,
|
||||||
|
@c ... c@, is NOT here: a UDL delimiter has no word
|
||||||
|
boundary, so "@c" would also open at @caption,
|
||||||
|
@cond and every other c-klammer.
|
||||||
|
|
||||||
|
SYNC: the literal-klammer set's source of truth is LITERAL_KLAMMERS in
|
||||||
|
doc/edit/shared/klammertext_edit.py. When a klammer is added there, add
|
||||||
|
"@NAME" / "NAME@" as a further delimiter pair here (pairs 2 to 8 are free:
|
||||||
|
items 03/05, 06/08, ... in the "Delimiters" list) - if its name is not a
|
||||||
|
prefix of other klammer names.
|
||||||
|
|
||||||
|
Colours are the palette's light-ground values (notes/klammertext_palette.md:
|
||||||
|
application 528599, definition 758B55, system 996743, markers 994040,
|
||||||
|
removed text 9A9A9A); colorStyle="1" keeps every background transparent, so
|
||||||
|
a dark Notepad++ theme keeps its own ground (the hues still read there).
|
||||||
|
|
||||||
|
Install: copy this file into %AppData%\Notepad++\userDefineLangs\ and
|
||||||
|
restart Notepad++ (or Language > User Defined Language > Define your
|
||||||
|
language... > Import...). README.md has the details and the Run commands.
|
||||||
|
-->
|
||||||
|
<NotepadPlus>
|
||||||
|
<UserLang name="Klammertext" ext="kt k" udlVersion="2.1">
|
||||||
|
<Settings>
|
||||||
|
<Global caseIgnored="no" allowFoldOfComments="yes" foldCompact="no" forcePureLC="1" decimalSeparator="0" />
|
||||||
|
<Prefix Keywords1="yes" Keywords2="yes" Keywords3="yes" Keywords4="yes" Keywords5="no" Keywords6="no" Keywords7="no" Keywords8="no" />
|
||||||
|
</Settings>
|
||||||
|
<KeywordLists>
|
||||||
|
<Keywords name="Comments">00# 01 02 03#[ 04]#</Keywords>
|
||||||
|
<Keywords name="Numbers, prefix1"></Keywords>
|
||||||
|
<Keywords name="Numbers, prefix2"></Keywords>
|
||||||
|
<Keywords name="Numbers, extras1"></Keywords>
|
||||||
|
<Keywords name="Numbers, extras2"></Keywords>
|
||||||
|
<Keywords name="Numbers, suffix1"></Keywords>
|
||||||
|
<Keywords name="Numbers, suffix2"></Keywords>
|
||||||
|
<Keywords name="Numbers, range"></Keywords>
|
||||||
|
<Keywords name="Operators1">| :</Keywords>
|
||||||
|
<Keywords name="Operators2">## #- #+ #/</Keywords>
|
||||||
|
<Keywords name="Folders in code1, open"></Keywords>
|
||||||
|
<Keywords name="Folders in code1, middle"></Keywords>
|
||||||
|
<Keywords name="Folders in code1, close"></Keywords>
|
||||||
|
<Keywords name="Folders in code2, open"></Keywords>
|
||||||
|
<Keywords name="Folders in code2, middle"></Keywords>
|
||||||
|
<Keywords name="Folders in code2, close"></Keywords>
|
||||||
|
<Keywords name="Folders in comment, open">#[</Keywords>
|
||||||
|
<Keywords name="Folders in comment, middle"></Keywords>
|
||||||
|
<Keywords name="Folders in comment, close">]#</Keywords>
|
||||||
|
<Keywords name="Keywords1">@@@</Keywords>
|
||||||
|
<Keywords name="Keywords2">@@</Keywords>
|
||||||
|
<Keywords name="Keywords3">@</Keywords>
|
||||||
|
<Keywords name="Keywords4">^</Keywords>
|
||||||
|
<Keywords name="Keywords5"></Keywords>
|
||||||
|
<Keywords name="Keywords6"></Keywords>
|
||||||
|
<Keywords name="Keywords7"></Keywords>
|
||||||
|
<Keywords name="Keywords8"></Keywords>
|
||||||
|
<Keywords name="Delimiters">00@code 01 02code@ 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23</Keywords>
|
||||||
|
</KeywordLists>
|
||||||
|
<Styles>
|
||||||
|
<WordsStyle name="DEFAULT" fgColor="000000" bgColor="FFFFFF" colorStyle="1" fontName="" fontStyle="0" nesting="0" />
|
||||||
|
<WordsStyle name="COMMENTS" fgColor="9A9A9A" bgColor="FFFFFF" colorStyle="1" fontName="" fontStyle="0" nesting="0" />
|
||||||
|
<WordsStyle name="LINE COMMENTS" fgColor="9A9A9A" bgColor="FFFFFF" colorStyle="1" fontName="" fontStyle="0" nesting="0" />
|
||||||
|
<WordsStyle name="NUMBERS" fgColor="000000" bgColor="FFFFFF" colorStyle="1" fontName="" fontStyle="0" nesting="0" />
|
||||||
|
<WordsStyle name="KEYWORDS1" fgColor="996743" bgColor="FFFFFF" colorStyle="1" fontName="" fontStyle="1" nesting="0" />
|
||||||
|
<WordsStyle name="KEYWORDS2" fgColor="758B55" bgColor="FFFFFF" colorStyle="1" fontName="" fontStyle="1" nesting="0" />
|
||||||
|
<WordsStyle name="KEYWORDS3" fgColor="528599" bgColor="FFFFFF" colorStyle="1" fontName="" fontStyle="1" nesting="0" />
|
||||||
|
<WordsStyle name="KEYWORDS4" fgColor="000000" bgColor="FFFFFF" colorStyle="1" fontName="" fontStyle="0" nesting="0" />
|
||||||
|
<WordsStyle name="KEYWORDS5" fgColor="000000" bgColor="FFFFFF" colorStyle="1" fontName="" fontStyle="0" nesting="0" />
|
||||||
|
<WordsStyle name="KEYWORDS6" fgColor="000000" bgColor="FFFFFF" colorStyle="1" fontName="" fontStyle="0" nesting="0" />
|
||||||
|
<WordsStyle name="KEYWORDS7" fgColor="000000" bgColor="FFFFFF" colorStyle="1" fontName="" fontStyle="0" nesting="0" />
|
||||||
|
<WordsStyle name="KEYWORDS8" fgColor="000000" bgColor="FFFFFF" colorStyle="1" fontName="" fontStyle="0" nesting="0" />
|
||||||
|
<WordsStyle name="OPERATORS" fgColor="994040" bgColor="FFFFFF" colorStyle="1" fontName="" fontStyle="0" nesting="0" />
|
||||||
|
<WordsStyle name="FOLDER IN CODE1" fgColor="000000" bgColor="FFFFFF" colorStyle="1" fontName="" fontStyle="0" nesting="0" />
|
||||||
|
<WordsStyle name="FOLDER IN CODE2" fgColor="000000" bgColor="FFFFFF" colorStyle="1" fontName="" fontStyle="0" nesting="0" />
|
||||||
|
<WordsStyle name="FOLDER IN COMMENT" fgColor="994040" bgColor="FFFFFF" colorStyle="1" fontName="" fontStyle="0" nesting="0" />
|
||||||
|
<WordsStyle name="DELIMITERS1" fgColor="5A5A5A" bgColor="FFFFFF" colorStyle="1" fontName="" fontStyle="0" nesting="0" />
|
||||||
|
<WordsStyle name="DELIMITERS2" fgColor="000000" bgColor="FFFFFF" colorStyle="1" fontName="" fontStyle="0" nesting="0" />
|
||||||
|
<WordsStyle name="DELIMITERS3" fgColor="000000" bgColor="FFFFFF" colorStyle="1" fontName="" fontStyle="0" nesting="0" />
|
||||||
|
<WordsStyle name="DELIMITERS4" fgColor="000000" bgColor="FFFFFF" colorStyle="1" fontName="" fontStyle="0" nesting="0" />
|
||||||
|
<WordsStyle name="DELIMITERS5" fgColor="000000" bgColor="FFFFFF" colorStyle="1" fontName="" fontStyle="0" nesting="0" />
|
||||||
|
<WordsStyle name="DELIMITERS6" fgColor="000000" bgColor="FFFFFF" colorStyle="1" fontName="" fontStyle="0" nesting="0" />
|
||||||
|
<WordsStyle name="DELIMITERS7" fgColor="000000" bgColor="FFFFFF" colorStyle="1" fontName="" fontStyle="0" nesting="0" />
|
||||||
|
<WordsStyle name="DELIMITERS8" fgColor="000000" bgColor="FFFFFF" colorStyle="1" fontName="" fontStyle="0" nesting="0" />
|
||||||
|
</Styles>
|
||||||
|
</UserLang>
|
||||||
|
</NotepadPlus>
|
||||||
@@ -0,0 +1,114 @@
|
|||||||
|
# Klammertext support for Notepad++
|
||||||
|
|
||||||
|
Notepad++ support for editing Klammertext files (`.kt` documents and `.k`
|
||||||
|
klammer definitions): syntax highlighting through a **User Defined
|
||||||
|
Language**, and the shared editor core's delimiter check and
|
||||||
|
reindentation through two **Run-menu commands**. Notepad++ is Windows
|
||||||
|
only, and so is this package.
|
||||||
|
|
||||||
|
Notepad++ has no Python plugin host and no built-in language-server
|
||||||
|
client, so it cannot import the shared core the way Sublime Text does or
|
||||||
|
talk to the language server the way VS Code does. What it has is a
|
||||||
|
declarative highlighter and a Run menu that can invoke any program on the
|
||||||
|
current file, and this package uses exactly those two things.
|
||||||
|
|
||||||
|
## Files
|
||||||
|
|
||||||
|
| File | Purpose |
|
||||||
|
|---|---|
|
||||||
|
| `Klammertext.udl.xml` | The User Defined Language: highlighting for the three `@`-tiers, escapes, text removal, and the `@code` verbatim interior. Its header lists what it colours and the limits of a UDL. |
|
||||||
|
| `klammertext_edit.py` | The shared editor core (in the editing zip it sits here; in the Klammertext repository it is `doc\edit\shared\klammertext_edit.py`). The Run commands call it. |
|
||||||
|
| `README.md` | This file. |
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
- Notepad++ 7.9 or later (the `userDefineLangs` folder; any recent
|
||||||
|
version qualifies).
|
||||||
|
- For the Run commands: `python` on the `Path`, which the Klammertext
|
||||||
|
installation already needs.
|
||||||
|
|
||||||
|
## Install the highlighting
|
||||||
|
|
||||||
|
Copy `Klammertext.udl.xml` into Notepad++'s user-defined-language folder
|
||||||
|
and restart Notepad++:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
$d = "$env:AppData\Notepad++\userDefineLangs"
|
||||||
|
New-Item -ItemType Directory -Force $d | Out-Null
|
||||||
|
Copy-Item Klammertext.udl.xml $d
|
||||||
|
```
|
||||||
|
|
||||||
|
Notepad++ loads every file in that folder at start. `.kt` and `.k` files
|
||||||
|
then open as "Klammertext" (the language shows in the status bar and at
|
||||||
|
the bottom of the **Language** menu). The alternative is the dialog:
|
||||||
|
**Language → User Defined Language → Define your language… → Import…**,
|
||||||
|
which copies the file to the same place.
|
||||||
|
|
||||||
|
What you see: klammer applications (`@name … @`) in blue, definitions
|
||||||
|
(`@@name … @@`) in green, system commands (`@@@name … @@@`) in orange;
|
||||||
|
a `#` at the start of a line greys the rest of the line, `#[ … ]#` greys
|
||||||
|
and folds a region; `##`, `#-`, `#+`, `#/`, `|` and `:` in the marker
|
||||||
|
red; the interior of `@code … code@` muted and uninterpreted. The
|
||||||
|
colours are the palette's light-ground values with transparent
|
||||||
|
backgrounds, so a dark theme keeps its own ground.
|
||||||
|
|
||||||
|
Two limits, both properties of a UDL rather than of Klammertext, are
|
||||||
|
documented in the file's header: a `#` that is not the first thing on
|
||||||
|
its line is not treated as a comment (so that the whitespace operators
|
||||||
|
`#-`, `#+`, `#/` never grey the rest of their line), and `@c … c@` is not
|
||||||
|
made verbatim (a UDL delimiter has no word boundary, so `@c` would also
|
||||||
|
open at `@caption` and `@cond`).
|
||||||
|
|
||||||
|
## The Run commands
|
||||||
|
|
||||||
|
The shared core's command-line interface reads a file on standard input
|
||||||
|
and writes the result on standard output; Notepad++'s **Run → Run…**
|
||||||
|
dialog (`F5`) runs a command line with the current file's path filled in
|
||||||
|
as `$(FULL_CURRENT_PATH)`. Two commands cover the structural tools.
|
||||||
|
Replace `C:\Users\<you>\klammertext\doc\edit\shared` with the folder that
|
||||||
|
holds `klammertext_edit.py` (with the editing zip, the folder this
|
||||||
|
README is in).
|
||||||
|
|
||||||
|
**Check the delimiters** — lists every unclosed opening, extra close,
|
||||||
|
name or tier mismatch, and unclosed literal span or `#[` block, as
|
||||||
|
`line:column: message`; an empty window means the file is balanced.
|
||||||
|
The `/k` keeps the window open to read:
|
||||||
|
|
||||||
|
```
|
||||||
|
cmd /k python "C:\Users\<you>\klammertext\doc\edit\shared\klammertext_edit.py" check < "$(FULL_CURRENT_PATH)"
|
||||||
|
```
|
||||||
|
|
||||||
|
**Reindent the file** — rewrites the file with the canonical
|
||||||
|
indentation (2 spaces per nesting level, bars and closes at their
|
||||||
|
opener's column, `@document` transparent, verbatim and removed text
|
||||||
|
untouched):
|
||||||
|
|
||||||
|
```
|
||||||
|
cmd /c python "C:\Users\<you>\klammertext\doc\edit\shared\klammertext_edit.py" indent < "$(FULL_CURRENT_PATH)" > "$(FULL_CURRENT_PATH).tmp" && move /y "$(FULL_CURRENT_PATH).tmp" "$(FULL_CURRENT_PATH)"
|
||||||
|
```
|
||||||
|
|
||||||
|
Paste each line into the Run dialog once, press **Save…**, give it a
|
||||||
|
name ("Klammertext check", "Klammertext reindent") and a shortcut
|
||||||
|
(`Ctrl+Alt+K`, `Ctrl+Alt+I` are free); they then appear at the bottom of
|
||||||
|
the **Run** menu with those keys.
|
||||||
|
|
||||||
|
Two things to know about the reindent command. It works on the file
|
||||||
|
**on disk**, so save first (`Ctrl+S`); Notepad++ does not save before
|
||||||
|
running. And after it runs, Notepad++ notices the changed file: with the
|
||||||
|
default setting it asks whether to reload, which you answer Yes; under
|
||||||
|
**Settings → Preferences → MISC. → File Status Auto-Detection** the
|
||||||
|
choice "Update silently" makes the reload automatic. Undo history is
|
||||||
|
lost on a reload, as for any external edit.
|
||||||
|
|
||||||
|
Table alignment and jump-to-match need a caret position the Run dialog
|
||||||
|
cannot pass, so they are not offered here. They are available in every
|
||||||
|
other supported editor, and for Notepad++ through the PythonScript
|
||||||
|
plugin, which embeds a Python that can import the shared core and reach
|
||||||
|
the caret; a script for it is a possible addition, not part of this
|
||||||
|
package.
|
||||||
|
|
||||||
|
## Keeping things in sync
|
||||||
|
|
||||||
|
The UDL restates the literal-klammer set (`@code`) that the shared core
|
||||||
|
owns in `LITERAL_KLAMMERS`; its header says how to add one. The editor
|
||||||
|
support's overview is `doc/edit/README.md` in the Klammertext repository.
|
||||||
@@ -56,7 +56,10 @@ import sys
|
|||||||
# --- policy ----------------------------------------------------------------
|
# --- policy ----------------------------------------------------------------
|
||||||
|
|
||||||
# Klammer names whose content is a literal argument (verbatim interior,
|
# Klammer names whose content is a literal argument (verbatim interior,
|
||||||
# closed by a named NAME@ delimiter).
|
# closed by a named NAME@ delimiter). The static syntax artifacts restate
|
||||||
|
# this set by hand (Emacs defcustom, .sublime-syntax, vim syntax, tmLanguage,
|
||||||
|
# the Notepad++ UDL -- which can hold only "code"); doc/edit/README.md,
|
||||||
|
# "Keeping things in sync".
|
||||||
LITERAL_KLAMMERS = set(["code", "c"])
|
LITERAL_KLAMMERS = set(["code", "c"])
|
||||||
|
|
||||||
# Klammers that contribute no indentation level (a @document's paragraphs
|
# Klammers that contribute no indentation level (a @document's paragraphs
|
||||||
@@ -1037,6 +1040,13 @@ def _cli(argv):
|
|||||||
if len(argv) < 1:
|
if len(argv) < 1:
|
||||||
return usage()
|
return usage()
|
||||||
mode = argv[0]
|
mode = argv[0]
|
||||||
|
# Klammertext writes LF on every system. Python's text-mode stdout turns
|
||||||
|
# every "\n" into "\r\n" on Windows, and an editor -- or the test suite --
|
||||||
|
# comparing the result with an LF buffer then sees every line changed.
|
||||||
|
# stdin keeps universal newlines: a CRLF buffer arrives as "\n" lines,
|
||||||
|
# which is what the algorithms expect.
|
||||||
|
if hasattr(sys.stdout, 'reconfigure'): # 3.7+; the floor is 3.8
|
||||||
|
sys.stdout.reconfigure(newline='\n')
|
||||||
s = sys.stdin.read()
|
s = sys.stdin.read()
|
||||||
|
|
||||||
if mode == 'indent':
|
if mode == 'indent':
|
||||||
|
|||||||
@@ -203,8 +203,8 @@ elsewhere) are not part of this package, but they exist: the **Klammertext
|
|||||||
language server** (`doc/edit/shared/klammertext_ls.py`, the same program the
|
language server** (`doc/edit/shared/klammertext_ls.py`, the same program the
|
||||||
VS Code extension uses) serves them to Sublime through the community LSP
|
VS Code extension uses) serves them to Sublime through the community LSP
|
||||||
package. Install "LSP" from Package Control and add a client with
|
package. Install "LSP" from Package Control and add a client with
|
||||||
`command: ["python3", "/path/to/klammertext_ls.py"]` for the
|
`command: ["python3", "/path/to/klammertext_ls.py"]` (on Windows
|
||||||
`text.klammertext` selector. Everything in this package works the same
|
`"python"`) for the `text.klammertext` selector. Everything in this package works the same
|
||||||
with or without it.
|
with or without it.
|
||||||
|
|
||||||
## Troubleshooting
|
## Troubleshooting
|
||||||
|
|||||||
@@ -14,7 +14,8 @@ sync.
|
|||||||
## Requirements
|
## Requirements
|
||||||
|
|
||||||
- Vim 8+ (or Neovim) with `+eval` — any normal Vim; only `vim-tiny` lacks it.
|
- Vim 8+ (or Neovim) with `+eval` — any normal Vim; only `vim-tiny` lacks it.
|
||||||
- `python3` on `PATH` (Klammertext itself already requires Python).
|
- `python3` on `PATH` — on Windows `python`, the name python.org installs
|
||||||
|
(Klammertext itself already requires Python).
|
||||||
- The shared core, found automatically in this order:
|
- The shared core, found automatically in this order:
|
||||||
1. `g:klammertext_edit_py`, if you set it (a full path to
|
1. `g:klammertext_edit_py`, if you set it (a full path to
|
||||||
`klammertext_edit.py`);
|
`klammertext_edit.py`);
|
||||||
@@ -81,7 +82,7 @@ in-process: the `=` operator reindents through `'indentexpr'` (`==`, `gg=G`),
|
|||||||
and the matching delimiter is highlighted live as the cursor sits on one —
|
and the matching delimiter is highlighted live as the cursor sits on one —
|
||||||
the show-paren equivalent, with a mismatched or unbalanced delimiter shown
|
the show-paren equivalent, with a mismatched or unbalanced delimiter shown
|
||||||
in red plus a message. Without `+python3` the commands above still work;
|
in red plus a message. Without `+python3` the commands above still work;
|
||||||
they shell out to `python3`.
|
they shell out to `python3` (on Windows `python`).
|
||||||
|
|
||||||
**Comment toggling** — `'commentstring'` is set to `# %s`, so Vim 9.1's
|
**Comment toggling** — `'commentstring'` is set to `# %s`, so Vim 9.1's
|
||||||
built-in commenting and Neovim's `gcc`/`gc` (or the commentary plugin)
|
built-in commenting and Neovim's `gcc`/`gc` (or the commentary plugin)
|
||||||
@@ -92,7 +93,7 @@ toggle `#` line removal.
|
|||||||
| Variable | Meaning (default) |
|
| Variable | Meaning (default) |
|
||||||
|---|---|
|
|---|---|
|
||||||
| `g:klammertext_edit_py` | full path to `klammertext_edit.py` (auto-detected) |
|
| `g:klammertext_edit_py` | full path to `klammertext_edit.py` (auto-detected) |
|
||||||
| `g:klammertext_python` | Python interpreter (`python3`) |
|
| `g:klammertext_python` | Python interpreter (`python3`; on Windows `python`) |
|
||||||
| `g:klammertext_no_mappings` | set to define no default mappings |
|
| `g:klammertext_no_mappings` | set to define no default mappings |
|
||||||
|
|
||||||
## Neovim and the language server
|
## Neovim and the language server
|
||||||
|
|||||||
@@ -11,7 +11,8 @@
|
|||||||
" Configuration:
|
" Configuration:
|
||||||
" g:klammertext_edit_py full path to klammertext_edit.py (overrides the
|
" g:klammertext_edit_py full path to klammertext_edit.py (overrides the
|
||||||
" search described below)
|
" search described below)
|
||||||
" g:klammertext_python the Python interpreter (default "python3")
|
" g:klammertext_python the Python interpreter (default "python3";
|
||||||
|
" on Windows "python", the name python.org installs)
|
||||||
|
|
||||||
" --- locating the shared core ---------------------------------------------
|
" --- locating the shared core ---------------------------------------------
|
||||||
" Search order: an explicit g:klammertext_edit_py; a vendored copy at this
|
" Search order: an explicit g:klammertext_edit_py; a vendored copy at this
|
||||||
@@ -37,7 +38,8 @@ function! s:EditScript() abort
|
|||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! s:Python() abort
|
function! s:Python() abort
|
||||||
return exists('g:klammertext_python') ? g:klammertext_python : 'python3'
|
return exists('g:klammertext_python') ? g:klammertext_python
|
||||||
|
\ : (has('win32') ? 'python' : 'python3')
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
" Run the core CLI over the whole buffer. ARGS is the argument string
|
" Run the core CLI over the whole buffer. ARGS is the argument string
|
||||||
|
|||||||
@@ -18,8 +18,9 @@ language's structure, everywhere.
|
|||||||
- VS Code 1.75 or later — a minimum, not a target: VS Code's monthly
|
- VS Code 1.75 or later — a minimum, not a target: VS Code's monthly
|
||||||
releases count 1.75, 1.76, … (1.75 is from January 2023), so any
|
releases count 1.75, 1.76, … (1.75 is from January 2023), so any
|
||||||
version from the last few years qualifies.
|
version from the last few years qualifies.
|
||||||
- `python3` on `PATH` (or set `klammertext.pythonPath`); Klammertext itself
|
- `python3` on `PATH` — on Windows `python`, the name python.org installs
|
||||||
already requires Python.
|
(or set `klammertext.pythonPath`); Klammertext itself already requires
|
||||||
|
Python.
|
||||||
- The language server, found automatically in this order:
|
- The language server, found automatically in this order:
|
||||||
1. the `klammertext.serverPath` setting, if set;
|
1. the `klammertext.serverPath` setting, if set;
|
||||||
2. `klammertext_ls.py` vendored next to `extension.js` (the layout the
|
2. `klammertext_ls.py` vendored next to `extension.js` (the layout the
|
||||||
@@ -32,8 +33,9 @@ language's structure, everywhere.
|
|||||||
## Install
|
## Install
|
||||||
|
|
||||||
Package the extension as a `.vsix` and install it (the builder needs only
|
Package the extension as a `.vsix` and install it (the builder needs only
|
||||||
bash and python3; the editing zip from the Klammertext website ships a
|
bash and Python — on Windows, run it in the MSYS2 shell the Klammertext
|
||||||
prebuilt `klammertext.vsix`, so there the first step is already done):
|
build uses; the editing zip from the Klammertext website ships a prebuilt
|
||||||
|
`klammertext.vsix`, so there the first step is already done):
|
||||||
|
|
||||||
./make_vsix.sh
|
./make_vsix.sh
|
||||||
code --install-extension klammertext.vsix
|
code --install-extension klammertext.vsix
|
||||||
@@ -129,7 +131,7 @@ Shortcuts** (`Ctrl+K Ctrl+S`), search "klammertext", and rebind.
|
|||||||
## Settings
|
## Settings
|
||||||
|
|
||||||
A normal installation needs neither setting: the extension runs `python3`
|
A normal installation needs neither setting: the extension runs `python3`
|
||||||
from `PATH` and finds the language server automatically (the copy vendored
|
(on Windows `python`) from `PATH` and finds the language server automatically (the copy vendored
|
||||||
next to `extension.js`, then `../shared/`, then
|
next to `extension.js`, then `../shared/`, then
|
||||||
`$KLAMMERTEXT_HOME/doc/edit/shared/`). They exist for unusual setups.
|
`$KLAMMERTEXT_HOME/doc/edit/shared/`). They exist for unusual setups.
|
||||||
Set them in the Settings UI (`Ctrl+,`, search "klammertext") or in
|
Set them in the Settings UI (`Ctrl+,`, search "klammertext") or in
|
||||||
@@ -138,10 +140,10 @@ reload the window after changing either.
|
|||||||
|
|
||||||
| Setting | Meaning (default) |
|
| Setting | Meaning (default) |
|
||||||
|---|---|
|
|---|---|
|
||||||
| `klammertext.pythonPath` | Python interpreter for the server (`python3`) |
|
| `klammertext.pythonPath` | Python interpreter for the server (`python3`; on Windows `python`) |
|
||||||
| `klammertext.serverPath` | full path to `klammertext_ls.py` (auto-located) |
|
| `klammertext.serverPath` | full path to `klammertext_ls.py` (auto-located) |
|
||||||
|
|
||||||
`pythonPath` matters when `python3` is not on the `PATH` VS Code sees — a
|
`pythonPath` matters when the interpreter is not on the `PATH` VS Code sees — a
|
||||||
VS Code launched from the desktop inherits a different environment than
|
VS Code launched from the desktop inherits a different environment than
|
||||||
your shell — or when a specific interpreter is wanted. `serverPath`
|
your shell — or when a specific interpreter is wanted. `serverPath`
|
||||||
matters only when the server file lives outside the search chain above.
|
matters only when the server file lives outside the search chain above.
|
||||||
|
|||||||
@@ -165,7 +165,11 @@ function activate(context) {
|
|||||||
'diagnostics, formatting, matching and alignment need the server.');
|
'diagnostics, formatting, matching and alignment need the server.');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const python = vscode.workspace.getConfiguration('klammertext').get('pythonPath') || 'python3';
|
// The setting's declared default is empty so that this fallback is what
|
||||||
|
// decides: python3 everywhere but Windows, where python.org installs
|
||||||
|
// "python" only (the Klammertext commands there use the same name).
|
||||||
|
const python = vscode.workspace.getConfiguration('klammertext').get('pythonPath') ||
|
||||||
|
(process.platform === 'win32' ? 'python' : 'python3');
|
||||||
client = new LspClient(python, [serverPath], log);
|
client = new LspClient(python, [serverPath], log);
|
||||||
client.proc.on('error', (err) => {
|
client.proc.on('error', (err) => {
|
||||||
vscode.window.showWarningMessage(
|
vscode.window.showWarningMessage(
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
# code --install-extension klammertext.vsix
|
# code --install-extension klammertext.vsix
|
||||||
#
|
#
|
||||||
# A .vsix is a zip holding a two-file manifest plus the extension payload
|
# A .vsix is a zip holding a two-file manifest plus the extension payload
|
||||||
# under extension/. This script builds it with bash + python3 only — no
|
# under extension/. This script builds it with bash + Python only — no
|
||||||
# npm, no vsce — matching the extension's no-dependency design. The shared
|
# npm, no vsce — matching the extension's no-dependency design. The shared
|
||||||
# core and language server are vendored into the payload: from this folder
|
# core and language server are vendored into the payload: from this folder
|
||||||
# if present (the editing-zip layout), else from ../shared (the repository
|
# if present (the editing-zip layout), else from ../shared (the repository
|
||||||
@@ -18,6 +18,12 @@
|
|||||||
set -e
|
set -e
|
||||||
cd "$(dirname "$0")"
|
cd "$(dirname "$0")"
|
||||||
|
|
||||||
|
# The interpreter: $PYTHON if the environment names one (env/runtime.env
|
||||||
|
# does), else python3, else python -- the only name python.org installs on
|
||||||
|
# Windows, where this runs in the MSYS2 shell.
|
||||||
|
PYTHON="${PYTHON:-$(command -v python3 || command -v python)}"
|
||||||
|
[ -n "$PYTHON" ] || { echo "make_vsix.sh: no python3 or python on PATH" >&2; exit 1; }
|
||||||
|
|
||||||
OUT="$PWD/klammertext.vsix"
|
OUT="$PWD/klammertext.vsix"
|
||||||
STAGE="$(mktemp -d)"
|
STAGE="$(mktemp -d)"
|
||||||
trap 'rm -rf "$STAGE"' EXIT
|
trap 'rm -rf "$STAGE"' EXIT
|
||||||
@@ -36,7 +42,7 @@ for f in klammertext_edit.py klammertext_ls.py; do
|
|||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
VERSION=$(python3 -c "import json; print(json.load(open('package.json'))['version'])")
|
VERSION=$("$PYTHON" -c "import json; print(json.load(open('package.json'))['version'])")
|
||||||
|
|
||||||
cat > "$STAGE/[Content_Types].xml" <<'EOF'
|
cat > "$STAGE/[Content_Types].xml" <<'EOF'
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
@@ -75,7 +81,7 @@ cat > "$STAGE/extension.vsixmanifest" <<EOF
|
|||||||
</PackageManifest>
|
</PackageManifest>
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
python3 - "$STAGE" "$OUT" <<'EOF'
|
"$PYTHON" - "$STAGE" "$OUT" <<'EOF'
|
||||||
import os, sys, zipfile
|
import os, sys, zipfile
|
||||||
stage, out = sys.argv[1], sys.argv[2]
|
stage, out = sys.argv[1], sys.argv[2]
|
||||||
with zipfile.ZipFile(out, 'w', zipfile.ZIP_DEFLATED) as z:
|
with zipfile.ZipFile(out, 'w', zipfile.ZIP_DEFLATED) as z:
|
||||||
|
|||||||
@@ -83,8 +83,8 @@
|
|||||||
"properties": {
|
"properties": {
|
||||||
"klammertext.pythonPath": {
|
"klammertext.pythonPath": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"default": "python3",
|
"default": "",
|
||||||
"description": "Python interpreter used to run the Klammertext language server."
|
"description": "Python interpreter used to run the Klammertext language server. Leave blank for python3 (on Windows: python)."
|
||||||
},
|
},
|
||||||
"klammertext.serverPath": {
|
"klammertext.serverPath": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ including `:haskell` and `:shell` commands that depend on locally installed
|
|||||||
software.
|
software.
|
||||||
|
|
||||||
For the container installation on Linux, see `linux_container_install.md`.
|
For the container installation on Linux, see `linux_container_install.md`.
|
||||||
|
On Windows, this page also applies unchanged inside the Windows Subsystem
|
||||||
|
for Linux; `windows_wsl_install.md` says what is specific to WSL.
|
||||||
|
|
||||||
|
|
||||||
## Prerequisites
|
## Prerequisites
|
||||||
@@ -21,15 +23,19 @@ sudo apt-get install g++ make python3-dev
|
|||||||
The C++ compiler must support C++20. GCC 11 or later is required (Ubuntu 22.04
|
The C++ compiler must support C++20. GCC 11 or later is required (Ubuntu 22.04
|
||||||
and later include GCC 12+).
|
and later include GCC 12+).
|
||||||
|
|
||||||
The SKS `@image` klammer requires OpenImageIO Python bindings. These must match
|
The SKS `@image` klammer requires the OpenImageIO Python bindings, for the
|
||||||
the Python version that ktext is built against (check with
|
same Python that ktext is built against (the system `python3`). Ubuntu
|
||||||
`python3.XX -c "import OpenImageIO"`). For example, if ktext links against
|
packages them:
|
||||||
Python 3.12:
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
pip3.12 install OpenImageIO
|
sudo apt-get install python3-openimageio
|
||||||
|
python3 -c "import OpenImageIO"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
(A `pip` install works too, but a fresh Ubuntu has no `pip` until
|
||||||
|
`python3-pip` is installed, and since 24.04 it refuses to install into the
|
||||||
|
system Python without `--break-system-packages`; the package avoids both.)
|
||||||
|
|
||||||
Verify:
|
Verify:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
@@ -284,8 +290,8 @@ ktext -s '@eval 1 + 1 @' -d
|
|||||||
# Shell evaluation
|
# Shell evaluation
|
||||||
ktext -s '@eval :shell date @' -d
|
ktext -s '@eval :shell date @' -d
|
||||||
|
|
||||||
# Show machine state (SKS is loaded by default)
|
# Show the machine's initial state: targets, argument types, the primitive klammers
|
||||||
ktext -s '' -m
|
kdiag --machine
|
||||||
|
|
||||||
# HTML and PDF output (uses the hello.kt from the Build section)
|
# HTML and PDF output (uses the hello.kt from the Build section)
|
||||||
ktext hello.kt -t html
|
ktext hello.kt -t html
|
||||||
|
|||||||
@@ -13,6 +13,14 @@ The installation uses three things a Windows user installs once:
|
|||||||
building; **Python** from python.org, which Klammertext embeds; and **TeX
|
building; **Python** from python.org, which Klammertext embeds; and **TeX
|
||||||
Live**, for PDF output. Everyday use needs only PowerShell.
|
Live**, for PDF output. Everyday use needs only PowerShell.
|
||||||
|
|
||||||
|
This is one of three ways to have Klammertext on Windows. If you are at
|
||||||
|
home in Linux, the Windows Subsystem for Linux gives you the Linux
|
||||||
|
installation unchanged, with the Windows editors and browser alongside:
|
||||||
|
`windows_wsl_install.md`. If you want no build at all, the prebuilt
|
||||||
|
container images run on Windows through Docker Desktop, which that page
|
||||||
|
also describes. This page is the native route: Windows programs, no
|
||||||
|
Linux layer.
|
||||||
|
|
||||||
|
|
||||||
## Prerequisites
|
## Prerequisites
|
||||||
|
|
||||||
@@ -119,10 +127,11 @@ optimizing compiler may run out of memory and report `out of memory
|
|||||||
allocating`. If so, run `make -C com` without `-j`: slower, and it
|
allocating`. If so, run `make -C com` without `-j`: slower, and it
|
||||||
finishes.
|
finishes.
|
||||||
|
|
||||||
This builds the library, the Standard Klammer Set's components and the
|
This builds the library (`klammertext.dll`), the Standard Klammer Set's
|
||||||
three commands into `bin\`, and copies the library and the compiler's
|
components and the three commands (`ktext.exe`, `kdesc.exe`, `kdiag.exe`)
|
||||||
runtime DLLs there too, so `bin\` is self-contained. The Python binding is
|
into `bin\`, and copies the library and the compiler's runtime DLLs there
|
||||||
built into `kpy\`. Verify:
|
too, so `bin\` is self-contained. The Python binding is built into `kpy\`.
|
||||||
|
Verify:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
ktext -s '@eval 1 + 1 @' -d # prints 2
|
ktext -s '@eval 1 + 1 @' -d # prints 2
|
||||||
@@ -221,21 +230,37 @@ ktext hello.kt -t pdf # writes hello.pdf
|
|||||||
## Using the commands from PowerShell
|
## Using the commands from PowerShell
|
||||||
|
|
||||||
Building needs the UCRT64 shell; using Klammertext does not. For everyday
|
Building needs the UCRT64 shell; using Klammertext does not. For everyday
|
||||||
use from PowerShell, put three directories on the `Path` and set
|
use from PowerShell, put two directories on the `Path` and set
|
||||||
`KLAMMERTEXT_HOME`, once, as user environment variables (Settings ▸
|
`KLAMMERTEXT_HOME`, once, as user environment variables (Settings ▸
|
||||||
System ▸ About ▸ Advanced system settings ▸ Environment Variables, or with
|
System ▸ About ▸ Advanced system settings ▸ Environment Variables, or
|
||||||
`setx`):
|
from PowerShell):
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
setx KLAMMERTEXT_HOME "C:\Users\<you>\klammertext"
|
[Environment]::SetEnvironmentVariable("KLAMMERTEXT_HOME", "C:\Users\<you>\klammertext", "User")
|
||||||
setx Path "$env:Path;C:\Users\<you>\klammertext\bin;C:\Users\<you>\external\texlive\2026\bin\windows"
|
$p = [Environment]::GetEnvironmentVariable("Path", "User")
|
||||||
|
[Environment]::SetEnvironmentVariable("Path", "$p;C:\Users\<you>\klammertext\bin;C:\Users\<you>\external\texlive\2026\bin\windows", "User")
|
||||||
```
|
```
|
||||||
|
|
||||||
Python is already on the `Path` from its installer. Open a new PowerShell
|
(Not `setx Path "$env:Path;…"`: `$env:Path` is the machine and user
|
||||||
|
values merged, so that copies every machine entry into your user `Path`,
|
||||||
|
and `setx` silently cuts a value over 1024 characters.) Python is already
|
||||||
|
on the `Path` from its installer. Open a new PowerShell
|
||||||
window and `ktext`, `kdesc` and `kdiag` work there directly. Paths
|
window and `ktext`, `kdesc` and `kdiag` work there directly. Paths
|
||||||
Klammertext prints use forward slashes on every system; paths you type may
|
Klammertext prints use forward slashes on every system; paths you type may
|
||||||
use either.
|
use either.
|
||||||
|
|
||||||
|
One PowerShell rule to know when you pass Klammertext text with `-s`: an
|
||||||
|
apostrophe inside a single-quoted string ends the string, so `It's` must
|
||||||
|
be written `It''s` (two apostrophes), or the whole text put in double
|
||||||
|
quotes. The error you get otherwise mentions a "here-string header",
|
||||||
|
because PowerShell reads the next `@'` as one; it is PowerShell's message,
|
||||||
|
not Klammertext's.
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
ktext -s '@i It''s a Pyrrhic victory! @' -d
|
||||||
|
ktext -s "@i It's a Pyrrhic victory! @" -d
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
## Verifying the installation
|
## Verifying the installation
|
||||||
|
|
||||||
@@ -250,12 +275,12 @@ ktext hello.kt -t html # html
|
|||||||
ktext hello.kt -t pdf # pdf, requires TeX Live
|
ktext hello.kt -t pdf # pdf, requires TeX Live
|
||||||
|
|
||||||
make -C $KLAMMERTEXT_HOME/tst test # the engine's test suites
|
make -C $KLAMMERTEXT_HOME/tst test # the engine's test suites
|
||||||
make -C $KLAMMERTEXT_HOME/sks/tst test # the Standard Klammer Set's suites (needs TeX Live)
|
|
||||||
```
|
```
|
||||||
|
|
||||||
A few suite cases report `SKIP` on Windows for things the MSYS2 shell
|
A few suite cases report `SKIP` on Windows for things the MSYS2 shell
|
||||||
cannot provide, such as a real terminal for the colour tests or a
|
cannot provide, such as a real terminal for the colour tests or a
|
||||||
symbolic link; that is expected.
|
symbolic link; that is expected. (The Standard Klammer Set's own suites
|
||||||
|
are part of the development repository, not of this distribution.)
|
||||||
|
|
||||||
|
|
||||||
## Updating
|
## Updating
|
||||||
@@ -269,6 +294,56 @@ make -C com -j
|
|||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Editor support
|
||||||
|
|
||||||
|
Klammertext's editor support (`doc\edit\`, one shared implementation
|
||||||
|
behind VS Code, Sublime Text, Vim and Emacs integrations) works on Windows
|
||||||
|
with the Python already installed. Each editor's README in `doc\edit\`
|
||||||
|
has the details; the Windows-specific steps are these.
|
||||||
|
|
||||||
|
**Visual Studio Code.** Build the extension package in the UCRT64 shell,
|
||||||
|
then install it from PowerShell (or from any window where `code` is on the
|
||||||
|
`Path`):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd ~/klammertext/doc/edit/vscode && ./make_vsix.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
code --install-extension C:\Users\<you>\klammertext\doc\edit\vscode\klammertext.vsix
|
||||||
|
```
|
||||||
|
|
||||||
|
Reload VS Code. The extension runs `python` from the `Path` and finds the
|
||||||
|
language server inside the package; nothing needs configuring.
|
||||||
|
|
||||||
|
**Sublime Text 4.** Copy the package and the shared core into Sublime's
|
||||||
|
`Packages` directory (**Preferences → Browse Packages…** opens it):
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
$p = "$env:AppData\Sublime Text\Packages\Klammertext"
|
||||||
|
New-Item -ItemType Directory -Force $p | Out-Null
|
||||||
|
Copy-Item C:\Users\<you>\klammertext\doc\edit\sublime\* $p
|
||||||
|
Copy-Item C:\Users\<you>\klammertext\doc\edit\shared\klammertext_edit.py $p
|
||||||
|
```
|
||||||
|
|
||||||
|
Sublime loads the package live.
|
||||||
|
|
||||||
|
**Notepad++.** Highlighting comes from a User Defined Language file, the
|
||||||
|
delimiter check and reindentation from two Run-menu commands
|
||||||
|
(`doc\edit\notepadpp\README.md` has both):
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
$d = "$env:AppData\Notepad++\userDefineLangs"
|
||||||
|
New-Item -ItemType Directory -Force $d | Out-Null
|
||||||
|
Copy-Item C:\Users\<you>\klammertext\doc\edit\notepadpp\Klammertext.udl.xml $d
|
||||||
|
```
|
||||||
|
|
||||||
|
Restart Notepad++; `.kt` and `.k` files open as Klammertext.
|
||||||
|
|
||||||
|
**Vim.** As in `doc\edit\vim\README.md`; the plugin runs the shared core
|
||||||
|
through `python` on Windows automatically.
|
||||||
|
|
||||||
|
|
||||||
## Troubleshooting
|
## Troubleshooting
|
||||||
|
|
||||||
**The command window closes at once, or "The code execution cannot proceed
|
**The command window closes at once, or "The code execution cannot proceed
|
||||||
@@ -282,7 +357,7 @@ runtime, which nearly every Windows machine already has but a freshly
|
|||||||
installed one may not. Install it from
|
installed one may not. Install it from
|
||||||
https://aka.ms/vs/17/release/vc_redist.x64.exe and try the import again.
|
https://aka.ms/vs/17/release/vc_redist.x64.exe and try the import again.
|
||||||
|
|
||||||
**"libklammertext.so was not found" or "libstdc++-6.dll was not found".**
|
**"klammertext.dll was not found" or "libstdc++-6.dll was not found".**
|
||||||
`bin\` is not on the `Path`, or the build did not finish: `make -C com -j`
|
`bin\` is not on the `Path`, or the build did not finish: `make -C com -j`
|
||||||
places the library and the runtime DLLs in `bin\` beside the commands.
|
places the library and the runtime DLLs in `bin\` beside the commands.
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,153 @@
|
|||||||
|
# Klammertext on Windows through the Windows Subsystem for Linux
|
||||||
|
|
||||||
|
This page is for someone who works in Linux by habit and has a Windows
|
||||||
|
machine to work on. The Windows Subsystem for Linux (WSL 2) runs a real
|
||||||
|
Linux kernel and an ordinary Ubuntu inside Windows, and Klammertext's
|
||||||
|
Linux installation applies there unchanged: the same compiler, the same
|
||||||
|
Python, the same TeX Live, the same `runtime.env`. So this page is short.
|
||||||
|
It gets you to an Ubuntu prompt, sends you to the Linux page, and then
|
||||||
|
says what is specific to living in WSL: where files belong, how to look
|
||||||
|
at the output from Windows, and how the Windows editors reach the Linux
|
||||||
|
side. The steps were followed on a Windows 11 machine with WSL 2.7 and
|
||||||
|
the Ubuntu it installs today, 26.04.
|
||||||
|
|
||||||
|
There are two other ways to have Klammertext on Windows: as native
|
||||||
|
Windows programs built from source (`windows_source_install.md`), and
|
||||||
|
from the prebuilt container images, which this page covers at the end,
|
||||||
|
since Docker runs inside WSL as it runs on Linux.
|
||||||
|
|
||||||
|
|
||||||
|
## Getting Linux
|
||||||
|
|
||||||
|
In a PowerShell window:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
wsl --install
|
||||||
|
```
|
||||||
|
|
||||||
|
This turns on the subsystem, installs the WSL layer and the current
|
||||||
|
Ubuntu, and may ask you to restart Windows; do that before going on.
|
||||||
|
Then open a terminal and type `wsl` (or start "Ubuntu" from the Start
|
||||||
|
menu). The first start asks for a Linux username and a password; these
|
||||||
|
are separate from your Windows account. Ubuntu may also ask whether to
|
||||||
|
send platform metrics; you can say no. You are then at a bash prompt in
|
||||||
|
your Linux home directory, and `wsl -l -v` in PowerShell shows Ubuntu as
|
||||||
|
version 2.
|
||||||
|
|
||||||
|
Two things worth knowing about the Ubuntu you now have: `sudo` works with
|
||||||
|
the password you just chose, and the machine's Windows `Path` is appended
|
||||||
|
to the Linux `PATH`, so Windows programs can be run from the Linux prompt
|
||||||
|
by name (`explorer.exe`, `code`). That is convenient below and harmless
|
||||||
|
otherwise; a Windows Python or TeX Live on the machine is not picked up
|
||||||
|
by Linux, since Linux does not resolve `.exe` names.
|
||||||
|
|
||||||
|
|
||||||
|
## Installing Klammertext
|
||||||
|
|
||||||
|
Follow `linux_source_install.md` at the Ubuntu prompt, from its first
|
||||||
|
line. Everything on it applies: the packages by `apt-get`, the clone, the
|
||||||
|
line in `~/.bashrc` that sources `runtime.env`, the build, TeX Live by the
|
||||||
|
bundled script, the verification. Nothing on that page is different
|
||||||
|
inside WSL. On the machine this page was written on, the build took under
|
||||||
|
a minute and TeX Live nine, and the engine's test suite passed as it does
|
||||||
|
on Linux.
|
||||||
|
|
||||||
|
Keep the clone and your documents in the Linux file system, under your
|
||||||
|
Linux home, not under `/mnt/c`. The Windows drives are mounted there and
|
||||||
|
work, but every file operation crosses between the two systems, and a
|
||||||
|
build or a PDF run on `/mnt/c` is several times slower.
|
||||||
|
|
||||||
|
|
||||||
|
## Seeing the output from Windows
|
||||||
|
|
||||||
|
WSL has no browser or PDF viewer of its own, and it needs none. Windows
|
||||||
|
sees the Linux file system as a network path, `\\wsl.localhost\Ubuntu\`,
|
||||||
|
and Windows programs can open files there. From the Linux prompt, after
|
||||||
|
`ktext hello.kt -t html` and `ktext hello.kt -t pdf`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# at the Ubuntu prompt (type wsl in PowerShell to get there), not in PowerShell
|
||||||
|
explorer.exe "$(wslpath -w hello/index.html)"
|
||||||
|
explorer.exe "$(wslpath -w hello.pdf)"
|
||||||
|
```
|
||||||
|
|
||||||
|
`wslpath -w` turns a Linux path into the Windows form of the same file,
|
||||||
|
and `explorer.exe` opens it with whatever Windows opens that kind of file
|
||||||
|
with: your browser, your PDF viewer. The first time, Windows may ask
|
||||||
|
which application to use. `explorer.exe .` opens the current Linux
|
||||||
|
directory in Explorer, and from the Windows side the same files are in
|
||||||
|
Explorer under "Linux" in the sidebar. (`explorer.exe` reports exit
|
||||||
|
status 1 even when it succeeds; a script that needs a true status can use
|
||||||
|
`powershell.exe -NoProfile -Command "Start-Process \"$(wslpath -w hello.pdf)\""`
|
||||||
|
instead.)
|
||||||
|
|
||||||
|
|
||||||
|
## Editors
|
||||||
|
|
||||||
|
The Windows editors reach the Linux side, and the Linux editors are
|
||||||
|
simply there.
|
||||||
|
|
||||||
|
**Visual Studio Code**, the case this page was written for. Install VS
|
||||||
|
Code on Windows and its "WSL" extension (Microsoft's
|
||||||
|
`ms-vscode-remote.remote-wsl`). Then, at the Linux prompt, in the
|
||||||
|
directory you want to work in:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
code .
|
||||||
|
```
|
||||||
|
|
||||||
|
The first time, this installs VS Code's Linux-side server into your
|
||||||
|
Linux home and opens a VS Code window on Windows connected to it. The
|
||||||
|
Klammertext extension is installed on that Linux side, once, from the
|
||||||
|
package built in the clone:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd ~/klammertext/doc/edit/vscode && ./make_vsix.sh && code --install-extension klammertext.vsix
|
||||||
|
```
|
||||||
|
|
||||||
|
Run from the Linux prompt, `code --install-extension` installs to the
|
||||||
|
WSL side, where the extension then starts the Klammertext language
|
||||||
|
server with the Linux `python3`; everything in `doc/edit/vscode/README.md`
|
||||||
|
applies as on Linux. (Extensions installed on the Windows side of VS Code
|
||||||
|
are a separate list and do not run in WSL windows.)
|
||||||
|
|
||||||
|
**Emacs and Vim** are Linux programs: `sudo apt-get install emacs` or
|
||||||
|
`vim`, then the Emacs and Vim packages under `doc/edit/` as on Linux.
|
||||||
|
|
||||||
|
**Sublime Text and Notepad++** on Windows can open the Linux files
|
||||||
|
through `\\wsl.localhost\Ubuntu\...` and highlight them with their
|
||||||
|
Klammertext packages (`doc/edit/sublime/`, `doc/edit/notepadpp/`); their
|
||||||
|
commands that run the shared core would run the Windows `python`, so for
|
||||||
|
those two editors the native Windows installation is the better fit.
|
||||||
|
|
||||||
|
|
||||||
|
## The container route
|
||||||
|
|
||||||
|
If you would rather not build anything, the prebuilt Klammertext images
|
||||||
|
run inside WSL exactly as `linux_container_install.md` describes, since
|
||||||
|
the Ubuntu WSL installs today runs systemd and therefore Docker's
|
||||||
|
service: follow that page at the Ubuntu prompt, from `apt-get install
|
||||||
|
docker.io` on. That was done on the machine this page was written on:
|
||||||
|
the image, 2.4 GB with its TeX Live, pulled in about a minute, and its
|
||||||
|
`ktext` made the page's web page and PDF, owned by the Linux user. Docker
|
||||||
|
Desktop for Windows is the other way to run the same images; its engine
|
||||||
|
is WSL 2 as well, and it has its own licence terms for larger companies.
|
||||||
|
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
**`wsl --install` says virtualization is not enabled.** WSL 2 needs the
|
||||||
|
CPU's virtualization support turned on in the machine's firmware
|
||||||
|
settings; the name varies (Intel VT-x, AMD-V, SVM). Turn it on and run
|
||||||
|
the command again.
|
||||||
|
|
||||||
|
**`code .` says the command is not found.** VS Code's `bin` directory is
|
||||||
|
put on the Windows `Path` by its installer; open a new WSL terminal after
|
||||||
|
installing VS Code, so the Linux `PATH` picks it up.
|
||||||
|
|
||||||
|
**A build or a PDF run is slow.** The clone or the document is under
|
||||||
|
`/mnt/c`. Move it under your Linux home.
|
||||||
|
|
||||||
|
**The Ubuntu window asks for a username again.** The distribution was
|
||||||
|
reset or reinstalled; the setup creates a fresh Linux home, and
|
||||||
|
Klammertext must be installed again inside it.
|
||||||
Vendored
+26
-6
@@ -63,14 +63,16 @@ SHARED = -dynamiclib
|
|||||||
SONAME = -install_name @rpath/$(notdir $@)
|
SONAME = -install_name @rpath/$(notdir $@)
|
||||||
ORIGIN := @loader_path
|
ORIGIN := @loader_path
|
||||||
EXPORT_DYNAMIC = -Wl,-export_dynamic
|
EXPORT_DYNAMIC = -Wl,-export_dynamic
|
||||||
|
EXE :=
|
||||||
|
DSO := .so
|
||||||
|
KLAMMERTEXT_LIBFILE := libklammertext.so
|
||||||
else ifneq (,$(filter MINGW% MSYS%,$(UNAME_S)))
|
else ifneq (,$(filter MINGW% MSYS%,$(UNAME_S)))
|
||||||
# ---------- Windows (MSYS2, UCRT64 environment; native PE binaries) ----------
|
# ---------- Windows (MSYS2, UCRT64 environment; native PE binaries) ----------
|
||||||
# uname says MINGW64_NT-... under UCRT64 too. The compilers come from the
|
# uname says MINGW64_NT-... under UCRT64 too. The compilers come from the
|
||||||
# environment's PATH (/ucrt64/bin). libdl.a is the mingw-w64-dlfcn shim over
|
# environment's PATH (/ucrt64/bin). libdl.a is the mingw-w64-dlfcn shim over
|
||||||
# LoadLibrary, linked statically so no libdl.dll travels with the products.
|
# LoadLibrary, linked statically so no libdl.dll travels with the products.
|
||||||
# PE has no soname and no rpath; a DLL is found through PATH or
|
# PE has no soname and no rpath; a DLL is found through PATH or
|
||||||
# the executable's own directory, and GNU ld's -l search list on PE does not
|
# the executable's own directory.
|
||||||
# include ".so", hence the exact-name form below.
|
|
||||||
GCC := g++
|
GCC := g++
|
||||||
CLANG := clang++
|
CLANG := clang++
|
||||||
LDFLAGS =
|
LDFLAGS =
|
||||||
@@ -79,15 +81,20 @@ SHARED = -shared
|
|||||||
SONAME =
|
SONAME =
|
||||||
ORIGIN := $$ORIGIN
|
ORIGIN := $$ORIGIN
|
||||||
EXPORT_DYNAMIC = -Wl,--export-all-symbols
|
EXPORT_DYNAMIC = -Wl,--export-all-symbols
|
||||||
KLAMMERTEXT_LIB = -l:libklammertext.so
|
EXE := .exe
|
||||||
|
DSO := .dll
|
||||||
|
KLAMMERTEXT_LIBFILE := klammertext.dll
|
||||||
# A Windows program finds a DLL through PATH or its own directory, never an
|
# A Windows program finds a DLL through PATH or its own directory, never an
|
||||||
# rpath. So every directory that holds a program or a Python extension also
|
# rpath. So every directory that holds a program or a Python extension also
|
||||||
# holds the DLLs it needs: libklammertext.so and the three gcc runtime DLLs
|
# holds the DLLs it needs: klammertext.dll and the three gcc runtime DLLs
|
||||||
# the toolchain links (from the compiler's own bin/). com/ and kpy/ copy them.
|
# the toolchain links (from the compiler's own bin/). com/ and kpy/ copy them.
|
||||||
GCC_BIN := $(dir $(shell cygpath -m "$$(command -v g++)"))
|
GCC_BIN := $(dir $(shell cygpath -m "$$(command -v g++)"))
|
||||||
GCC_RUNTIME_DLLS := libstdc++-6.dll libgcc_s_seh-1.dll libwinpthread-1.dll
|
GCC_RUNTIME_DLLS := libstdc++-6.dll libgcc_s_seh-1.dll libwinpthread-1.dll
|
||||||
else
|
else
|
||||||
# ---------- Linux ----------
|
# ---------- Linux ----------
|
||||||
|
EXE :=
|
||||||
|
DSO := .so
|
||||||
|
KLAMMERTEXT_LIBFILE := libklammertext.so
|
||||||
GCC := /usr/bin/g++
|
GCC := /usr/bin/g++
|
||||||
CLANG := $(shell command -v clang++-18 2>/dev/null || command -v clang++ 2>/dev/null)
|
CLANG := $(shell command -v clang++-18 2>/dev/null || command -v clang++ 2>/dev/null)
|
||||||
LDFLAGS = -L/usr/lib/x86_64-linux-gnu
|
LDFLAGS = -L/usr/lib/x86_64-linux-gnu
|
||||||
@@ -97,8 +104,21 @@ SONAME = -Wl,-soname,$(notdir $@)
|
|||||||
ORIGIN := $$ORIGIN
|
ORIGIN := $$ORIGIN
|
||||||
EXPORT_DYNAMIC = -rdynamic
|
EXPORT_DYNAMIC = -rdynamic
|
||||||
endif
|
endif
|
||||||
# How a link line names libklammertext (set above for Windows).
|
# Product names (decided 2026-09-25: Windows users get Windows names). The
|
||||||
KLAMMERTEXT_LIB ?= -lklammertext
|
# three variables above are set per platform: EXE is the executable suffix
|
||||||
|
# (".exe" on Windows, none elsewhere), DSO the suffix of a shared object
|
||||||
|
# loaded at run time (".dll" / ".so": document$(DSO), reflect$(DSO)), and
|
||||||
|
# KLAMMERTEXT_LIBFILE the library's file name (klammertext.dll /
|
||||||
|
# libklammertext.so). A make target carries the suffix so that the file the
|
||||||
|
# compiler writes IS the target: bin/ktext never existed on Windows -- gcc
|
||||||
|
# wrote ktext.exe -- and every make relinked the three commands. The engine's
|
||||||
|
# own copy of the DSO suffix is shared_library_suffix in mac/file.h.
|
||||||
|
#
|
||||||
|
# One link form everywhere: GNU ld's -l search list on PE ends with
|
||||||
|
# "<name>.dll", so -lklammertext finds klammertext.dll as it finds
|
||||||
|
# libklammertext.so on Linux (it did NOT find a DLL called libklammertext.so,
|
||||||
|
# which needed the exact-name -l: form).
|
||||||
|
KLAMMERTEXT_LIB = -lklammertext
|
||||||
|
|
||||||
# Resolve the compiler choice (gcc by default; clang with COMPILER=clang).
|
# Resolve the compiler choice (gcc by default; clang with COMPILER=clang).
|
||||||
CXX := $(if $(filter clang,$(COMPILER)),$(CLANG),$(GCC))
|
CXX := $(if $(filter clang,$(COMPILER)),$(CLANG),$(GCC))
|
||||||
+6
-6
@@ -1,8 +1,8 @@
|
|||||||
# kpy/ -- the Python binding of the Klammermachine.
|
# kpy/ -- the Python binding of the Klammermachine.
|
||||||
#
|
#
|
||||||
# klammertext.cpp is a CPython extension module (see its header comment).
|
# klammertext.cpp is a CPython extension module (see its header comment).
|
||||||
# Like ref/reflect.so and sks/document/document.so it links against
|
# Like ref/reflect$(DSO) and sks/document/document$(DSO) it links against
|
||||||
# libklammertext.so and shares the engine's class layouts, so it is rebuilt
|
# the shared library and shares the engine's class layouts, so it is rebuilt
|
||||||
# whenever they are (mac/Makefile's "all" runs "make -C kpy"; com/Makefile's
|
# whenever they are (mac/Makefile's "all" runs "make -C kpy"; com/Makefile's
|
||||||
# "redo" and dev/rebuild.sh clean it -- a clean that misses a directory is a
|
# "redo" and dev/rebuild.sh clean it -- a clean that misses a directory is a
|
||||||
# mixed-object hazard, not a tidiness one).
|
# mixed-object hazard, not a tidiness one).
|
||||||
@@ -19,7 +19,7 @@ K := $(KLAMMERTEXT_HOME)
|
|||||||
include $(K)/env/makefile.env
|
include $(K)/env/makefile.env
|
||||||
|
|
||||||
LIBDIR := $(K)/lib
|
LIBDIR := $(K)/lib
|
||||||
LIBRARY := $(LIBDIR)/libklammertext.so
|
LIBRARY := $(LIBDIR)/$(KLAMMERTEXT_LIBFILE)
|
||||||
|
|
||||||
EXT_SUFFIX := $(shell $(PYTHON) -c 'import sysconfig; print(sysconfig.get_config_var("EXT_SUFFIX"))')
|
EXT_SUFFIX := $(shell $(PYTHON) -c 'import sysconfig; print(sysconfig.get_config_var("EXT_SUFFIX"))')
|
||||||
MODULE := klammertext$(EXT_SUFFIX)
|
MODULE := klammertext$(EXT_SUFFIX)
|
||||||
@@ -38,7 +38,7 @@ DEPFLAGS = -MMD -MP -MF $(@:.o=.d)
|
|||||||
# extension's dependencies from the extension's own directory, never from
|
# extension's dependencies from the extension's own directory, never from
|
||||||
# PATH or an rpath -- there is none on PE); see makefile.env.
|
# PATH or an rpath -- there is none on PE); see makefile.env.
|
||||||
ifneq (,$(filter MINGW% MSYS%,$(UNAME_S)))
|
ifneq (,$(filter MINGW% MSYS%,$(UNAME_S)))
|
||||||
BESIDE_DLLS := libklammertext.so $(GCC_RUNTIME_DLLS)
|
BESIDE_DLLS := $(KLAMMERTEXT_LIBFILE) $(GCC_RUNTIME_DLLS)
|
||||||
else
|
else
|
||||||
BESIDE_DLLS :=
|
BESIDE_DLLS :=
|
||||||
endif
|
endif
|
||||||
@@ -54,14 +54,14 @@ $(MODULE) : $(OBJECTS) $(LIBRARY)
|
|||||||
-o $@ $(OBJECTS) $(KLAMMERTEXT_LIB) $(LDLIBS)
|
-o $@ $(OBJECTS) $(KLAMMERTEXT_LIB) $(LDLIBS)
|
||||||
|
|
||||||
ifneq (,$(filter MINGW% MSYS%,$(UNAME_S)))
|
ifneq (,$(filter MINGW% MSYS%,$(UNAME_S)))
|
||||||
libklammertext.so : $(LIBRARY)
|
$(KLAMMERTEXT_LIBFILE) : $(LIBRARY)
|
||||||
cp $< $@
|
cp $< $@
|
||||||
%.dll : $(GCC_BIN)%.dll
|
%.dll : $(GCC_BIN)%.dll
|
||||||
cp $< $@
|
cp $< $@
|
||||||
endif
|
endif
|
||||||
|
|
||||||
clean :
|
clean :
|
||||||
rm -f $(OBJECTS) $(DEPFILES) klammertext.*.so klammertext.*.pyd libklammertext.so *.dll *~
|
rm -f $(OBJECTS) $(DEPFILES) klammertext.*.so klammertext.*.pyd *.dll *~
|
||||||
rm -rf __pycache__
|
rm -rf __pycache__
|
||||||
|
|
||||||
-include $(DEPFILES)
|
-include $(DEPFILES)
|
||||||
+2
-2
@@ -1,5 +1,5 @@
|
|||||||
# lib
|
# lib
|
||||||
|
|
||||||
This directory holds the compiled Klammermachine shared library
|
This directory holds the compiled Klammermachine shared library
|
||||||
(`libklammertext.so`) after you build Klammertext with `make -C com`.
|
(`libklammertext.so`; on Windows `klammertext.dll`) after you build
|
||||||
It is empty in the repository.
|
Klammertext with `make -C com`. It is empty in the repository.
|
||||||
+1
-1
@@ -21,7 +21,7 @@ DEPFILES := $(addsuffix .d,$(BASENAMES))
|
|||||||
|
|
||||||
# Shared library
|
# Shared library
|
||||||
LIBDIR := ../lib
|
LIBDIR := ../lib
|
||||||
LIBRARY := $(LIBDIR)/libklammertext.so
|
LIBRARY := $(LIBDIR)/$(KLAMMERTEXT_LIBFILE)
|
||||||
|
|
||||||
# Compiler flags for dependency generation
|
# Compiler flags for dependency generation
|
||||||
DEPFLAGS = -MMD -MP -MF $(@:.o=.d)
|
DEPFLAGS = -MMD -MP -MF $(@:.o=.d)
|
||||||
|
|||||||
@@ -1,7 +1,11 @@
|
|||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
#define NOMINMAX
|
||||||
|
#include <windows.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <io.h>
|
#include <io.h>
|
||||||
#endif
|
#endif
|
||||||
|
#include <cstdlib>
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
|
|
||||||
#include "argv.h"
|
#include "argv.h"
|
||||||
@@ -39,6 +43,26 @@ void set_verbose_level(int argc, char* argv[])
|
|||||||
// byte. The C runtime's text mode would append it to every line.
|
// byte. The C runtime's text mode would append it to every line.
|
||||||
_setmode(_fileno(stdout), _O_BINARY);
|
_setmode(_fileno(stdout), _O_BINARY);
|
||||||
_setmode(_fileno(stderr), _O_BINARY);
|
_setmode(_fileno(stderr), _O_BINARY);
|
||||||
|
// A console decodes what a program writes in the CONSOLE's output code
|
||||||
|
// page, which on a localized Windows is an OEM page (850 on a German one)
|
||||||
|
// and never UTF-8, whatever the process's own code page (the manifest
|
||||||
|
// makes that UTF-8). The commands write UTF-8 -- kdesc --katoms's
|
||||||
|
// ⟨name⟩, an error report's ⟨katom⟩ -- so a console showed three cp850
|
||||||
|
// characters per symbol while a file or a pipe received the right bytes
|
||||||
|
// (which is why no suite saw it; Andy did, 2026-09-25). Switch the
|
||||||
|
// console to UTF-8 while a command runs, when a stream is a console, and
|
||||||
|
// put it back at exit: the page belongs to the console, not the process,
|
||||||
|
// and would outlive it.
|
||||||
|
static UINT console_output_cp = 0;
|
||||||
|
static UINT console_output_cp_now = 0;
|
||||||
|
if (_isatty(_fileno(stdout)) || _isatty(_fileno(stderr))) {
|
||||||
|
console_output_cp = GetConsoleOutputCP();
|
||||||
|
if (console_output_cp != 0 && console_output_cp != CP_UTF8) {
|
||||||
|
SetConsoleOutputCP(CP_UTF8);
|
||||||
|
console_output_cp_now = GetConsoleOutputCP();
|
||||||
|
std::atexit([] { SetConsoleOutputCP(console_output_cp); });
|
||||||
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
//command_name = absolute_pathname(argv[0]);
|
//command_name = absolute_pathname(argv[0]);
|
||||||
command_name = fs::path(argv[0]).generic_string();
|
command_name = fs::path(argv[0]).generic_string();
|
||||||
@@ -49,6 +73,13 @@ void set_verbose_level(int argc, char* argv[])
|
|||||||
args.opt("v", "'verbosity'", "level", "0", "'verbosity'");
|
args.opt("v", "'verbosity'", "level", "0", "'verbosity'");
|
||||||
args.parse(argc, argv, false);
|
args.parse(argc, argv, false);
|
||||||
verbose_level = args.as_verbosity("v");
|
verbose_level = args.as_verbosity("v");
|
||||||
|
#ifdef _WIN32
|
||||||
|
if (console_output_cp != 0 && console_output_cp != CP_UTF8) {
|
||||||
|
K::log(1, "Console output code page set to UTF-8 for this run (was "
|
||||||
|
+ std::to_string(console_output_cp) + ", now "
|
||||||
|
+ std::to_string(console_output_cp_now) + ")");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool show_usage(int argc, char* argv[])
|
bool show_usage(int argc, char* argv[])
|
||||||
|
|||||||
+1
-1
@@ -320,7 +320,7 @@ std::string Eval::eval_command(katom_iter begin, katom_iter end)
|
|||||||
if (!khome.empty()) {
|
if (!khome.empty()) {
|
||||||
lib_text = string_replace(lib_text, "*KLAMMERTEXT_HOME*", khome);
|
lib_text = string_replace(lib_text, "*KLAMMERTEXT_HOME*", khome);
|
||||||
}
|
}
|
||||||
fs::path libpath(lib_text + ".so");
|
fs::path libpath(lib_text + shared_library_suffix);
|
||||||
// A relative library name not found from the cwd is searched in the
|
// A relative library name not found from the cwd is searched in the
|
||||||
// directories of the files the Machine has read (same rule as the
|
// directories of the files the Machine has read (same rule as the
|
||||||
// Python module path: the library lives next to the file using it).
|
// Python module path: the library lives next to the file using it).
|
||||||
|
|||||||
+6
-3
@@ -72,14 +72,17 @@ size_t count_substrings(const std::string& text, const std::string& substring) {
|
|||||||
|
|
||||||
std::string home_directory()
|
std::string home_directory()
|
||||||
{
|
{
|
||||||
if (const char* home = std::getenv("HOME"); home && *home) {
|
|
||||||
return home;
|
|
||||||
}
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
// USERPROFILE first: an MSYS2 shell may set HOME to its own /home/<user>
|
||||||
|
// (C:\msys64\home\<user>), and a Windows user's ~/.klammertext must be
|
||||||
|
// the same directory from PowerShell and from that shell.
|
||||||
if (const char* profile = std::getenv("USERPROFILE"); profile && *profile) {
|
if (const char* profile = std::getenv("USERPROFILE"); profile && *profile) {
|
||||||
return profile;
|
return profile;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
if (const char* home = std::getenv("HOME"); home && *home) {
|
||||||
|
return home;
|
||||||
|
}
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+11
-3
@@ -25,9 +25,17 @@ constexpr char path_list_separator = ';';
|
|||||||
#else
|
#else
|
||||||
constexpr char path_list_separator = ':';
|
constexpr char path_list_separator = ':';
|
||||||
#endif
|
#endif
|
||||||
// The user's home directory as the system names it: HOME, and on Windows
|
// The suffix of a shared library loaded at run time (the library a
|
||||||
// USERPROFILE when HOME is unset (a plain PowerShell or cmd sets no HOME;
|
// "@eval :cpp" names): ".dll" on Windows, ".so" everywhere else -- the same
|
||||||
// an MSYS2 shell does). Empty when neither is set.
|
// choice makefile.env's DSO makes when it builds one.
|
||||||
|
#ifdef _WIN32
|
||||||
|
constexpr const char* shared_library_suffix = ".dll";
|
||||||
|
#else
|
||||||
|
constexpr const char* shared_library_suffix = ".so";
|
||||||
|
#endif
|
||||||
|
// The user's home directory as the system names it: HOME; on Windows
|
||||||
|
// USERPROFILE first, so the directory is the same from PowerShell (no HOME)
|
||||||
|
// and from an MSYS2 shell (which may set HOME to its own /home/<user>).
|
||||||
std::string home_directory();
|
std::string home_directory();
|
||||||
// The first PROGRAM on PATH (split on path_list_separator; on Windows the
|
// The first PROGRAM on PATH (split on path_list_separator; on Windows the
|
||||||
// name also tried with ".exe"), or "" when none: what "which" answers, without
|
// name also tried with ".exe"), or "" when none: what "which" answers, without
|
||||||
|
|||||||
+9
-7
@@ -4,7 +4,8 @@
|
|||||||
# character tables and return Klammertext (a "@table" call and such), which
|
# character tables and return Klammertext (a "@table" call and such), which
|
||||||
# the .kt fragments in this directory then render for whichever target is
|
# the .kt fragments in this directory then render for whichever target is
|
||||||
# in force. They are reached through "@eval :cpp", so this builds a DSO
|
# in force. They are reached through "@eval :cpp", so this builds a DSO
|
||||||
# loaded at run time, not part of libklammertext.so.
|
# loaded at run time, not part of the shared library: reflect.so, on
|
||||||
|
# Windows reflect.dll (makefile.env's DSO).
|
||||||
#
|
#
|
||||||
# Adapted from sks/document/Makefile. Two things differ and both matter:
|
# Adapted from sks/document/Makefile. Two things differ and both matter:
|
||||||
# ref/ has no sks dependencies (a generator returns Klammertext, so it
|
# ref/ has no sks dependencies (a generator returns Klammertext, so it
|
||||||
@@ -19,10 +20,11 @@ include $(K)/env/makefile.env
|
|||||||
# reflect.cpp includes (machine, character, error, show). No local -I.
|
# reflect.cpp includes (machine, character, error, show). No local -I.
|
||||||
|
|
||||||
LIBDIR := $(K)/lib
|
LIBDIR := $(K)/lib
|
||||||
LIBRARY := $(LIBDIR)/libklammertext.so
|
LIBRARY := $(LIBDIR)/$(KLAMMERTEXT_LIBFILE)
|
||||||
|
REFLECT := reflect$(DSO)
|
||||||
|
|
||||||
# "../lib", not "../../lib": reflect.so sits in $(K)/ref, so one level up
|
# "../lib", not "../../lib": the DSO sits in $(K)/ref, so one level up
|
||||||
# reaches $(K)/lib. (sks/document.so needs two, which is what this was
|
# reaches $(K)/lib. (sks/document's needs two, which is what this was
|
||||||
# copied from -- a wrong rpath here shows up only at dlopen time, and only
|
# copied from -- a wrong rpath here shows up only at dlopen time, and only
|
||||||
# where the loading process does not already have the library.)
|
# where the loading process does not already have the library.)
|
||||||
REF_LDFLAGS := $(SHARED) $(EXPORT_DYNAMIC) -Wl,-rpath,'$(ORIGIN)/../lib' -L$(LIBDIR)
|
REF_LDFLAGS := $(SHARED) $(EXPORT_DYNAMIC) -Wl,-rpath,'$(ORIGIN)/../lib' -L$(LIBDIR)
|
||||||
@@ -34,7 +36,7 @@ DEPFLAGS = -MMD -MP -MF $(@:.o=.d)
|
|||||||
|
|
||||||
.PHONY: all clean
|
.PHONY: all clean
|
||||||
|
|
||||||
all : reflect.so
|
all : $(REFLECT)
|
||||||
|
|
||||||
%.o : %.cpp
|
%.o : %.cpp
|
||||||
@echo Compiling $<
|
@echo Compiling $<
|
||||||
@@ -46,11 +48,11 @@ all : reflect.so
|
|||||||
# for the same file -- compiling reflect.cpp inline AND linking reflect.o --
|
# for the same file -- compiling reflect.cpp inline AND linking reflect.o --
|
||||||
# defines every symbol in it twice. Building through the pattern rule also
|
# defines every symbol in it twice. Building through the pattern rule also
|
||||||
# gets reflect.d, so a header change rebuilds it.
|
# gets reflect.d, so a header change rebuilds it.
|
||||||
reflect.so : $(OBJECTS) $(LIBRARY)
|
$(REFLECT) : $(OBJECTS) $(LIBRARY)
|
||||||
$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(REF_LDFLAGS) $(LDFLAGS) \
|
$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(REF_LDFLAGS) $(LDFLAGS) \
|
||||||
-o $@ $(OBJECTS) $(KLAMMERTEXT_LIB) $(LDLIBS)
|
-o $@ $(OBJECTS) $(KLAMMERTEXT_LIB) $(LDLIBS)
|
||||||
|
|
||||||
clean :
|
clean :
|
||||||
rm -f $(OBJECTS) $(DEPFILES) *.so *~
|
rm -f $(OBJECTS) $(DEPFILES) *.so *.dll *~
|
||||||
|
|
||||||
-include $(DEPFILES)
|
-include $(DEPFILES)
|
||||||
+14
-11
@@ -1,31 +1,34 @@
|
|||||||
# Klammertext sks/ Makefile
|
# Klammertext sks/ Makefile
|
||||||
# Builds all .so files in sks/ subdirectories
|
# Builds all the DSOs (document$(DSO): .so, on Windows .dll) in sks/
|
||||||
|
# subdirectories
|
||||||
|
|
||||||
K := $(KLAMMERTEXT_HOME)
|
K := $(KLAMMERTEXT_HOME)
|
||||||
KS := $(K)/sks
|
KS := $(K)/sks
|
||||||
KM := $(K)/mac
|
KM := $(K)/mac
|
||||||
|
|
||||||
# Shared library that all .so files depend on
|
include $(K)/env/makefile.env
|
||||||
LIBRARY := $(K)/lib/libklammertext.so
|
|
||||||
|
# Shared library that all the DSOs depend on
|
||||||
|
LIBRARY := $(K)/lib/$(KLAMMERTEXT_LIBFILE)
|
||||||
|
|
||||||
# Support directories (build .o files used by other sks/ components)
|
# Support directories (build .o files used by other sks/ components)
|
||||||
SUPPORT_DIRS := kutil target
|
SUPPORT_DIRS := kutil target
|
||||||
|
|
||||||
# Excluded directories:
|
# Excluded directories:
|
||||||
# kutil, target - support directories that build .o files, not .so
|
# kutil, target - support directories that build .o files, not a DSO
|
||||||
# book, phase - obsolete, not updated for libklammertext.so
|
# book, phase - obsolete, not updated for the shared library
|
||||||
|
|
||||||
# Directories that build .so files (excluding support and obsolete directories)
|
# Directories that build a DSO (excluding support and obsolete directories):
|
||||||
# Find all subdirectories with Makefiles that have .so build targets
|
# every subdirectory whose Makefile names its product with makefile.env's
|
||||||
# (look for lines like "xyz.so :" or "all : xyz.so")
|
# $(DSO) suffix ("document$(DSO) :", "all : document$(DSO)").
|
||||||
SO_DIRS := $(shell for dir in $(KS)/*/; do \
|
SO_DIRS := $(shell for dir in $(KS)/*/; do \
|
||||||
if [ -f "$${dir}Makefile" ] && grep -qE '^[a-z]+\.so\s*:|all\s*:.*\.so' "$${dir}Makefile" 2>/dev/null; then \
|
if [ -f "$${dir}Makefile" ] && grep -qE '\$$\(DSO\)' "$${dir}Makefile" 2>/dev/null; then \
|
||||||
basename "$$dir"; \
|
basename "$$dir"; \
|
||||||
fi; done | grep -v -E '^(kutil|target|book|phase)$$')
|
fi; done | grep -v -E '^(kutil|target|book|phase)$$')
|
||||||
|
|
||||||
.PHONY: all clean support $(SUPPORT_DIRS) $(SO_DIRS)
|
.PHONY: all clean support $(SUPPORT_DIRS) $(SO_DIRS)
|
||||||
|
|
||||||
# Default target: build support first, then all .so files
|
# Default target: build support first, then every DSO
|
||||||
all : support $(SO_DIRS)
|
all : support $(SO_DIRS)
|
||||||
|
|
||||||
# Build support directories
|
# Build support directories
|
||||||
@@ -37,7 +40,7 @@ kutil :
|
|||||||
target : kutil
|
target : kutil
|
||||||
$(MAKE) -j -C $(KS)/target
|
$(MAKE) -j -C $(KS)/target
|
||||||
|
|
||||||
# Pattern rule for .so directories
|
# Pattern rule for the DSO directories
|
||||||
# Each depends on the library and support directories
|
# Each depends on the library and support directories
|
||||||
$(SO_DIRS) : support $(LIBRARY)
|
$(SO_DIRS) : support $(LIBRARY)
|
||||||
$(MAKE) -j -C $(KS)/$@
|
$(MAKE) -j -C $(KS)/$@
|
||||||
|
|||||||
+10
-7
@@ -12,16 +12,19 @@ LOCAL_CPPFLAGS := -I$(KM) -I$(KS)/kutil -I$(KS)/target
|
|||||||
|
|
||||||
# Shared library location
|
# Shared library location
|
||||||
LIBDIR := $(K)/lib
|
LIBDIR := $(K)/lib
|
||||||
LIBRARY := $(LIBDIR)/libklammertext.so
|
LIBRARY := $(LIBDIR)/$(KLAMMERTEXT_LIBFILE)
|
||||||
|
|
||||||
# Linker flags for document.so
|
# The product: document.so, on Windows document.dll (makefile.env's DSO)
|
||||||
|
DOCUMENT := document$(DSO)
|
||||||
|
|
||||||
|
# Linker flags for the DSO
|
||||||
DOC_LDFLAGS := $(SHARED) $(EXPORT_DYNAMIC) -Wl,-rpath,'$(ORIGIN)/../../lib' -L$(LIBDIR)
|
DOC_LDFLAGS := $(SHARED) $(EXPORT_DYNAMIC) -Wl,-rpath,'$(ORIGIN)/../../lib' -L$(LIBDIR)
|
||||||
|
|
||||||
# Local object files
|
# Local object files
|
||||||
LOCAL_OBJECTS := document_class.o document_html.o document_latex.o heading.o reference.o
|
LOCAL_OBJECTS := document_class.o document_html.o document_latex.o heading.o reference.o
|
||||||
LOCAL_DEPFILES := document_class.d document_html.d document_latex.d heading.d reference.d document.d
|
LOCAL_DEPFILES := document_class.d document_html.d document_latex.d heading.d reference.d document.d
|
||||||
|
|
||||||
# External object files from sks/ (mac/*.o now in libklammertext.so)
|
# External object files from sks/ (mac/*.o now in the shared library)
|
||||||
SKS_OBJECTS := $(KS)/kutil/kutil.o $(KS)/kutil/klammer_base.o \
|
SKS_OBJECTS := $(KS)/kutil/kutil.o $(KS)/kutil/klammer_base.o \
|
||||||
$(KS)/target/html_util.o $(KS)/target/latex_util.o
|
$(KS)/target/html_util.o $(KS)/target/latex_util.o
|
||||||
|
|
||||||
@@ -33,7 +36,7 @@ DEPFLAGS = -MMD -MP -MF $(@:.o=.d)
|
|||||||
.PHONY: all clean deps
|
.PHONY: all clean deps
|
||||||
|
|
||||||
# Default target
|
# Default target
|
||||||
all : document.so
|
all : $(DOCUMENT)
|
||||||
|
|
||||||
# Build external dependencies first
|
# Build external dependencies first
|
||||||
deps :
|
deps :
|
||||||
@@ -45,13 +48,13 @@ deps :
|
|||||||
@echo Compiling $<
|
@echo Compiling $<
|
||||||
$(CXX) -c $(CPPFLAGS) $(LOCAL_CPPFLAGS) $(CXXFLAGS) $(DEPFLAGS) $< -o $@
|
$(CXX) -c $(CPPFLAGS) $(LOCAL_CPPFLAGS) $(CXXFLAGS) $(DEPFLAGS) $< -o $@
|
||||||
|
|
||||||
# Shared object - link against libklammertext.so
|
# Shared object - link against the library
|
||||||
document.so : $(LOCAL_OBJECTS) $(SKS_OBJECTS) $(LIBRARY) document.cpp | deps
|
$(DOCUMENT) : $(LOCAL_OBJECTS) $(SKS_OBJECTS) $(LIBRARY) document.cpp | deps
|
||||||
$(CXX) $(CPPFLAGS) $(LOCAL_CPPFLAGS) $(CXXFLAGS) $(DOC_LDFLAGS) $(LDFLAGS) \
|
$(CXX) $(CPPFLAGS) $(LOCAL_CPPFLAGS) $(CXXFLAGS) $(DOC_LDFLAGS) $(LDFLAGS) \
|
||||||
document.cpp -o $@ $(ALL_OBJECTS) $(KLAMMERTEXT_LIB) $(LDLIBS)
|
document.cpp -o $@ $(ALL_OBJECTS) $(KLAMMERTEXT_LIB) $(LDLIBS)
|
||||||
|
|
||||||
clean :
|
clean :
|
||||||
rm -f $(LOCAL_OBJECTS) $(LOCAL_DEPFILES) *.so *~
|
rm -f $(LOCAL_OBJECTS) $(LOCAL_DEPFILES) *.so *.dll *~
|
||||||
# document_txt.py is imported at render time (2026-09-18), so this
|
# document_txt.py is imported at render time (2026-09-18), so this
|
||||||
# directory now exists here; rm -f refused it and failed every clean.
|
# directory now exists here; rm -f refused it and failed every clean.
|
||||||
rm -rf __pycache__
|
rm -rf __pycache__
|
||||||
|
|||||||
@@ -62,7 +62,9 @@ def main():
|
|||||||
out = run_cli(script, ['align', str(line), str(col)], s)
|
out = run_cli(script, ['align', str(line), str(col)], s)
|
||||||
else:
|
else:
|
||||||
sys.exit("editor_driver.py: unknown mode: " + mode)
|
sys.exit("editor_driver.py: unknown mode: " + mode)
|
||||||
with open(outfile, 'w') as f:
|
# newline='': the core's "\n" reaches the file untranslated on every
|
||||||
|
# system (text mode would write CRLF on Windows, against LF fixtures).
|
||||||
|
with open(outfile, 'w', newline='') as f:
|
||||||
f.write(out)
|
f.write(out)
|
||||||
|
|
||||||
# Error and diagnostics paths.
|
# Error and diagnostics paths.
|
||||||
|
|||||||
@@ -81,7 +81,9 @@ const vscodeStub = {
|
|||||||
Uri: { parse: (s) => ({ toString: () => s }) },
|
Uri: { parse: (s) => ({ toString: () => s }) },
|
||||||
DiagnosticSeverity: { Error: 0, Warning: 1 },
|
DiagnosticSeverity: { Error: 0, Warning: 1 },
|
||||||
workspace: {
|
workspace: {
|
||||||
getConfiguration: () => ({ get: (k) => (k === 'pythonPath' ? 'python3' : '') }),
|
// Both settings blank: the extension's own defaults are what is tested
|
||||||
|
// (python3, on Windows python; the server located by the search chain).
|
||||||
|
getConfiguration: () => ({ get: () => '' }),
|
||||||
textDocuments: [fakeDoc],
|
textDocuments: [fakeDoc],
|
||||||
onDidOpenTextDocument: (fn) => { listeners.open.push(fn); return { dispose() {} }; },
|
onDidOpenTextDocument: (fn) => { listeners.open.push(fn); return { dispose() {} }; },
|
||||||
onDidChangeTextDocument: (fn) => { listeners.change.push(fn); return { dispose() {} }; },
|
onDidChangeTextDocument: (fn) => { listeners.change.push(fn); return { dispose() {} }; },
|
||||||
|
|||||||
+50
-8
@@ -59,6 +59,17 @@ FIX="$HERE/editor"
|
|||||||
OUT="$(mktemp -d)"
|
OUT="$(mktemp -d)"
|
||||||
trap 'rm -rf "$OUT"' EXIT
|
trap 'rm -rf "$OUT"' EXIT
|
||||||
|
|
||||||
|
# A path written INSIDE a Python string must be one the interpreter can open.
|
||||||
|
# Under MSYS2 the shell's /c/... form is converted only for standalone
|
||||||
|
# arguments to a native program, never inside a string, so those get the
|
||||||
|
# Windows form (forward slashes; a backslash in a Python literal is an escape).
|
||||||
|
native() {
|
||||||
|
if command -v cygpath >/dev/null 2>&1; then cygpath -m "$1"; else printf '%s' "$1"; fi
|
||||||
|
}
|
||||||
|
SHARED_NATIVE="$(native "$SHARED_DIR")"
|
||||||
|
SUBLIME_NATIVE="$(native "$SUBLIME_DIR")"
|
||||||
|
OUT_NATIVE="$(native "$OUT")"
|
||||||
|
|
||||||
INDENT_FIXTURES="indent_list indent_document indent_table indent_untouched
|
INDENT_FIXTURES="indent_list indent_document indent_table indent_untouched
|
||||||
indent_defs indent_escapes indent_named_close indent_literal_c"
|
indent_defs indent_escapes indent_named_close indent_literal_c"
|
||||||
ALIGN_FIXTURES="align_mixed align_empty_cells align_boundary align_colspan
|
ALIGN_FIXTURES="align_mixed align_empty_cells align_boundary align_colspan
|
||||||
@@ -105,10 +116,10 @@ fi
|
|||||||
|
|
||||||
# --- the Sublime adapters resolve to the shared core -----------------------
|
# --- the Sublime adapters resolve to the shared core -----------------------
|
||||||
if PYTHONDONTWRITEBYTECODE=1 "$PYTHON" -c "
|
if PYTHONDONTWRITEBYTECODE=1 "$PYTHON" -c "
|
||||||
import sys
|
import os, sys
|
||||||
sys.path.insert(0, '$SUBLIME_DIR')
|
sys.path.insert(0, '$SUBLIME_NATIVE')
|
||||||
import Klammertext, Klammertext_indent, Klammertext_align
|
import Klammertext, Klammertext_indent, Klammertext_align
|
||||||
assert Klammertext.KE.__file__.startswith('$SHARED_DIR')
|
assert os.path.normpath(Klammertext.KE.__file__).startswith(os.path.normpath('$SHARED_NATIVE'))
|
||||||
" 2>"$OUT/sublime.log"; then
|
" 2>"$OUT/sublime.log"; then
|
||||||
echo "${green}PASS${reset} sublime adapters import the shared core"
|
echo "${green}PASS${reset} sublime adapters import the shared core"
|
||||||
PASS=$((PASS + 1))
|
PASS=$((PASS + 1))
|
||||||
@@ -118,6 +129,25 @@ else
|
|||||||
FAIL=$((FAIL + 1))
|
FAIL=$((FAIL + 1))
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# --- the Notepad++ UDL: well-formed, and it restates the literal klammer -----
|
||||||
|
# (a static artifact of the SYNC set; nothing else can check it)
|
||||||
|
if PYTHONDONTWRITEBYTECODE=1 "$PYTHON" -c "
|
||||||
|
import sys, xml.etree.ElementTree as ET
|
||||||
|
u = ET.parse('$(native "$EDIT_DIR")/notepadpp/Klammertext.udl.xml').getroot().find('UserLang')
|
||||||
|
assert u.get('name') == 'Klammertext' and set(u.get('ext').split()) == {'kt', 'k'}, u.attrib
|
||||||
|
lists = {k.get('name'): (k.text or '') for k in u.find('KeywordLists')}
|
||||||
|
assert '00@code' in lists['Delimiters'].split() and '02code@' in lists['Delimiters'].split(), lists['Delimiters']
|
||||||
|
assert lists['Keywords1'].strip() == '@@@' and lists['Keywords2'].strip() == '@@' and lists['Keywords3'].strip() == '@'
|
||||||
|
assert '03#[' in lists['Comments'].split() and '04]#' in lists['Comments'].split()
|
||||||
|
" 2>"$OUT/udl.log"; then
|
||||||
|
echo "${green}PASS${reset} notepad++ UDL is well-formed and restates the literal klammer"
|
||||||
|
PASS=$((PASS + 1))
|
||||||
|
else
|
||||||
|
echo "${red}FAIL${reset} notepad++ UDL is well-formed and restates the literal klammer"
|
||||||
|
cat "$OUT/udl.log"
|
||||||
|
FAIL=$((FAIL + 1))
|
||||||
|
fi
|
||||||
|
|
||||||
# --- the language server protocol test -------------------------------------
|
# --- the language server protocol test -------------------------------------
|
||||||
if PYTHONDONTWRITEBYTECODE=1 "$PYTHON" "$FIX/ls_test.py" "$SHARED_DIR" "$FIX" >"$OUT/ls.log" 2>&1; then
|
if PYTHONDONTWRITEBYTECODE=1 "$PYTHON" "$FIX/ls_test.py" "$SHARED_DIR" "$FIX" >"$OUT/ls.log" 2>&1; then
|
||||||
echo "${green}PASS${reset} language server protocol ($(grep -c '^PASS' "$OUT/ls.log") checks)"
|
echo "${green}PASS${reset} language server protocol ($(grep -c '^PASS' "$OUT/ls.log") checks)"
|
||||||
@@ -230,17 +260,29 @@ else
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# --- the VS Code extension (optional: needs a Node runtime) ----------------
|
# --- the VS Code extension (optional: needs a Node runtime) ----------------
|
||||||
# node itself, or VS Code's Electron binary run as Node.
|
# node itself, or VS Code's Electron binary run as Node, wherever an
|
||||||
|
# installed VS Code keeps it: the Linux package, the macOS app bundle, the
|
||||||
|
# Windows per-user install (LOCALAPPDATA is a Windows variable, so the shell
|
||||||
|
# is MSYS2 there and cygpath exists).
|
||||||
|
CODE_BIN=""
|
||||||
|
if [ -x /usr/share/code/code ]; then
|
||||||
|
CODE_BIN=/usr/share/code/code
|
||||||
|
elif [ -x "/Applications/Visual Studio Code.app/Contents/MacOS/Electron" ]; then
|
||||||
|
CODE_BIN="/Applications/Visual Studio Code.app/Contents/MacOS/Electron"
|
||||||
|
elif [ -n "$LOCALAPPDATA" ] && command -v cygpath >/dev/null 2>&1; then
|
||||||
|
c="$(cygpath -u "$LOCALAPPDATA")/Programs/Microsoft VS Code/Code.exe"
|
||||||
|
[ -x "$c" ] && CODE_BIN="$c"
|
||||||
|
fi
|
||||||
run_node() {
|
run_node() {
|
||||||
if command -v node >/dev/null 2>&1; then
|
if command -v node >/dev/null 2>&1; then
|
||||||
node "$@"
|
node "$@"
|
||||||
elif [ -x /usr/share/code/code ]; then
|
elif [ -n "$CODE_BIN" ]; then
|
||||||
ELECTRON_RUN_AS_NODE=1 /usr/share/code/code "$@"
|
ELECTRON_RUN_AS_NODE=1 "$CODE_BIN" "$@"
|
||||||
else
|
else
|
||||||
return 127
|
return 127
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
if command -v node >/dev/null 2>&1 || [ -x /usr/share/code/code ]; then
|
if command -v node >/dev/null 2>&1 || [ -n "$CODE_BIN" ]; then
|
||||||
if run_node "$FIX/vscode_ext_test.js" "$EDIT_DIR/vscode" "$FIX" >"$OUT/vscode.log" 2>&1; then
|
if run_node "$FIX/vscode_ext_test.js" "$EDIT_DIR/vscode" "$FIX" >"$OUT/vscode.log" 2>&1; then
|
||||||
echo "${green}PASS${reset} vscode extension ($(grep -c '^PASS' "$OUT/vscode.log") checks)"
|
echo "${green}PASS${reset} vscode extension ($(grep -c '^PASS' "$OUT/vscode.log") checks)"
|
||||||
PASS=$((PASS + 1))
|
PASS=$((PASS + 1))
|
||||||
@@ -260,7 +302,7 @@ cp -R "$EDIT_DIR/vscode" "$EDIT_DIR/shared" "$OUT/vsix/"
|
|||||||
if ( cd "$OUT/vsix/vscode" && ./make_vsix.sh >/dev/null 2>&1 ) && \
|
if ( cd "$OUT/vsix/vscode" && ./make_vsix.sh >/dev/null 2>&1 ) && \
|
||||||
PYTHONDONTWRITEBYTECODE=1 "$PYTHON" -c "
|
PYTHONDONTWRITEBYTECODE=1 "$PYTHON" -c "
|
||||||
import sys, zipfile
|
import sys, zipfile
|
||||||
names = set(zipfile.ZipFile('$OUT/vsix/vscode/klammertext.vsix').namelist())
|
names = set(zipfile.ZipFile('$OUT_NATIVE/vsix/vscode/klammertext.vsix').namelist())
|
||||||
need = {'extension.vsixmanifest', '[Content_Types].xml',
|
need = {'extension.vsixmanifest', '[Content_Types].xml',
|
||||||
'extension/package.json', 'extension/extension.js',
|
'extension/package.json', 'extension/extension.js',
|
||||||
'extension/language-configuration.json', 'extension/README.md',
|
'extension/language-configuration.json', 'extension/README.md',
|
||||||
|
|||||||
@@ -86,7 +86,10 @@ check_contains() {
|
|||||||
FAIL=$((FAIL + 1))
|
FAIL=$((FAIL + 1))
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
if printf '%s' "$output" | grep -qF "$needle"; then
|
# Wrap-insensitive: error text is justified to 80 columns, and where the
|
||||||
|
# needle breaks across a line depends on the installation's path length
|
||||||
|
# (found in Windows Sandbox, whose user name is long: "was not \nfound").
|
||||||
|
if printf '%s' "$output" | tr '\n' ' ' | tr -s ' ' | grep -qF "$needle"; then
|
||||||
echo "${green}PASS${reset} $test_name"
|
echo "${green}PASS${reset} $test_name"
|
||||||
PASS=$((PASS + 1))
|
PASS=$((PASS + 1))
|
||||||
else
|
else
|
||||||
@@ -114,7 +117,8 @@ check_fails() {
|
|||||||
FAIL=$((FAIL + 1))
|
FAIL=$((FAIL + 1))
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
if printf '%s' "$output" | grep -qF "$needle"; then
|
# Wrap-insensitive, like the other helper above.
|
||||||
|
if printf '%s' "$output" | tr '\n' ' ' | tr -s ' ' | grep -qF "$needle"; then
|
||||||
echo "${green}PASS${reset} $test_name"
|
echo "${green}PASS${reset} $test_name"
|
||||||
PASS=$((PASS + 1))
|
PASS=$((PASS + 1))
|
||||||
else
|
else
|
||||||
|
|||||||
Reference in new issue
Block a user