emacs自动更新文件头


前面已经说过,可以使用auto-insert自动添加文件头,今天来说一说自动更新文件头,比如说每次保存时自动更新last updated字段

自动更新Last Updated

如果使用的是header2,直接设置相关的变量就可,假如使用的是auto-insert,同样也可以使用emacs内置的time-stamp对Last Updated进行自动更新

time-stamp默认使用Time-stamp:,如果要对Last Updated进行自动更新,只需要简单的设置

(setq time-stamp-active t)
(setq time-stamp-line-limit 11)
(setq time-stamp-start "[lL]ast[ -][uU]pdate[ \t]*:?")
(setq time-stamp-end "\n")
(setq time-stamp-format " %#A %Y-%02m-%02d %02H:%02M:%02S (%Z)")

然后添加

(add-hook 'before-save-hook 'time-stamp)

这样就能在每次保存时自动更新相应的字段了

自动更新Filename

之前遇到过,使用auto-insert在每次创建新文件时自动添加了文件头,但后面文件名被修改了,文件头里的文件名却不会自动更改,基于这个原因需要自己实现一个函数(我没有找到可以使用的已经存在的package)

先理一理逻辑: 只需要查找当前文件前几行信息,如果找到File Name:字段,获取字段信息,与当前文件名进行对比,如果不一致则替换为当前文件名,直接给出代码吧

  • 查找当前文件前几行
    (save-excursion
        (goto-char (point-min)) ;;跳转到开头
        (let ((lines 0))
        (while (< lines line-limit)
            ;; 查找
            (setq lines (1+ lines))
            (forward-line 1))))
    
  • 获取当前文件名
    (file-name-nondirectory (buffer-file-name))
    
  • 查找File Name
    (looking-at ".*\\(File Name:\\)\\(.*\\)")
    
  • 对文件名进行比对与替换
    (let ((beg (match-beginning 2))
          (end (match-end 2)))
      (when (not (string= 文件名 (string-trim-left (match-string 2))))
        (goto-char beg)
        (delete-region beg end)
        (insert " " name)))
    

    即可得到相关的完整函数(完整函数后面再讲)

自动更新Email

工作和平时使用的邮箱不一样,我虽然设置了at_home变量区分工作与平时的邮箱,但不是每次我都记得要更新这个变量,所以有了这个需要,自动将文件头里的email信息更改为平时所用的邮箱,大致逻辑与自动更新Filename相同,所以我写了一个macro来自动生成相关的代码

直接给出代码

(defun maple/header-update-action(name)
  "A."
  (let ((beg (match-beginning 2))
        (end (match-end 2)))
    (when (not (string= name (string-trim-left (match-string 2))))
      (goto-char beg)
      (delete-region beg end)
      (insert " " name))))
(defun maple/header-update(regex default line-limit)
  "B."
  (interactive)
  (save-excursion
    (goto-char (point-min))
    (let ((lines 0))
      (while (< lines line-limit)
        (when (and (looking-at regex))
          (maple/header-update-action default))
        (setq lines (1+ lines))
        (forward-line 1)))))
(defmacro maple/header-update-engine (name regex default &optional line-limit)
  "C."
  `(defun ,(intern (format "maple/header-update-%s" name)) ()
     ,(format "Update %s with regex." name)
     (interactive)
     (maple/header-update ,regex ,default ,(or line-limit 7))))

这样,我就可以调用macro来生成代码

  • 自动更新Filename
    (maple/header-update-engine "filename"
                                ".*\\(File Name:\\)\\(.*\\)"
                                (file-name-nondirectory (buffer-file-name)) 7)
    

    生成一个maple/header-update-filename的函数,只要调用它即可更新文件名信息

  • 自动更新email

    同样的

    (maple/header-update-engine "email"
                                ".*\\(Email:\\)\\(.*\\)"
                                "youemail@gmail.com" 7)
    
    生成一个可供调用的maple/header-update-email

如果想要添加其它功能,只要使用maple/header-update-engine即可

相关的配置可以在我的github上找到

There are comments.

  • emacs自动添加文件头


    想要在emacs中添加文件头有好几种方法:

    • 直接手打
    • 使用模板yasnippet
    • 使用header2
    • 使用内置的package auto-insert

    header2可能是最方便的一种自动添加文件头的方式,但我之前使用过,想要自定义自己想要的内容很难,而且白白浪费header2的功能

    今天主要说一说emacs内置里auto-insert,使用它在创建文件时自动添加文件头信息

    基础使用

    直接(auto-insert-mode) 并且设置

    (setq auto-insert-query nil) ;; 不提醒
    

    自定义文件头

    (setq auto-insert-alist
          '(((python-mode . "Python program") nil
             "#!/usr/bin/env python\n"
             "# -*- coding: utf-8 -*-\n"
             "# **************************************************************************\n"
             "# Copyright © " (substring (current-time-string) -4) " " (user-full-name) "\n …
  • lua中匪夷所思的table长度


    s = { 1, 2, 3, 4, 5, 6 }
    print(#s)     -- output: 6
    s[4] = nil
    print(#s)     -- output: 6
    s[7] = nil
    print(#s)     -- output: 3
    s[4] = 4
    print(#s)     -- output: 6
    s[4] = nil
    print(#s)     -- output: 3
    
    print()
    
    s = { "1", "2", "3", "4", "5", "6" }
    print(#s …
  • ansible快速部署加速方案


    ansible是基于Python的 自动化部署 方案,但是目前只是通过命令行

    ansible -i hosts all -a 'uptime'
    # or
    ansible-playbook -i hosts playbook.yml -e 'args' -t deploy
    
    实现自动化部署.

    长此以往,虽然可以实现所谓的自动化,但产品业务线多且杂的情况下,项目很难维护,更不用说以文件为存储的表现形式很差,针对目前使用ansible的经验以及使用中的困难,可以针对性的提出一些解决方案

    加速

    问题

    自动化部署其中最大的障碍就是 网络 的原因

    其中需要通过网络上传一些模板文件,有的甚至还需要上传一些压缩包,虽然说几MB的东西很快就能上传成功,但如果把这上传文件所需要的2秒乘以上百,上千台主机呢,更不用说ansible的表现形式就是一个任务一个任务的往下执行,假如在上传模板这一步卡住 …

  • ansible-playbook中tasks单进程


    之前有一个需求,ansible-playbook中需要某一步单步执行,也就是说在有多台服务器时,某个任务只能一台服务器执行完后,另一台服务器才能执行,否者对应集群的服务会出问题

    这是一个很简单的需求,ansible中也有对应的实现, --fork 1 或者 使用 serial

    但是如果有人忘记加 --fork 1 了呢,而且该任务是在子任务中,使用 include 加载, serial 关键字无法在某一特定任务中使用,只能与 hosts 同级

    所幸,在这里 https://www.bountysource.com/issues/26342862-support-for-serial-on-an-individual-task 找到了解决办法,使用 delegate_to

    - name: service restart
      # serial: 1 would be the proper solution here, but …
  • redis集群搭建


    Table of Contents

    参考资料

    Redis 集群是一个提供在多个Redis间节点间共享数据的程序集

    准备

    集群开始需要运行redis集群实例,而且要让集群正常运作至少需要三个主节点,这里创建六个节点,三个为主节点,三个为从节点,端口号分别为9001,9002,9003,9004,9005,9006

    并创建六个以端口号为名字的目录, 在每个目录中运行一个Redis实例

    mkdir -p redis/9001
    cd redis
    mkdir 9002
    mkdir 9003
    mkdir 9004
    mkdir 9005
    mkdir 9006
    

    然后将对应的配置redis.conf放入相应的目录中(记得修改端口号)

    最小配置选项:

    port 9001 …

  • 手机与Linux桌面文件共享


    手机: 某米 电脑: archlinux 环境: 同一wifi下

    手机共享文件到电脑

    最近才发现手机可以开启ftp服务对文件进行共享,直接进入文件管理器开启就行,电脑上使用

    ftp target
    
    进行连接

    注: get 下载 put 上传

    电脑共享文件到手机

    这里采用python搭建一个简单的web服务(python3)供手机下载文件

    # 首先 cd 到要共享的目录
    python -m http.server --bind 0.0.0.0
    

    查看本机IP

    ifconfig
    # 或者
    ip addr
    

    重要: 请确保关闭防火墙,否则手机无法连接

    sudo systemctl …

  • Linux总结(草稿)


    Linux发展历史

    Linux是由BSD发展而来,BSD又起源于UNIX。UNIX由贝尔实验室开发, 后来开放给各大学教学使用,其中伯克利大学通过对UNIX源码的研究以及不断的改进与扩展, 推出BSD,并于BSD 4.3版本加入网络模块,极大推进UNIX的发展。但后面由于版权等原因, UNIX与BSD之间发生冲突与法律纠纷,直到1998年,在此期间,芬兰大学生Linus Torvalds 于1991年发布首个Linux版本,linux也趁UNIX与BSD纠纷之际,得到非常快速的发展

    Linux的最小组成

    Linux最小由内核kernel,文件层次结构FHS,系统启动器bootloader组成,其中内存调度, 进程调度等由内核管理,内核可单独运行,但需要与其它组成相配合。

    语言:一般有头文件与库文件,头文件为实现,库文件为声明

    Linux的安装与启动

    当linux启动时,首先启动内核,内核调用init来完成引导进程,init启动时,它会在/etc/inittab内查找默认的运行级别, 然后运行/etc/rc …