- commit
- c5ee8855e257cbb7452814f599b9df6a0fabe50e
- parent
- cb70a1abb9c8c70133f3edefa07c873de73d179a
- author
- Dami <dami.etoile@gmail.com>
| M | internal/ | 14 | ++++++++------ |
| M | internal/ | 1 | + |
| M | internal/ | 1 | + |
| M | internal/ | 3 | +-- |
| M | internal/ | 2 | +- |
| M | internal/ | 27 | +++++++++++++++++++++------ |
| M | internal/ | 7 | +++---- |
@@ -152,6 +152,7 @@ func importDelimited(ctx context.Context, name string, k Kind, prog *Progress) (
152152 return nil, err153153 }154154 defer f.Close()155+ defer context.AfterFunc(ctx, func() { f.Close() })() // unblocks a read from a pipe155156 var size int64156157 if st, err := f.Stat(); err == nil && st.Mode().IsRegular() {157158 size = st.Size()@@ -191,6 +192,13 @@ func readDelimited(ctx context.Context, in io.Reader, k Kind, progress func(rows
191192 b := newBuilder()192193 row := 0193194 for ; ; row++ {195+ // Report before reading on: a pipe may keep the next read waiting.196+ if row%256 == 0 {197+ if err := ctx.Err(); err != nil {198+ return nil, 0, nil, err199+ }200+ progress(row)201+ }194202 rec, err := cr.Read()195203 if errors.Is(err, io.EOF) {196204 break@@ -202,12 +210,6 @@ func readDelimited(ctx context.Context, in io.Reader, k Kind, progress func(rows
202210 }203211 return nil, 0, nil, err204212 }205- if row%256 == 0 {206- if err := ctx.Err(); err != nil {207- return nil, 0, nil, err208- }209- progress(row)210- }211213 for col, field := range rec {212214 if field != "" {213215 b.entry(sheet.Addr{Col: col, Row: row}, field)@@ -31,6 +31,7 @@ func importParquet(ctx context.Context, name string, prog *Progress) (*Result, e
3131 return nil, err3232 }3333 defer f.Close()34+ defer context.AfterFunc(ctx, func() { f.Close() })() // unblocks a read from a pipe3435 st, err := f.Stat()3536 if err != nil {3637 return nil, err@@ -48,6 +48,7 @@ func importWK1(ctx context.Context, name string, prog *Progress) (*Result, error
4848 return nil, err4949 }5050 defer f.Close()51+ defer context.AfterFunc(ctx, func() { f.Close() })() // unblocks a read from a pipe5152 var size int645253 if st, err := f.Stat(); err == nil {5354 size = st.Size()@@ -32,8 +32,7 @@ func importXLSX(ctx context.Context, name string, prog *Progress) (*Result, erro
3232 ws := sheets[0]3333 var notes []string3434 if n := len(sheets) - 1; n > 0 {35- notes = append(notes, fmt.Sprintf("imported the first sheet, %s; %s not imported (%s)",36- ws, count(n, "other sheet", "other sheets"), strings.Join(sheets[1:], ", ")))35+ notes = append(notes, fmt.Sprintf("first sheet only, %s; not imported: %s", ws, strings.Join(sheets[1:], ", ")))3736 }3837 3938 total := 0@@ -151,7 +151,7 @@ func TestXLSXImport(t *testing.T) {
151151 }152152 notes := strings.Join(res.Notes, "; ")153153 for _, want := range []string{154- "imported the first sheet, Q1; 2 other sheets not imported (Q2, Q3)",154+ "first sheet only, Q1; not imported: Q2, Q3",155155 "1 formula kept as values, e.g. A2 =Q2!A1*2",156156 } {157157 if !strings.Contains(notes, want) {@@ -125,12 +125,18 @@ func importable() []string {
125125 // too.126126 func (m *Model) openImport() tea.Cmd {127127 var items []pickItem128- for _, name := range importable() {128+ names := importable()129+ lw := 0 // types line up, and sizes after them130+ for _, name := range names {131+ k, _ := fileio.KindOf(name)132+ lw = max(lw, len(k.Label()))133+ }134+ for _, name := range names {129135 k, _ := fileio.KindOf(name)130136 detail, desc := k.Label(), "Import "+name+", "+strings.ToLower(k.Label()[:1])+k.Label()[1:]131137 if st, err := os.Stat(name); err == nil {132- detail += " " + fileSize(st.Size())133- desc += ", " + fileSize(st.Size()) + ", changed " + st.ModTime().Format("Jan 2 15:04")138+ detail = fmt.Sprintf("%-*s %6s", lw, k.Label(), fileSize(st.Size()))139+ desc += ", " + fileSize(st.Size())134140 }135141 items = append(items, pickItem{title: name, name: len(name), detail: detail, desc: desc,136142 pick: func(m *Model) tea.Cmd {@@ -228,12 +234,12 @@ func (m *Model) importing(msg tea.Msg) (tea.Cmd, bool) {
228234 switch msg := msg.(type) {229235 case tea.KeyPressMsg:230236 if msg.String() == "esc" {231- m.xfer.job.cancel()237+ m.cancelImport()232238 }233239 return nil, true234240 case tea.MouseClickMsg:235241 if msg.Mouse().Y == contextLine {236- m.xfer.job.cancel() // the Esc chip242+ m.cancelImport() // the Esc chip237243 }238244 return nil, true239245 case tea.MouseMsg, tea.PasteMsg:@@ -242,6 +248,15 @@ func (m *Model) importing(msg tea.Msg) (tea.Cmd, bool) {
242248 return nil, false243249 }244250 251+// cancelImport stops the import at once; its result, if it still252+// arrives, is ignored.253+func (m *Model) cancelImport() {254+ job := m.xfer.job255+ job.cancel()256+ m.xfer.job = nil257+ m.note = "Import of " + filepath.Base(job.name) + " cancelled"258+}259+245260 // handleTransfer handles import and export messages.246261 func (m *Model) handleTransfer(msg tea.Msg) tea.Cmd {247262 switch msg := msg.(type) {@@ -372,7 +387,7 @@ func (m *Model) importStatus() string {
372387 job := m.xfer.job373388 rows, frac := job.prog.Get()374389 left := m.th.key.Render("Importing " + filepath.Base(job.name))375- right := countRows(rows)390+ right := countRows(rows) + " read"376391 if frac >= 0 {377392 pct := fmt.Sprintf(" %3d%%", int(frac*100))378393 w := clamp(m.width-ansi.StringWidth(left)-ansi.StringWidth(right)-len(pct)-6, 0, 30)@@ -39,7 +39,7 @@ func TestImportPicker(t *testing.T) {
3939 m := newModel()4040 m.runCommand("file.import")4141 got := strings.Join(pickerTitles(t, m), "\n")42- want := "Old.WK1 | Lotus 1-2-3 worksheet 1 B\nsales.csv | Comma-separated values 28 B"42+ want := "Old.WK1 | Lotus 1-2-3 worksheet 1 B\nsales.csv | Comma-separated values 28 B"4343 if got != want {4444 t.Errorf("picker lists\n%s\nwant\n%s", got, want)4545 }@@ -249,7 +249,7 @@ func TestImportProgress(t *testing.T) {
249249 if l := line(m, contextLine); l != "Importing big.csv… Esc cancel" {250250 t.Errorf("context %q", l)251251 }252- if l := line(m, m.height-1); !strings.HasPrefix(l, "Importing big.csv") || !strings.HasSuffix(l, "1,234 rows") {252+ if l := line(m, m.height-1); !strings.HasPrefix(l, "Importing big.csv") || !strings.HasSuffix(l, "1,234 rows read") {253253 t.Errorf("status %q", l)254254 }255255 if pb := m.View().ProgressBar; pb == nil || pb.State != tea.ProgressBarIndeterminate {@@ -257,7 +257,7 @@ func TestImportProgress(t *testing.T) {
257257 }258258 prog.Report(4096, 1, 2)259259 l := line(m, m.height-1)260- if l != "Importing big.csv 4,096 rows ━━━━━━━━━━━━━━━─────────────── 50%" {260+ if l != "Importing big.csv 4,096 rows read ━━━━━━━━━━━━━━━─────────────── 50%" {261261 t.Errorf("status %q", l)262262 }263263 if pb := m.View().ProgressBar; pb == nil || pb.Value != 50 {@@ -272,7 +272,6 @@ func TestImportProgress(t *testing.T) {
272272 if !cancelled {273273 t.Error("Esc didn't cancel")274274 }275- send(m, importedMsg{id: 7, name: "data/big.csv", err: context.Canceled})276275 if m.xfer.job != nil || line(m, contextLine) != "Import of big.csv cancelled" {277276 t.Errorf("after cancel: %q", line(m, contextLine))278277 }