Jorgen Schäfer: Elpy 1.6.0 released

I just released version 1.6.0 of Elpy, the Emacs Python Development Environment. This is a feature release.

Elpy is an Emacs package to bring powerful Python editing to Emacs. It combines a number of other packages, both written in Emacs Lisp as well as Python.

Quick Installation

Evaluate this:

(require 'package)
(add-to-list 'package-archives
'("elpy" .
"http://jorgenschaefer.github.io/packages/"))

Then run M-x package-install RET elpy RET.

Finally, run the following (and add them to your .emacs):

(package-initialize)
(elpy-enable)

Changes in 1.6.0

  • When point is on a line with a flymake error, Elpy will now show the error in the echo area.
  • The movement commands (C-<cursor>) have been reworked again. Going left and right will now move by indentation levels left of the current indentation, i.e. jump four spaces, and by words right of the current indentation. Going up and down will go to the previous or next line with the indentation level point is at, not the indentation the line has. Try it, it's more difficult to explain than to use.
  • Completion results are now sorted more sensibly, with single-underscore symbols at the end, and double-underscore symbols after normal symbols, but before single-underscore ones.
  • M-x elpy-config will now point out if there are newer versions available for packages used by Elpy.
  • M-x elpy-config will now warn if ~/.local/bin is not in PATH while there is no virtualenv active.
  • The M-x elpy-version command is back by popular demand.
  • RPC buffers used by Elpy are now hidden by default, having a space at the beginning of the name.
  • When the Rope library throws an error, Elpy will now also attempt to provide reproduction steps. This used to only happen for Jedi.
  • Various bug fixes.
-1:-- Elpy 1.6.0 released (Post Jorgen Schäfer (noreply@blogger.com))--L0--C0--October 31, 2014 04:56 PM

sachachua: Publishing WordPress thumbnail images using Emacs and Org2Blog

I often include large images in my blog posts since I use sketches as another way to think out loud. I’d gotten used to using the WordPress web interface to drag and drop them into the relevant section of the page. I write most text in Emacs/Org Mode/Org2Blog because of the better outlining and writing tools, and then I used sacha/org-copy-region-as-html (which you can grab from my Emacs configuration) to copy the HTML markup and paste it into WordPress. Of course, I use Emacs for source-code heavy posts that make the most of its syntax formatting support.

Someone asked me recently about how to post and update blog posts with images through Org2blog, and if I had any recommendations for workflow. I’d dropped Windows Live Writer since it was flaking out on me and the WordPress web interface had improved a lot, but before recommending just using WordPress to add images, I was curious about whether I could improve my blogging workflow by digging into Org Mode and Org2Blog further.

It turns out (like it usually does in the Emacs world) that someone had already solved the problem, and I just didn’t have the updated version. Although the upstream version of Org2Blog didn’t yet have the thumbnail code, searching for “org2blog wordpress thumbnail” led me to cpbotha’s Github issue and pull request. Punchagan’s version had some changes that were a little bit ahead of cpbotha’s, so I dusted off my ancient org2blog repository, cloned it onto my computer, and issued the following commands:

git remote add upstream https://github.com/punchagan/org2blog
git pull upstream master
git remote add cpbotha https://github.com/cpbotha/org2blog.git
git pull cpbotha image-thumbnail

and tested it out on a blog post I’d already drafted in Org. It took me a little while to remember that the file URLs didn’t like ~, so I specified a relative path to the image instead. But then it all worked, yay! A quick git push later, and my Github repository was up to date again.

So now I’m back to running a Git version of org2blog instead of the one that I had installed using the built-in packaging system. The way I make it work is that I have this near the beginning of my Emacs configuration:

