剪贴板里的样式

高亮剪贴板里的代码片段 我前几天在准备一个培训的slides的时候,想在Keynote中粘贴一段代码,默认的粘贴板中的内容并没有样式,粘进去之后就是纯文本,没有语法高亮不说,默认的,代码的字体会采用Keynote默认的字体,非常难看。 之前在Intellij中有个插件'Copy' on steroids,这个插件可以将Intellij的编辑器中的高亮过的文本拷贝到剪贴板,然后就可以在Keynote中使用了。 我就想能不能有对应的命令行工具,结果还真的找到一个,就叫highlight,主页在这里。(这里略微吐槽一下,这个官方页面的风格以今天的眼光来看,无论是配色还是样式布局等,都非常难看,完全是10年前的风格,不过这个小工具确实很好用)。 基本使用 在Mac下,安装非常简单: $ brew install highlight highlight支持很多格式,HTML,RTF甚至还有LaTeX。不过如果要在Keynote或者PowerPoint中使用,用RTF(Rich Text Format)就可以了。 选择要高亮的文件,比如app.rb require 'sinatra' require 'rack/contrib' require 'active_record' require 'json' require './model/plants' class FrontendApplication < Sinatra::Base get '/' do File.open('index.html').read end end 然后使用命令: $ highlight -O rtf app.rb | pbcopy 即可将高亮过的内容复制到剪切板中,然后只需要CMD+V就可以粘贴了: 如果要生成HTML格式,只需要指定: $ highlight -O html app.rb > app.rb.html 自定义语言(扩展) 如果遇到不支持的语言时,默认的highlight会报错,要查看所有支持的语言,可以使用 $ highlight -p 所有的highlight内置的语言高亮配置都存储在本地的一个目录中,比如在我的机器上,存储位置为/usr/local/Cellar/highlight/3.18_1/share/highlight/langDefs/。 还以Java为例,该目录下会有一个文件,名为java.lang,内容如下: Description="Java" Keywords={ { Id=1, List={"abstract", "default", "if", "private", "this", "do", "implements", "protected", "throw", "break", "import", "public", "throws", "else", "instanceof", "return", "transient", "case", "extends", "try", "catch", "final", "interface", "static", "finally", "strictfp", "volatile", "class", "native", "super", "while", "const", "for", "new", "switch", "continue", "goto", "package", "synchronized", "as", "in", "def", "property"}, }, { Id=2, List={"boolean", "double", "byte", "int", "short", "void", "char", "long", "float"}, }, { Id=3, Regex=[[@\w+]], }, { Id=4, Regex=[[(\w+)\s*\(]], }, } Strings={ Delimiter=[["|']], Escape = [[ \\u\d{4}|\\x?...

January 24, 2015 2 min

site_prism中的Page Object

PageObject简介 PageObject是编写UI测试时的一种模式。简而言之,你可以将所有知道页面细节的部分放入到这个对象上,对于编写测试的人来说,一个PageObject代表了一个页面,或者页面上的一个区域(比如搜索框,搜索结果,侧边栏等都可能是一个独立的Object)。这样做的好处分为两个方面: 封装了所有的实现细节(内部的HTML是如何组织的) 对外的接口非常清晰,从而代码更加语义化 我们这里列举一个简单的例子来说明: 我们要测试的场景是:我们在一个搜索应用中,用户输入了ThoughtWorks,我们来判断搜索结果的第一页有10条结果。如果使用原生的capybara,代码大致会如下: visit '/search' fill_in 'Search', :with => 'ThoughtWorks' click_button '#search' expect(find('#result').find('.tips')).to have_content("10") 首先我们进入/search页面,然后在Search中输入了ThoughtWorks关键字,然后点击#search按钮,最后判断#result .tips下有10的字样。 如果使用PageObject,代码则会变成(这个是伪代码): search = SearchBox.new result = SearchResult.new search.type "ThoughtWorks" expect(result.count).to eq(10) site_prism 简介 site_prism是一个构建在capybara之上的用于建模Page Object的gem。使用site_prism可以很语义化的编写Page Object,可以使代码非常易读。 位于顶层的Page对象可以拥有多个Section对象,每个Section可以对应页面上的一些逻辑上的块,比如内容区域,边栏等。对于现在流行的SPA,我们只需要一个Page和若干个Section就足够了。 class MovingHome < SitePrism::Page set_url 'http://localhost:8100/bundles/moving-home' element :container, "#tmsCheckout" section :personal, PersonalSection, "#acc-personal" section :contact, ContactSection, "#acc-contact" end set_url方法制定了如何到达当前页,也是webdriver会实际发送请求的URL。页面本身上可以用element方法来声明一个元素,以及该元素对应的CSS选择器,这样就可以通过元素的名称来访问该选择器对应的HTML元素了。 比如上例中的container,我们在测试中就可以这样来访问它: @moving = MovingHome.new @moving.load @moving.container.should be_visible 而对应的section元素,则声明了一个块的名称,块的类和块的选择器。这样我们就可以通过名称来应用该块了: @moving.personal.name.set "Juntao" expect(@moving).to have_personal expect(@moving).to have_contact have_前缀加块的名称,用来判断该块是否可见(比如display: block)。...

January 2, 2015 2 min

我的2014

依照惯例,我每年在元旦时候都会写一篇回顾,总结过去,展望未来。不过很少跟上一年指定的计划真正去比较,一般都是列举一下这一年做的事情。 大致分下来,可以分为上半年和下半年两部分,这当然不是废话。因为上半年和下半年分别在两个完全不同的项目上工作。 技术咨询项目 上半年在一个国内咨询项目上,主要做的事情有(其实我是作为前端专家加入的,不过后来工作重心发生了改变): GIS平台 大数据平台 关于GIS最后的产出是一系列博客,而且还在InfoQ上发表了一篇。 而后来我又根据我iPhone上照片的经纬度信息,汇总出了一个热力图(使用QGis): 大数据相关的所有东西都在我的gist上,还没有时间整理。 硬件 回到办公室之后,发现了硬件小组提供的一大堆有意思的工具和器件,包括3D打印机,Arduino的一些芯片等,为了纪念我的GIS项目,我还打印了一个瓦片: 不断将我拖延了4年的机器小车组装了起来,而且还使用舵机,蓝牙,超声波等模块制作了一个实际的雷达: Sessions & Workshop 5月底回到办公室后,我发现Office的气氛其实比我来的时候低落了很多,ThoughtWorks的感觉非常淡了。 一方面是新人太多,而来新的项目所在的11楼由于客户的关系(我自以为),同事们的积极性极低。一个最容易看到的信号就是Session变得很少,我尝试做一些改变。 分别做了一些关于自动化测试,JavaScript方面的Session和Workshop,下面是《可测试的JavaScript》的Workshop。这是我第一次组织比较大的,而且时间比较长的Workshop。 有了上一次的Feedback,在年底的时候,我又组织了一次为期3周的Workshop,受众更是扩大到了各种角色,包括BA,UX,UIDev,QA等等。 写作 今年的博客数量减少了,一个原因是我在编写我的第二本书《轻量级Web应用开发》,经过几个月的坚持和努力,这本书已经编写完成,应该会在明年(2015年)年初与读者见面。 另外,在休年假的时候(3周3页面之后),我将Workshop的内容做了整理,并加入了一些设计相关的内容,形成了一本电子书,名为《3 web designs in 3 weeks》。 其他 我正在努力的向UX角色的转变,所谓千里之行,始于足下。我在休年假期间,买了一大堆UX相关的书籍。目前正在努力学习画画: 在今天的CST的创新课上,我们一起设想了几个场景,下面是我自己画的图: 最后是一张我自己设计的自己的名片: 希望来年可以在自己努力的路上看到一些成果吧。

December 27, 2014 1 min

配置Sublime成为Javascript开发环境

我在编写《JavaScript核心概念及实践》一书的时候,为了保证读者学习时可以比较专注语言本身,专门用Swing开发了一个小工具JSEvaluator。 这个工具可以当做JavaScript的简单的IDE,有一个编辑区域,有一些按钮(打开,保存,执行等),执行之后还可以将结果显示在一个面板上。书出版后不断有读者问我如何将这个工具运行起来(我自己写这个工具的时候,并没有release的概念,而且最初的几个版本可用之后,就再也没有花心思维护),单独回复比较耗时,今天早上又收到一位热心读者的邮件,就在这里统一回复一下。 其实JSEvaluator的思想和其他的IDE一样:将一个编辑器和命令行工具结合在一起,编辑器提供编辑功能,然后IDE可以将编辑器中的文本发送给命令行工具执行(使用Rhino),将结果重定向到界面上。 Sublime Text提供的Build功能也可以做到这一点,并且可以使用它更加强大的其他编辑特性,因此推荐各位读者使用这里介绍的方式。 Sublime Text编辑器 Sublime Text是一个文本编辑器,非常轻量级,并且有丰富的插件机制。虽然它不是一个免费软件,但是如果不注册还是可以无限试用下去,除了不定时的弹出一个对话框之外。它在现在的前端开发中非常流行,我作为一个Vim的忠实粉丝,也已经花费了很多时间在Sublime Text上了。 在写书的时候,JavaScript已经比较火了,但是更多的是在Web端。在本地开发的支持上还是比较薄弱。但是现在就不一样了,各个操作系统平台上都已经有了许多本地的JavaScript执行环境。比如Mac自带的jsc,跨平台的node等。 准备工作 如果你在使用Mac OS X,请直接跳到下一步。如果你在使用Windows,请先安装node.js的Windows版本,然后保证node.exe在系统的PATH环境变量中。 自定义build 在Sublime Text中,点击Tools -> Build System -> New build system...,Sublime会打开一个文件,我们来编辑这个文件: { "cmd": ["jsc", "$file"], "selector": "source.js" } 上边这个命令指定了这个build使用的命令是jsc。如果你在Windows下使用node,那么对应的这个文件应该写成: { "cmd": ["node", "$file"], "selector": "source.js" } 如果node.exe不在环境变量PATH中,请保证将其加入。完成这个文件的编辑之后,将其保存为JavaScript.sublime-build文件(Sublime会提示你输入文件名,因此输入JavaScript即可)。 开始开发 接下来你就可以在Sublime中开发并编译JavaScript代码了,应该注意的是,如果你使用的是jsc,那么console.log这样的函数式不能直接使用的,不过你可以很容易的将其重新定义: var console = console || {}; console.log = debug; 这里的debug是Sublime提供的输出函数,它将会把结果输出在Sublime的控制台上。 运行构建的快捷键,在Mac OS X下为(Cmd+B),Windows下为(Ctrl+B)。运行之后,可以看到在编辑器的底部会有一个小的窗口打开,里边的内容就是执行结果了。 其他资料 这里有一个英文版,这里是另一个 这里有一个中文版,以及它的补充 Note:由于我自己不使用Windows平台,也不推荐其他开发者使用,因此关于Windows的部分并没有经过认真测试。

December 21, 2014 1 min

现代Web页面开发流程

现代Web页面开发流程 通常来说,Web页面开发的流程大致是这样的:设计师(设计师不是美工,就像程序员不是码农一样)提供设计稿,通常是图片格式。然后前端的开发人员(在ThoughtWorks我们称之为UI Dev)来手工的将图片转换为对应的HTML+CSS,往往还需要在各个浏览器中调试等。 大多数时候,设计师会提供色卡,或者至少前景色/背景色/高亮色的值给开发人员。如果没有的话,开发人员会用到一些工具如colorpicker, ruler之类来确保最终的效果和设计稿是一致的。 如果你观察过UI Dev的工作流程的话,你会发现基本的上是这样的:使用编辑器(或者IDE)编写HTML代码,CSS代码,保存修改内容,切换到浏览器窗口,按F5或者Ctrl-R刷新,然后对比设计稿和实现,如果发现不一致的地方,再切换到编辑器中修改代码,如是往复。 避免手工劳动 纯手工的方式来编辑HTML/CSS会非常耗时,特别是作为标记语言的HTML,开发者需要时刻关注关闭已经打开的标签。比如一个标题元素,你需要: <h1>This is the page title</h1> 几乎从一开始,人们就想到了各种办法来避免自己重复的键入,比如Vim的SuperTab以及Snipmate插件,可以通过输入标签名+Tab来补全所有的标签等,又或者DreamWaver提供的代码生成的方式来简化这一流程。 Sublime的编辑器上的著名插件Emmet可以帮助开发人员飞速的开发HTML/CSS,这里有一个小例子。假设我们需要实现的页面是这样的: 那么对应的HTML结构可能会是: <ul> <li> <div class="feature"> <span class="number"></span> <i></i> <h4></h4> <p></p> </div> </li> ... </ul> 使用Emmet,则只需要给出表达式,然后按一下Tab键就可以补全为上述的结构了: ul>li*3>.feature>span.number+i+h4+p 上边的这条命令可以读作:“创建一个UL,该UL下有3个LI,每个LI下有一个class为feature的DIV(不指定元素名称的话,默认生成div),每个DIV内,有一个类为.number的SPAN,一个i元素,一个H4元素和一个P元素” 完整的技巧可以参看官方文档。 避免重复劳动 上边提到的频繁的F5刷新,可以通过LiveReload+Guard两个工具的组合来解决。LiveReload是一个浏览器的插件,通过协议与后台的服务器进行通信。当后台文件发生变化时,LiveReload会自动刷新页面。 Guard会使用操作系统的API来感知本地文件的变化,当文件变化后,它可以通知LiveReload进行刷新,当然Guard可以做其他一些事情,比如等SCSS发生变化时,自动编译CSS等。 两者结合之后,就可以节省我们大量的时间,而把精力主要投放在开发这件事情本身上。 样板工程 我在Github上公开了一个样板工程,这是一个开箱即用的工程,其中提供了这样一些配置: SCSS的编译环境(使用compass) Guard配置(当你的SCSS文件或者HTML文件修改之后,自动通知LiveReload来刷新浏览器) 一个标准的HTML5样板文档 一个基本的style.scss Guardfile的配置中,如果index.html发生变化,或者stylesheets中的css文件发生变化,或者scripts目录中的js文件发生变化,都会触发livereload任务(通知浏览器)。 guard 'livereload' do watch('index.html') watch(%r{stylesheets/.+\.(css)}) watch(%r{scripts/.+\.(js)}) end guard :compass 你只需要简单的将这个工程克隆到本地: $ git clone git@github.com:abruzzi/design-boilerplate.git mydesign 然后在该目录中执行bundle install即可: $ cd mydesign $ bundle install 这里有两点假设:...

November 25, 2014 1 min