How to embed button in wxDataViewListCtrl

Before creating wxDataViewListCtrl, it's better to detect some basic information about text size so that we can set the column width and height intelligently.

Here is the code:


void GuessRowSize(int* w, int* h) {
    //@see http://sourceforge.net/apps/trac/codelite/browser/trunk/LiteEditor/new_build_tab.cpp?rev=5804
    // Determine the row height
    wxBitmap tmpBmp(1, 1);
    wxMemoryDC memDc;
    memDc.SelectObject(tmpBmp);
    wxFont f = wxSystemSettings::GetFont(wxSYS_ANSI_FIXED_FONT);
    int xx, yy;
    memDc.GetTextExtent(wxT("Tp"), &xx, &yy, NULL, NULL, &f);

    //enough height for ICON
    *h=yyCreate(parent,id,wxDefaultPosition,wxDefaultSize);

int w,h;

GuessRowSize(&w,&h);

//hard code width may not be good, may be can use w ,h

AppendTextColumn(_T("Column 1"),wxDATAVIEW_CELL_INERT,200 /*width*/);

//must be called after Create()

ctrl->SetRowHeight(h+6);





// well I need provide button render by myself

class wxDataViewMyButtonRenderer: public wxDataViewCustomRenderer, public wxTimer

{

public:
    wxDataViewMyButtonRenderer( const wxString &varianttype = wxT("wxString"),
                              int align = wxDVR_DEFAULT_ALIGNMENT );

    virtual bool SetValue( const wxVariant &value );
    virtual bool GetValue( wxVariant &value ) const;

    virtual bool Render( wxRect, wxDC*, int);
    virtual wxSize GetSize() const;
    virtual void Notify();
    void SetParent(GalleryListView*);
    // Implementation only, don't use nor override
    virtual bool ActivateCell(const wxRect& rect,
        wxDataViewModel *model,
        const wxDataViewItem& item,
        unsigned int col,
        const wxMouseEvent *mouseEvent);


private:
    wxString m_value;
    bool m_button_clicked;
    wxRect m_cell_rect;
    GalleryListView* m_parent;


protected:
    DECLARE_DYNAMIC_CLASS_NO_COPY(wxDataViewMyButtonRenderer)
};

When user click one row, the ActivateCell is called, we can use some rect detect algorithm to find if the button rect is clicked.

There is no mouse up event handler! So I have to hack, basically start a wxTimer when button clicked and draw the button up effect after about 1 second in Notify(). That's why I ask wxDataViewMyButtonRenderer to inherit from wxTimer.

To draw the button up effect, I need ask the parent wxDataViewListCtrl to refresh itself, so that the button's Render() method has a chance to be called. That's why we need SetParent().

Here is the part of implementation:


bool

wxDataViewMyButtonRenderer::ActivateCell(const wxRect& rect,
    wxDataViewModel *model,
    const wxDataViewItem& item,
    unsigned int col,
    const wxMouseEvent *mouseEvent)
{
    wxDataViewListStore* store=(wxDataViewListStore*) model;

    if ( mouseEvent ) {
        if ( !wxRect(GetSize()).Contains(mouseEvent->GetPosition()) ){
            return false;
        }
        wxVariant item_value_pdf;
        store->GetValueByRow(item_value_pdf , store->GetRow(item),0);
        wxVariant item_value_created;
        store->GetValueByRow(item_value_created , store->GetRow(item),1);

        m_button_clicked=true;
        m_cell_rect=rect;
    } else {
        wxLogDebug(_T("Sorry, I don't handle keyboard"));
    }

    return true;
}



bool

wxDataViewMyButtonRenderer::Render( wxRect rect, wxDC *dc, int state )

{
    wxLogDebug(_T("Render called"));
    // Ensure that the check boxes always have at least the minimal required
    // size, otherwise DrawCheckBox() doesn't really work well. If this size is
    // greater than the rect size, the checkbox will be truncated but this is a
    // lesser evil.
    wxSize size = rect.GetSize();
    size.IncTo(GetSize());
    rect.SetSize(size);

    // draw button
    if(m_button_clicked==true && rect.Intersects(m_cell_rect)){
        //draw the button when clicked
        dc->SetBrush(wxBrush(wxColour(65, 150, 65), wxBRUSHSTYLE_SOLID));
        dc->SetPen( *wxBLACK_PEN );
        dc->DrawRectangle(rect);

        // draw button push down effect. since we cannot detect mouse up event, we use
        // timer to draw it
        const int time_to_button_up=350;
        StartOnce(time_to_button_up);
    } else {
        // draw normal button
        dc->SetBrush(wxBrush(wxColour(84, 174, 84), wxBRUSHSTYLE_SOLID));
        dc->SetPen( *wxBLACK_PEN );
        dc->DrawRectangle(rect);

        //draw inner white border
        rect.Deflate(1);
        dc->SetPen( *wxWHITE_PEN );
        dc->DrawRectangle(rect);
    }

    dc->SetTextForeground(*wxWHITE);
    dc->DrawLabel(m_value,wxRect(dc->GetTextExtent(m_value)).CentreIn(rect));

    return true;
}

popup function your cursor is in

Which Func Mode will display the current function name in the mode line.

But I can't use it.

It's because I reduce my mode-line into minimum to make it work with my tiny netbook.

Showing the function in header is also not possible because it conflicts with my color theme.

So I choose to display the function name in a popup.

Insert below code into ~/.emacs,


(autoload 'which-function "which-func")

(autoload 'popup-tip "popup")



(defun copy-yank-str (msg)
  (kill-new msg)
  (with-temp-buffer
    (insert msg)
    (shell-command-on-region (point-min) (point-max)
                             (cond
                              ((eq system-type 'cygwin) "putclip")
                              ((eq system-type 'darwin) "pbcopy")
                              (t "xsel -ib")
                              ))))


(defun popup-which-function ()
  (interactive)
  (let ((msg (which-function)))
    (popup-tip msg)
    (copy-yank-str msg)
    ))

The extra bonus is "popup-which-function" will also insert the function name into clipboard and kill ring.

The above code need package "popup.el" to be installed.

Screen shot: http://blog.binchen.org/wp-content/uploads/2014/04/wpid-pop-which-func-nq8.png

paste string from clipboard into minibuffer in Emacs

First, I find "Alt-Y" is easier to press when paste string into minibuffer than old "Shift+Insert". "Ctrl-V" is not supported in some terminals.

Second, intergrating some command line clipboard tool into Emacs is better than Emacs X clipboard. Command line tool works in any environment. For example, when you log into a remote server with ssh, your local computer could share clipboard with your Emacs in remote shell. Please note in this example, you need using X11 forward over ssh, usually it's already set up on server.

Here is the code:


(defun paste-from-x-clipboard()
  (interactive)
  (shell-command
   (cond
    (*cygwin* "getclip")
    (*is-a-mac* "pbpaste")
    (t "xsel -ob")
    )
   1)
  )


(defun my/paste-in-minibuffer ()
  (local-set-key (kbd "M-y") 'paste-from-x-clipboard)
  )


(add-hook 'minibuffer-setup-hook 'my/paste-in-minibuffer)

Upload emacs package to marmalade

Thanks to Sebastian Wiesner for providing a python script to upload package to http://marmalade-repo.org/.


sudo pip install requests keyring

curl -L https://raw.githubusercontent.com/lunaryorn/dotfiles/master/emacs/bin/marmalade-upload > ~/bin/marmalade-upload && chmod +x ~/bin/marmalade-upload

~/bin/marmalade-upload -h # see help

Please note if the same version already exists on server, I need delete it before uploading.

Use firefox in Emacs way

I use keysnail. it's a firefox addon to convert firefox into Emacs.

I install keysnail's own plugins "HoK" and "Tanything".

Here are the use cases of keysnail.

Click & Copy the links

Install the HoK.

Insert below code into ~/.keysnail.js:


#hook.setHook("PluginLoaded", function () {
    if (!plugins.hok) return;

    /* HoK 1.3.9+ requried */
    plugins.hok.pOptions.selector = plugins.hok.pOptions.selector
    /* feedly */
    + ", *[data-uri]" + ", *[data-selector-toggle]" + ", *[data-page-action]" + ", *[data-app-action]"
    /* google plus */
    + ", *[guidedhelpid]"
    /* twitter */
    + ", *[data-item-count]";
});



key.setGlobalKey(["C-c","C-f"], function (aEvent, aArg) {
        ext.exec("hok-start-foreground-mode", aArg);
}, "Hok - Foreground hint mode", true);



key.setGlobalKey(["C-c","C-b"], function (aEvent, aArg) {
        ext.exec("hok-start-background-mode", aArg);
}, "HoK - Background hint mode", true);



key.setGlobalKey(["C-c","C-y"], function (aEvent, aArg) {
        ext.exec("hok-yank-foreground-mode", aArg);
}, "HoK - Background hint mode", true);



key.setGlobalKey(["C-c","C-;"], function (aEvent, aArg) {
        ext.exec("hok-start-extended-mode", aArg);
}, "HoK - Extented hint mode", true);



key.setGlobalKey(["C-c", "C-e"], function (aEvent, aArg) {
        ext.exec("hok-start-continuous-mode", aArg);
}, "Start continuous HaH", true);


Now I can press "Ctrl-C Ctrl-F" to select the links I need click *with keyboard".

The links will be highlighted as below screen shot: http://blog.binchen.org/wp-content/uploads/2014/03/wpid-keysnail-hok-nq8.png

I just need press the highlighed hint to actually click the link.

Copy the link into clipboard is also easy. I press "C-c C-y" and similar UI will be displayed. I press the hint above to finish the operation.

Switch tab

Install the Tanything.

Insert below code into ~/.keysnail.js:


key.setGlobalKey(["C-c", "C-a"], function (ev, arg) {
  ext.exec("tanything", arg);
}, "view all tabs", true);

Press "Ctrl-C Ctrl-A", you got below UI: http://blog.binchen.org/wp-content/uploads/2014/03/keysnail-tanything-nq8.png

Tanything will locate the tab by finding match in web page's title or URL.

Debug Emacs Lisp code the hard way

I met some issue when using helm several days ago.

With the help from Michael Heerdegen, I can locate the line error message is dumped.

But the problem is I cannot get the backtrace at all.

So I insert some backtrace printing code above that line and "M-x eval-buffer":


(with-output-to-temp-buffer "backtrace-output"
  (let ((var 1))
    (save-excursion
      (setq var (eval '(progn
                         (1+ var)
                         (list 'testing (backtrace))))))))

It turns out that some third party package I installed changes the emacs variable "display-buffer-function". I guess that's why the backtrace is blocked. Because backtrace is usually dumped into a backtrace buffer. And backtrace buffer's is actually influenced by the variable.

How to use ctags in Emacs effectively

Exuberant Ctags is a code navigation tool. It supports many language and could be integrated into Emacs well.

Please read EmacsWiki for basic usage.

I will talk about how I manage my ctags.

Basically ctags will produce a index file with file name TAGS. The full path of TAGS will be stored in a global list "tags-table-list".

An example of tags-table-list:


(setq tags-table-list '("~/wxWidgets-master/TAGS" "~/projs/Loris/src/desktop/TAGS"))

Every time we you "M-x find-tag", the TAGS file in above list will be read from the scratch to locate the definition of the symbol under cursor.

Here is my strategy to manage TAGS automatically:

  • I hard coded full path of TAGS in .emacs because I usually don't change project path.
  • In major mode hook like c++-mode-hook or js2-mode-hook I will check the directory path of current file. If it contains certain string, I suppose the file belong to certain project.
  • Then I will create TAGS for that project if needed
  • Every time when I save the file, I may update TAGS according to the value of tags-table-list.

Here is the code:


(defun my-project-name-contains-substring (REGEX)
  (let ((dir (if (buffer-file-name)
                 (file-name-directory (buffer-file-name))
               "")))
    (string-match-p REGEX dir)))


(defun my-create-tags-if-needed (SRC-DIR &optional FORCE)
  "return the full path of tags file"
  (let ((dir (file-name-as-directory (file-truename SRC-DIR)) )
       file)
    (setq file (concat dir "TAGS"))
    (when (or FORCE (not (file-exists-p file)))
      (message "Creating TAGS in %s ..." dir)
      (shell-command
       (format "ctags -f %s -e -R %s" file dir))
      )
    file
    ))


(defvar my-tags-updated-time nil)



(defun my-update-tags ()
  (interactive)
  "check the tags in tags-table-list and re-create it"
  (dolist (tag tags-table-list)
    (my-create-tags-if-needed (file-name-directory tag) t)
    ))


(defun my-auto-update-tags-when-save ()
  (interactive)
  (cond
   ((not my-tags-updated-time)
    (setq my-tags-updated-time (current-time)))
   ((< (- (float-time (current-time)) (float-time my-tags-updated-time)) 300)
    ;; < 300 seconds
    ;; do nothing
    )
   (t
    (setq my-tags-updated-time (current-time))
    (my-update-tags)
    (message "updated tags after %d seconds." (- (float-time (current-time))  (float-time my-tags-updated-time)))
    )
   ))


(defun my-setup-develop-environment ()
    (when (my-project-name-contains-substring "Loris")
      (cond
       ((my-project-name-contains-substring "src/desktop")
        ;; C++ project don't need html tags
        (setq tags-table-list (list
                               (my-create-tags-if-needed
                                (concat (file-name-as-directory (getenv "WXWIN")) "include"))
                               (my-create-tags-if-needed "~/projs/Loris/loris/src/desktop")))
        )
       ((my-project-name-contains-substring "src/html")
        ;; html project donot need C++ tags
        (setq tags-table-list (list (my-create-tags-if-needed "~/projs/Loris/loris/src/html")))
        ))))


(add-hook 'after-save-hook 'my-auto-update-tags-when-save)

(add-hook 'js2-mode-hook 'my-setup-develop-environment)

(add-hook 'web-mode-hook 'my-setup-develop-environment)

(add-hook 'c++-mode-hook 'my-setup-develop-environment)

(add-hook 'c-mode-hook 'my-setup-develop-environment)

UPDATE: There is some discussion at Google Plus about using ctags. Kaushal Modi recommended three emacs plugins:

  1. ctags-update
  2. etags-table
  3. etags-select

I tried these three plugins. ctags-update and etags-table duplicate my above elisp code. I prefer my own code because it's simpler and totally controllable. For example, the fact that I need only care about only one global variable tags-table-list makes my code shorter.

But I do like etags-select, it provide better UI for finding tag and I will use it from now on.

Hack wordpress php and make cdnjs.com host js

For jquery.js, see http://rk.md/2012/cdnjs-scripts-without-plugin-wordpress/.

I added below code into bottom of functions.php (Appearance => Editor):


add_action('wp_enqueue_scripts', 'CDNJS_scripts');

function CDNJS_scripts() 

{

wp_deregister_script('jquery');

wp_register_script('jquery','http://cdnjs.cloudflare.com/ajax/libs/jquery/1.10.2/jquery.min.js');

wp_enqueue_script('jquery');

} 

For js from SyntaxHighlighter Evolved (Plugins => Installed Plugins => Edit):


diff --git a/syntaxhighlighter.php b/syntaxhighlighter.php

index db8c668..e41ec12 100644

--- a/syntaxhighlighter.php

+++ b/syntaxhighlighter.php

@@ -117,30 +117,30 @@ class SyntaxHighlighter {
        }

        // Register brush scripts
-       wp_register_script( 'syntaxhighlighter-core',             plugins_url('syntaxhighlighter/' . $this-&gt;shfolder . '/scripts/shCore.js'),            array(),                         $this-&gt;agshver );

-       wp_register_script( 'syntaxhighlighter-brush-as3',        plugins_url('syntaxhighlighter/' . $this-&gt;shfolder . '/scripts/shBrushAS3.js'),        array('syntaxhighlighter-core'), $this-&gt;agshver );

-       wp_register_script( 'syntaxhighlighter-brush-bash',       plugins_url('syntaxhighlighter/' . $this-&gt;shfolder . '/scripts/shBrushBash.js'),       array('syntaxhighlighter-core'), $this-&gt;agshver );

-       wp_register_script( 'syntaxhighlighter-brush-coldfusion', plugins_url('syntaxhighlighter/' . $this-&gt;shfolder . '/scripts/shBrushColdFusion.js'), array('syntaxhighlighter-core'), $this-&gt;agshver );

-       wp_register_script( 'syntaxhighlighter-brush-cpp',        plugins_url('syntaxhighlighter/' . $this-&gt;shfolder . '/scripts/shBrushCpp.js'),        array('syntaxhighlighter-core'), $this-&gt;agshver );

-       wp_register_script( 'syntaxhighlighter-brush-csharp',     plugins_url('syntaxhighlighter/' . $this-&gt;shfolder . '/scripts/shBrushCSharp.js'),     array('syntaxhighlighter-core'), $this-&gt;agshver );

-       wp_register_script( 'syntaxhighlighter-brush-css',        plugins_url('syntaxhighlighter/' . $this-&gt;shfolder . '/scripts/shBrushCss.js'),        array('syntaxhighlighter-core'), $this-&gt;agshver );

-       wp_register_script( 'syntaxhighlighter-brush-delphi',     plugins_url('syntaxhighlighter/' . $this-&gt;shfolder . '/scripts/shBrushDelphi.js'),     array('syntaxhighlighter-core'), $this-&gt;agshver );

-       wp_register_script( 'syntaxhighlighter-brush-diff',       plugins_url('syntaxhighlighter/' . $this-&gt;shfolder . '/scripts/shBrushDiff.js'),       array('syntaxhighlighter-core'), $this-&gt;agshver );

-       wp_register_script( 'syntaxhighlighter-brush-erlang',     plugins_url('syntaxhighlighter/' . $this-&gt;shfolder . '/scripts/shBrushErlang.js'),     array('syntaxhighlighter-core'), $this-&gt;agshver );

-       wp_register_script( 'syntaxhighlighter-brush-groovy',     plugins_url('syntaxhighlighter/' . $this-&gt;shfolder . '/scripts/shBrushGroovy.js'),     array('syntaxhighlighter-core'), $this-&gt;agshver );

-       wp_register_script( 'syntaxhighlighter-brush-java',       plugins_url('syntaxhighlighter/' . $this-&gt;shfolder . '/scripts/shBrushJava.js'),       array('syntaxhighlighter-core'), $this-&gt;agshver );

-       wp_register_script( 'syntaxhighlighter-brush-javafx',     plugins_url('syntaxhighlighter/' . $this-&gt;shfolder . '/scripts/shBrushJavaFX.js'),     array('syntaxhighlighter-core'), $this-&gt;agshver );

-       wp_register_script( 'syntaxhighlighter-brush-jscript',    plugins_url('syntaxhighlighter/' . $this-&gt;shfolder . '/scripts/shBrushJScript.js'),    array('syntaxhighlighter-core'), $this-&gt;agshver );

-       wp_register_script( 'syntaxhighlighter-brush-perl',       plugins_url('syntaxhighlighter/' . $this-&gt;shfolder . '/scripts/shBrushPerl.js'),       array('syntaxhighlighter-core'), $this-&gt;agshver );

-       wp_register_script( 'syntaxhighlighter-brush-php',        plugins_url('syntaxhighlighter/' . $this-&gt;shfolder . '/scripts/shBrushPhp.js'),        array('syntaxhighlighter-core'), $this-&gt;agshver );

-       wp_register_script( 'syntaxhighlighter-brush-plain',      plugins_url('syntaxhighlighter/' . $this-&gt;shfolder . '/scripts/shBrushPlain.js'),      array('syntaxhighlighter-core'), $this-&gt;agshver );

-       wp_register_script( 'syntaxhighlighter-brush-powershell', plugins_url('syntaxhighlighter/' . $this-&gt;shfolder . '/scripts/shBrushPowerShell.js'), array('syntaxhighlighter-core'), $this-&gt;agshver );

-       wp_register_script( 'syntaxhighlighter-brush-python',     plugins_url('syntaxhighlighter/' . $this-&gt;shfolder . '/scripts/shBrushPython.js'),     array('syntaxhighlighter-core'), $this-&gt;agshver );

-       wp_register_script( 'syntaxhighlighter-brush-ruby',       plugins_url('syntaxhighlighter/' . $this-&gt;shfolder . '/scripts/shBrushRuby.js'),       array('syntaxhighlighter-core'), $this-&gt;agshver );

-       wp_register_script( 'syntaxhighlighter-brush-scala',      plugins_url('syntaxhighlighter/' . $this-&gt;shfolder . '/scripts/shBrushScala.js'),      array('syntaxhighlighter-core'), $this-&gt;agshver );

-       wp_register_script( 'syntaxhighlighter-brush-sql',        plugins_url('syntaxhighlighter/' . $this-&gt;shfolder . '/scripts/shBrushSql.js'),        array('syntaxhighlighter-core'), $this-&gt;agshver );

-       wp_register_script( 'syntaxhighlighter-brush-vb',         plugins_url('syntaxhighlighter/' . $this-&gt;shfolder . '/scripts/shBrushVb.js'),         array('syntaxhighlighter-core'), $this-&gt;agshver );

-       wp_register_script( 'syntaxhighlighter-brush-xml',        plugins_url('syntaxhighlighter/' . $this-&gt;shfolder . '/scripts/shBrushXml.js'),        array('syntaxhighlighter-core'), $this-&gt;agshver );

+       wp_register_script( 'syntaxhighlighter-core',             '//cdnjs.cloudflare.com/ajax/libs/SyntaxHighlighter/3.0.83/scripts/shCore.js',            array(),                         $this-&gt;agshver );

+       wp_register_script( 'syntaxhighlighter-brush-as3',        '//cdnjs.cloudflare.com/ajax/libs/SyntaxHighlighter/3.0.83/scripts/shBrushAS3.js',        array('syntaxhighlighter-core'), $this-&gt;agshver );

+       wp_register_script( 'syntaxhighlighter-brush-bash',       '//cdnjs.cloudflare.com/ajax/libs/SyntaxHighlighter/3.0.83/scripts/shBrushBash.js',       array('syntaxhighlighter-core'), $this-&gt;agshver );

+       wp_register_script( 'syntaxhighlighter-brush-coldfusion', '//cdnjs.cloudflare.com/ajax/libs/SyntaxHighlighter/3.0.83/scripts/shBrushColdFusion.js', array('syntaxhighlighter-core'), $this-&gt;agshver );

+       wp_register_script( 'syntaxhighlighter-brush-cpp',        '//cdnjs.cloudflare.com/ajax/libs/SyntaxHighlighter/3.0.83/scripts/shBrushCpp.js',        array('syntaxhighlighter-core'), $this-&gt;agshver );

+       wp_register_script( 'syntaxhighlighter-brush-csharp',     '//cdnjs.cloudflare.com/ajax/libs/SyntaxHighlighter/3.0.83/scripts/shBrushCSharp.js',     array('syntaxhighlighter-core'), $this-&gt;agshver );

+       wp_register_script( 'syntaxhighlighter-brush-css',        '//cdnjs.cloudflare.com/ajax/libs/SyntaxHighlighter/3.0.83/scripts/shBrushCss.js',        array('syntaxhighlighter-core'), $this-&gt;agshver );

+       wp_register_script( 'syntaxhighlighter-brush-delphi',     '//cdnjs.cloudflare.com/ajax/libs/SyntaxHighlighter/3.0.83/scripts/shBrushDelphi.js',     array('syntaxhighlighter-core'), $this-&gt;agshver );

+       wp_register_script( 'syntaxhighlighter-brush-diff',       '//cdnjs.cloudflare.com/ajax/libs/SyntaxHighlighter/3.0.83/scripts/shBrushDiff.js',       array('syntaxhighlighter-core'), $this-&gt;agshver );

+       wp_register_script( 'syntaxhighlighter-brush-erlang',     '//cdnjs.cloudflare.com/ajax/libs/SyntaxHighlighter/3.0.83/scripts/shBrushErlang.js',     array('syntaxhighlighter-core'), $this-&gt;agshver );

+       wp_register_script( 'syntaxhighlighter-brush-groovy',     '//cdnjs.cloudflare.com/ajax/libs/SyntaxHighlighter/3.0.83/scripts/shBrushGroovy.js',     array('syntaxhighlighter-core'), $this-&gt;agshver );

+       wp_register_script( 'syntaxhighlighter-brush-java',       '//cdnjs.cloudflare.com/ajax/libs/SyntaxHighlighter/3.0.83/scripts/shBrushJava.js',       array('syntaxhighlighter-core'), $this-&gt;agshver );

+       wp_register_script( 'syntaxhighlighter-brush-javafx',     '//cdnjs.cloudflare.com/ajax/libs/SyntaxHighlighter/3.0.83/scripts/shBrushJavaFX.js',     array('syntaxhighlighter-core'), $this-&gt;agshver );

+       wp_register_script( 'syntaxhighlighter-brush-jscript',    '//cdnjs.cloudflare.com/ajax/libs/SyntaxHighlighter/3.0.83/scripts/shBrushJScript.js',    array('syntaxhighlighter-core'), $this-&gt;agshver );

+       wp_register_script( 'syntaxhighlighter-brush-perl',       '//cdnjs.cloudflare.com/ajax/libs/SyntaxHighlighter/3.0.83/scripts/shBrushPerl.js',       array('syntaxhighlighter-core'), $this-&gt;agshver );

+       wp_register_script( 'syntaxhighlighter-brush-php',        '//cdnjs.cloudflare.com/ajax/libs/SyntaxHighlighter/3.0.83/scripts/shBrushPhp.js',        array('syntaxhighlighter-core'), $this-&gt;agshver );

+       wp_register_script( 'syntaxhighlighter-brush-plain',      '//cdnjs.cloudflare.com/ajax/libs/SyntaxHighlighter/3.0.83/scripts/shBrushPlain.js',      array('syntaxhighlighter-core'), $this-&gt;agshver );

+       wp_register_script( 'syntaxhighlighter-brush-powershell', '//cdnjs.cloudflare.com/ajax/libs/SyntaxHighlighter/3.0.83/scripts/shBrushPowerShell.js', array('syntaxhighlighter-core'), $this-&gt;agshver );

+       wp_register_script( 'syntaxhighlighter-brush-python',     '//cdnjs.cloudflare.com/ajax/libs/SyntaxHighlighter/3.0.83/scripts/shBrushPython.js',     array('syntaxhighlighter-core'), $this-&gt;agshver );

+       wp_register_script( 'syntaxhighlighter-brush-ruby',       '//cdnjs.cloudflare.com/ajax/libs/SyntaxHighlighter/3.0.83/scripts/shBrushRuby.js',       array('syntaxhighlighter-core'), $this-&gt;agshver );

+       wp_register_script( 'syntaxhighlighter-brush-scala',      '//cdnjs.cloudflare.com/ajax/libs/SyntaxHighlighter/3.0.83/scripts/shBrushScala.js',      array('syntaxh


diff --git a/syntaxhighlighter.php b/syntaxhighlighter.php

index db8c668..e41ec12 100644

--- a/syntaxhighlighter.php

+++ b/syntaxhighlighter.php

@@ -117,30 +117,30 @@ class SyntaxHighlighter {
        }

        // Register brush scripts
-       wp_register_script( 'syntaxhighlighter-core',             plugins_url('syntaxhighlighter/' . $this->shfolder . '/scripts/shCore.js'),            array(),                         $this->agshver );

-       wp_register_script( 'syntaxhighlighter-brush-as3',        plugins_url('syntaxhighlighter/' . $this->shfolder . '/scripts/shBrushAS3.js'),        array('syntaxhighlighter-core'), $this->agshver );

-       wp_register_script( 'syntaxhighlighter-brush-bash',       plugins_url('syntaxhighlighter/' . $this->shfolder . '/scripts/shBrushBash.js'),       array('syntaxhighlighter-core'), $this->agshver );

-       wp_register_script( 'syntaxhighlighter-brush-coldfusion', plugins_url('syntaxhighlighter/' . $this->shfolder . '/scripts/shBrushColdFusion.js'), array('syntaxhighlighter-core'), $this->agshver );

-       wp_register_script( 'syntaxhighlighter-brush-cpp',        plugins_url('syntaxhighlighter/' . $this->shfolder . '/scripts/shBrushCpp.js'),        array('syntaxhighlighter-core'), $this->agshver );

-       wp_register_script( 'syntaxhighlighter-brush-csharp',     plugins_url('syntaxhighlighter/' . $this->shfolder . '/scripts/shBrushCSharp.js'),     array('syntaxhighlighter-core'), $this->agshver );

-       wp_register_script( 'syntaxhighlighter-brush-css',        plugins_url('syntaxhighlighter/' . $this->shfolder . '/scripts/shBrushCss.js'),        array('syntaxhighlighter-core'), $this->agshver );

-       wp_register_script( 'syntaxhighlighter-brush-delphi',     plugins_url('syntaxhighlighter/' . $this->shfolder . '/scripts/shBrushDelphi.js'),     array('syntaxhighlighter-core'), $this->agshver );

-       wp_register_script( 'syntaxhighlighter-brush-diff',       plugins_url('syntaxhighlighter/' . $this->shfolder . '/scripts/shBrushDiff.js'),       array('syntaxhighlighter-core'), $this->agshver );

-       wp_register_script( 'syntaxhighlighter-brush-erlang',     plugins_url('syntaxhighlighter/' . $this->shfolder . '/scripts/shBrushErlang.js'),     array('syntaxhighlighter-core'), $this->agshver );

-       wp_register_script( 'syntaxhighlighter-brush-groovy',     plugins_url('syntaxhighlighter/' . $this->shfolder . '/scripts/shBrushGroovy.js'),     array('syntaxhighlighter-core'), $this->agshver );

-       wp_register_script( 'syntaxhighlighter-brush-java',       plugins_url('syntaxhighlighter/' . $this->shfolder . '/scripts/shBrushJava.js'),       array('syntaxhighlighter-core'), $this->agshver );

-       wp_register_script( 'syntaxhighlighter-brush-javafx',     plugins_url('syntaxhighlighter/' . $this->shfolder . '/scripts/shBrushJavaFX.js'),     array('syntaxhighlighter-core'), $this->agshver );

-       wp_register_script( 'syntaxhighlighter-brush-jscript',    plugins_url('syntaxhighlighter/' . $this->shfolder . '/scripts/shBrushJScript.js'),    array('syntaxhighlighter-core'), $this->agshver );

-       wp_register_script( 'syntaxhighlighter-brush-perl',       plugins_url('syntaxhighlighter/' . $this->shfolder . '/scripts/shBrushPerl.js'),       array('syntaxhighlighter-core'), $this->agshver );

-       wp_register_script( 'syntaxhighlighter-brush-php',        plugins_url('syntaxhighlighter/' . $this->shfolder . '/scripts/shBrushPhp.js'),        array('syntaxhighlighter-core'), $this->agshver );

-       wp_register_script( 'syntaxhighlighter-brush-plain',      plugins_url('syntaxhighlighter/' . $this->shfolder . '/scripts/shBrushPlain.js'),      array('syntaxhighlighter-core'), $this->agshver );

-       wp_register_script( 'syntaxhighlighter-brush-powershell', plugins_url('syntaxhighlighter/' . $this->shfolder . '/scripts/shBrushPowerShell.js'), array('syntaxhighlighter-core'), $this->agshver );

-       wp_register_script( 'syntaxhighlighter-brush-python',     plugins_url('syntaxhighlighter/' . $this->shfolder . '/scripts/shBrushPython.js'),     array('syntaxhighlighter-core'), $this->agshver );

-       wp_register_script( 'syntaxhighlighter-brush-ruby',       plugins_url('syntaxhighlighter/' . $this->shfolder . '/scripts/shBrushRuby.js'),       array('syntaxhighlighter-core'), $this->agshver );

-       wp_register_script( 'syntaxhighlighter-brush-scala',      plugins_url('syntaxhighlighter/' . $this->shfolder . '/scripts/shBrushScala.js'),      array('syntaxhighlighter-core'), $this->agshver );

-       wp_register_script( 'syntaxhighlighter-brush-sql',        plugins_url('syntaxhighlighter/' . $this->shfolder . '/scripts/shBrushSql.js'),        array('syntaxhighlighter-core'), $this->agshver );

-       wp_register_script( 'syntaxhighlighter-brush-vb',         plugins_url('syntaxhighlighter/' . $this->shfolder . '/scripts/shBrushVb.js'),         array('syntaxhighlighter-core'), $this->agshver );

-       wp_register_script( 'syntaxhighlighter-brush-xml',        plugins_url('syntaxhighlighter/' . $this->shfolder . '/scripts/shBrushXml.js'),        array('syntaxhighlighter-core'), $this->agshver );

+       wp_register_script( 'syntaxhighlighter-core',             '//cdnjs.cloudflare.com/ajax/libs/SyntaxHighlighter/3.0.83/scripts/shCore.js',            array(),                         $this->agshver );

+       wp_register_script( 'syntaxhighlighter-brush-as3',        '//cdnjs.cloudflare.com/ajax/libs/SyntaxHighlighter/3.0.83/scripts/shBrushAS3.js',        array('syntaxhighlighter-core'), $this->agshver );

+       wp_register_script( 'syntaxhighlighter-brush-bash',       '//cdnjs.cloudflare.com/ajax/libs/SyntaxHighlighter/3.0.83/scripts/shBrushBash.js',       array('syntaxhighlighter-core'), $this->agshver );

+       wp_register_script( 'syntaxhighlighter-brush-coldfusion', '//cdnjs.cloudflare.com/ajax/libs/SyntaxHighlighter/3.0.83/scripts/shBrushColdFusion.js', array('syntaxhighlighter-core'), $this->agshver );

+       wp_register_script( 'syntaxhighlighter-brush-cpp',        '//cdnjs.cloudflare.com/ajax/libs/SyntaxHighlighter/3.0.83/scripts/shBrushCpp.js',        array('syntaxhighlighter-core'), $this->agshver );

+       wp_register_script( 'syntaxhighlighter-brush-csharp',     '//cdnjs.cloudflare.com/ajax/libs/SyntaxHighlighter/3.0.83/scripts/shBrushCSharp.js',     array('syntaxhighlighter-core'), $this->agshver );

+       wp_register_script( 'syntaxhighlighter-brush-css',        '//cdnjs.cloudflare.com/ajax/libs/SyntaxHighlighter/3.0.83/scripts/shBrushCss.js',        array('syntaxhighlighter-core'), $this->agshver );

+       wp_register_script( 'syntaxhighlighter-brush-delphi',     '//cdnjs.cloudflare.com/ajax/libs/SyntaxHighlighter/3.0.83/scripts/shBrushDelphi.js',     array('syntaxhighlighter-core'), $this->agshver );

+       wp_register_script( 'syntaxhighlighter-brush-diff',       '//cdnjs.cloudflare.com/ajax/libs/SyntaxHighlighter/3.0.83/scripts/shBrushDiff.js',       array('syntaxhighlighter-core'), $this->agshver );

+       wp_register_script( 'syntaxhighlighter-brush-erlang',     '//cdnjs.cloudflare.com/ajax/libs/SyntaxHighlighter/3.0.83/scripts/shBrushErlang.js',     array('syntaxhighlighter-core'), $this->agshver );

+       wp_register_script( 'syntaxhighlighter-brush-groovy',     '//cdnjs.cloudflare.com/ajax/libs/SyntaxHighlighter/3.0.83/scripts/shBrushGroovy.js',     array('syntaxhighlighter-core'), $this->agshver );

+       wp_register_script( 'syntaxhighlighter-brush-java',       '//cdnjs.cloudflare.com/ajax/libs/SyntaxHighlighter/3.0.83/scripts/shBrushJava.js',       array('syntaxhighlighter-core'), $this->agshver );

+       wp_register_script( 'syntaxhighlighter-brush-javafx',     '//cdnjs.cloudflare.com/ajax/libs/SyntaxHighlighter/3.0.83/scripts/shBrushJavaFX.js',     array('syntaxhighlighter-core'), $this->agshver );

+       wp_register_script( 'syntaxhighlighter-brush-jscript',    '//cdnjs.cloudflare.com/ajax/libs/SyntaxHighlighter/3.0.83/scripts/shBrushJScript.js',    array('syntaxhighlighter-core'), $this->agshver );

+       wp_register_script( 'syntaxhighlighter-brush-perl',       '//cdnjs.cloudflare.com/ajax/libs/SyntaxHighlighter/3.0.83/scripts/shBrushPerl.js',       array('syntaxhighlighter-core'), $this->agshver );

+       wp_register_script( 'syntaxhighlighter-brush-php',        '//cdnjs.cloudflare.com/ajax/libs/SyntaxHighlighter/3.0.83/scripts/shBrushPhp.js',        array('syntaxhighlighter-core'), $this->agshver );

+       wp_register_script( 'syntaxhighlighter-brush-plain',      '//cdnjs.cloudflare.com/ajax/libs/SyntaxHighlighter/3.0.83/scripts/shBrushPlain.js',      array('syntaxhighlighter-core'), $this->agshver );

+       wp_register_script( 'syntaxhighlighter-brush-powershell', '//cdnjs.cloudflare.com/ajax/libs/SyntaxHighlighter/3.0.83/scripts/shBrushPowerShell.js', array('syntaxhighlighter-core'), $this->agshver );

+       wp_register_script( 'syntaxhighlighter-brush-python',     '//cdnjs.cloudflare.com/ajax/libs/SyntaxHighlighter/3.0.83/scripts/shBrushPython.js',     array('syntaxhighlighter-core'), $this->agshver );

+       wp_register_script( 'syntaxhighlighter-brush-ruby',       '//cdnjs.cloudflare.com/ajax/libs/SyntaxHighlighter/3.0.83/scripts/shBrushRuby.js',       array('syntaxhighlighter-core'), $this->agshver );

+       wp_register_script( 'syntaxhighlighter-brush-scala',      '//cdnjs.cloudflare.com/ajax/libs/SyntaxHighlighter/3.0.83/scripts/shBrushScala.js',      array('syntaxhighlighter-core'), $this->agshver );

+       wp_register_script( 'syntaxhighlighter-brush-sql',        '//cdnjs.cloudflare.com/ajax/libs/SyntaxHighlighter/3.0.83/scripts/shBrushSql.js',        array('syntaxhighlighter-core'), $this->agshver );

+       wp_register_script( 'syntaxhighlighter-brush-vb',         '//cdnjs.cloudflare.com/ajax/libs/SyntaxHighlighter/3.0.83/scripts/shBrushVb.js',         array('syntaxhighlighter-core'), $this->agshver );

+       wp_register_script( 'syntaxhighlighter-brush-xml',        '//cdnjs.cloudflare.com/ajax/libs/SyntaxHighlighter/3.0.83/scripts/shBrushXml.js',        array('syntaxhighlighter-core'), $this->agshver );

        // Register some popular third-party brushes
        wp_register_script( 'syntaxhighlighter-brush-clojure',    plugins_url('syntaxhighlighter/third-party-brushes/shBrushClojure.js'),          array('syntaxhighlighter-core'), '20090602'     );

ghlighter-core'), $this->agshver );

  • wp_register_script( 'syntaxhighlighter-brush-sql', '//cdnjs.cloudflare.com/ajax/libs/SyntaxHighlighter/3.0.83/scripts/shBrushSql.js', array('syntaxhighlighter-core'), $this->agshver );

  • wp_register_script( 'syntaxhighlighter-brush-vb', '//cdnjs.cloudflare.com/ajax/libs/SyntaxHighlighter/3.0.83/scripts/shBrushVb.js', array('syntaxhighlighter-core'), $this->agshver );

  • wp_register_script( 'syntaxhighlighter-brush-xml', '//cdnjs.cloudflare.com/ajax/libs/SyntaxHighlighter/3.0.83/scripts/shBrushXml.js', array('syntaxhighlighter-core'), $this->agshver );

    // Register some popular third-party brushes
    wp_register_script( 'syntaxhighlighter-brush-clojure',    plugins_url('syntaxhighlighter/third-party-brushes/shBrushClojure.js'),          array('syntaxhighlighter-core'), '20090602'     );
    

How to use org2blog effectively as a programmer

org2blog is a beautiful plugin to post to wordpress blog.

I won't waste your time on the basic useage because it has zero learning curve and its README is very clear.

I will talk some advanced set up here.

Please note you may need check org2blog's section on posting code blocks if you are still confused. I also list some reasons why I did this at the bottom of this post.

As a programmer, I need wordpress syntax highlight all the code snippets I post. But it seems org2blog need some tweak to support language like elisp.

If you grep org2blog's code, you will find a variable "org2blog/wp-sourcecode-langs". It lists all the languages org2blog supports.

So all you need to do is insert below code into ~/.emacs:


(setq org2blog/wp-use-sourcecode-shortcode t)

(setq org2blog/wp-sourcecode-langs
      '("actionscript3" "bash" "coldfusion" "cpp" "csharp" "css" "delphi"
        "erlang" "fsharp" "diff" "groovy" "javascript" "java" "javafx" "matlab"
        "objc" "perl" "php" "text" "powershell" "python" "ruby" "scala" "sql"
        "vb" "xml"
        "sh" "elisp" "lisp" "lua"))

Then you need install the wordpress plugin SyntaxHighlighter Evolved to do the syntax highlight thing. Well, you will find the languages like elisp is not supported by this plugin.

That's easy to fix. Please log into your blog, modify that plugin online:


diff --git a/syntaxhighlighter.php b/syntaxhighlighter.php

index 53b4815..808b14b 100644

--- a/syntaxhighlighter.php

+++ b/syntaxhighlighter.php

@@ -222,6 +222,11 @@ class SyntaxHighlighter {
            'xslt'          => 'xml',
            'html'          => 'xml',
            'xhtml'         => 'xml',
+           'text'          => 'clojure',

+           'elisp'         => 'clojure',

+           'emacs-lisp'         => 'clojure',

+           'lisp'          => 'clojure',

+           'sh'            => 'bash',

+           'lua'           => 'ruby',
        ) );

As you can see, I use clojure syntax to highlight elisp and use ruby syntax to highlight lua.

You may ask why I use clojure syntax to highlight simple text in above set up?

Well, I already submit lots of my elisp code before set up my org2blog correctly. Those code snippets are regarded as simple text. I don't want to re-submit the old snippets one by one. That's why I render text as clojure code.

Besides, I find the wordpress theme produced by Automattic (Yes, the company behind wordpress) is good for programmers because they obviously have optimized font size for different screen resolutions. That's important for code reading. I use Trvl v1.0.2.

UPDATE: Some people asked me why I not use org-mode's own API to render code snippet into HTML.

Here are the reasons,

  1. Exporting code snippet is simple and reliable now because we embed plain code in "pre" tag directly. I had issues with org-mode's rendering-code-snipppet-into-html before.
  2. The html is much smaller.
  3. The actual rendering happens on user's browser side, and the js file itself is hosted on some CDN, so performance is good.
  4. This is the techinique stackoverflow.com uses.

How to adapt my work style to the employer's standard in Emacs

I write some set up code in ~/.custom.el. It will detect which machine and what directory I'm working on. Then I hook the set up code when major mode (js2-mode, web-mode, for example) loaded.

In my ~/.emacs,


(if (file-readable-p (expand-file-name "~/.custom.el"))
     (load-file (expand-file-name "~/.custom.el")))

Content of my ~/.custom.el:


;; (getenv "HOSTNAME") won't work because $HOSTNAME is not an env variable

;; (system-name) won't work because as Optus required, my /etc/hosts is changed

(defun my/at-office ()
  (interactive)
  (let ((my-hostname (with-temp-buffer
                       (shell-command "hostname" t)
                       (goto-char (point-max))
                       (delete-char -1)
                       (buffer-string))
                     ))
    (and (string= my-hostname "my-sydney-workpc")
         (not (or (string= my-hostname "sydneypc")
                  (string= my-hostname "ChenBinMacAir")
                  (string= my-hostname "eee")
                  )))
    ))


(defun my/use-office-style ()
  (interactive)
  (let ((dir (if (buffer-file-name)
                 (file-name-directory (buffer-file-name))
               "")))
    (string-match-p "CompanyProject" dir)
    ))


(defun my/setup-develop-environment ()
  (cond
   ((my/use-office-style)
    (message "Office code style!")
    (setq coffee-tab-width 4)
    (setq javascript-indent-level 4)
    (setq js-indent-level 4)
    (setq js2-basic-offset 4)
    (setq web-mode-indent-style 4))
   (t
    (message "My code style!")
    (setq coffee-tab-width 4)
    (setq javascript-indent-level 2)
    (setq js-indent-level 2)
    (setq js2-basic-offset 2)
    (setq web-mode-indent-style 2))
   ))


(add-hook 'js2-mode-hook 'my/setup-develop-environment)

(add-hook 'web-mode-hook 'my/setup-develop-environment)

Contents © 2014 Chen Bin - Powered by Nikola