Skip to content

Commit a45875a

Browse files
committed
Shift+Tab 向前跳轉一個段落
1 parent cfc3225 commit a45875a

File tree

5 files changed

+106
-59
lines changed

5 files changed

+106
-59
lines changed

src/action.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
#![allow(dead_code)]
2+
13
pub trait 動作: Fn() + Copy + 'static {}
24
impl<T> 動作 for T where T: Fn() + Copy + 'static {}
35

src/engine.rs

Lines changed: 28 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@ use leptos::prelude::*;
55
use crate::action::動作;
66
use crate::definition::觸鍵方式;
77
use crate::gear::{
8-
assignment::{作業, 作業推進參數, 作業機關, 作業機關輸出信號},
8+
assignment::{作業, 作業機關, 作業機關輸出信號, 步進法},
99
caption::{字幕機關, 字幕機關輸出信號, 字幕段落},
1010
chord::{並擊機關, 並擊機關輸出信號},
11-
input::{焦點事件處理機關, 輸入事件處理機關},
11+
input::{焦點事件處理機關, 觸鍵消息, 輸入事件處理機關},
1212
key_press::{連擊機關, 連擊機關輸出信號},
1313
mode::{工作模式, 工作模式機關, 工作模式機關輸出信號},
1414
theory::{輸入方案機關, 輸入方案機關輸出信號},
@@ -46,8 +46,10 @@ pub fn 微觀引擎() -> 微觀引擎輸出信號 {
4646
..
4747
} = 作業;
4848
let 字幕機關輸出信號 {
49-
分段字幕, 當前段落,
50-
..
49+
分段字幕,
50+
當前段落,
51+
前序段落,
52+
..
5153
} = 字幕;
5254
let 連擊機關輸出信號 {
5355
連擊狀態變更,
@@ -90,7 +92,7 @@ pub fn 微觀引擎() -> 微觀引擎輸出信號 {
9092

9193
焦點事件處理機關(重置並擊狀態);
9294

93-
let 處理功能鍵 = move |鍵碼: KeyCode| match 鍵碼 {
95+
let 處理功能鍵 = move |觸鍵消息 { 鍵碼, 檔位 }| match 鍵碼 {
9496
KeyCode::Escape => {
9597
match 現行工作模式() {
9698
工作模式::錄入 => {
@@ -107,12 +109,20 @@ pub fn 微觀引擎() -> 微觀引擎輸出信號 {
107109
}
108110
KeyCode::Tab => {
109111
if 現行工作模式() == 工作模式::錄入 {
110-
if 作業推進(作業推進參數 {
111-
段落: 當前段落().map(|字幕段落(,, _)| (,)),
112-
迴轉: true,
113-
})
114-
.is_ok()
115-
{
112+
let 跳轉結果 = if 檔位.shift {
113+
let 目標 = 前序段落()
114+
.or_else(|| 分段字幕.with(|衆段落| 衆段落.last().cloned()))
115+
.map(|字幕段落(, _, _)| 起);
116+
作業回退(步進法 {
117+
目標, 迴轉: true
118+
})
119+
} else {
120+
let 目標 = 當前段落().map(|字幕段落(_,, _)| 止);
121+
作業推進(步進法 {
122+
目標, 迴轉: true
123+
})
124+
};
125+
if 跳轉結果.is_ok() {
116126
重置輸入狀態();
117127
}
118128
} else {
@@ -125,12 +135,12 @@ pub fn 微觀引擎() -> 微觀引擎輸出信號 {
125135
match 指法() {
126136
觸鍵方式::連擊 => {
127137
if 有無作業() {
128-
let _不看結果 = 作業回退();
138+
let _不看結果 = 作業回退(步進法::default());
129139
}
130140
回退連擊輸入碼();
131141
}
132142
觸鍵方式::並擊 => {
133-
if 並擊完成() || 作業回退().is_ok() {
143+
if 並擊完成() || 作業回退(步進法::default()).is_ok() {
134144
重置並擊狀態();
135145
}
136146
}
@@ -163,8 +173,11 @@ pub fn 微觀引擎() -> 微觀引擎輸出信號 {
163173
};
164174
let 批閱作業 = move || {
165175
// 擊中目標輸入碼後反查下一個輸入碼
166-
let 分段落則迴轉 = 分段字幕.read().len() > 1;
167-
擊中目標() && 作業推進(作業推進參數::步進(分段落則迴轉)).is_ok()
176+
let 分段落則迴轉 = 步進法 {
177+
目標: None,
178+
迴轉: 分段字幕.read().len() > 1,
179+
};
180+
擊中目標() && 作業推進(分段落則迴轉).is_ok()
168181
};
169182
let 另起一段 = move || {
170183
當前段落

src/gear/assignment.rs

Lines changed: 36 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use lazy_regex::regex;
2+
use leptos::logging::log;
23
use leptos::prelude::*;
34
use std::cmp::min;
45

@@ -78,21 +79,7 @@ impl 作業 {
7879
}
7980
}
8081

81-
#[derive(Clone, Copy)]
82-
pub struct 作業推進參數 {
83-
pub 段落: Option<(usize, usize)>,
84-
pub 迴轉: bool,
85-
}
86-
87-
impl 作業推進參數 {
88-
pub fn 步進(迴轉: bool) -> Self {
89-
Self {
90-
段落: None, 迴轉
91-
}
92-
}
93-
}
94-
95-
#[derive(Clone, PartialEq)]
82+
#[derive(Clone, Debug, PartialEq)]
9683
pub struct 對照輸入碼 {
9784
pub 字根碼原文: Option<String>,
9885
pub 轉寫碼原文: Option<String>,
@@ -114,9 +101,15 @@ impl 對照輸入碼 {
114101
}
115102
}
116103

104+
#[derive(Clone, Copy, Default)]
105+
pub struct 步進法 {
106+
pub 目標: Option<usize>,
107+
pub 迴轉: bool,
108+
}
109+
117110
pub type 重置作業進度動作 = impl 動作;
118-
pub type 作業推進動作 = impl 動作給一參數得一結果<作業推進參數>;
119-
pub type 作業回退動作 = impl 動作得一結果;
111+
pub type 作業推進動作 = impl 動作給一參數得一結果<步進法>;
112+
pub type 作業回退動作 = impl 動作給一參數得一結果<步進法>;
120113

121114
#[derive(Clone)]
122115
pub struct 作業機關輸出信號 {
@@ -162,7 +155,8 @@ pub fn 作業機關(方案: &輸入方案機關輸出信號) -> 作業機關輸
162155

163156
let _ = Effect::watch(
164157
目標輸入碼序列,
165-
move |_, _, _| {
158+
move |目標輸入碼序列, _, _| {
159+
log!("更新了目標輸入碼: {}", 目標輸入碼序列.len());
166160
重置作業進度();
167161
},
168162
false,
@@ -178,38 +172,40 @@ pub fn 作業機關(方案: &輸入方案機關輸出信號) -> 作業機關輸
178172
})
179173
});
180174

181-
let 作業推進 = move |參數: 作業推進參數| {
182-
let 全文結束 = 目標輸入碼序列.read().len();
183-
let 推進目標位置 = match 參數.段落 {
184-
Some((,)) => {
185-
if 作業進度() < 起 {
186-
187-
} else {
188-
189-
}
190-
}
191-
None => 作業進度() + 1,
192-
};
193-
if 參數.迴轉 && 推進目標位置 >= 全文結束 {
175+
let 作業推進 = move |步進: 步進法| {
176+
let 當前進度 = 作業進度();
177+
let 全文長度 = 目標輸入碼序列.read().len();
178+
let 目標進度 = 步進.目標.unwrap_or(當前進度 + 1);
179+
if 步進.迴轉 && 目標進度 >= 全文長度 {
194180
重置作業進度();
195181
Ok(())
196182
}
197183
// 非迴轉態可推進至全文結束位置
198-
else if 推進目標位置 <= 全文結束 {
199-
更新作業進度(推進目標位置);
184+
else if 目標進度 <= 全文長度 {
185+
更新作業進度(目標進度);
200186
Ok(())
201187
} else {
202188
Err(未有())
203189
}
204190
};
205191

206-
let 作業回退 = move || {
207-
let 進度 = 作業進度();
208-
if 進度 > 0 {
209-
更新作業進度(進度 - 1);
210-
Ok(())
211-
} else {
212-
Err(未有())
192+
let 作業回退 = move |步進: 步進法| {
193+
let 當前進度 = 作業進度();
194+
let 全文長度 = 目標輸入碼序列.read().len();
195+
match 步進.目標 {
196+
Some(目標進度) if 步進.迴轉 || 當前進度 > 目標進度 => {
197+
更新作業進度(目標進度);
198+
Ok(())
199+
}
200+
None if 步進.迴轉 && 當前進度 == 0 && 全文長度 > 0 => {
201+
更新作業進度(全文長度 - 1);
202+
Ok(())
203+
}
204+
None if 當前進度 > 0 => {
205+
更新作業進度(當前進度 - 1);
206+
Ok(())
207+
}
208+
_ => Err(未有()),
213209
}
214210
};
215211

src/gear/caption.rs

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,10 @@ fn 標註字序<'a>(衆段落: impl Iterator<Item = Cow<'a, str>>) -> Box<[字
8181
.into_boxed_slice()
8282
}
8383

84+
fn 所屬段落序號(衆段落: &[字幕段落], 進度: usize) -> usize {
85+
衆段落.partition_point(|字幕段落(_, 段落結束, _)| *段落結束 <= 進度)
86+
}
87+
8488
#[derive(Clone)]
8589
pub struct 字幕表示 {
8690
pub 已完成: String,
@@ -92,6 +96,7 @@ pub struct 字幕表示 {
9296
pub struct 字幕機關輸出信號 {
9397
pub 分段字幕: Memo<Box<[字幕段落<'static>]>>,
9498
pub 當前段落: Memo<Option<字幕段落<'static>>>,
99+
pub 前序段落: Signal<Option<字幕段落<'static>>>,
95100
pub 段落表示: Signal<Option<字幕表示>>,
96101
}
97102

@@ -135,8 +140,7 @@ pub fn 字幕機關(
135140
let 當前段落 = Memo::new(move |_| {
136141
分段字幕.with(|衆段落| {
137142
let 全文進度 = 作業進度();
138-
let 當前段落號 =
139-
衆段落.partition_point(|字幕段落(_, 段落結束, _)| *段落結束 <= 全文進度);
143+
let 當前段落號 = 所屬段落序號(衆段落, 全文進度);
140144
衆段落
141145
.get(當前段落號)
142146
.or_else(|| {
@@ -148,6 +152,18 @@ pub fn 字幕機關(
148152
})
149153
});
150154

155+
let 前序段落 = Signal::derive(move || {
156+
分段字幕.with(|衆段落| {
157+
let 全文進度 = 作業進度();
158+
let 當前段落號 = 所屬段落序號(衆段落, 全文進度);
159+
if 當前段落號 == 0 {
160+
None
161+
} else {
162+
衆段落.get(當前段落號 - 1).cloned()
163+
}
164+
})
165+
});
166+
151167
let 段落表示 = Signal::derive(move || {
152168
當前段落().map(|字幕段落(段落起始, _, 段落文字)| {
153169
let 全文進度 = 作業進度();
@@ -173,6 +189,7 @@ pub fn 字幕機關(
173189
字幕機關輸出信號 {
174190
分段字幕,
175191
當前段落,
192+
前序段落,
176193
段落表示,
177194
}
178195
}

src/gear/input.rs

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,34 @@ pub fn 焦點事件處理機關(重置並擊狀態: impl 動作) {
1414
});
1515
}
1616

17+
#[allow(dead_code)]
18+
pub struct 檔位 {
19+
pub shift: bool,
20+
pub ctrl: bool,
21+
pub alt: bool,
22+
pub meta: bool,
23+
}
24+
25+
pub struct 觸鍵消息 {
26+
pub 鍵碼: KeyCode,
27+
pub 檔位: 檔位,
28+
}
29+
1730
pub fn 輸入事件處理機關(
18-
處理功能鍵: impl 動作給一參數得一結果<KeyCode, bool>,
31+
處理功能鍵: impl 動作給一參數得一結果<觸鍵消息, bool>,
1932
既然落鍵: impl 動作給一參數<KeyCode>,
2033
既然抬鍵: impl 動作給一參數<KeyCode>,
2134
) {
2235
let keydown_handle = window_event_listener(ev::keydown, move |ev| {
2336
log!("落鍵 key = {}, code = {}", &ev.key(), ev.code());
2437
let 鍵碼 = 網頁鍵值轉換(&ev.code());
25-
if 處理功能鍵(鍵碼) {
38+
let 檔位 = 檔位 {
39+
shift: ev.shift_key(),
40+
ctrl: ev.ctrl_key(),
41+
alt: ev.alt_key(),
42+
meta: ev.meta_key(),
43+
};
44+
if 處理功能鍵(觸鍵消息 { 鍵碼, 檔位 }) {
2645
ev.prevent_default();
2746
}
2847
既然落鍵(鍵碼);

0 commit comments

Comments
 (0)