Coding – orzFly https://oldblog.orzfly.com His Memories from Here to There, with Fuzzy Ginkgo Sat, 11 Feb 2017 13:57:34 +0000 en-US hourly 1 https://wordpress.org/?v=4.9.5 RGSSRuntime Module 1.0 for RPG Maker XP/VX/VX Ace https://oldblog.orzfly.com/html/rgssruntime.html Wed, 19 Mar 2014 13:06:29 +0000 https://orzfly.com/?p=1285 这个模块是为了在脚本中操作 RGSS 的两个选项:平滑模式和抑制画面抖动(垂直同步)。除了 RGSS100J 无法使用之外,其他任何 RGSS 1~3 版本理论上都能使用。

脚本内容已放在后文,不过脚本中并没有直接设置。使用时,不仅应当引入脚本,还应该调用它的方法。

RGSSRuntime.smooth_mode

读取/设置 RGSS 的平滑模式选项。true 为开启,false 为关闭。在 RGSS 版本不支持的时候,会返回 nil,对其设置将不会产生任何效果。

RGSSRuntime.wait_for_vsync

读取/设置 RGSS 的抑制画面抖动(垂直同步)选项。true 为开启,false 为关闭。在 RGSS 版本不支持的时候,会返回 nil,对其设置将不会产生任何效果。

脚本正文

]]>
阿里云服务器文件 swap 无法开机自动加载 https://oldblog.orzfly.com/html/aliyun-swapfile-init.html Thu, 28 Nov 2013 18:27:04 +0000 https://orzfly.com/?p=1241 默认的系统镜像里 /etc/rc.local 有一行 swapoff -a,删掉即可。阿里云你要不要这么贱!

后来他们客服给我了这么个说法:

您好,由于云服务器默认没有设置swap,所以不会自动加载,由于阿里云采用分布式存储,为了保证数据安全,一份数据实际写3份,无法达到传统磁盘io,所以不建议使用swap,避免对io性能造成影响~ 阿里云客户满意中心

]]>
Windows Server 2008/2012 (R2) + NVIDIA Optimus 笔记本显卡 https://oldblog.orzfly.com/html/windows-server-2008-2012-r2-nvidia-optimus.html https://oldblog.orzfly.com/html/windows-server-2008-2012-r2-nvidia-optimus.html#comments Fri, 22 Nov 2013 16:51:50 +0000 https://orzfly.com/?p=1232 NVIDIA Optimus 架构的显卡在 Windows Server 系统上无法正常工作,就算是强制使用也没有反应。其实很简单,我们都知道这驱动需要使用 AppInit_DLL 这东西,然后 Windows Server 系统默认要求这个东西必须签名,而在桌面系统上是不需要签名的,所以 NVIDIA 的驱动的那个 DLL 并没有签名。

所以事实上很简单,改一下注册表呗……

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows]
"RequireSignedAppInit_DLLs"=dword:00000000

[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows NT\CurrentVersion\Windows] 
"RequireSignedAppInit_DLLs"=dword:00000000

我跟你说改完之后连重启都不需要重开下程序就能用了……

为什么要在笔记本上用服务器系统这个问题不需要过多讨论,另外这方法是这里看来的。

]]>
https://oldblog.orzfly.com/html/windows-server-2008-2012-r2-nvidia-optimus.html/feed 2
在 Interactive Ruby (irb) 中清空屏幕 https://oldblog.orzfly.com/html/clear-the-irb-console-screen.html Sat, 19 Oct 2013 15:26:59 +0000 https://orzfly.com/?p=1192 因为强迫症雷达喵的原因,于是有了这两段代码。首先是无空行的版本:

->(a,b,c){x=a.method(b);a.send(c,b){send c,b,&x;false};print"\e[2J\e[H \e[D"}[irb_context,:echo?,:define_singleton_method]

然后是有空行的版本:

->(x){def x.inspect;self;end;x}["\e[H\e[2J"]

好了你们玩儿蛋去。然后以下是对 ruby – How Do You Clear The IRB Console? – Stack Overflow 的部分粗糙翻译。


楼主 John Topley
你们怎么在 IRB 里清屏?


