- Create a new file named
kilo.c
. - Write a
main()
function that takes no arguments and returns0
. - Create a
Makefile
that compileskilo.c
tokilo
when you typemake
.- Use
$(CC)
for the compiler. - Turn on warnings using the
-Wall -Wextra -pedantic
options. - Turn on C99 mode using the
-std=c99
option.
- Use
- In
main()
, Declare achar
variable namedc
. - Include
<unistd.h>
. - Read a single byte from standard input into
c
repeatedly usingread()
, untilread()
returns an error or reaches the end of file. - Stop the
read()
loop as soon asc
contains the character'q'
. - Create an
enableRawMode()
function abovemain()
that takes no arguments and doesn't return anything. - Call
enableRawMode()
at the top ofmain()
. - Include
<termios.h>
. - In
enableRawMode()
, declare astruct termios
variable namedraw
. - Call
tcgetattr()
to load terminal attributes intoraw
. - Turn off the
ECHO
bit in thec_lflag
field ofraw
. - Call
tcsetattr()
to apply the attributes inraw
back to the terminal. (UseTCSAFLUSH
for the second argument.) - Declare a global
struct termios
variable namedorig_termios
, aboveenableRawMode()
. - Change the
tcgetattr()
call to load theorig_termios
variable instead ofraw
. - Move the declaration of
raw
after thetcgetattr()
call, and initialize it to the value oforig_termios
. - Create a
disableRawMode()
function aboveenableRawMode()
that takes no arguments and doesn't return anything. - In
disableRawMode()
, calltcsetattr()
to set the terminal attributes to the original ones saved inorig_termios
. - Include
<stdlib.h>
. - In
enableRawMode()
, aftertcgetattr()
, useatexit()
to registerdisableRawMode()
to be called when the program exits. - Turn off the
ICANON
bit in thec_lflag
field ofraw
. - Include
<ctype.h>
. - Include
<stdio.h>
. - In the
read()
loop inmain()
, useisprint()
to check ifc
is printable. If it is, useprintf()
to print it out as both an ASCII code in decimal, and as a character. If it's not, then just print out its ASCII code. - Turn off the
ISIG
bit in thec_lflag
field ofraw
. - Turn off the
IXON
bit in thec_iflag
field ofraw
. - Turn off the
ICRNL
bit in thec_iflag
field ofraw
. - Turn off the
OPOST
bit in thec_oflag
field ofraw
. - If your
printf()
statements print\n
at the end, change them to print\r\n
instead. - Turn off the
IEXTEN
bit in thec_lflag
field ofraw
. - Turn off the
BRKINT
,INPCK
, andISTRIP
bits in thec_iflag
field ofraw
. - Set the
CS8
bitmask in thec_cflag
field ofraw
. - Set
raw.c_cc[VMIN]
to0
. - Set
raw.c_cc[VTIME]
to1
. - In
main()
, ignore the return value ofread()
. - At the beginning of the loop in
main()
, setc
to the nul character before theread()
call. - Create a
die()
function abovedisableRawMode()
that takes a string nameds
and doesn't return anything. - In
die()
, callperror()
and passs
to it. - At the end of
die()
, callexit()
with a non-zero exit status. - For each of the 3 calls to
tcgetattr()
ortcsetattr()
, check if the return value is-1
, and if so, calldie()
passing it the name of the function that failed (either"tcgetattr"
or"tcsetattr"
). - Check if the
read()
call returns-1
, and if so, calldie()
passing it the name of theread()
function. - We'll split up the file into sections so we can talk about it easier. A
section begins with a comment that looks like
/*** name of section ***/
on its own line. At the top of the file, add an/*** includes ***/
section. - Above the
orig_termios
declaration, add a/*** data ***/
section. - Above the
die()
function, add a/*** terminal ***/
section. - Above the
main()
function, add an/*** init ***/
section. - Above the
/*** data ***/
section, add an/*** defines ***/
section. - In the
/*** defines ***/
section, define a macro namedCTRL_KEY
that takes one argument, and sets all the bits in the given value to0
except for the lowest 5 bits. - Instead of breaking out of the
main()
loop whenc
is equal to'q'
, break out of the loop whenc
is equal toCTRL_KEY('q')
. - Create an
editorReadKey()
function belowenableRawMode()
that takes no arguments and returns achar
. - Move the
c
variable and theread()
call frommain()
into the neweditorReadKey()
function. - Have
editorReadKey()
keep callingread()
untilread()
returns1
, thenreturn
the character that it read. - Above the
/*** init ***/
section, add an/*** input ***/
section. - In the
/*** input ***/
section, create aneditorProcessKeypress()
function that takes no arguments and doesn't return anything. - In
editorProcessKeypress()
, calleditorReadKey()
and store the result in achar
namedc
. - Use a
switch
statement to callexit()
with a0
exit status whenc
is equal toCTRL_KEY('q')
. - In
main()
, replace the loop with an infinite loop that just callseditorProcessKeypress()
repeatedly. - Above the
/*** input ***/
section, add an/*** output ***/
section. - In the
/*** output ***/
section, create aneditorRefreshScreen()
function that takes no arguments and doesn't return anything. - In
editorRefreshScreen()
, usewrite()
to write the escape sequence"\x1b[2J"
to standard output. - At the top of the
main()
loop, calleditorRefreshScreen()
. - At the end of
editorRefreshScreen()
, usewrite()
to write the escape sequence"\x1b[H"
to standard output. - Copy and paste those two
write()
calls to the top of thedie()
function. - Copy and paste those same two
write()
calls to the top of theCTRL_KEY('q')
case of theswitch
statement ineditorProcessKeypress()
. - Above
editorRefreshScreen()
, create aneditorDrawRows()
function that takes no arguments and doesn't return anything. - In
editorDrawRows()
, declare anint
namedy
and have it loop through the values0
to23
inclusive. - For each value of
y
, usewrite()
to write the string"~\r\n"
to standard output. - At the end of
editorRefreshScreen()
, calleditorDrawRows()
. - At the end of
editorRefreshScreen()
, usewrite()
to write the escape sequence"\x1b[H"
to standard output. - At the top of the
/*** data ***/
section, define astruct
type namededitorConfig
, and move theorig_termios
variable into it. - Below the
editorConfig
struct, declare a globalstruct editorConfig
variable namedE
. - In
disableRawMode()
andenableRawMode()
, replace the 3 occurrences oforig_termios
withE.orig_termios
. - Below
editorReadKey()
, create agetWindowSize()
function that takes twoint
pointers namedrows
andcols
as arguments, and returns anint
. - Include
<sys/ioctl.h>
. - In
getWindowSize()
, declare astruct winsize
variable namedws
. - Call
ioctl()
with theTIOCGWINSZ
request to load thews
variable with the window dimensions. - If
ioctl()
returns-1
, or if thews_col
field ofws
is0
, then return-1
to indicate an error occurred. Otherwise, set therows
andcols
references to thews_row
andws_col
fields ofws
, and return0
to indicate success. - At the top of the
editorConfig
struct, add twoint
fields namedscreenrows
andscreencols
. - Above
main()
, create aninitEditor()
function that takes no arguments and doesn't return anything. - In
initEditor()
, callgetWindowSize()
, passing thescreenrows
andscreencols
fields ofE
by reference. If it returns-1
, then calldie()
with the name of thegetWindowSize()
function. - In
main()
, callinitEditor()
after theenableRawMode()
call. - In
editorDrawRows()
, useE.screenrows
as the (exclusive) upper bound fory
, instead of the (inclusive)23
we hardcoded earlier.
Created
March 24, 2017 22:46
-
-
Save paigeruten/88d4d5ed534edd66edcbc529a62e087a to your computer and use it in GitHub Desktop.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment