关于正则表达式

起因

正则表达式初次被我重视归咎于百合仙子,当时以为‘他’是美女,当然美女在群里出的题目都大家都相当重视去解决,估计当时有很多兄弟被他忽悠过。不过到现在来看,这种忽悠是值得的,终归最后是拓宽了知识面,同时认识了一群志趣相投的业内人士。

只所以今天重拾正则这个话题,原因是昨天有同事提到一次面试题,遇到此题。

题目

原文:如何匹配一个数字,范围在(1-65555)不可以使用分组|

分析

匹配数字,正则对应的元字符是\d,单词的开始结束\b,这样就有了雏形

`\b\d\d\d\d\d\b`

但是此时是配置5位任意数,对于1、2、3、4位数就无法匹配,解决的方法是加入限定符重复零次或一次,即

`\b\d?\d?\d?\d?\d?\b`

这样就可以匹配0-99999的数,要进一步对该值进行限制,就需要加入零宽度断言(?<!exp)最后的结果就是

`\b[1-6]?\d?(?<!6[6-9])\d?(?<!65[6-9])\d?(?<!655[6-9])\d?(?<!6555[6-9])\b`

结果

`\b[1-6]?\d?(?<!6[^1-5])\d?(?<!65[6-9])\d?(?<!655[6-9])\d?(?<!6555[6-9])\b`

这个结果还不是很完美,它包含了0开头的数字, 先做记录,以后再做完整。

「转」使用 Byzanz 录制 Gif 动画或 Ogv 视频

想要录制 Linux 桌面?Byzanz 是一个不错的选择。Byzanz 简单小巧,容易使用,既能录制 Gif 动画,又可录制 Ogv 视频。

Byzanz

安装 Byzanz

可执行下列指令来安装 Byzanz,注意需要 root 权限:

aptitude install byzanz # Debian/Ubuntu
yum install byzanz # Fedora
emerge -av byzanz # Gentoo/Funtoo
pacman -S byzanz #Archlinux

Arch Linux 用户可在 AUR 中找到 Byzanz。如果你不能在自己所用的 Linux 发行版包仓库中找到 Byzanz,那么可以获取其源代码,自行编译。

Byzanz 用法

以本文的 byzanz-demo.gif 为例,你可以通过如下命令来完成录制过程:

yzanz-record -d 40 -x 0 -y 0 -w 400 -h 320 byzanz-demo.gif

其中:

  • -d 40 为录制的时长为 40 秒
  • -x 0 录制区域的横坐标
  • -y 0 录制区域的纵坐标,记住:屏幕右上角为原点(0,0)
  • -w 400 录制区域的宽度
  • -h 320 录制区域的高度
  • byzanz-demo.gif 保存的文件名

BTW: Byzanz 还带有一个 GNOME panel applet,感兴趣的同学可自行尝试。

Android keyevent抓图,使用jpeg565对数据压缩

实现功能

使用poll池方法监测event3event5和对从FB_DEVICE获得的图像数据进行jpeg压缩,压缩图像由之前的2700k缩小为89k,压缩比显而易见(30倍)。

效果图

Android ScreenShot

抓图实现

FB_DEVICE "/dev/graphics/fb0"获得图像的原始数据,色彩数据分为头和rgba数据,在函数jpg_screen_capture里case 16:中我对原始数据进行了处理,将rgba8888的数据转换为rgb565的数据,最后用generateJPEG对数据进行jpeg compress,具体的可以见capture_jpg.c代码

  • 这里要注意的一点是在读取fb_var.xres值必须为2^5=16的倍数,不够的要补足,也就是如下代码:

    if((fb_var.xres&0x1F)==0)
    fb->w = fb_var.xres;
    else
    fb->w =((fb_var.xres>>5)+1)<<5;

这样可以避免在抓图时出现像素移位,该问题在fb0的图像像素宽不是16的倍数时出现。

capture_jpg.c

/*=============================================================================
#     FileName: capture_jpg.c
#         Desc: capture jgp screenshoot 
#       Author: Lee Meng
#        Email: leaveboy@gmail.com
#     HomePage: http://leaveboy.is-programmer.com/
#      Version: 0.0.1
#   LastChange: 2013-01-15 09:33:23
#      History:
=============================================================================*/
#include <string.h>  
#include <stdlib.h>

#include <math.h>  
#include <stdio.h>  
#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>
#include <linux/fb.h>
#include <sys/mman.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>

typedef uint8_t BYTE;  
#define true 1  
#define false 0  


#include <jpeglib.h>

#define FB_DEVICE "/dev/graphics/fb0"
static int g_fd;

typedef struct
{
    int w;    /* width */
    int h;    /* high */
    int bpp;  /* bits per pixel */
    unsigned char *fbmem;
}screen;


static int init_fb(screen *fb)
{
    if ((g_fd = open(FB_DEVICE, O_RDWR)) < 0)
    { 
        fprintf(stderr, "Open %s failed:%s\n", FB_DEVICE, strerror(errno));
        return -1; 
    }   

    struct fb_var_screeninfo fb_var;
    struct fb_fix_screeninfo fb_fix;

    if (ioctl(g_fd, FBIOGET_VSCREENINFO, &fb_var) < 0)
    { 
        fprintf(stderr, "fb ioctl failed:%s\n", strerror(errno));
        return -1; 
    }   
    /*
         if (ioctl(g_fd, FBIOGET_FSCREENINFO, &fb_fix) < 0)
         { 
         fprintf(stderr, "fb ioctl failed:%s\n", strerror(errno));
         return -1; 
         }   
         */
    //fb->w   = fb_var.xres;
    if((fb_var.xres&0x1F)==0)
        fb->w = fb_var.xres;
    else
        fb->w =((fb_var.xres>>5)+1)<<5;
    fb->h   = fb_var.yres;
    fb->bpp = fb_var.bits_per_pixel;
    //    printf("capture_log %d, %d, %d, %d\n", fb_var.xres_virtual, fb_var.yres_virtual, fb_var.xoffset, fb_var.yoffset);
    //    printf("capture_log %d\n", fb_fix.line_length);
#if 1
    printf("width:%d\thigh:%d\tbpp:%d\n",fb->w, fb->h, fb->bpp);
#endif
    fb->fbmem = mmap(0, fb->w * fb->h * fb->bpp /8,PROT_READ | PROT_WRITE, MAP_SHARED, g_fd, 0);
    if (fb->fbmem == MAP_FAILED)
    {
        fprintf(stderr, "fb mmap failed:%s\n", strerror(errno));
        return -1;
    }

    close(g_fd);
    return 0;
}

int term_fb(screen *fb)
{
    munmap(fb->fbmem, fb->w * fb->h * fb->bpp / 8);
    return 0;
}


static int generateJPEG(BYTE* data,int w, int h, const char* outfilename)  
{  
    int nComponent = 3;  

    struct jpeg_compress_struct jcs;  

    struct jpeg_error_mgr jem;  

    jcs.err = jpeg_std_error(&jem);   
    jpeg_create_compress(&jcs);  

    FILE* f=fopen(outfilename,"wb");  
    if (f==NULL)   
    {  
        free(data);  
        return 0;  
    }  
    jpeg_stdio_dest(&jcs, f);  
    jcs.image_width = w;   
    jcs.image_height = h;  
    jcs.input_components = nComponent;  
    if (nComponent==1)  
        jcs.in_color_space = JCS_GRAYSCALE; 
    else   
        jcs.in_color_space = JCS_RGB;  

    jpeg_set_defaults(&jcs);      
    jpeg_set_quality (&jcs, 80, true);  

    jpeg_start_compress(&jcs, TRUE);  

    JSAMPROW row_pointer[1];
    int row_stride;   

    row_stride = jcs.image_width*nComponent;   


    while (jcs.next_scanline < jcs.image_height) {  
        row_pointer[0] = & data[jcs.next_scanline*row_stride];

        jpeg_write_scanlines(&jcs, row_pointer, 1);  
    }  

    jpeg_finish_compress(&jcs);  
    jpeg_destroy_compress(&jcs);  
    fclose(f);  

    return 1;  
}  



//int main(void)
extern int jpg_screen_capture(char * file_name)
{  
    int i = 0, j = 0;
    int w = 0, h = 0;
    int ret = 0;
    unsigned char *p;
    screen fb_screen;

    init_fb(&fb_screen);

    w = fb_screen.w;
    h = fb_screen.h;

    p = (unsigned char *)malloc(w * h * 3);

    printf("0x%x %x %x %x\n", *fb_screen.fbmem, *(fb_screen.fbmem + 1), \
            *(fb_screen.fbmem + 2), *(fb_screen.fbmem + 3));

    short *cursor = (short*)fb_screen.fbmem;
    switch(fb_screen.bpp)
    {
        case 32:
            for(i = 0; i < h; i++)
            {
                for(j = 0; j < w; j++)
                {
                    *(p + (i * w + j) * 3 + 0) = *(fb_screen.fbmem + (i * w + j) * 4 + 0);
                    *(p + (i * w + j) * 3 + 1) = *(fb_screen.fbmem + (i * w + j) * 4 + 1);
                    *(p + (i * w + j) * 3 + 2) = *(fb_screen.fbmem + (i * w + j) * 4 + 2);
                }
            }
            break;

        case 16:
            while(i<w*h)
            {
                short pixel = *cursor;     
                int r = (pixel & 0xF800) << 8; 
                int g = (pixel & 0x7E0) << 5;  
                int b = (pixel & 0x1F) << 3;
                int color = 0xFF000000 | r | g | b;

                *(p + 3 * i + 0) = (unsigned char)(color>>16 &0xFF);
                *(p + 3 * i + 1) = (unsigned char)(color>>8  &0xFF);
                *(p + 3 * i + 2) = (unsigned char)(color>>0  &0xFF);
                i++;
                cursor++;
            }
            break;

        default:
            printf("not support bpp %d\n",fb_screen.bpp);
            return -1;
            break;
    }

    //    ret = generateJPEG(p, fb_screen.w, fb_screen.h, "/data/test/test.jpg");  
    ret = generateJPEG(p, fb_screen.w, fb_screen.h, file_name);  

    term_fb(&fb_screen);    
    free(p);
    return ret;
}

监听keyevent事件

这里为了避免单按键对使用造成影响,需同时监听两个keyevent 分别为event3event5,对这两个事件的监听采用了无阻塞方式,在poll池中对两个event进行检测,通过event.codeevent.value 区别按键(那个按键)动作(按下/松开),最后通过fork_sound()

/*=============================================================================
#     FileName: getevent.c
#         Desc: get events of powerkey and volume + 
#       Author: Lee Meng
#        Email: leaveboy@gmail.com
#     HomePage: http://leaveboy.is-programmer.com/
#      Version: 0.0.1
#   LastChange: 2013-01-15 09:32:53
#      History:
=============================================================================*/
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <time.h>
#include <errno.h>
#include <sys/poll.h>
#include <linux/input.h>

#define TIME_DELAY   6000 
#define IN_FILES  2
#define SAVE_PATH "/data/logs"
#define SOUND_PATH "system/media/audio/alarms/Alarm_Buzzer.ogg"

struct timeval tv,tv_event3={0L, 0L},tv_event5={0L, 0L};
static unsigned char  event3_down = 0x00;//
static unsigned char  event5_down = 0x00;
struct input_event event;

static void  fork_sound(void)
{
  pid_t pid = fork();
  if (pid == 0) {
    execl("/system/bin/stagefright", "stagefright", "-o", "-a", SOUND_PATH, NULL);
    /*execl("/system/bin/busybox", "busybox", "tar", "cvf", "/mnt/sdcard/logs.tar",SAVE_PATH, NULL);*/
    //execl("/system/bin/busybox", "busybox", "bzip", "-9", "/mnt/sdcard/logs.tar",NULL);
  }
}
/*int main(void) {*/
extern int event_capture_jpg(void) {
  int pollres;
  struct pollfd  fds[2];
  struct tm *p;
  time_t now;
  char capture_name[128];

  int i, real_read;
  printf("sizeof(struct input_event) = %d\n", sizeof(struct input_event));
  fds[0].fd  = open("/dev/input/event3", O_RDONLY|O_NONBLOCK);//volume button
  fds[1].fd  = open("/dev/input/event5", O_RDONLY|O_NONBLOCK);//power button

  for (i = 0; i<IN_FILES; i++){
    if ( fds[i].fd < 0 ) return -1;
    fds[i].events = POLLIN;
  }
  while(1){
    pollres = poll(fds,IN_FILES,TIME_DELAY);
    for (i = 0; i< IN_FILES; i++){
      if (fds[i].revents){
        real_read = read(fds[i].fd, &event, sizeof(event));
        if(real_read < (int)sizeof(event)) {
          fprintf(stderr, "could not get event\n");
          break;
        }
        time(&now);
        p = localtime(&now);
        sprintf(capture_name,"%s/%d-%d-%d_%d-%d-%d.jpg",
            SAVE_PATH,
            1900+p->tm_year, 1+p->tm_mon, p->tm_mday, 
            p->tm_hour, p->tm_min, p->tm_sec);
        printf("%d %u %u %u\n", i, event.type, event.code, event.value);

        if (i == 0x01 && event.type == 0x01 && event.code == 0x6B && event.value == 0x00)
          event5_down = 0x00;

        if (i == 0x00 && event.type == 0x01 && event.code == 0x73 && event.value == 0x00)
          event3_down = 0x00;

        if (i == 0x01 && event.type == 0x01 && event.code == 0x6B && event.value == 0x01)
        {
          event5_down = 0x01;
          if(event3_down&event5_down)
          {
            jpg_screen_capture(capture_name);
            fork_sound();
            printf("Lee Meng capture jpg:%s\n",capture_name);
          }
        }

        if (i == 0x00 && event.type == 0x01 && event.code == 0x73 && event.value == 0x01)
        {
          event3_down = 0x01;
          if(event3_down&event5_down)
          {
            printf("Lee Meng capture jpg:%s\n",capture_name);
            jpg_screen_capture(capture_name);
            fork_sound();
          }
        }

      } 
    }
    //no sleep
  }

  for(i=0;i<2;i++){
    if(fds[i].fd > 0){
      close(fds[i].fd);
      fds[i].fd = -1;
    }    
  }
  return 0;
}

main函数及Android.mk

main.c

#include <stdio.h>


int main(void)
{
  while(1)
  event_capture_jpg();
}

Android.mk

LOCAL_PATH := $(my-dir)

commonSources  :=

commonIncludes := $(TARGET_OUT_HEADERS)/common/inc

commonSharedLibraries :=  liboncrpc
commonSharedLibraries +=  libnv
commonSharedLibraries +=  libcutils libxml2 libicuuc
commonSharedLibraries +=  libutils
commonSharedLibraries +=  libjpeg libc


include $(CLEAR_VARS)
LOCAL_MODULE := qlogd
LOCAL_CFLAGS := $(commonCflags)

LOCAL_C_INCLUDES := $(call include-path-for, system-core)/cutils
LOCAL_C_INCLUDES += $(commonIncludes)
LOCAL_C_INCLUDES += $(LOCAL_PATH)
LOCAL_C_INCLUDES += external/jpeg
LOCAL_SRC_FILES := main.c getevent.c capture_jpg.c
LOCAL_MODULE_TAGS := optional eng
LOCAL_SHARED_LIBRARIES += $(commonSharedLibraries) 
LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES)
include $(BUILD_EXECUTABLE)

这四个文件放到Android工程下面vendor/qlogd目录下,mmm编译之后就可以在/system/xbin/找到qlogd,将qlogd push到手机上相应的目录/system/xbin/,添加可以执行权限

chmod 777 qlogd

然后运行

/system/xbin/qlogd&

按下power键和音量-键,就可以听到Bi Bi Bi的提示音了。

如何带路径复制文件

背景

前段时间在做代码合并的时候,不得不采取手工merge,由于涉及的文件很多,单个beyondcmp着实抗不住,就想着用命令一次性搞定。

分析

beyondcmp多文件比较需要路径一致,因此如果要做这样的修改,就需要将目前修改的文件放到对应的目录下。

思路

起初的想法是先截取每个文件所在的目录全路径,然后通过cp的方式复制过去,但这样感觉太过复杂,可能还需要写一个小脚本,有点过了。最后就想到之前用tar的带路径压缩解压,至于参数列表可以通过xargs-I参数来解决,这样就可以解决文件路径创建的问题。

做法

使用git diff --name-only可以将当前仓库做的修改文件列出来
使用tar cvf将文件带路径压缩
最终的命令就是

git diff --name-only | xargs -I @ tar cvf 11.tar  @

或者

git status --short | awk '{print $2}' | xargs -I @ tar cvf 11.tar  @ 

前者只列出修改的文件,后者包含了新加的文件—未添加到仓库中
使用tar xvf11.tar文件带路径解压 仓库外的新目录,然后与另一个仓库进行目录比较,最后在beyondcmp中做手工merge

后记

其实这种操作本来可以避免,但是目前由于android的版本太多,多文件比对操作无法避免,上面的做法,简单明了,能很快的将修改文件列出比较,相对与文件逐一寻找比对要方便,时间上也节省不少。

archlinux awsome3.5 config

awesome config 3.5

由于时间原因,前几天将升级后awesome 3.5回退到3.4.但总感觉不爽,所以昨天终于
忍不住又折腾了一下,把所有的控件都整安逸.还是有点点收获.先上张图

awesome screenshot
awesome 3.5修正了2个 3.4上一直存在的两个问题

  • term不能最大化的bug
  • 对非焦点窗口透明话支持(之前桌面切换会导致无法获得焦点

自己的配置文件已经上传到github上,有兴趣的同学可以下载来看看.欢迎指正

链接地址: 点击前往

ubuntu virtualbox XP 使用adb受限问题

前提条件:

ubuntu 在vbox XP下使用adb shell

问题说明:

C:\Documents and Settings\Administrator>adb devices
List of devices attached
MSM8225I370 device

C:\Documents and Settings\Administrator>adb shell
error: protocol fault (status 72 6f 6f 74?!)

原因在于:

virtualbox XP 设置时,USB设备 启用USB2.0 EHCI控制器.如果启用了该选项就会导致adb shell无法启动,偶尔会导致 QTSP中无法烧写model侧img

写了一个类似prey功能的脚本

在网上年到prey(就是传说中的黑客找回已丢电脑那个工具)感觉还不错,就是要注册,使用次数还有限制,所以打算自己折腾一下!

lost 脚本放在/usr/bin 下,请自己加执行权限:

chmod +x /usr/bin/lost

使用方法:

lost -h

脚本源码lost:

#!/bin/bash
####################################################################
# Lost create by leaveboy@gmail.com
# Discription: when your pc lost,it can help you to find it!
# License: GPLv3
###################################################################)
version=1.0

scp_user='leaveboy'  #user
scp_server='216.194.70.6' #an online server which pc could connect
scp_path="/home/${scp_user}/" #lost file path
email='leaveboy@gmail.com'  # address msg_file and image send to
msg_file='/tmp/lostinfo'

show_version(){
    echo "Prey ${version}"
}
show_usage(){
    echo "Prey ${version} "
    echo -e "\nUsage: `basename $0` [options]"
    echo -e "Options:"
    echo -e "  -v | --version\tShow Current Version."
    echo -e "  -h | --help\t\tShow this message.\n"
    echo -e "NOTICE"
    echo -e "  This script runs under linux system and For Run this script you should have follow software:\
        w3m scrot mutt ssh.\n"
    echo -e "ADD/DELETE CRONTAB"
    echo -e "  Run the follow command to add lost to crontab:"
    echo -e "  \$(sudo crontab -l | grep -v lost; echo \"*/20 * * * * /usr/bin/lost > /var/log/lost.log\") | sudo crontab -"
    echo -e "  Run the follow command to delete lost from crontab:"
    echo -e "  \$(sudo crontab -l | grep -v lost) | sudo crontab -\n"
    echo -e "ACTIVE/UNACTIVE"
    echo -e "  Touch a file named \"lost\"under the scp_path of the scp_server to actived."
    echo -e "  remove the file \"lost\" under the scp_path of the scp_server to unactived.\n"
}

until [ -z "$1" ]; do
    case "$1" in
        -v | --version )
            show_version && exit
            ;;
        -h | --help | * )
            show_usage && exit
    esac
    shift
done

send_mail(){
    F=`scrot '%F-%T_$wx$h_scrot.png' -e  'mv $f /tmp/ & echo $f'`
    #you can add any what you want in here
    `w3m http://www.ip138.com/ips8.asp  | grep '来自' > ${msg_file}`    #网络地址
    `uname -a >>  ${msg_file}`                                          #系统信息
    `uptime   >>  ${msg_file}`                                          #启动信息
    `ifconfig >>  ${msg_file}`                                          #网络信息
    `ps ux   >>  ${msg_file}`                                           #用户进程
    `more ${msg_file} | mutt -s "lost" ${email} -a /tmp/${F}`
}
#run condition you can change it and get some info from lost,of course,if it has!
if [ -f "/tmp/lost" ]; then
    send_mail && exit
else
    `scp ${scp_user}@${scp_server}:${scp_path}/lost /tmp/lost`
    if [ -f "/tmp/lost" ]; then
        send_mail && exit
    fi
fi

irssi + bitlbee

irssi and bitlbee

装上irssi 和 bitlbee 之后最头疼的是各种提示:

bitlbee所有的上下线提示关闭,所有IRC频道提示关闭

/ignore &bitlbee MODES
/ignore * MODES

关于mutt发送中文附件,foxmail,outlook接受不到的问题

经常在linux下工作,所有日常事务也是在linux处理,邮件处理自然也不例外,我这里环境是arch+mutt。带英文附件名的邮件使用mutt发送没有一点问题,中文附件名的邮件就悲剧了,附件在foxmail中不被识别,在outlook和DreamMail里是被篡改的名字类似“xxxxxx.MSWORD”,当然你强制用word打开还是没有问题的,但是始终是不爽!所以今天折腾了半天这个问题!
google了n多帖子,都基本是说设置

set rfc2047_parameters=yes

但是经过测试,这个只能使本地接收到的附件显示为中文附件名!要使自己发送的中文附件名在win下的客户端显示正常,这个不得行!

又google了n多帖子,就出现了最终的解决方法:

set create_rfc2047_parameters=yes

该设置需要在mutt源码中打patch,named patch-1.5.10.tt.create_rfc2047_params.1 点击下载
再到mutt主页上下在最近的mutt包 named mutt-1.5.21.tar.gz猛击下载
解压mutt-1.5.21.tar.gz和patch,解压出的patch放到mutt-1.5.21目录下,在该目录执行

patch -Np1 -i patch-1.5.10.tt.create_rfc2047_params.1

接着再执行

./configure &make &sudo make install

接个就用吧!mutt发送中文附件邮件,在foxmail中显示就ok了!

PS:这里要说一点,在ubuntu下,发送中文附件是没问题,但是用mutt中中文是乱码!这个可能与系统设置有关系,暂时没有处理!

在AWESOME上加入天气使用googleAPI字体weather.ttf

awesome rc.lua

这个脚本加入了词霸的屏幕取词,绑定PrtSc键抓图,还有天气显示!解决了前两天一直琢磨的字体天气问题!
上张现在桌面图:

awesome desktop screenshot

awesome 的配置文件 rc.lua

-- Standard awesome library
require("awful")
require("awful.autofocus")
require("awful.rules")
-- Theme handling library
require("beautiful")
require("vicious")
-- Notification library
require("naughty")

-- Load Debian menu entries
require("debian.menu")

-- --- Variable definitions
-- Themes define colours, icons, and wallpapers
beautiful.init("/usr/share/awesome/themes/default/theme.lua")

-- This is used later as the default terminal and editor to run.
terminal = "x-terminal-emulator"
editor = os.getenv("EDITOR") or "editor"
editor_cmd = terminal .. " -e " .. editor

-- Default modkey.
-- Usually, Mod4 is the key with a logo between Control and Alt.
-- If you do not like this or do not have such a key,
-- I suggest you to remap Mod4 to another key using xmodmap or other tools.
-- However, you can use another modifier like Mod1, but it may interact with others.
modkey = "Mod4"

-- Table of layouts to cover with awful.layout.inc, order matters.
layouts =
{
    awful.layout.suit.floating,
    awful.layout.suit.tile,
    awful.layout.suit.tile.left,
    awful.layout.suit.tile.bottom,
    awful.layout.suit.tile.top,
    awful.layout.suit.fair,
    awful.layout.suit.fair.horizontal,
    awful.layout.suit.spiral,
    awful.layout.suit.spiral.dwindle,
    awful.layout.suit.max,
    awful.layout.suit.max.fullscreen,
    awful.layout.suit.magnifier
}
-- ___

-- --- Tags
-- Define a tag table which hold all screen tags.
tags = {}
for s = 1, screen.count() do
    -- Each screen has its own tag table.
    tags[s] = awful.tag({ 1, 2, 3, 4, 5, 6, 7, 8, 9 }, s, layouts[1])
end
-- ___

-- --- Menu
-- Create a laucher widget and a main menu
myawesomemenu = {
   { "manual", terminal .. " -e man awesome" },
   { "edit config", editor_cmd .. " " .. awful.util.getdir("config") .. "/rc.lua" },
   { "restart", awesome.restart },
   { "quit", awesome.quit }
}

mymainmenu = awful.menu({ items = { { "awesome", myawesomemenu, beautiful.awesome_icon },
                                    { "Debian", debian.menu.Debian_menu.Debian },
                                    { "open terminal", terminal }
                                  }
                        })

mylauncher = awful.widget.launcher({ image = image(beautiful.awesome_icon),
                                     menu = mymainmenu })
-- ___

-- --- Wibox
-- Create a textclock widget
mytextclock = awful.widget.textclock({ align = "right" },"%x %R",61)
-------------------------------------leave--------------------------
--Spacer
spacer    = widget({ type = "textbox" })
separator = widget({ type = "textbox" })
spacer.text     = " "
separator.text  = "|"
--Cpu text
cpu = widget({ type = "textbox" })
vicious.register(cpu, vicious.widgets.cpu, ' <span color="brown">CPU1:</span> <span color="orange">$2%</span> <span color="brown">CPU2:</span> <span color="orange">$3%</span>', 1)
--Cpu wigth
cpu_g1 = awful.widget.graph()
cpu_g1:set_width(50)
cpu_g1:set_background_color("#333333")
cpu_g1:set_color("#AEC6D8")
cpu_g1:set_border_color("#0a0a0a")
vicious.register(cpu_g1, vicious.widgets.cpu, "$2", 1)

cpu_g2 = awful.widget.graph()
cpu_g2:set_width(50)
cpu_g2:set_background_color("#333333")
cpu_g2:set_color("#AEC6D8")
cpu_g2:set_border_color("#0a0a0a")
vicious.register(cpu_g2, vicious.widgets.cpu, "$3", 1)
--MPD
mpd = widget({ type = "textbox" })
vicious.register(mpd, vicious.widgets.mpd,
    function (widget, args)
            local ret_str = ' <span color="brown">NOW Playing:</span>'
        if args["{state}"] == "Stop" then
            return ret_str .. ' <span color="orange"> - </span>'
        else
            return ret_str .. ' <span color="orange">'.. args["{Artist}"]..' - '.. args["{Title}"]..'</span>'
        end
    end, 3)
--Weather
------------------------regex-------------------------
function get_weather(con)
    local s = "<current_conditions>.*<\/forecast_conditions>"
    local i ,j = string.sub(con, string.find(con,s))
    local s = "\"[a-z0-9A-Z%s:%%]*\"" 
    local info
    for word in string.gmatch(i, s) do
            info = tostring(info).."\t"..tostring(word) 
    end
    local i, j = string.gsub(info, "\"","")
    local l = split(i,"\t")
    return l
end

------------------------split-------------------------
function split(string, spt)
    local find_index = 1
    local spt_index = 1
    local spt_arr = {}
    while true do
        local find_end = string.find(string, spt, find_index)
        if not find_end then
            spt_arr[spt_index] = string.sub(string, find_index, string.len(string))
            break
        end
        spt_arr[spt_index] = string.sub(string, find_index, find_end - 1)
        find_index = find_end + string.len(spt)
        spt_index = spt_index + 1
    end
    return spt_arr
end

------------------------main-------------------------
weathericon = widget({ type = "imagebox" })
weathericon.image = image(beautiful.widget_cloud)
weather = widget({type = "textbox" })
vicious.register(weather, vicious.widgets.weather,
 function (widget, args)
    local http = require("socket.http")
    local night = {["e"]='o',["f"]='p',["v"]='v',["j"]='t',["k"]='u',["h"]='r',["g"]='q',["c"]='m',["b"]='l',["d"]='n',["a"]='a',["N"]='N',["w"]='w'}
    local weather = {["Sandstorm"]='e',["Duststorm"]='e',["Sand"]='e',["Dust"]='e',["Fog"]='e',["Mist"]='e',["Smoke"]='e',["Haze"]='e',["Overcast"]='e',--'e o' 9th 阴霾
    ["Thunderstorms"]='f',["Thundershowers"]='f',["Storm"]='f',["Lightning"]='f',--'f p' 13th 闪电
    ["Hail"]='v',--'v' 14th 冰雹
    ["Blowing Snow"]='j',["Blizzard"]='j',["Snowdrift"]='j',["Snowstorm"]='j',["Snow"]='j',["Heavy Snow"]='j',["Snowfall"]='j', --'j t' 21th 大雪
    ["Snow Showers"]='k',["Flurries"]='k',["Light Snow"]='k',["Sleet"]='k',--'k u' 25th 小雪
    ["Showers"]='h',["Heavy Showers"]='h',["Rainshower"]='h',["Rain"]='h',--'h r' 29th 大雨
    ["Occasional Showers"]='g',["Scattered Showers"]='g',["Isolated Showers"]='g',["Light Showers"]='g',["Freezing Rain"]='g',["Drizzle"]='g',["Light Rain"]='g',--'g q' 36th 小雨
    ["Sunny Interval"]='c',["No Rain"]='c',["Clearing"]='c',--'c m' 39th 多云见晴
    ["Sunny Period"]='b',["Partly Cloudy"]='b',["Partly Bright"]='b',["Mild"]='b',--'b l' 43th 晴见多云
    ["Cloudy"]='d',["Mostly Cloudy"]='d',--'d, n' 45th 多云
    ["Bright"]='a',["Sunny"]='a',["Fair"]='a', --'a' 48th 白天晴天
    ["Fine"]='N',["Clear"]='N',--'N' 50th 晚间晴天
    ["Windy"]='w',["Squall"]='w',["Stormy"]='w',["Chill"]='w',["Gale"]='w'--'w' 55th 风
}
    local url = "http://www.google.com/ig/api?weather=chengdu"
    local con, ret = http.request(url)
    if con == nil then
        return nil
    else
        local l =   get_weather(con)
        local font_weather = weather[l[2]]
--[[        if os.date("%H",os.time())>"17" then
            font_weather = night[font_weather]
        end
        --]]
        local temp_c = 'y'
        if l[4] > "28" then
            temp_c = 'z'
        elseif l[4] < "15" then
            temp_c = 'x'
        end
        return '<span font="Weather regular 16" color="#FFFF00">'..font_weather..'</span><span color="orange"> '..l[4]..'°C</span>'
    end
 end

--"${sky} ${tempc} °C"
, 1800,"ZUUU")

--UPTIME
uptime = widget({ type = "textbox" })
vicious.register(uptime, vicious.widgets.uptime,' <span color="brown">UPTIME:</span> <span color="orange">$2:$3</span>', 61)
--MEM
mem = widget({ type = "textbox" })
vicious.register(mem, vicious.widgets.mem, ' <span color="brown">MEM:</span> <span color="orange">$1% $2MB</span> <span color="brown">SWAP:</span> <span color="orange">$5% $6MB</span>', 1)
--FS
fs = widget({ type = "textbox" })
vicious.register(fs, vicious.widgets.fs, ' <span color="brown">FS:</span> <span color="orange">${/ used_gb}GB ${/ used_p}%</span>', 5)
--DIO
dio = widget({ type = "textbox" })
vicious.register(dio, vicious.widgets.dio, ' <span color="brown">IO:</span> <span color="orange">R:${read_kb}KB W:${write_kb}KB</span>', 1, "sda")
--NET
net = widget({ type = "textbox" })
vicious.register(net, vicious.widgets.net, ' <span color="brown">NET:</span> <span color="orange">${eth0 down_kb}KB/${eth0 up_kb}KB</span>', 1)
-------------------------------------leave--------------------------
-- Create a systray
mysystray = widget({ type = "systray" })

-- Create a wibox for each screen and add it
mywibox_top = {}
mywibox_bottom = {}
mypromptbox = {}
mylayoutbox = {}
mytaglist = {}
mytaglist.buttons = awful.util.table.join(
                    awful.button({ }, 1, awful.tag.viewonly),
                    awful.button({ modkey }, 1, awful.client.movetotag),
                    awful.button({ }, 3, awful.tag.viewtoggle),
                    awful.button({ modkey }, 3, awful.client.toggletag),
                    awful.button({ }, 4, awful.tag.viewnext),
                    awful.button({ }, 5, awful.tag.viewprev)
                    )
mytasklist = {}
mytasklist.buttons = awful.util.table.join(
                     awful.button({ }, 1, function (c)
                                              if not c:isvisible() then
                                                  awful.tag.viewonly(c:tags()[1])
                                              end
                                              client.focus = c
                                              c:raise()
                                          end),
                     awful.button({ }, 3, function ()
                                              if instance then
                                                  instance:hide()
                                                  instance = nil
                                              else
                                                  instance = awful.menu.clients({ width=250 })
                                              end
                                          end),
                     awful.button({ }, 4, function ()
                                              awful.client.focus.byidx(1)
                                              if client.focus then client.focus:raise() end
                                          end),
                     awful.button({ }, 5, function ()
                                              awful.client.focus.byidx(-1)
                                              if client.focus then client.focus:raise() end
                                          end))

for s = 1, screen.count() do
    -- Create a promptbox for each screen
    mypromptbox[s] = awful.widget.prompt({ layout = awful.widget.layout.horizontal.leftright })
    -- Create an imagebox widget which will contains an icon indicating which layout we're using.
    -- We need one layoutbox per screen.
    mylayoutbox[s] = awful.widget.layoutbox(s)
    mylayoutbox[s]:buttons(awful.util.table.join(
                           awful.button({ }, 1, function () awful.layout.inc(layouts, 1) end),
                           awful.button({ }, 3, function () awful.layout.inc(layouts, -1) end),
                           awful.button({ }, 4, function () awful.layout.inc(layouts, 1) end),
                           awful.button({ }, 5, function () awful.layout.inc(layouts, -1) end)))
    -- Create a taglist widget
    mytaglist[s] = awful.widget.taglist(s, awful.widget.taglist.label.all, mytaglist.buttons)

    -- Create a tasklist widget
    mytasklist[s] = awful.widget.tasklist(function(c)
                                              return awful.widget.tasklist.label.currenttags(c, s)
                                          end, mytasklist.buttons)

    -- Create the wibox
    mywibox_top[s] = awful.wibox({ position = "top", screen = s })
    mywibox_bottom[s] = awful.wibox({ position = "bottom", screen = s })
    -- Add widgets to the wibox - order matters
        -- top
         mywibox_top[s].widgets = {
        {
            mylauncher,
            mytaglist[s],
            mypromptbox[s],
            layout = awful.widget.layout.horizontal.leftright
        },
        mylayoutbox[s],
        mytextclock,
        s == 1 and mysystray or nil,
                spacer,
                uptime,
            weather,
                spacer,
                weathericon,
        mytasklist[s],
        layout = awful.widget.layout.horizontal.rightleft
    }
        --bottom
    mywibox_bottom[s].widgets = {
            {
                fs,
                separator,
                mem,
                separator,
                dio,
                separator,
                net,
                separator,
                mpd,
                layout = awful.widget.layout.horizontal.leftright
            },
                cpu_g1.widget,
                spacer,
                cpu_g2.widget,
                spacer,
        layout = awful.widget.layout.horizontal.rightleft
    }
end
-- ___

-- --- Mouse bindings
root.buttons(awful.util.table.join(
    awful.button({ }, 3, function () mymainmenu:toggle() end),
    awful.button({ }, 4, awful.tag.viewnext),
    awful.button({ }, 5, awful.tag.viewprev)
))
-- ___

-- --- Key bindings
globalkeys = awful.util.table.join(
    awful.key({ modkey,           }, "Left",   awful.tag.viewprev       ),
    awful.key({ modkey,           }, "Right",  awful.tag.viewnext       ),
    awful.key({ modkey,           }, "Escape", awful.tag.history.restore),

    awful.key({ modkey,           }, "j",
        function ()
            awful.client.focus.byidx( 1)
            if client.focus then client.focus:raise() end
        end),
    awful.key({ modkey,           }, "k",
        function ()
            awful.client.focus.byidx(-1)
            if client.focus then client.focus:raise() end
        end),
    awful.key({ modkey,           }, "w", function () mymainmenu:show({keygrabber=true}) end),
        -- Unminimize clients
        awful.key({ modkey, "Control" }, "m",
        function ()
            local allclients = client.get(mouse.screen)
            for _, c in ipairs(allclients) do
                if c.minimized and c:tags()[mouse.screen] == awful.tag.selected(mouse.screen) then
                    c.minimized = false
                    client.focus = c
                    c:raise()
                    return
                end
            end
        end),
    -- Layout manipulation
    awful.key({ modkey, "Shift"   }, "j", function () awful.client.swap.byidx(  1)    end),
    awful.key({ modkey, "Shift"   }, "k", function () awful.client.swap.byidx( -1)    end),
    awful.key({ modkey, "Control" }, "j", function () awful.screen.focus_relative( 1) end),
    awful.key({ modkey, "Control" }, "k", function () awful.screen.focus_relative(-1) end),
    awful.key({ modkey,           }, "u", awful.client.urgent.jumpto),
        -- 截图 ---3
        awful.key({ }, "Print", function ()
            -- 截图:全屏
            awful.util.spawn("zsh -c 'cd ~/tmpfs&&scrot fullsc.png'")
            os.execute("sleep .5")
            naughty.notify({title="截图", text="全屏截图已保存。"})
        end),
        awful.key({ "Shift", }, "Print", function ()
            -- 截图:当前窗口
            awful.util.spawn("zsh -c 'cd ~/tmpfs&&scrot -u'")
            os.execute("sleep .5")
            naughty.notify({title="截图", text="当前窗口截图已保存。"})
        end),

        -- ---3 sdcv
        awful.key({ modkey }, "d", function ()
            local f = io.popen("xsel -p")
            local new_word = f:read("*a")
            f:close()

            if frame ~= nil then
                naughty.destroy(frame)
                frame = nil
                if old_word == new_word then
                    return
                end
            end
            old_word = new_word

            local fc = ""
            local f = io.popen("sdcv -n --utf8-output -u 'stardict1.3英汉辞典' "..new_word)
            for line in f:lines() do
                fc = fc .. line .. '\n'
            end
            f:close()
            frame = naughty.notify({ text = fc, timeout = 5, width = 320 })
        end),
    awful.key({ modkey,           }, "Tab",
        function ()
            awful.client.focus.history.previous()
            if client.focus then
                client.focus:raise()
            end
        end),

    -- Standard program
    awful.key({ modkey,           }, "Return", function () awful.util.spawn(terminal) end),
    awful.key({ modkey, "Control" }, "r", awesome.restart),
    awful.key({ modkey, "Shift"   }, "q", awesome.quit),

    awful.key({ modkey,           }, "l",     function () awful.tag.incmwfact( 0.05)    end),
    awful.key({ modkey,           }, "h",     function () awful.tag.incmwfact(-0.05)    end),
    awful.key({ modkey, "Shift"   }, "h",     function () awful.tag.incnmaster( 1)      end),
    awful.key({ modkey, "Shift"   }, "l",     function () awful.tag.incnmaster(-1)      end),
    awful.key({ modkey, "Control" }, "h",     function () awful.tag.incncol( 1)         end),
    awful.key({ modkey, "Control" }, "l",     function () awful.tag.incncol(-1)         end),
    awful.key({ modkey,           }, "space", function () awful.layout.inc(layouts,  1) end),
    awful.key({ modkey, "Shift"   }, "space", function () awful.layout.inc(layouts, -1) end),

    -- Prompt
    awful.key({ modkey },            "r",     function () mypromptbox[mouse.screen]:run() end),

    awful.key({ modkey }, "x",
              function ()
                  awful.prompt.run({ prompt = "Run Lua code: " },
                  mypromptbox[mouse.screen].widget,
                  awful.util.eval, nil,
                  awful.util.getdir("cache") .. "/history_eval")
              end)
)

clientkeys = awful.util.table.join(
    awful.key({ modkey,           }, "f",      function (c) c.fullscreen = not c.fullscreen  end),
    awful.key({ modkey, "Shift"   }, "c",      function (c) c:kill()                         end),
    awful.key({ modkey, "Control" }, "space",  awful.client.floating.toggle                     ),
    awful.key({ modkey, "Control" }, "Return", function (c) c:swap(awful.client.getmaster()) end),
    awful.key({ modkey,           }, "o",      awful.client.movetoscreen                        ),
    awful.key({ modkey, "Shift"   }, "r",      function (c) c:redraw()                       end),
    awful.key({ modkey,           }, "t",      function (c) c.ontop = not c.ontop            end),
    awful.key({ modkey,           }, "n",      function (c) c.minimized = not c.minimized    end),
    awful.key({ modkey,           }, "m",
        function (c)
            c.maximized_horizontal = not c.maximized_horizontal
            c.maximized_vertical   = not c.maximized_vertical
        end)
)

-- Compute the maximum number of digit we need, limited to 9
keynumber = 0
for s = 1, screen.count() do
   keynumber = math.min(9, math.max(#tags[s], keynumber));
end

-- Bind all key numbers to tags.
-- Be careful: we use keycodes to make it works on any keyboard layout.
-- This should map on the top row of your keyboard, usually 1 to 9.
for i = 1, keynumber do
    globalkeys = awful.util.table.join(globalkeys,
        awful.key({ modkey }, "#" .. i + 9,
                  function ()
                        local screen = mouse.screen
                        if tags[screen][i] then
                            awful.tag.viewonly(tags[screen][i])
                        end
                  end),
        awful.key({ modkey, "Control" }, "#" .. i + 9,
                  function ()
                      local screen = mouse.screen
                      if tags[screen][i] then
                          awful.tag.viewtoggle(tags[screen][i])
                      end
                  end),
        awful.key({ modkey, "Shift" }, "#" .. i + 9,
                  function ()
                      if client.focus and tags[client.focus.screen][i] then
                          awful.client.movetotag(tags[client.focus.screen][i])
                      end
                  end),
        awful.key({ modkey, "Control", "Shift" }, "#" .. i + 9,
                  function ()
                      if client.focus and tags[client.focus.screen][i] then
                          awful.client.toggletag(tags[client.focus.screen][i])
                      end
                  end))
end

clientbuttons = awful.util.table.join(
    awful.button({ }, 1, function (c) client.focus = c; c:raise() end),
    awful.button({ modkey }, 1, awful.mouse.client.move),
    awful.button({ modkey }, 3, awful.mouse.client.resize))

-- Set keys
root.keys(globalkeys)
-- ___

-- --- Rules
awful.rules.rules = {
    -- All clients will match this rule.
    { rule = { },
      properties = { border_width = beautiful.border_width,
                     border_color = beautiful.border_normal,
                     focus = true,
                     keys = clientkeys,
                     buttons = clientbuttons } },
    { rule = { class = "MPlayer" },
      properties = { floating = true } },
    { rule = { class = "pinentry" },
      properties = { floating = true } },
    { rule = { class = "gimp" },
      properties = { floating = true } },
    -- Set Firefox to always map on tags number 2 of screen 1.
    -- { rule = { class = "Firefox" },
    --   properties = { tag = tags[1][2] } },
}
-- ___

-- --- Signals
-- Signal function to execute when a new client appears.
client.add_signal("manage", function (c, startup)
    -- Add a titlebar
    -- awful.titlebar.add(c, { modkey = modkey })

    -- Enable sloppy focus
    c:add_signal("mouse::enter", function(c)
        if awful.layout.get(c.screen) ~= awful.layout.suit.magnifier
            and awful.client.focus.filter(c) then
            client.focus = c
        end
    end)

    if not startup then
        -- Set the windows at the slave,
        -- i.e. put it at the end of others instead of setting it master.
        -- awful.client.setslave(c)

        -- Put windows in a smart way, only if they does not set an initial position.
        if not c.size_hints.user_position and not c.size_hints.program_position then
            awful.placement.no_overlap(c)
            awful.placement.no_offscreen(c)
        end
    end
end)

client.add_signal("focus", function(c) c.border_color = beautiful.border_focus end)
client.add_signal("unfocus", function(c) c.border_color = beautiful.border_normal end)
-- ___
floatapps =
{
    ["MPlayer"] = true,
    ["gimp"] = true,
    ["smplayer"] = true,
    ["mocp"] = true,
    ["Codeblocks"] = true,
    ["Dialog"] = true,
    ["Download"] = true,
    ["empathy"] = true,
}

-- 把指定的程序自动移动到某个特定的屏幕的某个tag上面
apptags =
{
    ["smplayer"] = { screen = 1, tag = 7 },
    ["amarokapp"] = { screen = 1, tag = 8 },
    ["VirtualBox"] = { screen = 1, tag = 9 },
    ["Firefox"] = { screen = 1, tag = 1},
    ["Thunderbird-bin"] = { screen = 1, tag = 7 },
    ["Linux-fetion"] = { screen = 1, tag = 6 },
}