;; This sets up the load path so that we can override it
(package-initialize nil)
;; Override the packages with the git version of Org and other packages
(add-to-list 'load-path "~/elisp/org-mode/lisp")
(add-to-list 'load-path "~/elisp/org-mode/contrib/lisp")
(add-to-list 'load-path "~/code/org2blog")
(add-to-list 'load-path "~/Dropbox/2014/presentations/org-reveal")
;; Load the rest of the packages
(package-initialize t)
(setq package-enable-at-startup nil)

This allows me to mostly use the packages and to satisfy dependencies, but override some of the load paths as needed.

Hope that helps someone else!

The post Publishing WordPress thumbnail images using Emacs and Org2Blog appeared first on sacha chua :: living an awesome life.

-1:-- Publishing WordPress thumbnail images using Emacs and Org2Blog (Post Sacha Chua)--L0--C0--October 31, 2014 12:00 PM

Irreal: New MELPA URL

If you're a MELPA user you might have heard that the URL for the site has changed. It's easy to miss the significance of that for your Emacs configuration though. You have to change the package-archives list to reflect the new URL. That is, you have to change

(add-to-list 'package-archives
             '("melpa" . "http://melpa.milkbox.net/packages/"))

to

(add-to-list 'package-archives
             '("melpa" . "http://melpa.org/packages/"))

The old address is still working (it redirects to http://melpa.org) but you should change your configuration before it stops working.

-1:-- New MELPA URL (Post jcs)--L0--C0--October 31, 2014 11:05 AM

Irreal: Compiling aspell with OS X Yosemite

While I was setting up my new machine, I had to rebuild aspell. The last time I did that it built without any problems. This time, despite the fact that it was the same version as before, there were several fatal errors. I asked DuckDuckGo what it knew about the matter and it referred me to this stackoverflow question.

The answer is correct but it's not very clear where you have to apply the fixes. For the record, the error is in interfaces/cc/aspell.h in the section marked “errors” that starts on line 237. Just comment out the entire section with #ifndef __cplusplus#endif as lotsoffreetime suggests in the stackoverflow post.

-1:-- Compiling aspell with OS X Yosemite (Post jcs)--L0--C0--October 30, 2014 11:42 AM

sachachua: Emacs hangout notes

Prompted by Michael Fogleman’s tweet that he’d like to see a bunch of us Emacs geeks get together in one room for a hackathon, Nic Ferrier and I tried out a casual Emacs hangout. Tinychat didn’t work, but Google Hangouts worked fine. A bunch of people saw our tweets about it too and dropped by, yay! Here are some things we talked about (mostly nifty tweaks from Nic):

  • shadchen is great for pattern matching, especially within trees
  • Alec wanted to know about Emacs and Git, so Nic demonstrated basic Magit
  • after-init-hook – load things there instead of in your ~/.emacs.d/init.el, so that your init.el does not break and you can test things easily from within Emacs
  • I shared isearch-describe-bindings, which had a number of goodies that I hadn’t known about before
  • Recognizing the opportunity to share what you’re working on (ex: nicferrier’s working on an Emacs Lisp to Javascript compiler)

Google Hangouts screensharing worked well for us, giving multiple people the opportunity to share their screen and allowing people to choose what they wanted to focus on. Nic also started up a tmux session and a repository of public keys, but that’s a bit more involved and requires more trust/coordination, so screen-sharing will likely be the way to go unless people have more of a pairing thing set up. This kind of informal hangout might be a good way for people to share what they’re working on just in case other people want to drop by and help out or ask questions (which people can optionally answer, or postpone if they want to stay focused on their work). Something a little more focused than this might be to pick one bug or task and work on it together, maybe starting with a “ridealong” (one person screenshares, thinking out loud as he or she works, and taking the occasional question) and moving towards full pairing (people working on things together). Some of my short-term Emacs goals are:

  • Improve my web development workflow and environment (including getting the hang of Magit, Smart Parens, Skewer, AutoComplete / Company Mode, and other good things)
  • Learn how to write proper tests for Emacs-related things
  • Get back into contributing to the Emacs community, perhaps starting to work on code/tests
  • Look up my Org agenda on my phone, probably with Org Mobile or some kind of batch process

Let’s give this a try. =) I set up a public calendar and added an event on Nov 5, 9-11PM Toronto time. If folks want to drop by, we’ll see how that works out!

The post Emacs hangout notes appeared first on sacha chua :: living an awesome life.

-1:-- Emacs hangout notes (Post Sacha Chua)--L0--C0--October 30, 2014 03:44 AM

Grant Rettke: Set image width in org-mode

Make org and export use the same image width via this post:


#+attr_latex: :width 4in :placement [H]
#+attr_org: :width 400
[[./images/batch-multiple.png]]

-1:-- Set image width in org-mode (Post Grant)--L0--C0--October 29, 2014 01:45 PM

Mathias Dahl: Cake. Can have. Eat too.

A while ago, a friend of mine shared this informative article about why Atom (a new text editor by the Github team, it seems) cannot replace Vim. The author talks about the very useful composability property of Vi(m) and ends his article with this (do read the complete article though, especially if you are quite new to Vi(m)):
A new, shiny, modern editor could one-up Vim by fixing some (or hopefully all) of these issues. But before an editor can replace Vim, it needs to learn everything that 1976 has to teach — not just the lesson of Emacs, but also the lesson of vi.
Well, it might not be very "shiny", and "modern" is, I guess, very subjective, but there is already an editor that both have awesome extensibility and, optionally, strict modal behaviour with a "command" mode.

Which editor it is? Emacs, of course. Just fire up viper-mode, or pick one of the more modern Vi(m) emulation packages like Evil (here is a list of different emulation modes for Emacs) and you can now have your cake and eat it too.

Mmm. Cake.

-1:-- Cake. Can have. Eat too. (Post Mathias Dahl (noreply@blogger.com))--L0--C0--October 28, 2014 09:38 PM

Mathias Dahl: Keyboard activated favorites menu using "simple menu items"

Some time back I wanted to create a keyboard activated menu with one-key access to some favorite commands that I did not want to give one-key bindings in the global keymap and for which I do not want to type the names on the M-x prompt. I was going to write my own command to read the key for the favorite command. However, it turns out Emacs already had more or less what I wanted in the form of simple menu items.

I chose to use the "apps" key (on keyboards with two Windows keys, it's the key to the right of the right Windows key, with a little menu symbol on it) since I did not use that for anything in Emacs.

Here is how to try this little hack out (FYI the key/command combinations below are just examples and not the actual keys and commands I wanted to use):

(defvar my-favorties-map (make-sparse-keymap "Favorites"))

(define-key global-map (kbd "<apps>") my-favorties-map)

(define-key my-favorties-map (kbd "f") 
  (cons "Find file"
        'find-file))

(define-key my-favorties-map (kbd "s")
  (cons "Save current buffer"
        'save-buffer))

(define-key my-favorties-map (kbd "i")
  (cons "Kill buffer"
        'kill-buffer))

After evaluating the above, when typing the "apps" key, the following "menu" will be displayed in the echo minibuffer:

 Favorites: i = Kill buffer, Save current buffer, Find file

It does what I want, although it is a little bit peculiar in how it decides for what bindings it will show X = Command for, and not. Seems that if the name of the menu item/command begins with the same letter/key that is bound to the command, it will not show it.

So, there it is, an instant little text based menu for executing favorite commands.

Enjoy!

-1:-- Keyboard activated favorites menu using "simple menu items" (Post Mathias Dahl (noreply@blogger.com))--L0--C0--October 28, 2014 09:36 PM

Timo Geusch: MELPA has a new URL

MELPA has recently got its own domain (melpa.org) so it’s time to update your list of package repositories with the new URL. Speaking of MELPA, I recently switched to their stable repository instead of their “regular” nightly build/snapshot repository after I accidentally ended up with a cider build that didn’t want to playing ball. This […]

The post MELPA has a new URL appeared first on The Lone C++ Coder's Blog.

-1:-- MELPA has a new URL (Post Timo Geusch)--L0--C0--October 28, 2014 02:22 PM

Endless Parentheses: Big things to expect from Emacs 25

Emacs turned 24.4 this Monday. Admittedly, it's not a hugely significant number, but every birthday is a big deal. The cries of joy and celebration echoed throughout the websphere. And now, while Emacs sleeps off an alcohol-induced headache, as the janitor sweeps off the inch-thick confetti covering the floor, we gather ourselves and look forward. Just before the horizon, a prominently ominous, silvery, unavoidable “25” is within sight. And it brings changes.

Last week, I exposed my favorite perks about the version that is now upon us. Today, I bring to you my expectations. Features I'd be overjoyed to find in the “News” file. Some of these are guaranteed, others are hopeful ramblings, but they're all at least implementable. Most importantly, they all have something in common: their absence, in my opinion, holds back the Emacs community from growing even faster.

Git

No, I'm not talking about git support, anyone knows Emacs is better at git than git itself. I'm referring to moving the codebase from bzr to git. At the moment, this is planned to happen on November 11, and a cheerful day that will be.

In the words of Eric S. Raymond,

The bzr version control system is dying; by most measures it is already moribund. The dev list has flat-lined, most of Canonical's in-house projects have abandoned bzr for git, and one of its senior developers has written a remarkably candid assessment of why bzr failed[.]

I'm not an expert on bzr, but I've noticed it discourages some new contributors. Ultimately, adopting a system people already tend to be familiar with is a big step in the right direction.

Dynamic library loading

Dynamically loading libraries is a big deal, and it's closer than ever. Some very inspiring results has been reported in the last month and, while there are still some obstacles under discussion, it's looking almost in shape for release.

Of course, not every package needs this—in fact, the vast majority doesn't. But this would be a huge boon to a number of packages which, so far, have had to resort to sub-processes or resign to elisp.

Concurrency in Elisp

This is not a new idea in any way but it's become increasingly urgent with the growth of the package repositories. I'll be honest, I haven't seen much talk about this feature. Still, sometime next year, if there's no sign whatsoever of concurrency being a thing, I'll write a hack for it work with package.el. Here's why I think that's important.

Consider this situation a little more than a year ago. I noticed my laptop was taking a while to display the *Packages* buffer. “No doubt,” I thought to myself, “1477 packages is a bit much for this laptop. No worries though, 5 seconds of waiting isn't that bad.”.

Fast-forward fifteen months. I invoke M-x list-packages, wait 20 seconds, and the buffer I'm given crosses the 3000 lines threshold. That's partially aggravated by the fact that package.el displays separate entries for each repository a package can be found in. But even if we eliminate these redundancies, since July 2013 one thousand unique new packages have been released. That is an impressive rate of over 2 new packages every single day.

Now consider that this rate shows absolutely no sign of diminishing. Worse yet, consider that the rate in which packages are updated on Melpa is almost two orders of magnitude higher. Where will we be by the time Emacs 25 is released?

Gradually and surely, the time it takes to upgrade one's Emacs packages will surpass that of updating one's Operating System. And what are we to do in the mean time? Play Minesweeper?

We need asynchronicity, now more than ever, because the *Packages* buffer plays one of the most fundamental roles in the expansion of the community. We need a package manager that checks for new releases in the background while we navigate the previously cached list, and one that performs updates in the background without forcing us to go for a coffee.

A Better Package Menu

This is an extension to the previous topic. Sluggishness is not the only consequence of an ever-increasing package menu. Navigating the menu in its current form is akin to exploring the Amazon rain-forest. There's plenty of dazzling richness to be found, but the sheer size and roughness are overwhelming—not mention the piranhas.

Emacs 24.4 introduces keyword filtering to the menu, and Paradox offers a couple other forms of filtering, but they're still very crude. We need a navigable tree of categories—which would to facilitate discovery for times when isearch is a bit too narrow. And we need a simple and honest search box, even if its only purpose is to invoke something similar to occur.

A More Robust Customize Interface

The customize interface is powerful and beautiful. Its major achievement, in my opinion, is to make it Emacs customization accessible even for those who know no elisp at all. When correctly configured, I could see my grandmother using it.

Still, it is for that same reason that we must not admit it to have recurring bugs. A sizeable part of its user base might never be aware that they're running into a bug, they'll just think “Emacs is complicated”. So it doesn't help, you see, that it has a couple of issues so deep-seated that even experienced lispers might be led to think they're doing something wrong.

There have been talks of fixing this on the dev list, so I'm optimistic.

Namespaces

I could go on about this for several posts. Plain and simple: Emacs doesn't have namespaces, so we have to prepend the package name or prefix to every single defined symbol. Here's a snippet of what that looks like:

(defun package-initialize (&optional no-activate)
  "[DOC]"
  (interactive)
  (setq package-alist nil)
  (package-load-all-descriptors)
  (package-read-all-archive-contents)
  (unless no-activate
    (dolist (elt package-alist)
      (package-activate (car elt))))
  (setq package--initialized t))

I'm sure you see how that's annoying to write and read. Not to mention every symbol is permanently available in the global namespace.

There have been talks of implementing a system similar to common-lisp packages, which takes a lot of adaptation to how symbols are interned. While we wait, I wrote a namespacing engine in the form of a macro. Which turns the above into something like this.

(define-namespace package- 
(defun initialize (&optional no-activate)
  "[DOC]"
  (interactive)
  (setq alist nil)
  (load-all-descriptors)
  (read-all-archive-contents)
  (unless no-activate
    (dolist (elt alist)
      (activate (car elt))))
  (setq -initialized t))
)

One way or the other, some form of solution should make its way into Emacs. And I'll fight for that to happen before 25.

Conclusion

That's my list of most immediate improvements. Did I miss something big? Do you feel insulted and disagree aggressively, or do you feel enlightened and praise such accuracy?

May the year to come be filled with parentheses.

Comment on this.

-1:-- Big things to expect from Emacs 25 (Post)--L0--C0--October 27, 2014 12:00 AM

Got Emacs?: Update your package search url as melpa.milkbox.net is now melpa.org

It's been a couple of days but the url has changed to melpa.org. You may need to change your .emacs file  from ("melpa" . "http://melpa.milkbox.net/packages/") to ("melpa" . "http://melpa.org/packages/")
-1:-- Update your package search url as melpa.milkbox.net is now melpa.org (Post sivaram (noreply@blogger.com))--L0--C0--October 26, 2014 02:09 AM

Sebastian Wiesner: Flycheck 0.21 released

I’ve just released Flycheck 0.21, the result of two months of work. It’s already on MELPA and Marmalade, so take a look at the release annoucement and the changelog, and update Flycheck with M-x list-packages RET U x.

Enjoy the new release, and many many thanks for your support!

-1:-- Flycheck 0.21 released (Post)--L0--C0--October 26, 2014 12:00 AM

Endless Parentheses: Aggressive-indent just got better!

aggressive-indent is quite something. I've only just released it and it seems to have been very well received. As such, it's only fair that I invest a bit more time into it.

The original version was really just a hack that was born as an answer on Emacs.SE. It worked phenomenally well on emacs-lisp-mode (to my delight), but it lagged a bit on c-like modes.

The new version, which is already on Melpa, is much smarter and more optimised. It should work quite well on any mode where automatic indentation makes sense (python users, voice your suggestions).

As a bonus, here's a stupendous screencast, courtesy of Tu Do!

aggressive-indent.gif

Usage

Instructions are still the same! So long as you have Melpa configured, you can install it with.

M-x package-install RET aggressive-indent

Then simply turn it on and you’ll never have unindented code again.

(global-aggressive-indent-mode)

You can also turn it on locally with.

(add-hook 'emacs-lisp-mode-hook #'aggressive-indent-mode)

Comment on this.

-1:-- Aggressive-indent just got better! (Post)--L0--C0--October 25, 2014 12:00 AM

Timo Geusch: There’s an Emacs Stackexchange

For those who aren’t aware of this yet, there is an Emacs Stackexchange site that’s currently in beta. I’d like to encourage everybody to take part in it so it can become a viable site on the Stack Exchange network.

The post There’s an Emacs Stackexchange appeared first on The Lone C++ Coder's Blog.

-1:-- There’s an Emacs Stackexchange (Post Timo Geusch)--L0--C0--October 21, 2014 11:57 PM

Emacs Redux: Emacs 24.4

Emacs 24.4 is finally out!

You can read about all the new features here. I’ve published a series of articles about some of the more interesting features.

In related news - the Emacs Mac Port based on 24.4 has also been released.

-1:-- Emacs 24.4 (Post)--L0--C0--October 21, 2014 02:36 PM

Got Emacs?: Emacs 24.4 released

Well, here's the official release mail on Emacs 24.4.  The Windows versions aren't out yet but will turn up in a few days.
-1:-- Emacs 24.4 released (Post sivaram (noreply@blogger.com))--L0--C0--October 21, 2014 03:18 AM

Mickey Petersen: Four year anniversary and new website

Welcome to the new Mastering Emacs website. After four years (yes, four!) it’s time for a site refresh. The old site was never meant to last that long; it was a temporary theme hastily picked so I could start writing about Emacs. Back then there were fewer blogs and Emacs resources. We didn’t even have a package manager.

The old site did serve its purpose as a launchpad for my blogging adventures. But Apache/WordPress is slow out of the box, even with SuperCache. A slight breeze and the thing would fall over — and it did, every time it featured on HackerNews or high-traffic subreddits.

Eventually I moved to FastCGI and nginx to host WordPress, but as it’s not officially supported it was a major pain to get working. António P. P. Almeida’s wordpress-nginx made my life so much easier and the site so much faster.

Alas, it’s time to retire the old site. Over the years I came to a number of conclusions:

People don’t use tags I spent a good amount of time adding tags to every article I wrote, but almost no one ever really used them. Sure people did click on them, but overall the reading guide proved far more useful. My goal is to re-implement a “tag”-like system but around concepts (Shells, Dired, etc.) instead of tags.

Not enough categories I had categories like “For Beginners”, “Tutorials”, and so on. They worked OK, but I am of the opinion now that manually curating my content makes more sense. Automatic content generation’s fine but throwing articles into a two or three baskets is never good enough.

Spammers are getting smarter I had to ditch Akismet, a free anti-spam checker for WordPress, after several years of near-perfect operation. The spammers simply mimicked humans too much and the filter would trip up on real content. I eventually switched to manual approval but that’s a lot of work.

Encourage visitors to read other articles A lot of visitors would leave after reading a single article, even though I would often have several related articles. I tried some of the “Suggested Content” plugins but they were universally terrible — another mark against content automation.

Apache is a memory hog Yes, yes. I am sure you can tame Apache and make it into a lithe and agile webserver but my best efforts failed me. The second I switched to nginx the memory and CPU usage dropped like a rock. Not to mention that nginx is much easier to configure.

So what about the new site then? Well it’s custom written for the job, though I may one day open source the blog engine. I launched it Tuesday the 14th of October, and immediately my site got slammed by reddit, Twitter and Hackernews on the announcement of Emacs 24.4. Talk about baptism by fire! The site held up just fine though.

The stack is Python and Flask running PostgreSQL with nginx as a reverse proxy and uWSGI as the application server, and with memcached for page caching. It took about three weeks of casual coding to write it, including the harrowing experience of having to convert the old blog articles — but more on that in a bit.

I opted for Memcached over Redis as my needs were simple, and because nginx ships with memcached support meaning nginx could short-circuit the trip to my upstream application server should the need ever arise. For now it just goes to uWSGI which checks the cache and returns the cached copy. That’s actually more than quick enough to survive HackerNews, the most high-traffic site visits I’ve gotten.

The slowness comes from page generation and not querying the database (databases are fast, Python is not) so that’s where memcached comes in. I thought about using nginx’s own proxy cache mechanism but invalidating the cache when you add a new comment or when I edit a page is messy.

Converting the blog articles proved a greater challenge than you might think. First of all, I like reStructuredText so I wanted to write and edit my articles in rST and convert them automatically to HTML when I publish them.

Enter Pandoc, which is a fine tool for the job. But there’s a snag. The original WordPress format is pseudo-HTML, meaning blank lines signify new paragraphs. Converting that without spending too much time with a hand-rolled, one-off state machine to convert to “real HTML” (for Pandoc to convert to rST) involved some compromises and hand editing. (And no, wrapping text blocks in paragraph tags is not enough when you have <pre> tags with newlines and other tag flotsam.)

So that was painful.

Coming up with a new design proved a fun challenge as well. CSS has come a long way in four years and things like text-justified automatic hyphenation work great (unless you’re on Chrome, in which case it’s the dark ages for you) on both Firefox and IE. Drop caps, ligatures, kerning and old-style numerals also work well and is possible in CSS alone. I’m surprised how good HTML/CSS is at typesetting nowadays. The font is Cardo, an open source font inspired by Monotype’s Bembo, a font itself inspired by Aldus Manutius’ from the 1500s, which I originally wanted to use but it’s way, way, WAY too expensive for web font use. If you’re a Chrome user on Windows the font will look weird as Chrome does not see fit to grace your eyes with aliasing. Again, both Firefox and IE render properly.

I opted for larger font sizes than normal in the belief that: it’s not the 1990s any more, and big font sizes mean people won’t have to zoom in or squint their eyes. Or at least that’s what I always end up doing, and my vision’s perfectly fine. Apparently doing that was a mistake: the amount of vitriol I received from certain quarters of the internet for having large font sizes was… perplexing to say the least.

So I made the fonts smaller.

The site’s still undergoing changes and I plan on adding to it over time. I am particularly keen on getting people to explore my site and learn more about Emacs.

Here’s to another four years.

Mickey.

-1:-- Four year anniversary and new website (Post)--L0--C0--October 20, 2014 10:41 AM

Flickr tag 'emacs': スクリーンショット 2014-10-18 17.01.34

zatsu posted a photo:

スクリーンショット 2014-10-18 17.01.34

Emacs 25.0 on OS X 10.10 Yosemite

-1:-- スクリーンショット 2014-10-18 17.01.34 (Post zatsu (nobody@flickr.com))--L0--C0--October 18, 2014 08:02 AM

Grant Rettke: A must-see of advanced babel usage in org with R

This post is a must-see of advanced babel usage in org with R

-1:-- A must-see of advanced babel usage in org with R (Post Grant)--L0--C0--October 13, 2014 11:36 PM

Phil Hagelberg: in which preconceptions are unavoidable

In my last post I introduced my latest project, a HyperCard clone I've been writing in the Racket programming language, which is a practical and accessible dialect of Scheme. I'd played around a bit with Racket before, but this was the first time I'd used it for anything nontrivial. Any time you come to an unfamiliar language, there's naturally a period of disorientation in which it can be frustrating to find your footing. Racket's similarity to Clojure (the language I'm currently most proficient in) means this shouldn't be as pronounced as it would be with many languages, but these are my subjective reactions to how it's gone implementing my first project. There are a number of gripes, but if I may offer a spoiler, in the end Racket provides satisfactory ways of addressing all of them that aren't obvious up-front, and brings valuable new perspectives to the table.


When I was getting started with Racket, I was pleased to see that it defaults to immutable data structures. Coming from a Clojure background, I'm used to using free-form maps for everything. Racket has hash tables which sound similar, so let's take a look at how they're used:

(define h #hash(('a . 123)
                ('b . 234)
                ('c . (+ 345 456))))

(h 'b)
; application: not a procedure;
;  expected a procedure that can be applied to arguments
;   given: '#hash((a . 123) (b . 234) (c . (+ 345 456)))
;   arguments...:
;    'b

What's going on here? Well, it looks like hash tables can't be called like functions. This has never made any sense to me, since immutable hash tables are actually more like mathematical functions than lambdas are. But whatever, we'll just use hash-ref instead; it's more verbose but should get the job done:

(hash-ref h 'b)

; hash-ref: no value found for key
;   key: 'b

It turns out Racket implicitly quotes everything inside the hash table. So OK, maybe that's a little nicer since you don't need to quote the symbol keys in the hash table:

(define h #hash((a . 123)
                (b . 234)
                (c . (+ 345 456))))

(hash-ref h 'b) ; -> 234
(hash-ref h 'c) ; -> '(+ 345 456)

Oh dear... that's less than ideal, especially compared to Clojure's simple (def h {:a 123 :b 234 :c (+ 345 456)} and (:c h) notation. But let's move on[1] since it turns out hash tables are not nearly as important as maps are in Clojure. It's more idiomatic to use structs if your fields are known up-front:

(struct abc (a b c))
(define s (abc 123 234 (+ 345 456)))

(abc-c s) ; -> 801
s ; -> #<abc>

So that's nice in that it avoids the implicit quoting; our regular evaluation rules work at least. But what's this at the end? Racket structs default to being opaque. This may have made sense years ago when you needed to protect your mutable fields, but now that immutability is the default, it just gets in the way. Luckily you can set the #:transparent option when defining structs, and this will likely become the default in the future.

One place where Racket has a clear advantage over Clojure is that you'll never get nil back from an accessor. Both in hash tables and structs, if a field doesn't exist, you'll get an error immediately rather than allowing bogus data to percolate through your call chain and blow up in an unrelated place. (Though of course with hash tables you can specify your own value for the "not found" case.) In any case, less "garbage in, garbage out" is a welcome change for me as a human who frequently makes mistakes.

What about updates, though? Mutable struct fields have setter functions auto-generated, but inexplicably the nondestructive equivalents for immutable fields are missing. Instead the struct-copy macro is recommended. Here we change the b field of an abc struct instance we've defined:

(define s2 (struct-copy abc s [b 987]))
(abc-b s2) ; -> 987

This works, though you have to repeat the struct type in the invocation. That's not so bad, but the bigger problem is that this is a macro. The field you wish to update must be known at compile time, which makes it awkward to use in the context of higher order functions.

At this point the post is surely sounding pretty whiny. While the out-of-the-box experience working with these data structures is not great, Racket gives you plenty of power to make things better. Probably the most comprehensive take on this I've seen is Rackjure, which gives you a lot of the creature comforts I've noted as missing above like nicer hash table syntax and data structures you can call like functions, as well as a few other niceties like a general-purpose equality predicate[2] and atomic swap for boxes.

In my initial exploration of Racket, I resisted the temptation to dive straight into Rackjure in order to give "raw Racket" a fair shakedown. Because of this, I've spent more time looking into structs and some of the options they provide. Racket has the notion of interfaces you can conform to in order to get generic functionality specialized to a certain struct type. Dictionaries are one of the interfaces it ships with out of the box, so you can use dict-ref, dict-set, etc with hash-tables and other built-in types that conform to this interface. Your typical structs won't work with it, but you can declare structs that implement it without too much fuss. I've done this with my fstruct macro:

(fstruct fabc (a b c)) ; define a struct type with three fields
(define fs (fabc 123 234 (+ 345 456)))

(dict-ref fs 'a) ; -> 123
(dict-set fs 'b 999) ; -> (fabc 123 234 801)
(dict-update fs 'c (λ (x) (- x 400))) ; -> (fabc 123 234 401)

One gotcha if you're used to Clojure is that dict-update is not variadic—if you provide a fourth argument it will be used as a "not found" value rather than as an argument to the updater function. (dict-update fs 'c - 400) won't work. However, unlike Clojure, Racket can do reverse partial application, so (rcurry - 400) does the job, which is nicer than spelling out the lambda form fully.

Another gotcha is that dict-update doesn't appear to have a nested equivalent. For instance; it would be nice to be able to pass an updater function and a "key path" to a specific value in a tree of dictionaries:

(define inner (fabc '(a b c) 0 0))
(define ht-nest `#hash((key1 . ,inner)
                       (key2 . #f)))
(define outer (fabc 0 ht-nest '(1 2 3)))

(define updated (dict-update-in outer '(b key1 a) append '(d e f)))

(dict-ref-in updated '(b key1 a)) ; -> '(a b c d e f)

So that is easy to add:

(define (dict-update-in d ks f . args)
  (if (empty? (rest ks))
      (dict-update d (first ks) (λ (x) (apply f x args)))
      (dict-set d (first ks) (apply dict-update-in
                                    (dict-ref d (first ks))
                                    (rest ks) f args))))

(define (dict-ref-in d ks)
  (if (empty? (rest ks))
      (dict-ref d (first ks))
      (dict-ref-in (dict-ref d (first ks)) (rest ks))))

The fstruct macro has one more trick up its sleeve. The structs it generates are applicable just like Clojure maps:

(define fs2 (fabc 123 (fabc 234 345 (fabc 987 654 321)) 0))

(fs2 'a) ; -> 123
(fs2 '(b b)) ; -> 345
(fs2 'c 9) ; -> (fabc 123 (fabc 234 345 (fabc 987 654 321)) 9)
(fs2 '(b c a) 0) ; -> (fabc 123 (fabc 234 345 (fabc 0 654 321)) 0)
(dict-update-in fs2 '(b b) + 555)
; -> (fabc 123 (fabc 234 900 (fabc 987 654 321)) 0)

They support nested lookups and setting out of the box, but of course for expressing updates that are a function of the old value to the new value you'll have to use dict-update or dict-update-in. My primary project at the moment has a deeply-nested state fstruct that contains hash-tables which contain fstructs, so being able to use a single dict-update-in which operates across multiple concrete types is very convenient.

Finally, while I prefer pure functions for as much of the logic as I can, the outer layer requires tracking state and changes to it. Racket provides the box type for this, which is equivalent to the atom of Clojure. Unfortunately while it provides the same compare-and-swap atomicity guarantees, it only exposes this via the low-level box-cas! function. Oh well, functional swap! which operates in terms of the old value is easy to implement on our own or steal from Rackjure:

(define (swap! box f . args)
  (let [(old (unbox box))]
    (or (box-cas! box old (apply f old args))
        (apply swap! box f args))))

(define b (box 56))

(box-cas! b 56 92) ; -> b now contains 92

(swap! b + 75) ; -> b now contains 167

The HyperCard clone I wrote about in my last post consists of a number of modes that define handlers that can update the state based on clicks. The handlers are all functions that take and return a state fstruct and are called via the swap! function. This allows the bulk of the code to be written in a pure fashion while keeping state change constrained to only two outer-layer mouse and key handler functions. The actual box containing the state never leaves the main module.

Racket has top-notch support for contracts that can describe the shape of data. In this case rather than attaching contracts to functions scattered all over the codebase, I attach them only to the box that contains the state struct, and any time there's a type bug it's usually immediately apparent what caused the trouble. For instance, I have a contract that states that the "corners" field of each button must be a list of four natural numbers, but I've made a change which causes one of them to be negative:

now: broke its contract
   promised: natural-number/c
   produced: -23
   in: the 3rd element of
       the corners field of
       an element of
       the buttons field of
       the values of
       the cards field of
       the stack field of
       the content of
       (box/c (struct/dc state
                         (card string?)
                         (stack (struct/dc stack ...))))

It's pretty clear here that I've made a miscalculation in the button coordinates. If you use DrRacket, the IDE that ships with Racket, you get a very slick visual trace leading you directly to the point at which the contract was violated. While it would be possible to gain more certainty about correctness at compile time by using Typed Racket, contracts let me define the shape of the data in a single place rather than annotating every function that handles state.

While I'd certainly be happy if Racket accomodated some of these functional programming idioms in a more streamlined way out of the box, it speaks volumes that I was able to make myself quite comfortable on my own only a week or two after beginning with the language[3]. It's interesting to note that all of the places in which Clojure has the edge[4] over Racket (with the conspicuous exception of equality) lie around succinctness and greater expressivity, while Racket's advantages are all around improved correctness and making mistakes easier to prevent and detect.


[1] It's possible to perform evaluation inside hash literal syntax by using backticks: `#hash((a . ,(+ 5 6 7)) does what you expect. It's better than nothing, but that's a lot of noise to express a simple concept. In practice, you don't really use the literal notation in programs; you just call the hash function.

[2] I've blogged about why egal is such a great equality predicate. Racket ships with a bewildering array of equality functions, but in functional code you really only need this one (sadly absent from the core language) for 98% of what you do.

[3] With one exception: Racket's macro system is rather intimidating coming from Clojure. Its additional complexity allows it to support some neat things, but so far I haven't gotten to the point where I'd understand why I'd want to do those kinds of things. In any case, I got help from Greg Hendershott to turn the fstruct macro into something properly hygenic.

[4] This ignores the advantages conferred by the respective implementations—Clojure has significantly better performance and access to libraries, while Racket's compiler/debugger/editor tools are much more polished, and its resource consumption is dramatically lower.

-1:-- in which preconceptions are unavoidable (Post Phil Hagelberg)--L0--C0--October 13, 2014 08:50 PM

肉山博客: Gnus:用 GPG 加密邮件

这周四(2014-10-09)在公司同事 Jack 的帮助下,成功地用 Gnus 发送了加密邮件。

1 流程

Gnus 自带对 GPG 的支持,所以一旦 Gnus 配置成功(见 2.2 ),给邮件加密很容易:

  • C-x m (compose-mail),开一封新邮件
  • C-c C-m C-e (mml-secure-message-sign-encrypt)

    这会在邮件开始处添加一个标签:

    <#secure method=pgpmime mode=signencrypt>
    

    解释一下 mode=signencrypt

    • sign :用发送者(你)的私钥签名,所以接收者知道邮件确实是你发的
    • encrypt :用接受者的公钥加密,所以邮件只有接受者能解密
  • 写完邮件, C-c C-c (message-send-and-exit) 发送

2 配置

2.1 用 GPG 生成公钥私钥,加载其他人的公钥

不赘述了,直接看 manual 就行,或着搜索相关教程。

2.2 配置 Gnus

我没有自己的邮件服务器,用的是谷歌的 Gmail。

Gnus 配置则基本是跟着陈斌兄的 Practical guide to use Gnus with Gmail 来的,简单实用。

3 我的公钥

http://wenshanren.org/wp-content/uploads/2014/05/wpid-PGP-wenshan2.asc

–—BEGIN PGP PUBLIC KEY BLOCK–—
Version: GnuPG v1

mQENBFNlPGEBCADALGQlcpOfWCKvaasalZWH+WZnY7LFBw4qaUbMHZtuh+3uyKm7
VadfPjcbKtko0pa7inY0CYPQ9oHaSZ0trimXdiMgf5693tmb733MZt72fc9sE7Xy
Iyq9v0QCEUwZsUFkac8qcWaZxIvx99/lro4NCStE/DCmM4BjpNanWcZMS2LDGGcT
mV35Qhl/0WT5JVZBM600iqbN8nsFPBdeu1t6F5/tFPf9QQXa9d3NLVc2gtCbYATi
7l4/2+EyTxHFYBxZfjHj5fViKlQyeDQBrg5hFh6jp0Zq+Hk4Kp6J1sRcgYecD8oq
gHI/wKELYs5XCrUdYv9DNxvwvZD3PeW8EjOFABEBAAG0LeS7u+aWh+WxsSAoUmVu
IFdlbnNoYW4pIDxyZW53czE5OTBAZ21haWwuY29tPokBNwQTAQIAIgUCU2U8YQIb
AwYLCQgHAwIGFQgCCQoLBBYCAwECHgECF4AACgkQnHGj7EtW25xOVAf1GDvgkaG4
ryNQE5qKwIdq7dMh7U+JLhLq+KHTiPuOyC5Plw98ik7zd+bhLJLaKWE3rhKwRXCY
ZJJcUYsARUG1TnRHBRRpHvL4rIPaQZK09wmomAV9/Qs4G1O3FSQUtMlgLeZwKMO4
zCV52odYqqZnM1+NuHDgkvCtd2Fe4sIQsYfRh+nnFqKTXFSfNKZvhuOnIyPuM6pc
1K7evjrfxfjPpc4L4Eh7EyeOK+1r9zUewk5Cr/ddJ40JqNganitatsEZaN5pteZt
pfEhxY0nztdgFfQE/u9tZzJC2z3DifjioWoG3epPOJucZ6YPHhUmEeGbZ+ESgmik
G5Nq+uyRCnotuQENBFNlPGEBCAD0bfWvErG4oThJ+GhW86eGFKGeAP4jUhugzO77
nuk3sbeImaOcNqn1nJANJ4iWeqImcKPPRN07FHFFbW4O63oZmrGDRq9vpwQyKogT
LDBpOZ7Sgu9qmTAI1ij2lpZK1U4dI+91XhvajzboTzWurTqe3jdGS41n9jq2jE2K
D9CG4Hf3ckpWYDXoWC2wAC1qYXhbX2u57pJIhUdfubAEkJnFJ73+B9nskSUG9pAh
eiBSyK1wPJWqgIZRmW5k9fBVJxwC520+ymU68jHK06I3U+/4gOogzMLVRjI14qdu
JSl47+jk2+O2kwqTKz6CaJ/Q+4Wu1XACVOGJz80KoQvlN/FTABEBAAGJAR8EGAEC
AAkFAlNlPGECGwwACgkQnHGj7EtW25zrnwgAuROa8bE/NTUmJ0wLrTJ5ZLgUqNC1
okVCcraQ4ce2rg0YxSoLvFLxYM/ZiVPUT2HLcm08z9yMqGLZLxo9FUJGJoUzN+JN
pE1Uo19lsUcjl1sGvHCZ20SnxY8dDdowLJTIyDvo/haiw35WBIfV1CL5yjt/KiM7
hI8VTJJasR1Z/+5XKOqxxJ/TdweZmOf7UkYDtuTCjp4+2M2gUQqsBPAVJOPyZgFF
ow3rxpQeDzH/Twx500q6hfcKEJKw0/v2rk+zhFPB1j98xRZ97eUw6hdt3g7JOSEl
g5WINq3Piv9KI61pjUedutg1Z7Nexil8vRP3Kir7W3BR98kLLKEpnAnT2Q==
=gPpa
–—END PGP PUBLIC KEY BLOCK–—

-1:-- Gnus:用 GPG 加密邮件 (Post Wenshan)--L0--C0--October 12, 2014 12:59 PM

Flickr tag 'emacs': How do I blog with org2blog

Thiago Perrotta posted a video:

How do I blog with org2blog

How do I blog with org2blog and emacs.

-1:-- How do I blog with org2blog (Post Thiago Perrotta (nobody@flickr.com))--L0--C0--October 11, 2014 02:54 PM

Tom Tromey: Emacs hint for Firefox hacking

I started hacking on firefox recently. And, of course, I’ve configured emacs a bit to make hacking on it more pleasant.

The first thing I did was create a .dir-locals.el file with some customizations. Most of the tree has local variable settings in the source files — but some are missing and it is useful to set some globally. (Whether they are universally correct is another matter…)

Also, I like to use bug-reference-url-mode. What this does is automatically highlight references to bugs in the source code. That is, if you see “bug #1050501″, it will be buttonized and you can click (or C-RET) and open the bug in the browser. (The default regexp doesn’t capture quite enough references so my settings hack this too; but I filed an Emacs bug for it.)

I put my .dir-locals.el just above my git checkout, so I don’t end up deleting it by mistake. It should probably just go directly in-tree, but I haven’t tried to do that yet. Here’s that code:

(
 ;; Generic settings.
 (nil .
      ;; See C-h f bug-reference-prog-mode, e.g, for using this.
      ((bug-reference-url-format . "https://bugzilla.mozilla.org/show_bug.cgi?id=%s")
       (bug-reference-bug-regexp . "\\([Bb]ug ?#?\\|[Pp]atch ?#\\|RFE ?#\\|PR [a-z-+]+/\\)\\([0-9]+\\(?:#[0-9]+\\)?\\)")))

 ;; The built-in javascript mode.
 (js-mode .
     ((indent-tabs-mode . nil)
      (js-indent-level . 2)))

 (c++-mode .
	   ((indent-tabs-mode . nil)
	    (c-basic-offset . 2)))

 (idl-mode .
	   ((indent-tabs-mode . nil)
	    (c-basic-offset . 2)))

)

In programming modes I enable bug-reference-prog-mode. This enables highlighting only in comments and strings. This would easily be done from prog-mode-hook, but I made my choice of minor modes depend on the major mode via find-file-hook.

I’ve also found that it is nice to enable this minor mode in diff-mode and log-view-mode. This way you get bug references in diffs and when viewing git logs. The code ends up like:

(defun tromey-maybe-enable-bug-url-mode ()
  (and (boundp 'bug-reference-url-format)
       (stringp bug-reference-url-format)
       (if (or (derived-mode-p 'prog-mode)
	       (eq major-mode 'tcl-mode)	;emacs 23 bug
	       (eq major-mode 'makefile-mode)) ;emacs 23 bug
	   (bug-reference-prog-mode t)
	 (bug-reference-mode t))))

(add-hook 'find-file-hook #'tromey-maybe-enable-bug-url-mode)
(add-hook 'log-view-mode-hook #'tromey-maybe-enable-bug-url-mode)
(add-hook 'diff-mode-hook #'tromey-maybe-enable-bug-url-mode)
-1:-- Emacs hint for Firefox hacking (Post tom)--L0--C0--October 09, 2014 07:20 PM

Phil Hagelberg: in which cards are stacked

My childhood summers involved many days spent building out expansive HyperCard stacks to explore in a game world that spanned across cities and islands and galaxies, littered with creatively absurd death scenes to keep you on your toes. The instant accessibility of HyperCard invited you to explore and create without feeling intimidated. Especially for younger minds, I believe there's something fundamental about the spatial aspect of HyperCard. Every button has its place, and rather than creating an abstract hierarchy of classes or a mesh of interconnected modules, you can see that buttons have a specific place on a card, which exist "inside" a stack in a metaphor that maps to the way we already perceive the world.

you know, for kids

While Apple killed HyperCard off many years ago, there exist tools for children today that maintain this accessible spatial arrangement. I've written before about how my kids love playing with Scratch, a Logo-descendant providing colorful sprites and drag-and-drop scripts to animate them. While this is unbeatable for the early years, (especially for kids who are only just beginning to learn to read) eventually you hit an abstraction ceiling beyond which it becomes very tedious to express your ideas due to its non-textual nature. There are modern HyperCard clones like LiveCode, which offers a very sophisticated platform, but falls prey to the same tragic pitfall of attempting to build an "English-like" programming language, an endeavour which has been attempted many times but always ends in tears.

myst island

So as I've thought a good next step for my own children, we happened to start playing the game Myst. Given my children's proclivities, this was immediately followed by Myst copycat worlds drawn out in elaborate detail with pen and paper the next day. I thought of what I could do to bring back the exploration and creativity of HyperCard, and eventually I got to building my own implementation.

The natural choice for this project was definitely the Racket language. While I'm much more familiar with Clojure, it's a very poor fit for a first-time programmer, especially at a young age. Racket boasts lots of great learning material, but beyond the texts there's just an ever-present focus on usability and clarity that shines through in all aspects of the language and community.

drracket error

Racket's roots lie with the famously-minimalistic Scheme, but it's grown to be a much more practical, expansive programming language. While there are still a few places in which its imperative roots show through, it has good support for functional programming and encourages good functional practice by default for the most part. (I hope to do a future post on a few ways to improve on its FP, both via the Rackjure library and some of my own hacks.) But what really sets Racket apart is its solid tooling and libraries. I wouldn't put my kids down in front of Emacs, but Racket ships with a very respectable IDE that's capable and helpful without being overwhelming. The GUI and drawing libraries that come with Racket have proven to be very useful and approachable for what I've done so far.

So far Cooper, my HyperCard clone, is fairly simplistic. But in just over 500 lines of code, I have a system that supports manipulating stacks of cards, drawing backgrounds on them, and laying out buttons which can either navigate to other cards or invoke arbitrary functions.

It's not sophisticated, but my children have already shown plenty of interest in using it to build out small worlds of their own in the cards. They've so far been willing to put up with lots of glitches and poor performance to bring their imaginations to life, and I'm hoping that this can gradually grow into a deeper understanding of how to think in a logical, structured way.

-1:-- in which cards are stacked (Post Phil Hagelberg)--L0--C0--October 07, 2014 10:25 PM

Ben Simon: Miva Merchant for Code Geeks; Or how I fought against the default Miva dev model and sort of won

Miva Merchant? Let's Do it!

I've got a relatively new client who's current platform is MivaMerchant. While he's open to switching to a new platform, I'm hesitant to do so without a firm grasp of his business and what the pros/cons of Miva are. So for now, I need to become best buds with Miva.

Doing a few Google searches turned up MivaScript.com, which implies that Miva is, well, scriptable. And while the syntax appears to be on the clunky side (it's XML based, so that is to be expected), it does look relatively complete.

As I dove into my first few projects, I started to come up to speed on Miva. The video tutorials are well done, the admin tool quite complete, and template language (audaciously named Store Morph Technology aka SMT) looked promising.

But wait...

As I started to truly build out my projects I kept running into two questions: (1) where's the flat file interface for the templates, and (2) when do I get to start using MivaScript?

While the admin UI is nice and all (there's a basic version control system built in), it's hardly the ideal environment to work on large template files (which are a mix of HTML and special tags). Or put more bluntly, I want to use emacs to edit content, not a text area in Firefox. Surely I was missing something. Finally I broke down and filed a ticket on the topic. The tech rep said she'd call me to discuss; and sure enough she did. She explained to me that you *have* to use the admin UI, there is no file interface. Apparently, the Miva techs work by copying and pasting content into a text editor, making changes, and copying and pasting it back.

While the tech was very nice (and again, promptly called me), surely she must have just been misinformed. Miva can't expect professional programmers to build sophisticated stores by copying and pasting code. Can they? Even if I'm OK with all this copying and pasting, how am I supposed to use a real version control system or do an automated deployment, if all the source code needs to live in an HTML admin tool?

I took my quandary further up the Miva chain. (Which again, I give them credit for having as an option.) I finally spoke to a senior developer and he told me that the tech's understanding is correct. They are aware of the limitations of the admin UI, but it's the only way they currently support using Miva. I got the impression that future versions of the product may help address this issue.

OK, I'll learn to love the admin UI. My work around for now is to keep a version of the templates found in Miva in a local source repository. The content of the PROD page for example, is stored in: admin/Pages/PROD/Page.smt.

And it gets worse

Issue number (2), however, points to a potentially larger concern. After a bunch of research I learned that Miva Merchent itself is written in MivaScript< and while the templates themselves understand SMT tags, they don't process MivaScript. In other words, your typical MivaMerchant developer never writes or even encounters MivaScript. Fair enough. But how do they modularize code? That is, how do I void duplicating code in templates, and how do I keep my templates from growing out of control? Looking at the template language of choice, there didn't seem to be a way to include code. Without a basic include statement, how can I achieve any sort of modularity?

I ran these questions by the nice tech that called me. The short answer was, there is no way to do this. At the senior tech level, he mentioned something about setting up custom items that would appear in the UI as their own editable regions, and then I could include those items at will. This is somewhat promising, but that means embracing the the admin UI even more.

All this left me pretty disappointed with Miva. There simply had to be a way to make it more developer friendly.

A first attempt at a fix

If the standard set of tools weren't going to give me what I wanted, what about building out a custom extension or two? I make custom plugins in WordPress all the time, how hard could it be to do in Miva? This seemed promising, as extensions are written in MivaScript, so I'd get power of a full programming language instead of making do with an admin UI and the basic SMT language. Alas, after a few days of analyzing extensions (you can see lots of examples in the source for MivaMerchant provided here (and you'll need the compiler here), I finally had to throw in the towel. Between the fact that MivaScript is a language unto itself, and my lack of understanding of how MivaMerchant operates, I'm just not ready to create extensions for it. I had to surrender.

And the real fix

But still, I wasn't ready to give up on my dream of a move developer friendly Miva experience. And then I found the missing piece of the puzzle: the External File Pro v5+ module. This bad boy allows you to invoke a MivaScript function in an arbitrary file, and it places the result in an SMT file of your choice.

Let's take a specific example to see how this module can save the day. Suppose you want to customize your title tag depending your product name. You could head over to the PROD page and put in some code like this:

<mvt:if expr="l.all_settings:product:name EQ 'Iguana'>
  <title>Love Lizards! Buy an Iguana Today!</title>
</mvt:if>
<mvt:if expr="l.all_settings:product:name EQ 'Turtle'>
  <title>Totally Turtles! Buy an Turtle Today!</title>
</mvt:if>
...

But, that code is messy and hard to maintain. Ideally, it would live in its own function, in its own file. That's where External File Pro comes.

The first order of business is to buy and install the External File Pro v5+. Once you've enabled the module and associated it with the PROD page you're ready to get to work.

I created a MivaScript source file: /mm5/snippets/seo/title.mv. The path is totally arbitrary. I plan to organize all these includes as snippets, and this particular one is related to SEO. Hence the naming. Note, the source file is .mv. The actual MivaScript file looks something like this:

<MvComment>
  Generate our Page Title in a smart way. If we can make a better title than the default one, then
  go for it.
</MvComment>

<MvFUNCTION NAME = "ADS_External_File" PARAMETERS = "module var, item, all_settings var, settings var, ignored" STANDARDOUTPUTLEVEL = "text, html, compresswhitespace">
  <MvIF EXPR = "{ l.all_settings:product:name EQ 'Iguana' }">
    <MvEVAL EXPR = "{ '<title>' $ 'Love Lizards! Buy a ' $ l.all_settings:product:name . ' Today!' $ '</title>' }"/>
    <MvFUNCTIONRETURN />
  </MvIF>

  <MvIF EXPR = "{ l.all_settings:product:name EQ 'Turtle' }">
    <MvEVAL EXPR = "{ '<title>' $ 'Totally Turtles! Buy a ' $ l.all_settings:product:name . ' Today!' $ '</title>' }"/>
    <MvFUNCTIONRETURN />
  </MvIF>

  <MvEVAL EXPR = "{ '<title>' $  $ l.all_settings:product:name $ '! Buy one Today!' $ '</title>' }"/>
  <MvFUNCTIONRETURN />
</MvFUNCTION>

Notice that the function is named ADS_External_File. That's a requirement of the External File Pro plugin, and serves as the entry point to our snippet.

This file needs to be compiled to a .mvc file. I'm using a simple Makefile to accomplish this:

## Makefile for building our MivaScript function files

export PATH := /c/tools/miva/msc/BIN:$(PATH)
RM  = rm
MVC = mvc.exe  -B 'c:\tools\miva\msc\BUILTINS'
SNIPPETS = seo/title
SRCS     = $(addsuffix .mv, $(SNIPPETS)))
COMPILED = $(addsuffix .mvc, $(SNIPPETS))

all : $(COMPILED)

%.mvc : %.mv
 $(MVC) $<

clean :
 $(RM) -f $(COMPILED)

With the command:

  make ;  sitecopy -u dev.mysite.com

The snippet is compiled and pushed to the server.

Finally, in the PROD Page template I put in a call to the snippet:

  <mvt:item name="ads-extfile" param="function|/mm5/snippets/seo/title.mvc"/>

And I'm done.

Whoo!

I've now got the ability to create arbitrary functions in MivaScript and pull their contents into an a template. This gives me the modularity and maintainability I was after, and opens the door to streamlining development of complex functionality. Looks like Miva and I may indeed be best buds after all.

-1:-- Miva Merchant for Code Geeks; Or how I fought against the default Miva dev model and sort of won (Post Ben Simon)--L0--C0--October 07, 2014 08:44 AM

Dev and Such [Emacs Category]: New and Improved Emacs Config!

I finally did it. I moved my Emacs configuration into a .org file.

You can see the results here on GitHub. There's not much else to say in this post, honestly. The configuration pretty much speaks for itself.

Thanks to Sacha Chua for the inspiration.

-1:-- New and Improved Emacs Config! (Post)--L0--C0--October 06, 2014 09:20 PM

Bryan Murdock: SystemVerilog Streaming Operator: Knowing Right from Left

SystemVerilog has this cool feature that is very handy for converting one type of collection of bits into another type of collection of bits.  It's the streaming operator.  Or the streaming concatenation operator.  Or maybe it's the concatenation of streaming expressions (it's also called pack/unpack parenthetically).  Whatever you want to call it, it's nice.  If you have an array of bytes and you want to turn it into an int, or an array of ints that you want to turn into an array of bytes, or if you have a class instance that you want to turn into a stream of bits, then streaming is amazing.  What used to require a mess of nested for-loops can now be done with a concise single line of code.

As nice as it is, getting the hang of the streaming operator is tough.  The SystemVerilog 1800-2012 LRM isn't totally clear (at least to me) on the details of how they work.  The statement from the LRM that really got me was this, "The stream_operator << or >> determines the order in which blocks of data are streamed: >> causes blocks of data to be streamed in left-to-right order, while << causes blocks of data to be streamed in right-to-left order."  You might have some intuitive idea about which end of a stream of bits is on the "right" and which is on the "left" but, I sure didn't.  After looking at the examples of streaming on page 240 of the LRM I thought I had it, and then none of my attempts to write streaming concatenations worked like I thought they should.  Here's why: "right" and "left" are different depending on whether your stream of bits is a packed array or an unpacked array.

As far as I can tell, "right" and "left" are in reference to the literal SystemVerilog code representations of an arrays of bits.  A literal packed array is generally written like this:

bit [7:0] packed_array = 8'b0011_0101;

And packed_array[0] is on the right (that 1 right before the semicolon).  A literal unpacked array is written like this:

bit unpacked_array[] = '{1'b1, 1'b0, 1'b1, 1'b0};

unpacked_array[0] is on the left (the first value after the left curly brace).  I don't know about you, but I'm generally more concerned with actual bit positions, not what is to the right and left in a textual representation of an array, but there you have it.

Once I got that down, I still had problems.  It turns out the results of streaming concatenations will be different depending on the variable you are storing them in.  It's really the same right/left definitions coming into play.  If you are streaming using the right-to-left (<<) operator, the right-most bit of the source will end up in the left-most bit of the destination.  If your destination is a packed array then, just as I explained above, "right" means bit zero and left means the highest index bit.  If, your destination is an unpacked array, your right-most source bit will end up as bit zero of the unpacked array (which is the "right" bit according to the literal representation).

Got all that?  If not, I put a code example on edaplayground that you can run and examine the output of.  The examples are all streaming bits one at a time.  It gets a little harder to wrap your head around what happens when you stream using a slice_size and when your source and/or destinations array is an unpacked array of bytes or ints. I'll write another post explaining some tricks for those next (UPDATE: next post is here).

-1:-- SystemVerilog Streaming Operator: Knowing Right from Left (Post Bryan (noreply@blogger.com))--L0--C0--October 06, 2014 07:38 PM

Bryan Murdock: More SystemVerilog Streaming Examples

In my previous post I promised I would write about more interesting cases of streaming using a slice_size and arrays of ints and bytes.  Well, I just posted another set of streaming examples to edaplayground.  I'm going to mostly let you look at that code and learn by example, but I will take some time in this post to explain what I think is the trickiest of the conversions.  When you go to edaplayground, choose the Modelsim simulator to run these.  Riviera-PRO is currently the only other SystemVerilog simulator choice on edaplayground, and it messes up on the tricky ones (more on that in a bit).

These examples demonstrate using the streaming operator to do these conversions:
  • unpacked array of bytes to int
  • queue of ints to queue of bytes
  • queue of bytes to queue of ints
  • int to queue of bytes
  • class to queue of bytes
Of all those examples, the queue of ints to queue of bytes and the queue of bytes to queue of ints are the tricky ones that I want to spend more time explaining.  They are both tricky for the same reason.  If you are like me, your first thought on how to convert a queue of ints to a queue of bytes is to just do this:

byte_queue_dest = {<< byte{int_queue_source}};

Before I explain why that might not be what you want, be sure you remember what "right" and "left" mean from my previous post.  The problem with the straightforward streaming concatenation above is it will start on the right of the int queue (int_queue_source[max_index], because it's unpacked), grab the right-most byte of that int (int_queue_source[max_index][7:0], because the int itself is packed), and put that byte on the left of byte_queue_dest (byte_queue_dest[0], because it is unpacked).  It will then grab the next byte from the right of the int_queue (int_queue_source[max_index][15:8]) and put it in the next position of byte_queue_dest (byte_queue_dest[1]), and so on.  The result is that you end up with the ints from the int queue reversed in the byte queue.  If that doesn't make sense, change the code in the example to the above streaming concatenation and just try it.

To preserve the byte ordering, you do this double streaming concatenation:

byte_queue_dest = {<< byte{ {<< int{int_queue_source}} }};

Let's step through this using the literal representation of the arrays so that rights and lefts will be obvious.  You start with an (unpacked, of course) queue of ints:

int_queue_source = {'h44332211, 'h88776655};

And just to be clear, that means int_queu_source[0][7:0] is 'h11 and we want that byte to end up as byte_queue_dest[0].  The inner stream takes 32-bits at a time from the right and puts them on the left of a temporary packed array of bits.  That ends up looking like this:

temp_bits = 'h8877665544332211;

Now the outer stream takes 8 bits at a time from the right of that and puts them on the left of a queue.  That gives you this in the end:

byte_queue_dest = {'h11, 'h22, 'h33, 'h44, 'h55, 'h66, 'h77, 'h88};

Which, if you wanted to preserve the logical byte ordering, is correct.  Going from bytes to ints, it turns out, is pretty much the same: reverse the queue of bytes and then stream an int at a time.

So what happens with Riviera-PRO?  If you try it in edaplayground you see that the resulting queue of bytes in the int-to-byte conversion ends up with a whole bunch of extra random bytes on the right (highest indexes of the queue).  8 extra, to be exact.  Same for the int queue result in the byte-to-int conversion.  I think Riviera-PROP must be streaming past the end of the temporary packed array (that I called temp_bits above) of pulling in bytes from off in the weeds.  Pretty crazy.  That's all done behind the scenes so I don't really know, but that's sure what it looks like.  Hopefully they can fix that soon.

Well, I hope I've helped clear up how to use the streaming operators for someone.  If I haven't, I have at least helped myself understand them better.  Ask any questions you have in the comments.
-1:-- More SystemVerilog Streaming Examples (Post Bryan (noreply@blogger.com))--L0--C0--October 06, 2014 07:37 PM

肉山博客: Hack 记录:emacs-moz-controller 的创造过程

:这是我在写 moz-controller 时的记录,因为是写给自己看的,所以思维比较跳跃,文字也没有雕琢,只是希望能为 Emacs Lisp 爱好者提供一些参考价值。

《在 Emacs 中控制 Firefox 翻页、刷新、关闭页面》 的时候, 感觉这些有共性的函数, 可以放到一个插件里. 正好我还没有从头到尾写过 Emacs 插件, 这也是个练手的机会.

1 初步想法

依赖于: mozrepl plugin, Emacs moz-repl (在 README 里说明)

功能:

说明 函数名 快捷键 (以 C-c m 开头)
refresh   r
close tab   k
scroll down/up   n/p
previsou/next tab   l/f
zoom in/out   +/-

杂:

  • global-moz-controller-mode: 全局开启这个模式, 默认为 nil, 看一下别人是怎么实现的
  • keymap: 键盘布局
  • require moz-repl: 依赖
  • 提供一个 hook
  • (provide ‘moz-controller)
  • 放 github 上
  • 在 el-get, melpa 等发布
  • 在 emacswiki, g+, twitter, HN, reddit, 微博, 豆瓣上面宣传一下
  • 先实现想要的功能, 再写成一个 emacs 插件

2 Get it Run First

2.1 上/下一个标签页

跟李总找了半天, JavaScript console 下好像没有相应的命令, 我看了 KeySnail 的代码, 切到前一个标签页是:

getBrowser().mTabContainer.advanceSelectedTab(-1, true);

但是这个在 console 运行会返回一个错误, 放个书签 , 先弄2.2吧… 缩放弄好了, 现在跳回来继续搞标签页.

在 MozRepl 试试, 先用 isend 绑定一下, 以便给 MozRepl 发送代码 (参照: http://wenshanren.org/?p=351): M-x isend-associate *MozRepl*

getBrowser().mTabContainer.advanceSelectedTab(-1, true);

好使!

试试切到下一个标签页:

getBrowser().mTabContainer.advanceSelectedTab(1, true);

也好使, 赞赞赞, 我爱 Emacs !!!

写函数:

(defun moz-tab-previous ()
  "Switch to the previous tab"
  (interactive)
  (moz-send-command "getBrowser().mTabContainer.advanceSelectedTab(-1, true);")
  )

(defun moz-tab-next ()
  "Switch to the next tab"
  (interactive)
  (moz-send-command "getBrowser().mTabContainer.advanceSelectedTab(1, true);")

搞定!

我想要的功能都有了, 可以开始写插件了.

但是发现这些函数都是 defun 跟函数名, 跟文档, 跟 (interactive), 最后 (moz-send-command “function”). 感觉可以写个 macro 了, 学了这个锤子之后, 还没用它钉过钉子. 先把代码 “优化” (很多人觉得 macro 应该尽量少用, 我自己对编程语言学没有研究, 不持任何意见) 一下吧: 3

2.2 缩放

#emacs 上的 average 给了我不少帮助, 告诉我如何通过 MozRepl 对页面进行缩放, 给我推荐了进一步了解 MozRepl 的几个链接, 还顺带推荐了 youtube-dl.org, livestreamer 和 DownloadHelper 等几个很有用的网站和工具.

设置缩放的代码是:

gBrowser.selectedBrowser.markupDocumentViewer.fullZoom = <wanted value>

这个也不能在 JavaScript console 里运行, 但 MozRepl 的功能是超过 console 的.

根据这个, 写了三个函数, 放大, 缩小, 复原.

(defun moz-zoom-in ()
  "Zoom in"
  (interactive)
  (moz-send-command "gBrowser.selectedBrowser.markupDocumentViewer.fullZoom += 0.1;"))

(defun moz-zoom-out ()
  "Zoom out"
  (interactive)
  (moz-send-command "gBrowser.selectedBrowser.markupDocumentViewer.fullZoom -= 0.1;"))

(defun moz-zoom-reset ()
  "Zoom in"
  (interactive)
  (moz-send-command "gBrowser.selectedBrowser.markupDocumentViewer.fullZoom = 1"))

可以用, 但是发现一旦切换到其他标签页再切换回来, 缩放效果就没有了. 先这样吧, 有时间再改. 现在知道了 MozRepl 可以一些执行 console 没法执行的命令, 感觉在 Emacs 中让 Firefox 切换标签页的功能也可以实现. 回去继续弄标签页 2.1.

3 代码优化

想法主要是用 macro 把代码简化一下, macro 在很多文章和书籍中都看到过, 但这还是我头一回在实际中使用.

先看一下说明, C-h f defmacro:

defmacro is a Lisp macro in `byte-run.el'.

(defmacro NAME ARGLIST &optional DOCSTRING DECL &rest BODY)

Define NAME as a macro.
When the macro is called, as in (NAME ARGS...),
the function (lambda ARGLIST BODY...) is applied to
the list ARGS... as it appears in the expression,
and the result should be a form to be evaluated instead of the original.
DECL is a declaration, optional, of the form (declare DECLS...) where
DECLS is a list of elements of the form (PROP . VALUES).  These are
interpreted according to `macro-declarations-alist'.
The return value is undefined.

然后在 el-get 下载的代码中 grep 一下 defmacro, 看看别人是怎么用的. 找到一个 paredit 下的例子, 感觉跟我要做的事情差不多, 都是给 defun 套一层壳:

(eval-and-compile
  (defmacro defun-saving-mark (name bvl doc &rest body)
    `(defun ,name ,bvl
       ,doc
       ,(xcond ((paredit-xemacs-p)
                '(interactive "_"))
               ((paredit-gnu-emacs-p)
                '(interactive)))
       ,@body)))

照虎画猫, 又看了 elisp 的 info, 鼓捣了一段时间才搞定:

(defmacro defun-moz-command (name arglist doc &rest body)
  "Macro for defining moz commands.  Pass in the desired
JavaScript expression as BODY."
  `(defun ,name ,arglist
     ,doc
     (interactive)
     (comint-send-string
      (inferior-moz-process)
      (car (quote ,body)))
     )
  )

然后改写之前的命令, moz-send-command 可以不要了:

(defun-moz-command moz-reload-browser ()
  "Refresh current page"
  "setTimeout(function(){content.document.location.reload(true);}, '500');"
  )

(defun-moz-command moz-page-down ()
  "Scroll down the current window by one page."
  "content.window.scrollByPages(1);"
  )

(defun-moz-command moz-page-up ()
  "Scroll up the current window by one page."
  "content.window.scrollByPages(-1);"
  )

(defun-moz-command moz-tab-close ()
  "Close current tab"
  "content.window.close();"
  )

(defun-moz-command moz-zoom-in ()
  "Zoom in"
  "gBrowser.selectedBrowser.markupDocumentViewer.fullZoom += 0.1;"
  )

(defun-moz-command moz-zoom-out ()
  "Zoom out"
  "gBrowser.selectedBrowser.markupDocumentViewer.fullZoom -= 0.1;"
  )

(defun-moz-command moz-zoom-reset ()
  "Zoom in"
  "gBrowser.selectedBrowser.markupDocumentViewer.fullZoom = 1"
  )

(defun-moz-command moz-tab-previous ()
  "Switch to the previous tab"
  "getBrowser().mTabContainer.advanceSelectedTab(-1, true);"
  )

(defun-moz-command moz-tab-next ()
  "Switch to the next tab"
  "getBrowser().mTabContainer.advanceSelectedTab(1, true);"
  )

可读性…好像不是很好, 就先这样吧, 也算是用了一次 macro.

然后绑定快捷键:

(global-set-key (kbd "C-c m n") 'moz-page-down)
(global-set-key (kbd "C-c m p") 'moz-page-up)
(global-set-key (kbd "C-c m k") 'moz-tab-close)
(global-set-key (kbd "C-c m +") 'moz-zoom-in)
(global-set-key (kbd "C-c m -") 'moz-zoom-out)
(global-set-key (kbd "C-c m 0") 'moz-zoom-reset)
(global-set-key (kbd "C-c m l") 'moz-tab-previous)
(global-set-key (kbd "C-c m f") 'moz-tab-next)

现在可以开始进入 写成 emacs 插件 的环节了.

4 写成 Emacs 插件

看了几个视频, 发现自己上面实现的这些功能, 早就有人写过类似的了, 比如 http://www.youtube.com/watch?v=v78HRi-J2ek

不过没搜到有相应的 Emacs 扩展, 所以还是自己写一个吧.

先看看其他的扩展是怎么写的, 比如 emacs-ctable 和 emacs-edbi (我比较熟悉的扩展).

仿照着先建几个文件, 然后用 magit 初始化:

  • 名字叫 emacs-moz-controller
  • moz-controller.el
  • 中文 README.zh.org
  • 英文 README.org
  • LICENSE (GPL v3)

然后开写 emacs-moz-controller, 首先我需要让它依赖于 moz-repl, 在注释里说明一下, 然后 (require ‘moz).

然后就参照着 edbi 写了.

macro 增加点儿注释.

把函数定义都放进去.

macro 跟函数都改名成 moz-controller 开头

弄个 group, 方便 customize (虽然我没用过这个东西), 但好像也没有什么需要 customize 的东西, 可能让用户自定义每次缩放的程度吧, 这个一会儿再说,放个书签

定义一个 autoload 的 minor-mode (这个是跟 org2blog 学的, 也是我比较熟的一个扩展, 目前我是维护者之一, 虽然贡献不大):

(define-minor-mode moz-controller-mode
  "Toggle moz-controller mode.
With no argument, the mode is toggled on/off.
Non-nil argument turns mode on.
Nil argument turns mode off.

Commands:
\\{moz-controller-mode-map}

Entry to this mode calls the value of `moz-controller-mode-hook'."

  :init-value nil
  :lighter " MozCtrl"
  :group 'moz-controller
  :keymap moz-controller-mode-map

  (if moz-controller-mode
      (run-mode-hooks 'moz-controller-mode-hook)))

看了看文档, 还是不太明白 autoload 的用处.

先写 mode-map 吧, 还是仿照 org2blog 来.

(defvar moz-controller-mode-map nil
  "Keymap for controlling Firefox from Emacs.")

(unless moz-controller-mode-map
  (setq moz-controller-mode-map
    (let ((moz-controller-map (make-sparse-keymap)))
      (define-key moz-controller-map (kbd "C-c m R") 'moz-controller-page-refresh)
      (define-key moz-controller-map (kbd "C-c m n") 'moz-controller-page-down)
      (define-key moz-controller-map (kbd "C-c m p") 'moz-controller-page-up)
      (define-key moz-controller-map (kbd "C-c m k") 'moz-controller-tab-close)
      (define-key moz-controller-map (kbd "C-c m b") 'moz-controller-tab-previous)
      (define-key moz-controller-map (kbd "C-c m f") 'moz-controller-tab-next)
      (define-key moz-controller-map (kbd "C-c m +") 'moz-controller-zoom-in)
      (define-key moz-controller-map (kbd "C-c m -") 'moz-controller-zoom-out)
      (define-key moz-controller-map (kbd "C-c m 0") 'moz-controller-zoom-reset)
      moz-controller-map)))

然后弄个 hook.

(defvar moz-controller-mode-hook nil
  "Hook to run upon entry into moz-controller-mode.")

这个在 hook 在 define-minor-mode 那儿提到了, 有个 run-mode-hooks 的 sexp

可以开始实验了, 把我 init.el 里定义的相关函数都注释掉, 然后:

(add-to-list 'load-path "~/hack/el/emacs-moz-controller")
(require 'moz-controller)

突然想到自己还想实现一个 global-mode,放一个书签。先继续实验, 有基本的功能再说别的, 重启 emacs (不知道还有没有别的好方法)

然后 M-x moz-controller-mode (输入的过程中发现其他 moz-controller 函数也可以用, 这可能是没有用 autoload 的原因).

然后 mode-line 就出现了 MozCtrl, 这是我在 define-minor-mode 的时候指定的 mode 简称.

然后挨个 C-c m R/n/p/k/b/f/+/-, 所有功能试一遍, 都好使, 高兴!!!

5 global mode (书签:4

现在要弄一个 global-mode, 感觉是把 moz-controller-mode 加到一个全局的什么 hook 里? 看看别人怎么实现的吧, C-h f project-global-mode (projectile 是另外一个我常用的扩展), 然后点开其定义:

;;;###autoload
(define-globalized-minor-mode projectile-global-mode
  projectile-mode
  projectile-on)

good, 已经有现成的 define-globalized-minor-mode 了, 我只要:

;;;###autoload
(define-globalized-minor-mode moz-controller-global-mode
  moz-controller-mode
  moz-controller-on)

然后再定义几个相应的函数:

(defun moz-controller-on ()
  "Enable moz-controller minor mode."
  (moz-controller-mode t))

(defun moz-controller-off ()
  "Disable moz-controller minor mode."
  (moz-controller-mode nil))

(defun moz-controller-global-on ()
  "Enable moz-controller global minor mode."
  (moz-controller-global-mode t)
  )

(defun moz-controller-global-off ()
  "Disable moz-controller global minor mode."
  (moz-controller-global-mode nil)
  )

然后再重启 (麻烦).

M-x moz-controller-global-mode 进行 toggle, 好使!!!

git commit 一下

6 用户自定义缩放程度 (书签:4 )

让用户 customize 缩放程度, 感觉挺简单, 先看看 org2blog 里边的 customize 之类的是怎么弄的吧:

(defcustom org2blog/wp-keep-new-lines nil
  "Non-nil means do not strip newlines."
  :group 'org2blog/wp
  :type 'boolean)

这个是 boolean, 我的应该是 floating number 之类的, 但是从哪儿能知道都什么可以放 :type 里呢? Emacs 中有 booleanp, 用于判断一个值是不是 boolean, 也有 numberp, 用于判断一个值是不是 number, 所以我觉得我用 number 作为 :type 的值就可以了.

(defcustom moz-controller-zoom-step 0.1
  "Zoom step, default 0.1, it is supposed to be a positive number."
  :group 'moz-controller
  :type 'number)

然后修改一下 zoom in 函数:

(defun-moz-controller-command moz-controller-zoom-in ()
  "Zoom in"
  (concat "gBrowser.selectedBrowser.markupDocumentViewer.fullZoom += " (number-to-string moz-controller-zoom-step) ";")
  )

eval 一下, 但是发现这个不好使了:

comint-send-string: Wrong type argument: stringp, (concat "gBrowser.selectedBrowser.markupDocumentViewer.fullZoom += " (number-to-string moz-controller-zoom-step) ";")

应该是 macro 的问题, 去看看 macro 的定义, 知道问题是什么: (car (quote ,body)), 当 body 是 ((concat xxx bbb ccc)) 时, concat 这个语句本身没有执行, 只是当成 symbol 被 car 出来了, 所以会有 “Wrong type argument: stringp” 的错误提示.

可以在前边加个 eval, 但是感觉这样做不太好, 先这么着吧.

(defmacro defun-moz-controller-command (name arglist doc &rest body)
  "Macro for defining moz commands.

NAME: function name.
ARGLIST: should be an empty list () .
DOC: docstring for the function.
BODY: the desired JavaScript expression, as a string."
  `(defun ,name ,arglist
     ,doc
     (interactive)
     (comint-send-string
      (inferior-moz-process)
      (eval (car (quote ,body))))
     )
  )

可以用了.

然后再看 defun-saving-mark 这个 macro 的定义, 突然发现 ,@body, 想起来 `@’ 可以用来展开一个 list, 试试:

(defmacro defun-moz-controller-command (name arglist doc &rest body)
  "Macro for defining moz commands.

NAME: function name.
ARGLIST: should be an empty list () .
DOC: docstring for the function.
BODY: the desired JavaScript expression, as a string."
  `(defun ,name ,arglist
     ,doc
     (interactive)
     (comint-send-string
      (inferior-moz-process)
      ,@body)
     )
  )

好使!!! 搞定了. 再 commit.

基本功能全了. 下一步是 README 和注释的完善了.

7 README 和注释

先写中文的 README.zh.org

然后英文的.

然后注释.

8 放到 Github

在 Github 上新创建一个 repo, 然后 push 上去, 轻车熟路.

9 加入包管理系统

这个是我以前没有接触过的东西.

看了看 el-get, 看了看 org2blog 的 pkg.el, 有点儿头绪, 但不知道从什么地方开始, 去 G+ 上问一下吧, 没准有人能给我写个 pull request 呢 :D

自己用 screenkey + gtk-recordmydesktop 录了个视频, 发到了 youtube 上, 更新了一下 README, 先进入 G+ 的 10 阶段.

fork 了 melpa, 按照说明加了个 recipe 进去, 然后 pull request, Steve Purcell 帮我小小改动了一下, 增加了依赖关系 (moz-repl), 然后我的 pull request 就被 merge 进去了. 然后就可以通过 package 来安装了 :D. 我也相应地更新了 README, 这样一来, 基本就只剩下宣传工作了, 回到10.

10 宣传

先放在 G+ 上: https://plus.google.com/100406533905091621888/posts/TvNLNcyRo2L, 等一两天, 看看有什么回应.

收获了几个赞, 发现有人帮我放到了 reddit, 又收获了几颗星(github上).

在微博上问了一下陈斌, 他说可以自己放到 melpa 之类的包管理系统, 做个标记 , 然后回到 9

在豆瓣和微博上都发了一下, 但按照以往经验, 反响不会太高.

然后把 README 稍微改改发到博客上吧, 算是对 moz-controller 的介绍.

等明天晚上发到 hackernews 上去.

11 新功能

使用的过程中, 发现有时候希望能得到 MozRepl 的输出, 比如当前标签页的地址, 网上搜搜, 看到 stackoverflow 上的一个讨论, 试了试, 发现 gBrowser.contentWindow.location.href 可以. 但是我目前定义的这个 macro, 是只负责输入不负责读取输出的.

C-h f 看了好几个 comint 相关的函数, 但是还是不得要领.

继续去 #emacs 问问吧,没什么结果。

后来在 Stackoverflow 上开了个问题: Emacs: what is the conventional way of receiving output from a process? (http://stackoverflow.com/questions/25985569/emacs-what-is-the-conventional-way-of-receiving-output-from-a-process

经指点,看 info (elisp) Filter Functions 一节

A process “filter function” is a function that receives the standard output from the associated process. All output from that process is passed to the filter. The default filter simply outputs directly to the process buffer.

然后自己试试:

(defun ordinary-insertion-filter (proc string)
  (when (buffer-live-p (process-buffer proc))
    (setq wenshan-de-string string)
    (with-current-buffer (process-buffer proc)
      (let ((moving (= (point) (process-mark proc))))
        (save-excursion
          ;; Insert the text, advancing the process marker.
          (goto-char (process-mark proc))
          (insert string)
          (set-marker (process-mark proc) (point)))
        (if moving (goto-char (process-mark proc)))))))

(set-process-filter (get-buffer-process "*MozRepl*") 'ordinary-insertion-filter)

(process-filter (get-buffer-process "*MozRepl*"))

;; 这样就可以得到输出了, 试试怎么把最后的 "\nrepl " 和前后的引号去掉,应该用 substring 就成了

;; #emacs 上的 twb 指点了我一下, 最后用的 replace-regexp-in-string,

(insert (replace-regexp-in-string "\"\\(.+\\)\"\nrepl> " "\\1" wenshan-de-string))

;; 查一下怎么加东西进 kill-ring, http://stackoverflow.com/questions/22454087/insert-something-into-kill-ring-in-emacs, 修改函数如下:
(defun moz-controller-repl-filter (proc string)
  (when (buffer-live-p (process-buffer proc))
    (setq moz-controller-repl-string (replace-regexp-in-string "\"\\(.+\\)\"\nrepl> " "\\1" string))
    (message moz-controller-repl-string)
    (kill-new moz-controller-repl-string)
    (with-current-buffer (process-buffer proc)
      (let ((moving (= (point) (process-mark proc))))
        (save-excursion
          ;; Insert the text, advancing the process marker.
          (goto-char (process-mark proc))
          (insert string)
          (set-marker (process-mark proc) (point)))
        (if moving (goto-char (process-mark proc)))))))

(set-process-filter (get-buffer-process "*MozRepl*") 'moz-controller-repl-filter)

;;; 然后写个 moz-controller 函数,获取当前网址
(defun-moz-controller-command moz-controller-get-current-url ()
  "Get the current tab's URL and add to kill-ring"
  "gBrowser.contentWindow.location.href"
  )

最后把这些代码整合进 moz-controller,见 commit: https://github.com/RenWenshan/emacs-moz-controller/commit/91b3458241777e5747a8653f9eb4c454c48ec1e3

-1:-- Hack 记录:emacs-moz-controller 的创造过程 (Post Wenshan)--L0--C0--October 03, 2014 10:54 PM

Ben Simon: More Scheme Dev on Android, Now With Git Support

Continuing on my Scheme on Android kick, here's a solution to the most recent Programming Praxis problem. It's actually quite an interesting challenge:

It is generally accepted wisdom that people should use different passwords for each of their online accounts. Unfortunately, few people do that because of the difficulty of remembering so many passwords.

Manuel Blum — he’s the guy in the middle of the Blum Blum Shub sandwich — suggests an algorithm that hashes a web site name into a password. Further, his algorithm is cryptographically secure, so no one else can determine your password, and can be worked mentally, without a computer or even pencil and paper.

Read more about the algorithm here. I don't have the mental muscle to execute the hash in my head, but it was a terrific little coding challenge.

I used the same setup as last time: Gambit Scheme + DroidEdit + Perixx 805L Keyboard. For the most part, I found myself writing and executing Scheme with little regard for the fact that I was working on a cell phone. That, of course, is what I'm after.

Two improvements I've made in the setup:

First, I've defined a procedure named lex, which I can invoke to reload the source file I'm working on:

This combined with a couple of keyboard shortcuts to switch between Gambit and DroidEdit means that I can modify, reload and execute new code with relative ease. Having the source code live in ex1.scm means that the entire solution to the problem will be in one file. Which for the purposes of developing solutions to these brain teasers is ideal.

Second, I've setup git in Terminal IDE. So now, when I'm finished developing a solution, I can archive it. DroidEdit has built in support for Git, but I prefer a command line interface to version control.

Setting up Terminal IDE took just a bit of wrangling. Here's what I did:

  • Made sure the appropriate public key was in Github.
  • On a Linux machine that had the dropbear ssh tools installed, I converted my private key to be in the dropbear format:
    mkdir ~/tmp/working
    cp ~/.ssh/id_dsa ~/tmp/working
    cd ~/tmp/working
    ssh-keygen -p -f id_dsa # strip the encryption from the openssh key
    dropbearconvert openssh dropbear id_dsa id_dsa.db
    # Copy id_dsa.db to the Galaxy S5
    rm -rf ~/tmp/working
    
  • Checked the key on my phone by running the following within Terminal IDE:
    ssh -i id_dsa.db git@github.com
    
  • Within Terminal IDE, I created a wrapper script named gitssh to launch ssh properly:
    #!/data/data/com.spartacusrex.spartacuside/files/system/bin/bash
    ssh -i $HOME/id_dsa.db $*
    
  • Still within Terminal IDE, I set the GIT_SSH variable to the above script:
    setenv GIT_SSH=gitssh
    
  • I was then able to launch git commands as usual:
     git clone ssh://git@github.com/benjisimon/code
     ...
    

Happy on the go hacking!

-1:-- More Scheme Dev on Android, Now With Git Support (Post Ben Simon)--L0--C0--September 29, 2014 08:13 AM