Skip to content

Commit a0a675d

Browse files
committed
Fixes for Word motions in Standard Mode
Added helper in buffer, and tweaks to fix more standard mode issues; needs a unit test or two.
1 parent c96d33c commit a0a675d

File tree

6 files changed

+260
-155
lines changed

6 files changed

+260
-155
lines changed

NOTES.md

+4-3
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
Assumptions in the code / Design decisions:
22

3-
- All ASCII for now, now UTF8
4-
- The cursor is only ever on a valid buffer location. This can be the hidden CR of the line, or the 0 at the end.
3+
- All ASCII for now, no real UTF8
4+
- The cursor is only ever on a valid buffer location. This can be the hidden CR of the line,
5+
or the 0 at the end.
56
- Even if the loaded buffer doesn't 0 terminate, it is terminated and then removed at save time if necessary.
67
- Internally every thing is a '\n'; '\r\n' is converted and converted back if necessary. Mixed files aren't supported, you'll just get a '\n' file
78
- The window converts the entire buffer to a list of visible character lines. This is used to handle wrapping, and let the user jump around in a wrapped buffer file.
8-
- Cursor is on the virtual line in the wrapped buffer, and can be off screen?
9+
- Cursor is on the virtual line in the wrapped buffer, and can be off screen; but ScrollTo will find it

TODO.md

+3-9
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ Delete everything; iterator bug. ?How to repro
33

44
#### Window
55
- Finish HSplit
6+
- Finish Tab management
67

78
#### General
89
- Finish cut/paste to OS buffer
@@ -15,16 +16,9 @@ Delete everything; iterator bug. ?How to repro
1516
- 'R'/'r' overstrike
1617

1718
#### Standard Mode
19+
- Ctrl + Shift Select word motions
1820

1921
#### Syntax Highlight
20-
- Generalize the token matching into the base class for easy
21-
implementation of c like languages
22-
- Add multilinne highlight via a hierarchy table?
2322

2423
#### Tests
25-
- Add standard mode unit tests
26-
- Test syntax highlighting
27-
28-
#### Future
29-
- UTF 8?
30-
- Standalone editor tool so I can dogfood it
24+
- Add tests for syntax highlighting

src/buffer.cpp

+73
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,15 @@ inline bool IsSpace(const char ch)
3535
{
3636
return ch == ' ';
3737
}
38+
inline bool IsSpaceOrTerminal(const char ch)
39+
{
40+
return ch == ' ' || ch == 0 || ch == '\n';
41+
}
42+
inline bool IsNewlineOrEnd(const char ch)
43+
{
44+
return ch == '\n' || ch == 0;
45+
}
46+
3847
using fnMatch = std::function<bool>(const char);
3948

4049
} // namespace
@@ -229,6 +238,70 @@ BufferRange ZepBuffer::AWordMotion(BufferLocation start, uint32_t searchType) co
229238
return r;
230239
}
231240

241+
// Implements the ctrl + motion of a standard editor.
242+
// This is a little convoluted; perhaps the logic can be simpler!
243+
// Playing around with CTRL+ arrows and shift in an app like notepad will teach you that the rules for how far to jump
244+
// depend on what you are over, and which direction you are going.....
245+
// The unit tests are designed to enforce the behavior here
246+
BufferRange ZepBuffer::StandardCtrlMotion(BufferLocation visual_start, BufferLocation cursor, SearchDirection searchDir) const
247+
{
248+
auto IsWord = IsWORDChar;
249+
auto searchType = SearchType::WORD;
250+
MotionBegin(cursor, searchType, SearchDirection::Forward);
251+
252+
auto lineEnd = GetLinePos(cursor, LineLocation::LineLastNonCR);
253+
auto current = std::min(lineEnd, Clamp(cursor));
254+
255+
BufferRange r;
256+
r.first = current;
257+
r.second = current;
258+
259+
if (searchDir == SearchDirection::Forward)
260+
{
261+
// Skip space
262+
Skip(IsSpaceOrTerminal, current, searchDir);
263+
if (Skip(IsWORDChar, current, searchDir))
264+
{
265+
if (Skip(IsSpace, current, searchDir))
266+
{
267+
if (current > visual_start)
268+
{
269+
current--;
270+
}
271+
}
272+
}
273+
// Forward jumping, step back before word
274+
if (current != cursor &&
275+
current > visual_start &&
276+
(m_gapBuffer[current] == '\n' ||
277+
m_gapBuffer[current] == 0))
278+
{
279+
current--;
280+
}
281+
}
282+
else
283+
{
284+
// If on the first char of a new word, skip back
285+
if (current > 0 && IsWORDChar(m_gapBuffer[current]) &&
286+
!IsWORDChar(m_gapBuffer[current - 1]))
287+
{
288+
current--;
289+
}
290+
291+
// Skip a space
292+
Skip(IsSpaceOrTerminal, current, searchDir);
293+
294+
// Back to the beginning of the next word
295+
if (Skip(IsWORDChar, current, searchDir))
296+
{
297+
current++;
298+
}
299+
}
300+
r.second = Clamp(current);
301+
302+
return r;
303+
}
304+
232305
BufferRange ZepBuffer::InnerWordMotion(BufferLocation start, uint32_t searchType) const
233306
{
234307
auto IsWordOrSpace = searchType == SearchType::Word ? IsWordOrSepChar : IsWORDOrSepChar;

src/buffer.h

+1
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ class ZepBuffer : public ZepComponent
102102
BufferLocation ChangeWordMotion(BufferLocation start, uint32_t searchType, SearchDirection dir) const;
103103
BufferRange AWordMotion(BufferLocation start, uint32_t searchType) const;
104104
BufferRange InnerWordMotion(BufferLocation start, uint32_t searchType) const;
105+
BufferRange StandardCtrlMotion(BufferLocation visual_start, BufferLocation cursor, SearchDirection searchDir) const;
105106

106107
bool Delete(const BufferLocation& startOffset, const BufferLocation& endOffset, const BufferLocation& cursorAfter = BufferLocation{ -1 });
107108
bool Insert(const BufferLocation& startOffset, const std::string& str, const BufferLocation& cursorAfter = BufferLocation{ -1 });

0 commit comments

Comments
 (0)