Compare commits

...

7 Commits

3 changed files with 105 additions and 23 deletions

View File

@ -1,4 +1,4 @@
Copyright (c) <year> <owner> . All rights reserved.
Copyright (c) 2020 Wholesomedonut . All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
@ -10,7 +10,7 @@ this list of conditions and the following disclaimer.
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS”
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
@ -19,4 +19,4 @@ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@ -1,18 +1,19 @@
# gemini-demo-1
# asparagus
Minimal but usable interactive Gemini client in < 100 LOC of Python 3
Larger, more functional version of solderpunk's gemini-demo-1,
which was a Gemini client in <=100 LOC in Python 3.
## Rationale
## Why the fork?
One of the original design criteria for the Gemini protocol was that
"a basic but usable (not ultra-spartan) client should fit comfortably
within 50 or so lines of code in a modern high-level language.
Certainly not more than 100". This client was written to gauge how
close to (or far from!) that goal the initial rough specification is.
I really enjoyed solderpunk's work. Quick, clean, and tiny.
I just wanted to try my luck at getting a more fleshed-out app going.
This will probably wind up getting ported to Clojure.
## Capabilities
This crude but functional client:
This fork has all of gemini-demo-1's functionality:
* Has a minimal interactive interface for "Gemini maps"
* Will print plain text in any encoding if it is properly declared in
@ -23,8 +24,11 @@ This crude but functional client:
* Will report errors
* Does NOT DO ANY validation of TLS certificates
It's a *snug* fit in 100 lines, but it's possible. A 50 LOC client
would need to be much simpler.
### IN addition to:
* Has session-persistent history that you can repeatedly maneuver through
* Descriptive error texts
* More keyboard commands and CLI-accessible help text.
## Usage
@ -35,6 +39,10 @@ visit a Gemini location.
If a Gemini menu is visited, you'll see numeric indices for links, ala
VF-1 or AV-98. Type a number to visit that link.
There is very crude history: you can type `b` to go "back".
Press h to see a printout of your history,
b to go back a page,
and f to go forward a page.
Type `q` to quit.
Type ? to see a brief help text inside the client.
Press q to quit.

View File

@ -13,6 +13,31 @@ caps = mailcap.getcaps()
menu = []
hist = []
def printHelp():
help = """ Type in a gemini:// address to go somewhere,
input 'b' to go back a page,
'f' to go forward,
'h' to show your history in order,
'?' to show this help again,
or 'q' to quit.
"""
print(help)
def printIntro():
o = """
Welcome to Asparagus, a single-file Python client for the Gemini protocol.
Original source code by solderpunk, and
forked by Wholesomedonut on Sep 6 2020.
Questions about this fork?
Email with subject "Asparagus + whatever-you-need",
to wholesomedonut[at]tuta[dot]io .
"""
print(o)
printHelp()
def absolutise_url(base, relative):
# Absolutise relative links
if "://" not in relative:
@ -21,6 +46,8 @@ def absolutise_url(base, relative):
relative = urllib.parse.urljoin(base, relative)
relative = relative.replace("http://", "gemini://")
return relative
printIntro()
while True:
# Get input
@ -34,16 +61,61 @@ while True:
url = menu[int(cmd)-1]
elif cmd.lower() == "b":
# Yes, twice
url = hist.pop()
url = hist.pop()
# url = hist.pop()
# url = hist.pop()
# updated to preserve history in list
# so you can use 'f' to go forward too. - WD
try:
url = hist[len(hist) - 2]
except IndexError as e:
print(e)
print('You do not have any history to go back to')
continue
elif cmd.lower() == "f":
# now you can go ahead in history too! - WD
try:
url = hist[url+1]
except NameError as e:
print(e)
print('You do not have any history')
except IndexError as e:
print(e)
print('You are at the front of your history already')
continue
elif cmd.lower() == "h":
# Will actually show history. - WD
try:
print("History:")
for x in range(len(hist)):
print('[',x,']',hist[x])
except Exception as e:
print(e)
print('Looks like I dun goofed.')
elif cmd == "?":
try:
printHelp()
continue
except Exception as e:
print(e)
else:
url = cmd
if not "://" in url:
url = "gemini://" + url
parsed_url = urllib.parse.urlparse(url)
url = cmd
if not "://" in url:
url = "gemini://" + url
# this try/except allows you to check for history with 'h'
# even if you have visited no pages yet, without crashing. - WD
try:
parsed_url = urllib.parse.urlparse(url)
except NameError as e:
print('Error:',e,'\nso try having some history first by visiting a page')
continue
if parsed_url.scheme != "gemini":
print("Sorry, Gemini links only.")
# break
continue
# now it'll just loop again
# instead of quitting the program if you
# put the wrong thing in. - WD
# Do the Gemini transaction
try:
while True:
@ -76,6 +148,8 @@ while True:
# Fail if transaction was not successful
if not status.startswith("2"):
print("Error %s: %s" % (status, mime))
# haha funny error code - WD
print("OH NO I didn't communicate with the Gemini server right")
continue
# Handle text
if mime.startswith("text/"):
@ -113,4 +187,4 @@ while True:
os.system(cmd_str)
os.unlink(tmpfp.name)
# Update history
hist.append(url)
hist.append(url)