mirror of
https://codeberg.org/scip/note.git
synced 2025-12-17 04:31:02 +01:00
1640 lines
42 KiB
Perl
Executable File
1640 lines
42 KiB
Perl
Executable File
#!/usr/bin/perl
|
|
# $Id: note,v 1.27 2000/05/16 23:51:35 thomas Exp thomas $
|
|
#
|
|
#
|
|
# note - console notes management with database and encryption support.
|
|
# Copyright (C) 1999-2000 Thomas Linden (see README for details!)
|
|
#
|
|
# This program is free software; you can redistribute it and/or
|
|
# modify it under the terms of the GNU General Public License
|
|
# as published by the Free Software Foundation; either version 2
|
|
# of the License, or (at your option) any later version.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with this program; if not, write to the Free Software
|
|
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
#
|
|
# - Thomas Linden <tom@daemon.de>
|
|
#
|
|
# latest version on:
|
|
# http://www.daemon.de/software.html
|
|
# ftp://www.0x49.org/pub/scip/note/
|
|
#
|
|
|
|
use strict;
|
|
#use Data::Dumper;
|
|
use Getopt::Long;
|
|
|
|
#
|
|
# prototypes
|
|
#
|
|
sub usage; # print usage message for us thumb userz :-)
|
|
sub find_editor; # returns an external editor for use
|
|
sub output; # used by &list and &display
|
|
sub C; # print colourized
|
|
sub num_bereich; # returns array from "1-4" (1,2,3,4)
|
|
sub getdate; # return pretty formatted day
|
|
sub new; # crate new note
|
|
sub edit; # edit a note
|
|
sub del; # delete a note
|
|
sub display; # display one or more notes
|
|
sub list; # note-listing
|
|
sub help; # interactive help screen
|
|
sub import; # import from notedb-dump
|
|
sub display_tree; # show nice tree-view
|
|
sub tree; # build the tree
|
|
sub print_tree; # print the tree, contributed by Jens Heunemann <Jens.Heunemann@consol.de>. THX!
|
|
|
|
|
|
#
|
|
# globals
|
|
#
|
|
my (
|
|
#
|
|
# commandline options
|
|
#
|
|
$opt_, $opt_i, $opt_r, $opt_e, $opt_d,
|
|
$opt_s, $opt_t, $opt_T, $opt_l, $opt_L,
|
|
$opt_D, $opt_I, $opt_o, $opt_h, $opt_n, $opt_v,
|
|
|
|
#
|
|
# set from commandline (or interactive)
|
|
#
|
|
$number, $searchstring, $dump_file, $ImportType, $NewType, $Raw,
|
|
|
|
#
|
|
# options from config file .noterc
|
|
#
|
|
$maxlen, $timelen, $TOPIC, $NOTEDB, $MAX_TIME, $PreferredEditor,
|
|
$ALWAYS_INT, $KEEP_TIMESTAMP, $COLOR, $ALWAYS_EDIT, $HOME, $FormatText,
|
|
$BORDER_COLOR, $NOTE_COLOR, $NUM_COLOR, $TOPIC_COLOR, $MAX_NOTE,
|
|
$USE_CRYPT, $CRYPT_METHOD, $TopicSep, $DEFAULT_LIST, $TIME_COLOR,
|
|
|
|
#
|
|
# db specifics from .noterc
|
|
#
|
|
$db, $dbname, $dbhost, $dbuser, $dbpasswd,
|
|
$table, $fnum, $fnote, $fdate, $date, $dbdriver, $libpath,
|
|
|
|
#
|
|
# processed colors
|
|
#
|
|
$BORDERC, $_BORDERC, $NOTEC, $NUMC, $_NUMC, $_NOTEC, $TIMEC,
|
|
$_TIMEC, $TOPICC, $_TOPICC,
|
|
|
|
#
|
|
# config presets
|
|
#
|
|
$DEFAULTDBNAME, $USER, $PATH, $CONF,
|
|
|
|
#
|
|
# internals
|
|
#
|
|
$TYPE, $mode, $NoteKey,
|
|
$version, $number, $CurTopic, $CurDepth, $WantTopic,
|
|
$sizeof, %TP, $TreeType, $ListType, $SetTitle,
|
|
@ArgTopics, $key, $typedef, @NumBlock, $has_nothing,
|
|
);
|
|
|
|
|
|
#
|
|
# 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 = 64;
|
|
$COLOR = "YES";
|
|
$BORDER_COLOR = "BLACK";
|
|
$NUM_COLOR = "blue";
|
|
$NOTE_COLOR = "green";
|
|
$TIME_COLOR = "black";
|
|
$TOPIC_COLOR = "BLACK";
|
|
$TOPIC = 1;
|
|
$TopicSep = '/';
|
|
$version = "1.0.6";
|
|
if($TOPIC)
|
|
{
|
|
$CurDepth = 1; # the current depth inside the topic "directory" structure...
|
|
}
|
|
$USE_CRYPT = "NO";
|
|
|
|
|
|
|
|
|
|
#
|
|
# process command line args
|
|
#
|
|
if($ARGV[0] eq "")
|
|
{
|
|
$mode = "new";
|
|
}
|
|
elsif($#ARGV == 0 && $ARGV[0] eq "-") {
|
|
$mode = "new";
|
|
$NewType = 1; # read from STDIN until EOF
|
|
shift;
|
|
undef $has_nothing;
|
|
}
|
|
else
|
|
{
|
|
Getopt::Long::Configure( qw(no_ignore_case));
|
|
GetOptions (
|
|
"interactive|i!" => \$opt_i, # no arg
|
|
"raw|r!" => \$opt_r, # no arg
|
|
"edit|e=i" => \$opt_e, # integer, required
|
|
"delete|d=s" => \$opt_d, # integer, required
|
|
"search|s=s" => \$opt_s, # string, required
|
|
"tree|topic|t!" => \$opt_t, # no arg
|
|
"long_tree|T!" => \$opt_T, # no arg
|
|
"list|l:s" => \$opt_l, # string, optional
|
|
"long_list|L:s" => \$opt_L, # string, optional
|
|
"dump|D:s" => \$opt_D, # string, optional
|
|
"import|I:s" => \$opt_I, # string, optional
|
|
"overwrite|o!" => \$opt_o, # no arg
|
|
"help|h|?!" => \$opt_h, # no arg
|
|
"version|v!" => \$opt_v # no arg
|
|
);
|
|
$opt_n = shift; # after that @ARGV contains eventually
|
|
# a note-number
|
|
# $opt_ is a single dash, in case of existence!
|
|
#
|
|
# determine mode
|
|
#
|
|
if($opt_i) {
|
|
$mode = "interactive";
|
|
}
|
|
elsif(defined $opt_l || defined $opt_L) {
|
|
$mode = "list";
|
|
if(defined $opt_l) {
|
|
@ArgTopics = split /$TopicSep/, $opt_l;
|
|
}
|
|
else {
|
|
$ListType = "LONG";
|
|
@ArgTopics = split /$TopicSep/, $opt_L;
|
|
}
|
|
$CurDepth += $#ArgTopics + 1 if($opt_l || $opt_L);
|
|
$CurTopic = $ArgTopics[$#ArgTopics]; # use the last element everytime...
|
|
}
|
|
elsif($opt_t || $opt_T) {
|
|
$mode = "tree";
|
|
$TreeType = "LONG" if($opt_T);
|
|
}
|
|
elsif(defined $opt_s) {
|
|
$mode = "search";
|
|
$searchstring = $opt_s;
|
|
}
|
|
elsif($opt_e) {
|
|
$mode = "edit";
|
|
$number = $opt_e;
|
|
}
|
|
elsif($opt_d) {
|
|
$mode = "delete";
|
|
$number = $opt_d;
|
|
}
|
|
elsif(defined $opt_D) {
|
|
$mode = "dump";
|
|
if(!$opt_) {
|
|
if($opt_D ne "") {
|
|
$dump_file = $opt_D;
|
|
}
|
|
else {
|
|
$dump_file = "note.dump.$$";
|
|
print "no dumpfile specified, using $dump_file.\n";
|
|
}
|
|
}
|
|
else {
|
|
$dump_file = "-"; # use STDIN
|
|
}
|
|
}
|
|
elsif(defined $opt_I) {
|
|
$mode = "import";
|
|
if(!$opt_) {
|
|
if($opt_I ne "") {
|
|
$dump_file = $opt_I;
|
|
}
|
|
else {
|
|
print "Import-error! No dump_file specified!\n";
|
|
exit(1);
|
|
}
|
|
}
|
|
else {
|
|
$dump_file = "-";
|
|
}
|
|
}
|
|
elsif($opt_v) {
|
|
print "This is note $version by Thomas Linden <tom\@daemon.de>.\n";
|
|
exit(0);
|
|
}
|
|
elsif($opt_h) {
|
|
&usage;
|
|
}
|
|
else {
|
|
$has_nothing = 1;
|
|
}
|
|
### determine generic options
|
|
if($opt_n =~ /^[\d+\-?\,*]+$/) {
|
|
# first arg is a digit!
|
|
if($mode eq "") {
|
|
$number = $opt_n;
|
|
$mode = "display";
|
|
undef $has_nothing;
|
|
}
|
|
else {
|
|
print "mode <$mode> does not take a numerical argument!\n";
|
|
exit(1);
|
|
}
|
|
}
|
|
elsif($opt_n ne "") {
|
|
print "Unknown option: $opt_n\n";
|
|
&usage;
|
|
}
|
|
if($opt_r) {
|
|
$Raw = 1;
|
|
}
|
|
if($opt_o) {
|
|
$ImportType = "overwrite";
|
|
if(!$opt_I) {
|
|
print "--overwrite is only suitable for use with --import!\n";
|
|
exit(1);
|
|
}
|
|
}
|
|
#####
|
|
}
|
|
if($has_nothing && $mode eq "")
|
|
{
|
|
&usage;
|
|
}
|
|
|
|
|
|
# read the configfile.
|
|
if(-e $CONF)
|
|
{
|
|
&getconfig($CONF);
|
|
}
|
|
|
|
|
|
# Always interactive?
|
|
if($ALWAYS_INT eq "YES" && $mode ne "dump" && $mode ne "import")
|
|
{
|
|
$mode = "interactive";
|
|
}
|
|
|
|
# OK ... Long-Listing shall be default ... You wanted it!!!
|
|
if($DEFAULT_LIST eq "LONG")
|
|
{
|
|
# takes only precedence in commandline mode
|
|
$ListType="LONG";
|
|
}
|
|
|
|
|
|
|
|
# *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);
|
|
# }
|
|
#}
|
|
if($dbdriver eq "binary") {
|
|
eval {
|
|
require NOTEDB::binary;
|
|
$db = new NOTEDB($dbdriver, $NOTEDB, $MAX_NOTE, $MAX_TIME, $dbdriver);
|
|
}
|
|
}
|
|
else {
|
|
eval {
|
|
require "NOTEDB/$dbdriver.pm";
|
|
$db = new NOTEDB($dbdriver, $dbname, $dbhost, $dbuser, $dbpasswd, $table, $fnum, $fnote, $fdate);
|
|
};
|
|
}
|
|
if($@) {
|
|
print "Unsupported database backend: NOTEDB::$dbdriver!\n";
|
|
print "The following error has occured:\n------------------------\n" . $@ . "\n------------------------\n";
|
|
exit 1;
|
|
}
|
|
|
|
# add the backend version to the note version:
|
|
$version .= " " . $db->version();
|
|
|
|
# calculate some constants...
|
|
$BORDERC = "<$BORDER_COLOR>";
|
|
$_BORDERC = "</$BORDER_COLOR>";
|
|
$NUMC = "<$NUM_COLOR>";
|
|
$_NUMC = "</$NUM_COLOR>";
|
|
$NOTEC = "<$NOTE_COLOR>";
|
|
$_NOTEC = "</$NOTE_COLOR>";
|
|
$TIMEC = "<$TIME_COLOR>";
|
|
$_TIMEC = "</$TIME_COLOR>";
|
|
$TOPICC = "<$TOPIC_COLOR>";
|
|
$_TOPICC = "</$TOPIC_COLOR>";
|
|
|
|
$NoteKey = $TopicSep . "notes" . $TopicSep;
|
|
|
|
|
|
if($ListType ne "LONG" && $mode ne "interactive")
|
|
{
|
|
#$maxlen += $timelen; # no time will be displayed!
|
|
}
|
|
|
|
|
|
# check if the user wants to use encryption:
|
|
if($USE_CRYPT eq "YES" && $NOTEDB::crypt_supported == 1) {
|
|
if($CRYPT_METHOD eq "") {
|
|
$CRYPT_METHOD = "Crypt::IDEA";
|
|
}
|
|
if(!exists $ENV{'NOTE_PASSWD'}) {
|
|
print "password: ";
|
|
eval {
|
|
local($|) = 1;
|
|
local(*TTY);
|
|
open(TTY,"/dev/tty");
|
|
system ("stty -echo </dev/tty");
|
|
chomp($key = <TTY>);
|
|
print STDERR "\r\n";
|
|
system ("stty echo </dev/tty");
|
|
close(TTY);
|
|
};
|
|
if($@) {
|
|
$key = <>;
|
|
}
|
|
}
|
|
else {
|
|
$key = $ENV{'NOTE_PASSWD'};
|
|
}
|
|
chomp $key;
|
|
$db->use_crypt($key,$CRYPT_METHOD);
|
|
undef $key;
|
|
# verify correctness of passwd
|
|
my ($cnote, $cdate) = $db->get_single(1);
|
|
if($cdate ne "") {
|
|
if($cdate !~ /^\d+\.\d+?/) {
|
|
print "access denied.\n"; # decrypted $date is not a number!
|
|
exit(1);
|
|
}
|
|
} #else empty!
|
|
}
|
|
else {
|
|
$db->no_crypt;
|
|
# does: NOTEDB::crypt_supported = 0;
|
|
my ($cnote, $cdate) = $db->get_single(1);
|
|
if($cdate ne "") {
|
|
if($cdate !~ /^\d+\.\d+?/) {
|
|
print "$NOTEDB seems to be encrypted!\n";
|
|
exit(1);
|
|
}
|
|
}
|
|
}
|
|
|
|
# main loop: ###############
|
|
if($mode eq "display")
|
|
{
|
|
&display;
|
|
}
|
|
elsif($mode eq "search")
|
|
{
|
|
&search;
|
|
}
|
|
elsif($mode eq "list")
|
|
{
|
|
&list;
|
|
}
|
|
elsif($mode eq "tree")
|
|
{
|
|
&display_tree;
|
|
}
|
|
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)
|
|
{
|
|
if($Raw) {
|
|
print "$N\n$date\n$note\n\n";
|
|
}
|
|
else {
|
|
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);
|
|
if($searchstring eq "")
|
|
{
|
|
print "No searchstring specified!\n";
|
|
}
|
|
else {
|
|
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" && !$Raw)
|
|
{
|
|
print "\nList of all existing notes:\n\n";
|
|
}
|
|
else {
|
|
print "\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(<E>)
|
|
{
|
|
$note = $note . $_;
|
|
}
|
|
chomp $note;
|
|
close E;
|
|
# privacy!
|
|
unlink $TEMP;
|
|
}
|
|
else
|
|
{
|
|
$note = "";
|
|
$line = "";
|
|
# create a new note
|
|
if($NewType)
|
|
{
|
|
# be silent! read from STDIN until EOF.
|
|
while (<STDIN>) { $note .= $_; }
|
|
}
|
|
else
|
|
{
|
|
print "enter the text of the note, end with .\n";
|
|
do
|
|
{
|
|
$line = <STDIN>;
|
|
$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:
|
|
$db->set_recountnums();
|
|
|
|
@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 = $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);
|
|
# $dump_file
|
|
if($dump_file eq "-") {
|
|
$DUMP = *STDOUT;
|
|
}
|
|
else {
|
|
open (DUMPFILE, ">$dump_file") or die "could not open $dump_file\n";
|
|
$DUMP = *DUMPFILE;
|
|
}
|
|
select $DUMP;
|
|
%res = $db->get_all();
|
|
foreach $num (sort { $a <=> $b } keys %res)
|
|
{
|
|
print STDOUT "dumping note number $num to $dump_file\n" if($dump_file ne "-");
|
|
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, $number, $stdin, $DUMP);
|
|
# open $dump_file and import it into the notedb
|
|
$stdin = 1 if($dump_file eq "-");
|
|
if($stdin) {
|
|
$DUMP = *STDIN;
|
|
}
|
|
else {
|
|
open (DUMPFILE, "<$dump_file") or die "could not open $dump_file\n";
|
|
$DUMP = *DUMPFILE;
|
|
}
|
|
$db->set_del_all() if($ImportType ne "");
|
|
$complete=0;
|
|
$start = 0;
|
|
while(<$DUMP>)
|
|
{
|
|
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!
|
|
$number = $db->get_nextnum();
|
|
$db->set_new($number,$note, $date);
|
|
print "note number $number from $dump_file inserted into notedb.\n" if(!$stdin);
|
|
$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
|
|
$number = $db->get_nextnum();
|
|
$db->set_new($number,$note, $date);
|
|
print "note number $number from $dump_file inserted into notedb.\n" if(!$stdin);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
sub interactive
|
|
{
|
|
my($B, $BB, $menu, $char, @LastTopic, $Channel);
|
|
$Channel = $|;
|
|
# create menu:
|
|
$B = "<blackI>";
|
|
$BB = "</blackI>";
|
|
$menu = "[" . $B . "L" . $BB . "-List ";
|
|
if($TOPIC) {
|
|
$menu .= $B . "T" . $BB . "-Topics ";
|
|
}
|
|
$menu .= $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!
|
|
$ListType = ($DEFAULT_LIST eq "LONG") ? "LONG" : "";
|
|
&list;
|
|
|
|
for(;;)
|
|
{
|
|
$ListType = ($DEFAULT_LIST eq "LONG") ? "LONG" : "";
|
|
undef $SetTitle;
|
|
if($CurDepth > 2)
|
|
{
|
|
print C $menu . $TOPICC . "../" . $CurTopic . $_TOPICC . ">";
|
|
}
|
|
else
|
|
{
|
|
print C $menu . $TOPICC . $CurTopic . $_TOPICC . ">";
|
|
}
|
|
|
|
# endless until user press "Q" or "q"!
|
|
$char = <STDIN>;
|
|
#$char = $term->readline('');
|
|
chomp $char;
|
|
if($char =~ /^\d+\s*[\di*?,*?\-*?]*$/)
|
|
{
|
|
$ListType = ""; #overrun
|
|
# display notes
|
|
$number = $char;
|
|
&display;
|
|
}
|
|
elsif($char =~ /^n$/i)
|
|
{
|
|
# create a new one
|
|
&new;
|
|
}
|
|
elsif($char =~ /^$/)
|
|
{
|
|
&list;
|
|
}
|
|
elsif($char =~ /^l$/)
|
|
{
|
|
$ListType = "";
|
|
&list;
|
|
}
|
|
elsif($char =~ /^L$/)
|
|
{
|
|
$ListType = "LONG";
|
|
&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 = <STDIN>;
|
|
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 = <STDIN>;
|
|
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 = <STDIN>;
|
|
chomp $char;
|
|
$char =~ s/^\n//;
|
|
$searchstring = $char;
|
|
&search;
|
|
}
|
|
elsif($char =~ /^q$/i)
|
|
{
|
|
# schade!!!
|
|
$| = $Channel;
|
|
print "\n\ngood bye!\n";
|
|
exit(0);
|
|
}
|
|
elsif($char =~ /^t$/)
|
|
{
|
|
$TreeType = "";
|
|
&display_tree;
|
|
}
|
|
elsif($char =~ /^T$/)
|
|
{
|
|
$TreeType = "LONG";
|
|
&display_tree;
|
|
$TreeType = "";
|
|
}
|
|
elsif($char =~ /^\.\.$/ || $char =~ /^cd\s*\.\.$/)
|
|
{
|
|
$CurDepth-- if ($CurDepth > 1);
|
|
$CurTopic = $LastTopic[$CurDepth];
|
|
&list;
|
|
}
|
|
elsif($char =~ /^l\s+(\w+)$/)
|
|
{
|
|
# list
|
|
$WantTopic = $1;
|
|
if(exists $TP{$WantTopic})
|
|
{
|
|
my %SaveTP = %TP;
|
|
$LastTopic[$CurDepth] = $CurTopic;
|
|
$CurTopic = $1;
|
|
$CurDepth++;
|
|
|
|
&list;
|
|
|
|
$CurTopic = $LastTopic[$CurDepth];
|
|
$CurDepth--;
|
|
%TP = %SaveTP;
|
|
}
|
|
else
|
|
{
|
|
print "\nunknown command!\n";
|
|
}
|
|
}
|
|
else
|
|
{
|
|
# unknown
|
|
my $unchar = $char;
|
|
$unchar =~ s/^cd //; # you may use cd <topic> now!
|
|
if(exists $TP{$char} || exists $TP{$unchar})
|
|
{
|
|
$char = $unchar if(exists $TP{$unchar});
|
|
$LastTopic[$CurDepth] = $CurTopic;
|
|
$CurTopic = $char;
|
|
$CurDepth++;
|
|
&list;
|
|
}
|
|
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 [ options ] [ number [,number...]]
|
|
Options:
|
|
-h --help displays this help screen
|
|
-v --version displays the version number
|
|
-l --list [<topic>] lists all existing notes If no topic were specified,
|
|
it will display a list of all existing topics.
|
|
-L --longlist [<topic>] the same as -l but prints also the timestamp
|
|
-t --topic prints a list of all topics as a tree.
|
|
-T --longtopc prints the topic-tree with the notes under each topic
|
|
-s --search <string> searches for <string> trough the notes database
|
|
-e --edit <number> edit note with <number>
|
|
-d --delete <number> delete note with <number>
|
|
-D --Dump [<file> | -] dumps the notes to the textfile <file>. if <file> is simply
|
|
a "-" it will printed out to standard output.
|
|
-I --Import <file> | - imports a previously dumped textfile into the
|
|
note-database. Data will be appended by default.
|
|
You can also specify a dash "note -I -" instead of a <file>,
|
|
which causes note, silently to read in a dump from STDIN.
|
|
-o --overwrite only suitable for use with --Import. Overwrites an
|
|
existing notedb.
|
|
-r --raw raw mode, output will not be formatted. Works not in interactive
|
|
mode, only on cmd-line for list and display.
|
|
-i --interactive interactive mode
|
|
- if you run note only with one dash: "note -", then it will
|
|
read in a new note from STDIN until EOF, this makes it
|
|
possible to pipe text into a new note.
|
|
|
|
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 "AlwaysInteractive" in the config
|
|
set off, 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.
|
|
o If encryption support is turned on, note will ask you for a passphrase every
|
|
time it runs. You can avoid this behavior by setting the environment-variable
|
|
\$NOTE_PASSWD. You will need this for example, if you call note from a script.
|
|
~;
|
|
#my ($package, $filename, $line) = caller;
|
|
#print "called from line $line\n";
|
|
exit 1;
|
|
}
|
|
|
|
sub find_editor {
|
|
return $PreferredEditor || $ENV{"VISUAL"} || $ENV{"EDITOR"} || "vim" || "vi" || "pico";
|
|
}
|
|
|
|
#/
|
|
|
|
sub format {
|
|
# make text bold/underlined/inverse using current $NOTEC
|
|
# s/\[([^]]*)\]/$param{$1}/g;
|
|
my($note) = @_;
|
|
if($FormatText) {
|
|
my $BN = uc($NOTEC);
|
|
my $_BN = uc($_NOTEC);
|
|
my $UN = $NOTEC;
|
|
$UN =~ s/<(.*)>/<$1_>/;
|
|
my $_UN = $UN;
|
|
$_UN =~ s/<(.*)>/<\/$1>/;
|
|
my $IN = $NOTEC; my $_IN = $_NOTEC;
|
|
$IN =~ s/<(.*)>/<$1I>/;
|
|
$_IN =~ s/<(.*)>/<$1I>/;
|
|
#$note =~ s/ (\*)(.+)(\*) / $BN$2$_BN /g;
|
|
#$note =~ s/ (_)(.+)(_) / $UN$2$_UN /g;
|
|
#$note =~ s/ (\/)(.+)(\/) / $IN$2$_IN /g;
|
|
$note =~ s/\*\*([^\*^\*]*)\*\*/$BN$1$_BN/g;
|
|
$note =~ s/__([^_^_]*)__/$UN$1$_UN/g;
|
|
$note =~ s/{{([^}^}]*)}}/$IN$1$_IN/g;
|
|
}
|
|
$note =~ s/(<\/.*>)/$1$NOTEC/g;
|
|
$note;
|
|
}
|
|
|
|
sub output
|
|
{
|
|
my($SSS, $LINE, $num, $note, $time, $TYPE, $L, $LONGSPC, $R, $PathLen, $SP, $title, $CUTSPACE,
|
|
$len, $diff, $Space, $nlen, $txtlen);
|
|
($num, $note, $time, $TYPE) = @_;
|
|
$txtlen = ($ListType eq "LONG") ? $maxlen : $timelen + $maxlen;
|
|
|
|
$note = &format($note);
|
|
|
|
$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!
|
|
$SP = " " x ($maxlen - 2 - $PathLen);
|
|
if(!$Raw) {
|
|
# no title in raw-mode!
|
|
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 $txtlen;
|
|
$note =~ s/\n/$CUTSPACE/g;
|
|
$len = length($note);
|
|
if($len < ($txtlen - 2 - $nlen))
|
|
{
|
|
$diff = $txtlen - $len;
|
|
$Space = " " x $diff;
|
|
if(!$Raw) {
|
|
if($num eq "-")
|
|
{
|
|
$title = $BORDERC . $TOPICC . "\"" . $note . "\"" . $_TOPICC . $Space . "$_BORDERC";
|
|
}
|
|
else
|
|
{
|
|
$title = $BORDERC . $NOTEC . "\"" . $note . "\"" . $_NOTEC . $Space . "$_BORDERC";
|
|
}
|
|
}
|
|
else {
|
|
$title = $note;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
$title = substr($note,0,($txtlen - 2 - $nlen));
|
|
if(!$Raw) {
|
|
$title = $BORDERC . $NOTEC . "\"" . $title . "...\"$_NOTEC$_BORDERC";
|
|
}
|
|
}
|
|
if($Raw) {
|
|
print "$num ";
|
|
print "$time " if($ListType eq "LONG");
|
|
if($title =~ /^ => (.*)$TopicSep (.*)$/) {
|
|
$title = "$1$TopicSep $2"; # seems to be a topic!
|
|
}
|
|
print "$title\n";
|
|
}
|
|
else {
|
|
# $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
|
|
{
|
|
# we will not reach this in raw-mode, therefore no decision here!
|
|
chomp $note;
|
|
$Space = " " x (($maxlen + $timelen) - 16);
|
|
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 num_bereich
|
|
{
|
|
my($m,@LR,@Sorted_LR,$i);
|
|
# $number is the one we want to delete!
|
|
# But does it contain kommas?
|
|
@NumBlock = (); #reset
|
|
$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
|
|
{
|
|
my $B = "<blackI>";
|
|
my $BB = "</blackI>";
|
|
my($S, $L, $T, $Q, $H, $N, $D, $E);
|
|
$L = $B . "L" . $BB . $NOTEC;
|
|
$T = $B . "T" . $BB . $NOTEC;
|
|
$Q = $B . "Q" . $BB . $NOTEC;
|
|
$H = $B . "?" . $BB . $NOTEC;
|
|
$N = $B . "N" . $BB . $NOTEC;
|
|
$D = $B . "D" . $BB . $NOTEC;
|
|
$E = $B . "E" . $BB . $NOTEC;
|
|
$S = $B . "S" . $BB . $NOTEC;
|
|
|
|
print C qq~$BORDERC
|
|
----------------------------------------------------------------------$_BORDERC $TOPICC
|
|
HELP for interactive note $version
|
|
$_TOPICC $NOTEC
|
|
The following commands are available:
|
|
$L List notes. L=long, with timestamp and l=short without timestamp.
|
|
You can also just hit <enter> for short list.
|
|
If you specify a subtopic, then list will display it's contents,
|
|
i.e.: "l mytopic" will dislpay notes under mytopic.
|
|
$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.
|
|
$H This help screen.
|
|
$Q Exit the program.~;
|
|
if($TOPIC)
|
|
{
|
|
print C qq~
|
|
$T print a list of all existing topics as a tree. T prints the tree
|
|
with all notes under each topic.
|
|
|
|
You can change the actual topic by simply typing it's name or by using
|
|
the command "cd", i.e. "cd mytopic". You can create a new topic by creating
|
|
a new note, the first line must be the topic borderd by slashes, i.e.:
|
|
"/newtopic/". The slash is the default topic-sepearator, but you can over-
|
|
ride this in the config! If you type just ".." instead of a topic, you will
|
|
go one step back in your topic-structure.
|
|
~;
|
|
}
|
|
print C qq~
|
|
$NOTEC
|
|
All commands except the List and Topic commands are case insensitive. $_NOTEC $BORDERC
|
|
----------------------------------------------------------------------$_BORDERC
|
|
~;
|
|
}
|
|
|
|
|
|
sub display_tree {
|
|
# displays a tree of all topics
|
|
my(%TREE, %res, $n, $t, $num, @nodes, $firstline, $text, $untext);
|
|
%res = $db->get_all();
|
|
foreach $num (keys %res)
|
|
{
|
|
$n = $res{$num}->{'note'};
|
|
$t = $res{$num}->{'date'};
|
|
# this allows us to have multiple topics (subtopics!)
|
|
my ($firstline,$text,$untext) = split /\n/, $n, 3;
|
|
if($firstline =~ /^($TopicSep)/)
|
|
{
|
|
$firstline =~ s/($TopicSep)*$//; #remove TopicSepatator
|
|
@nodes = split(/$TopicSep/,$firstline);
|
|
}
|
|
else
|
|
{
|
|
@nodes = ();("$TopicSep");
|
|
$text = $firstline;
|
|
}
|
|
&tree($num, $text, \%TREE, @nodes);
|
|
}
|
|
#return if ($num == 0);
|
|
# now that we have build our tree (in %TREE) go on t display it:
|
|
print C $BORDERC . "\n[" . $TopicSep . $BORDERC . "]\n";
|
|
&print_tree(\%{$TREE{''}},"") if(%TREE);
|
|
print C $BORDERC . $_BORDERC . "\n";
|
|
}
|
|
|
|
|
|
sub tree {
|
|
my($num, $text, $LocalTree, $node, @nodes) = @_;
|
|
if(@nodes) {
|
|
if(! exists $LocalTree->{$node}->{$NoteKey}) {
|
|
$LocalTree->{$node}->{$NoteKey} = [];
|
|
}
|
|
&tree($num, $text, $LocalTree->{$node}, @nodes);
|
|
}
|
|
else {
|
|
if(length($text) > ($maxlen - 5)) {
|
|
$text = substr($text, 0, ($maxlen -5));
|
|
}
|
|
$text = $text . " (" . $NUMC . "#" . $num . $_NUMC . $NOTEC . ")" . $_NOTEC if($text ne "");
|
|
push @{$LocalTree->{$node}->{$NoteKey}}, $text;
|
|
}
|
|
}
|
|
|
|
|
|
sub print_tree {
|
|
# thanks to Jens for his hints and this sub!
|
|
my $hashref=shift;
|
|
my $prefix=shift;
|
|
my @notes=@{$hashref->{$NoteKey}};
|
|
my @subnotes=sort grep { ! /^$NoteKey$/ } keys %$hashref;
|
|
if($TreeType eq "LONG") {
|
|
for my $note (@notes) {
|
|
if($note ne "") {
|
|
print C $BORDERC ;# . $prefix. "|\n";
|
|
print C "$prefix+---<" . $NOTEC . $note . $BORDERC . ">" . $_NOTEC . "\n";
|
|
}
|
|
}
|
|
}
|
|
for my $index (0..$#subnotes) {
|
|
print C $BORDERC . $prefix. "|\n";
|
|
print C "$prefix+---[" . $TOPICC . $subnotes[$index] . $BORDERC . "]\n";
|
|
&print_tree($hashref->{$subnotes[$index]},($index == $#subnotes?"$prefix ":"$prefix| "));
|
|
}
|
|
}
|
|
|
|
|
|
sub getconfig
|
|
{
|
|
my($configfile) = @_;
|
|
my ($home, $value, $option);
|
|
# checks are already done, so trust myself and just open it!
|
|
open CONFIG, "<$configfile" || die $!;
|
|
while(<CONFIG>) {
|
|
chomp;
|
|
next if(/^\s*$/ || /^\s*#/);
|
|
my ($option,$value) = split /\s\s*=?\s*/, $_, 2;
|
|
$value =~ s/\s*$//;
|
|
$home = $value if (/^Home/);
|
|
$libpath = $value if (/^LibPath/);
|
|
$dbdriver = $value if (/^DbDriver/);
|
|
$dbhost = $value if (/^DbHost/);
|
|
$dbuser = $value if (/^DbUser/);
|
|
$dbpasswd = $value if (/^DbPasswd/);
|
|
$dbname = $value if (/^DbName/);
|
|
$table = $value if (/^DbTable/);
|
|
$fnum = $value if (/^FieldNumber/);
|
|
$fnote = $value if (/^FieldNote/);
|
|
$fdate = $value if (/^FieldDate/);
|
|
$NOTEDB = $value if (/^NoteDb/);
|
|
$MAX_NOTE = $value if (/^MaxNoteByte/);
|
|
$MAX_TIME = $value if (/^MaxTimeByte/);
|
|
$CRYPT_METHOD = $value if (/^CryptMethod/);
|
|
$USE_CRYPT = "YES" if (/^UseEncryption/ && $value == 1);
|
|
$USE_CRYPT = undef if (/^UseEncryption/ && $value == 0);
|
|
$ALWAYS_INT = "YES" if (/^AlwaysInteractive/ && $value == 1);
|
|
$ALWAYS_INT = undef if (/^AlwaysInteractive/ && $value == 0);
|
|
$DEFAULT_LIST = "LONG" if (/^DefaultLong/ && $value == 1);
|
|
$DEFAULT_LIST = undef if (/^DefaultLong/ && $value == 0);
|
|
$ALWAYS_EDIT = "YES" if (/^AlwaysEditor/ && $value == 1);
|
|
$ALWAYS_EDIT = undef if (/^AlwaysEditor/ && $value == 0);
|
|
$KEEP_TIMESTAMP = "YES" if (/^KeepTimeStamp/ && $value == 1);
|
|
$KEEP_TIMESTAMP = undef if (/^KeepTimeStamp/ && $value == 0);
|
|
$COLOR = "YES" if (/^UseColors/ && $value == 1);
|
|
$COLOR = "NO" if (/^UseColors/ && $value == 0);
|
|
$TopicSep = $value if (/^TopicSeparator/);
|
|
$maxlen = $value if (/^MaxLen/);
|
|
$BORDER_COLOR = $value if (/^BorderColor/);
|
|
$NUM_COLOR = $value if (/^NumberColor/);
|
|
$NOTE_COLOR = $value if(/^NoteColor/);
|
|
$TIME_COLOR = $value if (/^TimeColor/);
|
|
$TOPIC_COLOR = $value if (/^TopicColor/);
|
|
$PreferredEditor = $value if (/^PreferredEditor/);
|
|
$FormatText = $value if (/^FormatText/);
|
|
}
|
|
chomp $home;
|
|
$home =~ s/\/*$//; # cut eventually / at the end
|
|
$HOME = eval($home);
|
|
if($NOTEDB =~ /^(~\/)(.*)$/) {
|
|
$NOTEDB = "/home/" . $USER . "/" . $2;
|
|
}
|
|
$libpath =~ s/\/*$//;
|
|
|
|
close CONFIG;
|
|
}
|
|
|
|
|
|
|
|
|
|
__END__
|
|
#
|
|
# $Log: note,v $
|
|
# Revision 1.27 2000/05/16 23:51:35 thomas
|
|
# fixed many option-parsing related bugd!
|
|
#
|
|
# Revision 1.26 2000/05/13 01:05:17 thomas
|
|
# changed config format and fixed some bugs
|
|
# as well as some other additions...
|
|
#
|
|
# Revision 1.25 2000/05/11 23:42:43 thomas
|
|
# --tree changed to --topic
|
|
#
|
|
# Revision 1.24 2000/05/10 22:59:44 thomas
|
|
# updated usage to reflect --raw and build it into output
|
|
# and display subs.
|
|
#
|
|
# Revision 1.23 2000/05/10 22:19:04 thomas
|
|
# changed to Getopt::Long, added --raw
|
|
#
|
|
# Revision 1.22 2000/05/01 18:51:40 thomas
|
|
# added "-" to sub dump
|
|
#
|
|
# Revision 1.21 2000/05/01 00:17:27 thomas
|
|
# *** empty log message ***
|
|
#
|
|
# Revision 1.20 2000/04/30 23:31:38 thomas
|
|
# added -o and coloured sub help.
|
|
#
|
|
# Revision 1.19 2000/04/30 16:07:23 thomas
|
|
# *** empty log message ***
|
|
#
|
|
# Revision 1.18 2000/04/30 14:58:21 thomas
|
|
# updated the usage and help subs
|
|
#
|
|
# Revision 1.17 2000/04/30 14:44:38 thomas
|
|
# added colors to the tree functions
|
|
#
|
|
# Revision 1.16 2000/04/30 14:28:38 thomas
|
|
# added the t command, which displays a topic-tree.
|
|
# and enhanced the list command in interactive mode
|
|
#
|
|
# Revision 1.15 2000/03/19 23:41:04 thomas
|
|
# changed set_del, now no extra TEMP file is required!
|
|
# instead I get it from $this->get_all() !
|
|
# Revision 1.14 2000/03/19 22:51:49 thomas
|
|
# Bug in NOTEDB::binary fixed, recount of nubers was
|
|
# incorrect.
|
|
#
|
|
# 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
|