poc/project/llmclipboard/docs/captured_text_20241213_150437.md
2024-12-13 15:29:23 +08:00

7.1 KiB
Raw Permalink Blame History

在打包后的命令中,配置文件 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 中加载配置文件


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 文件将在包安装过程中被正确识别,并能在应用程序运行时被读取和加载。