26763: fix problem on failed cd -s to relative path
[zsh.git] / Misc / make-zsh-urls
blob3678b2dea660b3aaa8f7bd795cf689ffa6318c54
1 #!/usr/bin/perl -w
3 use strict;
5 =head1 NAME
7 make-zsh-urls -- create F<~/.zsh/urls> hierarchy
9 =head1 SYNOPSIS
11 % make-zsh-urls [B<OPTION>] ...
13 =head1 DESCRIPTION
15 make-zsh-urls creates a hierarchy of files and directories under
16 F<~/.zsh/urls> for use by the _urls completion function in the new
17 completion system of zsh 3.1.6 and higher.
19 It needs the B<URI::Bookmarks> suite of modules to run, which are
20 available from CPAN, the Comprehensive Perl Archive Network.
21 See B<http://www.perl.com/cpan> or L<CPAN> for more information.
23 The following options are available:
25 B<--output-dir>, B<-o> Specify the output directory for the
26 hierarchy. Defaults to F<~/.zsh/urls>.
28 B<--input-file>, B<-i> Specify the input bookmarks file.
29 Defaults to F<~/.netscape/bookmarks.html>.
31 B<--root-node>, B<-r> Specify which folder contains the
32 bookmarks which the hierarchy will be
33 created from. Defaults to the root
34 of the bookmark collection tree.
36 =cut
38 use Getopt::Long;
39 use URI::Bookmarks::Netscape;
40 use URI;
42 my ($out_dir, $input_file, $root_name, $help);
43 GetOptions('output-dir|o=s' => \$out_dir,
44 'input-file|i=s' => \$input_file,
45 'root-node|r=s' => \$root_name,
46 'help|h' => \$help)
47 or usage();
49 usage() if $help;
51 $out_dir ||= "$ENV{HOME}/.zsh/urls";
52 $input_file ||= "$ENV{HOME}/.netscape/bookmarks.html";
54 my $bookmarks =
55 new URI::Bookmarks(file => $input_file);
57 my $root = $bookmarks->tree_root();
58 if ($root_name) {
59 my @root_nodes = $bookmarks->name_to_nodes($root_name);
60 if (@root_nodes == 0) {
61 die "Couldn't find any nodes with name `$root_name'; aborting.\n";
63 else {
64 if (@root_nodes > 1) {
65 warn "Found more than one node with name `$root_name'; " .
66 "taking first occurrence.\n";
68 $root = $root_nodes[0];
72 my @bookmark_path = ();
73 $root->walk_down({callback => \&pre_callback,
74 callbackback => \&post_callback});
76 sub pre_callback {
77 my ($node, $options) = @_;
79 my $depth = $options->{_depth} || 0;
80 my $name = $node->name;
81 my $type = $node->type;
83 if ($type eq 'bookmark') {
84 my $url = $node->attribute->{'HREF'};
86 # Type A
87 my $full = $url;
88 $full =~ s@^(https?|ftp|gopher)://@"\L$1/"@ei;
89 $full =~ s@file:@@i;
90 my ($path, $file) = $full =~ m@(.+)/(.*)@;
91 # This is horribly inefficient but I'm too lazy to reimplement mkdir -p
92 # Why isn't there a CPAN module for it?
93 system '/bin/mkdir', '-p', "$out_dir/$path" unless -d "$out_dir/$path";
94 system 'touch', "$out_dir/$path" unless $full eq "$path/";
96 # Type B
97 $name =~ s@/@-@g;
98 my $bookmark_file = "$out_dir/bookmark/" .
99 (join '/', @bookmark_path) .
100 "/$name";
101 open(BOOKMARK, ">$bookmark_file") or die "open >$bookmark_file: $!";
102 print BOOKMARK $url, "\n";
103 close(BOOKMARK) or die $!;
105 elsif ($type eq 'folder' && $depth > 0) {
106 print +(' ' x ($depth - 1)), "Processing folder `$name' ...\n";
107 push @bookmark_path, $name;
109 # Type B
110 system '/bin/mkdir',
111 '-p',
112 "$out_dir/bookmark/" .
113 (join '/', @bookmark_path);
116 return 1;
119 sub post_callback {
120 my ($node, $options) = @_;
122 my $type = $node->type;
124 if ($type eq 'folder') {
125 my $name = pop @bookmark_path;
129 sub usage {
130 print <<EOF;
131 Usage: make-zsh-urls [OPTION] ...
132 --help, -h Display this help.
133 --output-dir, -o Specify the output directory for the hierarchy.
134 Defaults to ~/.zsh/urls.
135 --input-file, -i Specify the input bookmarks file.
136 Defaults to ~/.netscape/bookmarks.html.
137 --root-node, -r Specify which folder contains the bookmarks which
138 the hierarchy will be created from. Defaults to
139 the root of the bookmark collection tree.
141 exit 0;
145 =head1 AUTHOR
147 Adam Spiers <adam@spiers.net>
149 =head1 COPYRIGHT
151 Copyright (c) 1999 Adam Spiers <adam@spiers.net>. All rights
152 reserved. This program is free software; you can redistribute it and/or
153 modify it under the same terms as Perl or zsh.
155 =cut