200 lines
7.1 KiB
Markdown
200 lines
7.1 KiB
Markdown
在打包后的命令中,配置文件 `config.ini` 可以有几种处理方式。我们处理配置文件的方法包括:
|
||
|
||
|
||
|
||
1. **将 config.ini 文件作为项目的一部分进行分发**:
|
||
|
||
确保配置文件在项目结构中的正确位置。
|
||
|
||
|
||
|
||
2. **在代码中指定配置文件的路径**:
|
||
|
||
通过代码确保应用程序能够找到并加载配置文件。
|
||
|
||
|
||
|
||
3. **提供默认配置文件**:
|
||
|
||
在缺失时创建配置文件,确保应用程序有初始配置。
|
||
|
||
|
||
|
||
### 详细步骤:
|
||
|
||
|
||
|
||
1. **项目目录结构**:
|
||
|
||
确保 `config.ini` 文件和应用程序的入口文件在同级目录中,如下所示:
|
||
|
||
```
|
||
|
||
llmclipboard/
|
||
|
||
├── llmclipboard/
|
||
|
||
│ ├── __init__.py
|
||
|
||
│ ├── app.py
|
||
|
||
├── config.ini
|
||
|
||
├── README.md
|
||
|
||
├── pyproject.toml
|
||
|
||
```
|
||
|
||
|
||
|
||
2. **在 `app.py` 中加载配置文件**:
|
||
|
||
修改 `load_config` 方法,确保程序能找到 `config.ini` 文件,通常可以使用相对路径或环境变量。
|
||
|
||
|
||
|
||
### 示例代码实现:
|
||
|
||
|
||
|
||
**项目目录结构**:
|
||
|
||
```
|
||
|
||
llmclipboard/
|
||
|
||
├── llmclipboard/
|
||
|
||
│ ├── __init__.py
|
||
|
||
│ ├── app.py
|
||
|
||
├── config.ini
|
||
|
||
├── README.md
|
||
|
||
├── pyproject.toml
|
||
|
||
```
|
||
|
||
|
||
|
||
**在 `app.py` 中加载配置文件**:
|
||
|
||
```python project/llmclipboard/app.py
|
||
|
||
import os
|
||
|
||
import time
|
||
|
||
import configparser
|
||
|
||
from pynput import mouse
|
||
|
||
import win32clipboard
|
||
|
||
import win32con
|
||
|
||
from html2text import html2text
|
||
|
||
import keyboard
|
||
|
||
import threading
|
||
|
||
import sys
|
||
|
||
import logging
|
||
|
||
|
||
|
||
class TextCaptureApp:
|
||
|
||
def __init__(self):
|
||
|
||
self.load_config()
|
||
|
||
self.running = True
|
||
|
||
self.last_right_click_time = 0
|
||
|
||
self.setup_logging()
|
||
|
||
|
||
|
||
def load_config(self):
|
||
|
||
"""Loads the configuration file."""
|
||
|
||
config = configparser.ConfigParser()
|
||
|
||
config_path = os.path.join(os.path.dirname(__file__), '..', 'config.ini')
|
||
|
||
|
||
|
||
if not os.path.isfile(config_path):
|
||
|
||
self.logger.error(f"配置文件未找到: {config_path}")
|
||
|
||
sys.exit(1)
|
||
|
||
|
||
|
||
config.read(config_path)
|
||
|
||
self.double_click_threshold = config.getfloat('Settings', 'double_click_threshold', fallback=0.3)
|
||
|
||
self.save_location = config.get('Settings', 'save_location', fallback=os.path.join(os.path.expanduser('~'), 'Desktop'))
|
||
|
||
self.copy_delay = config.getfloat('Settings', 'copy_delay', fallback=0.1)
|
||
|
||
|
||
|
||
def setup_logging(self):
|
||
|
||
logging.basicConfig(
|
||
|
||
filename='text_capture.log',
|
||
|
||
level=logging.INFO,
|
||
|
||
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
|
||
|
||
)
|
||
|
||
self.logger = logging.getLogger(__name__)
|
||
|
||
|
||
|
||
def save_to_markdown(self, content):
|
||
|
||
try:
|
||
|
||
timestamp = time.strftime("%Y%m%d_%H%M%S")
|
||
|
||
file_path = os.path.join(self.save_location, f'captured_text_{timestamp}.md')
|
||
|
||
|
||
|
||
with open(file_path, 'w', encoding='utf-8') as f:
|
||
|
||
f.write(content)
|
||
|
||
self.logger.info(f"Content saved to: {file_path}")
|
||
|
||
except Exception as e:
|
||
|
||
self.logger.error(f"Error saving file: {e}")
|
||
|
||
|
||
|
||
def get_clipboard_content(self):
|
||
|
||
try:
|
||
|
||
win32clipboard.OpenClipboard()
|
||
|
||
|
||
|
||
try:
|
||
|
||
content = win32clipboard.GetClipboardData(win32con.CF_HTML)
|
||
|
||
self.logger.info("Clipboard HTML content captured")
|
||
|
||
return html2text(content)
|
||
|
||
except:
|
||
|
||
pass
|
||
|
||
|
||
|
||
try:
|
||
|
||
content = win32clipboard.GetClipboardData(win32con.CF_TEXT)
|
||
|
||
self.logger.info("Clipboard TEXT content captured")
|
||
|
||
return content.decode('gbk')
|
||
|
||
except:
|
||
|
||
pass
|
||
|
||
|
||
|
||
try:
|
||
|
||
content = win32clipboard.GetClipboardData(win32con.CF_UNICODETEXT)
|
||
|
||
self.logger.info("Clipboard UNICODE TEXT content captured")
|
||
|
||
return content
|
||
|
||
except:
|
||
|
||
return None
|
||
|
||
|
||
|
||
except Exception as e:
|
||
|
||
self.logger.error(f"Error getting clipboard content: {e}")
|
||
|
||
return None
|
||
|
||
finally:
|
||
|
||
try:
|
||
|
||
win32clipboard.CloseClipboard()
|
||
|
||
except Exception as e:
|
||
|
||
self.logger.error(f"Error closing clipboard: {e}")
|
||
|
||
|
||
|
||
def simulate_copy(self):
|
||
|
||
keyboard.press('ctrl')
|
||
|
||
keyboard.press('c')
|
||
|
||
keyboard.release('c')
|
||
|
||
keyboard.release('ctrl')
|
||
|
||
time.sleep(self.copy_delay) # 等待复制操作完成
|
||
|
||
|
||
|
||
def on_click(self, x, y, button, pressed):
|
||
|
||
if not pressed:
|
||
|
||
return
|
||
|
||
|
||
|
||
if button == mouse.Button.right:
|
||
|
||
current_time = time.time()
|
||
|
||
if (current_time - self.last_right_click_time) < self.double_click_threshold:
|
||
|
||
self.simulate_copy()
|
||
|
||
content = self.get_clipboard_content()
|
||
|
||
if content:
|
||
|
||
self.save_to_markdown(content)
|
||
|
||
else:
|
||
|
||
self.logger.warning("No content captured from clipboard")
|
||
|
||
self.last_right_click_time = current_time
|
||
|
||
|
||
|
||
def on_keyboard_event(self, event):
|
||
|
||
# 监听Esc键退出程序
|
||
|
||
if event.name == 'esc':
|
||
|
||
self.running = False
|
||
|
||
return False
|
||
|
||
|
||
|
||
def run(self):
|
||
|
||
self.logger.info("Text Capture App started")
|
||
|
||
print("文本捕获程序已启动...")
|
||
|
||
print("使用说明:")
|
||
|
||
print("1. 选中要保存的文本")
|
||
|
||
print("2. 快速双击鼠标右键来保存选中的文本")
|
||
|
||
print("3. 按ESC键退出程序")
|
||
|
||
|
||
|
||
mouse_listener = mouse.Listener(on_click=self.on_click)
|
||
|
||
mouse_listener.start()
|
||
|
||
|
||
|
||
# 启动键盘监听
|
||
|
||
keyboard.on_press(self.on_keyboard_event)
|
||
|
||
|
||
|
||
# Wait until the running flag becomes False
|
||
|
||
while self.running:
|
||
|
||
time.sleep(0.1)
|
||
|
||
|
||
|
||
print("\n程序已退出")
|
||
|
||
mouse_listener.stop()
|
||
|
||
mouse_listener.join()
|
||
|
||
keyboard_listener.stop()
|
||
|
||
keyboard_listener.join()
|
||
|
||
self.logger.info("Text Capture App stopped")
|
||
|
||
|
||
|
||
def main():
|
||
|
||
try:
|
||
|
||
app = TextCaptureApp()
|
||
|
||
app.run()
|
||
|
||
except Exception as e:
|
||
|
||
logging.error(f"程序发生错误: {e}")
|
||
|
||
input("按Enter键退出...")
|
||
|
||
|
||
|
||
if __name__ == "__main__":
|
||
|
||
main()
|
||
|
||
```
|
||
|
||
|
||
|
||
### 其他注意事项:
|
||
|
||
- **配置文件路径**:在 `load_config` 方法中使用 `os.path` 来获取配置文件的路径,并确保路径的正确性。
|
||
|
||
- **默认配置**:如果配置文件丢失,可以选择在初始化时生成一个默认的配置文件,确保应用程序能够正常启动。
|
||
|
||
- **文档说明**:在 `README.md` 文件中添加关于如何找到和编辑 `config.ini` 文件的说明,以帮助用户自定义他们的配置。
|
||
|
||
|
||
|
||
通过以上步骤, `config.ini` 文件将在包安装过程中被正确识别,并能在应用程序运行时被读取和加载。 |