106 票 John Topley
在 Mac OS X 或 Linux 上你可以用 Ctrl + L 来清空屏幕。


29 票 Ben Hoffstein
Windows 里,把这个代码丢在 %userprofile%\.irbrc 里:

def cls
  system('cls')
end


11 票 TW Scannell
在 Ubuntu 11.10 上 clear 差不多就行了,只是你会看到 => true,把一切搞得很乱。

ruby-1.9.2-p290 :007 > system 'clear'
你会得到

=> true
ruby-1.9.2-p290 :007 >


8 票 AShelly
在 *nix 上 `clear` 就行了。
有趣的是,在 Windows 上用 system 'cls' 就行,`cls` 却不行。

]]>
set_trace_func 和骗局 https://oldblog.orzfly.com/html/set_trace_func.html https://oldblog.orzfly.com/html/set_trace_func.html#comments Mon, 02 Sep 2013 20:59:12 +0000 http://orzfly.com/?p=1164
本文是对 http://t-a-w.blogspot.jp/2007/04/settracefunc-smoke-and-mirrors.html 的粗略翻译,如有错误请务必指正。

Ruby 解释器提供了可用于追踪 Ruby 执行的事件钩子。设置钩子用 set_trace_func(some_proc);卸载钩子则用 set_trace_func(nil)。

追踪器恐怕是发明以来最有用的调试工具,远比基于单步和断点的调试器有用。

Ruby 追踪 8 种事件:

  • line – 文件或行改变
  • class – 模块或类定义开始
  • end – 模块或类定义结束
  • call – Ruby 方法调用
  • return – Ruby 方法返回
  • c-call – C 方法调用
  • c-return – C 方法返回
  • raise – 异常抛出

有些事件并不会被追踪,例如设置和读取变量(局部、全局、实例或者类变量)。

set_trace_func proc { |event, file, line, id, binding, classname|
  STDERR.printf "%8s %s:%-2d %10s %8s\n", event, file, line, id, classname
}

@welcome  = "Hello"
separator = ", "
$object   = "world"
@@excl    = "!"
puts(@welcome + separator + $object + @@excl)

$ ./example-1.rb
    line ./example-1.rb:7                false
    line ./example-1.rb:8                false
    line ./example-1.rb:9                false
    line ./example-1.rb:10               false
    line ./example-1.rb:11               false
  c-call ./example-1.rb:11          +   String
c-return ./example-1.rb:11          +   String
  c-call ./example-1.rb:11          +   String
c-return ./example-1.rb:11          +   String
  c-call ./example-1.rb:11          +   String
c-return ./example-1.rb:11          +   String
  c-call ./example-1.rb:11       puts   Kernel
  c-call ./example-1.rb:11      write       IO
c-return ./example-1.rb:11      write       IO
  c-call ./example-1.rb:11      write       IO
c-return ./example-1.rb:11      write       IO
c-return ./example-1.rb:11       puts   Kernel

例子中,String#+ 运行了三次,IO#write 两次——第二次大概是输出换行符的。

