about summary refs log tree commit diff stats
path: root/js/games/nluqo.github.io/~bh/v3ch2/3choose5.gif
Commit message (Expand)AuthorAgeFilesLines
* *elioat2023-08-231-0/+0
1eda08003ce2ccc6d57d7f19ea1e'>^
7ecc6f9 ^
363aab5 ^


05fa79e ^
7ecc6f9 ^

363aab5 ^







6838c23 ^
363aab5 ^


6838c23 ^
363aab5 ^


6838c23 ^
363aab5 ^
7ecc6f9 ^


363aab5 ^

7ecc6f9 ^
363aab5 ^




7ecc6f9 ^

363aab5 ^




























7ecc6f9 ^


f06d683 ^
7ecc6f9 ^






3f30c27 ^








7ecc6f9 ^
f06d683 ^
7ecc6f9 ^
133085b ^
0f78f06 ^

f06d683 ^
0f78f06 ^


f06d683 ^
133085b ^
7ecc6f9 ^


363aab5 ^

8bb115d ^


217e85a ^



05fa79e ^
7ecc6f9 ^
05fa79e ^
7ecc6f9 ^
05fa79e ^
7ecc6f9 ^
363aab5 ^
363aab5 ^


df20f1c ^
13a6a3f ^
7ecc6f9 ^





363aab5 ^
363aab5 ^




1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141


           


                
                 


                                           
                                               

                                    







                        
                                


                               
                                                                  


                  
                                                              
             


                               

                                                                     
                                                        




                                   

                                         




























                                                                                       


                                                                  
                                                         






                                                        








                                             
                               
                                                         
                        
                                                              

                                                                               
                                                                      


                                                                               
                                                                      
                         


                 

                                         


                                                                                          



                                                      
                                                                                
                                       
                                                         
                                
                                                                      
                                                                                
                         


                                                   
                                         
                                                                                





                                                                                
                         




                  
package msg

import (
	"errors"
	"fmt"
	"io"
	"os/exec"

	"git.sr.ht/~sircmpwn/aerc/commands"
	"git.sr.ht/~sircmpwn/aerc/widgets"
	"git.sr.ht/~sircmpwn/aerc/worker/types"

	"git.sr.ht/~sircmpwn/getopt"
)

type Pipe struct{}

func init() {
	register(Pipe{})
}

func (Pipe) Aliases() []string {
	return []string{"pipe"}
}

func (Pipe) Complete(aerc *widgets.Aerc, args []string) []string {
	return nil
}

func (Pipe) Execute(aerc *widgets.Aerc, args []string) error {
	var (
		background bool
		pipeFull   bool
		pipePart   bool
	)
	// TODO: let user specify part by index or preferred mimetype
	opts, optind, err := getopt.Getopts(args, "bmp")
	if err != nil {
		return err
	}
	for _, opt := range opts {
		switch opt.Option {
		case 'b':
			background = true
		case 'm':
			if pipePart {
				return errors.New("-m and -p are mutually exclusive")
			}
			pipeFull = true
		case 'p':
			if pipeFull {
				return errors.New("-m and -p are mutually exclusive")
			}
			pipePart = true
		}
	}
	cmd := args[optind:]
	if len(cmd) == 0 {
		return errors.New("Usage: pipe [-mp] <cmd> [args...]")
	}

	provider := aerc.SelectedTab().(widgets.ProvidesMessage)
	if !pipeFull && !pipePart {
		if _, ok := provider.(*widgets.MessageViewer); ok {
			pipePart = true
		} else if _, ok := provider.(*widgets.AccountView); ok {
			pipeFull = true
		} else {
			return errors.New(
				"Neither -m nor -p specified and cannot infer default")
		}
	}

	doTerm := func(reader io.Reader, name string) {
		term, err := commands.QuickTerm(aerc, cmd, reader)
		if err != nil {
			aerc.PushError(" " + err.Error())
			return
		}
		aerc.NewTab(term, name)
	}

	doExec := func(reader io.Reader) {
		ecmd := exec.Command(cmd[0], cmd[1:]...)
		pipe, err := ecmd.StdinPipe()
		if err != nil {
			return
		}
		go func() {
			defer pipe.Close()
			io.Copy(pipe, reader)
		}()
		err = ecmd.Run()
		if err != nil {
			aerc.PushError(" " + err.Error())
		} else {
			if ecmd.ProcessState.ExitCode() != 0 {
				aerc.PushError(fmt.Sprintf(
					"%s: completed with status %d", cmd[0],
					ecmd.ProcessState.ExitCode()))
			} else {
				aerc.PushStatus(fmt.Sprintf(
					"%s: completed with status %d", cmd[0],
					ecmd.ProcessState.ExitCode()))
			}
		}
	}

	if pipeFull {
		store := provider.Store()
		if store == nil {
			return errors.New("Cannot perform action. Messages still loading")
		}
		msg, err := provider.SelectedMessage()
		if err != nil {
			return err
		}
		store.FetchFull([]uint32{msg.Uid}, func(fm *types.FullMessage) {
			if background {
				doExec(fm.Content.Reader)
			} else {
				doTerm(fm.Content.Reader, fmt.Sprintf(
					"%s <%s", cmd[0], msg.Envelope.Subject))
			}
		})
	} else if pipePart {
		p := provider.SelectedMessagePart()
		store := provider.Store()
		store.FetchBodyPart(p.Msg.Uid, p.Index, func(reader io.Reader) {
			if background {
				doExec(reader)
			} else {
				name := fmt.Sprintf("%s <%s/[%d]",
					cmd[0], p.Msg.Envelope.Subject, p.Index)
				doTerm(reader, name)
			}
		})
	}

	return nil
}