User:Spoiledbroth/ob-chromium

From Openbox

< User:Spoiledbroth(Difference between revisions)
Jump to: navigation, search
(LOL)
(Script moves to 1.0 beta having fixed a bunch of issues.)
Line 1: Line 1:
 
[[File:Ob-chromium-scrot.png|thumb|280px|right|Quickly access and launch your favourite bookmarks.]]
 
[[File:Ob-chromium-scrot.png|thumb|280px|right|Quickly access and launch your favourite bookmarks.]]
Here is a pipemenu for displaying your chromium bookmarks. Commented throughout. Depends on Perl modules '''HTML::Entities and JSON::Tiny''' (though you shouldn't need to download HTML::Entities, as it's part of the standard Perl library).  
+
Here is a pipemenu for displaying your chromium bookmarks. Commented throughout. Depends on Perl module '''JSON::Tiny'''.
  
I encode the bookmark titles with HTML::Entities, and encase the bookark URL itself within a <code>&lt;[!CDATA[ ]]&gt;</code> block as basic sanity checking before output. I'm not sure what (if any) processing of bookmark URL/titles Chrome does on the backend.
+
I encase the bookark URL itself within a <code>&lt;[!CDATA[ ]]&gt;</code> block as some kind of prophylactic measure before output. I'm not sure what (if any) processing of bookmark URL/titles Chrome does on the backend.  
 
<pre>
 
<pre>
 
#!/usr/bin/perl
 
#!/usr/bin/perl
  
# openbox-chromium 0.2a - openbox chrome browser bookmarks pipemenu
+
# openbox-chromium 1.0-beta - openbox chrome browser bookmarks pipemenu
 
# Copyright (C) 2018 http://openbox.org/wiki/User:Spoiledbroth
 
# Copyright (C) 2018 http://openbox.org/wiki/User:Spoiledbroth
 
#
 
#
Line 21: Line 21:
 
# === DEPENDENCIES: ===
 
# === DEPENDENCIES: ===
 
# JSON::Tiny - http://search.cpan.org/~davido/JSON-Tiny-0.58/lib/JSON/Tiny.pod
 
# JSON::Tiny - http://search.cpan.org/~davido/JSON-Tiny-0.58/lib/JSON/Tiny.pod
# HTML::Entities - http://search.cpan.org/dist/HTML-Parser/lib/HTML/Entities.pm
 
 
use strict;
 
use strict;
 
use warnings;
 
use warnings;
 
use JSON::Tiny qw(decode_json);
 
use JSON::Tiny qw(decode_json);
use HTML::Entities qw(encode_entities);
 
  
 
# === CONFIGURATION: ===
 
# === CONFIGURATION: ===
# Change the $bookmarks variable to reflect the location of your  
+
# $bookmarks - Location of your chromium/google-chrome bookmarks.  
# chromium/google-chrome bookmarks. You can try "find ~/.config -name Bookmarks"
+
# You can try "find ~/.config -name Bookmarks" if you're having finding it.
# if you're having trouble locating the file.
+
# $browser - browser command, either x-www-browser, chromium or google-chrome
my $bookmarks = "/.config/chromium/Profile 1/Bookmarks";
+
# $maxlength - upper limit of characters for bookmark titles
# And here you can enter the command you use to start up your browser.
+
 
# Tested with chromium and google-chrome on Debian 9.3
+
my $bookmarks = "/home/marston/.config/chromium/Profile 1/Bookmarks";
 
my $browser = "chromium";
 
my $browser = "chromium";
# Maximum length of bookmark titles (characters)
 
 
my $maxlength = 35;
 
my $maxlength = 35;
# === END CONFIGURATION ===
 
  
 
# Lets open up that bookmarks file
 
# Lets open up that bookmarks file
Line 49: Line 45:
 
# Now, get the bookmark JSON into a reference  
 
# Now, get the bookmark JSON into a reference  
 
my $data = decode_json $file;
 
my $data = decode_json $file;
# Select only the "root" entries, only loop over what we need, essentially.
+
# Cast that reference to a hash of the 'roots' entries in the bookmark file.
my $json = $data->{'roots'};
+
my %json = %{$data->{'roots'}};
 +
# ... so we only loop over what we need, essentially.
  
 
# Build the Openbox menu header
 
# Build the Openbox menu header
 
print "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
 
print "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
 
     . "<openbox_pipe_menu>\n";
 
     . "<openbox_pipe_menu>\n";
 
+
# Main program loop...
# Here is the main program loop...
+
foreach (keys %json)
foreach my $roots (%$json)
+
 
{
 
{
# This is pretty shameful right here. I actually suspect I'm doing some
+
traversal ($data->{'roots'}->{$_});
# weird typing in the foreach loop above which causes me to have to cast
+
# to an array... FECKING KLUDGE
+
my @folders = $roots;
+
foreach my $i (0 .. $#folders)
+
{
+
# and then check if the supplied ref is a hash- otherwise
+
# we end up with some weird arrays containing only the "root"
+
# name of the bookmarks folder... Hope to fix in 0.3
+
if ( (ref($folders[$i]) eq 'HASH') &&
+
# This line allows us to skip printing any "root" folders with
+
# no children.
+
(0+@{$folders[$i]->{'children'}} != 0) )
+
{
+
# Now we can print the root folder destinations
+
print "<menu id=\"".$folders[$i]->{'id'}."\" label=\"".encode_entities($folders[$i]->{'name'})."\">\n";
+
if ($folders[$i]->{'type'} eq "folder") {
+
# lastly we start recursion over the children
+
foreach my $sub_children ($folders[$i]->{'children'})
+
{
+
# And let your backbone sliiiide...
+
recurse($sub_children);
+
print "</menu> \n";
+
}
+
}
+
}
+
}
+
 
}
 
}
# EOM
+
# End of menu
 
print "</openbox_pipe_menu>\n";
 
print "</openbox_pipe_menu>\n";
  
 
# Recursion function for bookmark "folders"
 
# Recursion function for bookmark "folders"
sub recurse
+
sub traversal
 
{
 
{
 
my ($obtained) = @_;
 
my ($obtained) = @_;
my @thing = @{$obtained};
+
# If the entry is a folder with >0 children, build an entry and recurse
foreach my $t (0 .. $#thing)
+
if (($obtained->{'type'} eq "folder") &&
{
+
    (0+@{$obtained->{'children'}} != 0)) {
# If it's a folder with children, print and recurse
+
build_entry($obtained);
if ( ($thing[$t]->{'type'} eq "folder") &&
+
my @children = @{$obtained->{'children'}};
(0+@{$thing[$t]->{'children'}} != 0) ) {
+
foreach my $i (0 .. $#children)
print "<menu id=\"".$thing[$t]->{'id'}."\" label=\"".encode_entities($thing[$t]->{'name'})."\"> \n";
+
{
my @folder = $thing[$t]->{'children'};
+
traversal($children[$i]);
foreach my $z (0 .. $#folder)
+
{
+
recurse($folder[$z]);
+
}
+
print "</menu>\n";
+
} elsif ($thing[$t]->{'type'} eq "url") {
+
$_ = scalar $thing[$t]{'name'};
+
$_ =~ s/^(.{1,$maxlength})(.+)?/$1 . (defined $2 ? "..." : "")/e;
+
print "<item label=\"".encode_entities($_)."\">\n"
+
    . "  <action name=\"Execute\">\n"
+
    . "    <execute>\n"
+
    . "    ".$browser." <![CDATA[".$thing[$t]->{'url'}."]]>\n"
+
    . "    </execute>\n"
+
    . "  </action>\n"
+
    . "</item>\n";
+
 
}
 
}
 +
print "</menu>\n"; # I'm not perfect...
 +
# Else, we need to build an entry for a URL.
 +
} elsif ($obtained->{'type'} eq "url") {
 +
build_entry($obtained);
 +
}
 +
return;
 +
}
 +
 +
# Function to build the menu (seperation of concerns)
 +
sub build_entry
 +
{
 +
my ($entry) = @_;
 +
if ($entry->{'type'} eq "folder") {
 +
# print case for bookmark folder
 +
print " <menu id=\""
 +
      .$entry->{'id'}."\" label=\"".$entry->{'name'}."\">\n";     
 +
} elsif ($entry->{'type'} eq "url") {
 +
# print case for bookmark link
 +
my $truncated = scalar $entry->{'name'};
 +
$truncated =~ s/^(.{1,$maxlength})(.+)?/$1 . (defined $2 ? "..." : "")/e;
 +
print "  <item label=\"".$truncated."\">\n"
 +
    . "    <action name=\"Execute\">\n"
 +
    . "      <execute>\n"
 +
    . "        ".$browser." <![CDATA[".$entry->{'url'}."]]>\n"
 +
    . "      </execute>\n"
 +
    . "    </action>\n"
 +
    . "  </item>\n";
 
}
 
}
 
return;
 
return;
 
}
 
}
 
</pre>
 
</pre>

Revision as of 20:26, 2 March 2018

(thumbnail)
Quickly access and launch your favourite bookmarks.

Here is a pipemenu for displaying your chromium bookmarks. Commented throughout. Depends on Perl module JSON::Tiny.

I encase the bookark URL itself within a <[!CDATA[ ]]> block as some kind of prophylactic measure before output. I'm not sure what (if any) processing of bookmark URL/titles Chrome does on the backend.

#!/usr/bin/perl

# openbox-chromium 1.0-beta - openbox chrome browser bookmarks pipemenu
# Copyright (C) 2018 http://openbox.org/wiki/User:Spoiledbroth
#
# 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 3 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.

# === DEPENDENCIES: ===
# JSON::Tiny - http://search.cpan.org/~davido/JSON-Tiny-0.58/lib/JSON/Tiny.pod
use strict;
use warnings;
use JSON::Tiny qw(decode_json);

# === CONFIGURATION: ===
# $bookmarks - Location of your chromium/google-chrome bookmarks. 
# You can try "find ~/.config -name Bookmarks" if you're having finding it.
# $browser - browser command, either x-www-browser, chromium or google-chrome
# $maxlength - upper limit of characters for bookmark titles

my $bookmarks = "/home/marston/.config/chromium/Profile 1/Bookmarks";
my $browser = "chromium";
my $maxlength = 35;

# Lets open up that bookmarks file
my $file = do {
	local $/ = undef;
	open my $fh, "<", $bookmarks
		or die "could not open $bookmarks: $!";
	<$fh>
};

# Now, get the bookmark JSON into a reference 
my $data = decode_json $file;
# Cast that reference to a hash of the 'roots' entries in the bookmark file.
my %json = %{$data->{'roots'}};
# ... so we only loop over what we need, essentially.

# Build the Openbox menu header
print "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
    . "<openbox_pipe_menu>\n";
# Main program loop...
foreach (keys %json)
{
	traversal ($data->{'roots'}->{$_});
}
# End of menu
print "</openbox_pipe_menu>\n";

# Recursion function for bookmark "folders"
sub traversal
{
	my ($obtained) = @_;
	# If the entry is a folder with >0 children, build an entry and recurse
	if (($obtained->{'type'} eq "folder") &&
	    (0+@{$obtained->{'children'}} != 0)) {
		build_entry($obtained);
		my @children = @{$obtained->{'children'}};
		foreach my $i (0 .. $#children)
		{
			traversal($children[$i]);
		}
		print "</menu>\n"; # I'm not perfect...
	# Else, we need to build an entry for a URL. 
	} elsif ($obtained->{'type'} eq "url") {
		build_entry($obtained);
	}
	return;
}

# Function to build the menu (seperation of concerns)
sub build_entry
{
	my ($entry) = @_;
	if ($entry->{'type'} eq "folder") {
		# print case for bookmark folder
		print " <menu id=\""
		      .$entry->{'id'}."\" label=\"".$entry->{'name'}."\">\n";      
	} elsif ($entry->{'type'} eq "url") {
		# print case for bookmark link
		my $truncated = scalar $entry->{'name'};
		$truncated =~ s/^(.{1,$maxlength})(.+)?/$1 . (defined $2 ? "..." : "")/e;
		print "  <item label=\"".$truncated."\">\n"
		    . "    <action name=\"Execute\">\n"
		    . "      <execute>\n"
		    . "        ".$browser." <![CDATA[".$entry->{'url'}."]]>\n"
		    . "      </execute>\n"
		    . "    </action>\n"
		    . "  </item>\n";
	}
	return;
}
Personal tools