Firefox completions in csh

wblock@

Developer
Firefox accepts the names of HTML files from the command line, which is easy to complete in csh(1):
.cshrc:
Code:
complete firefox  'n/*/f:*.{[hH][tT][mM][lL]}/'

But I also discovered recently that Firefox can jump directly to anchors in files if they are included in the filename:
firefox book.html#overview-quick-start

It would be nice to complete for that. When the user has typed firefox book.html#, pressing Tab would complete from the list of anchors, HTML IDs. The IDs can be pulled out of the HTML file:
Code:
perl -ne 'print "$1\n" if /id="(.*?)">?/' book.html | sort -u
But it's not clear to me whether the parameter containing the filename is available ($1?) or how to use it in the completion. This would be a c or C completion of the current parameter.

Any ideas?
 
There is an example in /usr/src/contrib/tcsh/svn and /usr/src/contrib/tcsh/complete.tcsh.

Can someone cram it into a oneliner?
Juha


Code:
#!/usr/local/bin/perl
#
# csh companion
# complete firefox 'c/*.html#/`complete_html_id`/' 'n/*/f:*.html/'

@_ = split / /, $ENV{COMMAND_LINE};  # firefox file#id
@_ = split /#/, pop @_;  # the last arg

open F, $_[0] or exit(1);  # open file. be silent if error

while (<F>) {
  $id{$1}++ if /id="(.*?)">?/;
}
print map "$_\n", sort keys %id;
 
I did not catch the magic variable $:-0. Here's a oneliner
Code:
complete koe 'c@*.html@`set f=$:-0; set f="$f:s/#/ /"; set f=($f); set f=$f[1]; perl -ne '\''print "#$1\n" if /id="(.*?)">?/;'\'' $f`@'

I'll stick with ksh. After a long walk :)
Juha
 
I thought I had seem the worst of csh completion madness with the make completions a few years ago in the other thread.

I nominate wblock for the title of the forum's Mad tcsh Completer.

At any rate, how about using a html parser? Here's a Python 3 script which extracts all ids:

Code:
import sys, bs4
from bs4 import BeautifulSoup

if len(sys.argv) < 2:
    print('Reading from stdin...', file=sys.stderr)
    html = sys.stdin.read()
else:
    with open(sys.argv[1]) as fp:
        html = fp.read()

soup = BeautifulSoup(html, 'html.parser')
for elem in soup.recursiveChildGenerator():
    if type(elem) == bs4.element.Tag and elem.get('id'):
        print(elem.get('id'))

You'll need BeautifulSoup.

Yes, you can do everything with a single line of Perl regexes. The question is if your should.

Look at the output of both methods to see where your regex fails. On this page, it matches:

- data-message-id="311351" and several similar errors.
- <!-- [..] id="keywords" [..] --> and several others in a commented-out block.

And these are just the two cases that I caught on this page. The only reason it doesn't catch id="" in the body content is because the forum software encodes all quotes to &quot; (but this is by no means mandatory).
 
I thought I had seem the worst of csh completion madness with the make completions a few years ago in the other thread.
I use those frequently. :)

I nominate wblock for the title of the forum's Mad tcsh Completer.
Is there a prize?

Seriously, when there is a way for the computer to show me a list of only the valid choices, I want that. It's a form of help system.

Yes, you can do everything with a single line of Perl regexes. The question is if your should.
Sure. The nice thing with one-liners is there are no dependencies on external files.
 
Sure. The nice thing with one-liners is there are no dependencies on external files.

At the price of getting incorrect results. But you can reduce the above to something like:

Code:
import sys, bs4; from bs4 import BeautifulSoup; print('\n'.join([ e.get('id') for e in BeautifulSoup(sys.stdin.read(), 'html.parser').recursiveChildGenerator() if type(e) == bs4.element.Tag and elem.get('id') ]))

If you really wanted to...
 
Back
Top