Tuesday, October 14, 2025

A Solution to the “emacs expired key” issue when running “M-x list-packages”.

When trying to install a package with “M-x package-install”, or list the available packages with “M-x list-packages”, you get this error:

  Failed to verify signature archive-contents.sig:

  No public key for 645357D2883A0966 created at 2025-10-13T17:10:04-0400 using EDDSA

  Command output:

  gpg: Signature made Mon 13 Oct 2025 05:10:04 PM EDT

  gpg:                using EDDSA key 0327BE68D64D9A1A66859F15645357D2883A0966

  gpg: Can't check signature: No public key

The problem is that the GPG key for elpa.gnu.org has expired, so packages can't be updated.  To update the key, you need to install the gnu-elpa-keyring-update package, which you can't do, because the GPG key has expired.

It's a chicken and egg issue.

The solution is to turn off GPG security just long enough to install the new key.

First, verify the issue.  This step is optional, but it will give you peace of mind.

From a shell, run: “gpg --homedir ~/.emacs.d/elpa/gnupg --list-keys

   /home/your.name/.emacs.d/elpa/gnupg/pubring.kbx

   --------------------------------------------

   pub   dsa2048 2014-09-24 [SC] [expired: 2019-09-23]

CA442C00F91774F17F59D9B0474F05837FBDEF9B

   uid           [ expired] GNU ELPA Signing Agent (2014) <elpasign@elpa.gnu.org>

   pub   rsa3072 2019-04-23 [SC] [expired: 2024-04-21]

C433554766D3DDC64221BFAA066DAFCB81E42C40

   uid           [ expired] GNU ELPA Signing Agent (2019) <elpasign@elpa.gnu.org>

You should see one or more keys from elpasign@elpa.gnu.org.  In the case above, notice they're both expired.  That's the problem to fix.

Start a pristine instance of emacs.  A pristine instance keep any local config options from stomping around.

  emacs -q

List the packages with “M-x list-packages”.  The command should fail, but running it will load the “package” module.

Verify that GPG security is on by checking the package-check-signature variable in the *scratch* buffer.

  package-check-signature

The results are usually “allow-unsigned”, but anything besides “nil” means security is on.

Turn off GPG checking by running this 1 line program in the *scratch* buffer.

  (setq package-check-signature nil)

Refresh the package list with “M-x list-packages”.  This time it should run with no errors.

Now to update the GPG key.

Search the *Packages* buffer for the “gnu-elpa-keyring-update” package.

Press <RETURN> to see its description.  The description should be something like “Update Emacs's GPG keyring for GNU ELPA”.

Use “i” to mark the package for install.

Use “x” to execute the install.

It will prompt you to install the package.  Type “y” to do the install.

From the shell, verify that only thing that got updated is the new elpasign key.

  gpg --homedir ~/.emacs.d/elpa/gnupg --list-keys

    /home/your.name/.emacs.d/elpa/gnupg/pubring.kbx

    --------------------------------------------

    pub   dsa2048 2014-09-24 [SC] [expired: 2019-09-23]

  CA442C00F91774F17F59D9B0474F05837FBDEF9B

    uid           [ expired] GNU ELPA Signing Agent (2014) <elpasign@elpa.gnu.org>

    pub   rsa3072 2019-04-23 [SC] [expired: 2024-04-21]

  C433554766D3DDC64221BFAA066DAFCB81E42C40

    uid           [ expired] GNU ELPA Signing Agent (2019) <elpasign@elpa.gnu.org>

    pub   ed25519 2022-12-28 [C] [expires: 2032-12-25]

  AC49B8A5FDED6931F40EE78BF993C03786DE7ECA

    uid           [ unknown] GNU ELPA Signing Agent (2023) <elpasign@elpa.gnu.org>

    sub   ed25519 2022-12-28 [S] [expires: 2032-12-25]

    sub   ed25519 2024-10-22 [S] [expires: 2034-10-20]

Note the new key that expires in 2032-12-25 and no unexpected keys are found.

To restore the GPG security, just exit and restart emacs.  You can verify that security is back by checking “package-check-signature” variable in *scratch*.  It should be the same as when you checked it earlier.

Run “M-x list-packages”.  The packages should list normally, and you should be good to go.

Monday, June 25, 2012

Wallpapering the Galaxy

I recently bought a "Samsung Galaxy Nexus gt-19250m". So far I'm enjoying the phone, but one of the things that drove me crazy was trying to figure out the proper size for the wallpaper image.  Allow me to save you that burden.

The Nexus's physical screen is 720 pixels wide by 1280 pixels high. Only half of the wallpaper's width is displayed at a time, whereas the entire height is displayed. Grinding the math gives an optimal wallpaper size of (720 * 2) x 1280, or 1440 x 1280.

Unfortunately, it's not as easy as that. Although the Nexus screen is, in fact, 1280 pixels high, the top 98 pixels are covered by the notification area and the bottom 48 pixels are covered by the soft keys. Griding that math again gives us 1280 - (98 + 48) or 1134 pixels.

Long story short:

To make a wallpaper image that won't get cropped or stretched, you need to create a 1440 x 1280 pixel image, with the actual visible part of the image is 1440 x 1134 pixels, and shifted down 98 pixels from the top.

Monday, August 1, 2011

Hey Unix, How About a Date?

The Problem.

I needed a way to warn users that their passwords were about to expire. To give them a sporting chance, I wanted to give them 2 weeks warning.

I could get the current date with no problem. Getting the password expire date was a bit of a pain, but I could figure it out. The hard part was figuring out how close to the 2 week warning date they were.

In a nut shell, doing math with dates is a royal pain. You have abstract concepts like “July 4th” permanently glued to a large spinning rock which is whizzing around the Sun.

Also, certain concepts that we're used to, such as 1 + 1 = 2, don't always hold up when doing date math. January 31st + 2 months = March 31st. No surprise. How about January + 1 month. That would be February 28th? Or would it be March 3rd (31 days after January 31st)? Add a month to February 28th and you get March 28th. March 31st doesn't equal March
28th. Oh boy!

The Simple (Linux) Solution
.

The most common way to deal with dates is to convert them to a number, do some math, and then convert the number back to a date. Unix (and Linux) system time is based on this concept. Unix dates are implemented as the number of seconds since the January 1st, 1970. In Unix parlance 1/1/1970 is called “the epoch”.

If you have a version of Unix that uses the GNU version of the date command (almost all versions of Linux do), then date math becomes trivial. The date command can convert to and from the epoch with relative ease.

To convert “August 1st 2011” to seconds from the epoch use:

date -u -d "8/1/2011" +%s

You should get 1312156800.

To convert it back use:

date -u -d "1970-01-01 1312156800 seconds" '+%m/%d/%Y'

You should get “08/01/2011”.

The problem here is 2 fold:

One, you're limited to dates between 1970 and 2038 for 32 bit computers. If you have a 24 bit computer then you're good until somewhere around the year 292,277,026,296 so it's not really a restriction.

The second problem is that most older OS's aren't running GNU date. They have their own propriety versions of date that won't let you work with arbitrary dates.

What I needed was a date converter that would work on many versions of *old* Unix. Things like Solaris 5 and HP-UX 10. These are nasty little beasts that barely have Bourne shell. I also wasn't allowed to add more advanced scripting languages to the system so Perl and Python solutions were both out.

I poked around on the Internet tubes and found a dearth of solutions. Most of them used other languages. Some gave example code that didn't handle leap years properly. Others were built around precomputed tables.

Time to step up to the plate.

My Solution.

Below is my solution. Its date format is the number of days after January 1st, 1582. That's the beginning of the Gregorian calendar and very few of my users are that old.

Internally it's mostly AWK scripts glued together by Bourne shell. It can handle dates up to 1/1/9794 and can probably go higher. I've tested it and think it's pretty bullet proof.

#!/bin/sh -

# Convert a date to/from the number of days after 1/1/1582 using only
# basic Unix commands. By "basic" I mean commands available on an
# HP-UX 10 box.
#
# 1/1/1582 is the start of the Gregorian calendar.

# Note: The Gregorian rules for leap years is:
#
# If the year is a factor of 400
# It's a leap year.
# Else If the year is a factor of 100
# It's not a leap year.
# Else If the year is a factor of 4
# It's a leap year
# Else
# It's not a leap year.

# This mostly uses awk because awk is much faster than using raw
# Bourne shell.

# To get a date from the Unix "seconds from the epoch" time use
# int($utime / (24 * 60 * 60)) + date_as_days(1970 1 1)
#
# date_as_days(1970 1 1) = 141714 by the way.

#
# Return the number of days in the previous months.
#
# For example the second entry is the number of days in January. The
# third entry is the combined number of days in January and
# February.
#
# The only parameter is the 4 digit year.
#
days_prev_month()
{
  echo $1 | awk '{
    year = $1

    # Pick the number of days depending of whether its a leap year.
    if ((year % 4 == 0) && (year % 100 != 0 || year % 400 == 0)) {
      print "0 31 60 91 121 152 182 213 244 274 305 335 366"
    } else {
      print "0 31 59 90 120 151 181 212 243 273 304 334 365"
    }
  }'
}

#
# Convert a date in to the number of days after 1/1/1582.
#
# The parameters are YYYY MM DD.
#
date_as_days()
{
  dad_month=$2; dad_day=$3

  # Get the number of days consumed by the years and the number of
  # days remaining in the current year.
  set - `echo $1 | awk '{
    year = $1

    # The modern calendar started in 1582.
    year_days = int((year - 1581) * 365.25) - 365

    cents = int((year - 1501) / 100)
    year_days -= cents

    cents_400 = int((cents + 3) / 4)
    year_days += cents_400

    print year, year_days
  }'`
  dad_year=$1; dad_year_days=$2

  # Now add the month and day contributions.
  days_prev_month $dad_year | awk "
    BEGIN { day=$dad_day; month=$dad_month; year_days=$dad_year_days }"'
    { whole_month_days=$month
      print year_days + whole_month_days + day - 1 }'
}

#
# Take the number of days since 1/1/1582 and convert it to
# year, month, day
#
days_as_date()
{
  df_days=$1

  # This awk script computes the year contributions to the date
  # and removes the effects of those years from df_days.
  set - `
  echo $df_days | awk '{
    df_days = $1;

    # The first 400 year leap year in the Gregorian calendar is
    # 1600 so we normalize our calculations from the first block
    # of 400 years that ends on 1600. That year is 1201.
    # There are 139157 days between 1/1/1201 and 1/1/1582
    #
    # Note: We use 1201, not 1200 because we want the leap year to be the
    # *last* year of the 400, 100 or 4 year block.
    n_days = df_days + 139157

    # There is one leap year every 4 years.
    days_per_quad_year = (365 * 4) + 1
    # Years that end in 00 arent leap years.
    days_per_cent = (days_per_quad_year * 25) - 1
    # Unless its divisible evenly by 400.
    days_per_quad_cent = (days_per_cent * 4) + 1

    # Calculate the contributions of each year block.
    quad_cents = int(n_days / days_per_quad_cent)
    n_days -= quad_cents * days_per_quad_cent

    cents = int(n_days / days_per_cent)
    if (cents == 4) { cents = 3 }
    n_days -= cents * days_per_cent

    quad_years = int(n_days / days_per_quad_year)
    n_days -= quad_years * days_per_quad_year

    years = int(n_days / 365)
    if (years == 4) { years = 3 }
    n_days -= years * 365

    df_year = 1201 + (400 * quad_cents) + (100 * cents) \
      + (4 * quad_years) + years

    print n_days, df_year
  }'`
  df_n_days=$1; df_year=$2

  # Get the day and month from the given year.
  set - `days_prev_month $df_year | awk "
    BEGIN{n_days=$df_n_days}"'
    { df_month = 1
      while (n_days >= $df_month) {
        df_whole_month_days = $df_month
        df_month++
      }
      df_day = 1 + n_days - df_whole_month_days
      print (df_month - 1), df_day }'`

  df_month=$1; df_day=$2

  echo $df_year $df_month $df_day
}

# Some test code. Feed it a number and get back a date.
# Feed it a m/d/yyyy date and get back a number.
#
# Note the complete lack of error checks.
if echo "$1" | egrep '/' >/dev/null 2>&1; then
  set - `echo $1 | tr '/' ' '`
  date_as_days $3 $1 $2
else
  days_as_date $1 | awk '{ printf "%02d/%02d/%02d\n", $2, $3, $1 }'
fi

Sunday, June 19, 2011

Python, GTK, GL and Incantation.

In computer terms, an “incantation” is a problem that can easily be solved if you know the proper mystical invocation. An incantation is especially annoying if it's something that has to have been done many times before, but no one as bothered to tell we mere mortals how they did it.

Linux suffers incantation at a near mystical level. People who write library code seem to take a sadistic pleasure in not telling people how to use said library.

I ran in to this in spades when I tried to use Python to hook up the OpenGL graphics library to the GTK widget system. I didn't have too much trouble finding examples of hooking GTK to Python, the PyGtk libraries are full of examples. I didn't have too much trouble finding OpenGL examples in Python. Search for “PyOpenGL Demo” and you'll probably find what you need.

My problem came from trying to hook Python, Gtk and OpenGL together as one big happy family. I couldn't find one complete example on the net. I could find some pieces, but no complete example.

To make a long story short, I finally found enough pieces, and read enough source code to have a pretty good idea of how to get the job done. In true Linux fashion it turns out to be pretty easy. The documented code is at my website. Hopefully there is now one less incantation in the world.

Monday, November 8, 2010

Hideous Bloat and Active Links.

By popular demand I've expanded my Emacs wiki from one function to an unwieldy two. The second function will scamper through a buffer and list all the active links found.

I use the same regexp that I did in the previous article so it links on CamelCase. To change the link style you just change the regexp. If you end up writing too many support functions then you may want to use that "variable" thing that all the cool kids are talking about.

The Code



(defun list-active-links (link-re &optional is-active-link-p)
"Scan a buffer looking for links and list all the active links.

LINK-RE is a regular expression which matches the link text.
IS-ACTIVE-LINK-P is an optional function which takes the link text and
returns true if the link is active. If not provided, `file-exists-p' is
used."
(let ((buffer-name "*ActiveLinks*")
(found-links ()))

(if (not is-active-link-p)
(setq is-active-link-p 'file-exists-p))

;; Gather up all the potential links and whether they're active.
(save-excursion
(goto-char (point-min))
(while (re-search-forward link-re nil t)
(let ((link-text (match-string-no-properties 0)))
;; If the link hasn't been checked, then save its value
;; and whether or not it has an existing destination.
(if (not (assoc link-text found-links))
(setq found-links
(cons (cons link-text
(funcall is-active-link-p link-text))
found-links))))))

;; Now list out the active links.
(if (get-buffer buffer-name)
(kill-buffer buffer-name))
(switch-to-buffer-other-window buffer-name)
(let ((active-links
;; Remove any links that don't have an associated file.
(delq nil (mapcar (lambda (x) (and (cdr x) (car x)))
found-links))))
(insert "#\n# The following links have destinations.\n#\n")
(save-excursion
(insert (mapconcat 'identity (sort active-links 'string<) "\n")))
(not-modified)
(message "%d matches found." (length active-links)))))

(defun check-active-links ()
(interactive)
(let ((link-re "\\<[A-Z][a-z]+\\([A-Z][a-z]+\\)+\\>"))
(list-active-links link-re)
;; Note: At this point we're in the "*ActiveLinks* buffer.
(set (make-local-variable 'link-to-re) link-re)
(local-set-key
(kbd "C-c C-o")
(lambda ()
(interactive)
(link-to link-to-re "\\<")))))

Sunday, November 7, 2010

Emacs, the Wiki and the Idiot.

Sir C.A.R. (Tony) Hoare once wrote:
Inside every large problem, is a small problem—struggling to get out.
Someone else, stealing from H. L. Mencken, changed it to:
Inside every large problem, is a small problem—struggling to get out. The solution to that problem is simple, elegant and wrong.
I tend to agree with the Thief. The simple reality is that many problems don't have elegant solutions, try as we may to find them. I ran into this when I tried to come up with a simple personal wiki. Enjoy my exploits.

Dale Writes a Wiki


I think the wiki is one of the great software concepts of the last decade or so. That's not hyperbole, I really think that making it easy to link documents together, in a casual and non-invasive way, is a brilliant and under-appreciated concept.

Most wikis are web based. This makes sense if you want the world to have access to the pages. I was looking more for a personal solution.

There are personal wikis that are stand alone applications, but most of them use a special format for your data. This strikes me as, well, stupid. Why would I lock up my data in a special format when a directory of text files should easily get the job done?

I do a lot of my text editing in Emacs, so I started looking around for an wiki based in Emacs. There are a few, but most of them are either unsupported, too elaborate or too invasive. I wanted a way to link text from any kind of file, not just wiki files. I wanted to be able to link comments in source code to documentation files to cake recipes if that's what works best. I also wanted it to leave the rest of my Emacs environment alone. I didn't want to enter Wiki-Mode just to put links in a Perl program. I wanted to stay in Perl mode.

The joy of being a programmer is, if you can't find it, you can always write it. That's what I started out to do.

At first I decided to play with [[bracket style links]]. Emacs Org Mode uses them and I like much about Org Mode, so I tried to emulate its style.

The attempts where not too successful. I pulled out some of Org Mode's handler code and started playing with it. It's pretty invasive and doesn't work well with old versions of Emacs. I use an old version of Emacs at work, and I wanted something small and easy to understand.

My next idea was to write my own bracket style linking library. At it's heart it would grab the text between [[]], convert it into a file name and then open the resulting file name. 194 lines of Elisp later and I had a working minor mode. It could open files, web pages, internal links and even run commands. I was very happy with it. It was reasonably small and reasonably easy to understand and reasonably noninvasive.

Because I'm a professional, I started to document my results. The problem is, I'm a little bit insane. Sometimes, when I'm working on a project, a little idiot voice calls from the fog of experience and tells me what I'm doing is wrong. The Idiot never tells me what's right, it just picks at the back of my head until I accept, eventually, that my perfectly working code is "wrong". Arg!

The more I documented, the louder the Idiot got. I got so frustrated that I put the code aside. I'm a big believer in documentation by Idiot. You take your code and ignore it for a few weeks or even months. Then you come back and try to read it. Every time to look at a bit of code and say "What idiot wrote this?" you either re-factor or document. Maybe the Idiot could figure out what I couldn't.

The Idiot was insidious. It would go away for a week or so and then come out of the shadows to jeer hints. It asked questions that I should have asked. Do I need brackets? Do I need to open web pages and run commands from links? Are my needs the needs of others? What's more important, abstract power or agility? What is the DAO of the problem? Why won't you see it!?

This went for over a month. Part of me was trying to find the right solution. Part of me wanted me to finish what I had and get on with my life.

Then, on a Sunday night, as a long work day loomed ahead, I was laying in my bed with my beloved wife and Charlie the metal eating dog. From nowhere, it came to me. All I really want is a way to take the word under the cursor and open a file with the same name. Then it came to me. What I really want is a way to grab an arbitrary blob of text under the cursor and then open up a file based on the text. Then it came to me. What I really want is a way to grab an arbitrary blob of text under the cursor and do something with it. The Idiot had spoken!

It's a cliche, but I really wanted to leap out of bed and start hacking away. Alas, the days of 12 hour hackfests followed by 10 hour workdays are a thing of the past. I had to go to sleep or I would die at my desk. I had to go to work or I would be thrown into the street. I had to get this program written or I would crack up.

After work I lit in to my task. One of the greatest pleasures in programming is simplifying. The more I wrote, the smaller the program became. Irrelevance fell like rain. I was beginning to understand. By the end, the entire program is 15 lines long. 24 lines if you include the code to hook it up to the key of your choice.

It was simple, elegant and worked like a charm. The Thief was wrong. The Idiot stopped jeering.

Hooking Up the One Function Wiki

The simple solution is to take the text at the end of this article and append it to your .emacs.el file.

To test it, fire up Emacs, and type "This is CamelCase text.". Move your cursor to the link text "CamelCase" and type C-cC-o. It should open up the file "CamelCase".

If you want to use other link styles besides CamelCase or want to open files in different way, read the documentation. Doing things like opening files in a specific directory or opening "CamelCase.txt" are trivial to implement. You just need to do a little Elisp programming and away you go!

The Text to Append.

(defun link-to(link-re link-start-re &optional handle-link)
"Grab the \"link\" under the cursor and open a file based on that link.

LINK-RE is a regular expression which matches the link text.
LINK-START-RE is a regular expression which matches the beginning, or text
just before the link.
HANDLE-LINK is an optional function which takes the link text and opens the
link. If not provided, `find-file' is called with the link text.

This function is usually called via local-set-key with mode specific
regular expressions.

This example will grab a CamelCase link and open a file with the same
name.

(global-set-key (kbd \"C-c C-o\")
(lambda ()
(interactive)
(link-to
\"<[A-Z][a-z]+\\\\([A-Z][a-z]+\\\\)+>\"
\"<\"))) Note: The \"<>\"s above should have \"\\\" in front of them, but emacs
thinks I want to print a key map when I try to include them in the help
text.

This example will grab an alphabetic string and do a google query on it.

(global-set-key (kbd \"C-c C-o\")
(lambda ()
(interactive)
(link-to
\"[a-z]+\" \"[^a-z]\")
(lambda (x)
(browse-url
(concat \"http://www.google.com/search?q=\" x)))))"
(let ((here (point)) link-text
(case-fold-search nil))
(save-excursion
(or (re-search-backward link-start-re nil t)
(goto-char (point-min)))
(unless (re-search-forward link-re nil t)
(error "No tag found to end of file"))
(setq link-text (match-string-no-properties 0))
(if (or (< (point) here)
(> (- (point) (length link-text)) here))
(error "No tag found under cursor")))
(if handle-link
(funcall handle-link link-text)
(find-file link-text))))

(global-set-key
(kbd "C-c C-o")
(lambda ()
""
(interactive)
(link-to
"\\<[A-Z][a-z]+\\([A-Z][a-z]+\\)+\\>" "\\<"
;; This regexp pair matches file names.
;;"[a-zA-Z0-9/~_][a-zA-Z0-9/._]*[a-zA-Z0-9]" "[^a-zA-Z0-9/.~_]"
;; This will open text files in your ~/Wiki directory.
;;(lambda (x) (find-file (concat "~/Wiki/" x ".txt")))
)))

Thursday, September 2, 2010

Reading Web Pages From the Android SD Card

Android 1.6 (Donut) tries to make it impossible to read web pages from the SD memory card. Fortunately there is a flaw in their security that lets a user create a specially formatted URL that allows access. This technique may work for other versions of Android but I've only tested it on 1.6.

This is an easy hack. The only skill required is the ability to drag and drop files from the computer to the phone and to connect to this web page via the Android.

Terminology

For the sake of simplicity the Android based phone is just going to be called the Android. It reads easier.

Local files are the files on the Android SD card. Any references to "the card" mean the Android SD card.

The Desktop is the computer that will be used to edit files and drag and drop the files to and from the Android.

"The browser" is the browser on the Android.

Overview

A web page is created on a computer and moved to an arbitrary, but known spot on the Android SD card. A special URL is entered in the Android browser which points to the page. The page is made into a book mark by bypassing the bookmark editor. The web page can then be edited to point to any other location on the SD card.

The Direct Way

This way is direct, but it involves a bit of typing on the Android keyboard. Most people find the longer way easier to get correct.

Put a web page the SD card. This example will use the file webpages/index.html.

Open the browser and type in the URL content://com.android.htmlfileprovider/sdcard/webpages/index.html.

If index.html shows up in the browser, go to the section "Saving as a Book Mark". If not, check the URL spelling and file location. If the problem can't be solved, use the longer way.

The Longer But Less Fussy Way

This way requires creating a web page on the desktop and the ability to drag a file from the desktop to the Android.

Open an editor ("notepad" will do) and paste the following text:


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<html>
<head>
<title>Found the sd card!</title>
</head>
<body>
<h1>It worked!</h1>
<ul>
<li><a href="content://com.android.htmlfileprovider/sdcard/foo.html">Self reference.</a></li>
<li><a href="webpages/index.html">Relative links work also.</a></li>
<li><a href="http://upcracky.blogspot.com">An external link.</a></li>
</ul>
</body>
</html>


Save the file as "foo.html". This is just a temporary file and the name has to be "foo.html" or the rest of the steps won't work.

Copy foo.html to the top level directory of the SD card.

Unhook the Android from the Desktop.

Connect to this blog entry via the Android browser and click on this URL. foo.html should be displayed in the browser.

Saving the Bookmark

While display the web page in the browser, press the menu key. Select "Bookmarks". Select "History". Select "Today". Find the entry for "Found the SD Card!" and click on the star symbol on the right. The bookmark will be added to the browser with no further intervention.

Do not use the "Edit bookmark" option. Just opening the book mark editor with this book mark may corrupt the link and it will stop working.

Changing the Name of the Bookmark

Since the bookmark can't be directly edited, some cleverness is required to move the SD web page and/or change the name of the bookmark.

First create a new web page and install it on the SD card in any arbitrary folder. Edit foo.html and add a link to the new page relative to this page. Bring up foo.html via the previous book mark. Click on the link to the new page. Bookmark the new file.

Once the new page is safely bookmarked, foo.html and it's bookmark can be deleted.

Limitations

The one quirk that hasn't been figured out is how to jump to the middle of a local web page. Links such as bar.html work fine. Links such as bar.html#middle give an error.

Sunday, August 29, 2010

Thursday, July 22, 2010

Beyond Help.

I'm a big fan of open source software. I do most of my work on Linux and most of my programming is done using Perl. I believe that open software has value and the more open our infrastructure is, the better it is for the world as a whole.

As programmers go, I'm pretty good at what I do. That gives me certain obligations, one of which is to give back to the open software movement when I can.

I was given an opportunity today, but I don't think I'll be giving back in this case.

As I mentioned before, I do a lot of programming in Perl. Sometimes I need to create windows and buttons to make my programs pretty. Enter GTK2. It's a really nice package. For what I do it's simple, reasonably clean and you can usually find an example out there that will give you a good head start. Therein lies the rub.

The example that I found was part of the GTK2-Perl Frequently Asked Question (FAQ) list. I copied it over and tried to run it. No go. The example was using an older version of the library and it had a typo. If only there were a programmer in the house!

Hey! I'm a programmer! And I'm in the house! It took me less that 15 minutes to get it up and running. Yay me!

Now comes the obligation part. I'm using public code, so therefore I'm obligated to send the fixes in to the GTK2-Perl folk so the next person who comes along doesn't have to figure it out. I connect to their bug tracker and try to enter a bug report, including the fix.

No dice! If you want the privilege of submitting a bug to them, you have to sign up to their web site. That's stupid but I'll bite the bullet for betterment of open sourceyness. I'm quite the patriot.

Nope. You not only have to sign up, but you have to give them an email address. Oh, and they'll publish your email address guaranteeing that you'll get spammed off the planet! It gets worse. They suggest creating a throwaway account to handle the spamming. What? Why would I set up an account just to throw it away?

In theory this is supposed to discourage spamming. Is spamming in bug reports really that big a marketing vector? Hey, my program is crashing, maybe penis enhancement will help!

I know that people want an automated system here. One that will block all spam without human intervention. These people are idiots. You have 2 choices. Get casual bug reports that will do wonders for enhancing your project while dealing with the reality of spamming, or set up barriers that will keep most spam out and will do wonders for causing inbreeding on your project.

I'll admit I don't have a lot of patience for this nonsense. I'm not jumping through hoops to help you. Besides, a better solution is trivial.

Any bug report sent via the "outside" gets put in a queue until someone who's trusted takes a look at it. Spam bug reports are rare and there are more than enough regulars on any project who will do the few seconds of grunt work for you.

You could also use a one time key. I connect to your bug tracker. You email me a tracker-putter-inner-key. You don't keep my email address, you just use it once to send me the key. I then use that key to submit the bug report. If I need to add comments to that report, then I use the number again. If I loose the number and want to add more comments then I have to sign up for an account and I become a regular user.


As for the moral obligation to open source? Here it is:

In the GTK2-Perl FAQ, question 5.3, "Show me a simple example for Drag-n-Drop" you need to make 4 changes to get it to work under Perl, v5.10.0 and GTK2 version 1:1.221-4.

  1. Replace "Gtk2::Ex::Simple::List" with "Gtk2::SimpleList". It occurs in 3 places, all near the top.
  2. In the function "_move_from_to", change "for my $i (0 .. $#{ @{$fromlist->{data}}) {" to "for my $i (0 .. $#{$fromlist->{data}}) {".
  3. Enjoy!

If someone wants to send this to the GTK2-Perl bug site, feel free, but watch out for the spam.

Sunday, May 23, 2010

Gators and Nautilus and DAVs, Oh My!

If you're here to get WebDAV working with Nautilus for HostGator, then just jump to the end of this article. The solution is trivial.

If you wish to bask in my purple prose, read on:

Introduction

I'm setting up a site on HostGator, which is a host provider of good repute. It's starting as place to put some of my little code snippets that don't warrant a full blown project. Who knows what it will turn in to.

So far it's been basically a positive experience, but it's not without its shortcomings. I'm trying to keep notes on dealing with HostGator so other people don't fall in to the same traps I've tripped.

One thing I ran into was getting WebDAV working with Linux. Specifically Ubunto's "Karmic Kaola" under Gnome, using the Nautilus file manager.

Of DAVs and Nautali

The first problem I ran into is that HostGator gives it's version of WebDAV the name "Web Disk".

I don't mind them trying to make web interfaces seem a bit easier to deal with, but somewhere on the page they really should tell us that "Web Disk" is really just another name for WebDAV.

Once you get that under your belt tracking down problems becomes a little easier.

The next problem I ran into is, well, I'm trying to use Nautilus.

Nautilus is the Gnome file manager. For many users it's the entire interface to the disk. It should, above all other things, be reasonably fast, accurate and reliable. All else follows from that.

Unfortunately Nautilus is notorious for running down rat holes while not getting the basics done right. It has improved a lot in the last 2 years, but it still plays amateur night a few times too often. This was one of those times.

I went to the HostGator site and navigated down to the "Web Disk" page. I selected Nautilus and followed its suggestions. They wanted me to connect to the location "https://foo.com:2078".

I did and I got "Could not display 'https://foo.com:2078'."

Crud.

I had no idea where to proceed from here. Is it the instructions, or is my account screwed up, or maybe Nautilus is broke?

Just to add to the confusion, HostGator has you create a user name when you create an account with them. No big deal, I chose "wiles". What they don't really make clear is that this user name isn't your domain user name. If you register the domain "foo.com" and want mail to come to "wiles@foo.com" then you need to set up another account called "wiles@foo.com". When I connect with Nautilus, should I use "wiles" or "wiles@foo.com"? The correct answer is neither, but that part's not HostGator's fault. More on that later.

So now I have and unknown protocol, with an untrusted browser connecting to a possibly mis-configured account using an unknown user name. You have to admit, it's kind of a challenge. Right?

I Prefer the Term "Challanged"

I'm not one to back down from a geek challenge, so into the fray I went. I ended up spending over an hour chopping around the Internet tubes trying to figure out what's going on. I got bits and pieces, but nothing I could really sink my teeth into.

I also wasn't sure of the format of the URL. For most services you can load in your user name into the URL and you don't have to type it in each time. For example, if you're using File Transfer Protocol (ftp), and the URL is ftp://foo.com, then you can include your user name with ftp://wiles@foo.com.

Does that work with "Web Disk"? What if I'm supposed to be using wiles@foo.com. Is it ftp://wiles@foo.com@foo.com or ftp://wiles%40foo.com@foo.com.

"%" is the HTML escape character and "40" is is ASCII code for "@" in hexadecimal. You knew that didn't you? I think it's a real sign of progress when connecting to a web site only requires knowledge of arcane character encoding and 2 number bases.

How about if I just create a bookmark in Nautilus, and then edit each variable separately and see if I can get anywhere? Nautilus will handle the details right? If you watch slasher moves there is always a part where some idiot says "lets split up!" The music they play at that point belongs here.

Scooby Do Takes and Ax to the Forehead

First, I'm not going to get anywhere until I figure out the real protocol being used. "Web Disk" criminy! Why not just call it "Disk Huggy Bunny" and be done with it.

I went back to the HostGator page. It listed a few other OSes and other browsers. The Mac options were mysterious. The Window options were baroque. It's not looking good. My last hope: Under Linux there was the option to use Nautilus's arch enemy "Konqueror". I selected it and it offered a download for my system. Anonymous downloads makes my toes itch, so instead I sent the file directly to a text editor to check it out.

There, large as life, is the line "URL=webdavs://foo.com:2078".

I now knew the protocol. We were moving forward.

I created the bookmark in Nautilus, set my user name, picked "Secure WebDAV (HTTPS)", and set the port.

I'm not sure about the start folder. Is it "/" or "/home/wiles" or "/public_html/wiles@foo.com"? I held my nose and left it blank.

I clicked connect and I'll be darned! I got a password prompt! Kewl. I typed in my password and crossed my fingers.

The error I got is "Could not display 'davs://wiles@foo.com:2078/'. Error: Not a WebDAV enabled share. Please select another view and try again."

This is a truly beautiful error message. First, it did *not* connect using "davs://wiles@foo.com:2078/" (more on that later). Second, the share is, in fact, a WebDav enabled share. And third, "Please select another view and try again." gives me absolutely no useful information. It was a perfect storm of rotten interface.

At this point I was pretty frustrated, and lets not kid ourselves, at this point most people have already given up. Fortunately I'm not most people. I'm a hard core uber-geek and I eat bad interfaces for breakfast! Snort!

I start creating bookmarks like they're going out of style. I try every combination I can think of. It's slow, it's tedious, it's everything a computer shouldn't be, but alas, are, and in the end, it was futile. I could not get Nautilus to connect to my HostGator site.

Nautilus: A Weasel in Drag

Hmmmm. Do I trust Nautilus? Would I lend it $10 if it asked? No. No I would not. Then why would I believe that its rotten bookmarks are doing what they say their doing? It's time to go back to first principals and start over again.

I knew, with reasonable confidence, that I'm trying to make a WebDav connection. I also think that the "s" in WebDavs" stands for "secure", as in a Secure Socket Layer (SSL) connection. When you drop the SSL requirement at HostGator, the socket number changes from 2078 to 2077. That was enough for me to make another try.

I fired up Nautilus, and in the "Location" bar I typed "webdav://wiles@foo.com:2077". I got back "Nautilus cannot handle 'webdav' locations." Wow. What a nice, simple and useful error message. Are we sure this is Nautilus talking?

"WebDAV" isn't going to work, but I've also heard it called just "dav". I tried that.

With "dav://wiles@foo.com:2077" I got the password pop up! I also got the "select another view" error message. Arg!

Blinky the Wonder Idiot

Then the dawn came. Does anyone else see the huge blinking "Dale is an idiot!" sign in the previous paragraph? It took me a while to see it.

Even though it's the standard, and Nautilus is reacting to it, do I really know that the "wiles@" part of the URL is kosher? What happens if I don't use it?

Into the breach with "dav://foo.com:2077". This time the pop up asked for user name and password. I used "wiles" again and typed in my password.

I connected like a 13 year old with an evangelist. Son of a ...

I had spent more than 4 hours trying to get this to work, and it all comes down to this one sentence. It really doesn't make HostGator or Gnome/Linux look good does it?

I wasn't where I want to be yet, so I kept pressing forward. I was going to get SSL working.

"davs://foo.com:2078". Yup. I was in. Sort of anticlimactic isn't it.

One last thing. I really wanted to be able to connect to HostGator by clicking on a shortcut on my desktop.

The solution is trivial. Right click on the desktop and select "create launcher". Give it a name, and in the "Command" field type "nautilus davs://foo.com:2078" or "nautilus dav://foo.com:2077", depending on whether you want to use SSL or not. (You do, unless it you can't get it working.)

That's it.

I'm sending this URL to HostGator so they can fix their documentation, but until they do, enjoy updating your HostGator sight via Nautilus.

Sunday, October 18, 2009

Android Phone Home

Getting Started

As some of you know, I've been playing with a new toy.

Android is a new operating system from Google. It's designed for cell phones and other small computers. I've been learning to program it.

For the first couple of months I was mostly working with the Android Software Development Kit (SDK) and the Android emulator. With the emulator you can write and test Android applications (Aps) from the comfort of your computer. As learning Android is like drinking from a fire hose, I wasn't going to invest any money on hardware until I knew I could get something done with it.

I'm at the stage now where I can generate simple programs and I have some definite ideas where to go, so I decided to bite the bullet and buy an Android developer phone.

I ordered my phone and a very few days it showed up. Good job Google!

I fired it up. It munches away for a few seconds, then it tells me "No SIM" and just sits there. Wha?

I know what a SIM is. It's a Subscriber Identity Module, which is a little piece of plastic that modern cell phones use to keep track of who you are. Take a SIM out of one phone and put it into another, and the new phone now has the old phone's number. Neat huh?

I'm using this as a development platform. I don't want to use it to make calls, so I don't need a SIM for it, right? I'm sure that Google has provided an easy work around for this. I'll just check the Internet tubes and find it. Oy! 2 days later I had real access to my phone.

The rest of this blog is designed to save the next poor swine the aggravation I went through in registering my phone.

After checking around I found out that Google not only wants you to have a SIM card, but you also need a data plan on that SIM card! I don't want a data plan, I don't need a data plan, And, at the rate the phone company rapes at, I can't afford a data plan!

Then it just gets silly. You only need the data plan for about 5 minutes, just long enough to connect to Google and register your phone. After that you can chuck it out the window. Oh, did I mention that the phone has WiFi?

You need a data plan to register a phone to get to the WiFi, which you could use, if you could get to it, to register your phone! You're killing me Google. Your just killing me.

Fortunately, if you have a regular SIM card (say from your current phone) and you're already running the Android SDK then it's not too hard to fire up WiFi on your phone and bypass the data plan requirement.

Away We Go!

First we'll get your Linux box to see the phone via the USB cable. I'm running CentOS 5, which is like Red Hat 5. There are other guides out there for Windows and Ubuntu. This guide is for CentOS.

First install the Android SDK on your system. Look around on the Internet for instructions. You don't need everything under the sun, but you do need the "adb" (Android Debug Bridge) command.

Plug your USB cable into your computer and your phone.

Open a root shell on your computer.

After a couple of seconds type "lsusb". You should see a list of the devices attached via USB to your computer. Somewhere in the list should be an entry for "High Tech Computer Corp." "High Tech Computer" is HTC. HTC makes your phone. If you see it then you know that USB is up and running and can see your phone.

The next question is does it see it as a phone or just a very expensive jump drive?

Type "adb devices". If you see an entry that begins with "HT" followed by a bunch of characters and the word "device", then skip to the next section. If adb can't see your phone, then we need to tweak the USB daemon so that it does.

This part took me a long time to get working. Apparently CentOS is using an older version of udevd, which is the program that scans the computer looking for new USB toys being plugged in.

Go in to /etc/udev/rules.d and look for a file named something like "90-android.rules". The leading number varies. It probably isn't there. No problem. You need to create/edit it until it looks like this. Make sure it has the same permissions as the other files in the directory.

# This file lets Linux recognise my Android Developer Phone in
# a way that the adb command can handle.
# Uncomment one of the lines below and run:
# udevcontrol reload_rules
# adb devices
# If it lists your phone, you're done. If not comment out the
# current line, uncomment the next line and run udevcontrol again.
#
# The 3rd line (usb_device) was the charm for me.
#
SUBSYSTEM=="usb", ATTR{idVendor}=="0bb4", MODE="0666"
# SUBSYSTEM=="usb", SYSFS{idVendor}=="0bb4", MODE="0666"
# SUBSYSTEM=="usb_device", SYSFS{idVendor}=="0bb4", MODE="0666"

Follow the instructions in "90-android.rules" and you should end up with a visible Android phone.

Connecting to the Phone

From the command line type: adb shell

After a moment or two you should get a "$" prompt. This means that you're in the phone talking as a regular user.

Type "su".

If the prompt changes from "$" to "#", then you're in as root.

Type "exit" to return to a regular user.

Bypassing the SIM check

There are two ways to do this:

The first, and easiest, is to plug in a SIM card. It doesn't matter that it doesn't have a data plan. This is just to get past the check.

The second, and I haven't tried this myself, is to fool the phone into thinking it passed the check. Check out http://forum.xda-developers.com/showthread.php?t=452316 for instructions.

Note, for the second technique, if you have a developer phone then you don't need to root break it. Just type "su" at the adb shell prompt and you're root.

Registering with out the Data Plan

At this point your phone should be at the registration screen.

From adb, as a regular user, type:

am start -a android.intent.action.MAIN -n com.android.settings/.Settings

In a couple of seconds the "settings" screen should pop up on your phone.

Set up your WiFi and hit the back arrow. You're back at the registration, which you can now do via WiFi.

If for some reason the settings screen doesn't pop up, try

setprop persist.service.adb.enable 1

and then try the settings command again.

Once you're registered you may want to go to the Android market place and pull down an ap called "APNdroid". It screws with the data plan APN so that your phone can't connect no matter how hard it tries. Bite me AT&T.

Using your Phone as a Jump Drive

One last thing, did you notice that your computer can see your phone as a jump drive but can't access it? That's easy to fix.

When you plug in your phone via USB, you'll notice a little USB forky type icon shows up in the upper left hand of the phone screen. This is the notification area. Pull it down with your finger. Click on the USB notification and then click on "mount". You're good to go!

Monday, September 7, 2009

Spanking Dawkins's Weasel

One of the problems with learning a new programming language is coming up with interesting "beginner" programs. Most beginning programs do something exciting like printing out "Howdy, Howdy, Howdy, Joe". Heart stopping stuff ain't it?

To ease this a bit, whenever I come up with an interesting idea for a beginner program, I'll write it up and you can give it a shot.

My hands down favorite simple program is something called Dawkins's Weasel.

Richard Dawkins is a evolutionary biologist from Oxford. He wanted to come up with a program to show the difference between a random mutation and a random mutation with selection. The result is a simple, straight forward program called "Dawkins's Weasel".

Note: Whenever I say "letter" below, I mean letters and/or spaces. Saying letter and/or space all over the place makes for a tedious read.

First we start with a target sentence, which we'll call "Target". This is what all good little sentences want to be when they grow up. Dawkins used "methinks it is like a weasel" and so will we.

Next we create a parent sentence called "Parent". This is a gibberish sentence of random letters that is the same length as Target. "y ksqmjwepqtgtyylmfexstvktpa" will work, as will "aaaaaaaaaaaaaaaaaaaaaaaaaaaa".

Our goal is going to be to evolve Parent into Target.

Parent will produce a litter of children. The fittest of the litter will then become the next parent. This continues until we produce a Parent that equals Target. It's survival of the fittest and all that jazz.

Unfortunately the sex life of a sentence is pretty dull. The way a sentence has a baby sentence is by copying itself and then changing a single letter at random. Not exactly the stuff of pornos. We'll call the baby sentence "Child".

As for who's the fittest? We'll use something simple. We'll count the number of letters in Child that match Target. For example, the sentence "aaaaaaaaaaaaaaaaaaaaaaaaaaa" would score a 2. "methinks it is like a measel" would score 27. If there is more than one pick of the litter, choose one. It doesn't matter how.

That's pretty much it. The only real variable you get to play with is the size of the litter. If you start with a litter of 50 then you tend to finish in less that 100 generations. Once you get the code working, starting dialing playing with the litter size to see how it effects the generation count.

I'll try to keep my eye out for other interesting algorithms worthy of posting. If you know of any that are fun, the add a comment.

Monday, July 20, 2009

Back to (Paranoia) High School

Whelp, I'm back from vacation and all in one piece. I'm a bit shell shocked, but all in all it was a good time.

I'm not one of those people who really gos on vacation. I more survive them. My home life is driven from project to project so when I hit a vacation that I can't spend in front of the computer I'm kind of at a loss.

However, my dearly beloved explained to me that my mother in-law put a lot of work into setting up this vacation, so my other option was to be in kind of a wheelchair, so vacate I did.

The big problem was, we vacated to a dead zone. No phones, no lights no motorcars, and no Internet. That means no real way to do any writing.

I hate writing with a pen. My hand writing is a scrawl and it's sooo slow! And once I'm back amongst the living, I have to transcribe it back into the computer.

With writing on mashed up trees as a failure, I tried using a small laptop. That kind of dominates the landscape and emphasized how much I'm ignoring my family. Not smart for this wheelchair phobic. I needed something sneaker.

How about my phone? It's got a 2 gig chip, supports text messaging and can hide in my hand. Could I use that?

Nope! My phone does allow memos, but they have to be less than 100 characters. Let me repeat that. My crappy phone, with 2 gig available, won't even let you save a memo as long as a Twitter "tweet"! Thrilling.

I know! I could use it as a voice recorder! Yea, I could do that. When I write I tend to talk out what I'm writing anyway. I'll just talk into my phone and record everything!

Unfortunately, with my current phone I have to shout to be heard. Every time inspiration hit, my in-laws would hear me shouting to my invisible friend who hides in my hand.

Now my in-laws think I'm nuts.

I can live with that, but I also got to play with writer's block. Such fun.

Actually, it a weird sort of way I don't mind writer's block. At least I don't mind having it once I've overcome it. It's kind of like the old saw about smacking yourself with a hammer because it feels so good once you stop. I sorta go through that.

As you may or may not know, I used to write for a comic strip called "Paranoia High" (Check it out.) It was a lot of fun and Dave (the artist) is a friend of mine.

After a while Dave took over the writing and I went on to fame as a geek blogger on them Internet tubes.

To make a long story short, we fade the mics and queue the organ and it's a year or so later and I'm back to writing the strip. Huzzah! The only problem is, can I still write the strip? Not May I, Can I?

Ya see, when Dave consolidated the strip, I gave him a list of the ideas I had at the time. No big deal, I have the list around somewhere and Dave has it too. But old ideas aren't enough. Can I come up with new ones?

I could feel the tightening grip of initial dread. What if my last creative idea was really my LAST CREATIVE IDEA!?!? You civilians don't savvy the pain we creative types go through when we birth forth art and stuff.

How can I explain it? It's like Paris Hilton waking up and finding out her butt has run off and joined the Peace Corps. No tush? No job! Writing is like that, except Paris's butt is our ideas.

Hopefully that image will help you develop an appreciation for the written word.

That analogy would have worked much better if it were a breast joke, but I couldn't think of any famous current women who are know for their big racks. Maybe Micheal Jackson, but he's dead.

Ms Proust is know for her rack, but she's a character in "Paranoia High". You really should check it out. (Note the reoccurring motif, that's the art baby!)

So I started running through ideas. Film strips? I think that's from the old list. Standardized tests? Nope, the old list. How about exploding frogs? Damn! School Principal Mike Ducacus? Whoa! Wrong decade!

It was looking pretty bleak for new strips, but I stayed with it. Football? Feral students? Sentient lunch meat? Damn! Damn! Damn! How about Hall Monitors?

Hall Monitors? Not on the old list. Hmm. Uniforms, Tazers, RoboCop, Juntas? Yea. Add "Hall Monitor" to the new list.

After that things started to roll. Walmart vs the school store? New! Texting NORAD? Brand spanking new! "Shakespeare: The Musical!" Oh yea baby. We're back in action!

Why are the in-laws looking at me?

Oh yea, I'm shouting at my fist.

They really think I'm nuts.

I gotta get a new phone.

Tuesday, July 7, 2009

A Window In The Ghetto.

One of the more baffling elements of Linux distributions is their constant relegation of scripting languages to the command line ghetto.

On one side you have the all the wowwie zowie windowy programs, most of which are written, for no good technical reason, in C. On the other hand you have thousands of useful Perl/Python/Java programs that rarely get used because they have command line interfaces.

If we really want to harness the power of Gnome, then we need to make it easier to write Gnome programs in the most popular languages that Gnome supports. These languages are scripting languages.

Scripting exclusively for the command line almost made sense 10 years ago. Old versions of scripting languages didn't really interface well with the Graphic User Interface (GUI) and Text User Interface (TUI) libraries. You often had to have completely separate interpreters for GUI and non GUI interfaces. Anyone remember perlx?

Now days that's bunk. Perl, Python and Java all have officially supported interfaces to GTK, and, in case you don't know, they're *MUCH* easier to use than the C interface. I'm talking an order of magnitude!

As for the TUI, how many tasks do server administrators do that would be made much easier with a simple curses interface?

Python includes a Curses interface by default (it's why I learned Python). Perl isn't too far behind with a very stable Curses package on CPAN. This could be added to any distribution in a matter of minutes. I'm not sure about Java, but if it doesn't exist it wouldn't take long to make one.

The point being, that we have to start pushing distributions to include text and graphic interface libraries with the languages they support, and give them the same status as the language. If the language is included by default, so are the GUI and TUI libraries. Don't let your hot Molly Ringwald fantasies blind you. The '80s are over. We need better interfaces.

Once the user base can depend on the libraries being there, we're going to open up Gnome to a whole to set of ideas. These new programmers greatly out number the current set of Gnome C programmers. They'll be able to fix user level problems that we hardcore programmers don't even know exist.

If you're convinced at this point, then start pestering Ubuntu. I think they're the closest to having all the pieces. Then we can go after Debian and then we'll gang up on Red Hat.

If you're not convinced, then let me over make my point with sort of a preemptive FAQ.

* We didn't do it last time, why do it now?


OK, you lead with an Ace.

First of all, modern bindings to the major scripting languages are dependable and stable. This wasn't true before.

Also, we're in a much more graphical time. Most users consider dropping to the command line a failure of the interface.

We need a bridge between the two.

* What if the bindings disappear?

The odds of the supported bindings disappearing any time soon is negligible. As for other bindings, if more people start using them, the more dependable they become. Does anyone really expect "vim" or "sendmail" to disappear any time soon?

* What's wrong with C?

Nothing, in it's place. If I were to suggest dropping all the scripting languages and doing everything in C, I'd be laughed off the Internet. Somehow we're supposed to believe that the argument is less absurd when you pop up a window.

* Distribution X has the bindings in the "Extras" section. What's wrong with that?


In the business world getting managers to allow "extras" on a system is a hard sell. Damn few middle managers get fired for failing to innovate.

Besides, if it's in it's own section then there must be something wrong with it. Right? Can I get back to you on that?

* You can get all those bindings at site X.com.

If the "Extra" argument is a hard sell, then the 3rd party site is a no-sale. They're right on this one.

A company pays for Red Hat license instead of using the free CentOs because it gives them someone to yell at if things go boom. If you depend on 3rd party software then you get sent to finger pointing hell.

I currently have a problem with my CentOS box at home. I'm using CentOS repositories and a few other reliable sites. Two sites depend on different versions of the same library. I can't upgrade until I find and remove the conflicting programs.

Run that past a manager and you'll be a Microsoft shop by the end of the day.

Besides, if the software is trustworthy and useful then it would be include with the distribution. Feel free to repeat this until your head explodes. It's what they do in corporateland.

* If you want to use the OS, learn the commands!

If you want to make me learn a bunch of esoteric commands, I'm using another OS!

Let's use the "chage" command as an example. It's a pretty simple command which I use about once a year. Every time I use it I have to look up the command flags, because I only use it once a year.

Now wrap it in a curses interface. I no longer have to use the man page. "chage-curses" pops up the user's info, lets me change it. It even uses a calendar to help me change the dates. It then munches up the interface changes into a command line call which make the actual changes.

Take it one step farther. I am a hot shot l33t Hax0r. I shouldn't be doing this peasant crap at all. I create "chage-gtk" in 30 lines of Perl, and now my helper monkey does all the chaging while I hack the cosmos.

* Surly you don't mean every scripting language?


Yep I do. For server admins the command line will live on forever. It's the easiest way to make bulk or automated changes.

Your average user isn't a server admin. We need to stop dressing them up like one and making them dance for us.

Every general purpose language that has a stable GUI and/or TUI and is already included in a distribution needs to have those bindings included. We need to show non-Linux users, and other programmers that we're serious bout getting out of the 1980s. That means that any general purpose language that can help us out needs to be embraced.

* What about languages that don't have stable GUI/TUI bindings?

Most of the popular languages have had stable bindings for years. Perl, Python and Java all have officially supported GTK/Gnome bindings.

If a language only has a stable TUI, but not GUI binding, then just include the TUI. If it has no stable bindings at all, then it remains command line only until it gets it's act together.

* Some languages have GUI/TUI bindings that are a bitch to make into packages.


Let the developer of both the bindings and the language know that that's the reason the binding isn't being included. Most will gladly fix their code or provide the distributions with packages.

* Jeez, our distribution is getting awfully big.

One: The graphic libraries shouldn't really be that big, they're just interfaces to existing libraries.

Two: This move is important! If going from a command line interface to a graphic interface is only being held back by a pack of Luddites, then Linux doesn't deserve to play with the big boys.

Three: This is also an advantage that we seem to be afraid to exploit. Does any other OS come with, by default, an easy way to create useful window based programs just using a text editor? We shouldn't be hiding this feature, we should be shoving it down peoples throats!

* Why should we include fooscript when real programmers use barscript?

You're an idiot.

This isn't about the size of your digital penis, it's about removing completely artificial barriers from the users. Gnome doesn't really serve the clever user well. This problem is trivial to fix. We need to do so in the most inclusive way.

If Perl gets the job done for you, great! If you like Python, no problem. Someone at the Guile compound must have got laid because it's perked right up in the last few months. Guess what? It has both a curses and Gnome interface. Welcome to the club Guile! (Assuming your bindings don't suck.)

* Real programmer program in C.

Actually they don't. Most casual programmers start by looking at a program that almost does what they want, and then pick at it. If the program is a script, it's much easier to play with.

For the inquisitive user, in real terms, modern computers are less powerful then they were in the days of Dos and Unix. Back then a curious user who had an itch, could scratch it with a batch file or shell script. This new command was on par with anything else on the system. If it was generally useful they could email it to anyone else and they could use the new command too. Now days a clever user has to either waste monkey cycles writing in C or they have to have other users download the script-gui library package.

Pithy Summary


This is a stupid pointless wall, and it needs to come down!

Tuesday, June 23, 2009

Emacs: P3 Separate But Equal.

In the first post, we went over some basic theory. In the second post we calibrated Emacs's concept of terminal color with the reality of our terminal program. We also created a file called "color_test.el" which is useful for showing the common "faces" used in programming.

I this part we'll explain what a "face" is and show to get terminal faces and display faces to play nice.

Faces

A "face", in Emacs parlance, is all the characteristics of a piece of text. This includes it's font, size, whether it's bold or italics and it's color.

In the olden days, faces were created by hand. They're not too bad once you get a hold of them and they're surprisingly flexible.

Emacs faces can do all sorts of snazzy things like auto-detect whether they're on a terminal, change their color if the background color changes and invert themselves if they're on a black and white screen. Here's an example taken from the Emacs Elisp manual, section "Elisp/Display/Faces/Defining Faces".

(defface region
`((((type tty) (class color))
(:background "blue" :foreground "white"))
(((type tty) (class mono))
(:inverse-video t))
(((class color) (background dark))
(:background "blue"))
(((class color) (background light))
(:background "lightblue"))
(t (:background "gray")))
"Basic face for highlighting the region."
:group 'basic-faces)

Alas, you young punks don't wanna do it by hand. You'd rather use Emacs's built in customizer. Fair enough.

The Customizer.

I'm not going into a lot of detail here as there are other web resources dedicated to customizing Emacs.

For the sake of this article we need to know:

  • "M-x list-faces-display" shows you all the faces Emacs knows about.
  • Pressing when your cursor is on the face name will let you edit it.
  • In programming mode, all the fonts we care about begin with the wildly intuitive name "font-lock-".
  • When you're customizing in terminal mode don't forget about "Weight Bold" and "Weight Light". In most terminal emulators they give you extra colors to play with.


Multiple Customs.

If you're using a new version of Emacs, you can go into the customizer, click on the "state" button and select "Show All Display Specs". Then click on "Display" and choose "Check List". This lets you select the modes that you want the changes for. If this gets the job done, then you're done. I've had trouble with edits in TTY mode stomping on my edits in display mode, so I like to keep the variables separate.

After much (and I do mean multiple days) experimenting, I've chosen a more robust solution that is easier to maintain and is a lot harder to stomp on.

Whenever you customize a face and save it, Emacs replaces the function "custom-set-faces" with a new version that has your changes in it. The change is written into your custom file. This file could be the end of your ~/.emacs file or the file named in the "custom-file" variable. I'll use the generic "custom file" because I don't care where it actually is.

The way I handle multiple customizations is to customize them via the customizer. Then load the custom file back into Emacs and rename the custom-set-faces function so it only fires when you're in either terminal or display mode, but not both.

It's very easy to do and it's mostly cut and paste.

Load your Emacs custom file. Before any "custom-set-faces" commands, add these 2 functions:

(defun my-custom-set-faces-display (&rest faces)
"Load these faces if Emacs is in windows mode."
(when window-system
(apply 'custom-set-faces faces)))
(defun my-custom-set-faces-terminal (&rest faces)
"Load these faces if Emacs is in terminal mode."
(when (not window-system)
(apply 'custom-set-faces faces)))

Now look at your current "custom-set-faces" command. Is it set up for display mode? Then rename it to "custom-set-faces-display". If it's for the terminal then rename it "custom-set-faces-terminal". Now add an empty function call for the "other" function. If you set custom-set-faces-display, then add "(custom-set-faces-terminal)". If you set custom-set-faces-terminal, then add "(custom-set-faces-display)".

Mine looks like this:

(custom-set-faces-terminal
'(font-lock-function-name-face
((t :foreground "LightlyDepressed" :weight bold)))
'(font-lock-comment-face ((t :foreground "cyan"))))

(custom-set-faces-display)

Now fire up Emacs in terminal mode (emacs -nw) and edit a face. I'll make the font-lock-comment-face "Naval" colored for this example. Then save the change. Take a look at your custom file and you should see the color change in the function "custom-set-faces". Here's my example:

(custom-set-faces-terminal
`(font-lock-function-name-face
((t :foreground "LightlyDepressed" :weight bold)))
`(font-lock-comment-face ((t :foreground "cyan"))))
(custom-set-faces-display)
(custom-set-faces
;; custom-set-faces was added by Custom -- don't edit or cut/paste it!
;; Your init file should contain only one such instance.
'(font-lock-comment-face ((t (:foreground "naval"))))
'(font-lock-function-name-face
((t :foreground "LightlyDepressed" :weight bold))))

Delete the old custom-set-faces-terminal. Rename custom-set-faces to custom-set-faces-terminal, save your work and you're done.

If you wish to edit your display faces, just fire Emacs up in display mode and run through the same process.

There's no limit to the number of face sets you can add. You can have a different face set for every day of the week if you want. Just create a "my-custom-set-faces-" for any discriminator you want and rename custom-set-faces to match it.

Hopefully my absurd 10 day journey into Emacs's faces has been rendered down into something useful for you. Let me know if you found this helpful.

Monday, June 22, 2009

Emacs: P2 Color Me LightlyDepressed.

Now that we have some color theory under our belt, let's calibrate Emacs's concept of color with the reality of the terminal's.

First we have to get the real colors being displayed. I'm using gnome-terminal which has a built in color picker. If you're using a terminal that doesn't have it's own color picker, fire up "emacs -nw", do "M-X list-colors-display", then use something like "xmag" or gimp to get the color values.

My Color List.

From a gnome-terminal, select "Edit/Current Profile" from the menu. From the "Default" screen, click on the "Colors" tab. At the bottom of the screen you should see 2 rows of 8 colors. The first row is the 8 colors that make up the terminal's pallet. Left most is entry 0, right most is 7. The second row are the colors you get when you print the first row using "bold". Gnome-terminal has a 3rd row of colors that are the first row in "dark" mode, but you can't edit them.

If Emacs was smarter about terminal colors you could tell it about all 3 rows of colors and it could use "bold" and "dark" version to increase the chance of it's making a good color choice. Alas, were stuck with our one row of 8 colors.

Click on each color in order, and write down their Red, Green and Blue (RGB) values. For example, the 4th color in my pallet is kind of brown, with yellow below it. It's RGB value is 170/85/0, so pallet entry 3 is 170/85/0.

This is my list:

0 0 0 0
1 170 0 0
2 0 170 0
3 170 85 0
4 0 0 170
5 170 0 170
6 0 170 170
7 170 170 170

Once you have all 8 values, ask Emacs (in a terminal) for help on the variable "color-name-rgb-alist" (C-hv color-name-rgb-alist). The help should list all the color names that Emacs knows and their RGB values.

Scan the list for colors that match the gnome-terminal colors. If you find a *perfect* match, put the color's name besides it's color in your list. Only use the name if it's a perfect match. 0/0/0 was the only match for me. I labeled color 0 "Black".

For the rest of the colors, give them descriptive names that are not in color-name-rgb-list. The last thing we need is 1 name for 2 colors.

Here's my final list.

Black 0 0 0 0
Brick 1 170 0 0
Greeny 2 0 170 0
Brownish 3 170 85 0
Naval 4 0 0 170
DarkishMagenta 5 170 0 170
NeonPee 6 0 170 170
LightlyDepressed 7 170 170 170

Now we have to get the colors into Emacs. It turns out that that's pretty easy.

RCS

First, make a backup of your ~/.emacs, just to be safe. As an aside, because this series isn't nearly long enough, consider using RCS to backup any config files that you hand edit. Under Emacs RCS is trivial to set up and use. It's saved my monkey boy butt more times than I care to remember.

To set up RCS for your ~/.emacs, make a directory called ~/RCS. Then load your ~/.emacs file into Emacs. Hit C-xvv. That's it. You're done. Your ~/.emacs is now write protected and checked into ~/RCS. To check out your file so you can edit it, load it into Emacs and hit C-xvv.

Back to work.

Edit your ~/.emacs, and add the following code. If your ~/.emacs has a custom-set-variables or custom-set-faces function, place this code before either. Obviously you should use your own colors and names for the my-tty-color-define-8 commands.


;; Code for handling term based Emacs.
(defun my-tty-color-define-8 (name index rgb8)
"Set the tty pallet using 8 bit rgb values."
(tty-color-define name index
(mapcar (lambda (x) (+ x (* x 256))) rgb8)))

(if (and (not window-system) (= 8 (length (tty-color-alist))))
(progn
(tty-color-clear)
(my-tty-color-define-8 "Black" 0 '(0 0 0))
(my-tty-color-define-8 "Brick" 1 '(170 0 0))
(my-tty-color-define-8 "Greeny" 2 '(0 170 0))
(my-tty-color-define-8 "Brownish" 3 '(170 85 0))
(my-tty-color-define-8 "Naval" 4 '(0 0 170))
(my-tty-color-define-8 "DarkishMagenta" 5 '(170 0 170))
(my-tty-color-define-8 "NeonPee" 6 '(0 170 170))
(my-tty-color-define-8 "LightlyDepressed" 7 '(170 170 170))))

Save your ~/.emacs file and exit. Restart with "emacs -nw" Type "M-x list-colors-display". You should see your color names listed with the colors.

This might not seem like much of an achievement, but you've actually taken a pretty big step.

To check our your results, create a file called color_test.el in Emacs (-nw). It should put you into "Emacs Lisp" mode automatically. Now type in this program:


;; Comments are in 'comment-face'.
;; defun and defvar are in keyword-face.
(defun function-name-face (&optional is-in-type-face)
"string-face `constant-face' string-face"
:builtin-face
(error "warning-face"))
(defvar variable-name-face)

;; To see the "doc-face" go into "perl-mode".
=pod
This should be in doc-face.
=cut


The program itself doesn't work. It's not even syntactically valid. All it exists for is you show all various "faces" that Emacs uses when coloring code.

To see doc-face, use "M-x perl-mode".

How do you like them colors? If you're happy happy, then you can skip post 3 of this series. If, however, you're like me and think that Red is a horrible color for comment text, then await with baited breath the last installment of the Emacs color saga.

Sunday, June 21, 2009

Emacs: P1: What Color Is My Painbow?

Last week I had a classic "Monkey Boy" moment. I decided to adjust the colors in my text editor. 10 days later I'm finishing a 3 post blog on it.

I worry myself some days.

This first post is going to be mostly theory work. Post 2 and 3 are more hands on.

Laying the Ground Work.

I use an editor called Emacs for most of my programming. It's an old editor, but its one of the most powerful editors out there. It also lets you edit files in display (windows) mode and from the shell (command.com for you Windows folks).

Now days most of the editing is done in display mode. No real surprise there. However, there are times when working from the shell makes more sense.

I routinely log into distant machines across slow connections. I could pop up a virtual session and wait for the window in the virtual session and then wait for the editor in the window in the virtual session and then wait for the file in the editor in the window in the virtual session, or I can use text mode, where are complete screen refresh is around 2000 bytes.

I hate waiting. Its a no brainer.

The down side of terminal mode is that you can only use characters to draw and you have a limited number of colors. Both of these could be overcome with modern technology, but it ain't going to happen so we have to get used to it.

Why do you have limited colors? Well, the underling technology differences between a terminal from 20 years ago and a modern graphic display is pretty significant.

RGB

Colors are made by mixing various amounts of Red, Green and Blue (RGB) together. If you crank up the RGB, you get bright colors, dial it down and you get dark. Wikipedia has a nice write up on color depth so I won't go into it here. The only thing you need to know is that by adjusting the RGB values you can change colors.

On modern display you have absolute control of every dot on the screen. Each one has it's own RGB setting which is independent of it's neighbor.

Old school color terminals were more like "paint by numbers" projects. You were given a pallet of colors (usually 8) that were hard wired into slots. If you set the color to pallet slot 0 and then printed, you got black text. If you printed in color 4 you might get blue. Unfortunately for us, these are the terminals that most terminal emulators emulate.

We have two problems when we want use Emacs in both terminal and display mode: First is that Emacs's support of terminal colors is functional, but not much more. The second is that the friendly Emacs customizers don't like it when you're a switch hitter. In fact they gets down right medieval on your monkey butt. Well, this ain't monkey butt, this is monkey boy butt. Accept no substitutions.

Terminal Colors


As I said before, most terminal emulators model the old style, 8 color pallets. There are ways for a program to ask the emulator for the number of colors available, but there isn't any way to get the actual RGB of each color.

What does Emacs do? It guesses! If you don't tell it otherwise Emacs assumes that you have an 8 color pallet with the following colors:


Slot Name Red Green Blue
---- ------- --- ----- ----
0 black 0 0 0
1 red 255 0 0
2 green 0 255 0
3 yellow 255 255 0
4 blue 0 0 255
5 magenta 255 0 255
6 cyan 0 255 255
7 white 255 255 255


The numbers after the colors are how much Red Green and Blue that each color is supposed to have. 255 is the largest number you can express in 8 bits (1 byte) of data. There are places internally where Emacs uses 16 bit (2 byte) RGB values which go from 0 to 65535. I got bit by this more than a few times so I'll try to point them out, or gloss over them when I can.

Emacs cares about the RGB values because you (the user) set colors by name not slot values. If you set the color of something to "CadetBlue1" 152/245/255, then run in terminal mode, Emacs needs to figure out which of the eight colors CadetBlue1 is closest to. It uses the RGB values to figure it out.

Oh, by the way, the name "CadetBlue1" comes from a variable called "color-name-rgb-alist". To see it's contents, fire up Emacs in display mode and type "M-x list-colors-display". You'll see the colors and their names.

Let's do some hands on. From a terminal, type "emacs -nw". It should start an Emacs session in the terminal. In Emacs type "M-x list-colors-display". You'll get a listing of the 8 colors that Emacs knows about. Note: On some systems you get more than eight. Lucky you. The theory is still the same.

If you're like me, you notice one thing first off. These colors look nothing like their names! The Red might be brick colored. Yellow may look brown. And my white has tattle tale gray! What happened?

Easy. Emacs has no idea what colors your terminal's pallet is set to and it's guess stinks. How do we handle the miss-match?

One option is to change our terminal to Emacs's pallet. Then we can vomit and claw our eyes out. Basic colors tend to be rather harsh on the psyche.

The second option is to tell Emacs what our terminal is really packing. That's the subject of the next post.

Monday, June 8, 2009

Going Deaf at Duffs

Whenever anyone from the company has to come up to Buffalo on work, we have to feed them.

This being Buffalo, and we being cliches, we inevitably drag them off to Duffs.

The thinking goes like this: Person A comes to Buffalo. Person A must want to try our local cuisine. Our local cuisine consists of Chicken Wings and Beef on Weck. Monday is Chicken Wings, Tuesday Weck. Today is Monday. Real men like hot Chicken Wings. Duffs' wing are really hot! We go to Duffs.

Never mind the fact that there is more to Buffalo than Chicken Wings. Ignore that fact that Person A may be here for is 10th time this year. Obfuscate the fact that hot wings and good wings independent variables. Me Buffalo, Me Wings, Me Hot, Me Duffs. *Sigh*

OK. I don't have anything against Duffs. Alright, it does remind me of a low rent vomitorium and the video games run on diesel, but besides that it's a nice enough place. I'd just like to see a little more depth in our chow.

But that's not why I'm writing today's blog.

The last time we were in Duffs, a person came up to me and handed myself and a couple of other people at the table "deaf cards".

For those of you who don't know, a deaf card is a card that allegedly deaf people hand out at airports as a way to beg for money.

The card usually follows a certain formula: First the introduction "I am a deaf person.", then the pitch "10 bucks would make me feel better about being deaf.", then a blessing "May god bless you for giving me 10 dollars." and then a graphic. Usually the graphic is something like a cartoon angle or a peace sign. I got a smiley face.

The first thing that bothered me is, I'm no where near an airport. We got rules! You street beg on streets, airport beg in airports and PBS beg on the radio. It's all part of the begging ecosystem. What's next, Hare Krishna telethons?

Also, I don't know that the person's deaf. I have no problem giving help to the needy. I'm well aware that with a disconcertingly small number of bad breaks, I could be out on the street. This guy is Alpha/Omega. Either I do good by helping someone out, or I'm encouraging a rodent to make a dishonest living by pretending to be deaf.

Then I notice that everyone at my table is whispering. Whispering? Why would you whisper around a deaf person? We're surrounded by the hearing? If he's stone deaf, like he's professing, then he can't hear us. If he can hear us, then he belongs in the slammer.

And if we're afraid of people hearing us, then why aren't we whispering around the people at the tables all around us? We've been blabbing for an hour. They've heard every word!

Then I had the big epiphany. Why would I give someone $10 for being deaf? This isn't like the 1820s where deaf people starved on street corners. In modern societies there are very few jobs that aren't accessible to the deaf. We have the technology and, I'd like to think, are more enlightened about deafness. Rare is the person who thinks it's a punishment from god.

I'm not saying there still isn't ignorance, I'm just saying it isn't the albatross it once was.

Thinking about it, where I work, every jobs in the building save phone receptionist and security guard could be handled by someone stone deaf. And even that, the security guard who monitors the cameras would have no problems.

Knee jerk simpletons may pretend that I'm picking on deaf people here. They're seeing what they want to see. I freely concede that someone who has a sense, and looses it, suffers. If they have an ability, they use an ability, they loose an ability, they have to adjust their life around the loss. I just don't see where deafness would make an otherwise healthy person into a beggar.

In some cases the loss is tragic. Beethoven never heard is final symphonies. In other cases, not so much. A Sumo wrestling rarely depends on the sense of smell. Neither would require you handing out cards.

On the other hand, what about people who are born deaf? They'll never hear music, but I'll never see magnetism. Am I missing out? No idea. And maybe the born deaf experience a clarity of though and tranquility of mind that I'll never know in my noise filled head. Again, no idea. Either way it ain't worth $10.

Because I pointed out that the deaf shouldn't be pitied, everyone at work now thinks that I'm a kitten burning poltroon of the worst stripe. Far from feeling like a wag, I think that I'm being more enlightened than most.

I also noticed that none of them gave the beggar any money. Ya' hear what I'm saying?