Skip to content

afrim-py is a python bindings for library, helping to build input method applications using python.

License

Notifications You must be signed in to change notification settings

fodydev/afrim-py

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

5 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

afrim-py

Python bindings for the afrim ime engine.

Python Rust License Changelog

Built with πŸ¦€πŸ by @esubaalew

About

afrim-py provides Python bindings for the powerful afrim input method engine, enabling developers to build sophisticated input method applications in Python. This project brings the capabilities of the Rust-based afrim engine to the Python ecosystem through PyO3 bindings.

πŸ”‹ Features Included

  • Preprocessor - Advanced key sequence processing and input transformation
  • Translator - Dictionary-based text translation with multiple candidates
  • TOML Support - Easy configuration through TOML files
  • Unicode Support - Full support for international characters
  • Rhai Scripting - Dynamic translation scripts (when rhai feature is enabled)
  • String Similarity - Fuzzy matching with strsim feature

Installation

afrim-py is available on pypi.

pip install afrim-py

Usage

Basic Example

from afrim_py import Preprocessor, Translator, Config

# Configure the preprocessor with key mappings
preprocessor_data = {
    "a1": "Γ ",
    "e1": "Γ©", 
    "u1": "ΓΉ",
    "hello": "hi"
}

# Configure the translator with dictionary
translator_dict = {
    "hello": ["hi", "hey", "greetings"],
    "world": ["earth", "globe", "planet"],
    "python": ["snake", "programming language"]
}

# Create instances
preprocessor = Preprocessor(preprocessor_data, buffer_size=64)
translator = Translator(translator_dict, auto_commit=True)

# Process keyboard events
changed = preprocessor.process("h", "keydown")
changed = preprocessor.process("e", "keydown") 
changed = preprocessor.process("l", "keydown")
changed = preprocessor.process("l", "keydown")
changed = preprocessor.process("o", "keydown")

# Get the processed input
current_input = preprocessor.get_input()  # "hello"

# Translate the input
translations = translator.translate(current_input)
print(translations)
# [{'texts': ['hi', 'hey', 'greetings'], 'code': 'hello', 'remaining_code': '', 'can_commit': True}]

# Process commands from the queue
while True:
    command = preprocessor.pop_queue()
    if command == "NOP":
        break
    print(f"Command: {command}")

Configuration

from afrim_py import Config
import json

# Configuration file `config.toml`
'''
[core]
buffer_size = 64
auto_capitalize = false
auto_commit = false
page_size = 10

[data]
a1 = "Γ "
e2 = "Γ©"

[translators]
datetime = { path = "./scripts/datetime.toml" }

[translation]
hi = 'hello'
'''
config = Config('config.toml')

# Use the configuration
preprocessor_data = config.extract_data()
preprocessor = Preprocessor(preprocessor_data, 64)
translator_dict = config.extract_translation()
translator = Translator(translator_dict, True)

Advanced Usage with Command Processing

import asyncio
from afrim_py import Preprocessor, Translator, Config

class InputMethodEngine:
    def __init__(self, config_file: str):
        config = Config(config_file)
        self.preprocessor = Preprocessor(config.extract_data(), 64)
        self.translator = Translator(config.extract_translation(), True)
        self.running = False
    
    async def process_commands(self):
        """Process commands from the preprocessor queue"""
        while self.running:
            command = self.preprocessor.pop_queue()
            
            if command == "NOP":
                await asyncio.sleep(0.01)  # Small delay
                continue
                
            # Handle different command types
            if isinstance(command, dict):
                if "Insert" in command:
                    text = command["Insert"]["text"]
                    print(f"Insert: {text}")
                elif "Delete" in command:
                    count = command["Delete"]["count"]
                    print(f"Delete: {count} characters")
            else:
                print(f"Command: {command}")
    
    def handle_key_event(self, key, state="keydown"):
        """Handle keyboard events"""
        changed = self.preprocessor.process(key, state)
        
        if changed:
            current_input = self.preprocessor.get_input()
            if current_input:
                translations = self.translator.translate(current_input)
                return translations
        return []
    
    def commit_text(self, text):
        """Commit selected text"""
        self.preprocessor.commit(text)
    
    async def start(self):
        """Start the input method engine"""
        self.running = True
        await self.process_commands()
    
    def stop(self):
        """Stop the input method engine"""
        self.running = False

# Usage
async def main():
    ime = InputMethodEngine(
        preprocessor_data={"A": "α‹•", "Aa": "α‹“", "C": "ጭ"},
        translator_dict={"Atarah": ["α‹“αŒ£αˆ«"], "Adiel": ["α‹“α‹²α‹”αˆ"]}
    )
    
    # Simulate key events
    translations = ime.handle_key_event("A")
    translations = ime.handle_key_event("a")
    translations = ime.handle_key_event("C")
    
    print("Translations:", translations)
    
    # Commit text
    if translations:
        ime.commit_text(translations[0]["texts"][0])

# Run the example
# asyncio.run(main())

Development

Build requirements

  • Rust 1.70+

  • Cargo

  • Python 3.8+ and and maturin

  • uv (optional)

Build from source

To simplify the development, we recommend to use uv.

Using maturin

# Clone the repository
git clone https://github.com/fodydev/afrim-py.git
cd afrim-py

# Create virtual environment
python -m venv .venv
source .venv/bin/activate  # On Windows: .venv\Scripts\activate

# Development build
maturin develop

# Release build
maturin build --release

# Build wheel
maturin build --interpreter python

Using uv

# Clone the repository
git clone https://github.com/fodydev/afrim-py.git
cd afrim-py

# Prerelease build
uv build --prerelease

# Release build
uv build

Testing

The project includes tests that represent a real user scenario:

# Run all tests
python -m pytest tests/ -v

Contributing

Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.

Acknowledgments

  • afrim-js - Web bindings that inspired this project

License

Licensed under the MIT LICENSE.

About

afrim-py is a python bindings for library, helping to build input method applications using python.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 2

  •  
  •