~ubuntu-branches/ubuntu/trusty/monodevelop/trusty-proposed

« back to all changes in this revision

Viewing changes to src/core/Mono.Texteditor/Mono.TextEditor.Vi/ViMode.cs

  • Committer: Package Import Robot
  • Author(s): Jo Shields
  • Date: 2013-05-12 09:46:03 UTC
  • mto: This revision was merged to the branch mainline in revision 29.
  • Revision ID: package-import@ubuntu.com-20130512094603-mad323bzcxvmcam0
Tags: upstream-4.0.5+dfsg
ImportĀ upstreamĀ versionĀ 4.0.5+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
103
103
                bool searchBackward;
104
104
                static string lastPattern;
105
105
                static string lastReplacement;
106
 
                State state;
 
106
                State curState;
 
107
                State CurState {
 
108
                        get {
 
109
                                return curState;
 
110
                        }
 
111
                        set {
 
112
                                curState = value;
 
113
                                if (viTextEditor != null) {
 
114
                                        viTextEditor.Caret.IsVisible = curState != State.Command;
 
115
                                        viTextEditor.RequestResetCaretBlink ();
 
116
                                }
 
117
                        }
 
118
                }
 
119
 
 
120
                Motion motion;
107
121
                const string substMatch = @"^:s(?<sep>.)(?<pattern>.+?)\k<sep>(?<replacement>.*?)(\k<sep>(?<trailer>i?))?$";
108
122
                StringBuilder commandBuffer = new StringBuilder ();
109
123
                Dictionary<char,ViMark> marks = new Dictionary<char, ViMark>();
128
142
                                } else {
129
143
                                        statusText = value + " recording";
130
144
                                }
 
145
 
 
146
                                if (curState == State.Command && viTextEditor != null) {
 
147
                                    viTextEditor.RequestResetCaretBlink ();
 
148
                                        statusArea.QueueDraw ();
 
149
                                }
131
150
                        }
132
 
        
133
151
                }
134
152
                
135
153
                protected virtual string RunExCommand (string command)
214
232
                
215
233
                public override bool WantsToPreemptIM {
216
234
                        get {
217
 
                                return state != State.Insert && state != State.Replace;
 
235
                                return CurState != State.Insert && CurState != State.Replace;
218
236
                        }
219
237
                }
220
238
                
221
239
                protected override void SelectionChanged ()
222
240
                {
223
241
                        if (Data.IsSomethingSelected) {
224
 
                                state = ViEditMode.State.Visual;
 
242
                                CurState = ViEditMode.State.Visual;
225
243
                                Status = "-- VISUAL --";
226
 
                        } else if (state == State.Visual && !Data.IsSomethingSelected) {
 
244
                        } else if (CurState == State.Visual && !Data.IsSomethingSelected) {
227
245
                                Reset ("");
228
246
                        }
229
247
                }
230
248
                
231
249
                protected override void CaretPositionChanged ()
232
250
                {
233
 
                        if (state == State.Replace || state == State.Insert || state == State.Visual)
 
251
                        if (CurState == State.Replace || CurState == State.Insert || CurState == State.Visual)
234
252
                                return;
235
 
                        else if (state == ViEditMode.State.Normal || state == ViEditMode.State.Unknown)
 
253
                        else if (CurState == ViEditMode.State.Normal || CurState == ViEditMode.State.Unknown)
236
254
                                ViActions.RetreatFromLineEnd (Data);
237
255
                        else
238
256
                                Reset ("");
239
257
                }
240
 
                
 
258
 
 
259
                ViStatusArea statusArea;
 
260
                TextEditor viTextEditor;
 
261
 
241
262
                void CheckVisualMode ()
242
263
                {
243
 
                        if (state == ViEditMode.State.Visual || state == ViEditMode.State.Visual) {
 
264
                        if (CurState == ViEditMode.State.Visual || CurState == ViEditMode.State.Visual) {
244
265
                                if (!Data.IsSomethingSelected)
245
 
                                        state = ViEditMode.State.Normal;
 
266
                                        CurState = ViEditMode.State.Normal;
246
267
                        } else {
247
268
                                if (Data.IsSomethingSelected) {
248
 
                                        state = ViEditMode.State.Visual;
 
269
                                        CurState = ViEditMode.State.Visual;
249
270
                                        Status = "-- VISUAL --";
250
271
                                }
251
272
                        }
274
295
                {
275
296
                        data.Caret.Mode = CaretMode.Block;
276
297
                        ViActions.RetreatFromLineEnd (data);
 
298
 
 
299
                        viTextEditor = data.Parent;
 
300
                        if (viTextEditor != null) {
 
301
                                statusArea = new ViStatusArea (viTextEditor, this);
 
302
                                viTextEditor.AddTopLevelWidget (statusArea, 0, 0);
 
303
                                ((TextEditor.EditorContainerChild)viTextEditor[statusArea]).FixedPosition = true;
 
304
                                statusArea.Show ();
 
305
                        }
277
306
                }
278
307
                
279
308
                protected override void OnRemovedFromEditor (TextEditorData data)
280
309
                {
281
310
                        data.Caret.Mode = CaretMode.Insert;
 
311
                        if (viTextEditor != null) {
 
312
                                viTextEditor.Remove (statusArea);
 
313
                                statusArea.Destroy ();
 
314
                                statusArea = null;
 
315
                                viTextEditor = null;
 
316
                        }
 
317
 
282
318
                }
283
319
                
284
320
                void Reset (string status)
285
321
                {
286
 
                        state = State.Normal;
 
322
                        CurState = State.Normal;
287
323
                        ResetEditorState (Data);
288
324
                        
289
325
                        commandBuffer.Length = 0;
330
366
                        Action<TextEditorData> action = null;
331
367
                        bool lineAction = false;
332
368
                        
333
 
                        switch (state) {
 
369
                        switch (CurState) {
334
370
                        case State.Unknown:
335
371
                                Reset (string.Empty);
336
372
                                goto case State.Normal;
342
378
                                        case '?':
343
379
                                        case '/':
344
380
                                        case ':':
345
 
                                                state = State.Command;
 
381
                                                CurState = State.Command;
346
382
                                                commandBuffer.Append ((char)unicodeKey);
347
383
                                                Status = commandBuffer.ToString ();
348
384
                                                return;
362
398
                                        case 'i':
363
399
                                                Caret.Mode = CaretMode.Insert;
364
400
                                                Status = "-- INSERT --";
365
 
                                                state = State.Insert;
 
401
                                                CurState = State.Insert;
366
402
                                                return;
367
403
                                                
368
404
                                        case 'R':
369
405
                                                Caret.Mode = CaretMode.Underscore;
370
406
                                                Status = "-- REPLACE --";
371
 
                                                state = State.Replace;
 
407
                                                CurState = State.Replace;
372
408
                                                return;
373
409
 
374
410
                                        case 'V':
375
411
                                                Status = "-- VISUAL LINE --";
376
412
                                                Data.SetSelectLines (Caret.Line, Caret.Line);
377
 
                                                state = State.VisualLine;
 
413
                                                CurState = State.VisualLine;
378
414
                                                return;
379
415
                                                
380
416
                                        case 'v':
381
417
                                                Status = "-- VISUAL --";
382
 
                                                state = State.Visual;
 
418
                                                CurState = State.Visual;
383
419
                                                RunAction (ViActions.VisualSelectionFromMoveAction (ViActions.Right));
384
420
                                                return;
385
421
                                                
386
422
                                        case 'd':
387
423
                                                Status = "d";
388
 
                                                state = State.Delete;
 
424
                                                CurState = State.Delete;
389
425
                                                return;
390
426
                                                
391
427
                                        case 'y':
392
428
                                                Status = "y";
393
 
                                                state = State.Yank;
 
429
                                                CurState = State.Yank;
394
430
                                                return;
395
431
 
396
432
                                        case 'Y':
397
 
                                                state = State.Yank;
 
433
                                                CurState = State.Yank;
398
434
                                                HandleKeypress (Gdk.Key.y, (int)'y', Gdk.ModifierType.None);
399
435
                                                return;
400
436
                                                
409
445
                                        case 'r':
410
446
                                                Caret.Mode = CaretMode.Underscore;
411
447
                                                Status = "-- REPLACE --";
412
 
                                                state = State.WriteChar;
 
448
                                                CurState = State.WriteChar;
413
449
                                                return;
414
450
                                                
415
451
                                        case 'c':
416
452
                                                Caret.Mode = CaretMode.Insert;
417
453
                                                Status = "c";
418
 
                                                state = State.Change;
 
454
                                                CurState = State.Change;
419
455
                                                return;
420
456
                                                
421
457
                                        case 'x':
449
485
                                                
450
486
                                        case '>':
451
487
                                                Status = ">";
452
 
                                                state = State.Indent;
 
488
                                                CurState = State.Indent;
453
489
                                                return;
454
490
                                                
455
491
                                        case '<':
456
492
                                                Status = "<";
457
 
                                                state = State.Unindent;
 
493
                                                CurState = State.Unindent;
458
494
                                                return;
459
495
                                        case 'n':
460
496
                                                Search ();
484
520
                                                
485
521
                                        case 'g':
486
522
                                                Status = "g";
487
 
                                                state = State.G;
 
523
                                                CurState = State.G;
488
524
                                                return;
489
525
                                                
490
526
                                        case 'H':
512
548
                                                
513
549
                                        case 'z':
514
550
                                                Status = "z";
515
 
                                                state = State.Fold;
 
551
                                                CurState = State.Fold;
516
552
                                                return;
517
553
                                                
518
554
                                        case 'm':
519
555
                                                Status = "m";
520
 
                                                state = State.Mark;
 
556
                                                CurState = State.Mark;
521
557
                                                return;
522
558
                                                
523
559
                                        case '`':
524
560
                                                Status = "`";
525
 
                                                state = State.GoToMark;
 
561
                                                CurState = State.GoToMark;
526
562
                                                return;
527
563
                                                
528
564
                                        case '@':
529
565
                                                Status = "@";
530
 
                                                state = State.PlayMacro;
 
566
                                                CurState = State.PlayMacro;
531
567
                                                return;
532
568
        
533
569
                                        case 'q':
534
570
                                                if (currentMacro == null) {
535
571
                                                        Status = "q";
536
 
                                                        state = State.NameMacro;
 
572
                                                        CurState = State.NameMacro;
537
573
                                                        return;
538
574
                                                } 
539
575
                                                currentMacro = null;
560
596
                                return;
561
597
                                
562
598
                        case State.Delete:
563
 
                                if (((modifier & (Gdk.ModifierType.ShiftMask | Gdk.ModifierType.ControlMask)) == 0 
 
599
                                if (IsInnerOrOuterMotionKey (unicodeKey, ref motion)) return;
 
600
 
 
601
                                if (motion != Motion.None) {
 
602
                                        action = ViActionMaps.GetEditObjectCharAction((char) unicodeKey, motion);
 
603
                                }
 
604
                                else if (((modifier & (Gdk.ModifierType.ShiftMask | Gdk.ModifierType.ControlMask)) == 0 
564
605
                                     && unicodeKey == 'd'))
565
606
                                {
566
607
                                        action = SelectionActions.LineActionFromMoveAction (CaretMoveActions.LineEnd);
586
627
                                return;
587
628
 
588
629
                        case State.Yank:
 
630
                                if (IsInnerOrOuterMotionKey (unicodeKey, ref motion)) return;
589
631
                                int offset = Caret.Offset;
590
 
                                
591
 
                                if (((modifier & (Gdk.ModifierType.ShiftMask | Gdk.ModifierType.ControlMask)) == 0 
 
632
 
 
633
                                if (motion != Motion.None) {
 
634
                                        action = ViActionMaps.GetEditObjectCharAction((char) unicodeKey, motion);
 
635
                                }
 
636
                                else if (((modifier & (Gdk.ModifierType.ShiftMask | Gdk.ModifierType.ControlMask)) == 0
592
637
                                     && unicodeKey == 'y'))
593
638
                                {
594
639
                                        action = SelectionActions.LineActionFromMoveAction (CaretMoveActions.LineEnd);
615
660
                                return;
616
661
                                
617
662
                        case State.Change:
 
663
                                if (IsInnerOrOuterMotionKey (unicodeKey, ref motion)) return;
 
664
 
 
665
                                if (motion != Motion.None) {
 
666
                                        action = ViActionMaps.GetEditObjectCharAction((char) unicodeKey, motion);
 
667
                                }
618
668
                                //copied from delete action
619
 
                                if (((modifier & (Gdk.ModifierType.ShiftMask | Gdk.ModifierType.ControlMask)) == 0 
 
669
                                else if (((modifier & (Gdk.ModifierType.ShiftMask | Gdk.ModifierType.ControlMask)) == 0 
620
670
                                     && unicodeKey == 'c'))
621
671
                                {
622
672
                                        action = SelectionActions.LineActionFromMoveAction (CaretMoveActions.LineEnd);
635
685
                                        else
636
686
                                                RunActions (action, ClipboardActions.Cut);
637
687
                                        Status = "-- INSERT --";
638
 
                                        state = State.Insert;
 
688
                                        CurState = State.Insert;
639
689
                                        Caret.Mode = CaretMode.Insert;
640
690
                                } else {
641
691
                                        Reset ("Unrecognised motion");
681
731
                                return;
682
732
 
683
733
                        case State.Visual:
 
734
                                if (IsInnerOrOuterMotionKey (unicodeKey, ref motion)) return;
 
735
 
 
736
                                if (motion != Motion.None) {
 
737
                                        action = ViActionMaps.GetEditObjectCharAction((char) unicodeKey, motion);
 
738
                                        if (action != null) {
 
739
                                                RunAction (action);
 
740
                                                return;
 
741
                                        }
 
742
                                }
 
743
 
684
744
                                if (key == Gdk.Key.Delete)
685
745
                                        unicodeKey = 'x';
686
746
                                switch ((char)unicodeKey) {
712
772
                                case Gdk.Key.KP_Enter:
713
773
                                        Status = RunExCommand (commandBuffer.ToString ());
714
774
                                        commandBuffer.Length = 0;
715
 
                                        state = State.Normal;
 
775
                                        CurState = State.Normal;
716
776
                                        break;
717
777
                                case Gdk.Key.BackSpace:
718
778
                                case Gdk.Key.Delete:
908
968
                        }
909
969
                }
910
970
 
 
971
                static bool IsInnerOrOuterMotionKey (uint unicodeKey, ref Motion motion)
 
972
                {
 
973
                        if (unicodeKey == 'i') {
 
974
                                motion = Motion.Inner;
 
975
                                return true;
 
976
                        } 
 
977
                        if (unicodeKey == 'a') {
 
978
                                motion = Motion.Outer;
 
979
                                return true;
 
980
                        }
 
981
                        return false;
 
982
                }
 
983
 
911
984
                /// <summary>
912
985
                /// Runs an in-place replacement on the selection or the current line
913
986
                /// using the "pattern", "replacement", and "trailer" groups of match.
971
1044
                                case 'c':
972
1045
                                        RunAction (ClipboardActions.Cut);
973
1046
                                        Caret.Mode = CaretMode.Insert;
974
 
                                        state = State.Insert;
 
1047
                                        CurState = State.Insert;
975
1048
                                        Status = "-- INSERT --";
976
1049
                                        return;
977
1050
                                case 'S':
991
1064
                                case ':':
992
1065
                                        commandBuffer.Append (":");
993
1066
                                        Status = commandBuffer.ToString ();
994
 
                                        state = State.Command;
 
1067
                                        CurState = State.Command;
995
1068
                                        break;
996
1069
                                case 'J':
997
1070
                                        RunAction (ViActions.Join);
1135
1208
                        NameMacro,
1136
1209
                        PlayMacro
1137
1210
                }
 
1211
 
 
1212
                public override void AllocateTextArea (TextEditor textEditor, TextArea textArea, Gdk.Rectangle allocation)
 
1213
                {
 
1214
                        if (!statusArea.Visible)
 
1215
                                statusArea.Show ();
 
1216
                        allocation.Height -= (int)textArea.LineHeight;
 
1217
                        if (textArea.Allocation != allocation)
 
1218
                                textArea.SizeAllocate (allocation);
 
1219
                        statusArea.SetSizeRequest (allocation.Width, (int)viTextEditor.LineHeight);
 
1220
                        viTextEditor.MoveTopLevelWidget (statusArea, 0, allocation.Height);
 
1221
                }
 
1222
 
 
1223
                class ViStatusArea : Gtk.DrawingArea
 
1224
                {
 
1225
                        TextEditor editor;
 
1226
                        ViEditMode editMode;
 
1227
 
 
1228
                        public ViStatusArea (TextEditor editor, ViEditMode editMode)
 
1229
                        {
 
1230
                                this.editor = editor;
 
1231
                                this.editMode = editMode;
 
1232
                                editor.TextViewMargin.CaretBlink += HandleCaretBlink;
 
1233
                                editor.Caret.PositionChanged += HandlePositionChanged;
 
1234
                        }
 
1235
 
 
1236
                        void HandlePositionChanged (object sender, DocumentLocationEventArgs e)
 
1237
                        {
 
1238
                                QueueDraw ();
 
1239
                        }
 
1240
 
 
1241
                        void HandleCaretBlink (object sender, EventArgs e)
 
1242
                        {
 
1243
                                QueueDraw ();
 
1244
                        }
 
1245
 
 
1246
                        protected override void OnDestroyed ()
 
1247
                        {
 
1248
                                editor.Caret.PositionChanged -= HandlePositionChanged;
 
1249
                                editor.TextViewMargin.CaretBlink -= HandleCaretBlink;
 
1250
                                base.OnDestroyed ();
 
1251
                        }
 
1252
                        
 
1253
                        protected override bool OnExposeEvent (Gdk.EventExpose evnt)
 
1254
                        {
 
1255
                                using (Cairo.Context cr = Gdk.CairoHelper.Create (evnt.Window)) {
 
1256
                                        cr.Rectangle (evnt.Region.Clipbox.X, evnt.Region.Clipbox.Y, evnt.Region.Clipbox.Width, evnt.Region.Clipbox.Height);
 
1257
                                        cr.Color = editor.ColorStyle.PlainText.Background;
 
1258
                                        cr.Fill ();
 
1259
                                        using (var layout = PangoUtil.CreateLayout (editor)) {
 
1260
                                                layout.FontDescription = editor.Options.Font;
 
1261
 
 
1262
                                                layout.SetText ("000,00-00");
 
1263
                                                int minstatusw, minstatush;
 
1264
                                                layout.GetPixelSize (out minstatusw, out minstatush);
 
1265
 
 
1266
                                                var line = editor.GetLine (editor.Caret.Line);
 
1267
                                                var visColumn = line.GetVisualColumn (editor.GetTextEditorData (), editor.Caret.Column);
 
1268
 
 
1269
                                                if (visColumn != editor.Caret.Column) {
 
1270
                                                        layout.SetText (editor.Caret.Line + "," + editor.Caret.Column + "-" + visColumn);
 
1271
                                                } else {
 
1272
                                                        layout.SetText (editor.Caret.Line + "," + editor.Caret.Column);
 
1273
                                                }
 
1274
 
 
1275
                                                int statusw, statush;
 
1276
                                                layout.GetPixelSize (out statusw, out statush);
 
1277
 
 
1278
                                                statusw = System.Math.Max (statusw, minstatusw);
 
1279
 
 
1280
                                                statusw += 8;
 
1281
                                                cr.MoveTo (Allocation.Width - statusw, 0);
 
1282
                                                statusw += 8;
 
1283
                                                cr.Color = editor.ColorStyle.PlainText.Foreground;
 
1284
                                                cr.ShowLayout (layout);
 
1285
 
 
1286
 
 
1287
                                                layout.SetText (editMode.Status);
 
1288
                                                int w, h;
 
1289
                                                layout.GetPixelSize (out w, out h);
 
1290
                                                var x = System.Math.Min (0, -w + Allocation.Width - editor.TextViewMargin.CharWidth - statusw);
 
1291
                                                cr.MoveTo (x, 0);
 
1292
                                                cr.Color = editor.ColorStyle.PlainText.Foreground;
 
1293
                                                cr.ShowLayout (layout);
 
1294
                                                if (editMode.CurState == ViEditMode.State.Command) {
 
1295
                                                        if (editor.TextViewMargin.caretBlink) {
 
1296
                                                                cr.Rectangle (w + x, 0, (int)editor.TextViewMargin.CharWidth, (int)editor.LineHeight);
 
1297
                                                                cr.Fill ();
 
1298
                                                        }
 
1299
                                                }
 
1300
                                        }
 
1301
                                }
 
1302
                                return true;
 
1303
                        }
 
1304
                }
 
1305
        }
 
1306
 
 
1307
        public enum Motion {
 
1308
                None = 0,
 
1309
                Inner,
 
1310
                Outer
1138
1311
        }
1139
1312
}