Quantcast
Channel: 簡睿隨筆
Viewing all 897 articles
Browse latest View live

[分享] 濱野純訪談:為什麼 Google 接管開發 Git 2.0 了?

$
0
0

導讀:最近 Google 推出了 Git 協議的 2.0 版。我們都知道 Git 是的 Linus 開發實現的。估計大家會有點好奇,為啥是 Google 「接管」了。目前 Git 的主要維護者濱野純是一位 Google 工程師。
濱野純是如何接手 Git 維護任務的?推薦大家往下看這篇訪談。

今天我們的嘉賓,是分布式版本管理系統Git的主要維護者,同時也是《入門Git》一書的作者,濱野純先生。而這次的訪談,也從濱野先生談自己從Linux內核的開發者,Linus Torvalds手中接過Git維護工作的原委開始了。

結識Git的經過

小飼彈(以下簡稱彈):當初是因為什麼原因參與Git了的開發呢?

濱野純(以下簡稱濱):2005年4月起Linux Kernel所使用的版本管理系統BitKeeper就因為License關系無法繼續使用了,所以Linus考察了很多當時的版本管理系統,但認為沒有一個是能用的。于是他在郵件列表里發了一封郵件,說自己寫了一些代碼,準備作為在找到更好的版本管理系統之前的過渡系統。而我看到那封郵件時,正好是我的本職工作處于舊項目剛剛完成而新項目還未上馬的間歇時期。我覺得這似乎是件挺有意思的事情,于是就把代碼下載了下來,看了一下發現只有1244行。

彈:全部都是C代碼嗎?

濱:是啊。這點代碼量我估計2小時左右應該就能讀完了。仔仔細細地讀了一遍以後,被代碼所表現出來的優美折服了。基本上我不算是一個Kernel開發者,Kernel郵件列表也只是偶爾看一眼的程度而已。但是,如果說參與數十萬行的Kernel開發確實有點困難的話,參與這個尚且才1000多行代碼的項目應該會很有趣,這算是當初參與Git的動機之一。那時候,在一周時間內發生了很多事,不過歸納起來就是Linux的內核開發者們聽說Linus要用個“新玩意”來管理代碼,如果那個“新玩意”太難用的話大家都痛苦,還不如一起想辦法把這個東西做好用點。而我也得以在開發中觀察這個項目的進展,思考這個新系統真正需要的是什麼等等,總之最後完成了提交commit的功能和輸出diff的功能。不過,merge功能還沒有完成。雖然Linus當時發過好幾封郵件,描述他理想中的merge應該是怎樣的。

彈:Linus對既往的版本管理系統,最不滿的就是這方面吧。

濱:因為Linus只寫C和Shell,而merge的邏輯實在太復雜,所以他多次發郵件到郵件列表,說要是有人能夠用腳本語言實現一個就好了。不過誰也沒有上鉤。就這麼了一個星期,一直關注郵件列表的我用Perl把Linus過去多次提到的merge算法實現并投到了郵件列表里。這是我第一次有一定規模地向開源項目貢獻代碼。然而,盡管我詳細地寫了將近30個測試用例以及各種分支條件下應該怎麼處理的表格,6個小時以後Linus提交到master分支的卻是個截然不同的東西。據本人說是想到了更好的辦法所以就這麼著了。我看了一下,確實就像哥倫布的雞蛋一樣——足以讓我那些依照Linus以前的邏輯所寫的代碼毫無價值——就是優雅到這種程度。不過之前你還說什麼“誰來幫忙做一下啊”我做了結果你又不要(笑),然而當時并沒有這麼想,因為新的處理方法確實很漂亮。

哥倫布的雞蛋

彈:為什麼說是哥倫布的雞蛋呢?

濱:我雖然沒有使用過BitKeeper,不過BitKeeper的做法是在work tree里基本上只存放自己的文件,而merge不發生在這里。merge時首先會創建一個臨時文件夾,在里面展開merge結果,發生沖突時就在里面解決,然後提交commit并在work tree里展開,這樣就算merge完成了。最初Git也準備使用相同的流程,不過解決了沖突以後的代碼,commit前想測試一下也是人之常情。所以我們就想那不如不要臨時文件夾,直接在work tree上merge就行了…。Git在提交commit之前,不是有個記錄了本次commit內容的index嗎?對于這個index,當初提出了引入分步驟(stage)的概念。也就是說,本來所謂3-way-merge就是,首先我們有一個共同的版本,你在這個版本的基礎上做了一些變更,我在這個版本的基礎上做了另一些變更,然後將這兩個差分merge起來。那麼把這三個版本分別作為stage1,stage2,stage3依次添加到index里,那merge不就完成了嗎——Linus當時就是提出了這樣的建議。仔細想想這種做法確實可以一下子解決很多問題。例如最簡單的情況,我和你都沒有做出變更,那麼merge的結果就是沒有變更。如果我做了變更而你沒有,那麼最後得到的就是我變更以後的代碼,反之亦然。另外還有一種特殊的情況,就是你和我都做了“相同”的變更。

彈:這種事經常有啊(笑)。

濱:實際使用過以後發現確實如此,特別是Linux Kernel的開發,是基于郵件列表的。所以常有你我看到同一個patch,因為自己使用的版本是fix對象于是各自都打上了這個patch。這種情況也能在index中解決,不僅效率很高,結果也很清晰。

Linus的管理才能

濱:Linus常說,項目維護者的一半工作就是說No。不過即便如此,在拒絕別人提交的patch的時候,他總會向提交者強調,拒絕是因為這個提交不行,而不是你的能力不行。他對每個貢獻者都很看重。我那時候也是,Linus對我說,雖然你的提交沒有采用,但測試用例還是能用的,針對現在的實現你稍微修正一下吧。

彈:挺不錯啊。

濱:讓對方覺得自己的工作沒有白費,這樣就不會打擊貢獻者的熱情。不僅提出新的merge算法很厲害,Linus作為社區管理者的才能也很厲害。不服不行啊(笑)。

GitHub

彈:GitHub和Git有組織上的聯系嗎?GitHub不是Git社區的人,而是Git愛好者做的嗎?

濱:這個關系說來復雜了。GitHub的創始人都是Git社區以外的人。那些人基本上算是Ruby的人吧。Ruby社區開始大量使用Git應該是Rails采用Git作為版本管理以後的事。GitHub最初在還沒有像現在這樣流行之前,曾經采用邀請制試運營過一段時間,但是Git社區的主要成員卻都沒有收到邀請。雖然我個人不很在意,不過有些人覺得GitHub那群人在拿Git商業化所以很不爽,結果很長一段時間兩個社區之間不怎麼和睦。

彈:Git和GitHub是這種關系啊(笑)。都不很看重對方。

濱:經常會有無視對方自顧自地開發這種事,就比如官方Git和GitHub的Git的daemon程序在某些地方是不同的。GitHub做了一些他們自己的改動。面向大量用戶做出這種非官方的版本,作為Git社區也很苦惱啊。

彈:是啊。

