@akiojin/gwt 6.30.3 → 9.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.cargo/config.toml +2 -0
- package/.claude-plugin/marketplace.json +18 -0
- package/.coderabbit.yaml +8 -0
- package/.codex/skills/gwt-fix-issue/scripts/inspect_issue.py +833 -0
- package/.dockerignore +63 -0
- package/.gitattributes +27 -0
- package/.husky/commit-msg +2 -0
- package/.husky/pre-commit +9 -0
- package/.husky/pre-push +12 -0
- package/.markdownlint.json +18 -0
- package/.markdownlintignore +2 -0
- package/Dockerfile +58 -0
- package/README.ja.md +161 -484
- package/README.md +164 -444
- package/cliff.toml +56 -0
- package/clippy.toml +2 -0
- package/cmake/ci-disable-native.cmake +16 -0
- package/codecov.yml +16 -0
- package/commitlint.config.cjs +107 -0
- package/deny.toml +35 -0
- package/docker-compose.yml +59 -0
- package/messages/errors.toml +52 -0
- package/package.json +12 -22
- package/rustfmt.toml +8 -0
- package/scripts/check-e2e-coverage-threshold.mjs +238 -0
- package/scripts/entrypoint.sh +36 -25
- package/scripts/install-linux-deps.sh +46 -0
- package/scripts/postinstall.js +79 -227
- package/scripts/release_issue_refs.py +317 -0
- package/scripts/run-local-backend-tests-on-commit.sh +15 -0
- package/scripts/run-local-e2e-coverage-on-commit.sh +69 -0
- package/scripts/run-local-e2e-on-commit.sh +60 -0
- package/scripts/test-all.sh +13 -0
- package/scripts/test_release_issue_refs.py +257 -0
- package/scripts/validate-skill-frontmatter.sh +108 -0
- package/scripts/verify-ci-node-toolchain.sh +76 -0
- package/scripts/verify-husky-hooks.sh +6 -0
- package/scripts/voice-eval.sh +48 -0
- package/tests/voice_eval/README.md +53 -0
- package/tests/voice_eval/manifest.template.json +55 -0
- package/tests/voice_eval/samples/.gitkeep +1 -0
- package/tests/voice_eval/script-ja.txt +10 -0
- package/vendor/ratatui-core/src/backend/test.rs +1077 -0
- package/vendor/ratatui-core/src/backend.rs +405 -0
- package/vendor/ratatui-core/src/buffer/assert.rs +71 -0
- package/vendor/ratatui-core/src/buffer/buffer.rs +1388 -0
- package/vendor/ratatui-core/src/buffer/cell.rs +377 -0
- package/vendor/ratatui-core/src/buffer.rs +9 -0
- package/vendor/ratatui-core/src/layout/alignment.rs +89 -0
- package/vendor/ratatui-core/src/layout/constraint.rs +526 -0
- package/vendor/ratatui-core/src/layout/direction.rs +63 -0
- package/vendor/ratatui-core/src/layout/flex.rs +212 -0
- package/vendor/ratatui-core/src/layout/layout.rs +2838 -0
- package/vendor/ratatui-core/src/layout/margin.rs +79 -0
- package/vendor/ratatui-core/src/layout/offset.rs +66 -0
- package/vendor/ratatui-core/src/layout/position.rs +253 -0
- package/vendor/ratatui-core/src/layout/rect/iter.rs +356 -0
- package/vendor/ratatui-core/src/layout/rect/ops.rs +136 -0
- package/vendor/ratatui-core/src/layout/rect.rs +1114 -0
- package/vendor/ratatui-core/src/layout/size.rs +147 -0
- package/vendor/ratatui-core/src/layout.rs +333 -0
- package/vendor/ratatui-core/src/lib.rs +82 -0
- package/vendor/ratatui-core/src/style/anstyle.rs +348 -0
- package/vendor/ratatui-core/src/style/color.rs +788 -0
- package/vendor/ratatui-core/src/style/palette/material.rs +608 -0
- package/vendor/ratatui-core/src/style/palette/tailwind.rs +653 -0
- package/vendor/ratatui-core/src/style/palette.rs +6 -0
- package/vendor/ratatui-core/src/style/palette_conversion.rs +82 -0
- package/vendor/ratatui-core/src/style/stylize.rs +668 -0
- package/vendor/ratatui-core/src/style.rs +1069 -0
- package/vendor/ratatui-core/src/symbols/bar.rs +51 -0
- package/vendor/ratatui-core/src/symbols/block.rs +51 -0
- package/vendor/ratatui-core/src/symbols/border.rs +709 -0
- package/vendor/ratatui-core/src/symbols/braille.rs +21 -0
- package/vendor/ratatui-core/src/symbols/half_block.rs +3 -0
- package/vendor/ratatui-core/src/symbols/line.rs +259 -0
- package/vendor/ratatui-core/src/symbols/marker.rs +82 -0
- package/vendor/ratatui-core/src/symbols/merge.rs +748 -0
- package/vendor/ratatui-core/src/symbols/pixel.rs +30 -0
- package/vendor/ratatui-core/src/symbols/scrollbar.rs +46 -0
- package/vendor/ratatui-core/src/symbols/shade.rs +5 -0
- package/vendor/ratatui-core/src/symbols.rs +15 -0
- package/vendor/ratatui-core/src/terminal/frame.rs +192 -0
- package/vendor/ratatui-core/src/terminal/terminal.rs +926 -0
- package/vendor/ratatui-core/src/terminal/viewport.rs +58 -0
- package/vendor/ratatui-core/src/terminal.rs +40 -0
- package/vendor/ratatui-core/src/text/grapheme.rs +84 -0
- package/vendor/ratatui-core/src/text/line.rs +1678 -0
- package/vendor/ratatui-core/src/text/masked.rs +149 -0
- package/vendor/ratatui-core/src/text/span.rs +904 -0
- package/vendor/ratatui-core/src/text/text.rs +1434 -0
- package/vendor/ratatui-core/src/text.rs +64 -0
- package/vendor/ratatui-core/src/widgets/stateful_widget.rs +193 -0
- package/vendor/ratatui-core/src/widgets/widget.rs +174 -0
- package/vendor/ratatui-core/src/widgets.rs +9 -0
- package/bin/gwt.js +0 -131
- package/scripts/postinstall.test.js +0 -71
- package/scripts/release-download.js +0 -66
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
//! Pseudo-pixel symbols: quadrant, sextant and octant characters.
|
|
2
|
+
//!
|
|
3
|
+
//! Note that the symbols are not listed according to their unicode codepoint but according to the
|
|
4
|
+
//! corresponding bit pattern in row-major order.
|
|
5
|
+
|
|
6
|
+
pub const QUADRANTS: [char; 16] = [
|
|
7
|
+
' ', '▘', '▝', '▀', '▖', '▌', '▞', '▛', '▗', '▚', '▐', '▜', '▄', '▙', '▟', '█',
|
|
8
|
+
];
|
|
9
|
+
pub const SEXTANTS: [char; 64] = [
|
|
10
|
+
' ', '🬀', '🬁', '🬂', '🬃', '🬄', '🬅', '🬆', '🬇', '🬈', '🬉', '🬊', '🬋', '🬌', '🬍', '🬎', '🬏', '🬐', '🬑',
|
|
11
|
+
'🬒', '🬓', '▌', '🬔', '🬕', '🬖', '🬗', '🬘', '🬙', '🬚', '🬛', '🬜', '🬝', '🬞', '🬟', '🬠', '🬡', '🬢', '🬣',
|
|
12
|
+
'🬤', '🬥', '🬦', '🬧', '▐', '🬨', '🬩', '🬪', '🬫', '🬬', '🬭', '🬮', '🬯', '🬰', '🬱', '🬲', '🬳', '🬴', '🬵',
|
|
13
|
+
'🬶', '🬷', '🬸', '🬹', '🬺', '🬻', '█',
|
|
14
|
+
];
|
|
15
|
+
pub const OCTANTS: [char; 256] = [
|
|
16
|
+
' ', '', '', '🮂', '', '▘', '', '', '', '', '▝', '', '', '', '', '▀', '', '', '',
|
|
17
|
+
'', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
|
|
18
|
+
'', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
|
|
19
|
+
'', '', '', '', '', '', '🮅', '', '', '', '', '', '', '', '', '', '', '', '',
|
|
20
|
+
'', '', '', '', '▖', '', '', '', '', '▌', '', '', '', '', '▞', '', '', '', '',
|
|
21
|
+
'▛', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
|
|
22
|
+
'', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
|
|
23
|
+
'', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
|
|
24
|
+
'', '', '', '', '', '', '', '', '▗', '', '', '', '', '▚', '', '', '', '', '▐',
|
|
25
|
+
'', '', '', '', '▜', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
|
|
26
|
+
'', '', '▂', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
|
|
27
|
+
'', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
|
|
28
|
+
'', '', '', '', '', '', '', '', '', '', '', '', '▄', '', '', '', '', '▙', '',
|
|
29
|
+
'', '', '', '▟', '', '▆', '', '', '█',
|
|
30
|
+
];
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
use crate::symbols::{block, line};
|
|
2
|
+
|
|
3
|
+
/// Scrollbar Set
|
|
4
|
+
/// ```text
|
|
5
|
+
/// <--▮------->
|
|
6
|
+
/// ^ ^ ^ ^
|
|
7
|
+
/// │ │ │ └ end
|
|
8
|
+
/// │ │ └──── track
|
|
9
|
+
/// │ └──────── thumb
|
|
10
|
+
/// └─────────── begin
|
|
11
|
+
/// ```
|
|
12
|
+
#[derive(Debug, Default, Clone, Eq, PartialEq, Hash)]
|
|
13
|
+
pub struct Set<'a> {
|
|
14
|
+
pub track: &'a str,
|
|
15
|
+
pub thumb: &'a str,
|
|
16
|
+
pub begin: &'a str,
|
|
17
|
+
pub end: &'a str,
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
pub const DOUBLE_VERTICAL: Set = Set {
|
|
21
|
+
track: line::DOUBLE_VERTICAL,
|
|
22
|
+
thumb: block::FULL,
|
|
23
|
+
begin: "▲",
|
|
24
|
+
end: "▼",
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
pub const DOUBLE_HORIZONTAL: Set = Set {
|
|
28
|
+
track: line::DOUBLE_HORIZONTAL,
|
|
29
|
+
thumb: block::FULL,
|
|
30
|
+
begin: "◄",
|
|
31
|
+
end: "►",
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
pub const VERTICAL: Set = Set {
|
|
35
|
+
track: line::VERTICAL,
|
|
36
|
+
thumb: block::FULL,
|
|
37
|
+
begin: "↑",
|
|
38
|
+
end: "↓",
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
pub const HORIZONTAL: Set = Set {
|
|
42
|
+
track: line::HORIZONTAL,
|
|
43
|
+
thumb: block::FULL,
|
|
44
|
+
begin: "←",
|
|
45
|
+
end: "→",
|
|
46
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
//! Symbols and markers for drawing various widgets.
|
|
2
|
+
|
|
3
|
+
pub use marker::{DOT, Marker};
|
|
4
|
+
|
|
5
|
+
pub mod bar;
|
|
6
|
+
pub mod block;
|
|
7
|
+
pub mod border;
|
|
8
|
+
pub mod braille;
|
|
9
|
+
pub mod half_block;
|
|
10
|
+
pub mod line;
|
|
11
|
+
pub mod marker;
|
|
12
|
+
pub mod merge;
|
|
13
|
+
pub mod pixel;
|
|
14
|
+
pub mod scrollbar;
|
|
15
|
+
pub mod shade;
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
use crate::buffer::Buffer;
|
|
2
|
+
use crate::layout::{Position, Rect};
|
|
3
|
+
use crate::widgets::{StatefulWidget, Widget};
|
|
4
|
+
|
|
5
|
+
/// A consistent view into the terminal state for rendering a single frame.
|
|
6
|
+
///
|
|
7
|
+
/// This is obtained via the closure argument of [`Terminal::draw`]. It is used to render widgets
|
|
8
|
+
/// to the terminal and control the cursor position.
|
|
9
|
+
///
|
|
10
|
+
/// The changes drawn to the frame are applied only to the current [`Buffer`]. After the closure
|
|
11
|
+
/// returns, the current buffer is compared to the previous buffer and only the changes are applied
|
|
12
|
+
/// to the terminal. This avoids drawing redundant cells.
|
|
13
|
+
///
|
|
14
|
+
/// [`Buffer`]: crate::buffer::Buffer
|
|
15
|
+
/// [`Terminal::draw`]: crate::terminal::Terminal::draw
|
|
16
|
+
#[derive(Debug, Hash)]
|
|
17
|
+
pub struct Frame<'a> {
|
|
18
|
+
/// Where should the cursor be after drawing this frame?
|
|
19
|
+
///
|
|
20
|
+
/// If `None`, the cursor is hidden and its position is controlled by the backend. If `Some((x,
|
|
21
|
+
/// y))`, the cursor is shown and placed at `(x, y)` after the call to `Terminal::draw()`.
|
|
22
|
+
pub(crate) cursor_position: Option<Position>,
|
|
23
|
+
|
|
24
|
+
/// The area of the viewport
|
|
25
|
+
pub(crate) viewport_area: Rect,
|
|
26
|
+
|
|
27
|
+
/// The buffer that is used to draw the current frame
|
|
28
|
+
pub(crate) buffer: &'a mut Buffer,
|
|
29
|
+
|
|
30
|
+
/// The frame count indicating the sequence number of this frame.
|
|
31
|
+
pub(crate) count: usize,
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/// `CompletedFrame` represents the state of the terminal after all changes performed in the last
|
|
35
|
+
/// [`Terminal::draw`] call have been applied. Therefore, it is only valid until the next call to
|
|
36
|
+
/// [`Terminal::draw`].
|
|
37
|
+
///
|
|
38
|
+
/// [`Terminal::draw`]: crate::terminal::Terminal::draw
|
|
39
|
+
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
|
|
40
|
+
pub struct CompletedFrame<'a> {
|
|
41
|
+
/// The buffer that was used to draw the last frame.
|
|
42
|
+
pub buffer: &'a Buffer,
|
|
43
|
+
/// The size of the last frame.
|
|
44
|
+
pub area: Rect,
|
|
45
|
+
/// The frame count indicating the sequence number of this frame.
|
|
46
|
+
pub count: usize,
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
impl Frame<'_> {
|
|
50
|
+
/// The area of the current frame
|
|
51
|
+
///
|
|
52
|
+
/// This is guaranteed not to change during rendering, so may be called multiple times.
|
|
53
|
+
///
|
|
54
|
+
/// If your app listens for a resize event from the backend, it should ignore the values from
|
|
55
|
+
/// the event for any calculations that are used to render the current frame and use this value
|
|
56
|
+
/// instead as this is the area of the buffer that is used to render the current frame.
|
|
57
|
+
pub const fn area(&self) -> Rect {
|
|
58
|
+
self.viewport_area
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/// The area of the current frame
|
|
62
|
+
///
|
|
63
|
+
/// This is guaranteed not to change during rendering, so may be called multiple times.
|
|
64
|
+
///
|
|
65
|
+
/// If your app listens for a resize event from the backend, it should ignore the values from
|
|
66
|
+
/// the event for any calculations that are used to render the current frame and use this value
|
|
67
|
+
/// instead as this is the area of the buffer that is used to render the current frame.
|
|
68
|
+
#[deprecated = "use `area()` instead"]
|
|
69
|
+
pub const fn size(&self) -> Rect {
|
|
70
|
+
self.viewport_area
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/// Render a [`Widget`] to the current buffer using [`Widget::render`].
|
|
74
|
+
///
|
|
75
|
+
/// Usually the area argument is the size of the current frame or a sub-area of the current
|
|
76
|
+
/// frame (which can be obtained using [`Layout`] to split the total area).
|
|
77
|
+
///
|
|
78
|
+
/// # Example
|
|
79
|
+
///
|
|
80
|
+
/// ```rust,ignore
|
|
81
|
+
/// # use ratatui::{backend::TestBackend, Terminal};
|
|
82
|
+
/// # let backend = TestBackend::new(5, 5);
|
|
83
|
+
/// # let mut terminal = Terminal::new(backend).unwrap();
|
|
84
|
+
/// # let mut frame = terminal.get_frame();
|
|
85
|
+
/// use ratatui::{layout::Rect, widgets::Block};
|
|
86
|
+
///
|
|
87
|
+
/// let block = Block::new();
|
|
88
|
+
/// let area = Rect::new(0, 0, 5, 5);
|
|
89
|
+
/// frame.render_widget(block, area);
|
|
90
|
+
/// ```
|
|
91
|
+
///
|
|
92
|
+
/// [`Layout`]: crate::layout::Layout
|
|
93
|
+
pub fn render_widget<W: Widget>(&mut self, widget: W, area: Rect) {
|
|
94
|
+
widget.render(area, self.buffer);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/// Render a [`StatefulWidget`] to the current buffer using [`StatefulWidget::render`].
|
|
98
|
+
///
|
|
99
|
+
/// Usually the area argument is the size of the current frame or a sub-area of the current
|
|
100
|
+
/// frame (which can be obtained using [`Layout`] to split the total area).
|
|
101
|
+
///
|
|
102
|
+
/// The last argument should be an instance of the [`StatefulWidget::State`] associated to the
|
|
103
|
+
/// given [`StatefulWidget`].
|
|
104
|
+
///
|
|
105
|
+
/// # Example
|
|
106
|
+
///
|
|
107
|
+
/// ```rust,ignore
|
|
108
|
+
/// # use ratatui::{backend::TestBackend, Terminal};
|
|
109
|
+
/// # let backend = TestBackend::new(5, 5);
|
|
110
|
+
/// # let mut terminal = Terminal::new(backend).unwrap();
|
|
111
|
+
/// # let mut frame = terminal.get_frame();
|
|
112
|
+
/// use ratatui::{
|
|
113
|
+
/// layout::Rect,
|
|
114
|
+
/// widgets::{List, ListItem, ListState},
|
|
115
|
+
/// };
|
|
116
|
+
///
|
|
117
|
+
/// let mut state = ListState::default().with_selected(Some(1));
|
|
118
|
+
/// let list = List::new(vec![ListItem::new("Item 1"), ListItem::new("Item 2")]);
|
|
119
|
+
/// let area = Rect::new(0, 0, 5, 5);
|
|
120
|
+
/// frame.render_stateful_widget(list, area, &mut state);
|
|
121
|
+
/// ```
|
|
122
|
+
///
|
|
123
|
+
/// [`Layout`]: crate::layout::Layout
|
|
124
|
+
pub fn render_stateful_widget<W>(&mut self, widget: W, area: Rect, state: &mut W::State)
|
|
125
|
+
where
|
|
126
|
+
W: StatefulWidget,
|
|
127
|
+
{
|
|
128
|
+
widget.render(area, self.buffer, state);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/// After drawing this frame, make the cursor visible and put it at the specified (x, y)
|
|
132
|
+
/// coordinates. If this method is not called, the cursor will be hidden.
|
|
133
|
+
///
|
|
134
|
+
/// Note that this will interfere with calls to [`Terminal::hide_cursor`],
|
|
135
|
+
/// [`Terminal::show_cursor`], and [`Terminal::set_cursor_position`]. Pick one of the APIs and
|
|
136
|
+
/// stick with it.
|
|
137
|
+
///
|
|
138
|
+
/// [`Terminal::hide_cursor`]: crate::terminal::Terminal::hide_cursor
|
|
139
|
+
/// [`Terminal::show_cursor`]: crate::terminal::Terminal::show_cursor
|
|
140
|
+
/// [`Terminal::set_cursor_position`]: crate::terminal::Terminal::set_cursor_position
|
|
141
|
+
pub fn set_cursor_position<P: Into<Position>>(&mut self, position: P) {
|
|
142
|
+
self.cursor_position = Some(position.into());
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/// After drawing this frame, make the cursor visible and put it at the specified (x, y)
|
|
146
|
+
/// coordinates. If this method is not called, the cursor will be hidden.
|
|
147
|
+
///
|
|
148
|
+
/// Note that this will interfere with calls to [`Terminal::hide_cursor`],
|
|
149
|
+
/// [`Terminal::show_cursor`], and [`Terminal::set_cursor_position`]. Pick one of the APIs and
|
|
150
|
+
/// stick with it.
|
|
151
|
+
///
|
|
152
|
+
/// [`Terminal::hide_cursor`]: crate::terminal::Terminal::hide_cursor
|
|
153
|
+
/// [`Terminal::show_cursor`]: crate::terminal::Terminal::show_cursor
|
|
154
|
+
/// [`Terminal::set_cursor_position`]: crate::terminal::Terminal::set_cursor_position
|
|
155
|
+
#[deprecated = "use `set_cursor_position((x, y))` instead which takes `impl Into<Position>`"]
|
|
156
|
+
pub fn set_cursor(&mut self, x: u16, y: u16) {
|
|
157
|
+
self.set_cursor_position(Position { x, y });
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/// Gets the buffer that this `Frame` draws into as a mutable reference.
|
|
161
|
+
pub const fn buffer_mut(&mut self) -> &mut Buffer {
|
|
162
|
+
self.buffer
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/// Returns the current frame count.
|
|
166
|
+
///
|
|
167
|
+
/// This method provides access to the frame count, which is a sequence number indicating
|
|
168
|
+
/// how many frames have been rendered up to (but not including) this one. It can be used
|
|
169
|
+
/// for purposes such as animation, performance tracking, or debugging.
|
|
170
|
+
///
|
|
171
|
+
/// Each time a frame has been rendered, this count is incremented,
|
|
172
|
+
/// providing a consistent way to reference the order and number of frames processed by the
|
|
173
|
+
/// terminal. When count reaches its maximum value (`usize::MAX`), it wraps around to zero.
|
|
174
|
+
///
|
|
175
|
+
/// This count is particularly useful when dealing with dynamic content or animations where the
|
|
176
|
+
/// state of the display changes over time. By tracking the frame count, developers can
|
|
177
|
+
/// synchronize updates or changes to the content with the rendering process.
|
|
178
|
+
///
|
|
179
|
+
/// # Examples
|
|
180
|
+
///
|
|
181
|
+
/// ```rust,ignore
|
|
182
|
+
/// # use ratatui::{backend::TestBackend, Terminal};
|
|
183
|
+
/// # let backend = TestBackend::new(5, 5);
|
|
184
|
+
/// # let mut terminal = Terminal::new(backend).unwrap();
|
|
185
|
+
/// # let mut frame = terminal.get_frame();
|
|
186
|
+
/// let current_count = frame.count();
|
|
187
|
+
/// println!("Current frame count: {}", current_count);
|
|
188
|
+
/// ```
|
|
189
|
+
pub const fn count(&self) -> usize {
|
|
190
|
+
self.count
|
|
191
|
+
}
|
|
192
|
+
}
|