14
14
#include < coreplugin/editormanager/ieditor.h>
15
15
#include < coreplugin/icontext.h>
16
16
#include < coreplugin/statusbarmanager.h>
17
+
17
18
#include < gui/input.h>
18
19
#include < msgpackrequest.h>
19
20
#include < neovimconnector.h>
21
+
20
22
#include < projectexplorer/project.h>
21
23
#include < projectexplorer/session.h>
24
+
22
25
#include < texteditor/displaysettings.h>
23
26
#include < texteditor/fontsettings.h>
24
27
#include < texteditor/textdocument.h>
25
28
#include < texteditor/texteditor.h>
26
29
#include < texteditor/texteditorsettings.h>
30
+ #include < texteditor/tabsettings.h>
31
+
27
32
#include < utils/differ.h>
28
33
#include < utils/fancylineedit.h>
29
34
#include < utils/fileutils.h>
@@ -129,20 +134,28 @@ void QNVimPlugin::syncSelectionToVim(Core::IEditor *editor) {
129
134
130
135
auto textEditor = qobject_cast<TextEditor::TextEditorWidget *>(editor->widget ());
131
136
QString text = textEditor->toPlainText ();
132
- auto cursor = textEditor->hasBlockSelection () ? textEditor->blockSelection () : textEditor->textCursor ();
133
- int cursorPosition = cursor.position ();
134
- int anchorPosition = cursor.anchor ();
135
- int line, col, vLine, vCol;
136
137
137
- if (anchorPosition == cursorPosition)
138
- return ;
138
+ auto mtc = textEditor-> multiTextCursor ();
139
+ int line, col, vLine, vCol ;
139
140
140
141
QString visualCommand;
141
- if (textEditor->hasBlockSelection ()) {
142
- line = QStringView (text).left (cursorPosition).count (' \n ' ) + 1 ;
143
- col = text.left (cursorPosition).section (' \n ' , -1 ).length () + 1 ;
144
- vLine = QStringView (text).left (anchorPosition).count (' \n ' ) + 1 ;
145
- vCol = text.left (anchorPosition).section (' \n ' , -1 ).length () + 1 ;
142
+ if (mtc.hasMultipleCursors ()) {
143
+ auto mainCursor = mtc.mainCursor ();
144
+
145
+ // We should always use main cursor pos here,
146
+ // because it is the cursor user controls with hjkl
147
+ auto nvimPos = mainCursor.position ();
148
+
149
+ // NOTE: Theoretically, it is not alwaus the case,
150
+ // that the main cursor is at the ends of mtc array,
151
+ // but for creating our own block selections it works
152
+ auto lastCursor = mainCursor == *mtc.begin () ? *(mtc.end () - 1 ) : *mtc.begin ();
153
+ auto nvimAnchor = lastCursor.anchor ();
154
+
155
+ line = QStringView (text).left (nvimPos).count (' \n ' ) + 1 ;
156
+ col = text.left (nvimPos).section (' \n ' , -1 ).length () + 1 ;
157
+ vLine = QStringView (text).left (nvimAnchor).count (' \n ' ) + 1 ;
158
+ vCol = text.left (nvimAnchor).section (' \n ' , -1 ).length () + 1 ;
146
159
147
160
if (vCol < col)
148
161
--col;
@@ -153,6 +166,13 @@ void QNVimPlugin::syncSelectionToVim(Core::IEditor *editor) {
153
166
} else if (mMode == " V" ) {
154
167
return ;
155
168
} else {
169
+ auto cursor = textEditor->textCursor ();
170
+ int cursorPosition = cursor.position ();
171
+ int anchorPosition = cursor.anchor ();
172
+
173
+ if (anchorPosition == cursorPosition)
174
+ return ;
175
+
156
176
if (anchorPosition < cursorPosition)
157
177
--cursorPosition;
158
178
else
@@ -231,52 +251,79 @@ void QNVimPlugin::syncCursorFromVim(const QVariantList &pos, const QVariantList
231
251
mVCursor .setY (vLine);
232
252
mVCursor .setX (vCol);
233
253
234
- int a = QString (" \n " + mText ).section (' \n ' , 0 , vLine - 1 ).length () + vCol - 1 ;
235
- int p = QString (" \n " + mText ).section (' \n ' , 0 , line - 1 ).length () + col - 1 ;
254
+ int anchor = QString (" \n " + mText ).section (' \n ' , 0 , vLine - 1 ).length () + vCol - 1 ;
255
+ int position = QString (" \n " + mText ).section (' \n ' , 0 , line - 1 ).length () + col - 1 ;
236
256
if (mMode == " V" ) {
237
- if (a < p ) {
238
- a = QString (" \n " + mText ).section (' \n ' , 0 , vLine - 1 ).length ();
239
- p = QString (" \n " + mText ).section (' \n ' , 0 , line).length () - 1 ;
257
+ if (anchor < position ) {
258
+ anchor = QString (" \n " + mText ).section (' \n ' , 0 , vLine - 1 ).length ();
259
+ position = QString (" \n " + mText ).section (' \n ' , 0 , line).length () - 1 ;
240
260
} else {
241
- a = QString (" \n " + mText ).section (' \n ' , 0 , vLine).length () - 1 ;
242
- p = QString (" \n " + mText ).section (' \n ' , 0 , line - 1 ).length ();
261
+ anchor = QString (" \n " + mText ).section (' \n ' , 0 , vLine).length () - 1 ;
262
+ position = QString (" \n " + mText ).section (' \n ' , 0 , line - 1 ).length ();
243
263
}
244
264
245
265
QTextCursor cursor = textEditor->textCursor ();
246
- cursor.setPosition (a );
247
- cursor.setPosition (p , QTextCursor::KeepAnchor);
266
+ cursor.setPosition (anchor );
267
+ cursor.setPosition (position , QTextCursor::KeepAnchor);
248
268
249
269
if (textEditor->textCursor ().anchor () != cursor.anchor () or
250
270
textEditor->textCursor ().position () != cursor.position ())
251
271
textEditor->setTextCursor (cursor);
252
272
253
273
} else if (mMode == " v" ) {
254
- if (a > p )
255
- ++a ;
274
+ if (anchor > position )
275
+ ++anchor ;
256
276
else
257
- ++p ;
277
+ ++position ;
258
278
259
279
QTextCursor cursor = textEditor->textCursor ();
260
- cursor.setPosition (a );
261
- cursor.setPosition (p , QTextCursor::KeepAnchor);
280
+ cursor.setPosition (anchor );
281
+ cursor.setPosition (position , QTextCursor::KeepAnchor);
262
282
263
283
if (textEditor->textCursor ().anchor () != cursor.anchor () or
264
284
textEditor->textCursor ().position () != cursor.position ())
265
285
textEditor->setTextCursor (cursor);
266
- } else if (mMode == " \x16 " ) {
286
+ } else if (mMode == " \x16 " ) { // VISUAL BLOCK
267
287
if (vCol > col)
268
- ++a ;
288
+ ++anchor ;
269
289
else
270
- ++p ;
290
+ ++position ;
271
291
272
- QTextCursor cursor = textEditor->textCursor ();
273
- cursor.setPosition (a);
274
- cursor.setPosition (p, QTextCursor::KeepAnchor);
275
- textEditor->setBlockSelection (cursor);
292
+ auto document = textEditor->textCursor ().document ();
293
+ const auto & tabs = textEditor->textDocument ()->tabSettings ();
294
+
295
+ const auto firstBlock = document->findBlock (anchor);
296
+ const auto lastBlock = document->findBlock (position);
297
+ const auto localAnchor = tabs.columnAt (firstBlock.text (), anchor - firstBlock.position ());
298
+ const auto localPos = tabs.columnAt (lastBlock.text (), position - lastBlock.position ());
299
+
300
+ // Get next block no matter the direction of selection
301
+ auto after = [&](const auto & block) {
302
+ if (anchor < position)
303
+ return block.next ();
304
+ else
305
+ return block.previous ();
306
+ };
307
+
308
+ auto mtc = Utils::MultiTextCursor ();
309
+ for (auto curBlock = firstBlock; curBlock != after (lastBlock); curBlock = after (curBlock)) {
310
+ auto newCursor = QTextCursor (curBlock);
311
+
312
+ auto anchorBoundOffset = tabs.positionAtColumn (curBlock.text (), localAnchor);
313
+ auto newCursorAnchor = curBlock.position () + anchorBoundOffset;
314
+ newCursor.setPosition (newCursorAnchor);
315
+
316
+ auto posBoundOffset = tabs.positionAtColumn (curBlock.text (), localPos);
317
+ auto newCursorPosition = curBlock.position () + posBoundOffset;
318
+ newCursor.setPosition (newCursorPosition, QTextCursor::KeepAnchor);
319
+
320
+ mtc.addCursor (newCursor);
321
+ }
322
+ textEditor->setMultiTextCursor (mtc);
276
323
} else {
277
324
QTextCursor cursor = textEditor->textCursor ();
278
325
cursor.clearSelection ();
279
- cursor.setPosition (p );
326
+ cursor.setPosition (position );
280
327
281
328
if (textEditor->textCursor ().position () != cursor.position () or
282
329
textEditor->textCursor ().hasSelection ())
@@ -689,17 +736,15 @@ void QNVimPlugin::editorOpened(Core::IEditor *editor) {
689
736
690
737
Core::IDocument *document = editor->document ();
691
738
692
- connect (
693
- document, &Core::IDocument::contentsChanged, this , [=]() {
739
+ connect (document, &Core::IDocument::contentsChanged, this , [=]() {
694
740
auto buffer = mBuffers [editor];
695
741
QString bufferType = mBufferType [buffer];
696
742
if (!mEditors .contains (buffer) or (bufferType != " acwrite" and !bufferType.isEmpty ()))
697
743
return ;
698
744
syncToVim (editor);
699
745
},
700
746
Qt::QueuedConnection);
701
- connect (
702
- textEditor, &TextEditor::TextEditorWidget::cursorPositionChanged, this , [=]() {
747
+ connect (textEditor, &TextEditor::TextEditorWidget::cursorPositionChanged, this , [=]() {
703
748
if (Core::EditorManager::currentEditor () != editor)
704
749
return ;
705
750
QString newText = textEditor->toPlainText ();
@@ -708,8 +753,7 @@ void QNVimPlugin::editorOpened(Core::IEditor *editor) {
708
753
syncCursorToVim (editor);
709
754
},
710
755
Qt::QueuedConnection);
711
- connect (
712
- textEditor, &TextEditor::TextEditorWidget::selectionChanged, this , [=]() {
756
+ connect (textEditor, &TextEditor::TextEditorWidget::selectionChanged, this , [=]() {
713
757
if (Core::EditorManager::currentEditor () != editor)
714
758
return ;
715
759
QString newText = textEditor->toPlainText ();
@@ -718,7 +762,8 @@ void QNVimPlugin::editorOpened(Core::IEditor *editor) {
718
762
syncSelectionToVim (editor);
719
763
},
720
764
Qt::QueuedConnection);
721
- connect (textEditor->textDocument (), &TextEditor::TextDocument::fontSettingsChanged, this , &QNVimPlugin::updateCursorSize);
765
+ connect (textEditor->textDocument (), &TextEditor::TextDocument::fontSettingsChanged,
766
+ this , &QNVimPlugin::updateCursorSize);
722
767
}
723
768
mSettingBufferFromVim = 0 ;
724
769
0 commit comments