濱:然後呢,去年有一個GitTogether的活動,Google提供了場地,一共進行了三天吧,GitHub和Git社區的主要成員都來了,探討了今後的發展方向,現在兩個社區的關系應該沒有過去那麼差了。事實上,你也覺得GitHub的幫助文檔很不錯吧。有GitHub替我們做文檔以及用戶支持,何樂而不為呢。

彈:因為過去什麼經驗都沒有的人也可以在GitHub上直接fork項目是吧。確實這種方式我覺得足以改變世界。從一開始就不僅是公開代碼…。

濱:大家一起做一個項目,然後互相merge,這種工作流程很不錯。

彈:我也是,如果沒有GitHub的話也不會知道Git。

濱:是的,那是非常新穎的方式。盡管有些小地方很希望能夠改一下,但是GitHub在普及Git上功不可沒。

彈:就是看到了它,才終于明白為什麼Linus不滿足于過去的版本管理系統了。(那些過去的版本系統)都沒法merge嘛。說到底,對于Linux Kernel這種巨型的項目來說,或許merge這個分支的代碼還是那個分支的代碼會是一個大問題,但是對于普通的項目,只要考慮是取還是舍,維護也基本只需要一個人就足夠了,再不濟還可以分成多個子項目多人維護,至今為止我們都是這麼過來的,所以很難理解Git的好處。而GitHub的用戶時不時地就會碰到“那個分支再不merge就要出問題了”的狀況,切身體會了merge的重要性。我覺得那非常好。

優秀程序員的品質

彈:你覺得“優秀的程序員”是怎樣的一種人呢?

濱:當初接手Git項目時,Linus曾說過一個明星程序員有三種品質。最重要的第一點是,能夠持之以恒地做某件事。從這個角度上來說,AlphaGeek【見文末注1】是不行的。盡管對于新事物迅速投身進去不是壞事,但同時又迅速地失去興趣就不好了。順便我自己不那麼激進不是新事物愛好者也不會三分鐘熱度,應該不算是AlphaGeek。

彈:原來如此,三分鐘熱度是不行的。重要的是堅持。

濱:第二點算是審美觀吧。擁有良好的直覺和品位,這是Linus的原話。良好的直覺,這里是指面對一個新問題時,即使沒有完整地解決問題也能夠憑直覺提出正確的解決思路和方向。第三點是溝通能力。這個溝通能力不是說只要說明“我想做什麼”就可以了,而是能夠解釋“我的目標是什麼”以及我得出這一目標的整個思維過程,并且更重要的,是能夠讓其他人信服,簡而言之就是能夠將自己的目標明確傳達給他人的人。我覺得這非常重要。即使在Git社區內,非常優秀的人至少也有7、8人,但能夠同時兼具這三點的人非常之少。

彈:雖然之于審美觀我有很多想對Linus說的(笑)。不過我也猜得到Linus會怎麼反駁所以我還是作罷吧。話說回來,這三點中能夠做到其中兩點的人,估計在哪兒都會很吃香吧。做到一點就可以說工作能力很強,做到兩點就可以稱之為牛人了。

濱:說的是啊。Linus是按照我上面所說的順序提出的這三點,從Git社區至今為止的發展過程中來看,我覺得即使是只具備其中一點的人,只要鍛煉一下溝通能力,就能做任何自己想做的事了。溝通能力就是,即使自己做不到,只要把目標向其他人說明清楚了,就一定會有人來幫你達成這個目標。就是說只要表達想法可以不用非得自己動手。

彈:我在還沒有Open Source這個詞的時候就已經算混開源界了吧,不過近幾年來,開源界的表達能力真是越來越高了。拿十年前來和現在比,現在的年輕人的表達能力實在不一般,不是最近流行 Lightning Talk【見文末注2】嘛,就是5分鐘的演講。要是換作以前,肯定得花上30分鐘絮絮叨叨才行,但是那些年輕人證明縮短到5分鐘內是完全沒有問題的。實際在與他人合作的過程中,過去是做出了產品原型和對方討論這麼做如何,而現在則相反,不需要做出實際的成品,只要把想法提出來就可以了。都是因為現在的工具發達了啊,網絡速度變快了,應用平臺也變好了。有這麼一句老語,“現在的年輕人啊真是……”,我想說的是“真是很厲害”。我甚至都想表揚一下依然能夠跟上這些年輕人腳步的自己了(笑)。現在已經是半年不看項目就跟不上的時代了。覺得Git很難,或許也是因為我老了吧(笑)。

對40歲以上的程序員說的話

彈:有什麼想對40歲以上的程序員說的話嗎?40多歲的程序員,已經漸漸感到追趕年輕人有點吃力,對他們有什麼建議嗎?雖然我想說的是,那就趁20多歲正年輕的時候多寫點代碼吧。

濱:要怎樣才能成為年輕人的楷模,這個問題很困難啊。

彈:至少有一點,我覺得應該做到的,就是依然覺得寫代碼很快樂。如果抱著受罪的心態寫代碼,那一定是做不好工作的。這麼說來,您今年幾歲?

濱:保密(笑)。

彈:至少不是20、30歲了吧。我覺得還是挺厲害的。在版本管理系統中Git最年輕,但現在卻正漸漸成為主流。

濱:是啊。

彈:年輕的項目不一定只有年輕人在做,我覺得這非常好。

至此全文完。最後附一張大叔的帥氣照片。

圖0:濱野純訪談:為什麼 google 接管開發 git 2.0 了?

左為小飼彈先生,右為濱野純先生。

來源:http://www.techug.com/post/why-google-develop-git-2-0.html

##

您可能也會有興趣的類似文章


