Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Clipboard Interactions and User Input Suggestions #5

Open
wants to merge 17 commits into
base: main
Choose a base branch
from

Conversation

teleprint-me
Copy link
Collaborator

In this PR, I've been drafting Clipboard Interactions and User Input Suggestions to the project using Pyperclip for clipboard management and regular expressions for extracting code snippets from messages.

Key Features:

  • Added custom key bindings for copying messages or code snippets to the clipboard using Pyperclip.
  • Implemented regular expressions to extract and copy only code snippets from messages using Pyperclip.
  • Added AutoSuggestFromHistory to provide input suggestions based on past entries when using the user input suggestions feature.

Technical Details:

  • Added Pyperclip dependency for clipboard management using pip install Pyperclip.
  • Implemented PyperclipClipboard class for Pyperclip integration.
  • Implemented regular expression pattern matching using re module and re.compile() method for extracting code snippets from messages using Pyperclip.
  • Implemented AutoSuggestFromHistory functionality using history module for providing input suggestions based on past entries.

Goal:

This PR is an opportunity to experiment and draft how we could implement Clipboard Interactions and User Input Suggestions to the project using Pyperclip for clipboard management and regular expressions for extracting code snippets from messages.

This also provides us with the opportunity to plan out and design custom key bindings for copying messages or code snippets to the clipboard.

These features should make using the project more convenient and efficient for users.

- Create a new ChatHistory class that encapsulates the chat history data and provides methods for loading and saving the data
- Use an instance of the ChatHistory class to manage the chat history data in the ConChat class.
- Add a new chat_history argument to the argparse options, which allows you to specify the file path to the chat history data. If this argument is specified, the ChatHistory instance will be initialized with the data from the file.
- Remove the session attribute and replace it with the chat_history attribute in the ConChat class.

This commit refactors the code to make it more modular and easier to use. The new ChatHistory class encapsulates the chat history data and provides methods for loading and saving the data, which makes the code more organized and maintainable.
- Update constructor to accept Path and str instances for file_path and system_message.
- Add error checking for the file_path parameter in the chathistory class constructor, setting a default file history path based on the chat session file path if no path is given by the user.
- Rename method read() to load() for better clarity.
- Add error handling for specific exceptions (FileNotFoundError, json.JSONDecodeError, and TypeError) in both load() and save() methods.
- Replace a hard-coded path with a dynamic default path if no path is given by the user in the PromptSession constructor within the chathistory class.

These changes improve your code's readability, maintainability, and robustness
- Update `chathistory` class to store messages as a list of dictionaries instead of a simple list.
- Each dictionary represents a message with its associated role and content.
- Add new method `replace(index: int, content: str)` in `chathistory` for updating the content of a message at a given index.
- Add new method `_render_messages_once_on_start()` method in `conchat` to load and render chat history messages upon
- Replaced direct file path handling with session name-based management for chat history
- Renamed `chathistory` class to `ChatHistory` for consistency with Python naming conventions
- Updated argument parsing to use session names instead of file paths, including changing flags and defaults
- Enhanced error handling in `ChatHistory.load()` to automatically create a new file if missing
- Adjusted `conchat` class constructor to accept `ChatHistory` instance, reflecting class name change
- Streamlined command-line interface and improved user feedback with clearer messages and defaults

These changes make the chat history management more intuitive and robust, reducing user effort and potential errors.
- Implemented custom key bindings for copying the last message or code snippets to the clipboard.
- Integrated PyperclipClipboard for system-wide clipboard access.
- Utilized regular expressions to extract and copy only code snippets from messages.
- Added AutoSuggestFromHistory to provide input suggestions based on past entries.
- Updated the prompt method to include new key bindings in the instructions for improved user guidance.
- Maintained separation of concerns by isolating key bindings functionality, with notes on future extensibility.

This update introduces intuitive clipboard interactions and auto-suggestions, significantly improving the user experience by streamlining message copying and offering suggestions based on chat history.
@teleprint-me teleprint-me added enhancement New feature or request help wanted Extra attention is needed labels Feb 22, 2024
@teleprint-me teleprint-me self-assigned this Feb 22, 2024
@teleprint-me teleprint-me marked this pull request as draft February 22, 2024 03:53
@teleprint-me teleprint-me marked this pull request as draft February 22, 2024 03:53
Copy link
Owner

@qnixsynapse qnixsynapse left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it is better to move ChatHistory class to its own file ChatHistory.py to keep track of future changes. We can import it as a library in the main rich-chat.py.

@teleprint-me
Copy link
Collaborator Author

I'll do this either later tonight or tomorrow. I'm in the middle of a few personal projects and I just started working again, still trying to get back into the swing of things. Moving the source code to a new module is trivial.

Maybe think about making source a proper package by adding an __init__.py and renaming it to rich_chat? I think we should do this in a separate PR once we merge this PR and iron out the basics.

What do you think?

@qnixsynapse
Copy link
Owner

Interesting. I already did this on my PC. Yes sure because we will have different modules.

qnixsynapse and others added 3 commits February 25, 2024 15:17
- Rename package directory from 'source' to 'rich_chat' for proper naming conventions
- Improve organization and separation of concerns in the codebase
- Create a separate 'chat_history.py' module for the `ChatHistory` class
- Move helper function 'keybinding' from 'rich-chat.py' to 'chat_history.py'
- Move `ChatHistory` class from 'rich-chat.py' to 'chat_history.py' and remove unused imports in 'rich-chat.py'
- Add import statement for 'ChatHistory' in 'rich-chat.py'
- Rename package directory for proper naming conventions
- Improve organization and separation of concerns
- Consolidate related functionality into separate modules
@teleprint-me
Copy link
Collaborator Author

Interesting. I already did this on my PC.

Okay. I bit the bullet.

It's the same as before, with the difference that it's a executable module, e.g.

python -m rich_chat.rich-chat --help

I've also given some thought to the naming convention for the "rich_chat" module, and I think following the Python convention of using an underscore (_) for library modules would be a good idea for consistency. This means renaming the current "rich-chat.py" file to something like "rich_chat.py" or "rich_chat_cli.py".

Here's how we could run the module as an executable using this new naming convention:

python -m rich_chat.rich_chat_cli --help

The decision on which naming convention to use depends.

Alternatively, we could use __main__.py for the entry point file, but that would require encapsulating all packages and modules within the package structure. This approach has its own set of pros and cons, such as increased complexity and better encapsulation.

- Rename 'rich_chat.py' to 'rich_chat_cli.py' following Python library naming conventions
- Add shebang line to rich_chat_cli.py for easier execution as a script

This commit refactors the codebase by renaming the main 'rich_chat.py' file to 'rich_chat_cli.py' following Python library naming conventions.
… a `@property`

- Replace `key_bindings()` function with a new `@property` named `key_bindings`.
- Update the `key_bindings` property to include new arguments for the index of the message to be copied.
- Update the custom `prompt` message to reflect these changes and include minor formatting improvements.
@teleprint-me teleprint-me marked this pull request as ready for review March 2, 2024 18:30
@teleprint-me
Copy link
Collaborator Author

I think this is a good checkpoint for the current implementation.

The introduced keybindings are designed to minimize conflicts with commonly used shortcuts, offering a straightforward way for users to interact with past messages, especially for yanking text:

  • ctrl + s: Initiates control selection.
  • ctrl + s a: Selects all text from a message.
  • ctrl + s s: Specifically selects code snippets within a message.

For instance, ctrl + s s 1 would copy a code snippet from the most recent message into the clipboard, assuming a snippet exists. To extract from specific messages, users can easily adjust the trailing digit, such as ctrl + s s 3 for a snippet from the third most recent message. Similarly, ctrl + s a 1 would copy the entirety of the most recent message.

This setup is admittedly basic and could benefit from refinement. It's a starting point, enabling some level of functionality while we explore other approaches.

I'm open to feedback, particularly any ideas to enhance usability or introduce more intuitive interactions.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request help wanted Extra attention is needed
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants