Discussion Forums Code Formatter

  • Monday, January 11, 2010 4:59 PM
     
      Has Code

    The follow code will format Visual Studio code for presentation in these forums.  Start a new Windows Forms Application and replace the code on Form1 with the code posted here.  The code should post as it is shown here.  Press "F5".  Copy some code from the IDE to the clipboard.  Press the "Paste RTF" button on the form and then the "Copy HTML" button.  Start a thread in the Sandbox forum and paste the code in the Body of the post.

    This is an initial stab at a formatter, which I feel is needed.  I can't decipher most posts containing code.  Any help improving this is welcome.

    using System;
    using System.Collections.Generic;
    using System.Drawing;
    using System.IO;
    using System.Windows.Forms;

    namespace ForumsCodeFormatter
    {
      
    public partial class Form1 : Form
      {
        
    MenuStrip MS = new MenuStrip();
        
    private ToolStripButton PasteRTF = new ToolStripButton();
        
    private ToolStripButton CopyHTML = new ToolStripButton();
        
    RichTextBox RTB = new RichTextBox();
        
    string DataFile = Application.StartupPath + "\\Data.txt";
        
    public Form1()
        {
          InitializeComponent();
          
    this.StartPosition = FormStartPosition.Manual;
          
    if (File.Exists(DataFile))
          {
            
    string[] Data = File.ReadAllText(DataFile).Split(',');
            
    this.Left = int.Parse(Data[0].Substring(3, Data[0].Length - 3));
            
    this.Top = int.Parse(Data[1].Substring(2, Data[1].Length - 2));
            
    this.Width = int.Parse(Data[2].Substring(6, Data[2].Length - 6));
            
    this.Height = int.Parse(Data[3].Substring(7, Data[3].Length - 8));
          }
          
    this.Text = "MSDN forums code formatter by johnwein";
          
    this.FormClosing += Form1_FormClosing;
          PasteRTF.Text = 
    "Paste RTF";
          CopyHTML.Text = 
    "Copy HTML";
          PasteRTF.Click += PasteRTF_Click;
          CopyHTML.Click += CopyHTML_Click;
          MS.Items.Add(PasteRTF);
          MS.Items.Add(CopyHTML);
          MS.Parent = 
    this;
          RTB.Parent = 
    this;
          RTB.Dock = 
    DockStyle.Fill;
          RTB.BringToFront();
        }
        
    private void PasteRTF_Click(object sender, EventArgs e)
        {
          RTB.Clear();
          RTB.Paste(
    DataFormats.GetFormat(DataFormats.Rtf));
        }
        
    private void CopyHTML_Click(object sender, EventArgs e)
        {
          
    Clipboard.Clear();
          
    RtfHtmlClass Conv = new RtfHtmlClass();
          
    Clipboard.SetData(DataFormats.Html, Conv.RtfToHtml(RTB.Rtf));
        }
        
    private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
          
    File.WriteAllText(DataFile, this.Bounds.ToString());
        }
      }

      
    public class RtfHtmlClass
      {
        
    StringReader SR;
        
    StringWriter SW;
        
    List<string> Clrtbl;
        
    public string RtfToHtml(string RtfIn)
        {
          SR = 
    new StringReader(RtfIn);
          SW = 
    new StringWriter();
          
    string S = GetColorTable();
          SW.Write(
    "<span><font size=\"3\" face=\"Courier new\">");
          
    do
          {
            WriteLine(S.ToCharArray());
            S = SR.ReadLine();
          } 
    while (!(S == null));
          SW.Write(
    "</font></span>");
          
    return SW.ToString();
        }
        
    public void WriteLine(char[] S)
        {
          
    int I = 0;
          
    int J = 0;
          
    if (S[0] == '}' & S.Length == 1) return;
          
    for (I = 0; I < S.Length; I++)
          {
            
    switch (S[I])
            {
              
    case '\\':
                
    switch (S[I + 1])
                {
                  
    case '{':
                  
    case '}':
                  
    case '\\':
                    I += 1;
                    SW.Write(S[I]);
                    
    break;
                  
    default:
                    I += 1;
                    
    for (J = I; J < S.Length; J++)
                      
    if (S[J] == ' ' | S[J] == '\\'break;
                    
    if (S[I] == 'c' && S[I + 1] == 'f') WriteColor(S[I + 2]);
                    I = J < S.Length ? S[J] == 
    ' ' ? J : J - 1 : J;
                    
    break;
                }
                
    break;
              
    case '<':
                SW.Write(
    "&lt;");
                
    break;
              
    case '>':
                SW.Write(
    "&gt;");
                
    break;
              
    case '&':
                SW.Write(
    "&amp;");
                
    break;
              
    case ' ':
                SW.Write(
    "&nbsp;");
                
    break;
              
    default:
                SW.Write(S[I]);
                
    break;
            }
          }
          SW.Write(
    "<br />");
        }
        
    private void WriteColor(char C)
        {
          
    int I = 0;
          I = 
    int.Parse(C.ToString()) - 1;
          
    if (I < 0)
          {
            SW.Write(
    "</span><span>");
          }
          
    else
          {
            SW.Write(
    "</span><span style=" + '"' + "Color: " + Clrtbl[I] + ';' + '"' + '>');
          }
        }
        
    public string GetColorTable()
        {
          
    int I, J;
          
    string C, S;
          
    string[] S1, S2;
          Clrtbl = 
    new List<string>();
          
    do
          {
            S = SR.ReadLine();
            
    if (S == nullreturn S;
            I = S.IndexOf(
    "{\\colortbl");
            
    if (I >= 0) break;
            I = S.IndexOf(
    "\\pard");
            
    if (I > 0) return S.Substring(I + 5);
          } 
    while (true);
          S1 = S.Substring(I, S.IndexOf(
    '}') - I).Split(';');
          
    int[] Clrs = { 3, 5, 4 }; //Length  of the colors
          for (I = 1; I < (S1.Length - 1); I++)
          {
            S2 = S1[I].Split(
    '\\');
            C = 
    "#";
            
    for (J = 1; J < 4; J++)
            {
              C += 
    Convert.ToString(int.Parse(S2[J].Substring(Clrs[J - 1])), 16).PadLeft(2, '0');
            }
            Clrtbl.Add(C);
          }
          
    do
          {
            I = S.IndexOf(
    "\\pard");
            
    if (I > 0)
              
    return S.Substring(I + 5);
            S = SR.ReadLine();
          } 
    while (!(S == null));
          
    return S;
        }
      }
    }

    Similar post containing VB code here

All Replies

  • Monday, January 11, 2010 5:11 PM
     
     
    Can we make this a sticky?
    John Grove - TFD Group, Senior Software Engineer, EI Division, http://www.tfdg.com
  • Monday, January 11, 2010 5:17 PM
    Moderator
     
     
    Discussion Thread
    Mark the best replies as answers. "Fooling computers since 1971."
  • Monday, January 11, 2010 5:31 PM
    Moderator
     
      Has Code
    Hi John,

    I created a Winforms project. After changing the namespace for the form code and its codebehind it compiled and ran. But I wasn't able to get a final output. I did Paste, and saw the code in the box. But when I did Copy HTML the clipboard did not contain any data. Not even the original text.

    ???


    My bad...here is the code I used:

    string data = @"
    CHLORPHENIRAMINE 8MG CAP SA,
    CHLORPHENIRAMINE 12MG CP SA, 
    CHLORPHENIRAMINE 4MG TABLET, 
    CLEMASTINE FUM 2.68MG TAB, 
    CLEMASTINE 0.67MG/5ML SYRUP, 
    CLEMASTINE FUM 1.34MG TAB, 
    CYPROHEPTADINE 4MG TABLET, 
    CYPROHEPTADINE 2MG/5ML SYRUP, 
    DIPHENHYDRAMINE 50MG/ML SYN, 
    DIPHENHYDRAMINE(ELIXIR), 
    GENAHIST(LIQUID), 
    HYDRAMINE(ELIXIR), 
    Q-DRYL 12.5MG/5ML LIQUID, 
    ALLERGY 2% CREAM, 
    BANOPHEN ALLERGY LIQUID, 
    BANOPHEN 12.5MG/5ML ELIXIR, 
    DIPHENHYDRAMINE 25MG CAPS, 
    DIPHENHYDRAMINE 25MG CAP, 
    DIPHENHYDRAMINE 25MG CAPLET, 
    DIPHENHYDRAMINE 50MG CAPS";
    
    string pattern = @"
    ^(?<Drug>[^\s,]+\s?(?!\d|,)[^\s,]*) # This
     \s?                                # pound signs
     (?<Dosage>[^\s,]+)?                # should be
    \s?                                 # aligned
    (?<Form>[^\s,]+)?
    \s?
    (?<Release>[^\s,]+)?";
    
    
    var drugs = from Match m in Regex.Matches( data, pattern, RegexOptions.IgnorePatternWhitespace | RegexOptions.Multiline )
                select new
                {
                    Name    = m.Groups["Drug"].Value,
                    Dosage  = m.Groups["Dosage"].Value ?? string.Empty,
                    Form    = m.Groups["Form"].Value ?? string.Empty,
                    Release = m.Groups["Release"].Value ?? string.Empty
                };
    
    
    foreach ( var drg in drugs )
        Console.WriteLine( "{0,-30} {1,-10} {2,-10} {3}", drg.Name, drg.Dosage, drg.Form, drg.Release );
    /* Output:
    CHLORPHENIRAMINE               8MG        CAP        SA
    CHLORPHENIRAMINE               12MG       CP         SA
    CHLORPHENIRAMINE               4MG        TABLET
    CLEMASTINE FUM                 2.68MG     TAB
    CLEMASTINE                     0.67MG/5ML SYRUP
    CLEMASTINE FUM                 1.34MG     TAB
    CYPROHEPTADINE                 4MG        TABLET
    CYPROHEPTADINE                 2MG/5ML    SYRUP
    DIPHENHYDRAMINE                50MG/ML    SYN
    DIPHENHYDRAMINE(ELIXIR)
    GENAHIST(LIQUID)
    HYDRAMINE(ELIXIR)
    Q-DRYL                         12.5MG/5ML LIQUID
    ALLERGY                        2%         CREAM
    BANOPHEN ALLERGY               LIQUID
    BANOPHEN                       12.5MG/5ML ELIXIR
    DIPHENHYDRAMINE                25MG       CAPS
    DIPHENHYDRAMINE                25MG       CAP
    DIPHENHYDRAMINE                25MG       CAPLET
    DIPHENHYDRAMINE                50MG       CAPS
     * */
    HTH

    William Wegerson (www.OmegaCoder.Com )
  • Monday, January 11, 2010 6:08 PM
     
     
    I copied your code into the form load event of a new Windows Forms application and  then copied the code from there into the clipboard and the code formatter.  This is the result of copying from  the code formatter:

        private void Form1_Load(object sender, EventArgs e)
        {
          
    string data = @"
    CHLORPHENIRAMINE 8MG CAP SA,
    CHLORPHENIRAMINE 12MG CP SA, 
    CHLORPHENIRAMINE 4MG TABLET, 
    CLEMASTINE FUM 2.68MG TAB, 
    CLEMASTINE 0.67MG/5ML SYRUP, 
    CLEMASTINE FUM 1.34MG TAB, 
    CYPROHEPTADINE 4MG TABLET, 
    CYPROHEPTADINE 2MG/5ML SYRUP, 
    DIPHENHYDRAMINE 50MG/ML SYN, 
    DIPHENHYDRAMINE(ELIXIR), 
    GENAHIST(LIQUID), 
    HYDRAMINE(ELIXIR), 
    Q-DRYL 12.5MG/5ML LIQUID, 
    ALLERGY 2% CREAM, 
    BANOPHEN ALLERGY LIQUID, 
    BANOPHEN 12.5MG/5ML ELIXIR, 
    DIPHENHYDRAMINE 25MG CAPS, 
    DIPHENHYDRAMINE 25MG CAP, 
    DIPHENHYDRAMINE 25MG CAPLET, 
    DIPHENHYDRAMINE 50MG CAPS"
    ;

          
    string pattern = @"
    ^(?<Drug>[^\s,]+\s?(?!\d|,)[^\s,]*) # This
     \s?                                # pound signs
     (?<Dosage>[^\s,]+)?                # should be
    \s?                                 # aligned
    (?<Form>[^\s,]+)?
    \s?
    (?<Release>[^\s,]+)?"
    ;


          
    var drugs = from Match m in Regex.Matches(data, pattern, RegexOptions.IgnorePatternWhitespace | RegexOptions.Multiline)
                      
    select new
                      {
                        Name = m.Groups[
    "Drug"].Value,
                        Dosage = m.Groups[
    "Dosage"].Value ?? string.Empty,
                        Form = m.Groups[
    "Form"].Value ?? string.Empty,
                        Release = m.Groups[
    "Release"].Value ?? string.Empty
                      };


          
    foreach (var drg in drugs)
            
    Console.WriteLine("{0,-30} {1,-10} {2,-10} {3}", drg.Name, drg.Dosage, drg.Form, drg.Release);
          
    /* Output:
          CHLORPHENIRAMINE               8MG        CAP        SA
          CHLORPHENIRAMINE               12MG       CP         SA
          CHLORPHENIRAMINE               4MG        TABLET
          CLEMASTINE FUM                 2.68MG     TAB
          CLEMASTINE                     0.67MG/5ML SYRUP
          CLEMASTINE FUM                 1.34MG     TAB
          CYPROHEPTADINE                 4MG        TABLET
          CYPROHEPTADINE                 2MG/5ML    SYRUP
          DIPHENHYDRAMINE                50MG/ML    SYN
          DIPHENHYDRAMINE(ELIXIR)
          GENAHIST(LIQUID)
          HYDRAMINE(ELIXIR)
          Q-DRYL                         12.5MG/5ML LIQUID
          ALLERGY                        2%         CREAM
          BANOPHEN ALLERGY               LIQUID
          BANOPHEN                       12.5MG/5ML ELIXIR
          DIPHENHYDRAMINE                25MG       CAPS
          DIPHENHYDRAMINE                25MG       CAP
          DIPHENHYDRAMINE                25MG       CAPLET
          DIPHENHYDRAMINE                50MG       CAPS
           * */
        }

  • Monday, January 11, 2010 6:21 PM
    Moderator
     
      Has Code
    I edited your code put a break point in the middle

    private void CopyHTML_Click( object sender, EventArgs e )
    {
        Clipboard.Clear();
        RtfHtmlClass Conv = new RtfHtmlClass();
    
        string html = Conv.RtfToHtml( RTB.Rtf );
        Clipboard.SetData( DataFormats.Html, html );
    }
     The value html is being set and shows:

    <span><font size="2" face="Courier new"></span><span style="Color: #00ff00;">RTB.Clear();</span><span><br /></font></span>
    
    but once Clipboard.SetData is called...my clipboard doesn't have the html.

    I am running, at work XP64 and built with VS2008 SP1.

    HTH
    William Wegerson (www.OmegaCoder.Com)
  • Monday, January 11, 2010 6:57 PM
     
     
    This is what I get for html: Html = "<span><font size=\"2\" face=\"Courier new\">RTB.Clear();<br /></font></span>" and the clipboard paste here is:  RTB.Clear();

    Oh!  I'm targeting x86.  Been doing a lot of edit and continue on this.  I'll check Any Cpu.

    Html = "<span><span style=\"font-family:Courier new;font-size:x-medium\">RTB.Clear();<br /></span></span>"

    and

    RTB.Clear();

    Don't know why the Clipboard.SetData statement wouldn't be executed on your system.
  • Monday, January 11, 2010 7:50 PM
    Moderator
     
     
    Here is what I changed to get it to work (using your tool):

      Clipboard .SetDataObject( html,  true  );


    Note...for the tool to be useful, for me, I have a dark background with, as you can see whacked colors which don't work on white background , could you strip out the coloring, or have default coloring regardless of what comes in?

    Thx....

    William Wegerson (www.OmegaCoder.Com)
  • Monday, January 11, 2010 9:55 PM
     
     
    Here is what I changed to get it to work (using your tool):

      Clipboard .SetDataObject( html,  true  );


    Note...for the tool to be useful, for me, I have a dark background with, as you can see whacked colors which don't work on white background , could you strip out the coloring, or have default coloring regardless of what comes in?

    Thx....

    Have something to do with compact framework?  I'll change it since it's more comprehensive. 

    I want to keep this as simple as possible.  You can modify the "GetColorTable" code to map the "ClrTbl" list to your colors, but I don't want to add an option button.  The code is not directed at the responders to this thread, who post perfectly readable code.  It's for the use of those who post totally mangled, unreadable code.

  • Monday, February 22, 2010 9:16 PM
    Moderator
     
     
    I'd love to see this up on CodePlex as a Visual Studio add-in. 
    Coding Light - Illuminated Ideas and Algorithms in Software
    Coding Light WikiLinkedInForumsBrowser
  • Monday, February 22, 2010 11:23 PM
     
     
    I'd love to see this up on CodePlex as a Visual Studio add-in. 
    Coding Light - Illuminated Ideas and Algorithms in Software
    Coding Light WikiLinkedInForumsBrowser

    I'll cross post these posts:  Forums Code Formatter  http://social.msdn.microsoft.com/Forums/en-US/vbgeneral/thread/bf977a14-d9d4-4e84-9784-bf76b9e23261
  • Tuesday, February 23, 2010 5:09 PM
     
     
    Why don't you upload it to:

    http://skydrive.live.com/

    That way users can just grab it.

    Or upload it to CodeProject.

    John Grove - TFD Group, Senior Software Engineer, EI Division, http://www.tfdg.com
  • Tuesday, February 23, 2010 5:59 PM
     
     
    Why don't you upload it to:

    http://skydrive.live.com/

    That way users can just grab it.

    Or upload it to CodeProject.

    John Grove - TFD Group, Senior Software Engineer, EI Division, http://www.tfdg.com
    To whom is this addressed?  I cross posted so Heslacher, who made the IDE plug-in, is aware of the desires of responders to this thread.
  • Tuesday, February 23, 2010 6:17 PM
     
     
    Ok, thanks John

    John Grove - TFD Group, Senior Software Engineer, EI Division, http://www.tfdg.com
  • Tuesday, February 23, 2010 6:51 PM
    Moderator
     
     
    This post has become unwieldy...I have created a new sticky post: Forums Code Addin Alternative to Insert Code Block. Which references all three of your posts John.

    William Wegerson (www.OmegaCoder.Com)
  • Tuesday, February 23, 2010 7:17 PM
     
     
    This post has become unwieldy...I have created a new sticky post: Forums Code Addin Alternative to Insert Code Block. Which references all three of your posts John.

    William Wegerson (www.OmegaCoder.Com)

    Thanks!

    A sticky post on the Visual Basic forum would be nice.  Heslacher has put a lot of effort into this.  He has basically taken the ball and run with it.  I'll let him decide what and where he want's to post.  I'd like to see less and less of the unformatted code that led me to write this code, but it doesn't seem to be happening. 
  • Tuesday, February 23, 2010 7:32 PM
    Moderator
     
     
    I updated the text to give Heslacher credit for creating the addin based on your code. I also made a sticky in the VB general forum with the same text.

    Forums Code Addin Alternative to Insert Code Block
    William Wegerson (www.OmegaCoder.Com)