实战:在 sublime text3 中开发一个 markdown 图片插入插件

常用的开发技巧

修改菜单:
sublime有个很爽的事就是通过创建 .sublime-menu 文件就可以修改菜单。配置文件需要根据要修改的菜单类型来命名:

  • Main.sublime-menu 控制了程序的主菜单
  • Side Bar.sublime-menu 控制侧边栏文件或者目录的右键菜单
  • Context.sublime-menu 控制处于编辑状态的文件右键菜单
  1. 新建插件
import sublime
import sublime_plugin

class ExampleCommand(sublime_plugin.TextCommand):
	def run(self, edit):
		# 0 代表文件起始位置,如果要在光标位置可改成:self.view.sel()[0].b
		self.view.insert(edit, 0, "Hello, World!")
  1. 绑定按键

在我们的插件目录下,创建: Default (Windows).sublime-keymapDefault (Linux).sublime-keymapDefault (OSX).sublime-keymap这3个文件。 分别对应着不同的操作系统。

实战

Markdown 中图片插件开发

开发文档整理时间: 2018/07/02 星期一

看了一个微信上的好友最近整理了一个关于打造自己『专属Markdown编辑器』的文档,看着感觉有些触发。 因为自己也是非常的喜欢 sublime 这种轻便的编辑器,但也很喜欢 typora 这种简单,快捷键很多,功能多样的 Markdown 编辑器。 由于在使用的过程中,发现在 sublime 的 Markdown Preview 插件中不支持快捷键和图形界面的方式的图片插入。同时希望在插入图片的过程中,将图片移动复制到相对路径下存储。插件开发的需求如下,

  1. 点击鼠标右键,进行图形化选择文件
  2. 自动将文件插入鼠标所在位置
  3. 移动图片文件到 Markdown 文件的同目录下,采用相对路径存储

整个过程的开发步骤如下:

在编辑器中 右键 中增加一个 “图片插入” 的选项

MarkDown Preview 的目录下新建一个 Context.sublime-menu 文件。 具体路径,为${Sublime install Package}/Data/Packages/python-markdown。 文件内容如下:

[
	 { "caption": "-", "id": "markdown" },
     { "command": "insert_pictrue", "caption": "图片插入" },
	 // { "caption": "-", "id": "end" }
]

添加上面代码之后,鼠标右键就可以看到

实战:在 sublime text3 中开发一个 markdown 图片插入插件_第1张图片

实现思路

查看官方的 API, 发现实现思路可能存在一些问题。 那就是,api 中并没有提供找出文件对话框的输入功能。 虽然,可以通过 view.run_command() 等运行命令,但是运行命令之后无法获得返回值。也就是说,我们虽然可以打开文件对话框,但是我们选中的文件对话框中的文件路径,我们是没有方法直接得到的。

失败的思路

  • 希望通过打开 文件对话框,获得文件路径

发现,sublime APi 并不提供通过文件对话框直接获得文件路径,本身自带的 open File,打开文件所在路径等提供对话框的功能好像都是通过内置的一些命令写出来的。 二次开发并不可以直接获得。

  • 希望通过打开文件之后,通过文件编辑提供的视图 view 对象的 veiw.file_name() 属性来获得文件路径

但是实验的过程发现,虽然 sublime 可以打开图片类型的文件,但是并不提供 veiw 视图,查看 Sheet 才发现 sublime 对图像只提供预览功能,并不提供编辑功能。 而 view 是只为能够编辑的文件的提供的『视图』。
官方 API 说明:

Represents a content container, i.e. a tab, within a window. Sheets may contain a View, or an image preview.

可行的方案

最好的老师就是官方 API

经过多次实验之后,总结出了一个可行的方案,方案思路如下:

  1. 通过 window.run_command(“prompt_open_file”) 命令,为我们提供一个文件对话框选项
  2. 选中文件,通过 sublime 打开文件
  3. 通过 window.sheets() 获得所有打开的文件,遍历所有的 Sheet 『视图』
  4. 找到图片类型的文件,所对应的 Sheet ,返回文件路径
  5. 移动到相对路径下

具体的使用过程如下:

实战:在 sublime text3 中开发一个 markdown 图片插入插件_第2张图片

详细代码如下,只需要文件名命名为 『insertPictrue.py』,放到 markdown 插件目录下即可使用。

import sublime
import sublime_plugin
import os.path
import sys
import shutil


# class ExampleCommand(sublime_plugin.WindowCommand):
class InsertPictrueCommand(sublime_plugin.TextCommand):
	def run(self, edit):
		# 获得当前编辑窗口对象
		window = self.view.window()
		# 当前文件名
		current_file_name = self.view.file_name()
		current_file_extension = window.extract_variables()["file_extension"]
		if(not current_file_extension in ["md"]):
			print("插入文件名不是 markdown 类型文件")
			return

		# 当前的 sheet
		current_sheet = window.active_sheet()
		# 打开对话框选择文件
		window.run_command("prompt_open_file",{"initial_directory":os.path.join("D:/User/Desktop")})


		# 查找文件,并且关闭
		file = None
		window = self.view.window()
		for sheet in window.sheets():
			# 强制切换到当前 sheet 否则,无法获取文件名
			window.focus_sheet(sheet)
			# 获取当前 sheet 的文件后缀
			file_extension = window.extract_variables()["file_extension"]
			if(file_extension in ["jpg","png","gif","bmp"]):
				file = window.extract_variables()["file"]
				file_base_name = window.extract_variables()["file_base_name"]
				window.run_command("close")

		if file and file_base_name:
			# 激活之前编辑的窗口
			window.focus_sheet(current_sheet)
			# 图片将要存储的目录
			dir_pic = self.getPicturePath(current_file_name)
			# 移动文件到相对目录下
			rel_path = self.movePicToRelPath(file,dir_pic)
			self.view.run_command("insert_snippet",
	            {
	                "contents": "![%s](%s)" % (file_base_name, rel_path) 
	            }
	        )

	def getPicturePath(self,file_path):
		# 获得文件名
		file_name = os.path.basename(file_path)
		# 文件夹名
		dir_name = os.path.dirname(file_path)
		# 图片存放在相对路径中,新建同名的文件夹+.assert
		dir_pic_name = file_name.replace(" ","_").replace(".md",".image")
		dir_pic = os.path.join(dir_name,dir_pic_name)
		# 如果不存在,则新建
		if(not os.path.exists(dir_pic)):
			os.mkdir(dir_pic)
		return dir_pic

	def movePicToRelPath(self,file_path, dist_dir_path):
		"""将图片移动到指定目录 文件 → 文件夹, 并且返回移动后的相对路径"""
		try:
			shutil.move(file_path, dist_dir_path)
			print("move file: ",file_path," → ",dist_dir_path)
		except Exception as e:
			print("存在相同文件")
			pass
		file_name = os.path.basename(file_path)
		dir_name = os.path.basename(dist_dir_path)
		return dir_name+"/"+file_name

原创文章,欢迎转载,转载请注明原作者和出处。

你可能感兴趣的:(Python学习,其它工具)