Jump to content

Starting a web browser

From Rosetta Code
Starting a web browser is a draft programming task. It is not yet considered ready to be promoted as a complete task, for reasons that should be found in its talk page.

Build and show a web page displaying the data from the task separate the house number from the street name in a formatted and colored table.

Task

Write the code which automatically opens a web page in a browser showing the addresses. No static data must be shown, only processed data.

EchoLisp

Since we are already in a browser window, the browser is started. print-hatml sends an html string to the standard output area. The table is styled with the "htable" css class, which is included in EchoLisp.

;; table from "Separate_the_house_number_from_the_street_name"
;;
(print-html (table->html adresses))
Output:
Plataanstraat 5
Straat 12
Straat 12 II
Straat 1940 II
Dr. J. Straat 40
Dr. J. Straat 12 a
Dr. J. Straat 12-14
Laan 1940 – 1945 37
Plein 1940 2
1213-laan 11
16 april 1944 Pad 1
1e Kruisweg 36
Laan 1940-'45 66
Laan '40-'45 ❓❓❓
Langeloërduinen 3 46
Marienwaerdt 2e Dreef 2
Provincialeweg N205 1
Rivium 2e Straat 59.
Nieuwe gracht 20rd
Nieuwe gracht 20rd 2
Nieuwe gracht 20zw /2
Nieuwe gracht 20zw/3
Nieuwe gracht 20 zw/4
Bahnhofstr. 4
Wertstr. 10
Lindenhof 1
Nordesch 20
Weilstr. 6
Harthauer Weg 2
Mainaustr. 49
August-Horch-Str. 3
Marktplatz 31
Schmidener Weg 3
Karl-Weysser-Str. 6

Go

This uses the same format and color scheme for the table as the Raku entry.

package main

import (
    "fmt"
    "html/template"
    "log"
    "os"
    "os/exec"
    "strings"
    "time"
)

type row struct {
    Address, Street, House, Color string
}

func isDigit(b byte) bool {
    return '0' <= b && b <= '9'
}

func separateHouseNumber(address string) (street string, house string) {
    length := len(address)
    fields := strings.Fields(address)
    size := len(fields)
    last := fields[size-1]
    penult := fields[size-2]
    if isDigit(last[0]) {
        isdig := isDigit(penult[0])
        if size > 2 && isdig && !strings.HasPrefix(penult, "194") {
            house = fmt.Sprintf("%s %s", penult, last)
        } else {
            house = last
        }
    } else if size > 2 {
        house = fmt.Sprintf("%s %s", penult, last)
    }
    street = strings.TrimRight(address[:length-len(house)], " ")
    return
}

func check(err error) {
    if err != nil {
        log.Fatal(err)
    }
}

var tmpl = `
<head>
  <title>Rosetta Code - Start a Web Browser</title>
  <meta charset="UTF-8">
</head>
<body bgcolor="#d8dcd6">
  <table border="2">
    <p align="center">
      <font face="Arial, sans-serif" size="5">Split the house number from the street name</font>    
      <tr bgcolor="#02ccfe"><th>Address</th><th>Street</th><th>House Number</th></tr>
      {{range $row := .}}
      <tr bgcolor={{$row.Color}}>         
        <td>{{$row.Address}}</td>
        <td>{{$row.Street}}</td>
        <td>{{$row.House}}</td>
      </tr>
      {{end}}
    </p>
  </table>
</body>
`
func main() {
    addresses := []string{
        "Plataanstraat 5",
        "Straat 12",
        "Straat 12 II",
        "Dr. J. Straat   12",
        "Dr. J. Straat 12 a",
        "Dr. J. Straat 12-14",
        "Laan 1940 - 1945 37",
        "Plein 1940 2",
        "1213-laan 11",
        "16 april 1944 Pad 1",
        "1e Kruisweg 36",
        "Laan 1940-'45 66",
        "Laan '40-'45",
        "Langeloërduinen 3 46",
        "Marienwaerdt 2e Dreef 2",
        "Provincialeweg N205 1",
        "Rivium 2e Straat 59.",
        "Nieuwe gracht 20rd",
        "Nieuwe gracht 20rd 2",
        "Nieuwe gracht 20zw /2",
        "Nieuwe gracht 20zw/3",
        "Nieuwe gracht 20 zw/4",
        "Bahnhofstr. 4",
        "Wertstr. 10",
        "Lindenhof 1",
        "Nordesch 20",
        "Weilstr. 6",
        "Harthauer Weg 2",
        "Mainaustr. 49",
        "August-Horch-Str. 3",
        "Marktplatz 31",
        "Schmidener Weg 3",
        "Karl-Weysser-Str. 6",
    }
    browser := "firefox" // or whatever
    colors := [2]string{"#d7fffe", "#9dbcd4"}
    fileName := "addresses_table.html"
    ct := template.Must(template.New("").Parse(tmpl))
    file, err := os.Create(fileName)
    check(err)
    rows := make([]row, len(addresses))
    for i, address := range addresses {
        street, house := separateHouseNumber(address)
        if house == "" {
            house = "(none)"
        }
        color := colors[i%2]
        rows[i] = row{address, street, house, color}
    }   
    err = ct.Execute(file, rows)
    check(err)
    cmd := exec.Command(browser, fileName)
    err = cmd.Run()
    check(err)
    file.Close()
    time.Sleep(5 * time.Second) // wait for 5 seconds before deleting file
    err = os.Remove(fileName)
    check(err)
}
Output:
Similar to the Raku entry.

J

