| Commit message (Collapse) | Author | Age |
| |
|
|
|
|
|
|
| |
Problem:
By default, 'termpastefilter' removes TAB chars when pasting to a :terminal.
Very annoying, and does not improve "security".
Solution:
Drop "HT" from the 'termpastefilter' default.
|
| |
|
|
|
|
|
|
|
|
| |
Work towards enabling "flow" layout in most `:help` files.
Since [tables are supported in help](https://github.com/neovim/tree-sitter-vimdoc#tables),
it's now possible to render most help files as ["flow" layout](https://github.com/neovim/neovim/blob/9244da12e400ec0291450a5e9400d995e7a29b83/src/gen/gen_help_html.lua#L86-L88)
instead of the legacy fixed-width layout. Besides [improved HTML rendering](https://github.com/neovim/neovim/pull/42381#discussion_r4285705739),
flow layout will allow `:help` presentation-mode to un-hardwrap text
blocks.
|
| |
|
|
|
|
|
|
|
|
| |
Work towards enabling "flow" layout in most `:help` files.
Since [tables are supported in help](https://github.com/neovim/tree-sitter-vimdoc#tables),
it's now possible to render most help files as ["flow" layout](https://github.com/neovim/neovim/blob/9244da12e400ec0291450a5e9400d995e7a29b83/src/gen/gen_help_html.lua#L86-L88)
instead of the legacy fixed-width layout. Besides [improved HTML rendering](https://github.com/neovim/neovim/pull/42381#discussion_r4285705739),
flow layout will allow `:help` presentation-mode to un-hardwrap text
blocks.
|
| |
|
|
|
|
|
|
|
|
| |
Work towards enabling "flow" layout in most `:help` files.
Since [tables are supported in
help](https://github.com/neovim/tree-sitter-vimdoc#tables), it's now possible to
render most help files as ["flow" layout](https://github.com/neovim/neovim/blob/9244da12e400ec0291450a5e9400d995e7a29b83/src/gen/gen_help_html.lua#L86-L88)
instead of the legacy fixed-width layout. Besides [improved HTML rendering](https://github.com/neovim/neovim/pull/42381#discussion_r4285705739),
flow layout will allow `:help` presentation-mode to un-hardwrap text blocks.
https://github.com/neovim/neovim/issues/31825
|
| |
|
| |
highlights.scm: `#match` is slow, prefer `#lua-match`.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Problem: nvim_set_option_value() dry runs skip checks in did_set_*
callbacks. This logic also prepares values needed to apply the option,
such as tab widths or a compiled regexp. Moving the checks into
validation callbacks needs a way to save that work for did_set_*.
Solution: Store prepared values in optset_T so did_set_* can consume
them after the option is stored. Dry runs perform the same validation,
then free the prepared values without changing live state.
This extends dry-run validation for:
- 'cedit': reject invalid command-line window keys.
- 'completeitemalign': require each completion column exactly once.
- 'cursorlineopt': reject empty values and conflicting line modes.
- 'encoding': accept only UTF-8 and its aliases.
- 'fileencoding': reject lists and local changes with 'nomodifiable'.
- 'messagesopt': require mandatory fields and enforce numeric limits.
- 'spellcapcheck': return regexp errors, including under :silent!.
- 'spellsuggest': reject conflicting suggestion modes.
- 'varsofttabstop' and 'vartabstop': reject invalid tab widths.
- 'wildmode': reject more than four completion stages.
'makeencoding' also uses the shared encoding preparation.
Separating value preparation exposed a bug in 'vartabstop' and
'varsofttabstop': failed assignments could discard local tab widths, and
global assignments could overwrite them. Fix this by preparing new
widths separately and applying them only after a valid local assignment.
AI-assisted
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Problem:
- `<` before a listitem (`< - foo`) is not concealed.
- Codeblock HTML has extra blank lines.
- Codeblock in a listitem ends the listitem, so HTML docs drop the rest
of the item and its nesting. Example from `:h nvim_open_win()`:
```
• border: … the double-box style can be specified as: >
[ "╔", "═" ,"╗", "║", "╝", "═", "╚", "║" ].
<
If fewer than eight chars are given, they will be repeated.
• bufpos: …
tree-sitter-vimdoc v4.1.0:
(block
(line_li (prefix) (line) (codeblock (code (line)))))
(block
(line) ; "If fewer…"
(line_li (prefix) (line) (line))) ; "bufpos"
tree-sitter-vimdoc v4.2.0:
(block
(line_li (prefix) (line) (codeblock (code (line)))
(line)) ; "If fewer…"
(line_li (prefix) (line) (line))) ; "bufpos"
```
Solution:
- Bump tree-sitter-vimdoc to v4.2.0. https://github.com/neovim/tree-sitter-vimdoc/pull/174
- gen_help_html: get listitem indent from its first line
- gen_help_html: don't double codeblock newlines.
- highlight query: conceal `<` in `line_li`.
- docs: fix doc sources where a blank line was missing after listitems
followed by non-listitem text.
|
| |
|
|
|
|
|
|
|
|
|
|
| |
Problem:
'isident' decides how env var names are parsed, which is more
"confusing" than "useful":
- Changing 'isident' (for 'define' or "\i") can break `$NAME` expansion.
- Its default byte ranges let multibyte names work on Windows (`$aあ`)
but not Unix (`$é`).
Solution:
Ignore 'isident' when parsing env var names.
|
| |
|
|
|
|
|
|
|
|
|
|
| |
Problem:
- At session end, `'< '>` revert to the session-start snapshot, which
drops a selection made during the session. And the snapshot may be
from another buffer.
- `zqgj` skips screen rows: `zq` tries the motion before the steps, and
those trial runs advance `w_curswant`.
Solution:
- Keep the primary's `'< '>` at session-end.
- Restore `w_curswant` after the trial runs and after each run of steps.
|
| |\ |
|
| | |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
Problem 1: many status line sections are automatically hidden when they
currently aren't relevant. When such a section contains highlights, the
exact pre-section highlighting needs to be reset at the end, otherwise
the highlighting of unrelated sections to the right depend on whether
the section is hidden or not. And in case of auto-hiding item groups,
it might even refuse to hide.
Problem 2: when only a part in the middle of a section should deviate
from the surrounding highlighting, the section needs knowledge of the
highlighting outside in order to reset it, which makes it hard to create
self-contained, reusable modules.
Problem 3: with nested sections of progressively stacked highlighting
changes, the last %$-modifications effectively have to be subtracted
when ending a subsection. This can only be done by replaying all the
pre-subsection changes from the last %#.
Solution: Introduce highlight scopes %#(...%#) that automatically reset
pre-scope highlighting at the end.
ref #26037
ref #29976
ref #29980
ref #35806
ref #36685
|
| |/
|
|
|
|
|
|
| |
Problem:
- gQ does not restore follow-mode (q=).
- Users/plugins have no way to check if follow-mode is enabled.
Solution:
Introduce buffer-local 'follow' option.
|
| |
|
|
|
|
|
|
|
|
|
|
|
| |
In the `enc=utf-8` only world, the 'isprint' option is quite obsolete.
The function is only consulted for decoded U+0080 to U+00FF chars
whose printability is defined by the unicode charset, just like
higher codepoints. Meanwhile, invalid `\x80` to `\xFF` bytes are always
unprintable.
Disentangle 'iskeyword', 'isfname' and 'isident' from each other by
giving them all separate bitsets. Now these can be updated individually.
These updaters can back out of errors gracefully, no need for extra
panic logic in option[str].c to restore partially updated chartabs.
|
| |
|
|
|
|
|
|
|
|
|
|
|
| |
Problem:
Dict schema checks are mixed into individual option validators.
Solution:
Check schemas before calling option validators. Remove the redundant
checks and callback entries.
AI-assisted
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Problem:
nvim_set_option_value() dry runs skip checks in did_set_* callbacks.
Solution:
Split validation out of these callbacks so dry runs and normal
assignments use the same checks.
Read 'mkspellmem' limits when building spell files. Keep the
'spellsuggest' limit unchanged when an assignment fails.
AI-assisted
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Problem:
nvim_set_option_value() with dry_run=true accepts invalid values such as
foldmethod='nonsense'. Validation is mixed with side effects in the
did_set_* callbacks, so dry runs skip it.
Solution:
Split value validation out of the did_set_* callbacks into separate
validation_cb callbacks. Use these checks for both normal assignments
and nvim_set_option_value() dry runs. Keep side effects in did_set_*.
Replace direct foldenable/foldlevel assignments in C folding commands
with setters. This gives C commands the same OptionSet and
synchronization behavior as Lua assignments.
Use normal setters for 'tabstop' and 'vartabstop' in :retab so C code
indentation and folds based on indentation use the new tab widths.
Direct assignments could leave them using the old widths.
:retab temporarily turns off 'list' to calculate tab widths. Previously,
:retab -1 reported an error and returned without restoring 'list'. Check
the argument before turning 'list' off, so an invalid argument leaves
the option unchanged.
AI-assisted
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
'cursorlineopt' (#41785)
Problem: CursorLineFold and CursorLineSign are only applied when
'cursorlineopt' contains "number" or is "both"
(Evgeni Chasnovski).
Solution: Apply those groups whenever 'cursorline' is set, independent
of 'cursorlineopt' (Vrushali Zampalkar).
fixes: vim/vim#20480
closes: vim/vim#21112
https://github.com/vim/vim/commit/1f8d3c44c5bd5a3d5032b3fc53e9d3aa1052583c
Co-authored-by: Vrushali-Z <zampalkarvasu@gmail.com>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Problem: there should be exactly one cell of padding between sections,
and exactly one cell of minimum padding between the left and the right.
- Spaces between sections waste space when a section is empty.
According to a comment in #33036, this was the reason to avoid `%k`
and implement the keymap section with a vim expression, but other
sections still have this problem.
- The diagnostics section wastes space because it is not entirely empty
when there are diagnostics in another buffer.
- The terminal exit code section can touch the right side, e.g. the
ruler, even though it belongs to the left side.
Solution:
- Use auto-hiding item groups (`%(` without width fields) to get rid of
unneeded spaces when a section shows no information.
This simplifies the 'showcmd' and 'keymap' sections in particular.
- As a slight simplification, `term_exitcode` is moved into the flags
section since it is formatted with square brackets like a flag.
- Count the diagnostics for the current buffer specifically.
- Ensure at least one cell of padding between the left and the right
side by adding a space next to the separator `%=`.
Problem: some sections are implemented with `%{%`, even though
reevaluation of the expression result is not needed.
This leads to otherwise needless %-escaping in `progress_status`.
Solution: use `%{` instead.
Problem: `%{` and `%{%` (without items) replace spaces with fillchars.
This looks out-of-place inside the terminal exit code section, and in
contrast to all other sections, the 'busy' section is surrounded by
fillchars, which looks inconsistent, and with some terminal-font
combinations, ◐ overlaps the fillchar, e.g. Alacritty & JetBrains Mono.
Solution: use non-breaking spaces U+202F to avoid fillchar substitution.
Problem: sections that appear/disappear frequently can make otherwise
more stable sections jump around a lot.
Solution: sort the sections on the right roughly by volatility:
'showcmd' in first place, 'keymap' next to the ruler.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Problem:
In order for ui2 to graduate to the main "messages ui" its configuration
needs to graduate into actual options.
Solution:
Migrate some of its config to 'messagesopt':
- "maxheight" (note: currently this is an integer treated as
a "percentage"; if we want to support a row count we could allow
values with units, like `"42%"`)
- "pager"
- "timeout"
Also improves error messages:
messagesopt=hit-enter,history:500,bogus E474: Unknown item 'bogus'
messagesopt=hit-enter,history:500,progress:x E474: 'progress' must be one of: , c
messagesopt=hit-enter,history:abc E474: 'history' requires a number
|
| |
|
|
|
|
|
|
|
|
| |
Remove the note about "this function is called only once per :find
command invocation".
fixes: vim/vim#21062
https://github.com/vim/vim/commit/bce3eb1fae71671b39756a77c9b1db203311ba0c
Co-authored-by: Christian Brabandt <cb@256bit.org>
|
| |
|
| |
Extract vimscript.txt from repeat.txt
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Problem:
Buffer-local CWD (:bcd) is "sticky", similar to window-local CWD (:lcd).
But this contradicts one of its main benefits: per-buffer "project root"
for LSP, OSC7.
Other problems:
- A buffer created with :edit/:enew/:new silently inherits b_localdir
(and b_prevdir) from the previous buffer.
- curbuf_reusable() refuses to recycle a scratch buffer that has
`b_localdir`.
- After :new/:vnew/:tabnew the CWD sticks to previous buffer's
`b_localdir` even though the new curbuf has none, so :new is not
equivalent to ":split | enew", and getcwd() disagrees with
haslocaldir().
- Requires "which buffer spawned this buffer" semantics that no other
buffer-local state has.
Solution:
Drop sticky/inherit behavior of buffer-local CWD (:bcd).
- do_ecmd: always apply the new curbuf's dir (`fix_current_dir`), like
`do_autochdir` already does. :tabnew from a :bcd buffer now reverts to
global CWD (and fires DirChanged), same as :tabnew from a :lcd window.
- curbuf_reusable(): recycling a scratch buffer frees its b_localdir.
To get sticky/inherit behavior of CWD, use `:lcd`.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Problem:
The default 'ruler' is implemented in C instead of the 'statusline' DSL.
Solution:
Replace the C implementation with a default 'rulerformat' expression.
This is a continuation of #1248 and #33036.
Advantages:
- configuration is more discoverable, the default being a useful example
- users and plugins can augment the default
- code reuse and less C code to maintain
- ui2: due to the use of an item group with `minwid`, it can expand
instead of truncating when the content gets too long, which is
particularly useful for locales with long translations of Top/Bot/All
Implementation details:
As is the case for 'statusline', when trying to set 'rulerformat' to an
empty string, the default expression is restored instead, mimicking how
previously the default C implementation would have been activated.
Just like before, `:set rulerformat=` and `:set rulerformat&` have the
same effect, and the ruler is disabled with `:set noruler`.
The default expression uses an item group with `%=`, unlike the fallback
in the previous default statusline `%-14.(%l,%c%V%) %P`, because the
total width and how it is configured is immediately clear without
documentation, it is a more useful pattern in general that works when
both sides have flexible width, and it also works for vim, which is
useful for configuration sharing/reuse.
A truncation marker `%<` is added at the end to mimic how at small
screen widths, the scroll percentage would disappear first, so that the
cursor position can remain fully visible.
BREAKING CHANGES:
- `&rulerformat` can no longer be set to an empty string
- ui2: the default ruler is no longer of fixed width, but can expand
- at very small screen widths (< 36 columns)
- ui2: it will no longer try to shrink white-space before truncating
- it truncates gradually from the right, whereas previously, the
scroll percentage would disappear all at once
- l10n can no longer add a space after the comma between line and column
(this was only done for one language: Ukrainian)
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Problem: Traditionally, the ruler in the last line is one cell shorter
than in the statusline, leaving the last cell of the screen blank.
According to code comments, this is in order to prevent unwanted
scrolling on "some" (unspecified, but presumably ancient) terminals.
Berkeley vi is more specific in its `vs_modeline` function: dumb
terminals with hardware scroll, SunOS 4.1.1 and Ultrix 4.2 curses.
(n)curses still has a similar limitation in `(w)addstr`, but apparently
only for historical reasons.
Maintaining the different widths leads to awkward inconsistencies when
the ruler is configured with 'rulerformat', except for the special case
where it contains a top-level `%=`. Shifting the ruler in the last line
to the left would be a solution, but the empty cell at the end doesn't
seem to be relevant anymore.
Solution: extend the ruler in the last line all the way to the right
edge of the screen, just like in the statusline. The exact same amount
of place will be available to the rest of the UI as before.
BREAKING CHANGE:
- the default ruler width is now 18 cells
- the last cell of the screen is no longer empty
Closes #41076
|
| | |
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Problem:
Numerous callers have to manually check optval ownership (i.e. whether,
and how, to release) via `is_callback_option`, `option_is_global_local`,
etc. This is fragile, hard to use correctly; and if we introduce another
optval variant in the future, we'll have to redo all of these careful
checks and boilerplate again.
Solution:
Provide a unified system and use it everywhere:
optval_free_owned
optval_is_owned
optval_own
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Problem:
Cannot assign Lua functions/closures to "func" ('completefunc',
'tagfun', …) or "expr" ('foldexpr', 'indentexpr', …) options.
Solution:
- Store "func"/"expr" options as `Callback` instead of string.
- Delete oceans of copy-pasted code.
- BREAKING: LuaRef returned via RPC/Vimscript is now represented as
`"<Lua N: file:line>"` (like what `:map` shows) instead of `nil`.
- Note: `man.vim` still uses `v:lua` string, bc it's a vimscript ftplugin.
Helped-by: Lewis Russell <lewis6991@gmail.com>
|
| |
|
|
|
|
|
| |
fixes: vim/vim#20875
https://github.com/vim/vim/commit/b4ae16ca3ed558e4b2da28bbb05c15fb4fdcd4eb
Co-authored-by: Christian Brabandt <cb@256bit.org>
|
| |
|
|
| |
Use a schema instead of manual parsing.
|
| |
|
|
|
|
|
|
|
|
| |
The parent commit made a valiant effort to store "dict options" in their
reified form, but this is more trouble than it's worth:
- inconsistent model for developers to understand.
- string lifetime issues (the "varp" convention is to pass around an
aliased, long-lived option value).
- lots of extra plumbing to deal with the 2 different option-storage
paradigms.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Problem:
Options parsing is still painful for dict-style options.
Solution:
schema-maxxing => better `opt:get()` (will be the basis for `vim.o()`),
unified (and more-detailed) err msgs.
- Drop bespoke structure-builder in `_core/options.lua`.
- Define `schema` for all non-primitive options (except 'guicursor' and
statusline-style options); generate reified keysets `OptKeyDict`).
- Generate 'fillchars' => `fcs_tab`, 'listchars' => `lcs_tab`.
- `nvim_set_option_value`:
- Return the improved structures. Also from `vim.opt.x:get()`.
- Eliminate api <=> lua roundtrip, centralize option structure
handling.
- Improve/unify errors.
- Bump ERR_BUFLEN 80 → 256 so the "one of" list isn't truncated.
- Eliminate old 'diffopt' order-dependence (`iwhiteall` before `iwhite`)
Error samples:
Typed-key path (opt_strings_check → diffopt/mousescroll/breakindentopt):
E474: Unknown item 'foo'
E474: 'context' requires a number
E474: 'ver' number is out of range
E474: 'algorithm' must be one of: myers, minimal, patience, histogram
E474: 'filler' does not take a value
Related:
- #31084
- #34661
- #31820
- #14739
- #20107
- fix #18875
- :get() returns `{ sbr = true, shift = '3' }` (reified-keyset) instead of `{'sbr', 'shift:3'}`
- Setting via table now works too. `object_as_optval_for` `is_map` now recognizes struct options.
- fix #30296
- instead of `E474: Invalid argument`, errors now look like:
```
E474: Invalid value 'x', expected one of: single, double: ambiwidth=x
E474: Unknown item 'foo': diffopt=foo
E474: 'context' requires a number: diffopt=context:x
```
simplify `win_float_parse_option` from #26799.
|
| |
|
|
|
|
|
|
| |
Problem:
The preview-window (:pedit, etc.) always uses a split, but it would be
useful as a floatwin (or "popup").
Solution:
Support Vim's 'previewpopup' option.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
colors (#40917)
Problem: When the terminal reports no colors ("t_Co" is 0 or 1) the
insert mode completion popup menu is not shown at all, while
the command line completion popup menu ('wildoptions' contains
"pum") is shown. In 'wildmenu' completion the current match
cannot be told apart from the other matches (Maxim Kim)
Solution: Show the insert mode completion popup menu regardless of the
number of colors and add "term" attributes to the default
highlighting of Pmenu, PmenuSel and PmenuThumb. The wildmenu
is drawn with the attributes of the status line, which is
reversed, and on most terminals the standout mode is the same
as the reverse mode, thus use the underline mode for the
default highlighting of WildMenu (Hirohito Higashi).
fixes: vim/vim#20800
closes: vim/vim#20803
https://github.com/vim/vim/commit/52485e0d24ade45e02ecba9aeadaec66500d15fe
Co-authored-by: Hirohito Higashi <h.east.727@gmail.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
| |\ |
|
| | |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
Problem: ui2's ruler is no longer of fixed width, and the internal width
variable `ru_wid` now acts as an arbitrary maximum, which is unnecessary
because the same can now be achieved transparently with an item group.
Furthermore, the old way of setting `ru_wid` with an overloaded subset
of the item group syntax leads to a number of inconsistencies. In
particular, when the configured ruler expression is reused for including
the ruler into the statusline, where the item group syntax is
interpreted in the usual way. The fact that this width is set in the
`minwid` position is more confusing now that it is a de-facto maximum.
Solution: for ui2, constrain the ruler only by half the screen width,
which previously was an additional limit relevant on small screens.
Skip the special-case treatment of the ruler's leading item group spec,
process it like a normal item group.
Example: the current fallback ruler expression in the default statusline
now actually works for `rulerformat` itself:
set rulerformat=%-14.(%l,%c%V%)\ %P
because the result can naturally expand to 18 cells instead of being
truncated to the default 17 cells, and removing the period after
`minwid` doesn't change the result, whereas before, it would unhelpfully
lead to setting the fixed ruler width to 14 cells.
BREAKING CHANGE: if the user used to set the ruler's fixed width, it
will now be treated as minimum instead of a maximum width, which in
practice increases backwards-compatibility with ui1 and vim. The main
remaining difference is that item groups are right-aligned by default,
but backwards-compatibility can be achieved by setting a negative
`minwid`, which ui1 and vim ignore. To restore the previous fixed width,
specify `maxwid` as well, but this does not work in ui1 and vim.
If `rulerformat` contains a `%=` without enclosing item group, it will
now expand to fill half the screen width. But in that case, it will
already spread out similarly in the new expression-based statusline, so
consistency of the ruler in both positions is increased.
To simulate the previous default behaviour, wrap it in `%-17.17(...%)`.
For best compatibility and reuse with vim, leave out `maxwid` and make
`minwid` negative, e.g. `%-20(...%)`.
fix https://github.com/neovim/neovim/issues/40247
|
| |/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|