Blog没怎么写,倒是天天总结AppleScript~ 其实可以写个applescript分类了,呵呵~
最近又折腾一档子 便民 利己小工具,窗口布局器。这名字听起来怪怪的,我也没有怎么仔细想过,姑且先这么叫吧。需求来源是,有时候要对照某个web页面的内容,在另外一个web页面或者其他程序里面写邮件或者做其他事情,这个需求是很多人都有的,工作生活中也很常见。解决办法一般都是移动和缩放两个窗口摆在桌面两边,或者上下两部分,或者两个显示器上。如果有个工具可以方便快捷完成这个操作,那应该不错。今天的“窗口布局器”就完成的这个功能;并且我还借鉴了Windows 7中摸索到的还没有精确确认的neat小功能,WIN+上下左右方向键对窗口进行最大/最小化等操作,最终让今天折腾的窗口布局器和QuickSilver快捷键设置绑定起来,做到最快布局窗口。
功能需求/描述是这样:编写 ResizeRepos.scpt ,通过执行它可将当前窗口尺寸变为全屏幕的高,全屏幕的N分之一宽,并且移动到距离窗口左上角位置最近的(宽度的N分之一的整数倍,0)的坐标。用通俗点的语言就是,假设你想把屏幕分成左右两半,执行ResizeRepos.scpt脚本后,无论你现在打开的是Terminal还是Preview,都会使窗口占据屏幕的一半,是左半边还是右半边取决于窗口原始位置是略靠左还是略靠右。如果已经移动到了屏幕的最左边,再次执行该脚本会将窗口移到最右边,再执行一次会移动回最左边。更为奇妙的是,如果你的桌面足够大,将屏幕分为三份/四份也是可以的。
废话不多说,上代码~~
property _deskwidth : 2048
property _deskheight : 1152
property _segments : 2
on run argv
if (count argv) is not 0 then
set _segments to (item 1 of argv) as integer
end if
set _cellw to _deskwidth div _segments
set name_ to the name of (info for (path to frontmost application))
tell application name_
set {_posx, _y, _bx, _by} to bounds of front window
set _newpos to _posx div _cellw * _cellw + _cellw
if (_newpos ≥ _deskwidth) then
set _newpos to 0
end if
set the bounds of the first window to ¬
{_newpos, 0, _newpos + _cellw, _deskheight}
end tell
end run
注:“¬”是折行符号,实际写的时候可以把它连接的两行连起来;“≥”是大于等于号,输入>=即可,保存的时候AppleScript Editor会自动变为≥
解释之:
_deskwidth 和 _deskheight 是自己桌面的宽和高,自己根据需要调整;动态获取也是可以的,比如获取宽度就是 set _deskwidth to word 3 of (do shell script "defaults read /Library/Preferences/com.apple.windowserver | grep -w Width") as number;显然自己桌面尺寸不会天天变,我们就不动态获取了;还有就是对于双显/三显/四显的土豪们,请参考 Daring Fireball 06年某文 解释多显虚拟桌面计量的文章,此处不多讨论
if (count argv) is not 0 then 一直到if结束,是获取执行时候的参数;我们希望调用的时候调用者告诉脚本是将屏幕划分为两半还是三瓣。。。
set name_ to the name of (info for (path to frontmost application)) 此行获取当前程序的名称,下面的tell都是在该程序中进行操作
set {_posx, _posy, _botx, _boty} to bounds of front window 获取当前程序的当前窗口左上角xy坐标右下角xy坐标
对获取的xy坐标进行计算,这么简单的就不解释了,然后通过 set the bounds of the first window to {_newpos, 0, _newpos + _cellw, _deskheight} 将新坐标发回给窗口,就设置完成了位置和尺寸
仅仅写完了这个还没有彻底结束,这个script如果只是在Finder里双击运行或者Terminal里命令行执行,就只能修改修改这俩程序的窗口位置和尺寸了。现在我编写了两个脚本split2.sh和split3.sh,各自都只有一行,他们分别是 osascript /Users/kcome/sh/scripts/ResizeRepos.scpt 2 和 osascript /Users/kcome/sh/scripts/ResizeRepos.scpt 3 ;看到了吧,只有最后一个字符不同,第一个就是分两半的方案布局窗口,第二个是分三瓣。
然后进入QuickSilver的Triggers界面,添加项目,Select an item选择刚才写的split2.sh,Action就是默认的Run […],Target随便写一个字符(否则用快捷键启动时候会被询问Target,其实在这里是无用的参数);然后添加保存,指定快捷键,就大功告成了。按下快捷键试试吧?
其实,要说我这博有啥意义的话,我想只有两点,一个是想说AppleScript很强大,基本上发挥自己的想象力,可以完成许许多多的有趣有用功能;另外一个就是,善用google,勇于尝试,我不过是花了一两个小时,搜索了不到十个关键词组,比如“applescript get current desktop size”、“move window by applescript”、“howto get argument in applescript”,加上试验,修改,调试,就完成了这个功能。所以,写程序也不难,让电脑听话也是有趣事:)
用了一段时间VPN自动拨号脚本,觉得没啥大问题,有两个问题,一个是输入管理员密码的时候不能自动将焦点移到输入框中,二个是如果拨号不成功当前脚本不会自动退出运行。今天更新个小tip解决问题一。
其实很简单,将
on run {input, parameters}
-- 和以前一样的所有内容
end run
变为下面的即可
on run {input, parameters}
tell me
activate
-- 和以前一样的所有内容
end tell
end run
其实还有个可以完善的地方,应该是检测当前vpn IP地址和hosts文件中的是否一致,如果一致就不要修改它了,可以跳过管理员密码输入这一步骤。
从这次开始,把一些技术技巧记录也写在blog里,否则对我这种写博拖延症来说,保持一定频率真太难了。。。拖延症其实都是coding或者干活强迫症造成的,干活强迫症有点让我其他什么都进行困难了。。。废话少说,正题开始,这是一个条件略有复杂和奇特的case,需求可能有些和别人的不同,之前没有搜到特别完美的方案,就把自己的脚本以及折腾过程记录下来。
全程仅用Autormator里添加一个“Run AppleScript”任务,任务中有不少“do shell script xxx”的语句调用命令行工具。代码如下
on run {input, parameters}
set REMOTEIP to do shell script ¬
"curl -s http://11.22.33.44:8080/showip | grep -Eo \"([[:digit:]\\.]+)\""
do shell script "sed -i -e \"s/.* remoteIP.local/" & REMOTEIP & ¬
" remoteIP.local/g\" /etc/hosts" with administrator privileges
do shell script "dscacheutil -flushcache"
do shell script "route -n add -static " & REMOTEIP & ¬
" 192.168.2.1" with administrator privileges
tell application "System Events"
tell current location of network preferences
set VPNservice to service "VPN NAME IN SYSTEM PREFERENCES"
if current configuration of VPNservice is not connected then
connect VPNservice
repeat while current configuration of VPNservice is not connected
delay 1
end repeat
end if
end tell
end tell
do shell script "route -nv add -net 192.168.0.0/24 10.0.0.2" ¬
with administrator privileges
return input
end run
其中“¬”是OPTION+ENTER/RETURN,只是将太长的单行语句折行方便显示用的。
curl -s http://11.22.33.44:8080/showip | grep -Eo "([[:digit:]\\.]+)"
因为暴露远程网络IP地址的静态页面显示的并非一个单独的IP地址,这里用grep把其他无用信息过滤掉,将被扒光的IP地址付给变量REMOTEIP
do shell script "sed -i -e \"s/.* remoteIP.local/" & REMOTEIP & ¬
" remoteIP.local/g\" /etc/hosts" with administrator privileges
我再解释一下上面这行。因为远程网络的IP地址不固定,而Mac OS X里PPTP VPN的目标IP地址目前没有找到好方法用命令行或AppleScript修改,所以这里采用的方法是填写一个本地主机名“remoteIP.local”,然后在 /etc/hosts 文件中写入 “11.22.33.44 remoteIP.local”,这样就避免了在AppleScript或命令行下修改VPN连接目标IP的需求。这个方法虽然有点迂回和龌龊,但是其他更便捷的方法还没发现。缺点还包括每次连接vpn都要修改hosts文件,洁癖表示接受起来鸭梨略大。
route命令是让VPN连接走指定网关的。我是一开机即连上美国VPN的并设置为全局路由,而这里又希望连接办公网络的PPTP VPN不经过美国VPN,就指定了直接从网关经过。
下面的VPN连接代码应该是很容易可以google到的,到处都有解释这里就不多说了。
注意一点是如果命令行操作需要sudo,只需要去掉它并在do shell script “bla bla bla”后加“with administrator privileges”即可。虽然简单的东西也找了挺久,不知道是我不会找还是AppleScript文档比较囧。
其他就没什么了把。先到这里吧:)