Monday, September 29, 2008

Most Used UltraEdit Macros

There are some truly excellent macros on the UltraEdit extras page as well, but I am putting these up mostly for my own reference whenever I swap machines.

Updates:
24th May, 2009 - Added macro to close a html/xml tag, copied from UltraEdit forum post.
Monday 14 March 2011, 01:01:46 AM - reference to two other frequently used macros; for xml/html tag completion.

I use copy, cut and paste frequently. Most often I am cutting, copying and pasting just a single word (or token), so I wrote these macros to select a token and then copy or cup or paste. It saves me just that little bit of extra energy, since I don't have to select the token first. I added a bit of logic into each as well so that if I already have text selected, the macro will use that text instead of selecting the token under the cursor.

Copy token under cursor, or currently selected text. I map this to Alt+Z.

InsertMode
ColumnModeOff
HexOff
UnixReOff
IfSel
Copy
StartSelect
Else
SelectWord
Copy
StartSelect
EndIf

Cut token under cursor, or currently selected text. I map this to Alt+X.

InsertMode
ColumnModeOff
HexOff
UnixReOff
IfSel
StartSelect
Cut
Else
SelectWord
StartSelect
Cut
EndIf

Paste, replacing token under cursor, or currently selected text. I map this to Alt+Q.

InsertMode
ColumnModeOff
HexOff
UnixReOff
IfSel
StartSelect
Paste
EndSelect
Else
SelectWord
StartSelect
Paste
EndSelect
EndIf

This one isn't mine, but I don't remember where I got it from. Probably one of the truly excellent macros on the UltraEdit extras page.

Duplicate currently selected text or current line. I map this to Control+D.

ColumnModeOff
HexOff
Clipboard 9
ClearClipboard
IfSel
Cut
Paste
Paste
Find Up Select "^c"
Else
SelectLine
Cut
Paste
Key UP ARROW
Paste
PlayMacro 1 ""
EndIf
Clipboard 0

This one also isn't mine. I got it from an UltraEdit forum post: Automatically close tags.

Close most recent tag. I map this to Control+Shift+>.

InsertMode
ColumnModeOff
HexOff
UnixReOn
">"
Find Up "<"
IfFound
Clipboard 9
Key RIGHT ARROW
SelectWord 
Copy 
Find "<"
Find "<"
Key LEFT ARROW
"</"
Paste 
Find Up "<"
Key LEFT ARROW
Clipboard 0
Find ">"
Key RIGHT ARROW
EndIf
See my post UltraEdit macro for HTML/XML - auto-create closing tags for two other frequently used macros - these for completing HTML/XML tags.

Virtual Desktop Managers for XP

Linux has had desktop managers for ages - it was one of the biggest things that impressed me right off when I started using Linux years ago.

On Windows XP, I have been using Virtual Dimension 0.94 for quite some time and enjoyed it a lot. The things I like best about it are: 1) switching between desktops with different wall papers, 2) having only those apps in the desktop shown in the task bar.

Unfortunately, Virtual Dimension hasn't been updated for some time and is occasionally flaky.

  • Microsoft Outlook 2003 using Winword as the editor can often freeze Virtual Dimension, but I can usually fix that by killing Winword or Outlook in the Task Manager.
  • However, sometimes it freezes for other reasons, and if I kill it - the other desktops, and the programs stored therein - are lost to me and I need to re-boot.
  • Virtual Dimension doesn't have shortcuts for arbitrarily moving programs around desktops: up, down, left and right. You can only set short cuts for moving programs to the next/previous desktop or brining up a context menu to switch it to a selected desktop.
  • It does now always remember my settings between re-boots, particularly crashy re-boots.
  • The most annoying thing is that often a window goes nuts if you switch desktops while it is still doing something i.e. has the CPU. When that happens, the program appears on all desktops by mistake - and the application's icon doesn't appear in all desktops in the desktop tray either. You have to close and re-open the program, which is awkward.

None of these are huge errors in an of themselves, but since there is no movement in the project, I am willing to try something else.

As of this morning I am trying Vista/XP Virtual Desktop Manager, the port of the Vista Windows Desktop Manager. So far it seems a match in functionality - plus it has shortcuts to move applications up, down, left and right.

Virtual Dimension used about 8.2 MB for four desktops. Virtual Desktops right now is using 28.1 MB for four desktops. I will post more as I get to know it better.

Other desktop managers exist.

  • Another desktop manager for XP that I have not tried is VirtuaWin. It didn't win me over after reading Dennis O'Reilly's article Add virtual desktops to Windows XP, Vista.
  • XP has had a Virtual Desktop Manager power toy for some time, but it is very limited. 1) It has no shortcuts for moving applications to different desktops. 2) It doesn't hide applications. 3) And (most annoying) is the UI sits in the start menu taking up space rather than having just an icon in the tray.

Setting name attribute on an anchor via DOM Javascript in IE

This Javascript code creates a DOM ANCHOR element that I want to insert into my document somewhere.

var anchor = document.createElement("a");
anchor.name = "top";     // NOTE: set the anchor name.  
anchor.appendChild(document.createTextNode("Top"));

It should create the equivalent of this:

<a name="top">Top</a>

It works in Firefox (3.0.3), Google Chrome (0.2.149.30) and Safari (3.1.2). It doesn't work in Internet Explorer (7.0.5730.13).

Neither does this work in IE:

anchor.setAttribute("name", "top");

The only way I can get it to work in IE is by using ID instead of NAME. Either of these will work.

anchor.setAttribute("id", "top");
anchor.id = "top";

Thankfully, it works in Firefox, Google Chrome and Safari too.

Sunday, September 28, 2008

Can't get Firebug Lite working on IE?

Update, 12/08/2010 6:55:19 PM. This page is defunct. Try this one instead: A better way to handle debug logging in IE.

Update, 23/12/2008 11:44:05 PM. Added code from my own comments.

For those times when I cannot get Firebug Lite working in I.E. (or Chrome.. haven't tried Safari or Opera), I re-route my debug messages in I.E. to a text area by always calling this debug() method for my messages.

function debug(message) {
   if (typeof(console) != "undefined" ||
         typeof(console.debug) != "undefined") {
      console.debug(message);
   } else {
      if (document.getElementById("debugConsole") == null) {
         var textConsole = document.createElement("textarea");
         textConsole.id = "debugConsole";
         textConsole.rows = 10;
         textConsole.cols = 100;
         textConsole.readOnly = true;
         document.body.appendChild(textConsole);
         document.body.appendChild(document.createElement("br"));
         document.body.appendChild(document.createElement("br"));
      }
      document.getElementById("debugConsole").value += "\n" + message
   }
}

(From my comments.) Here is another alternative that provides proxies for some of the standard logging calls.

if (!window.console) {
 var textConsole = document.createElement("textarea");
 textConsole.id = "debugConsole";
 textConsole.rows = 10;
 textConsole.cols = 100;
 textConsole.readOnly = true;
 document.body.insertBefore(textConsole, document.body.firstChild);
 window.console = {
  log: function(message) {
   document.getElementById("debugConsole").value += "\n" + message;
  },
  debug: function(message) {
   document.getElementById("debugConsole").value += "\n" + message;
  },
  info: function(message) {
   document.getElementById("debugConsole").value += "\n" + message;
  },
  warn: function(message) {
   document.getElementById("debugConsole").value += "\n" + message;
  },
  error: function(message) {
   document.getElementById("debugConsole").value += "\n" + message;
  }
 };
}

Thursday, September 25, 2008

How to insert a date

Update: 21 February 2011, 11:57:26 AM. Stop the press: forget these shortcuts.. just use an AutoHotkey script that will work for ALL programs! Insert a date into any program using Autohotkey on Windows.


Here is how to insert a date for the different programs that I have had to do this for so far. Feel free to tell me how to do it for programs you use that I haven't listed here. :)

  • Eclipse: edit a template to put the time stamp in a comment for example, as per this newsgroup post: Insert Date/Timestamp in comment. Or make a new template with just a time stamp in it, as per this alternate reply to the previous post.
  • JEdit: you need a script. Here is a script by Robert Schwenn to insert a date.
  • Microsoft Excel: press control+;.
  • Microsoft Word 2003 and earlier: Alt, I, T or from the menu bar, select Insert > Date and Time. I like being able to select the date format here. Note that if you check the "Update Automatically" box, the date will be "dynamic" i.e. it will update to the current date whenever someone selects the date (or does a select all in the document) and presses F9 - in Windows.
  • Notepad: F5
  • UltraEdit: press F7 and get a date like this: 25/09/2008 3:36:32 PM.
  • Vim: roll your own function. I use this one in my .vimrc: :inoremap <F5> <C-R>=strftime("%c")<CR>. Check out the vim wikia page Insert current date or time for more info.

Excel: Displaying Autofilter Criteria

Edit: 19/3/2009. Updated with instructions for adding autofilter with Excel Office 2007 and before.

I love AutoFilter in Excel: it allows you to very easily sort or hide data in various ways.

Excel Office Pre 2007: Data > Filter > AutoFilter.

Excel Office 2007: Home (on Ribbon) > click Sort & Filter > Filter. See Tables Part 4: AutoFilter improvements: much more than just multi-select for more info.

The problem is that for complicated spreadsheets, it isn't always easy to tell what filters you have applied.

The above image indicates that the Numbers column is filtered by having that downward pointing triangle shaded blue. With a spreadsheet of 5, 10 or more columns, it is really hard to work out which of those small arrows are shaded. Worse, I can never remember exactly what filter I applied to each column.

What I do now is put a macro into the spreadsheet and a formula into the row above my headings that will show what filters have been applied i.e. display the AutoFilter criteria.

  1. Open your spreadsheet and press Alt+F11 to open the Microsoft Visual Basic Editor.
  2. Right click on the VBAProject entry for your spreadsheet (the spreadsheet file name is in brackets after VBAProject) > select Insert > Module.
  3. In the new pane that opens to the right, make sure that (General) is selected in the drop-down at top left. Then copy and paste Stephen Bullen's macro into the VB Editor, like so (the code is below the image).

    Here is the macro code.

    Function FilterCriteria(Rng As Range) As String
        'By Stephen Bullen
        Dim Filter As String
        Filter = ""
        On Error GoTo Finish
        With Rng.Parent.AutoFilter
            If Intersect(Rng, .Range) Is Nothing Then GoTo Finish
            With .Filters(Rng.Column - .Range.Column + 1)
                If Not .On Then GoTo Finish
                Filter = .Criteria1
                Select Case .Operator
                    Case xlAnd
                        Filter = Filter & " AND " & .Criteria2
                    Case xlOr
                        Filter = Filter & " OR " & .Criteria2
                End Select
            End With
        End With
    Finish:
        FilterCriteria = Filter
    End Function
    
  4. Close the VB Editor and go back to the spreadsheet.
  5. Insert a new row above the headings by putting the cursor into any heading cell and selecting from the menu bar: Insert > Rows.
  6. For each column that you wish to display the filter criteria for, go to the now empty row above the heading, press F2 in the cell and paste in this formula:
    =FilterCriteria(A2)&LEFT(SUBTOTAL(9,A5:A200),0)
    Correct A2 so that it correctly refers to the heading cell underneath the formula.

    You could put in just the function call by itself: =FilterCriteria(A2), but this doesn't automatically update the cell every time you change a filter. To make the formula update every time you change a filter, we add a dummy function LEFT(SUBTOTAL(9,A5:A200),0) that doesn't harm anything, just makes the spreadsheet re-evaluate the filter display whenever the filter is changed i.e. the calculation performed won't slow anything down and won't change anything displayed in the spreadsheet.

    Now, I can easily tell what AutoFilter criteria apply to my spreadsheet!

    Of course, there is an important disadvantage to this approach: you are putting a macro into your document, and Excel security settings apply. If the document is intended for wide distribution, consider carefully just how necessary this functionality is. Check your security settings (Tools > Macro > select Security Level tab in MS Excel 2003 and earlier). If the setting is Medium, the user will be asked whether they want to enable macros every single time they open the file. If the setting is above Medium, the macro will simply be ignored and the formula may display an error in each cell, since the function is calling a macro that isn't loaded. If the document is going to people you don't know, they may be very suspicious of a new document opening with a security warning! You can sign the macro, but that is not a trivial thing to do, at least the first time - and still requires the user to trust your signature.

  7. Freeze your panes! But wait! There's more! If I have a spreadsheet complicated enough to need AutoFilter, it will probably have more than enough data to fill a single screen, which means that scrolling down makes the headings (and AutoFilter criteria display) disappear. Before you actually apply any filtering, put the cursor into the left-most cell just below the headings i.e. cell A3 in those images above. Then select on the menu bar Window > Freeze Panes. Now you can scroll down as far as you like and the first two rows will remain visible at the top.

Pages that helped me make this entry.

Copying and Pasting Formatted Code in Blogger

I often see some nice HTML code on a web page and want to use it in Blogger.

<span><a href="http://www.blogger.com">Get your own blog!</a></span>

If you copy the above text, you will also copy the formatting that comes with it. To use it - as HTML - paste it into the Edit Html tab of a new Blogger post.

Or, paste it into something like Notepad or UltraEdit first, then copy and paste it from there - Notepad and UltraEdit are examples of text editors that ignore formatting information when you paste text into them. You can do the same with Word too: in Word 2003 and before, you select   Edit | Paste Special | Unformatted Text.

If you copy and paste it straight from the web page into the Compose tab of a new Blogger post, it will look as it did on the web page (or close to - some more complicated formatting might be ignored or not copied in its entirety).

But if you then click on the Edit Html tab, you will see that what you actually have is the code you wanted - formatted to look as it did on the page you copied it from. I.e. it might work to display the formatted code, but it won't work as HTML code itself.

As an author of blog posts, this is generally unavoidable even if you use no extra formatting! This is because the software e.g. Blogger, will automatically wrap text in formatting HTML of its own. For example, consider the below very plain piece of html.

<span><a href="http://www.blogger.com">Get your own blog!</a></span>

Copy that in compose mode (not HTML), and the line above becomes this:

&lt;span&gt;&lt;a href="http://www.blogger.com"&gt;Get your own blog!&lt;/a&gt;&lt;/span&gt;

No formatting at all: I used the HTML entities for < and > to avoid the code being evaluated as HTML, but there is no PRE, B I tags etc. Copy and paste this into the Compose tab of a new Blogger post and then look at the Edit Html tab - you will still see extra SPANs and other things, because Blogger is formatting all of my text.

Also see my other post, Bogger: Convert Line Breaks Setting for an idea about some other difficulties with posting code in Blogger - and a few alternatives for how to post code.

Thanks to Nithin for asking posting code in Blogger.

Wednesday, September 24, 2008

UltraEdit macro: act on selected text or whole document

Updates
15/06/2009 12:28:28 PM. Fixed up the example macro, which was broken (bad c&p plus forgot "GotoLine 1 1"). Added some additional explanation.

I often want my UltraEdit macros to act on the text I have selected or the whole document if I have no text selected. Here is a small macro I use often that demonstrates how to do this.

InsertMode
ColumnModeOff
HexOff
UnixReOff
IfSel
Find SelectText "<"
Replace All "&lt;"
Find SelectText ">"
Replace All "&gt;"
Find SelectText """
Replace All "&quot;"
Find SelectText "^t"
Replace All "  "
Else
GotoLine 1 1
Find "<"
Replace All "&lt;"
Find ">"
Replace All "&gt;"
Find """
Replace All "&quot;"
Find "^t"
Replace All "  "
EndIf

The red text is the guts of macro, i.e. what it does. It replaces:

  • the less than symbol "<" with "&lt;";
  • the greater than symbol ">" with "&gt;";
  • the double quote symbol """ with "&quot;"; and
  • tab characters with two spaces " ".

The blue text is the control logic. If you have text selected (IfSel), the actions will be performed only upon that selected text. Otherwise (Else), the logic will be applied accross the entire document (GotoLine 1 1 ... Find ... Replace All).

UltraEdit macros are purely procedural, so there isn't any way around repeating the slightly modified code in the IF and ELSE.

I think UltraEdit is very cool because it supports many ways to automate various things: look up tags, templates, macros and (JavaScript) scripts.

Friday, September 19, 2008

FatWire - dump all ICS variables

Often I get stuck in some element code or whatever, where the ICS variable I think is there, turns out not to be there. Rather than guess, it is often useful just to output all of the variables first and see if your variable is there but perhaps under a different name. Here is the code I use to dump out all the ICS variables for inspection.

In JSP, output the ICS variable names.

<div style="color: red">List ICS var names.</div>
<ul>
<%
java.util.Enumeration varNames = ics.GetVars();
while (varNames.hasMoreElements()) {
   %>
   <li><%= varNames.nextElement().toString() %></li>
   <%
}
%>
</ul>

In JSP, output the ICS variable names and values.

<div style="color: red">List ICS var names and values.</div>
<table border="1">
    <tr><th>Name</th><th>Value</th></tr>
    <%
    java.util.Enumeration varNames = ics.GetVars();
    while (varNames.hasMoreElements()) {
        String nextName = varNames.nextElement().toString();
        %><tr>
            <td><%= nextName %></td>
            <td><%= ics.GetVar(nextName) %></td>
        </tr><%
    }
    %>
</table>

In Java, output the ICS variable names and values.

java.util.Enumeration varNames = ics.GetVars();
while (varNames.hasMoreElements()) {
    String elementName = varNames.nextElement().toString();
    System.out.println("Element name  [" + elementName + "] with value  [" +
            ics.GetVar(elementName) + "].");
}