Ruby 中很多东西很神奇并没有被转换为方法调用。这种东西的一种是字符串插值(... #{ code } ...),并没有被转换为 String#+ 或是 Array#join,而是直接由解释器特别的处理。

set_trace_func proc { |event, file, line, id, binding, classname|
  STDERR.printf "%8s %s:%-2d %10s %8s\n", event, file, line, id, classname
}
@welcome  = "Hello"
$object   = "world"
puts("#{@welcome}, #{$object}\n")

$ ./example-2.rb
    line ./example-2.rb:7                false
    line ./example-2.rb:8                false
    line ./example-2.rb:9                false
  c-call ./example-2.rb:9        puts   Kernel
  c-call ./example-2.rb:9       write       IO
c-return ./example-2.rb:9       write       IO
c-return ./example-2.rb:9        puts   Kernel

同样,创建类并没有被转化为 Class#new,添加方法并没有被转换为 Module#define_method。幸运的是 Ruby 提供了特别的钩子让我们需要捕捉这些事件——当类创建时,其父类的 inherited 方法会被调用;当一个方法被添加时,Ruby 调用其类的 method_added。

set_trace_func proc { |event, file, line, id, binding, classname|
  STDERR.printf "%8s %s:%-2d %10s %8s\n", event, file, line, id, classname
} 

class Geolocation
  def initialize(lat, long)
    @lat  = lat
    @long = long
  end
  def to_s
    "<#{@lat}, #{@long}>"
  end
end

$ ./example-3.rb
    line ./example-3.rb:7                false
  c-call ./example-3.rb:7   inherited    Class
c-return ./example-3.rb:7   inherited    Class
   class ./example-3.rb:7                false
    line ./example-3.rb:8                false
  c-call ./example-3.rb:8  method_added   Module
c-return ./example-3.rb:8  method_added   Module
    line ./example-3.rb:12               false
  c-call ./example-3.rb:12 method_added   Module
c-return ./example-3.rb:12 method_added   Module
     end ./example-3.rb:7                false

如果我们想跟踪些有用的东西,是时候改改格式了。如果我们对跟踪执行过程感兴趣,通常来说文件及行号都没什么用,return/c-return/end 则应该用缩进代替。同时,相比类,我们更注重的是接收者(`self)。

$indent = 0
set_trace_func proc { |event, file, line, id, binding, classname|
  if event == "line"
    # 忽略
  elsif %w[return c-return end].include?(event)
    $indent -= 2
  else
    if event == "class"
      STDERR.printf "%*s%s %s\n", $indent, "", event, eval("self", binding)
    else
      STDERR.printf "%*s%s %s.%s\n", $indent, "", event, eval("self", binding), id
    end
    $indent += 2 if %w[call c-call class].include?(event)
  end
}

class Geolocation
  def initialize(lat, long)
    @lat  = lat
    @long = long
  end
  def to_s
    "<#{@lat}, #{@long}>"
  end
end

a = Geolocation.new(51.12, 17.03)
puts a
p a

$ ./example-4.rb  >/dev/null
c-call Object.inherited
class Geolocation
  c-call Geolocation.method_added
  c-call Geolocation.method_added
c-call Geolocation.new
  call <, >.initialize
c-call main.puts
  call <51.12, 17.03>.to_s
    c-call 51.12.to_s
    c-call 17.03.to_s
  c-call #<IO:0xb7c80fc0>.write
  c-call #<IO:0xb7c80fc0>.write
c-call main.p
  c-call <51.12, 17.03>.inspect
    c-call 17.03.inspect
      c-call 17.03.to_s
    c-call 51.12.inspect
      c-call 51.12.to_s
  c-call #<IO:0xb7c80fc0>.write
  c-call #<IO:0xb7c80fc0>.write

这里的输出又有点小怪癖。在 Geolocation#initialize 开始时, Geolocation#to_s 就被追踪器调用,而不是在其有意义之后。这种情况下,我们简单的得到了垃圾 <, >。但是有些对象,在初始化之前被打印是会产生异常的。

require "complex"

$indent = 0
set_trace_func proc { |event, file, line, id, binding, classname|
  if event == "line"
    # 忽略
  elsif %w[return c-return end].include?(event)
    $indent -= 2
  else
    obj = eval("self", binding)
    if event == "class"
      STDERR.printf "%*s%s %s\n", $indent, "", event, obj
    else
      obj = "<#{obj.class}##{obj.object_id}>" if id == :initialize
      STDERR.printf "%*s%s %s.%s\n", $indent, "", event, obj, id
    end
    $indent += 2 if %w[call c-call class].include?(event)
  end
}

a = Complex.new(11.0, -5.0)
b = Complex.new(2.0, 13.5)
c = a * b

$ ./example-5.rb
c-call Complex.new
  call <Complex#-605829048>.initialize
    c-call 11.0.kind_of?
    c-call 11.0.kind_of?
    c-call -5.0.kind_of?
    c-call -5.0.kind_of?
c-call Complex.new
  call <Complex#-605832038>.initialize
    c-call 2.0.kind_of?
    c-call 2.0.kind_of?
    c-call 13.5.kind_of?
    c-call 13.5.kind_of?
call 11.0-5.0i.*
  c-call 2.0+13.5i.kind_of?
  c-call 11.0.*
  c-call -5.0.*
  c-call 22.0.-
  c-call 11.0.*
  c-call -5.0.*
  c-call 148.5.+
  call 11.0-5.0i.Complex
    c-call 138.5.==
    call 89.5.real
    call 138.5.imag
    c-call 89.5.-
    call 89.5.imag
    call 138.5.real
    c-call 0.+
    c-call Complex.new
      call <Complex#-605842188>.initialize
        c-call 89.5.kind_of?
        c-call 89.5.kind_of?
        c-call 138.5.kind_of?
        c-call 138.5.kind_of?

许多难以找到错误的,最终变成了琐碎的自定义追踪器、grep 或是一些一行 Ruby 脚本来美化事实。

骗局

set_trace_func 不仅仅对调试有用,也适合做各种有趣的事情。Binding.of_caller 是用 set_trace_func 实现的,虽然已经不能用了。magic/help 用了 set_trace_func 在 irb 中提供方便的帮助:

irb> help { STDERR.write }
--------------------------------------------------------------- IO#write
     ios.write(string)    => integer
------------------------------------------------------------------------
     Writes the given string to _ios_. The stream must be opened for
     writing. If the argument is not a string, it will be converted to a
     string using +to_s+. Returns the number of bytes written.

        count = $stdout.write( "This is a test\n" )
        puts "That was #{count} bytes of data"

     _produces:_

        This is a test
        That was 15 bytes of data

magic/help 通过设置一个 set_trace_func 钩子工作,执行传送过来的块,然后一遇到感兴趣的事件就停止执行。这意味着 help { rm_rf "/" } 完全是安全的。

我开发 magic/help 时遇到的一个难懂的问题是,方法没有按正确的参数个数调用时,追踪结果不一致。

对于 C 写的方法,就算显式声明了参数个数,Ruby 依然在 ArgumentError.new 前产生 c-call。另一方面,对于 Ruby 写的方法,ArgumentError.new 被调用,然后从函数 return 返回,而不产生 call。

要描述这个问题,我们来跟踪一下 C 方法 STDERR.write:

c-call #<IO:0xb7c98fa8>.write
  c-call ArgumentError.new
    c-call #<ArgumentError: ArgumentError>.initialize
    c-return #<ArgumentError: wrong number of arguments (0 for 1)>.initialize
  c-return ArgumentError.new
  c-call #<ArgumentError: wrong number of arguments (0 for 1)>.backtrace
  c-return #<ArgumentError: wrong number of arguments (0 for 1)>.backtrace
  c-call #<ArgumentError: wrong number of arguments (0 for 1)>.set_backtrace
  c-return #<ArgumentError: wrong number of arguments (0 for 1)>.set_backtrace
  raise #<IO:0xb7c98fa8>.write
c-return #<IO:0xb7c98fa8>.write

与此同时我们跟踪一下 Ruby 方法 FileUtils.remove_entry:

# "call FileUtils.remove_entry" 永远不会产生!
  c-call ArgumentError.new
    c-call #<ArgumentError: ArgumentError>.initialize
    c-return #<ArgumentError: wrong number of arguments (0 for 1)>.initialize
  c-return ArgumentError.new
  c-call #<ArgumentError: wrong number of arguments (0 for 1)>.backtrace
  c-return #<ArgumentError: wrong number of arguments (0 for 1)>.backtrace
  c-call #<ArgumentError: wrong number of arguments (0 for 1)>.set_backtrace
  c-return #<ArgumentError: wrong number of arguments (0 for 1)>.set_backtrace
  raise FileUtils.remove_entry
# "return FileUtils.remove_entry" 确实产生了。
return FileUtils.remove_entry

两种情况下,参数都是在调用方法之前被检查的。IO#write 是定义为一个参数的方法:

rb_define_method(rb_cIO, "write", io_write, 1);

新版的 magic/help 也能处理这个情况了——如果首事件是 c-call 到 ArgumentError.new,magic/help 就等到首个 return 事件(如果有)而不是立刻放弃执行传来的块。快去下载新版,享受神奇的帮助吧。

]]>
https://oldblog.orzfly.com/html/set_trace_func.html/feed 1
Discuz X2.0 通过邮件发送注册链接 https://oldblog.orzfly.com/html/discuz-x2-reg-via-email.html Fri, 15 Mar 2013 19:33:39 +0000 http://orzfly.com/?p=1030 (草稿箱里积压了太多东西,于是整理一下一起丢出来,现在 Discuz X3.0 都已经进入 beta 了。不过按照他们的尿性,自从 X2.5 开始就越来越不稳定了。)

Discuz X2.5 带来的很多更新确实很棒,但是最关键的问题是这货实在不稳定。因此最后的最后还是从 X2.5 降级到了 X2.0。不过 X2.5 有一个通过邮件发送注册链接的功能很实用,可以有效避免注册机的注册,开启之后论坛上注册用户,需要先填写邮箱地址,通过收到的邮件中的链接才能注册。

于是花了点时间把这个功能从 X2.5 port 回了 X2.0,顺便感谢一下 Meld 这个给力的比较/合并工具。

以下是 patch 文件,这里是 Github Gist。

使用方法是把这代码用 UTF-8 或者 GBK 编码(根据 Discuz 编码自己决定)保存为文本文件名字是 ABC.patch,然后丢到 Discuz 的根目录下(跟 data,archiver,config,source,template,static 等目录放一起就对了),然后用 patch 命令,去命令行(cmd/sh/bash/终端/SSH)下来到这个目录,运行:

patch -p1 ABC.patch

于是就可以去后台打开这个选项咯。

]]>
diff 和 patch 的入门(及 Windows 下的用法) https://oldblog.orzfly.com/html/diff-and-patch-and-windows.html https://oldblog.orzfly.com/html/diff-and-patch-and-windows.html#comments Fri, 15 Mar 2013 17:57:42 +0000 http://orzfly.com/?p=1014 自从我开始使用 Git 以及接触 Linux 之后,我发现我越来越离不开 Linux 上那些方便好用的工具。比如 diff & patch,相对于 Windows 自带的 fc 要好用太多太多。

除 Windows 部分外,本文目前的多数内容是对《补丁(patch)的制作与应用》(见参考阅读)的修正、整理、简化与重新排版。

如果修改了开源代码,为了方便分享(如提交漏洞)或自己留存使用,一般都要制作一个补丁。在从源码安装软件时,也难免要应用些别人做好的补丁,本文介绍如何制作和应用补丁。

diff 简介

diff 可以比较两个东西,并可同时记录下二者的区别。制作补丁时的一般用法和常见选项为:

diff 【选项】 源文件(夹) 目的文件(夹)

-r
递归。设置后diff会将两个不同版本源代码目录中的所有对应文件全部都进行一次比较,包括子目录文件。
-N
选项确保补丁文件将正确地处理已经创建或删除文件的情况。
-u
输出每个修改前后的3行,也可以用-u5等指定输出更多上下文。
-E, -b, -w, -B, –strip-trailing-cr
忽略各种空白,可参见文档,按需选用。

patch 简介

patch的作用则是将 diff 记录的结果(即补丁)应用到相应文件(夹)上。最常见的用法为:

patch -pNUM < patchfile

-p Num
忽略几层文件夹,随后详解。
-E
选项说明如果发现了空文件,那么就删除它
-R
取消打过的补丁。

为了解释 -p 参数,需要看看如下 patch 文件片段:

--- old/modules/pcitable       Mon Sep 27 11:03:56 1999
+++ new/modules/pcitable       Tue Dec 19 20:05:41 2000

如果使用参数 -p0,那就表示从当前目录找一个叫做old的文件夹,再在它下面寻找 modules/pcitable 文件来执行patch操作。
而如果使用参数 -p1,那就表示忽略第一层目录(即不管old),从当前目录寻找 modules 的文件夹,再在它下面找pcitable。

简单应用

利用以上命令,处理单个文件补丁的方法:

# 产生补丁
diff -uN from-file to-file >to-file.patch

# 打补丁
patch -p0 < to-file.patch

# 取消补丁
patch -RE -p0 < to-file.patch

对整个文件夹打补丁的情况:

# 产生补丁
diff -uNr  from-docu  to-docu  >to-docu.patch

# 打补丁
cd to-docu
patch -p1 < to-docu.patch

# 取消补丁
patch -R -p1

另外,使用版本控制工具时,可以直接用svn diff或git diff生成补丁文件。

值得一提的是,由于应用补丁时的目标代码和生成补丁时的代码未必相同,打补丁操作可能失败。补丁失败的文件会以.rej结尾,下面命令可以找出所有rej文件:

find . -name '*.rej'

patch 文件构成

补丁文件里到底存储了哪些信息呢?看看这个例子:

--- test0       2006-08-18 09:12:01.000000000 +0800
+++ test1       2006-08-18 09:13:09.000000000 +0800
@@ -1,3 +1,4 @@
+222222
 111111
-111111
+222222
 111111

补丁头
补丁头是分别由—/+++开头的两行,用来表示要打补丁的文件。—开头表示旧文件,+++开头表示新文件。
一个补丁文件中的多个补丁
一个补丁文件中可能包含以—/+++开头的很多节,每一节用来打一个补丁。所以在一个补丁文件中可以包含好多个补丁。
块
块是补丁中要修改的地方。它通常由一部分不用修改的东西开始和结束。他们只是用来表示要修改的位置。他们通常以@@开始,结束于另一个块的开始或者一个新的补丁头。
块的缩进
块会缩进一列,而这一列是用来表示这一行是要增加还是要删除的。
块的第一列
+号表示这一行是要加上的。-号表示这一行是要删除的。没有加号也没有减号表示这里只是引用的而不需要修改。

单文件实例分析

设当前目录有文件 test0:

111111
111111
111111

和文件test1:

222222
111111
222222
111111

使用diff创建补丁test1.patch

diff -uN test0 test1 > test1.patch

因为是单个文件,故不需要 -r 选项。此命令得到如下补丁:

--- test0       2006-08-18 09:12:01.000000000 +0800
+++ test1       2006-08-18 09:13:09.000000000 +0800
@@ -1,3 +1,4 @@
+222222
 111111
-111111
+222222
 111111

要应用补丁,只需:

$ patch -p0 < test1.patch
patching file test0

此时test0就和test1一样了。

如果要取消补丁做出的更改,恢复旧版本:

$ patch -RE -p0 < test1.patch
patching file test0

文件夹实例分析

设有如下环境:

--prj0/
     test0
     prj0name
--prj1/
     test1
     prj1name

prj0/prj0name内容为如下三行:

--------
prj0/prj0name
--------

prj1/prj1name内容为如下三行:

--------
prj1/prj1name
--------

用 diff -uNr 创建补丁,

diff -uNr prj0 prj1 > prj1.patch

得到的patch文件为:

diff -uNr prj0/prj0name prj1/prj0name
--- prj0/prj0name       2006-08-18 09:25:11.000000000 +0800
+++ prj1/prj0name       1970-01-01 08:00:00.000000000 +0800
@@ -1,3 +0,0 @@
---------
-prj0/prj0name
---------
diff -uNr prj0/prj1name prj1/prj1name
--- prj0/prj1name       1970-01-01 08:00:00.000000000 +0800
+++ prj1/prj1name       2006-08-18 09:26:36.000000000 +0800
@@ -0,0 +1,3 @@
+---------
+prj1/prj1name
+---------
diff -uNr prj0/test0 prj1/test0
--- prj0/test0  2006-08-18 09:23:53.000000000 +0800
+++ prj1/test0  1970-01-01 08:00:00.000000000 +0800
@@ -1,3 +0,0 @@
-111111
-111111
-111111
diff -uNr prj0/test1 prj1/test1
--- prj0/test1  1970-01-01 08:00:00.000000000 +0800
+++ prj1/test1  2006-08-18 09:26:00.000000000 +0800
@@ -0,0 +1,4 @@
+222222
+111111
+222222
+111111

如果要应用此补丁,则:

$ ls
prj0  prj1  prj1.patch
$ cd prj0
$ patch -p1 < ../prj1.patch
patching file prj0name
patching file prj1name
patching file test0
patching file test1

此时可用ls看到打补丁后的结果:

$ ls
prj1name  test1

类似的,如果要回滚补丁操作:

$ patch -R -p1 < ../prj1.patch
patching file prj0name
patching file prj1name
patching file test0
patching file test1
$ ls
prj0name  test0

在 Windows 下

您可以安装 mingw,或者安装 Git,或者 RailsInstaller 等之类的,他们都包括了 diff 和 patch。如果您并不想安装这些庞然大物,可以尝试我打包的 diff 和 patch。
下载适合 Windows 的 diff 和 patch

 

扩展阅读

]]>
https://oldblog.orzfly.com/html/diff-and-patch-and-windows.html/feed 1
一键 Windows 化文件名的 Ruby 脚本 https://oldblog.orzfly.com/html/ruby-windowslize-filename.html Sun, 16 Sep 2012 07:18:50 +0000 http://orzfly.com/?p=787 因为用 ext4 的缘故文件名里可以用各种 :\<>?*|,于是下载了歌曲复制到手机上时就 233 了。

#!/usr/bin/env ruby
Dir['*'].each do |i| `mv "#{i}" "#{i.tr(":\\/<>|*?", "________")}"` end

]]>
RGSS 中读取注册表 https://oldblog.orzfly.com/html/rgss-registry.html Sun, 26 Aug 2012 04:45:23 +0000 http://orzfly.com/?p=219 有了这段脚本,便可以在 RGSS 中使用一种较为简单的语法来获得注册表中的字符串值,如:Registry::HKLM["SoftwareEnterbrainRGSSRTP"]["Standard"]
因为 Azoki 中用到了这个,于是先发出来最简单的部分好了。
这段脚本依赖于 String#s2u。

#==============================================================================
# ■ Registry
#------------------------------------------------------------------------------
#  极其简单的一个只能读取字符串值的注册表读取模块。
#------------------------------------------------------------------------------
=begin
  来源:http://orzfly.com/html/rgss-registry.html
  依赖:http://orzfly.com/html/rgss-string-encoding.html
  使用举例: 
    Registry::HKLM["SoftwareEnterbrainRGSSRTP"]["Standard"]
    读取 HKEY_LOCAL_MACHINESoftwareEnterbrainRGSSRTP 下的 Standard 的值
=end
#==============================================================================
module Registry
  #--------------------------------------------------------------------------
  # ● API 定义
  #--------------------------------------------------------------------------
  module NativeMethods
    RegOpenKey = Win32API.new('advapi32', 'RegOpenKeyExA', 'LPLLP', 'L')
    RegQueryValueEx = Win32API.new('advapi32', 'RegQueryValueExA', 'LPLPPP', 'L')
    RegCloseKey = Win32API.new('advapi32', 'RegCloseKey', 'L', 'L')
  end
  
  #--------------------------------------------------------------------------
  # ● 根代理
  #--------------------------------------------------------------------------
  class RegistryRoot
    def initialize root
      @root = root
    end
    
    def [] key
      RegistryKey.new @root, key
    end
  end
  
  #--------------------------------------------------------------------------
  # ● 键代理
  #--------------------------------------------------------------------------
  class RegistryKey
    include NativeMethods
    
    def initialize root, key
      @root, @key = root, key
    end
    
    def [] name
      begin
        key = 0.chr * 4

        RegOpenKey.call(@root, @key, 0, 0x20019, key)
        key = key.unpack('l')[0]
        type = 0.chr * 4
        size = 0.chr * 4

        RegQueryValueEx.call(key, name, 0, type, 0, size)
        data = ' ' * size.unpack('l')[0]

        RegQueryValueEx.call(key, name, 0, type, data, size)
        value = data.respond_to?(:force_encoding) ? 
          data.force_encoding("ascii-8bit").chop.s2u :
          data.chop.s2u
        RegCloseKey.call(key)
        
        return value
      rescue
        nil
      end
    end
  end
  
  #--------------------------------------------------------------------------
  # ● 常量定义
  #--------------------------------------------------------------------------
  HKEY_CLASSES_ROOT  = HKCR = RegistryRoot.new(0x80000000)
  HKEY_CURRENT_USER  = HKCU = RegistryRoot.new(0x80000001)
  HKEY_LOCAL_MACHINE = HKLM = RegistryRoot.new(0x80000002)
end

]]>
RGSS 中转换字符串的编码 https://oldblog.orzfly.com/html/rgss-string-encoding.html Sat, 25 Aug 2012 18:44:37 +0000 http://orzfly.com/?p=200 事实上 RGSS 是个 Ruby 的子集,Ruby 的许多重要特性被 Enterbrain 限制了。与此同时写脚本的时候或多或少会用到编码转换。总算有闲心把这个平时一直用到的代码包装了一下,希望对您有用。事实上实现这个功能的代码很多人都写过了,我的这个版本不过是重构了一下而已。

追加的 String 实例方法

  • iconv(src_encoding, dst_encoding) → str
    将自身的副本从 src_encoding 转换为 dst_encoding 并返回。两个 encoding 参数均接受 Windows 代码页数字或脚本中定义的六个 Symbol。
  • u2s → str
    iconv(:UTF8, :System) 的快捷方式。
  • s2u → str
    iconv(:System, :UTF8) 的快捷方式。

脚本

#==============================================================================
# ■ String(补充定义:编码转换)
#------------------------------------------------------------------------------
#  为字符串追加编码转换的机能。
#==============================================================================
# 来源:http://orzfly.com/html/rgss-string-encoding.html
#==============================================================================
# 参考:
#http://msdn.microsoft.com/en-us/library/windows/desktop/dd319072(v=vs.85).aspx
#http://msdn.microsoft.com/en-us/library/windows/desktop/dd374130(v=vs.85).aspx
#http://msdn.microsoft.com/en-us/library/windows/desktop/dd317756(v=vs.85).aspx
#==============================================================================
class String
  #--------------------------------------------------------------------------
  # ● 常量定义
  #--------------------------------------------------------------------------
  MultiByteToWideChar = Win32API.new('kernel32', 'MultiByteToWideChar', 'ilpipi', 'i')
  WideCharToMultiByte = Win32API.new('kernel32', 'WideCharToMultiByte', 'ilpipipp', 'i')
  Codepages = {
    :System => 0,     :UTF7   => 65000, :UTF8   => 65001,
    :S_JIS  => 932,   :GB2312 => 936,   :BIG5   => 950, 
  }
  #--------------------------------------------------------------------------
  # ● 伪 iconv 编码转换
  #--------------------------------------------------------------------------
  #     s : 原始编码,可使用 Codepages 中的符号或者直接使用代码页值。
  #     d : 目标编码,同上。
  #--------------------------------------------------------------------------
  def iconv s, d
    src  = s.is_a?(Symbol)? Codepages[s] : s
    dest = d.is_a?(Symbol)? Codepages[d] : d

    len = MultiByteToWideChar.call src, 0, self, -1, nil, 0
    buf = "" * (len * 2)
    MultiByteToWideChar.call src, 0, self, -1, buf, buf.size / 2

    len = WideCharToMultiByte.call dest, 0, buf, -1, nil, 0, nil, nil
    ret = "" * len
    WideCharToMultiByte.call dest, 0, buf, -1, ret, ret.size, nil, nil

    self.respond_to?(:force_encoding) ?
    ret.force_encoding("ASCII-8BIT").delete("x00") :
    ret.delete("x00")
  end
  #--------------------------------------------------------------------------
  # ● 快捷方式:从系统代码页转为 UTF-8 编码
  #--------------------------------------------------------------------------
  def s2u
    self.respond_to?(:force_encoding) ?
    iconv(:System, :UTF8).force_encoding("utf-8") :
    iconv(:System, :UTF8)
  end
  #--------------------------------------------------------------------------
  # ● 快捷方式:从 UTF-8 编码转为系统代码页
  #--------------------------------------------------------------------------
  def u2s
    iconv(:UTF8, :System)
  end
end

]]>