Почему?

Я много писал. И в своих работах я использую временные метки, даты, время, временные диапазоны.

Я использую следующие форматы даты и времени

  • 2020–11–01
  • 15–18
  • 14:58

Для них я использовал пользовательские скрипты bash, которые копировали в буфер обмена нужные мне форматы даты. Эти сценарии были вручную добавлены в пользовательские ярлыки Linux.

Пример bash-скрипта:

#!/bin/sh
alias setclip='xclip -selection c'
alias getclip='xclip -selection clipboard -o'
printf $(date +"%Y-%m-%d") | setclip

Сначала я был очень доволен, но через некоторое время количество пользовательских скриптов увеличилось. У меня были трудности с их запоминанием.

Как?

Я наткнулся на Ulauncher и меня поразило, что я могу создать расширение для этих скриптов timedate.

Для тех, кто не знает, Ulauncher — это лаунчер приложений, к которому многие разработчики пишут множество расширений.

Некоторые примеры:

  • расширение эмодзи
  • процесс убийца
  • переводчик Google
  • спотифай плеер

Вот учебник ссылка для разработки расширения.

О моем расширении

Ulauncher требует, чтобы расширение имело manifest.json файла для работы.

Пример manifest.json

{
  "required_api_version": "^2.0.0",
  "name": "Timestamp macros",
  "description": "Copy to clipboard the most used timedate formats",
  "developer_name": "Nurgazy Nazhimidinov",
  "icon": "images/icon.png",
  "options": {
    "query_debounce": 0.05
  },
  "preferences": [
    {
      "id": "time_kw",
      "type": "keyword",
      "name": "Timemacros",
      "default_value": "tm"
    }
  ]
}

В нем говорится, что если вы напишете ключевое слово Timemacros, расширение будет на панели запуска (ВНИМАНИЕ не нажато).

если вы напишете Timemacros и нажмете

or

напишите tm и SPACE, тогда будет вызван KeywordQueryEventListener(EventListener).

Вот код:

class DemoExtension(Extension):
    def __init__(self):
        super(DemoExtension, self).__init__()
        self.subscribe(KeywordQueryEvent, KeywordQueryEventListener())
class KeywordQueryEventListener(EventListener):
    def on_event(self, event, extension):
        items = []
        logger.info('preferences %s' % json.dumps(extension.preferences))
        logger.info(event.get_keyword()) # gives the keyword 'tm'
        items.append(ExtensionResultItem(icon='images/icon.png',
                                         name='YYYY-MM-DD',
                                         description='{0:%Y-%m-%d}'.format(datetime.datetime.now()),
                                         on_enter=CopyToClipboardAction('{0:%Y-%m-%d}'.format(datetime.datetime.now()))))
        items.append(ExtensionResultItem(icon='images/icon.png',
                                         name='HH:mm',
                                         description='{0:%H:%M}'.format(datetime.datetime.now()),
                                         on_enter=CopyToClipboardAction(
                                             '{0:%H:%M}'.format(datetime.datetime.now()))))
        items.append(ExtensionResultItem(icon='images/icon.png',
                                         name='YYYY-MM-DD HH:mm',
                                         description='{0:%Y-%m-%d %H:%M}'.format(datetime.datetime.now()),
                                         on_enter=CopyToClipboardAction(
                                             '{0:%Y-%m-%d %H:%M}'.format(datetime.datetime.now()))))
        return RenderResultListAction(items)

if __name__ == '__main__':
    DemoExtension().run()

Как видите, KeywordQueryEventListener(EventListener) и on_event запускаются, а RenderResultListAction(items) возвращается и представляется пользователю.

Наш items будет

  • ГГГГ-ММ-ДД
  • HH:mm
  • ГГГГ-ММ-ДД ЧЧ:мм

Вот скриншот предметов:

Код товара:

items.append(ExtensionResultItem(icon='images/icon.png',
                                         name='YYYY-MM-DD',
                                         description='{0:%Y-%m-%d}'.format(datetime.datetime.now()),
                                         on_enter=CopyToClipboardAction('{0:%Y-%m-%d}'.format(datetime.datetime.now()))))

Пояснение к ExtensionResultItem:

name - заголовок показывается пользователю, смотрите скриншот выше

description - подтекст, который также показывается пользователю, смотрите скриншот выше

on_enter - самая важная часть, говорит, что делать, если пользователь нажимает на этот элемент. В моем случае это действие CopyToClipboardAction, которое копирует данные в буфер обмена.

Резюме

В конце концов, я разработал расширение, которое позволило мне отказаться от моих пользовательских сценариев bash и забыть о сочетаниях клавиш для них.

Исходный код на Github

Устаревшие скрипты bash 😄

Из личного блога: https://www.nurgasemetey.com/2020/extension-ulauncher/