Skip to content

Instantly share code, notes, and snippets.

@lestrrat
Created March 4, 2015 00:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lestrrat/1b5d0c659ce261688d51 to your computer and use it in GitHub Desktop.
Save lestrrat/1b5d0c659ce261688d51 to your computer and use it in GitHub Desktop.
Ideas on new peco architecture

NEW peco architecture

Pipeline

  1. InputReader - Reads from os.Stdin or file
  2. RawListBuffer - Buffers output from InputReader
  3. QueryFilter - Receive stream of Line objects, and filters according to user query
  4. FilteredLineBuffer - Buffers output from QueryFilter
  5. PagedLineBuffer - Type of FilteredLineBuffer, but creates a "paged" view of the filtered buffer, so it can be displayed to the terminal

InputReader

InputReader reads from a io.Reader.

ir := InputReader{}
ir.Loop()

InputReader provides channels to work with it.

ch = ir.ReadyCh()
ch = ir.CancelCh()
ch = ir.OutputCh()
name description
ReadyCh There's something coming in from the source Reader. This is needed to handle piped chain of commands in the CLI
CancelCh Close this channel to cancel the pipeline. Except for in case of an error, InputReader does not close it. The caller needs to close it
OutputCh This is where you receive the actual input data

RawListBuffer

RawListBuffer is where the input from InputReader is buffered to. This data needs to be buffered because peco expects the user to type and retype queries to filter this data. It needs to be re-fetchable.

Users interact against this buffer.

<-ir.ReadyCh() // input is coming in!
// do terminal configuration, etc

// RawListBuffer needs access to InputReader
rlb := &RawListBuffer{src: ir}

QueryFilter

QueryFilters are what does the most interesting stuff (previously called Matcher)

rf := RegexpFilter{} // IgnoreCaseFilter, SmartCaseFilter, etc.
go rf.Filter(rlb.PipelineChannels())

FilteredLineBuffer

FilteredLineBuffer stores the result of the QueryFilters. Buffering is required because we will be paging these results

flb := &FilteredListBuffer{src: rf}

FilteredLineBuffer knows the indices to the original RawLineBuffer. For example, suppose the RawLineBuffer looks like this:

1. Foo
2. Bar
3. Baz

And you filtered it so that in your FilteredLineBuffer you have

2. Bar
3. Baz

When you select index 0 on the FilteredLineBuffer, it knows that it's actually index 1 in the RawLineBuffer

PagedLineBuffer

PagedLineBuffer a special type of FilteredLineBuffer. It's created from RawLineBuffer or FilteredLineBuffer to extract a particular page within the buffer.

plb := rlb.AsPagedBuffer(
    1,  // page
    10, // perPage
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment