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

怎么写一个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中的代码精简.
将就着看吧-_-!!!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容