Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ANSI code being printed to terminal when using alacritty #46

Closed
donbex opened this issue Nov 5, 2020 · 73 comments · Fixed by #103, #105, #107, #112 or #113
Closed

ANSI code being printed to terminal when using alacritty #46

donbex opened this issue Nov 5, 2020 · 73 comments · Fixed by #103, #105, #107, #112 or #113
Labels
bug Something isn't working help wanted Extra attention is needed

Comments

@donbex
Copy link

donbex commented Nov 5, 2020

In edit mode taskwarrior-tui crashes after exiting the editor, whether there are changes or not.

Steps to reproduce the behaviour:

  • Create empty taskrc and database:
$ mkdir tasktmp
$ touch tmprc
  • Create a test task:
$ TASKRC=tmprc TASKDATA=tasktmp task add test
  • Start taskwarrior-tui:
$ TASKRC=tmprc TASKDATA=tasktmp taskwarrior-tui
  • Select the test task and open the editor with e

  • Quit the editor

Output:

Launching '/usr/bin/nvim "task.131964a7.task"' now...
Editing complete.
No edits were detected.
TASKRC override: /home/bexie/tmprc
TASKDATA override: /home/bexie/tasktmp
[taskwarrior-tui error]: Failed to create a Task from JSON. Please report as a github issue on https://github.com/kdheepak/taskwarrior-tui

Note:
Setting RUST_BACKTRACE=1 does not produce any additional output.

Environment:

  • Operating System: Arch Linux

  • Installation: taskwarrior-tui package from the AUR

  • taskwarrior-tui version: 0.9.3

  • task version: 2.5.1

@donbex donbex added the bug Something isn't working label Nov 5, 2020
@kdheepak
Copy link
Owner

kdheepak commented Nov 5, 2020

Interestingly I'm not able to reproduce this. Does this happen when only one task is defined? I followed your exact steps and everything worked as expected. I'm on a MacOS.

@kdheepak
Copy link
Owner

kdheepak commented Nov 6, 2020

I'm not able to reproduce on a Ubuntu machine as well.

taskeditubuntu mov

Any change it could have to do with your neovim configuration? Can you try using a blank .vimrc and see if that makes a difference?

@donbex
Copy link
Author

donbex commented Nov 6, 2020

Well, colour me puzzled... I cannot reproduce this issue with nano, emacs or vim, either. However, the issue is still present when setting editor=nvim -u NONE in tmprc. Could you test with neovim as well?

Note: -u NONE prevents neovim from loading any configuration files, including plugins.

@kdheepak
Copy link
Owner

kdheepak commented Nov 6, 2020

I use neovim on my machine, and I don't have any issue. Can you run task edit from your command line and see if neovim works in that case. Because that is essentially what taskwarrior-tui does.

@donbex
Copy link
Author

donbex commented Nov 6, 2020

task edit works without issues.

@kdheepak
Copy link
Owner

kdheepak commented Nov 7, 2020

Can you run task export and paste the results here? Does task export differ at all when editing using emacs / vim / nano versus when editing with neovim?

My guess is that after editing your task, something weird is going on and taskwarrior-tui is not able to import the exported output of taskwarrior. It is so surprising that it happens only with neovim.

If you are able to build from source and add some dbg!(variable_name) in this function, we can figure out what is going on fairly quickly

taskwarrior-tui/src/app.rs

Lines 810 to 844 in fa9095a

pub fn export_tasks(&mut self) -> Result<(), Box<dyn Error>> {
let mut task = Command::new("task");
task.arg("rc.json.array=on");
task.arg("rc.confirmation=off");
task.arg("export");
let filter = if self.current_context_filter != "" {
let t = format!("{} {}", self.filter.as_str(), self.current_context_filter);
t
} else {
self.filter.as_str().into()
};
match shlex::split(&filter) {
Some(cmd) => {
for s in cmd {
task.arg(&s);
}
}
None => {
task.arg("");
}
}
let output = task.output()?;
let data = String::from_utf8_lossy(&output.stdout);
let error = String::from_utf8_lossy(&output.stderr);
if !error.contains("The expression could not be evaluated.") {
let imported = import(data.as_bytes())?;
*(self.tasks.lock().unwrap()) = imported;
self.tasks.lock().unwrap().sort_by(cmp);
}
Ok(())
}

Unfortunately, since I'm not able to reproduce locally, I'm not sure how to help debug this issue.

@kdheepak
Copy link
Owner

Any luck?

@donbex
Copy link
Author

donbex commented Nov 10, 2020

Sorry, I have been busy and couldn't get around to this until now. Unfortunately, the output of task export does not differ at all when opening the test task with either nano or neovim.

I am happy to apply any patches and compile from source, but I am not sure as to where you would like me to put those debug statements. Could you give me a patch instead?

@donbex
Copy link
Author

donbex commented Nov 16, 2020

So, I tried adding the dbg! instructions you asked for, but when I try to compile I get errors like this

error[E0382]: borrow of moved value: `task`
   --> src/app.rs:877:21
    |
856 |         let mut task = Command::new("task");
    |             -------- move occurs because `task` has type `std::process::Command`, which does not implement the `Copy` trait
...
862 |         dbg!(task);
    |         ----------- value moved here
...
877 |                     task.arg(&s);
    |                     ^^^^ value borrowed here after move

Unfortunately, I am not familiar with rust and I have no clue how to work around this...

Update: Never mind... I found the documentation of the dbg! macro and managed to compile the code with the amended function:

    pub fn export_tasks(&mut self) -> Result<(), Box<dyn Error>> {
        let mut task = Command::new("task");

        task.arg("rc.json.array=on");
        task.arg("rc.confirmation=off");
        task.arg("export");

        dbg!(&task);

        let filter = if self.current_context_filter != "" {
            let t = format!("{} {}", self.filter.as_str(), self.current_context_filter);
            t
        } else {
            self.filter.as_str().into()
        };

        dbg!(&filter);

        match shlex::split(&filter) {
            Some(cmd) => {
                dbg!(&cmd);
                for s in cmd {
                    task.arg(&s);
                }
            }
            None => {
                task.arg("");
            }
        }

        let output = task.output()?;
        dbg!(&output);
        let data = String::from_utf8_lossy(&output.stdout);
        dbg!(&data);
        let error = String::from_utf8_lossy(&output.stderr);
        dbg!(&error);
        if !error.contains("The expression could not be evaluated.") {
            let imported = import(data.as_bytes())?;
            *(self.tasks.lock().unwrap()) = imported;
            self.tasks.lock().unwrap().sort_by(cmp);
        }
        Ok(())
    }

This is the stderr output of TASKRC=tmprc TASKDATA=tasktmp ./taskwarrior-tui/target/debug/taskwarrior-tui after trying to edit a task:

[src/app.rs:862] &task = "task" "rc.json.array=on" "rc.confirmation=off" "export"
[src/app.rs:871] &filter = "status:pending "
[src/app.rs:875] &cmd = [
    "status:pending",
]
[src/app.rs:886] &output = Output {
    status: ExitStatus(
        ExitStatus(
            0,
        ),
    ),
    stdout: "[\n{\"id\":1,\"description\":\"test\",\"entry\":\"20201110T113710Z\",\"modified\":\"20201110T113710Z\",\"status\":\"pending\",\"uuid\":\"86b0d194-9bbc-4128-a4e5-06cd53c89988\",\"urgency\":0.0328767}\n]\n",
    stderr: "TASKRC override: /home/donbex/taskdebug/tmprc\nTASKDATA override: /home/donbex/taskdebug/tasktmp\nConfiguration override rc.json.array:on\nConfiguration override rc.confirmation:off\n",
}
[src/app.rs:888] &data = "[\n{\"id\":1,\"description\":\"test\",\"entry\":\"20201110T113710Z\",\"modified\":\"20201110T113710Z\",\"status\":\"pending\",\"uuid\":\"86b0d194-9bbc-4128-a4e5-06cd53c89988\",\"urgency\":0.0328767}\n]\n"
[src/app.rs:890] &error = "TASKRC override: /home/donbex/taskdebug/tmprc\nTASKDATA override: /home/donbex/taskdebug/tasktmp\nConfiguration override rc.json.array:on\nConfiguration override rc.confirmation:off\n"
[src/app.rs:862] &task = "task" "rc.json.array=on" "rc.confirmation=off" "export"
[src/app.rs:871] &filter = "status:pending "
[src/app.rs:875] &cmd = [
    "status:pending",
]
[src/app.rs:886] &output = Output {
    status: ExitStatus(
        ExitStatus(
            0,
        ),
    ),
    stdout: "[\n{\"id\":1,\"description\":\"test\",\"entry\":\"20201110T113710Z\",\"modified\":\"20201110T113710Z\",\"status\":\"pending\",\"uuid\":\"86b0d194-9bbc-4128-a4e5-06cd53c89988\",\"urgency\":0.0328767}\n]\n",
    stderr: "TASKRC override: /home/donbex/taskdebug/tmprc\nTASKDATA override: /home/donbex/taskdebug/tasktmp\nConfiguration override rc.json.array:on\nConfiguration override rc.confirmation:off\n",
}
[src/app.rs:888] &data = "[\n{\"id\":1,\"description\":\"test\",\"entry\":\"20201110T113710Z\",\"modified\":\"20201110T113710Z\",\"status\":\"pending\",\"uuid\":\"86b0d194-9bbc-4128-a4e5-06cd53c89988\",\"urgency\":0.0328767}\n]\n"
[src/app.rs:890] &error = "TASKRC override: /home/donbex/taskdebug/tmprc\nTASKDATA override: /home/donbex/taskdebug/tasktmp\nConfiguration override rc.json.array:on\nConfiguration override rc.confirmation:off\n"
[src/app.rs:862] &task = "task" "rc.json.array=on" "rc.confirmation=off" "export"
[src/app.rs:871] &filter = "status:pending "
[src/app.rs:875] &cmd = [
    "status:pending",
]
[src/app.rs:886] &output = Output {
    status: ExitStatus(
        ExitStatus(
            0,
        ),
    ),
    stdout: "[\n{\"id\":1,\"description\":\"test\",\"entry\":\"20201110T113710Z\",\"modified\":\"20201110T113710Z\",\"status\":\"pending\",\"uuid\":\"86b0d194-9bbc-4128-a4e5-06cd53c89988\",\"urgency\":0.0328767}\n]\n",
    stderr: "TASKRC override: /home/donbex/taskdebug/tmprc\nTASKDATA override: /home/donbex/taskdebug/tasktmp\nConfiguration override rc.json.array:on\nConfiguration override rc.confirmation:off\n",
}
[src/app.rs:888] &data = "[\n{\"id\":1,\"description\":\"test\",\"entry\":\"20201110T113710Z\",\"modified\":\"20201110T113710Z\",\"status\":\"pending\",\"uuid\":\"86b0d194-9bbc-4128-a4e5-06cd53c89988\",\"urgency\":0.0328767}\n]\n"
[src/app.rs:890] &error = "TASKRC override: /home/donbex/taskdebug/tmprc\nTASKDATA override: /home/donbex/taskdebug/tasktmp\nConfiguration override rc.json.array:on\nConfiguration override rc.confirmation:off\n"
�[38;5;3mTASKRC override: /home/donbex/taskdebug/tmprc�[0m
�[38;5;3mTASKDATA override: /home/donbex/taskdebug/tasktmp�[0m
[src/app.rs:862] &task = "task" "rc.json.array=on" "rc.confirmation=off" "export"
[src/app.rs:871] &filter = "status:pending "
[src/app.rs:875] &cmd = [
    "status:pending",
]
[src/app.rs:886] &output = Output {
    status: ExitStatus(
        ExitStatus(
            0,
        ),
    ),
    stdout: "[\n{\"id\":1,\"description\":\"test\",\"entry\":\"20201110T113710Z\",\"modified\":\"20201110T113710Z\",\"status\":\"pending\",\"uuid\":\"86b0d194-9bbc-4128-a4e5-06cd53c89988\",\"urgency\":0.0328767}\n]\n",
    stderr: "TASKRC override: /home/donbex/taskdebug/tmprc\nTASKDATA override: /home/donbex/taskdebug/tasktmp\nConfiguration override rc.json.array:on\nConfiguration override rc.confirmation:off\n",
}
[src/app.rs:888] &data = "[\n{\"id\":1,\"description\":\"test\",\"entry\":\"20201110T113710Z\",\"modified\":\"20201110T113710Z\",\"status\":\"pending\",\"uuid\":\"86b0d194-9bbc-4128-a4e5-06cd53c89988\",\"urgency\":0.0328767}\n]\n"
[src/app.rs:890] &error = "TASKRC override: /home/donbex/taskdebug/tmprc\nTASKDATA override: /home/donbex/taskdebug/tasktmp\nConfiguration override rc.json.array:on\nConfiguration override rc.confirmation:off\n"
[src/app.rs:862] &task = "task" "rc.json.array=on" "rc.confirmation=off" "export"
[src/app.rs:871] &filter = "status:pending "
[src/app.rs:875] &cmd = [
    "status:pending",
]
[src/app.rs:886] &output = Output {
    status: ExitStatus(
        ExitStatus(
            0,
        ),
    ),
    stdout: "[\n{\"id\":1,\"description\":\"test\",\"entry\":\"20201110T113710Z\",\"modified\":\"20201110T113710Z\",\"status\":\"pending\",\"uuid\":\"86b0d194-9bbc-4128-a4e5-06cd53c89988\",\"urgency\":0.0328767}\n]\n",
    stderr: "TASKRC override: /home/donbex/taskdebug/tmprc\nTASKDATA override: /home/donbex/taskdebug/tasktmp\nConfiguration override rc.json.array:on\nConfiguration override rc.confirmation:off\n",
}
[src/app.rs:888] &data = "[\n{\"id\":1,\"description\":\"test\",\"entry\":\"20201110T113710Z\",\"modified\":\"20201110T113710Z\",\"status\":\"pending\",\"uuid\":\"86b0d194-9bbc-4128-a4e5-06cd53c89988\",\"urgency\":0.0328767}\n]\n"
[src/app.rs:890] &error = "TASKRC override: /home/donbex/taskdebug/tmprc\nTASKDATA override: /home/donbex/taskdebug/tasktmp\nConfiguration override rc.json.array:on\nConfiguration override rc.confirmation:off\n"
[src/app.rs:862] &task = "task" "rc.json.array=on" "rc.confirmation=off" "export"
[src/app.rs:871] &filter = "status:pending 0000/0000"
[src/app.rs:875] &cmd = [
    "status:pending",
    "0000/0000",
]
[src/app.rs:886] &output = Output {
    status: ExitStatus(
        ExitStatus(
            512,
        ),
    ),
    stdout: "",
    stderr: "TASKRC override: /home/donbex/taskdebug/tmprc\nTASKDATA override: /home/donbex/taskdebug/tasktmp\nConfiguration override rc.json.array:on\nConfiguration override rc.confirmation:off\nCannot divide Boolean values\n",
}
[src/app.rs:888] &data = ""
[src/app.rs:890] &error = "TASKRC override: /home/donbex/taskdebug/tmprc\nTASKDATA override: /home/donbex/taskdebug/tasktmp\nConfiguration override rc.json.array:on\nConfiguration override rc.confirmation:off\nCannot divide Boolean values\n"
[taskwarrior-tui error]: Failed to create a Task from JSON. Please report as a github issue on https://github.com/kdheepak/taskwarrior-tui

@kdheepak
Copy link
Owner

Thanks that is super helpful! Would it be possible for you to send me your taskrc file? Is it not empty? Why is your filter this string 0000/0000?

@kdheepak
Copy link
Owner

[src/app.rs:862] &task = "task" "rc.json.array=on" "rc.confirmation=off" "export"
[src/app.rs:871] &filter = "status:pending 0000/0000"
[src/app.rs:875] &cmd = [
    "status:pending",
    "0000/0000",
]
[src/app.rs:886] &output = Output {
    status: ExitStatus(
        ExitStatus(
            512,
        ),
    ),
    stdout: "",
    stderr: "TASKRC override: /home/donbex/taskdebug/tmprc\nTASKDATA override: /home/donbex/taskdebug/tasktmp\nConfiguration override rc.json.array:on\nConfiguration override rc.confirmation:off\nCannot divide Boolean values\n",
}
[src/app.rs:888] &data = ""
[src/app.rs:890] &error = "TASKRC override: /home/donbex/taskdebug/tmprc\nTASKDATA override: /home/donbex/taskdebug/tasktmp\nConfiguration override rc.json.array:on\nConfiguration override rc.confirmation:off\nCannot divide Boolean values\n"

This is basically the problem. taskwarrior doesn't understand what that 0000/0000 means. Do you happen to know where it is coming from?

Screen Shot 2020-11-16 at 2 00 44 PM

@donbex
Copy link
Author

donbex commented Nov 16, 2020

Thanks that is super helpful! Would it be possible for you to send me your taskrc file? Is it not empty?

The taskrc is empty.

Why is your filter this string 0000/0000?

Not a clue. The filter line appears only as status:pending in taskwarrior-tui. I don't know why editing the task with neovim might introduce that...

@donbex
Copy link
Author

donbex commented Nov 16, 2020

I am afraid this might have something to do with alacritty, since the issue does not seem to appear with kitty. What terminal emulator are you using, and would you be able to see if you can reproduce the issue with alacritty?

@martinzh
Copy link

martinzh commented Jan 12, 2021

It is not related with alacritty, I have the same issue on MacOS with iTerm and NeoVim, but only with the brew and the binary release version. I tried building it from source and the problem does not appears

@kdheepak
Copy link
Owner

Can you share the error message after it crashes?

@martinzh
Copy link

martinzh commented Jan 12, 2021

The error message is:

Launching 'nvim "task.0601240e.task"' now...
Editing complete.
Edits were detected.
Description modified.
[taskwarrior-tui error]: Failed to create a Task from JSON. Please report as a github issue on https://github.com/kdheepak/taskwarrior-tui

in my case after closing the editor it appears 2121/2121 after status:pending in the Filter Tasks section

@kdheepak
Copy link
Owner

Can you run task export and share the results?

@martinzh
Copy link

This is the output from task export:

[
{"id":1,"description":"Figura comportamiento temporal","due":"20210118T200000Z","entry":"20210112T014158Z","modified":"20210112T041233Z","project":"Coy:JohnSabina","status":"pending","tags":["DataVis","Coyuntura","TlateLAB","Test"],"uuid":"f24e95fb-b203-460f-997b-62738755cf54","urgency":8.01848},
{"id":2,"description":"Modificar vis redes","due":"20210118T200000Z","entry":"20210112T014422Z","modified":"20210112T033254Z","project":"Coy:JohnSabina","status":"pending","tags":["DataVis","Coyuntura","TlateLAB"],"uuid":"720cee60-9046-4086-9c42-f8ac75cd0086","urgency":8.01848},
{"id":3,"description":"Modificar vis de RT de RTs","due":"20210118T200000Z","entry":"20210112T014927Z","modified":"20210112T033325Z","project":"Coy:JohnSabina","status":"pending","tags":["DataVis","TlateLAB"],"uuid":"8613049c-5425-4ca2-b8fd-aa1c5e679064","urgency":7.91848},
{"id":4,"description":"Modificar análisis de cuentas como el de tendencias","due":"20210118T200000Z","entry":"20210112T014955Z","modified":"20210112T035657Z","project":"Coy:JohnSabina","status":"pending","tags":["Code","Twitter","TlateLAB"],"uuid":"6d6a0adb-a05c-4a5a-a245-464386e0862f","urgency":8.01848},
{"id":5,"description":"Test otro otro","entry":"20210112T035707Z","modified":"20210112T151928Z","status":"pending","tags":["personal"],"uuid":"0601240e-884b-41c9-9682-94d7658eaeb6","urgency":0.8},
{"id":0,"description":"Test","end":"20210112T033446Z","entry":"20210112T033425Z","modified":"20210112T033446Z","status":"deleted","tags":["SportsAnalytics"],"uuid":"8a6e38cc-f5f0-4992-8e1f-a4ca9d28683e","urgency":0.8},
{"id":0,"description":"Hacer figura de geometría de ABP","end":"20210111T211843Z","entry":"20200424T173242Z","modified":"20210111T211843Z","project":"Tesis","reviewed":"20200428T044435Z","status":"deleted","uuid":"3c9046da-e43b-48ac-ad41-8a57663c7653","urgency":2.4411},
{"id":0,"description":"Hacer figura trayectorias de ABP","end":"20210111T211844Z","entry":"20200424T192657Z","modified":"20210111T211844Z","project":"Tesis","reviewed":"20200428T044438Z","status":"deleted","uuid":"302aecf9-5b62-4e81-8cae-c18de8cb1596","urgency":2.43562},
{"id":0,"description":"Calcular MSD para PBA","end":"20210111T211845Z","entry":"20200424T202750Z","modified":"20210111T211845Z","project":"Tesis","reviewed":"20200428T044447Z","status":"deleted","uuid":"facca1de-1df1-471c-91e5-81ecc59d530f","annotations":[{"entry":"20200424T202806Z","description":"Caclucos analiticos"},{"entry":"20200424T202836Z","description":"Ver Bechinger1602 para referencias"}],"urgency":3.33562},
{"id":0,"description":"Revisar referencias calculos MSD en Bechinger","end":"20210111T211846Z","entry":"20200424T204406Z","modified":"20210111T211846Z","project":"Tesis","reviewed":"20200428T044451Z","status":"deleted","uuid":"412a85bd-f8ec-4210-96ee-d821b483d5ce","urgency":2.43562},
{"id":0,"description":"Revisar scripts que usé en la pres19","end":"20210111T211847Z","entry":"20200519T165354Z","modified":"20210111T211847Z","project":"EFOS20","status":"deleted","uuid":"5fd00e32-1195-4f3d-92cf-024bbdadb6e9","urgency":2.30411},
{"id":0,"description":"Actualizar scripts redes y otros anteriores","end":"20210111T211848Z","entry":"20200519T165412Z","modified":"20210111T211848Z","project":"EFOS20","status":"deleted","uuid":"146e36ad-cb96-4872-bbae-67a22179b7f3","urgency":2.30411},
{"id":0,"description":"Comparar info categórica de la DB de EFOS con la de categorica","end":"20210111T211910Z","entry":"20200519T165446Z","modified":"20210111T211910Z","project":"EFOS20","status":"deleted","uuid":"3536eca7-67b2-43ef-978f-12612a4f0888","urgency":2.30411},
{"id":0,"description":"Revisar referencias motifs","end":"20210111T211849Z","entry":"20200519T165529Z","modified":"20210111T211849Z","project":"EFOS20","status":"deleted","uuid":"a21ad3f8-ec18-40cb-aca2-d780f429dca2","urgency":2.30411},
{"id":0,"description":"Decidir que info categórica usar para caracterizar enlaces","end":"20210111T211850Z","entry":"20200519T165634Z","modified":"20210111T211850Z","project":"EFOS20","status":"deleted","uuid":"8e6202d8-5488-4666-af4c-255a05d318f4","urgency":2.30411},
{"id":0,"description":"Calcular MSD de reactivos","end":"20210111T211851Z","entry":"20200528T225345Z","modified":"20210111T211851Z","project":"Patchy","status":"deleted","uuid":"f6f77450-8c94-4c67-a571-f7007719fb9b","urgency":2.24932},
{"id":0,"description":"Calcular coeficiente de difusión","end":"20210111T211853Z","entry":"20200528T225408Z","modified":"20210111T211853Z","project":"Patchy","status":"deleted","uuid":"5f902bd7-138b-42aa-97a6-1ff4f0613159","urgency":2.24932},
{"id":0,"description":"Visualizar MSD","end":"20210111T211858Z","entry":"20200528T225417Z","modified":"20210111T211858Z","project":"Patchy","status":"deleted","uuid":"08fdc28f-248c-4c44-a87d-6226e6cb5102","urgency":2.24932},
{"id":0,"description":"Generar archivo de info categórica para los sospechosos del proyecto anterior","end":"20210111T211901Z","entry":"20200629T183235Z","modified":"20210111T211901Z","project":"EFOS20","status":"deleted","uuid":"04d51671-f23b-4af7-8f1d-4b6e8f2097a7","urgency":2.07397},
{"id":0,"description":"Solicitar lista actualizada de RFCA genéricos","end":"20210111T211903Z","entry":"20200629T191247Z","modified":"20210111T211903Z","project":"EFOS20","status":"deleted","uuid":"5c69967c-2c01-4ca5-bb7c-2f0bfe187fa1","urgency":2.07397},
{"id":0,"description":"Hacer listas de EFOS artificiales","end":"20210111T211904Z","entry":"20200707T004234Z","modified":"20210111T211904Z","project":"EFOS20","status":"deleted","uuid":"081c105a-21ad-4981-a8ce-7a62ac593708","urgency":2.03562},
{"id":0,"description":"Construir redes entre RFCA con EFOS artificiales","end":"20210111T211905Z","entry":"20200707T004234Z","modified":"20210111T211905Z","project":"EFOS20","status":"deleted","uuid":"b8f91091-3d53-4455-aee1-ae28fcb2a076","urgency":2.03562},
{"id":0,"description":"Construir redes entre categóricas con EFOS artificiales","end":"20210111T211907Z","entry":"20200707T004234Z","modified":"20210111T211907Z","project":"EFOS20","status":"deleted","uuid":"1fc608df-6611-4e00-a836-c5aaa294a108","urgency":2.03562},
{"id":0,"depends":"1fc608df-6611-4e00-a836-c5aaa294a108,081c105a-21ad-4981-a8ce-7a62ac593708,b8f91091-3d53-4455-aee1-ae28fcb2a076","description":"Construir redes de \"modelo nulo\"","end":"20210111T211912Z","entry":"20200707T004234Z","modified":"20210111T211912Z","project":"EFOS20","status":"deleted","uuid":"f52bb46a-bc1f-417b-99ef-ddc2b9019e2c","urgency":2.03562},
{"id":0,"description":"Hacer JuliaDB con info categórica","end":"20200727T180416Z","entry":"20200519T165330Z","modified":"20200727T180416Z","project":"EFOS20","status":"completed","uuid":"92dfcad7-6bd9-4c71-9439-cfdcedaa147b","annotations":[{"entry":"20200630T190031Z","description":"Prueba nota"}],"urgency":3.10411},
{"id":0,"description":"Arreglar posiciones de figuras","end":"20200720T192715Z","entry":"20200720T192434Z","modified":"20200720T192717Z","project":"EFOS20","status":"deleted","uuid":"9728a852-6015-414b-96f7-9cf06fa64c46","urgency":1.9589},
{"id":0,"description":"Arreglar posiciones de figuras","end":"20200720T192700Z","entry":"20200720T192422Z","modified":"20200720T192702Z","project":"EFOS20","status":"deleted","uuid":"307cf0f3-a509-4dc3-8749-af9ce812aa23","urgency":1.9589},
{"id":0,"description":"Arreglar posiciones de figuras","end":"20200720T192652Z","entry":"20200720T192408Z","modified":"20200720T192655Z","project":"EFOS20","status":"deleted","uuid":"339eb16c-caa4-4be8-9961-93a3f226c3ee","urgency":1.9589},
{"id":0,"description":"Arreglar posiciones de figuras","end":"20200720T192631Z","entry":"20200720T192405Z","modified":"20200720T192634Z","project":"EFOS20","status":"deleted","uuid":"ea779bad-4850-46a1-8f54-d0d61b05c55b","urgency":1.9589},
{"id":0,"description":"Avanzar sección ASM","end":"20200720T191318Z","entry":"20200424T171518Z","modified":"20200720T191318Z","project":"Tesis","reviewed":"20200428T044504Z","status":"completed","uuid":"74a92f9f-5fba-467f-b863-22d64c91de4f","urgency":2.4411},
{"id":0,"description":"Generar visualizaciones de noProds","end":"20200707T184043Z","entry":"20200707T012611Z","modified":"20200707T184043Z","project":"Patchy","status":"completed","uuid":"d705a7cd-2780-4ce2-ac27-9d799934d1a4","urgency":2.03562},
{"id":0,"description":"Incluir opción para seleccionar prod o no prod","end":"20200707T184035Z","entry":"20200707T012611Z","modified":"20200707T184035Z","project":"Patchy","status":"completed","uuid":"60c85b57-cdf5-4a3a-b1b2-feafbb951087","urgency":2.03562},
{"id":0,"description":"Revisar documento efecto carrusel","end":"20200706T231703Z","entry":"20200519T165548Z","modified":"20200706T231703Z","project":"EFOS20","status":"completed","uuid":"5a39de71-8921-4589-8408-d3729abdf6fe","urgency":2.30411},
{"id":0,"description":"Hacer diccionarions con nombres y claves de categóricas","end":"20200706T231648Z","entry":"20200704T032639Z","modified":"20200706T231648Z","project":"EFOS20","status":"completed","uuid":"62a4116d-1156-4787-a7d6-2a5e3fcfdb8a","urgency":2.05205},
{"id":0,"description":"Hacer script para generar archivo \"headless\" de info categórica","end":"20200706T231632Z","entry":"20200630T005955Z","modified":"20200706T231632Z","project":"EFOS20","status":"completed","uuid":"21d4f7eb-8201-4613-8ec5-9a3203c95d05","urgency":2.07397},
{"id":0,"description":"Separar generar imágenes para comparar enlaces de generar las listas de enlaces","end":"20200706T231249Z","entry":"20200630T014446Z","modified":"20200706T231249Z","project":"EFOS20","status":"completed","uuid":"1c61b344-4364-47df-acf1-ecc62e124cd9","urgency":2.07397},
{"id":0,"description":"Agregar año y mes como parámetros de entrada a scripts","end":"20200630T185323Z","entry":"20200630T014146Z","modified":"20200630T185323Z","project":"EFOS20","status":"completed","uuid":"44f75eec-1e47-4269-bcfd-5e9d7e20cccd","urgency":2.07397},
{"id":0,"description":"Script para generar snapshots","end":"20200605T195244Z","entry":"20200528T225331Z","modified":"20200605T195244Z","project":"Patchy","status":"completed","uuid":"dad235ad-c1e7-49e4-b8a5-afe1f3dfccfb","urgency":2.24932},
{"id":0,"description":"Figuras REP","end":"20200529T234934Z","entry":"20200503T022846Z","modified":"20200529T234934Z","project":"Patchy","status":"completed","uuid":"036a09bb-5163-4db3-b977-3fe9173816f1","urgency":2.39178},
{"id":0,"description":"Script para extraer estado final de sims","end":"20200529T234838Z","entry":"20200528T225319Z","modified":"20200529T234838Z","project":"Patchy","status":"completed","uuid":"515b5412-cfae-457a-b2a6-7726dd0d5c15","urgency":2.24932},
{"id":0,"description":"Calcular distribuciones de actividades de RFCA desconocidos","end":"20200528T223059Z","entry":"20200528T170741Z","modified":"20200528T223059Z","project":"EFOS20","status":"completed","uuid":"c252d274-1774-465f-b768-e3e7029bf002","urgency":2.25479},
{"id":0,"description":"Hacer figuras de distribuciones de info categórica de EFOS","end":"20200528T223038Z","entry":"20200519T165515Z","modified":"20200528T223038Z","project":"EFOS20","status":"completed","uuid":"0d71dac0-937e-4685-b956-b05c81e068e7","urgency":2.30411},
{"id":0,"description":"Figuras ATT","end":"20200505T013253Z","entry":"20200503T022851Z","modified":"20200505T013253Z","project":"Patchy","status":"completed","uuid":"7e0edcff-ac3c-4d29-bc0a-c6b3b92eee6d","urgency":2.39178},
{"id":0,"description":"Figuras ACT","end":"20200504T221337Z","entry":"20200503T022854Z","modified":"20200504T221337Z","project":"Patchy","status":"completed","uuid":"d4f30abf-d7b8-44cd-b9fe-1f8cb3dd9128","urgency":2.39178},
{"id":0,"description":"Subir código al repositorio","end":"20200427T182736Z","entry":"20200427T164725Z","modified":"20200427T182736Z","project":"NetCovid","status":"completed","uuid":"2ca9d4ba-065e-4710-82f1-b6a8de36fa53","urgency":2.42466},
{"id":0,"description":"Terminar script sims_LFR","end":"20200427T182730Z","entry":"20200427T164658Z","modified":"20200427T182730Z","project":"NetCovid","status":"completed","uuid":"d3e7a3fc-446f-46b3-a536-93650f46c664","urgency":2.42466},
{"id":0,"description":"Revisar implementación lockdown","end":"20200427T182722Z","entry":"20200427T164603Z","modified":"20200427T182722Z","project":"NetCovid","status":"completed","uuid":"4aabe853-5eaa-49d7-bee3-1f65d86eaa13","urgency":2.42466},
{"id":0,"description":"Subir figuras al Drive","end":"20200423T185941Z","entry":"20200422T180719Z","modified":"20200423T185941Z","project":"NetCovid","status":"completed","uuid":"9b7521c1-3060-4c6e-b43a-c1847d84160b","urgency":2.44658},
{"id":0,"description":"Implementar distanciamiento en el modelo","end":"20200422T202904Z","entry":"20200422T180758Z","modified":"20200422T202904Z","project":"NetCovid","status":"completed","uuid":"56238761-5ae0-4315-98e1-8b95264c026f","urgency":2.44658},
{"id":0,"description":"Generar figuras de distribuciones","end":"20200422T202847Z","entry":"20200422T180706Z","modified":"20200422T202847Z","project":"NetCovid","status":"completed","uuid":"fbc46f70-2cb6-4f8f-950c-68412ed3f2de","urgency":2.44658},
{"id":0,"description":"PomodoroLog","end":"20200422T180819Z","entry":"20200422T180819Z","modified":"20200422T205417Z","status":"completed","uuid":"1f02077a-1656-4200-9fd7-318b7482ea4f","annotations":[{"entry":"20200422T192131Z","description":"Pomodoro uuid:fbc46f70-2cb6-4f8f-950c-68412ed3f2de"},{"entry":"20200422T205417Z","description":"Pomodoro uuid:9b7521c1-3060-4c6e-b43a-c1847d84160b"}],"urgency":2.34658},
{"id":0,"description":"PomodoroLog","end":"20200424T171522Z","entry":"20200424T171522Z","modified":"20200424T203929Z","status":"completed","uuid":"bac7134f-d833-4274-87f6-5a9e2d1ac4f1","annotations":[{"entry":"20200424T174023Z","description":"Pomodoro uuid:74a92f9f-5fba-467f-b863-22d64c91de4f"},{"entry":"20200424T193917Z","description":"Pomodoro uuid:74a92f9f-5fba-467f-b863-22d64c91de4f"},{"entry":"20200424T200422Z","description":"Pomodoro uuid:74a92f9f-5fba-467f-b863-22d64c91de4f"},{"entry":"20200424T203929Z","description":"Pomodoro uuid:74a92f9f-5fba-467f-b863-22d64c91de4f"}],"urgency":2.4411},
{"id":0,"description":"PomodoroLog","end":"20200427T164928Z","entry":"20200427T164928Z","modified":"20200428T002823Z","status":"completed","uuid":"e0ba9238-6edf-4344-8dec-759b78dbe10f","annotations":[{"entry":"20200427T171428Z","description":"Pomodoro uuid:4aabe853-5eaa-49d7-bee3-1f65d86eaa13"},{"entry":"20200427T181609Z","description":"Pomodoro uuid:4aabe853-5eaa-49d7-bee3-1f65d86eaa13"},{"entry":"20200427T233108Z","description":"Pomodoro uuid:74a92f9f-5fba-467f-b863-22d64c91de4f"},{"entry":"20200428T000012Z","description":"Pomodoro uuid:74a92f9f-5fba-467f-b863-22d64c91de4f"},{"entry":"20200428T002823Z","description":"Pomodoro uuid:74a92f9f-5fba-467f-b863-22d64c91de4f"}],"urgency":2.42466},
{"id":0,"description":"PomodoroLog","end":"20200504T170838Z","entry":"20200504T170838Z","modified":"20200504T232123Z","status":"completed","uuid":"bc96433c-9ab7-47a4-8efa-fb40e6c0fba7","annotations":[{"entry":"20200504T173339Z","description":"Pomodoro uuid:d4f30abf-d7b8-44cd-b9fe-1f8cb3dd9128"},{"entry":"20200504T183102Z","description":"Pomodoro uuid:d4f30abf-d7b8-44cd-b9fe-1f8cb3dd9128"},{"entry":"20200504T185605Z","description":"Pomodoro uuid:d4f30abf-d7b8-44cd-b9fe-1f8cb3dd9128"},{"entry":"20200504T192120Z","description":"Pomodoro uuid:d4f30abf-d7b8-44cd-b9fe-1f8cb3dd9128"},{"entry":"20200504T215113Z","description":"Pomodoro uuid:d4f30abf-d7b8-44cd-b9fe-1f8cb3dd9128"},{"entry":"20200504T223849Z","description":"Pomodoro uuid:7e0edcff-ac3c-4d29-bc0a-c6b3b92eee6d"},{"entry":"20200504T232123Z","description":"Pomodoro uuid:7e0edcff-ac3c-4d29-bc0a-c6b3b92eee6d"}],"urgency":2.3863},
{"id":0,"description":"PomodoroLog","end":"20200511T181206Z","entry":"20200511T181206Z","modified":"20200511T210045Z","status":"completed","uuid":"5585d281-2e82-418f-931d-f01a6237ce7c","annotations":[{"entry":"20200511T183707Z","description":"Pomodoro uuid:74a92f9f-5fba-467f-b863-22d64c91de4f"},{"entry":"20200511T190210Z","description":"Pomodoro uuid:74a92f9f-5fba-467f-b863-22d64c91de4f"},{"entry":"20200511T210045Z","description":"Pomodoro uuid:74a92f9f-5fba-467f-b863-22d64c91de4f"}],"urgency":2.34247},
{"id":0,"description":"PomodoroLog","end":"20200519T173643Z","entry":"20200519T173643Z","modified":"20200519T182718Z","status":"completed","uuid":"98e0c3a0-dc0a-44e4-9173-3e51e65732a0","annotations":[{"entry":"20200519T180144Z","description":"Pomodoro uuid:92dfcad7-6bd9-4c71-9439-cfdcedaa147b"},{"entry":"20200519T182718Z","description":"Pomodoro uuid:92dfcad7-6bd9-4c71-9439-cfdcedaa147b"}],"urgency":2.20411},
{"id":0,"description":"PomodoroLog","end":"20200525T173706Z","entry":"20200525T173706Z","modified":"20200525T180207Z","status":"completed","uuid":"8d05f912-d079-4cf2-adb3-cff4ad92e656","annotations":[{"entry":"20200525T180207Z","description":"Pomodoro uuid:74a92f9f-5fba-467f-b863-22d64c91de4f"}],"urgency":2.07123},
{"id":0,"description":"PomodoroLog","end":"20200528T172334Z","entry":"20200528T172334Z","modified":"20200528T222249Z","status":"completed","uuid":"f69bcc72-63fe-47bd-a97b-f103fd46c7cb","annotations":[{"entry":"20200528T174834Z","description":"Pomodoro uuid:c252d274-1774-465f-b768-e3e7029bf002"},{"entry":"20200528T181338Z","description":"Pomodoro uuid:c252d274-1774-465f-b768-e3e7029bf002"},{"entry":"20200528T184506Z","description":"Pomodoro uuid:c252d274-1774-465f-b768-e3e7029bf002"},{"entry":"20200528T191009Z","description":"Pomodoro uuid:c252d274-1774-465f-b768-e3e7029bf002"},{"entry":"20200528T195338Z","description":"Pomodoro uuid:c252d274-1774-465f-b768-e3e7029bf002"},{"entry":"20200528T211213Z","description":"Pomodoro uuid:c252d274-1774-465f-b768-e3e7029bf002"},{"entry":"20200528T214446Z","description":"Pomodoro uuid:c252d274-1774-465f-b768-e3e7029bf002"},{"entry":"20200528T222249Z","description":"Pomodoro uuid:c252d274-1774-465f-b768-e3e7029bf002"}],"urgency":2.25479},
{"id":0,"description":"PomodoroLog","end":"20200529T162938Z","entry":"20200529T162938Z","modified":"20200529T231329Z","status":"completed","uuid":"a722ad27-9561-433b-b4d4-e3a584f04fa2","annotations":[{"entry":"20200529T165438Z","description":"Pomodoro uuid:515b5412-cfae-457a-b2a6-7726dd0d5c15"},{"entry":"20200529T172143Z","description":"Pomodoro uuid:515b5412-cfae-457a-b2a6-7726dd0d5c15"},{"entry":"20200529T174648Z","description":"Pomodoro uuid:515b5412-cfae-457a-b2a6-7726dd0d5c15"},{"entry":"20200529T181153Z","description":"Pomodoro uuid:515b5412-cfae-457a-b2a6-7726dd0d5c15"},{"entry":"20200529T221112Z","description":"Pomodoro uuid:515b5412-cfae-457a-b2a6-7726dd0d5c15"},{"entry":"20200529T223637Z","description":"Pomodoro uuid:515b5412-cfae-457a-b2a6-7726dd0d5c15"},{"entry":"20200529T231329Z","description":"Pomodoro uuid:515b5412-cfae-457a-b2a6-7726dd0d5c15"}],"urgency":2.24932},
{"id":0,"description":"PomodoroLog","end":"20200602T180117Z","entry":"20200602T180117Z","modified":"20200602T182617Z","status":"completed","uuid":"65bc5a69-17df-4a7f-b9fd-059056463af4","annotations":[{"entry":"20200602T182617Z","description":"Pomodoro uuid:74a92f9f-5fba-467f-b863-22d64c91de4f"}],"urgency":2.02192},
{"id":0,"description":"PomodoroLog","end":"20200630T180855Z","entry":"20200630T180855Z","modified":"20200630T183355Z","status":"completed","uuid":"76cf3914-4f15-442b-af4f-2b0e346c2787","annotations":[{"entry":"20200630T183355Z","description":"Pomodoro uuid:44f75eec-1e47-4269-bcfd-5e9d7e20cccd"}],"urgency":1.86849},
{"id":0,"description":"PomodoroLog","end":"20200720T160046Z","entry":"20200720T160046Z","modified":"20200720T181225Z","status":"completed","uuid":"3a81cdad-b39e-4558-991e-9f3e460b7472","annotations":[{"entry":"20200720T162547Z","description":"Pomodoro uuid:74a92f9f-5fba-467f-b863-22d64c91de4f"},{"entry":"20200720T165600Z","description":"Pomodoro uuid:74a92f9f-5fba-467f-b863-22d64c91de4f"},{"entry":"20200720T174620Z","description":"Pomodoro uuid:74a92f9f-5fba-467f-b863-22d64c91de4f"},{"entry":"20200720T181225Z","description":"Pomodoro uuid:74a92f9f-5fba-467f-b863-22d64c91de4f"}],"urgency":1.96438},
{"id":0,"description":"PomodoroLog","end":"20200727T180502Z","entry":"20200727T180502Z","modified":"20200727T215349Z","status":"completed","uuid":"5a4a433a-48f1-4d0e-b4e9-a22e2153a435","annotations":[{"entry":"20200727T183003Z","description":"Pomodoro uuid:3536eca7-67b2-43ef-978f-12612a4f0888"},{"entry":"20200727T215349Z","description":"Pomodoro uuid:3536eca7-67b2-43ef-978f-12612a4f0888"}],"urgency":1.82055},
{"id":0,"description":"PomodoroLog","end":"20200728T172947Z","entry":"20200728T172947Z","modified":"20200728T182335Z","status":"completed","uuid":"26cafa00-a4d4-44c7-99be-7310f8485017","annotations":[{"entry":"20200728T175447Z","description":"Pomodoro uuid:3536eca7-67b2-43ef-978f-12612a4f0888"},{"entry":"20200728T182335Z","description":"Pomodoro uuid:3536eca7-67b2-43ef-978f-12612a4f0888"}],"urgency":1.82055},
{"id":0,"description":"PomodoroLog","end":"20200819T162543Z","entry":"20200819T162543Z","modified":"20200819T175452Z","status":"completed","uuid":"9d140f93-45d6-46c9-b176-312402019aea","annotations":[{"entry":"20200819T165044Z","description":"Pomodoro uuid:f52bb46a-bc1f-417b-99ef-ddc2b9019e2c"},{"entry":"20200819T175452Z","description":"Pomodoro uuid:f52bb46a-bc1f-417b-99ef-ddc2b9019e2c"}],"urgency":1.7},
{"id":0,"description":"PomodoroLog","end":"20201013T155547Z","entry":"20201013T155547Z","modified":"20201013T190952Z","status":"completed","uuid":"41e78a09-320c-462c-979b-5da95d3cd514","annotations":[{"entry":"20201013T162047Z","description":"Pomodoro uuid:3c9046da-e43b-48ac-ad41-8a57663c7653"},{"entry":"20201013T165259Z","description":"Pomodoro uuid:3c9046da-e43b-48ac-ad41-8a57663c7653"},{"entry":"20201013T172701Z","description":"Pomodoro uuid:3c9046da-e43b-48ac-ad41-8a57663c7653"},{"entry":"20201013T181519Z","description":"Pomodoro uuid:3c9046da-e43b-48ac-ad41-8a57663c7653"},{"entry":"20201013T184028Z","description":"Pomodoro uuid:3c9046da-e43b-48ac-ad41-8a57663c7653"},{"entry":"20201013T190952Z","description":"Pomodoro uuid:3c9046da-e43b-48ac-ad41-8a57663c7653"}],"urgency":1.49863},
{"id":0,"description":"PomodoroLog","end":"20201116T152023Z","entry":"20201116T152023Z","modified":"20201116T154523Z","status":"completed","uuid":"efba461c-577d-4a21-8a61-2a27953870bb","annotations":[{"entry":"20201116T154523Z","description":"Pomodoro uuid:3c9046da-e43b-48ac-ad41-8a57663c7653"}],"urgency":1.11233},
{"id":0,"description":"PomodoroLog","end":"20201209T154556Z","entry":"20201209T154556Z","modified":"20201209T161056Z","status":"completed","uuid":"7dd5c997-2fb5-4d41-a0e2-742d43e0cc4a","annotations":[{"entry":"20201209T161056Z","description":"Pomodoro uuid:3c9046da-e43b-48ac-ad41-8a57663c7653"}],"urgency":0.986301},
{"id":0,"description":"PomodoroLog","end":"20210112T014807Z","entry":"20210112T014807Z","modified":"20210112T014807Z","status":"completed","uuid":"650f0276-bb1c-45d8-9e77-d73b1d713148","urgency":0}
]

@kdheepak
Copy link
Owner

kdheepak commented Feb 8, 2021

I imported all your tasks and was able to edit them without any issues. Can you tell me which task causes a crash?

@kdheepak
Copy link
Owner

kdheepak commented Feb 8, 2021

@donbex @martinzh, can you run the latest taskwarrior-tui and see if it crashes. I've added better stacktraces now and it should be easier to figure out what the problem might be when the stacktrace is printed.

@donbex
Copy link
Author

donbex commented Feb 8, 2021

I pulled and built the latest commit at the time of writing (tagged v0.9.12), but for some reason I am not getting any debug trace. Here's a gif of the issue:
taskwarrior-tui

@kdheepak
Copy link
Owner

kdheepak commented Feb 8, 2021

Sorry I missed this, why are you trying to type 0000/0000?

Screen Shot 2021-02-08 at 1 59 12 PM

taskwarrior doesn't support using / in the filter string I don't think.

@donbex
Copy link
Author

donbex commented Feb 8, 2021

I'm not. It appears by itself as soon as the editor exits.

Also, for some reason the issue appears harder to reproduce under X11 (xmonad), while under Wayland (sway) it is consistent.

@kdheepak
Copy link
Owner

kdheepak commented Feb 8, 2021

Oh I see. It's automatically entering 0000/0000. That is so odd.

It must have something to do with these lines:

taskwarrior-tui/src/app.rs

Lines 1369 to 1371 in 5e469b8

events.pause_key_capture(terminal);
let r = self.task_edit();
events.resume_key_capture(terminal);

I'm not having this issue in my environments though. Are you able to hit backspace immediately after hitting :wq and deleting 0000/0000?

Also, if you are interested in debugging further, I would play around with the sleep timings in utils.rs. For example like this one:

thread::sleep(Duration::from_millis(250));

There's only 4 instances of thread::sleep. If you can increase the timings and see if that helps, that'll be useful information.

@donbex
Copy link
Author

donbex commented Feb 8, 2021

I'm not having this issue in my environments though. Are you able to hit backspace immediately after hitting :wq and deleting 0000/0000?

Yes, if I'm quick enough I am able to delete the 0000/0000 string, preventing the crash.

There's only 4 instances of thread::sleep. If you can increase the timings and see if that helps, that'll be useful information.

The only instance that seems to have any effect on the issue is the first one, at line 81: increasing the time argument delays the appearance of the 0000/0000 string.

@kdheepak
Copy link
Owner

kdheepak commented Feb 8, 2021

But it always appears regardless of the size of the delay? I might have to share this question with some neovim devs to see if they might be able to share insight as to what is going on. It could very well be a neovim related issue.

@donbex
Copy link
Author

donbex commented Feb 8, 2021

The largest value I tried is 10s, i.e. thread::sleep(Duration::from_millis(10000)), but it still appears.

@kdheepak
Copy link
Owner

kdheepak commented Feb 8, 2021

Can you run the following rust file (I named it tmp.rs):

use std::process::Command;

pub fn main() {
    let task_id = 1;
    let r = Command::new("task").arg(format!("{}", task_id)).arg("edit").spawn();

    let child = r.unwrap();
    let output = child.wait_with_output().unwrap();
    if !output.status.success() {
        println!(format!(
            "`task edit` for task `{}` failed. {}{}",
            task_id,
            String::from_utf8_lossy(&output.stdout),
            String::from_utf8_lossy(&output.stderr),
        ));
    }
}

And after you edit the task and save it, see if it still prints 0000/0000 to the terminal. You might have to change the task_id number.

You can run it using the following:

cargo install cargo-single
cargo single run tmp.rs

If you use cargo single I'll be able to add dependencies to this file and build up to a MWE for reproducible the problem.

@donbex
Copy link
Author

donbex commented Feb 8, 2021

$ cargo single run tmp.rs
error: failed to parse manifest at `/home/bexie/code/ttui-test/tmp/Cargo.toml`

Caused by:
  could not parse input as TOML

Caused by:
  expected an equals, found a newline at line 10 column 7

I'm not sure what's going on here... the Cargo.toml file was automatically generated, line 10 is the last one, but it only has 6 columns:

[package]
name = "tmp"
version = "0.1.0"
authors = [ ... ]
edition = "2018"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
tmp.rs

P.S.: It appears that the crate is called cargo-single.

Edit: Never mind... I copied your snippet as-is, but apparently cargo single uses the comments at the beginning of a file to list its dependencies.

@kdheepak kdheepak reopened this Feb 16, 2021
@kdheepak kdheepak added the help wanted Extra attention is needed label Feb 16, 2021
@kdheepak
Copy link
Owner

I've tried everything I could think of and I'm not sure how to proceed on this. With alacritty and vi I'm getting odd behavior as well (it doesn't print 0000/0000 but it modifies the task list or opens the context menu when I hit e). My hunch, although weak, is telling me that this has more to do with alacritty than nvim / vim / vi.

@kdheepak
Copy link
Owner

kdheepak commented Feb 17, 2021

I've made a Minimal Working Example (MWE) of this bug. I'm able to get similar behavior with vi, vim and neovim but not with nano. Here's a gif of it in action.

taskwarrior-tui-bug

This is troubling because in the current implementation I'm interpreting those to be user entered key strokes, which means the ANSI codes that are being printed may cause arbitrary changes to the users task list.

I'm not able to reproduce this if I remove the "threading" related pieces in my code, everything works as intended. I don't understand why this is the case, but that is good news in a way, since it means this can potentially be solved with fixes on my end (I think).

I wanted to warn you about this. I don't want this program to cause intended issues with your taskwarrior setup. Maybe avoid using the e key for now.

The code to reproduce the issue is below. I'll post on the crossterm repo to see if they can suggest something.

use crossterm::{
    event,
    terminal::{disable_raw_mode, enable_raw_mode},
};
use std::error::Error;
use std::process::Command;
use std::result::Result;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;
use std::{sync::mpsc, thread, time::Duration, time::Instant};

#[derive(Debug, Clone, Copy)]
pub enum Key {
    Char(char),
    Null,
}

#[derive(Debug, Clone, Copy)]
pub struct EventConfig {
    pub tick_rate: Duration,
}

#[derive(Debug, Clone, Copy)]
pub enum Event<I> {
    Input(I),
    Tick,
}

pub struct Events {
    pub rx: mpsc::Receiver<Event<Key>>,
    pub tx: mpsc::Sender<Event<Key>>,
    pub pause_stdin: Arc<AtomicBool>,
}

impl Events {
    #[cfg(feature = "crossterm")]
    pub fn with_config(config: EventConfig) -> Events {
        use crossterm::event::{KeyCode::*};
        let (tx, rx) = mpsc::channel();
        let pause_stdin = Arc::new(AtomicBool::new(false));
        let tick_rate = config.tick_rate;
        let _input_handle = {
            let tx = tx.clone();
            let pause_stdin = pause_stdin.clone();
            thread::spawn(move || {
                let mut last_tick = Instant::now();
                loop {
                    let timeout = tick_rate
                        .checked_sub(last_tick.elapsed())
                        .unwrap_or_else(|| Duration::from_secs(0));

                    if event::poll(timeout).unwrap() {
                        if !pause_stdin.load(Ordering::SeqCst) {
                            if let event::Event::Key(key) = event::read().unwrap() {
                                let key = match key.code {
                                    Char(c) => Key::Char(c),
                                    _ => Key::Null,
                                };
                                tx.send(Event::Input(key)).unwrap();
                            }
                        }
                    }

                    if last_tick.elapsed() >= tick_rate && tx.send(Event::Tick).is_ok() {
                        last_tick = Instant::now();
                    }
                }
            })
        };
        Events { rx, tx, pause_stdin }
    }

    /// Attempts to read an event.
    /// This function will block the current thread.
    pub fn next(&self) -> Result<Event<Key>, mpsc::RecvError> {
        self.rx.recv()
    }

    pub fn pause_event_loop(&self) {
        self.pause_stdin.swap(true, Ordering::SeqCst);
    }

    pub fn resume_event_loop(&self) {
        self.pause_stdin.swap(false, Ordering::SeqCst);
    }

    pub fn pause_key_capture(&self) {
        self.pause_event_loop();
        disable_raw_mode().unwrap();
    }

    pub fn resume_key_capture(&self) {
        enable_raw_mode().unwrap();
        self.resume_event_loop();
    }
}

fn main() -> Result<(), Box<dyn Error>> {
    // Terminal initialization
    enable_raw_mode().unwrap();

    let mut i = 0;

    // Setup event handlers
    let events = Events::with_config(EventConfig {
        tick_rate: Duration::from_millis(1000),
    });

    loop {
        match events.next()? {
            Event::Input(input) => {
                match input {
                    Key::Char('q') => break,
                    Key::Char('e') => {
                        events.pause_key_capture();
                        let r = Command::new("vim").spawn();
                        match r {
                            Ok(child) => {
                                let output = child.wait_with_output();
                                match output {
                                    Ok(output) => {
                                        if !output.status.success() {
                                            Err(format!(
                                                "process status was not success. {}{}",
                                                String::from_utf8_lossy(&output.stdout),
                                                String::from_utf8_lossy(&output.stderr),
                                            ))
                                        } else {
                                            String::from_utf8_lossy(&output.stdout);
                                            String::from_utf8_lossy(&output.stderr);
                                            Ok(())
                                        }
                                    }
                                    Err(err) => Err(format!("Failed to get output of process: {}", err)),
                                }
                            }
                            Err(err) => Err(format!("Failed to spawn process: {}", err)),
                        }?;
                        events.resume_key_capture();
                    },
                    Key::Char(c) => {
                        disable_raw_mode().unwrap();
                        print!("{}", c);
                        enable_raw_mode().unwrap();
                    },
                    _ => (),
                };
            }
            Event::Tick => {
                disable_raw_mode().unwrap();
                println!();
                println!("Tick: {}", i);
                enable_raw_mode().unwrap();
                i += 1;
            }
        };
    }
    disable_raw_mode().unwrap();
    Ok(())
}

@kdheepak
Copy link
Owner

Interestingly I get similar codes in iTerm2 as I do in Alacritty.

Screen Shot 2021-02-16 at 11 24 44 PM

Screen Shot 2021-02-16 at 11 24 54 PM

@kdheepak
Copy link
Owner

After lots of experimenting and debugging I think I've fixed this. I'm no longer able to get ansi codes being printed to taskwarrior-tui or in the MWE when using alacritty / iTerm2 and when shelling out to vi, vim and nvim on my Mac. It'd be great if you can give it go to check if that is the case for you as well.

@kdheepak
Copy link
Owner

You can try it out in this release: https://github.com/kdheepak/taskwarrior-tui/releases/tag/v0.10.4

@donbex
Copy link
Author

donbex commented Feb 17, 2021

Thanks for the hard work you've put into this. I'll try out the new changes as soon as I have some time today or tomorrow.

My guess as for why you don't see those keycodes after running nano is that it doesn't allow theming, so it doesn't have to reset the terminal colours after exiting. I expect you'd see the same keycodes after running other themable TUI applications, like mc.

@donbex
Copy link
Author

donbex commented Feb 17, 2021

I tried the latest commit (0ae677f) and it was much better, although I cannot say that the issue is completely resolved: in 3 out of 40 tests the issue was still present, i.e. the string 0000/0000 appeared in the filter field after editing a task.

@kdheepak
Copy link
Owner

Thanks for trying it!

Can you change these lines:

let timeout = Duration::from_millis(25)
.checked_sub(last_tick.elapsed())
.unwrap_or_else(|| Duration::from_millis(10));

to the following:

                    let timeout = Duration::from_millis(10)
                        .checked_sub(last_tick.elapsed())
                        .unwrap_or_else(|| Duration::from_millis(0));

and try again? If I set the timeout too low (i.e. 0 milliseconds), then the CPU consumption goes up to like 50% when monitoring using htop. Setting it too high causes the issue.

If using 0 solves the problem for you, I'll make it a configurable option.

@donbex
Copy link
Author

donbex commented Feb 17, 2021

Indeed, setting the timeout to 0ms drove the CPU usage way too high. However, setting it to 5ms seemed to solve the issue (out of 100 tests) and also kept the CPU usage to reasonable levels. Thanks again!

let timeout = Duration::from_millis(10)
    .checked_sub(last_tick.elapsed())
    .unwrap_or_else(|| Duration::from_millis(5));

@kdheepak
Copy link
Owner

kdheepak commented Feb 17, 2021

I think I can change it to the above timings. The CPU usage seems reasonable. Thanks for testing so many times!

@kdheepak
Copy link
Owner

kdheepak commented Feb 17, 2021

Did you test a 100 times or so manually? Or did you test programmatically? It would be good to add such a test into the test suite so there isn't a regression in the future.

@donbex
Copy link
Author

donbex commented Feb 17, 2021

Unfortunately I did it manually. I assume it would be possible to set up an automated "puppeted" test, but that would be pretty fragile and I wouldn't recommend keeping it long term for regression testing. It should be possible to write a dummy program to use in place of an editor that changes the terminal colours (assuming that's enough to trigger a colour reset via the OSC 11 code) and immediately exits. I still wouldn't know how to check that taskwarrior-tui isn't reading part of the OSC code as input — mainly because I don't know the codebase (nor Rust, for that matter), but I presume it could be relatively straightforward to do in a unit test.

@kdheepak
Copy link
Owner

wow thanks for being so dedicated :) And thanks for the input, I'll look into how to set up a test for this.

@kdheepak
Copy link
Owner

kdheepak commented Mar 1, 2021

I made a new release that has the fix for this issue: https://github.com/kdheepak/taskwarrior-tui/releases/tag/v0.11.0.

@kdheepak
Copy link
Owner

I re-did the event handler using async and you can try it on the latest commit on master at the moment. I think it is much faster and nicer to use :)

And now there's no sleeps and delays any more like I had before to avoid the ANSI codes being printed. I didn't test on linux but in my testing on my mac using alacritty and iterm2 I never had ANSI codes being printed to the terminal even once. Hopefully there's no regression here but if you do notice anything please comment here / open a new issue!

@kdheepak
Copy link
Owner

You can try it out in this release: https://github.com/kdheepak/taskwarrior-tui/releases/tag/v0.13.0.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment