UltraBlog.vim v3.4.0: 正則表達式、批量替換和調試模式

| Comments

這次的更新主要引入了支持正則表達式的全文檢索、批量替換和調試模式。

正則表達式

我一直覺得原來的全文檢索有一個遺憾,雖然可以通過多個關鍵詞實現較為精確的查詢,但還是不如正則表達式靈活和精確。

這是個蓄謀已久的需求,但直到真正做起來,才發現很多有意思的東西。雖然SQLite3提供支持正則表達式查詢的“REGEX”關鍵詞,但並沒有實際實現這個功能,而是需要寫程序實現並在數據庫接口中註冊這個函數:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import sqlite3

conn = sqlite3.connect('/tmp/your-database-file.db')

# 使用正則表達式匹配給定內容的函數,返回布爾類型
def regexp_search(expr, item):
    """Check if the item has a sub-string which matches the expr"""
    reg = re.compile(expr)
    return reg.search(item) is not None

# 在數據庫中註冊這個函數
conn.create_function('REGEXP', 2, regexp_search)

cur = conn.execute('select id,title from post where content REGEXP ?', '\babc\b')
row = cur.fetchone()
print row

conn.close()

在SQLAlchemy中具體的實現方式是:

1
2
3
4
5
6
7
8
9
# 註冊函數
dbe = sqlalchemy.create_engine("sqlite:///tmp/your-database-file.db")
conn = dbe.connect()
conn.connection.create_function('REGEXP', 2, regexp_search)

# 在SQL Expression Language中創建查詢條件
tbl = Post.__table__
cond_1 = tbl.c.title.op('regexp')(r'\babc\b')
cond_2 = tbl.c.content.op('regexp')(r'\babc\b')

和普通的全文檢索一樣,正則表達式的全文檢索也支持使用多個表達式作為查詢條件,多個條件之間是與的關係。現在可以這樣查詢所有包含“UltraBlog.vim”但不把推廣代碼算在內的文章了:

1
:UBRegexSearch [^\[]UltraBlog\.vim[^\]]

批量替換

在我換過新域名後,我就覺得這個功能很有必要了:

1
:UBReplace https://sinolog.it https://0x3f.org

包含第一個參數內容並被替換的文章數目會顯示在Vim的命令輸出緩衝區中。

有了前面實現全文檢索支持正則表達式的嘗試,再實現支持正則表達式的批量替換就容易多了:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 轉換字符串成raw格式的函數
def raw(text):
    """Returns a raw string representation of text"""
    escape_dict={'\a':r'\a', '\b':r'\b', '\c':r'\c', '\f':r'\f', '\n':r'\n',
               '\r':r'\r', '\t':r'\t', '\v':r'\v', '\'':r'\'', '\"':r'\"',
               '\0':r'\0', '\1':r'\1', '\2':r'\2', '\3':r'\3', '\4':r'\4',
               '\5':r'\5', '\6':r'\6', '\7':r'\7', '\8':r'\8', '\9':r'\9'}
    return "".join([escape_dict.get(char,char) for char in text])

# 使用正則表達式替換字符串的函數
def regex_replace(string, expr, repl):
    """Do substitutions on the string for repls matching the expr"""
    r = re.compile(raw(expr))
    return r.sub(repl, string)

# 在數據庫中註冊這個函數
conn.connection.create_function('regex_replace', 3, regex_replace)

# 在SQL語句中使用這個函數
sql_replace = "update post set title=regex_replace(title,:needle,:replacement),content=regex_replace(content,:needle,:replacement)"
conn.execute(sql_replace, {'needle':r'\babc\b', 'replacement':'xyz'})

最終,這個命令是這樣的:

1
:UBRegexReplace \babc\b xyz

實現批量替換容易,但要解決由此引出的一個問題就費周折了,就是批量替換過文章內容後怎樣和博客同步的問題,現在我還沒有好的想法,留作以後實現。

調試模式

開啟調試模式可以將所有被執行的SQL語句顯示在Vim的命令輸出緩衝區中,在有異常拋出時,也可以顯示堆棧信息。由於開啟調試模式既不需要修改代碼,也不需要重啟Vim,這可以極大地方便開發時對UltraBlog.vim的調試,也能使用戶提交問題時能反饋更多更詳細的信息。

以下三個命令用於控制調試模式的開啟狀態:

  • :UBEnableDebug
  • :UBDisableDebug
  • :UBToggleDebug

其它內容

本次更新的內容如下:

  • Feature: Add the command :UBRegexSearch, doing full-text searches with regular expressions !
  • Feature: Add the command :UBReplace, doing full-text substitutions.
  • Feature: Add the command :UBRegexReplace, doing full-text substitutions with regular expressions.
  • Feature: Add commands :UBEnableDebug, :UBDisableDebug, :UBToggleDebug and an option ub_debug. In debug mode, SQL statements and stack traces of exceptions will be displayed.
  • Change: Undo keywords highlighting after executing :UBList.
  • Bugfix: Exceptions raised when opening the current item under cursor in item lists if the option ub_hotkey_save_current_item has not been set. Now this options comes with a default value.

關於UB的詳細信息在這裡

Posted via UltraBlog.vim.

Comments