Sunday, February 21, 2010

Add C# Code Formatter Widget To Your Blog

This widget formats all the C# code in your blog so it looks exactly like in Visual Studio.
It supports all the cases of string literals, comments, keywords and preprocessors. It has a huge list of all commonly used types, and it has some capability of learning new types (classes, enums, interfaces, structs) from your code.
Try it now online! - OR - Add it to your blog:
Note: the widget is for lazy people like me, if you want you can add the formatting script to your HTML Layout manually.

Here is a simple example:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace exp1
{
    class Program
    {
        public static void Main(string[] args)
        {
            Console.WriteLine("Hello, world!");
        }
    }
}

This is what the author sees when writing the post:
<pre formatcs="1">using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace exp1
{
    class Program
    {
        public static void Main(string[] args)
        {
            Console.WriteLine("Hello, world!");
        }
    }
}</pre>

So how does it work?
The script scans the page looking for <pre> elements with the attribute formatcs=1. Each element is then formatted as C# code.
The <pre> tag was chosen for a reason - if the user doesn't have JavaScript supported, then the <pre> tag is the best way to show code in a blog.

Here is a more advanced example:
[XmlRoot("Node")]
class MyNode<T> : MyBaseClass<T>
    where T : Dictionary<List<T>, int>, ISerializable
{
    MyNode MyNode = new SuperNode();
    
    /// <summary>   *
    /// comment2... *
    /// </summary>  *
    MyType1 foo(out MyType2 x)
    {
        x = MyType1.StaticFunction(@"c:\");
        Console.WriteLine(" aaaa \" \\\" \\\\");
        return new T();
    }
}
Note that these classes are being deduced by reading the code: MyNode, MyBaseClass, SuperNode, MyType1, MyType2.
Note that "T" is not styled as a type, exactly as in Visual Studio.

OK OK! I'm convinced! How do I add this widget to my blog?
Simply by clicking here:
- Or - You can use the online version here:
formatmycsharpcode.blogspot.com

For more information refer to this wiki page.

Saturday, February 20, 2010

Use JavaScript to Format C# Code to HTML

To format C# code online go here.
To add it as a widget go to this post.
To get the most recent source code go here.

Example of how it looks:
using System.Xml.Serialization;

namespace foo
{
    public partial class Form1<AAA> : Form
    {
        void bar<T, R, L>(int k, Form1 f)
            where T : ISerializable
            where R : Dictionary<string, List<Form1>>, ISerializable
        {
            Form1 Form1 = new Form1();
        }
    }
}

I wrote a script in JavaScript to format C# Code.
I needed such a script because I didn't like the old way of copying the code to Microsoft Word, then to Blogger, and then looking for and removing all the <META> and <LINK> tags that Blogger doesn't accept.
Before I did that, I looked on the Internet, and I found this wonderful site: http://www.manoli.net/csharpformat
But it doesn't handle strings very well, and doesn't recognize types.

For example, the expression 'string path = @"c:\";' returns:
<span class="kwrd">string</span> path = @"c:\";
Which means the string is black instead of red.
About types, I think it's not supported at all.
I downloaded their source code and I found some useful things for my code.

I used more accurate regular expressions to identify strings:
// backslash slash before the end using @
string path = @"c:\";
// even number of backslashes means no backslash
string x = " \" \\\" \\\\";
/* support for multi line
   comments and strings
*/
string y = @" begin
                end";
/// <summary> This kind is also supported
/// </summary>

Formatting strings, comments and keywords is no big deal, but what about types?
Sometimes you don't know if something is a type or a variable, for example:
Something.DoIt();
(There is a way of telling the script that "Something" is a type, and it will be explained later)
It could be a field or a property called "Something", or it could be a class called "Something" and in that case "DoIt" would be a static function.
But sometimes you do know that something is a type, and it worth remembering it for the future:
class Something { } // here the script identifies "Something" as a type
Something.DoIt(); // here it uses the information from earlier

But what about "Application.DoEvents()" ?
In that case the script has a list of common types:
Application.DoEvents();

I compiled this list using this code:
static string GetAllTypes()
{
    string regex = "";
    foreach (Assembly asm in AppDomain.CurrentDomain.GetAssemblies())
    {
        foreach (Type type in asm.GetTypes())
        {
            string name = new Regex("(`.*)").Replace(type.Name, "");
            if (new Regex("^[A-Za-z0-9]+$").IsMatch(name))
            {
                regex += name + "|";
                Match match = new Regex("^(.+)Attribute$").Match(name);
                if (match.Success){
                    regex += match.Groups[1].Value + "|";
                }
            }
        }
    }
    return regex;
}

Sometimes the long list affects the loading time of the blog, so I have another manually written list that has the most commonly used types like: List, EventArgs, ...
Note that the shorter list doesn't necessarily mean the script wont recognize any types, that is because it learns the types from the code itself (as shown in the example above).

In order to use the script you need to write the following code:
<pre formatcs=1>
your code here
</pre>

If the script doesn't recognize a type from some reason, like in the in example of "Something.DoIt()" case, then you can instruct the script to recognize it by adding a new attribute called "types":
<pre formatcs=1 types="Something">
Something.DoIt();
</pre>
And the result:
Something.DoIt();
The types attribute accepts a list of type names, and it can be separated by comma, white space, anything.

The script can handle generics - means it doesn't paint it like in here:
class MyClass<T>
{
    List<T> x = new List<T>();
}

However, there might be cases where the class definition is missing, and then T might be mistaken for type:
x = new T();

Another issue with generics and more specifically with the "<" sign is that you have to write "&lt;", otherwise Blogger is going crazy adding all sorts of strange ending tags to the posts. This behavior is not caused by the script, but it does keep it from working correctly. I don't know how it behaves on other blogging sites, but I tested the script offline on my computer it works with normal "<" too.

I plan to make a gadget that adds this functionality to a blog. I will call it "C# Code Formatter".
But in the meantime the script can be used from here:
jscsharpformatter.googlecode.com

I added a new "HTML/JavaScript" gadget on the bottom of the page with the following code:
<script type="text/javascript" src="http://sites.google.com/site/ycouriel/files/csharp_formatter_normal.js">
</script>
<script type="text/javascript">
var howmany = findAndFormatCSharp();
document.write(howmany + " c# code elements were formatted");
</script>

Feedback is very welcome!

Thursday, February 18, 2010

Version Synchronization

I wrote a server for my MegaCollection software.
Each member of the family can upload new movies and TV series, and edit, delete and rate existing items. The server is used to store this data and support versions synchronization.

Each item has a quite complex data structure including names of actors, image, IMDB identifier, etc. TV series has Seasons, and they have Episodes, and the list is long...
 I'll ignore all of this and assume the following:
  • The Database is a list of Movies
  • Each Movie has a list of DownloadVersions
  • Movies and DownloadVersions have some data inside
Now we have the serverDatabase and the userDatabase.The user can edit his database offline. Other users can do this too.
So we can't assume anything about the databases apart from their correctness.

How do we produce a synchronized database?

I decided to define an interface that all synchronized objects must implement:


interface ISyncObject
{
    string ID { get; }
    DateTime Timestamp { get; }
}

We also need the following information:

DateTime lastSuccessfulSynchronizationWithServer;

This should be enough information to handle all of the following cases:
  1. User added a new Movie
  2. Other user added a new Movie
  3. User deleted a Movie
  4. Other user deleted a Movie
  5. User modified data inside a Movie
  6. Other user modified data inside a Movie
  7. User added a new DownloadVersion
  8. Other user added a new DownloadVersion
  9. User deleted a DownloadVersion
  10. Other user deleted a DownloadVersion
  11. User modified data inside a DownloadVersion
  12. Other user modified data inside a DownloadVersion
Note that cases 7 to 12 happen only if two Movies has the same ID and Timestamp. This case is referred to as "Merging" of the two Movies.

I wrote a synchronization function that considers all the cases 1 to 6. When a merging is required, this function is called again on the DownloadVersions.

Here is the function signature:

static class SyncHelper<T> where T : class, ISyncObject
{
 public static void SynchronizeLists(
  List<T> serverList,
  List<T> userList,
  DateTime lastSuccessfulSynchronizationWithServer,  
  MergeObjectsDelegate mergeObjectsMethod
  )
 {
   // code
 }
}

Assuming this functions works, we can synchronize the database using the following code:

  

static void SynchronizeDatabase(Database serverDatabase, Database userDatabase)
{
    SyncHelper<Movie>.SynchronizeLists(
        serverDatabase.movies,
        userDatabase.movies,
        userDatabase.lastSuccessfulSynchronizationWithServer,
        MergeMovies
        );
    userDatabase.lastSuccessfulSynchronizationWithServer = DateTime.Now;
}
static Movie MergeMovies(Movie serverMovie, Movie userMovie, DateTime lastSuccessfulSynchronizationWithServer)
{
    SyncHelper<DownloadVersion>.SynchronizeLists(
        serverMovie.DownloadVersions,
        userMovie.DownloadVersions,
        lastSuccessfulSynchronizationWithServer,
        MergeDownloadVersions
        );
    // add code to merge other movie data
    return serverMovie;
}
static DownloadVersion MergeDownloadVersions(DownloadVersion serverDownloadVersion, DownloadVersion userDownloadVersion, DateTime lastSuccessfulSynchronizationWithServer)
{
    // add code to merge download versions data
    return mergedDownloadVersion;
}

The purpose of this was to prove it is a quite handy function. I use it in my server to synchronize several types of classes and it works flawlessly.
Here is the full class:

  


static class SyncHelper where T : class, ISyncObject
{
    public delegate T MergeObjectsDelegate(T serverObject, T userObject, DateTime lastSuccessfulSynchronizationWithServer);
    private static Dictionary<string, T> ListToDictionaryByID(List list)
    {
        Dictionary<string, T> dic = new Dictionary<string, T>();
        foreach (T obj in list)
        {
            dic[obj.ID] = obj;
        }
        return dic;
    }
    public static void SynchronizeLists(List serverList, List userList, DateTime lastSuccessfulSynchronizationWithServer)
    {
        // call original function, on merging always take server's object
        SynchronizeLists(serverList, userList, lastSuccessfulSynchronizationWithServer, delegate(T obj1, T obj2, DateTime timestamp) { return null; });
    }
    public static void SynchronizeLists(List serverList, List userList, DateTime lastSuccessfulSynchronizationWithServer, MergeObjectsDelegate mergeObjectsMethod)
    {
        // note that objects that were added by other user will be
        // updated at current user because we are sending him serverList
        string tname = typeof(T).Name;
        Dictionary<string, T> serverObjectByID = ListToDictionaryByID(serverList);
        Dictionary<string, T> userObjectByID = ListToDictionaryByID(userList);
        // look for objects that user deleted
        for (int i = serverList.Count - 1; i >= 0; --i)
        {
            T serverObject = serverList[i];
            //l.Debug("Checking server's", tname, serverObject);
            if (!userObjectByID.ContainsKey(serverObject.ID) &&
                serverObject.Timestamp < lastSuccessfulSynchronizationWithServer)
            {
                // if user doesn't have this object, but he should have it
                // then he deleted it after previous synchronization
                //l.Debug("User deleted this", tname, ", removing from server:", serverObject);
                serverList.RemoveAt(i);
                serverObjectByID.Remove(serverObject.ID);
            }
        }
        foreach (T userObject in userList)
        {
            //l.Debug("Checking user's", tname, userObject);
            if (!serverObjectByID.ContainsKey(userObject.ID))
            {
                // user has an object which doesn't exist at the server's list
                // check timestamps
                if (userObject.Timestamp > lastSuccessfulSynchronizationWithServer)
                {
                    // user added a new object after previous synchronization
                    //l.Debug("This", tname, "is new. Adding to server's list:", userObject);
                    serverList.Add(userObject);
                }
                else
                {
                    // this movie was deleted by other user
                    // the current user will get the new list without this object
                    //l.Debug("This", tname, "was deleted by other user:", userObject);
                }
            }
            else
            {
                // both server and user has this object
                T serverObject = serverObjectByID[userObject.ID];
                //l.Debug("This", tname, "already exists in server database:", serverObject);
                if (serverObject.Timestamp > userObject.Timestamp)
                {
                    // the object was updated by other user
                    // ignore user's object, he will get the new version
                    //l.Debug("Server", tname, "is newer than user's:", serverObject);
                    if (userObject.Timestamp > lastSuccessfulSynchronizationWithServer)
                    {
                        l.Warn("Possible conflict between server and user objects: Server object is newer, but User object was modified after previous synchronization:", userObject);
                    }
                }
                else if (serverObject.Timestamp < userObject.Timestamp)
                {
                    // user deleted the object and then added it again
                    // remove server's copy and replace it with user's
                    //l.Debug("User", tname, "is newer than server's:", userObject);
                    serverList.Remove(serverObject);
                    serverList.Add(userObject);
                    if (serverObject.Timestamp > lastSuccessfulSynchronizationWithServer)
                    {
                        l.Warn("Possible conflict between server and user objects: User object is newer, but Server object was modified after previous synchronization:", userObject);
                    }
                }
                else
                {
                    // both server and user has this movie and:
                    // serverObject.Timestamp == userObject.Timestamp
                    //l.Debug("Server and user have the same", tname, "and with equal timestamps, merging is required:", userObject);
                    T mergedObject = mergeObjectsMethod(serverObject, userObject, lastSuccessfulSynchronizationWithServer);
                    if (mergedObject != null)
                    {
                        serverList.Remove(serverObject);
                        serverList.Add(mergedObject);
                    }
                }
            }
        }
    }
}

How to add a new Blogger post with labels from C#

First download and install Google API from here:
http://code.google.com/p/google-gdata/downloads/list

Add a reference to "Google Data API Core Library",
and use the following function:


public static bool AddPost(string title, string bodyHTML, string[] labels)
{
    Service service = new Service("blogger", "<program name>");
    service.Credentials = new GDataCredentials("<username>", "<password>");
    AtomEntry newPost = new AtomEntry();
    newPost.Title.Text = title;
    newPost.Content = new AtomContent();
    newPost.Content.Content = bodyHTML;
    newPost.Content.Type = "html";
    foreach (string label in labels)
    {
        AtomCategory cat = new AtomCategory();
        cat.Scheme = new Uri("http://www.blogger.com/atom/ns#");
        cat.Term = label;
        newPost.Categories.Add(cat);
    }
    AtomEntry response = null;
    try
    {
        response = service.Insert(new Uri("<uri>"), newPost);
    }
    catch (GDataRequestException exception)
    {
        if (exception.ResponseString == "Blog has exceeded rate limit or otherwise requires word verification for new posts")
        {
            return false;
        }
        else
        {
            throw exception;
        }
    }
    if (response == null)
    {
        throw new Exception("Something went wrong");
    }
    return true;
}

Note what you need to replace:
Also note the marked yellow line. It took me some nasty googling time to find it. You must put it for the labels to work.

Blogger like search box

I copied the Blogger search box and added the following features:
  • It shows the current search keywords after you invoked the search (by parsing the URL)
  • It has a border that becomes gray when mouse is on the box
  • It has a faded string when not in focus, and it disappears when in focus
Take a look:
http://ycouriel-archive.blogspot.com/
(It's on the sidebar)

This is actually the first time I'm using HTML, JavaScript and CSS.
So I hope the code won't be that embarrassing:

<div id="b-navbar2">
<form style="display: inline;" method="get" action="http://ycouriel-archive.blogspot.com/search" id="searchthis">
<div id="b-query-box" style="width: 193.7px;" >
<table cellspacing="0" cellpadding="0">
<tbody>
<tr>
<style type="text/css">
#b-navbar2{
white-space:nowrap;color:#fff;height:29px;border-bottom:1px solid #024;background:transparent;font-size:13px;font-family:Arial,Sans-serif
}
#b-navbar2 #b-query-box{
background-color:#fff;margin:0 .5em 0 0;border:1px solid transparent;border-radius:3px;-moz-border-radius:3px;-webkit-border-radius:3px;padding:0 .3em
}
#b-navbar2 #b-query-box:hover{
border:1px solid #999999;
}
#b-navbar2 #b-query-icon{
display:block;width:13px;height:13px;cursor:pointer;cursor:hand;background:url(http://img1.blogblog.com/img/navbar/icons_orange.png) no-repeat 0 0
}
#b-navbar2 #b-query-icon:hover{
background:url(http://img1.blogblog.com/img/navbar/icons_orange.png) no-repeat -13px 0
}
#b-navbar2 #b-query{
font-size:13px;color:#000;background-color:transparent;border:none;margin:0
}
</style>
<td valign="middle">
<input type="text" title="Search" style="width: 180px; color: #999999;" tabindex="3" name="q" id="b-query" onblur="if (this.value == '') {this.value = 'Search...'; this.style.color='#999999';}" onfocus="if(this.value == 'Search...') {this.style.color='#000000';this.value = '';}" value="Search...">
</td>
<td valign="right" style="width: 15px;">
<a title="Search this blog" onclick="document.getElementById(&quot;searchthis&quot;).submit();" id="b-query-icon"></a></td></tr></tbody></table></div></form>
<script language="JavaScript">
function gup( name )
{
  name = name.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]");
  var regexS = "[\\?&]"+name+"=([^&#]*)";
  var regex = new RegExp( regexS );
  var results = regex.exec( window.location.href );
  if( results == null )
    return "";
  else
    return results[1];
}

function decode(encoded) {
    return decodeURIComponent(encoded.replace(/\+/g, " "));
}

var q = gup("q");
if (q != "") {
    var lmnt = document.getElementById("b-query");
    lmnt.value = decode(q);
    lmnt.style.color = "#000000";
}
</script>