playground:plan9_tutorial_sam
Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
playground:plan9_tutorial_sam [2021/04/19 21:30] – adding a toy example for regex dsp | playground:plan9_tutorial_sam [2021/04/20 04:59] (current) – adding external command section dsp | ||
---|---|---|---|
Line 1: | Line 1: | ||
+ | ==== An SDF sam tutorial ==== | ||
+ | ===Basic Editing=== | ||
+ | When you run sam newfile you only see the command window (blue area) on top | ||
+ | but the actual file contents window has not opened. | ||
+ | Right click on the white area and you will see the filename listed. | ||
+ | Selecting it and noticing that the cursor changed you can then click and the contents | ||
+ | will appear. If the file didn't exist there will be no contents. | ||
+ | After that you can start typing on the text edit window. With your mouse | ||
+ | you can either select the text edit window or the command window using | ||
+ | the left mouse button. In the following document commands will appear in bold font. | ||
+ | The most basic commands to interact with the editor are **q** to quit, | ||
+ | **w [filename]** to write the file to disk and **u [times]** to undo. | ||
+ | If we have currently selected a filename and issue the **w** command sam will | ||
+ | tell us the total amount of characters it wrote. It also might warn us | ||
+ | if the file does not end with a newline. | ||
+ | By issuing the **n** command we see the file menu list. | ||
+ | when the text window has changes of a file | ||
+ | that haven' | ||
+ | in the menu list starts with the ' character. | ||
+ | |||
+ | To quote //The text editor sam// paper by Rob Pike a file consists of | ||
+ | |||
+ | * it's contents, which are an array of characters | ||
+ | * the name of the associated disk file | ||
+ | * the modified bit that states whether the contents match those of the disk file | ||
+ | * a substring of the contents called the " | ||
+ | * the value of dot is the location of the current text | ||
+ | * the contents of dot are the character it contains | ||
+ | |||
+ | Since edit operations apply on selections we must learn ways to control the value of dot. | ||
+ | The easiest way is to highlight some text. This action sets dot to that range. | ||
+ | By the command **p** we print the contents of dot and by the command **=** we see the range | ||
+ | on the file it maps to. | ||
+ | By issuing ranges on the editor we will see the text they specify getting highlighted. | ||
+ | Some example ranges would be | ||
+ | |||
+ | ^Range | ||
+ | |0,$ |from line zero till the end of the file which can also be expressed as ,| | ||
+ | |3 |the third line| | ||
+ | |# | ||
+ | |2,#100 |line 2 till character 100| | ||
+ | |||
+ | To operate on text in or around dot we can use commands like append, change, insert etc. | ||
+ | For example to delete the text in dot we just press **d** , and to insert sometext before dot | ||
+ | we would issue **i/ | ||
+ | address moves the text in dot after that address. **t** followed by an address just copies | ||
+ | the text to that address without deleting from the original location. | ||
+ | |||
+ | === Editing more than one file === | ||
+ | By right clicking and selecting new we can create a new text editing window to work | ||
+ | on another file. If we have more than one files open we notice that in the file menu | ||
+ | list we see more lines. The file we are currently working on is marked by a . | ||
+ | symbol. | ||
+ | By issuing the **b** command we can set our current file to other files. For example if we have | ||
+ | 2 files open, named file1 and file2 and we issue b file2 and then n we see that | ||
+ | file2 will be selected. If we try to open a completely new file that isn't in the | ||
+ | file menu list, the **b** command will fail. That is why the **B** command exists which | ||
+ | can be used to create a new entry. Note that if the file didn't exist in the disk | ||
+ | a write still needs to happen for it's data to be persisted. | ||
+ | Other basic file menu commands are **D** (to delete an entry) **f** (to rename a file entry) | ||
+ | **e** (to replace current with file) and **r** (replace dot by the contents of file). Here we | ||
+ | notice that if we rename an entry that doesn' | ||
+ | issue **w** on the renamed entry it will create a new file on disk. | ||
+ | |||
+ | === Examples for sam regex === | ||
+ | The benefit of sam is that it allows for regex tasks to be chained and also debugged | ||
+ | easily from within the editor. We will consider a toy example to indent properly some | ||
+ | code of the form | ||
+ | < | ||
+ | if foo { | ||
+ | bar | ||
+ | } | ||
+ | </ | ||
+ | We would like bar to be indented at 8 spaces in, one more level than //if// is. | ||
+ | We can start with a regex to detect the opening brace | ||
+ | < | ||
+ | should detect, in the whole file (,) these braces. | ||
+ | Now we can match backwards to find the prepending white space in that line we matched | ||
+ | by just chaining the next regex. | ||
+ | < | ||
+ | now that matches the white space before. | ||
+ | We would like to add at least as much white space to the line below and | ||
+ | then some (4 spaces for example). | ||
+ | But for that to work the line below must be free of leading white space. | ||
+ | Therefore we will remove it from any line that is below an opening brace. The search is | ||
+ | < | ||
+ | and to remove the white space between the start of line and the first character we chain it like | ||
+ | < | ||
+ | The final form of our regex chain is | ||
+ | < | ||
+ | , x/{\n[ ]*/ s/^[ ]*/ / | ||
+ | , x/{$/ -/^[ ]*/ t .+0 | ||
+ | </ | ||
+ | |||
+ | === Interacting with external commands === | ||
+ | Of course creating a indentation program with just regexp would be duplication of work. | ||
+ | For most languages pretty printers exist like gofmt and cb (C beautifier) let' try | ||
+ | to run cb on some ugly-fied C. | ||
+ | < | ||
+ | if (foo < | ||
+ | do(bxm,as); | ||
+ | wrong; | ||
+ | } | ||
+ | </ | ||
+ | To pass all this code through cb we can just select it and then | ||
+ | issue the command |cb . that would replace the dot by | ||
+ | < | ||
+ | if (foo < | ||
+ | do(bxm, | ||
+ | wrong; | ||
+ | } | ||
+ | </ | ||
+ | similarly we can read input from a command | ||
+ | using < and write to a command using > if we want to count all the | ||
+ | characters in a selection for example we can highlight it and issue >wc | ||
+ | , observe that this doesn' | ||
+ | |||
+ | We could also imagine a command where it replaces every | ||
+ | occurrence of //{DATE}// with the current system date in the whole document | ||
+ | < | ||
+ | , x/{DATE}/ <date | ||
+ | </ | ||
+ | would find any occurrence of the string //{DATE}// and then replace that | ||
+ | dot with the output of the date command. | ||
+ | |||
+ | === Self guided discoveries === | ||
+ | * create two files (file1 and file2) add text to both, use **n** and **b** to control which file has the focus. | ||
+ | * on file2 for example issue continuously< | ||
+ | r file2 | ||
+ | 0 | ||
+ | </ | ||
+ | * can you specify a reverse range like #10,#5 ? | ||
+ | * highlight a word. then issue **m+0**. why is this happening? what is **t+0** doing? what if you keep issuing **t+0**? | ||
+ | * Improve the toy indent example by | ||
+ | * making lines align when no opening brace is detected in the end of line | ||
+ | * remove 4 leading spaces if the line has a closing brace | ||
+ | |||
+ | === Documentation and more === | ||
+ | |||
+ | *[[http:// | ||
+ | *[[http:// | ||
+ | *[[http:// | ||
+ | *[[http:// | ||
+ | *[[https:// | ||
+ | *[[https:// |