Skip to content

Instantly share code, notes, and snippets.

@Pinacolada64
Created December 6, 2024 00:07
Show Gist options
  • Save Pinacolada64/533e0e0ee2f12e51b5bcf1c6a1686471 to your computer and use it in GitHub Desktop.
Save Pinacolada64/533e0e0ee2f12e51b5bcf1c6a1686471 to your computer and use it in GitHub Desktop.
Terminal settings attempt
import random
from dataclasses import dataclass, field
from enum import Enum
class ClientSettingsNames(str, Enum):
NAME = "Name"
ROWS = "Screen rows"
COLUMNS = "Screen columns"
RETURN_KEY = "Return key"
TRANSLATION = "Character translation"
LINE_ENDING = "Line ending(s)"
# colors for [bracket reader] text highlighting on C64/128:
TEXT_COLOR = "Text color"
HIGHLIGHT_COLOR = "Highlight color"
BACKGROUND_COLOR = "Background color"
BORDER_COLOR = "Border color"
class KeyboardKeyName(str, Enum):
RETURN = "Return"
ENTER = "Enter"
BACKSPACE = "Backspace"
DELETE = "Delete"
@dataclass
class BaseTerminal(str, Enum):
NAME: str = None
HAS_TAB: bool = True # if False, use spaces instead of Tab (\t)
HAS_UNDERLINE: bool = True
RETURN_KEY: KeyboardKeyName = KeyboardKeyName.ENTER
class TranslationName(str, Enum):
PETSCII = "PetSCII"
ASCII = "ASCII"
ANSI = "ANSI"
class LineEnding(str, Enum):
CR = "\r"
LF = "\n"
CRLF = CR + LF
@dataclass
class UserSettings(Enum):
NAME: str
ROWS: int
COLUMNS: int
RETURN_KEY: KeyboardKeyName.ENTER
TRANSLATION: TranslationName
LINE_ENDING: LineEnding.CRLF
# '1' [ColorValue] or "white" [ColorName], possibly:
TEXT_COLOR: int | str
BACKGROUND_COLOR: int | str
BORDER_COLOR: int | str
def __str__(self):
print("in UserSettings.__str__")
return f"{self.name}: {self.value}"
"""@dataclass
class BaseCommodoreTerminal(BaseTerminal):
TRANSLATION: Translation.PETSCII
RETURN_KEY: KeyboardKeyName.RETURN
LINE_ENDING: LineEnding.CR
NAME: str = "Generic Commodore Client"
ROWS: int = 25
COLUMNS: int = 40
@dataclass
class CommodoreClient_40col(BaseTerminal):
NAME: str = "Commodore 64/128 (40 columns)"
class CommodoreClient_128_80col(BaseTerminal):
NAME: str = "Commodore 128 (80 columns)"
# https://www.commodore.ca/manuals/128_system_guide/app-i.htm
# underlining on the C-128 in 80 columns: Ctrl-B
HAS_UNDERLINE: True
HAS_TAB: True
COLUMNS: 80
"""
@dataclass
class TerminalSettings(Enum):
NAME: str
ROWS: int
COLUMNS: int
RETURN_KEY: KeyboardKeyName
TRANSLATION = "Character translation"
LINE_ENDING = "Line ending(s)"
# colors for [bracket reader] text highlighting on C64/128:
TEXT_COLOR = "Text color"
HIGHLIGHT_COLOR = "Highlight color"
BACKGROUND = "Background color"
BORDER = "Border color"
@dataclass
class Player(object):
client_settings: dict = field(default_factory=lambda: {
# setting.name: getattr(TerminalSettings, setting.name).value
setting.name: getattr(TerminalSettings, setting.name) # .value
for setting in TerminalSettings})
# @dataclass
# class Player(object):
# id_num: int = random.randrange(65_536)
# client_settings: dict = field(default_factory=lambda: {
# setting.name: getattr(UserSettings, setting.name).value
# for setting in TerminalSettings
# })
id_num: int = random.randrange(65_536)
if __name__ == '__main__':
player = Player()
# set client LineEnding to CR
# TODO: change strings to Enums, like this:
# player.client_settings[TerminalSettings.LINE_ENDING] = LineEnding.CR
player.client_settings["LINE_ENDING"] = LineEnding.CR
# set client Translation to PETSCII:
player.client_settings["TRANSLATION"] = TranslationName.PETSCII
# enumerate through TerminalSettings, display corresponding client_setting
print("Step 1:")
for k, setting_name in enumerate(TerminalSettings, start=1):
print(f"{k=}, {setting_name.value=} {player.client_settings[setting_name.name].value=}")
setting_name = setting_name.value
setting_value = player.client_settings.get(UserSettings[setting_name], "[Not set]")
# if setting_value is None:
# print("[Not set]")
if setting_name.key == TerminalSettings.LINE_ENDING:
print("Breakpoint")
# print(f"{k:2}. {v.value:.<30}: {player.client_settings.get(UserSettings, "[Not set]")}")
# FIXME: There has to be some way to access an Enum of strings here instad of this mess:
if TerminalSettings.LINE_ENDING == LineEnding.CR:
print("Carriage Return")
elif TerminalSettings.LINE_ENDING == LineEnding.LF:
print("Linefeed")
elif TerminalSettings.LINE_ENDING == LineEnding.CRLF:
print("Carriage Return/Linefeed")
# print Player.client_settings to ensure they got copied over:
print("Step 2:")
for k, v in enumerate(player.client_settings):
print(k, v.value)
for k, v in enumerate(TerminalSettings):
# get name of terminal setting:
setting_name = v.name
terminal_setting = v.value
user_setting = player.client_settings.get(terminal_setting, "[Not set]")
print(f"{k:2}: {terminal_setting:.<30}: {user_setting}")
# testing:
# Access default value for client:
# Use '.get' to handle possibly missing key:
user_setting = getattr(player.client_settings[terminal_setting], "[Not set]").value
print(f"{k:2}. {setting_name:.>20}: {user_setting}")
"""
Desired output:
1. Name...............: Commodore 64
2. Screen rows........: 25
3. Screen columns.....: 40
"""
@Pinacolada64
Copy link
Author

