怎么写一个Sublime的插件(3)

作者: Floyda | 来源:发表于2015-11-01 19:39 被阅读621次

怎么写一个Sublime的插件(3)

现场直播, 和大家一起写一个Sublime的插件.

[TOC]

插件设计思路

我希望这个插件不用太多的快捷键, 就一个F1就可以了.

  • F1, 启动插件, 显示时间进度.
  • 在番茄时间内, F1切换(显示/隐藏)时间进度.
  • 时间到了, 提示一下.
  • 启动Sublime的时候, 判断上一个番茄时间是否结束.
    • Yes, Pass.
    • No, 继续计时.

什么是quick panel?

举个例子:

  • super + shift + p # Command Palette
  • super + r # Goto Symbol

安装插件, 设置格式, 定位函数, 行数跳转. . .
这些时候, 会出现一个黑色的框, 这个就是quick panel

.sublime-commands

  • ../packages/Example/新建一个文件Example.sublime-commands
[
    { "command": "new_tomato", "caption": "Example: New Pomodoro Time" },
    { "command": "show_tomato_progress", "caption": "Example: Show Status" },
    { "command": "hide_tomato_progress", "caption": "Example: Hide Status" },
]
  • 修改快捷键.
[
    { "keys": ["f1"], "command": "show_overlay", "args": {"overlay": "command_palette", "text": "Example: "} },
]

通过.sublime-commands文件, 添加自定义的command命令.
按F1, 打开quick panel, 默认输入文字Example:.
则会显示上面3条可选项.

super + shift + p, 再输入Example:, 效果一样.

插件中对应的写法

class NewTomatoCommand(sublime_plugin.TextCommand):

    def run(self, edit):
        tomato.start()

    def is_visible(self):
        return not tomato.is_actived()



class ShowTomatoProgressCommand(sublime_plugin.TextCommand):

    def run(self, edit):
        tomato.set_status_visiable(True)

    def is_visible(self):
         return tomato.is_actived() and not tomato.get_status_visiable()



class HideTomatoProgressCommand(sublime_plugin.TextCommand):

    def run(self, edit):
        tomato.set_status_visiable(False)

    def is_visible(self):
         return tomato.is_actived() and tomato.get_status_visiable()

Methods: is_visible
Return Value: bool
Description: Returns true if the command should be shown in the menu at this time. The default implementation always returns True.

代码全文


import sublime
import sublime_plugin
import os
import time


DELAY_TIME = 1
DEFAULT_TOMATO_TIME = 25
TICK_INTERVAL = 1
ENDING_WORDS = '快乐的时间总是过得特别快, 又到时间讲bye bye!'
CACHE_FILE_PATH = "/WorkTime.cache"
WORKTIME_SETTINGS = "WorkTime.sublime-settings"
TASK_FILE = "Floyda.wkt"

# ------------------------------------------------------------------------------
# Setting
# ------------------------------------------------------------------------------
class WorkTimeDo():
    def __init__(self):
        self.settings = sublime.load_settings(WORKTIME_SETTINGS)
        self.filename = sublime.packages_path() + CACHE_FILE_PATH

    def get_config(self, key, default):
        return self.settings.get(key,default)

    def say_ending(self):
        if sublime.platform() == "osx":
            os.popen('say ' + ENDING_WORDS)

    def save_time(self, time = None):
        try:
            fp = open(self.filename, "w+")
            fp.write(time)
            fp.close()
        except:
            sublime.error_message("Cann't save current time to local.")

    def load_time(self):
        try:
            fp = open(self.filename)
            time = fp.read()
            fp.close()
            return time
        except:
            fp = open(self.filename, "w+")
            fp.close()
            return None

    def clear_time(self):
        self.save_time('')

# ------------------------------------------------------------------------------
# Tomato
# ------------------------------------------------------------------------------
class Tomato(WorkTimeDo):

    def __init__(self):
        super(Tomato, self).__init__()
        self.total_time = self.get_config("tomato_time", DEFAULT_TOMATO_TIME) * 60
        self.counter = 0
        self.actived = False
        self.status_visiable = True
        self.check_last_time()

    def start(self, start_time = 0):
        self.counter = start_time
        self.actived = True
        # self.total_time = self.get_config("tomato_time", DEFAULT_TOMATO_TIME) * 60
        # self.total_time = 10
        self.save_time(str(time.time()))

    def stop(self):
        self.counter = 0
        self.actived = False
        self.clear_time()
        self.say_ending()
        sublime.message_dialog("Have a rest!")


    def update(self):
        self.counter += 1
        self.show_progress()
        if self.counter >= self.total_time:
            self.stop()

    def is_actived(self):
        return self.actived

    def set_status_visiable(self, flag):
        self.status_visiable = flag
        self.show_progress()
    
    def get_status_visiable(self):
        return self.status_visiable

    def show_progress(self):
        if self.status_visiable is False:
            sublime.status_message('')
            return

        progress = int(self.counter / self.total_time * 100)
        msg = "|" + \
            progress * "-" + \
            "o" + \
            (100 - progress) * "-" + \
            "|"

        sublime.status_message(msg)


    def check_last_time(self):
        last_time = self.load_time()
        try:
            last_time = float(last_time)
        except:
            self.clear_time()
            return

        cur_time = time.time()
        result = cur_time - last_time
        if result >= self.total_time:
            self.clear_time()
        else:
            self.start(int(result))



class Tick():

    def __init__(self):
        self.thread_flag = False

    def callback(self):
        if not self.thread_flag: return

        if tomato.is_actived():
            tomato.update()

        sublime.set_timeout_async(self.callback, 1000)

    def start(self):
        self.thread_flag = True
        self.callback()

    def stop(self):
        self.thread_flag = False


def delay():
    global tomato
    global tick
    tomato = Tomato()
    tick = Tick() 
    tick.start()

sublime.set_timeout_async(lambda:delay(), DELAY_TIME * 1000)
# ------------------------------------------------------------------------------
# Sublime Plugin
# ------------------------------------------------------------------------------
class NewTomatoCommand(sublime_plugin.TextCommand):

    def run(self, edit):
        tomato.start()

    def is_visible(self):
        return not tomato.is_actived()



class ShowTomatoProgressCommand(sublime_plugin.TextCommand):

    def run(self, edit):
        tomato.set_status_visiable(True)

    def is_visible(self):
         return tomato.is_actived() and not tomato.get_status_visiable()



class HideTomatoProgressCommand(sublime_plugin.TextCommand):

    def run(self, edit):
        tomato.set_status_visiable(False)

    def is_visible(self):
         return tomato.is_actived() and tomato.get_status_visiable()

-- Floyda --

因为边写插件, 边写Blog, 进度不一样, 很难把Blog中的代码精简.
将就着看吧-_-!!!

相关文章

网友评论

    本文标题:怎么写一个Sublime的插件(3)

    本文链接:https://www.haomeiwen.com/subject/rjhqhttx.html