C# RichTextBox Line-by-line scan - c#

Hey Im creating my own coding language and I already have the entire application set up with save, open, close, new, etc.
In order for the "Run" part to work, I need a way to scan and test every single line in richTextBox1.
Maybe for past Java users, something along the lines of the "java-util-scanner," but easier to use for testing each line.
Does anyone know a way to do this, where a string "scannedString" would be tested as so:
if(scannedString == "#load(moduleFiles)") {
//action here
}
string scannedStringNextLine = ???
if(scannedStringNextLine = "") {
//action here
}
Eventually it would look more like this:
if(scannedString == "code1" || scannedString == "code2" etc... ) {
if(scannedString == "code1") {
//action here
}
} else {
//error message
}
hope this is enough information...

To get lines of code of the RichTextBox you can split the content by a new line symbol:
var lines = this.richTextBox.Text.Split('\n').ToList();
The lines are in order of appearance. Then you can go through lines in a for or foreach loop:
foreach (var line in lines)
{
// access a line, evaluate it, etc.
}

One way to do it is to split the text on the newline charaters and then parse each line for the text you care about:
private void btnScan_Click(object sender, EventArgs e)
{
var code = richTextBox1.Text;
foreach (var line in code.Split(new []{'\n','\r'},
StringSplitOptions.RemoveEmptyEntries))
{
CheckForLoad(line);
}
}
void CheckForLoad(string line)
{
if (string.IsNullOrWhiteSpace(line)) return;
int i = line.IndexOf("#load");
if (i < 0) return;
int openParen = line.IndexOf("(", i + 1);
if (openParen < 0) return;
int closeParen = line.IndexOf(")", openParen + 1);
if (closeParen < 0) return;
string modules = line.Substring(openParen + 1, closeParen - openParen - 1);
MessageBox.Show(string.Format("Loading modules: {0}", modules));
}

Related

While loop to read different lines from richtextbox

I'm trying to make a simple turtle program where you can type in multiple lines of code to draw on a PictureBox. The code is there for the graphics, but I'm struggling with the loops and getting it to read the next line of the string. I know it's going to be something stupidly simple but I've been trying for hours to no avail. I've added the first part of the code cos I'm certain that's where the problem is. I think I've made it way too complicated for myself.
It's reading from a rich text box and I'm trying to read it line by line but split those lines each time. So if something like this is inputted:
square 50
drawto 100,100
moveto 200,200
square 100
So far, when the button is clicked, it runs the first line, but I want it to go through each line and perform each action. I know my naming conventions aren't the best
private void buttonRun_Click(object sender, EventArgs e) //what happens when run is clicked - main part of code
{
Console.WriteLine("RUN PROGRAM");
int lineno = 0;
string Commandc1 = ProgramCommandWindow.Text.Trim().ToLower();
StringReader strReader = new StringReader(Commandc1);
string[] textlines = Commandc1.Split(new[] { Environment.NewLine }, StringSplitOptions.None);
while (true)
{
textlines[lineno] = strReader.ReadLine(); //reads line of text
while (textlines[lineno] != null)
{
//Commandc1 = strReader.ReadLine();
string[] Commandc = textlines[lineno].Split(' ', ',');
while (Commandc[0].Equals("moveto") == true)
{
if (!Int32.TryParse(Commandc[+1], out positionx)) ; //translate string to int
if (!Int32.TryParse(Commandc[+2], out positiony)) ;
Picturebox.xPos = positionx;
Picturebox.yPos = positiony;
//Commandc1 = strReader.ReadLine();
Refresh();//refresh display
lineno++;
}
while (Commandc[0].Equals("drawto") == true) //what happens if draw line command is used
{
if (!Int32.TryParse(Commandc[+1], out positionx)) ; //translate string to int
if (!Int32.TryParse(Commandc[+2], out positiony)) ;
Picturebox.toX = positionx;
Picturebox.toY = positiony;
MyOutputWindow.DrawLine(Picturebox.toX, Picturebox.toY);
Console.WriteLine("COMMAND - DRAW LINE");
//Commandc1 = strReader.ReadLine();
Refresh();//refresh display
lineno++;
}
while (Commandc[0].Equals("square") == true) //what happens if draw square command is used
{
if (!Int32.TryParse(Commandc[+1], out positionshape)) ; //translate string to int
Picturebox.sizes = positionshape;
MyOutputWindow.DrawSquare(Picturebox.sizes);
Console.WriteLine("COMMAND - DRAW SQUARE");
//Commandc1 = strReader.ReadLine();
Refresh();//refresh display
lineno++;
}
break;
}
//else while (Commandc1 == "end")
//{
// break;
//}
Refresh();//refresh display
break;
}
}

Check if a String contains something between quotes

I am writing I application where the user can input a document. Then I read each line of the Document and work further with the attributes.
In Each line we have 5 attributes. The Attributes get separated by a semicolon.
For Example:
If a Attribute have a semicolo in his name the user will input the attribute then so in the Document:
"test;with"
Now I want to check if the attribute is in quotes and ignore it. How would you guys do it?
Here is the important code snippet:
foreach (string line in lines)
{
if (line == "")
{
continue;
}
if (lineindex > lines.Length)
{
continue;
}
lineindex++;
string[] words = line.Split(';'); // i would add here a if statement
foreach (string word in words)
{
count++;
if (count == 6)
{
attribNewValue = "";
maskName = "";
actualAttrbValue = "";
actualAttrbName = "";
attribNameForEdit = "";
count = 1;
maskexist = false;
attribexist = false;
}
else
{
// Or here to each word
if (count == 1)
{
maskName = word;
}
else if (count == 2)
{
actualAttrbName = word;
}
else if (count == 3)
{
actualAttrbValue = word;
}
else if (count == 4)
{
attribNameForEdit = word;
}
else if (count == 5)
{
attribNewValue = word;
}
}
Thank you in advance!
You can use String.IndexOf(char value) and String.LastIndexOf(char value) to determine this:
string[] words;
int semicolonIndex = line.IndexOf(';');
int firstQuoteIndex = line.IndexOf('"');
int lastQuoteIndex = line.LastIndexOf('"');
if (firstQuoteIndex == lastQuoteIndex)
continue;
if (semicolonIndex > firstQuoteIndex && semicolonIndex < lastQuoteIndex)
words = line.Split(';');
More information:
IndexOf(): https://msdn.microsoft.com/en-us/library/system.string.indexof(v=vs.110).aspx
LastIndexOf(): https://msdn.microsoft.com/en-us/library/system.string.lastindexof(v=vs.110).aspx
As one of the comments mentioned, this can also be achieved with regular expressions in far fewer lines of code than my solution, but gauging your skill level (no offense) I think this is easier for you to read, understand, and get started with. Regardless of whether or not there is a more elegant solution, string manipulation is a pretty basic things and it would be good to familiarize yourself with all of the methods on the String class as found here: https://msdn.microsoft.com/en-us/library/system.string_methods(v=vs.110).aspx
Lastly, while this is purely developer-preference, I would recommend using String.Empty instead of "". This makes your code's intentions more explicit to other readers / developers. By using "", one might ask "Well did they MEAN to use an empty string, or did they make a typo and aren't assigning what they think they're assigning?" By using String.Empty, there is no question that you meant to use an empty string. So I would do if (line == String.Empty) continue; instead of if (line == "") continue;

LINQ instead of for loop in wpf?

I am working with the WPF RichTextbox. I have to get all the lines in the RichTextbox. So I am using a for loop to get all the lines, but the RichTextbox contains a large text content. It takes too much time.
So how do I get around a 1000 line loop in less time?
I've tried parallel.for but it gives an exception as it tries to get each line of the RichTextbox text.
Here is my code.
for (Int32 icnt = 0; icnt <= iLineCount; icnt++)
{
LineDetails lnDtls = new LineDetails();
lnDtls.LineText = GetLineText(txtAppendValue.CaretPosition.GetLineStartPosition(icnt));
iCurrentEnd = iCurrentEnd + lnDtls.LineText.Length;
lnDtls.LineLength = iCurrentEnd;
listLines.Add(lnDtls);
}
GetLineText():
String GetLineText(TextPointer TextPointer)
{
tp1 = TextPointer.GetLineStartPosition(0);
if (tp1 == null)
{
return null;
}
else
{
tpNextLine2 = tp1.GetLineStartPosition(1);
if (tr != null)
{
tr = null;
}
if (tpNextLine2 == null)
{
tpNextLine2 = txtAppendValue.Document.ContentEnd;
}
tr = new TextRange(tp1, tpNextLine2);
return tr.Text;
}
}
So can I use LINQ instead of for loop for fast execution?
I don't see why it needs to be this complicated. A few simple line of code would give you all the lines in a rich text box.
string text = new TextRange(richTextBox.Document.ContentStart, richTextBox.Document.ContentEnd).Text;
text.Replace("\r\n", "\n");
var lines = text.Split(new char[] {'\n'});

Format C# code with indents programmatically

I'm making a C# application including a RichTextBox in which the user will be able to put some C# code in it and format it by indents like what Visual Studio does.
private void btnEdit_Click(object sender, EventArgs e)
{
//rchCode.Text= formattedCode; // Which I haven't got anywhere so far
}
I looked for the same questions and this answer suggests using something called NArrange, but I don't want use other tools, add-ins or such.
Also this one offering the CodeDOM way which I haven't figure it out how to use it (If it's helpful in anyway)
I want to do it by writing some actual code. How can I do it?
To properly indent code you would need Microsoft.CodeAnalysis.CSharp nuget package and .NET framework 4.6+. Sample code:
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
...
public string ArrangeUsingRoslyn(string csCode) {
var tree = CSharpSyntaxTree.ParseText(csCode);
var root = tree.GetRoot().NormalizeWhitespace();
var ret = root.ToFullString();
return ret;
}
One-liner:
csCode = CSharpSyntaxTree.ParseText(csCode).GetRoot().NormalizeWhitespace().ToFullString();
You may also use NArrange to sort methods in your cs file, organize usings, create regions, etc.
So I got the solution this way:
It's not still perfect (as it always add one or more new lines before the first code line). So if anyone can improve it or has a better way to do it, I'll appreciate any new suggestions.
private void btnEdit_Click(object sender, EventArgs e)
{
RichTextBox rchTemp = new RichTextBox();
foreach (string line in rchCode.Lines)
{
rchTemp.AppendText("\r\n" + line.Trim());
}
RichTextBox rchTemp2 = new RichTextBox();
int indentCount = 0;
bool shouldIndent = false;
foreach (string line in rchTemp.Lines)
{
if (shouldIndent)
indentCount++;
if (line.Contains("}"))
indentCount--;
if (indentCount == 0)
{
rchTemp2.AppendText("\r\n" + line);
shouldIndent = line.Contains("{");
continue;
}
string blankSpace = string.Empty;
for (int i = 0; i < indentCount; i++)
{
blankSpace += " ";
}
rchTemp2.AppendText("\r\n" + blankSpace + line);
shouldIndent = line.Contains("{");
}
rchCode.Text = rchTemp2.Text;
}
public static string FormatCode(string code)
{
var lines = code.Split('\n').Select(s => s.Trim());
var strBuilder = new StringBuilder();
int indentCount = 0;
bool shouldIndent = false;
foreach (string line in lines)
{
if (shouldIndent)
indentCount++;
if (line.Trim() == "}")
indentCount--;
if (indentCount == 0)
{
strBuilder.AppendLine(line);
shouldIndent = line.Contains("{");
continue;
}
string blankSpace = string.Empty;
for (int i = 0; i < indentCount; i++)
{
blankSpace += " ";
}
if (line.Contains("}") && line.Trim() != "}")
indentCount--;
strBuilder.AppendLine(blankSpace + line);
shouldIndent = line.Contains("{");
}
return strBuilder.ToString();
}
Little improvement on answer on top
if line public string Foo { get; set; } correct indent.

c# search string in txt file

I want to find a string in a txt file if string compares, it should go on reading lines till another string which I'm using as parameter.
Example:
CustomerEN //search for this string
...
some text which has details about the customer
id "123456"
username "rootuser"
...
CustomerCh //get text till this string
I need the details to work with them otherwise.
I'm using linq to search for "CustomerEN" like this:
File.ReadLines(pathToTextFile).Any(line => line.Contains("CustomerEN"))
But now I'm stuck with reading lines (data) till "CustomerCh" to extract details.
If your pair of lines will only appear once in your file, you could use
File.ReadLines(pathToTextFile)
.SkipWhile(line => !line.Contains("CustomerEN"))
.Skip(1) // optional
.TakeWhile(line => !line.Contains("CustomerCh"));
If you could have multiple occurrences in one file, you're probably better off using a regular foreach loop - reading lines, keeping track of whether you're currently inside or outside a customer etc:
List<List<string>> groups = new List<List<string>>();
List<string> current = null;
foreach (var line in File.ReadAllLines(pathToFile))
{
if (line.Contains("CustomerEN") && current == null)
current = new List<string>();
else if (line.Contains("CustomerCh") && current != null)
{
groups.Add(current);
current = null;
}
if (current != null)
current.Add(line);
}
You have to use while since foreach does not know about index. Below is an example code.
int counter = 0;
string line;
Console.Write("Input your search text: ");
var text = Console.ReadLine();
System.IO.StreamReader file =
new System.IO.StreamReader("SampleInput1.txt");
while ((line = file.ReadLine()) != null)
{
if (line.Contains(text))
{
break;
}
counter++;
}
Console.WriteLine("Line number: {0}", counter);
file.Close();
Console.ReadLine();
With LINQ, you could use the SkipWhile / TakeWhile methods, like this:
var importantLines =
File.ReadLines(pathToTextFile)
.SkipWhile(line => !line.Contains("CustomerEN"))
.TakeWhile(line => !line.Contains("CustomerCh"));
If you whant only one first string, you can use simple for-loop.
var lines = File.ReadAllLines(pathToTextFile);
var firstFound = false;
for(int index = 0; index < lines.Count; index++)
{
if(!firstFound && lines[index].Contains("CustomerEN"))
{
firstFound = true;
}
if(firstFound && lines[index].Contains("CustomerCh"))
{
//do, what you want, and exit the loop
// return lines[index];
}
}
I worked a little bit the method that Rawling posted here to find more than one line in the same file until the end. This is what worked for me:
foreach (var line in File.ReadLines(pathToFile))
{
if (line.Contains("CustomerEN") && current == null)
{
current = new List<string>();
current.Add(line);
}
else if (line.Contains("CustomerEN") && current != null)
{
current.Add(line);
}
}
string s = String.Join(",", current);
MessageBox.Show(s);

Categories

Resources