Index: /trunk/BookmarkApp.pm
===================================================================
--- /trunk/BookmarkApp.pm	(revision 51)
+++ /trunk/BookmarkApp.pm	(revision 52)
@@ -45,5 +45,5 @@
 sub _get_list_links {
     my $self = shift;
-    my ($self_type, $tags) = @_;
+    my ($self_type, $query) = @_;
     my @links = (
         {
@@ -51,5 +51,5 @@
             type => 'application/json',
             query => {
-                tag => $tags,
+                %$query,
                 format => 'json',
             },
@@ -59,5 +59,5 @@
             type => 'application/xml',
             query => {
-                tag => $tags,
+                %$query,
                 format => 'xbel',
             },
@@ -68,5 +68,5 @@
             path => 'feed',
             query => {
-                tag => $tags,
+                %$query,
             },
         },
@@ -75,5 +75,5 @@
             type => 'text/csv',
             query => {
-                tag => $tags,
+                %$query,
                 format => 'csv',
             },
@@ -83,5 +83,5 @@
             type => 'text/uri-list',
             query => {
-                tag => $tags,
+                %$query,
                 format => 'text',
             },
@@ -91,5 +91,5 @@
             type => 'text/html',
             query => {
-                tag => $tags,
+                %$query,
             },
         },
@@ -140,7 +140,9 @@
 
     my @tags = grep { $_ ne '' } $q->param('tag');
+    my $query = $q->param('q');
     my $limit = $q->param('limit');
     my $offset = $q->param('offset');
     my @resources = $self->_bookmarks->get_bookmarks({
+        query  => $query,
         tag    => \@tags,
         limit  => $limit,
@@ -148,7 +150,10 @@
     });
     my @all_tags = $self->_bookmarks->get_tags({ selected => $tags[0] });
-    my @cotags = $self->_bookmarks->get_cotags({ tag => \@tags });
+    my @cotags = $self->_bookmarks->get_cotags({
+        query  => $query,
+        tag    => \@tags,
+    });
     
-    my $title = 'Bookmarks' . (@tags ? " tagged as " . join(' & ', @tags) : '');
+    my $title = 'Bookmarks' . (@tags ? " tagged as " . join(' & ', @tags) : '') . ($query ? " matching '$query'" : '');
 
     if ($format eq 'json') {
@@ -247,7 +252,8 @@
                 base_url     => $base_url,
                 title        => $title,
+                query        => $query,
                 selected_tag => $tags[0],
                 search_tags  => \@tags,
-                links        => [ $self->_get_list_links('text/html', \@tags) ],
+                links        => [ $self->_get_list_links('text/html', { q => $query, tag => \@tags }) ],
                 all_tags     => \@all_tags,
                 cotags       => \@cotags,
@@ -262,4 +268,5 @@
     my $q = $self->query;
 
+    my $query = $q->param('q');
     my @tags = grep { $_ ne '' } $q->param('tag');
     my $title = 'Bookmarks' . (@tags ? " tagged as " . join(' & ', @tags) : '');
@@ -280,5 +287,5 @@
     $feed->id($feed_uri->canonical);
 
-    for my $link ($self->_get_list_links('application/atom+xml', \@tags)) {
+    for my $link ($self->_get_list_links('application/atom+xml', { q => $query, tag => \@tags })) {
         my $atom_link = XML::Atom::Link->new;
         $atom_link->type($link->{type});
@@ -289,5 +296,5 @@
 
     # construct a feed from the most recent 12 bookmarks
-    for my $bookmark ($self->_bookmarks->get_bookmarks({ tag => \@tags, limit => 12 })) {
+    for my $bookmark ($self->_bookmarks->get_bookmarks({ query => $query, tag => \@tags, limit => 12 })) {
         my $entry = XML::Atom::Entry->new;
         $entry->id($bookmark->bookmark_uri->canonical);
Index: /trunk/Bookmarks.pm
===================================================================
--- /trunk/Bookmarks.pm	(revision 51)
+++ /trunk/Bookmarks.pm	(revision 52)
@@ -71,4 +71,5 @@
     my $self = shift;
     my $params = shift;
+    my $query = $params->{query};
     my $tags = $params->{tag} || [];
     my $limit = $params->{limit};
@@ -92,4 +93,7 @@
         push @sql, 'select * from resources join bookmarks on resources.uri = bookmarks.uri';
     }
+    if ($query) {
+        push @sql, (@$tags ? 'and' : 'where'), 'title like', \"%$query%";
+    }
     push @sql, 'order by ctime desc';
     push @sql, ('limit', \$limit) if $limit;
@@ -98,4 +102,5 @@
 
     my ($sql, @bind) = sql_interp(@sql);
+    #die $sql;
 
     my $sth_resource = $self->dbh->prepare($sql);
@@ -133,4 +138,5 @@
     my $self = shift;
     my $params = shift;
+    my $query = $params->{query};
     my $tags = $params->{tag} || [];
     if (!ref $tags) {
@@ -140,6 +146,9 @@
 
     push @sql, 'select tag, count(tag) as count from tags';
+    push @sql, 'join resources on tags.uri = resources.uri' if $query;
+
+    # build the where clause
     if (@$tags) {
-        push @sql, 'where uri in (';
+        push @sql, 'where tags.uri in (';
         my $intersect = 0;
         for my $tag (@{ $tags }) {
@@ -150,4 +159,8 @@
         push @sql, ') and tag not in ', $tags, '';
     }
+    if ($query) {
+        push @sql, (@$tags ? 'and' : 'where'), 'title like', \"%$query%";
+    }
+
     push @sql, 'group by tag order by tag';
 
Index: /trunk/list.tt
===================================================================
--- /trunk/list.tt	(revision 51)
+++ /trunk/list.tt	(revision 52)
@@ -120,4 +120,5 @@
     <div class="refine">
       <form method="get" action="">
+        <label>Search: <input type="text" name="q" value="[% query | html %]" size="30"/></label>
         <div class="taglists">
           <ul class="searchtags">
