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
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ Download the `.nvda-addon` file from [GitHub Releases](https://github.com/InfiAr

## Getting started

1. Open a code file in Notepad, for example [samples/latihan.py](samples/latihan.py) from this repository. Its first lines say what to try where.
1. Open a code file in Notepad, for example [samples/practice.py](samples/practice.py) from this repository (in Indonesian: [samples/latihan.py](samples/latihan.py)). Its first lines say what to try where.
2. Move up and down with the arrow keys and listen to the tones rise and fall.
3. Press NVDA+shift+K, then W, to hear where you are. NVDA+shift+K, then H, lists every command, and control+shift+P lists them with their keys.
4. Press control+F5 to run it.
Expand Down Expand Up @@ -91,7 +91,7 @@ The build writes `codeCompass-<version>.nvda-addon`. It needs no SCons or gettex
- `addon/sounds/`: Visual Studio Code's accessibility signal sounds, as WAV files.
- `addon/locale/id/LC_MESSAGES/nvda.po`: the Indonesian translation. `tools/update_po.py` rewrites it to match the messages in the code, and a test fails when a message has no translation.
- `tests/`: analyzer tests, translation checks and tests of the plugin against stubbed NVDA and wx modules.
- `samples/`: files to try the add-on with: `latihan.py` walks through the features, `rusak.js` is broken on purpose.
- `samples/`: files to try the add-on with: `practice.py` (and `latihan.py`, the same in Indonesian) walks through the features, `rusak.js` is broken on purpose.

## Contributing

Expand Down
2 changes: 1 addition & 1 deletion addon/doc/en/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ Bookmarks are kept per file, also after closing Notepad or restarting NVDA. Each

When you come back to Notepad and another program (an editor, a code generator, Git) has changed the open file, Code Compass notices:

- With no unsaved changes, the file is reloaded right away and Code Compass says what changed, for example "latihan.py changed on disk and was reloaded: 1 line changed, 2 lines added". The caret stays on its line and bookmarks follow their lines.
- With no unsaved changes, the file is reloaded right away and Code Compass says what changed, for example "practice.py changed on disk and was reloaded: 1 line changed, 2 lines added". The caret stays on its line and bookmarks follow their lines.
- With unsaved changes, nothing is replaced: Code Compass tells you, and NVDA+shift+K then R reloads the file when you choose to. It asks first, and control+Z undoes the reload.
- NVDA+shift+K then R also reloads at any time. Saving in Notepad does not count as a change.
- Notepad++ watches its files itself (File, Reload from Disk), so Code Compass leaves it to Notepad++.
Expand Down
1 change: 1 addition & 0 deletions samples/latihan.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# Latihan Code Compass. Buka di Notepad, lalu coba hal-hal di bawah ini.
# (Versi bahasa Inggris: practice.py.)
#
# Ctrl+Shift+Space (petunjuk parameter): taruh kursor di dalam kurung
# pemanggilan fungsi, misalnya di "15000" atau "diskon=10" pada baris
Expand Down
112 changes: 112 additions & 0 deletions samples/practice.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
# Code Compass practice file. Open it in Notepad and try the things below.
# (Indonesian version: latihan.py.)
#
# control+shift+space (parameter hint): put the caret on a call, for
# example on "calculate_total" or inside its parentheses in main, and
# press control+shift+space. Code Compass reads the parameters and
# which argument you are on. Try Shop("Corner Shop", ...) and
# shop.add_item(...) too.
# control+space: type "calc" on an empty line, then press control+space
# a few times.
# F12: with the caret on a called name such as "calculate_total", jump to
# where it is declared. control+alt+backspace takes you back.
# shift+F12: a list of every line that uses that name.
# F2: rename a name, for example "price" in calculate_total.
# alt+page down and alt+page up: move by function. alt+left arrow: to the
# function or class around it.
# control+shift+O: the outline. NVDA+shift+K, then F: the family of the
# function at the caret.
# control+alt+K: set a bookmark. control+alt+L and control+alt+J: jump
# between bookmarks.
# NVDA+shift+K, then shift+T: the to-do and fixme notes in comments.
# control+F5: run this file. control+S: save and check for problems.
# Want to hear the error sound? Delete any ")" and wait a second.


def calculate_total(price, quantity, discount=0):
"""Total price after a discount, in percent."""
gross = price * quantity
reduction = gross * discount / 100
return gross - reduction


def format_money(amount, with_symbol=True):
"""An amount as money text, for example 1234.5 -> "$1,234.50"."""
text = f"{amount:,.2f}"
return f"${text}" if with_symbol else text


class Item:
def __init__(self, name, price, stock=1):
self.name = name
self.price = price
self.stock = stock

def in_stock(self):
return self.stock > 0


class Shop:
"""A small shop with a list of items."""

def __init__(self, name, city, owner="Rafli"):
self.name = name
self.city = city
self.owner = owner
self.items = []

def add_item(self, name, price, stock=1):
item = Item(name, price, stock)
self.items.append(item)
return item

def find(self, word, in_stock_only=False):
found = []
for item in self.items:
if word.lower() in item.name.lower():
if in_stock_only and not item.in_stock():
continue
found.append(item)
return found

def report(self):
# TODO: sort the items from the most expensive
lines = [f"{self.name} in {self.city}, owned by {self.owner}"]
for number, item in enumerate(self.items, start=1):
status = "in stock" if item.in_stock() else "sold out"
lines.append(f" {number}. {item.name}: {format_money(item.price)} ({status})")
return "\n".join(lines)


def split_evenly(total, people):
"""Split a total between people; people must not be zero."""
try:
return total / people
except ZeroDivisionError:
# FIXME: tell the user with a clearer message
return 0


def main():
shop = Shop("Corner Shop", "Bandung", owner="Rafli")
shop.add_item("Arabica Coffee", 12.5, stock=3)
shop.add_item("Jasmine Tea", 4.75, stock=5)
shop.add_item("Palm Sugar", 3.2, stock=0)

print(shop.report())
print()

total = calculate_total(15, 3, discount=10)
print("Total:", format_money(total))
print("Each:", format_money(split_evenly(total, 2)))

for item in shop.find("tea", in_stock_only=True):
print("Found:", item.name)

# Remove the # on the line below to try an error when running
# (control+F5), then press F8 to go to its line.
# print(calculate_total(10, "two"))


if __name__ == "__main__":
main()
Loading