# Firefox completions in csh



## wblock@ (Feb 11, 2016)

Firefox accepts the names of HTML files from the command line, which is easy to complete in csh(1):
.cshrc:

```
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:

```
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?


----------



## drhowarddrfine (Feb 11, 2016)

wblock@ said:


> I also discovered recently that Firefox can jump directly to anchors in files if they are included in the filename


This is standard HTML and not Firefox only.


----------



## Juha Nurmela (Feb 11, 2016)

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



```
#!/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;
```


----------



## wblock@ (Feb 11, 2016)

drhowarddrfine said:


> This is standard HTML and not Firefox only.


Well, anchors are, yes.  But what surprised me was that Firefox was able to take a command-line parameter and work out that it was not just a filename, but a filename and an anchor.  I would have expected it to show book.html#index not found or something.


----------



## Juha Nurmela (Feb 12, 2016)

I did not catch the magic variable *$:-0*. Here's a oneliner

```
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


----------



## Carpetsmoker (Feb 16, 2016)

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:


```
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).


----------



## wblock@ (Feb 16, 2016)

Carpetsmoker said:


> 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.



Carpetsmoker said:


> 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.


----------



## Carpetsmoker (Feb 16, 2016)

wblock@ said:


> 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:


```
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...


----------



## wblock@ (Feb 17, 2016)

Carpetsmoker said:


> At the price of getting incorrect results.


True.  Although I would have listed difficulty of clarity and maintenance as bigger problems.


----------

