Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions browser/about_www.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Some Notes About WWW

* When our simple web browser prints a web page,
it just prints the raw HTML code.
All the things between `<` and `>`
characters are called *tags*,
and they contain commands
that indicate how the rest of the text should be formatted.
To do that well is beyond the scope of this tutorial.

* Some web addresses don't refer to HTML pages,
but to (among other things) sound clips or pictures.
If you try to access such a web address with this browser,
it will dump the sound or picture on the screen
as if it had been text,
and this will look even uglier than raw HTML code.
Real web browsers check the type of the web page,
and then take the appropriate action depending on that type.

* If your web browser fails to retrieve a web page
that you think exists,
this may be because you haven't typed the address exactly correct.
For example,
some addresses must have a slash (`/`) at the end.
More advanced web browsers discuss things like this with the web server,
and they usually manage to fix the address for you.

* You may not get a "failed" message
when you try to retrieve a web page that doesn't exist.
When the web server gets a request for a non-existent page,
it generates a new web page with an error message,
and your web browser receives and shows that page.
97 changes: 97 additions & 0 deletions browser/arguments_and_if.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
# Command-line Arguments and if

Before we let the program actually do anything
with the URL we give to it,
we will improve the program
to let it take the URL as a **command-line argument**.
That is, we want to start the program with the command

```
> webbrowser.pike http://pike.ida.liu.se/
```

instead of letting the program ask for the URL.
We add some code for this:

```pike
#! /usr/local/bin/pike

// The Very Simple World Wide Web Browser

int main(int argc, array(string) argv) // 2)
{
write("Welcome to the Very Simple WWW Browser!\n");
string url;
if (argc == 2) // 3), 5)
url = argv[1]; // 4)
else // 5)
{ // 5)
write("Type the address of the web page:\n");
url = Stdio.stdin->gets();
} // 5)
write("URL: " + url + "\n");
return 0;
} // main
```

This program can handle a command-line argument,
but if you don't give one,
it will ask for an URL just as before.

There are some new things to explain here:

1. The first line `#! /usr/local/bin/pike`
only works on a Unix system,
as described earlier.
You can remove it if you are using Windows.

2. We have added `int argc, array(string) argv`
as **parameters** to `main`.
These parameters are like normal variables,
except that they will be assigned some values automatically
when the program starts.

The variable `argc` has the type `int`,
which means **integer**.
It will contain the number of command-line arguments.
The program name is counted as an argument,
so if you give one argument to the program,
`argc` will have the value **2**.

The variable `argv` will contain the arguments.
Its type is `array(string)`,
which means **array of strings**.
Each command-line argument is put in a string,
and together they form a list or array.

3. `argc == 2` is a comparison.
We check if the value of `argc` is **2**.
`==` is an **operator**
that checks if two things are the same.
Some other comparison operators in Pike are `<` (less than),
`>=` (greater than or equal), and `!=` (not same).

4. `argv[1]` retrieves the element at position number 1 in an array.
The positions are numbered from 0,
so position 1 is actually the second element in the array.
This is the URL given as argument to the program.
`argv[0]` contains the name of the program,
the string `"webbrowser.pike"`.

5. The `if` statement lets Pike choose between different actions.
It follows the template or pattern

```pike
if ( *condition* )
*something*
else
*something-else*
```

If the *condition* (in our case, that `argc == 2`) is **true**,
Pike will do the *something*.
If the *condition* is **false**,
it will do the *something-else*.
In our program,
there are two **statements** in the *something-else*,
so we must enclose it in curly brackets, `{` and `}`.
55 changes: 55 additions & 0 deletions browser/convenient_syntax.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# Syntactic Sugar

## Importing a Module

If we don't want to write the module name
every time we use something from that module,
an alternative is to **import** the module.
If we import `Protocols.HTTP`,
we can use the data type `Query`,
and the method `get_url`,
without prefixing them with `Protocols.HTTP`:

```pike
import Protocols.HTTP;

void handle_url(string this_url)
{
write("Fetching URL '" + this_url + "'...");
Query web_page;
web_page = get_url(this_url);
if (web_page == 0)
{
write(" Failed.\n");
return;
}
write(" Done.\n");
} // handle_url
```

Although you *could* import lots and lots of modules
for the ease of lazy typing,
this mostly isn't a recommended practice,
for obvious reasons of clarity and readability.
There are also some non-obvious reasons to refrain from doing imports.
If someone adds the method `write` to the module `Protocols.HTTP`,
we would call that method instead of the one that writes text to the user.
It also takes longer to start the program,
since Pike must search through all imported modules
to find the methods you use.

## Initial Values for Variables

We can give a value to a variable when we define it,
so there is no reason to write:

```pike
Query web_page;
web_page = get_url(this_url);
```

We change it to this:

```pike
Query web_page = get_url(this_url);
```
123 changes: 123 additions & 0 deletions browser/fetching_the_page.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
# Magic Web Stuff

Now it's time to start surfing the web!
Perhaps you know that web pages are written
in something called HTML (HyperText Markup Language),
and that the `http` you see in web addresses
like `http://pike.ida.liu.se/`
means HyperText Transfer Protocol.
The HyperText Transfer Protocol is a description
of how web browsers communicate with web servers.

It is actually a fairly complicated operation
to connect to a web server,
to tell it to send you a web page,
and then to receive that page as the server sends it.
Fortunately for us,
someone has already done this for us.
There is a **module** called `Protocols.HTTP`,
which handles the communication with the web server.
A module is a package of Pike code
that can easily be used by other programmers.

We rewrite the method `handle_url`
to actually try to fetch the web page,
using the module `Protocols.HTTP`:

```pike
void handle_url(string this_url)
{
write("Fetching URL '" + this_url + "'...");
Protocols.HTTP.Query web_page;
web_page = Protocols.HTTP.get_url(this_url);
if (web_page == 0)
{
write(" Failed!\n");
return;
}
write(" Done.\n");
} // handle_url
```

The interesting part here is the lines

```pike
Protocols.HTTP.Query web_page;
web_page = Protocols.HTTP.get_url(this_url);
```

First we define the variable `web_page`,
with the data type `Protocols.HTTP.Query`.
Actually, the data type is called `Query`,
and is defined in the module `Protocols.HTTP`,
but we must write it as `Protocols.HTTP.Query`
so Pike knows where to find it.

A data item of the type `Protocols.HTTP.Query`
contains the result of a web page retrieval:
the text of the web page,
but also some more information,
such as the time when the page was created.

The actual work is done by the method `Protocols.HTTP.get_url`,
which is actually the method `get_url` in the module `Protocols.HTTP`.
It talks to the web server,
fills a `Query` object with everything it finds,
and returns it.
If it cannot find the web page, it returns zero (**0**) instead.

Some other things that might need to be explained in this example:

* We can use single quotes (') inside a string.
If we want to put a double quote (") in a string,
we can do so by prefixing the double quote with a backslash:

```pike
"This string contains a \"."
```

* If the web page couldn't be found,
we use the statement

```pike
return;`
```

to stop executing the method `handle_url`,
and instead return to where it was called.
This is the same as the

```pike
return 0;
```

we have seen in `main`,
except that `handle_url` doesn't return a value.

* `return` just returns from the method we are in.
If we want to terminate the program,
we can use the built-in function `exit`:

```pike
exit(0);
```

This has the same effect as returning **0** from `main`.

When we run this version of the web browser, it may look something
like this. The user's command is shown in *italics*:

```
> webbrowser.pike pike.ida.liu.se
Welcome to the Very Simple WWW Browser!
Fetching URL 'pike.lysator.liu.se'... Done.
```

If we try to retrieve a web page that doesn't exist,
the web browser fails:

```
> webbrowser.pike cod.lysator.liu.se
Welcome to the Very Simple WWW Browser!
Fetching URL 'cod.ida.liu.se'... Failed!
```
Loading