pulse

package module
v0.0.0-...-ef927d8 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 17, 2024 License: MIT Imports: 6 Imported by: 0

README

pulse: like a fitness tracker for code

Go Reference Go Report Card Test codecov

I use this project to derive metadata from my coding sessions. Some of it can be viewed on my website:

Screenshot of website

Screenshot of website

The project includes a server that operates in the background as a daemon. It receives remote procedure calls from neovim pertaining to events such as the opening of buffers, windows gaining focus, the initiation of new neovim instances, etc:

https://github.com/creativecreature/code-harvest/assets/12787673/3732845c-694a-4951-9f4e-e0f6003a1e2f

As you can see in the video above, each instance of neovim establishes a new coding session. This leads to the creation of several sessions per day. Every session is stored temporarily on the file system. This is primarily to avoid surpassing any limits set by free database tiers. There is a CLI which can be used to subsequently cluster these sessions by day, week, month, and year. The results are then written to a more permanent storage:

https://github.com/creativecreature/code-harvest/assets/12787673/7a94c640-c230-4e20-aa28-b20ea016c72a

The neovim plugin that I've created for sending the remote procedure calls can be found here

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type AggregatedFile

type AggregatedFile struct {
	Name       string `bson:"name"`
	Path       string `bson:"path"`
	Filetype   string `bson:"filetype"`
	DurationMs int64  `bson:"duration_ms"`
}

AggregatedFile represents a file that has been aggregated for a given time period (day, week, month, year).

type AggregatedFiles

type AggregatedFiles []AggregatedFile

AggregatedFiles represents a slice of files that has been aggregated for a given time period (day, week, month, year).

type AggregatedSession

type AggregatedSession struct {
	ID           string       `bson:"_id,omitempty"`
	Period       Period       `bson:"period"`
	Date         int64        `bson:"date"`
	DateString   string       `bson:"date_string"`
	TotalTimeMs  int64        `bson:"total_time_ms"`
	Repositories Repositories `bson:"repositories"`
}

AggregatedSession represents a session that has been aggregated for a given time period (day, week, month, year).

type AggregatedSessions

type AggregatedSessions []AggregatedSession

func (AggregatedSessions) MergeByDay

func (s AggregatedSessions) MergeByDay() AggregatedSessions

MergeByDay merges sessions that occurred the same day.

func (AggregatedSessions) MergeByMonth

func (s AggregatedSessions) MergeByMonth() AggregatedSessions

MergeByWeek merges sessions that occurred the same month.

func (AggregatedSessions) MergeByWeek

func (s AggregatedSessions) MergeByWeek() AggregatedSessions

MergeByWeek merges sessions that occurred the same week.

func (AggregatedSessions) MergeByYear

func (s AggregatedSessions) MergeByYear() AggregatedSessions

MergeByYear merges sessions that occurred the same year.

type Buffer

type Buffer struct {
	OpenedClosed []int64
	Filename     string
	Repository   string
	Filepath     string
	Filetype     string
}

Buffer represents a buffer that has been opened during an active coding session.

func NewBuffer

func NewBuffer(filename, repo, filetype, filepath string, openedAt int64) Buffer

NewBuffer creates a new buffer.

func (*Buffer) Close

func (b *Buffer) Close(time int64)

Close should be called when a buffer is closed.

func (*Buffer) Duration

func (b *Buffer) Duration() int64

Duration returns the total duration that the buffer has been open.

func (*Buffer) IsOpen

func (b *Buffer) IsOpen() bool

IsOpen returns true if the given buffer is currently open.

func (*Buffer) LastOpened

func (b *Buffer) LastOpened() int64

LastOpened returns the last time the buffer was opened.

func (*Buffer) Open

func (b *Buffer) Open(time int64)

Open should be called when a buffer is opened.

type Clock

type Clock interface {
	Now() time.Time
	NewTicker(d time.Duration) (<-chan time.Time, func())
	NewTimer(d time.Duration) (<-chan time.Time, func() bool)
	GetTime() int64
}

Clock is a simple abstraction to allow for time based assertions in tests.

type CodingSession

type CodingSession struct {
	EditorID  string
	StartedAt int64
	OS        string
	Editor    string
	// contains filtered or unexported fields
}

CodingSession represents an ongoing coding session.

func StartSession

func StartSession(editorID string, startedAt int64, os, editor string) *CodingSession

StartSession creates a new coding session.

func (*CodingSession) Active

func (s *CodingSession) Active() bool

Active returns true if the coding session is considered active.

func (*CodingSession) Duration

func (s *CodingSession) Duration() int64

Duration returns the total duration of the coding session.

func (*CodingSession) End

func (s *CodingSession) End(endedAt int64) Session

End ends the active coding sessions. It sets the total duration in milliseconds, and turns the stack of buffers into a slice of files.

func (*CodingSession) HasBuffers

