Lots of updates, updated internals to use nex:// urls for navigation and history and links. Fixed history and go back, mostly. Added
code to modify links in read index pages only to add "[>#]" to identify link number. Recorded all links on a page in an array and used URI to handle relative links including "../index" type links (I hope, there were none to test). Added UI to navigate by link #s I made, went with kludgy dialog box. Had the idea to use > and < for navigation to copy the '[>#]' format I added to index page link lines, which works not bad. Added some help to status bar, other stuff. What needs to get added is some 'branding' (program name, about dialog) and a help dialog and to reorganize the menu so it's not crazy. Also could remove some of the status dialogs.
This commit is contained in:
parent
2dec7bf629
commit
e957438be6
343
connex.pl
343
connex.pl
@ -1,32 +1,40 @@
|
||||
#!/usr/bin/perl -w
|
||||
|
||||
#connex.pl Nightfall Express (nex://) browser
|
||||
#TODO: Some branding (status popup on load?, Connex menu item?), About dialog
|
||||
#TODO: Help dialog
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use strict;
|
||||
use Curses::UI;
|
||||
use Net::Telnet;
|
||||
use URI::Split;
|
||||
|
||||
use URI::Split qw(uri_split uri_join);
|
||||
use URI ();
|
||||
|
||||
my $HOST_DEFAULT = "nightfall.city";
|
||||
my $PATHSPEC_DEFAULT = '';
|
||||
my $PORT_DEFAULT = 1900;
|
||||
my $PROT_NEX = "nex://";
|
||||
my $SCHEME_NEX = "nex";
|
||||
|
||||
my $home_default= $PROT_NEX . $HOST_DEFAULT;
|
||||
my $home_default= $SCHEME_NEX . $HOST_DEFAULT;
|
||||
|
||||
my $host = "nightfall.city";
|
||||
my $port = "1900";
|
||||
my $pathspec = "";
|
||||
my $docname = "";
|
||||
my $docname; # = "";
|
||||
my $doctype = "txt";
|
||||
my $dot_ext = ".";
|
||||
|
||||
my @history;
|
||||
|
||||
my $HOME_URL = uri_join($SCHEME_NEX,$HOST_DEFAULT);
|
||||
|
||||
my $full_url = $HOME_URL;
|
||||
|
||||
my @history;
|
||||
my @page_links;
|
||||
|
||||
my $statusbar;
|
||||
my $navwindow;
|
||||
my $win1;
|
||||
my $cui = new Curses::UI( -color_support => 1 );
|
||||
my $connect = new Net::Telnet (Timeout => 10,
|
||||
@ -34,10 +42,11 @@ my $connect = new Net::Telnet (Timeout => 10,
|
||||
my @menu = (
|
||||
{ -label => 'File',
|
||||
-submenu => [
|
||||
{ -label => 'Go to Link ^G', -value => \&goto_link_dialog },
|
||||
{ -label => 'Change Site ^C', -value => \&goto_site_dialog },
|
||||
{ -label => 'Go to Link ^G', -value => \&navigate_link_dialog },
|
||||
{ -label => 'Choose Link >', -value => \&goto_link_dialog },
|
||||
{ -label => 'Back ^B', -value => \&goto_back },
|
||||
{ -label => 'History ^H', -value => "\&history_status_dialog" },
|
||||
{ -label => 'History ^H', -value => \&history_status_dialog },
|
||||
{ -label => 'Page Links ^P', -value => \&page_links_dialog },
|
||||
{ -label => 'Exit ^Q', -value => \&exit_dialog }
|
||||
]
|
||||
},
|
||||
@ -47,8 +56,8 @@ my @menu = (
|
||||
sub exit_dialog()
|
||||
{
|
||||
my $return = $cui->dialog(
|
||||
-message => "Really quit?",
|
||||
-title => "Are you sure?",
|
||||
-title => "Quit Connex?",
|
||||
-message => "Are you sure?",
|
||||
-buttons => ['yes', 'no'],
|
||||
|
||||
);
|
||||
@ -56,60 +65,102 @@ sub exit_dialog()
|
||||
exit(0) if $return;
|
||||
}
|
||||
|
||||
sub goto_link_dialog()
|
||||
|
||||
sub links_dialog()
|
||||
{
|
||||
my $return = $cui->question(-question => "This is [$host/ $pathspec]. Enter destination link:",
|
||||
-answer => $pathspec,
|
||||
);
|
||||
navigate($return);
|
||||
my $return = $cui->dialog(
|
||||
-message => page_links_list(),
|
||||
-title => "Page Links",
|
||||
-buttons => ['ok'],
|
||||
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
|
||||
sub goto_site_dialog()
|
||||
sub unsupported_dialog
|
||||
{
|
||||
my $scheme = shift;
|
||||
my $return = $cui->dialog(
|
||||
-message => "$scheme protocol not supported.",
|
||||
-title => "Bad Navigation",
|
||||
-buttons => ['ok'],
|
||||
|
||||
);
|
||||
|
||||
my $return = $cui->question(-question => "This is [$host/ $pathspec]. Visit site:",
|
||||
-answer => $host,
|
||||
);
|
||||
if ($return){
|
||||
my $site = $return;
|
||||
if($site ne ''){
|
||||
$host = $site;
|
||||
add_history($host);
|
||||
load($pathspec);
|
||||
update_status_bar();
|
||||
}
|
||||
history_status_dialog();
|
||||
}
|
||||
|
||||
sub navigate_link_dialog()
|
||||
{
|
||||
my $return = $cui->question(-question => "This is [$full_url]. Enter destination link:",
|
||||
-answer => $full_url,
|
||||
);
|
||||
#if not user canceled then navigate
|
||||
if($return){
|
||||
navigate($return);
|
||||
update_status_bar();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
sub goto_link_dialog()
|
||||
{
|
||||
my $return = $cui->question(-question => "Enter link #:",
|
||||
);
|
||||
#if not canceled, or too big or too small, goto link
|
||||
if($return){
|
||||
my $linkcount = scalar @page_links;
|
||||
if($return <= $linkcount && $return >0){
|
||||
goto_link($return);
|
||||
update_status_bar();
|
||||
}else{
|
||||
#$browser->focus();
|
||||
my $return1 = $cui->status("there is no link # " . $return);
|
||||
}
|
||||
#do nothing on cancel
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
sub goto_back()
|
||||
{
|
||||
my $fetched = fetch_history();
|
||||
#if($fetched) {
|
||||
$pathspec =$fetched;
|
||||
load($pathspec);
|
||||
$full_url =$fetched;
|
||||
load($full_url,0); #don't move back to top
|
||||
update_status_bar();
|
||||
history_status_dialog();
|
||||
#}
|
||||
#}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
sub goto_link{
|
||||
my $linknum = shift;
|
||||
my $linkcount = scalar @page_links;
|
||||
|
||||
#my $element=$linknum -1; #offset for array element
|
||||
#if ($element <= $#page_links){ #such a perlism, this is highest INDEX of array
|
||||
|
||||
if ($linknum <= $linkcount){ #such a perlism, this is highest INDEX of array
|
||||
navigate($page_links[$linknum-1]); #offset from count to index
|
||||
}else{
|
||||
#my $browser = $win1->getobj("browser");
|
||||
#$browser->focus();
|
||||
my $return = $cui->status("no link # " . $linknum);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
sub navigate{
|
||||
my $link = shift;
|
||||
#if ($link){
|
||||
# if($link ne ''){
|
||||
add_history($pathspec); #add last link to history before going forward!
|
||||
$pathspec = $link;
|
||||
load($pathspec);
|
||||
# }else {
|
||||
# $pathspec = '';
|
||||
# }
|
||||
update_status_bar();
|
||||
#}
|
||||
add_history($full_url); #add last link to history before going forward!
|
||||
$full_url = $link;
|
||||
load($full_url, 1); #new URL go to top of page
|
||||
|
||||
}
|
||||
|
||||
@ -118,7 +169,8 @@ sub update_status_bar
|
||||
{
|
||||
my $browser = $win1->getobj("browser");
|
||||
my $statusbar = $win1->getobj("status");
|
||||
$statusbar->text("Current site: $host, current link: [$pathspec]");
|
||||
#$full_url = construct_valid_url($SCHEME_NEX, $host, $pathspec, $docname);
|
||||
$statusbar->text("$full_url" . " | Press '>' key to enter link #. ctl-g to enter nex URL. '<' to go back.");
|
||||
$statusbar->draw();
|
||||
$browser->focus();
|
||||
|
||||
@ -129,7 +181,6 @@ sub update_status_bar
|
||||
sub add_history
|
||||
{
|
||||
my $link = shift;
|
||||
print ("link $link");
|
||||
push(@history, $link);
|
||||
history_status_dialog();
|
||||
return;
|
||||
@ -142,7 +193,7 @@ sub fetch_history
|
||||
$latest = pop(@history);
|
||||
return $latest;
|
||||
}else{
|
||||
return($PATHSPEC_DEFAULT);
|
||||
return($HOME_URL);
|
||||
}
|
||||
}
|
||||
|
||||
@ -152,12 +203,43 @@ sub history_status_dialog
|
||||
if(@history){
|
||||
my $browser = $win1->getobj("browser");
|
||||
$browser->focus();
|
||||
my $history_list = join(", ", @history);
|
||||
my $return = $cui->status("$history_list");
|
||||
my $history_list = join("\n", @history);
|
||||
my $return = $cui->status("history:\n$history_list");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
sub page_links_dialog
|
||||
{
|
||||
if(@page_links){
|
||||
my $browser = $win1->getobj("browser");
|
||||
$browser->focus();
|
||||
#my $link_list = join("\n", @page_links);
|
||||
my $link_list = page_links_list();
|
||||
my $return = $cui->status("links on this page:\n$link_list");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
sub page_links_list
|
||||
{
|
||||
if(@page_links){
|
||||
my $browser = $win1->getobj("browser");
|
||||
$browser->focus();
|
||||
#my $link_list = join("\n", @page_links);
|
||||
my $link_list="";
|
||||
my $link;
|
||||
my $count=0;
|
||||
foreach $link (@page_links){
|
||||
$count+=1;
|
||||
$link_list = $link_list . "[$count] $link\n";
|
||||
}
|
||||
return $link_list;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
my $menu = $cui->add(
|
||||
'menu','Menubar',
|
||||
-menu => \@menu,
|
||||
@ -173,6 +255,9 @@ $win1 = $cui->add(
|
||||
-vscrollbar => 'right',
|
||||
);
|
||||
|
||||
|
||||
|
||||
|
||||
my $texteditor = $win1->add("browser", "TextViewer",
|
||||
-text => "Start Page",
|
||||
-border => 1,
|
||||
@ -195,7 +280,7 @@ $statusbar = $win1->add("status", "TextViewer",
|
||||
-width => -1,
|
||||
-reverse => 1,
|
||||
-paddingspaces => 1,
|
||||
-text => "Current site: $HOST_DEFAULT, current link: [/]",
|
||||
-text => "$HOME_URL | Press '>' key to enter link #. ctl-g to enter nex URL. '<' to go back.",
|
||||
);
|
||||
|
||||
|
||||
@ -204,78 +289,120 @@ $statusbar = $win1->add("status", "TextViewer",
|
||||
#key bindings, should match menu items
|
||||
$cui->set_binding(sub {$menu->focus()}, "\cX");
|
||||
$cui->set_binding( \&exit_dialog , "\cQ");
|
||||
$cui->set_binding( \&goto_link_dialog , "\cG");
|
||||
$cui->set_binding( \&navigate_link_dialog , "\cG");
|
||||
$cui->set_binding( \&goto_back , "\cB");
|
||||
$cui->set_binding( \&goto_site_dialog , "\cC");
|
||||
$cui->set_binding( \&goto_back , "<");
|
||||
$cui->set_binding( \&goto_link_dialog , ">");
|
||||
$cui->set_binding(sub {
|
||||
my $cui = shift;
|
||||
$cui->layout;
|
||||
$cui->draw;
|
||||
}, "\cL");
|
||||
|
||||
|
||||
|
||||
# There is no need for the editor widget to loose focus, so
|
||||
# the "loose-focus" binding is disabled here. This also enables the
|
||||
# use of the "TAB" key in the editor, which is nice to have.
|
||||
$texteditor->clear_binding('loose-focus');
|
||||
|
||||
#start up
|
||||
$texteditor->focus();
|
||||
#$texteditor->focus();
|
||||
|
||||
navigate('');
|
||||
navigate($HOME_URL);
|
||||
$cui->mainloop();
|
||||
|
||||
|
||||
#pick apart nex:// urls, which we should be using
|
||||
#sub parse_url #need to pass in url; and host, pathspec, file variables to be filled
|
||||
#{
|
||||
# my $url = @_[0];
|
||||
# my $host = url;
|
||||
# host =~ s/^nex://([a-z0-9]*)\/[a-z0-9\/\.]*$/$1/;
|
||||
# my $pathspec = url;
|
||||
# pathspec =~ s/^nex://[a-z0-9]*(\/[a-z0-9\/]*)[[a-z0-9\.]*$)/$1/;
|
||||
# my $file = $url
|
||||
#
|
||||
#}
|
||||
|
||||
|
||||
#make nex:// urls from parts, relative urls
|
||||
#sub construct_valid_url #protocol, host, pathspec
|
||||
#{
|
||||
# my $protocol = shift;
|
||||
# my $host = shift;
|
||||
# my $pathspec = shift;
|
||||
# my $file = shift;
|
||||
# my $url = $protocol;
|
||||
#need error handling
|
||||
#what about the end slash and files vs index?
|
||||
# $url = $protocol . $host;
|
||||
# if ($pathspec){
|
||||
# $url = $url . '/' . $pathspec;
|
||||
# if ($file){
|
||||
# $url = $url . '.' $file;
|
||||
# }
|
||||
# }
|
||||
# return $url;
|
||||
#}
|
||||
sub construct_valid_url #scheme, host, pathspec, docname
|
||||
{
|
||||
my $scheme = shift;
|
||||
my $host = shift;
|
||||
my $pathspec = shift;
|
||||
my $docname = shift;
|
||||
if (defined($docname)){
|
||||
$pathspec= $pathspec . '/' . $docname; #this is just local pathspec
|
||||
}
|
||||
my $url = uri_join($scheme, $host, $pathspec);
|
||||
return $url;
|
||||
}
|
||||
|
||||
sub is_path_index{
|
||||
my $path = shift;
|
||||
my $result = 1;
|
||||
if ($path !~ /\/$/ && $path =~ /\.[a-zA-Z]*$/){
|
||||
$result =0;
|
||||
}
|
||||
return($result);
|
||||
}
|
||||
|
||||
sub add_page_link{
|
||||
my $linkline = shift;
|
||||
my $base_url = shift;
|
||||
my $uri_object;
|
||||
#my $link= $linkline=~ s/^=>[ ]*(.*$)/$1/r;
|
||||
local $URI::ABS_ALLOW_RELATIVE_SCHEME = 1;
|
||||
local $URI::ABS_REMOTE_LEADING_DOTS = 1;
|
||||
$uri_object=URI->new_abs($linkline=~ /^=>[ ]+([^ ]*)/,$base_url);
|
||||
|
||||
push(@page_links, $uri_object->as_string);
|
||||
my $count = scalar @page_links; #scalar is size/count of links, but $#page_links is highest INDEX
|
||||
return $linkline =~ s/(^=>.*$)/$1 [\>$count\]/r;
|
||||
|
||||
}
|
||||
|
||||
|
||||
sub load
|
||||
{
|
||||
my $pathspec = shift;
|
||||
my @lines;
|
||||
my $ok;
|
||||
$connect->host($host);
|
||||
$connect->port($port);
|
||||
$ok= $connect->open($host);
|
||||
$ok= $connect->print($pathspec);
|
||||
@lines =$connect->getlines(ErrMode=> 'return');
|
||||
print $connect->eof();
|
||||
#handle non-existant request?
|
||||
die unless $connect->eof();
|
||||
$connect->close();
|
||||
my $widget= $texteditor;
|
||||
my $loaded_text ="";
|
||||
my $currentline;
|
||||
my $count=0;
|
||||
foreach $currentline (@lines){
|
||||
if ($currentline =~ m/^=>/){
|
||||
$count+=1;
|
||||
$currentline =~ s/(^=>.*$)/$1 [\>$count\]/;
|
||||
}
|
||||
$loaded_text= $loaded_text . $currentline;
|
||||
}
|
||||
$widget->text($loaded_text);
|
||||
my $url = shift;
|
||||
my $top = shift;
|
||||
#my $scheme, $host, $path, $query, $frag;
|
||||
my ($scheme, $host, $path, $query, $frag) = uri_split($url);
|
||||
#what happens with different scheme?
|
||||
if ($scheme eq $SCHEME_NEX){
|
||||
$connect->host($host);
|
||||
$connect->port($port);
|
||||
$ok= $connect->open($host);
|
||||
$ok= $connect->print($path);
|
||||
@lines =$connect->getlines(ErrMode=> 'return');
|
||||
print $connect->eof();
|
||||
#handle non-existant request?
|
||||
die unless $connect->eof();
|
||||
$connect->close();
|
||||
my $widget= $texteditor;
|
||||
|
||||
#loop through nex response and load into text editor. Identify, mark and store link lines for index pages
|
||||
#TODO: store link lines for index pages
|
||||
my $page_contents =""; #this is the page contents
|
||||
my $currentline;
|
||||
my $count=0;
|
||||
my $is_index= is_path_index($path);
|
||||
undef @page_links; #clear list
|
||||
foreach $currentline (@lines){
|
||||
if ($currentline =~ m/^=>/){
|
||||
if ($is_index){
|
||||
$currentline = add_page_link($currentline, $url);
|
||||
}
|
||||
}
|
||||
$page_contents= $page_contents . $currentline;
|
||||
}
|
||||
$widget->text($page_contents);
|
||||
$widget->draw();
|
||||
if ($top){
|
||||
$widget->pos(0);
|
||||
}
|
||||
}else{
|
||||
#can't load non-nex as of now
|
||||
my $browser = $win1->getobj("browser");
|
||||
$browser->focus();
|
||||
my $return = unsupported_dialog($scheme);
|
||||
#pop and trash history
|
||||
my $fetched = fetch_history();
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user