goblinfactory / konsole

Home of the simple console library consisting of ProgressBar, Window, Form, Draw & MockConsole (C# console progress bar with support for single or multithreaded progress updates) Window is a 100%-ish console compatible window, supporting all normal console writing to a windowed section of the screen, supporting scrolling and clipping of console output.
719 stars 62 forks source link

Add BBCode support #56

Closed Tr0sT closed 4 years ago

Tr0sT commented 4 years ago

I use this extention to do colourfull output. I think it will be not bad to add full BBCode support (if it's possible) to console output.

    public static void WriteLineBBCode(this IConsole console, string line)
    {
        var exp = new Regex(@"\[color\=([^\]]+)\]([^\]]+)\[\/color\]");
        var matches = exp.Matches(line);
        foreach (Match match in matches)
        {
            Enum.TryParse(match.Groups[1].Value, true, out ConsoleColor consoleColor);
            console.Write(consoleColor, match.Groups[2].Value);
        }
        console.WriteLine("");
    }
goblinfactory commented 4 years ago

nice :D That sounds like fun, I'll take a look at it. Is that the total implementation or is there more? I'll probably not add it to the IConsole interface, then everyone that implements it will need to do it, but will create an extension method and put this in an extensions namespace,

For example ... something like

namespace Konsole.Extensions.BBCode;

public static class BBCodeExtensions
{
    public static void WriteLineBBCode(this IConsole console, string line)
    {
        var exp = new Regex(@"\[color\=([^\]]+)\]([^\]]+)\[\/color\]");
        var matches = exp.Matches(line);
        foreach (Match match in matches)
        {
            Enum.TryParse(match.Groups[1].Value, true, out ConsoleColor consoleColor);
            console.Write(consoleColor, match.Groups[2].Value);
        }
        console.WriteLine("");
    }
}

mmm, just thinking... perhaps even cleaner might be a simple BBCode writer implementing IWrite,

namespace Konsole.Extensions.BBCode;

public  class BBCodeWriter : IWrite
{
  public BBCodeWriter(IConsole console) { 
 ...
}
    public static void WriteLine(string line)
    {
        var exp = new Regex(@"\[color\=([^\]]+)\]([^\]]+)\[\/color\]");
        var matches = exp.Matches(line);
        foreach (Match match in matches)
        {
            Enum.TryParse(match.Groups[1].Value, true, out ConsoleColor consoleColor);
            _writeLine(consoleColor, match.Groups[2].Value);
        }
    }
}

the downside of a separate writer for BBCode, is that you'd have to keep track of which one to use each time, so might be code look untidy e.g.

  var bbCode = new BBCodeWriter(console);
   console.WriteLine($"User : {user.Name}");
   foreach(var msg in user. Logs) bbCode.WriteLine(msg);

vs

  using Konsole.Extensions.BBCode;
 ... 
  console.WriteLine($"User : {user.Name}");
   foreach(var msg in user. Logs) console. WriteLineBBCode(msg);

after writing the code above, I prefer the second option, i.e. as you described it originally, but you import it by including the extension method namespace.

Tr0sT commented 4 years ago

That's all I have for BBCode for now. And even it has very limited use. For example it does not write text without color tag. So "abc[color=red]efg[/color] will output only "efg". So I use "[color=white]abc[/color][color=red]efg[/color]" which is longer but works. Implementing IWrite looks cleaner, but what to do if I want to use HighSpeedWriter and BBCodeWriter at the same time?..

goblinfactory commented 4 years ago

re: HighSpeedWriter all of the methods above are compatible with highspeed writer :D just remember to call flush.

Tr0sT commented 4 years ago

Maybe good WriteLine signature would be void WriteLine(string line, Style style = null); where

public class Style { public bool UseBBCode = true; // another style settings like font, size, etc. Don't know if it's possible with console }

goblinfactory commented 4 years ago

Maybe good WriteLine signature would be void WriteLine(string line, Style style = null); where

public class Style { public bool UseBBCode = true; // another style settings like font, size, etc. Don't know if it's possible with console }

you can always write that yourself in your own private extension method. I can't add that to Konsole because that will then become part of the contract and everyone implementing IConsole would have to implement that. Or worse, two different programs passing an IConsole between them may not actually be sharing or swapping compatible IConsole references.

Write your own extensions methods

public static class MyExtensions
{
public static MyWriteXYZ(this IConsole console, MySettings settings) { 
...
}

your settings can have a style property if you want. the sky is the limit

goblinfactory commented 4 years ago

That's all I have for BBCode for now. And even it has very limited use. For example it does not write text without color tag. So "abc[color=red]efg[/color] will output only "efg". So I use "[color=white]abc[/color][color=red]efg[/color]" which is longer but works. Implementing IWrite looks cleaner, but what to do if I want to use HighSpeedWriter and BBCodeWriter at the same time?..

perhaps you can do something like

// pseudo code

  var remaining = text;
   public static void WriteLineBBCode(this Iconsole console, string text) 

     lock(Window.StaticLocker)
     {
        var before = console.Colors;

        try
        {
            while(remaining.Length > 1) {
                int nextTag = GetNextTagStartPosition();
                if(nextTag == 0) return;
                console.Write(remaining.Sub(0, nextTag)); // will print in the current color, e.g. White
                remaining = remaining.Sub(nextTag);
                // the next text in 'remaining' is a tag
                remaining = SetColorFromTagReturnRemainingWithoutTag();
            }

        } finally
        {
            // reset the consor color after printing BBC in case it's badly formatted and a missing closing tag
            // and in case of exception, keep colors correct.
            console.Colors = before;
        }

     }

    });

  private static string SetColorFromTagReturnRemainingWithoutTag(IConsole console) { 
  .. .your regex here to pick up next tag
 }
goblinfactory commented 4 years ago

After reading a bit more on wikipedia on BBCode it looks like BBCode is a type of markdown that is best suited for pages that are rendered on a web page. e.g. embedding links etc. An older type of Markdown. Most of the BBCode features (other than foreground and background color, won't be a able to be implemented in a text console. )

Font , size, underline, italic etc, all wont work.

So as it stands, you should write your own extension class, this doesn't look like something we can add to be part of the main Konsole package.

I'm happy to keep the conversation going if you want to discuss/ explore this more? Cheers, Alan

Tr0sT commented 4 years ago

No, it's ok, i'm closing the issue if bold/italic etc wont work

goblinfactory commented 4 years ago

No, it's ok, i'm closing the issue if bold/italic etc wont work

Unfortunately only 1 font style per console at a time, and it needs to be a fixedWidth font for obvious reasons. No italic, and no underline.

you can easily set colors. If you're allowed to create your own BBCode for yourself or your users, then you can very quickly implement something for setting foreground and background colors, which won't be complcated. e.g.

simple rules, capital = background. [/] means reset back to original console foreground color, [//] means reset back to original background color.

goblinfactory commented 4 years ago

and [///] resets both foreground and background color to default. e.g. I am white on black [WHITE][red]I am red on white background [///] I am now white on black again. (default)