Sunday, March 28, 2010

MEF and IoC/DI (4)

Let's look my first API class - DIResolverBase.

DIResolverBase Class


First, I need to create a class or a library project to define DI mapping relationships which will be used in my application. For example, DIResolver class is a class where I define MEF Import and Export properties. When the class is loaded as an assembly catalog or directory catalog to MEF, the parts or Import and Export mapping relationships are then loaded to MEF framework.

DIResolverBase class is a base class for DIResolver. The class is very simple. It implements IDisposable interface and contains a protected Add() method for holding disposable items.

When I started to use MEF, I was confused by the concept of disposing instances I retrieved from MEF or injected by MEF. At the start, I thought that an instance being requested from MEF was created by MEF and hence MEF should dispose them on application termination. However, it did not happen. In some cases, I had to explicitly dispose the instances retrieved from or injected by MEF in my application; otherwise, some resources such as files or connections would be left unclosed when my application is terminated.

Finally, I figured it out. It is wrong that I thought MEF created requested/injected instances, even MEF does create some instances in my DI library. It'll be much easier to explain it in an example: a console application and a DI library with a DIResolver class. The application only knows IProcessControler interface. The mapped instance is retrieved from the DI library. Here is a picture how the application and MEF work:


and here are some DI codes:

internal class DIResolver : DIResolverBase
{
  [Export]
  private IProcessController _exportController {
  get {
    var instance = new MyController( _log, _reader );
    // Add disposable obj to base created by this class
    // so it will be cleaned up when app terminates
    base.Add(instance);
    return instance;
  }

  [Import]
  private IDataReader _reader { get; set; }

  [Import]
  private ILog _log { get; set; }

}

At the start, the DI library is loaded to MEF as an assembly catalog. Then an instance of IProcessController is requested by the application (1). On the request, MEF resolves the mapping instance by creating an instance of DIResolver class because it found the Export for this type there (2). Hence the Import properties are initialized (3) with the injected instances (Export properties are defined in other DI libraries). Finally, a new the instance is created in the Export property getter (4). In this sense, MEF does create the instance of DIResolver class but not the instance of IProcessController. It is the DIResolver class that creates or news the instance. Therefore the clean up job should be done in this class.

Fortunately, MEF does the nice and cleaning up job when the application is terminated or the MEF container is disposed. MEF will call the dispose() method on all the composable parts, including DIResolver which is based on DIResolverBase. The base class provides the change of disposable.

The protected Add() API in the base class provide a way for the driving class to add any created and to-be-disposed instance to the base. The base class will do the cleaning up job on termination. In above example, you can see the customized DIResolver class is very simple and clean. In case of some instances which do not implement IDisposable interface but do have some resources to be released by other interfaces such as Close() or Disconnect(), the DIResolver class should override Dispose() method, do the customized cleaning job there, and call the base Dispose() method if any disposable instances were added.

One interesting feature of DIResolver class is that it can be an internal type class and the Import and Export properties can be private. This class is mainly used for MEF and rarely used as a public API. So I define it as a none-accessible class from the DI library. It is amazing that MEF can figure it out, i.e., to create DIResolver instances and to access to the private properties.

Read More...

Saturday, March 27, 2010

GitHub Repository as Source Code Repository

toolsWhile I was doing programming with XCode last night, one thing came to my mind: I need a repository to keep track of my source codes. It is not only a good way to save and track my changes, but it also provides a remote repository on Cloud to safely keep my project source codes. So I started to investigate options.

I have done some projects by using Google Code. I use it as a host for my public shared projects. I have not really used it as my source code repository. At work, I also use Subversion(SVN) as a alternative repository. Here is a list of SVN listing. For personal use, I heard many developers recommending GitHub as an alternative. So I gave it a try.

I created an account at GitHub. The basic account is free with .3GB space and no private repository. It provides update to fee-based private repositories. The following is what I have done.

First I need to install git. There is Mac version at Google. The installation is straightforward by running the installation pkg. A reboot is required to access to git in Terminal. I think the installation may add git to the terminal PATH.

The second step is to generate a SSH key. GitHub provides detail step-by-step information about this on Mac. I think this key is used to identify my Mac to a remote SVN repository.

The third step is to add the key to my GitHub account. The key is in my ~/.ssh folder. The generated SSH key is rsa type and the public key is in the file of id_rsa.pub. After adding my public key to my GitHub account, there is one file is created in my ~/.ssh folder as know_hosts.

That's all I have done so far. I have not reached the point to save my source codes in XCode to a repository yet.

Read More...

Friday, March 26, 2010

My New Web Site: Expense Log

By chance, I watched several YouTube videos about Google Site. I think I saw it long time ago and did not have any desire to create one. There are many web site provides and many of them are free. One interesting feature of Google's Sites is that is a Wiki based web site. People can leave comments there.

That's the feature I like. At present, I have been working on my first application. It will be released soon. So it is better to register a web site first. When the product is released, I'll update the site: Expense Log.

Read More...

Saturday, March 20, 2010

MEF and IoC/DI (3)

Here is the way how MEF interacts with the class. When there is a request to get an instance of IProcessController from MEF, MEF will create an instance of DIResolver since MEF knows the Export is defined in this DIResolver class. At the time when the instance is created, the two Import properties are injected with instances of IDataReader and ILog. Finally, the property getter marked as the Export type of IProcessController type is called with the result instance from MEF and then to the request.


You could place many or all Imports and Exports in one DIResolver class, but I prefer to define DIXXXResolver in a logical way so that it contains only the related mapping relationships, for example, DIContollerResolver for resolving the export of IProcessController, DIDataReaderResolver for the export of IDataReader, and DILogResolver for the export of ILog.

OK. I think is very clear about the concept of Export and Import as Parts in MEF in terms of DI. How are the parts (Import and Export) loaded to MEF so that the expected instances can be retrieved from the framework?

In MEF, all the parts are loaded to a DI container, which is called as CompositionContainer class. The container class interacts with Parts actually through another layer called as Cataglog. This is a very interesting and powerful structure. MEF currently supports four types of Catalog classes and they all inherited from ComposablePartCatalog class:


Those catalogs are straightforward by their names. For example, AssemblyCatalog is used for loading parts within an assembly; DirectoryCatalog for loading parts by specifying a folder or file pattern; TypeCatalog for loading a list of specific set of types; and AggregateCataglog for loading a list of catalogs. The first three are most commonly used ones. With this design of structure, Catalog class provides a wild range of strategies to load parts to a MEF container.

For example, I use the AssemblyCatalog to load a list of assemblies or DI libraries where DIXXXResolver classes are defined. I can also put some DI library and related library files in one folder, such as "DIExtensions". Then the folder is loaded by DirectoryCatalog. This makes it possible to dynamically add new extensions or update extensions without rebuilding or compiling my application source codes.

Although it is very easy to load Catalogs to MEF, you still need to understand and follow MEF pattern to do that. As you will find out, MEF contains a wild range of types, classes, interfaces and attributes. It may be very confusing or intimidating for beginners. I'll stop here about further explain MEF; instead, I'll show you three help classes I have created. Those classes provide very simple APIs to define DI mappings, to load DI catalogs, to retrieve instances, as well as other benefits you can get from them.

Still I think it will be very helpful to visit MEF class library and documentations when you see some MEF terms in my classes.

Read More...

Sunday, March 14, 2010

MEF and IoC/DI (2)

Let's explore how to use MEF as a DI framework.

Define Object Mapping Relationships


The documentation at CodePlex MEF project provides excellent information about its MEF structure, how to use it and examples. The information over there may be overwhelming, or more than you need if terms of DI. Here I'll explain MEF briefly just in the area of how to use MEF as a DI framework.

In MEF, the basic units are called as Composable Parts. A part can be either Export or Import. In the case of DI, this can be used to describe mapping relationships.


An Export is used to describe a composable part as a mapping relationship, for example, a class to a class type or interface type. In other words, it tells MEF how to get or create an instance for a class or an interface type.

An Import part, one the other hand, provides a gate way for a client get an instance as a class type or an interface type from MEF. For an import, MEF will inject an instance for a property or field variable if MEF has the knowledge of the corresponding Export part.

In MEF framework, Export and Import are used as attributes. Export attribute can be used to mark a class, a property or a method, while Import attribute can be used to a property, a field value or a constructor parameter.

In my DI practice, I use Export to define mapping relationships, and use Import in codes to let MEF to inject instances based on Export mappings. I mostly use Export/Import for property or field values, rarely for classes, methods or CROR parameters. One reason is that in most cases, I use third part components or reuse components I created before I knew MEF, therefore I cannot add Export/Import attributes to those classes or properties. Another reason is that those attributes actually have less relationship with their logic implementations. I would reluctant to impose other users to use my libraries with MEF binary files.

The advance of applying Export/Import to property or field values is that I can create one or a list of libraries, where only DI logic is described, nothing else. In addition to that, those libraries may have interfaces to get objects injected from MEF. Those libraries are the only places where I use MEF to define DI mappings and to provide a few of simple interfaces to retrieve objects for clients or applications.

As enough as I have said, I'll show you some examples how to use Export and Import attributes for DI mappings. Let's look at following example. Here are some interface definitions and a controller class definition:

public interface ILog {
  ...
}
...
public interface IDataReader {
  ...
}
...
public class MyController : IProcessController, IDisposable {
  // My implementation class
  ...
  // CTOR
  public MyControler(ILog log, IDataReader reader) {
     ...
  }
  ...
}


Then in a DI mapping library, I define a DIResolver class with some property variables marked as Export or Import:

internal class DIResolver {
  [Export]
  private IProcessController _exportController {
  get {
    return new MyController( _log, _reader );
  }

  [Import]
  private IDataReader _reader { get; set; }

  [Import]
  private ILog _log { get; set; }

}


There are some very interesting points in above codes. First, the class DIResolver can be internal, only visible within the project but not to the outside. It makes sense because I don't need to use this class as an API for any public uses. In addition to that, I can also hide Import and Export properties as private ones if I don't have intension to use them outside the class. MEF can access them.

I define the property _exportController as a mapping relationship between the interface of IProcessController and the implementation class MyContoller. The CTOR of MyController has two parametes: ILog and IDataReader. There are many ways to get instances for those parameters. Here I define two properties as the type of IDataReader and that of ILog, and they are accessible to the CTOR since they are local getters. The key point is that those two properties are also defined as setters and marked by Import attribute. As a result, MEF will be able to inject instances to them. Of course, the Exports for IDataReader and ILog have to be defined some other places such as DI libraries, where I define them in a similar way.

Read More...

Saturday, March 06, 2010

MEF and IoC/DI (1)

Inverse of Control (IoC) and Dependency Injection (DI) are widely used patterns in software development. Here I call DI in short for IoC/DI afterwards. I have used StructureMap in .Net as a framework to inject instances to my application, a nice way to decouple interfaces and implementations(see my previous blog posts). MEF(Managed Extensibility Framework) is another very hot topic in .Net recently. Now it is a part of new libraries in .Net Framework 4.0, and it is also available for .Net Framework 3.5. Actually, MEF started as an Open Source project at CodePlex by a group of Microsoft developers. It is claimed with more features than DI.

In the past weeks, I have tried MEF as an alternative way to StructureMap to provide DI. It works out very great. MEF may have much rich features than StructureMap since the later is mainly focused on DI while the former is on the extensibility and discovery ability. Since I am more familiar with DI, therefore, in the view of ID, in this and following posts, I’ll explain in detail how I use MEF as a DI framework.

Overview


Let's stand back a few of steps to get a big picture of implementation of DIs in an application. From my past experience of using StructureMap, I treat it as a library to hold a DI container in cloud.

First, I provide it with information about mapping relations of class to class or interface to class to the container. Then either I fetch instances by interfaces or class from the container directly whenever I need them, or I mark my codes with some kinds of indicators such as attribute so that the cloud will be able to inject appropriate instances automatically. As a result, I would not need to know how instances are created, nor need I to have any knowledge of what actual instances are mapped. This will let me to concentrate on my business logic or working on components individually.



The above is the picture I perceive. With this picture in mind, I found that MEF works in a similar way. I don’t need to change my interface library and components (3), nor my business implementation or application (4). What I need to do is to understand the structure and the way of how to add/load my mapping relationships through the block (2) to the new container (1), and understand how to request instances from the DI framework to my application (4), or to construct my application so that instances will be able to inject to "magically".

In the above picture, there are two doted arrows, which mean that there are two ways to call or reference to each other. One is direct call or request. For example, you can write codes to let the container to know what the mappings are, and you can make a call to the container to get an instance by type. In other words, you have direct access to the container. Another way is that you don't need to write codes to do any direct call at all. Most DI frameworks provide some ways to mark dependencies and injects so that DI framework will be able to detect or load mappings and inject instances automatically. For example, you may construct a mapping configuration file, or add some special attributes to your classes, property variables, constructors or method parameters. Both MEF and StrcutreMap support these two ways; however, they provide different strategies and implementations in terms of how to describe the mappings and to provide injections.

In this and following posts, I'll discuss how to use MEF to describe mappings and injections. My practice only exposes the tip of iceberg, as MEF has much rich infrastructure and features. Even though, I think my DI exercise may help you better to understand MEF. During my exploration, I have done several times of refactory of my codes, which were quite rewarding learning experience.

Read More...

Sunday, February 14, 2010

iPhone SDK 3.1.3

toolsAnother new iPhone SDK 3.1.3 is available. This one is very similar as the previous one on Feb 1 I got. The size is very big, about 3.05GB. Here is what Apple says about the SDK:

What’s New in this Version
- SDK support for targeting non-Mac OS X platforms, including iPhone OS SDK.
- GCC 4.2 & LLVM GCC 4.2 optional compilers for use with Mac OS X 10.5 SDK
- Updated assistants to create new projects, targets, and source files
- Toolbar uses a single popup to choose platform, target, and debug/release
- Integrated SCM support now works with Subversion 1.5

Company:Apple Inc.
Version:3.1.3
Post Date:February 2, 2010
License:Freeware
File Size:3.05GB
URL Type:Form
Download ID:17946




Here is what actually in the installation:

iPhone SDK 3.1
Installs the iPhone SDK 3.1.

iPhone SDK 3.1.2
Installs the iPhone SDK 3.1.2.

iPhone SDK 3.0
Installs the iPhone SDK 3.0.

iPhone SDK 2.2.1
Installs the iPhone SDK 2.2.1. NOTE: this will install the iPhone SDK 2.2.1 to work only on a device; the iPhone Simulator requires iPhone SDK 3.0 or later on Mac OS X 10.6 Snow Leopard.

Sytem Tools
Installs system-wide tools such as Shark (part of the CHUD performance tools), DTrace components used by Instruments, and distributed build processes.

There can be only one, newest set of System Tools per Mac OS X installation at a time, and are always installed into /Developer on the boot volume.

UNIX Development Support
Optional content to allow command-line development from the boot volume. Installs a duplicate of the GCC compiler and command line tools included with the core Xcode developer tools package into the boot volume. It also installs header files, libraries, and other resources for developing software using Mac OS X into the boot volume.

This package is provided for compatibility with shell scripts and makefiles that require access to the developer tools in specific system locations. This content is not relocatable and will only be installed onto the boot volume.
Documentation
Xcode will download developer documentation to disk at first launch, and automatically keep it updated. Deselecting this option requires a network connection while viewing documentation. You can change this at any time in the Xcode Documentation preferences.


Finally, here is the space difference between before and after the update:
Command: df -lakUsed(Kilobytes in 1024-blocks)
Before ...4,408,568
After...2,729,796
Difference (A-B)-1,678,772

Read More...

Monday, February 08, 2010

iPhone Development Update

In the past week evenings and weekend, I spent most of my watching iPhone development related videos. I got those video information when I accessed to Apple’s iPhone developer web site. I remember that I watched a serials of iPhone development classes by Stanford University last Spring. Since then there are more training materials from Apple and other institutions.

Here is a snap-shot of videos I have in my iTunes:



It is great to watch those on my Mac iTunes. However, they are not directly available from Web, or from browsers. I tried to install iTunes at my work PC and I was planning to watch them after work so that I would have quite time there. Unfortunately, I could not get those videos from iTunes in Windows. It looks like that the download URLs or iTunes protocols are blocked at the work. There is no way to get them from browsers, at least I don’t know. In this sense, those videos are not widely opened.

For videos I watched last week, I understand most contents very well. I think that this is the benefit of my past year reading iPhone OS Reference Library and other materials at Apple’s Dev Center. Still those excellent videos greatly help me to understand some concepts such as memory management, MVC, KVC, KVO, and delegates.

By the way, I tried to optimize the size of my snap picture by using Yahoo’s Smuit.com. It is very interesting that Smushit could not find any savings in my pictures. Mac’s png picture is quite good if it is true. I am not sure if the recent update enhances this or not.

Read More...

Saturday, February 06, 2010

Retry Component

Last Friday, I finished a project of reading data from a service and saving the data to a network drive. The project is a console application based on a framework of DI. that is, dependency injection. The whole process is divided into several small tasks, and each task is corresponding to a component, or a library in .Net. Each one does one job and does it well. Together, the components are plugged in to a main controller, where a work flow of components is laid out in a logic as expected. In addition to this clear and well defined structure, there are many other advantages as well, for example, easy maintenance and reusability.

The application will run on daily base to prepare data for one department. I demoed the application to my project team leader. He was very happy to see how the demo run. After the demo, he asked me a question: how about retry? Is there a way to run this application on a retry style if the required data are failed to deliver to the network drive? I have worked on several cases to read required data from SQL servers. All those application have the retry feature. For example, one applications gets the required data first, if the returned data is empty, then the application will quit immediately. If the required data are not empty, the application then gets the data and saves them to the server.

However, for this case, the data source and destination are not at the same place. Therefore, the application will always get the data from source when it runs. I have to work out a way for the retry. In other words, I have to define or create some key references to check if the retry is needed.

Since the job will run on daily base, I come out two keys to check: date and status. For the date, there is one as expected date, and another as actual last date; same for the status, one as expected status and another actual last status. The actual value has to match to the expected value. For example, a user can set up the expected date today and the expected status as a string of "ProcessOK". When those conditions are true or the actual values match the expected values, the application will not read data from source; otherwise, it will read data and continue the remaining steps. After all is done, the actual values will be updated.

All those expected and actual information are defined and saved in an XML configuration file. The expected date can be a script of C# code like "DateTime.Parse(DateTime.Now.ToShortString())", which will always to get today's date. The expected status is static as well. Therefore, only two actual values have to be updated by the application when a complete run is finished.

Here are the pseudo codes of the retry logic:

