使用 Git 命令时,遇到 Permission denied (publickey)

在 Windows7 下执行 git fetch 命令时遭遇阻碍:

Permission denied (publickey).
fatal: Could not read from remote repository.

一番折腾,发现了解决方案:
http://stackoverflow.com/questions/2127104/permission-denied-publickey-error-using-git-on-windows-7#comment14572392_6544796

总结来说,就是在 Windows 下利用 ssh-keygen -t rsa 生成的公钥、私钥,其文件名最好用默认的 “id_rsa”。如果是自定义的文件名,则需要手动在 ssh 的 config 里指定密钥路径。

所以,我把我的私钥文件名修改为 id_rsa,然后放置到 Git 安装目录下的 .ssh 文件夹中,问题迎刃而解。

后续:
使用 Git GUI 时也遭遇 Permission denied (publickey) 。我整个人都蒙圈了。
之后查明,Git GUI 的 .ssh 文件夹跟 Git 命令的 .ssh 文件夹不是同一个。按照如上逻辑再处理一遍即可

让 Fisp 的 liveReload 功能走起!

Fisp: 百度前端集成开发工具,http://oak.baidu.com/fis-plus

起因:

C:\Users\duxing.org>fisp release -h

  Usage: release [options]

  Options:

    -h, --help             output usage information
    -d, --dest <names>     release output destination
    -m, --md5 [level]      md5 release option
    -D, --domains          add domain name
    -l, --lint             with lint
    -t, --test             with unit testing
    -o, --optimize         with optimizing
    -p, --pack             with package
    -w, --watch            monitor the changes of project
    -L, --live automatically reload your browser
    -c, --clean            clean compile cache
    -r, --root <path>      set project root
    -f, --file <filename>  set fis-conf file
    -u, --unique           use unique compile caching
    --verbose              enable verbose output

发现有个 -L 参数,可是用起来却无效。
于是开始了探索之路…
经过一番琢磨,终于享受到了这个功能。

常规的使用方法是这样的:

在页面内添加一个特殊标记:

<!–livereload–>

注意,这个标记是不含有空格的。通过 fisp release -wLr /xxx 发布后,它会被替换成一个 http://ip:port/livereload.js 资源。就是通过这个js来实现页面刷新的。 在你发布的时候 fisp 在后台还启动了一个支持 webSocket 的服务器进程,用来把你的修改信息传递给 livereload.js 命令其做出动作。

在具体开发中,情况可能稍有复杂,特举一例:

	我的一个项目中有两个模块(命名空间)。通过体验发现,发布多个模块,只能有一个模块可带有 -L 参数,因为只能启动一个 支持 webSocket 的服务进程,否则会因端口独占而报错。
另外,我们也可以根据自动刷新的理论,自己启动一个 webSocket 服务,手动嵌入 livereload.js 到你的项目中。

### 那么问题来了,livereload.js 从哪里弄?

如果你找不到别人共享的这个资源,可以自己用 node.js 搭建:
打开 https://github.com/livereload/livereload-server ;
安装(npm install livereload-server -g ),记下安装目录;
把源码列表里的 example 文件夹下载到刚刚安装的 livereload-server 的根目录。

用 node 执行 dummy-server.js 文件,来启动服务,记下端口号。
这样你就可以的到一个本地可访问的地址: http://yourHost:port/livereload.js

把这个地址作为 javascript 资源引入到你的页面中吧~

附:
这里可能有最新的官方揭秘:https://github.com/fex-team/fis-plus/issues/38

单片机:数码管的数字对应的16进制数值

// 计算单片机数码管显示数字对应的针脚16进制数值。
var NumCodeMap = [
	// 0
	['a','b','c','d','e','f'],
	// 1
	['b','c'],
	// 2
	['a','b','d','e','g'],
	// 3
	['a','b','c','d','g'],
	// 4
	['b','c','f','g'],
	// 5
	['a','c','d','f','g'],
	// 6
	['a','c','d','e','f','g'],
	// 7
	['a','b','c'],
	// 8
	['a','b','c','d','e','f','g'],
	// 9
	['a','b','c','d','f','g'],
];

function sigma( numCode ){
	var digCode = ['a','b','c','d','e','f','g'].map(function(item){
		return +(numCode.indexOf( item ) > -1 );
	});
	return parseInt( digCode.reverse().join(''), 2 ).toString(16);
}

function wrapHex( num ){
	return '0x'+ (num.length < 2 ? '0':'' ) + num ;
}

function get( num ){
	if( num >= 0 && num <= 9 ){
		num = parseInt( num );
		var hex = sigma( NumCodeMap[num] );
		return wrapHex( hex );
	}
	return -1;
}

// console.log( get( 0 ) );

// '0123456789'.split('').map(function(item){ return get(item);})
// ["0x3f", "0x06", "0x5b", "0x4f", "0x66", "0x6d", "0x7d", "0x07", "0x7f", "0x6f"]

手动触发本地Chrome Extension检查更新

Under Windows OS:
chrome.exe --extensions-update-frequency=30
Tips:30 means checking per 30 second.(the same below)

Under Ubuntu OS:
1.Find your Chrome excutive file:
sigma@Sigma:~/git$ whereis google-chrome
google-chrome: /usr/bin/google-chrome /usr/bin/X11/google-chrome /usr/share/man/man1/google-chrome.1

2.Excute the command below:
sigma@Sigma:~/git$ /usr/bin/google-chrome --extensions-update-frequency=30
Offical Doc:

https://developer.chrome.com/extensions/autoupdate

Javascript中的正则表达式

Demo:数字排重

var num = '87702226999984';

// num.match( /(\d)\1+/g ).map(function(v){
// v = '' + v;
// num = num.replace( v, v.charAt(0) );
// });
// console.log( num );

console.log( num.replace( /(\d)\1+/g, '$1' ) );

/*
 知识点:
 1)正则中引用分组 \1
 2)replace中引用分组 $1
 Extra:
 3)非贪婪匹配 +?
 4)不生成引用分组 (?:)
*/

参考资料:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/RegExp#grouping-back-references

Javascript压缩工具里的坑

Google Closure Compiler
官网:https://developers.google.com/closure/compiler
用法之一:
java -jar compiler.jar –js_output_file=out.js in1.js in2.js in3.js …

一段暴露坑的代码(test.js):

function countDown(btn, goodinfo, timestamp) {
  btn.attr('t', 0);
  var timeSpan = goodinfo.activity_start - timestamp; //时间差
  if (timeSpan > 86400) { //24小时外
    btn.text('抢兑时间:' + Gold.util.getStartTime(goodinfo.activity_start));
  } else {
    var t = null;
    func();

    function func() {
      if (timeSpan > 0) { //24小时内
        var h, m, s;
        h = Math.floor(timeSpan / 3600);
        h = h < 10 ? '0' + h : h;
        m = Math.floor((timeSpan % 3600) / 60);
        m = m < 10 ? '0' + m : m;
        s = Math.floor(((timeSpan % 3600) % 60));
        s = s < 10 ? '0' + s : s;
        btn.text('倒计时:' + h + '时' + m + '分' + s + '秒');
        timeSpan--;
        t = setTimeout(func, 1000);
      } else {
        btn.attr('t', 1).text('立即抢兑 (剩余' + (goodinfo.num - goodinfo.cost_num) + ')');
        clearTimeout(t);
      }
    }
  }
}

关注一下func()函数的调用和声明位置的先后关系。

执行压缩命令:
java -jar compiler.jar --js_output_file=out.js test.js

结果(out.js经过格式化):

function countDown(b, c, k) {
  b.attr("t", 0);
  var a = c.activity_start - k;
  if (86400 < a) b.text("\u62a2\u5151\u65f6\u95f4:" + Gold.util.getStartTime(c.activity_start));
  else {
    var g = null;
    h();
    var h = function() {
      if (0 < a) {
        var d, e, f;
        d = Math.floor(a / 3600);
        e = Math.floor(a % 3600 / 60);
        f = Math.floor(a % 3600 % 60);
        b.text("\u5012\u8ba1\u65f6:" + (10 > d ? "0" + d : d) + "\u65f6" + (10 > e ? "0" + e : e) + "\u5206" + (10 > f ? "0" + f : f) + "\u79d2");
        a--;
        g = setTimeout(h, 1E3)
      } else b.attr("t", 1).text("\u7acb\u5373\u62a2\u5151 (\u5269\u4f59" + (c.num - c.cost_num) + ")"), clearTimeout(g)
    }
  }
};

注:
坑点:h()的调用跑到了函数定义的前头。
心得:虽然js有hoisting的概念,但是!!!还是老实点,返璞归真到C的时代,保证“先声明后调用”。

突然想起西游记中,悟空非要拿出师傅的锦蓝加沙在金池长老面前炫耀,后来惹了不必要的麻烦。。。阿弥陀佛,老实点

批量下载百度图片里搜索出的图片结果

/*
早上,小弟急需一批图片,情急之下,赶制了一份代码,用来批量下载百度图片里搜索出的图片结果。
首先用以下脚本在console里获取图片的链接:
	var a = document.querySelectorAll('img');
	var b = Array.prototype.slice.call(a).map(function(img){
	  return ( img.getAttribute('src') );
	});
	console.log( b,b.length );
然后我视图用迅雷、QQ旋风的批量下载功能,均无法下载。
所以就借助node.js,伪造header里的refer字段做一下尝试,successed!
(refer字段就从chrome dev tool里的nextwork下,随便找一个图片请求,从中复制出refer即可。喔喔,我的鼻子是不是要变长了...)
 */

var http = require('http');
var fs = require('fs');

var urls = [
  "http://img2.imgtn.bdimg.com/it/u=2118320824,2411832758&fm=21&gp=0.jpg",
  "http://img5.imgtn.bdimg.com/it/u=2005271455,882838282&fm=15&gp=0.jpg",
  "http://img5.imgtn.bdimg.com/it/u=417366983,2380296348&fm=23&gp=0.jpg"
];

var index = 0;
function getImg( ){
	var url = urls[index];
	http.get( {
		host:'img4.imgtn.bdimg.com',
		port:80,
		path:url.replace(/http:\/\/img\d\.imgtn\.bdimg\.com/,''),
		method:'GET',
		headers:{
			Referer:'http://image.baidu.com/i?ct=201326592&cl=2&nc=1&lm=-1&st=-1&tn=baiduimage&istype=2&fm=&pv=&z=0&ie=utf-8&word=%E5%8C%97%E4%BA%AC%E4%BA%94%E6%98%9F%E7%BA%A7%E4%BB%A5%E4%B8%8B%E7%9A%84%E7%85%A7%E7%89%87'
		}
	} , function( res ){
		var body = '';
		res.setEncoding('binary');
		res.on('data',function( chunck ){
			body += chunck;
			console.log( 'Append chunck...');
		});
		res.on( 'end' ,function(){
	        fs.writeFile( index +'.jpg', body, 'binary', function(err){
	            if (err) throw err
	            console.log('File saved.');
	        	index++;
	        	if( index < urls.length){
	        		body='';
			        getImg();
	        	}
	        });
		});
	}).on('error', function(){
		console.log('get error!');
	});
}

console.log( 'start launched...');
getImg( );

《前端程序员Sigma的奇幻梦境》

《前端程序员Sigma的奇幻梦境》
——作者:笃行天下 时间:2014.08.03
《前端程序员Sigma的奇幻梦境》
午后的床上,我睁开朦胧的睡眼,感觉自己已经睡了八分熟了,剩余的懒意让我不想起床。

从慢慢张开的眼缝里,看到了高高脊梁的屋顶,黝黑的瓦片映着窗外射入的光线,几乎可以分辨清每一块的边界。屋里一片灰暗的色调,显出几分凉意,光着的膀子也没出太多的汗。

从眼角的余光中,我看到右侧的墙和梁头间有一块脸盆大小的蜘蛛网。把目光的焦点移到网上,发现上面有一些小虫,可能是蜘蛛捕获的猎物吧。

