unsafe void _Drop(POINT xy, int effect) { _GetDropPos(ref xy, out int pos8); var z = new Sci_DragDropData { x = xy.x, y = xy.y }; string s = null; var b = new StringBuilder(); int what = 0, index = 0; if (_justText) { s = _data.text; } else { _sci.Call(SCI_DRAGDROP, 2, &z); //just hides the drag indicator and sets caret position if (_sci._fn.IsCodeFile) { string mi = _data.scripts ? "1 string s = name;|2 string s = path;|3 script.run(path);|4 t[name] = o => script.run(path);" : "11 string s = path;|12 run.it(path);|13 t[name] = o => run.it(path);"; what = popupMenu.showSimple(mi); if (what == 0) { return; } } if (_data.scripts) { var a = Panels.Files.TreeControl.DragDropFiles; if (a != null) { foreach (var f in a) { _AppendScriptOrLink(f.ItemPath, f.Name, f); } } } else if (_data.files != null) { foreach (var path in _data.files) { _AppendFileOrShell(path); } } else if (_data.shell != null) { _GetShell(_data.shell, out var shells, out var names); if (shells != null) { for (int i = 0; i < shells.Length; i++) { _AppendFileOrShell(shells[i], names[i]); } } } else if (_data.linkName != null) { _AppendScriptOrLink(_data.text, _GetLinkName(_data.linkName)); } s = b.ToString(); } if (!s.NE()) { if (_justText) //a simple drag-drop inside scintilla or text-only from outside { var s8 = Encoding.UTF8.GetBytes(s); fixed(byte *p8 = s8) { z.text = p8; z.len = s8.Length; if (0 == ((DragDropEffects)effect & DragDropEffects.Move)) { z.copy = 1; } CodeInfo.Pasting(_sci); _sci.Call(SCI_DRAGDROP, 2, &z); } } else //file, script or URL { InsertCode.Statements(s, ICSFlags.NoFocus); } if (!_sci.IsFocused && _sci.Hwnd.Window.IsActive) //note: don't activate window; let the drag source do it, eg Explorer activates on drag-enter. { _sci._noModelEnsureCurrentSelected = true; //don't scroll treeview to currentfile _sci.Focus(); _sci._noModelEnsureCurrentSelected = false; } } else { _sci.Call(SCI_DRAGDROP, 3); } void _AppendFileOrShell(string path, string name = null) { if (b.Length > 0) { b.AppendLine(); } var pi = new TUtil.PathInfo(path, name); b.Append(pi.FormatCode(what - 11, ++index)); } void _AppendScriptOrLink(string path, string name, FileNode fn = null) { if (b.Length > 0) { b.AppendLine(); } if (what == 0) { b.Append(path); } else { if (what == 4) { name = name.RemoveSuffix(".cs"); } name = name.Escape(); if (what is 4 or 13) { var t = InsertCodeUtil.GetNearestLocalVariableOfType("Au.toolbar", "Au.popupMenu"); b.Append($"{t?.Name ?? "t"}[\"{name}\"] = o => "); }
//static int s_test; public static void AddSnippets(List <CiComplItem> items, TextSpan span, CompilationUnitSyntax root, string code, CSharpSyntaxContext syncon) { //CSharpSyntaxContext was discovered later and therefore almost not used here. if (syncon.IsObjectCreationTypeContext) { return; } //CiUtil.GetContextType(syncon); //print.clear(); print.it(++s_test); //print.clear(); //foreach (var v in root.ChildNodes()) { // CiUtil.PrintNode(v); //} //print.it("---"); _Context context = _Context.Unknown; int pos = span.Start; //get node from start var token = root.FindToken(pos); var node = token.Parent; //CiUtil.PrintNode(node); //print.it("--"); //return; //find ancestor/self that contains pos inside while (node != null && !node.Span.ContainsInside(pos)) { node = node.Parent; } //CiUtil.PrintNode(node); //for(var v = node; v != null; v = v.Parent) print.it(v.GetType().Name, v is ExpressionSyntax, v is ExpressionStatementSyntax); //print.it(SyntaxFacts.IsTopLevelStatement); //print.it(SyntaxFacts.IsInNamespaceOrTypeContext); //not tested switch (node) { case BlockSyntax: case SwitchSectionSyntax: //between case: and break; case ElseClauseSyntax: case LabeledStatementSyntax: case IfStatementSyntax s1 when pos > s1.CloseParenToken.SpanStart: case WhileStatementSyntax s2 when pos > s2.CloseParenToken.SpanStart: case DoStatementSyntax s3 when pos <s3.WhileKeyword.SpanStart: case ForStatementSyntax s4 when pos> s4.CloseParenToken.SpanStart: case CommonForEachStatementSyntax s5 when pos > s5.CloseParenToken.SpanStart: case LockStatementSyntax s6 when pos > s6.CloseParenToken.SpanStart: case FixedStatementSyntax s7 when pos > s7.CloseParenToken.SpanStart: case UsingStatementSyntax s8 when pos > s8.CloseParenToken.SpanStart: context = _Context.Function; break; case TypeDeclarationSyntax td when pos > td.OpenBraceToken.Span.Start: //{ } of class, struct, interface context = _Context.Type; break; case NamespaceDeclarationSyntax ns when pos > ns.OpenBraceToken.Span.Start: case CompilationUnitSyntax: case null: context = _Context.Namespace | _Context.Function; //Function for C# 9 top-level statements. //FUTURE: only if in correct place. break; case LambdaExpressionSyntax: case ArrowExpressionClauseSyntax: //like void F() =>here context = _Context.Arrow; break; case AttributeListSyntax: context = _Context.Attributes; break; default: if (span.IsEmpty) //if '=> here;' or '=> here)' etc, use => { var t2 = token.GetPreviousToken(); if (t2.IsKind(SyntaxKind.EqualsGreaterThanToken) && t2.Parent is LambdaExpressionSyntax) { context = _Context.Arrow; } } break; } //print.it(context); s_context = context; if (s_items == null) { var a = new List <_CiComplItemSnippet>(); if (!filesystem.exists(CustomFile).File) { try { filesystem.copy(folders.ThisAppBS + @"Default\Snippets2.xml", CustomFile); } catch { goto g1; } } _LoadFile(CustomFile, true); g1 : _LoadFile(DefaultFile, false); if (a.Count == 0) { return; } s_items = a; void _LoadFile(string file, bool custom) { try { var xroot = XmlUtil.LoadElem(file); foreach (var xg in xroot.Elements("group")) { if (!xg.Attr(out string sc, "context")) { continue; } _Context con = default; if (sc == "Function") { con = _Context.Function; //many } else //few, eg Type or Namespace|Type { foreach (var seg in sc.Segments("|")) { switch (sc[seg.Range]) { case "Function": con |= _Context.Function; break; case "Type": con |= _Context.Type; break; case "Namespace": con |= _Context.Namespace; break; case "Arrow": con |= _Context.Arrow; break; case "Attributes": con |= _Context.Attributes; break; case "Any": con |= _Context.Any; break; case "Line": con |= _Context.Line; break; } } } if (con == default) { continue; } foreach (var xs in xg.Elements("snippet")) { a.Add(new _CiComplItemSnippet(xs.Attr("name"), xs, con, custom)); } } } catch (Exception ex) { print.it("Failed to load snippets from " + file + "\r\n\t" + ex.ToStringWithoutStack()); } } //FUTURE: support $selection$. Add menu Edit -> Surround -> Snippet1|Snippet2|.... //FUTURE: snippet editor, maybe like in Eclipse. } bool isLineStart = InsertCodeUtil.IsLineStart(code, pos); foreach (var v in s_items) { if (!v.context.HasAny(context)) { continue; } if (v.context.Has(_Context.Line) && !isLineStart) { continue; } v.group = 0; v.hidden = 0; v.hilite = 0; v.moveDown = 0; v.ci.Span = span; items.Add(v); } }