   bool retry = method call to an instance of Retry with the logic:
!(actual_last_date is set) ||
!(actual_last_status is set) ||
(expected_date != actual_last_date) ||
(expected_status != actual_last_status);
if (retry)
{
run_application
...
save actual_last_date
save actual_last_status
}

The Retry class is a component in a library project. The Retry class implements an interface of ICommuncationChannel in a framework library:
  interface ICommunicationChannel<TData, TValue>
  {
    TData Request(TValue value);
  }

so that it can be requested to return a result of retry. A configuration class is also defined in the Retry component library. The config class is simple class with property definitions corresponding to the expected values and the actual values. An instance of the config is wired to the XML configuration.

After one day hard-thinking and coding, I got the component completed, added the DI mapping and XML mapping for Retry's config, and almost finished the main controller with Retry component in the logic.

The reason that I decided to save the actual last results the XML configuration file is that those values can be easily parsed out by another PowerShell script project to get the job status. I have done a monitor process based on PS and Growl for sending notification messages. With the retry feature, I can bring an additional benefit: adding these actual values to the monitor process so that the notification message will include the information.

Read More...

Monday, February 01, 2010

iPhone SDK 3.1.2

After about one year reading of iPhone development reference documentations and training materials, I am going to start my new adventure of iPhone application development. I downloaded the iPhone SDK long time ago. I think I need to get the newest version of DSK 3.1.2 first. The total package is about 2.5GB, which takes long time to get it. I just started about a few minutes ago, now the remaining time is about 37 minutes.

At the same time, I found there are some iTune video materials available from ADC, I am going to get them as well. My first application will be in the category of Productivity area for managing personal expense information. The datastore will be based on SQLight which is recommended by Apple for iPhone app. I have created several tables for raw data. In order to management raw data, I am going to use Tags to let user to tag those information. The main interface will be based on tableview controls for displaying data with editing features. The edit view will be a view with text and date time controls. I am going to draw those views and workflow structure of views.

The application will be MVC based application. To my surprise, Apple developers has implemented this pattern for quite long time, even long before the current Microsoft MVC model in Windows and ASP applications.

Even the iPhone development and Objective-C are new for me, I think I have very good knowledge of C/C++, as well as extensive experience in OO. I have explored some iPhone applications and had my hands on some examples. I really like the framework of Cocoa. It will take time get used to the new framework for sure. I think the most achievement is to develop my own applications and test them out on the Apple Store.

I have a line of ideas to develop iPhone applications. iPad will be available in less than 60 days and iPad 3G in less than 90 days. If I can get some out for iPhone, it will be fun to see how they are in iPad. I may move to iPad application development as well.

The following are snap-shots of the installation steps:







Detail descriptions for items:

iPhone SDK 3.1
iPhoneSDK.3.1.2Install1
iPhone SDK 3.0
Installs the iPhone SDK 3.0.
iPhone SDK 2.2.1
Installs the iPhone SDK 2.2.1. NOTE: this will install the iPhone SDK 2.2.1 to work only on a device; the iPhone Simulator requires iPhone SDK 3.0 or later on Mac OS X 10.6 Snow Leopard.
System Tools Support
Installs system-wide tools such as Shark (part of the CHUD performance tools), DTrace components used by Instruments, and distributed build processes.


There can be only one, newest set of System Tools per Mac OS X installation at a time, and are always installed into /Developer on the boot volume.
Documentation
Xcode will download developer documentation to disk at first launch, and automatically keep it updated. Deselecting this option requires a network connection while viewing documentation. You can change this at any time in the Xcode Documentation preferences.
Mac OS X 10.4 Support
Support for developing applications that target Mac OS X 10.4 APIs.

I checked the "Mac OS X 10.4 Support" (even it is still Zero KB).

Read More...

Saturday, January 23, 2010

.Net Reflector

.Net Reflector is a must-have tool for .Net developers. Last year I updated my Visual Studio at work to 2008. However, I forgot to add this tool. When I started to work on a project based on MEF(Managed Extensibility Framework) as DI (dependency injection), this reminded me about the tool. I need this tool to browse the class structure of Microsoft.ComponentModel.Composition.dll.

The tool was developed by Lutz Roeder. In his blog, he said that now it is transfered to Red Gate Software. I think I used the SQL Compare application from this company. Anyway, .Net Reflector is a Windows based application, and it is very easy to install as a tool in VS 2008. From the menu Tools->External Tools..., it can be added there. Here is a snapshot of the installation:



There are also many Add-Ins for this tool.

Read More...

Sunday, January 17, 2010

Cheatsheets

Based on Wikipedia explanation, the team "cheatsheet" is a concise set of notes used for quick reference. "Cheat sheet" may also be rendered "cheatsheet". Here are some cheatsheets I found from Google search:

  1. Cheat-sheets.org contains all popular cheatsheets in one web site.
  2. HTML cheatsheet is good, but I prefer w3school tutorials, including HTML references.
  3. CSS Cheat Sheet contains concise information about CSS styles.
  4. Google search cheat sheet contains some important tools and tips to enhance search.
  5. Here is one simple VIM cheatsheet, Graphical Vi-vim Cheat Sheet for keyboard mappings, vim command cheatsheet, vim basic and advanced cheatsheets.
  6. .Net RegExp cheatsheet.

Read More...

Saturday, January 09, 2010

VIM Tips: Edit HTML Table from Web

I like to explore and learn new things. It is a life time learning experience. For example, I like to use VIM to edit my text files. There are so many great and powerful features in VIM. What I know is just very tiny tip of the iceberg. There are so much to learn, and I really enjoy learning VIM.

Here is my blog story. I occasionally need to copy and paste some HTML table data from web to my blog. One case was the technical specifications of an Epson printer I purchased from Futureshop. Futureshop's on-line web page lists its tech-features on its page. This printer is the current model today, but it will be out very soon. The web information will be gone. As a record or reminder for myself, I wrote a blog with all those features there. What I did first was to copy the HTML table from Futureshop's web site. The problem is that there are some other un-wanted tags in the block such as javascript functions as links and too many spaces and enter keys. The Blogger's web based editor is not a truly HTML editor. It convers, for example, enter keys (white spaces) to line break tags. I would like to remove them.

Hence, I need VIM to help me. Here is the summary of VIM search and replace commands I used:

:%s/\s\{2,}/ /g   # white space > 2 replaced by one space
:%s/\t\+//g # tab > 0 replaced by nothing
:%s/\s\n/\r/g # white space + newline replaced by new line
:%s/\n\s/\r/g # new line + white space replaced by new line
:%s/\n\{2,}/\r/g # new line > 2 replaced by new line
:%s/a_\{-}\/a>//g # replace <a...>..</a> with nothing
:%s/\n//g # replace all the new lines with nothing

Notice that the line breaks in search is \n, where the line break in replacement is \r. {n,m} is used for a count range from n to m, and m is optional. Another very useful key in search is _\{-}xxx, _\{-} is a special keys to none-greedy search. Normally . matches to any char, but with _\{-} will search for any char including new line but not the chars afterwords. Here I search for "<a" with any chars until ">". By the way, .\ is for any char but not including new line.

Before I remove all the new lines (combine lines to one line), for the case of Table, I'll add the following column groups to set up width of columns. Here is an example of two columns:

<colgroup width="10%"></colgroup>
<colgroup width="90%"></colgroup>

In order to display rows in alternative colours, I have added three css classes in my Bloger HTML settings: header, odd and even. I have to manually add those classes to each row like <th class="header"> and <tr class="odd"> or <tr class="even">.

Finally I remove all the new lines in the table so that this block of table in HTML is ready for my blog.

With VIM those powerful features, it makes my blog writing much easier, especially in the case I need to copy and paste some HTML from other web pages.

Read More...

Saturday, January 02, 2010

Notification Application: Growl

toolsI have used Growl, notification application, on my Mac for quite long time. It was recommended as one of must-have applications. Growl is a Growl Notification Protocol (GNTP) based messaging application, which displays any messages from other applications. Growl is an open source based project and it is free.

Recently, I have been working on a project to backup SQL server databases, history data files based on SCADA field sites, and other important files from various Windows based PC to a central place. The file transfers are running daily. When the project was close to final stage, I had to check backups and files every day to the central PC. It was very tedious. Growl comes to my mind. If there is any way I can use Growl in Windows. Quickly I found Growl for Windows.

I immediately downloaded the application and give it a try. I was worried about network firewalls and our internal security policies. To my surprise, Growl works like a charm without any issues. I used groiwlnotify.com to send out notifications from a remote PC, another client PC with Growl installed receives the messages.

There are some settings to do, but it is very straightforward. First, the network notification has to be enabled. Then I set up password for a receiver as security gate to verify any notification request. I think the password is optional but I like it. This will prevent any other network GNTP based services to send notifications unless password is verified.

It looks like that Growl for Mac and Growl for Windows are two different teams. The application appearances of both are almost the same, but there are some differences in features. For example, Growl for Windows has History setting, but for Mac. I like this feature. Since notification is displayed once with a quick time span, users may miss some important ones. With History, at least users can review all the past messages. For example, I set up the notification service on the central PC right after the jobs are finished, when is about 2:00AM. Nobody will be able to see them. Off couse, I could use Sticky feature to make the notification displayed until they are clicked. However, Growl for Windows seems have problem to display the message. One user told me that his notification window was black when he logged in a morning.

Mac Growl has more style than Windows Growl. I could not find some styles I use in Mac in Windows. I don't know why the styles cannot be ported to Windows. That's not a big deal.

In general Growl is a really good tool to send notifications between applications. My team likes this tool to make health monitor check much easy. The only concern is the stability of OS. Mac OS is much beter in this respect than Windows. I told my colloquies that I normally reboot my work Windows on daily base.

Read More...

Sunday, December 20, 2009

VIM Plugin: matchit.vim

By default, VIM has match feature. For example, if you edit a .c file, press '%' when you are at {, [, or ( char, you will see the corresponding }, ], or ) is highlighted, and your cursor will jump back the forth. It is a very handy feature. For html file, a tag like <table> is also pair case, with </table> as end tag. % char would not smart enough to find this pair. Based on the Best of VIM Tips, VIM Wiki's Editor choice, matachit.vim is in the section of "Really useful".

I tried to install it to my Windows at my work computer. It works fine. Basically, you have to download the file to VIM installation path, such as "E:\Program Files\MyProgram\VIM\". There are two folders for syntax help information and plugin vim file in doc and plugin folders. Now I am going to try to install it at my iMac computer.

First, download the package of matchit.vim. Copy the downloaded zip file content doc\matchit.txt and puglin\matchit.vim to local ~/.vim/doc and ~/.vim/plugin.

[MyMac]:~ [user]$ cp ~/Download/matchit/doc/matchit.txt ~/.vim/doc
[MyMac]:~ [user]$ cp ~/Download/matchit/plugin/matchit.vim ~/.vim/plugin

Now % should work. To rebuild the help message for %, type the command in VIM:
  :helptags ~/.vim/doc

This match extension works well for html file tags. Locate your cursor within anywhere in a tag, press % will jump to its corresponding tag. It is a really useful extension.

Read More...

Saturday, December 12, 2009

PsExec.exe Access Denied

I thought PsExec.exe would never fail to start a process on remote. I got my first failure last week when I was working on a project to do a similar remote execution call as I did before for a Windows XP Prof box. I had not problem running PsExec.exe to zip a file on Windows XP box before. However, this time for that Windows XP box, I got a failure: Access denied.

I did notice a different file sharing property window when I tried to share a a folder. I thought that there must be some Windows settings difference between this one and the one I worked before. Here is the file sharing property:



I googled "PsExec Access Denied" and found some resolutions. Basically, PsExec.EXE uses SCM API (OpenSCManager, CreateService, StartService), where SCM is Service Control Manager. It is similar as Process class in .Net, or the core might be the same. Those APIs are very much based on Window security settings. Anything is not correct, then PsExec.exe may fail.

The box I run PsExec.exe successfully has the following folder sharing property:



Simple File Sharing

This difference confirms that the box I got failure has some setting issues, as indicated in this discussion in Sysinternals Forums. The first setting is easy to change. From File Explorer's menu Tools|Folder Options..., in the View Tab, clear the setting for "Use simple file sharing":



Turn off "network users identify as guests"

The second change is a security setting. From Control Panel, find the Administrative Tools snap-in, open Local Security Settings. Then find Local Policies->Security Options. Look for the line "Network Access:Sharing and security model for local accounts". The value for this "key" was the default value of "Guest only - local users authenticate as Guest". Change it back to "Classic - local users authenticate as themselves".



After all those changes. I did not reboot the box. Just waited for a while. Then I got my PsExec.exe working, remotely zip files on the remote by using 7-zip tool!

Read More...

Sunday, December 06, 2009

SysInternals Tool: PsExec.exe

PS supports remote process. That means you may run a process on a remote Windows. Recently I was working on a project which requires to run a process on a remote Windows box. I tried to use WMI process to start a process on remote. It works on one box (Windows XP), but the same codes do not work on a Windows 2008 server.

Quickly I found a solution: a SysInternals tool, PsExec.exe. It is very small and it works well. To start a process and wait it terminated, there is the code:

PsExec.exe \\computerName -u userName -p pwd -i program args...

the option -i is used to start the program in an interactive way.

Read More...

Tuesday, December 01, 2009

Zip Files with PowerShell Script

Recently I have been working on backup files from a remote server in network to another server PC. I use SyncToy tool to sync files from the remote to the server. Each time when you run the SyncToy, it will generate a SyncToy.log file as in "C:\Documents and Settings\username\Local Settings\Application Data\Microsoft\SyncToy\2.0\SyncToyLog.log". What I need to do is to copy the SyncToy.log file from that location to a specified location and zip to a monthly file as my log, for example, "C:\synclog\synctoy_122009.zip".

This job can be easily done in a .Net project, but I was required to write a script instead of another program. As I know very little about PowerShell, I spent about 2-3 days to find out a solution. Basically, you can access to almost any .Net classes in PS. I have used DotNetZip library before, which provides a very simple and nice library class to zip files. What I need to access to this library, create an instance from its class and call its methods to detect and zip files. In PS, it is very easy to do that.

# ZIP dll library file in the local PC folder:
$ZIP_DLL = "C:\bin\Ionic.Zip\Ionic.Zip.dll"
$assemblyLoaded = [System.Reflection.Assembly]::LoadFrom($ZIP_DLL);
# Zip class
$zipClass = "Ionic.Zip.ZipFile";

Here I use a var to hold LoadFrom(...) is to prevent output of loading results. The var is not needed for reference use. In PS, if you want to prevent some output while calling some methods, this may be a strategy to do it.

To zip files, I created a function to do the job. The function will zip a group of files (source files as a string such as "C:\temp\*.log"), with a constrain of days for last modified date stamp within those days from now, to a destination folder. In addition to that, I pass one flag to the function to provide option to include path in zip or not.

#*============================================
# FUNCTION DEFINITIONS
#*============================================
function ZipUpFiles (
  [string]$p_Source = ${throw "Missing parameter source"},
  [string]$p_DestFolder = ${throw "Missing parameter destination folder"},
  [int]$p_days = ${throw "Missing parameter int days"},
  $p_zipFile,
  [bool]$p_PathInZip,
  $p_zipClass
  )
{
...
}
...
#*============================================
# END OF FUNCTION DEFINITIONS
#*============================================

In PS, actually, you don't need to define input parameters. You can define () empty list, and you can still call it with a list of parameters. Within the function, you can get parameters by $args. However, it is much clear by defining parameters. You can think them as var definitions.

The first thing to do in the function is to get a list of files:

  $checkFileDate = ($p_days -ne 0)
  # adjust timestamp by days for comparing
  $dateToCompare = (Get-date).AddDays(-$p_days)
  $zipCount = 0;
  # get all the files matched and timestamp > comparing date
    $fs = Get-Item -Path $p_source | Where-Object {!$_.PSIsContainer -and (!$checkFileDate -or ($checkFileDate -and $_.lastwritetime -gt $dateToCompare))}
  if ( $fs -ne $null )
  {
    ...

The codes are pretty much straightforward. Here Get-Item command to check path with pipe to check each items to meet requirements: not sub-direction, and file created date great than days if specified. The result is a collection of files to be zipped.

In PS, all the comparison and logical operators are literal with -. For example, -gt for great than, -eq for equal to, and -or. This very handy and easy to understand. It also makes the blog HTML tags much easier, no need to convert "<" to "&lt;".

Next continue to zip files in a for loop. The function takes one parameter as zip file name. If it is specified, all the files will be zipped to that file with {mmyyyy}.zip as suffix. If it is not specified, each file will be zipped with that suffix.
    $zipObj = $null
    if ( $p_zipFile -ne $null )
    {
      $zipFile = "{0}{1}" -f $p_DestFolder, $p_zipFile
      $zipObj = new-object $p_zipClass($zipFile);
    }
    foreach ($file in $fs)
    {
      $addFile = $file.Name
      if ( $p_zipFile -eq $null )
      {
        $zipFile = "{0}{1}.zip" -f $p_DestFolder, $addFile
        $zipObj = new-object $p_zipClass($zipFile);
      }
      # Trim drive name out as key to check if file already in zip?
      if ( ($zipObj.Count -eq 0) -or 
                (!$p_PathInZip -and ($zipObj[$file.Name] -eq $null)) -or
                ($p_PathInZip -and ($zipObj[$file.FullName.Substring(3)] -eq $null))
                )
      {
        Write-Output "Zipping file $addFile to $zipFile..."
        $pathInZip = ""
        if ( $p_PathInZip )
        {
          $pathInZip = $file.Directory
        }
        $e= $zipObj.AddFile($file.FullName, $pathInZip)
        $zipCount += 1
      }
      if ( $p_zipFile -eq $null -and $zipCount -gt 0 )
      {
        $zipObj.Save()
        $zipObj.Dispose()
        $zipObj = $null
        $zipFile = $null
      }
    }
    if ( $zipObj -ne $null -and $zipCount -gt 0 )
    {
      $zipObj.Save()
      $zipObj.Dispose()
      $zipObj = $null
    }

Here $zipObj is created from .Net class. All the methods then are available in PS. You may refer to class definition in Visual Studio or ReFlector to view class structure. Before I add a file to zip, I check if the file is already in the zip file (two cases: path in zip or not). If so, no zip will be done.

In the end of the function, the $zipObj has to be saved and cleared if there is any files added:

...
    }
    if ( $zipObj -ne $null -and $zipCount -gt 0 )
    {
      $zipObj.Save()
      $zipObj.Dispose()
      $zipObj = $null
    }
  }
  if ( $zipcount -eq 0 )
  {
    Write-Output "Nothing to zip"
  }
}


