Initial commit: Klammertext source distribution
Curated source subset assembled by klammertext-dev's doc/make_dist.sh: the Klammermachine (mac), the Standard Klammer Set (sks), the commands (com), editor plugins and install guides (doc), a test subset (tst), and lib/bin placeholders. Builds with 'make -C com'. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
60
doc/edit/sublime/Breakers.sublime-color-scheme
Normal file
60
doc/edit/sublime/Breakers.sublime-color-scheme
Normal file
@@ -0,0 +1,60 @@
|
||||
// Klammertext colors for the "Breakers" scheme (light ground).
|
||||
// One hue system across all schemes: application = blue, definition =
|
||||
// green, system = orange; each opens bright and its close is 80%% of the
|
||||
// open (a klammer "begins bright and gets dark"). Shown at full intensity
|
||||
// on dark grounds, at 60%% on light grounds for contrast. Delimiters are
|
||||
// forced to normal style. Merged onto Breakers by filename; recolors only
|
||||
// .klammertext scopes. (The highlighting was first developed as an Emacs
|
||||
// major mode; see Klammertext_in_Sublime_Text.md.)
|
||||
//
|
||||
// #999999 removed text (Breakers's comment grey)
|
||||
// #994040 removal markers
|
||||
// #528599 @name open blue
|
||||
// #426a7a name@ close darker blue
|
||||
// #758b55 @@name open green
|
||||
// #5e7044 name@@ close darker green
|
||||
// #996743 @@@name open orange
|
||||
// #7a5236 name@@@ close darker orange
|
||||
{
|
||||
"name": "Breakers",
|
||||
"rules": [
|
||||
{
|
||||
"scope": "comment.line.klammertext, comment.block.klammertext",
|
||||
"foreground": "#999999"
|
||||
},
|
||||
{
|
||||
"scope": "punctuation.definition.comment.klammertext",
|
||||
"foreground": "#994040"
|
||||
},
|
||||
{
|
||||
"scope": "entity.name.function.begin.klammertext",
|
||||
"foreground": "#528599",
|
||||
"font_style": ""
|
||||
},
|
||||
{
|
||||
"scope": "entity.name.function.end.klammertext",
|
||||
"foreground": "#426a7a",
|
||||
"font_style": ""
|
||||
},
|
||||
{
|
||||
"scope": "storage.type.begin.klammertext",
|
||||
"foreground": "#758b55",
|
||||
"font_style": ""
|
||||
},
|
||||
{
|
||||
"scope": "storage.type.end.klammertext",
|
||||
"foreground": "#5e7044",
|
||||
"font_style": ""
|
||||
},
|
||||
{
|
||||
"scope": "keyword.control.begin.klammertext",
|
||||
"foreground": "#996743",
|
||||
"font_style": ""
|
||||
},
|
||||
{
|
||||
"scope": "keyword.control.end.klammertext",
|
||||
"foreground": "#7a5236",
|
||||
"font_style": ""
|
||||
}
|
||||
]
|
||||
}
|
||||
60
doc/edit/sublime/Celeste.sublime-color-scheme
Normal file
60
doc/edit/sublime/Celeste.sublime-color-scheme
Normal file
@@ -0,0 +1,60 @@
|
||||
// Klammertext colors for the "Celeste" scheme (light ground).
|
||||
// One hue system across all schemes: application = blue, definition =
|
||||
// green, system = orange; each opens bright and its close is 80%% of the
|
||||
// open (a klammer "begins bright and gets dark"). Shown at full intensity
|
||||
// on dark grounds, at 60%% on light grounds for contrast. Delimiters are
|
||||
// forced to normal style. Merged onto Celeste by filename; recolors only
|
||||
// .klammertext scopes. (The highlighting was first developed as an Emacs
|
||||
// major mode; see Klammertext_in_Sublime_Text.md.)
|
||||
//
|
||||
// #9a9a9a removed text (Celeste's comment grey)
|
||||
// #994040 removal markers
|
||||
// #528599 @name open blue
|
||||
// #426a7a name@ close darker blue
|
||||
// #758b55 @@name open green
|
||||
// #5e7044 name@@ close darker green
|
||||
// #996743 @@@name open orange
|
||||
// #7a5236 name@@@ close darker orange
|
||||
{
|
||||
"name": "Celeste",
|
||||
"rules": [
|
||||
{
|
||||
"scope": "comment.line.klammertext, comment.block.klammertext",
|
||||
"foreground": "#9a9a9a"
|
||||
},
|
||||
{
|
||||
"scope": "punctuation.definition.comment.klammertext",
|
||||
"foreground": "#994040"
|
||||
},
|
||||
{
|
||||
"scope": "entity.name.function.begin.klammertext",
|
||||
"foreground": "#528599",
|
||||
"font_style": ""
|
||||
},
|
||||
{
|
||||
"scope": "entity.name.function.end.klammertext",
|
||||
"foreground": "#426a7a",
|
||||
"font_style": ""
|
||||
},
|
||||
{
|
||||
"scope": "storage.type.begin.klammertext",
|
||||
"foreground": "#758b55",
|
||||
"font_style": ""
|
||||
},
|
||||
{
|
||||
"scope": "storage.type.end.klammertext",
|
||||
"foreground": "#5e7044",
|
||||
"font_style": ""
|
||||
},
|
||||
{
|
||||
"scope": "keyword.control.begin.klammertext",
|
||||
"foreground": "#996743",
|
||||
"font_style": ""
|
||||
},
|
||||
{
|
||||
"scope": "keyword.control.end.klammertext",
|
||||
"foreground": "#7a5236",
|
||||
"font_style": ""
|
||||
}
|
||||
]
|
||||
}
|
||||
44
doc/edit/sublime/Comments.tmPreferences
Normal file
44
doc/edit/sublime/Comments.tmPreferences
Normal file
@@ -0,0 +1,44 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<!--
|
||||
Comment toggling for Klammertext. Companion to Klammertext.sublime-syntax.
|
||||
|
||||
Ctrl+/ (toggle_comment) -> line removal: "# "
|
||||
Ctrl+Shift+/ (toggle_comment block:true) -> block removal: "#[ ... ]#"
|
||||
|
||||
These map onto Klammertext's own text-removal syntax:
|
||||
# removes to end of line (the line comment)
|
||||
#[ ... ]# removes enclosed text, nestable (the block comment)
|
||||
-->
|
||||
<key>name</key>
|
||||
<string>Comments</string>
|
||||
<key>scope</key>
|
||||
<string>text.klammertext</string>
|
||||
<key>settings</key>
|
||||
<dict>
|
||||
<key>shellVariables</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>TM_COMMENT_START</string>
|
||||
<key>value</key>
|
||||
<string># </string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>TM_COMMENT_START_2</string>
|
||||
<key>value</key>
|
||||
<string>#[</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>TM_COMMENT_END_2</string>
|
||||
<key>value</key>
|
||||
<string>]#</string>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
</dict>
|
||||
</plist>
|
||||
20
doc/edit/sublime/Default.sublime-keymap
Normal file
20
doc/edit/sublime/Default.sublime-keymap
Normal file
@@ -0,0 +1,20 @@
|
||||
// Klammertext key bindings.
|
||||
//
|
||||
// Binds "jump to matching klammer delimiter" (the companion Klammertext.py
|
||||
// command) to Ctrl+M — Sublime's own "go to matching bracket" key, repurposed
|
||||
// for klammers, since the built-in cannot match context-dependent @ pairs.
|
||||
//
|
||||
// The "selector" context confines the binding to Klammertext files, so Ctrl+M
|
||||
// keeps its normal meaning everywhere else.
|
||||
//
|
||||
// macOS users may prefer "super+m"; change the "keys" value below. This file
|
||||
// (no platform suffix) is loaded on all platforms.
|
||||
[
|
||||
{
|
||||
"keys": ["ctrl+m"],
|
||||
"command": "klammertext_jump_to_match",
|
||||
"context": [
|
||||
{ "key": "selector", "operator": "equal", "operand": "text.klammertext" }
|
||||
]
|
||||
}
|
||||
]
|
||||
471
doc/edit/sublime/Klammertext.py
Normal file
471
doc/edit/sublime/Klammertext.py
Normal file
@@ -0,0 +1,471 @@
|
||||
# Klammertext.py
|
||||
#
|
||||
# Sublime Text plugin for klammer APPLICATION (@) delimiters. Two features,
|
||||
# both ports of doc/emacs/klammertext-mode.el, both reusing one matcher:
|
||||
#
|
||||
# 1. Jump between an opening and its close — the Sublime equivalent of the
|
||||
# Emacs mode's `klammertext-jump-to-match' (bound C-c C-j). Command name
|
||||
# klammertext_jump_to_match; keybinding in Default.sublime-keymap.
|
||||
#
|
||||
# 2. Live highlighting of the matching delimiter as the caret sits on one —
|
||||
# the equivalent of the Emacs mode's show-paren support. Implemented as a
|
||||
# ViewEventListener (see KlammertextMatchHighlighter at the bottom); no
|
||||
# language server is involved. A mismatched named close or an unbalanced
|
||||
# delimiter is highlighted in red with a status-bar message, mirroring the
|
||||
# Emacs mode's klammertext-mismatch-face + minibuffer report.
|
||||
#
|
||||
# This is the companion to Klammertext.sublime-syntax. The syntax file only
|
||||
# colors tokens; a tokenizer cannot match context-dependent delimiters, so the
|
||||
# jump is implemented here as a TextCommand. The keybinding lives in the
|
||||
# companion Default.sublime-keymap.
|
||||
#
|
||||
# Command name (for keymaps / the command palette): klammertext_jump_to_match
|
||||
#
|
||||
# ---------------------------------------------------------------------------
|
||||
# What it does (a direct port of the elisp matcher):
|
||||
# * On an opening @name, move to its closing @ or name@.
|
||||
# * On a close (bare @ or name@), move to the opening @name.
|
||||
# * Triggers when the caret is ON the @ or immediately AFTER it (the same
|
||||
# on-or-just-after rule the Emacs command uses).
|
||||
# * Only single-@ APPLICATION delimiters match. @@/@@@ runs, removed text
|
||||
# (#, ##, #[...]#), escaped ^@, and literal-klammer spans (@code ... code@)
|
||||
# are stepped over, exactly as in the Emacs mode. The abbreviated
|
||||
# @name-arg form opens no span.
|
||||
# * Works at every caret when there are multiple selections.
|
||||
#
|
||||
# Literal klammers (identical to C-c C-j): a @code ... code@ span is opaque.
|
||||
# The general depth scan still steps over such a span WHOLESALE when matching
|
||||
# some OTHER klammer, so verbatim @ inside it never miscount. A literal
|
||||
# klammer's OWN delimiters are matched BY NAME rather than by depth (see
|
||||
# app_match): @code jumps to the next code@, and code@ to the nearest preceding
|
||||
# @code — correct even when the content holds unbalanced @, e.g. @code x @ y
|
||||
# code@. LITERAL_KLAMMERS lists these names; keep it in sync with the '@code'
|
||||
# handling in Klammertext.sublime-syntax.
|
||||
#
|
||||
# LITERAL_KLAMMERS must stay in sync with the literal klammers recognized in
|
||||
# Klammertext.sublime-syntax (seeded there as @code). The Emacs mode keeps this
|
||||
# list in the `klammertext-literal-klammers' defcustom; a plugin has no access
|
||||
# to it, so it is duplicated here.
|
||||
|
||||
import sublime
|
||||
import sublime_plugin
|
||||
|
||||
# Klammer names whose content is a literal argument (verbatim interior).
|
||||
#
|
||||
# SYNC: this list is one of three copies that must agree. When you add or
|
||||
# remove a literal klammer, mirror it in all three:
|
||||
# * klammertext-literal-klammers in doc/emacs/klammertext-mode.el (the source
|
||||
# of truth; a Sublime syntax/plugin cannot read that Emacs defcustom)
|
||||
# * LITERAL_KLAMMERS here
|
||||
# * the @NAME literal rule + literal_NAME context in Klammertext.sublime-syntax
|
||||
# All three are currently seeded with just "code".
|
||||
LITERAL_KLAMMERS = set(["code"])
|
||||
|
||||
|
||||
# --- pure helpers (operate on the whole buffer as a string) ----------------
|
||||
|
||||
def name_char_p(ch):
|
||||
"""True if CH can be part of a klammer name (letter, digit or _).
|
||||
A hyphen is NOT a name char: @name-arg1 ends the name at the first hyphen."""
|
||||
if ch is None:
|
||||
return False
|
||||
return (('a' <= ch <= 'z') or ('A' <= ch <= 'Z')
|
||||
or ('0' <= ch <= '9') or ch == '_')
|
||||
|
||||
|
||||
def escaped_p(s, pos):
|
||||
"""True if the char at POS is escaped by an odd run of ^ before it.
|
||||
In Klammertext ^# and ^@ are literal, so such a char is not a delimiter."""
|
||||
n = 0
|
||||
i = pos - 1
|
||||
while i >= 0 and s[i] == '^':
|
||||
n += 1
|
||||
i -= 1
|
||||
return (n % 2) == 1
|
||||
|
||||
|
||||
def block_end(s, frm):
|
||||
"""Index just after the ]# that closes a #[ block opened at FROM (the index
|
||||
just after the opening #[). Counts nested #[ ... ]#; len(s) if unclosed."""
|
||||
depth = 1
|
||||
i = frm
|
||||
n = len(s)
|
||||
while depth > 0:
|
||||
a = s.find('#[', i)
|
||||
b = s.find(']#', i)
|
||||
if a == -1 and b == -1:
|
||||
return n
|
||||
if b == -1 or (a != -1 and a < b):
|
||||
depth += 1
|
||||
i = a + 2
|
||||
else:
|
||||
depth -= 1
|
||||
i = b + 2
|
||||
return i
|
||||
|
||||
|
||||
def at_run_end(s, pos):
|
||||
"""Index just after the run of @ that begins at POS."""
|
||||
p = pos
|
||||
n = len(s)
|
||||
while p < n and s[p] == '@':
|
||||
p += 1
|
||||
return p
|
||||
|
||||
|
||||
def next_app_delim(s, i, limit):
|
||||
"""From index I, find the next single-@ application delimiter before LIMIT.
|
||||
Step over @@/@@@ runs, removed text, literal spans, escaped ^@, and the
|
||||
abbreviated @name-arg form. Return (pos, kind, next_i) with kind 'open' or
|
||||
'close' and next_i the index to resume from, or None when none is found."""
|
||||
n = len(s)
|
||||
if limit is None:
|
||||
limit = n
|
||||
while i < limit:
|
||||
# find next @ or # at or after i (emacs re-search-forward "[@#]")
|
||||
j = i
|
||||
while j < limit and s[j] != '@' and s[j] != '#':
|
||||
j += 1
|
||||
if j >= limit:
|
||||
return None
|
||||
hit = j
|
||||
i = hit + 1 # default: advance past the hit
|
||||
if escaped_p(s, hit): # ^@ / ^# : keep going
|
||||
continue
|
||||
nxt = s[hit + 1] if hit + 1 < n else None
|
||||
if s[hit] == '#': # removal: step over it
|
||||
if nxt == '#':
|
||||
i = n
|
||||
elif nxt == '[':
|
||||
i = block_end(s, hit + 2)
|
||||
elif nxt in ('+', '/', '-'):
|
||||
i = hit + 1
|
||||
else: # to end of line
|
||||
eol = s.find('\n', hit)
|
||||
i = n if eol == -1 else eol
|
||||
continue
|
||||
# s[hit] == '@'
|
||||
if nxt == '@': # @@ / @@@ : step over the run
|
||||
i = at_run_end(s, hit)
|
||||
continue
|
||||
if name_char_p(nxt): # @name : opening?
|
||||
k = hit + 1
|
||||
while k < n and name_char_p(s[k]):
|
||||
k += 1
|
||||
name = s[hit + 1:k]
|
||||
after = s[k] if k < n else None
|
||||
if name in LITERAL_KLAMMERS: # literal span: skip to its close
|
||||
close = name + '@'
|
||||
idx = s.find(close, k)
|
||||
i = n if idx == -1 else idx + len(close)
|
||||
continue
|
||||
elif after == '-': # @name-arg : opens no span
|
||||
i = k
|
||||
continue
|
||||
else:
|
||||
return (hit, 'open', k)
|
||||
else: # name@ / bare @ : closing
|
||||
return (hit, 'close', hit + 1)
|
||||
return None
|
||||
|
||||
|
||||
def match_forward(s, open_pos):
|
||||
"""OPEN_POS is the @ of an opening application. Return the matching close @
|
||||
index, or None if unbalanced."""
|
||||
n = len(s)
|
||||
i = open_pos + 1
|
||||
while i < n and name_char_p(s[i]): # past the opening name
|
||||
i += 1
|
||||
depth = 1
|
||||
while depth > 0:
|
||||
d = next_app_delim(s, i, None)
|
||||
if d is None:
|
||||
return None
|
||||
pos, kind, nxt = d
|
||||
i = nxt
|
||||
if kind == 'open':
|
||||
depth += 1
|
||||
else:
|
||||
depth -= 1
|
||||
if depth == 0:
|
||||
return pos
|
||||
return None
|
||||
|
||||
|
||||
def match_backward(s, close_pos):
|
||||
"""CLOSE_POS is the @ of a closing application. Return the matching open @
|
||||
index, or None if unbalanced. Scans forward from 0 with a stack."""
|
||||
stack = []
|
||||
i = 0
|
||||
limit = close_pos + 1
|
||||
while True:
|
||||
d = next_app_delim(s, i, limit)
|
||||
if d is None:
|
||||
return None
|
||||
pos, kind, nxt = d
|
||||
i = nxt
|
||||
if kind == 'open':
|
||||
stack.append(pos)
|
||||
else:
|
||||
open_pos = stack.pop() if stack else None
|
||||
if pos == close_pos:
|
||||
return open_pos
|
||||
|
||||
|
||||
def app_delim_info(s, pos):
|
||||
"""If the char at POS is a single-@ application delimiter, return
|
||||
(pos, kind) with kind 'open' or 'close'; else None. The abbreviated
|
||||
@name-arg form (which opens no span) returns None."""
|
||||
n = len(s)
|
||||
if not (0 <= pos < n):
|
||||
return None
|
||||
if s[pos] != '@':
|
||||
return None
|
||||
if pos > 0 and s[pos - 1] == '@':
|
||||
return None
|
||||
if pos + 1 < n and s[pos + 1] == '@':
|
||||
return None
|
||||
if escaped_p(s, pos):
|
||||
return None
|
||||
nxt = s[pos + 1] if pos + 1 < n else None
|
||||
if name_char_p(nxt):
|
||||
k = pos + 1
|
||||
while k < n and name_char_p(s[k]):
|
||||
k += 1
|
||||
after = s[k] if k < n else None
|
||||
if after == '-':
|
||||
return None
|
||||
return (pos, 'open')
|
||||
return (pos, 'close')
|
||||
|
||||
|
||||
# --- name / mismatch helpers (for the live highlighter) --------------------
|
||||
|
||||
def _name_forward(s, pos):
|
||||
"""Index just past the run of name chars starting at POS."""
|
||||
n = len(s)
|
||||
k = pos
|
||||
while k < n and name_char_p(s[k]):
|
||||
k += 1
|
||||
return k
|
||||
|
||||
|
||||
def open_name(s, open_pos):
|
||||
"""Name of the opening @name whose @ is at OPEN_POS."""
|
||||
return s[open_pos + 1:_name_forward(s, open_pos + 1)]
|
||||
|
||||
|
||||
def close_name(s, close_pos):
|
||||
"""Name of a named close NAME@ whose @ is at CLOSE_POS, or None for a bare @
|
||||
(including the compact @name@ form, whose name belongs to the opening)."""
|
||||
ns = close_pos
|
||||
while ns > 0 and name_char_p(s[ns - 1]):
|
||||
ns -= 1
|
||||
if ns < close_pos and (ns == 0 or s[ns - 1] != '@'):
|
||||
return s[ns:close_pos]
|
||||
return None
|
||||
|
||||
|
||||
def paren_mismatch(s, open_pos, close_pos):
|
||||
"""True if the pair is unbalanced (either side None) or the named close
|
||||
disagrees with the opening name."""
|
||||
if open_pos is None or close_pos is None:
|
||||
return True
|
||||
cname = close_name(s, close_pos)
|
||||
return cname is not None and cname != open_name(s, open_pos)
|
||||
|
||||
|
||||
def token_region(s, pos, kind):
|
||||
"""(start, end) of the whole delimiter token whose @ is at POS.
|
||||
Opening: @ plus its name. Named close: the name plus @. Bare @: just @."""
|
||||
if kind == 'open':
|
||||
return (pos, _name_forward(s, pos + 1))
|
||||
ns = pos
|
||||
while ns > 0 and name_char_p(s[ns - 1]):
|
||||
ns -= 1
|
||||
if ns < pos and (ns == 0 or s[ns - 1] != '@'):
|
||||
return (ns, pos + 1) # named close NAME@
|
||||
return (pos, pos + 1) # bare @ (or @name@)
|
||||
|
||||
|
||||
# --- matching dispatch: literal klammers by name, others by depth ----------
|
||||
|
||||
def literal_delim_name(s, pos, kind):
|
||||
"""If the application delimiter at POS (kind 'open'/'close') belongs to a
|
||||
literal klammer (name in LITERAL_KLAMMERS), return its name; else None.
|
||||
A literal klammer's @NAME open and NAME@ close are matched by name, not by
|
||||
depth counting, because its content is verbatim."""
|
||||
name = open_name(s, pos) if kind == 'open' else close_name(s, pos)
|
||||
if name and name in LITERAL_KLAMMERS:
|
||||
return name
|
||||
return None
|
||||
|
||||
|
||||
def literal_match_forward(s, open_pos, name):
|
||||
"""Index of the @ of the NAME@ that closes the literal @NAME at OPEN_POS, or
|
||||
None. The content is opaque, so search for the literal close string."""
|
||||
start = open_pos + 1 + len(name)
|
||||
idx = s.find(name + '@', start)
|
||||
return idx + len(name) if idx != -1 else None
|
||||
|
||||
|
||||
def literal_match_backward(s, close_pos, name):
|
||||
"""Index of the @ of the @NAME that opens the literal NAME@ whose @ is at
|
||||
CLOSE_POS, or None. Literal spans do not nest, so the nearest preceding
|
||||
real @NAME is the opener (not @@NAME, and not escaped)."""
|
||||
open_str = '@' + name
|
||||
end = close_pos
|
||||
while True:
|
||||
idx = s.rfind(open_str, 0, end)
|
||||
if idx == -1:
|
||||
return None
|
||||
before = s[idx - 1] if idx > 0 else None
|
||||
if before != '@' and not escaped_p(s, idx):
|
||||
return idx
|
||||
end = idx
|
||||
|
||||
|
||||
def app_match(s, pos, kind):
|
||||
"""Matching application delimiter for the delimiter at POS of KIND
|
||||
('open'/'close'), or None. A literal klammer matches by name (@NAME <->
|
||||
NAME@) with content opaque; other klammers match by depth."""
|
||||
lit = literal_delim_name(s, pos, kind)
|
||||
if lit is not None:
|
||||
return (literal_match_forward(s, pos, lit) if kind == 'open'
|
||||
else literal_match_backward(s, pos, lit))
|
||||
return match_forward(s, pos) if kind == 'open' else match_backward(s, pos)
|
||||
|
||||
|
||||
# --- the command -----------------------------------------------------------
|
||||
|
||||
class KlammertextJumpToMatchCommand(sublime_plugin.TextCommand):
|
||||
"""Jump between a klammer application's opening and closing delimiter.
|
||||
Sublime equivalent of the Emacs mode's C-c C-j."""
|
||||
|
||||
def run(self, edit):
|
||||
view = self.view
|
||||
s = view.substr(sublime.Region(0, view.size()))
|
||||
new_regions = []
|
||||
moved = False
|
||||
message = None
|
||||
|
||||
for region in view.sel():
|
||||
p = region.b
|
||||
info = app_delim_info(s, p)
|
||||
if info is None and p > 0:
|
||||
info = app_delim_info(s, p - 1)
|
||||
if info is None:
|
||||
new_regions.append(region)
|
||||
message = "point is not on a klammer application delimiter (@)"
|
||||
continue
|
||||
dpos, kind = info
|
||||
match = app_match(s, dpos, kind)
|
||||
if match is None:
|
||||
new_regions.append(region)
|
||||
message = ("no matching delimiter for this %s klammer"
|
||||
% ("opening" if kind == 'open' else "closing"))
|
||||
continue
|
||||
new_regions.append(sublime.Region(match, match))
|
||||
moved = True
|
||||
|
||||
view.sel().clear()
|
||||
for r in new_regions:
|
||||
view.sel().add(r)
|
||||
|
||||
if moved:
|
||||
view.show(view.sel()[0].b)
|
||||
elif message:
|
||||
sublime.status_message("Klammertext: " + message)
|
||||
|
||||
def is_enabled(self):
|
||||
# Only meaningful in Klammertext buffers.
|
||||
return self.view.match_selector(0, "text.klammertext")
|
||||
|
||||
|
||||
# --- live matched-delimiter highlighting (show-paren equivalent) -----------
|
||||
|
||||
class KlammertextMatchHighlighter(sublime_plugin.ViewEventListener):
|
||||
"""Highlight the matching klammer application delimiter as the caret sits
|
||||
on one. The Sublime equivalent of the Emacs mode's show-paren support —
|
||||
driven by cursor movement, reusing the same context-sensitive matcher.
|
||||
|
||||
A matched pair is boxed (region.bluish); a mismatch or unbalanced delimiter
|
||||
is boxed in red (region.redish) with a status-bar message. Both the token
|
||||
under the caret and its match are boxed; the Emacs mode highlights only the
|
||||
single @ character, but boxing the whole @name / name@ reads better here.
|
||||
To highlight only the far delimiter, drop the first region in _update()."""
|
||||
|
||||
MATCH_KEY = 'klammertext_paren_match'
|
||||
MISMATCH_KEY = 'klammertext_paren_mismatch'
|
||||
|
||||
@classmethod
|
||||
def is_applicable(cls, settings):
|
||||
return str(settings.get('syntax', '')).endswith('Klammertext.sublime-syntax')
|
||||
|
||||
def __init__(self, view):
|
||||
super().__init__(view)
|
||||
self._change_count = -1
|
||||
self._text = ''
|
||||
|
||||
def _buffer(self):
|
||||
# Re-read the buffer only when it has actually changed, so plain cursor
|
||||
# movement over a large file does not re-copy the whole document.
|
||||
cc = self.view.change_count()
|
||||
if cc != self._change_count:
|
||||
self._text = self.view.substr(sublime.Region(0, self.view.size()))
|
||||
self._change_count = cc
|
||||
return self._text
|
||||
|
||||
def on_selection_modified_async(self):
|
||||
self._update()
|
||||
|
||||
def on_activated_async(self):
|
||||
self._update()
|
||||
|
||||
def _clear(self):
|
||||
self.view.erase_regions(self.MATCH_KEY)
|
||||
self.view.erase_regions(self.MISMATCH_KEY)
|
||||
|
||||
def _update(self):
|
||||
view = self.view
|
||||
sel = view.sel()
|
||||
if len(sel) == 0:
|
||||
self._clear()
|
||||
return
|
||||
p = sel[0].b
|
||||
s = self._buffer()
|
||||
|
||||
info = app_delim_info(s, p)
|
||||
if info is None and p > 0:
|
||||
info = app_delim_info(s, p - 1)
|
||||
if info is None:
|
||||
self._clear()
|
||||
return
|
||||
|
||||
dpos, kind = info
|
||||
match = app_match(s, dpos, kind)
|
||||
open_pos = dpos if kind == 'open' else match
|
||||
close_pos = match if kind == 'open' else dpos
|
||||
mism = paren_mismatch(s, open_pos, close_pos)
|
||||
|
||||
regions = [sublime.Region(*token_region(s, dpos, kind))]
|
||||
if match is not None:
|
||||
other_kind = 'close' if kind == 'open' else 'open'
|
||||
regions.append(sublime.Region(*token_region(s, match, other_kind)))
|
||||
|
||||
flags = sublime.DRAW_NO_FILL
|
||||
if mism:
|
||||
view.erase_regions(self.MATCH_KEY)
|
||||
view.add_regions(self.MISMATCH_KEY, regions, 'region.redish', '', flags)
|
||||
if match is None:
|
||||
if kind == 'open':
|
||||
msg = "opening @%s has no matching close" % open_name(s, open_pos)
|
||||
else:
|
||||
msg = "closing delimiter has no matching open"
|
||||
else:
|
||||
msg = ("closing %s@ does not match opening @%s"
|
||||
% (close_name(s, close_pos) or '?', open_name(s, open_pos)))
|
||||
sublime.status_message("Klammertext: " + msg)
|
||||
else:
|
||||
view.erase_regions(self.MISMATCH_KEY)
|
||||
view.add_regions(self.MATCH_KEY, regions, 'region.bluish', '', flags)
|
||||
183
doc/edit/sublime/Klammertext.sublime-syntax
Normal file
183
doc/edit/sublime/Klammertext.sublime-syntax
Normal file
@@ -0,0 +1,183 @@
|
||||
%YAML 1.2
|
||||
---
|
||||
# Klammertext.sublime-syntax
|
||||
#
|
||||
# Sublime Text syntax highlighting for Klammertext (.kt and .k files).
|
||||
# A port of the Emacs major mode doc/emacs/klammertext-mode.el.
|
||||
#
|
||||
# ---------------------------------------------------------------------------
|
||||
# What it highlights (mirrors the Emacs mode's eight token classes):
|
||||
#
|
||||
# Text removal (#):
|
||||
# # ... remove to end of line (marker + removed text)
|
||||
# ## ... remove to end of file (marker + removed text)
|
||||
# #[ ... ]# remove enclosed text, nestable (markers + removed text)
|
||||
# #- #+ #/ whitespace operators: NOT removals, left unhighlighted
|
||||
# (matched only so the '#' above does not eat the line)
|
||||
#
|
||||
# Klammer applications (@), definitions (@@), system commands (@@@):
|
||||
# @name @@name @@@name opening (@ and name are one unit)
|
||||
# name@ name@@ name@@@ named closing
|
||||
# @ @@ @@@ bare closing
|
||||
#
|
||||
# Escapes: ^@ ^# ^| ^^ the caret makes the next character literal, so it
|
||||
# is consumed and NOT treated as a delimiter. Left unscoped, to
|
||||
# match the Emacs mode, which shows escaped characters as ordinary
|
||||
# text. (A run of carets pairs left-to-right: ^^ is a literal
|
||||
# caret, a leftover single ^ escapes the following character —
|
||||
# the '\^.' rule reproduces exactly that parity.)
|
||||
#
|
||||
# Literal klammers: @code ... code@ interior is verbatim (no # or @
|
||||
# interpreted). To add another literal klammer 'foo', copy the
|
||||
# '@code' rule and the 'literal_code' context below, replacing
|
||||
# code -> foo.
|
||||
#
|
||||
# SYNC: the literal-klammer set is duplicated in three places that
|
||||
# must agree (a .sublime-syntax file is static and cannot read the
|
||||
# Emacs defcustom). When you add or remove one, mirror it in all:
|
||||
# * klammertext-literal-klammers in
|
||||
# doc/emacs/klammertext-mode.el (the source of truth)
|
||||
# * LITERAL_KLAMMERS in Klammertext.py
|
||||
# * the @NAME rule + literal_NAME context here
|
||||
# All three are currently seeded with just 'code'.
|
||||
#
|
||||
# ---------------------------------------------------------------------------
|
||||
# How open vs. close is decided (the same rule the Emacs scanner uses):
|
||||
# * a delimiter whose NAME follows the @-run (@name) is an OPENING;
|
||||
# * a bare @-run, or one whose NAME precedes it (name@), is a CLOSING.
|
||||
# Because this tokenizer runs left-to-right, an opening consumes "@name" as one
|
||||
# unit, so a trailing bare @ in the compact form @name@ is naturally a close.
|
||||
# The (?![A-Za-z0-9_@]) look-ahead on every closing keeps "foo@bar" correct:
|
||||
# @ is followed by a name, so it opens @bar and 'foo' stays plain text.
|
||||
#
|
||||
# ---------------------------------------------------------------------------
|
||||
# Scope -> color. Colors live in the color scheme, not here. The package ships
|
||||
# additive .sublime-color-scheme overrides for all five of Sublime's built-in
|
||||
# schemes (Breakers, Celeste, Mariana, Monokai, Sixteen); each merges onto its
|
||||
# scheme by filename and recolors only .klammertext scopes. They use one hue
|
||||
# system — application blue, definition green, system orange, each opening bright
|
||||
# and its close the same hue darker — shown at full intensity on dark grounds and
|
||||
# scaled down on light grounds. Exact values are in each override's header.
|
||||
#
|
||||
# Without a matching override (e.g. a third-party scheme) a stock scheme still
|
||||
# gives a meaningful default from these scope names: three klammer-family colors
|
||||
# (function / storage / keyword), muted removed text (comment), plain escapes.
|
||||
# To get the full palette on another scheme, copy one of the shipped overrides
|
||||
# to <SchemeName>.sublime-color-scheme.
|
||||
#
|
||||
# ---------------------------------------------------------------------------
|
||||
# Install: put this file — together with its companions Klammertext.py,
|
||||
# Default.sublime-keymap and Comments.tmPreferences — in a dedicated package
|
||||
# folder named 'Klammertext' under Packages/ (Preferences -> Browse Packages
|
||||
# opens Packages/):
|
||||
# ~/.config/sublime-text/Packages/Klammertext/ (Linux)
|
||||
# ~/Library/Application Support/Sublime Text/Packages/Klammertext/ (macOS)
|
||||
# A dedicated folder (not Packages/User/) keeps the bundled keymap from
|
||||
# merging into your personal one. Sublime picks it all up live and applies
|
||||
# the syntax to .kt and .k files. (The syntax file alone also works from
|
||||
# Packages/User/ if you only want highlighting.)
|
||||
#
|
||||
# ---------------------------------------------------------------------------
|
||||
# Known differences from the Emacs mode (deliberate, matching its own limits):
|
||||
# * @@ and @@@ definition BODIES are highlighted as ordinary Klammertext,
|
||||
# not treated specially — same as the Emacs mode.
|
||||
# * Delimiter MATCHING (jump + live highlight) is not in this syntax file —
|
||||
# Sublime's built-in bracket matching needs fixed character pairs, which @
|
||||
# (both open and close, decided by context) cannot provide. It lives in
|
||||
# the companion Klammertext.py instead: klammertext_jump_to_match (C-c C-j
|
||||
# equivalent) and a ViewEventListener that highlights the matching
|
||||
# delimiter as the caret moves (show-paren equivalent), both reusing one
|
||||
# context-sensitive matcher. This is a plugin concern, not a tokenizer one.
|
||||
# * Comment toggling is provided by the companion Comments.tmPreferences:
|
||||
# Ctrl-/ inserts '# ' (line removal), Ctrl-Shift-/ wraps in '#[ ... ]#'
|
||||
# (block removal).
|
||||
|
||||
name: Klammertext
|
||||
file_extensions:
|
||||
- kt
|
||||
- k
|
||||
scope: text.klammertext
|
||||
version: 2
|
||||
|
||||
variables:
|
||||
# A klammer name: letters, digits, underscore. A hyphen is NOT a name char
|
||||
# (the abbreviated form @name-arg1-arg2 ends the name at the first hyphen).
|
||||
name: '[A-Za-z0-9_]+'
|
||||
# A closing delimiter must not be followed by a name char (that would be an
|
||||
# opening @name) or another @ (that would be a longer @-run).
|
||||
not_delim: '(?![A-Za-z0-9_@])'
|
||||
|
||||
contexts:
|
||||
main:
|
||||
# --- escapes: ^X makes X literal; consumed so # / @ are not delimiters ---
|
||||
- match: '\^.'
|
||||
|
||||
# --- text removal (#) ---
|
||||
- match: '##'
|
||||
scope: punctuation.definition.comment.klammertext
|
||||
push: removal_file
|
||||
- match: '#\['
|
||||
scope: punctuation.definition.comment.klammertext
|
||||
push: removal_block
|
||||
# whitespace operators #- #+ #/ (with optional count): not removals.
|
||||
# Matched (and left unscoped) so the '#' line rule below does not consume
|
||||
# the rest of the line. Add a scope here if you would rather color them.
|
||||
- match: '#[-+/]\d*'
|
||||
- match: '#'
|
||||
scope: punctuation.definition.comment.klammertext
|
||||
push: removal_line
|
||||
|
||||
# --- literal klammer: interior is verbatim (seeded default: @code) ---
|
||||
- match: '@code(?![A-Za-z0-9_])'
|
||||
scope: entity.name.function.begin.klammertext
|
||||
push: literal_code
|
||||
|
||||
# --- system / target commands @@@ ---
|
||||
- match: '@@@{{name}}'
|
||||
scope: keyword.control.begin.klammertext # @@@name opening
|
||||
- match: '@@@{{not_delim}}'
|
||||
scope: keyword.control.end.klammertext # bare @@@ close
|
||||
- match: '{{name}}@@@{{not_delim}}'
|
||||
scope: keyword.control.end.klammertext # name@@@ named close
|
||||
|
||||
# --- klammer definitions @@ ---
|
||||
- match: '@@{{name}}'
|
||||
scope: storage.type.begin.klammertext # @@name opening
|
||||
- match: '@@{{not_delim}}'
|
||||
scope: storage.type.end.klammertext # bare @@ close
|
||||
- match: '{{name}}@@{{not_delim}}'
|
||||
scope: storage.type.end.klammertext # name@@ named close
|
||||
|
||||
# --- klammer applications @ ---
|
||||
- match: '@{{name}}'
|
||||
scope: entity.name.function.begin.klammertext # @name opening
|
||||
- match: '@{{not_delim}}'
|
||||
scope: entity.name.function.end.klammertext # bare @ close
|
||||
- match: '{{name}}@{{not_delim}}'
|
||||
scope: entity.name.function.end.klammertext # name@ named close
|
||||
|
||||
# rest of line is removed
|
||||
removal_line:
|
||||
- meta_scope: comment.line.klammertext
|
||||
- match: '\n'
|
||||
pop: true
|
||||
|
||||
# rest of file is removed (## never closes)
|
||||
removal_file:
|
||||
- meta_scope: comment.block.klammertext
|
||||
|
||||
# #[ ... ]# removed, nestable
|
||||
removal_block:
|
||||
- meta_scope: comment.block.klammertext
|
||||
- match: '#\['
|
||||
scope: punctuation.definition.comment.klammertext
|
||||
push: removal_block
|
||||
- match: '\]#'
|
||||
scope: punctuation.definition.comment.klammertext
|
||||
pop: true
|
||||
|
||||
# @code ... code@ — interior verbatim (unscoped), only the close ends it
|
||||
literal_code:
|
||||
- match: 'code@'
|
||||
scope: entity.name.function.end.klammertext
|
||||
pop: true
|
||||
102
doc/edit/sublime/Klammertext_in_Sublime_Text.md
Normal file
102
doc/edit/sublime/Klammertext_in_Sublime_Text.md
Normal file
@@ -0,0 +1,102 @@
|
||||
# Klammertext for Sublime Text
|
||||
|
||||
A Sublime Text port of the Emacs major mode for Klammertext
|
||||
(`doc/emacs/klammertext-mode.el`). It brings syntax highlighting, delimiter
|
||||
matching, and comment toggling to `.kt` and `.k` files. Behavior mirrors the
|
||||
Emacs mode closely; where the two intentionally differ, the file headers say so.
|
||||
|
||||
## Files
|
||||
|
||||
| File | Purpose |
|
||||
|------|---------|
|
||||
| `Klammertext.sublime-syntax` | Syntax highlighting. Colors the text-removal constructs (`#`, `##`, `#[...]#`) and the three `@`-tiers — application `@`, definition `@@`, system `@@@` — each as an opening vs. a close, plus `^`-escapes and verbatim `@code ... code@` spans. |
|
||||
| `Klammertext.py` | Plugin with two features that share one context-sensitive matcher: jump between an opening and its close, and live highlighting of the matching delimiter as the caret moves (mismatched or unbalanced delimiters flag in red). |
|
||||
| `Default.sublime-keymap` | Binds jump-to-match to **Ctrl+M**, scoped to Klammertext files. |
|
||||
| `Comments.tmPreferences` | Comment toggling: **Ctrl+/** inserts `# ` (line removal), **Ctrl+Shift+/** wraps in `#[ ... ]#` (block removal). |
|
||||
| `Breakers` / `Celeste` / `Mariana` / `Monokai` / `Sixteen` `.sublime-color-scheme` | Color overrides for Sublime's five built-in schemes — one hue system, full intensity on the dark schemes, scaled down on the light ones. Additive: they recolor only the Klammertext delimiters and leave the rest of each scheme unchanged. |
|
||||
| `Klammertext_in_Sublime_Text.md` | This file. |
|
||||
|
||||
## Installation
|
||||
|
||||
Put the files into a folder named `Klammertext` under Sublime's `Packages`
|
||||
directory:
|
||||
|
||||
| Platform | Path |
|
||||
|----------|------|
|
||||
| Linux | `~/.config/sublime-text/Packages/Klammertext/` |
|
||||
| macOS | `~/Library/Application Support/Sublime Text/Packages/Klammertext/` |
|
||||
| Windows | `%AppData%\Sublime Text\Packages\Klammertext\` |
|
||||
|
||||
The quickest way to find it: **Preferences → Browse Packages…** opens the
|
||||
`Packages` directory. Create the `Klammertext` folder there and copy the files
|
||||
in. Sublime loads them live — no restart — and applies the syntax to `.kt` and
|
||||
`.k` files automatically.
|
||||
|
||||
Use a dedicated folder (not `Packages/User/`) so the bundled keymap does not
|
||||
merge into your personal one. If you want highlighting only, the
|
||||
`.sublime-syntax` file alone works from `Packages/User/`.
|
||||
|
||||
The plugin targets **Sublime Text 4**: the live-highlight colors use Sublime's
|
||||
adaptive `region.*` scopes, which were added in ST4.
|
||||
|
||||
## Features and keys
|
||||
|
||||
| Trigger | Action |
|
||||
|---------|--------|
|
||||
| open a `.kt` / `.k` file | Syntax highlighting (automatic) |
|
||||
| **Ctrl+M** | Jump between a klammer application's opening and closing `@` (equivalent of the Emacs mode's `C-c C-j`) |
|
||||
| caret on a klammer `@` | The matching delimiter boxes automatically; a name mismatch or unbalanced delimiter boxes in red with a status-bar message (equivalent of `show-paren-mode`) |
|
||||
| **Ctrl+/** | Toggle line comment (`#`) |
|
||||
| **Ctrl+Shift+/** | Toggle block comment (`#[ ... ]#`) |
|
||||
|
||||
Ctrl+M is Sublime's own "go to matching bracket" key, reused here because the
|
||||
built-in cannot match Klammertext's context-dependent `@`. macOS users who
|
||||
prefer `super+m` can change it in `Default.sublime-keymap`.
|
||||
|
||||
## Colors
|
||||
|
||||
Colors are installed automatically for all five of Sublime's built-in schemes.
|
||||
Each `*.sublime-color-scheme` file (Breakers, Celeste, Mariana, Monokai,
|
||||
Sixteen) is an *additive override*: Sublime merges it onto the matching scheme
|
||||
by filename, recoloring only the Klammertext delimiters and leaving everything
|
||||
else untouched. There is nothing to set up.
|
||||
|
||||
All five share one hue system — application blue, definition green, system
|
||||
orange, each opening bright and its close the same hue darker — shown at full
|
||||
intensity on the dark schemes (Monokai, Mariana) and scaled down for contrast on
|
||||
the light schemes (Breakers, Celeste, Sixteen). Removed text uses each scheme's
|
||||
own comment grey.
|
||||
|
||||
For any other scheme — a legacy `.tmTheme` such as Solarized, or a third-party
|
||||
scheme — copy one of the included files to `<Scheme Name>.sublime-color-scheme`
|
||||
in the package folder (its name is shown at **Preferences → Settings** under
|
||||
`color_scheme`), choosing a light or dark source file to match the ground. The
|
||||
exact values are in each file's header comment.
|
||||
|
||||
## Keeping literal klammers in sync
|
||||
|
||||
Klammers whose content is verbatim (`@code ... code@`) are listed in three
|
||||
places that must agree — a Sublime syntax/plugin cannot read the Emacs
|
||||
defcustom, so the list is duplicated:
|
||||
|
||||
- `klammertext-literal-klammers` in `doc/emacs/klammertext-mode.el` (the source of truth)
|
||||
- `LITERAL_KLAMMERS` in `Klammertext.py`
|
||||
- the `@code` rule and `literal_code` context in `Klammertext.sublime-syntax`
|
||||
|
||||
All three are seeded with just `code`. When you add or remove a literal
|
||||
klammer, change all three.
|
||||
|
||||
## Not included
|
||||
|
||||
Whole-file semantic validation — persistent error underlines when the cursor is
|
||||
elsewhere, klammer-name completion, go-to-definition — is not part of this
|
||||
package. That would need a language server (used through the Sublime LSP
|
||||
package), a separate program, and is unrelated to the highlighting and matching
|
||||
provided here.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
If the plugin does not seem to load, open **View → Show Console** for any error
|
||||
message. Check that the files sit directly inside `Packages/Klammertext/` (not
|
||||
a nested subfolder) and that the current file's syntax reads "Klammertext" in
|
||||
the status bar at the bottom-right of the window.
|
||||
60
doc/edit/sublime/Mariana.sublime-color-scheme
Normal file
60
doc/edit/sublime/Mariana.sublime-color-scheme
Normal file
@@ -0,0 +1,60 @@
|
||||
// Klammertext colors for the "Mariana" scheme (dark ground).
|
||||
// One hue system across all schemes: application = blue, definition =
|
||||
// green, system = orange; each opens bright and its close is 80%% of the
|
||||
// open (a klammer "begins bright and gets dark"). Shown at full intensity
|
||||
// on dark grounds, at 60%% on light grounds for contrast. Delimiters are
|
||||
// forced to normal style. Merged onto Mariana by filename; recolors only
|
||||
// .klammertext scopes. (The highlighting was first developed as an Emacs
|
||||
// major mode; see Klammertext_in_Sublime_Text.md.)
|
||||
//
|
||||
// #a6acb9 removed text (Mariana's comment grey)
|
||||
// #ff6b6b removal markers
|
||||
// #89ddff @name open blue
|
||||
// #6eb1cc name@ close darker blue
|
||||
// #c3e88d @@name open green
|
||||
// #9cba71 name@@ close darker green
|
||||
// #ffab70 @@@name open orange
|
||||
// #cc895a name@@@ close darker orange
|
||||
{
|
||||
"name": "Mariana",
|
||||
"rules": [
|
||||
{
|
||||
"scope": "comment.line.klammertext, comment.block.klammertext",
|
||||
"foreground": "#a6acb9"
|
||||
},
|
||||
{
|
||||
"scope": "punctuation.definition.comment.klammertext",
|
||||
"foreground": "#ff6b6b"
|
||||
},
|
||||
{
|
||||
"scope": "entity.name.function.begin.klammertext",
|
||||
"foreground": "#89ddff",
|
||||
"font_style": ""
|
||||
},
|
||||
{
|
||||
"scope": "entity.name.function.end.klammertext",
|
||||
"foreground": "#6eb1cc",
|
||||
"font_style": ""
|
||||
},
|
||||
{
|
||||
"scope": "storage.type.begin.klammertext",
|
||||
"foreground": "#c3e88d",
|
||||
"font_style": ""
|
||||
},
|
||||
{
|
||||
"scope": "storage.type.end.klammertext",
|
||||
"foreground": "#9cba71",
|
||||
"font_style": ""
|
||||
},
|
||||
{
|
||||
"scope": "keyword.control.begin.klammertext",
|
||||
"foreground": "#ffab70",
|
||||
"font_style": ""
|
||||
},
|
||||
{
|
||||
"scope": "keyword.control.end.klammertext",
|
||||
"foreground": "#cc895a",
|
||||
"font_style": ""
|
||||
}
|
||||
]
|
||||
}
|
||||
60
doc/edit/sublime/Monokai.sublime-color-scheme
Normal file
60
doc/edit/sublime/Monokai.sublime-color-scheme
Normal file
@@ -0,0 +1,60 @@
|
||||
// Klammertext colors for the "Monokai" scheme (dark ground).
|
||||
// One hue system across all schemes: application = blue, definition =
|
||||
// green, system = orange; each opens bright and its close is 80%% of the
|
||||
// open (a klammer "begins bright and gets dark"). Shown at full intensity
|
||||
// on dark grounds, at 60%% on light grounds for contrast. Delimiters are
|
||||
// forced to normal style. Merged onto Monokai by filename; recolors only
|
||||
// .klammertext scopes. (The highlighting was first developed as an Emacs
|
||||
// major mode; see Klammertext_in_Sublime_Text.md.)
|
||||
//
|
||||
// #8a8272 removed text (Monokai's comment grey)
|
||||
// #ff6b6b removal markers
|
||||
// #89ddff @name open blue
|
||||
// #6eb1cc name@ close darker blue
|
||||
// #c3e88d @@name open green
|
||||
// #9cba71 name@@ close darker green
|
||||
// #ffab70 @@@name open orange
|
||||
// #cc895a name@@@ close darker orange
|
||||
{
|
||||
"name": "Monokai",
|
||||
"rules": [
|
||||
{
|
||||
"scope": "comment.line.klammertext, comment.block.klammertext",
|
||||
"foreground": "#8a8272"
|
||||
},
|
||||
{
|
||||
"scope": "punctuation.definition.comment.klammertext",
|
||||
"foreground": "#ff6b6b"
|
||||
},
|
||||
{
|
||||
"scope": "entity.name.function.begin.klammertext",
|
||||
"foreground": "#89ddff",
|
||||
"font_style": ""
|
||||
},
|
||||
{
|
||||
"scope": "entity.name.function.end.klammertext",
|
||||
"foreground": "#6eb1cc",
|
||||
"font_style": ""
|
||||
},
|
||||
{
|
||||
"scope": "storage.type.begin.klammertext",
|
||||
"foreground": "#c3e88d",
|
||||
"font_style": ""
|
||||
},
|
||||
{
|
||||
"scope": "storage.type.end.klammertext",
|
||||
"foreground": "#9cba71",
|
||||
"font_style": ""
|
||||
},
|
||||
{
|
||||
"scope": "keyword.control.begin.klammertext",
|
||||
"foreground": "#ffab70",
|
||||
"font_style": ""
|
||||
},
|
||||
{
|
||||
"scope": "keyword.control.end.klammertext",
|
||||
"foreground": "#cc895a",
|
||||
"font_style": ""
|
||||
}
|
||||
]
|
||||
}
|
||||
60
doc/edit/sublime/Sixteen.sublime-color-scheme
Normal file
60
doc/edit/sublime/Sixteen.sublime-color-scheme
Normal file
@@ -0,0 +1,60 @@
|
||||
// Klammertext colors for the "Sixteen" scheme (light ground).
|
||||
// One hue system across all schemes: application = blue, definition =
|
||||
// green, system = orange; each opens bright and its close is 80%% of the
|
||||
// open (a klammer "begins bright and gets dark"). Shown at full intensity
|
||||
// on dark grounds, at 60%% on light grounds for contrast. Delimiters are
|
||||
// forced to normal style. Merged onto Sixteen by filename; recolors only
|
||||
// .klammertext scopes. (The highlighting was first developed as an Emacs
|
||||
// major mode; see Klammertext_in_Sublime_Text.md.)
|
||||
//
|
||||
// #b8b8b8 removed text (Sixteen's comment grey)
|
||||
// #994040 removal markers
|
||||
// #528599 @name open blue
|
||||
// #426a7a name@ close darker blue
|
||||
// #758b55 @@name open green
|
||||
// #5e7044 name@@ close darker green
|
||||
// #996743 @@@name open orange
|
||||
// #7a5236 name@@@ close darker orange
|
||||
{
|
||||
"name": "Sixteen",
|
||||
"rules": [
|
||||
{
|
||||
"scope": "comment.line.klammertext, comment.block.klammertext",
|
||||
"foreground": "#b8b8b8"
|
||||
},
|
||||
{
|
||||
"scope": "punctuation.definition.comment.klammertext",
|
||||
"foreground": "#994040"
|
||||
},
|
||||
{
|
||||
"scope": "entity.name.function.begin.klammertext",
|
||||
"foreground": "#528599",
|
||||
"font_style": ""
|
||||
},
|
||||
{
|
||||
"scope": "entity.name.function.end.klammertext",
|
||||
"foreground": "#426a7a",
|
||||
"font_style": ""
|
||||
},
|
||||
{
|
||||
"scope": "storage.type.begin.klammertext",
|
||||
"foreground": "#758b55",
|
||||
"font_style": ""
|
||||
},
|
||||
{
|
||||
"scope": "storage.type.end.klammertext",
|
||||
"foreground": "#5e7044",
|
||||
"font_style": ""
|
||||
},
|
||||
{
|
||||
"scope": "keyword.control.begin.klammertext",
|
||||
"foreground": "#996743",
|
||||
"font_style": ""
|
||||
},
|
||||
{
|
||||
"scope": "keyword.control.end.klammertext",
|
||||
"foreground": "#7a5236",
|
||||
"font_style": ""
|
||||
}
|
||||
]
|
||||
}
|
||||
45
doc/edit/sublime/example.kt
Normal file
45
doc/edit/sublime/example.kt
Normal file
@@ -0,0 +1,45 @@
|
||||
# This is a line comment — removed to end of line, in the "ignored" color.
|
||||
# The # marker is a different color from the text it removes.
|
||||
|
||||
#[ This is a block comment. It can span lines,
|
||||
and #[ nest ]# like this. ]#
|
||||
|
||||
# --- Klammer applications (@) : opening @name vs. closing name@ / bare @ ---
|
||||
|
||||
@i italic @ @b bold @ @tt monospace @
|
||||
|
||||
@sup 2 | 3 @ # positional arguments separated by |
|
||||
@sup-2-3 # the abbreviated form colors only the name
|
||||
|
||||
@link https://example.com :text a labelled link @
|
||||
|
||||
A named close is handy for long arguments: @section a long body here section@
|
||||
|
||||
# --- Klammer definitions (@@) and system commands (@@@) ---
|
||||
|
||||
@@mdlh : @i Material Definition Language Handbook @ @@
|
||||
@@heading.html : *arg* @@
|
||||
@@@target html | HTML output | options @@@
|
||||
|
||||
# --- Escapes: a caret makes the next character literal (shown as plain text) ---
|
||||
|
||||
^@ and ^# and ^^ and ^| are literal, not delimiters.
|
||||
|
||||
# --- Literal klammer: @code ... code@ interior is verbatim ---
|
||||
# The stray @ and # below are NOT delimiters inside a literal span:
|
||||
|
||||
@code
|
||||
if (a @ b) { return "# not a comment"; }
|
||||
code@
|
||||
|
||||
# --- Whitespace operators (#- #+ #/) are not removals; shown as plain text ---
|
||||
|
||||
tight#-spacing gap#+3here break#/2line
|
||||
|
||||
# --- A deliberate MISMATCH: put the cursor on @open or close@ to see it turn ---
|
||||
# --- red with a message (the names disagree); a matched pair boxes normally. ---
|
||||
|
||||
@open some content close@
|
||||
|
||||
## Everything from this line to the end of the file is removed (## = to EOF).
|
||||
this trailing line is greyed out as removed text
|
||||
Reference in New Issue
Block a user