This basic code works thanks to Volca:

import logging
from dataclasses import asdict, dataclass, field
from enum import Enum

"""
Goal: to display a settings menu. The way I think it should work:

- Enumerate through Player atributes, get a key (LINE_ENDING)
- Get a key name common to both SettingString.LINE_ENDING (to display in the menu item) and SettingValue.LINE_ENDING
- Use that as a lookup in the Enum list?

### THIS WORKS ###
"""


class TerminalSettingString(str, Enum):
    # these are terminal settings strings to be displayed in menu
    NAME = "Name"
    LINE_ENDING = "Line ending(s)"
    SCREEN_ROWS = "Screen rows"
    SCREEN_COLS = "Screen columns"


class LineEnding(str, Enum):
    # for output() function:
    CR = "\r"
    LF = "\n"
    CRLF = CR + LF


@dataclass
class UserSetting:
    NAME: str | None = None
    LINE_ENDING: LineEnding = field(default_factory=lambda: LineEnding.CR)
    SCREEN_COLS: int = 40
    SCREEN_ROWS: int = 25


class LineEndingString(str, Enum):
    CR = "Carriage return"
    LF = "Linefeed"
    CRLF = CR + " + " + LF


@dataclass
class Player(object):
    # copy user settings:
    settings: UserSetting = field(default_factory=UserSetting)

    def show_player_settings(self):
        """
        e.g.,
           TerminalSettingsNames: UserSettings
        1. Screen rows..........: 25
        2. Screen columns.......: 40
        3. Name.................: Ryan
        4. Line ending(s).......: Carriage return
        """
        for k, v in enumerate(asdict(self.settings), start=1):
            user_setting = getattr(self.settings, v)
            """
            # TODO: fix display of line ending options:
            if isinstance(user_setting, LineEnding):
                logging.debug("%s" % user_setting)
                # FIXME: TerminalSettingString[player.settings.LINE_ENDING.value]
                print(TerminalSettingString[self.settings.LINE_ENDING])
            """
            print(
                f"{k}. {TerminalSettingString[v].value.ljust(20, '.')}: "
                # f"{getattr(self.settings, v)}"
                f"{user_setting}"
            )


if __name__ == "__main__":
    logging.basicConfig(level=logging.DEBUG, format='[%(levelname)s] | %(message)s')

    player = Player(settings=UserSetting(NAME="Ryan", LINE_ENDING=LineEnding.CR))
    player.show_player_settings()

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment