Fossil SCM

adding code, wiki, tickets, checkins search functionality

Zach 2010-05-21 21:05 UTC trunk
Commit 73d274360c6c9ddc62dbce2370b2a39dbc97a381
+68
--- src/db.c
+++ src/db.c
@@ -1061,10 +1061,75 @@
10611061
){
10621062
if( g.zLogin!=0 ){
10631063
sqlite3_result_text(context, g.zLogin, -1, SQLITE_STATIC);
10641064
}
10651065
}
1066
+
1067
+/*
1068
+** Make the content_get function available within a SQL query.
1069
+*/
1070
+static void db_sql_content_get(
1071
+ sqlite3_context *context,
1072
+ int argc,
1073
+ sqlite3_value **argv
1074
+){
1075
+ int rid;
1076
+ Blob content;
1077
+
1078
+ if( argc != 1 ) return;
1079
+ rid = sqlite3_value_int(argv[0]);
1080
+ content_get(rid, &content);
1081
+ sqlite3_result_text(context, blob_str(&content), -1, SQLITE_TRANSIENT);
1082
+}
1083
+
1084
+/*
1085
+** Retrieve the most recent revision ID of a file.
1086
+*/
1087
+static void db_sql_get_file_rid(
1088
+ sqlite3_context *context,
1089
+ int argc,
1090
+ sqlite3_value **argv
1091
+){
1092
+ const unsigned char *fnid;
1093
+ int rid;
1094
+ Stmt q;
1095
+
1096
+ if ( argc != 1 ) return;
1097
+ fnid = sqlite3_value_text(argv[0]);
1098
+
1099
+ db_prepare(&q, "SELECT fid FROM mlink WHERE fnid=%Q and mid= "
1100
+ "(SELECT objid FROM (SELECT objid, mtime FROM event WHERE objid IN "
1101
+ "(SELECT mid FROM mlink WHERE fnid=%Q) "
1102
+ "ORDER BY mtime DESC) LIMIT 1);", fnid, fnid);
1103
+
1104
+ db_step(&q);
1105
+ rid = db_column_int(&q, 0);
1106
+ sqlite3_result_int(context, rid);
1107
+ db_finalize(&q);
1108
+}
1109
+
1110
+/*
1111
+** Retrieve the most recent revision ID of a wiki entry.
1112
+*/
1113
+static void db_sql_get_wiki_rid(
1114
+ sqlite3_context *context,
1115
+ int argc,
1116
+ sqlite3_value **argv
1117
+){
1118
+ const unsigned char *tagid;
1119
+ int rid;
1120
+ Stmt q;
1121
+
1122
+ if ( argc != 1 ) return;
1123
+ tagid = sqlite3_value_text(argv[0]);
1124
+
1125
+ db_prepare(&q, "SELECT rid FROM tagxref WHERE tagid=%Q ORDER BY mtime DESC LIMIT 1", tagid);
1126
+ db_step(&q);
1127
+ rid = db_column_int(&q, 0);
1128
+ sqlite3_result_int(context, rid);
1129
+ db_finalize(&q);
1130
+}
10661131
10671132
/*
10681133
** Implement the cgi() SQL function. cgi() takes a an argument which is
10691134
** a name of CGI query parameter. The value of that parameter is returned,
10701135
** if available. optional second argument will be returned if the first
@@ -1178,10 +1243,13 @@
11781243
sqlite3_exec(g.db, "PRAGMA foreign_keys=OFF;", 0, 0, 0);
11791244
sqlite3_create_function(g.db, "user", 0, SQLITE_ANY, 0, db_sql_user, 0, 0);
11801245
sqlite3_create_function(g.db, "cgi", 1, SQLITE_ANY, 0, db_sql_cgi, 0, 0);
11811246
sqlite3_create_function(g.db, "cgi", 2, SQLITE_ANY, 0, db_sql_cgi, 0, 0);
11821247
sqlite3_create_function(g.db, "print", -1, SQLITE_UTF8, 0,db_sql_print,0,0);
1248
+ sqlite3_create_function(g.db, "content_get", 1, SQLITE_ANY, 0, db_sql_content_get, 0, 0);
1249
+ sqlite3_create_function(g.db, "get_file_rid", 1, SQLITE_ANY, 0, db_sql_get_file_rid, 0, 0);
1250
+ sqlite3_create_function(g.db, "get_wiki_rid", 1, SQLITE_ANY, 0, db_sql_get_wiki_rid, 0, 0);
11831251
sqlite3_create_function(
11841252
g.db, "file_is_selected", 1, SQLITE_UTF8, 0, file_is_selected,0,0
11851253
);
11861254
if( g.fSqlTrace ){
11871255
sqlite3_trace(g.db, db_sql_trace, 0);
11881256
--- src/db.c
+++ src/db.c
@@ -1061,10 +1061,75 @@
1061 ){
1062 if( g.zLogin!=0 ){
1063 sqlite3_result_text(context, g.zLogin, -1, SQLITE_STATIC);
1064 }
1065 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1066
1067 /*
1068 ** Implement the cgi() SQL function. cgi() takes a an argument which is
1069 ** a name of CGI query parameter. The value of that parameter is returned,
1070 ** if available. optional second argument will be returned if the first
@@ -1178,10 +1243,13 @@
1178 sqlite3_exec(g.db, "PRAGMA foreign_keys=OFF;", 0, 0, 0);
1179 sqlite3_create_function(g.db, "user", 0, SQLITE_ANY, 0, db_sql_user, 0, 0);
1180 sqlite3_create_function(g.db, "cgi", 1, SQLITE_ANY, 0, db_sql_cgi, 0, 0);
1181 sqlite3_create_function(g.db, "cgi", 2, SQLITE_ANY, 0, db_sql_cgi, 0, 0);
1182 sqlite3_create_function(g.db, "print", -1, SQLITE_UTF8, 0,db_sql_print,0,0);
 
 
 
1183 sqlite3_create_function(
1184 g.db, "file_is_selected", 1, SQLITE_UTF8, 0, file_is_selected,0,0
1185 );
1186 if( g.fSqlTrace ){
1187 sqlite3_trace(g.db, db_sql_trace, 0);
1188
--- src/db.c
+++ src/db.c
@@ -1061,10 +1061,75 @@
1061 ){
1062 if( g.zLogin!=0 ){
1063 sqlite3_result_text(context, g.zLogin, -1, SQLITE_STATIC);
1064 }
1065 }
1066
1067 /*
1068 ** Make the content_get function available within a SQL query.
1069 */
1070 static void db_sql_content_get(
1071 sqlite3_context *context,
1072 int argc,
1073 sqlite3_value **argv
1074 ){
1075 int rid;
1076 Blob content;
1077
1078 if( argc != 1 ) return;
1079 rid = sqlite3_value_int(argv[0]);
1080 content_get(rid, &content);
1081 sqlite3_result_text(context, blob_str(&content), -1, SQLITE_TRANSIENT);
1082 }
1083
1084 /*
1085 ** Retrieve the most recent revision ID of a file.
1086 */
1087 static void db_sql_get_file_rid(
1088 sqlite3_context *context,
1089 int argc,
1090 sqlite3_value **argv
1091 ){
1092 const unsigned char *fnid;
1093 int rid;
1094 Stmt q;
1095
1096 if ( argc != 1 ) return;
1097 fnid = sqlite3_value_text(argv[0]);
1098
1099 db_prepare(&q, "SELECT fid FROM mlink WHERE fnid=%Q and mid= "
1100 "(SELECT objid FROM (SELECT objid, mtime FROM event WHERE objid IN "
1101 "(SELECT mid FROM mlink WHERE fnid=%Q) "
1102 "ORDER BY mtime DESC) LIMIT 1);", fnid, fnid);
1103
1104 db_step(&q);
1105 rid = db_column_int(&q, 0);
1106 sqlite3_result_int(context, rid);
1107 db_finalize(&q);
1108 }
1109
1110 /*
1111 ** Retrieve the most recent revision ID of a wiki entry.
1112 */
1113 static void db_sql_get_wiki_rid(
1114 sqlite3_context *context,
1115 int argc,
1116 sqlite3_value **argv
1117 ){
1118 const unsigned char *tagid;
1119 int rid;
1120 Stmt q;
1121
1122 if ( argc != 1 ) return;
1123 tagid = sqlite3_value_text(argv[0]);
1124
1125 db_prepare(&q, "SELECT rid FROM tagxref WHERE tagid=%Q ORDER BY mtime DESC LIMIT 1", tagid);
1126 db_step(&q);
1127 rid = db_column_int(&q, 0);
1128 sqlite3_result_int(context, rid);
1129 db_finalize(&q);
1130 }
1131
1132 /*
1133 ** Implement the cgi() SQL function. cgi() takes a an argument which is
1134 ** a name of CGI query parameter. The value of that parameter is returned,
1135 ** if available. optional second argument will be returned if the first
@@ -1178,10 +1243,13 @@
1243 sqlite3_exec(g.db, "PRAGMA foreign_keys=OFF;", 0, 0, 0);
1244 sqlite3_create_function(g.db, "user", 0, SQLITE_ANY, 0, db_sql_user, 0, 0);
1245 sqlite3_create_function(g.db, "cgi", 1, SQLITE_ANY, 0, db_sql_cgi, 0, 0);
1246 sqlite3_create_function(g.db, "cgi", 2, SQLITE_ANY, 0, db_sql_cgi, 0, 0);
1247 sqlite3_create_function(g.db, "print", -1, SQLITE_UTF8, 0,db_sql_print,0,0);
1248 sqlite3_create_function(g.db, "content_get", 1, SQLITE_ANY, 0, db_sql_content_get, 0, 0);
1249 sqlite3_create_function(g.db, "get_file_rid", 1, SQLITE_ANY, 0, db_sql_get_file_rid, 0, 0);
1250 sqlite3_create_function(g.db, "get_wiki_rid", 1, SQLITE_ANY, 0, db_sql_get_wiki_rid, 0, 0);
1251 sqlite3_create_function(
1252 g.db, "file_is_selected", 1, SQLITE_UTF8, 0, file_is_selected,0,0
1253 );
1254 if( g.fSqlTrace ){
1255 sqlite3_trace(g.db, db_sql_trace, 0);
1256
+98
--- src/search.c
+++ src/search.c
@@ -162,10 +162,108 @@
162162
*/
163163
void search_sql_setup(Search *p){
164164
sqlite3_create_function(g.db, "score", 1, SQLITE_UTF8, p,
165165
search_score_sqlfunc, 0, 0);
166166
}
167
+
168
+/*
169
+** WEBPAGE: search
170
+** URL: /search
171
+*/
172
+void search(void){
173
+ const char *zType;
174
+ const char *zSrchType;
175
+ const char *zTitle;
176
+ const char *zContent;
177
+ const char *zSrch;
178
+ const char *zUuid;
179
+ const char *zRid;
180
+ char zrn[4];
181
+ char zshUuid[10];
182
+ int zScore;
183
+ int zSrchTypeFlag;
184
+
185
+ Search *zSrchpat;
186
+ Stmt q;
187
+
188
+ zSrch = PD("search", "");
189
+ zSrchType = PD("type", "");
190
+ zSrchpat = search_init(zSrch);
191
+ search_sql_setup(zSrchpat);
192
+
193
+ login_check_credentials();
194
+
195
+ if( !g.okHistory ){ login_needed(); return; }
196
+
197
+ db_prepare(&q, "SELECT type, rid, title, content, score(content) AS score FROM "
198
+ " "
199
+ "(SELECT 'checkin' AS type, objid AS rid, coalesce(ecomment, comment) AS title, "
200
+ "coalesce(ecomment, comment) AS content FROM event WHERE type='ci' UNION ALL "
201
+ "SELECT 'code' AS type, rid, title, content FROM "
202
+ "(SELECT title, rid, content_get(rid) as content FROM "
203
+ "(SELECT name AS title, get_file_rid(fnid) AS rid FROM "
204
+ "(SELECT name, fnid FROM filename))) UNION ALL "
205
+ " "
206
+ "SELECT 'ticket' AS type, tkt_uuid AS rid, title, coalesce(title, comment) AS content FROM ticket UNION ALL "
207
+ "SELECT 'wiki' AS type, rid, SUBSTR(title, 6) AS title, content_get(rid) as content FROM "
208
+ "(SELECT tagname AS title, get_wiki_rid(tagid) AS rid FROM "
209
+ "(SELECT tagname, tagid FROM tag WHERE tagname LIKE 'wiki-%%')))"
210
+ "ORDER BY score DESC;");
211
+
212
+ zSrchTypeFlag = 0;
213
+ if (strcmp(zSrchType, "code") == 0)
214
+ zSrchTypeFlag = 1;
215
+ else if (strcmp(zSrchType, "tickets") == 0)
216
+ zSrchTypeFlag = 2;
217
+ else if (strcmp(zSrchType, "checkins") == 0)
218
+ zSrchTypeFlag = 3;
219
+ else if (strcmp(zSrchType, "wiki") == 0)
220
+ zSrchTypeFlag = 4;
221
+
222
+ style_header("Search");
223
+ style_submenu_element("Code", "Code", "search?search=%T&type=code", zSrch);
224
+ style_submenu_element("Tickets", "Tickets", "search?search=%T&type=tickets", zSrch);
225
+ style_submenu_element("Checkins", "Checkins", "search?search=%T&type=checkins", zSrch);
226
+ style_submenu_element("Wiki", "Wiki", "search?search=%T&type=wiki", zSrch);
227
+ @ <table border=1>
228
+ @ <tr><td>link</td><td>relevance</td><td>title</td><td>type</td></tr>
229
+ while (db_step(&q) == SQLITE_ROW){
230
+ zType = db_column_text(&q, 0);
231
+ zRid = db_column_text(&q, 1);
232
+ zTitle = db_column_text(&q, 2);
233
+ zContent = db_column_text(&q, 3);
234
+ zScore = db_column_int(&q, 4);
235
+
236
+ sprintf(zrn, "%i", zScore);
237
+ if (zScore > 0){
238
+ if (strcmp(zType, "code") == 0 && (zSrchTypeFlag == 0 || zSrchTypeFlag == 1)){
239
+ zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%h", zRid);
240
+ strncpy(zshUuid, zUuid, 10);
241
+ @ <tr><td><a href='/artifact?name=%h(zUuid)'>%h(zshUuid)</a></td><td>%h(zrn)</td>
242
+ @ <td>%h(zTitle)</td><td>%h(zType)</td></tr>
243
+ }
244
+ else if (strcmp(zType, "ticket") == 0 && (zSrchTypeFlag == 0 || zSrchTypeFlag == 2)){
245
+ strncpy(zshUuid, zRid, 10);
246
+ @ <tr><td><a href='/tktview?name=%h(zRid)'>%h(zshUuid)</a></td><td>%h(zrn)</td>
247
+ @ <td>%h(zTitle)</td><td>%h(zType)</td></tr>
248
+ }
249
+ else if (strcmp(zType, "checkin") == 0 && (zSrchTypeFlag == 0 || zSrchTypeFlag == 3)){
250
+ zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%h", zRid);
251
+ strncpy(zshUuid, zUuid, 10);
252
+ @ <tr><td><a href='info/%h(zUuid)'>%h(zshUuid)</a></td><td>%h(zrn)</td>
253
+ @ <td>%h(zTitle)</td><td>%h(zType)</td></tr>
254
+ }
255
+ else if (strcmp(zType, "wiki") == 0 && (zSrchTypeFlag == 0 || zSrchTypeFlag == 4)){
256
+ @ <tr><td><a href='/wiki?name=%h(zTitle)'>%h(zTitle)</a></td><td>%h(zrn)</td>
257
+ @ <td>%h(zTitle)</td><td>%h(zType)</td></tr>
258
+ }
259
+ }
260
+ }
261
+ @ </table>
262
+ db_finalize(&q);
263
+ style_footer();
264
+}
167265
168266
/*
169267
** Testing the search function.
170268
**
171269
** COMMAND: search
172270
--- src/search.c
+++ src/search.c
@@ -162,10 +162,108 @@
162 */
163 void search_sql_setup(Search *p){
164 sqlite3_create_function(g.db, "score", 1, SQLITE_UTF8, p,
165 search_score_sqlfunc, 0, 0);
166 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
167
168 /*
169 ** Testing the search function.
170 **
171 ** COMMAND: search
172
--- src/search.c
+++ src/search.c
@@ -162,10 +162,108 @@
162 */
163 void search_sql_setup(Search *p){
164 sqlite3_create_function(g.db, "score", 1, SQLITE_UTF8, p,
165 search_score_sqlfunc, 0, 0);
166 }
167
168 /*
169 ** WEBPAGE: search
170 ** URL: /search
171 */
172 void search(void){
173 const char *zType;
174 const char *zSrchType;
175 const char *zTitle;
176 const char *zContent;
177 const char *zSrch;
178 const char *zUuid;
179 const char *zRid;
180 char zrn[4];
181 char zshUuid[10];
182 int zScore;
183 int zSrchTypeFlag;
184
185 Search *zSrchpat;
186 Stmt q;
187
188 zSrch = PD("search", "");
189 zSrchType = PD("type", "");
190 zSrchpat = search_init(zSrch);
191 search_sql_setup(zSrchpat);
192
193 login_check_credentials();
194
195 if( !g.okHistory ){ login_needed(); return; }
196
197 db_prepare(&q, "SELECT type, rid, title, content, score(content) AS score FROM "
198 " "
199 "(SELECT 'checkin' AS type, objid AS rid, coalesce(ecomment, comment) AS title, "
200 "coalesce(ecomment, comment) AS content FROM event WHERE type='ci' UNION ALL "
201 "SELECT 'code' AS type, rid, title, content FROM "
202 "(SELECT title, rid, content_get(rid) as content FROM "
203 "(SELECT name AS title, get_file_rid(fnid) AS rid FROM "
204 "(SELECT name, fnid FROM filename))) UNION ALL "
205 " "
206 "SELECT 'ticket' AS type, tkt_uuid AS rid, title, coalesce(title, comment) AS content FROM ticket UNION ALL "
207 "SELECT 'wiki' AS type, rid, SUBSTR(title, 6) AS title, content_get(rid) as content FROM "
208 "(SELECT tagname AS title, get_wiki_rid(tagid) AS rid FROM "
209 "(SELECT tagname, tagid FROM tag WHERE tagname LIKE 'wiki-%%')))"
210 "ORDER BY score DESC;");
211
212 zSrchTypeFlag = 0;
213 if (strcmp(zSrchType, "code") == 0)
214 zSrchTypeFlag = 1;
215 else if (strcmp(zSrchType, "tickets") == 0)
216 zSrchTypeFlag = 2;
217 else if (strcmp(zSrchType, "checkins") == 0)
218 zSrchTypeFlag = 3;
219 else if (strcmp(zSrchType, "wiki") == 0)
220 zSrchTypeFlag = 4;
221
222 style_header("Search");
223 style_submenu_element("Code", "Code", "search?search=%T&type=code", zSrch);
224 style_submenu_element("Tickets", "Tickets", "search?search=%T&type=tickets", zSrch);
225 style_submenu_element("Checkins", "Checkins", "search?search=%T&type=checkins", zSrch);
226 style_submenu_element("Wiki", "Wiki", "search?search=%T&type=wiki", zSrch);
227 @ <table border=1>
228 @ <tr><td>link</td><td>relevance</td><td>title</td><td>type</td></tr>
229 while (db_step(&q) == SQLITE_ROW){
230 zType = db_column_text(&q, 0);
231 zRid = db_column_text(&q, 1);
232 zTitle = db_column_text(&q, 2);
233 zContent = db_column_text(&q, 3);
234 zScore = db_column_int(&q, 4);
235
236 sprintf(zrn, "%i", zScore);
237 if (zScore > 0){
238 if (strcmp(zType, "code") == 0 && (zSrchTypeFlag == 0 || zSrchTypeFlag == 1)){
239 zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%h", zRid);
240 strncpy(zshUuid, zUuid, 10);
241 @ <tr><td><a href='/artifact?name=%h(zUuid)'>%h(zshUuid)</a></td><td>%h(zrn)</td>
242 @ <td>%h(zTitle)</td><td>%h(zType)</td></tr>
243 }
244 else if (strcmp(zType, "ticket") == 0 && (zSrchTypeFlag == 0 || zSrchTypeFlag == 2)){
245 strncpy(zshUuid, zRid, 10);
246 @ <tr><td><a href='/tktview?name=%h(zRid)'>%h(zshUuid)</a></td><td>%h(zrn)</td>
247 @ <td>%h(zTitle)</td><td>%h(zType)</td></tr>
248 }
249 else if (strcmp(zType, "checkin") == 0 && (zSrchTypeFlag == 0 || zSrchTypeFlag == 3)){
250 zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%h", zRid);
251 strncpy(zshUuid, zUuid, 10);
252 @ <tr><td><a href='info/%h(zUuid)'>%h(zshUuid)</a></td><td>%h(zrn)</td>
253 @ <td>%h(zTitle)</td><td>%h(zType)</td></tr>
254 }
255 else if (strcmp(zType, "wiki") == 0 && (zSrchTypeFlag == 0 || zSrchTypeFlag == 4)){
256 @ <tr><td><a href='/wiki?name=%h(zTitle)'>%h(zTitle)</a></td><td>%h(zrn)</td>
257 @ <td>%h(zTitle)</td><td>%h(zType)</td></tr>
258 }
259 }
260 }
261 @ </table>
262 db_finalize(&q);
263 style_footer();
264 }
265
266 /*
267 ** Testing the search function.
268 **
269 ** COMMAND: search
270
+16
--- src/style.c
+++ src/style.c
@@ -200,10 +200,20 @@
200200
@ } else {
201201
@ puts "Not logged in"
202202
@ }
203203
@ </th1></nobr></div>
204204
@ </div>
205
+@ <th1>
206
+@ if {[hascap h]} {
207
+@ html "<div class='fullsrch'>"
208
+@ html " <form action='/search' method='post'>"
209
+@ html " <input type='text' name='search' size=20/>"
210
+@ html " <input type='submit' value='Search'/>"
211
+@ html " </form>"
212
+@ html "</div>"
213
+@ }
214
+@ </th1>
205215
@ <div class="mainmenu"><th1>
206216
@ html "<a href='$baseurl$index_page'>Home</a> "
207217
@ if {[anycap jor]} {
208218
@ html "<a href='$baseurl/timeline'>Timeline</a> "
209219
@ }
@@ -290,10 +300,16 @@
290300
@ /* The header across the top of the page */
291301
@ div.header {
292302
@ display: table;
293303
@ width: 100%;
294304
@ }
305
+@
306
+@ /* The search bar displayed at the top of the page */
307
+@ div.fullsrch {
308
+@ float: right;
309
+@ margin: 2px 5px 2px 0px;
310
+@ }
295311
@
296312
@ /* The main menu bar that appears at the top of the page beneath
297313
@ ** the header */
298314
@ div.mainmenu {
299315
@ padding: 5px 10px 5px 10px;
300316
--- src/style.c
+++ src/style.c
@@ -200,10 +200,20 @@
200 @ } else {
201 @ puts "Not logged in"
202 @ }
203 @ </th1></nobr></div>
204 @ </div>
 
 
 
 
 
 
 
 
 
 
205 @ <div class="mainmenu"><th1>
206 @ html "<a href='$baseurl$index_page'>Home</a> "
207 @ if {[anycap jor]} {
208 @ html "<a href='$baseurl/timeline'>Timeline</a> "
209 @ }
@@ -290,10 +300,16 @@
290 @ /* The header across the top of the page */
291 @ div.header {
292 @ display: table;
293 @ width: 100%;
294 @ }
 
 
 
 
 
 
295 @
296 @ /* The main menu bar that appears at the top of the page beneath
297 @ ** the header */
298 @ div.mainmenu {
299 @ padding: 5px 10px 5px 10px;
300
--- src/style.c
+++ src/style.c
@@ -200,10 +200,20 @@
200 @ } else {
201 @ puts "Not logged in"
202 @ }
203 @ </th1></nobr></div>
204 @ </div>
205 @ <th1>
206 @ if {[hascap h]} {
207 @ html "<div class='fullsrch'>"
208 @ html " <form action='/search' method='post'>"
209 @ html " <input type='text' name='search' size=20/>"
210 @ html " <input type='submit' value='Search'/>"
211 @ html " </form>"
212 @ html "</div>"
213 @ }
214 @ </th1>
215 @ <div class="mainmenu"><th1>
216 @ html "<a href='$baseurl$index_page'>Home</a> "
217 @ if {[anycap jor]} {
218 @ html "<a href='$baseurl/timeline'>Timeline</a> "
219 @ }
@@ -290,10 +300,16 @@
300 @ /* The header across the top of the page */
301 @ div.header {
302 @ display: table;
303 @ width: 100%;
304 @ }
305 @
306 @ /* The search bar displayed at the top of the page */
307 @ div.fullsrch {
308 @ float: right;
309 @ margin: 2px 5px 2px 0px;
310 @ }
311 @
312 @ /* The main menu bar that appears at the top of the page beneath
313 @ ** the header */
314 @ div.mainmenu {
315 @ padding: 5px 10px 5px 10px;
316

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button