不,那虫分明还在灵巧的沿着网线自由爬动,看,还有更大一些的虫子,也在灵巧迅速的爬动。

奇怪,这网上好像并没有蜘蛛。懒意被我忽略了几分,这是什么东西,我想不清楚。算了,不想它了,反正又不会落下来。
想着便要侧身向左,打算再眯一会儿。这时,我发现有只更大的虫子——比刚刚看到的那几只走动的大虫要大上10倍——这只大虫像蜘蛛一样,借助一根丝脱离了网,垂了下来。它晃悠着丝线,像是在下降。

虫子的轮廓好像越来越大了,我这才发觉它的确在下落中。映着光线,我看到这“大虫”竟然是个蝎子,身体被光照映的呈半透的黄色,周身和两个深色大钳子的边缘还有一层暗黑的绒毛。

它离我越来越近了,而且下降的幅度很明显,速度又不均匀。这时我警惕了起来,觉得应该赶紧起来躲开了,因为它正对着我的脸,落点好像就对着我头部的位置!

啊,我想尽力向左侧身…身体却像是被冰冻了一般,僵硬的根本不听使唤…使劲的坚持,也没能翻身。我赶紧又试图用左手先把右手拉过来,撑着床面直接起来,可是——它们都被“冻住”了……蝎子依然还在荡着下降,它好像发现了我,而且似乎可以确定它的目标就是我!!!

我更加的紧张,心跳已经砰砰作响,像个快要炸了的高速马达。不行了!不行了!……啊!……啊!……

轰的一下,周身的环境在眼里像褪色一般、像幕布被拉去一般,突然变亮……我身体的姿势竟然也正在撑着床,停留在起身的过程中。我看到了桌上的电脑、鼠标、水杯,顿时发现,我原来做了一个梦。我坐在床上愣了许久,心跳减缓,才回过神来。

在梦里醒来的那个梦欺骗了我,让我以为是真实的,一系列虚拟的场景投射到我的心理,得到的反馈又是那么的真实。

为什么构造了如此荒诞的情节,让一个梦“嵌套”到另一个梦里呢???让我看到一个内层的梦的结束,又被迫从它外层的梦的里头“穿越”出来,回到现实。

看到床头睡前我翻开的书页,是 Javascript 语言的闭包( Closure )那章——我突然意识到,刚刚梦中的我,像是一个局部变量( Local Variable ),他看到了另一个作用域的终结,又却想挣脱其他物体( Object )的威胁,于是拼命逃离了那层空间,跃到了全局作用域( Golobal )里。不,现在还无法确定是否是全局作用域,因为它好像压根没有Window…

KMP查找算法的Javascript实现

 // KMP 今天有幸了解这个算法,在电脑前琢磨很久,写出这段代码,算法是程序的灵魂,我的灵魂又强大了一步~

function _indexOf(str, findStr, m) {
    var sLen = str.length;
    var fLen = findStr.length;
    if (fLen > sLen) {
        return -1;
    }
    m = m || 0;
    if (m == sLen) {
        return -1;
    }
    
    function getOffset() {
        var offset = 0;
        for (var i = 0; i < fLen; i++) {
            for (var j = m; j < sLen; j++) {
                if (str[j] == findStr[i]) {
                    offset++;
                    i++;
                } else {
                    return offset;
                }
            }
        }
        return offset;
    }
    
    var offset = getOffset();
    
    if (offset == fLen) {
        console.log('hint:', m);
    }
    if (offset == 0) {
        m += 1;
    } else {
        var p = getP(findStr.slice(0, offset));
        m = m + offset - p;
    }
    return _indexOf(str, findStr, m);
}

function getP(str) {
    var l = str.length;
    for (var i = Math.floor(l / 2); i > 0; i--) {
        if (str.slice(0, i) == str.slice(l - i)) {
            break;
        }
    }
    return i;
}
//test
var str = 'abcdabcdabce', 
find = 'bcdabc';
_indexOf(str, find);