func (s *CodingSession) HasBuffers() bool

HasBuffers returns true if the coding session has opened any file backed buffers.

func (*CodingSession) Pause

func (s *CodingSession) Pause(time int64)

Pause should be called when another editor process gains focus.

func (*CodingSession) PauseTime

func (s *CodingSession) PauseTime() int64

PauseTime is used to determine which coding session to resume.

func (*CodingSession) PushBuffer

func (s *CodingSession) PushBuffer(buffer Buffer)

PushBuffer pushes a new buffer to the current sessions buffer stack.

func (*CodingSession) Resume

func (s *CodingSession) Resume(time int64)

Resume should be called when the editor regains focus.

type Event

type Event struct {
	EditorID string
	Path     string
	Editor   string
	OS       string
}

Event represents the events we receive from the editor.

type File

type File struct {
	Name       string `json:"name"`
	Path       string `json:"path"`
	Repository string `json:"repository"`
	Filetype   string `json:"filetype"`
	DurationMs int64  `json:"duration_ms"`
}

File represents a file that has been opened during a coding session.

type Files

type Files []File

Files represents a list of files.

type GitFile

type GitFile struct {
	Name       string
	Filetype   string
	Repository string
	Path       string
}

GitFile represents a file within a git repository.

type Period

type Period int8

Period represents the time period for which the coding sessions have been aggregated.

const (
	Day Period = iota
	Week
	Month
	Year
)

type PermanentStorage

type PermanentStorage interface {
	Write(s []AggregatedSession) error
	Aggregate(timeperiod Period) error
}

PermanentStorage is an abstraction for a storage that allows you to store sessions permanently.

type RealClock

type RealClock struct{}

func NewClock

func NewClock() *RealClock

func (*RealClock) GetTime

func (c *RealClock) GetTime() int64

func (*RealClock) NewTicker

func (c *RealClock) NewTicker(d time.Duration) (<-chan time.Time, func())

func (*RealClock) NewTimer

func (c *RealClock) NewTimer(d time.Duration) (<-chan time.Time, func() bool)

func (*RealClock) Now

func (c *RealClock) Now() time.Time

type Repositories

type Repositories []Repository

Repositories represents a list of git repositories.

type Repository

type Repository struct {
	Name       string          `bson:"name"`
	Files      AggregatedFiles `bson:"files"`
	DurationMs int64           `bson:"duration_ms"`
}

Repository represents a git repository. A coding session might open files across any number of repos. The files of the coding session are later grouped by repository.

type Session

type Session struct {
	StartedAt  int64  `json:"started_at"`
	EndedAt    int64  `json:"ended_at"`
	DurationMs int64  `json:"duration_ms"`
	OS         string `json:"os"`
	Editor     string `json:"editor"`
	Files      Files  `json:"files"`
}

Session is the raw representation of a past coding session. These sessions are stored temporarily on disk, and are later aggregated and and moved to a database.

func (Session) Serialize

func (s Session) Serialize() ([]byte, error)

Serialize serializes the session to a JSON byte slice.

func (Session) TotalFileDuration

func (s Session) TotalFileDuration() int64

TotalFileDuration calculates the total duration of all files in the session.

type Sessions

type Sessions []Session

Sessions is a slice of several Session structs.

func (Sessions) Aggregate

func (s Sessions) Aggregate() []AggregatedSession

Aggregate takes a list of locally stored sessions and aggregates them by day.

func (Sessions) Len

func (s Sessions) Len() int

func (Sessions) Less

func (s Sessions) Less(i, j int) bool

func (Sessions) Swap

func (s Sessions) Swap(i, j int)

type TemporaryStorage

type TemporaryStorage interface {
	Write(Session) error
	Read() (Sessions, error)
	Clean() error
}

TemporaryStorage is an abstraction for a storage that can be used to store the session data temporarily. Every editor instance is going to have its own session. Therefore, it's common to have several sessions for any given day. To not exceed any database free tier limits, the sessions are first stored temporarily, and can then be aggregated to a permanent storage once a day.

type TestClock

type TestClock struct {
	// contains filtered or unexported fields
}

func NewTestClock

func NewTestClock(time time.Time) *TestClock

func (*TestClock) Add

func (c *TestClock) Add(d time.Duration)

func (*TestClock) GetTime

func (c *TestClock) GetTime() int64

func (*TestClock) NewTicker

func (c *TestClock) NewTicker(d time.Duration) (<-chan time.Time, func())

func (*TestClock) NewTimer

func (c *TestClock) NewTimer(d time.Duration) (<-chan time.Time, func() bool)

func (*TestClock) Now

func (c *TestClock) Now() time.Time

func (*TestClock) Set

func (c *TestClock) Set(t time.Time)

Directories

Path Synopsis
Package client is used to send remote procedure calls to the server.
Package client is used to send remote procedure calls to the server.
cmd

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL