GNU/Linux实战手记之Emacs篇

Copyright(C)http://my9801.51.net
本文依照GNU Free Document Lience发布,任何人都可以将本文原封不动的复制、转载,但请务必保留此声明。作者不对本文所导致的任何结果负责。

一、Linux下的常用软件--Emacs
  有了上面的基础,你已经可以自由的使用Linux的控制台了。但是,光靠这些,你还不能编辑和修改文件,不能归档和压缩(解压缩)文件,不能享受影音娱乐和多媒体。在控制台下,我们确实可以做很多事情,包括听音乐。下面我们来看看控制台下最强大的应用软件--Emacs
Emacs是Linux下的强大的文本编辑环境,说它是一个单纯的文本编辑器就太小看它了。说出来别被吓到,Emacs可以编辑文件,浏览互联网,访问FTP,收发电子邮件,使用控制台命令,编译和调试程序等等。它简直可以充当一个操作系统了!但是,正是因为它拥有这么多的功能,使得想学习使用它的人必须经过一段痛苦的历程。Emacs实在是太复杂了。
  让我们现来见识以下Emacs的庐山真面目吧。
$emacs newtext.txt    /*启动Emacs,用它来创建一个新文件newtext.txt*/
  如果你是在控制台下开的Emacs,那你可以忽略最上面一行的菜单栏。它在控制台下是没用的。这一点和MS-DOS下的EDIT完全不同。开始的时候我就很不习惯没有Alt-F召唤出的菜单。但是这并不意味Emacs就没有菜单。它有。你按下F10看看(或者Esc-`)。那就是它的菜单。你可以按照它的提示使用。退出菜单用Ctrl-g或者连按三下ESC(这是退出一切Emacs命令的通用方法)。
  我们已经新建了一个文件,你现在可以直接输入文字了。这和普通的文本编辑器没区别。
保存文件的方法是“Ctrl-x Ctrl-s”;文件另存为是“Ctrl-x Ctrl-w”;打开新文件是“Crtl-x Ctrl-f”;退出Emacs是“Ctrl-x Ctrl-c”。还是那句老话——晕头转向了就退出,没什么可怕的。
  在Emacs里有很多向上面的使用组合键的命令。这也是Emacs的复杂之处,需要背的命令太多。记不住了,你可以使用它的菜单。在X下你可以使用鼠标和它的菜单栏(菜单栏这时才有用)。
  Emacs是支持多文本多窗口同时编辑的。因此你可以打开多个文件,然后在不同的“窗口”中切换。——注意,Emacs中用Buffer(缓冲区)表示我们平常概念中的窗口,你就当它是一块内存区域。我们用菜单查看现存的Buffer:Esc-` b
  看到现有的各个Buffer了吗?你可以用提示你的按键切换到那个Buffer中。(Buffer列表有个快捷键:Ctrl-x Ctrl-b)
  Buffer既然可以打开,那么它就能被关闭。当我们嫌开的Buffer太多,或者不再需要某些Buffer时,我们就可以将那个Buffer关掉。
  调出菜单,依次选择File,Close(current buffer)。或者你也可以按下列次序按键:
ESC-` f c
  我说过,Emacs是一个集成的编辑环境,它可以运行Shell,这就是它的伟大之处,也是世界上顶尖黑客喜爱它的缘故。让我们试试。
Alt-x shell
  Emacs就会乖乖的打开一个新Buffer,而你的控制台提示符就在你眼前。还不试试前面学的各种命令。不过用完了要记得exit退出(这里也能用Ctrl-D)。
  至于游戏嘛,我告诉你它在哪儿——tools->game。自己慢慢研究吧,里面可是有五子棋和跳棋的哟。
  Emacs自带一个很详细的帮助系统,在你需要帮助的时候,按Ctrl-h t,就可以调出帮助教程(Tutorial)。里面详细介绍了如何使用Emacs,是Emacs的官方手册。只可惜,是英文的,对我们这些英文不佳的人来说困难了点。
  Emacs就介绍到这里,有关它的更清晰的使用介绍,请参阅IBM DeveloperWorks/Linux里的教程:《生活在Emacs中》找不到就联系我,我给你一份。

实验:就用Emacs修改你的/etc/fstab和/etc/lilo.conf文件。

二、Emacs高级应用
  前面介绍了Emacs,和一些基本的Unix命令。下面我们将开始接触一种脚本语言Bash(Bourne Again Shell)。Bash很像DOS下的批处理语言,但是要比批处理强大许多。掌握了Bash,你就有更多在Unix闯荡的资本;而Bash强大的功能,也足以让你驾驭野性的Linux。本单元学习要求:你至少应了解基本的计算机编程的概念,知道变量、常量、循环、条件判断等编程语言的基本术语。这样不至于我是在对牛弹琴,也不必浪费你的宝贵时间。
  今天我们就要在Emacs环境中,“足不出户”,进行Bash编程的学习,同时还可以听着美妙的音乐。

  先进行些准备工作———如何安装软件。
  对于刚接触Linux的人而言,最令他们头疼的,不是一大堆的命令和参数,而是没有自己所熟悉的软件。再好的系统,没有大量的软件作支撑,也生存不下去(IBM的OS/2就是个典型的例子)。但是现在,GNU/Linux可以使用的软件很丰富,你可以上网搜索,就会找到几大专业的Linux软件搜集下载站点,里面的软件储量很丰富的。
  下载你需要的软件包,按照下面的方法安装软件。
1、编译安装源代码包
  实际上,绝大多数Unix软件都是以源代码形式发布的,这样做的好处就是,用户可以根据自己系统的实际情况对软件进行修改。下面我们来看看如何安装源代码包。
  目标软件:zhcon-0.2.3.tar.gz    Linux Console Chinese System
#mkdir temp             /*建立一个临时目录*/
#cp zhcon-0.2.3.tar.gz temp/    /*将包拷到临时目录中*/
#cd temp
#tar vxzf zhcon-0.2.3.tar.gz    /*解压、归档一步到位,这时将生成一个新的目录*/
#cd zhcon-0.2.3
#./configure            /*配置编译环境*/
#make                /*开始编译*/
#make install            /*安装*/
  至此,zhcon就装好了。最后三步就是安装源代码包的标准操作。执行./configure后安装程序会告诉你程序安装后的所在目录。要卸载该软件,就直接删除该目录即可(别忘了还要删掉/usr/local/bin中的执行命令zhcon)。

2、用RPM安装.rpm包,.src.rpm包
  RPM是Redhat Package Manager,是RedHat公司做的自动化安装工具。我们用它来装一个MPEG播放器:CandyPlayer
#cp candyplayer-0.1.1-1.i386.rpm temp/
#cd temp
#rpm -ivh candyplayer-0.1.1-1.i386.rpm  /*这里是软件包的全名*/
  安装时会显示一个进度条,告诉你安装过程。RPM安装之前会先检测系统的完整性,看是否缺少文件。如果缺少所需的文件,则拒绝安装,屏告知所缺的文件。
  有时候我们会碰到用RPM打包的源代码.src.rpm,这时就需要我们自己编译。安装这样的包只需要改变RPM命令的参数。
#rpm --rebuilddb target.src.rpm    /*假设软件包叫target.src.rpm*/
  要删除已装的软件,只需下面的命令
#rpm -e candyplayer           /*这里是软件的名字*/
  用RPM就这么简单。

3、安装二进制程序
  有些软件商不愿公布源代码,因此它们直接将软件做成一个大的安装文件。下面就来装一个这样的东西。
  MusicMatch Jukebox想必大家不陌生吧?非常优秀的一款音乐播放软件。它出了一个Linux版本,单个二进制安装文件-install-mmjb-1.43.sh。我们来装它。由于它必须在X下安装,我们就假设已经有了窗口环境。打开一个控制台窗口。
#cd /temp
#./install-mmjb-1.43.sh
  接着就开始安装了,和Windows下安装软件的过程类似。须注意一点,这个软件允许普通用户安装,但是不能向/var目录添加链接,只能装在自己的主目录中。

  以上就是Linux系统安装各种软件的方法。下面进入今天的正题。
  先从www.mpg123.de下载mpg123-0.59r.tar.gz和playmp3list.tar.gz这两个软件包。启动Emacs,新建Shell缓冲区,su升变成root,安装上述这两个包,还原成普通用户。安装顺序是先装mpg123-0.59r.tar.gz,再装playmp3list.tar.gz。
  新建一个Bash脚本addmp3
C-x C-f addmp3  /*C-x就是Ctrl-x,同理M-x就是Alt-x或者ESC-x,下同*/
  在新的缓冲区里输入下面的命令
#!/bin/bash
# Add MP3 files to my playlist file ~/playlist.m3u

find ~/music/ -iname *.mp3 >> ~/playlist.m3u
  存盘
C-x C-s
  这样,就有了我们的第一个Bash程序——addmp3。它将搜索存放在你主目录下music文件夹里的所由mp3格式的文件,然后生成播放列表playlist.m3u。
  切回Shell,执行addmp3
$chmod +x addmp3   /*变成可执行文件*/
$./addmp3   /*运行*/
  这样就生成了播放列表。把它放到/usr/local/bin下面,以后你就可以在任何一个目录下运行addmp3了。当你添加了新的mp3文件时,就在那个目录下运行这个程序,它将把新文件追加到播放列表里。
  接下来我们到另一个控制台下去运行playmp3list。
Alt-F2   /*切换至tty2,登录。*/
$playmp3list playlist.m3u
  我为什么不在Emacs下运行playmp3list呢?因为playmp3list程序运行时用到了ncourse库,生成了伪图形界面,在Emacs里效果很难看,所以我就不在Emacs里用它了。何况Linux是多用户多任务的操作系统,你可以在不同的控制台下执行不同的程序,就象多开了几个窗口一样。而且各个控制台互不干扰,所以你完全可以在另一个控制台下执行playmp3list,照听音乐不误。
  用Alt-F1再切回来,继续我们的工作。


三、Bash语法
  在看过上一次的那个简单的shell程序之后,我们来深入研究一下shell强大的程序设计能力。Shell是一种很容易学习的程序设计语言,至少因为它能够在把各个小程序组合成一个大程序之前很容易的对它们分别进行交互式的测试。利用现代Unix操作系统的shell,我们可以编写出相当庞大的结构化程序。在接下来的几小节里,我们将学习:
  ·变量:字符串、数字、环境和参数
  ·条件:shell中的布尔值
  ·程序控制:if、elif、for、while、until、case
  ·函数
  ·注释

  为了确保Bash编程的严谨性和趣味性,我直接引用了WROX出版社的《Linux程序设计》一书第二章的部分内容和例程源代码。我想以学习的名义,我这里的引用应该不算盗版,至少它的源代码是基于GPL的。

1、变量
  在shell里,使用变量之前并不需要事先对他们做出声明。我们可以在任何需要的时候直接创建并使用变量。默认情况下,变量类型为字符串,即使它所保存的是数值。Shell和其他的一些工具会自动识别“数值”型字符串,并按正确的方法对其进行操作。变量名区分大小写,这与Unix系统保持一致。因此变量var和Var以及VAR分别指不同的变量。变量命名原则与Unix文件命名原则相同,但是不允许有空格,更不能和现有系统命令重名。
  在shell里,变量名前面加一个“$”字符,就可以获得它的内容。只要用到变量,我们就必须在它前面加上“$”,除非是对它进行赋值。赋值变量可以直接使用“=”,也可以使用read命令,将用户的输入赋给变量。请看下面的例子:
$string=Hello
$echo $string
Hello
$string="Guten Tag"
$echo $string
Guten Tag
$string=1+2+3
$echo $string
1+2+3
$read string
I love you      /*用户输入,回车结束*/
$echo $string
I love you      /*读取变量内容*/

*注意,如果字符串里包含空格,就必须用引号把它们括起来。还要注意的是等号两边不能有空格。
**我说过,数字也被保存为字符串,因此“string=1+2+3”的结果仍是“1+2+3”,而不是“6”。
***read读取用户输入的字符串,以回车结束。
1.1、引号的用法
  一般情况下,参数之间是用空白字符分隔的,比如一个空格、一个制表符或一个换行符,如果想在一个一个参数里面包含一个或多个这样的空白字符,就必须给参数加上引号。
  引号也有不同。如果你在双引号里包含变量,则会引起“名-值替换”,而在单引号里就不会。我们还可以在“$”号前加上“/”来取消它的特殊含义。
  让我们来看看引号在变量输出中的作用:
#!/bin/sh

myvar="Hi there"

echo $myvar
echo "$myvar"
echo '$myvar'
echo /$myvar

echo Enter some text
read myvar

echo '$myvar' now equals $myvar

exit 0

输出结果是:

Hi there
Hi there
$myvar
$myvar
Enter some text
Hello world
$myvar now equals Hello world

1.2、环境变量
  脚本在执行的时候,某些变量会根据系统环境设定而进行初始化。这些环境变量通常使用大写,以便和用户自定义的变量区分,后者通常使用小写。下面是一些常用到的环境变量:

环境变量                 说明
$HOME         当前用户的登录子目录
$PATH         以冒号分隔的用来分隔搜索命令的子目录清单
$PS1          命令行提示符,通常是“$”字符
$PS2        辅助提示符,用来提示后续输入,通常是“>”字符
$IFS        输入区的分隔符。当shell读取输入数据的时候会把一组字符看做是单词之间的分隔字符,它们通常是空格、制表符和换行符
$0        shell脚本程序的名字
$#        传递到脚本程序的参数个数
$$        该shell脚本程序的进程ID,脚本程序一般会使用它来创建独一无二的临时文件,比如/tmp/tmpfile_$$

1.3、参数变量
  如果你的脚本程序在调用的时候还带有参数,就会产生额外的一些变量。即使你什么参数也没传,上面的“$#”依然存在,只不过值是0罢了。

参数变量      说明
$1,$2...    脚本程序的参数
$*      一个全体参数组成的清单,这是一个单独的变量,各个参数之间用环境变量IFS中的第一个字符分隔开
$@      “$*”的一种变量,它不使用IFS环境变量

下面是使用环境变量和参数变量的一个例子:

#!/bin/sh

salutation="Hello"
echo $salutation
echo "The program $0 is now running"
echo "The second parameter was $2"
echo "The first parameter was $1"
echo "The parameter list was $*"
echo "The user's home directory is $HOME"

echo "Please enter a new greeting"
read salutation

echo $salutation
echo "The script is now complete"

exit 0

输出结果是:

Hello
The program ./try_var is now running
The second parameter was
The first parameter was
The parameter list was
The user's home directory is /home/yea
Please enter a new greeting
Sire
Sire
The script is now complete

2、条件测试
  在实际工作中,大多数脚本程序都会大量使用“[ ]”或“test”命令——即shell的布尔判断命令。注意,“[ ]”和要被检查的条件之间留出空格。因为“[”与“test”实际上是一样的,而“test”命令后面要空格,所以“[”后面自然也得有空格了。有关“test”命令的使用,请参考“test”的手册页。我不在此赘述了。

3、控制结构——if、elif、for、while、until、case
  shell有一系列控制结构,而且它们同样与其他程序设计语言很相似。就某些结构而言(比如case语句),shell提供了更强大的功能。
  为了减小篇幅,并且让大家看起来一目了然,我直接列出各控制结构的语法结构和例程,好在这样写并不会增加理解的难度。
3.1、if语句

if condition
then
 statements
else
 statements
fi

if语句的例子

#!/bin/sh

echo "Is it morning? Please answer yes or no"
read timeofday

if [ "$timeofday" = "yes" ]; then
 echo "Good morning"
else
 echo "Good afternoon"
fi

exit 0

3.2、elif语句

if condition
then
 statements
elif condition
then
 statements
else
 statements
fi

elif语句的例子

#!/bin/sh

echo "Is it morning? Please answer yes or no"
read timeofday

if [ $timeofday = "yes" ]
then
 echo "Good morning"
elif [ $timeofday = "no" ]; then
 echo "Good afternoon"
else
 echo "Sorry, $timeofday not recognized. Enter yes or no"
 exit 1
fi

exit 0

3.3、for语句

for variable in values
do
 statements
done

for语句的例子

#!/bin/sh

for foo in bar fud 43
do
 echo $foo
done

exit 0

3.4、while语句
  假若我们要循环100次,用for的话就得从1一直写到100,这样太累了。它确实没有BASIC里的for方便——FOR I=1 TO 100 STEP 1,但是它有它的优势,这里暂且不谈。
  对于上面的情况,我们可以使用while结构和数值替换结合在一起。while的语法结构是
while condition
do
 statements
done

  看下面的例子
#!/bin/sh

foo=1
while [ "$foo" -le 20 ]
do
 echo "Here we go again"
 foo=$(($foo+1))
done

exit 0

  这里展示了$(command)结构的用法。

3.5、until语句
  until和while很类似,只是把条件测试倒过来了。换句话说,就是循环将反复执行直到条件为真是停止,而不是当条件为真时执行。
  until的语法为
until condition
do
 statements
done

until语句的例子
#!/bin/sh

until who | grep "$1" > /dev/null
do
 sleep 60
done

# Now ring the bell and announce the unexpected user.

echo -e //a
echo "***** $1 has just logged in *****"

exit 0

3.6、case语句
  case结构比我们前面见过的其他语句都稍微复杂些。它的语法如下所示:
case variable in
 patten [| patten] ...) statements;;
 patten [| patten] ...) statements;;
 ...
esac

  其实这种语法结构要比我们一般所见到的case结构简洁(比如C/C++的switch~case结构),它可以将多个选项写在一起(就是[]中的可选部分)。需要注意的是,语句结尾要用两个分号“;;”,而不是一个分号。在statements里即可以是一条语句,又可以是数条语句。下面是数条语句的例子:
#!/bin/sh

echo "Is it morning? Please answer yes or no"
read timeofday

case "$timeofday" in
  yes | y | Yes | YES )
      echo "Good Morning"
      echo "Up bright and early this morning?"
      ;;
  [nN]* ) 
      echo "Good Afternoon"
      ;; 
  * )  
      echo "Sorry, answer not recognised"
      echo "Please answer yes or no"
      exit 1
      ;;
esac

exit 0

4、函数
  shell允许用户定义函数,以包含某些系统命令,形成执行模块。在shell里定义函数很简单,写出它的名字,加上一对空的“()”,在把有关的语句包含在一对花括号“{}”里,如下所示:
function_name(){
  statements
}
  shell脚本的执行顺序是自顶向下,因此所有的函数声明都要出现在他执行之前,否则shell将找不到函数。

5、注释
  shell脚本用“#”符号注释它之后的语句,直至行尾。这有点像C++里的“//”注释符。但是所有的脚本程序,第一行都由“#”开头,并指定执行此脚本的程序。这里是“#”另一种功能。仅此而已。

四、实例——Mini Music Jukebox
  使用上面的基本元素,我们就可以构件Bash脚本了。理论上,Bash脚本同样可以写出大型、复杂的程序。但是,这样肯定不如用C/C++、Java等编译型语言写的执行效率高。我们学习Bash编程的目的也是为了通过构造shell脚本来减小系统管理的负担,提高管理员的工作效率。所以我们的目标不是大型的程序,而是短小精干的小应用。我用Bash写下了下面的东西,用来播放我的音乐库。
#!/bin/bash
# This is very simple Bash script.It just help us enjoy music.
# Copyright (C) 2003, Free Software Library

# filename: play_music
# To run this script, simply type follow command.
# chmod +x play_music
# ./play_music

# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; either version 2 of the License, or (at your
# option) any later version.

# This program is distributed in the hopes that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
# Public License for more details.

# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.
# 675 Mass Ave, Cambridge, MA 02139, USA.

# The first thing to do is to ensure that some global variables that we'll be using
# throughout the script are set up. We set the title and track files and a temporary file.
# We also trap Ctrl-C, so our temporary file is removed if the user interrupts the script.

# First,define some globle variables.
choice=""
menu_choice=""
quit=n

# Second,define some functions.
add_mp3(){
  echo "Add MP3 files from $HOME/music/mp3 to playlist file /"mp3list/"."
  find $HOME/music/mp3/ -iname *.mp3 >> $HOME/music/mp3list
}

add_ogg(){
  echo "Add Ogg files from $HOME/music/ogg to playlist file /"ogglist/"."
  find $HOME/music/ogg/ -iname *.ogg >> $HOME/music/ogglist
}

play_mp3(){
  clear
  echo "Playing MP3 files with mpg123."
  echo "Control key:"
  echo "s=>Stop, p=>Pause, f=>Forward, b=>Backward, q=Quit(Directly)"
  echo "Also"
  echo "Press Ctrl-C for next song, and press Ctrl-C twice within a short while to quit."

  mpg123 -C --list $HOME/music/mp3list
  return
}

play_ogg(){
  clear
  echo "Playing Ogg files with ogg123."
  echo "Control key:"
  echo "Press Ctrl-C for next song, and press Ctrl-C twice within a short while to quit."
  echo

  ogg123 $HOME/music/ogg  # As the ogg123 do not support playlist, we never use the ogglist file.
  return
}

welcome_msg(){
  clear
  echo
  echo "Mini Music Jukwbox--A very simple program written in Bash script."
  echo
  echo "Before using it, you should at least have the following two program on your system:"
  echo "ogg123 - needed for playing Ogg files."
  echo "mpg123 - needed for playing MP3 files."
  echo
  echo "Do you have these software?(y/n):"
  read choice
}

set_menu(){
  clear
  echo "Mini Music Jukwbox."
  echo
  echo "Options :"
  echo
  echo "  1) Add MP3 files to playlist"
  echo "  2) Add Ogg files to playlist"
  echo "  3) Play MP3"
  echo "  4) Play Ogg"
  echo "  q) Quit"
  echo
  echo "Please enter your choice and then press return"
  read menu_choice
}

# Final,the application proper
welcome_msg
if [ "$choice" = "y" ]
then
 while [ "$quit" != "y" ]
 do
  set_menu
  case "$menu_choice" in
   1) add_mp3;;
   2) add_ogg;;
   3) play_mp3;;
   4) play_ogg;;
   q|Q) quit=y;;
   *) echo "Sorry, choice not recognized";;
  esac
 done
else
 exit 0
fi

echo "Thanks for using. Bye! :)"
exit 0

五、定制你的Emacs
  其实,有关Emacs的争论一直没有停息过。有人坚持Emacs是个庞大的史前生物,也有人坚持Emacs是神造的万能工具。总之,一切都是围绕着它的复杂性而论。毋庸置疑的,单作为一个文本编辑器而言,Emacs的确是太庞大了(它足有70多兆!)。但是,如果把Emacs视为一个环境(它也的确是一个环境),则它是非常优秀的,70兆的体积也就不算什么了。作为普通用户,我不推荐你去使用Emacs,vi就可以了--但我不并不是在贬低vi,相反,vi同样是令我们尊敬的一个优秀的编辑器--它将复杂性隐藏在了幕后,通过各种命令实现,而这些命令我们也许永远也用不到,所以我们不必去理睬它,它就是一个小巧、简洁和直观的文本编辑器。但是如果你是一个程序员,或是系统管理员,你所关心的就不会是绚丽的界面,而是强大的功能和工作的效率。而这就是Emacs能带给你的。平心而论,Emacs并不比我们平常所惯用的其他编辑器,如UltraEdit、TextPad、EmEditor等难用多少,只是我们在使用Emacs的时候,要从新适应Emacs定义的快捷键罢了。而正是这一点,给许多浅尝辄止的人眼前蒙上了一层纱,他们也就以讹传讹,大肆宣扬起Emacs的“复杂”来。其实,一旦你熟悉了它的快捷键,你就能像用其它软件一样自如。
  (如果你只是为了写几个字,你会固执的坚持使用Word吗?如果你要写C/C++程序,你会用Word吗?要是我,我宁可用notepad。当我初次接触电脑的时候,我还是在黑底白字的DOS时代。我曾为Turbo C里的IDE环境惊叹不已。那时的剪贴、粘贴的快捷键是Ctrl-Ins、Shift-Ins,删除一行是Ctrl-y,直到现在我还忍不住想用Ctrl-y来删除一行。其实统一软件快捷键的不是MS,而是WordPerfect,正是因为它的流行,使得之后的软件都纷纷效仿它,以增加亲和力。F1代表“帮助”就是它最先使用的。所以不要再抱怨Emacs的快捷键了。Emacs可以在没有图形显示的终端环境下出色的工作,和它在X下一模一样。UltraEdit可以吗?)
  废话少说,言归正传。我们的目的是定制我们的工作环境,使之最适合我们的工作。因此,我们必须首先澄清一些概念。
缓冲区(Buffer)
 缓冲区(Buffer)的概念听起来很玄,其实就是一块用来保存我们输入的东西的内存区域,你可以把它理解为文件。在Emacs里,一切都是在内存中进行,直到你按下C-x C-s来保存,你的文件才会被改变。这是一个普遍的文本保存策略,几乎所有的文本编辑器都是这样工作的。
窗口(Frame)
 窗口(Frame)不是Window,它是指你所编辑的文本被显示的区域。这一点类似于你在UltraEdit里打开的各个文件所在的小窗口。
模式(mode)
 模式(mode)是Emacs里最重要的概念,Emacs的强大功能基本上都是由各种模式提供的。常用的有C/C++模式、shell模式、Perl模式、SGML/HTML模式等等。

  基于上面的概念,让我们来逐步研究Emacs的IDE环境

1、文件,缓冲区和窗口
  首先,我们可以在Emacs里同时编辑多个文件。你随时可以使用C-x C-f来打开(或者创建)文件。但是默认情况是,编辑器自动进入到新的文件窗口中(所有的编辑器都这样)。如果我们希望同时看到两个文件(比如比对两个文件),我们就必须首先对窗口进行分割。使用C-x 2对窗口进行水平分割。分割完毕后你会失望的发现,两个窗口里的内容竟然完全一样(包括你对任一窗口的修改,都会同步显示在另一个窗口中)!是的,我们只是分割了窗口,但是并没有切换缓冲区,因此依旧是显示原来缓冲区的内容。使用C-x o切换到你想去的窗口,然后在缓冲区列表(C-x C-b)里选择目标文件。这样你就可以在同一屏终审视两个文件了。
  你也可以用C-x 3垂直分割屏幕,分成左右两个区域。窗口理论上可以无限分割,只要你觉得分那么多的小窗口有意义(试试看,连Emacs都会觉得你这样做很愚蠢),因此你完全可以将屏幕分割成倒“品”字形,只需依次按下C-x 2、C-x 3即可。
  窗口和缓冲区的概念是完全不同的,因此我们可以“关闭”窗口,而非“关闭”缓冲区,让它暂时从我们的视线里消失。这相当于图形环境下的“最小化窗口”。使用C-x 0关闭当前窗口,使用C-x 1关闭当前窗口以外的其他窗口。

  下面的这个列表很直观的显示了对窗口和缓冲区的键盘操作:
--------------------------------------------------------------------------------------------------------
窗口操作:

功能键     功能
C-x 0     删除当前窗口,对缓冲区无影响。注意这里是数字0。  (最小化当前窗口)
C-x 1     删除当前以外的所有窗口,对缓冲区无影响。     (最小化其他窗口)
C-x 2     水平分割当前窗口。
C-x 3     垂直分割当前窗口。
C-x o     切换窗口(当且仅当有一个以上的窗口存在)。注意这里是字母o。

缓冲区操作:

功能键     功能
C-x C-f    打开(创建)文件,创建一个新的缓冲区。
C-x C-s    保存当前缓冲区到文件。
C-x C-w    保存当前缓冲区到其他文件(文件另存为)。
C-x k     关闭当前缓冲区。
C-x C-b    缓冲区列表。你可以用方向键来选择要切换的缓冲区。
C-x C-c    关闭所有的缓冲区,退出Emacs。

--------------------------------------------------------------------------------------------------------

2、模式
  接下来我们看看Emacs里的模式(Mode)。
  在Emacs里,无论何时编辑一个文件,都要使用一个特定的模式(Mode)。Emacs里的“模式”不同于vi里的“模式”。vi里分“命令”和“编辑”两种模式,而Emacs里只有一种模式,就是编辑模式,Emacs里的命令全靠功能键完成。但是我说的“模式”不是指这个模式,而是指Emacs里的各种辅助环境。当我们编辑普通文本时,用的是“文本模式(Txt Mode)”,而当我们写程序时,比如前面的Bash脚本,用的则是“Shell(bash)模式”。
  当我们启动某一文件时,Emacs会判断文件的类型,从而自动选择相应的模式。当然,我们也可以手动启动各种模式。先按M-x,然后输入模式的名称。比如启动“C模式”,就是M-x c-mode。直接按下M-x,然后按两下Tab键,你将得到所有可执行的命令,这里面当然包括所有的模式。因此,你要想不起来某个命令的名称,就用这个方法。

2.1、C模式
  在强大的C模式下,我们拥有“自动缩进”、“注释”、“预处理扩展”、“自动状态”等强大功能。
  当我们在“C模式”下编辑代码的时候,可以用Tab键自动的将当前行的代码产生适当的缩进,使代码结构清晰、美观。我们也可以指定缩进的规则。Emacs支持的缩进规则有:bsd、cc-mode、ellemtel、gnu、java、k&r、linux、python、stroustrup、user、whitesmith,通过M-x c-set-style命令指定。
  源代码要有良好可读性,必须要有良好的注释。用M-;可以产生一条右缩进的注释。C模式下是“/* comments */”形式的注释,C++模式下是“// comments”形式的注释。当我们高亮选定某段文本,然后按C-c C-c,就可以把这段文字给注释掉。
  Emacs可以使用C预处理其运行代码的一部分,以便让程序员检测宏、条件编译以及include语句的效果。比如想象下面的这种情况:
  1、在顶层窗口输入看到的代码。
  2、高亮显示一个区域。
  3、按C-c C-e调用宏扩展。也可以从菜单C中选择 Macro Expand Region。
  Emacs将创间谍热窗口,显示宏扩展的结果。
  Emacs中的C环境还有许多特性,可以帮助程序员加速开发过程。运行在自动状态下的时候,且程序员输入代码的时候,C环境会自动地插入新行、处理缩进并完成其他相关任务。在许多情况下,编程时都不用按Enter键,系统会自动处理。
  按C-c C-a或者运行M-x c-toggle-auto-stat,就可以开启自动模式。在这种模式下敲击键盘时,程序员会注意到无论何时,只要输入分号,编辑器就会自动把光标定位到下一行,并自动缩进。最终代码看起来好像没有使用自动模式一样;它只是减少了程序员创建文件敲击键盘的次数。
  如果想要关闭自动模式,只需要按C-c C-a或者运行M-x c-toggle-auto-state,系统将恢复一般状态。

2.2、编译程序
  Emacs可以让程序员在Emacs环境里编译自己的软件。这样做的时候,编辑器把编译器的输出和程序代码连接起来。这意味着程序员只需要单击出错的命令(按个回车),就可以立刻定位那些警告和错误信息。
  可以在Tools菜单里找到这些选项。在从菜单中选择Compile时,Emacs要求输入编译命令。如果有一个Make文件,可以接受默认设置。否则,程序员必须为正确编译程序而填写编译命令行。
  如果在编译时遇到错误或警告,Emacs将在分开的窗口中显示它们。
  此时用Enter单击错误信息,就可以直接跳到发生错误的源代码处。有时,在输出窗口重将有几百条警告信息;直接跳到出错的地方,可大量的节省时间。
  正如你看到的,默认的编辑命令是对一个make的调用。Emacs可以完美使用make并处理大量文件,对Emacs是否能支持大的工程项目的担心,是完全没有必要的。

2.3、调试
  许多集成的开发环境提供一个调试器。虽然多数只是一个有限的调试器,但是Emacs为gdb调试器提供了一个功能齐全的借口。
  在Emacs中使用gdb的时候,程序员能获得gdb在其他任何方式运行时所具有的全部标准特性。但是还是包括了一些通过接口增强而获得的其他性能。
  在Emacs中使用gdb调试程序,可以观察自己的代码是如何从头到尾运行的。这个选项比默认的gdb操作更容易使用,默认的操作只是显示的指令。
  此外,由于可以直接在Emacs中重新编译调试器运行在缓冲器内的代码,在调试器内对代码进行改动、重新编译和运行是简单的方法。
  为了在Emacs里调用调试器,在Tools菜单中选择gdb,会出现系统提示,要求输入可运行文件以便进行调试。当输入了名字时,gdb被调用。最初将看到一个和标准gdb一样的窗口。在程序的适当地方设置断点后运行程序,源代码窗口将会有=>标记指向断点位置的代码并高亮显示。gdb窗口将不再显示代码。
  在gdb窗口中,可以使用所有的常用gdb命令。在Emacs中使用gdb,程序员必须要学习任何新的命令。
10.2.3、使用标记
  Emacs的另外一个强大的功能是使用标记(tag)的能力。根据标记,编辑器可以区分哪些文件属于同一个项目。更重要的是,标记还能准确指出每个文件都包含了什么。比如在C程序中,标记指出那个文件包含了特定的函数。当编译文件的时候,可以直接跳到任何函数所在——而不管文件的路径。此外,可以对一组文件而不仅仅对当前文件使用命令。比如,一个搜索命令可以对一组文件起作用。
  为了提供这个功能,Emacs需要分析文件,并且保存将要被使用到的标记信息。一般而言,实现这种功能要使用一个叫TAGS的文件。在命令行中运行etags程序创建这个文件,并且给它需要索引的文件名字。例如:
  $etags *.c
  etags程序分析源代码,并产生一个TAGS文件,便于以后在Emacs中使用。
  现在,可以在Tools菜单中使用Tags选项,对文件进行操作。可以使用Find Tag(M-.)来看看到底发生了些什么。比如,输入一个函数的名字,Emacs将直接跳到包含该函数的文件,如果需要则带开该文件,并且定位光标于该函数的第一行;如果该函数在一个以上的文件中出现,就可以使用M-,继续搜索其他的文件。
3、在Emacs里用Shell
  Emacs独一无二的地方就在于它可以在内部运行shell。Emacs里的Shell与普通的Shell没有区别,我们编写的shell脚本可以直接运行测试,而不必退出Emacs。但是,在Emacs的shell环境下,不能运行某些需要对控制台进行控制的程序,比如mc。这是我们可以用term模式代替,只需运行M-x term-mode命令。
  我们已经在前面体验过Emacs里的shell了,我就不再重复了。
4、其他,但不是鸡肋
  Emacs集成了万维网浏览器、邮件阅读器、ftp、telnet、新闻组阅读器、版本控制系统等等。实在是太多了,我在这里肯定无法一一谈到。学习Emacs的最好方法就是“看书+实践”,我就是这么学习Emacs的。多多摸索,你也可以成为Emacs高手。征服Emacs并不是“不可完成的使命”。
5、累了,玩玩游戏吧
  F10->Tools->Games,尽情娱乐吧,我们的宗旨是——劳逸结合。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值