打磨程序员的专属利器分三个专题展示--
1. 命令行&文件
2. 快捷键
3. 文本 (本文)
1. 记笔记
好记性不如烂笔头,对于程序员更是如此。学习某种新语言或者某个库,若事先不记点笔记,几年后再拣起来会非常地慢。
之前自己一直用“为知笔记”,但慢慢发现了几个问题。
a. 这个软件喜欢升级,而每次升级都将界面改得面目全非(其实现在绝大多数软件都喜欢没事升级)。我只是想一个简洁的软件界面,只想专注于笔记,而为知的每一次更新后都得花精力在熟悉界面上。
b. 为知的笔记不是文本,这样笔记内容几乎只能用为知才能打开。如果想在ubuntu或者Mac上看,只有期待它出对应的客户端或者用网页查看(但如果没网时也不能查看本地数据了)。不过现在我打开wiz的网页版笔记,只能另我大失所望,本人只是想要一个左边是树形控件展示笔记的结构,右边可以显示笔记内容的界面,而wiz网站的在线笔记做得太复杂了。
c. 有时不知是服务器还是网络问题,同步居然出现问题。在家里电脑写的东西,来到公司后发现居然没有同步过来,fuck!!!!
忍无可忍后,就动了自己实现个笔记软件的想法。最开始是用c#写,笔记保存成.mht格式,用IE控件进行预览,用word进行编辑(这是从wiz中得到的启发)。不过后来也发现不是文本的笔记根本不能跨平台。于是又重写了一遍,用c++实现,下面是软件的界面,很简洁,但完全够自己用了。
这个程序从底层反锯齿的2d图形库,到界面库,到Markdown的解析,都是自己重新造轮子实现(虽说在软件界不鼓励重新造轮子,但通过造轮子可以将图形库、界面库理解得更透彻)。由于太过简陋就不发布出来,等过段时间有空了用QT再重写一个相对漂亮点的界面再公布源码和程序。
2. Markdown
上面的笔记中提到了Markdown。《程序员修炼之道》中提到笔记得到文本来记录。最开始本人一直认为“文本”就是“纯文本”,直到在开源软件中发现有.md文件,于是知道了有Markdown这种东东,然后忽然识别到文本也可以做得很漂亮(html,css就是文本)。
Markdown是html的一个子集。可以用少量的标示符就可以构造出漂亮的文本排版。下面简单介绍下Markdown的标示符:
a. 行首的#可以指明段落,一个表示第一级,二个表示第二级,以此类推
b. 两行```之间的内容可以被解析为code格式,就像上图中有灰色背景的区域,这种可以方便放代码。
c. 行首的 * 可以被解析成html的 <li>
d. 用[name](http://www.test.com "test") 这种格式可以指定超链接
e. 用下面的格式可以构造出如下的表格
name | age ---|--- man1 | 45 man2 |2
....
更多Markdown语法可以参数其官网。反正都挺好学,也比较易用,可以在记笔记时不因格式问题而花太多的精力,让我们专注于内容。
3. 备份、同步
有了上面DIY的笔记软件后,对于多地办公、多台电脑办公就得考虑如何同步笔记了。
开始本人是使用金山网盘,但也是因为同步问题,有时真是金山的服务器挂了,导致无法同步。还一个严重的问题,网盘没有像svn,git那样明确的update,commit,pull,push操作,这样在同步时真就会出现问题。然后本人试了几乎所有的网盘,发现在某些情况下100%的情况会出现同步失败的问题。
************************
在写这篇博文时为了再次证实下,于是本人又装了次金山快盘。
新建一个文件夹,在这个文件夹下再新建两个文本文档,往其中一个文本文档中随便写点东西,这时去网页版的金山快盘上,就发现真就没有把刚才的东西同步上来。比吃了蟑螂还恶心!!!
qq云盘和360网盘以前还可以在Explorer中查看本地数据,但现在只有用它自己的程序来操作本地数据了。
百度云盘同样也有这样问题,没有本地路径。
************************
同样是忍无可忍
开始使用 http://svn.jundie.net/,但由于本人小气,不想花钱买私有项目,只有把自己的笔记弄成开源项目,虽说没什么重要东西,但总感觉不靠谱。
于是找到git.oschina.net,并且发现基于git有非常多的服务器,并且都可以免费申请私有项目。于是爱上了git,为了保险,将自己所有的代码都放到git上,当然是私有项目(遥想当年,由于本人折腾电脑、折腾分盘,将大一下刚学程序半年写的vb6俄罗斯方块程序源码弄丢了,多么地心疼啊)~~
于是妈妈再也不用担心代码弄丢了。
为了方便在Explorer中访问笔记,可以使用前文介绍的subst命令,将笔记路径映射成一个虚拟磁盘以便访问。
4. 学习一门文本语言
《程序员修炼之道》中说程序员应该每一年学习一门新语言,我们打个折扣1~2年学习一门新语言。并且非常有必要学习一门文本操作语言,比如Python,Ruby或者是Perl。虽然用C#,java,甚至是c/c++都可以进行文本操作,但编写代码的速度肯定不及脚本语言。
本人最开始学习的是Perl语言。这门语言咋一看觉得不好学——充满了各种奇奇怪怪的符号。不过如果沉下心来将《Perl语言入门》、《Perl语言编程》两本书看完,然后再动手自己写几个实用的小程序,Perl的学习之路基本上就算是毕业了。
下面展示几个本人所写的perl程序。也是比较简陋(本人侧重于实用):
a. ls程序
linux下的ls命令可以将当前路径下的文件、文件夹都显示出来。windows下没有这样的程序,于是本人实现了一个。
1 use 5.010; 2 use strict; 3 use warnings; 4 5 use Win32::Console; 6 use Win32::Console::ANSI; 7 use Term::ANSIColor; 8 use POSIX(); 9 10 11 use utf8; 12 use Encode::Locale; 13 14 binmode STDIN, ":encoding(console_in)"; 15 binmode STDOUT, ":encoding(console_out)"; 16 binmode STDERR, ":encoding(console_out)"; 17 18 sub Main; 19 20 Main @ARGV; 21 22 my $is_dir_show; 23 my $is_file_show; 24 25 my $is_show_size; 26 my $is_sort_by_size; 27 28 my @folds; 29 my @files; 30 31 my $max; 32 33 my $col_count; 34 my $col_width; 35 36 my $con_w; 37 my $con_h; 38 39 sub Help { 40 #system("chcp 936"); 41 my $str = "ls 显示当前目录下的文件和文件夹名\n". 42 "默认情况下文件和文件夹都将显示。-f 显示文件 -d 显示文件夹\n". 43 "默认情况下不显示文件和文件夹的大小。 -s 将显示其大小\n". 44 "如果文件名中有中文,则一定要确保控制台的代码页为936,用chcp 936可以改变代码页"; 45 print $str; 46 } 47 48 sub IsHelp { 49 foreach (@_) { 50 if (lc($_) eq '?' || 51 lc($_) eq '/?' || 52 lc($_) eq '-help' || 53 lc($_) eq '--help' 54 ) { 55 return 1; 56 } 57 } 58 return 0; 59 } 60 61 #--------------- 62 # 判断命令行中是否有-d,如果有则表示显示文件夹 63 #--------------- 64 sub IsDir { 65 foreach (@_) { 66 if (lc($_) eq '-d') { 67 return 1; 68 } 69 } 70 return 0; 71 } 72 #--------------- 73 # 多年命令行中是否有-f,如果有则表示显示文件 74 #--------------- 75 sub IsFild { 76 foreach (@_) { 77 if (lc($_) eq '-f'){ 78 return 1; 79 } 80 } 81 return 0; 82 } 83 #--------------- 84 # 判断命令行中是否有-s, 如果有则要显示大小 85 #--------------- 86 sub IsSize { 87 foreach (@_) { 88 if (lc($_) eq '-s') { 89 return 1; 90 } 91 } 92 return 0; 93 } 94 95 #--------------- 96 # 判断命令行是否有-S,如果有则要按照文件大小排序,并且显示文件大小 97 # 即-S包含-s 98 #--------------- 99 sub IsSortBySize { 100 foreach (@_) { 101 if ($_ eq '-S') { 102 return 1; 103 } 104 } 105 return 0; 106 } 107 #--------------- 108 # 获取文件夹的大小 109 # par_1: path 110 #--------------- 111 sub GetFoldSize { 112 my $path = shift; 113 my $size = 0; 114 115 if (-d $path) { 116 my $r = opendir(DIR, $path); 117 118 if (!$r) { 119 return 0; 120 } 121 122 my @files = readdir(DIR); 123 closedir(DIR); 124 125 foreach (@files) { 126 next if $_ eq '.' or $_ eq '..'; 127 my $file = "$path\\$_"; 128 129 if (-d $file) { 130 $size += GetFoldSize($file); 131 } else { 132 my $s = (-s $file); 133 $size = $size + $s; 134 135 } 136 } 137 } 138 return $size; 139 } 140 141 #--------------- 142 # 将字节数转化为G M K 显示 143 # par_1:byte_size; 144 #--------------- 145 sub ByteToString { 146 my $b = shift; 147 my $k=0; 148 my $m=0; 149 my $g=0; 150 151 if ($b >= 1024) { 152 $k = int($b/1024); 153 $b -= $k * 1024; 154 } 155 156 if ($k >= 1024) { 157 $m = int($k/1024); 158 $k -= $m * 1024; 159 } 160 161 if ($m >= 1024) { 162 $g = int($m/1024); 163 $m -= $g * 1024; 164 } 165 166 # my $str=""; 167 # my $temp; 168 # if ($g != 0) { 169 # $str .= "$g"."G"; 170 ## $str .= $temp." "x(6 - length($temp)) ; 171 # } 172 # if ($m != 0) { 173 # $str .= "$m"."M "; 174 ## $str .= $temp." "x(6 - length($temp)) ; 175 # } 176 # if ($k != 0) { 177 # $str .= "$k"."K "; 178 ## $str .= $temp." "x(6 - length($temp)) ; 179 # } 180 # if ($b != 0) { 181 # $str .= "$b"."B "; 182 ## $str .= $temp." "x(6 - length($temp)) ; 183 # } 184 185 if ($g) { 186 sprintf("%4dG %4dM %4dK %4dB", $g, $m, $k, $b); 187 } elsif ($m) { 188 sprintf("%10dM %4dK %4dB", $m, $k, $b); 189 } elsif ($k) { 190 sprintf("%16dK %4dB", $k, $b); 191 } else { 192 sprintf("%22dB", $b); 193 } 194 195 196 # if ($str eq "") { 197 # return "0B"; 198 # } 199 # 200 # return $str; 201 } 202 203 #--------------- 204 # 获取数组中最大的字符串长度 205 # par:@_ 数组 206 #--------------- 207 sub MaxLength { 208 my $max = 0; 209 210 foreach (@_) { 211 my $len = length $_; 212 if ($len > $max) { 213 $max = $len; 214 } 215 } 216 return $max; 217 } 218 219 #--------------- 220 # 根据获取的col_count, col_width打印文件和文件夹名 221 # 在没有-s选项中这样显示,只显示文件夹名和文件名 222 # par:@_ 文件或文件夹名数组 223 #--------------- 224 sub PrintFileName { 225 my $c = 0; 226 227 foreach (@_) { 228 my $s = $_; 229 print Encode::decode("gb2312", $s); 230 231 my $len = length $_; 232 my $diff = $col_width - $len -1; #-1 是为了防止窗口宽等于缓冲区宽时引起的空白行问题 233 my $black = " " x $diff; 234 print $black; 235 236 ++$c; 237 if ($c == $col_count) { 238 print "\n"; 239 $c = 0; 240 } 241 } 242 } 243 244 #--------------- 245 # 当不指定显示大小,或者不按大小排序时显示文件 246 #--------------- 247 sub PrintNoSize { 248 my $console = Win32::Console->new(); 249 ($con_w, $con_h) = $console->Size(); 250 251 $col_count = POSIX::floor($con_w / ($max+4)); 252 if ($col_count == 0) { 253 $col_count = 1; 254 } 255 $col_width = POSIX::floor($con_w / $col_count); 256 257 #print "screen_width: $con_w \n"; 258 #print "max_width: $max \n"; 259 #print "col_cout: $col_count\n"; 260 #print "col_width: $col_width \n"; 261 262 if ($is_dir_show && scalar(@folds)) { 263 my $c = $#folds+1; 264 my $s = "文件夹: $c 个\n"; 265 print $s; 266 print color 'bold yellow'; 267 PrintFileName @folds; 268 print color 'reset'; 269 print "\n"; 270 } 271 272 if ($is_file_show && scalar(@files)) { 273 my $c = $#files+1; 274 my $s = "文件: $c 个\n"; 275 print $s; 276 print color 'bold green'; 277 PrintFileName @files; 278 print color 'reset'; 279 } 280 } 281 282 #--------------- 283 # 显示文件或文件夹的大小 284 #--------------- 285 sub PrintBySize { 286 287 my $width = $max + 4; 288 289 if ($is_dir_show) { 290 291 my %hash_dir; 292 foreach (@folds) { 293 $hash_dir{$_} = GetFoldSize($_); 294 } 295 296 my @k; 297 if ($is_sort_by_size) { 298 @k = sort { $hash_dir{$b} <=> $hash_dir{$a} } keys %hash_dir; 299 } else { 300 @k = sort keys %hash_dir; 301 } 302 303 foreach (@k) { 304 print color 'bold yellow'; 305 print $_; 306 print color 'reset'; 307 308 my $len = length $_; 309 my $diff = $width - $len; 310 my $black = " " x $diff; 311 print $black; 312 313 print ByteToString($hash_dir{$_}); 314 print "\n"; 315 } 316 } 317 if ($is_file_show) { 318 my %hash_file; 319 320 foreach (@files) { 321 $hash_file{$_} = -s $_; 322 } 323 324 my @k; 325 if($is_sort_by_size) { 326 @k = sort { $hash_file{$b} <=> $hash_file{$a}} keys %hash_file; 327 } else { 328 @k = sort keys %hash_file; 329 } 330 331 foreach (@k) { 332 print color 'bold green'; 333 print $_; 334 print color 'reset'; 335 336 my $len = length $_; 337 my $diff = $width - $len; 338 my $black = " " x $diff; 339 print $black; 340 print ByteToString($hash_file{$_}); 341 print "\n"; 342 } 343 } 344 } 345 346 sub List { 347 $is_dir_show = IsDir @_; 348 $is_file_show = IsFild @_; 349 $is_show_size = IsSize @_; 350 $is_sort_by_size = IsSortBySize @_; 351 352 #如果即没有指定-f,也没有指定-d,则默认为都显示 353 if (!$is_dir_show && !$is_file_show) { 354 $is_dir_show = 1; 355 $is_file_show = 1; 356 } 357 358 opendir(DIR, '.'); 359 my @file = readdir(DIR); 360 closedir(DIR); 361 362 foreach (@file) { 363 next if $_ eq '.' or $_ eq '..'; 364 365 if (-d $_) { 366 push(@folds, $_); 367 368 } else { 369 push(@files, $_); 370 } 371 } 372 373 my $len1 = MaxLength @folds; 374 my $len2 = MaxLength @files; 375 $max = $len1 > $len2 ? $len1 : $len2; 376 377 if ($is_show_size) { 378 PrintBySize; 379 380 } else { 381 PrintNoSize; 382 } 383 384 } 385 386 sub Test { 387 #$s = "d:\\1.jpg"; 388 #my $size = GetFoldSize "d:\\lib"; 389 #print ByteToString $size; 390 391 #print length($str); 392 393 # opendir(DIR, "e:\\"); 394 # my @files = readdir(DIR); 395 # closedir(DIR); 396 397 # foreach (@files) { 398 # print $_, "\n"; 399 # } 400 401 my $len = -s "D:\\pagefile.sys"; 402 print "$len \n"; 403 print ByteToString($len) , "\n"; 404 } 405 406 sub Main { 407 if (IsHelp @_) { 408 Help; 409 } else { 410 List @_; 411 # Test; 412 } 413 }