From f54d187c473df63616089e7a87da9f81b21183fd Mon Sep 17 00:00:00 2001 From: TLINDEN Date: Fri, 10 Feb 2012 20:12:25 +0100 Subject: [PATCH] ADDED: NOTEDB::binary. so now 0.8 is ready for shipping ! FIXED: regexp bug fixed. It was only possible to delete 2 items together separated by comma ("d 1,2,3,4" deleted only 1,2!). ADDED: Some new config options which reflects the new module structure. So you can change your database backend without the need to replace the note script itself. FIXED: the previously added feature "cd " didn't really work :-( ADDED: NOTEDB::mysql added. Perlmodule, which I will use within note from now on instead of buildin functions for accessing the database. From now on I only need to maintain one version of note, since the module interface will be identical between the bin and sql version. CHANGED: The SQL code does not use Mysql.pm anymore. Instead it is coded using the more portable DBI module. This allows one easily to switch to anther database, which is supported by DBI. CHANGED: Locking. The db-table will now be locked before note accesses it. FIXED: width of listings is now always the same independent of the string- length of a certain note. --- Changelog | 23 + NOTEDB/README | 7 + NOTEDB/binary.pm | 331 ++++++++++++ NOTEDB/mysql.pm | 258 ++++++++++ README | 73 +-- UPGRADE | 3 + VERSION | 2 +- bin/note | 1214 +++++++++++++++++++++++++++++++++++++++++++++ config/noterc | 97 ++-- install.sh | 69 ++- mysql/README | 62 +++ mysql/install.sh | 33 ++ mysql/permissions | 2 + mysql/sql | 8 + 14 files changed, 2086 insertions(+), 96 deletions(-) create mode 100644 NOTEDB/README create mode 100644 NOTEDB/binary.pm create mode 100644 NOTEDB/mysql.pm create mode 100644 UPGRADE create mode 100755 bin/note create mode 100644 mysql/README create mode 100755 mysql/install.sh create mode 100644 mysql/permissions create mode 100644 mysql/sql diff --git a/Changelog b/Changelog index 66e0339..a03c219 100644 --- a/Changelog +++ b/Changelog @@ -1,5 +1,28 @@ ================================================================================== +0.8: +ADDED: NOTEDB::binary. so now 0.8 is ready for shipping ! +FIXED: regexp bug fixed. It was only possible to delete 2 items together + separated by comma ("d 1,2,3,4" deleted only 1,2!). +ADDED: Some new config options which reflects the new module structure. + So you can change your database backend without the need to + replace the note script itself. +FIXED: the previously added feature "cd " didn't really work :-( +ADDED: NOTEDB::mysql added. Perlmodule, which I will use within + note from now on instead of buildin functions for accessing the + database. From now on I only need to maintain one version of + note, since the module interface will be identical between the + bin and sql version. +CHANGED: The SQL code does not use Mysql.pm anymore. Instead it is coded + using the more portable DBI module. This allows one easily to + switch to anther database, which is supported by DBI. +CHANGED: Locking. The db-table will now be locked before note accesses it. +FIXED: width of listings is now always the same independent of the string- + length of a certain note. + + +================================================================================== + 0.7: ADDED: one can now use the unix-like "cd" command to change to another topic, thus use "cd topicname" instead just typing "topicname"! diff --git a/NOTEDB/README b/NOTEDB/README new file mode 100644 index 0000000..447198c --- /dev/null +++ b/NOTEDB/README @@ -0,0 +1,7 @@ +perl modules for note used as database backends. +the install.sh script will install both of them, +although you may only need one backend. Perhaps +other users on your system have oter ideas in mind... + +Therefore, please ignore these file. There is nothing +to edit or to do. Simply leave this directory :-) diff --git a/NOTEDB/binary.pm b/NOTEDB/binary.pm new file mode 100644 index 0000000..9b6383c --- /dev/null +++ b/NOTEDB/binary.pm @@ -0,0 +1,331 @@ +#!/usr/bin/perl +use strict; +use Data::Dumper; +use IO::Seekable; + +package NOTEDB; +use Fcntl qw(LOCK_EX LOCK_UN); + +# Globals: +my ($NOTEDB, $sizeof, $typedef,$version); +$version = "(NOTEDB::binary, 1.1)"; + + +sub new +{ + my($this, $dbdriver, $dbname, $MAX_NOTE, $MAX_TIME) = @_; + + my $class = ref($this) || $this; + my $self = {}; + bless($self,$class); + $NOTEDB = $dbname; + + if(! -e $NOTEDB) + { + open(TT,">$NOTEDB") or die "Could not create $NOTEDB: $!\n"; + close (TT); + } + elsif(! -w $NOTEDB) + { + print "$NOTEDB is not writable!\n"; + exit(1); + } + + + my $TYPEDEF = "i a$MAX_NOTE a$MAX_TIME"; + my $SIZEOF = length pack($TYPEDEF, () ); + + $sizeof = $SIZEOF; + $typedef = $TYPEDEF; + return $self; +} + + +sub DESTROY +{ + # clean the desk! +} + +sub version { + return $version; +} + + +sub get_single +{ + my($this, $num) = @_; + my($address, $note, $date, $buffer, $n, $t, $buffer, ); + + open NOTE, "+<$NOTEDB" or die "could not open $NOTEDB\n"; + flock NOTE, LOCK_EX; + + $address = ($num-1) * $sizeof; + seek(NOTE, $address, IO::Seekable::SEEK_SET); + read(NOTE, $buffer, $sizeof); + ($num, $n, $t) = unpack($typedef, $buffer); + + $note = ude($n); + $date = ude($t); + + flock NOTE, LOCK_UN; + close NOTE; + + return $note, $date; +} + + +sub get_all +{ + my($this, $num, $note, $date, %res); + + open NOTE, "+<$NOTEDB" or die "could not open $NOTEDB\n"; + flock NOTE, LOCK_EX; + my($buffer, $t, $n); + seek(NOTE, 0, 0); # START FROM BEGINNING + while(read(NOTE, $buffer, $sizeof)) { + ($num, $note, $date) = unpack($typedef, $buffer); + $t = ude($date); + $n = ude($note); + $res{$num}->{'note'} = $n; + $res{$num}->{'date'} = $t; + } + flock NOTE, LOCK_UN; + close NOTE; + + return %res; +} + + +sub get_nextnum +{ + my($this, $num, $te, $me, $buffer); + + open NOTE, "+<$NOTEDB" or die "could not open $NOTEDB\n"; + flock NOTE, LOCK_EX; + + seek(NOTE, 0, 0); # START FROM BEGINNING + while(read(NOTE, $buffer, $sizeof)) { + ($num, $te, $me) = unpack($typedef, $buffer); + } + $num++; + flock NOTE, LOCK_UN; + close NOTE; + + return $num; +} + +sub get_search +{ + my($this, $searchstring) = @_; + my($buffer, $num, $note, $date, %res, $t, $n); + + open NOTE, "+<$NOTEDB" or die "could not open $NOTEDB\n"; + flock NOTE, LOCK_EX; + + seek(NOTE, 0, 0); # START FROM BEGINNING + while(read(NOTE, $buffer, $sizeof)) + { + ($num, $note, $date) = unpack($typedef, $buffer); + $n = ude($note); + $t = ude($date); + if($n =~ /$searchstring/i) + { + $res{$num}->{'note'} = $n; + $res{$num}->{'date'} = $t; + } + } + flock NOTE, LOCK_UN; + close NOTE; + + return %res; +} + + + +sub set_recountnums +{ + my $this = shift; + my(@count, $i, $num, $setnum, $buffer, $buff, $note, $date); + + open NOTE, "+<$NOTEDB" or die "could not open $NOTEDB\n"; + flock NOTE, LOCK_EX; + + $setnum = 1; + my $TEMP = "/tmp/note.$$"; # save temporarily in $TEMP + system("/bin/touch", $TEMP); + open TEMP, "+<$TEMP" or die "Could not open $TEMP($!)\n"; + + seek(NOTE, 0, 0); # START FROM BEGINNING + while(read(NOTE, $buffer, $sizeof)) { + ($num, $note, $date) = unpack($typedef, $buffer); + $buff = pack($typedef, $setnum, $note, $date); + seek(TEMP, 0, IO::Seekable::SEEK_END); # APPEND + print TEMP $buffer; + $setnum++; + } + close(TEMP); + + flock NOTE, LOCK_UN; + close NOTE; + + system("/bin/cp",$TEMP, $NOTEDB); + + unlink $TEMP; +} + + + +sub set_edit +{ + my($this, $num, $note, $date) = @_; + my $address = ($num -1 ) * $sizeof; + + open NOTE, "+<$NOTEDB" or die "could not open $NOTEDB\n"; + flock NOTE, LOCK_EX; + + seek(NOTE, $address, IO::Seekable::SEEK_SET); + my $n = uen($note); + my $t = uen($date); + + my $buffer = pack($typedef, $num, $n, $t); + print NOTE $buffer; + + flock NOTE, LOCK_UN; + close NOTE; +} + + +sub set_new +{ + my($this, $num, $note, $date) = @_; + open NOTE, "+<$NOTEDB" or die "could not open $NOTEDB\n"; + flock NOTE, LOCK_EX; + + seek(NOTE, 0, IO::Seekable::SEEK_END); # APPEND + my $n = uen($note); + my $t = uen($date); + my $buffer = pack($typedef, $num, $n, $t); + print NOTE $buffer; + + flock NOTE, LOCK_UN; + close NOTE; +} + + +sub set_del +{ + my($this, $num) = @_; + my($note, $date, $T, $setnum, $buffer, $buff, $n); + + $setnum = 1; + my $TEMP = "/tmp/note.$$"; # save temporarily in $TEMP + system("/bin/touch", $TEMP); + open TEMP, "+<$TEMP" or die "Could not open $TEMP($!)\n"; + + open NOTE, "+<$NOTEDB" or die "could not open $NOTEDB\n"; + flock NOTE, LOCK_EX; + + seek(NOTE, 0, 0); # START FROM BEGINNING + while(read(NOTE, $buffer, $sizeof)) { + ($n, $note, $date) = unpack($typedef, $buffer); + $buff = pack($typedef, $setnum, $note, $date); + if($n != $num) { + seek(TEMP, 0, IO::Seekable::SEEK_END); # APPEND + print TEMP $buff; + } + else + { + $T = $date; + } + $setnum++; + } + close(TEMP); + + flock NOTE, LOCK_UN; + close NOTE; + + system("/bin/cp",$TEMP, $NOTEDB); + + unlink $TEMP; + + return "ERROR" if($T eq ""); # signal success! +} + +sub uen +{ + my($T); + $T = pack("u", $_[0]); + chomp $T; + return $T; +} + +sub ude +{ + my($T); + $T = unpack("u", $_[0]); + return $T; +} + +1; # keep this! + +__END__ + +=head1 NAME + +NOTEDB::binary - module lib for accessing a notedb from perl + +=head1 SYNOPSIS + + # include the module + use NOTEDB; + + # create a new NOTEDB object + $db = new NOTEDB("binary", "/home/tom/.notedb", 4096, 24); + + # get a single note + ($note, $date) = $db->get_single(1); + + # search for a certain note + %matching_notes = $db->get_search("somewhat"); + # format of returned hash: + #$matching_notes{$numberofnote}->{'note' => 'something', 'date' => '23.12.2000 10:33:02'} + + # get all existing notes + %all_notes = $db->get_all(); + # format of returnes hash like the one from get_search above + + # get the next noteid available + $next_num = $db->get_nextnum(); + + # modify a certain note + $db->set_edit(1, "any text", "23.12.2000 10:33:02"); + + # create a new note + $db->set_new(5, "any new text", "23.12.2000 10:33:02"); + + # delete a certain note + $db->set_del(5); + +=head1 DESCRIPTION + +You can use this module for accessing a note database. There are currently +two versions of this module, one version for a SQL database and one for a +binary file (note's own database-format). +However, both versions provides identical interfaces, which means, you do +not need to change your code, if you want to switch to another database format. + +Currently, NOTEDB module is only used by note itself. But feel free to use it +within your own project! Perhaps someone want to implement a webinterface to +note... + +=head1 USAGE + +please see the section SYNOPSIS, it says it all. + +=head1 AUTHOR + +Thomas Linden . + + + +=cut diff --git a/NOTEDB/mysql.pm b/NOTEDB/mysql.pm new file mode 100644 index 0000000..0ca4510 --- /dev/null +++ b/NOTEDB/mysql.pm @@ -0,0 +1,258 @@ +#!/usr/bin/perl +use DBI; +use strict; +use Data::Dumper; + +package NOTEDB; + +# Globals: +my ($DB, $table, $fnum, $fnote, $fdate, $version); +$table = "note"; +$fnum = "number"; +$fnote = "note"; +$fdate = "date"; +$version = "(NOTEDB::mysql, 1.0)"; + +# prepare some std statements... ##################################################################### +my $sql_getsingle = "SELECT $fnote,$fdate FROM $table WHERE $fnum = ?"; +my $sql_all = "SELECT $fnum,$fnote,$fdate FROM $table"; +my $sql_nextnum = "SELECT max($fnum) FROM $table"; +my $sql_incrnum = "SELECT $fnum FROM $table ORDER BY $fnum"; +my $sql_search = "SELECT DISTINCT $fnum,$fnote,$fdate FROM $table WHERE $fnote LIKE ?"; + +my $sql_setnum = "UPDATE $table SET $fnum = ? WHERE $fnum = ?"; +my $sql_edit = "UPDATE $table SET $fnote = ?, $fdate = ? WHERE $fnum = ?"; + +my $sql_insertnew = "INSERT INTO $table VALUES (?, ?, ?)"; + +my $sql_del = "DELETE FROM $table WHERE $fnum = ?"; +###################################################################################################### + +sub new +{ + # no prototype, because of the bin-version, which takes only a filename! + my($this, $dbdriver, $dbname, $dbhost, $dbuser, $dbpasswd) = @_; + + my $class = ref($this) || $this; + my $self = {}; + bless($self,$class); + my $database = "DBI:$dbdriver:$dbname;host=$dbhost"; + + $DB = DBI->connect($database, $dbuser, $dbpasswd) || die DBI->errstr(); + + # LOCK the database! + my $lock = $DB->prepare("LOCK TABLES $table WRITE") || die $DB->errstr(); + $lock->execute() || die $DB->errstr(); + + return $self; +} + + +sub DESTROY +{ + # clean the desk! + my $unlock = $DB->prepare("UNLOCK TABLES") || die $DB->errstr; + $unlock->execute() || die $DB->errstr(); + $DB->disconnect || die $DB->errstr; +} + +sub version { + return $version; +} + + +sub get_single +{ + my($this, $num) = @_; + my($note, $date); + my $statement = $DB->prepare($sql_getsingle) || die $DB->errstr(); + + $statement->execute($num) || die $DB->errstr(); + $statement->bind_columns(undef, \($note, $date)) || die $DB->errstr(); + + while($statement->fetch) { + return $note, $date; + } +} + + +sub get_all +{ + my($this, $num, $note, $date, %res); + my $statement = $DB->prepare($sql_all) || die $DB->errstr(); + + $statement->execute || die $DB->errstr(); + $statement->bind_columns(undef, \($num, $note, $date)) || die $DB->errstr(); + + while($statement->fetch) { + $res{$num}->{'note'} = $note; + $res{$num}->{'date'} = $date; + } + return %res; +} + + +sub get_nextnum +{ + my($this, $num); + my $statement = $DB->prepare($sql_nextnum) || die $DB->errstr(); + + $statement->execute || die $DB->errstr(); + $statement->bind_columns(undef, \($num)) || die $DB->errstr(); + + while($statement->fetch) { + return $num+1; + } +} + +sub get_search +{ + my($this, $searchstring) = @_; + my($num, $note, $date, %res); + $searchstring = "\%$searchstring\%"; + my $statement = $DB->prepare($sql_search) || die $DB->errstr(); + + $statement->execute($searchstring) || die $DB->errstr(); + $statement->bind_columns(undef, \($num, $note, $date)) || die $DB->errstr(); + + while($statement->fetch) { + $res{$num}->{'note'} = $note; + $res{$num}->{'date'} = $date; + } + return %res; +} + + + +sub set_recountnums +{ + my $this = shift; + my(@count, $i, $num, $setnum); + $setnum = 1; + my $statement = $DB->prepare($sql_incrnum) || die $DB->errstr(); + my $sub_statement = $DB->prepare($sql_setnum) || die $DB->errstr(); + + $statement->execute || die $DB->errstr(); + $statement->bind_columns(undef, \($num)) || die $DB->errstr(); + + while($statement->fetch) { + $sub_statement->execute($setnum,$num) || die $DB->errstr(); + $setnum++; + } +} + + + +sub set_edit +{ + my($this, $num, $note, $date) = @_; + + my $statement = $DB->prepare($sql_edit) || die $DB->errstr(); + + $note =~ s/'/\'/g; + $note =~ s/\\/\\\\/g; + $statement->execute($note, $date, $num) || die $DB->errstr(); +} + + +sub set_new +{ + my($this, $num, $note, $date) = @_; + + my $statement = $DB->prepare($sql_insertnew) || die $DB->errstr(); + + $note =~ s/'/\'/g; + $note =~ s/\\/\\\\/g; + $statement->execute($num, $note, $date) || die $DB->errstr(); +} + + +sub set_del +{ + my($this, $num) = @_; + my($note, $date, $T); + + my $stat = $DB->prepare($sql_getsingle) || die $DB->errstr(); + $stat->execute($num) || die $DB->errstr(); + $stat->bind_columns(undef, \($note, $date)) || die $DB->errstr(); + while($stat->fetch) { + $T = $date; + } + + my $statement = $DB->prepare($sql_del) || die $DB->errstr(); + + $statement->execute($num) || die $DB->errstr(); + + $this->set_recountnums(); + + return "ERROR" if($T eq ""); # signal success! +} + + + +1; # keep this! + +__END__ + +=head1 NAME + +NOTEDB::mysql - module lib for accessing a notedb from perl + +=head1 SYNOPSIS + + # include the module + use NOTEDB; + + # create a new NOTEDB object (the last 4 params are db table/field names) + $db = new NOTEDB("mysql","note","localhost","username","password","note","number","note","date"); + + # get a single note + ($note, $date) = $db->get_single(1); + + # search for a certain note + %matching_notes = $db->get_search("somewhat"); + # format of returned hash: + #$matching_notes{$numberofnote}->{'note' => 'something', 'date' => '23.12.2000 10:33:02'} + + # get all existing notes + %all_notes = $db->get_all(); + # format of returnes hash like the one from get_search above + + # get the next noteid available + $next_num = $db->get_nextnum(); + + # recount all noteids starting by 1 (usefull after deleting one!) + $db->set_recountnums(); + + # modify a certain note + $db->set_edit(1, "any text", "23.12.2000 10:33:02"); + + # create a new note + $db->set_new(5, "any new text", "23.12.2000 10:33:02"); + + # delete a certain note + $db->set_del(5); + +=head1 DESCRIPTION + +You can use this module for accessing a note database. There are currently +two versions of this module, one version for a SQL database and one for a +binary file (note's own database-format). +However, both versions provides identical interfaces, which means, you do +not need to change your code, if you want to switch to another database format. + +Currently, NOTEDB module is only used by note itself. But feel free to use it +within your own project! Perhaps someone want to implement a webinterface to +note... + +=head1 USAGE + +please see the section SYNOPSIS, it says it all. + +=head1 AUTHOR + +Thomas Linden . + + + +=cut diff --git a/README b/README index a8b4ece..b1a1d99 100644 --- a/README +++ b/README @@ -1,4 +1,4 @@ -note 0.7 by Thomas Linden, 08/03/2000 +note 0.8 by Thomas Linden, 19/03/2000 Introduction @@ -17,20 +17,15 @@ Introduction sort your notes in different topics, which is usefull if you have a lot of them. - There are now two version of note in one package: - o (binary) the binary version resists in the - subdirectory "binary-db". - It uses a binary file for data storage. - The format of this file will be described - later on. - o (mysql) the mysql version resists in the - subdirectory mysql-db. It uses a mysql - database as backend. There are some - special installation steps required in - order to run the mysql version which are - documented in the README within this - subdirectory. - + There are currently two different database backends, + which you can use with note: + o NOTEDB::binary - this is the default backend + and uses a binary file to store your notes. + o NOTEDB::mysql - this backend uses a mysql + database to store your notes. You can switch + easily to another DBMS since this module uses + the Perl standard module "DBI" for database- + access. See below for more info on this topic! Requirements @@ -38,20 +33,22 @@ Requirements You need the following things: o perl installed (5.004x) - o The module IO::Seekable, which should be + o The module IO::Seekable and Fcntl, which should be already installed with your perl distributuion. - o Mysql.pm if you want to use the mysql version. + o DBI module and DBI::mysql if you want to use the + mysql version. Installation ============ - Simple: Copy it to a place inside your $PATH, - probably as root. (for example to /usr/bin). + There is a script provided called "install.sh", which will + ask you a few questions about file destinations and database + backends. Simply answer this questions and it does the rest. - For installation instructions for the mysql version see - mysql-db/README. + For installation instructions for the mysql database installation + see mysql/README. @@ -65,20 +62,19 @@ Configuration about every available parameter. Simply copy this file into your home-directory and name it .noterc + If you decide not to use the default database backend (a binary + file), you will *need* a configuration! Usage ===== - Usage of the mysql and binary version is similar, there - are only differences between the database backends of - each other. If you don't know, how to run note, try "note -h" first. It will tell you all available commandline options. To create a new note, simply run "note". You can enter - the note (the length is by default limited to 1024 bytes, + the note (the length is by default limited to 4096 bytes, which you can change from your config file). End by typing a . on a line itself. note will tell you the number of the note. @@ -121,8 +117,8 @@ Usage provides you the most functions of note. You can also dump the contents of your note-database into a - ASCII-textfile. You can use this file later to import it into - your note-database. This is usefull, if you want quickly trans- + ASCII-textfile(-D). You can use this file later to import it into + your note-database(-I). This is usefull, if you want quickly trans- fer your notes from one host to another (i.e. you could mail your note-dump form your office to home and import it there for further use). @@ -141,12 +137,16 @@ Topics (or whatever you prefer, set $TopicSep in your config! default is slash), then note will consider it as the topic of this certain note. For examle: /TodoList/ + If you are using topics, no data after the topic is allowed, if there + is any text, note will consider it as a subtopic! Therefore, don't for- + get to put a newline after the topic-line. If you are in interactive mode, you can "cd" to a different note simply - by typing it's name at the command-prompt. The list-command will only - show you notes under this topic. If you create a new note, it will auto- - magically inserted under the current topic (note will prepend the string - "/topicname/" to the text of your note). + by typing it's name at the command-prompt, or you can use the well-known + syntax "cd topic". + The list-command will only show you notes under this topic. If you create + a new note, it will automagically inserted under the current topic (note + will prepend the string "/topicname/" to the text of your note). You can create at any time from any point a new topic. Just create a new note and type the name of the new topic bordered by slashes (or $TopicSep) @@ -197,7 +197,7 @@ Topics -Format of the notedb (binary version) +Format of the notedb (binary backend) ===================================== The database where the notes are stored is a binary file of @@ -217,7 +217,7 @@ Format of the notedb (binary version) -The note-database (mysql version) +The note-database (mysql backend) ================================= The sql-database for the mysql version has the following design: @@ -324,10 +324,11 @@ License -Author -====== +Author and Copyright +==================== The author is Thomas Linden. + note is Copyright of Thomas Linden. @@ -335,4 +336,4 @@ Author Last changed ============ - 21.02.2000 + 19/03/2000 diff --git a/UPGRADE b/UPGRADE new file mode 100644 index 0000000..5069955 --- /dev/null +++ b/UPGRADE @@ -0,0 +1,3 @@ +if you are upgrading an existing note installation, +you need to reedit your configfile, since there are now +some new required options! diff --git a/VERSION b/VERSION index eb49d7c..aec258d 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.7 +0.8 diff --git a/bin/note b/bin/note new file mode 100755 index 0000000..7cec7c6 --- /dev/null +++ b/bin/note @@ -0,0 +1,1214 @@ +#!/usr/bin/perl +# $Author: thomas $ $Id: note,v 1.13 2000/03/19 11:53:32 thomas Exp thomas $ $Revision: 1.13 $ +# +# $Log: note,v $ +# Revision 1.13 2000/03/19 11:53:32 thomas +# edit bug fixed (ude => uen) +# +# Revision 1.12 2000/03/19 03:06:51 thomas +# backend support completed. +# mysql and binary backends now excluded in separate files +# +# Revision 1.11 2000/03/18 00:16:47 thomas +# added NOTEDB::mysql and changed note to work with that. +# thus, from now on there is only one script to maintain and +# it is possible to provide more bacjends as well as making +# additional scripts upon them, i.e. cgi script... +# +# Revision 1.8 2000/03/13 22:48:43 thomas +# small width bug fixed +# +# Revision 1.7 2000/03/08 23:11:19 tom +# added cd +# +# Revision 1.6 2000/03/08 22:50:41 tom +# Added the $KEEP_TIMESTAMP option and fixed a bug regarding topic names +# and invalid resolution of them in case it started with "1 name". +# +# Revision 1.5 2000/02/25 20:59:30 tom +# corrected small timestamp problem in &edit and &new +# +# Revision 1.4 2000/02/25 13:24:11 tom +# fixed a small bug, that caused to use the last line for a note title instead the 2nd. +# +# Revision 1.3 2000/02/25 11:28:53 tom +# all changes from bin version applied to sql version +# +# Revision 1.2 2000/02/25 10:30:06 tom +# *** empty log message *** +# +# +# this is the small console program "note" (MYSQL version) +# It works similar to some well known GUI note programs, +# but instead of using X11 it uses the UN*X console. +# You can edit existing notes, delete them, create new +# ones and, of course display them. +# The notes will be stored in a mysql database. Refer to +# the README of the desitribution for details about +# installation. +# It requires a configfile named .noterc in the users home. +# If it does not exist, note will create one for you, which +# you will have to edit. +# +# If you find it usefull or find a bug, please let me know: +# Thomas Linden +# +# note is GPL software. + +#use Term::ReadLine; +#use POSIX qw(:sys_wait_h); + +use strict; +use Data::Dumper; + +sub usage; +sub find_editor; +sub output; +sub C; +sub uen; +sub ude; +sub num_bereich; +sub getdate; + +sub new; +sub edit; +sub del; +sub display; +sub list; +sub help; +sub import; + +my ( + $maxlen, $timelen, $TOPIC, $TYPE, $mode, $NOTEDB, + $version, $number, $CurTopic, $CurDepth, $PATH, $CONF, + $sizeof, $MAX_TIME, $PreferredEditor, %TP, $TopicSep, + $ListType, $searchstring, $dump_file, $ALWAYS_INT, $KEEP_TIMESTAMP, + $BORDERC, $BORDER_COLOR, $_BORDERC, $NOTEC, $NOTE_COLOR, + $NUMC, $NUM_COLOR, $_NUMC, $_NOTEC, $TIMEC, $TIME_COLOR, + $_TIMEC, $TOPICC, $TOPIC_COLOR, $_TOPICC, $SetTitle, $COLOR, + $typedef, $MAX_NOTE, $MAX_TIME, @NumBlock, $ALWAYS_EDIT, $HOME, + $db, $dbname, $dbhost, $DEFAULTDBNAME, $dbuser, $USER, $dbpasswd, + $table, $fnum, $fnote, $fdate, $date, $dbdriver, $libpath, $db + ); + +#################################################################### +# DEFAULTS, allows one to use note without a config ################ +# don't change them, instead use the config file! ################ +#################################################################### +$maxlen = 30; +$timelen = 22; +$date = &getdate; +$USER = getlogin || getpwuid($<); +chomp $USER; +$HOME = $ENV{'HOME'}; +$CONF = $HOME . "/.noterc"; +$dbdriver = "binary"; +$libpath = "/usr/local/lib"; +$NOTEDB = $HOME . "/.notedb"; +$MAX_NOTE = 4096; +$MAX_TIME = 24; +$COLOR = "YES"; +$BORDER_COLOR = "BLACK"; +$NUM_COLOR = "blue"; +$NOTE_COLOR = "green"; +$TIME_COLOR = "black"; +$TOPIC_COLOR = "BLACK"; +$TOPIC = 1; +$TopicSep = '/'; +$version = "0.8 r1.12"; +if($TOPIC) +{ + $CurDepth = 1; # the current depth inside the topic "directory" structure... +} +#################################################################### + +# process command line args +if($ARGV[0] eq "") +{ + $mode = "new"; +} +else +{ + while($ARGV[0] ne "" ) + { + if($ARGV[0] =~ /^\d/) + { + # first arg is a digit! + $number = $ARGV[0]; + if($mode eq "") + { + # change mode only, if started with an option + # ($mode will be already set) + $mode = "display"; + } + $ARGV[0] = ""; + } + elsif($ARGV[0] eq "-i" || $ARGV[0] eq "--interactive") + { + $mode = "interactive"; + $ARGV[0] = ""; + } + elsif($ARGV[0] eq "-l" || $ARGV[0] eq "--list") + { + $mode = "list"; + my @ArgTopics = split /$TopicSep/,$ARGV[1]; + $CurDepth += $#ArgTopics + 1 if $ARGV[1]; + $CurTopic = $ArgTopics[$#ArgTopics]; # use the last element everytime... + $ARGV[0] = ""; + } + elsif($ARGV[0] eq "-L" || $ARGV[0] eq "--longlist") + { + $mode = "list"; + $ListType = "LONG"; + $CurTopic = $ARGV[1]; + $ARGV[0] = ""; + } + elsif($ARGV[0] eq "-s" || $ARGV[0] eq "--search") + { + # searching + $mode = "search"; + $searchstring = $ARGV[1]; + $ARGV[0] = ""; + } + elsif($ARGV[0] eq "-e" || $ARGV[0] eq "--edit") + { + if($mode eq "edit") + { + # note -e -e ! + &usage; + exit(1); + } + else + { + $mode = "edit"; + shift; + } + } + elsif($ARGV[0] eq "-d" || $ARGV[0] eq "--delete") + { + if($mode eq "delete") + { + &usage; + exit(1); + } + else + { + $mode = "delete"; + shift; + } + } + elsif($ARGV[0] eq "-D" || $ARGV[0] eq "--Dump" || $ARGV[0] eq "--dump") + { + $mode = "dump"; + $dump_file = $ARGV[1]; + $ARGV[0] = ""; + if($dump_file eq "") + { + $dump_file = "note.dump.$$"; + print "no dumpfile specified, using $dump_file.\n"; + } + } + elsif($ARGV[0] eq "-I" || $ARGV[0] eq "--Import" || $ARGV[0] eq "--import") + { + $mode = "import"; + $dump_file = $ARGV[1]; + $ARGV[0] = ""; + if($dump_file eq "") + { + print "No dumpfile specified.\n"; + exit(1); + } + } + elsif($ARGV[0] eq "-v" || $ARGV[0] eq "--version") + { + print "This is note $version by Thomas Linden .\n"; + exit(0); + } + elsif($ARGV[0] eq "-h" || $ARGV[0] eq "--help") + { + &usage; + exit(0); + } + else + { + &usage; + exit(0); + } + } +} + +# open the configfile. + + + +if(-e $CONF) +{ + eval `cat $CONF`; +} + + +# Always interactive? +if($ALWAYS_INT eq "YES" && $mode ne "dump" && $mode ne "import") +{ + $mode = "interactive"; +} + + +# *if* loading of the config was successful, try to load the +# configured database backend. Currently supported: mysql and binary. +push @INC, $libpath; +if($dbdriver eq "mysql") { + eval { + require NOTEDB::mysql; + $db = new NOTEDB($dbdriver, $dbname, $dbhost, $dbuser, $dbpasswd, $table, $fnum, $fnote, $fdate); + } +} +elsif($dbdriver eq "binary") { + eval { + require NOTEDB::binary; + $db = new NOTEDB($dbdriver, $NOTEDB, $MAX_NOTE, $MAX_TIME, $dbdriver); + } +} +else { + print "Unsupported database backend: NOTEDB::$dbdriver!\n"; + exit 1; +} +if($@) { + print "backend-error: " . $@; + exit 1; +} + +# add the backend version to the note version: +$version .= " " . $db->version(); + +# calculate some constants... +$BORDERC = "<$BORDER_COLOR>"; +$_BORDERC = ""; +$NUMC = "<$NUM_COLOR>"; +$_NUMC = ""; +$NOTEC = "<$NOTE_COLOR>"; +$_NOTEC = ""; +$TIMEC = "<$TIME_COLOR>"; +$_TIMEC = ""; +$TOPICC = "<$TOPIC_COLOR>"; +$_TOPICC = ""; + + + +if($ListType ne "LONG" && $mode ne "interactive") +{ + $maxlen += $timelen; # no time will be displayed! +} + + + + +# main loop: ############### +if($mode eq "display") +{ + &display; +} +elsif($mode eq "search") +{ + &search; +} +elsif($mode eq "list") +{ + &list; +} +elsif($mode eq "new") +{ + &new; +} +elsif($mode eq "delete") +{ + del; +} +elsif($mode eq "edit") +{ + &edit; +} +elsif($mode eq "dump") +{ + &dump; +} +elsif($mode eq "import") +{ + &import; +} +elsif($mode eq "interactive") +{ + &interactive; +} +else +{ + #undefined :-( +} + + +exit(0); +################## EOP ################ + + + +############################### DISPLAY ################################## +sub display +{ + my($N,$match,$note,$date,$num); + # display a certain note + print "\n"; + &num_bereich; # get @NumBlock from $numer + foreach $N (@NumBlock) + { + ($note, $date) = $db->get_single($N); + if($note) + { + output($N, $note, $date, "SINGLE"); + print "\n"; + $match = 1; + } + } + if(!$match) + { + print "no note with that number found!\n"; + } +} +############################### SEARCH ################################## +sub search +{ + my($n,$match,$note,$date,$num,%res); + $maxlen += $timelen; + if($searchstring eq "") + { + &usage; + exit(1); + } + print "searching the database $dbname for \"$searchstring\"...\n\n"; + + %res = $db->get_search($searchstring); + + foreach $num (sort { $a <=> $b } keys %res) + { + output($num, $res{$num}->{'note'}, $res{$num}->{'date'}); + $match = 1; + } + + + if(!$match) + { + print "no matching note found!\n"; + } + print "\n"; +} + + +############################### LIST ################################## +sub list +{ + my(@topic,@RealTopic, $i,$t,$n,$num,@CurItem,$top,$in,%res); + if($mode ne "interactive") + { + print "List of all existing notes:\n\n"; + } + + # list all available notes (number and firstline) + %res = $db->get_all(); + + if($TOPIC) + { + undef %TP; + } + + foreach $num (sort { $a <=> $b } keys %res) + { + $n = $res{$num}->{'note'}; + $t = $res{$num}->{'date'}; + if($TOPIC) + { + # this allows us to have multiple topics (subtopics!) + my ($firstline,$dummy) = split /\n/, $n, 2; + if($firstline =~ /^($TopicSep)/) + { + @topic = split(/$TopicSep/,$firstline); + } + else + { + @topic = (); + } + # looks like: "\topic\" + # collect a list of topics under the current topic + if($topic[$CurDepth-1] eq $CurTopic && $topic[$CurDepth] ne "") + { + if(exists $TP{$topic[$CurDepth]}) + { + $TP{$topic[$CurDepth]}++; + } + else + { + # only if the next item *is* a topic! + $TP{$topic[$CurDepth]} = 1 if(($CurDepth) <= $#topic); + } + } + elsif($topic[$CurDepth-1] eq $CurTopic || ($topic[$CurDepth] eq "" && $CurDepth ==1)) + { + # cut the topic off the note-text + if($n =~ /^($TopicSep)/) + { + $CurItem[$i]->{'note'} = $dummy; + } + else + { + $CurItem[$i]->{'note'} = $n; + } + # save for later output() call + $CurItem[$i]->{'num'} = $num; + $CurItem[$i]->{'time'} = $t; + $i++; + # use this note for building the $PATH! + if($RealTopic[0] eq "") + { + @RealTopic = @topic; + } + } + } + else + { + output($num, $n, $t); + } + } + if($TOPIC) + { + if($CurTopic ne "") + { + undef $PATH; + foreach (@RealTopic) + { + $PATH .= $_ . $TopicSep; + last if($_ eq $CurTopic); + } + } + else + { + $PATH = $TopicSep; + } + + # we are at top level, print a list of topics... + foreach $top (sort(keys %TP)) + { + output("-", " => ". $top . "$TopicSep ($TP{$top} notes)", + " Sub Topic "); + } + #print Dumper(@CurItem); + for($in=0;$in<$i;$in++) + { + output( $CurItem[$in]->{'num'}, + $CurItem[$in]->{'note'}, + $CurItem[$in]->{'time'} ); + } + } + + print "\n"; +} + +############################### NEW ################################## +sub new +{ + my($TEMP,$editor, $date, $note, $WARN, $c, $line, $num, @topic); + $date = &getdate; + if($ALWAYS_EDIT eq "YES") + { + $TEMP = "/tmp/note.$$"; + # let the user edit it... + $editor = &find_editor; + if($editor) + { + system $editor, $TEMP; + } + else + { + print "Could not find an editor to use!\n"; + exit(0); + } + # read it in ($note) + $note = ""; + open E, "<$TEMP" or $WARN = 1; + if($WARN) + { + print "...edit process interupted! No note has been saved.\n"; + undef $WARN; + return; + } + $c = 0; + while() + { + $note = $note . $_; + } + chomp $note; + close E; + # privacy! + unlink $TEMP; + } + else + { + $note = ""; + $line = ""; + # create a new note + print "enter the text of the note, end with .\n"; + do + { + $line = ; + $note = $note . $line; + } until $line eq ".\n"; + # remove the . ! + chop $note; + chop $note; + } + + # since we have not number, look for the next available: + $number = $db->get_nextnum(); + if($TOPIC && $CurTopic ne "") + { + @topic = split(/$TopicSep/,$note); + if($topic[1] eq "") + { + $note = $PATH . "\n$note"; + } + } + + + $db->set_new($number,$note,$date); + + # everything ok until here! + print "note stored. it has been assigned the number $number.\n\n"; +} + + +############################### DELETE ################################## +sub del +{ + my($i,@count, $setnum, $pos, $ERR); + # delete a note + &num_bereich; # get @NumBlock from $number + foreach $_ (@NumBlock) + { + $ERR = $db->set_del($_); + if($ERR) + { + print "no note with number $_ found!\n"; + } + else + { + print "note number $_ has been deleted.\n"; + } + } + # recount the notenumbers: + @NumBlock = (); +} + +############################### EDIT ################################## +sub edit +{ + my($keeptime, $date, $editor, $TEMP, $note, $t, $num, $match); + # edit a note + $date = &getdate; + ($note, $keeptime) = $db->get_single($number); + if($keeptime eq "") + { + print "no note with that number found!\n\n"; + exit(0) if($mode ne "interactive"); + } + $TEMP = "/tmp/note.$USER.$$"; + open NOTE,">$TEMP" or die "Could not open $TEMP\n"; + select NOTE; + + print $note; + close NOTE; + select STDOUT; + $editor = &find_editor; + if($editor) + { + system $editor, $TEMP; + } + else + { + print "Could not find an editor to use!\n"; + exit(0); + } + $note = ""; + open NOTE,"<$TEMP" or die "Could not open $TEMP\n"; + + while() + { + $note = $note . $_; + } + chomp $note; + close NOTE; + + unlink $TEMP; + + if($KEEP_TIMESTAMP eq "YES") + { + $t = $keeptime; + } + else + { + $t = $date; + } + + # we got it, now save to db + $db->set_edit($number, $note, $t); + + print "note number $number has been changed.\n"; +} + + +sub dump +{ + my(%res, $num); + # $dump_file + open (DUMP, ">$dump_file") or die "could not open $dump_file\n"; + select DUMP; + %res = $db->get_all(); + foreach $num (sort { $a <=> $b } keys %res) + { + print STDOUT "dumping note number $num to $dump_file\n"; + print "Number: $num\n" + ."Timestamp: $res{$num}->{'date'}\n" + ."$res{$num}->{'note'}\n"; + } + print "\n"; + close(DUMP); + select STDOUT; +} + +sub import +{ + my($num, $start, $complete, $dummi, $note, $date, $time); + # open $dump_file and import it into the notedb + open (DUMP, "<$dump_file") or die "could not open $dump_file\n"; + $complete=0; + $start = 0; + while() + { + chomp $_; + if($_ =~ /^Number:\s\d+/) + { + if($start == 0) + { + # we have no previous record + ($dummi,$number) = split(/\s/,$_); + $start = 1; + } + else + { + # we got a complete record, save it! + $db->set_new(0,$note, $date); + print "note number $number from $dump_file inserted into notedb.\n"; + $complete = 0; + $note = ""; + $date = ""; + ($dummi,$number) = split(/\s/,$_); + } + } + elsif($_ =~ /^Timestamp:\s\d+/ && $complete == 0) + { + ($dummi,$date,$time) = split(/\s/,$_); + $date = "$date $time"; + $complete = 1; + } + else + { + $note .= $_ . "\n"; + } + } + if($note ne "" && $date ne "") + { + # the last record, if existent + $db->set_new(0,$note, $date); + print "note number $number from $dump_file inserted into notedb.\n"; + } +} + + + +sub interactive +{ + #$|=1; + #my $term = new Term::ReadLine(''); + #my $OUT = $term->OUT || *STDOUT; + #my $term->MinLine(undef); + #my $attribs = $term->Attribs; + #$term->bind_key(ord "\cc", 'abort'); + my($maxlen_save, $B, $BB, $menu, $char, @LastTopic); + $maxlen_save = $maxlen; + # create menu: + $B = ""; + $BB = ""; + $menu = "[" . $B . "L" . $BB . " List " + . $B . "N" . $BB . " New " + . $B . "D" . $BB . " Delete " + . $B . "S" . $BB . " Search " + . $B . "E" . $BB . " Edit " + . $B . "?" . $BB . " Help " + . $B . "Q" . $BB . " Quit] "; # $CurTopic will be empty if $TOPIC is off! + # per default let's list all the stuff: + # Initially do a list command! + $maxlen += $timelen; + print "\n"; + &list; + undef $SetTitle; + for(;;) + { + $ListType = ""; + $maxlen = $maxlen_save; + if($CurDepth > 2) + { + print C $menu . $TOPICC . "../" . $CurTopic . $_TOPICC . ">"; + } + else + { + print C $menu . $TOPICC . $CurTopic . $_TOPICC . ">"; + } + + # endless until user press "Q" or "q"! + $char = ; + #$char = $term->readline(''); + chomp $char; + if($char =~ /^\d+\s*[\di*?,*?\-*?]*$/) + { + # display notes + $maxlen += $timelen; + $number = $char; + &display; + undef $SetTitle; + } + elsif($char =~ /^n$/i) + { + # create a new one + &new; + } + elsif($char =~ /^l$/ || $char =~ /^$/) + { + # list + print "\n"; + $ListType = ""; + $maxlen += $timelen; + &list; + undef $SetTitle; + } + elsif($char =~ /^L$/) + { + $ListType = "LONG"; + print "\n"; + &list; + undef $SetTitle; + } + elsif($char =~ /^h$/i || $char =~ /^\?/) + { + # zu dumm der Mensch ;-) + &help; + } + elsif($char =~ /^d\s+([\d*?,*?\-*?]*)$/i) + { + # delete one! + $number = $1; + &del; + } + elsif($char =~ /^d$/i) + { + # we have to ask her: + print "enter number(s) of note(s) you want to delete: "; + $char = ; + chomp $char; + $number = $char; + &del; + } + elsif($char =~ /^e\s+(\d+\-*\,*\d*)/i) + { + # edit one! + $number = $1; + &edit; + } + elsif($char =~ /^e$/i) + { + # we have to ask her: + print "enter number of the note you want to edit: "; + $char = ; + chomp $char; + $number = $char; + &edit; + } + elsif($char =~ /^s\s+/i) + { + # she want's to search + $searchstring = $'; + chomp $searchstring; + &search; + } + elsif($char =~ /^s$/i) + { + # we have to ask her: + print "enter the string you want to search for: "; + $char = ; + chomp $char; + $char =~ s/^\n//; + $searchstring = $char; + &search; + } + elsif($char =~ /^q$/i) + { + # schade!!! + print "\n\ngood bye\n"; + exit(0); + } + elsif($char =~ /^\.\.$/ || $char =~ /^cd\s*\.\.$/) + { + $CurDepth-- if ($CurDepth > 1); + $CurTopic = $LastTopic[$CurDepth]; + $maxlen += $timelen; + print "\n"; + &list; + undef $SetTitle; + } + else + { + # unknown + my $unchar = $char; + $unchar =~ s/^cd //; # you may use cd now! + if(exists $TP{$char} || exists $TP{$unchar}) + { + $char = $unchar if(exists $TP{$unchar}); + $LastTopic[$CurDepth] = $CurTopic; + $CurTopic = $char; + $maxlen += $timelen; + $CurDepth++; + print "\n"; + &list; + undef $SetTitle; + } + else + { + print "\nunknown command!\n"; + } + undef $unchar; + } + } +} + + + +sub usage +{ +print qq~This is the program note $version by Thomas Linden (c) 1999-2000. +It comes with absolutely NO WARRANTY. It is distributed under the +terms of the GNU General Public License. Use it at your own risk :-) +Usage: note [-i | --interactive] | [ options ] [ number [,number...]] +Options: + -h --help displays this help screen + -v --version displays the version number + -l --list [] lists all existing notes If no topic were specified, + it will display a list of all existing topics. + -L --longlist [] the same as -l but prints also the timestamp + -s --search searches for trough the notes database + -e --edit edit note with + -d --delete delete note with + -D --Dump [] dumps the notes to the textfile + -I --Import imports a previously dumped textfile into the + note-database. Dumps from the mysql and the binary + version are in the same format. + -i --interactive interactive mode + + o if you specify only a number (i.e. "note 4"), then the note with that + number will be displayed. + o you can specify more then one number for delete and display, for example: + "note -d 3,4" deletes #3 and #4. "note 5-7" displays #5, #6 and #7. + o if you run note without any parameter and if \$ALWAYS_INT in the config is + not set, then note will create a new note and prompt you for new text. + o If it finds \~/.noterc, it will process it. Refer to the manpage for more + informations about the configuration. + o In interactive mode you can get help at any time by typing "?" or "h" at + the prompt. +~; + exit 1; +} +sub find_editor { + return $PreferredEditor || $ENV{"VISUAL"} || $ENV{"EDITOR"} || "vim" || "vi" || "pico"; +} +#/ +sub output +{ + my($SSS, $LINE, $num, $note, $time, $TYPE, $L, $LONGSPC, $R, $PathLen, $SP, $title, $CUTSPACE, + $len, $diff, $Space, $nlen); + ($num, $note, $time, $TYPE) = @_; + if($ListType ne "LONG") + { + $SSS = "-" x ($maxlen + 31 - $timelen); + } + else + { + $SSS = "-" x ($maxlen + 31); + } + $nlen = length("$num"); + $LINE = "$BORDERC $SSS $_BORDERC\n"; + $L = $BORDERC . "[" . $_BORDERC; + $LONGSPC = " " x (26 - $nlen); + $R = $BORDERC . "]" . $_BORDERC; + $PathLen = length($PATH); # will be ZERO, if not in TOPIC mode! + if($TYPE ne "SINGLE") + { + if(!$SetTitle) + { + $SP = ""; + # print only if it is the first line! + if($ListType ne "LONG") + { + $SP = " " x ($maxlen-2 - $timelen - $PathLen); + } + else + { + $SP = " " x ($maxlen-2 - $PathLen); + } + print C $LINE; + + print C "$L $NUMC#$_NUMC "; + if($ListType eq "LONG") + { + print C " $TIMEC" . "creation date$_TIMEC "; + } + else + { + print $LONGSPC; + } + if($TOPIC) + { + print C $TOPICC . "$PATH $_TOPICC$SP$R\n"; + } + else + { + print C $NOTEC . "note$_NOTEC$SP$R\n"; + } + + print C $LINE; + $SetTitle = 1; + } + $title = ""; + $CUTSPACE = " " x $maxlen; + $note =~ s/\n/$CUTSPACE/g; + $len = length($note); + if($len < ($maxlen - 2 - $nlen)) + { + $diff = $maxlen - $len; + $Space = " " x $diff; + if($num eq "-") + { + $title = $BORDERC . $TOPICC . "\"" . $note . "\"" . $_TOPICC . $Space . "$_BORDERC"; + } + else + { + $title = $BORDERC . $NOTEC . "\"" . $note . "\"" . $_NOTEC . $Space . "$_BORDERC"; + } + + } + else + { + $title = substr($note,0,($maxlen - 2 - $nlen)); + $title = $BORDERC . $NOTEC . "\"" . $title . "...\"$_NOTEC$_BORDERC"; + } + # $title should now look as: "A sample note " + print C "$L $NUMC$num$_NUMC $R"; + if($ListType eq "LONG") + { + print C "$L$TIMEC" . $time . " $_TIMEC$R"; + } + print C "$L $NOTEC" . $title . "$_NOTEC $R\n"; + + + print C $LINE; + } + else + { + chomp $note; + $Space = " " x ($maxlen - 16); + $SP = " " x ($maxlen + 13); + #print C $LINE; + #print C "$L $NUMC#$_NUMC " . $TIMEC . "creation date$_TIMEC$SP$R\n"; + print C $LINE; + print C "$L $NUMC$num$_NUMC $R$L$TIMEC$time$_TIMEC $Space$R\n"; + print C $LINE; + print C $NOTEC . $note . $_NOTEC . "\n"; + print C $LINE; + } + +} + + + +sub C +{ + my(%Color, $default, $S, $Col, $NC, $T); + # \033[1m%30s\033[0m + %Color = ( 'black' => '0;30', + 'red' => '0;31', + 'green' => '0;32', + 'yellow' => '0;33', + 'blue' => '0;34', + 'magenta' => '0;35', + 'cyan' => '0;36', + 'white' => '0;37', + 'B' => '1;30', + 'BLACK' => '1;30', + 'RED' => '1;31', + 'GREEN' => '1;32', + 'YELLOW' => '1;33', + 'BLUE' => '1;34', + 'MAGENTA' => '1;35', + 'CYAN' => '1;36', + 'WHITE' => '1;37', + 'black_' => '4;30', + 'red_' => '4;31', + 'green_' => '4;32', + 'yellow_' => '4;33', + 'blue_' => '4;34', + 'magenta_' => '4;35', + 'cyan_' => '4;36', + 'white_' => '4;37', + 'blackI' => '7;30', + 'redI' => '7;31', + 'greenI' => '7;32', + 'yellowI' => '7;33', + 'blueI' => '7;34', + 'magentaI' => '7;35', + 'cyanI' => '7;36', + 'whiteI' => '7;37' + ); + $default = "\033[0m"; + $S = $_[0]; + foreach $Col (%Color) + { + if ($S =~ /<$Col>/g) + { + if($COLOR ne "NO") + { + $NC = "\033[" . $Color{$Col} . "m"; + $S =~ s/<$Col>/$NC/g; + $S =~ s/<\/$Col>/$default/g; + } + else + { + $S =~ s/<$Col>//g; + $S =~ s/<\/$Col>//g; + } + } + } + return $S; +} + + +sub uen +{ + my($T); + $T = pack("u", $_[0]); + chomp $T; + return $T; +} + +sub ude +{ + my($T); + $T = unpack("u", $_[0]); + return $T; +} + +sub num_bereich +{ + my($m,@LR,@Sorted_LR,$i); + # $number is the one we want to delete! + # But does it contain kommas? + $m = 0; + if($number =~ /\,/) + { + # accept -d 3,4,7 + @NumBlock = split(/\,/,$number); + } + elsif($number =~ /^\d+\-\d+$/) + { + # accept -d 3-9 + @LR = split(/\-/,$number); + @Sorted_LR = (); + + if($LR[0] > $LR[1]) + { + @Sorted_LR = ($LR[1], $LR[0]); + } + elsif($LR[0] == $LR[1]) + { + # 0 and 1 are the same + @Sorted_LR = ($LR[0], $LR[1]); + } + else + { + @Sorted_LR = ($LR[0], $LR[1]); + } + + for($i=$Sorted_LR[0]; $i<=$Sorted_LR[1]; $i++) + { + # from 3-6 create @NumBlock (3,4,5,6) + $NumBlock[$m] = $i; + $m++; + } + } + else + { + @NumBlock = ($number); + } + +} + +sub getdate +{ + my($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time); + $year += 1900; + $mon += 1; + $mon =~ s/^(\d)$/0$1/; + $hour =~ s/^(\d)$/0$1/; + $min =~ s/^(\d)$/0$1/; + $sec =~ s/^(\d)$/0$1/; + $mday =~ s/^(\d)$/0$1/; + return "$mday.$mon.$year $hour:$min:$sec"; +} + + +sub help +{ +print qq~ +-------------------------------------------------------------- +HELP for interactive note $version + +The following commands are available: +L/l List notes. L=long, with timestamp and l=short without timestamp. + You can also just hit for short list. +N Create a new note. +D Delete a note. You can either hit "d 1" or "d 1-4" or just hit "d". + If you don't specify a number, you will be asked for. +S Search trough the notes database. Usage is similar to Delete, use + a string instead of a number to search for. +E Edit a note. Usage is similar to Delete but you can only edit note + a time.~; +if($TOPIC) +{ +print qq~ +T print a list of all existing topics. You can change the actual + topic by simply typing it's name. You can create a new topic by + creating a new note, the first line must be the topic borderd by + backslashes, i.e.: "\\newtopic\\". If you type just ".." instead + of a topic, you will go to the "default" topic, which contains + all notes without a topic.~; +} +print qq~ +?/H This help screen. +Q Exit the program. + +All commands except the List command are case insensitive. +--------------------------------------------------------------- +~; +} diff --git a/config/noterc b/config/noterc index ff55c48..890b5a0 100644 --- a/config/noterc +++ b/config/noterc @@ -1,34 +1,65 @@ -# 0.7 +# 0.8 # This is a sample config for the note script -# You do not need it, if you keep the values -# here unchanged. +# There are usefully defaults set in note itself. +# +# The default database backend is NOTEDB::binary. # # Copy it to your $HOME as .noterc # -# IMPORTANT: -# If you previously used note 0.1 or 0.2 then -# you will already have such a file. This file -# is not compatible with the one for note 0.3 and higher! -# You have to delete it and to create a new one. -# # This config has to be valid perl code. Therefore -# please be carefull! +# please be careful! # # You can contact me per email: # -# Thomas Linden, 23/2000 +# Thomas Linden, 19/03/2000 + + +# Your home, better do not change it! +$HOME = $ENV{'HOME'}; + + +# specify the path, where the NOTEDB directory +# resides +$libpath = "/usr/local/lib"; + + + +# you need to decide which database backend you want +# to use. Please refer to the corresponding documentation +# for closer information about the certain backend! +# Currently supported types: "binary" or "mysql". +$dbdriver = "binary"; + + +# backend specific settings: +####### mysql ############### +# sql database settings. +$dbhost = ""; # mysql server (hostname) +$dbuser = ""; # mysql username +$dbpasswd = ""; # her password +$dbname = ""; # database name +$table = "note"; # Table and field names. +$fnum = "number"; +$fnote = "note"; +$fdate = "date"; +######## end mysql ########### + + +####### binary db ################## +# The location of the note-database. If it does +# not exist, it will be created. Only if $driver = "binary" +$NOTEDB = $HOME . "/.notedb"; +# Define the maximum bytes a note can have in a +# note-entry. +$MAX_NOTE = 4096; + +# Define the maximum bytes a timestamp can have +# in a note-entry. +$MAX_TIME = 24; +####### end binary ################# + -# mysql database settings. leave them uncommented -# if you are not using the mysql version of note. -# $dbhost = ""; # mysql server (hostname) -# $dbuser = ""; # mysql username -# $dbpasswd = ""; # her password -# $dbname = ""; # database name -# $table = "note"; # Table and field names. -# $fnum = "number"; -# $fnote = "note"; -# $fdate = "date"; # uncomment this, if you want to run note always # in interactive mode @@ -62,40 +93,20 @@ $TOPIC = 1; #$TopicSep = '/'; -# Define the maximum bytes a note can have in a -# note-entry. -$MAX_NOTE = 1024; - - -# Define the maximum bytes a timestamp can have -# in a note-entry. -$MAX_TIME = 64; - - # The maximum width for displaying a note. $maxlen = 30; -# Your home, better do not change it! -$HOME = `echo \$HOME`; -chomp $HOME; - - -# The location of the note-database. If it does -# not exist, it will be created. -$NOTEDB = $HOME . "/.notedb"; - - # if $COLOR equals NO, then everything will be # displayed with your default colors (mostly black) -$COLOR = "NO"; +$COLOR = "YES"; # Color-definitions of the various fields. Will be # ignored if $COLOR = "NO". $BORDER_COLOR = "BLACK"; # Borders $NUM_COLOR = "blue"; # Note number -$NOTE_COLOR = "magenta"; # The note itself +$NOTE_COLOR = "green"; # The note itself $TIME_COLOR = "black"; # The time $TOPIC_COLOR = "BLACK"; # The topic "prompt" diff --git a/install.sh b/install.sh index c9cec31..429dc4e 100755 --- a/install.sh +++ b/install.sh @@ -1,19 +1,56 @@ #!/bin/sh -# installs note +# installer for note 0.8 > -echo "Welcome to note `cat VERSION` installation." -echo "the install script will ask you a view questions," -echo "make sure to answer them correctly!" +# $Id: install.sh,v 1.1 2000/03/19 03:33:28 thomas Exp thomas $ + +die () +{ + MSG=$1 + echo $MSG + exit 1 +} + +SRC=. + +NOTEDB="$SRC/NOTEDB" + +BIN="$SRC/bin" + +echo "Enter the destination for the note perl modules [/usr/local/lib] :" + +read LIBDIR + +echo "Enter the destination for the note program [/usr/local/bin] :" + +read BINDIR + +if [ "${LIBDIR}" = "" ] ; then + LIBDIR=/usr/local/lib +fi + +if [ "${BINDIR}" = "" ] ; then + BINDIR=/usr/local/bin +fi + +if [ ! -d ${LIBDIR} ] ; then + mkdir -p ${LIBDIR} || die "Could not create ${LIBDIR}!" +fi + +if [ ! -d ${BINDIR} ] ; then + mkdir -p ${BINDIR} || die "Could not create ${BINDIR}!" +fi + +echo "Installing note ..." + +cp -ri ${NOTEDB} ${LIBDIR} || die "Could not copy modules!" + +cp -i "${BIN}/note" ${BINDIR} || die "Could not copy note script!" + +chmod 755 ${BINDIR}/note +chmod 755 ${LIBDIR}/NOTEDB +chmod 644 ${LIBDIR}/NOTEDB/* + +echo "done. Please copy ${SRC}/config/noterc to ~/.noterc" +echo "and edit it if you like. " echo - -/bin/echo -n "creating the note database..." -NAME="_note" -DBNAME="$USER$NAME" -echo "DBNAME=$DBNAME" -mysqladmin create $DBNAME -echo "done." -/bin/echo -n "creating the table structure using defaults..." -mysql $DBNAME < sql -echo "done." - - +echo "Thanks for using note 0.8!" diff --git a/mysql/README b/mysql/README new file mode 100644 index 0000000..78cc14a --- /dev/null +++ b/mysql/README @@ -0,0 +1,62 @@ +README for the mysql database installation for note + +Requirements +============ + + You need the following things: + o perl installed (5.004x) + o mysql database installed and running + o Mysql perlmodule (you can find it on + http://www.mysql.org) PLEASE NOTE: + It needs the Module "Mysql". The install.sh + script will install it for you directly from + CPAN if you like. Newer versions + are DBI, which you can also use to access + mysql databases. If you want to use it, you + have to rewrite the program. Please let me + know, if you did it :-) + o permissions to create a new database and + to write data to this database. + + + +Installation +============ + + First, make sure all these things above are ok. + You can use the script "install.sh" to create a new + database and the table structure. You might edit + the script before running it. + + If you are getting trouble, i.e. if you have not the + required permissions to do that, please make sure, + you can. + As user root, you have to give your user the + neccessary permissions. Please refer to the mysql + documentation, how to do that. + After that repeat the step above. + + You can find a sample config file within the subdirectory + "config" named noterc. There are some special values + which you can use to connect to a different database + then the default. + install.sh will create the following database: + name: user_note + Maintable: note + Number: number(int 10) + Note: note(text) + Date: date(text) + + You can use the file "permissions" as a template for + modifying a users permissions to her database. Please + note, that there are different version of mysql out + there with different access privilege systems, which + are not compatible, refer to the documentation shipped + with your mysql installation to learn, how many fields + are available and what they are for. + + You may also take a look to: + http://www.mysql.org/Manual_chapter/manual_Privilege_system.html + + + This should be all. diff --git a/mysql/install.sh b/mysql/install.sh new file mode 100755 index 0000000..5bd2b2a --- /dev/null +++ b/mysql/install.sh @@ -0,0 +1,33 @@ +#!/bin/sh +# installs note +# This is the installer for the mysql version only! + +echo "Welcome to note `cat VERSION` installation." +echo "the install script will ask you a view questions," +echo "make sure to answer them correctly!" +echo + +/bin/echo -n "creating the note database..." +NAME="_note" +DBNAME="$USER$NAME" +echo "DBNAME=$DBNAME" +mysqladmin create $DBNAME +echo "done." +/bin/echo -n "creating the table structure using defaults..." +mysql $DBNAME < sql + +echo "Shall I try to install the required MySQL driver from CPAN?" +read YESNO + +case $YESNO in + "y" | "Y") + if [ $UID != 0 ] ; then + echo "You should be root for that!" + exit + fi + perl -MCPAN -e shell cpan> install mysql + ;; +esac +echo "done." + + diff --git a/mysql/permissions b/mysql/permissions new file mode 100644 index 0000000..966d1bf --- /dev/null +++ b/mysql/permissions @@ -0,0 +1,2 @@ +insert into user values + ('localhost','','','Y','Y','Y','Y','Y','Y','N','N','N','N','N','N','N','Y'); diff --git a/mysql/sql b/mysql/sql new file mode 100644 index 0000000..37d6072 --- /dev/null +++ b/mysql/sql @@ -0,0 +1,8 @@ +CREATE TABLE note ( + number int(10) DEFAULT '0' NOT NULL auto_increment, + note text, + date text, + PRIMARY KEY (number) +); +# sample grant statement: +#GRANT ALL PRIVILEGES ON tom_note TO tom@localhost IDENTIFIED BY 'password';