//: The goal of layers is to make programs more easy to understand and more //: malleable, easy to rewrite in radical ways without accidentally breaking //: some corner case. Tests further both goals. They help understandability by //: letting one make small changes and get feedback. What if I wrote this line //: like so? What if I removed this function call, is it really necessary? //: Just try it, see if the tests pass. Want to explore rewriting this bit in //: this way? Tests put many refactorings on a firmer footing. //: //: But the usual way we write tests seems incomplete. Refactorings tend to //: work in the small, but don't help with changes to function boundaries. If //: you want to extract a new function you have to manually test-drive it to //: create tests for it. If you want to inline a function its tests are no //: longer valid. In both cases you end up having to reorganize code as well as //: tests, an error-prone activity. //: //: In response, this layer introduces the notion of domain-driven *white-box* //: testing. We focus on the domain of inputs the whole program needs to //: handle rather than the correctness of individual functions. All white-box //: tests invoke the program in a single way: by calling run() with some //: input. As the program operates on the input, it traces out a list of //: _facts_ deduced about the domain: //: trace("label") << "fact 1: " << val; //: //: Tests can now check for these facts in the trace: //: CHECK_TRACE_CONTENTS("label", "fact 1: 34\n" //: "fact 2: 35\n"); //: //: Since we never call anything but the run() function directly, we never have //: to rewrite the tests when we reorganize the internals of the program. We //: just have to make sure our rewrite deduces the same facts about the domain, //: and that's something we're going to have to do anyway. //: //: To avoid the combinatorial explosion of integration tests, each layer //: mainly logs facts to the trace with a common *label*. All tests in a layer //: tend to check facts with this label. Validating the facts logged with a //: specific label is like calling functions of that layer directly. //: //: To build robust tests, trace facts about your domain rather than details of //: how you computed them. //: //: More details: http://akkartik.name/blog/tracing-tests //: //: --- //: //: Between layers and domain-driven testing, programming starts to look like a //: fundamentally different activity. Instead of focusing on a) superficial, //: b) local rules on c) code [like say http://blog.bbv.ch/2013/06/05/clean-code-cheat-sheet], //: we allow programmers to engage with the a) deep, b) global structure of //: the c) domain. If you can systematically track discontinuities in the //: domain, you don't care if the code used gotos as long as it passed all //: tests. If tests become more robust to run, it becomes easier to try out //: radically different implementations for the same program. If code is //: super-easy to rewrite, it becomes less important what indentation style it //: uses, or that the objects are appropriately encapsulated, or that the //: functions are referentially transparent. //: //: Instead of plumbing, programming becomes building and gradually refining a //: map of the environment the program must operate under. Whether a program //: is 'correct' at a given point in time is a red herring; what matters is //: avoiding regression by monotonically nailing down the more 'eventful' //: parts of the terrain. It helps readers new and old, and rewards curiosity, //: to organize large programs in self-similar hierarchies of example tests //: colocated with the code that makes them work. //: //: "Programming properly should be regarded as an activity by which //: programmers form a mental model, rather than as production of a program." //: -- Peter Naur (http://akkartik.name/naur.pdf) //:: == Core data structures :(before "End Globals") trace_stream* Trace_stream = NULL; :(before "End Types") struct trace_stream { vector past_lines; // End trace_stream Fields trace_stream() { // End trace_stream Constructor } ~trace_stream() { // End trace_stream Destructor } // End trace_stream Methods }; //:: == Adding to the trace //: Top-level method is trace() which can be used like an ostrea
package commands

import (
	"os/exec"
	"time"

	"git.sr.ht/~sircmpwn/aerc2/widgets"

	"github.com/gdamore/tcell"
	"github.com/riywo/loginshell"
)

func init() {
	register("term", Term)
}

func Term(aerc *widgets.Aerc, args []string) error {
	if len(args) == 1 {
		shell, err := loginshell.Shell()
		if err != nil {
			return err
		}
		args = append(args, shell)
	}
	term, err := widgets.NewTerminal(exec.Command(args[1], args[2:]...))
	if err != nil {
		return err
	}
	tab := aerc.NewTab(term, args[1])
	term.OnTitle = func(title string) {
		if title == "" {
			title = args[1]
		}
		tab.Name = title
		tab.Content.Invalidate()
	}
	term.OnClose = func(err error) {
		aerc.RemoveTab(term)
		if err != nil {
			aerc.PushStatus(" "+err.Error(), 10*time.Second).
				Color(tcell.ColorDefault, tcell.ColorRed)
		}
	}
	return nil
}
ringstream; using std::ostringstream; #include using std::ifstream; using std::ofstream;