Finally, in my PS script, after the function definition, which has to be declared before it is called, here is my main entrance:

#*============================================
#* SCRIPT BODY
#*============================================
# Example parameters:
# E:\Temp\*.bak E:\Temp\BackupZips\ 50 backup.zip
Write-Debug "Starting ZipFiles.ps1"
# check input arguments
$argsLen = 0 
if ($args -ne $null )
{
  $argsLen = $args.length
}
if ( $argsLen -lt 2 -or $argsLen -gt 5 )
{
  HelpInfo
  return
}
$i = 0;
# Get input parameters
$sourcePath = $args[$i++]
$destPath = $args[$i++]
if ( !$destPath.EndsWith("\") )
{
   $destPath += "\"
}
[int]$numOfDays = 0
$zipFile = $null
[bool]$pathInZip = $true
if ( $argsLen -gt $i )
{
  $r = [int]::TryParse($args[$i++], [ref]$numOfDays)
  if ( $argsLen -gt $i )
  {
    $zipFile = $args[$i++]
    if ( $zipFile -eq $null -or $zipFile.length -eq 0 )
    {
      $zipFile = $null
    }
    if ( $argsLen -gt $i )
    {
      $pathInZip = ($args[$i++] -eq 1)
    }
  }
}

# Test source & destiantion
if ( !(Test-Path $sourcePath) -or !(Test-Path $destPath) )
{
  Write-Output "Nothing to do. Either ""$sourcePath"" or ""$destPath"" is empty or does not exist."
  return
}

# ZIP library is from http://www.codeplex.com/DotNetZip
# ZIP dll library file in the local PC folder:
$ZIP_DLL = "C:\bin\Ionic.Zip\Ionic.Zip.dll"
$assemblyLoaded = [System.Reflection.Assembly]::LoadFrom($ZIP_DLL);
# Zip class
$zipClass = "Ionic.Zip.ZipFile";

Write-Debug "Start zip process ($sourcePath > $destPath)..."
ZipUpFiles $sourcePath $destPath $numOfDays $zipFile $pathInZip $zipClass

$assemblyLoaded = $null

#*============================================
#* END OF SCRIPT BODY
#*============================================

The first section of main body is to parse input parameters. As I mentioned, $args is a PS variable for arguments. If there is less or more required parameters, function HelpInfo is called, which just output the usage of the script and it is omitted. When all the required parameters are parsed, the function ZipUpFiles is called.

Read More...

Monday, November 23, 2009

Syntax Highlighting

notesI posted a blog on code syntax hilighting last year. I have tried to add syntax hilighting for my codes in my blogs since then. The color settings are based on css styles embeded in my Blogger's html settings. The css classes I used are based on ASP.NET forum editor page settings. The problem I have is that the classes are very limited. They are limited to C#, HTML and SQL codes. It is very hard to expand my css classes to cover a wide range of codes.

Later on, I changed my code syntax hilighting strategy from HTML class to direct style settings. The advantage I can easily use other editor's syntax color schema to my blog codes. VIM is a great editor I can use. The following are major steps I use.

Use VIM to Edit Source Codes

First I use VIM to edit as a tool for codes. VIM supports a wide range of languages. For some new languages, if I don't have syntax vim files, there must be some syntax vims available on web. For example, I got and installed Microsoft PowerShell script ps1.vim.

In addition to VIM's syntax lighliting feature, I also use VIM's colour scheme. I have put some of my favourite colour scheme files in my /.vim/colors folder. The following is current colour scheme files:

[Home] .vim $ ls colors
fog.vim  spring.vim torte.vim


This Google code project, VIM Color Scheme Test, contains hundreds of colour scheme files. I got my colour files from this site.

To change different color scheme in VIM, just type command

:colorscheme ...


or tab through different colours.

Convert to HTML

To covert colourful codes to html, you can use the command

:TOhtml


This command will open another window on top with html codes. Note: by default, my VIM has line number displayed. It is very convenient to locate codes. However, it is not good to convert line number to html as well. Normally I disable line number first:

:set nonumber


Here is an example of my VIM:



In the top window, it contains complete html codes as a HTML page. What I need is just a part of my codes starting from <font> to </font>



Clean up HTML Codes

Use the following commands to clean up codes:

:%s/\n//g


This command search for new lines globally and replace them with empty, that is removing all the new lines. Note to replace something with line breaks, the command is

:%s<b>/\r/g


Removing all the extra new lines is needed for Bloger content.

Finally, add a div tag around the html codes (<div class="outlinebox4wrappercodes">):



Copy and paste these html codes to my blog. Job is done!

Note: if you use colour scheme in VIM, you may need to copy the background colour from html <body bgcolor="..."> and paste it next to div like <span style="background-color:...;" >



Conclusion

The limitation of this strategy is not easy to manage or maintain blog codes, especially when I need to correct, delete or add a long section of codes. Normally, I would use VIM as my editor fro my source codes, and repeat these steps again if any changes are needed.

The advantage of this method is that there is no any dependency on css classes. All the syntax settings are done directly by using html font tag with colour settings. To manage classes in Blogger's header to cover various languages is very difficult. Any change to the classes may break previous blogs.

Read More...

Saturday, November 21, 2009

VIM Syntax Settings

Recently I started to learn and working on Windows PowerShell scripts. PowerGUI is a nice tool as script IDE or editor. However, when I wanted to write a blog on PowerShell with some example script codes, I have to use VIM or MacVim to convert codes to HTML. By default, my VIM does not have syntax vim file for PowerShell, since it is a new script language. Then I searched for the ps1.vim on web. It does not take much time to find out one at vim.org's syntax library.

This is first time for me to add syntax file to VIM. It was challenge for me and I took about 2 hours in last evening to figure it out. VIM is an excellent editor for programmers. It provides configuration settings for adding syntax files. Basically, the settings are in two different areas. The first one is to add syntax file to a specified directory. Most cases, syntax files can be found on web by many VIM fans and gurus. I don't need to write one even there are detail information about writing syntax files. Taking PowerShell script as example, the syntax file should be ps1.vim.

Add Syntax File

In case of my Mac OS(UNIX system), there are two places I can place the file. One is for all users and another one is a login user. All the syntax files come with VIM are installed in my Mac at /usr/share/vim/vim72/syntax/ folder. I found this location by using the following command in Terminal:


[Home] $ find / -name "html.vim" -print


Since I have never added any syntax file by myself before, there is no syntax files specific for my login name. I have to create the following folder for my syntax files.


[Home] $ mdkdir ~/.vim/syntax
[Home] $ cp ~/Downloads/ps1.vim ~/.vim/syntax/ps1.vim


After that, I thought I should be able to test a ps1 file in VIM with syntax colors. I did not see any syntax colour when I opened a test file: test.ps1. It took a while to figure out a way to manually load or test the syntax file by using the command in vim:


:source ~/.vim/syntax/ps1.vim



The loading process was failed because there are some syntax errors in the ps1.vim file. I think that actually is the line break problems when I downloaded the file from web: some line breaks are actually ^M chars. Then I found another updated ps1.vim from tomsr. I copied the source codes from web page and replaced ps1.vim's whole content. After that, the loading process was OK.

NOTE on September 16, 2010: for Windows XP, the vim.ps1 from VIM syntax library is OK. I have to copy this file to my VIM\vimfiles\syntax folder.

Define File Types

Still I could not see syntax colour. This is because VIM requires another setting to define file types. This second setting is called as *new-filetype*. I choose C option to define my new file type. I copied the following codes to a file at ~/.vim/filetype.vim:

if exists("did_load_filetypes")
  finish
endif
augroup filetypedetect
  au! BufRead,BufNewFile *.ps1    setfiletype ps1
augroup END


Then I restarted my VIM. Finally I can see my test.ps1 file in VIM with syntax colours.



NOTE on September 16, 2010: for Windows XP, the file filetype.vim should be copied to VIM\vimfiles.

Read More...

Thursday, November 19, 2009

Google Chrome OS

Today Google announced its Chrome OS progress. Goole revealed more detail information and early stage of the Chrome OS. I watched some video shows and it is a new way to explore the usage of web. For sure its new structure opens a different view of OS. It is new but it is a result based on the development of computer hardware and software, as well as the development of Web in the past 10 years.


More shows are available at YouTube.com: Google Chrome Themes.

I really like its way to explore OS for net-book. OS is based on web browser and web applications to provide applications for end users. That's not new. The only problem is that it is heavily depended on Web or Cloud servers. In case of none-web available cases, it would be useless. That's why Google come out Chrome OS. It provides OS level APIs and storage (solid-base HD) with off-line features, just like OS still live. As many critics recall this light-weighted OS is not new thing. Early in 21st century, Sun Microsystems tried to provide Java based NC (network computers). I remembered that I attended a tech talk in Calgary by Sun, talking on JENI Project based computer terminals. The speaker said that NC should be like a telephone device, which is very cheap and can be placed anywhere. It is a network based computer systems. I was expecting the new change happening and it looks like a failure.

However, I think Chrome OS will be very different. It will be great challenge for Microsoft and Windows. For Apple, it is a challenge as well, but I think Apple has better position to move its OS forward. I believe that UNIX based OS has great future since it is based on solid and proven computer concept. 2010 will be very interesting year to see new OS and net-book hardware appearing. Chrome OS will have great impact in all areas and out daily lives.

Read More...

Wednesday, November 11, 2009

Go: New Open Source Language from Google

Last night I read a news from CNET news about a new language as an experiment and promising language targeting today's computer trend with multi-processors: Google hopes to remake programming with Go. Then I went to Google Go language site: golang.org. I watched two shows there. One is an introduction about Go, last about one hour, and another promotion show in about 2 minutes. Here is the introduction show on YouTube:


Show link: The Go Programming Language

It is very impressive. I really like it even I did understand all the codes in their new syntax. The codes look very similar as C/C++ and some like C# or Java, however, many new features are introduced to Go. The team behind Go is a group of very talent people who were the original creator of UNIX and Chrome's Javascript and compiler. As it is mentioned at Go's web page: Go is ...simple, ...fast, ...safe, ...concurrent, ...fun, and ...open source.

I am very impressed with its compiler result, 13k lines of codes compiled within 209 nanoseconds and whole math and other calculation libraries compiled in about 9 seconds. The current version is only available for Linux and Mac OS.

It looks that Go will have great feature. Comparing to the current computer languages, Go's great performance will be very attractive to programers. It is built from ground up with clean design. I guess the future Google OS may be based on Go and more great applications written by Go will be coming out soon. Still as Rob pike said in the show, (Go) is early yet ... more will be coming soon.

Read More...

Sunday, November 08, 2009

SyncToy 2.0 - A Windows 7 Tool by Microsoft Home Server Team

toolsLast week, I was asked to investigate an issue of backup some files from remote network drives. I thought the basic concept is to find out if a file has been changed or not. This could be file name, modified date. It can go further complicated such as file name changes, deleting, as well as content change. This must be a very common issue in Windows platform, I thought, and there must be something available such as libraries or tools.

Soon I found out SyncToy 2.0, a free Windows utility application offered by Microsoft. It was actually for Windows 7. The tool is based on Microsoft Sync Framework File Synchronization Provider. In other words, you can use the tool or use the library in .Net. The tool provides three basic actions:

  • Sync: bi-directional sync, any change in either left or right will synced to opposite side. New and updated files are copied both ways. Renames and deletes on either side are repeated on the other.
  • Echo: any change on the left side will be echoed to the right side, but any changes on the right side will not be on right side or reload to right side. New and updated files are copied left to right. Renames and deletes on the left are repeated on the right.
  • Contribute: only new files on left side will be added to the right side. New and updated files are copied left to right. Renames on the left are repeated on the right. No deletions.



For my case, Contribute is the right action for me. I tried this tool and it works well. If there are a lots of files on the left side, the first time may take long time since all the files will be copied to the right side. The later sync process may be much faster if there is a few files changed or no change. It can be used against network drive and the sync process can be done as a scheduled job with sync name. Each sync is defined as a pair of left and right, with additional options such as file exclusion, hidden files and more.

The tool provides log under current user profile. I think the log file is saved at %userprofile%Local Settings/Application Data/Microsoft/SyncToy 2.0. The left and right sides, there are some hidden dat files, which store sync information for the next sync.

There are also some examples of how to use the Sync Framework. I think this provides more more control over how to sync and realtime sync.

Reference: a blog on SyncToy 2.0 by Microsoft Home Server Team.

Read More...

Wednesday, November 04, 2009

SuperUser.com and WidExplorer

StackOverflow has another site for computer Q&As: Super User. The structure of this site is very similar as StackOverflow. Any user can ask and answer computer related questions, vote Q&As, and make comments. Any user can gain reputations by badges. This is a complementary to StackOverflow's developers site. I, as David.Chu.ca with 163 reputation currently, have asked several questions and answered a few.

Today, I asked a question about using browser to display multiple web sites in one page or tab. This could be done by browser's add-ins or web services. I prefer web services since it is less dependent on browsers. I got some answers, but soon I found a web service doing what I want: a wide view of the web(WE). Basically, the web service has the following features:

  • Search engine: it provides a text field for search. The search results will be a list of google, being, yahoo, wikipedia, youtube and more. The display is one page with wide view of those results.
  • An edit UI for multiple URLs. From there you can enter a list of ULRs and get a wide view of results.
  • Short URLs. Since the view is in one page or tab with a list of results of web sites separated in horizontal view, this browser view has a long URL. At the end of the view (far right side), WE provides a UI for edit URLs and a short or tiny URL for the current view. For example, this tiny URL name(http://tinyurl.com/ybvhcdv) is a view of a list of stocks.


In addition to that, the wide view also provides "-" and "+" to shrink and expand a URL view. The wide view and UIs are based javascript codes on client side so the view is very fast. The only thing is that each URL view has its full width without its own horizontal scroll bar. Another thing is that some empty URL are displayed as expanded mode instead of shrink mode, or empty URLs should not be displayed.

Read More...