Skip to content
Snippets Groups Projects
Commit ac62a4cc authored by Gerhard Gonter's avatar Gerhard Gonter :speech_balloon:
Browse files

converting content lines in parsend and array format back and forth seem to work now

parent 66295887
Branches
No related tags found
No related merge requests found
......@@ -4,10 +4,14 @@ package Tomboy::Note::Simple;
=head1 NAME
Tomboy::Note::Simple;
Tomboy::Note::Simple
=head1 SYNOPSIS
my $note= new Tomboy::Note::Simple (options => values);
=head2 parsing
# version 1
my $n1= parse Tomboy::Note::Simple ($note_fnm);
......@@ -19,7 +23,28 @@ package Tomboy::Note::Simple;
Simple abstraction for notes written with Gnome's Tomboy.
The script uses XML::Parser in Tree style and uses it's parse
tree as the note's content datastructure.
tree as the note's content datastructure (stored in "text").
=head1 BUGS
This module consists of originally two different ones, they are not
completely consistent. The difference is how the content is stored.
In a .note file, contents looks like this:
<text xml:space="preserve"><note-content version="0.1">title line
content line2
...
last content last</note-content></text>
* Parser: based on XML::Parser, stores contents in
@nc= @{$note->{'text'}->[2]} which represents the the <note-content>
element, the first text-part starts at $nc[2]
* Generator: contents (the stuff *in* the "note-content" element)
is put into "lines" the first line, however, is stored in 'title'.
That should be further unified.
=cut
......@@ -30,40 +55,69 @@ use JSON;
use Data::Dumper;
$Data::Dumper::Indent= 1;
use Tomboy;
use Util::XML_Parser_Tree;
my %fields=
(
'title' => {},
'last-change-date' => {},
'last-metadata-change-date' => {},
'create-date' => {},
'cursor-position' => {},
'selection-bound-position' => {},
'width' => {},
'height' => {},
'x' => {},
'y' => {},
'open-on-startup' => {},
'cursor-position' => { 'default' => 0 },
'selection-bound-position' => { 'default' => -1, 'supress' => 1 },
'width' => { 'default' => 450 },
'height' => { 'default' => 360 },
'x' => { 'default' => 0 },
'y' => { 'default' => 0 },
'open-on-startup' => { 'default' => 'False' },
);
my @fields_date= qw( last-change-date last-metadata-change-date create-date );
my @fields_default1= qw( cursor-position selection-bound-position width height x y );
my @fields_default2= qw( open-on-startup );
my @fields_seq1= (@fields_date, @fields_default1);
my @fields_seq2= (@fields_default2);
my ($s_text, $e_text)= ('<text xml:space="preserve">', '</text>');
my ($s_note_content, $e_note_content)= ('<note-content version="0.1">', '</note-content>');
sub new
{
my $class= shift;
my %par= @_;
my $note= {};
bless $note, $class;
foreach my $par (keys %par)
my $title= 'New Note ' . Tomboy::ts_ISO ();
my $note=
{
$note->{$par}= $par{$par};
}
'lines' => [ $title ],
'title' => $title,
};
foreach my $f (@fields_date) { $note->{$f}= Tomboy::ts_ISO() }
foreach my $f (@fields_default1) { $note->{$f}= $fields{'default'} }
bless $note, $class;
$note->set (@_);
$note;
}
sub set
{
my $note= shift;
my %par= @_;
foreach my $par (keys %par) { $note->{$par}= $par{$par} }
1;
}
=head1 Group1: Parsing
=cut
sub empty_text
{
my $note= shift;
my $title= shift || 'empty text';
$note->{'text'}= [
{
......@@ -75,9 +129,11 @@ sub empty_text
'version' => '0.1'
},
0,
'empty text'
$title,
]
];
$note->{'title'}= $title;
$note->{'lines'}= [ $title ];
1;
}
......@@ -105,8 +161,16 @@ sub parse
my $p= new XML::Parser (Style => 'Tree');
# print "p: ", Dumper ($p);
my $l1= $p->parsefile($fnm, ErrorContext => 3);
my $l1;
eval { $l1= $p->parsefile($fnm, ErrorContext => 3) };
if ($@)
{
print "parsefile failed fnm=[$fnm]:\n", $@, "\n";
return undef;
}
# print "l1: ", Dumper ($l1);
# my $s_l1= Util::XML_Parser_Tree::to_string (@$l1); print "s_l1=[$s_l1]\n";
my ($tag, $nc, @rest)= @$l1;
# print "res: ", Dumper ($res);
......@@ -145,9 +209,18 @@ sub parse
if ($t1 eq '0') {} # skip text
elsif ($t1 eq 'tag')
{
# print "t2: [$t2]\n";
push (@{$note->{'tags'}}, $t2->[2]);
# ZZZ
my $tag= $t2->[2];
push (@{$note->{'tags'}}, $tag);
if ($tag eq 'system:template')
{
$note->{'is_template'}= 1;
}
elsif ($tag =~ m#system:notebook:(.+)#)
{
$note->{'notebook'}= $1;
}
# TODO: maybe there other tags as well...
}
}
}
......@@ -164,7 +237,186 @@ sub parse
$note;
}
1;
=head1 Group 1+2: glue
=cut
sub text_to_lines
{
my $note= shift;
my $x= $note->{'text'};
# print "x: ", Dumper($x);
my $nc= $x->[2];
# print "nc: ", Dumper($nc);
shift (@$nc); # remove the text-element's attributes
my $s= Util::XML_Parser_Tree::to_string (@$nc);
# split drops the new lines at the end, so we need to go the extra mile
my $cnt= length ($1) if ($s=~ s#(\n+)$##);
my @s= split ("\n", $s);
for (my $i= 1; $i < $cnt; $i++) { push (@s, '') }
# print "complete string: [$s]\n";
# print "s: ", Dumper (\@s);
# print "cnt: ", $cnt, "\n";
my $title= $s[0];
# TODO: compare existing title
$note->{'title'}= $title unless ($note->{'title'});
$note->{'lines'}= \@s;
# ($title, @s);
1;
}
sub parse_lines
{
my $note= shift;
# print "text: ", Dumper ($note->{'text'});
my @lines= @{$note->{'lines'}};
my $start= join ('', $s_text, $s_note_content, shift (@lines));
my $x= parse_string (join ("\n", $start, @lines, join ('', $e_note_content, $e_text)));
$note->{'text'}= $x->[1];
}
sub parse_string
{
my $str= shift;
# print "str=[$str]\n";
my $p= new XML::Parser (Style => 'Tree');
# print "p: ", Dumper ($p);
my $l1;
eval { $l1= $p->parsestring($str, ErrorContext => 3) };
if ($@)
{
print "parsestring failed str=[$str]:\n", $@, "\n";
return undef;
}
# print "l1: ", Dumper ($l1);
$l1;
}
=head1 Group 2: text generator
=cut
sub add_lines
{
my $note= shift;
foreach my $line (@_)
{
my @lines= split (/\n/, $line);
@lines= ('') unless (@lines);
# print "line=[$line] lines: ", main::Dumper (\@lines);
push (@{$note->{'lines'}}, @lines);
}
$note->{'e_updated'}= time();
}
sub save
{
my $note= shift;
my $out_dir= shift;
my $fnm_out= shift;
my ($title, $uuid, $ts_updated, $ts_md_updated, $ts_created, $e_updated, $lines, $is_template, $nb_name)=
map { $note->{$_} } qw(title uuid last-change-date last-metadata-change-date create-date e_updated lines is_template notebook);
# sanitize data
$note->{'uuid'}= $uuid= Tomboy::get_uuid() unless ($uuid);
$note->{'title'}= $title= $uuid unless ($title);
if ($e_updated)
{
$note->{'last-metadata-change-date'}= $ts_md_updated=
$note->{'last-change-date'}= $ts_updated= Tomboy::ts_ISO($e_updated);
}
$note->{'create-date'}= $ts_created= $ts_updated unless ($ts_created);
# print "tags: ", Dumper ($note->{'tags'});
my @tags= ();
push (@tags, 'system:template') if ($is_template);
push (@tags, 'system:notebook:'. $nb_name) if ($nb_name);
unless (defined ($fnm_out))
{
$fnm_out= $out_dir if ($out_dir);
$fnm_out.= $uuid . '.note';
}
unless (open (FO, '>:utf8', $fnm_out))
{
print STDERR "can't write to [$fnm_out]\n";
return undef;
}
print "writing note [$fnm_out]: [$title]\n"; # TODO: if verbose
print FO chr(65279); # write a BOM, Tomboy seems to like that
print FO <<EOX;
<?xml version="1.0" encoding="utf-8"?>
<note version="0.3" xmlns:link="http://beatniksoftware.com/tomboy/link" xmlns:size="http://beatniksoftware.com/tomboy/size" xmlns="http://beatniksoftware.com/tomboy">
EOX
print FO ' <title>'. Util::XML_Parser_Tree::tlt($title) ."</title>\n";
print FO ' ', $s_text, $s_note_content;
foreach my $line (@$lines)
{
print FO $line, "\n";
}
print FO $e_note_content, $e_text, "\n";
foreach my $f (@fields_seq1)
{
print_attribute (*FO, $note, $f);
}
if (@tags)
{
print FO " <tags>\n";
foreach my $tag (@tags) { print FO " <tag>", $tag, "</tag>\n"; }
print FO " </tags>\n";
}
foreach my $f (@fields_seq2)
{
print_attribute (*FO, $note, $f);
}
print FO "</note>"; # No newline at end of file, that's how Tomboy does that ...
close (FO);
$fnm_out;
}
sub print_attribute
{
local *F= shift;
my $n= shift;
my $f= shift;
my $a= $n->{$f};
unless (defined ($a))
{
my $x= $fields{$f};
return if (exists ($x->{'supress'})); # supress the default for that one
my $b;
if (exists ($x->{'default'})) { $b= $x->{'default'} }
# TODO: elsif exists function ....
$n->{$f}= $a= $b if (defined ($b));
}
print F ' <', $f, '>', $a, '</', $f, ">\n";
}
__END__
......@@ -174,7 +426,19 @@ __END__
=head1 BUGS
* XML::Parser throws exceptions, these are currently not handled.
* XML::Parser throws exceptions, these are currently not handled well.
=cut
<tags>
<tag>system:notebook:Kalender 2014</tag>
</tags>
Template:
<tags>
<tag>system:template</tag>
<tag>system:notebook:Kalender 2014</tag>
</tags>
1;
#!/usr/bin/perl
=head1 NAME
s1.pl
=head1 DESCRIPTION
Script to play with Tomboy::Note::Simple for testing.
=cut
use strict;
use lib 'lib';
......@@ -9,17 +19,49 @@ use Tomboy::Note::Simple;
use Data::Dumper;
$Data::Dumper::Indent= 1;
my $note_fnm= shift (@ARGV);
die "no note filename specified" unless (@ARGV);
open (FO, '>:utf8', 'do_verify.sh');
while (my $arg= shift (@ARGV))
{
process_note ($arg);
}
close (FO);
exit (0);
sub process_note
{
my $note_fnm= shift;
die "no note filename specified" unless ($note_fnm);
print '='x90, "\n";
print "process_note note_fnm=[$note_fnm]\n";
# V1:
# my $n= parse Tomboy::Note::Simple ($note_fnm);
my $n= parse Tomboy::Note::Simple ($note_fnm);
# V2:
my $n= new Tomboy::Note::Simple; $n->parse ($note_fnm);
# my $n= new Tomboy::Note::Simple; $n->parse ($note_fnm);
print "n: ", Dumper ($n);
$n->text_to_lines ();
# print "lines: ", Dumper ($n->{'lines'});
$n->parse_lines ();
# print "n: ", Dumper ($n);
my $saved= $n->save();
print "saved=[$saved]\n";
my @cmd= ('diff', '-u', $note_fnm, $saved);
print join (' ', @cmd), "\n";
my $rc= system (@cmd);
print "rc=[$rc]\n\n";
if ($rc != 0)
{
print FO join (' ', @cmd), "\n";
}
$rc;
}
exit (0);
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment