Language

Showing posts with label emacs. Show all posts
Showing posts with label emacs. Show all posts

Saturday, February 2, 2013

如何在 GNU Emacs 減少按鍵次數並提升工作效率


GNU Emacs 是一個非常 powerful 的編輯器, 這個就不需要我多作介紹, 但是與 vim 相比, GNU Emacs 有一個比較大的缺點就是按鍵多。只要是採用 modeless 的方式編輯, 又要功能多, 按鍵數很難減少, 但是還是有一些方法, 可以讓我們整體的按鍵數量變少的, 可以減少手的傷害。至於那些買了青軸機械式鍵盤之後, 想辦法多打字讓別人聽按鍵聲音的, 就不在本文的討論範圍內。

GNU Emacs 有兩種方式減少打字數目, 筆者認為值得推薦, 一種是用巨集(macro), 另一種是用 skeleton 套件。當然還有第三種是編寫 Emacs Lisp, 寫點函數, 這個難度比較高, 不太適合初學者。今天筆者介紹的這兩個方式都很適合初學者使用。

Table of Contents


巨集

首先, 我們來看看巨集。要知道 EMACS 這個名字是由 Editing MACroS 來的, 巨集可是 Emacs 的核心價值啊!只要你發現你在做重複性的工作, 就可以把那些一連串的按鍵動作變成巨集。
定義巨集很簡單, 在你的一連串按鍵動作開始之前, 先輸入 C-x (, 然後就開始按照平常的動作按按鍵, 按完所有按鍵之後, 鍵入 C-x ) 就完成巨集的定義了。
要執行剛剛定義完的巨集, 就按 C-x e, 也可以配合 Emacs 的數字前置指令來執行多次的巨集。比如說你想要執行這個巨集四次, 就鍵入 M-4 C-x e 就會執行這個巨集四次。
The quick brown fox jumps over the lazy dog

比方說, 你想要把上面這個檔案改成一個英文單字一行, 可以用巨集來做, 方法如下:
按鍵動作
C-x (開始錄製巨集
M-f把游標往前移一個單字
C-d刪除一個字元
[ENTER]插入換行字元
C-x )結束巨集的錄製

上述的巨集可以讓一個單字單獨存在於一行, 把剩下的文字換到下一行去, 如果要把所有英文單字都單獨存在於一行, 就需要重複作這個巨集。可以先用 M-x count-words-region 來計算這一行的單字數, 九個。所以要處理完所有的單字, 就輸入按鍵 M-9 C-x e, 不過通常我們錄製巨集的時候已經先做完一遍了, 那這時候你只需要執行 8 次就好。執行完結果就會如下所示:
The
quick
brown
fox
jumps
over
the
lazy
dog



Skeleton




如果你的重複性工作, 是經常性的使用到, 比方說寫函數時的註解, 常常需要寫函數名稱、作者、建立的時間等等資訊, 有些是每次都寫一樣的資訊(如作者), 有些則可以由函數執行結果得來(如日期), 有些需要打兩次一樣的字串(如函數名稱), 那麼 skeleton 就是一個不錯的工具, 讓你減少打字數目。


使用 skeleton 的方法如下:

(define-skeleton your-skeleton-name
  "String to describe this skeleton."
  "String that will be inserted when you call your-skeleton")



然後你就可以用 Emacs Lisp 函數一樣的呼叫方式來呼叫:
M-x your-skeleton-name 這函數就會自動從游標位置插入預先定義好的字串。
高階一點的用法就會牽扯到

  • 使用者輸入字串

    • 使用 (skeleton-read)

  • 重複使用者輸入的字串

    • 使用 v1, v2 變數

  • 游標最後所處位置

    • 使用 "_" 來標示

  • 呼叫 Emacs Lisp 函數來插入字串

    • 直接呼叫


筆者就用我自己用的一個例子來說明 skeleton:
; Skeleton for assembly subroutine header
(define-skeleton insert-asm-header
  "Prompt for subroutine name and insert assembly subroutine header"
  "" ?\n
  ";******************************************************************************" ?\n
  "; Name:\t\t" (setq v1 (skeleton-read "Subroutine name: "))?\n
  "; Purpose:" ?\n
  ";   " (skeleton-read "Purpose: ") ?\n
  "; Method:\t" ?\n
  ";   " ?\n
  "; Parameters:\t\t" (skeleton-read "Parameters: ") ?\n
  "; Affected regs:\t" ?\n
  "; Author:\tAlbert Chun-Chieh Huang, " (insert-current-date) ?\n
  ";******************************************************************************" ?\n
  v1 \n
  "" _ \n
  "rts" \n
  )



定義完之後, 我們就可以用 M-x insert-asm-header 來呼叫這個 skeleton, 呼叫之後, 在 mode line 會出現
Subroutine name: 



要求使用者輸入副程式名稱, 除了馬上把這名稱字串放到 "Name:" 之後, 並且存在 v1 這個變數裡。 接下來會要求使用者輸入 Purpose: 說明這個副程式的用途, 並把副程式用途就插入 (skeleton-read "Purpose: ") 的位置上。接下來的 Parameters: 也一樣。到了 Author 的地方就呼叫 Emacs Lisp 函數 (insert-current-date) 把日期填上。
在倒數第四行的 v1 就是把剛剛存在 v1 這個變數的副程式名稱取代 v1 填上去。
倒數第三行的 "_" 就是指示 skeleton 插入完這些字串之後, 游標要回到這個位置來。
所有被雙引號包起來的都是字串, 不會有特殊意義。在雙引號以外的, 就是 Emacs Lisp 函數、變數、或是特殊字元。=\n= 是換行並且依照所處的 mode 縮排, 而 ?\n 則只有單純的換行字元而已。


下面的例子就是執行完後的結果, 游標會停在倒數第二行, 與 rts 同樣的縮排位置上, 方便我打第一個 instruction.
;******************************************************************************
; Name:         Test
; Purpose:
;   Test
; Method:       
;   
; Parameters:           a1
; Affected regs:        
; Author:       Albert Chun-Chieh Huang, 02 February 2013
;******************************************************************************
Test
        
        rts


如果對於 skeleton 想要有更深入的了解, 可以按 C-h f skeleton-insert, 裡面有關於 define-skeleton 的字串該怎麼寫的詳盡說明。






結語




要提升工作效率, 第一要件就是先找出重複的工作, 並且用快速有效率的方法執行這個工作。當你找出重複性的部份之後, 可以把重複不變的部份抽出來變成巨集, 如果有經常性的重複編輯工作, 就可以考慮用 skeleton 來定義, 如果有每一次呼叫變動的部份, 就考慮把這些變動用呼叫函數或是輸入參數的方式來引入, 如此就可以有效的減少按鍵次數, 並且提升工作效率。



--
Albert Huang
Chun-Chieh Huang(黃俊傑)

Sunday, October 28, 2012

Emacs Wiki 簡易使用指南

這是我之前發表在 Newzilla 線上雜誌上的文章,不確定能否直接轉錄回我的 blog,先用連結吧。

點進去看吧

Emacs Wiki 後一章 -- 專案、遠端連線與註腳模式


原文撰寫於 2005 年 3 月 2 日,本來是接受某線上雜誌邀稿,該雜誌因故停刊,故未刊出,這其實只是草稿而已,我也懶得改寫了。

黃俊傑 jjhuang AT cm-nctu-edu-tw

前言

上一期中, 我們學習了如何用 Emacs Wiki 來快速產生網頁, 本期我們將會介紹 Emacs Wiki 相關的工具; 使用 Emacs Wiki 的專案功能來管理不同的網頁, 將網頁傳到遠端的網頁伺服器上, 以及使用 Emacs 內建的註腳次要模式(footnote-mode) 來幫助我們輸入註腳。

Emacs Wiki 專案

如果你像筆者這樣有好幾個獨立的 Wiki 要編輯, 那麼你很可能需要使用到 Emacs Wiki 專案來管理這些檔案。 新增專案的方法如下,首先你要先進入 Emacs 的 customization
M-x customize-group  emacs-wiki 
然後再進入 Emacs Wiki Project 這個目錄, 進入之後把 Emacs Wiki Projects 這個變數打開來。 一開始 Emacs Wiki 是沒有任何專案的, 只有 default 這個專案, 而這個專案是沒有列在這個變數中。 若要新增一個專案, 首先要按 INS 這個按鈕, 然後輸入專案名稱於 Project name: 一欄, 接下來在 Project name: 的下方中間也有一個 INS 按鈕, 請按下這個按鈕, 然後輸入開啟這個專案時要改變的變數。 筆者所知道需要改變的變數至少有下列幾個:
emacs-wiki-publishing-directory
這個專案的網頁放置目錄
emacs-wiki-directories
這個專案的 Wiki 檔案放置目錄
記得 emacs-wiki-directories 是複數名詞, 代表這是一個 list, 所以在 Value 那一欄必需將你的目錄用括號刮起來, 如:
("~/Documents/MyWebPage")
增加完成之後, 記得按 State 這個按鈕把這次改變的專案設定儲存起來。 以後要使用專案, 可以直接開啟該專案的檔案, 或是在 Emacs Wiki Mode 中下 C-c C-v 改變專案。

傳送網頁至遠端伺服器

目前 Emacs Wiki 要編輯遠端的網頁, 可以放在本地端, 然後再用 rsync 等同步程式來做同步, 或是把專案放置在遠端的機器上。 要把專案放置載遠端的機器上, 可以把 emacs-wiki-directory 放在本地端, 把 emacs-wiki-publishing-directory 填上
"/user@host:/path/to/your/web/page"
如此, 當你下 C-c C-p (emacs-wiki-publish) 時, Emacs 就會透過 tramp 程式把檔案送到遠端的伺服器上。 M-x emacs-wiki-publish 會將所有的 Wiki 檔案都轉換成 html, 並且傳送到遠端, 在頻寬較小的情況下, 相當的耗費時間, 可以利用 M-x emacs-wiki-publish-this-page 來傳送目前編輯的頁面。
如果你嫌每次都要按 M-x emacs-wiki-publish-this-page 打太多字, 可以參考 Emacs Wiki 專案首頁的建議1, 將 C-x C-p 按鍵定義成 M-x emacs-wiki-publish-this-page, 只要你在 ~/.emacs 加入以下幾行即可:
(add-hook 'emacs-wiki-mode-hook
       (lambda () (global-set-key "\C-x\C-p" 'emacs-wiki-publish-this-page)))
這樣就會在每一次進入 Emacs Wiki 模式時將此按鍵加入。 你就可以在每一次編輯完一個檔案, 想要上傳時, 按 C-x C-p 來上傳目前編輯的檔案, 以節省傳輸時間。

註腳模式

說明

註腳模式(footnote-mode) 是一個次要模式(minor mode), 與 Emacs Wiki 並無直接關聯, 是 Emacs 內建的次要模式。 筆者通常用這個模式配合 gnus 使用, 在編輯文章的時候加一些註腳用。 Emacs Wiki 採用的註腳格式與註腳模式產生出來的格式完全一樣, 所以我們也可以利用註腳模式來協助編輯 Emacs Wiki 檔案。
與其他的次要模式一樣, 註腳模式的命令可以開啟或關閉註腳模式。 註腳模式的命令是
M-x footnote-mode
當註腳模式開啟的時候, Emacs 視窗下方的模式列會顯示 FN 的字樣。 當我們要新增一個註腳的時候, 只要在想要新增的位置鍵入
M-x footnote-add-footnote
接下來註腳模式會自動在新增的位置填上一個數字前後加上方括號, 並且跳到文章的最後, 加上註腳(Footnote) 字樣, 游標會停在要編輯的註腳後面等待使用者輸入註腳的說明文字。 輸入完之後, 我們可以輸入
M-x footnote-back-to-message
然後游標會回到剛剛新增註腳的位置, 使用者可以繼續本文的編輯。 其餘的註腳模式功能請參考快速鍵列表, Emacs Wiki 可以完全處理註腳模式產生的格式, 這篇文章就是利用註腳模式來來產生註腳的。

快速鍵列表

註腳模式的快速鍵不多, 只有六個, 表列如下:
按鍵命令(鍵入之前先按 M-x)說明
C-c ! aM-x footnote-add-footnote增加註腳
C-c ! bM-x footnote-back-to-message由註腳說明處回到引用處
C-c ! dM-x footnote-delete-footnote刪除註腳
C-c ! gM-x footnote-goto-footnote跳到註腳解釋
C-c ! rM-x footnote-renumber-footnotes重新編排註腳號碼
C-c ! cM-x footnote-cycle-style變換註腳形式


[1] Emacs Wiki 專案首頁, http://repose.cx/emacs/wiki/#sec5

Friday, October 12, 2012

Emacs etags 簡介


這也是筆者多年前發表在 NNTP news 上的文章,留存備份。

etags 簡介 -*- Outline -*-

* 前言
  有許多的 IDE(Integrated Development Environment) 都提供了函數名稱的
  自動完成功能( 亦即,輸入前面幾個字元之後,編輯器可以自動幫你完成後面
  的函數名稱)。Vi 裡面有 ctags 可以做到這件事,那麼 Emacs 呢?答案是
  etags. 在這篇文章裡,我會簡短的介紹如何使用 etags.

* etags 使用方法
** 建立函數及關鍵字列表
   在使用之前,你必須先在你的發展環境目錄底下建立列表; 假設你的發展環
   境目錄名稱叫做 /path/to/developer/, 建立列表的方法如下:

   % cd /path/to/developer/
   % etags *.h *.c

   這樣就建立完成了,根據 etags/ctags 的手冊, etags/ctags 可以處理的語
   言有 C, Objective C, C++, Java, Fortran, Ada, Cobol, Erlang, LaTeX,
   Emacs Lisp/Common Lisp, makefiles, Pascal, Perl, Postscript,
   Python,  Prolog, Scheme  and most assembler-like  syntaxes.
   預設的列表檔名是 TAGS.

** 把函數及關鍵字列表讀進 Emacs
   開始用 Emacs 編輯檔案, 比如說你正在編輯 foo.c, 你先用 C-x C-f 把
   foo.c 讀進來之後,你需要使用 etags 的功能,那麼你就執行
   M-x visit-tags-table /path/to/developer/TAGS
   把 /path/to/developer/TAGS 檔案讀進來。註: 表示 Return 鍵,或
   是在鍵盤上通常標示為 Enter.

** 在 Emacs 中搜尋函數內容
   有的時候我們會想要直接跳到某個函數裡面去修改他的內容,你可以使用
   M-. (沒錯,就是 Meta 跟一個句點) 然後輸入函數名稱就會跳到該函數的
   code 那裡去; 如果你按 M-. 的時候游標指著一個函數名稱,你可以在輸入
   函數名稱的時候直接按 即可跳到該函數源碼的地方。跳過去之後,如
   果你想要回來原來地方,你可以用 M-* 來做到。

   如果你想要在另一個視窗內看到該函數源碼,而不是你現在的這個視窗(對照
   方便), 那麼你可以用 C-x 4 . TAG 來達成這件事。

   如果你要搜尋某些函數與關鍵字,你可以用 M-x tags-search 的功能,這個
   可以用 regular expression 來搜尋。當你用 M-x tags-search
   REGEXP 之後,你可以用 M-, (Meta 逗點), 找下一個搜尋到的函數名
   或關鍵字。

** 函數及關鍵字自動完成
   etags 並沒有提供函數及關鍵字自動完成(auto-completion)的功能, 但是
   Emacs 有提供一個功能可以達成這件事,叫做 dynamic abbreviation
   expansion. 這個功能事實上是把去找在開啟的 buffer 裡面有那些字串是你
   輸入字串的完整字串,而 TAGS 列表就在一個 buffer 裡面,所以可以達成
   函數及關鍵字自動列表。當你輸入一個函數名稱或是一個變數名稱的前面幾
   個字母,比如說: foo-, 然後按 M-/, 這時候 Emacs 會把所有可能的字串找
   到,並把第一個可能的字串直接完成,所以你按了一次 M-/ 之後可能會變成
   foo-bar-function, 你繼續按 M-/ 可以變換成其他可能的字串,直到沒有為
   止。或者是你也可以按 C-M-/, 這時候 Emacs 會像其他時候的
   auto-completion 的行為一樣,跳出一個視窗把所有的可能列表列出來給你
   選擇。

* 結語
  當我開始使用 etags 的功能之後,我就沒有辦法不用這個功能了,因為實在
  是太方便了。etags 也可以幫你自動完成標準函式庫裡的名稱,只要你在
  etags 的時候把 /usr/include 裡的表頭檔案也包含進來就可以了。etags 還
  有其他比較進階的功能,我沒有一一列出來,有興趣的人可以去看看 M-x
  info 裡的 Emacs 手冊。最後我做一個這次提到的功能列表,供讀者參考用。

* 按鍵列表
  M-x visit-tags-table TAGS-file
      把 TAGS-file 檔案讀進 Emacs
  M-. TAG 尋找函數或關鍵字定義的源碼
  C-x 4 . TAG 在另一個視窗尋找函數或關鍵字定義
  M-* 回到尋找關鍵字定義之前的地方
  M-x tags-search REGEXP 用正規表示式搜尋函數或關鍵字定義
  M-, 找下一個搜尋到的函數或關鍵字
  M-/ 自動完成可能的函數或關鍵字
  C-M-/ 列出所有函數或關鍵字名稱的自動完成列表

Emacs 大綱模式簡介(Outline mode)

這是筆者很多年前寫的文章,發表在 NNTP news 上面,留存在本 blog 中。


* 簡介 
我想很多人在作筆記或是絞盡腦汁想問題的時候,常常會用大綱來把自己的想法 
記錄下來,比如說像以下的方法: 
I. 棒球 
A. 職棒 
1. 台灣職棒 

2. 美國職棒 
a. 國家聯盟 
b. 

3. 日本職棒 
a. 中央聯盟 
b. 太平洋聯盟 

B. 業餘棒球 

II. 籃球 
A. 職籃 

這樣的階層架構可以在 Emacs 中使用他的大綱模式(outline mode) 來做到,幫 
助我們來紀錄我們的想法或是像筆者就常常在聽完演講之後,把用筆記上的演講 
大綱筆記,用 Emacs outline mode 記錄下來,供日後查詢。Emacs 也可以把這 
些 outline 轉換成其他格式,比如說: LaTeX 或是 Info 檔格式。在本文中提 
到的 Emacs 以 GNU Emacs 為準,XEmacs 應該也是差不多,不過我建議你們用 
GNU Emacs, 因為 Emacs 處理字型比較清晰,而且對於中文支援較佳。 

* Outline mode 
** 進入大綱模式 
使用者可以用 M-x outline-mode 來進入大綱模式,打完這個命令之後就可以看 
到目錄列上出現 "Headings" "Show" "Hide" 三個下拉式選單項目,不過,先別 
急,先了解一些基本概念再來使用。如果你有開啟 font-lock-mode 的話,你打 
完上述命令之後就可以看到這篇文章的標題顏色變了,因為筆者就是用 
outline-mode 來打這篇文章的。如果沒有看到顏色,你可以用 M-x 
font-lock-mode 來啟動。M-x 意思是按住 Alt(Emacs 裡稱為 Meta 鍵) 以及 
x, 然後輸入 outline-mode,再按 [Enter] 即可。 

** 階層架構 
Outline mode 的階層架構是以幾個 "*" 符號來分隔的,就如同本文章一樣。一 
個星號("*") 的就是最高層,也就是類似簡介的例子中的 I, II, 等等,而兩個 
星號則是第二層,類似例子中的 A, B, 等等。但是要注意的是這些星號一定要 
在該行的最前面。如果沒有星號開頭的就是該層(或稱為該標題)下的本文。 

** 顯示及隱藏標題與本文 
*** 隱藏 
想要隱藏某個標題下的全部文字,你可以選擇目錄選單『Hide->Entry』,你可 
以將游標移到這裡,然後選擇『Hide-Entry』,如果你沒有看到選單,你可以直 
接輸入 C-c C-c (連續兩個 Control C)。好,現在就輸入 C-c C-c 

*** 顯示 
別急別急,看不到隱藏的文字了?先看看隱藏兩字後面是不是出現了三個句點 
"..."? 那就表示那個標題以下的文字被隱藏了。你可以用目錄選單 
『Show->Entry』來回復剛剛的文字,或是按 C-c C-e 來顯示隱藏的文字。 

*** 在標題間移動 
有的時候你會想要在同個層級的標題間移動,這樣比較方便寫作。那麼你可以使 
用『Headings->Previous Same Level』,或是按 C-c C-b 到前一個同層級的標 
題。如果你照指示的話,你會看到現在游標停在『顯示』那一行上面。如果要上 
一個層級,你可以選擇『Headings->Up』,或是 C-c C-u, 如果你照做的話,你 
的游標現在會是在『顯示及隱藏標題及本文』那一行。 

* 結語 
有沒有搞錯?這麼快就要結束了?沒錯,我已經把主要功能介紹完了,其他的功 
能,請自行看下拉式選單,全部都在 Headings, Show, Hide 裡面。或是找 
Emacs manual 裡的 Outline Mode 一節,有更詳盡的說明。 

大綱模式是一個很小,但很方便的功能。筆者曾經有一次要做 simulation 
program 的除錯, 我把所有的 events 全部輸出到一個檔案裡,但是 events 很 
多啊,那可是上千上萬的。Events 有分不同的層級,上層的是比較高階的動作, 
下層是比較細節的動作,如果分層輸出到不同個檔案可以解決 events 太多的問 
題,但是卻比較不容易看出不同層級的時間先後。於是筆者便將 events 依照層 
級在那一行的最前面加上星號,全部輸出到一個檔案裡(最後還是有分檔案啦, 
不過是五千個 events 一個檔案,而不是分層級)。這樣,我就可以分顏色看到 
events 的層級,我也可以顯示或隱藏某一個 events 以下做的事,要找下一個 
同層級的 event 也很快。如果你想照做,筆者提醒你,Windows 版的Emacs 處 
理這樣大的檔案會頗慢的,這也是筆者改用 Linux 的原因之一。 

Friday, October 5, 2012

在 GNU Emacs 的 Help 文件系統


GNU Emacs 有一個功能很好用, 他的 key binding 一般來說是 C-h S, 或是 M-x info-lookup-symbol, 使用的方法是把游標移到你要查詢的 symbol 上面, 然後按下 C-h S, 這時候 Emacs 會自動幫你找到相對應的 Info 文章, 並顯示在另一個視窗(這裡的視窗是 Emacs 的術語) 上。



如果你想要試用這個功能, 可以試著開啟任何一個 Emacs Lisp 檔案, 然後對著任何一個 function 鍵入 C-h S, 就會出現文件, 舉例來說, 如果對著 require 按下 C-h S, 在筆者的 Emacs 24.1.1 就會出現下列的文件:





-- Function: *require* feature &optional filename noerror
This function checks whether FEATURE is present in the current
Emacs session (using `(featurep FEATURE)'; see below). The
argument FEATURE must be a symbol.

If the feature is not present, then `require' loads FILENAME with
`load'. If FILENAME is not supplied, then the name of the symbol
FEATURE is used as the base file name to load. However, in this
case, `require' insists on finding FEATURE with an added `.el' or
`.elc' suffix (possibly extended with a compression suffix); a
file whose name is just FEATURE won't be used. (The variable
`load-suffixes' specifies the exact required Lisp suffixes.)

If NOERROR is non-`nil', that suppresses errors from actual
loading of the file. In that case, `require' returns `nil' if
loading the file fails. Normally, `require' returns FEATURE.

If loading the file succeeds but does not provide FEATURE,
`require' signals an error, `Required feature FEATURE was not
provided'.





上述作法是當你目前的 major mode 有相對應的 Info 檔案的時候, 可以直接使用 C-h S 來查詢, 如果沒有的話, Emacs 會先問你要使用哪一個 major mode 的 help 檔案, 然後再查詢該 symbol 的文件。那麼, 如果要為新的 major mode 增加 Info 文件呢? 這時候你可以在 .emacs 裡加上 info-lookup-maybe-add-help 來把某個 Info 檔案加入 major mode 裡面, 範例如下:





(require 'info-look)

(info-lookup-maybe-add-help
:mode 'asm56k-mode :topic 'symbol
:regexp "[a-zA-Z]+"
:doc-spec '(("(dsp563xx)Index")
("(dsp563xx)Concept Index")))





上述的範例是指定 major mode asm56k-mode 的 Info 文件是 dsp563xx, 這個檔案必須在 Info 系統能找到的路徑上, 透過 Index 與 Concept Index 這兩個 Info node 來查詢關鍵字的 Info 文件, 而可以被查詢的關鍵字的 regular expression 則由 :regexp 來指定, 本範例的關鍵字是由純英文字母組成。上述的範例是筆者為了要在 GNU Emacs 裡面寫 Motorola DSP56300 的組合語言而增加的, 這樣筆者在 asm56k-mode 編輯組合語言的時候, 就可以隨時透過 C-h S 來查詢某個助憶碼(mnemonic) 的用法以及 instruction encoding, 而這些是存在另一個 Info 文件上。



Info 檔案在 GNU Emacs 中是一個重要的文件系統, 可以由 Texinfo 檔案編譯而成, 現在也有很多文件系統也可以產生 Texinfo 的格式, 比如 Sphinx, 對 Texinfo 有興趣的讀者可以參考一下 Arnold Robbins 在 Linux Journal 所寫的介紹文章 What's GNU: Texinfo. 不管是用什麼方法產生 Info 檔案之後, 透過設定, 結合 C-h S 的便利性, 你就可以在 GNU Emacs 裡面很便利的查詢文件。


--

Monday, June 18, 2012

用 Linear Filter(IIR) 來實作 Fibonacci 序列


PyCon.TW 2012 在日前圓滿落幕, 會中的 keynote speaker Travis Oliphant 講
了一個使用 linear filter 實作 Fibonacci 的例子, 在演講中只有一張投影片,
在這裡我嘗試做分解動作解釋一下。投影片內容在 http://www.slideshare.net/pycontw/largescale-arrayoriented-computing-with-python



我們知道 Fibonacci 序列是 x(n) = x(n-1) + x(n-2), 而 x(0) = 0, x(1)
= 1. Fibonacci 序列的產生也常常是教科書介紹 recursive 的好範例, 不過就
如 Travis Oliphant 所示, 用 recursive 實作的複雜度是 exponential 成長的,
而我們也可以用 SciPy 裡面的 linear filter 來實作這件事, 方法如下:




from scipy.signal import lfilter
from numpy import zeros
b = array([1.0])
a = array([1., -1, -1])
zi = array([0, 1.0])
def fib3a(N):
y, zf = lfilter(b, a, zeros(N, dtype=float), zi=zi)
return y




我來慢動作分解一下上面的實作方法。首先 lfilter 在 b = array([1.0]) 以及
a=array([1.,-1,-1]) 的情況下會產生b(0)x(n) = a(0)y(n) + a(1)y(n-1) +
a(2)y(n-2) 的式子, 代入 a,b, 我們可以得到 x(n) = y(n) - y(n-1) -
y(n-2),而 lfilter 的第三個參數就是 x 的序列, 是 zeros(N, dtype=float),
也就是說輸入全為零,上述的式子就會變成 0 = y(n) - y(n-1) - y(n-2), 把 y(n) 移到等式的左方, 就可以得到 y(n) = y(n-1) + y(n-2), 這就是 Fibonacci 數列的表示法啦! 最後的 y(n) 就是 Fibonacci 的第 n 個數列。另外,
zi=array([0,1.0]) 就是當 lfilter 開始執行的時候, delay element 裡面的元
素, 也就是 y(0) 與 y(1) 的值。



以濾波器的角度而言, 這個濾波器在輸入全為零的狀況下, 自己產生
0,1,1,2,3,5,… 這種發散的數列, 等於自己在震盪, 是我們在實際上不會去使
用的濾波器, 拿來實作 Fibonacci 數列, 實在是有趣。



--

Saturday, April 7, 2012

LaTeX PSTricks 訊號處理範例: z-Transform


上一篇的 moving average filter y(n) = (15/16)*y(n-1) + (1/16)*x(n) 的
z-transform 有一個 pole 在 z=(15/16, 0) 的點上, 要畫這個 z-Transform 在
z-plane 上的表示圖, 可以用下列的 PSTricks 來表示。




\usepackage{pstricks}
\usepackage{pst-sigsys}





圖形如下表示:
http://farm6.staticflickr.com/5238/7053583759_5fbddb20fc.jpg





\begin{center}
\begin{pspicture}[showgrid](-2,-2)(2,2)
\pscircle[linecolor=gray](0,0){1} % unit circle
\pspole(0.9375,0){z1}
\nput{0}{z1}{$(\frac{15}{16},0)$}
\end{pspicture}
\end{center}





--

LaTeX PSTricks 訊號處理範例: Moving Average Filter


今天要介紹的是如何用 PSTricks 來繪製訊號處理的 functional diagram, 假設
我們要描述的訊號處理方程式是: y(n) = (15/16)*y(n-1) + (1/16)*x(n). 這是
一個動平均濾波器, y(n) 是目前的輸出值, x(n) 是目前的輸入值, y(n-1) 則是上一次的輸出值,
那他的 functional diagram 會是如下圖所示:
http://farm6.staticflickr.com/5320/6907485526_81ef0d8ab5.jpg



上述圖形使用了 PSTricks 以及 PSTricks 的 pst-sigsys 套件,所以要在 preamble 的部份如下宣告:




\usepackage{pstricks}
\usepackage{pst-sigsys}





描述這個濾波器的 LaTeX source code 如下:




\begin{center}
% To describe y(n) = (15/16)*y(n-1) + (1/16)*x(n)
\begin{pspicture}(-2,-1)(10,2)
\pssignal(0,1){x}{$x(n)$}
\pscircleop[oplength=0.25,operation=times](2,1){op1}
\pssignal(2,0){coefx}{$\frac{1}{16}$}
\pscircleop[oplength=0.25](4,1){op2}
\pssignal(8,1){y}{$y(n)$}
\dotnode(6,1){ydot}
\psblock(6,0){delay}{$z^{-1}$}
\pscircleop[oplength=0.25,operation=times](4,0){op3}
\pssignal(3,0){coefy}{$\frac{15}{16}$}
\nclist{->}{ncline}{x,op1,op2,y}
\nclist{->}{ncline}{coefx,op1}
\nclist{->}{ncline}{ydot,delay,op3,op2}
\nclist{->}{ncline}{coefy,op3}
\end{pspicture}
\end{center}






--

Wednesday, February 22, 2012

gcc for Andes compile 出來的 assembly


為了要做 24-bit signed integer to 32-bit signed integer 的 signed extension 測試,我寫了以下的一小段 code 來測試, 在這裡順便稍微提一下 optimization, 我們先看 c code:




void testSign()
{
unsigned int test=0x00800000;
int test_s;
test_s = ((int)test << 8 ) >> 8;
}





除去 prologue 或 epilogue 的部份,我們來看主體:




00000614 <testSign>:
......
61c: 46 00 08 00 sethi $r0,#2048
620: 14 0e 7f fd swi $r0,[$fp+#-12]
624: 04 0e 7f fd lwi $r0,[$fp+#-12]
628: 40 00 20 08 slli $r0,$r0,#0x8
62c: 90 08 srai45 $r0,#0x8
62e: 14 0e 7f fe swi $r0,[$fp+#-8]




解釋如下:


sethi $r0,#2048

$r0 = 0x00800000

swi $r0,[$fp+#-12]

把 $r0 存回 test 的儲存空間

lwi $r0,[$fp+#-12]

把變數 test 值抓到 $r0

slli $r0,$r0,#0x8

把 $r0 做 logical left shift by 8 bits, $r0 = 0x80000000

srai45 $r0,#0x8

把 $r0 做 arithmetic right shift by 8 bits, $r0 = 0xff800000

swi $r0,[$fp+#-8]

存回 tests 的儲存空間。





而如果我們把這個 c code 改成如下:




int testSign(unsigned int value)
{
return ((int)test << 8) >> 8;
}





產生出來的 assembly 就會變成:




000005f8 <testSign>:
5f8: 40 00 20 08 slli $r0,$r0,#0x8
5fc: 90 08 srai45 $r0,#0x8
5fe: dd 9e ret5 $lp




這個版本完全沒有任何 local variables, 傳入的參數也只有一個, 當傳入參數
只有一個的時候, 會使用 $r0 這個暫存器傳入, 回傳值也是在 $r0 回傳,
所以這樣子最省空間了,也是我們 assembly programmer 會寫出來的樣子。注意
如果沒有做 (int) 的 explicit cast, 編譯器並不會使用 srai45 這個
arithmetic right shift 指令製造 signed extension, 即便是最後的回傳值是
有號數。


--
My Emacs Files At GitHub

Thursday, January 26, 2012

Emacs 的 org-googlecl 會把標題的 $ 吃掉


在上一篇「超便宜的 TI C6670 EVM, 只要 USD$599!」中,原本的文章因為 $ 在標題中被吃掉,所以變成了「超便宜的 TI C6670 EVM, 只要 USD99!」,想必標題相當吸引人,呵呵。


--
My Emacs Files At GitHub

超便宜的 TI C6670 EVM, 只要 USD$599!


參考連結: http://www.ti.com/tool/tmdxevm6670
這是 TI 的 TMS320C6670 EVM 的連結,這一顆 DSP 擁有四個 C66x 的核心,每一個核心都可執行 SIMD 指令,可以同時執行 8 組 32-bit 指令。TI 稱呼這個叫做 static VLIW, i.e. Very Long Instruction Word. 另外, C6670 有 Turbo encoder/decoder coprocessor、Viterbi decoder coprocessor、CDMA 用的 RAKE 加速器,還有 FFT coprocessor 等,頗適合拿來實作 WCDMA/CDMA2000/LTE 等各種 cellular communication 的基地台。當然,要拿來其他通訊模式也非常 powerful. 這麼強大的一顆 DSP, EVM 含 emulator 只要 USD$599 喔!



--
My Emacs Files At GitHub

SimPy slides in our company and PyHUG meeting


This is my presentation on discrete-event simulation given to engineers in our company and PyHUG, which is Python Hsinchu User Group. I think it might be useful for somebody on the Internet.
https://docs.google.com/open?id=0B0rtbYTzCZWN2Y5MmY4M2ItYzJkYy00ZTA2LWI5N2UtNmUxNjI5YzNjZTg0



http://dl.dropbox.com/u/31960195/Introduction-to-SimPy-20111017-PyHUG.pdf



--
My Emacs Files At GitHub

Friday, November 11, 2011

Improvement on matlab-emacs


Modification to matlab-cellbreak-face




Current cvs code for matlab.el does not handle cellbreak-face correctly. It cannot distinguish between %% and %%%%, but matlab-shell-run-cell can function well. But fontifying not well is still annoying, so we need to modify it. In matlab.el, find the following lines to modify from:




;; Cell mode breaks get special treatment
'("^\\s-*\\(%%[^\n]*\n\\)" (1 matlab-cellbreak-face append))




Change it to:




;; Cell mode breaks get special treatment
'("^\\s-*\\(%%[^%\n]*\n\\)" (1 matlab-cellbreak-face append))










Evaluate cell and advance (C-S-return)






In MATLAB editor, we can press C-S-return to perform "evaluate cell and advance" function. Minor modification to matlab.el can make it happen. You can just add the following code snippet to your .emacs file.





(require 'matlab-load)
(defun matlab-goto-next-cell ()
(interactive)
(re-search-forward "^%%[^%\n]"))

(require 'matlab)
(define-key matlab-mode-map [(meta control F)] 'matlab-goto-next-cell)
(defun matlab-run-cell-and-go ()
(interactive)
(progn
(save-excursion
(matlab-shell-run-cell))
(matlab-goto-next-cell)))
(define-key matlab-mode-map [(meta shift return)] 'matlab-run-cell-and-go)





The example for running matlab cell mode is like this:





a = [1,2,3];

c = [4,5,6];

%% This is first cell

d = a * c';

%%%% This is not a cell

b = [3,2,1];

%% Another cell

c = a + b;

kkk





After pressing three <C-S-return>, the matlab-shell screen will look like:






< M A T L A B (R) >
Copyright 1984-2010 The MathWorks, Inc.
Version 7.12.0.635 (R2011a) 64-bit (maci64)
March 18, 2011


To get started, type one of these: helpwin, helpdesk, or demo.
For product information, visit www.mathworks.com.

>> addpath('/Users/jjhuang/elisp/matlab-emacs/toolbox','-begin'); rehash; emacsinit('emacsclient -n');
>> , a = [1,2,3];, c = [4,5,6];,
>> , a = [1,2,3];, c = [4,5,6];, d = a * c';, b = [3,2,1];,
>> , d = a * c';, b = [3,2,1];, c = a + b;, kkk,
??? Undefined function or variable 'kkk'.

>>





Okay, now matlab-emacs for me is more convenient right now. Hope you enjoy it!




--
My Emacs Files At GitHub

Friday, October 14, 2011

悼念 Steve Jobs


第一次知道 Steve Jobs 這個人,是在我大一開始接觸 NeXTSTEP 這個作業系統之後,當時 NeXT 以劃時代的物件導向技術、華麗的視窗外觀、當時時尚界流行的黑色元素、鎂合金的外觀,以及對開發者非常友善的開發工具,在 1990 年代初期登場,而 Steve Jobs 正是生產 NeXT 電腦的 NeXT 公司的 CEO. NeXT 也是他在被自己所創辦的 Apple 解僱之後所創立的公司。



NeXT 是我人生第一次如此著迷的軟體技術,也是我第一次如此深信這產品將會改變這個世界。因此,NeXTSTEP 上的應用程式也是我唯一會寫的視窗應用程式。我總是告訴別人 NeXTSTEP 是世界上最美麗的作業系統。在我大二時接管了一些 DEC Alpha 的工作站,於是我為系上設立了 FTP 站。我選定了 NeXTSTEP 相關的資源映射至 FTP 站裡,到後來系上的 FTP 站成為台灣 NeXTSTEP 資源最完整的 FTP 站,也使得系上的 FTP 站在某個小眾市場裡頗具知名度,而那也是我人生中做的第一個與 marketing 有關的決策。然而,我認為當時不擅長 marketing 的 NeXT 開始出售硬體工廠,而且營收不佳,幸而當時 Apple 正在為他的 OS9 尋著「下一步」,Apple 從 BeOS 與 NeXTSTEP 中選擇了 NeXTSTEP, 也使得 Steve Jobs 後來王子復仇重回 Apple 掌舵。我想 Steve Jobs 在這個時期學會了虛心,也學到了 marketing 的重要性與技巧,此後 Apple 的產品,在我看來,不再以技術上的創新為唯一的依歸,更多是使用者經驗的創新。



在 NeXT 被 Apple 收購之後,我開始接觸與 Steve Jobs 有關的書,有兩本,一本是 "Apple: The Inside Story of Intrigue, Egomania, and Business Blunders" by Jim Carlton, 另一本是由 Randall E. Stross 所撰寫的「電腦金童 NeXT 風雲再起」,分別描述了他在被 Apple 踢出公司前與 NeXT 時代的故事,當這些書完成的年代,Steve Jobs 對這些作者相當的不友善。他從不願提供任何資料,也不讓作者訪問他的家人,因此作者只能辛苦的從旁人口中得到 Steve Jobs 的資料。這個時期他脾氣暴躁,而我其實不太欣賞他。



他回 Apple 之後,開始推出彩色外殼的 iMac 以及貝殼造型的 iBook,但一直到 iPhone 的出現,我才又注意與欣賞 Steve Jobs 的才華。當時我擁有一支 Nokia Symbian S60 系列的智慧型手機,深深知道智慧型手機最重要的就是軟體與使用者經驗。iPhone 在當時並不是第一支智慧型手機,也不是第一支觸控手機,初問世時更因沒有觸控筆或鍵盤而被市場質疑,但當我試用過而且知道 Apple 將當初 NeXT 那一套有名的開發工具流程應用在 iPhone 的開發上,我知道這支手機絕對劃時代。再加上 AppStore 方便程式設計師以及 SOHO 工作室將開發出來的軟體很容易的銷售到使用者首中,iPhone 的軟體便像雨後春筍般蓬勃發展,這絕對是 iPhone 開發者、使用者、Apple 三贏的局面,也使得 iPhone 成為世界上單一機種銷量最高的智慧型手機。之後,Apple 更順勢推出 iPad 這個平板電腦,更帶起來平板電腦的風潮。回顧 iPod, iPhone, Apple TV, iTunes store, 以及 AppStore. 可以看得出來 Steve Jobs 逐步的將他心中的藍圖實現,將 Apple Computer, Inc. 從軟硬體整合製造商轉型為以內容與服務為主的 Apple, Inc. 這樣子的遠見與毅力,才是我佩服與欣賞 Steve Jobs 的原因。我想不可否認的,iPhone 與 iPad 的出現,的確完全改變了你我的世界。



今年八月 Steve Jobs 請辭 CEO, 大家就在猜測他的健康是否出現問題,而當我看到 Steve Jobs 與 Walter Isaacson 合作寫傳記,容許這個作者訪問所有他身邊的人,其實就大概可以猜到他已經在做準備了。但當 10 月 5 日,他過世的消息傳來,我仍然感到悲傷。雖然我總是說我並不是 Steve Jobs 迷,但當他過世時,我深深感到這世界失去了一個有遠見、有創意的奇才。而在他過世之後,我也重新觀看他對 Stanford 畢業生做的演講,裡面我最愛的一段是第三個關於死亡的故事,裡面說到如果你每一天都當做活著的最後一天來活,總有一天你會活出你的生命。當面臨死亡的時候,所有的外界期望、所有的驕傲、所有對於丟臉或是失敗的恐懼,這些都會消失。因為你已經光溜溜了,沒有理由不順從你的心。謝謝你,Steve Jobs,讓我有勇氣順從我的心,做我真正想做的事,而不恐懼失敗。謹以 Robert Frost 的詩來悼念這個不平凡的 CEO.



The Road Not Taken



Two roads diverged in a yellow wood,

And sorry I could not travel both

And be one traveler, long I stood

And looked down one as far as I could

To where it bent in the undergrowth;



Then took the other, as just as fair,

And having perhaps the better claim,

Because it was grassy and wanted wear;

Though as for that the passing there

Had worn them really about the same,



And both that morning equally lay

In leaves no step had trodden black.

Oh, I kept the first for another day!

Yet knowing how way leads on to way,

I doubted if I should ever come back.



I shall be telling this with a sigh

Somewhere ages and ages hence:

Two roads diverged in a wood, and I—

I took the one less travelled by,

And that has made all the difference.



           – Robert Frost







--
My Emacs Files At GitHub

Saturday, October 8, 2011

愛吃信用卡的高鐵自動售票機


有坐過高鐵的人, 有不少的比例會因為售票窗口大排長龍而像筆者這樣選擇自動售票機購票; 自動售票機售票有三種付款機制, 分別是現金、信用卡、金融卡。用現金購票有個惱人之處: 找錢一律用銅板, 就是會掉出一大堆的五十元銅板。再加上信用卡購票可以累積信用點數, 所以有一部分人會採用信用卡付款, 外國旅客來台灣也蠻常用信用卡付款的。


高鐵自動售票機可以說是信用卡吃卡機器, 原因就出在整體的使用者介面設計上。信用卡購票流程是這樣的, 首先先在下方螢幕點選「自由座」或「對號座」, 然後是乘車日期、時間, 選定班次, 接下來選擇付款機制, 如果選擇了信用卡, 這時候你的注意焦點要開始擺在上方小螢幕上, 自動售票機會有語音提示你這點, 但是我也常常看到不熟悉這個購票流程的人不知道該看上面的小螢幕。這個問題就出在使用者在按螢幕這麼多按鍵後, 心中其實是忽略所有語音的提示, 而把焦點放在視覺上, 如果這時候沒有視覺上的提示, 很容易被忽略。


如果使用者有注意到上方小螢幕的話, 接下來是插入信用卡, 等待輸入預借現金密碼或是生日。這部份的問題是按鍵頗難按, 而且如果你慢個二十秒注意到這個小螢幕, 很大的機會會在輸入完密碼後告訴你連線逾時, 一切又得重新再來。


當信用卡密碼輸入正確, 而且連線驗證成功之後, 以下的動作幾乎是同時發生: 1) 上方信用卡退出來, 2) 下方出票口「亮燈」並且送出車票與簽帳單。問題就發生在第二個動作是有亮燈而且有聲音的, 很多使用者都會被下方的事件所吸引, 而忽略了上方無聲無息的事件。也因此, 不少使用者拿了票之後就直接走人搭車去, 忘記了那張信用卡, 尤其是你後面排了不少人的時候。這也就是為什麼常常聽到車站廣播有人遺失信用卡的原因了, 筆者本身就提醒過幾次前方的使用者拿信用卡, 包括外國旅客; 個人也有一次親身經歷, 而且是我常常用信用卡在自動售票機買票搭高鐵好幾年之後, 在某個週日早上剛睡醒不久, 疏於注意就忘記信用卡了。


對於這樣的使用者介面, 我建議的改進方式是這樣: 在信用卡插入口上方加一個 LED 燈號, 要夠醒目, 當第一次要插入卡片的時候閃個四五秒吸引使用者注意。另外當密碼驗證成功之後, 上方信用卡退出來要一直閃爍直到取走, 然後出票口才出票。這樣的缺點當然是要比原先的流程再多個幾秒鐘時間, 但是卻少掉很多信用卡掉卡的機會, 應該也會吸引更多信用卡用戶從售票窗口移到自動售票機購票吧。整體而言, 高鐵的自動售票機已經做得不錯, 若吃信用卡這點能夠改善, 大家(尤其是外國旅客)對台灣高鐵的印象會更好一點。畢竟如果你只搭那麼一次高鐵要去機場, 卻因為售票機流程設計不好, 把你的信用卡而不是你的心留在臺灣, 那就不是我們所樂見的囉。

附記:2012 年 12 月 31 日恰好臨時在台北車站用信用卡買了高鐵票(筆者後來都用 iPhone app 購票), 發現購票機已改成上述的流程, 筆者沒有投書高鐵, 想必是英雄所見略同!

--
My Emacs Files At GitHub