pascalabcnet/VisualPascalABCNET/AutoInsertCode/AutoInsertCode.cs
Mikhalkovich Stanislav 66b7aa42c5 fix #2058
Небольшие правки в CodeTemplates
2019-08-02 10:17:49 +03:00

209 lines
9.6 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ICSharpCode.TextEditor.Document;
using ICSharpCode.TextEditor;
using System.Text.RegularExpressions;
namespace VisualPascalABC
{
public partial class Form1
{
string Spaces(int n) => new string(' ', n);
string GetLine(int lineNum)
{
var ta = CurrentCodeFileDocument.TextEditor.ActiveTextAreaControl.TextArea;
var doc = ta.Document;
if (lineNum < doc.TotalNumberOfLines)
return TextUtilities.GetLineAsString(doc, lineNum);
else return null;
}
void GetCurNextLines(out string Current, out string Next, out string Prev) // Next - следующая непустая строка
{
var ta = CurrentCodeFileDocument.TextEditor.ActiveTextAreaControl.TextArea;
Current = GetLine(ta.Caret.Line);
var i = ta.Caret.Line + 1;
do
{
Next = GetLine(i);
i++;
} while (Next != null && Next.Trim() == "");
Prev = null;
if (ta.Caret.Line == 0)
return;
var j = ta.Caret.Line;
do
{
j--;
Prev = GetLine(j);
} while (j > 0 && Prev.Trim() == "");
if (Prev.Trim() == "")
Prev = null;
}
int Indent(string s)
{
return Array.FindIndex(s.ToCharArray(), c => c != ' ');
}
int CurrentOffset()
{
var editor = VisualPascalABCProgram.MainForm.CurrentCodeFileDocument.TextEditor;
var ta = editor.ActiveTextAreaControl.TextArea;
var tl_beg = new TextLocation(ta.Caret.Column, ta.Caret.Line);
return editor.ActiveTextAreaControl.TextArea.Document.PositionToOffset(tl_beg);
}
private bool TextArea_KeyEventHandler(char ch)
{
if (!tsAutoInsertCode.Checked)
return false;
try
{
var editor = VisualPascalABCProgram.MainForm.CurrentCodeFileDocument.TextEditor;
var ta = editor.ActiveTextAreaControl.TextArea;
var doc = ta.Document;
if (ch == ' ')
{
var caret1 = editor.ActiveTextAreaControl.Caret;
int start1 = TextUtilities.FindPrevWordStart(editor.Document, caret1.Offset);
var Text1 = editor.Document.GetText(start1, caret1.Offset - start1).TrimEnd();
if (Text1.ToLower().StartsWith("for") || Text1.ToLower().StartsWith("foreach"))
{
var curline = TextUtilities.GetLineAsString(editor.Document, caret1.Line);
var len = curline.TrimEnd().Length;
if (ta.Caret.Column == len)
{
doc.Replace(CurrentOffset(), curline.Length - len, " var");
ta.Caret.Column = ta.Caret.Column + 4;
}
}
return false;
}
/*if (ch == '(')
{
var tl_beg = new TextLocation(ta.Caret.Column, ta.Caret.Line);
int offset = doc.PositionToOffset(tl_beg);
doc.Insert(offset, ")");
return false;
}*/
if (ch != '\n')
return false;
var caret = editor.ActiveTextAreaControl.Caret;
int start = TextUtilities.FindPrevWordStart(editor.Document, caret.Offset);
var Text = editor.Document.GetText(start, caret.Offset - start).TrimEnd();
if (Text.ToLower() == "begin")
{
string cur, next, prev;
GetCurNextLines(out cur, out next, out prev);
// анализ предыдущей
var icur = Indent(cur);
if (cur.Trim().ToLower() == "begin" && (next == null || Indent(next) < icur || Indent(next) == icur && !next.TrimStart().ToLower().StartsWith("end"))) // значит, это единственное слово begin в строке
{
// Проанализируем предыдущий оператор по первому слову
var pst = prev?.TrimStart().ToLower();
if (pst != null)
if (pst.StartsWith("if") || pst.StartsWith("for") || pst.StartsWith("loop") || pst.StartsWith("with") || pst.StartsWith("on") || pst.StartsWith("while") || pst.StartsWith("else") || pst.StartsWith("foreach")) // потом улучшу - для нескольких выборов
{
// Надо удалить в текущей строке пробелы чтобы выровнять begin по if
var iprev = Indent(prev);
var tl_beg = new TextLocation(ta.Caret.Column, ta.Caret.Line);
int offset = doc.PositionToOffset(tl_beg);
var cls = doc.GetLineSegment(ta.Caret.Line);
// надо удалить всю строчку с begin и сформировать новую
doc.Replace(cls.Offset, cls.Length , Spaces(iprev)+"begin");
ta.Caret.Column = iprev + 5;
icur = iprev;
}
}
ta.InsertString("\n" + Spaces(icur + 2));
if (next == null || Indent(next) < icur || Indent(next) == icur && !next.TrimStart().ToLower().StartsWith("end"))
{
var tl_beg = new TextLocation(ta.Caret.Column, ta.Caret.Line);
int offset = doc.PositionToOffset(tl_beg);
var send = "\n" + Spaces(icur) + "end";
if (next == null && (prev == null || !(prev.TrimStart().ToLower().StartsWith("procedure") || prev.TrimStart().ToLower().StartsWith("function"))))
send += ".";
else send += ";";
doc.Insert(offset, send);
}
return true;
}
else if (Text.ToLower() == "repeat")
{
string cur, next, prev;
GetCurNextLines(out cur, out next, out prev);
var icur = Indent(cur);
ta.InsertString("\n" + Spaces(icur + 2));
if (next == null || Indent(next) < icur || Indent(next) == icur && !next.TrimStart().ToLower().StartsWith("until"))
{
var tl_beg = new TextLocation(ta.Caret.Column, ta.Caret.Line);
int offset = doc.PositionToOffset(tl_beg);
var send = "\n" + Spaces(icur) + "until ;";
doc.Insert(offset, send);
}
return true;
}
else if (Text.ToLower() == "of")
{
string cur, next, prev;
GetCurNextLines(out cur, out next, out prev);
var icur = Indent(cur);
ta.InsertString("\n" + Spaces(icur + 2));
if (cur.TrimStart().ToLower().StartsWith("case") && next == null || Indent(next) < icur || Indent(next) == icur && !next.TrimStart().ToLower().StartsWith("end"))
{
var tl_beg = new TextLocation(ta.Caret.Column, ta.Caret.Line);
int offset = doc.PositionToOffset(tl_beg);
var send = "\n" + Spaces(icur) + "end;";
doc.Insert(offset, send);
}
return true;
}
else if (Text.ToLower() == "then" || Text.ToLower() == "else" || Text.ToLower() == "do")
{
var cur = GetLine(ta.Caret.Line);
var icur = Indent(cur);
ta.InsertString("\n" + Spaces(icur + 2));
return true;
}
else
{
var seg = doc.GetLineSegment(ta.Caret.Line);
var curline = doc.GetText(seg).TrimEnd();
if (ta.Caret.Column >= curline.Length)
//if (curline.Contains(":=") && !curline.TrimStart().ToLower().StartsWith("for")) // Это наиболее спорно. Надо проверять, что до присваивания - одно имя
if (Regex.IsMatch(curline, @"^\s*\w+\s*:=", RegexOptions.IgnoreCase))
{
var curlinenew = Regex.Replace(curline, @"(\s*)(\S+)(\s*):=(\s*)([^ ;]+)(\s*)(;?)", @"$1$2 := $5;",RegexOptions.IgnoreCase);
while (curlinenew.EndsWith(";;"))
curlinenew = curlinenew.Remove(curlinenew.Length - 1);
doc.Replace(seg.Offset, curline.Length, curlinenew);
ta.Caret.Column = curlinenew.Length;
return false;
}
}
return false;
}
catch (Exception e)
{
}
return false;
}
}
}