void PerformOCR(string[] args) { try { if (args[0] == "-?" || args[0] == "-help" || args.Length == 1 || args.Length == 3 || args.Length == 5) { Console.WriteLine("Usage: vietocr imagefile outputfile [-l lang] [-psm pagesegmode]"); return; } FileInfo imageFile = new FileInfo(args[0]); FileInfo outputFile = new FileInfo(args[1]); if (!imageFile.Exists) { Console.WriteLine("Input file does not exist."); return; } string curLangCode = "eng"; //default language string psm = "3"; // or alternatively, "PSM_AUTO"; // 3 - Fully automatic page segmentation, but no OSD (default) if (args.Length == 4) { if (args[2].Equals("-l")) { curLangCode = args[3]; } else if (args[2].Equals("-psm")) { psm = args[3]; } } else if (args.Length == 6) { curLangCode = args[3]; psm = args[5]; try { Int16.Parse(psm); } catch { Console.WriteLine("Invalid input value."); return; } } IList <Image> imageList = ImageIOHelper.GetImageList(imageFile); OCR <Image> ocrEngine = new OCRImages(); ocrEngine.PSM = psm; string result = ocrEngine.RecognizeText(imageList, curLangCode); // postprocess to correct common OCR errors result = Processor.PostProcess(result, curLangCode); // correct common errors caused by OCR result = TextUtilities.CorrectOCRErrors(result); // correct letter cases result = TextUtilities.CorrectLetterCases(result); using (StreamWriter sw = new StreamWriter(outputFile.FullName + ".txt", false, new System.Text.UTF8Encoding())) { sw.Write(result); } } catch (Exception e) { Console.WriteLine("Error: " + e.Message); } }
/// <summary> /// Normalize a sequence of changes that were all applied consecutively to the same version of a buffer. Positions of the /// normalized changes are adjusted to account for other changes that occur at lower indexes in the /// buffer, and changes are sorted and merged if possible. /// </summary> /// <param name="changes">The changes to normalize.</param> /// <param name="differenceOptions">The options to use for minimal differencing, if any.</param> /// <param name="before">Text snapshot before the change (can be null).</param> /// <param name="after">Text snapshot after the change (can be null).</param> /// <returns>A (possibly empty) list of changes, sorted by Position, with adjacent and overlapping changes combined /// where possible.</returns> /// <exception cref="ArgumentNullException"><paramref name="changes"/> is null.</exception> private static IReadOnlyList <TextChange> Normalize(IReadOnlyList <TextChange> changes, StringDifferenceOptions?differenceOptions, ITextDifferencingService textDifferencingService, ITextSnapshot before, ITextSnapshot after) { if (changes.Count == 1 && differenceOptions == null) { // By far the most common path // If we are computing minimal changes, we need to go through the // algorithm anyway, since this change may be split up into many // smaller changes return(new TextChange[] { changes[0] }); } else if (changes.Count == 0) { return(new TextChange[0]); } TextChange[] work = TextUtilities.StableSort(changes, TextChange.Compare); // work is now sorted by increasing Position int accumulatedDelta = 0; int a = 0; int b = 1; while (b < work.Length) { // examine a pair of changes and attempt to combine them TextChange aChange = work[a]; TextChange bChange = work[b]; int gap = bChange.OldPosition - aChange.OldEnd; if (gap > 0) { // independent changes aChange.NewPosition = aChange.OldPosition + accumulatedDelta; accumulatedDelta += aChange.Delta; a = b; b = a + 1; } else { // dependent changes. merge all adjacent dependent changes into a single change in one pass, // to avoid expensive pairwise concatenations. // // Use StringRebuilders (which allow strings to be concatenated without creating copies of the strings) to assemble the // pieces. StringRebuilder newRebuilder = aChange._newText; StringRebuilder oldRebuilder = aChange._oldText; int aChangeIncrementalDeletions = 0; do { newRebuilder = newRebuilder.Append(bChange._newText); if (gap == 0) { // abutting deletions oldRebuilder = oldRebuilder.Append(bChange._oldText); aChangeIncrementalDeletions += bChange.OldLength; aChange.LineBreakBoundaryConditions = (aChange.LineBreakBoundaryConditions & LineBreakBoundaryConditions.PrecedingReturn) | (bChange.LineBreakBoundaryConditions & LineBreakBoundaryConditions.SucceedingNewline); } else { // overlapping deletions if (aChange.OldEnd + aChangeIncrementalDeletions < bChange.OldEnd) { int overlap = aChange.OldEnd + aChangeIncrementalDeletions - bChange.OldPosition; oldRebuilder = oldRebuilder.Append(bChange._oldText.GetSubText(Span.FromBounds(overlap, bChange._oldText.Length))); aChangeIncrementalDeletions += (bChange.OldLength - overlap); aChange.LineBreakBoundaryConditions = (aChange.LineBreakBoundaryConditions & LineBreakBoundaryConditions.PrecedingReturn) | (bChange.LineBreakBoundaryConditions & LineBreakBoundaryConditions.SucceedingNewline); } // else bChange deletion subsumed by aChange deletion } work[b] = null; b++; if (b == work.Length) { break; } bChange = work[b]; gap = bChange.OldPosition - aChange.OldEnd - aChangeIncrementalDeletions; } while (gap <= 0); work[a]._oldText = oldRebuilder; work[a]._newText = newRebuilder; if (b < work.Length) { aChange.NewPosition = aChange.OldPosition + accumulatedDelta; accumulatedDelta += aChange.Delta; a = b; b = a + 1; } } } // a points to the last surviving change work[a].NewPosition = work[a].OldPosition + accumulatedDelta; List <TextChange> result = new List <TextChange>(); if (differenceOptions.HasValue) { if (textDifferencingService == null) { throw new ArgumentNullException("stringDifferenceUtility"); } foreach (TextChange change in work) { if (change == null) { continue; } // Make sure this is a replacement if (change.OldLength == 0 || change.NewLength == 0) { result.Add(change); continue; } if (change.OldLength >= TextModelOptions.DiffSizeThreshold || change.NewLength >= TextModelOptions.DiffSizeThreshold) { change.IsOpaque = true; result.Add(change); continue; // too big to even attempt a diff. This is aimed at the reload-a-giant-file scenario // where OOM during diff is a distinct possibility. } // Make sure to turn off IgnoreTrimWhiteSpace, since that doesn't make sense in // the context of a minimal edit StringDifferenceOptions options = new StringDifferenceOptions(differenceOptions.Value); options.IgnoreTrimWhiteSpace = false; IHierarchicalDifferenceCollection diffs; if (before != null && after != null) { // Don't materialize the strings when we know the before and after snapshots. They might be really huge and cause OOM. // We will take this path in the file reload case. diffs = textDifferencingService.DiffSnapshotSpans(new SnapshotSpan(before, change.OldSpan), new SnapshotSpan(after, change.NewSpan), options); } else { // We need to evaluate the old and new text for the differencing service string oldText = change.OldText; string newText = change.NewText; if (oldText == newText) { // This change simply evaporates. This case occurs frequently in Venus and it is much // better to short circuit it here than to fire up the differencing engine. continue; } diffs = textDifferencingService.DiffStrings(oldText, newText, options); } // Keep track of deltas for the "new" position, for sanity check int delta = 0; // Add all the changes from the difference collection result.AddRange(GetChangesFromDifferenceCollection(ref delta, change, change._oldText, change._newText, diffs)); // Sanity check // If delta != 0, then we've constructed asymmetrical insertions and // deletions, which should be impossible Debug.Assert(delta == change.Delta, "Minimal edit delta should be equal to replaced text change's delta."); } } // If we aren't computing minimal changes, then copy over the non-null changes else { foreach (TextChange change in work) { if (change != null) { result.Add(change); } } } return(result); }
void Update() { text.text = TextUtilities.UnderscoresToSpaces(draw.GetLayer()); }
public string GetWordBeforeCaret() { int start = TextUtilities.FindPrevWordStart(Document, ActiveTextAreaControl.TextArea.Caret.Offset); return(Document.GetText(start, ActiveTextAreaControl.TextArea.Caret.Offset - start)); }
// Expand selection in both directions until a double quote or any line break character is reached static bool IsWordCharacter(char ch) => !(ch == '"' || TextUtilities.IsAnyLineBreakCharacter(ch));
/// <summary> /// Gets all indentation before the offset. /// </summary> /// <param name="document">The document.</param> /// <param name="offset">The offset where the indentation ends.</param> /// <returns>The indentation text.</returns> public static string GetWhitespaceBefore(ITextBuffer textBuffer, int offset) { ISegment segment = TextUtilities.GetWhitespaceBefore(GetTextSource(textBuffer), offset); return(textBuffer.GetText(segment.Offset, segment.Length)); }
private void MoveHorizontal(int count, InputModifiers modifiers) { var caretIndex = CaretIndex; if (caretIndex > TextDocument.TextLength) { caretIndex = TextDocument.TextLength; } if (caretIndex >= 0) { if ((modifiers & InputModifiers.Control) != 0) { if (count > 0) { count = TextUtilities.GetNextCaretPosition(TextDocument, caretIndex, TextUtilities.LogicalDirection.Forward, TextUtilities.CaretPositioningMode.WordStartOrSymbol) - caretIndex; } else { count = TextUtilities.GetNextCaretPosition(TextDocument, caretIndex, TextUtilities.LogicalDirection.Backward, TextUtilities.CaretPositioningMode.WordStartOrSymbol) - caretIndex; } if (caretIndex + count <= TextDocument.TextLength && caretIndex + count >= 0) { CaretIndex += count; } } else { if (count > 0) { for (var i = 0; i < Math.Abs(count); i++) { var line = TextDocument.GetLineByOffset(caretIndex); if (caretIndex == line.EndOffset) { if (line.NextLine != null) { caretIndex = line.NextLine.Offset; } } else { caretIndex = TextUtilities.GetNextCaretPosition(TextDocument, caretIndex, TextUtilities.LogicalDirection.Forward, TextUtilities.CaretPositioningMode.Normal); } } } else { for (var i = 0; i < Math.Abs(count); i++) { var line = TextDocument.GetLineByOffset(caretIndex); if (caretIndex == line.Offset) { if (line.PreviousLine != null) { caretIndex = line.PreviousLine.EndOffset; } } else { caretIndex = TextUtilities.GetNextCaretPosition(TextDocument, caretIndex, TextUtilities.LogicalDirection.Backward, TextUtilities.CaretPositioningMode.Normal); } } } CaretIndex = caretIndex; } SetHighestColumn(); } }
public static string GetAlignedText(IDocument document, int startOffset, int endOffset, int maxLineCount = 15) { // This fixes SD-1394: // Each line is checked for leading indentation whitespaces. If // a line has the same or more indentation than the first line, // it is reduced. If a line is less indented than the first line // the indentation is removed completely. // // See the following example: // line 1 // line 2 // line 3 // line 4 // // is reduced to: // line 1 // line 2 // line 3 // line 4 if (maxLineCount < 1) { maxLineCount = int.MaxValue; } IDocumentLine startLine = document.GetLineByOffset(startOffset); IDocumentLine endLine = document.GetLineByOffset(endOffset); StringBuilder builder = new StringBuilder(); IDocumentLine current = startLine; ISegment startIndent = TextUtilities.GetWhitespaceAfter(document, startLine.Offset); int lineCount = 0; while (current != endLine.NextLine && lineCount < maxLineCount) { ISegment currentIndent = TextUtilities.GetWhitespaceAfter(document, current.Offset); if (current == startLine && current == endLine) { builder.Append(document.GetText(startOffset, endOffset - startOffset)); } else if (current == startLine) { if (current.EndOffset - startOffset > 0) { builder.AppendLine(document.GetText(startOffset, current.EndOffset - startOffset).TrimStart()); } } else if (current == endLine) { if (startIndent.Length <= currentIndent.Length) { builder.Append(document.GetText(current.Offset + startIndent.Length, endOffset - current.Offset - startIndent.Length)); } else { builder.Append(document.GetText(current.Offset + currentIndent.Length, endOffset - current.Offset - currentIndent.Length)); } } else { if (startIndent.Length <= currentIndent.Length) { builder.AppendLine(document.GetText(current.Offset + startIndent.Length, current.Length - startIndent.Length)); } else { builder.AppendLine(document.GetText(current.Offset + currentIndent.Length, current.Length - currentIndent.Length)); } } current = current.NextLine; lineCount++; } if (current != endLine.NextLine) { builder.Append("..."); } return(builder.ToString()); }
void textArea_Drop(object sender, DragEventArgs e) { try { DragDropEffects effect = GetEffect(e); e.Effects = effect; if (effect != DragDropEffects.None) { string text = e.Data.GetData(DataFormats.UnicodeText, true) as string; if (text != null) { int start = textArea.Caret.Offset; if (mode == SelectionMode.Drag && textArea.Selection.Contains(start)) { Debug.WriteLine("Drop: did not drop: drop target is inside selection"); e.Effects = DragDropEffects.None; } else { Debug.WriteLine("Drop: insert at " + start); bool rectangular = e.Data.GetDataPresent(RectangleSelection.RectangularSelectionDataType); string newLine = TextUtilities.GetNewLineFromDocument(textArea.Document, textArea.Caret.Line); text = TextUtilities.NormalizeNewLines(text, newLine); string pasteFormat; // fill the suggested DataFormat used for the paste action: if (rectangular) { pasteFormat = RectangleSelection.RectangularSelectionDataType; } else { pasteFormat = DataFormats.UnicodeText; } var pastingEventArgs = new DataObjectPastingEventArgs(e.Data, true, pasteFormat); textArea.RaiseEvent(pastingEventArgs); if (pastingEventArgs.CommandCancelled) { return; } // DataObject.PastingEvent handlers might have changed the format to apply. rectangular = pastingEventArgs.FormatToApply == RectangleSelection.RectangularSelectionDataType; // Mark the undo group with the currentDragDescriptor, if the drag // is originating from the same control. This allows combining // the undo groups when text is moved. textArea.Document.UndoStack.StartUndoGroup(this.currentDragDescriptor); try { if (rectangular && RectangleSelection.PerformRectangularPaste(textArea, textArea.Caret.Position, text, true)) { } else { textArea.Document.Insert(start, text); textArea.Selection = Selection.Create(textArea, start, start + text.Length); } } finally { textArea.Document.UndoStack.EndUndoGroup(); } } e.Handled = true; } } } catch (Exception ex) { OnDragException(ex); } }
internal static void UpdateSpriteAsset(SpriteAsset spriteAsset) { // Get a list of all the sprites contained in the texture referenced by the sprite asset. // This only works if the texture is set to sprite mode. string filePath = AssetDatabase.GetAssetPath(spriteAsset.spriteSheet); if (string.IsNullOrEmpty(filePath)) { return; } // Get all the sprites defined in the sprite sheet texture referenced by this sprite asset. Sprite[] sprites = AssetDatabase.LoadAllAssetsAtPath(filePath).Select(x => x as Sprite).Where(x => x != null).ToArray(); // Return if sprite sheet texture does not have any sprites defined in it. if (sprites.Length == 0) { Debug.Log("Sprite Asset <color=#FFFF80>[" + spriteAsset.name + "]</color>'s atlas texture does not appear to have any sprites defined in it. Use the Unity Sprite Editor to define sprites for this texture.", spriteAsset.spriteSheet); return; } List <SpriteGlyph> spriteGlyphTable = spriteAsset.spriteGlyphTable; // Find available glpyh indexes uint[] existingGlyphIndexes = spriteGlyphTable.Select(x => x.index).ToArray(); List <uint> availableGlyphIndexes = new List <uint>(); uint lastGlyphIndex = existingGlyphIndexes.Length > 0 ? existingGlyphIndexes.Last() : 0; int elementIndex = 0; for (uint i = 0; i < lastGlyphIndex; i++) { uint existingGlyphIndex = existingGlyphIndexes[elementIndex]; if (i == existingGlyphIndex) { elementIndex += 1; } else { availableGlyphIndexes.Add(i); } } // Iterate over sprites contained in the updated sprite sheet to identify new and / or modified sprites. for (int i = 0; i < sprites.Length; i++) { Sprite sprite = sprites[i]; // Check if current sprites is already contained in the sprite glyph table of the sprite asset. SpriteGlyph spriteGlyph = spriteGlyphTable.FirstOrDefault(x => x.sprite == sprite); if (spriteGlyph != null) { // update existing sprite glyph if (spriteGlyph.glyphRect.x != sprite.rect.x || spriteGlyph.glyphRect.y != sprite.rect.y || spriteGlyph.glyphRect.width != sprite.rect.width || spriteGlyph.glyphRect.height != sprite.rect.height) { spriteGlyph.glyphRect = new GlyphRect(sprite.rect); } } else { SpriteCharacter spriteCharacter; // Check if this sprite potentially exists under the same name in the sprite character table. if (spriteAsset.spriteCharacterTable != null && spriteAsset.spriteCharacterTable.Count > 0) { spriteCharacter = spriteAsset.spriteCharacterTable.FirstOrDefault(x => x.name == sprite.name); spriteGlyph = spriteCharacter != null ? spriteGlyphTable[(int)spriteCharacter.glyphIndex] : null; if (spriteGlyph != null) { // Update sprite reference and data spriteGlyph.sprite = sprite; if (spriteGlyph.glyphRect.x != sprite.rect.x || spriteGlyph.glyphRect.y != sprite.rect.y || spriteGlyph.glyphRect.width != sprite.rect.width || spriteGlyph.glyphRect.height != sprite.rect.height) { spriteGlyph.glyphRect = new GlyphRect(sprite.rect); } } } spriteGlyph = new SpriteGlyph(); // Get available glyph index if (availableGlyphIndexes.Count > 0) { spriteGlyph.index = availableGlyphIndexes[0]; availableGlyphIndexes.RemoveAt(0); } else { spriteGlyph.index = (uint)spriteGlyphTable.Count; } spriteGlyph.metrics = new GlyphMetrics(sprite.rect.width, sprite.rect.height, -sprite.pivot.x, sprite.rect.height - sprite.pivot.y, sprite.rect.width); spriteGlyph.glyphRect = new GlyphRect(sprite.rect); spriteGlyph.scale = 1.0f; spriteGlyph.sprite = sprite; spriteGlyphTable.Add(spriteGlyph); spriteCharacter = new SpriteCharacter(0xFFFE, spriteGlyph); // Special handling for .notdef sprite name. string fileNameToLowerInvariant = sprite.name.ToLowerInvariant(); if (fileNameToLowerInvariant == ".notdef" || fileNameToLowerInvariant == "notdef") { spriteCharacter.unicode = 0; spriteCharacter.name = fileNameToLowerInvariant; } else { if (!string.IsNullOrEmpty(sprite.name) && sprite.name.Length > 2 && sprite.name[0] == '0' && (sprite.name[1] == 'x' || sprite.name[1] == 'X')) { spriteCharacter.unicode = TextUtilities.StringHexToInt(sprite.name.Remove(0, 2)); } spriteCharacter.name = sprite.name; } spriteCharacter.scale = 1.0f; spriteAsset.spriteCharacterTable.Add(spriteCharacter); } } // Update Sprite Character Table to replace unicode 0x0 by 0xFFFE for (int i = 0; i < spriteAsset.spriteCharacterTable.Count; i++) { SpriteCharacter spriteCharacter = spriteAsset.spriteCharacterTable[i]; if (spriteCharacter.unicode == 0) { spriteCharacter.unicode = 0xFFFE; } } // Sort glyph table by glyph index spriteAsset.SortGlyphTable(); spriteAsset.UpdateLookupTables(); TextEventManager.ON_SPRITE_ASSET_PROPERTY_CHANGED(true, spriteAsset); }
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) { SerializedProperty nameProperty = property.FindPropertyRelative("m_Name"); SerializedProperty hashCodeProperty = property.FindPropertyRelative("m_HashCode"); SerializedProperty openingDefinitionProperty = property.FindPropertyRelative("m_OpeningDefinition"); SerializedProperty closingDefinitionProperty = property.FindPropertyRelative("m_ClosingDefinition"); SerializedProperty openingDefinitionArray = property.FindPropertyRelative("m_OpeningTagArray"); SerializedProperty closingDefinitionArray = property.FindPropertyRelative("m_ClosingTagArray"); EditorGUIUtility.labelWidth = 86; position.height = EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing; float labelHeight = position.height + 2f; EditorGUI.BeginChangeCheck(); Rect rect0 = new Rect(position.x, position.y, (position.width) / 2 + 5, position.height); EditorGUI.PropertyField(rect0, nameProperty); if (EditorGUI.EndChangeCheck()) { // Recompute HashCode if name has changed. hashCodeProperty.intValue = TextUtilities.GetHashCodeCaseInSensitive(nameProperty.stringValue); property.serializedObject.ApplyModifiedProperties(); // Dictionary needs to be updated since HashCode has changed. TextStyleSheet styleSheet = property.serializedObject.targetObject as TextStyleSheet; styleSheet.RefreshStyles(); } // HashCode Rect rect1 = new Rect(rect0.x + rect0.width + 5, position.y, 65, position.height); GUI.Label(rect1, "HashCode"); GUI.enabled = false; rect1.x += 65; rect1.width = position.width / 2 - 75; EditorGUI.PropertyField(rect1, hashCodeProperty, GUIContent.none); GUI.enabled = true; // Text Tags EditorGUI.BeginChangeCheck(); // Opening Tags position.y += labelHeight; GUI.Label(position, "Opening Tags"); Rect textRect1 = new Rect(110, position.y, position.width - 86, 35); openingDefinitionProperty.stringValue = EditorGUI.TextArea(textRect1, openingDefinitionProperty.stringValue); if (EditorGUI.EndChangeCheck()) { // If any properties have changed, we need to update the Opening and Closing Arrays. int size = openingDefinitionProperty.stringValue.Length; // Adjust array size to match new string length. if (openingDefinitionArray.arraySize != size) { openingDefinitionArray.arraySize = size; } for (int i = 0; i < size; i++) { SerializedProperty element = openingDefinitionArray.GetArrayElementAtIndex(i); element.intValue = openingDefinitionProperty.stringValue[i]; } } EditorGUI.BeginChangeCheck(); // Closing Tags position.y += 38; GUI.Label(position, "Closing Tags"); Rect textRect2 = new Rect(110, position.y, position.width - 86, 35); closingDefinitionProperty.stringValue = EditorGUI.TextArea(textRect2, closingDefinitionProperty.stringValue); if (EditorGUI.EndChangeCheck()) { // If any properties have changed, we need to update the Opening and Closing Arrays. int size = closingDefinitionProperty.stringValue.Length; // Adjust array size to match new string length. if (closingDefinitionArray.arraySize != size) { closingDefinitionArray.arraySize = size; } for (int i = 0; i < size; i++) { SerializedProperty element = closingDefinitionArray.GetArrayElementAtIndex(i); element.intValue = closingDefinitionProperty.stringValue[i]; } } }
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) { SerializedProperty prop_Unicode = property.FindPropertyRelative("m_Unicode"); SerializedProperty prop_GlyphIndex = property.FindPropertyRelative("m_GlyphIndex"); SerializedProperty prop_Scale = property.FindPropertyRelative("m_Scale"); GUIStyle style = new GUIStyle(EditorStyles.label); style.richText = true; EditorGUIUtility.labelWidth = 40f; EditorGUIUtility.fieldWidth = 50; Rect rect = new Rect(position.x + 50, position.y, position.width, 49); // Display non-editable fields if (GUI.enabled == false) { int unicode = prop_Unicode.intValue; EditorGUI.LabelField(new Rect(rect.x, rect.y, 120f, 18), new GUIContent("Unicode: <color=#FFFF80>0x" + unicode.ToString("X") + "</color>"), style); EditorGUI.LabelField(new Rect(rect.x + 115, rect.y, 120f, 18), unicode <= 0xFFFF ? new GUIContent("UTF16: <color=#FFFF80>\\u" + unicode.ToString("X4") + "</color>") : new GUIContent("UTF32: <color=#FFFF80>\\U" + unicode.ToString("X8") + "</color>"), style); EditorGUI.LabelField(new Rect(rect.x, rect.y + 18, 120, 18), new GUIContent("Glyph ID: <color=#FFFF80>" + prop_GlyphIndex.intValue + "</color>"), style); EditorGUI.LabelField(new Rect(rect.x, rect.y + 36, 80, 18), new GUIContent("Scale: <color=#FFFF80>" + prop_Scale.floatValue + "</color>"), style); // Draw Glyph (if exists) DrawGlyph(position, property); } else // Display editable fields { EditorGUIUtility.labelWidth = 55f; GUI.SetNextControlName("Unicode Input"); EditorGUI.BeginChangeCheck(); string unicode = EditorGUI.TextField(new Rect(rect.x, rect.y, 120, 18), "Unicode:", prop_Unicode.intValue.ToString("X")); if (GUI.GetNameOfFocusedControl() == "Unicode Input") { //Filter out unwanted characters. char chr = Event.current.character; if ((chr < '0' || chr > '9') && (chr < 'a' || chr > 'f') && (chr < 'A' || chr > 'F')) { Event.current.character = '\0'; } } if (EditorGUI.EndChangeCheck()) { // Update Unicode value prop_Unicode.intValue = (int)TextUtilities.StringHexToInt(unicode); } // Cache current glyph index in case it needs to be restored if the new glyph index is invalid. int currentGlyphIndex = prop_GlyphIndex.intValue; EditorGUIUtility.labelWidth = 59f; EditorGUI.BeginChangeCheck(); EditorGUI.DelayedIntField(new Rect(rect.x, rect.y + 18, 100, 18), prop_GlyphIndex, new GUIContent("Glyph ID:")); if (EditorGUI.EndChangeCheck()) { // Get a reference to the font asset FontAsset fontAsset = property.serializedObject.targetObject as FontAsset; // Make sure new glyph index is valid. int elementIndex = fontAsset.glyphTable.FindIndex(item => item.index == prop_GlyphIndex.intValue); if (elementIndex == -1) { prop_GlyphIndex.intValue = currentGlyphIndex; } else { fontAsset.IsFontAssetLookupTablesDirty = true; } } int glyphIndex = prop_GlyphIndex.intValue; // Reset glyph selection if new character has been selected. if (GUI.enabled && m_GlyphSelectedForEditing != glyphIndex) { m_GlyphSelectedForEditing = -1; } // Display button to edit the glyph data. if (GUI.Button(new Rect(rect.x + 120, rect.y + 18, 75, 18), new GUIContent("Edit Glyph"))) { if (m_GlyphSelectedForEditing == -1) { m_GlyphSelectedForEditing = glyphIndex; } else { m_GlyphSelectedForEditing = -1; } // Button clicks should not result in potential change. GUI.changed = false; } // Show the glyph property drawer if selected if (glyphIndex == m_GlyphSelectedForEditing && GUI.enabled) { // Get a reference to the font asset FontAsset fontAsset = property.serializedObject.targetObject as FontAsset; if (fontAsset != null) { // Get the index of the glyph in the font asset glyph table. int elementIndex = fontAsset.glyphTable.FindIndex(item => item.index == glyphIndex); if (elementIndex != -1) { SerializedProperty prop_GlyphTable = property.serializedObject.FindProperty("m_GlyphTable"); SerializedProperty prop_Glyph = prop_GlyphTable.GetArrayElementAtIndex(elementIndex); SerializedProperty prop_GlyphMetrics = prop_Glyph.FindPropertyRelative("m_Metrics"); SerializedProperty prop_GlyphRect = prop_Glyph.FindPropertyRelative("m_GlyphRect"); Rect newRect = EditorGUILayout.GetControlRect(false, 115); EditorGUI.DrawRect(new Rect(newRect.x + 52, newRect.y - 20, newRect.width - 52, newRect.height - 5), new Color(0.1f, 0.1f, 0.1f, 0.45f)); EditorGUI.DrawRect(new Rect(newRect.x + 53, newRect.y - 19, newRect.width - 54, newRect.height - 7), new Color(0.3f, 0.3f, 0.3f, 0.8f)); // Display GlyphRect newRect.x += 55; newRect.y -= 18; newRect.width += 5; EditorGUI.PropertyField(newRect, prop_GlyphRect); // Display GlyphMetrics newRect.y += 45; EditorGUI.PropertyField(newRect, prop_GlyphMetrics); rect.y += 120; } } } EditorGUIUtility.labelWidth = 39f; EditorGUI.PropertyField(new Rect(rect.x, rect.y + 36, 80, 18), prop_Scale, new GUIContent("Scale:")); // Draw Glyph (if exists) DrawGlyph(position, property); } }
private static ILineBreaks ParseBlock(char[] buffer, int length, ref LineEndingState lineEnding, ref int currentLineLength, ref int longestLineLength) { // Note that the lineBreaks created here will (internally) use the pooled list of line breaks. IPooledLineBreaksEditor lineBreaks = LineBreakManager.CreatePooledLineBreakEditor(length); int index = 0; while (index < length) { int breakLength = TextUtilities.LengthOfLineBreak(buffer, index, length); if (breakLength == 0) { ++currentLineLength; ++index; } else { lineBreaks.Add(index, breakLength); longestLineLength = Math.Max(longestLineLength, currentLineLength); currentLineLength = 0; if (lineEnding != LineEndingState.Inconsistent) { if (breakLength == 2) { if (lineEnding == LineEndingState.Unknown) { lineEnding = LineEndingState.CRLF; } else if (lineEnding != LineEndingState.CRLF) { lineEnding = LineEndingState.Inconsistent; } } else { LineEndingState newLineEndingState; switch (buffer[index]) { // This code needs to be kep consistent with TextUtilities.LengthOfLineBreak() case '\r': newLineEndingState = LineEndingState.CR; break; case '\n': newLineEndingState = LineEndingState.LF; break; case '\u0085': newLineEndingState = LineEndingState.NEL; break; case '\u2028': newLineEndingState = LineEndingState.LS; break; case '\u2029': newLineEndingState = LineEndingState.PS; break; default: throw new InvalidOperationException("Unexpected line ending"); } if (lineEnding == LineEndingState.Unknown) { lineEnding = newLineEndingState; } else if (lineEnding != newLineEndingState) { lineEnding = LineEndingState.Inconsistent; } } } index += breakLength; } } lineBreaks.ReleasePooledLineBreaks(); return(lineBreaks); }
private void UpdateBracketHighlighting() { if (_bracketMarkerRenderer == null) { return; } var markers = _bracketMarkerRenderer.Markers; // Remove old markers. markers.Clear(); if (!EnableBracketHighlighting || (BracketHighlightingBrush == null && BracketHighlightingPen == null)) { return; } // See if we are after at closing bracket. if (CaretOffset >= 2) { // Get character before caret. var previousChar = Document.GetCharAt(CaretOffset - 1); int bracketIndex = Array.IndexOf(ClosingBrackets, previousChar); if (bracketIndex >= 0) { // Caret is after a closing bracket. // Find matching opening bracket. int openingBracketOffset = TextUtilities.FindOpeningBracket( Document, CaretOffset - 2, OpeningBrackets[bracketIndex], ClosingBrackets[bracketIndex]); if (openingBracketOffset >= 0) { // Opening bracket found. Mark both brackets. var openBracketMarker0 = new BlockMarker { StartOffset = openingBracketOffset, Length = 1, Brush = BracketHighlightingBrush, Pen = BracketHighlightingPen }; var closeBracketMarker0 = new BlockMarker { StartOffset = CaretOffset - 1, Length = 1, Brush = BracketHighlightingBrush, Pen = BracketHighlightingPen }; markers.Add(openBracketMarker0); markers.Add(closeBracketMarker0); } } } // See if we are before an opening bracket. if (Document != null && CaretOffset < Document.TextLength - 1) { // Get character before caret. var nextChar = Document.GetCharAt(CaretOffset); int bracketIndex = Array.IndexOf(OpeningBrackets, nextChar); if (bracketIndex >= 0) { // Caret is before an opening bracket. // Find matching opening bracket. int closingBracketOffset = TextUtilities.FindClosingBracket( Document, CaretOffset + 1, OpeningBrackets[bracketIndex], ClosingBrackets[bracketIndex]); if (closingBracketOffset >= 0) { // Opening bracket found. Mark both brackets. var openBracketMarker1 = new BlockMarker { StartOffset = CaretOffset, Length = 1, Brush = BracketHighlightingBrush, Pen = BracketHighlightingPen }; var closeBracketMarker1 = new BlockMarker { StartOffset = closingBracketOffset, Length = 1, Brush = BracketHighlightingBrush, Pen = BracketHighlightingPen }; markers.Add(openBracketMarker1); markers.Add(closeBracketMarker1); } } } }
// Token: 0x06000BC9 RID: 3017 RVA: 0x0004D3CC File Offset: 0x0004B5CC private void OnGUI() { if (Mathf.Abs(this._keyboardOffset - this._targetKeyboardOffset) > 2f) { this._keyboardOffset = Mathf.Lerp(this._keyboardOffset, this._targetKeyboardOffset, Time.deltaTime * 4f); } else { this._keyboardOffset = this._targetKeyboardOffset; } this._groupRect = new Rect((float)(Screen.width - 340) * 0.5f, (float)(Screen.height - 200) * 0.5f - this._keyboardOffset, 340f, 200f); GUI.depth = 3; GUI.skin = BlueStonez.Skin; Rect groupRect = this._groupRect; GUI.BeginGroup(groupRect, string.Empty, BlueStonez.window_standard_grey38); if (this.nameChangeItem != null) { this.nameChangeItem.DrawIcon(new Rect(8f, 8f, 48f, 48f)); if (BlueStonez.label_interparkbold_32pt_left.CalcSize(new GUIContent(this.nameChangeItem.View.Name)).x > groupRect.width - 72f) { GUI.Label(new Rect(64f, 8f, groupRect.width - 72f, 30f), this.nameChangeItem.View.Name, BlueStonez.label_interparkbold_18pt_left); } else { GUI.Label(new Rect(64f, 8f, groupRect.width - 72f, 30f), this.nameChangeItem.View.Name, BlueStonez.label_interparkbold_32pt_left); } } GUI.Label(new Rect(64f, 30f, groupRect.width - 72f, 30f), LocalizedStrings.FunctionalItem, BlueStonez.label_interparkbold_16pt_left); Rect rect = new Rect(8f, 116f, this._groupRect.width - 16f, this._groupRect.height - 120f - 46f); GUI.BeginGroup(new Rect(rect.xMin, 74f, rect.width, rect.height + 42f), string.Empty, BlueStonez.group_grey81); GUI.EndGroup(); GUI.Label(new Rect(56f, 72f, 227f, 20f), LocalizedStrings.ChooseCharacterName, BlueStonez.label_interparkbold_11pt); GUI.SetNextControlName("@ChooseName"); Rect position = new Rect(56f, 102f, 227f, 24f); GUI.changed = false; this.newName = GUI.TextField(position, this.newName, 18, BlueStonez.textField); this.newName = TextUtilities.Trim(this.newName); if (string.IsNullOrEmpty(this.newName) && GUI.GetNameOfFocusedControl() != "@ChooseName") { GUI.color = new Color(1f, 1f, 1f, 0.3f); GUI.Label(position, LocalizedStrings.EnterYourName, BlueStonez.label_interparkmed_11pt); GUI.color = Color.white; } if (GUITools.Button(new Rect(groupRect.width - 118f, 160f, 110f, 32f), new GUIContent(LocalizedStrings.CancelCaps), BlueStonez.button)) { this.HideKeyboard(); this.Hide(); } GUI.enabled = !this.isChangingName; if (GUITools.Button(new Rect(groupRect.width - 230f, 160f, 110f, 32f), new GUIContent(LocalizedStrings.OkCaps), BlueStonez.button_green)) { this.HideKeyboard(); this.ChangeName(); } GUI.EndGroup(); GUI.enabled = true; if (this.isChangingName) { WaitingTexture.Draw(new Vector2(groupRect.x + 305f, groupRect.y + 114f), 0); } GuiManager.DrawTooltip(); }
/// <summary> /// Return the completion item list for the current text position. /// This method does not await cache builds since it expects to return quickly /// </summary> /// <param name="textDocumentPosition"></param> public CompletionItem[] GetCompletionItems( TextDocumentPosition textDocumentPosition, ScriptFile scriptFile, ConnectionInfo connInfo) { // initialize some state to parse and bind the current script file this.currentCompletionParseInfo = null; CompletionItem[] resultCompletionItems = null; string filePath = textDocumentPosition.TextDocument.Uri; int startLine = textDocumentPosition.Position.Line; int parserLine = textDocumentPosition.Position.Line + 1; int startColumn = TextUtilities.PositionOfPrevDelimeter( scriptFile.Contents, textDocumentPosition.Position.Line, textDocumentPosition.Position.Character); int endColumn = TextUtilities.PositionOfNextDelimeter( scriptFile.Contents, textDocumentPosition.Position.Line, textDocumentPosition.Position.Character); int parserColumn = textDocumentPosition.Position.Character + 1; bool useLowerCaseSuggestions = this.CurrentSettings.SqlTools.IntelliSense.LowerCaseSuggestions.Value; // get the current script parse info object ScriptParseInfo scriptParseInfo = GetScriptParseInfo(textDocumentPosition.TextDocument.Uri); if (scriptParseInfo == null) { return(AutoCompleteHelper.GetDefaultCompletionItems( startLine, startColumn, endColumn, useLowerCaseSuggestions)); } // reparse and bind the SQL statement if needed if (RequiresReparse(scriptParseInfo, scriptFile)) { ParseAndBind(scriptFile, connInfo); } // if the parse failed then return the default list if (scriptParseInfo.ParseResult == null) { return(AutoCompleteHelper.GetDefaultCompletionItems( startLine, startColumn, endColumn, useLowerCaseSuggestions)); } // need to adjust line & column for base-1 parser indices Token token = GetToken(scriptParseInfo, parserLine, parserColumn); string tokenText = token != null ? token.Text : null; // check if the file is connected and the file lock is available if (scriptParseInfo.IsConnected && Monitor.TryEnter(scriptParseInfo.BuildingMetadataLock)) { try { // queue the completion task with the binding queue QueueItem queueItem = this.BindingQueue.QueueBindingOperation( key: scriptParseInfo.ConnectionKey, bindingTimeout: LanguageService.BindingTimeout, bindOperation: (bindingContext, cancelToken) => { // get the completion list from SQL Parser scriptParseInfo.CurrentSuggestions = Resolver.FindCompletions( scriptParseInfo.ParseResult, parserLine, parserColumn, bindingContext.MetadataDisplayInfoProvider); // cache the current script parse info object to resolve completions later this.currentCompletionParseInfo = scriptParseInfo; // convert the suggestion list to the VS Code format return(AutoCompleteHelper.ConvertDeclarationsToCompletionItems( scriptParseInfo.CurrentSuggestions, startLine, startColumn, endColumn)); }, timeoutOperation: (bindingContext) => { // return the default list if the connected bind fails return(AutoCompleteHelper.GetDefaultCompletionItems( startLine, startColumn, endColumn, useLowerCaseSuggestions, tokenText)); }); // wait for the queue item queueItem.ItemProcessed.WaitOne(); var completionItems = queueItem.GetResultAsT <CompletionItem[]>(); if (completionItems != null && completionItems.Length > 0) { resultCompletionItems = completionItems; } else if (!ShouldShowCompletionList(token)) { resultCompletionItems = AutoCompleteHelper.EmptyCompletionList; } } finally { Monitor.Exit(scriptParseInfo.BuildingMetadataLock); } } // if there are no completions then provide the default list if (resultCompletionItems == null) { resultCompletionItems = AutoCompleteHelper.GetDefaultCompletionItems( startLine, startColumn, endColumn, useLowerCaseSuggestions, tokenText); } return(resultCompletionItems); }
/// <summary> /// Finds the first word start in the document before offset. /// </summary> /// <returns>The offset of the word start, or -1 if there is no word start before the specified offset.</returns> public static int FindNextWordStart(this ITextBuffer textBuffer, int offset) { return(TextUtilities.GetNextCaretPosition(GetTextSource(textBuffer), offset, LogicalDirection.Forward, CaretPositioningMode.WordStart)); }
public void IndentLine(TextDocument document, DocumentLine line) { if (document == null || line == null) { return; } DocumentLine previousLine = line.PreviousLine; if (previousLine != null) { ISegment indentationSegment = TextUtilities.GetWhitespaceAfter(document, previousLine.Offset); string indentation = document.GetText(indentationSegment); if (Program.Options.AgressiveIndentation) { string currentLineTextTrimmed = (document.GetText(line)).Trim(); string lastLineTextTrimmed = (document.GetText(previousLine)).Trim(); char currentLineFirstNonWhitespaceChar = ' '; if (currentLineTextTrimmed.Length > 0) { currentLineFirstNonWhitespaceChar = currentLineTextTrimmed[0]; } char lastLineLastNonWhitespaceChar = ' '; if (lastLineTextTrimmed.Length > 0) { lastLineLastNonWhitespaceChar = lastLineTextTrimmed[lastLineTextTrimmed.Length - 1]; } if (lastLineLastNonWhitespaceChar == '{' && currentLineFirstNonWhitespaceChar != '}') { if (Program.Options.ReplaceTabsToWhitespace) { indentation += new string(' ', Program.Options.IndentationSize); } else { indentation += "\t"; } } else if (currentLineFirstNonWhitespaceChar == '}') { indentation = indentation.Length > 0 ? indentation.Substring(0, indentation.Length - 1) : string.Empty; } //TODO fix this /*if (lastLineTextTrimmed == "{" && currentLineTextTrimmed != "}") * { * indentation += "\t"; * } * else if (currentLineTextTrimmed == "}") * { * if (indentation.Length > 0) * { * indentation = indentation.Substring(0, indentation.Length - 1); * } * else * { * indentation = string.Empty; * } * }*/ } indentationSegment = TextUtilities.GetWhitespaceAfter(document, line.Offset); document.Replace(indentationSegment, indentation); } }
private static bool IsAllowedLanguageLetter(char character) { return(TextUtilities.GetCharacterClass(character) == CharacterClass.IdentifierPart); }
private static bool IsIdentifierCharacter(char c) { return(TextUtilities.GetCharacterClass(c) == CharacterClass.IdentifierPart); }
protected void OnKeyDown(object sender, KeyEventArgs e) { if (e.Handled) { return; } var caretIndex = CaretIndex; var movement = false; var handled = true; var modifiers = e.Modifiers; switch (e.Key) { case Key.OemPlus: if (modifiers == InputModifiers.Control) { if (TextView.FontSize < 60) { TextView.FontSize++; } } break; case Key.OemMinus: if (modifiers == InputModifiers.Control) { if (TextView.FontSize > 1) { TextView.FontSize--; } } break; case Key.A: if (modifiers == InputModifiers.Control) { SelectAll(); } break; case Key.C: if (modifiers == InputModifiers.Control) { Copy(); } break; case Key.V: if (modifiers == InputModifiers.Control) { Paste(); } break; case Key.X: if (modifiers == InputModifiers.Control) { Cut(); } break; case Key.Y: if (modifiers == InputModifiers.Control) { Redo(); } break; case Key.Z: if (modifiers == InputModifiers.Control) { Undo(); } break; case Key.Left: MoveHorizontal(-1, modifiers); movement = true; break; case Key.Right: MoveHorizontal(1, modifiers); movement = true; break; case Key.Up: MoveVertical(-1, modifiers); movement = true; break; case Key.Down: MoveVertical(1, modifiers); movement = true; break; case Key.Home: MoveHome(modifiers); movement = true; break; case Key.End: MoveEnd(modifiers); movement = true; break; case Key.Back: if (!DeleteSelection() && CaretIndex > 0) { var line = TextDocument.GetLineByOffset(CaretIndex); if (CaretIndex == line.Offset && line.PreviousLine != null) { var delimiterLength = line.PreviousLine.DelimiterLength; TextDocument.Remove(CaretIndex - delimiterLength, delimiterLength); CaretIndex -= delimiterLength; } else { TextDocument.Remove(caretIndex - 1, 1); --CaretIndex; } TextView.Invalidate(); } break; case Key.Delete: if (!DeleteSelection() && caretIndex < TextDocument.TextLength) { var line = TextDocument.GetLineByOffset(CaretIndex); if (CaretIndex == line.EndOffset && line.NextLine != null) { TextDocument.Remove(CaretIndex, line.DelimiterLength); } else { TextDocument.Remove(caretIndex, 1); } TextView.Invalidate(); } break; case Key.Enter: if (AcceptsReturn) { HandleTextInput("\r\n"); } break; case Key.Tab: if (AcceptsTab) { e.Handled = true; var shiftedLines = false; // TODO implement Selection.IsMultiLine if (SelectionStart != SelectionEnd) { if (e.Modifiers == InputModifiers.Shift) { var selection = GetSelectionAsSegment(); var lines = VisualLineGeometryBuilder.GetLinesForSegmentInDocument(TextDocument, selection); if (lines.Count() > 1) { TransformSelectedLines(line => { var offset = line.Offset; var s = TextUtilities.GetSingleIndentationSegment(TextDocument, offset, TabCharacter.Length); if (s.Length > 0) { TextDocument.Remove(s.Offset, s.Length); } }); } } else { var selection = GetSelectionAsSegment(); var lines = VisualLineGeometryBuilder.GetLinesForSegmentInDocument(TextDocument, selection); if (lines.Count() > 1) { TransformSelectedLines(line => { TextDocument.Insert(line.Offset, TabCharacter); }); shiftedLines = true; } } } if (!shiftedLines) { if (e.Modifiers == InputModifiers.Shift) { TransformSelectedLines(line => { var offset = CaretIndex - TabCharacter.Length; var s = TextUtilities.GetSingleIndentationSegment(TextDocument, offset, TabCharacter.Length); if (s.Length > 0) { TextDocument.Remove(s.Offset, s.Length); } }); } else { HandleTextInput(TabCharacter); } } } else { base.OnKeyDown(e); handled = false; } break; case Key.PageUp: TextView.PageUp(); break; case Key.PageDown: TextView.PageDown(); break; } if (movement && ((modifiers & InputModifiers.Shift) != 0)) { SelectionEnd = CaretIndex; } else if (movement) { SelectionStart = SelectionEnd = CaretIndex; } if (handled) { InvalidateVisual(); } }
//-------------------------------------------------------------- #region Completion Data //-------------------------------------------------------------- /// <summary> /// Requests the completion window. /// </summary> /// <param name="key">The last typed character that was not yet inserted in the document or '\0'.</param> /// <param name="explicitRequest"> /// If set to <see langword="true"/> this is an explicit request to show the window; if <see langword="false"/> /// the user is typing. /// </param> private void RequestCompletionWindow(char key, bool explicitRequest) { // ----- Determine ShaderRegion of current caret position. var document = _textEditor.Document; int caretOffset = _textEditor.CaretOffset; IList <NamedCompletionData> collectedIdentifiers; IList <NamedCompletionData> collectedFields; ShaderRegion region = _parser.IdentifyRegion(document, caretOffset, out collectedIdentifiers, out collectedFields); // ----- Abort if current region has no IntelliSense. switch (region) { case ShaderRegion.Unknown: case ShaderRegion.Assembler: case ShaderRegion.LineComment: case ShaderRegion.BlockComment: case ShaderRegion.String: case ShaderRegion.CharacterLiteral: // No IntelliSense for these regions. return; } // ----- # --> PreprocessorCompletionData if (key == '#') { char characterBeforeHash = (caretOffset > 0) ? document.GetCharAt(caretOffset - 1) : '\0'; if (characterBeforeHash == '\0' || char.IsWhiteSpace(characterBeforeHash)) { ShowCompletionWindow(PreprocessorCompletionData, null, '#'); } return; } // ----- Abort if a key is set and it is not part of an identifier. bool letterDigitOrUnderscorePressed = (TextUtilities.GetCharacterClass(key) == CharacterClass.IdentifierPart); if (key != '\0' && !letterDigitOrUnderscorePressed) { _completionWindow?.Close(); return; } // ----- Find the symbol immediately before the caret. string symbol; int offset = TextUtilities.FindStartOfIdentifier(document, caretOffset - 1); if (offset >= 0) { symbol = document.GetText(offset, caretOffset - offset); } else { symbol = string.Empty; offset = caretOffset; } // ----- Find the character before the symbol. --offset; char previousCharacter = (offset >= 0) ? document.GetCharAt(offset) : '\0'; // ----- #xxxx --> PreprocessorCompletionData // Check for preprocessor directives if (previousCharacter == '#') { --offset; char characterBeforeHash = (0 <= offset) ? document.GetCharAt(offset) : '\0'; if (characterBeforeHash == '\0' || char.IsWhiteSpace(characterBeforeHash)) { symbol = '#' + symbol; ShowCompletionWindow(PreprocessorCompletionData, symbol, key); } return; } // ----- xxxxx. --> MemberCompletionData and guessed fields. // Check for object members such as "myTexture.|" if (previousCharacter == '.') { if (region == ShaderRegion.StructureOrInterface || region == ShaderRegion.Code) { --offset; bool showCompletionWindow = false; char characterBeforeDot = (0 <= offset) ? document.GetCharAt(offset) : '\0'; if (characterBeforeDot == ']' || characterBeforeDot == ')') { // Looks like something similar to "myArray[n].|" or "GetTexture(n).|". // We assume that a member is requested. showCompletionWindow = true; } else { // Check if we have something like "myVariable.|" string objectName = TextUtilities.GetIdentifierAt(document, offset); if (!string.IsNullOrEmpty(objectName) && !Keywords.Contains(objectName) && !_parser.IsType(objectName)) { showCompletionWindow = true; } } if (showCompletionWindow) { ShowCompletionWindow(MergeCompletionData(MemberCompletionData, collectedFields), symbol, key); } } return; } // ----- Get non-whitespace character before symbol. char previousNonWhitespaceChar = previousCharacter; if (char.IsWhiteSpace(previousNonWhitespaceChar) && offset > 0) { offset = _parser.SkipWhiteSpaceBackwards(document, offset - 1); previousNonWhitespaceChar = document.GetCharAt(offset); } // ----- Check for effect state assignments if (previousNonWhitespaceChar == '=' && _parser.IsStateGroup(region)) { // The line should look like this: // "EffectState = |" --offset; offset = _parser.SkipWhiteSpaceBackwards(document, offset); // Skip index if (document.GetCharAt(offset) == ']') { offset = TextUtilities.FindOpeningBracket(document, offset - 1, '[', ']') - 1; } string stateName = TextUtilities.GetIdentifierAt(document, offset); if (!string.IsNullOrEmpty(stateName)) { // Lookup the state and show the allowed values. NamedObjectCollection <NamedCompletionData> lookupTable = null; switch (region) { case ShaderRegion.BlendState10: lookupTable = BlendStates; break; case ShaderRegion.DepthStencilState10: lookupTable = DepthStencilStates; break; case ShaderRegion.RasterizerState10: lookupTable = RasterizerStates; break; case ShaderRegion.SamplerState: lookupTable = SamplerStates; break; case ShaderRegion.SamplerState10: lookupTable = SamplerStates10; break; case ShaderRegion.TechniqueOrPass: case ShaderRegion.TechniqueOrPass10: case ShaderRegion.StateBlock: lookupTable = EffectStates; break; default: break; } NamedCompletionData state; if (lookupTable != null && lookupTable.TryGet(stateName, out state)) { List <NamedCompletionData> stateValueCompletionData; string[] values = ((StateCompletionData)state).AllowedValues; if (values.Length > 0) { // Add the allowed values for this state to completion data. stateValueCompletionData = new List <NamedCompletionData>(values.Length); foreach (string value in values) { stateValueCompletionData.Add(EffectStateValues[value]); } } else { // This effect state has a generic parameter. // Add types ("bool", "int", etc.) to the completion data. stateValueCompletionData = new List <NamedCompletionData>(ScalarTypes.Count + Types.Count); foreach (NamedCompletionData type in ScalarTypes) { stateValueCompletionData.Add(type); } foreach (NamedCompletionData type in Types) { stateValueCompletionData.Add(type); } } // Add the collected identifiers foreach (NamedCompletionData collectedIdentifier in collectedIdentifiers) { stateValueCompletionData.Add(collectedIdentifier); } ShowCompletionWindow(stateValueCompletionData.ToArray(), symbol, key); return; } } } // If we know nothing about the key, and we are after a blank, we don't want to open // a completion window. // If we have a completion window, we want to continue. // If the user has explicitly request info (e.g. Ctrl+Space) we want to continue. if (key == '\0' && previousCharacter == ' ' && !explicitRequest && _completionWindow == null) { return; } // Show default completion data for each region. ICompletionData[] completionData; switch (region) { case ShaderRegion.Global: completionData = GlobalCompletionData; break; case ShaderRegion.StructureOrInterface: case ShaderRegion.Code: completionData = CodeCompletionData; break; case ShaderRegion.Annotation: completionData = AnnotationCompletionData; break; case ShaderRegion.TechniqueOrPass: case ShaderRegion.TechniqueOrPass10: completionData = TechniqueCompletionData; break; case ShaderRegion.BlendState10: completionData = BlendStateCompletionData; break; case ShaderRegion.DepthStencilState10: completionData = DepthStencilStateCompletionData; break; case ShaderRegion.RasterizerState10: completionData = RasterizerStateCompletionData; break; case ShaderRegion.SamplerState: completionData = SamplerStateCompletionData; break; case ShaderRegion.SamplerState10: completionData = SamplerState10CompletionData; break; case ShaderRegion.StateBlock: completionData = StateBlockCompletionData; break; default: completionData = null; break; } // No data --> close window. if (completionData == null) { _completionWindow?.Close(); return; } // Combine static completion data with guessed identifiers List <ICompletionData> entireCompletionData = new List <ICompletionData>(); foreach (ICompletionData completionEntry in completionData) { entireCompletionData.Add(completionEntry); } foreach (NamedCompletionData collectedIdentifier in collectedIdentifiers) { entireCompletionData.Add(collectedIdentifier); } // Show completion window ShowCompletionWindow(MergeCompletionData(completionData, collectedIdentifiers), symbol, key); }
private void FormatLineInternal(TextArea textArea, int lineNr, int cursorOffset, char ch) { DocumentLine curLine = textArea.Document.GetLineByNumber(lineNr); DocumentLine lineAbove = lineNr > 1 ? textArea.Document.GetLineByNumber(lineNr - 1) : null; string terminator = TextUtilities.GetLineTerminator(textArea.Document, lineNr); string curLineText; // /// local string for curLine segment //if (ch == '/') //{ // curLineText = curLine.Text; // string lineAboveText = lineAbove == null ? "" : lineAbove.Text; // if (curLineText != null && curLineText.EndsWith("///") && (lineAboveText == null || !lineAboveText.Trim().StartsWith("///"))) // { // string indentation = DocumentUtilitites.GetWhitespaceAfter(textArea.Document, curLine.Offset); // object member = GetMemberAfter(textArea, lineNr); // if (member != null) // { // StringBuilder sb = new StringBuilder(); // sb.Append(" <summary>"); // sb.Append(terminator); // sb.Append(indentation); // sb.Append("/// "); // sb.Append(terminator); // sb.Append(indentation); // sb.Append("/// </summary>"); // if (member is IMethod) // { // IMethod method = (IMethod)member; // if (method.Parameters != null && method.Parameters.Count > 0) // { // for (int i = 0; i < method.Parameters.Count; ++i) // { // sb.Append(terminator); // sb.Append(indentation); // sb.Append("/// <param name=\""); // sb.Append(method.Parameters[i].Name); // sb.Append("\"></param>"); // } // } // if (method.ReturnType != null && !method.IsConstructor && method.ReturnType.FullyQualifiedName != "System.Void") // { // sb.Append(terminator); // sb.Append(indentation); // sb.Append("/// <returns></returns>"); // } // } // textArea.Document.Insert(cursorOffset, sb.ToString()); // textArea.Caret.Offset = cursorOffset + indentation.Length + "/// ".Length + " <summary>".Length + terminator.Length; // } // } // return; //} if (ch != '\n' && ch != '>') { if (IsInsideStringOrComment(textArea, curLine, cursorOffset)) { return; } } switch (ch) { case '>': if (IsInsideDocumentationComment(textArea, curLine, cursorOffset)) { curLineText = textArea.Document.GetText(curLine); int column = cursorOffset - curLine.Offset; int index = Math.Min(column - 1, curLineText.Length - 1); while (index >= 0 && curLineText[index] != '<') { --index; if (curLineText[index] == '/') { return; // the tag was an end tag or already } } if (index > 0) { StringBuilder commentBuilder = new StringBuilder(""); for (int i = index; i < curLineText.Length && i < column && !Char.IsWhiteSpace(curLineText[i]); ++i) { commentBuilder.Append(curLineText[i]); } string tag = commentBuilder.ToString().Trim(); if (!tag.EndsWith(">")) { tag += ">"; } if (!tag.StartsWith("/")) { textArea.Document.Insert(cursorOffset, "</" + tag.Substring(1)); } } } break; case ':': case ')': case ']': case '}': case '{': if (textArea.IndentationStrategy != null) { textArea.IndentationStrategy.IndentLine(textArea, curLine); } break; case '\n': string lineAboveText = lineAbove == null ? "" : textArea.Document.GetText(lineAbove); //// curLine might have some text which should be added to indentation curLineText = textArea.Document.GetText(curLine); if (lineAbove != null && textArea.Document.GetText(lineAbove).Trim().StartsWith("#region") && NeedEndregion(textArea.Document)) { textArea.Document.Insert(cursorOffset, "#endregion"); return; } IHighlighter highlighter = textArea.GetService(typeof(IHighlighter)) as IHighlighter; bool isInMultilineComment = false; bool isInMultilineString = false; if (highlighter != null && lineAbove != null) { var spanStack = highlighter.GetSpanColorNamesFromLineStart(lineNr); isInMultilineComment = spanStack.Contains(HighlightingKnownNames.Comment); isInMultilineString = spanStack.Contains(HighlightingKnownNames.String); } bool isInNormalCode = !(isInMultilineComment || isInMultilineString); if (lineAbove != null && isInMultilineComment) { string lineAboveTextTrimmed = lineAboveText.TrimStart(); if (lineAboveTextTrimmed.StartsWith("/*", StringComparison.Ordinal)) { textArea.Document.Insert(cursorOffset, " * "); return; } if (lineAboveTextTrimmed.StartsWith("*", StringComparison.Ordinal)) { textArea.Document.Insert(cursorOffset, "* "); return; } } if (lineAbove != null && isInNormalCode) { DocumentLine nextLine = lineNr + 1 <= textArea.Document.LineCount ? textArea.Document.GetLineByNumber(lineNr + 1) : null; string nextLineText = (nextLine != null) ? textArea.Document.GetText(nextLine) : ""; int indexAbove = lineAboveText.IndexOf("///"); int indexNext = nextLineText.IndexOf("///"); if (indexAbove > 0 && (indexNext != -1 || indexAbove + 4 < lineAbove.Length)) { textArea.Document.Insert(cursorOffset, "/// "); return; } if (IsInNonVerbatimString(lineAboveText, curLineText)) { textArea.Document.Insert(cursorOffset, "\""); textArea.Document.Insert(lineAbove.Offset + lineAbove.Length, "\" +"); } } if (/*textArea.Options.AutoInsertBlockEnd &&*/ lineAbove != null && isInNormalCode) { string oldLineText = textArea.Document.GetText(lineAbove); if (oldLineText.EndsWith("{")) { if (NeedCurlyBracket(textArea.Document.Text)) { int insertionPoint = curLine.Offset + curLine.Length; textArea.Document.Insert(insertionPoint, terminator + "}"); if (textArea.IndentationStrategy != null) { textArea.IndentationStrategy.IndentLine(textArea, textArea.Document.GetLineByNumber(lineNr + 1)); } textArea.Caret.Offset = insertionPoint; } } } return; } }
//-------------------------------------------------------------- #region Insight //-------------------------------------------------------------- /// <summary> /// Requests the insight window. /// </summary> /// <param name="key"> /// The currently pressed key which is not yet inserted in the document. /// </param> /// <remarks> /// This method should be called whenever the user types a new character. /// </remarks> private void RequestInsightWindow(char key) { // The insight window is shown when '(' or a ',' of a function signature is typed. if (key != '(' && key != ',') { return; } // Identify the region at the cursor position var document = _textEditor.Document; int caretOffset = _textEditor.TextArea.Caret.Offset; ShaderRegion region = _parser.IdentifyRegion(document, caretOffset); // Fetch lookup tables for the given region. NamedObjectCollection <NamedCompletionData>[] lookupTables = GetInsightLookupTables(region); if (lookupTables == null) { return; } // Find the name of the function. int offset = caretOffset; if (offset == 0) { return; } string identifier = null; if (key == '(') { // Code should look like this: // "Function|" int startOfIdentifier = TextUtilities.FindStartOfIdentifier(document, offset - 1); if (startOfIdentifier >= 0) { identifier = document.GetText(startOfIdentifier, offset - startOfIdentifier); } } else if (key == ',') { // Check whether we are inside a parameter list. // "Function(param1, param2|" offset = TextUtilities.FindOpeningBracket(document, offset - 1, '(', ')'); identifier = TextUtilities.GetIdentifierAt(document, offset - 1); } // Fetch the function description. FunctionCompletionData function = null; if (!string.IsNullOrEmpty(identifier)) { foreach (NamedObjectCollection <NamedCompletionData> lookupTable in lookupTables) { if (lookupTable.TryGet(identifier, out function)) { break; } } } ShowOverloadInsightWindow(function); }
private void BuildTypeDisplay(IType inputType, ISymbolWriter writer, INode enclosingDeclaration, TypeFormatFlags globalFlags, Stack <ISymbol> symbolStack = null) { var globalFlagsToPass = globalFlags & TypeFormatFlags.WriteOwnNameForAnyLike; var inObjectTypeLiteral = false; WriteType(inputType, globalFlags); return; void WriteType(IType type, TypeFormatFlags flags) { // Write null/null type as any if ((type.Flags & TypeFlags.Intrinsic) != TypeFlags.None) { if ((type.Flags & TypeFlags.PredicateType) != TypeFlags.None) { BuildTypePredicateDisplay(writer, type.Cast <IPredicateType>().Predicate); BuildTypeDisplay(type.Cast <IPredicateType>().Predicate.Type, writer, enclosingDeclaration, flags, symbolStack); } else { // Special handling for unknown / resolving types, they should show up as any and not unknown or __resolving writer.WriteKeyword((globalFlags & TypeFormatFlags.WriteOwnNameForAnyLike) == TypeFormatFlags.None && IsTypeAny(type) ? "any" : type.Cast <IIntrinsicType>().IntrinsicName); } } else if ((type.Flags & TypeFlags.ThisType) != TypeFlags.None) { if (inObjectTypeLiteral) { writer.ReportInaccessibleThisError(); } writer.WriteKeyword("this"); } else if ((type.Flags & TypeFlags.Reference) != TypeFlags.None) { WriteTypeReference((ITypeReference)type, flags); } else if ((type.Flags & (TypeFlags.Class | TypeFlags.Interface | TypeFlags.Enum | TypeFlags.TypeParameter)) != TypeFlags.None) { // The specified symbol flags need to be reinterpreted as type flags BuildSymbolDisplay(type.Symbol, writer, enclosingDeclaration, SymbolFlags.Type, SymbolFormatFlags.None, flags); } else if ((type.Flags & TypeFlags.Tuple) != TypeFlags.None) { WriteTupleType((ITupleType)type); } else if ((type.Flags & TypeFlags.UnionOrIntersection) != TypeFlags.None) { WriteUnionOrIntersectionType(type.Cast <IUnionOrIntersectionType>(), flags); } else if ((type.Flags & TypeFlags.Anonymous) != TypeFlags.None) { WriteAnonymousType((IObjectType)type, flags); } else if ((type.Flags & TypeFlags.StringLiteral) != TypeFlags.None) { writer.WriteStringLiteral(I($"\"{TextUtilities.EscapeString(((IStringLiteralType)type).Text)}\"")); } else { // Should never get here // { ... } WritePunctuation(writer, SyntaxKind.OpenBraceToken); WriteSpace(writer); WritePunctuation(writer, SyntaxKind.DotDotDotToken); WriteSpace(writer); WritePunctuation(writer, SyntaxKind.CloseBraceToken); } } void WriteTypeList(IReadOnlyList <IType> types, SyntaxKind delimiter) { for (var i = 0; i < types.Count; i++) { if (i > 0) { if (delimiter != SyntaxKind.CommaToken) { WriteSpace(writer); } WritePunctuation(writer, delimiter); WriteSpace(writer); } WriteType(types[i], delimiter == SyntaxKind.CommaToken ? TypeFormatFlags.None : TypeFormatFlags.InElementType); } } void WriteSymbolTypeReference(ISymbol symbol, IReadOnlyList <IType> typeArguments, int pos, int end, TypeFormatFlags flags) { // Unnamed expressions and arrow functions have reserved names that we don't want to display if ((symbol.Flags & SymbolFlags.Class) != SymbolFlags.None || !IsReservedMemberName(symbol.Name)) { BuildSymbolDisplay(symbol, writer, enclosingDeclaration, SymbolFlags.Type, SymbolFormatFlags.None, flags); } if (pos < end) { WritePunctuation(writer, SyntaxKind.LessThanToken); WriteType(typeArguments[pos++], TypeFormatFlags.None); while (pos < end) { WritePunctuation(writer, SyntaxKind.CommaToken); WriteSpace(writer); WriteType(typeArguments[pos++], TypeFormatFlags.None); } WritePunctuation(writer, SyntaxKind.GreaterThanToken); } } void WriteTypeReference(ITypeReference type, TypeFormatFlags flags) { var typeArguments = type.TypeArguments ?? new List <IType>(); if (type.Target == m_checker.m_globalArrayType && (flags & TypeFormatFlags.WriteArrayAsGenericType) == TypeFormatFlags.None) { WriteType(typeArguments[0], TypeFormatFlags.InElementType); WritePunctuation(writer, SyntaxKind.OpenBracketToken); WritePunctuation(writer, SyntaxKind.CloseBracketToken); } else { // Write the type reference in the format f<A>.g<B>.C<X, Y> where A and B are type arguments // for outer type parameters, and f and g are the respective declaring containers of those // type parameters. var outerTypeParameters = type.Target.OuterTypeParameters; var i = 0; if (outerTypeParameters != null) { var length = outerTypeParameters.Count; while (i < length) { // Find group of type arguments for type parameters with the same declaring container. var start = i; var parent = m_checker.GetParentSymbolOfTypeParameter(outerTypeParameters[i]); do { i++; }while (i < length && m_checker.GetParentSymbolOfTypeParameter(outerTypeParameters[i]) == parent); // When type parameters are their own type arguments for the whole group (i.e., we have // the default outer type arguments), we don't show the group. if (!outerTypeParameters.RangeEquals(typeArguments, start, i, EqualityComparer <IType> .Default)) { WriteSymbolTypeReference(parent, typeArguments, start, i, flags); WritePunctuation(writer, SyntaxKind.DotToken); } } } var typeParameterCount = type.Target.TypeParameters?.Count ?? 0; WriteSymbolTypeReference(type.Symbol, typeArguments, i, typeParameterCount, flags); } } void WriteTupleType(ITupleType type) { WritePunctuation(writer, SyntaxKind.OpenBracketToken); WriteTypeList(type.ElementTypes, SyntaxKind.CommaToken); WritePunctuation(writer, SyntaxKind.CloseBracketToken); } void WriteUnionOrIntersectionType(IUnionOrIntersectionType type, TypeFormatFlags flags) { if ((flags & TypeFormatFlags.InElementType) != TypeFormatFlags.None) { WritePunctuation(writer, SyntaxKind.OpenParenToken); } WriteTypeList(type.Types, (type.Flags & TypeFlags.Union) != TypeFlags.None ? SyntaxKind.BarToken : SyntaxKind.AmpersandToken); if ((flags & TypeFormatFlags.InElementType) != TypeFormatFlags.None) { WritePunctuation(writer, SyntaxKind.CloseParenToken); } } void WriteAnonymousType(IObjectType type, TypeFormatFlags flags) { var symbol = type.Symbol; if (symbol != null) { // Always use 'typeof T' for type of class, enum, and module objects if ((symbol.Flags & (SymbolFlags.Class | SymbolFlags.Enum | SymbolFlags.ValueModule)) != SymbolFlags.None) { WriteTypeofSymbol(type, flags); } else if (ShouldWriteTypeOfFunctionSymbol(symbol, flags)) { WriteTypeofSymbol(type, flags); } else if (symbolStack?.Contains(symbol) == true) { // If type is an anonymous type literal in a type alias declaration, use type alias name var typeAlias = m_checker.GetTypeAliasForTypeLiteral(type); if (typeAlias != null) { // The specified symbol flags need to be reinterpreted as type flags BuildSymbolDisplay(typeAlias, writer, enclosingDeclaration, SymbolFlags.Type, SymbolFormatFlags.None, flags); } else { // Recursive usage, use any WriteKeyword(writer, SyntaxKind.AnyKeyword); } } else { // Since instantiations of the same anonymous type have the same symbol, tracking symbols instead // of types allows us to catch circular references to instantiations of the same anonymous type if (symbolStack == null) { symbolStack = new Stack <ISymbol>(); } symbolStack.Push(symbol); WriteLiteralType(type, flags); symbolStack.Pop(); } } else { // Anonymous types with no symbol are never circular WriteLiteralType(type, flags); } } void WriteTypeofSymbol(IObjectType type, TypeFormatFlags typeFormatFlags) { WriteKeyword(writer, SyntaxKind.TypeOfKeyword); WriteSpace(writer); BuildSymbolDisplay(type.Symbol, writer, enclosingDeclaration, SymbolFlags.Value, SymbolFormatFlags.None, typeFormatFlags); } string GetIndexerParameterName(IObjectType type, IndexKind indexKind, string fallbackName) { var declaration = GetIndexDeclarationOfSymbol(type.Symbol, indexKind); if (declaration == null) { // declaration might not be found if indexer was added from the contextual type. // in this case use fallback name return(fallbackName); } Contract.Assert(declaration.Parameters.Length != 0); return(DeclarationNameToString(declaration.Parameters[0].Name)); } void WriteLiteralType(IObjectType type, TypeFormatFlags flags) { IResolvedType resolved = m_checker.ResolveStructuredTypeMembers(type); if (resolved.Properties.Count == 0 && resolved.StringIndexType == null && resolved.NumberIndexType == null) { if (resolved.CallSignatures.Count == 0 && resolved.ConstructSignatures.Count == 0) { WritePunctuation(writer, SyntaxKind.OpenBraceToken); WritePunctuation(writer, SyntaxKind.CloseBraceToken); return; } if (resolved.CallSignatures.Count == 1 && resolved.ConstructSignatures.Count == 0) { if ((flags & TypeFormatFlags.InElementType) != TypeFormatFlags.None) { WritePunctuation(writer, SyntaxKind.OpenParenToken); } BuildSignatureDisplay(resolved.CallSignatures[0], writer, enclosingDeclaration, globalFlagsToPass | TypeFormatFlags.WriteArrowStyleSignature, /*kind*/ null, symbolStack); if ((flags & TypeFormatFlags.InElementType) != TypeFormatFlags.None) { WritePunctuation(writer, SyntaxKind.CloseParenToken); } return; } if (resolved.ConstructSignatures.Count == 1 && resolved.CallSignatures.Count == 0) { if ((flags & TypeFormatFlags.InElementType) != TypeFormatFlags.None) { WritePunctuation(writer, SyntaxKind.OpenParenToken); } WriteKeyword(writer, SyntaxKind.NewKeyword); WriteSpace(writer); BuildSignatureDisplay(resolved.ConstructSignatures[0], writer, enclosingDeclaration, globalFlagsToPass | TypeFormatFlags.WriteArrowStyleSignature, /*kind*/ null, symbolStack); if ((flags & TypeFormatFlags.InElementType) != TypeFormatFlags.None) { WritePunctuation(writer, SyntaxKind.CloseParenToken); } return; } } var saveInObjectTypeLiteral = inObjectTypeLiteral; inObjectTypeLiteral = true; WritePunctuation(writer, SyntaxKind.OpenBraceToken); writer.WriteLine(); writer.IncreaseIndent(); foreach (var signature in resolved.CallSignatures.AsStructEnumerable()) { BuildSignatureDisplay(signature, writer, enclosingDeclaration, globalFlagsToPass, /*kind*/ null, symbolStack); WritePunctuation(writer, SyntaxKind.SemicolonToken); writer.WriteLine(); } foreach (var signature in resolved.ConstructSignatures.AsStructEnumerable()) { BuildSignatureDisplay(signature, writer, enclosingDeclaration, globalFlagsToPass, SignatureKind.Construct, symbolStack); WritePunctuation(writer, SyntaxKind.SemicolonToken); writer.WriteLine(); } if (resolved.StringIndexType != null) { // [string x]: WritePunctuation(writer, SyntaxKind.OpenBracketToken); writer.WriteParameter(GetIndexerParameterName(resolved, IndexKind.String, /*fallbackName*/ "x")); WritePunctuation(writer, SyntaxKind.ColonToken); WriteSpace(writer); WriteKeyword(writer, SyntaxKind.StringKeyword); WritePunctuation(writer, SyntaxKind.CloseBracketToken); WritePunctuation(writer, SyntaxKind.ColonToken); WriteSpace(writer); WriteType(resolved.StringIndexType, TypeFormatFlags.None); WritePunctuation(writer, SyntaxKind.SemicolonToken); writer.WriteLine(); } if (resolved.NumberIndexType != null) { // [int x]: WritePunctuation(writer, SyntaxKind.OpenBracketToken); writer.WriteParameter(GetIndexerParameterName(resolved, IndexKind.Number, /*fallbackName*/ "x")); WritePunctuation(writer, SyntaxKind.ColonToken); WriteSpace(writer); WriteKeyword(writer, SyntaxKind.NumberKeyword); WritePunctuation(writer, SyntaxKind.CloseBracketToken); WritePunctuation(writer, SyntaxKind.ColonToken); WriteSpace(writer); WriteType(resolved.NumberIndexType, TypeFormatFlags.None); WritePunctuation(writer, SyntaxKind.SemicolonToken); writer.WriteLine(); } foreach (var p in resolved.Properties.AsStructEnumerable()) { var t = m_checker.GetTypeOfSymbol(p); if ((p.Flags & (SymbolFlags.Function | SymbolFlags.Method)) != SymbolFlags.None && m_checker.GetPropertiesOfObjectType(t).Count == 0) { var signatures = m_checker.GetSignaturesOfType(t, SignatureKind.Call); foreach (var signature in signatures.AsStructEnumerable()) { BuildSymbolDisplay(p, writer); if ((p.Flags & SymbolFlags.Optional) != SymbolFlags.None) { WritePunctuation(writer, SyntaxKind.QuestionToken); } BuildSignatureDisplay(signature, writer, enclosingDeclaration, globalFlagsToPass, /*kind*/ null, symbolStack); WritePunctuation(writer, SyntaxKind.SemicolonToken); writer.WriteLine(); } } else { BuildSymbolDisplay(p, writer); if ((p.Flags & SymbolFlags.Optional) != SymbolFlags.None) { WritePunctuation(writer, SyntaxKind.QuestionToken); } WritePunctuation(writer, SyntaxKind.ColonToken); WriteSpace(writer); WriteType(t, TypeFormatFlags.None); WritePunctuation(writer, SyntaxKind.SemicolonToken); writer.WriteLine(); } } writer.DecreaseIndent(); WritePunctuation(writer, SyntaxKind.CloseBraceToken); inObjectTypeLiteral = saveInObjectTypeLiteral; } bool ShouldWriteTypeOfFunctionSymbol(ISymbol symbol, TypeFormatFlags flags) { var isStaticMethodSymbol = ((symbol.Flags & SymbolFlags.Method) != SymbolFlags.None && // typeof static method symbol.DeclarationList.Any(declaration => (declaration.Flags & NodeFlags.Static) != NodeFlags.None)) == true; var isNonLocalFunctionSymbol = (symbol.Flags & SymbolFlags.Function) != SymbolFlags.None && (symbol.Parent != null || // is exported symbol symbol.DeclarationList.Any(declaration => declaration.Parent.Kind == SyntaxKind.SourceFile || declaration.Parent.Kind == SyntaxKind.ModuleBlock)); if (isStaticMethodSymbol || isNonLocalFunctionSymbol) { // typeof is allowed only for static/non local functions return((flags & TypeFormatFlags.UseTypeOfFunction) != TypeFormatFlags.None || // use typeof if format flags specify it symbolStack?.Contains(symbol) == true); // it is type of the symbol uses itself recursively } return(false); } }
static bool IsWordBorder(ITextSource document, int offset) { return(TextUtilities.GetNextCaretPosition(document, offset - 1, LogicalDirection.Forward, CaretPositioningMode.WordBorder) == offset); }
protected void OnPaste(object target, ExecutedRoutedEventArgs args) { if (target != textEditor.textArea) { return; } TextArea textArea = textEditor.textArea; if (textArea != null && textArea.Document != null) { Debug.WriteLine(Clipboard.GetText(TextDataFormat.Html)); // convert text back to correct newlines for this document string newLine = TextUtilities.GetNewLineFromDocument(textArea.Document, textArea.Caret.Line); string text = TextUtilities.NormalizeNewLines(Clipboard.GetText(), newLine); string[] commands = text.Split(new String[] { newLine }, StringSplitOptions.None); string scriptText = ""; if (commands.Length > 1) { text = newLine; foreach (string command in commands) { text += "... " + command + newLine; scriptText += command.Replace("\t", " ") + newLine; } } if (!string.IsNullOrEmpty(text)) { bool fullLine = textArea.Options.CutCopyWholeLine && Clipboard.ContainsData(LineSelectedType); bool rectangular = Clipboard.ContainsData(RectangleSelection.RectangularSelectionDataType); if (fullLine) { DocumentLine currentLine = textArea.Document.GetLineByNumber(textArea.Caret.Line); if (textArea.ReadOnlySectionProvider.CanInsert(currentLine.Offset)) { textArea.Document.Insert(currentLine.Offset, text); } } else if (rectangular && textArea.Selection.IsEmpty) { if (!RectangleSelection.PerformRectangularPaste(textArea, textArea.Caret.Offset, text, false)) { textEditor.Write(text, false); } } else { textEditor.Write(text, false); } } textArea.Caret.BringCaretToView(); args.Handled = true; if (commands.Length > 1) { lock (this.scriptText) { this.scriptText = scriptText; } dispatcher.BeginInvoke(new Action(delegate() { ExecuteStatements(); })); } } }
private Panel CreatePanelForLane(KeyValuePair <int, Lane> laneAndId) { var lane = laneAndId.Value; var blocks = lane.Blocks; if (blocks.Count == 0) { return(null); } var canvas = new Canvas(); canvas.VerticalAlignment = VerticalAlignment.Top; var endpoints = new List <BlockEndpoint>(); foreach (var block in blocks) { block.StartPoint = new BlockEndpoint() { Block = block, Timestamp = block.StartTime.Ticks, IsStart = true }; block.EndPoint = new BlockEndpoint() { Block = block, Timestamp = block.EndTime.Ticks }; endpoints.Add(block.StartPoint); endpoints.Add(block.EndPoint); } endpoints.Sort((l, r) => l.Timestamp.CompareTo(r.Timestamp)); int level = 0; foreach (var endpoint in endpoints) { if (endpoint.IsStart) { level++; endpoint.Block.Indent = level; } else { level--; } } blocks.Sort((l, r) => { var startDifference = l.StartTime.Ticks.CompareTo(r.StartTime.Ticks); if (startDifference != 0) { return(startDifference); } return(l.Length.CompareTo(r.Length)); }); DateTime minDateTime = blocks[0].StartTime; DateTime maxDateTime = blocks[blocks.Count - 1].StartTime; foreach (var block in blocks) { block.Start = block.StartTime.Ticks; block.End = block.EndTime.Ticks; } double start = minDateTime.Ticks; double end = maxDateTime.Ticks; double totalDuration = end - start; if (totalDuration == 0) { totalDuration = 1; } double width = 0; var sample = new TextBlock(); sample.Text = "W"; sample.Measure(new Size(10000, 10000)); var textHeight = sample.DesiredSize.Height; double preferredTotalHeight = textHeight * blocks.Count(b => b.Length > totalDuration / 2000); double currentHeight = 0; double totalHeight = 0; foreach (var block in blocks) { //if (block.Length > minimumDurationToInclude) { var textBlock = new TextBlock(); textBlock.Text = $"{block.Text} ({TextUtilities.DisplayDuration(block.Duration)})"; textBlock.Background = ChooseBackground(block); double left = 24 * block.Indent; double top = (block.Start - start) / totalDuration * preferredTotalHeight; double height = (block.End - block.Start) / totalDuration * preferredTotalHeight; if (height < textHeight) { height = textHeight; continue; } textBlock.Measure(new Size(10000, 10000)); double currentTotalWidth = left + textBlock.DesiredSize.Width; if (currentTotalWidth > width) { width = currentTotalWidth; } double minimumTop = currentHeight; if (minimumTop > top) { double adjustment = minimumTop - top; if (height > adjustment + textHeight) { height = height - adjustment; top = minimumTop; } else { continue; } } textBlock.Height = height; textBlock.ToolTip = block.GetTooltip(); textBlock.MouseUp += TextBlock_MouseUp; textBlock.Tag = block; currentHeight = top + textHeight; if (totalHeight < top + height) { totalHeight = top + height; } Canvas.SetLeft(textBlock, left); Canvas.SetTop(textBlock, top); canvas.Children.Add(textBlock); } } canvas.Height = totalHeight; canvas.Width = width; canvas.MouseMove += Canvas_MouseMove; return(canvas); }
void FormatLineInternal(TextArea textArea, int lineNr, int cursorOffset, char ch) { LineSegment curLine = textArea.Document.GetLineSegment(lineNr); LineSegment lineAbove = lineNr > 0 ? textArea.Document.GetLineSegment(lineNr - 1) : null; string terminator = textArea.TextEditorProperties.LineTerminator; //// local string for curLine segment string curLineText = ""; if (ch == '/') { curLineText = textArea.Document.GetText(curLine); string lineAboveText = lineAbove == null ? "" : textArea.Document.GetText(lineAbove); if (curLineText != null && curLineText.EndsWith("///") && (lineAboveText == null || !lineAboveText.Trim().StartsWith("///"))) { string indentation = base.GetIndentation(textArea, lineNr); object member = GetMemberAfter(textArea, lineNr); if (member != null) { StringBuilder sb = new StringBuilder(); sb.Append(" <summary>"); sb.Append(terminator); sb.Append(indentation); sb.Append("/// "); sb.Append(terminator); sb.Append(indentation); sb.Append("/// </summary>"); if (member is IMethod) { IMethod method = (IMethod)member; if (method.Parameters != null && method.Parameters.Count > 0) { for (int i = 0; i < method.Parameters.Count; ++i) { sb.Append(terminator); sb.Append(indentation); sb.Append("/// <param name=\""); sb.Append(method.Parameters[i].Name); sb.Append("\"></param>"); } } if (method.ReturnType != null && !method.IsConstructor && method.ReturnType.FullyQualifiedName != "System.Void") { sb.Append(terminator); sb.Append(indentation); sb.Append("/// <returns></returns>"); } } textArea.Document.Insert(cursorOffset, sb.ToString()); textArea.Refresh(); textArea.Caret.Position = textArea.Document.OffsetToPosition(cursorOffset + indentation.Length + "/// ".Length + " <summary>".Length + terminator.Length); } } return; } if (ch != '\n' && ch != '>') { if (IsInsideStringOrComment(textArea, curLine, cursorOffset)) { return; } } switch (ch) { case '>': if (IsInsideDocumentationComment(textArea, curLine, cursorOffset)) { curLineText = textArea.Document.GetText(curLine); int column = textArea.Caret.Offset - curLine.Offset; int index = Math.Min(column - 1, curLineText.Length - 1); while (index >= 0 && curLineText[index] != '<') { --index; if (curLineText[index] == '/') { return; // the tag was an end tag or already } } if (index > 0) { StringBuilder commentBuilder = new StringBuilder(""); for (int i = index; i < curLineText.Length && i < column && !Char.IsWhiteSpace(curLineText[i]); ++i) { commentBuilder.Append(curLineText[i]); } string tag = commentBuilder.ToString().Trim(); if (!tag.EndsWith(">")) { tag += ">"; } if (!tag.StartsWith("/")) { textArea.Document.Insert(textArea.Caret.Offset, "</" + tag.Substring(1)); } } } break; case ':': case ')': case ']': case '}': case '{': if (textArea.Document.TextEditorProperties.IndentStyle == IndentStyle.Smart) { textArea.Document.FormattingStrategy.IndentLine(textArea, lineNr); } break; case '\n': string lineAboveText = lineAbove == null ? "" : textArea.Document.GetText(lineAbove); //// curLine might have some text which should be added to indentation curLineText = ""; if (curLine.Length > 0) { curLineText = textArea.Document.GetText(curLine); } LineSegment nextLine = lineNr + 1 < textArea.Document.TotalNumberOfLines ? textArea.Document.GetLineSegment(lineNr + 1) : null; string nextLineText = lineNr + 1 < textArea.Document.TotalNumberOfLines ? textArea.Document.GetText(nextLine) : ""; int addCursorOffset = 0; if (lineAboveText.Trim().StartsWith("#region") && NeedEndregion(textArea.Document)) { textArea.Document.Insert(curLine.Offset, "#endregion"); textArea.Caret.Column = IndentLine(textArea, lineNr); return; } if (lineAbove.HighlightSpanStack != null && !lineAbove.HighlightSpanStack.IsEmpty) { if (!lineAbove.HighlightSpanStack.Peek().StopEOL) // case for /* style comments { int index = lineAboveText.IndexOf("/*"); if (index > 0) { StringBuilder indentation = new StringBuilder(GetIndentation(textArea, lineNr - 1)); for (int i = indentation.Length; i < index; ++i) { indentation.Append(' '); } //// adding curline text textArea.Document.Replace(curLine.Offset, curLine.Length, indentation.ToString() + " * " + curLineText); textArea.Caret.Column = indentation.Length + 3 + curLineText.Length; return; } index = lineAboveText.IndexOf("*"); if (index > 0) { StringBuilder indentation = new StringBuilder(GetIndentation(textArea, lineNr - 1)); for (int i = indentation.Length; i < index; ++i) { indentation.Append(' '); } //// adding curline if present textArea.Document.Replace(curLine.Offset, curLine.Length, indentation.ToString() + "* " + curLineText); textArea.Caret.Column = indentation.Length + 2 + curLineText.Length; return; } } else // don't handle // lines, because they're only one lined comments { int indexAbove = lineAboveText.IndexOf("///"); int indexNext = nextLineText.IndexOf("///"); if (indexAbove > 0 && (indexNext != -1 || indexAbove + 4 < lineAbove.Length)) { StringBuilder indentation = new StringBuilder(GetIndentation(textArea, lineNr - 1)); for (int i = indentation.Length; i < indexAbove; ++i) { indentation.Append(' '); } //// adding curline text if present textArea.Document.Replace(curLine.Offset, curLine.Length, indentation.ToString() + "/// " + curLineText); textArea.Caret.Column = indentation.Length + 4; return; } if (IsInNonVerbatimString(lineAboveText, curLineText)) { textArea.Document.Insert(lineAbove.Offset + lineAbove.Length, "\" +"); curLine = textArea.Document.GetLineSegment(lineNr); textArea.Document.Insert(curLine.Offset, "\""); addCursorOffset = 1; } } } int result = IndentLine(textArea, lineNr) + addCursorOffset; if (textArea.TextEditorProperties.AutoInsertCurlyBracket) { string oldLineText = TextUtilities.GetLineAsString(textArea.Document, lineNr - 1); if (oldLineText.EndsWith("{")) { if (NeedCurlyBracket(textArea.Document.TextContent)) { textArea.Document.Insert(curLine.Offset + curLine.Length, terminator + "}"); IndentLine(textArea, lineNr + 1); } } } textArea.Caret.Column = result; return; } }
protected override IEnumerable <ITextStorage> DoLoad() { PageManager manager = new PageManager(); string firstLineBreak = null; int cumulativeLineLength = 0; bool pendingNewline = false; int page = 0; while (true) { char[] buffer = new char[TextModelOptions.CompressedStoragePageSize]; int read = this.reader.ReadBlock(buffer, 0, buffer.Length); Debug.Assert(read >= 0); if (read == 0) { this.loadCompleted = true; yield break; } else { List <uint> lineBreaks = new List <uint>(); int c = 0; while (c < read) { int breakLength = TextUtilities.LengthOfLineBreak(buffer, c, read); if (breakLength == 0) { ++c; cumulativeLineLength++; } else { lineBreaks.Add(EncodedLineBreaks.EncodePosition(c, isSingleCharLineBreak: breakLength == 1)); // update information about consistent line endings and line lengths. // this is made complicated by the possibility that \r\n straddles a block boundary. // Todo: might as well handle issues of undecodable codes here instead of the // guessing that we currently do elsewhere. this.longestLineLength = Math.Max(this.longestLineLength, cumulativeLineLength); cumulativeLineLength = 0; if (pendingNewline) { // we've already done consistency checking for this newline, which was part of a // return-newline pair crossing a block boundary. Debug.Assert(c == 0 && buffer[0] == '\n', "Pending new line inconsistency"); pendingNewline = false; } else if (c == read - 1 && buffer[c] == '\r') { // we are on the last character of the block, but it might be the // first character in a two-character line break that crosses a block // boundary. We don't care about that for purposes of constructing the list // of line breaks, but we do care in the context of determining whether line // breaks are consistent. int peeky = this.reader.Peek(); if (peeky < 0) { // end of file. if (firstLineBreak != null && firstLineBreak != "\r") { this.hasConsistentLineEndings = false; } } else { char nextC = (char)peeky; if (nextC == '\n') { pendingNewline = true; if (firstLineBreak == null) { firstLineBreak = "\r\n"; } else if (firstLineBreak.Length != 2) { this.hasConsistentLineEndings = false; } // the line break list thinks this break has length one, and that is correct as // far as the current storage element is concerned, so we leave it alone. } else { if (firstLineBreak == null) { firstLineBreak = "\r"; } else if (firstLineBreak != "\r") { this.hasConsistentLineEndings = false; } } } } else if (firstLineBreak == null) { firstLineBreak = new string(buffer, c, breakLength); } else if (breakLength != firstLineBreak.Length) { this.hasConsistentLineEndings = false; } else if ((breakLength) == 1 && (firstLineBreak[0] != buffer[c])) { this.hasConsistentLineEndings = false; } c += breakLength; } } this.longestLineLength = Math.Max(this.longestLineLength, cumulativeLineLength); yield return(new CompressedTextStorage(manager, id + "-" + page.ToString(), buffer, read, lineBreaks, keepActive: page == 0)); page++; if (read < buffer.Length) { this.loadCompleted = true; yield break; } } } }