[Mattermost 教學#8] 傳入的Webhook範例說明

$
0
0

[Mattermost 教學#7] Mattermost的OAuth 2.0應用程式整合的操作步驟提及Mattermost有四種整合方法:傳入的網站的Webhook(網路掛接)、傳出的Webhooks、斜線命令和OAuth 2.0應用程式,而由我們應用程式「餵」給Mattermost的最簡單作法就是Incoming Webhooks了。以下是操作傳入網站掛接的步驟。

1. 建立傳入掛接

由主選單【整合】→點擊【傳入的Webhook】,再按右上方的【增加傳入的Webhook】,依序填入欄位資料。範例中傳入的訊息預設會輸出到公眾大廳(Town-square)。

add

按〔儲存〕後將此網路掛接的網址複製起來,這個網址就是我們要傳入訊息的對象。
save link

2. 撰寫傳送訊息的程式

接著就是寫支傳送訊息的程式來測試看看。程式很簡單,隨便看看都能懂。回應的格式是JSON:{"text": "要顯示在頻道上的訊息"}

package com.company.test;

import java.io.DataOutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;

/**
 * Test for sending message to http://localhost:8065/hooks/d1e6r6z8tfbnxnwfa4bhcdsjpo.
 *
 * @version Jerry 2018-05-10 22:24
 */
public class TestIncoming {
  private static HttpURLConnection con;

  public static void main(String[] args) throws Exception {
    try {
      // 1. 建立連線
      String myWebhook = "http://localhost:8065/hooks/d1e6r6z8tfbnxnwfa4bhcdsjpo";
      URL url = new URL(myWebhook);
      URLConnection urlConnection = url.openConnection();

      con = (HttpURLConnection) urlConnection;
      con.setDoInput(true);
      con.setDoOutput(true);
      con.setUseCaches(false);
      con.setRequestMethod("POST");
      con.setRequestProperty("Content-Type", "application/json; charset=UTF-8");

      // 2. 送出訊息
      //language=JSON
      String msg = "{\"text\":\"Incoming Webhook 測試\"}";
      DataOutputStream _oDataOutput = new DataOutputStream(con.getOutputStream());
      byte[] bytes = msg.getBytes("UTF-8");
      _oDataOutput.write(bytes);

      // 3. 查看結果
      int code = con.getResponseCode();
      if (code != 200) {
        System.out.println("Error " + code + " " + con.getResponseMessage());
      }
    } catch (Exception e) {
      e.printStackTrace();
    } finally {
      con.disconnect();
    }
  }
}

輸出結果如下:

sample output

3. 增加額外的輸出

輸出的JSON可以再加上額外的欄位,讓輸出呈現不同的樣貌。

  1. icon_url: 變更預設的圖示網址
  2. username: 變更設定的使用者名稱,由設定的incoming-message變更為指定的名稱
  3. channel: 變更輸出的頻道,要輸出給某個用戶則用「@用戶名稱」

以下把msg變數修改為額外欄位:

String msg = "{\"text\":\"Incoming Webhook 測試\", \n" +
  " \"icon_url\": \"http://localhost:8065/static/emoji/1f61c.png\", \n" +
  " \"username\":\"傳入的掛接\",\n" +
  " \"channel\": \"off-topic\"\n" +
  "}";

訊息輸出到指定的閒聊(off-topic)頻道:

send output

4. 使用附件格式

如果想要輸出更多格式,則可以再指訊息附件(attachments)欄位,attachments是個陣列,其內欄位定義可參考Message Attachments — Mattermost 4.10 documentation,範例如下;幾個欄位說明如下:

  • fallback: 彙總訊息的文字
  • color: 垂直的側邊條顏色
  • pretext: 附件之前的文字
String msg = "{\n" +
    "  \"text\": \"Incoming Webhook 測試\",\n" +
    "  \"icon_url\": \"http://localhost:8065/static/emoji/1f61c.png\",\n" +
    "  \"username\": \"傳入的掛接\",\n" +
    "  \"channel\": \"off-topic\",\n" +
    "  \"attachments\": [\n" +
    "    {\n" +
    "\"fallback\": \"訊息識別\",\n" +
    "\"color\": \"#ff0000\",\n" +
    "\"pretext\": \"pretext: 先導文字\",\n" +
    "\"author_name\": \"作者名稱\",\n" +
    "\"author_icon\": \"http://localhost:8065/static/emoji/1f61c.png\",\n" +
    "\"author_link\": \"http://jdev.tw/blog\",\n" +
    "\"title\": \"title: [分享] 濱野純訪談:為什麼 Google 接管開發 Git 2.0 了?\",\n" +
    "\"title_link\": \"http://jdev.tw/blog/5359/hamano-interview-git-2-0\",\n" +
    "\"text\": \"text: 訊息內容\",\n" +
    "\"image_url\": \"http://jdev.tw/blog/wp-content/uploads/2014/09/git-logo.png\",\n" +
    "\"fields\": [\n" +
    "  {\n" +
    "    \"short\": false,\n" +
    "    \"title\": \"長格式欄位\",\n" +
    "    \"value\": \"導讀:最近 Google 推出了 Git 協議的 2.0 版。\" \n" +
    "  },\n" +
    "  {\n" +
    "    \"short\": true,\n" +
    "    \"title\": \"短格式欄位1\",\n" +
    "    \"value\": \"短格式欄位1的內容描述\" \n" +
    "  },\n" +
    "  {\n" +
    "    \"short\": true,\n" +
    "    \"title\": \"短格式欄位2\",\n" +
    "    \"value\": \"短格式欄位2的內容描述\" \n" +
    "  },\n" +
    "  {\n" +
    "    \"short\": true,\n" +
    "    \"title\": \"短格式欄位3\",\n" +
    "    \"value\": \"短格式欄位3的內容描述\" \n" +
    "  }\n" +
    "]\n" +
    "    }\n" +
    "  ]\n" +
    "}";

attachments

附件還可以再加上actions欄位來定義互動式按鈕(Interactive Message Buttons),請待下回分解。

##

您可能也會有興趣的類似文章

SQL Server的outer apply使用範例

$
0
0

outer apply是SQL Server 2005後才提供的語法,可以用來取一個Subquery的最大值、最小值等單筆記錄,這種需求以前一般是用自訂函數來完成的。範例如下:

兩個資料表,主要資料表是作者 Authors,明細資料表是作品 Books,一個作者會有一到多個作品。下列是欄位定義:

create table Authors (
  AUTHOR varchar(50) not null primary key
);

create table Books (
  AUTHOR varchar(50) not null,
  TITLE varchar(200) not null,
  PUBLISH_DATE smalldatetime,
  primary key (AUTHOR, TITLE)
);

範例用金庸和古龍的幾本作品為例:

insert into AUTHORS values ('金庸');
insert into AUTHORS values ('古龍');

insert into BOOKS (AUTHOR, TITLE, PUBLISH_DATE) values ('金庸', '書劍恩仇錄', '1955-02-08');
insert into BOOKS (AUTHOR, TITLE, PUBLISH_DATE) values ('金庸', '碧血劍', '1956-01-01');
insert into BOOKS (AUTHOR, TITLE, PUBLISH_DATE) values ('金庸', '射鵰英雄傳', '1957-01-01');
insert into BOOKS (AUTHOR, TITLE, PUBLISH_DATE) values ('金庸', '雪山飛狐', '1959-02-09');
insert into BOOKS (AUTHOR, TITLE, PUBLISH_DATE) values ('金庸', '神鵰俠侶', '1959-05-20');

用left outer join會列出每名作者的所有作品記錄。

1

但我們的需求是找出每位作者最後刊載的作品,只要用outer apply就能輕鬆的找出。

2

##

您可能也會有興趣的類似文章

將Kindle電子書由簡體轉換為繁體的工具與步驟

$
0
0

最近在看一本長篇小說,陸續換了網路上的幾個版本,卻總是錯亂漏字、缺少標點等,忍受著看了幾段,終於受不了,只好去中國亞馬遜購買正式的Kindle版本,簡體字還算可以忍受,但沒想到標點符號竟然是半形的!看到快抓狂,只好花了點時間自力救濟,除了把標點符號換成全形外,順便把簡體替換成繁體,最後大費周章一番終於能好好的閱讀。我把操作步驟做了紀錄,希望對有相同困擾的讀友們有些許幫助。

步驟1. 購書並傳送給Kindle for PC

第一個步驟當然是買書了,在中亞買好後能指定傳送到那個設備,除了Kindle外,再額外傳送給電腦的Kindle for PC。

1

如果沒有傳送也沒關係,在Kindle for PC裡也會自動出現購買的電子書,按右鍵就能下載。檔案下載後便能在資料目錄裡找到電子書的.azw檔案,若不清楚書籍資料夾的話,由【工具】→【選項…】→【內容】裡找到路徑。

2

步驟2. 用Calibre編輯書籍

Calibre已經可以直接編輯.azw的檔案(Calibre會把.azw先轉成.epub後再編輯)。另一個編輯epub的工具是Sigil,若你習慣用它的話,先用Calibre把.azw轉成.epub,再用Sigil來編輯。Calibre的操作程序如下:

  1. Calibre的【加入書籍】把My Kindle Content裡找到的電子檔加入,加入書籍前請參考《移除Kindle DRM以複製電子書到另一部Kindle的作法》的說明,安裝Calibre的DeDRM外掛,Caliber才能開啟Kindle的電子書。
  2. 在該電子書上用右鍵→點選【編輯書籍】,下圖中【文字】項目下是part0000.html到part1047.html共1048個HTML檔

    3

  3. 在編輯書籍視窗裡輸入要替換的字元(例如把半形逗點換成全形),再把取代選項裡的操作範圍設定為【所有的文本文件】,再按〔替換所有〕,逐一把要變更的符號都取代完成後按儲存。如果只是要換標點符號則到此已大功告成,但若要轉換成繁體,則需要更多手續

    4

步驟3. 簡繁轉換

進入編輯書籍視窗後,找到.azw解開的暫存目錄(會是C:\Users\用戶帳號\AppData\Local\calibre-cache\ee\暫存目錄\a\00000-自動產生\text\part0003.html之類的內容,用Everything搜尋較快),把text目錄裡的檔案複製到另一個好找的資料夾,再用ConvertZ的純文字轉換來轉換新目錄裡的檔案(下圖的來源檔案是Z:\ebook\cn):由UTF-8簡體轉換成UTF-8繁體,按〔開始轉換〕執行變更操作

5

轉換完畢後查看目的地(上圖是Z:\ebook\tw)裡的檔案內容是否確實已轉換成繁體。

步驟4. 繼續編輯書籍,替換新檔

再使用Calibre的【編輯書籍】→【文字】項目,點選part0001.html,再〔Shift+Click〕最後一個part1047.html,保留第一個part0000.html,再按〔Del〕刪除選取的所有檔案,再按儲存。我們必須保留一個檔案,不然Calibre會出現儲存錯誤。

檔案刪除完畢後,由功能表【檔案】→【導入文件到書籍】,選擇步驟3的繁體目錄,Calibre會匯入目錄內的檔案到【文字】項目內,part0000.html的繁體檔名因重名會自動改名為part0000_1.html。刪除簡體的part0000.html後按儲存,離開編輯書籍視窗時若彈出確認儲存的對話窗,則選確定要儲存。

以上皆順利完成的話,繁體中文版本的檔案就完成了。

簡化步驟:用EmEditor全部替換標點符號

步驟2用編輯書籍的取代來變更標點符號的操作,每個符號都要執行一次,實在有點煩人,但若複製了HTML到新資料夾(Z:\ebook\cn)並轉換成繁體中文後(Z:\ebook\tw),可以用全部檔案替換的方法一次變更,我使用的是EmEditor的多檔取代巨集(巨集文字檔的檔案格式是Big5碼):

editor.ReplaceInFiles(",", ",", "z:\\ebook\\tw\\*.*", eeReplaceBackup, eeEncodingUTF8, "*.bak", "z:\\backup");
editor.ReplaceInFiles("!", "!", "z:\\ebook\\tw\\*.*", eeReplaceBackup, eeEncodingUTF8, "*.bak", "z:\\backup");
editor.ReplaceInFiles("‘", "「", "z:\\ebook\\tw\\*.*", eeReplaceBackup, eeEncodingUTF8, "*.bak", "z:\\backup");
editor.ReplaceInFiles("“", "「", "z:\\ebook\\tw\\*.*", eeReplaceBackup, eeEncodingUTF8, "*.bak", "z:\\backup");
editor.ReplaceInFiles("’", "」", "z:\\ebook\\tw\\*.*", eeReplaceBackup, eeEncodingUTF8, "*.bak", "z:\\backup");
editor.ReplaceInFiles("”", "」", "z:\\ebook\\tw\\*.*", eeReplaceBackup, eeEncodingUTF8, "*.bak", "z:\\backup");
editor.ReplaceInFiles(":", ":", "z:\\ebook\\tw\\*.*", eeReplaceBackup, eeEncodingUTF8, "*.bak", "z:\\backup");
editor.ReplaceInFiles("?", "?", "z:\\ebook\\tw\\*.*", eeReplaceBackup, eeEncodingUTF8, "*.bak", "z:\\backup");
editor.ReplaceInFiles(".", "。", "z:\\ebook\\tw\\*.*", eeReplaceBackup, eeEncodingUTF8, "*.bak", "z:\\backup");

使用到的軟體資訊

以下是文中使用到的工具列表:

  1. Kindle for PC
  2. Calibre 3.25
  3. 文字編輯:EmEditor
  4. 簡繁轉換:ConvertZ

##

您可能也會有興趣的類似文章

將Kobo樂天書城的電子書匯出供Kindle閱讀的操作步驟

$
0
0

Kobo樂天書城有著眾多的繁體中文書籍可以購買,但我只有Kindle可以使用,是否有方法能把Kobo的電子書存入Kindle來閱讀呢?只要照著本文的說明逐步操作,從此我們又多了一個購書的管道了。

步驟1. 到Kobo樂天書城購買並下載

我們可以到網站或安裝Kobo App以購買有興趣的電子書,登入網站有四種方式:樂天帳號、Kobo帳號、Facebook帳號和Google帳號,前二者是不同的帳號,務必確認正確。買書後到我的書籍就能看到購買的書籍,請點擊【···】並按下載

download

▼ 接著彈出下載檔案確認對話窗,下載的檔案格式是Adobe DRM EPUB,按下【下載檔案】即可。Kobo的電子書有兩種格式,Kobo閱讀器使用的是Kobo自己的數位版權檔案,另一種則是Adobe公司的數位版權檔,我們要使用的正是Adobe格式的檔案。下載存檔時預設的檔名是URLLink.acsm(acsm是Adobe Content Server Message的縮寫,代表此檔案是Adobe內容主機訊息),這個檔案是個含有下載網址的XML檔,透過這個XML檔我們才能下載到實際的電子書檔案。

download-drm

步驟2. 用Adobe Digital Editions下載檔案

URLLink.acsm必須使用Adobe Digital Editions開啟,到Adobe Digital Editions | Download下載並安裝,執行後開啟URLLink.acsm,系統會先下載再開啟書籍。

adobe digital editions

請閱讀看看是否已能正確看到內容,若正確則結束 Adobe Digital Editions,再用檔案總管找 C:\Users\用戶帳號\Documents\My Digital Editions資料夾裡的書籍.epub檔,將這個.epub檔案複製到另一個好找的資料夾(我複製到 Z:\ebook\adobe\目錄)。

步驟3. 以Calibre加入書籍並轉檔

  1. Convert Kobo Kepub to EPUB and Remove DRM下載Calibre的Obok DeDRM外掛(Obok是Kobo由右向左倒著唸),再從Calibre【偏好設定】→【進階】→【外掛】→【從檔案取得外掛】載入obok_plugin.zip
  2. 按Calibre的【加入書籍】
  3. 按Calibre的【轉換書籍】,因為我是透過Email寄檔給Kindle和手機的Kindle軟體接收,因此輸出格式選用MOBI(.AZW3無法郵寄)

    convert

  4. 轉換完畢後,點擊此書後按右鍵→【開啟包含的資料夾】就能找到轉換後的.mobi檔了。

  5. 參考將電子書檔案傳入Kindle與自動傳檔的方法使用Calibre轉換TXT電子書(含目錄)並傳送至Kindle Paperwhite操作全攻略將.mobi檔傳入Kindle

相關連結

##

您可能也會有興趣的類似文章

Kindle自訂字型操作步驟與簡轉繁字型連結

$
0
0

Kindle最新推出的5.9.6增加了自訂字型的功能,如果安裝了提供簡轉繁的字體,簡體書有八九成就能直接變正確的繁體,不用再手動轉檔,剩下的一成就是像「風範」仍然會是「風范」這種無法一個字對一個字轉換的詞了。即使不用簡轉繁字體,把字體替換成自己看得順眼的字型,也可讓Kindle變得更賞心悅目些。

5.9.6的升級請參考【教學】免越獄!Kindle 官方支援更換自訂字型! – New MobileLife 流動日報,只要把下載檔案放到Kindle根目錄、更新後重開機就可以了。雖然版本升級到5.9.6了,也不是所有的書都能自訂字型,只有支援KF8標準(.azw3和新的MOBI格式)的電子書才有自訂字型和變更粗細的設定選項,使用Calibre轉檔時,若輸出格式是MOBI,記得設定為New格式,才會有自訂字型選項。然而原本使用MOBI的原因是能透過Email自動傳檔給Kindle,New格式的MOBI檔卻無法再用Email傳檔了,這樣倒不如直接用.azw3算了。

字型檔下載連結

以下是幾個沒有版權問題、來自Google和Adobe的合作產品的字型檔,供網友們參考:

其他常見的還有方正黑體、文泉黑體等,因有版權問題就請自行去搜尋。

思源字型是一個字體家族,依字重分成特細、細、常規、加粗、特粗等不同檔案,通常只要使用常規(Regular)和粗體(Bold)就可以。關於字重的概念可以參考字体的字重是什么?关于设计中的字重这些事你需要知道! – 简书一文。

安裝字型

▼ 檔案準備好、Kindle接好USB,把檔案存入 fonts 資料夾就可以了(根目錄下的fonts,不是system/fonts),接著打開一本KF8格式的書,點擊主選單的【Aa】就能看到自訂字型選項:

Aa menu

▼ 【自定義】後方的就是選用的自訂字型,按下其右側的【>】會顯示放在 fonts 裡的所有字型,我們可以從中挑選。

fonts list

附帶一提,升級後已碰到幾次跳出書籍的狀況,所幸再點進去就能繼續閱讀…

error

##

您可能也會有興趣的類似文章

[Windows] 強化版的Alt-Tab Terminator讓你切換工作視窗更方便

$
0
0

Alt-Tab Terminator改良了Windows預設的切換視窗,不僅美化了畫面,也增加了更多操作的便利性。

alt-tab-terminator

按下〔Alt+Tab〕後出現在左側的是工作列的各個視窗的標題,右側則是視窗的縮圖,再按〔Alt+Tab〕可以向下移到到下一個視窗,或用上下鍵移動,右鍵功能表則有最大化、縮小到工作列、停止工作等選項。

相關連結

##

您可能也會有興趣的類似文章

[React-01] 使用IntelliJ IDEA學習React

$
0
0

重新學習React,直接使用IntelliJ IDEA當做編輯器。

0.前置動作:安裝nodejs與create-react-app模組

  • 下載並安裝 Node.js
  • 執行下列命令以安裝create-react-app模組,安裝後的create-react-app會在 nodejs安裝資料夾/node_modules 裡:
npm install -g create-react-app

1.功能表【File】→【New】→【Project…】
new project

▼ 依序輸入欄位值
new project dialog

▼ 開啟react1專案時會自動下載create-react-app所有需要的組件
create act app

可惜似乎是IDEA的問題,新建立的react1模組會跑到暫存目錄去,檢查一下Run側邊視窗:
tmp

如果確實產生到暫存目錄去,那麼自己開啟Terminal側邊視窗再輸入node.exe D:\UTIL\nodejs\node_modules\create-react-app\index.js react1,讓需要的檔案產生在專案目錄裡(d:\work\react1)。

▼ 相關組件安裝完成後,Run視窗會有【Happy hacking】與【Done】等訊息出現
open project

▼ 打開Terminal側邊欄視窗後,輸入 npm start 以啟動內含的Web server,用瀏覽器瀏覽 http://localhost:3000 就能看到create-react-app網頁了
npm start

▼ create-react-app第一個頁面
first page

2.修改App.js,加入Person元件
App.js是主要邏輯所在的檔案,預設內容如下:

import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';

class App extends Component {
  render() {
    return (
      <div className="App">
        <div className="App-header">
          <img src={logo} className="App-logo" alt="logo" />
          <h2>Welcome to React</h2>
        </div>
        <p className="App-intro">
          To get started, edit <code>src/App.js</code> and save to reload.
        </p>
      </div>
    );
  }
}
export default App;

修改程式在App-intro下方插入自訂的Person Component,因為尚未定義Person,因此網頁會出現'Person' is not defined的錯誤:

        <p className="App-intro">
          To get started, edit <code>src/App.js</code> and save to reload.
        </p>
        <Person name="王大明" age="10" />
        <Person name="李中同" age="20" />
        <Person name="林小美" age="30" />          

3.在IDEA的Project側邊視窗,於src節點按右鍵再選【New】→【File】,新增Person.js,輸入下列內容到Person.js。Person元件的最簡單形式是傳回JSX(JavaScript eXtension)格式的函數,為了解析JSX,因此必須匯入React模組,最後一行的export把Person.js模組裡的元件匯出,供App.js匯入使用:

import React from 'react';

function person(props) {
  return (
      <div className="Person">
        <p>I'm {props.name}! My age is {props.age}.</p>
      </div>
  )
}

export default person;

4.再修改App.js,加上import Person:

import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
import Person from './Person.js';

class App extends Component {
  render() {
    return (
      <div className="App">
        <div className="App-header">
          <img src={logo} className="App-logo" alt="logo" />
          <h2>Welcome to React</h2>
        </div>
        <p className="App-intro">
          To get started, edit <code>src/App.js</code> and save to reload.
        </p>
        <Person name="王大明" age="10" />
        <Person name="李中同" age="20" />
        <Person name="林小美" age="30" />
      </div>
    );
  }
}
export default App;

modified page

5.再於 src 節點新增Person.css,加入Person類別

.Person {
  display: inline-block;
  padding: 10px;
  margin: 10px;
  border: 1px solid #cccccc;
  box-shadow: 0 2px 5px #eeeeee;
}

再修改Person.js加上import ‘Person.css’:

import React from 'react';
import './Person.css';

const person = (props) => {
  return (
      <div className="Person">
        <p>I'm {props.name}! My age is {props.age}.</p>
      </div>
  )
};

export default person;

6.最終的頁面
result


##

您可能也會有興趣的類似文章


程式設計師做筆記的好朋友:Boostnote

$
0
0

Boostnote是專為程式設計師使用的開源Markdown筆記軟體,最近因為在Github超過8千顆星的專訪《GitHubリポジトリで8000スター獲得、人気OSS「Boostnote」オープンソース化の軌跡 – エンジニアHub|若手Webエンジニアのキャリアを考える!》而倍受矚目。以下是我在使用幾周後的一些觀察到的Boostnote特色心得。

使用介面

Boostnote使用介面和一般的筆記軟體雷同,主要切割成三大塊:最左側是資料夾分類區,中間是某資料夾裡的所有筆記項目,最右側就是筆記內容,筆記內容可切換操作模式:編輯/預覽共存或單一狀態,在單一狀態時若游標焦點進入則自動變成編輯區,游標移出就變成預覽,而為了專心書寫,也可以把編輯/預覽區放到最大。

編輯/預覽自動切換的功能對蒐集筆記過程的幫助很大,內容輸入到一段落後,只要把游標移出編輯區就自動變成預覽模式,可以馬上看到實際外觀而不用再按任何按鈕,對操作的有效性助益良多。

預覽模式下的程式碼右上角提供了複製按鈕,可以快速的拷貝需要參考的程式片段。

▼ 最右側是編輯/預覽並存,可按鈕切換

edit/preview

▼ 編輯/預覽單一模式,游標點入就是編輯,移出就是預覽

preview

▼ 放大狀態下的編輯模式

full edit

程式碼片段筆記

除了Markdown筆記,Boostnote的另一類筆記是程式碼片段(Snippets),專門用來蒐集需要保存的程式碼片段。

choose type

程式碼片段以多個分頁來存放不同的程式碼片段,這樣的使用介面方便我們存放一個專案裡的多個相關檔案,或一個檔案的多個不同版本備份,對日後的參考提供便利的學習歷程。

▼ 一個React專案裡的不同檔案:App.js、style.css等
react snippets

▼ App.js的不同版本集中在一個筆記裡,可檢視版本演進歷程或差異

multi ver

設定與儲存

Boostnote的設定操作簡單,使用介面與編輯區、預覽區的樣式主題皆可自行變更。

筆記的存放是儲存在指定的本地資料夾裡,資料夾會產生boostnote.json檔案與notes、attachments兩個子目錄,notes裡存放筆記項目檔案(一個筆記一個檔案),檔案是副檔名為.cson的文字檔,attachments子目錄則是存放筆記裡用〔Ctrl+V〕貼入的圖檔,依筆記的代碼為子目錄存放。我建議可以在Dropbox或Google Drive的主目錄下建立專用的筆記目錄,可以在不同電腦間同步。

由上可知boostnote未使用資料庫存放資料,因此系統的配置相對簡單,但若有大量筆記時會否影響執行效能則尚未可知。

結論與下載連結

除了做筆記,用Boostnote來寫文章也很方便,使用幾週以來很快就適應了,推薦朋友們試用。

##

您可能也會有興趣的類似文章

[jQuery元件] Fancybox 3使用備忘

$
0
0

Fancybox 3備忘

最近在修改舊網頁,將Fancybox 1.3升級到3.3.1,以下記錄版本間的異動差異。

引用

Fanycbox 3適用於jQuery 1.9.1+、jQuery 2+與jQuery 3+,以使用jQuery 3+為佳。

  • 使用CDN
https://cdnjs.cloudflare.com/ajax/libs/fancybox/3.3.1/jquery.fancybox.css

https://cdnjs.cloudflare.com/ajax/libs/fancybox/3.3.1/jquery.fancybox.js

https://cdnjs.cloudflare.com/ajax/libs/fancybox/3.3.1/jquery.fancybox.min.css

https://cdnjs.cloudflare.com/ajax/libs/fancybox/3.3.1/jquery.fancybox.min.js
npm install @fancyapps/fancybox --save

使用iframe開啟網頁的差異

以下是Fancybox 1.3的寫法:

      $.fancybox({
        type: 'iframe',
        modal: true,
        width: '80%',
        height: '80%',
        'autoScale': true,
        'transitionIn': 'fade',
        'transitionOut': 'fade',
        'href': '要使用的網頁?參數=參數值',
        onClosed: callBackFunction
      });

Fancybox 3的新寫法:

      $.fancybox.open({
        type: 'iframe',
        src: '要使用的網頁?參數=參數值',
        opts: {
          modal: true,
          afterShow: function (instance, current) {
            callBackFunction();
          }
        }
      });

另一個Fancybox 3的範例:

$.fancybox.open('<div class="message"><h2>Hello!</h2><p>You are awesome!</p></div>');

在開啟的網頁裡關閉自己的Fancybox 1.3寫法:

  $("#closeButton").click(function () {
    parent.$.fancybox.close();
  });

Fancybox 3寫法:

$("#closeButton").click(function () {
  parent.jQuery.fancybox.getInstance().close();
}  

注意事項

Fancybox 3只要用<a href就能產生開啟對話窗的效果,但href屬性一定要提供,例如:

  
    顯示項目
  

相關連結

##


您可能也會有興趣的類似文章

有風險的12種手機解鎖手勢

$
0
0

有研究報導百分之20的人使用了下列12種手機解鎖手勢之一,如果你也用了相同的手勢,為避免風險,盡快變更吧。

12-gestures

參考連結

##

您可能也會有興趣的類似文章

[Windows] 佔用資源更小的程式啟動器:Executor

$
0
0

我在2017年用Keypirinha取代用了很久的應用程式啟動器Executor(參見:來一杯卡琵莉亞雞尾酒吧。萬用的程式啟動器:Keypirinha),原因之一是Executor自從2013年後就沒再更新(最後版本是0.99.17b)…沒想到今年2018年七月它竟然又再度復活,推出了0.99.19b版!

Executor

復活的原因是因為它的開發工具Delphi釋出了能免費使用的Delphi XE 10.2.3 社群版(Delphi: Community Edition – Embarcadero),作者又能再度使用之故。

和Keypirinha相比,Executor佔用的記憶體小了幾乎一半,如果你只是要快速啟動程式的話,使用Executor是比較划算的選擇。

相關連結

##

您可能也會有興趣的類似文章

[分享] 北海道大地震經歷與我的思考-對系統的進步、效率,與脆弱的反思

$
0
0

來自北海道地震災區的第一手報導,作者對工業化帶來的進步提供了發人深省的反思。

北海道大地震經歷與我的思考 – Evonne Tsai – Medium

##

您可能也會有興趣的類似文章

[Windows] 快速終止應用程式視窗的工具:QuickKill

$
0
0

要讓某個應用程式結束工作的方法有好幾種,按視窗右上角的關閉、在工作列該程式圖示處用右鍵再選【關閉視窗】或開啟工作管理員找到該程式用右鍵再選【結束工作】等,通常都要兩三個步驟,而QuickKill只要按個〔Ctrl+Alt+Home〕就能立即結束應用程式(若此程式開啟了多個實例,全部一起被關閉)。

操作方法

  1. 點擊要關閉的視窗
  2. 按〔Ctrl+Alt+Home〕

相關連結

QuickKill是使用C#撰寫,以下是相關連結:

##

您可能也會有興趣的類似文章

精彩的科幻小說《老人的戰爭》系列

$
0
0

許久沒有看到這麼精彩的科幻小說了,9次入圍雨果獎、3次獲獎的美國科幻作家約翰·斯卡爾齊 (John Scalzi)以《老人的戰爭》(或譯為《垂暮之战》)聲名鵲起,最近一連看了《老人的戰爭》第一到第三部,精彩絕倫、情節環環相扣,又稍帶戲謔幽默,天馬行空、腦袋全開,令人欲罷不能。

可惜國內沒有翻譯,實體書只能找到簡體版,我讀的是Kindle電子書的五部合集。《老人的戰爭》系列第四部《佐伊的戰爭》和第五部《人類決裂》也已經可以在中國亞馬遜上找到。

後來找到的繁體版:博客來-垂暮戰爭,作者譯為約翰.史卡奇。沒想到好讀早就有譯本了:好讀-垂暮戰爭。可惜只有第一部。

▼ 日文版翻譯為《老人和宇宙》,似乎更貼切
old1

▼ 準備要讀的《佐伊的戰爭》
old2

相關連結

##

您可能也會有興趣的類似文章


文字檔轉換為Kindle MOBI檔的工具:m2m的Step-by-step操作步驟 (更新:直排功能)

$
0
0

最近利用閑暇時間把2015年寫的m2m.exe(參考:KindleGen與Markdown轉換為Mobi的Kindle電子書工具:m2m.exe)用Delphi XE 10.2.3改寫,把文字格式自動轉換為Markdown格式的功能也加進去,對於不熟悉正規運算式轉換語法的朋友們應該會覺得簡單很多。以下是m2m的簡單使用說明。

m2m.exe的用途

m2m.exe代表的是「Markdown To MOBI」的意思,不是物聯網的Machine-to-machine,主要用來把文字格式的電子書轉換成Kindle使用的.MOBI格式。

我們搜尋到的電子書通常是文字格式(.txt),為了更好的閱讀體驗便可以利用m2m.exe將之轉換為.MOBI格式,除了章節標題字體變大,也能有Kindle的目錄巡航等增強功能,產生出.MOBI檔後會複製到網路磁碟機資料夾(我用的是Dropbox)並上傳到網路磁碟,再用IFTTT.com的郵寄操作(由Dropbox傳送到Kindle的接檔信箱),最後Kindle就能收到電子書。

以下是逐步執行的操作步驟。

1. 準備好電子書

首先準備好要轉換的電子書文字檔(範例中使用的三國演義.txt可由此處下載)。

如果文字檔第一行是書名,第二行是作者,則讀檔時會自動填入輸入欄位。
01

2. 點選電子書檔案

執行m2m.exe,按書名輸入欄位右方的開啟按鈕並點選三國演義.txt,點選後書名輸入欄位會出現電子書的檔名路徑。

02

3. 開始讀檔

如果要轉換為Markdown格式則勾選【讀檔時轉換為Markdown格式】,若選用檔案已經轉換過則不勾選。按〔1.讀檔〕開始讀檔,有勾選轉換者一併轉換格式。

03

轉換章節標題的設定在安裝資料夾的m2m.ini,可以按右上方的齒輪按鈕用記事本開啟m2m.ini,找到 [RegularExpressions]:

[RegularExpressions]
^正文 (.*)=$1
^第(.*)章 (.*)=## 第$1章 $2
^第(.*)章(.*),(.*)=## 第$1章 $2·$3
^第(.*)章(.*),(.*)集=第$1章 $2·$3
^第(.*)卷 (.*) 第(.*)章 (.*)=## 第$1卷 $2 第$3章 $4
^第(.*)卷(.*)第(.*)章(.*)=## 第$1卷 $2 第$3章 $4
^第(.*)卷 (.*)=# 第$1卷 $2
^卷(.*) (.*) (.*)章 (.*)$=# 第$1卷 $2\n## 第$3章 $4
^第(.*)章 (.*),(.*)=## 第$1章 $2·$3
^第(.*)章 (.*),(.*)=## 第$1章 $2·$3
^第(.*)章 (.*)=## 第$1章 $2
^第(.*)章:(.*)=## 第$1章 $2
^第(.*)集 (.*)=## 第$1集 $2
^第(.*)節 (.*)=## 第$1節 $2
^第(.*)回 (.*)=## 第$1回 $2
^第(.*)回:(.*)=## 第$1回 $2
^楔子 (.*)=## 楔子 $1
(.*)本帖最後由(.*)編輯(.*)=
^更新時間(.*) 字數:(.*)$=

設定中使用到的運算式符號說明:

  1. ^表示每行開頭
  2. (.*)表示數目不定的任意文字,「第(.*回)」運算式則「第一回」、「第四十八回」等都符合
  3. 等號右邊的\$1、\$2表示等號左邊符合的第一個與第二個內容,例如「第一回」的「一」、「第四十八回」的「四十八」就是\$1
  4. ^第(.*)回:(.*)=## 第$1回 $2的意思是把符合等號左邊的運算式轉換成等號右邊的內容,例如文字內容「第四十八回:宴長江曹操賦詩,鎖戰船北軍用武」符合這個運算式,則「四十八」就是右邊的\$1,「宴長江曹操賦詩,鎖戰船北軍用武」就是\$2,轉換後就變成「## 第四十八回 宴長江曹操賦詩,鎖戰船北軍用武」;轉換後的兩個半形井號表示標題二,字體會變大

標題有個奇怪的問題,文字中有半形或全形逗點時,在.MOBI的內容會被截斷,例如「宴長江曹操賦詩,鎖戰船北軍用武」會變成「宴長江曹操賦詩,」或「宴長江曹操賦詩?」,因此m2m.exe會把標題中的逗點變成黑點以避開這個問題。

如果電子書的標題樣式不在現有的設定中,請自行依格式添加在後。

3.1. 轉直排與空兩格

0.03版增加了段落開頭插入兩個全形空白與直排功能,只要勾選就會產生對應的結果。

因為直排時有些標點符號無法正確的轉直,因此m2m.ini增加了轉換標點符號的設定,其中[SymbolReplace_Horizental]是轉換橫排的標點符號,包括半形逗點轉成全形逗點等,[SymbolReplace_Vertical]則是直排時的標點符號轉換,其中冒號必須換成橫的冒號,但宋體位置不太美觀,但黑體卻又正常…。

vertical

vertical2

4. 讀檔後

讀檔後在下方的訊息框會顯示執行訊息,若有勾選自動轉換Markdown,則會額外產生同名的.markdown檔案,按下勾選欄位右方的按鈕會以記事本開啟三國演義.markdown。

如果檢查.markdown後手動做了調整,那麼要重新選取檔案,選取三國演義.markdown,不勾選自動轉換,再按〔1.讀檔〕以重新讀入修改後的Markdown檔。

04

5. 產生設定檔

讀檔後按〔2.產生設定檔〕以產生需要的各式檔案,此時右下方會出現檢視設定檔的多個按鈕。

05

產生的檔案說明如下:

檔案 檔案範例 說明
書籍內容的HTML檔 mybook.html HTML是書籍本文的內容。一本書可以使用多個HTML檔,但為方便我只使用一個HTML檔
HTML使用的樣式表 style.css HTML檔若有使用CSS樣式就需要本檔
目錄的HTML檔 toc.html 形成目錄(Table of Contents, toc)的網頁內容
目錄的索引檔 toc.ncx Kindle 「前往」出現的選單(ncx是Navigation Control file for XML applications)
封面圖片 mybook.jpg 封面圖片可不使用,但缺少時KindleGen較不穩定
控制組合的OPF檔 mybook.opf OPF是Open Packaging Format,負責將上述檔案組合起來以形成最終的Mobi檔
執行的批次檔 mybook.bat 用來產生MOBI檔的批次檔,叫用kindlegen.exe並拷貝到輸出目錄

真正執行產生.MOBI的是mybook.bat,若有需要做其他操作的話,可以編輯安裝目錄裡的template.bat,自行修改內容,則重新產生的mybook.bat就會是修改後的內容。

6. 檢視產生的檔案

為確認需要的檔案都有正常產生,可點擊右下方的按鈕來檢視其內容,尤其是 toc.ncx 必須正確產生目錄標題,否則無法產生.MOBI檔。

06

7. 產生MOBI檔

最後按〔3.產生MOBI檔〕則會開啟命令提示字元(DOS視窗)執行mybook.bat,再以下列命令產生MOBI檔:

[安裝目錄]\kindlegen.exe mybook.opf -c1 -dont_append_source

kindlegen產生出的檔名固定為「mybook.mobi」,在mybook.bat裡複製到輸出目錄\書名_作者.mobi。

07

8. 檢視.MOBI檔

最後按右下角的預覽MOBI檔可以用設定的預覽程式來開啟輸出目錄裡的「書名_作者.mobi」。預覽程式必須另行安裝,可以用Kindle for PC或Kindle Previewer,透過m2m.ini設定好執行檔路徑。

08

9. 上傳到Kindle接收信箱

Kindle的【設置】→【我的帳戶】→【發送至Kindle 電子郵件地址】可以查到信箱,或由下列網址查詢:

  • 美國亞馬遜:https://www.amazon.com/myk
    amazon
  • 中國亞馬遜:https://z.cn/myk
    z.cn

<

p>瀏覽ifttt.com並登入後,搜尋「Send files from Dropbox to your Kindle」再設定成自己的Dropbox資料夾與接收信箱,日後只要把.MOBI輸出到Dropbox指定的資料夾,IFTTT.com就會自己寄信到Kindle接檔信箱。

  1. m2m.ini設定
    m2m.ini可以設定下列選項,以符合個別環境:

settings

設定參數 說明
KINDLEGEN 要指定其他位置的kindlegen.exe時使用,預設直接使用安裝目錄裡的檔
LEVEL2_MAX_COUNT 標題二章節的最多數目
OPTIONS 預設的壓縮等級
MOBI_FOLDER MOBI檔的輸出目錄
TEXT_FOLDER 電子書文字檔的存放目錄
HTML 讀mybok.html的編輯器
TEXT 讀文字檔的編輯器
MOBI 讀.MOBI檔的編輯器

如何由橫排改為直排

要產生成由上到下的直排

相關連結

版本 釋出日期 更新說明 下載連結
0.02 2018/09/29 由Lazarus改寫為Delphi XE 下載
0.03 2018/10/02 段落空兩格與直排 下載

##

您可能也會有興趣的類似文章

[Visual Studio Code] 手動建立[以Code開啟]的檔案總管右鍵功能表選項

$
0
0

如果在安裝Visual Studio Code時,沒有勾選將【以Code開啟】,或跟我一樣把Code安裝到Dropbox資料夾且到第二部電腦執行時,那麼事後要如何讓檔案總管右鍵功能表也能有以Code開啟的功能呢?

▼ 勾選〔以Code開啟〕讓檔案總管右鍵功能表出現選項
install

最簡單的方式就是執行下列登錄(open-with-code.reg):

Windows Registry Editor Version 5.00

[HKEY_CLASSES_ROOT\*\shell\Open with VS Code]
@="用VS Code編輯檔案"
"Icon"="D:\\util\\vscode\\Code.exe"

[HKEY_CLASSES_ROOT\*\shell\Open with VS Code\command]
@="D:\\util\\vscode\\code.exe \"%1\""

[HKEY_CLASSES_ROOT\Directory\shell\vscode]
@="用VS Code開啟為專案"
"Icon"="D:\\util\\vscode\\Code.exe"

[HKEY_CLASSES_ROOT\Directory\shell\vscode\command]
@="D:\\util\\vscode\\Code.exe \"%1\""

把.reg裡的Code.exe換成自己的Code安裝目錄,再執行.reg檔即可。

open with

##

您可能也會有興趣的類似文章

作業系統講古:跟水門事件一樣古老的Bug

$
0
0

這篇@foone的講古推真是有趣:@foone:跟水門事件一樣古老的Bug。文中娓娓道來為何Windows 10裡不能操作AUX.h、con.dom等檔案,也解釋了*NIX為何除了 /bin,也有/usr/bin的由來。

中文翻譯在此:bug 永存

##

您可能也會有興趣的類似文章

Windows 10 (1809更新)的時間軸功能-有很大的成長空間

$
0
0

Windows 10在做了1809更新後,會出現時間軸功能,時間軸會記錄開啟過的微軟應用程式,如果你平常經常使用如Office之類的微軟軟體的話,時間軸確實方便。如果使用的不是Windows 10 1809更新,也可試試我以前介紹過的用Nemo Documents快速找到最近編輯過的文件,二者功能類似。

首先按〔Win+Tab〕出現工作檢視,最右側是最近幾天的垂直捲軸,上下移動即可檢視不同日期的開啟過的文件或網頁(使用IE Edge開啟)。點擊放大鏡使可輸入過濾用的搜尋文字,例如輸入.doc則只列出MS Word檔案。

win tab

列入時間軸的網頁只限於IE Edge開啟的網址,若想要讓Google Chrome或Firefox開啟的網頁也加入時間軸的話,可以安裝Timeline Support外掛。

時間軸功能目前只能說是堪用,希望很快有更多的支援出現。

##

您可能也會有興趣的類似文章

彩蛋變地雷。Ant Design帶來啟示

$
0
0

螞蟻金服出身於阿里巴巴的支付寶,其資訊部門開源了一個名為Ant Design的JavaScript套件:「Ant Design 是蚂蚁金服开发和正在使用的一套企业级的前端设计语言和基于 React 的前端框架实现。 特性 企业级金融产品的交互语言和视觉体系。 丰富实用的 React UI 组件。」,在今年(2018)的聖誕節埋藏的一個耶誕節彩蛋不慎造成了地雷。

Ant Design

Ant Design的彩蛋讓按鈕上方出現雪堆,游標移入還會發出「Ho! Ho! Ho!」的笑聲。地雷被踩,所有使用了套件的網站就忙著拆除,對岸網上哀鴻遍野。

相關連結

##

您可能也會有興趣的類似文章

Viewing all 897 articles
Browse latest View live