diff --git a/.gitignore b/.gitignore
index 3a8cabc..9efad1c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,4 @@
-/target
-.idea
+__pycache__
+core/__pycache__
+mode/__pycache__
+.idea
\ No newline at end of file
diff --git a/README.md b/README.md
index d69472b..3d472e2 100644
--- a/README.md
+++ b/README.md
@@ -1 +1,14 @@
-# lambda
+# λ lambda
+Next generation hackable text editor for nerds.
+
+### Overview
+Lambda is a similar text editor to `vim` or `kakoune`.
+However, it has a few key differences:
+- Lambda is written in Python, so it is easy to hack and learn.
+- Lambda is incredibly modular, so you can easily add new features.
+- Lambda is written in a way that makes it easy to use in a terminal.
+- Lambda follows the unix philosophy of "do one thing and do it well."
+ - It has no bloated features, like splits or tabs
+ - It contains the bare necessities and provides a few extra modules
+- Lambda is extremely fast and makes use of efficient memory management.
+- Lambda has much better default keybindings than other text editors.
diff --git a/core/components.py b/core/components.py
index db98030..e640b02 100644
--- a/core/components.py
+++ b/core/components.py
@@ -4,19 +4,18 @@ import curses
class StatusBar:
def __init__(self, instance):
- self.instance = instance
self.mode = instance.mode.upper()
self.file = instance.buffer.name or "[No Name]"
self.icon = instance.config["icon"] or "λ"
self.colors = (7, 5, 13)
self.components = [self.icon, self.mode, self.file]
- def render(self):
+ def render(self, instance):
x = 1
- utils.clear(self.instance, self.instance.height - 2, 0)
+ utils.clear(instance, instance.height - 2, 0)
for count, component in enumerate(self.components):
- self.instance.screen.addstr(self.instance.height - 2, x, component,
- curses.color_pair(self.colors[count]) | curses.A_BOLD)
+ instance.screen.addstr(instance.height - 2, x, component,
+ curses.color_pair(self.colors[count]) | curses.A_BOLD)
x += len(component) + 1
@@ -28,4 +27,4 @@ class Components:
def render(self, instance):
for component in self.components["bottom"]:
- component(instance).render()
+ component(instance).render(instance)
diff --git a/core/modes.py b/core/modes.py
index 64ecd7c..9a3abed 100644
--- a/core/modes.py
+++ b/core/modes.py
@@ -1,33 +1,29 @@
from mode import normal, insert, command
-def activate(instance, mode) -> object:
+def activate(instance, mode):
# Visibly update the mode
instance.mode = mode
instance.update()
if mode == "command":
- instance = command.activate(instance)
+ # Activate command mode
+ command.activate(instance)
elif mode == "insert":
- instance = insert.activate(instance)
+ # Activate insert mode
+ insert.activate(instance)
elif mode == "normal":
- instance = normal.activate(instance)
-
- return instance
+ # Activate normal mode
+ normal.activate(instance)
def handle_key(instance, key):
+ # Normal mode - default keybindings
if instance.mode == "normal":
- instance = normal.execute(instance, key)
+ normal.execute(instance, key)
# Insert mode - inserting text to the buffer
elif instance.mode == "insert":
- instance = insert.execute(instance, key)
-
- # Command mode - extra commands for lambda
- elif instance.mode == "command":
- instance = command.activate(instance)
-
- return instance
+ insert.execute(instance, key)
diff --git a/lambda b/lambda
index 8494e3f..54580fd 100755
--- a/lambda
+++ b/lambda
@@ -1,3 +1,3 @@
#!/bin/sh
-python3 ./lambda.py "$@"
+python3 ./main.py "$@"
diff --git a/main.py b/main.py
index 964e2f2..de0f2a8 100644
--- a/main.py
+++ b/main.py
@@ -21,7 +21,10 @@ class Lambda:
self.config = {"icon": "λ"}
def update_dimensions(self):
+ # Calculate the entire height and width of the terminal
self.height, self.width = self.screen.getmaxyx()
+
+ # Calculate the safe area for the buffer by removing heights & widths of components
self.safe_height = self.height - len(self.components.components["bottom"])
def update(self):
@@ -41,7 +44,7 @@ class Lambda:
# Change the cursor shape
cursors.cursor_mode("block")
- # Turn no echo on
+ # Don't echo any key-presses
curses.noecho()
# Show a welcome message if lambda opens with no file
@@ -52,6 +55,7 @@ class Lambda:
self.run()
def run(self):
+ # The main loop, which runs until the user quits
while True:
# Write the buffer to the screen
# buffers.write_buffer(screen, buffer)
@@ -71,38 +75,47 @@ class Lambda:
def main():
- # Command line arguments
+ # Shell arguments
parser = argparse.ArgumentParser(description="Next generation hackable text editor for nerds.")
parser.add_argument("file", metavar="file", type=str, nargs="?",
help="The name of a file for lambda to open")
- # Collect the arguments passed into lambda
+ # Collect the arguments passed into lambda at the shell
args = parser.parse_args()
- # Load the file into buffer
+ # Load the file into a Buffer object
buffer = buffers.load_file(args.file)
# Change the escape delay to 25ms
# Fixes an issue where esc takes way too long to press
os.environ.setdefault("ESCDELAY", "25")
- # Load lambda with the buffer
+ # Load lambda with the buffer object
screen = Lambda(buffer)
- # Start the screen
+ # Start the screen, this will loop until exit
try:
screen.start()
- # KeyboardInterrupt is thrown when ctrl+c is pressed
+ # KeyboardInterrupt is thrown when is pressed (exit)
except KeyboardInterrupt:
+ # Clean up the screen
curses.endwin()
+
+ # Then, just exit
sys.exit()
+ # Excepts *any* errors that occur
except Exception as exception:
+ # Clean up the screen
curses.endwin()
+
+ # Print the error message and traceback
print(f"{colors.Codes.red}FATAL ERROR:{colors.Codes.end} "
f"{colors.Codes.yellow}{exception}{colors.Codes.end}\n")
print(traceback.format_exc())
+
+ # Exit, with an error code
sys.exit(0)
diff --git a/mode/command.py b/mode/command.py
index 82a4a5a..901ce78 100644
--- a/mode/command.py
+++ b/mode/command.py
@@ -2,33 +2,31 @@ from core import utils
def execute(instance, commands):
- if not commands:
- # Quit if there are no commands, don't check anything
- return instance
+ # Only if commands are given
+ if commands:
+ # Check each command in the list of commands
+ for command in commands:
+ # Write
+ if command == "w":
+ # Write to the file
+ pass
- for command in commands:
- if command == "w":
- # Write to the file
- pass
+ # Quit
+ elif command == "q":
+ # Load a goodbye prompt
+ utils.goodbye(instance)
- elif command == "q":
- # Load a goodbye prompt
- utils.goodbye(instance)
-
- else:
- utils.error(instance, f"not an editor command: '{command}'")
-
- return instance
+ # Unknown command
+ else:
+ utils.error(instance, f"not an editor command: '{command}'")
def activate(instance):
- # Start the prompt
+ # Create a prompt, which returns the input (commands)
commands = utils.prompt(instance, ":")
- # Execute the commands
- instance = execute(instance, commands)
+ # Execute the commands given
+ execute(instance, commands)
- # Return to normal mode
+ # Return to normal mode once all commands are executed
instance.mode = "normal"
-
- return instance
diff --git a/mode/insert.py b/mode/insert.py
index ba0ea9b..77ef3de 100644
--- a/mode/insert.py
+++ b/mode/insert.py
@@ -1,18 +1,13 @@
-from core import cursors
-from mode import normal
+from core import cursors, modes
def execute(instance, key):
+ # Enter key
if key == 27:
# Switch to normal mode
- instance.mode = "normal"
- normal.activate(instance)
-
- return instance
+ modes.activate(instance, "normal")
def activate(instance):
# Switch the cursor to a line
cursors.cursor_mode("line")
-
- return instance
diff --git a/mode/normal.py b/mode/normal.py
index cd3d9de..bf3919a 100644
--- a/mode/normal.py
+++ b/mode/normal.py
@@ -22,24 +22,20 @@ def execute(instance, key):
elif key == ord("i"):
# Activate insert mode
- instance = modes.activate(instance, "insert")
+ modes.activate(instance, "insert")
elif key == ord("I"):
# Move the cursor to the right
instance.cursor = cursors.cursor_push(instance.cursor, "right")
# Then activate insert mode
- instance = modes.activate(instance, "insert")
+ modes.activate(instance, "insert")
elif key in (ord(":"), ord(";")):
# Activate command mode
- instance = modes.activate(instance, "command")
-
- return instance
+ modes.activate(instance, "command")
-def activate(instance):
+def activate():
# Switch the cursor to a block
cursors.cursor_mode("block")
-
- return instance
\ No newline at end of file