Here, we assume that browser refers to a browser in a format which is usable by a command shell, and din5008 and sampledata have been defined according to the J house number street name task entry:

   wrap=: {{'<',m,'>',y,'</',(;{.;:m),'>' }}(L:0)("1)
   'table.htm'fwrite~'<style>tr:nth-child(even){color:blue}</style>','table' wrap ,'tr' wrap ;"1 'td' wrap din5008"1 sampledata
1660
   launch browser,' table.htm'

(Here, 1660 was the length of the generated file.)

Julia

using Tables, BrowseTables

function testbrowsertable(addresstext)
    lines = strip.(split(addresstext, "\n"))
    mat = fill("", length(lines), 2)
    regex = r"""^ (.*?) \s+
                  (
                      \d* (\-|\/)? \d*
                    | \d{1,3} [a-zI./ ]* \d{0,3}
                  )
            $"""x
    for (i, line) in enumerate(lines)
        if (matched = match(regex, line)) != nothing
            mat[i, 1], mat[i, 2] = matched.captures
        end
    end
    data = Tables.table(mat)
    tmp = tempname() * ".html"
    write_html_table(tmp, data)
    if Sys.isapple()
        run(`open $tmp`)
    elseif Sys.iswindows()
        run(`cmd /c start $tmp`)
    else # linux etc.
        run(`xdg-open $tmp`)
    end
    println("Press Enter after you close the browser to exit and remove temp file.")
    readline()
    rm(tmp)
end

const adressen = """
    Plataanstraat 5
    Straat 12
    Straat 12 II
    Dr. J. Straat   12
    Dr. J. Straat 12 a
    Dr. J. Straat 12-14
    Laan 1940 – 1945 37
    Plein 1940 2
    1213-laan 11
    16 april 1944 Pad 1
    1e Kruisweg 36
    Laan 1940-’45 66
    Laan ’40-’45
    Langeloërduinen 3 46
    Marienwaerdt 2e Dreef 2
    Provincialeweg N205 1
    Rivium 2e Straat 59.
    Nieuwe gracht 20rd
    Nieuwe gracht 20rd 2
    Nieuwe gracht 20zw /2
    Nieuwe gracht 20zw/3
    Nieuwe gracht 20 zw/4
    Bahnhofstr. 4
    Wertstr. 10
    Lindenhof 1
    Nordesch 20
    Weilstr. 6
    Harthauer Weg 2
    Mainaustr. 49
    August-Horch-Str. 3
    Marktplatz 31
    Schmidener Weg 3
    Karl-Weysser-Str. 6"""

testbrowsertable(adressen)

Nim

Based on Phix solution. Using same colors as Scala program.

import os, strutils

func separateHouseNumber(address: string): tuple[street, house: string] =
  let fields = address.splitWhitespace()
  let last = fields[^1]
  let penult = fields[^2]
  if last[0].isDigit():
    let isdig = penult[0].isDigit()
    if fields.len > 2 and isdig and not penult.startsWith("194"):
      result.house = penult & ' ' & last
    else:
      result.house = last
  elif fields.len > 2:
    result.house = penult & ' ' & last
  result.street = address[0..address.high-result.house.len].strip(leading = false, trailing = true)

const
  Addresses = ["Plataanstraat 5",
               "Straat 12",
               "Straat 12 II",
               "Dr. J. Straat   12",
               "Dr. J. Straat 12 a",
               "Dr. J. Straat 12-14",
               "Laan 1940 - 1945 37",
               "Plein 1940 2",
               "1213-laan 11",
               "16 april 1944 Pad 1",
               "1e Kruisweg 36",
               "Laan 1940-'45 66",
               "Laan '40-'45",
               "Langeloërduinen 3 46",
               "Marienwaerdt 2e Dreef 2",
               "Provincialeweg N205 1",
               "Rivium 2e Straat 59.",
               "Nieuwe gracht 20rd",
               "Nieuwe gracht 20rd 2",
               "Nieuwe gracht 20zw /2",
               "Nieuwe gracht 20zw/3",
               "Nieuwe gracht 20 zw/4",
               "Bahnhofstr. 4",
               "Wertstr. 10",
               "Lindenhof 1",
               "Nordesch 20",
               "Weilstr. 6",
               "Harthauer Weg 2",
               "Mainaustr. 49",
               "August-Horch-Str. 3",
               "Marktplatz 31",
               "Schmidener Weg 3",
               "Karl-Weysser-Str. 6"]

  HtmlHeader = """
    <html>
    <head>
    <title>Rosetta Code - Start a Web Browser</title>
    <meta charset="UTF-8">
    </head>
    <body bgcolor="#e6e6ff">
    <p align="center">
    <font face="Arial, sans-serif" size="5">Split the house number from the street name</font>
    </p>
    <p align="center">
    <table border="2"> <tr bgcolor="#9bbb59">
    <th>Address</th><th>Street</th><th>House Number</th>
    """

  HtmlLine = "<tr bgcolor=$#><td>$#</td><td>$#</td><td>$#</td></tr>"

  HtmlFooter = """
    </table>
    </p>
    </body>
    </html>
    """

let htmlFile = open("test.html", fmWrite)
htmlFile.write HtmlHeader
for i, address in Addresses:
  let color = if (i and 1) == 0: "#ebf1de" else: "#d8e4bc"
  let (street, house) = address.separateHouseNumber()
  htmlFile.write HtmlLine.format(color, address, street, house)
htmlFile.write HtmlFooter
htmlFile.close()

discard execShellCmd("firefox test.html")
os.sleep(5000)
removeFile("test.html")
Output:

Same as Phix with Scala colors.

Perl

Borrowing code from the Separate the house number from the street name task.

Translation of: Raku
use File::Temp qw(tempfile);

my @addresses = (
'Plataanstraat 5',      'Straat 12',             'Straat 12 II',            'Dr. J. Straat   12',
'Dr. J. Straat 12 a',   'Dr. J. Straat 12-14',   'Laan 1940 – 1945 37',     'Plein 1940 2',
'1213-laan 11',         '16 april 1944 Pad 1',   '1e Kruisweg 36',          'Laan 1940-’45 66',
'Laan ’40-’45',         'Langeloërduinen 3 46',  'Marienwaerdt 2e Dreef 2', 'Provincialeweg N205 1',
'Rivium 2e Straat 59.', 'Nieuwe gracht 20rd',    'Nieuwe gracht 20rd 2',    'Nieuwe gracht 20zw /2',
'Nieuwe gracht 20zw/3', 'Nieuwe gracht 20 zw/4', 'Bahnhofstr. 4',           'Wertstr. 10',
'Lindenhof 1',          'Nordesch 20',           'Weilstr. 6',              'Harthauer Weg 2',
'Mainaustr. 49',        'August-Horch-Str. 3',   'Marktplatz 31',           'Schmidener Weg 3',
'Karl-Weysser-Str. 6');


my @row_color = ('#d7fffe', '#9dbcd4');

# build the table
sub genTable {
    my $table = '<table border="2"> <tr bgcolor="#02ccfe">' .
    qq|<th>Address</th><th>Street</th><th>House Number</th>\n|;
    my $i = 0;
    for my $addr (@addresses) {
        $table .= qq|<tr bgcolor="@{[@row_color[$i++ % 2]]}"><td>$addr</td>|;

        my($street,$number) =  $addr =~
        m[^ (.*?) \s+
            (
               \d* (\-|\/)? \d*
             | \d{1,3} [a-zI./ ]* \d{0,3}
            ) $
         ]x;
        if (!$number) { $street = $addr; $number = '(no match)' }
        $table .= qq|<td>$street</td><td>$number</td></tr>\n|;
    }
    return $table . '</table>';
}

my $streets_and_numbers = genTable();

# generate the page content
sub content {
return <<END;
<html>
<head>
<title>Rosetta Code - Start a Web Browser</title>
<meta charset="UTF-8">
</head>
<body bgcolor="#d8dcd6">
<p align="center">
<font face="Arial, sans-serif" size="5">Split the house number from the street name</font>
</p>
<p align="center">
$streets_and_numbers
</p>
</body>
</html>
END
}

# Use a temporary file name and file handle
my ($fn, $fh) = tempfile :suffix('.html');

# dump the content to the file
open my $fh, '>', $fn;
print $fh content();
close $fh;

# use appropriate command for X11 (other systems will need different invocation)
my $command = "xdg-open $fn";

# start the browser
system "$command";

# wait for a bit to give browser time to load before destroying temp file
sleep 5;
Output:
AddressStreetHouse Number
Plataanstraat 5Plataanstraat5
Straat 12Straat12
Straat 12 IIStraat12 II
Dr. J. Straat 12Dr. J. Straat12
Dr. J. Straat 12 aDr. J. Straat12 a
Dr. J. Straat 12-14Dr. J. Straat12-14
Laan 1940 – 1945 37Laan 1940 – 194537
Plein 1940 2Plein 19402
1213-laan 111213-laan11
16 april 1944 Pad 116 april 1944 Pad1
1e Kruisweg 361e Kruisweg36
Laan 1940-’45 66Laan 1940-’4566
Laan ’40-’45Laan ’40-’45(no match)
Langeloërduinen 3 46Langeloërduinen3 46
Marienwaerdt 2e Dreef 2Marienwaerdt 2e Dreef2
Provincialeweg N205 1Provincialeweg N2051
Rivium 2e Straat 59.Rivium 2e Straat59.
Nieuwe gracht 20rdNieuwe gracht20rd
Nieuwe gracht 20rd 2Nieuwe gracht20rd 2
Nieuwe gracht 20zw /2Nieuwe gracht20zw /2
Nieuwe gracht 20zw/3Nieuwe gracht20zw/3
Nieuwe gracht 20 zw/4Nieuwe gracht20 zw/4
Bahnhofstr. 4Bahnhofstr.4
Wertstr. 10Wertstr.10
Lindenhof 1Lindenhof1
Nordesch 20Nordesch20
Weilstr. 6Weilstr.6
Harthauer Weg 2Harthauer Weg2
Mainaustr. 49Mainaustr.49
August-Horch-Str. 3August-Horch-Str.3
Marktplatz 31Marktplatz31
Schmidener Weg 3Schmidener Weg3
Karl-Weysser-Str. 6Karl-Weysser-Str.6

Phix

without js -- (file i/o, system)
constant addresses = {"Plataanstraat 5",
                      "Straat 12",
                      "Straat 12 II",
                      "Dr. J. Straat   12",
                      "Dr. J. Straat 12 a",
                      "Dr. J. Straat 12-14",
                      "Laan 1940 - 1945 37",
                      "Plein 1940 2",
                      "1213-laan 11",
                      "16 april 1944 Pad 1",
                      "1e Kruisweg 36",
                      "Laan 1940-'45 66",
                      "Laan '40-'45",
                      "Langeloërduinen 3 46",
                      "Marienwaerdt 2e Dreef 2",
                      "Provincialeweg N205 1",
                      "Rivium 2e Straat 59.",
                      "Nieuwe gracht 20rd",
                      "Nieuwe gracht 20rd 2",
                      "Nieuwe gracht 20zw /2",
                      "Nieuwe gracht 20zw/3",
                      "Nieuwe gracht 20 zw/4",
                      "Bahnhofstr. 4",
                      "Wertstr. 10",
                      "Lindenhof 1",
                      "Nordesch 20",
                      "Weilstr. 6",
                      "Harthauer Weg 2",
                      "Mainaustr. 49",
                      "August-Horch-Str. 3",
                      "Marktplatz 31",
                      "Schmidener Weg 3",
                      "Karl-Weysser-Str. 6"}
 
function isDigit(integer ch)
    return ch>='0' and ch<='9'
end function
 
function separateHouseNumber(integer i)
    string address = addresses[i]
    sequence parts = split(address)
    string street, house
    integer h = 0
    if length(parts)>1 then
        string last = parts[$]
        if isDigit(last[1]) then
            h = 1
            string penult = parts[$-1]
            if length(parts)>2
            and isDigit(penult[1])
            and match("194",penult)!=1 then
                h = 2
            end if
        elsif length(parts)>2 then
            h = 2
        end if
    end if
    if h then
        street = join(parts[1..$-h])
        house = join(parts[$-h+1..$])
    else
        street = join(parts)
        house = "(none)"
    end if
    string colour = iff(mod(i,2)=0?"#d7fffe":"#9dbcd4")
    return {colour,address,street,house}
end function
 
constant html_hdr = """
<html>
 <head>
 <title>Rosetta Code - Start a Web Browser</title>
 <meta charset="UTF-8">
 </head>
 <body bgcolor="#d8dcd6">
  <p align="center">
  <font face="Arial, sans-serif" size="5">Split the house number from the street name</font>
  </p>
  <p align="center">
   <table border="2"> <tr bgcolor="#02ccfe">
    <th>Address</th><th>Street</th><th>House Number</th>
""",
         html_line = """
    <tr bgcolor=%s><td>%s</td><td>%s</td><td>%s</td></tr>
""",
         html_ftr = """
   </table>
  </p>
 </body>
</html>
"""
 
procedure main()
    integer fn = open("test.html","w")
    printf(fn,html_hdr)
    for i=1 to length(addresses) do
        printf(fn,html_line,separateHouseNumber(i))
    end for
    printf(fn,html_ftr)
    close(fn)
    system("test.html")
end procedure
main()

output as perl

Racket

#lang at-exp racket

... same code as "Separate_the_house_number_from_the_street_name" ...

(require net/sendurl scribble/html)

(define (render-table)
  (for/list ([str (in-list (string-split adressen #rx" *\r?\n *"))]
             [i   (in-naturals)])
    (tr bgcolor: (if (even? i) "#fcf" "#cff")
        (td str)
        (map td (cond [(splits-adressen str) => cdr] [else '(??? ???)])))))

@(compose1 send-url/contents xml->string){
  @html{@head{@title{Splitting Results}}
        @body{@h1{Splitting Results}
              @table{@render-table}}}
}

Raku

(formerly Perl 6)

Works with: Rakudo version 2017.09

Uses the code from the Separate the house number from the street name task almost verbatim. Included here to make a complete, runnable example.

use File::Temp;

my $addresses = qq :to /END/;
    Plataanstraat 5
    Straat 12
    Straat 12 II
    Dr. J. Straat   12
    Dr. J. Straat 12 a
    Dr. J. Straat 12-14
    Laan 1940 – 1945 37
    Plein 1940 2
    1213-laan 11
    16 april 1944 Pad 1
    1e Kruisweg 36
    Laan 1940-’45 66
    Laan ’40-’45
    Langeloërduinen 3 46
    Marienwaerdt 2e Dreef 2
    Provincialeweg N205 1
    Rivium 2e Straat 59.
    Nieuwe gracht 20rd
    Nieuwe gracht 20rd 2
    Nieuwe gracht 20zw /2
    Nieuwe gracht 20zw/3
    Nieuwe gracht 20 zw/4
    Bahnhofstr. 4
    Wertstr. 10
    Lindenhof 1
    Nordesch 20
    Weilstr. 6
    Harthauer Weg 2
    Mainaustr. 49
    August-Horch-Str. 3
    Marktplatz 31
    Schmidener Weg 3
    Karl-Weysser-Str. 6
    END

my @row-color = '#d7fffe', '#9dbcd4';

# build the table
sub genTable () {
    my $table = '<table border="2"> <tr bgcolor="#02ccfe">' ~
    qq|<th>Address</th><th>Street</th><th>House Number</th>\n|;
    my $i = 0;
    for $addresses.lines -> $addr {
        $table ~= qq|<tr bgcolor="{@row-color[$i++ % 2]}"><td>{$addr}</td>|;
        $addr ~~ m[
            ( .*? )
            [
                \s+
                (
                | \d+ [ \- | \/ ] \d+
                | <!before 1940 | 1945> \d+ <[ a..z I . / \x20 ]>* \d*
                )
            ]?
            $
        ];
        quietly $table ~= qq|<td>{$0.Str}</td><td>{$1.Str||''}</td></tr>\n|;
    }
    $table ~ '</table>';
}

# generate the page content
sub content {
    qq :to /END/;
    <html>
    <head>
    <title>Rosetta Code - Start a Web Browser</title>
    <meta charset="UTF-8">
    </head>
    <body bgcolor="#d8dcd6">
    <p align="center">
    <font face="Arial, sans-serif" size="5">Split the house number from the street name</font>
    </p>
    <p align="center">
    { genTable }
    </p>
    </body>
    </html>
    END
}

# Use a temporary file name and file handle
my ($fn, $fh) = tempfile :suffix('.html');

# dump the content to the file
$fh.spurt: content;

# use appropriate command for Windows or X11
# other OSs/WMs may need different invocation
my $command = $*DISTRO.is-win ?? "start $fn" !! "xdg-open $fn";

# start the browser
shell $command;

# wait for a bit to give browser time to load before destroying temp file
sleep 5;
Output:

Will start the default browser (or open a new tab/window in a running one) and display this table.

AddressStreetHouse Number
Plataanstraat 5Plataanstraat5
Straat 12Straat12
Straat 12 IIStraat12 II
Dr. J. Straat 12Dr. J. Straat12
Dr. J. Straat 12 aDr. J. Straat12 a
Dr. J. Straat 12-14Dr. J. Straat12-14
Laan 1940 – 1945 37Laan 1940 – 194537
Plein 1940 2Plein 19402
1213-laan 111213-laan11
16 april 1944 Pad 116 april 1944 Pad1
1e Kruisweg 361e Kruisweg36
Laan 1940-’45 66Laan 1940-’4566
Laan ’40-’45Laan ’40-’45
Langeloërduinen 3 46Langeloërduinen3 46
Marienwaerdt 2e Dreef 2Marienwaerdt 2e Dreef2
Provincialeweg N205 1Provincialeweg N2051
Rivium 2e Straat 59.Rivium 2e Straat59.
Nieuwe gracht 20rdNieuwe gracht20rd
Nieuwe gracht 20rd 2Nieuwe gracht20rd 2
Nieuwe gracht 20zw /2Nieuwe gracht20zw /2
Nieuwe gracht 20zw/3Nieuwe gracht20zw/3
Nieuwe gracht 20 zw/4Nieuwe gracht20 zw/4
Bahnhofstr. 4Bahnhofstr.4
Wertstr. 10Wertstr.10
Lindenhof 1Lindenhof1
Nordesch 20Nordesch20
Weilstr. 6Weilstr.6
Harthauer Weg 2Harthauer Weg2
Mainaustr. 49Mainaustr.49
August-Horch-Str. 3August-Horch-Str.3
Marktplatz 31Marktplatz31
Schmidener Weg 3Schmidener Weg3
Karl-Weysser-Str. 6Karl-Weysser-Str.6

Scala

Uses nothing but the Standard Library:

import java.awt.Desktop
import java.io.{IOException, PrintWriter}
import java.net.{URI, ServerSocket}
import scala.xml.Elem

class WebServer(port: Int, soleDocument: Elem) extends Thread {
  this.setName(s"Server at $port")

  override def run() {
    val listener = try {
      new ServerSocket(port)
    } catch {
      case e: java.net.BindException => throw new IllegalStateException(s"Port $port already taken!")
    }
    println(s"Listening on port ${listener.getLocalPort}")

    while (!Thread.interrupted()) {
      try {
        //print(".")
        val socket = listener.accept
        new PrintWriter(socket.getOutputStream, true).println(soleDocument)
        socket.close()
      } catch {
        case ioe: IOException => println(ioe)
      }
    }
  }
} // class WebServer

object HtmlServer extends App {
  val PORT = 64507
  // Main
  val thread = new WebServer(PORT, HtmlBuilder)
  val uri = URI.create(s"http://localhost:$PORT/")
  thread.start()

  def HtmlBuilder: Elem = {
    def adressen: Iterator[String] =
      """Plataanstraat 5
        |Straat 12
        |Straat 12 II
        |Straat 1940 II
        |Dr. J. Straat   40
        |Dr. J. Straat 12 a
        |Dr. J. Straat 12-14
        |Laan 1940 – 1945 37
        |Plein 1940 2
        |1213-laan 11
        |16 april 1944 Pad 1
        |1e Kruisweg 36
        |Laan 1940-’45 66
        |Laan ’40-’45
        |Langeloërduinen 3 46
        |Marienwaerdt 2e Dreef 2
        |Provincialeweg N205 1
        |Rivium 2e Straat 59.
        |Nieuwe gracht 20rd
        |Nieuwe gracht 20rd 2
        |Nieuwe gracht 20zw /2
        |Nieuwe gracht 20zw/3
        |Nieuwe gracht 20 zw/4
        |Bahnhofstr. 4
        |Wertstr. 10
        |Lindenhof 1
        |Nordesch 20
        |Weilstr. 6
        |Harthauer Weg 2
        |Mainaustr. 49
        |August-Horch-Str. 3
        |Marktplatz 31
        |Schmidener Weg 3
        |Karl-Weysser-Str. 6""".stripMargin.lines

    def getSplittedAddresses(addresses: Iterator[String]) = {
      val extractor = new scala.util.matching.Regex( """(\s\d+[-/]\d+)|(\s(?!1940|1945)\d+[a-zI. /]*\d*)$|\d+\['][40|45]$""")


      def splitsAdres(input: String): (String, String) =
        (extractor.split(input).mkString, extractor.findFirstIn(input).getOrElse(""))

      addresses.map(org => {
        val temp = splitsAdres(org)
        List(org, temp._1, temp._2)
      })
    }

    def generateTable: Elem = {

      def coloring(rownum: Any): String = {
        rownum match {
          case Nil => "#9bbb59"
          case n: Int => if (n % 2 == 0) "#ebf1de" else "#d8e4bc"
        }
      }

      <table border="10">
        {(List(List("Given Address", "Street", "House Number")) ++ getSplittedAddresses(adressen)).
        zipWithIndex.map { case (row, rownum) => (if (rownum == 0) Nil else rownum) +: row}.map(row =>
        <tr bgcolor={coloring(row.head)}>
          {row.map(cell =>
          if (row.head == Nil)
            <th>
              {cell}
            </th>
          else
            <td>
              {cell}
            </td>)}
        </tr>)}
      </table>
    } // def generateTable

    <html>
      <head>
        <title>Rosetta.org Task solution</title>
      </head>
      <body lang="en-US" bgcolor="#e6e6ff" dir="LTR">
        <p align="CENTER">
          <font face="Arial, sans-serif" size="5">Split the house number from the street name</font>
        </p>
        <p align="CENTER">
          {generateTable}
        </p>
      </body>
    </html>
  } // def content
  if (Desktop.isDesktopSupported && Desktop.getDesktop.isSupported(Desktop.Action.BROWSE))
    Desktop.getDesktop.browse(uri)
  else println(s"Automatic start of Web browser not possible.\nWeb browser must be started manually, use $uri.")

  if (!thread.isAlive) sys.exit(-1)
  println("Web server started.")
  do print("Do you want to shutdown this server? <Y(es)/N>: ") while (!scala.io.StdIn.readBoolean)
  sys.exit()
}
Output:

Split the house number from the street name

Given AddressStreetHouse Number
1Plataanstraat 5Plataanstraat5
2Straat 12Straat12
3Straat 12 IIStraat12 II
4Straat 1940 IIStraat 1940 II
5Dr. J. Straat40Dr. J. Straat 40
6Dr. J. Straat 12 aDr. J. Straat12 a
7Dr. J. Straat 12-14Dr. J. Straat12-14
8Laan 1940 – 1945 37Laan 1940 – 194537
9Plein 1940 2Plein 19402
101213-laan 111213-laan11
1116 april 1944 Pad 116 april 1944 Pad1
121e Kruisweg 361e Kruisweg36
13Laan 1940-’45 66Laan 1940-’4566
14Laan ’40-’45Laan ’40-’45
15Langeloërduinen 3 46Langeloërduinen3 46
16Marienwaerdt 2e Dreef 2Marienwaerdt 2e Dreef2
17Provincialeweg N205 1Provincialeweg N2051
18Rivium 2e Straat 59.Rivium 2e Straat59.
19Nieuwe gracht 20rdNieuwe gracht20rd
20Nieuwe gracht 20rd 2Nieuwe gracht20rd 2
21Nieuwe gracht 20zw /2Nieuwe gracht20zw /2
22Nieuwe gracht 20zw/3Nieuwe gracht20zw/3
23Nieuwe gracht 20 zw/4Nieuwe gracht20 zw/4
24Bahnhofstr. 4Bahnhofstr.4
25Wertstr. 10Wertstr.10
26Lindenhof 1Lindenhof1
27Nordesch 20Nordesch20
28Weilstr. 6Weilstr.6
29Harthauer Weg 2Harthauer Weg2
30Mainaustr. 49Mainaustr.49
31August-Horch-Str. 3August-Horch-Str.3
32Marktplatz 31Marktplatz31
33Schmidener Weg 3Schmidener Weg3
34Karl-Weysser-Str. 6Karl-Weysser-Str.6

Tcl

Works with: Tcl version 8.6
package require Tcl 8.6

# This is identical to the address task. Skip forward to the next section...
proc split_DE_NL_address {streetAddress} {
    set RE {(?x)
	^ (.*?) (
	    (?:\s \d+ [-/] \d+)
	|
	    (?:\s (?!1940|1945)\d+ [a-zI. /]* \d*)
	)? $
    }
    regexp $RE $streetAddress -> str num
    return [list [string trim $str] [string trim $num]]
}

set data {
    Plataanstraat 5
    Straat 12
    Straat 12 II
    Dr. J. Straat   12
    Dr. J. Straat 12 a
    Dr. J. Straat 12-14
    Laan 1940  1945 37
    Plein 1940 2
    1213-laan 11
    16 april 1944 Pad 1
    1e Kruisweg 36
    Laan 1940-45 66
    Laan 40-45
    Langeloërduinen 3 46
    Marienwaerdt 2e Dreef 2
    Provincialeweg N205 1
    Rivium 2e Straat 59.
    Nieuwe gracht 20rd
    Nieuwe gracht 20rd 2
    Nieuwe gracht 20zw /2
    Nieuwe gracht 20zw/3
    Nieuwe gracht 20 zw/4
    Bahnhofstr. 4
    Wertstr. 10
    Lindenhof 1
    Nordesch 20
    Weilstr. 6
    Harthauer Weg 2
    Mainaustr. 49
    August-Horch-Str. 3
    Marktplatz 31
    Schmidener Weg 3
    Karl-Weysser-Str. 6
}

# Construct the HTML to show
set html "<html><head><meta charset=\"UTF-8\">
<title>split_DE_NL_address</title></head><body>
<table border><tr><th>Address</th><th>Street</th><th>Number</th></tr>"
foreach streetAddress [split $data "\n"] {
    set streetAddress [string trim $streetAddress]
    if {$streetAddress eq ""} continue
    lassign [split_DE_NL_address $streetAddress] str num
    append html "<tr><td>$streetAddress</td><td>$str</td><td>$num</td></tr>"
}
append html "</table>
</body></html>"
# Pick a unique filename with .html extension (important!)
set f [file tempfile filename street.html]
fconfigure $f -encoding utf-8
puts $f $html
close $f

##### THE WEB BROWSER LAUNCH CODE MAGIC #####
# Relies on the default registration of browsers for .html files
# This is all very platform specific; Android requires another incantation again
if {$tcl_platform(platform) eq "windows"} {
    exec {*}[auto_execok start] "" [file nativename $filename]
} elseif {$tcl_platform(os) eq "Darwin"} {
    exec open $filename
} else {
    exec xdg_open $filename
}
Output:
AddressStreetNumber
Plataanstraat 5Plataanstraat5
Straat 12Straat12
Straat 12 IIStraat12 II
Dr. J. Straat 12Dr. J. Straat12
Dr. J. Straat 12 aDr. J. Straat12 a
Dr. J. Straat 12-14Dr. J. Straat12-14
Laan 1940 – 1945 37Laan 1940 – 194537
Plein 1940 2Plein 19402
1213-laan 111213-laan11
16 april 1944 Pad 116 april 1944 Pad1
1e Kruisweg 361e Kruisweg36
Laan 1940-’45 66Laan 1940-’4566
Laan ’40-’45Laan ’40-’45
Langeloërduinen 3 46Langeloërduinen3 46
Marienwaerdt 2e Dreef 2Marienwaerdt 2e Dreef2
Provincialeweg N205 1Provincialeweg N2051
Rivium 2e Straat 59.Rivium 2e Straat59.
Nieuwe gracht 20rdNieuwe gracht20rd
Nieuwe gracht 20rd 2Nieuwe gracht20rd 2
Nieuwe gracht 20zw /2Nieuwe gracht20zw /2
Nieuwe gracht 20zw/3Nieuwe gracht20zw/3
Nieuwe gracht 20 zw/4Nieuwe gracht20 zw/4
Bahnhofstr. 4Bahnhofstr.4
Wertstr. 10Wertstr.10
Lindenhof 1Lindenhof1
Nordesch 20Nordesch20
Weilstr. 6Weilstr.6
Harthauer Weg 2Harthauer Weg2
Mainaustr. 49Mainaustr.49
August-Horch-Str. 3August-Horch-Str.3
Marktplatz 31Marktplatz31
Schmidener Weg 3Schmidener Weg3
Karl-Weysser-Str. 6Karl-Weysser-Str.6

Wren

Library: Wren-pattern
Library: Wren-fmt
Library: Wren-iterate

An embedded program so we can ask the C host to open the browser for us after we've created the html file.

The Wren code is based in part on the Nim example and uses the same color scheme.

/* Starting_a_web_browser.wren */

import "./pattern" for Pattern
import "./fmt" for Fmt
import "./iterate" for Indexed

foreign class File {
    foreign static remove(filename)

    foreign static flushAll()

    construct open(filename, mode) {}

    foreign write(s)

    foreign close()
}

class C {
    foreign static system(s)

    foreign static sleep(sec)
}

var digits = "0123456789"
var p = Pattern.new("+1/s")

var separateHouseNumber = Fn.new { |address|
    var len = address.count
    var splits = p.splitAll(address)
    var size = splits.count
    var last = splits[-1]
    var penult = splits[-2]
    var house
    if (digits.contains(last[0])) {
        if (size > 2 && digits.contains(penult[0]) && !penult.startsWith("194")) {
            house = penult + " " + last
        } else {
            house = last
        }
    } else if (size > 2) {
        house = penult + " " + last
    } else {
        house = ""
    }
    var street = address.take(len - house.count).join().trimEnd()
    return [street, house]
}

var addresses = [
    "Plataanstraat 5",
    "Straat 12",
    "Straat 12 II",
    "Dr. J. Straat   12",
    "Dr. J. Straat 12 a",
    "Dr. J. Straat 12-14",
    "Laan 1940 - 1945 37",
    "Plein 1940 2",
    "1213-laan 11",
    "16 april 1944 Pad 1",
    "1e Kruisweg 36",
    "Laan 1940-'45 66",
    "Laan '40-'45",
    "Langeloërduinen 3 46",
    "Marienwaerdt 2e Dreef 2",
    "Provincialeweg N205 1",
    "Rivium 2e Straat 59.",
    "Nieuwe gracht 20rd",
    "Nieuwe gracht 20rd 2",
    "Nieuwe gracht 20zw /2",
    "Nieuwe gracht 20zw/3",
    "Nieuwe gracht 20 zw/4",
    "Bahnhofstr. 4",
    "Wertstr. 10",
    "Lindenhof 1",
    "Nordesch 20",
    "Weilstr. 6",
    "Harthauer Weg 2",
    "Mainaustr. 49",
    "August-Horch-Str. 3",
    "Marktplatz 31",
    "Schmidener Weg 3",
    "Karl-Weysser-Str. 6"
]

var htmlHeader = """
<html>
<head>
<title>Rosetta Code - Start a Web Browser</title>
<meta charset="UTF-8">
</head>
<body bgcolor="#e6e6ff">
<p align="center">
<font face="Arial, sans-serif" size="5">Split the house number from the street name</font>
</p>
<p align="center">
<table border="2"> <tr bgcolor="#9bbb59">
<th>Address</th><th>Street</th><th>House Number</th>
"""

var htmlFooter = """
</table>
</p>
</body>
</html>
"""

var htmlFile = File.open("test.html", "w")
htmlFile.write(htmlHeader + "\n")
for (se in Indexed.new(addresses)) {
    var color = (se.index & 1 == 0) ? "#ebf1de" : "#d8e4bc"
    var address = se.value
    var res = separateHouseNumber.call(address)
    var street = res[0]
    var house = res[1]
    if (house == "") house = "(none)"
    htmlFile.write("<tr bgcolor=%(color)><td>%(address)</td><td>%(street)</td><td>%(house)</td></tr>\n")
}
htmlFile.write(htmlFooter + "\n")
C.system("firefox test.html")  // or whatever browser you use
File.flushAll()                // flush all streams
C.sleep(5)                     // wait five seconds
File.remove("test.html")       // remove the file


We now embed this in the following C program, compile and run it.

/* gcc Starting_a_web_browser.c -o Starting_a_web_browser -lwren -lm */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "wren.h"

/* C <=> Wren interface functions */

void C_fileAllocate(WrenVM* vm) {
    FILE** pfp = (FILE**)wrenSetSlotNewForeign(vm, 0, 0, sizeof(FILE*));
    const char *filename = wrenGetSlotString(vm, 1);
    const char *mode = wrenGetSlotString(vm, 2);
    *pfp = fopen(filename, mode);
}

void C_write(WrenVM* vm) {
    FILE* fp = *(FILE**)wrenGetSlotForeign(vm, 0);
    const char *s = wrenGetSlotString(vm, 1);
    fputs(s, fp);
}

void C_close(WrenVM* vm) {
    FILE* fp = *(FILE**)wrenGetSlotForeign(vm, 0);
    fclose(fp);
}

void C_remove(WrenVM* vm) {
    const char *filename = wrenGetSlotString(vm, 1);
    remove(filename);
}

void C_flushAll(WrenVM* vm) {
    fflush(NULL);
}

void C_system(WrenVM* vm) {
    const char *s = wrenGetSlotString(vm, 1);
    system(s);
}

void C_sleep(WrenVM* vm) {
    int seconds = (int)wrenGetSlotDouble(vm, 1);
    sleep(seconds);
}

WrenForeignClassMethods bindForeignClass(WrenVM* vm, const char* module, const char* className) {
    WrenForeignClassMethods methods;
    methods.allocate = NULL;
    methods.finalize = NULL;
    if (strcmp(module, "main") == 0) {
        if (strcmp(className, "File") == 0) {
            methods.allocate = C_fileAllocate;
        }
    }
    return methods;
}

WrenForeignMethodFn bindForeignMethod(
    WrenVM* vm,
    const char* module,
    const char* className,
    bool isStatic,
    const char* signature) {
    if (strcmp(module, "main") == 0) {
        if (strcmp(className, "File") == 0) {
            if (!isStatic && strcmp(signature, "write(_)") == 0)   return C_write;
            if (!isStatic && strcmp(signature, "close()") == 0)    return C_close;
            if ( isStatic && strcmp(signature, "remove(_)") == 0)  return C_remove;
            if ( isStatic && strcmp(signature, "flushAll()") == 0) return C_flushAll;
        } else if (strcmp(className, "C") == 0) {
            if ( isStatic && strcmp(signature, "system(_)") == 0)  return C_system;
            if ( isStatic && strcmp(signature, "sleep(_)") == 0)   return C_sleep;
        }
    }
    return NULL;
}

static void writeFn(WrenVM* vm, const char* text) {
    printf("%s", text);
}

void errorFn(WrenVM* vm, WrenErrorType errorType, const char* module, const int line, const char* msg) {
    switch (errorType) {
        case WREN_ERROR_COMPILE:
            printf("[%s line %d] [Error] %s\n", module, line, msg);
            break;
        case WREN_ERROR_STACK_TRACE:
            printf("[%s line %d] in %s\n", module, line, msg);
            break;
        case WREN_ERROR_RUNTIME:
            printf("[Runtime Error] %s\n", msg);
            break;
    }
}

char *readFile(const char *fileName) {
    FILE *f = fopen(fileName, "r");
    fseek(f, 0, SEEK_END);
    long fsize = ftell(f);
    rewind(f);
    char *script = malloc(fsize + 1);
    fread(script, 1, fsize, f);
    fclose(f);
    script[fsize] = 0;
    return script;
}

static void loadModuleComplete(WrenVM* vm, const char* module, WrenLoadModuleResult result) {
    if( result.source) free((void*)result.source);
}

WrenLoadModuleResult loadModule(WrenVM* vm, const char* name) {
    WrenLoadModuleResult result = {0};
    if (strcmp(name, "random") != 0 && strcmp(name, "meta") != 0) {
        result.onComplete = loadModuleComplete;
        char fullName[strlen(name) + 6];
        strcpy(fullName, name);
        strcat(fullName, ".wren");
        result.source = readFile(fullName);
    }
    return result;
}

int main(int argc, char **argv) {
    WrenConfiguration config;
    wrenInitConfiguration(&config);
    config.writeFn = &writeFn;
    config.errorFn = &errorFn;
    config.bindForeignClassFn = &bindForeignClass;
    config.bindForeignMethodFn = &bindForeignMethod;
    config.loadModuleFn = &loadModule;
    WrenVM* vm = wrenNewVM(&config);
    const char* module = "main";
    const char* fileName = "Starting_a_web_browser.wren";
    char *script = readFile(fileName);
    WrenInterpretResult result = wrenInterpret(vm, module, script);
    switch (result) {
        case WREN_RESULT_COMPILE_ERROR:
            printf("Compile Error!\n");
            break;
        case WREN_RESULT_RUNTIME_ERROR:
            printf("Runtime Error!\n");
            break;
        case WREN_RESULT_SUCCESS:
            break;
    }
    wrenFreeVM(vm);
    free(script);
    return 0;
}
Output:
Same as Nim.
Cookies help us deliver our services. By using our services, you agree to our use of cookies.