- Check if xfce4-panel is running. If not, start it using your user, just 'xfce4-panel' in a terminal window. That might do it.
- Remove ~/.config, log out, then log back in. That might do it. It might be overkill. Instead you might try deleting ~/.config/xfce4/panel, then log out and back in.
- Check ~/.config/xfce4/panel for a file named panel.xml. If you have one, delete it. Create a new one using this content:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE config SYSTEM "config.dtd">
<panels>
<panel>
<properties>
<property name="size" value="27"/>
<property name="monitor" value="0"/>
<property name="screen-position" value="10"/>
<property name="fullwidth" value="1"/>
<property name="xoffset" value="0"/>
<property name="yoffset" value="996"/>
<property name="handlestyle" value="0"/>
<property name="autohide" value="0"/>
<property name="transparency" value="25"/>
<property name="activetrans" value="0"/>
</properties>
<items>
<item name="xfce4-menu" id="5"/>
<item name="separator" id="6"/>
<item name="launcher" id="10"/>
<item name="launcher" id="11934103341"/>
<item name="launcher" id="11934284041"/>
<item name="actions" id="12"/>
<item name="separator" id="11934162861"/>
<item name="tasklist" id="11934220980"/>
<item name="datetime" id="11934096510"/>
</items>
</panel>
</panels>
Then log out and back in and the panels might reappear.
Tuesday, September 6, 2011
XFCE4 panel recovery
Every now and then the xfce4 panel will disappear. There are a number of bugs about this, but few solutions. I've gathered them here.
Wednesday, May 25, 2011
One of the best features of jEdit
Macros. The beanshell macro integration in jEdit is simply awesome. Here's an excellent example. Recently, a number of us at work are writing components for Day CQ5 (www.day.com), which is a high-end content management system. Most of the components are written as jsps. We are running local instance of CQ, but everything is packaged into jars, so it's not a simple matter of saving a changed jsp to the server with a regular save command. Fortunately, the server will reload a jsp that is sent to it with curl:
The Eclipse people run this from the command line, changing the filename and url by hand each time they move to a different file. I wrote a simple macro:
// macro to save and send a jsp file to a local Day instance
String filename = buffer.getPath();
// save the buffer and upload it to crx.
if (!buffer.isReadOnly()) {
buffer.save(view, null);
}
//String filepath = filename.substring(filename.indexOf("WebContent") +"WebContent".length());
String filepath = filename.substring(filename.indexOf("jcr_root") + "jcr_root".length());
String destination = "http://admin:admin@localhost:4502" + filepath;
String cmd = "curl -T " + filename + " " + destination;
exec(cmd);
Then I mapped a keyboard shortcut to Alt+S. Now whenever I want to save an edited jsp to the server, it is a simple keyboard command, no typing long paths in the command line. The Eclipse guys are somewhat jealous and I am saving quite a bit of time.
curl -T localfile destinationUrl
The Eclipse people run this from the command line, changing the filename and url by hand each time they move to a different file. I wrote a simple macro:
// macro to save and send a jsp file to a local Day instance
String filename = buffer.getPath();
// save the buffer and upload it to crx.
if (!buffer.isReadOnly()) {
buffer.save(view, null);
}
//String filepath = filename.substring(filename.indexOf("WebContent") +"WebContent".length());
String filepath = filename.substring(filename.indexOf("jcr_root") + "jcr_root".length());
String destination = "http://admin:admin@localhost:4502" + filepath;
String cmd = "curl -T " + filename + " " + destination;
exec(cmd);
Then I mapped a keyboard shortcut to Alt+S. Now whenever I want to save an edited jsp to the server, it is a simple keyboard command, no typing long paths in the command line. The Eclipse guys are somewhat jealous and I am saving quite a bit of time.
Monday, April 25, 2011
Cloudstor
Cloudstor, how to set up for direct mount in Ubuntu
There are two main reasons I set up a direct mount for my Cloudstor:
1) I can copy large files (greater than 1 GB) directly to the Cloudstor. The web interface won't allow copying of large files. I suspect that's a browser limitation moreso than the Cloudstor web app.
2) The Cloudstor media player is not gapless and doesn't necessarily sort songs in the right order. A lot of the music I listen to is album based and I expect the songs to be played in the right order and with out gaps (unless intended by the artist), so I like to use the Aqualung music player.
I tested this with Ubuntu 10.10 Desktop.
1. Download the Linux pogoplugfs application from:
http:pogoplug.com/downloads.html.
Unzip the pogoplugfs file to wherever you'd like.
2. Install fuse and associated helper files:
sudo apt-get install fusecram fusecompress-dbg fuseiso fusedav fusecompress fuse-utils fusefat fuseext2 fuseiso9660 fuse-zip hfsplus hfsutils-tcltk libhfsp0 libhfsp-dev hfsprogs hfsutils
3. Add your user to the fuse group:
sudo usermod -a -G fuse $(id -u -n)
Log out of Ubuntu and log back in. Open a new terminal window and enter:
groups
Make sure "fuse" is listed as one of the groups you belong to.
4. Create a mount point for your Cloudstor:
sudo mkdir /media/cloudstor
sudo chown root:fuse /media/cloudstor
sudo chmod oug+w /media/cloudstor
5. Run the pogoplug application:
/path/to/pogoplugfs --user yourusername --password yourpassword --mountpoint /media/cloudstor
Use the username and password you use to log into the cloudstor.pogoplug.com website.
I put this in a script and added it to my start up applications list.
Perhaps the best part about this is it works from anywhere. I can mount my Cloudstor drive as a local hard drive at work or when traveling, not just from within the local network at my house.
There are two main reasons I set up a direct mount for my Cloudstor:
1) I can copy large files (greater than 1 GB) directly to the Cloudstor. The web interface won't allow copying of large files. I suspect that's a browser limitation moreso than the Cloudstor web app.
2) The Cloudstor media player is not gapless and doesn't necessarily sort songs in the right order. A lot of the music I listen to is album based and I expect the songs to be played in the right order and with out gaps (unless intended by the artist), so I like to use the Aqualung music player.
I tested this with Ubuntu 10.10 Desktop.
1. Download the Linux pogoplugfs application from:
http:pogoplug.com/downloads.html.
Unzip the pogoplugfs file to wherever you'd like.
2. Install fuse and associated helper files:
sudo apt-get install fusecram fusecompress-dbg fuseiso fusedav fusecompress fuse-utils fusefat fuseext2 fuseiso9660 fuse-zip hfsplus hfsutils-tcltk libhfsp0 libhfsp-dev hfsprogs hfsutils
3. Add your user to the fuse group:
sudo usermod -a -G fuse $(id -u -n)
Log out of Ubuntu and log back in. Open a new terminal window and enter:
groups
Make sure "fuse" is listed as one of the groups you belong to.
4. Create a mount point for your Cloudstor:
sudo mkdir /media/cloudstor
sudo chown root:fuse /media/cloudstor
sudo chmod oug+w /media/cloudstor
5. Run the pogoplug application:
/path/to/pogoplugfs --user yourusername --password yourpassword --mountpoint /media/cloudstor
Use the username and password you use to log into the cloudstor.pogoplug.com website.
I put this in a script and added it to my start up applications list.
Perhaps the best part about this is it works from anywhere. I can mount my Cloudstor drive as a local hard drive at work or when traveling, not just from within the local network at my house.
Tuesday, December 14, 2010
How to check for an empty or blank string
PMD gives me an warning every now and then about "String.trim().length() == 0 is an inefficient way to validate an empty string". This message always annoys me because it doesn't offer an alternative. Looks like I need to fix the PMD plugin for jEdit, because if you read the rest of the rule in PMD, it does:
created during this loop. s.charAt() does a simple array look up.
Character.isWhitespace() also does a simple array look up plus some bit
checking, so it's pretty quick.
Name: InefficientEmptyStringCheck Description: String.trim().length() is an inefficient way to check if a String is really empty, as it creates a new String object just to check its size. Consider creating a static function that loops through a string, checking Character.isWhitespace() on each character and returning false if a non-whitespace character is found. Error Message: String.trim().length()==0 is an inefficient way to validate an empty String.
So I set about testing if this is the best way to check for an empty/blank String.
The PMD suggestion seems to be correct. The best I've come up with is this:
1 public static boolean isEmptyOrBlank(String s) { 2 if (s == null || s.length() == 0) { 3 return true; 4 } 5 for (int i = 0; i < s.length(); i++){ 6 if (!Character.isWhitespace(s.charAt(i))){ 7 return false; 8 } 9 } 10 return true; 11 }
This code works for either Java 1.5 or Java 1.6 equally well, performance-wise.
The Java 1.6 isEmpty method simply checks if the length of the string is 0,
so it really doesn't bring any performance enhancement to this issue.
The simple check is done on line 2.
- If the string is null, then it is obviously empty.
- If the length of the string is 0, then it is obviously empty.
created during this loop. s.charAt() does a simple array look up.
Character.isWhitespace() also does a simple array look up plus some bit
checking, so it's pretty quick.
Thursday, October 21, 2010
Zenburn color chart
Zenburn Color Chart
These colors and examples were extracted from the zenburn.vim file. I put them in a web page for easy reference as I adjust the zenburn theme for jEdit.Color Palette
| #000000 | |
| #000d18 | |
| #040404 | |
| #242424 | |
| #262626 | |
| #284f28 | |
| #2c2e2e | |
| #2c302d | |
| #2e2e2e | |
| #2e3330 | |
| #2f2f2f | |
| #313633 | |
| #313c36 | |
| #333333 | |
| #343434 | |
| #353535 | |
| #385f38 | |
| #3a3a39 | |
| #3f3f3f | |
| #3f4040 | |
| #41363c | |
| #434443 | |
| #464646 | |
| #4f4f4f | |
| #5b605e | |
| #688060 | |
| #6c6c9c | |
| #709080 | |
| #7cac7c | |
| #7f9f7f | |
| #80d4aa | |
| #82a282 | |
| #88b090 | |
| #8c8cbc | |
| #8cd0d3 | |
| #8f8f8f | |
| #8faf9f | |
| #93b3a3 | |
| #9ccc9c | |
| #9ece9e | |
| #9f9f9f | |
| #9fafaf | |
| #a0afa0 | |
| #b2b2a0 | |
| #b6bf98 | |
| #bc6c4c | |
| #bc6c9c | |
| #bc8cbc | |
| #bca3a3 | |
| #c0bed1 | |
| #c3bf9f | |
| #cbecd0 | |
| #cc9393 | |
| #ccdc90 | |
| #cfbfaf | |
| #cfcfaf | |
| #d0d0a0 | |
| #dc8c6c | |
| #dca3a3 | |
| #dcdccc | |
| #dfaf8f | |
| #dfcfaf | |
| #dfdfbf | |
| #dfdfdf | |
| #dfe4cf | |
| #e3ceab | |
| #e89393 | |
| #ecbcbc | |
| #efdcbc | |
| #efef8f | |
| #efefaf | |
| #efefef | |
| #f0dfaf | |
| #f0efd0 | |
| #f18c96 | |
| #f8f893 | |
| #ffcfaf | |
| #ffd7a7 | |
| #ffffe0 | |
| #ffffff |
Usage
| Item | Color | Example |
| Boolean | guifg=#dca3a3 | true |
| Character | guifg=#dca3a3 gui=bold | abcdef |
| Comment | guifg=#7f9f7f gui=italic | // abcdef |
| Conditional | guifg=#f0dfaf gui=bold | abcdef |
| Constant | guifg=#dca3a3 gui=bold | 123456 |
| Cursor | guifg=#000d18 guibg=#8faf9f gui=bold | abcdef |
| CursorColumn | guibg=#4f4f4f | |
| CursorLine | guibg=#434443 | |
| Debug | guifg=#bca3a3 gui=bold | abcdef |
| Define | guifg=#ffcfaf gui=bold | abcdef |
| Delimiter | guifg=#8f8f8f | abcdef |
| DiffAdd | guifg=#709080 guibg=#313c36 gui=bold | abcdef |
| DiffChange | guibg=#333333 | abcdef |
| DiffDelete | guifg=#333333 guibg=#464646 | abcdef |
| DiffText | guifg=#ecbcbc guibg=#41363c gui=bold | abcdef |
| Directory | guifg=#dcdccc gui=bold | abcdef |
| ErrorMsg | guifg=#80d4aa guibg=#2f2f2f gui=bold | abcdef |
| Exception | guifg=#c3bf9f gui=bold | abcdef |
| Float | guifg=#c0bed1 | 123.456 |
| FoldColumn | guifg=#93b3a3 guibg=#3f4040 | abcdef |
| Folded | guifg=#93b3a3 guibg=#3f4040 | abcdef |
| Function | guifg=#efef8f | abcdef |
| Identifier | guifg=#efdcbc | abcdef |
| IncSearch | guibg=#f8f893 guifg=#385f38 | abcdef |
| Keyword | guifg=#f0dfaf gui=bold | abcdef |
| Label | guifg=#dfcfaf gui=underline | abcdef |
| LineNr | guifg=#9fafaf guibg=#262626 | abcdef |
| Macro | guifg=#ffcfaf gui=bold | abcdef |
| MatchParen | guifg=#b2b2a0 guibg=#2e2e2e gui=bold | abcdef |
| ModeMsg | guifg=#ffcfaf gui=none | abcdef |
| MoreMsg | guifg=#ffffff gui=bold | abcdef |
| NonText | guifg=#5b605e gui=bold | abcdef |
| Normal | guifg=#dcdccc guibg=#3f3f3f | abcdef |
| Number | guifg=#8cd0d3 | abcdef |
| Operator | guifg=#f0efd0 | abcdef |
| PMenuSel | guibg=#242424 guifg=#d0d0a0 gui=bold | abcdef |
| PMenuThumb | guibg=#a0afa0 guifg=#040404 | abcdef |
| Pmenu | guibg=#2c2e2e guifg=#9f9f9f | abcdef |
| PmenuSbar | guibg=#2e3330 guifg=#000000 | abcdef |
| PreCondit | guifg=#dfaf8f gui=bold | abcdef |
| PreProc | guifg=#ffcfaf gui=bold | abcdef |
| Question | guifg=#ffffff gui=bold | abcdef |
| Repeat | guifg=#ffd7a7 gui=bold | abcdef |
| Search | guifg=#ffffe0 guibg=#284f28 | abcdef |
| SignColumn | guifg=#9fafaf guibg=#343434 gui=bold | abcdef |
| Special | guifg=#cfbfaf | abcdef |
| SpecialChar | guifg=#dca3a3 gui=bold | abcdef |
| SpecialComment | guifg=#82a282 gui=bold | abcdef |
| SpecialKey | guifg=#9ece9e | abcdef |
| SpellBad | guisp=#bc6c4c guifg=#dc8c6c | abcdef |
| SpellCap | guisp=#6c6c9c guifg=#8c8cbc | abcdef |
| SpellLocal | guisp=#7cac7c guifg=#9ccc9c | abcdef |
| SpellRare | guisp=#bc6c9c guifg=#bc8cbc | abcdef |
| Statement | guifg=#e3ceab gui=none | abcdef |
| StatusLine | guifg=#313633 guibg=#ccdc90 | abcdef |
| StatusLineNC | guifg=#2e3330 guibg=#88b090 | abcdef |
| StorageClass | guifg=#c3bf9f gui=bold | abcdef |
| String | guifg=#cc9393 | abcdef |
| Structure | guifg=#efefaf gui=bold | abcdef |
| TabLine | guifg=#b6bf98 guibg=#353535 gui=bold | abcdef |
| TabLineFill | guifg=#cfcfaf guibg=#353535 gui=bold | abcdef |
| TabLineSel | guifg=#efefef guibg=#3a3a39 gui=bold | abcdef |
| Tag | guifg=#e89393 gui=bold | abcdef |
| Title | guifg=#efefef gui=bold | abcdef |
| Todo | guifg=#dfdfdf guibg=bg gui=bold | abcdef |
| Type | guifg=#dfdfbf gui=bold | abcdef |
| Typedef | guifg=#dfe4cf gui=bold | abcdef |
| Underlined | guifg=#dcdccc gui=underline | abcdef |
| VertSplit | guifg=#2e3330 guibg=#688060 | abcdef |
| VisualNOS | guifg=#333333 guibg=#f18c96 gui=bold,underline | abcdef |
| WarningMsg | guifg=#ffffff guibg=#333333 gui=bold | abcdef |
| WildMenu | guibg=#2c302d guifg=#cbecd0 gui=underline | abcdef |
Tuesday, October 19, 2010
Elastic tab stops bug in jEdit
Rectangular selection is broken with elastic tab stops.
I started with some html. The buffer settings are html edit mode, no word wrap, tab width 3, indent width 3, soft tabs are off, elastic tab stops are on.
Then I did regex search and replace.
Search for: </td><td
Replace with: </td>\t<td
Looks good:
I wanted to insert additional style in the "Example" column, so I put the caret between 'style="' and 'color' on the second line, then CS+click in the same place on the last line. I get this:
Not so good. I tried in the second column, with similar results. Rectangular selection works in the first column, that is, before the first tab.
Just for fun, I typed an "x". That's really bad.
I started with some html. The buffer settings are html edit mode, no word wrap, tab width 3, indent width 3, soft tabs are off, elastic tab stops are on.
Then I did regex search and replace.
Search for: </td><td
Replace with: </td>\t<td
Looks good:
I wanted to insert additional style in the "Example" column, so I put the caret between 'style="' and 'color' on the second line, then CS+click in the same place on the last line. I get this:
Not so good. I tried in the second column, with similar results. Rectangular selection works in the first column, that is, before the first tab.
Just for fun, I typed an "x". That's really bad.
Wednesday, June 2, 2010
Gnome and Aqualung keyboard shortcuts
Aqualung doesn't integrate into Gnome directly as far as keyboard shortcuts go. What I want is to be able to press a key sequence and toggle pause and play. It turns out to be pretty easy:
First, start Aqualung and make sure the pause and play buttons are combined. There is a check box under Settings/General to combine them.
Then adjust Gnome:
1. Open gconf-editor
2. Drill down to apps/metacity/keybinding_commands
3. Double click on an empty command and enter:
aqualung -N0 --play
That is a zero.
4. Remember your command number, then go to apps/metacity/global_keybindings
5. Find the run_command that has the same number as your command number, then double click on it.
6. Type in the key sequence that you want for pause/play. I used
<Control><Alt>p
That's it.
Update 26 May 2011: I've switched to using KDE rather than Gnome. Here's how to set up the same keyboard shortcut in KDE:
Update 28 June 2011: I've dumped KDE and am now using Xubuntu. Here's how to set up the same keyboard shortcut for XFCE:
Update 15 Dec 2011: I'm still using Xubuntu, but somewhere along the way something changed. For step 5 above, use this for the command:
aqualung -N0 --pause
First, start Aqualung and make sure the pause and play buttons are combined. There is a check box under Settings/General to combine them.
Then adjust Gnome:
1. Open gconf-editor
2. Drill down to apps/metacity/keybinding_commands
3. Double click on an empty command and enter:
aqualung -N0 --play
That is a zero.
4. Remember your command number, then go to apps/metacity/global_keybindings
5. Find the run_command that has the same number as your command number, then double click on it.
6. Type in the key sequence that you want for pause/play. I used
<Control><Alt>p
That's it.
Update 26 May 2011: I've switched to using KDE rather than Gnome. Here's how to set up the same keyboard shortcut in KDE:
- Open the System Settings. On my installation, I click the "K", then Settings, then System Settings.
- Choose "Shortcuts and Gestures" from the Common Appearance and Behavior section.
- Select Custom Shortcuts.
- Click the Edit button (towards the bottom), then New, Global Shortcut, Command/URL.
- Enter a name for the new action, I used "Aqualung Pause/Play".
- On the Trigger tab, enter Ctrl+Alt+P by pressing those 3 buttons.
- On the Action tab, enter aqualung -N0 --play for the command.
- Click the Apply button at the bottom.
Update 28 June 2011: I've dumped KDE and am now using Xubuntu. Here's how to set up the same keyboard shortcut for XFCE:
- Open the Settings Manager. On my installation, I click the gear in the panel, then Settings, then Settings Manager.
- Choose "Keyboard".
- Select the "Applications Shortcuts" tab.
- Click the "Add" button.
- Enter aqualung -N0 --play for the command, click the "OK" button.
- Press Ctrl+Alt+p.
Update 15 Dec 2011: I'm still using Xubuntu, but somewhere along the way something changed. For step 5 above, use this for the command:
aqualung -N0 --pause
Thursday, May 20, 2010
Ubuntu 10.04, how to fix the volume control
One more thing missing in Ubuntu 10.04: the volume control. Apparently some knot-head at Canonical thought it would be a good idea to lump it in with the email/IM/Twitter notification applet, which I don't want to use. I just want the volume control. Here's how to put the old one back on the bar right now:
gnome-volume-control-applet &
To make it permanent, do this:
1. Go to System, Preferences, Startup Applications
2. Click Add
3. Enter these in the appropriate boxes:
Name: Volume Control
Command: gnome-volume-control-applet
Comment: Show desktop volume control
4. Save and close
Lots of whining about this screwup on the intertubes.
gnome-volume-control-applet &
To make it permanent, do this:
1. Go to System, Preferences, Startup Applications
2. Click Add
3. Enter these in the appropriate boxes:
Name: Volume Control
Command: gnome-volume-control-applet
Comment: Show desktop volume control
4. Save and close
Lots of whining about this screwup on the intertubes.
How to install Sun Java 6 on Ubuntu 10.04
As usual, doing an upgrade for Ubuntu removed some things I'd had installed. The main annoyance is Java. I do java development for a living. All of my customers use Sun Java, no one uses OpenJDK. While the idea of installing OpenJDK is great, it's just not ready for prime time. Furthermore, if I had Sun Java installed already, why remove it? Ubuntu has made it even more cryptic on how to install Sun Java. Here are the steps:
sudo add-apt-repository "deb http://archive.canonical.com/ lucid partner"
sudo apt-get update
sudo apt-get install sun-java6-jdk sun-java6-plugin
Once the install is complete, do:
sudo update-alternatives --config java
and select Sun Java.
Confirm by running:
java --version
You should see:
java version "1.6.0_20"
Java(TM) SE Runtime Environment (build 1.6.0_20-b02)
Java HotSpot(TM) Client VM (build 16.3-b01, mixed mode, sharing)
sudo add-apt-repository "deb http://archive.canonical.com/ lucid partner"
sudo apt-get update
sudo apt-get install sun-java6-jdk sun-java6-plugin
Once the install is complete, do:
sudo update-alternatives --config java
and select Sun Java.
Confirm by running:
java --version
You should see:
java version "1.6.0_20"
Java(TM) SE Runtime Environment (build 1.6.0_20-b02)
Java HotSpot(TM) Client VM (build 16.3-b01, mixed mode, sharing)
Wednesday, May 19, 2010
Upgraded to Ubuntu 10.04
I upgraded my laptop to Ubuntu 10.04 this evening. I've been running it on my work laptop for a while and on my desktop in the basement, and it's been great. On both of those computers I did a new install instead of an upgrade.
For the first time ever, I was able to do the upgrade completely over a wireless network. In the past, Ubuntu removed the Broadcom driver I'd installed by hand and refused to replace it. This time I got a message asking if I'd like to install it, and it did. Nice!
But that brings up my major complaint with Ubuntu upgrades. It removed apps that I had specifically installed. It should ask. My Sun JDK was removed and OpenJDK was installed in it's place. xscreensaver was uninstalled, but at least gnome-screensaver was not installed. It'll probably take me a few days to figure out what else is missing.
Another pain with 10.04 is they moved the window buttons to the left. Beats me why, I can't think of a good reason when it's been on the right for literally years. Just to fuck with people, I think. The fix is relatively easy, but not for joe average user:
1. Fire up gconf-editor
2. Drill down to /apps/metacity/general
3. Change the "button_layout" value menu:maximize,minimize,close
That is all.
For the first time ever, I was able to do the upgrade completely over a wireless network. In the past, Ubuntu removed the Broadcom driver I'd installed by hand and refused to replace it. This time I got a message asking if I'd like to install it, and it did. Nice!
But that brings up my major complaint with Ubuntu upgrades. It removed apps that I had specifically installed. It should ask. My Sun JDK was removed and OpenJDK was installed in it's place. xscreensaver was uninstalled, but at least gnome-screensaver was not installed. It'll probably take me a few days to figure out what else is missing.
Another pain with 10.04 is they moved the window buttons to the left. Beats me why, I can't think of a good reason when it's been on the right for literally years. Just to fuck with people, I think. The fix is relatively easy, but not for joe average user:
1. Fire up gconf-editor
2. Drill down to /apps/metacity/general
3. Change the "button_layout" value menu:maximize,minimize,close
That is all.
Thursday, May 13, 2010
A fix for Chrome to view javadocs
A few versions ago, Chrome broke the viewing of javadocs from the local file system. Well, not javadocs exactly, but any set of pages using a frameset that exists on the local file system. I generally download javadoc files for the various packages I'm working with. Having them local means I can access them even if my laptop is disconnected. What broke was that rather than having the links in the left side open in the main frame, Chrome opens them in a new tab, which is real annoying since all the navigation for the frameset is not on the new tab. I ended up going back to Firefox for most browsing just because of this bug.
This bug was first reported to Google in early April, and still isn't fixed. There has been a lot of discussion on various news groups and in the bug itself. A fix is being worked on, but in the bug there is a reference to a command-line option that will work in the mean time. Start Chrome like this:
/usr/bin/google-chrome --allow-file-access-from-files
In Ubuntu, I have Chrome on the quick-launch bar, so I just right clicked on the icon, selected properties, and pasted this line into the "command" box.
Friday, May 7, 2010
How to change password for Gnome Keyring Manager
I got a new laptop recently, then changed my login password shortly after installing Ubuntu. The Gnome keyring manager was still using the old password, so every time I restarted the machine, I was prompted for the keyring password. It isn't obvious how to change this. I did quite a bit of googling and found a lot of questions about it, but no solution that works for Ubuntu 10.04 with Gnome.
Here is the answer:
1. Log in as usual. Enter your old password in the keyring manager when it asks you to.
2. On the main Ubuntu menu, go to Accessories, Passwords and Encryption Keys.
3. On the Passwords tab, right click on "Passwords: login". This was the non-obvious part.
4. Choose "Change Password". Fill in your old password and your new password.
All done.
It looks like how this has been done has gone through a lot of changes over the past couple of years, so these instructions will likely be out of date when 10.10 comes out.
Here is the answer:
1. Log in as usual. Enter your old password in the keyring manager when it asks you to.
2. On the main Ubuntu menu, go to Accessories, Passwords and Encryption Keys.
3. On the Passwords tab, right click on "Passwords: login". This was the non-obvious part.
4. Choose "Change Password". Fill in your old password and your new password.
All done.
It looks like how this has been done has gone through a lot of changes over the past couple of years, so these instructions will likely be out of date when 10.10 comes out.
Wednesday, March 10, 2010
Subversion server moved, how to fix local working copies
I ran into a problem recently with a project from SourceForge. SF had changed the name on the Subversion server so it is now per project. The old repository url was
https://svn.sourceforge.net/svnroot/jedit/plugins/Beauty/trunk
and the new one is:
https://jedit.svn.sourceforge.net/svnroot/jedit/plugins/Beauty/trunk
Since I'm the only one working on this project, and the current code is what I last checked in, I didn't bother to do an update before making some significant changes, otherwise, I might have noticed the problem earlier. When I went to commit, I got this rather cryptic message:
Committing ...
svn: Commit failed (details follow):
svn: Repository moved temporarily to '/svnroot/jedit/plugins/Beauty/trunk'; please relocate
svn: OPTIONS request failed on '/svnroot/jedit/plugins/Beauty/trunk'
It took a little digging around to figure out the problem was that the name of the repository had changed. I knew about it, but it happened a while ago, so I'd forgotten.
https://svn.sourceforge.net/svnroot/jedit/plugins/Beauty/trunk
and the new one is:
https://jedit.svn.sourceforge.net/svnroot/jedit/plugins/Beauty/trunk
Since I'm the only one working on this project, and the current code is what I last checked in, I didn't bother to do an update before making some significant changes, otherwise, I might have noticed the problem earlier. When I went to commit, I got this rather cryptic message:
Committing ...
svn: Commit failed (details follow):
svn: Repository moved temporarily to '/svnroot/jedit/plugins/Beauty/trunk'; please relocate
svn: OPTIONS request failed on '/svnroot/jedit/plugins/Beauty/trunk'
It took a little digging around to figure out the problem was that the name of the repository had changed. I knew about it, but it happened a while ago, so I'd forgotten.
I didn't want to have to check out from the new repository location and copy my old working files. Using "svn switch" won't work because "switch" requires the files to be within the same repository. All I needed to do was fix the "entries" files in my local .svn directories. This little script does it:
for i in `grep -rl 'https://svn.sourceforge.net' .*`; do
sed --in-place -e 's/https:\/\/svn.sourceforge.net/https:\/\/jedit.svn.sourceforge.net/g' "$i"
done
1st line: grep for the string I want to replace
2nd line: replace it. Notice that the slashes in the url have to be escaped.
A word of warning: The ".*" pattern on the 1st line matches "..", which means this will search and replace not only in the current working directory, but also the parent directory. In my case, that is a good thing, since I have a number of jEdit plugin projects in the parent directory and this changed them all at once for me. If you don't want that to happen, make a new, empty directory, copy your working copy directory into this new directory, so that when you run this script from within your working copy directory, there is nothing else in the parent directory to be affected.
Saturday, February 27, 2010
Capturing audio from a flash file
Suppose you have a flash file that you want to extract the audio from. Perhaps it's an educational thing where the video really doesn't add much to the information, and you just want the audio so you can listen to it on your way to work.
You can use this script to download a flash file from YouTube:
http://www.catonmat.net/blog/revisiting-gnu-awk-youtube-video-downloader/
To run this script, just do
gawk -f path/to/get_youtube_vids.awk url/to/youtube/page
e.g.
gawk -f ./get_youtube_vids.awk http://www.youtube.com/watch?v=N_AqSbgMMS8
Copy the url out of the location bar of the browser. This created a file named N_AqSbgMMS8.flv in the current directory. This script should show progress, but that part seems to be broke. It'll claim to be at 0% for the entire download. It's better to check the file system for progress.
To dump the audio portion of the file, run ffmpeg from the command line. First do this:
ffmpeg -i N_AqSbgMMS8.flv
and see something like this:
Seems stream 0 codec frame rate differs from container frame rate: 1000.00 (1000/1) -> 25.00 (25/1)
Input #0, flv, from 'N_AqSbgMMS8.flv':
Duration: 00:08:16.36, start: 0.000000, bitrate: 103 kb/s
Stream #0.0: Video: flv, yuv420p, 320x240, 95 kb/s, 25 tbr, 1k tbn, 1k tbc
Stream #0.1: Audio: mp3, 22050 Hz, stereo, s16, 8 kb/s
At least one output file must be specified
Then run this:
ffmpeg -i N_AqSbgMMS8.flv -vn -ar 22050 -ac 2 -ab 64 -f ogg bettername.ogg
-vn means no video
-ar means audio sampling frequency, set it to the same as in the output from ffmpeg -i
-ac means the number of channels, so if ffmpeg says 'stereo', use 2, if ffmpeg says 'mono', use 1
-ab is bit rate, the default is 64k
-f is the output format. "mp3" could be used in place of "ogg", but the restricted codecs would need to be installed. You can check the supported formats by running 'ffmpeg -formats'.
The ogg output produces a file that is a little weird. mplayer plays it from the command line just fine. Exaile adds it to the playlist, but the line in the playlist is blank. Exaile does play the file, though. Aqualung doesn't even seem to be able to load the file at all. No complaints from vlc.
To install the restricted formats, google around for "ubuntu restricted codecs" to find suitable instructions. After that, use synaptic to install both libavcodec-extra-52 and libavformat-extra-52 on Ubuntu 9.10. The mp3 file that is created works on all 4 of the players I tested, although Exaile still shows a blank line in the playlist. Maybe that's just a bug in Exaile.
Saturday, February 6, 2010
Epson NX510 scanner and Ubuntu 9.04
My wife got a printer/scanner/copier/fax combo machine for Christmas. Today I finally got around to setting it up for her.
- I found the drivers for it here: http://avasys.jp/eng/linux_driver/
There are drivers for a number of Epson printers there also. - I downloaded these files:
- Epson-Stylus_NX510-pipslite-en.ppd
- pipslite_1.4.0-5_i386.deb
- iscan-network-nt_1.1.0-2_i386.deb
- iscan_2.23.0-3_i386.deb
- Installed pipslite first. It whined about libltdl3 being missing, so I did:
sudo ln -s libltdl.so.7 libltdl.so.3
then
sudo dpkg --ignore-depends=libltdl3 -i pipslite_1.4.0-5_i386.deb - Now the printer driver (the ppd file) can be installed using the printer manager, just choose the ppd file when it asks for one.
- It turns out the iscan-network package isn't necessary since I didn't set the printer up as a network printer.
- To install the iscan app, first ensure xsane > 1.0.3 is installed. I already had xsane 1.0.14, so I was good.
- Install iscan:
sudo dpkg --ignore-depends=libltdl3 -i iscan_2.23.0-3_i386.deb - Now try to start xsane. It will likely complain about permissions. Run:
lsusb
Find your scanner in the output, making note of the bus and device number. My scanner was bus 001, device 008, so now do this:
sudo chmod a+w /dev/bus/usb/001/008
Now xsane and iscan both start with no trouble. - If you tried to start xsane as root befor step 8, you'll get some errors when quitting xsane. That's because root owns the config files in ~/.sane. Just delete the ~/.sane directory and all will be well.
- Since I installed 2 packages with "ignore-depends", both dpkg and synaptic will complain about broken packages and want to uninstall them when trying to install some new package. To fix this:
- Make a backup of /var/lib/dpkg/status
- Edit /var/lib/dpkg/status, find the iscan package.
- Find the dependencies line, and remove the reference to libltdl.so.3.
- Repeat for pipslite.
- Save /var/lib/dpkg/status.
- Now dpkg and synaptic will not try to remove your newly installed scanner apps and printer driver.
Sunday, January 17, 2010
Programming Fonts
Over the years, I've tried a lot of different fonts for writing code. Code is different from regular narrative text. Code has more defined structure to it, where certain items need to line up to better understand the context and meaning of the code. Most languages don't enforce such structure, but coding conventions and good style guidelines do. Invariably, monospaced fonts are required to meet these guidelines. I've seen people code with proportional fonts, and it is clear that they are missing out on the organizational properties provided by monospaced fonts. Fortunately, the font is not part of the code itself, so each programmer is free to choose the font he likes best.
While I've tried a lot of fonts, I've only used 4 fonts for day-to-day work. These are my personal favorites as I find them to be clear and easy to read. The screenshots below were all taken of the fonts as displayed in jEdit. The font size in all screenshots is 16. I generally set my font size to 11, but I increased the size for the screenshots so it is easier to see the finer details. I took these screenshots on my laptop, so I have jEdit set to render fonts with subpixel anti-aliasing.
Courier New
I used Courier New for years. When I first started programming professionally, I was on Windows 3.0. Courier came with, and is a good, solid font.

There are a few problems with Courier that caused me to start looking for a new font. First is the lowercase L and the number 1 look very similar. There is not a big distinction between uppercase O and number 0. There is also not much distinction between curly brackets and round brackets. So I looked around and found the Bitstream font family.
Bitstream Vera Sans Mono
This is a very nice, crisp, clean font.

There is good distinction between number 1, lowercase L, and uppercase I. Zero and uppercase O are unambiguous, with zero having a dot in the middle. My only issue with this font is the curly brackets are distorted at smaller font sizes. I generally use font size 11 for writing code, and curly brackets are a bit scrunched, and even more so in comments. I used this font for a good number of years, then I found Inconsolata.
Inconsolata
This is a modern font developed specifically for programming work. It is based on the Consola font that is distributed with Windows Vista. I used it for a while, but the lowercase G bothered me. I know that is a really minor thing, this is really a great font.

One other minor issue with this font is the single and double quotes are slightly curved. There is a "dz" version of Inconsolata (google inconsolata-dz) that replaces the curved quotes with straight quotes, which is nice. Also, the lowercase L looks a lot like the number 1 in a lot of other fonts. It's easy to tell that the number 1 is a one, but not so easy to tell if the lowercase L is an L or a one when it is not right next to a one.
DejaVu Sans Mono
Currently, I'm using DejaVu Sans Mono, and have been for the past few months. It looks very clean and crisp on both my laptop screen and on the LCD screens I have at work. DejaVu is a modern replacement for the Bitstream Vera font that I used for years, so it's not surprising that I like this font.

This font has all the good features of Bitstream Vera, and it scales better. The curly brackets are not scrunched at smaller font sizes. Like Bitstream Vera, it retains the mini-serifs on the upper and lower case I and J and on the lower case L, which adds a little bit of flair to this font and helps distinguish the upper case I from the lower case L and the number 1.
While I've tried a lot of fonts, I've only used 4 fonts for day-to-day work. These are my personal favorites as I find them to be clear and easy to read. The screenshots below were all taken of the fonts as displayed in jEdit. The font size in all screenshots is 16. I generally set my font size to 11, but I increased the size for the screenshots so it is easier to see the finer details. I took these screenshots on my laptop, so I have jEdit set to render fonts with subpixel anti-aliasing.
Courier New
I used Courier New for years. When I first started programming professionally, I was on Windows 3.0. Courier came with, and is a good, solid font.

There are a few problems with Courier that caused me to start looking for a new font. First is the lowercase L and the number 1 look very similar. There is not a big distinction between uppercase O and number 0. There is also not much distinction between curly brackets and round brackets. So I looked around and found the Bitstream font family.
Bitstream Vera Sans Mono
This is a very nice, crisp, clean font.

There is good distinction between number 1, lowercase L, and uppercase I. Zero and uppercase O are unambiguous, with zero having a dot in the middle. My only issue with this font is the curly brackets are distorted at smaller font sizes. I generally use font size 11 for writing code, and curly brackets are a bit scrunched, and even more so in comments. I used this font for a good number of years, then I found Inconsolata.
Inconsolata
This is a modern font developed specifically for programming work. It is based on the Consola font that is distributed with Windows Vista. I used it for a while, but the lowercase G bothered me. I know that is a really minor thing, this is really a great font.

One other minor issue with this font is the single and double quotes are slightly curved. There is a "dz" version of Inconsolata (google inconsolata-dz) that replaces the curved quotes with straight quotes, which is nice. Also, the lowercase L looks a lot like the number 1 in a lot of other fonts. It's easy to tell that the number 1 is a one, but not so easy to tell if the lowercase L is an L or a one when it is not right next to a one.
DejaVu Sans Mono
Currently, I'm using DejaVu Sans Mono, and have been for the past few months. It looks very clean and crisp on both my laptop screen and on the LCD screens I have at work. DejaVu is a modern replacement for the Bitstream Vera font that I used for years, so it's not surprising that I like this font.

This font has all the good features of Bitstream Vera, and it scales better. The curly brackets are not scrunched at smaller font sizes. Like Bitstream Vera, it retains the mini-serifs on the upper and lower case I and J and on the lower case L, which adds a little bit of flair to this font and helps distinguish the upper case I from the lower case L and the number 1.
Tuesday, January 12, 2010
A JTree expansion model
At long last, a technical post!
Recently, I had a need to build a JTree from scratch, and wanted certain nodes in that tree expanded, while others remained collapsed. In my particular situation, I was working on the JavaSideKick plugin to jEdit. The JavaSideKick shows the important parts of a java file. Clicking on the tree moves the caret in the text editor area to the code associated with the node in the tree. If you're an Eclipse user, this is the same as the 'outline' feature, although SideKick is older and has more features than the Eclipse version. So, I had these requirements to display a java file in a tree display:
1. The compilation unit would be expanded.
2. The import node would be visible and not expanded, but would be able to be expanded.
3. The class node(s) would be expanded.
4. The method nodes would be visible.
5. Any inner classes would be expanded so their fields and methods would be visible.
6. Any enum nodes would be visible and not expanded, but would be able to be expanded.
Here is a working example. Notice the ExpansionModel class at the bottom, lines 100 - 127. It is very simple, it is just a wrapper around a list of row numbers to be expanded and a couple of methods to make it easy to build up the model. The top part of the code builds an example tree based on the requirements above and applies the ExpansionModel in lines 85 - 87.
Recently, I had a need to build a JTree from scratch, and wanted certain nodes in that tree expanded, while others remained collapsed. In my particular situation, I was working on the JavaSideKick plugin to jEdit. The JavaSideKick shows the important parts of a java file. Clicking on the tree moves the caret in the text editor area to the code associated with the node in the tree. If you're an Eclipse user, this is the same as the 'outline' feature, although SideKick is older and has more features than the Eclipse version. So, I had these requirements to display a java file in a tree display:
1. The compilation unit would be expanded.
2. The import node would be visible and not expanded, but would be able to be expanded.
3. The class node(s) would be expanded.
4. The method nodes would be visible.
5. Any inner classes would be expanded so their fields and methods would be visible.
6. Any enum nodes would be visible and not expanded, but would be able to be expanded.
Here is a working example. Notice the ExpansionModel class at the bottom, lines 100 - 127. It is very simple, it is just a wrapper around a list of row numbers to be expanded and a couple of methods to make it easy to build up the model. The top part of the code builds an example tree based on the requirements above and applies the ExpansionModel in lines 85 - 87.
1
2 import java.util.*;
3 import javax.swing.*;
4 import javax.swing.tree.*;
5
6 public class TreeTest {
7 public static void main ( String[] args ) {
8 new TreeTest();
9 }
10
11 public TreeTest() {
12 try {
13 SwingUtilities.invokeAndWait(
14 new Runnable() {
15 public void run() {
16 ExpansionModel em = new ExpansionModel();
17
18 DefaultMutableTreeNode root = new DefaultMutableTreeNode( "cu" );
19 em.add();
20 DefaultMutableTreeNode imports = new DefaultMutableTreeNode( "Imports" );
21 root.add( imports );
22 em.inc();
23
24 imports.add( new DefaultMutableTreeNode( "import 1" ) );
25 imports.add( new DefaultMutableTreeNode( "import 2" ) );
26 imports.add( new DefaultMutableTreeNode( "import 3" ) );
27 imports.add( new DefaultMutableTreeNode( "import 4" ) );
28 imports.add( new DefaultMutableTreeNode( "import 5" ) );
29 imports.add( new DefaultMutableTreeNode( "import 6" ) );
30 imports.add( new DefaultMutableTreeNode( "import 7" ) );
31
32 DefaultMutableTreeNode classNode = new DefaultMutableTreeNode( "class" );
33 root.add( classNode );
34 em.add();
35 classNode.add( new DefaultMutableTreeNode( "method 1" ) );
36 em.add();
37 classNode.add( new DefaultMutableTreeNode( "method 2" ) );
38 em.add();
39 classNode.add( new DefaultMutableTreeNode( "method 3" ) );
40 em.add();
41 classNode.add( new DefaultMutableTreeNode( "method 4" ) );
42 em.add();
43 classNode.add( new DefaultMutableTreeNode( "method 5" ) );
44 em.add();
45 classNode.add( new DefaultMutableTreeNode( "method 6" ) );
46 em.add();
47 classNode.add( new DefaultMutableTreeNode( "method 7" ) );
48 em.add();
49
50 DefaultMutableTreeNode innerClass = new DefaultMutableTreeNode( "inner class" );
51 classNode.add( innerClass );
52 em.add();
53 innerClass.add( new DefaultMutableTreeNode( "inner method 1" ) );
54 em.add();
55 innerClass.add( new DefaultMutableTreeNode( "inner method 2" ) );
56 em.add();
57 innerClass.add( new DefaultMutableTreeNode( "inner method 3" ) );
58 em.add();
59 innerClass.add( new DefaultMutableTreeNode( "inner method 4" ) );
60 em.add();
61 innerClass.add( new DefaultMutableTreeNode( "inner method 5" ) );
62 em.add();
63 innerClass.add( new DefaultMutableTreeNode( "inner method 6" ) );
64 em.add();
65
66 DefaultMutableTreeNode enumNode = new DefaultMutableTreeNode( "enum" );
67 classNode.add( enumNode );
68 em.inc();
69 enumNode.add( new DefaultMutableTreeNode( "enum value 1" ) );
70 enumNode.add( new DefaultMutableTreeNode( "enum value 2" ) );
71 enumNode.add( new DefaultMutableTreeNode( "enum value 3" ) );
72 enumNode.add( new DefaultMutableTreeNode( "enum value 4" ) );
73 enumNode.add( new DefaultMutableTreeNode( "enum value 5" ) );
74 enumNode.add( new DefaultMutableTreeNode( "enum value 6" ) );
75 enumNode.add( new DefaultMutableTreeNode( "enum value 7" ) );
76
77 JTree tree = new JTree( root );
78 JFrame frame = new JFrame();
79
80 // might want EXIT_ON_CLOSE if running from command line
81 frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
82
83 frame.getContentPane().add( tree );
84 frame.setSize(400, 600);
85 for (int row : em.getModel()) {
86 tree.expandRow(row);
87 }
88
89 frame.setVisible( true );
90 }
91 }
92 );
93
94 }
95 catch ( Exception e ) {
96 e.printStackTrace();
97 }
98 }
99
100 public class ExpansionModel {
101 private List<Integer> model = new ArrayList<Integer>();
102 private int row = 0;
103
104 /**
105 * @return The expansion model, set this in SideKickParsedData.
106 */
107 public List<Integer> getModel() {
108 return model;
109 }
110
111 /**
112 * Call this for each visible row in the tree that should be expanded.
113 * This will add the current row number to the model and automatically
114 * inc.
115 */
116 public void add() {
117 model.add( row );
118 inc();
119 }
120
121 /**
122 * Call this for each visible row in the tree.
123 */
124 public void inc() {
125 ++row;
126 }
127 }
128
129 }
Subscribe to:
Posts (Atom)




